diff options
389 files changed, 19385 insertions, 3645 deletions
diff --git a/Documentation/Intel-IOMMU.txt b/Documentation/Intel-IOMMU.txt new file mode 100644 index 00000000000..c2321903aa0 --- /dev/null +++ b/Documentation/Intel-IOMMU.txt @@ -0,0 +1,115 @@ +Linux IOMMU Support +=================== + +The architecture spec can be obtained from the below location. + +http://www.intel.com/technology/virtualization/ + +This guide gives a quick cheat sheet for some basic understanding. + +Some Keywords + +DMAR - DMA remapping +DRHD - DMA Engine Reporting Structure +RMRR - Reserved memory Region Reporting Structure +ZLR - Zero length reads from PCI devices +IOVA - IO Virtual address. + +Basic stuff +----------- + +ACPI enumerates and lists the different DMA engines in the platform, and +device scope relationships between PCI devices and which DMA engine controls +them. + +What is RMRR? +------------- + +There are some devices the BIOS controls, for e.g USB devices to perform +PS2 emulation. The regions of memory used for these devices are marked +reserved in the e820 map. When we turn on DMA translation, DMA to those +regions will fail. Hence BIOS uses RMRR to specify these regions along with +devices that need to access these regions. OS is expected to setup +unity mappings for these regions for these devices to access these regions. + +How is IOVA generated? +--------------------- + +Well behaved drivers call pci_map_*() calls before sending command to device +that needs to perform DMA. Once DMA is completed and mapping is no longer +required, device performs a pci_unmap_*() calls to unmap the region. + +The Intel IOMMU driver allocates a virtual address per domain. Each PCIE +device has its own domain (hence protection). Devices under p2p bridges +share the virtual address with all devices under the p2p bridge due to +transaction id aliasing for p2p bridges. + +IOVA generation is pretty generic. We used the same technique as vmalloc() +but these are not global address spaces, but separate for each domain. +Different DMA engines may support different number of domains. + +We also allocate gaurd pages with each mapping, so we can attempt to catch +any overflow that might happen. + + +Graphics Problems? +------------------ +If you encounter issues with graphics devices, you can try adding +option intel_iommu=igfx_off to turn off the integrated graphics engine. + +If it happens to be a PCI device included in the INCLUDE_ALL Engine, +then try enabling CONFIG_DMAR_GFX_WA to setup a 1-1 map. We hear +graphics drivers may be in process of using DMA api's in the near +future and at that time this option can be yanked out. + +Some exceptions to IOVA +----------------------- +Interrupt ranges are not address translated, (0xfee00000 - 0xfeefffff). +The same is true for peer to peer transactions. Hence we reserve the +address from PCI MMIO ranges so they are not allocated for IOVA addresses. + + +Fault reporting +--------------- +When errors are reported, the DMA engine signals via an interrupt. The fault +reason and device that caused it with fault reason is printed on console. + +See below for sample. + + +Boot Message Sample +------------------- + +Something like this gets printed indicating presence of DMAR tables +in ACPI. + +ACPI: DMAR (v001 A M I OEMDMAR 0x00000001 MSFT 0x00000097) @ 0x000000007f5b5ef0 + +When DMAR is being processed and initialized by ACPI, prints DMAR locations +and any RMRR's processed. + +ACPI DMAR:Host address width 36 +ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed90000 +ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed91000 +ACPI DMAR:DRHD (flags: 0x00000001)base: 0x00000000fed93000 +ACPI DMAR:RMRR base: 0x00000000000ed000 end: 0x00000000000effff +ACPI DMAR:RMRR base: 0x000000007f600000 end: 0x000000007fffffff + +When DMAR is enabled for use, you will notice.. + +PCI-DMA: Using DMAR IOMMU + +Fault reporting +--------------- + +DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000 +DMAR:[fault reason 05] PTE Write access is not set +DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000 +DMAR:[fault reason 05] PTE Write access is not set + +TBD +---- + +- For compatibility testing, could use unity map domain for all devices, just + provide a 1-1 for all useful memory under a single domain for all devices. +- API for paravirt ops for abstracting functionlity for VMM folks. diff --git a/Documentation/filesystems/Exporting b/Documentation/filesystems/Exporting index 31047e0fe14..87019d2b598 100644 --- a/Documentation/filesystems/Exporting +++ b/Documentation/filesystems/Exporting @@ -2,9 +2,12 @@ Making Filesystems Exportable ============================= -Most filesystem operations require a dentry (or two) as a starting +Overview +-------- + +All filesystem operations require a dentry (or two) as a starting point. Local applications have a reference-counted hold on suitable -dentrys via open file descriptors or cwd/root. However remote +dentries via open file descriptors or cwd/root. However remote applications that access a filesystem via a remote filesystem protocol such as NFS may not be able to hold such a reference, and so need a different way to refer to a particular dentry. As the alternative @@ -13,14 +16,14 @@ server-reboot (among other things, though these tend to be the most problematic), there is no simple answer like 'filename'. The mechanism discussed here allows each filesystem implementation to -specify how to generate an opaque (out side of the filesystem) byte +specify how to generate an opaque (outside of the filesystem) byte string for any dentry, and how to find an appropriate dentry for any given opaque byte string. This byte string will be called a "filehandle fragment" as it corresponds to part of an NFS filehandle. A filesystem which supports the mapping between filehandle fragments -and dentrys will be termed "exportable". +and dentries will be termed "exportable". @@ -89,11 +92,9 @@ For a filesystem to be exportable it must: 1/ provide the filehandle fragment routines described below. 2/ make sure that d_splice_alias is used rather than d_add when ->lookup finds an inode for a given parent and name. - Typically the ->lookup routine will end: - if (inode) - return d_splice(inode, dentry); - d_add(dentry, inode); - return NULL; + Typically the ->lookup routine will end with a: + + return d_splice_alias(inode, dentry); } @@ -101,67 +102,39 @@ For a filesystem to be exportable it must: A file system implementation declares that instances of the filesystem are exportable by setting the s_export_op field in the struct super_block. This field must point to a "struct export_operations" -struct which could potentially be full of NULLs, though normally at -least get_parent will be set. - - The primary operations are decode_fh and encode_fh. -decode_fh takes a filehandle fragment and tries to find or create a -dentry for the object referred to by the filehandle. -encode_fh takes a dentry and creates a filehandle fragment which can -later be used to find/create a dentry for the same object. - -decode_fh will probably make use of "find_exported_dentry". -This function lives in the "exportfs" module which a filesystem does -not need unless it is being exported. So rather that calling -find_exported_dentry directly, each filesystem should call it through -the find_exported_dentry pointer in it's export_operations table. -This field is set correctly by the exporting agent (e.g. nfsd) when a -filesystem is exported, and before any export operations are called. - -find_exported_dentry needs three support functions from the -filesystem: - get_name. When given a parent dentry and a child dentry, this - should find a name in the directory identified by the parent - dentry, which leads to the object identified by the child dentry. - If no get_name function is supplied, a default implementation is - provided which uses vfs_readdir to find potential names, and - matches inode numbers to find the correct match. - - get_parent. When given a dentry for a directory, this should return - a dentry for the parent. Quite possibly the parent dentry will - have been allocated by d_alloc_anon. - The default get_parent function just returns an error so any - filehandle lookup that requires finding a parent will fail. - ->lookup("..") is *not* used as a default as it can leave ".." - entries in the dcache which are too messy to work with. - - get_dentry. When given an opaque datum, this should find the - implied object and create a dentry for it (possibly with - d_alloc_anon). - The opaque datum is whatever is passed down by the decode_fh - function, and is often simply a fragment of the filehandle - fragment. - decode_fh passes two datums through find_exported_dentry. One that - should be used to identify the target object, and one that can be - used to identify the object's parent, should that be necessary. - The default get_dentry function assumes that the datum contains an - inode number and a generation number, and it attempts to get the - inode using "iget" and check it's validity by matching the - generation number. A filesystem should only depend on the default - if iget can safely be used this way. - -If decode_fh and/or encode_fh are left as NULL, then default -implementations are used. These defaults are suitable for ext2 and -extremely similar filesystems (like ext3). - -The default encode_fh creates a filehandle fragment from the inode -number and generation number of the target together with the inode -number and generation number of the parent (if the parent is -required). - -The default decode_fh extract the target and parent datums from the -filehandle assuming the format used by the default encode_fh and -passed them to find_exported_dentry. +struct which has the following members: + + encode_fh (optional) + Takes a dentry and creates a filehandle fragment which can later be used + to find or create a dentry for the same object. The default + implementation creates a filehandle fragment that encodes a 32bit inode + and generation number for the inode encoded, and if necessary the + same information for the parent. + + fh_to_dentry (mandatory) + Given a filehandle fragment, this should find the implied object and + create a dentry for it (possibly with d_alloc_anon). + + fh_to_parent (optional but strongly recommended) + Given a filehandle fragment, this should find the parent of the + implied object and create a dentry for it (possibly with d_alloc_anon). + May fail if the filehandle fragment is too small. + + get_parent (optional but strongly recommended) + When given a dentry for a directory, this should return a dentry for + the parent. Quite possibly the parent dentry will have been allocated + by d_alloc_anon. The default get_parent function just returns an error + so any filehandle lookup that requires finding a parent will fail. + ->lookup("..") is *not* used as a default as it can leave ".." entries + in the dcache which are too messy to work with. + + get_name (optional) + When given a parent dentry and a child dentry, this should find a name + in the directory identified by the parent dentry, which leads to the + object identified by the child dentry. If no get_name function is + supplied, a default implementation is provided which uses vfs_readdir + to find potential names, and matches inode numbers to find the correct + match. A filehandle fragment consists of an array of 1 or more 4byte words, @@ -172,5 +145,3 @@ generated by encode_fh, in which case it will have been padded with nuls. Rather, the encode_fh routine should choose a "type" which indicates the decode_fh how much of the filehandle is valid, and how it should be interpreted. - - diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt index 35985b34d5a..2f75e750e4f 100644 --- a/Documentation/i386/boot.txt +++ b/Documentation/i386/boot.txt @@ -168,6 +168,8 @@ Offset Proto Name Meaning 0234/1 2.05+ relocatable_kernel Whether kernel is relocatable or not 0235/3 N/A pad2 Unused 0238/4 2.06+ cmdline_size Maximum size of the kernel command line +023C/4 2.07+ hardware_subarch Hardware subarchitecture +0240/8 2.07+ hardware_subarch_data Subarchitecture-specific data (1) For backwards compatibility, if the setup_sects field contains 0, the real value is 4. @@ -204,7 +206,7 @@ boot loaders can ignore those fields. The byte order of all fields is littleendian (this is x86, after all.) -Field name: setup_secs +Field name: setup_sects Type: read Offset/size: 0x1f1/1 Protocol: ALL @@ -356,6 +358,13 @@ Protocol: 2.00+ - If 0, the protected-mode code is loaded at 0x10000. - If 1, the protected-mode code is loaded at 0x100000. + Bit 6 (write): KEEP_SEGMENTS + Protocol: 2.07+ + - if 0, reload the segment registers in the 32bit entry point. + - if 1, do not reload the segment registers in the 32bit entry point. + Assume that %cs %ds %ss %es are all set to flat segments with + a base of 0 (or the equivalent for their environment). + Bit 7 (write): CAN_USE_HEAP Set this bit to 1 to indicate that the value entered in the heap_end_ptr is valid. If this field is clear, some setup code @@ -480,6 +489,29 @@ Protocol: 2.06+ cmdline_size characters. With protocol version 2.05 and earlier, the maximum size was 255. +Field name: hardware_subarch +Type: write +Offset/size: 0x23c/4 +Protocol: 2.07+ + + In a paravirtualized environment the hardware low level architectural + pieces such as interrupt handling, page table handling, and + accessing process control registers needs to be done differently. + + This field allows the bootloader to inform the kernel we are in one + one of those environments. + + 0x00000000 The default x86/PC environment + 0x00000001 lguest + 0x00000002 Xen + +Field name: hardware_subarch_data +Type: write +Offset/size: 0x240/8 +Protocol: 2.07+ + + A pointer to data that is specific to hardware subarch + **** THE KERNEL COMMAND LINE diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 6accd360da7..b2361667839 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -772,6 +772,23 @@ and is between 256 and 4096 characters. It is defined in the file inttest= [IA64] + intel_iommu= [DMAR] Intel IOMMU driver (DMAR) option + off + Disable intel iommu driver. + igfx_off [Default Off] + By default, gfx is mapped as normal device. If a gfx + device has a dedicated DMAR unit, the DMAR unit is + bypassed by not enabling DMAR with this option. In + this case, gfx device will use physical address for + DMA. + forcedac [x86_64] + With this option iommu will not optimize to look + for io virtual address below 32 bit forcing dual + address cycle on pci bus for cards supporting greater + than 32 bit addressing. The default is to look + for translation below 32 bit and if not available + then look in the higher range. + io7= [HW] IO7 for Marvel based alpha systems See comment before marvel_specify_io7 in arch/alpha/kernel/core_marvel.c. diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt index 5fbcc22c98e..168117bd6ee 100644 --- a/Documentation/memory-hotplug.txt +++ b/Documentation/memory-hotplug.txt @@ -2,7 +2,8 @@ Memory Hotplug ============== -Last Updated: Jul 28 2007 +Created: Jul 28 2007 +Add description of notifier of memory hotplug Oct 11 2007 This document is about memory hotplug including how-to-use and current status. Because Memory Hotplug is still under development, contents of this text will @@ -24,7 +25,8 @@ be changed often. 6.1 Memory offline and ZONE_MOVABLE 6.2. How to offline memory 7. Physical memory remove -8. Future Work List +8. Memory hotplug event notifier +9. Future Work List Note(1): x86_64's has special implementation for memory hotplug. This text does not describe it. @@ -307,8 +309,58 @@ Need more implementation yet.... - Notification completion of remove works by OS to firmware. - Guard from remove if not yet. +-------------------------------- +8. Memory hotplug event notifier +-------------------------------- +Memory hotplug has event notifer. There are 6 types of notification. + +MEMORY_GOING_ONLINE + Generated before new memory becomes available in order to be able to + prepare subsystems to handle memory. The page allocator is still unable + to allocate from the new memory. + +MEMORY_CANCEL_ONLINE + Generated if MEMORY_GOING_ONLINE fails. + +MEMORY_ONLINE + Generated when memory has succesfully brought online. The callback may + allocate pages from the new memory. + +MEMORY_GOING_OFFLINE + Generated to begin the process of offlining memory. Allocations are no + longer possible from the memory but some of the memory to be offlined + is still in use. The callback can be used to free memory known to a + subsystem from the indicated memory section. + +MEMORY_CANCEL_OFFLINE + Generated if MEMORY_GOING_OFFLINE fails. Memory is available again from + the section that we attempted to offline. + +MEMORY_OFFLINE + Generated after offlining memory is complete. + +A callback routine can be registered by + hotplug_memory_notifier(callback_func, priority) + +The second argument of callback function (action) is event types of above. +The third argument is passed by pointer of struct memory_notify. + +struct memory_notify { + unsigned long start_pfn; + unsigned long nr_pages; + int status_cahnge_nid; +} + +start_pfn is start_pfn of online/offline memory. +nr_pages is # of pages of online/offline memory. +status_change_nid is set node id when N_HIGH_MEMORY of nodemask is (will be) +set/clear. It means a new(memoryless) node gets new memory by online and a +node loses all memory. If this is -1, then nodemask status is not changed. +If status_changed_nid >= 0, callback should create/discard structures for the +node if necessary. + -------------- -8. Future Work +9. Future Work -------------- - allowing memory hot-add to ZONE_MOVABLE. maybe we need some switch like sysctl or new control file. diff --git a/MAINTAINERS b/MAINTAINERS index 4ed41394e49..1fd6d02a79b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1963,11 +1963,6 @@ M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (subscribers-only) S: Maintained -INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT -P: Ingo Molnar -M: mingo@redhat.com -S: Maintained - INTEL I8XX RANDOM NUMBER GENERATOR SUPPORT P: Jeff Garzik M: jgarzik@pobox.com @@ -4269,9 +4264,15 @@ M: jacmet@sunsite.dk L: linux-serial@vger.kernel.org S: Maintained -X86 3-LEVEL PAGING (PAE) SUPPORT +X86 ARCHITECTURE (32-BIT AND 64-BIT) +P: Thomas Gleixner +M: tglx@linutronix.de P: Ingo Molnar M: mingo@redhat.com +P: H. Peter Anvin +M: hpa@zytor.com +L: linux-kernel@vger.kernel.org +T: git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git S: Maintained YAM DRIVER FOR AX.25 diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index e1c470752eb..ee07dceae1d 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c @@ -465,7 +465,7 @@ EXPORT_SYMBOL(pci_free_consistent); Write dma_length of each leader with the combined lengths of the mergable followers. */ -#define SG_ENT_VIRT_ADDRESS(SG) (page_address((SG)->page) + (SG)->offset) +#define SG_ENT_VIRT_ADDRESS(SG) (sg_virt((SG))) #define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG)) static void diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 44ab0dad403..9d371e47655 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -442,7 +442,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, BUG_ON(dir == DMA_NONE); for (i = 0; i < nents; i++, sg++) { - struct page *page = sg->page; + struct page *page = sg_page(sg); unsigned int offset = sg->offset; unsigned int length = sg->length; void *ptr = page_address(page) + offset; diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index ad28dc76fc9..7888551ed93 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -71,7 +71,7 @@ config GENERIC_CALIBRATE_DELAY config IRQCHIP_DEMUX_GPIO bool - depends on (BF53x || BF561 || BF54x) + depends on (BF52x || BF53x || BF561 || BF54x) default y source "init/Kconfig" @@ -85,6 +85,21 @@ choice prompt "CPU" default BF533 +config BF522 + bool "BF522" + help + BF522 Processor Support. + +config BF525 + bool "BF525" + help + BF525 Processor Support. + +config BF527 + bool "BF527" + help + BF527 Processor Support. + config BF531 bool "BF531" help @@ -144,13 +159,18 @@ endchoice choice prompt "Silicon Rev" + default BF_REV_0_1 if BF527 default BF_REV_0_2 if BF537 default BF_REV_0_3 if BF533 default BF_REV_0_0 if BF549 config BF_REV_0_0 bool "0.0" - depends on (BF549) + depends on (BF549 || BF527) + +config BF_REV_0_1 + bool "0.2" + depends on (BF549 || BF527) config BF_REV_0_2 bool "0.2" @@ -176,6 +196,11 @@ config BF_REV_NONE endchoice +config BF52x + bool + depends on (BF522 || BF525 || BF527) + default y + config BF53x bool depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537) @@ -204,6 +229,12 @@ choice configuration to ensure that all the other settings are correct. +config BFIN527_EZKIT + bool "BF527-EZKIT" + depends on (BF522 || BF525 || BF527) + help + BF533-EZKIT-LITE board Support. + config BFIN533_EZKIT bool "BF533-EZKIT" depends on (BF533 || BF532 || BF531) @@ -299,11 +330,17 @@ config MEM_MT48LC8M32B2B5_7 depends on (BFIN561_BLUETECHNIX_CM) default y +config MEM_MT48LC32M16A2TG_75 + bool + depends on (BFIN527_EZKIT) + default y + config BFIN_SHARED_FLASH_ENET bool depends on (BFIN533_STAMP) default y +source "arch/blackfin/mach-bf527/Kconfig" source "arch/blackfin/mach-bf533/Kconfig" source "arch/blackfin/mach-bf561/Kconfig" source "arch/blackfin/mach-bf537/Kconfig" @@ -329,7 +366,7 @@ config CLKIN_HZ int "Crystal Frequency in Hz" default "11059200" if BFIN533_STAMP default "27000000" if BFIN533_EZKIT - default "25000000" if BFIN537_STAMP + default "25000000" if (BFIN537_STAMP || BFIN527_EZKIT) default "30000000" if BFIN561_EZKIT default "24576000" if PNAV10 help @@ -362,7 +399,7 @@ config VCO_MULT range 1 64 default "22" if BFIN533_EZKIT default "45" if BFIN533_STAMP - default "20" if BFIN537_STAMP + default "20" if (BFIN537_STAMP || BFIN527_EZKIT) default "22" if BFIN533_BLUETECHNIX_CM default "20" if BFIN537_BLUETECHNIX_CM default "20" if BFIN561_BLUETECHNIX_CM @@ -398,7 +435,7 @@ config SCLK_DIV range 1 15 default 5 if BFIN533_EZKIT default 5 if BFIN533_STAMP - default 4 if BFIN537_STAMP + default 4 if (BFIN537_STAMP || BFIN527_EZKIT) default 5 if BFIN533_BLUETECHNIX_CM default 4 if BFIN537_BLUETECHNIX_CM default 4 if BFIN561_BLUETECHNIX_CM @@ -450,6 +487,7 @@ comment "Memory Setup" config MEM_SIZE int "SDRAM Memory Size in MBytes" default 32 if BFIN533_EZKIT + default 64 if BFIN527_EZKIT default 64 if BFIN537_STAMP default 64 if BFIN561_EZKIT default 128 if BFIN533_STAMP @@ -459,6 +497,7 @@ config MEM_ADD_WIDTH int "SDRAM Memory Address Width" default 9 if BFIN533_EZKIT default 9 if BFIN561_EZKIT + default 10 if BFIN527_EZKIT default 10 if BFIN537_STAMP default 11 if BFIN533_STAMP default 10 if PNAV10 @@ -749,9 +788,19 @@ config LARGE_ALLOCS a lot of RAM, and you need to able to allocate very large contiguous chunks. If unsure, say N. +config BFIN_GPTIMERS + tristate "Enable Blackfin General Purpose Timers API" + default n + help + Enable support for the General Purpose Timers API. If you + are unsure, say N. + + To compile this driver as a module, choose M here: the module + will be called gptimers.ko. + config BFIN_DMA_5XX bool "Enable DMA Support" - depends on (BF533 || BF532 || BF531 || BF537 || BF536 || BF534 || BF561 || BF54x) + depends on (BF52x || BF53x || BF561 || BF54x) default y help DMA driver for BF5xx. diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index 368933760d2..3c87291bcda 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -12,12 +12,17 @@ LDFLAGS_vmlinux := -X OBJCOPYFLAGS := -O binary -R .note -R .comment -S GZFLAGS := -9 +CFLAGS += $(call cc-option,-mno-fdpic) +AFLAGS += $(call cc-option,-mno-fdpic) CFLAGS_MODULE += -mlong-calls KALLSYMS += --symbol-prefix=_ KBUILD_DEFCONFIG := BF537-STAMP_defconfig # setup the machine name and the machine dependent settings +machine-$(CONFIG_BF522) := bf527 +machine-$(CONFIG_BF525) := bf527 +machine-$(CONFIG_BF527) := bf527 machine-$(CONFIG_BF531) := bf533 machine-$(CONFIG_BF532) := bf533 machine-$(CONFIG_BF533) := bf533 @@ -32,6 +37,9 @@ machine-$(CONFIG_BF561) := bf561 MACHINE := $(machine-y) export MACHINE +cpu-$(CONFIG_BF522) := bf522 +cpu-$(CONFIG_BF525) := bf525 +cpu-$(CONFIG_BF527) := bf527 cpu-$(CONFIG_BF531) := bf531 cpu-$(CONFIG_BF532) := bf532 cpu-$(CONFIG_BF533) := bf533 @@ -97,12 +105,23 @@ archclean: $(Q)$(MAKE) $(clean)=$(boot) -all: vmImage boot := arch/$(ARCH)/boot BOOT_TARGETS = vmImage -.PHONY: $(BOOT_TARGETS) +PHONY += $(BOOT_TARGETS) install +KBUILD_IMAGE := $(boot)/vmImage + +all: vmImage + $(BOOT_TARGETS): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + +install: + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install + define archhelp echo '* vmImage - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage)' + echo ' install - Install kernel using' + echo ' (your) ~/bin/$(CROSS_COMPILE)installkernel or' + echo ' (distribution) PATH: $(CROSS_COMPILE)installkernel or' + echo ' install to $$(INSTALL_PATH)' endef diff --git a/arch/blackfin/boot/Makefile b/arch/blackfin/boot/Makefile index 8cd33560e81..522f3c12406 100644 --- a/arch/blackfin/boot/Makefile +++ b/arch/blackfin/boot/Makefile @@ -26,3 +26,6 @@ $(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE $(obj)/vmImage: $(obj)/vmlinux.gz $(call if_changed,uimage) @echo 'Kernel: $@ is ready' + +install: + sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)" diff --git a/arch/blackfin/boot/install.sh b/arch/blackfin/boot/install.sh new file mode 100644 index 00000000000..9560a6b2910 --- /dev/null +++ b/arch/blackfin/boot/install.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# +# arch/blackfin/boot/install.sh +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1995 by Linus Torvalds +# +# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin +# Adapted from code in arch/i386/boot/install.sh by Mike Frysinger +# +# "make install" script for Blackfin architecture +# +# Arguments: +# $1 - kernel version +# $2 - kernel image file +# $3 - kernel map file +# $4 - default install path (blank if root directory) +# + +verify () { + if [ ! -f "$1" ]; then + echo "" 1>&2 + echo " *** Missing file: $1" 1>&2 + echo ' *** You need to run "make" before "make install".' 1>&2 + echo "" 1>&2 + exit 1 + fi +} + +# Make sure the files actually exist +verify "$2" +verify "$3" + +# User may have a custom install script + +if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi +if which ${CROSS_COMPILE}installkernel >/dev/null 2>&1; then + exec ${CROSS_COMPILE}installkernel "$@" +fi + +# Default install - same as make zlilo + +back_it_up() { + local file=$1 + [ -f ${file} ] || return 0 + local stamp=$(stat -c %Y ${file} 2>/dev/null) + mv ${file} ${file}.${stamp:-old} +} + +back_it_up $4/uImage +back_it_up $4/System.map + +cat $2 > $4/uImage +cp $3 $4/System.map diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig new file mode 100644 index 00000000000..df974e785ee --- /dev/null +++ b/arch/blackfin/configs/BF527-EZKIT_defconfig @@ -0,0 +1,1241 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.22.9 +# +# CONFIG_MMU is not set +# CONFIG_FPU is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_BLACKFIN=y +CONFIG_ZONE_DMA=y +CONFIG_BFIN=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +# CONFIG_GENERIC_TIME is not set +CONFIG_GENERIC_GPIO=y +CONFIG_FORCE_MAX_ZONEORDER=14 +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_IRQCHIP_DEMUX_GPIO=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SYSVIPC=y +# CONFIG_IPC_NS is not set +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_UTS_NS is not set +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_EVENTFD=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_BIG_ORDER_ALLOC_NOFAIL_MAGIC=3 +# CONFIG_NP2 is not set +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_RT_MUTEXES=y +CONFIG_TINY_SHMEM=y +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set + +# +# Blackfin Processor Options +# + +# +# Processor and Board Settings +# +# CONFIG_BF522 is not set +# CONFIG_BF525 is not set +CONFIG_BF527=y +# CONFIG_BF531 is not set +# CONFIG_BF532 is not set +# CONFIG_BF533 is not set +# CONFIG_BF534 is not set +# CONFIG_BF536 is not set +# CONFIG_BF537 is not set +# CONFIG_BF542 is not set +# CONFIG_BF544 is not set +# CONFIG_BF548 is not set +# CONFIG_BF549 is not set +# CONFIG_BF561 is not set +CONFIG_BF_REV_0_0=y +# CONFIG_BF_REV_0_1 is not set +# CONFIG_BF_REV_0_2 is not set +# CONFIG_BF_REV_0_3 is not set +# CONFIG_BF_REV_0_4 is not set +# CONFIG_BF_REV_0_5 is not set +# CONFIG_BF_REV_ANY is not set +# CONFIG_BF_REV_NONE is not set +CONFIG_BF52x=y +CONFIG_BFIN_SINGLE_CORE=y +CONFIG_BFIN527_EZKIT=y +# CONFIG_BFIN533_EZKIT is not set +# CONFIG_BFIN533_STAMP is not set +# CONFIG_BFIN537_STAMP is not set +# CONFIG_BFIN533_BLUETECHNIX_CM is not set +# CONFIG_BFIN537_BLUETECHNIX_CM is not set +# CONFIG_BFIN548_EZKIT is not set +# CONFIG_BFIN561_BLUETECHNIX_CM is not set +# CONFIG_BFIN561_EZKIT is not set +# CONFIG_BFIN561_TEPLA is not set +# CONFIG_PNAV10 is not set +# CONFIG_GENERIC_BOARD is not set +CONFIG_MEM_MT48LC32M16A2TG_75=y + +# +# BF527 Specific Configuration +# + +# +# Alternative Multiplexing Scheme +# +# CONFIG_BF527_SPORT0_PORTF is not set +CONFIG_BF527_SPORT0_PORTG=y +CONFIG_BF527_SPORT0_TSCLK_PG10=y +# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set +# CONFIG_BF527_UART1_PORTF is not set +CONFIG_BF527_UART1_PORTG=y +# CONFIG_BF527_NAND_D_PORTF is not set +CONFIG_BF527_NAND_D_PORTH=y + +# +# Interrupt Priority Assignment +# + +# +# Priority +# +CONFIG_IRQ_PLL_WAKEUP=7 +CONFIG_IRQ_DMA0_ERROR=7 +CONFIG_IRQ_DMAR0_BLK=7 +CONFIG_IRQ_DMAR1_BLK=7 +CONFIG_IRQ_DMAR0_OVR=7 +CONFIG_IRQ_DMAR1_OVR=7 +CONFIG_IRQ_PPI_ERROR=7 +CONFIG_IRQ_MAC_ERROR=7 +CONFIG_IRQ_SPORT0_ERROR=7 +CONFIG_IRQ_SPORT1_ERROR=7 +CONFIG_IRQ_UART0_ERROR=7 +CONFIG_IRQ_UART1_ERROR=7 +CONFIG_IRQ_RTC=8 +CONFIG_IRQ_PPI=8 +CONFIG_IRQ_SPORT0_RX=9 +CONFIG_IRQ_SPORT0_TX=9 +CONFIG_IRQ_SPORT1_RX=9 +CONFIG_IRQ_SPORT1_TX=9 +CONFIG_IRQ_TWI=10 +CONFIG_IRQ_SPI=10 +CONFIG_IRQ_UART0_RX=10 +CONFIG_IRQ_UART0_TX=10 +CONFIG_IRQ_UART1_RX=10 +CONFIG_IRQ_UART1_TX=10 +CONFIG_IRQ_OPTSEC=11 +CONFIG_IRQ_CNT=11 +CONFIG_IRQ_MAC_RX=11 +CONFIG_IRQ_PORTH_INTA=11 +CONFIG_IRQ_MAC_TX=11 +CONFIG_IRQ_PORTH_INTB=11 +CONFIG_IRQ_TMR0=12 +CONFIG_IRQ_TMR1=12 +CONFIG_IRQ_TMR2=12 +CONFIG_IRQ_TMR3=12 +CONFIG_IRQ_TMR4=12 +CONFIG_IRQ_TMR5=12 +CONFIG_IRQ_TMR6=12 +CONFIG_IRQ_TMR7=12 +CONFIG_IRQ_PORTG_INTA=12 +CONFIG_IRQ_PORTG_INTB=12 +CONFIG_IRQ_MEM_DMA0=13 +CONFIG_IRQ_MEM_DMA1=13 +CONFIG_IRQ_WATCH=13 +CONFIG_IRQ_PORTF_INTA=13 +CONFIG_IRQ_PORTF_INTB=13 +CONFIG_IRQ_SPI_ERROR=7 +CONFIG_IRQ_NFC_ERROR=7 +CONFIG_IRQ_HDMA_ERROR=7 +CONFIG_IRQ_HDMA=7 +CONFIG_IRQ_USB_EINT=10 +CONFIG_IRQ_USB_INT0=11 +CONFIG_IRQ_USB_INT1=11 +CONFIG_IRQ_USB_INT2=11 +CONFIG_IRQ_USB_DMA=11 + +# +# Board customizations +# +# CONFIG_CMDLINE_BOOL is not set + +# +# Clock/PLL Setup +# +CONFIG_CLKIN_HZ=25000000 +# CONFIG_BFIN_KERNEL_CLOCK is not set +CONFIG_MAX_VCO_HZ=600000000 +CONFIG_MIN_VCO_HZ=50000000 +CONFIG_MAX_SCLK_HZ=133000000 +CONFIG_MIN_SCLK_HZ=27000000 + +# +# Kernel Timer/Scheduler +# +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 + +# +# Memory Setup +# +CONFIG_MEM_SIZE=64 +CONFIG_MEM_ADD_WIDTH=10 +CONFIG_BOOT_LOAD=0x1000 +CONFIG_BFIN_SCRATCH_REG_RETN=y +# CONFIG_BFIN_SCRATCH_REG_RETE is not set +# CONFIG_BFIN_SCRATCH_REG_CYCLES is not set + +# +# Blackfin Kernel Optimizations +# + +# +# Memory Optimizations +# +CONFIG_I_ENTRY_L1=y +CONFIG_EXCPT_IRQ_SYSC_L1=y +CONFIG_DO_IRQ_L1=y +CONFIG_CORE_TIMER_IRQ_L1=y +CONFIG_IDLE_L1=y +# CONFIG_SCHEDULE_L1 is not set +CONFIG_ARITHMETIC_OPS_L1=y +CONFIG_ACCESS_OK_L1=y +# CONFIG_MEMSET_L1 is not set +# CONFIG_MEMCPY_L1 is not set +# CONFIG_SYS_BFIN_SPINLOCK_L1 is not set +# CONFIG_IP_CHECKSUM_L1 is not set +CONFIG_CACHELINE_ALIGNED_L1=y +# CONFIG_SYSCALL_TAB_L1 is not set +# CONFIG_CPLB_SWITCH_TAB_L1 is not set +CONFIG_RAMKERNEL=y +# CONFIG_ROMKERNEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_LARGE_ALLOCS=y +CONFIG_BFIN_DMA_5XX=y +# CONFIG_DMA_UNCACHED_2M is not set +CONFIG_DMA_UNCACHED_1M=y +# CONFIG_DMA_UNCACHED_NONE is not set + +# +# Cache Support +# +CONFIG_BFIN_ICACHE=y +CONFIG_BFIN_DCACHE=y +# CONFIG_BFIN_DCACHE_BANKA is not set +# CONFIG_BFIN_ICACHE_LOCK is not set +# CONFIG_BFIN_WB is not set +CONFIG_BFIN_WT=y +CONFIG_L1_MAX_PIECE=16 + +# +# Asynchonous Memory Configuration +# + +# +# EBIU_AMBCTL Global Control +# +CONFIG_C_AMCKEN=y +CONFIG_C_CDPRIO=y +# CONFIG_C_AMBEN is not set +# CONFIG_C_AMBEN_B0 is not set +# CONFIG_C_AMBEN_B0_B1 is not set +# CONFIG_C_AMBEN_B0_B1_B2 is not set +CONFIG_C_AMBEN_ALL=y + +# +# EBIU_AMBCTL Control +# +CONFIG_BANK_0=0x7BB0 +CONFIG_BANK_1=0x5554 +CONFIG_BANK_2=0x7BB0 +CONFIG_BANK_3=0xFFC0 + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +# CONFIG_PCI is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF_FDPIC=y +CONFIG_BINFMT_FLAT=y +CONFIG_BINFMT_ZFLAT=y +# CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETLABEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 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_MW320D=m +CONFIG_MTD_RAM=y +CONFIG_MTD_ROM=m +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_BF5xx=m +CONFIG_BFIN_FLASH_SIZE=0x400000 +CONFIG_EBIU_FLASH_BASE=0x20000000 +# CONFIG_MTD_UCLINUX is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_BFIN=m +CONFIG_BFIN_NAND_BASE=0x20212000 +CONFIG_BFIN_NAND_CLE=2 +CONFIG_BFIN_NAND_ALE=1 +CONFIG_BFIN_NAND_READY=3 +CONFIG_MTD_NAND_IDS=m +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ONENAND is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNPACPI is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# Misc devices +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_FIXED_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_SMC91X is not set +CONFIG_BFIN_MAC=y +CONFIG_BFIN_MAC_USE_L1=y +CONFIG_BFIN_TX_DESC_NUM=10 +CONFIG_BFIN_RX_DESC_NUM=20 +CONFIG_BFIN_MAC_RMII=y +# CONFIG_SMSC911X is not set +# CONFIG_DM9000 is not set +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_UINPUT is not set +# CONFIG_BF53X_PFBUTTONS is not set +# CONFIG_TWI_KEYPAD is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_AD9960 is not set +# CONFIG_SPI_ADC_BF533 is not set +# CONFIG_BF5xx_PFLAGS is not set +# CONFIG_BF5xx_PPIFCD is not set +# CONFIG_BF5xx_TIMERS is not set +# CONFIG_BF5xx_PPI is not set +# CONFIG_BFIN_SPORT is not set +# CONFIG_BFIN_TIMER_LATENCY is not set +# CONFIG_TWI_LCD is not set +# CONFIG_AD5304 is not set +# CONFIG_BF5xx_TEA5764 is not set +# CONFIG_BF5xx_FBDMA is not set +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_BFIN=y +CONFIG_SERIAL_BFIN_CONSOLE=y +# CONFIG_SERIAL_BFIN_DMA is not set +CONFIG_SERIAL_BFIN_PIO=y +# CONFIG_SERIAL_BFIN_UART0 is not set +CONFIG_SERIAL_BFIN_UART1=y +# CONFIG_BFIN_UART1_CTSRTS is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_BFIN_SPORT is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# CAN, the car bus and industrial fieldbus +# +# CONFIG_CAN4LINUX is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_BFIN_WDT=y +CONFIG_HW_RANDOM=y +# CONFIG_GEN_RTC is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_BLACKFIN_GPIO is not set +CONFIG_I2C_BLACKFIN_TWI=m +CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=50 +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_AD5252 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCF8575 is not set +# CONFIG_SENSORS_PCA9543 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BFIN=y +# CONFIG_SPI_BITBANG is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_AT25 is not set +# CONFIG_SPI_SPIDEV is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# HID Devices +# +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# Enable Host or Gadget support to see Inventra options +# + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_MAX6902 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_BFIN=y + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# PBX support +# +# CONFIG_PBX is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4DEV_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS 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_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_YAFFS_FS=m +CONFIG_YAFFS_YAFFS1=y +# CONFIG_YAFFS_DOES_ECC is not set +CONFIG_YAFFS_YAFFS2=y +CONFIG_YAFFS_AUTO_YAFFS2=y +# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set +CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10 +# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set +# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set +CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=m +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_ASCII 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 + +# +# Distributed Lock Manager +# +# CONFIG_DLM is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_DEBUG_MMRS=y +CONFIG_DEBUG_HUNT_FOR_ZERO=y +CONFIG_DEBUG_BFIN_HWTRACE_ON=y +CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y +# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE is not set +# CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_TWO is not set +CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0 +# CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set +# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set +CONFIG_EARLY_PRINTK=y +CONFIG_CPLB_INFO=y +CONFIG_ACCESS_CHECK=y + +# +# Security options +# +# CONFIG_KEYS is not set +CONFIG_SECURITY=y +# CONFIG_SECURITY_NETWORK is not set +CONFIG_SECURITY_CAPABILITIES=y + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig index e80f3d59c28..d8569888a1c 100644 --- a/arch/blackfin/configs/BF548-EZKIT_defconfig +++ b/arch/blackfin/configs/BF548-EZKIT_defconfig @@ -809,7 +809,14 @@ CONFIG_UNIX98_PTYS=y # IPMI # # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_BFIN_WDT=y CONFIG_HW_RANDOM=y # CONFIG_GEN_RTC is not set # CONFIG_R3964 is not set diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index 8aeb6066b19..8a4cfb293b2 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -9,6 +9,7 @@ obj-y := \ sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \ fixed_code.o cplbinit.o cacheinit.o reboot.o bfin_gpio.o +obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o obj-$(CONFIG_DUAL_CORE_TEST_MODULE) += dualcore_test.o diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index e19164fb4cd..503eef4c7fe 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c @@ -420,6 +420,32 @@ unsigned short get_dma_curr_ycount(unsigned int channel) } EXPORT_SYMBOL(get_dma_curr_ycount); +unsigned long get_dma_next_desc_ptr(unsigned int channel) +{ + BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE + && channel < MAX_BLACKFIN_DMA_CHANNEL)); + + return dma_ch[channel].regs->next_desc_ptr; +} +EXPORT_SYMBOL(get_dma_next_desc_ptr); + +unsigned long get_dma_curr_desc_ptr(unsigned int channel) +{ + BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE + && channel < MAX_BLACKFIN_DMA_CHANNEL)); + + return dma_ch[channel].regs->curr_desc_ptr; +} + +unsigned long get_dma_curr_addr(unsigned int channel) +{ + BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE + && channel < MAX_BLACKFIN_DMA_CHANNEL)); + + return dma_ch[channel].regs->curr_addr_ptr; +} +EXPORT_SYMBOL(get_dma_curr_addr); + static void *__dma_memcpy(void *dest, const void *src, size_t size) { int direction; /* 1 - address decrease, 0 - address increase */ diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 3fe0cd49e8d..ce85d4bf34c 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -124,7 +124,7 @@ static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { }; #endif -#ifdef BF537_FAMILY +#if defined(BF527_FAMILY) || defined(BF537_FAMILY) static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { (struct gpio_port_t *) PORTFIO, (struct gpio_port_t *) PORTGIO, @@ -139,6 +139,21 @@ static unsigned short *port_fer[gpio_bank(MAX_BLACKFIN_GPIOS)] = { #endif +#ifdef BF527_FAMILY +static unsigned short *port_mux[gpio_bank(MAX_BLACKFIN_GPIOS)] = { + (unsigned short *) PORTF_MUX, + (unsigned short *) PORTG_MUX, + (unsigned short *) PORTH_MUX, +}; + +static const +u8 pmux_offset[][16] = + {{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ + { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ + { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ + }; +#endif + #ifdef BF561_FAMILY static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = { (struct gpio_port_t *) FIO0_FLAG_D, @@ -186,6 +201,10 @@ static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX}; #endif +#ifdef BF527_FAMILY +static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB}; +#endif + #ifdef BF561_FAMILY static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB}; #endif @@ -238,7 +257,7 @@ static int cmp_label(unsigned short ident, const char *label) return -EINVAL; } -#ifdef BF537_FAMILY +#if defined(BF527_FAMILY) || defined(BF537_FAMILY) static void port_setup(unsigned short gpio, unsigned short usage) { if (!check_gpio(gpio)) { @@ -354,6 +373,18 @@ inline u16 get_portmux(unsigned short portno) return (pmux >> (2 * gpio_sub_n(portno)) & 0x3); } +#elif defined(BF527_FAMILY) +inline void portmux_setup(unsigned short portno, unsigned short function) +{ + u16 pmux, ident = P_IDENT(portno); + u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; + + pmux = *port_mux[gpio_bank(ident)]; + pmux &= ~(3 << offset); + pmux |= (function & 3) << offset; + *port_mux[gpio_bank(ident)] = pmux; + SSYNC(); +} #else # define portmux_setup(...) do { } while (0) #endif diff --git a/arch/blackfin/kernel/dma-mapping.c b/arch/blackfin/kernel/dma-mapping.c index 94d7b119b71..a16cb03c529 100644 --- a/arch/blackfin/kernel/dma-mapping.c +++ b/arch/blackfin/kernel/dma-mapping.c @@ -160,8 +160,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, BUG_ON(direction == DMA_NONE); for (i = 0; i < nents; i++, sg++) { - sg->dma_address = (dma_addr_t)(page_address(sg->page) + - sg->offset); + sg->dma_address = (dma_addr_t) sg_virt(sg); invalidate_dcache_range(sg_dma_address(sg), sg_dma_address(sg) + diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c new file mode 100644 index 00000000000..cb7ba9bfc79 --- /dev/null +++ b/arch/blackfin/kernel/gptimers.c @@ -0,0 +1,250 @@ +/* + * bfin_gptimers.c - derived from bf53x_timers.c + * Driver for General Purpose Timer functions on the Blackfin processor + * + * Copyright (C) 2005 John DeHority + * Copyright (C) 2006 Hella Aglaia GmbH (awe@aglaia-gmbh.de) + * + * Licensed under the GPLv2. + */ + +#include <linux/kernel.h> +#include <linux/module.h> + +#include <asm/io.h> +#include <asm/blackfin.h> +#include <asm/gptimers.h> + +#ifdef DEBUG +# define tassert(expr) +#else +# define tassert(expr) \ + if (!(expr)) \ + printk(KERN_DEBUG "%s:%s:%i: Assertion failed: " #expr "\n", \ + __FILE__, __func__, __LINE__); +#endif + +#define BFIN_TIMER_NUM_GROUP (BFIN_TIMER_OCTET(MAX_BLACKFIN_GPTIMERS - 1) + 1) + +typedef struct { + uint16_t config; + uint16_t __pad; + uint32_t counter; + uint32_t period; + uint32_t width; +} GPTIMER_timer_regs; + +typedef struct { + uint16_t enable; + uint16_t __pad0; + uint16_t disable; + uint16_t __pad1; + uint32_t status; +} GPTIMER_group_regs; + +static volatile GPTIMER_timer_regs *const timer_regs[MAX_BLACKFIN_GPTIMERS] = +{ + (GPTIMER_timer_regs *)TIMER0_CONFIG, + (GPTIMER_timer_regs *)TIMER1_CONFIG, + (GPTIMER_timer_regs *)TIMER2_CONFIG, +#if (MAX_BLACKFIN_GPTIMERS > 3) + (GPTIMER_timer_regs *)TIMER3_CONFIG, + (GPTIMER_timer_regs *)TIMER4_CONFIG, + (GPTIMER_timer_regs *)TIMER5_CONFIG, + (GPTIMER_timer_regs *)TIMER6_CONFIG, + (GPTIMER_timer_regs *)TIMER7_CONFIG, +#endif +#if (MAX_BLACKFIN_GPTIMERS > 8) + (GPTIMER_timer_regs *)TIMER8_CONFIG, + (GPTIMER_timer_regs *)TIMER9_CONFIG, + (GPTIMER_timer_regs *)TIMER10_CONFIG, + (GPTIMER_timer_regs *)TIMER11_CONFIG, +#endif +}; + +static volatile GPTIMER_group_regs *const group_regs[BFIN_TIMER_NUM_GROUP] = +{ + (GPTIMER_group_regs *)TIMER0_GROUP_REG, +#if (MAX_BLACKFIN_GPTIMERS > 8) + (GPTIMER_group_regs *)TIMER8_GROUP_REG, +#endif +}; + +static uint32_t const dis_mask[MAX_BLACKFIN_GPTIMERS] = +{ + TIMER_STATUS_TRUN0, + TIMER_STATUS_TRUN1, + TIMER_STATUS_TRUN2, +#if (MAX_BLACKFIN_GPTIMERS > 3) + TIMER_STATUS_TRUN3, + TIMER_STATUS_TRUN4, + TIMER_STATUS_TRUN5, + TIMER_STATUS_TRUN6, + TIMER_STATUS_TRUN7, +#endif +#if (MAX_BLACKFIN_GPTIMERS > 8) + TIMER_STATUS_TRUN8, + TIMER_STATUS_TRUN9, + TIMER_STATUS_TRUN10, + TIMER_STATUS_TRUN11, +#endif +}; + +static uint32_t const irq_mask[MAX_BLACKFIN_GPTIMERS] = +{ + TIMER_STATUS_TIMIL0, + TIMER_STATUS_TIMIL1, + TIMER_STATUS_TIMIL2, +#if (MAX_BLACKFIN_GPTIMERS > 3) + TIMER_STATUS_TIMIL3, + TIMER_STATUS_TIMIL4, + TIMER_STATUS_TIMIL5, + TIMER_STATUS_TIMIL6, + TIMER_STATUS_TIMIL7, +#endif +#if (MAX_BLACKFIN_GPTIMERS > 8) + TIMER_STATUS_TIMIL8, + TIMER_STATUS_TIMIL9, + TIMER_STATUS_TIMIL10, + TIMER_STATUS_TIMIL11, +#endif +}; + +void set_gptimer_pwidth(int timer_id, uint32_t value) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + timer_regs[timer_id]->width = value; + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_pwidth); + +uint32_t get_gptimer_pwidth(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return timer_regs[timer_id]->width; +} +EXPORT_SYMBOL(get_gptimer_pwidth); + +void set_gptimer_period(int timer_id, uint32_t period) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + timer_regs[timer_id]->period = period; + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_period); + +uint32_t get_gptimer_period(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return timer_regs[timer_id]->period; +} +EXPORT_SYMBOL(get_gptimer_period); + +uint32_t get_gptimer_count(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return timer_regs[timer_id]->counter; +} +EXPORT_SYMBOL(get_gptimer_count); + +uint32_t get_gptimer_status(int group) +{ + tassert(group < BFIN_TIMER_NUM_GROUP); + return group_regs[group]->status; +} +EXPORT_SYMBOL(get_gptimer_status); + +void set_gptimer_status(int group, uint32_t value) +{ + tassert(group < BFIN_TIMER_NUM_GROUP); + group_regs[group]->status = value; + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_status); + +uint16_t get_gptimer_intr(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return (group_regs[BFIN_TIMER_OCTET(timer_id)]->status & irq_mask[timer_id]) ? 1 : 0; +} +EXPORT_SYMBOL(get_gptimer_intr); + +void clear_gptimer_intr(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + group_regs[BFIN_TIMER_OCTET(timer_id)]->status = irq_mask[timer_id]; +} +EXPORT_SYMBOL(clear_gptimer_intr); + +void set_gptimer_config(int timer_id, uint16_t config) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + timer_regs[timer_id]->config = config; + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_config); + +uint16_t get_gptimer_config(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + return timer_regs[timer_id]->config; +} +EXPORT_SYMBOL(get_gptimer_config); + +void enable_gptimers(uint16_t mask) +{ + int i; + tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0); + for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) { + group_regs[i]->enable = mask & 0xFF; + mask >>= 8; + } + SSYNC(); +} +EXPORT_SYMBOL(enable_gptimers); + +void disable_gptimers(uint16_t mask) +{ + int i; + uint16_t m = mask; + tassert((mask & ~BLACKFIN_GPTIMER_IDMASK) == 0); + for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) { + group_regs[i]->disable = m & 0xFF; + m >>= 8; + } + for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i) + if (mask & (1 << i)) + group_regs[BFIN_TIMER_OCTET(i)]->status |= dis_mask[i]; + SSYNC(); +} +EXPORT_SYMBOL(disable_gptimers); + +void set_gptimer_pulse_hi(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + timer_regs[timer_id]->config |= TIMER_PULSE_HI; + SSYNC(); +} +EXPORT_SYMBOL(set_gptimer_pulse_hi); + +void clear_gptimer_pulse_hi(int timer_id) +{ + tassert(timer_id < MAX_BLACKFIN_GPTIMERS); + timer_regs[timer_id]->config &= ~TIMER_PULSE_HI; + SSYNC(); +} +EXPORT_SYMBOL(clear_gptimer_pulse_hi); + +uint16_t get_enabled_gptimers(void) +{ + int i; + uint16_t result = 0; + for (i = 0; i < BFIN_TIMER_NUM_GROUP; ++i) + result |= (group_regs[i]->enable << (i << 3)); + return result; +} +EXPORT_SYMBOL(get_enabled_gptimers); + +MODULE_AUTHOR("Axel Weiss (awe@aglaia-gmbh.de)"); +MODULE_DESCRIPTION("Blackfin General Purpose Timers API"); +MODULE_LICENSE("GPL"); diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index 356078ec462..ae28aac6fec 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -11,7 +11,7 @@ #include <asm/reboot.h> #include <asm/system.h> -#if defined(BF537_FAMILY) || defined(BF533_FAMILY) +#if defined(BF537_FAMILY) || defined(BF533_FAMILY) || defined(BF527_FAMILY) #define SYSCR_VAL 0x0 #elif defined(BF561_FAMILY) #define SYSCR_VAL 0x20 diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 8dcd76e87ed..0e746449c29 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -459,7 +459,7 @@ static u_long get_vco(void) return vco; } -/*Get the Core clock*/ +/* Get the Core clock */ u_long get_cclk(void) { u_long csel, ssel; @@ -493,12 +493,24 @@ u_long get_sclk(void) } EXPORT_SYMBOL(get_sclk); +unsigned long sclk_to_usecs(unsigned long sclk) +{ + return (USEC_PER_SEC * (u64)sclk) / get_sclk(); +} +EXPORT_SYMBOL(sclk_to_usecs); + +unsigned long usecs_to_sclk(unsigned long usecs) +{ + return get_sclk() / (USEC_PER_SEC * (u64)usecs); +} +EXPORT_SYMBOL(usecs_to_sclk); + /* * Get CPU information for use by the procfs. */ static int show_cpuinfo(struct seq_file *m, void *v) { - char *cpu, *mmu, *fpu, *name; + char *cpu, *mmu, *fpu, *vendor, *cache; uint32_t revid; u_long cclk = 0, sclk = 0; @@ -508,70 +520,83 @@ static int show_cpuinfo(struct seq_file *m, void *v) mmu = "none"; fpu = "none"; revid = bfin_revid(); - name = bfin_board_name; cclk = get_cclk(); sclk = get_sclk(); - seq_printf(m, "CPU:\t\tADSP-%s Rev. 0.%d\n" - "MMU:\t\t%s\n" - "FPU:\t\t%s\n" - "Core Clock:\t%9lu Hz\n" - "System Clock:\t%9lu Hz\n" - "BogoMips:\t%lu.%02lu\n" - "Calibration:\t%lu loops\n", - cpu, revid, mmu, fpu, - cclk, - sclk, - (loops_per_jiffy * HZ) / 500000, - ((loops_per_jiffy * HZ) / 5000) % 100, - (loops_per_jiffy * HZ)); - seq_printf(m, "Board Name:\t%s\n", name); - seq_printf(m, "Board Memory:\t%ld MB\n", physical_mem_end >> 20); - seq_printf(m, "Kernel Memory:\t%ld MB\n", (unsigned long)_ramend >> 20); - if (bfin_read_IMEM_CONTROL() & (ENICPLB | IMC)) - seq_printf(m, "I-CACHE:\tON\n"); - else - seq_printf(m, "I-CACHE:\tOFF\n"); - if ((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE)) - seq_printf(m, "D-CACHE:\tON" -#if defined CONFIG_BFIN_WB - " (write-back)" -#elif defined CONFIG_BFIN_WT - " (write-through)" -#endif - "\n"); - else - seq_printf(m, "D-CACHE:\tOFF\n"); - + switch (bfin_read_CHIPID() & CHIPID_MANUFACTURE) { + case 0xca: + vendor = "Analog Devices"; + break; + default: + vendor = "unknown"; + break; + } + seq_printf(m, "processor\t: %d\n" + "vendor_id\t: %s\n" + "cpu family\t: 0x%x\n" + "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK)\n" + "stepping\t: %d\n", + 0, + vendor, + (bfin_read_CHIPID() & CHIPID_FAMILY), + cpu, cclk/1000000, sclk/1000000, + revid); + + seq_printf(m, "cpu MHz\t\t: %lu.%03lu/%lu.%03lu\n", + cclk/1000000, cclk%1000000, + sclk/1000000, sclk%1000000); + seq_printf(m, "bogomips\t: %lu.%02lu\n" + "Calibration\t: %lu loops\n", + (loops_per_jiffy * HZ) / 500000, + ((loops_per_jiffy * HZ) / 5000) % 100, + (loops_per_jiffy * HZ)); + + /* Check Cache configutation */ switch (bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) { case ACACHE_BSRAM: - seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n"); + cache = "dbank-A/B\t: cache/sram"; dcache_size = 16; dsup_banks = 1; break; case ACACHE_BCACHE: - seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n"); + cache = "dbank-A/B\t: cache/cache"; dcache_size = 32; dsup_banks = 2; break; case ASRAM_BSRAM: - seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n"); + cache = "dbank-A/B\t: sram/sram"; dcache_size = 0; dsup_banks = 0; break; default: + cache = "unknown"; + dcache_size = 0; + dsup_banks = 0; break; } + /* Is it turned on? */ + if (!((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE))) + dcache_size = 0; - seq_printf(m, "I-CACHE Size:\t%dKB\n", BFIN_ICACHESIZE / 1024); - seq_printf(m, "D-CACHE Size:\t%dKB\n", dcache_size); - seq_printf(m, "I-CACHE Setup:\t%d Sub-banks/%d Ways, %d Lines/Way\n", + seq_printf(m, "cache size\t: %d KB(L1 icache) " + "%d KB(L1 dcache-%s) %d KB(L2 cache)\n", + BFIN_ICACHESIZE / 1024, dcache_size, +#if defined CONFIG_BFIN_WB + "wb" +#elif defined CONFIG_BFIN_WT + "wt" +#endif + , 0); + + seq_printf(m, "%s\n", cache); + + seq_printf(m, "icache setup\t: %d Sub-banks/%d Ways, %d Lines/Way\n", BFIN_ISUBBANKS, BFIN_IWAYS, BFIN_ILINES); seq_printf(m, - "D-CACHE Setup:\t%d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n", + "dcache setup\t: %d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n", dsup_banks, BFIN_DSUBBANKS, BFIN_DWAYS, BFIN_DLINES); #ifdef CONFIG_BFIN_ICACHE_LOCK @@ -625,6 +650,15 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "No Ways are locked\n"); } #endif + + seq_printf(m, "board name\t: %s\n", bfin_board_name); + seq_printf(m, "board memory\t: %ld kB (0x%p -> 0x%p)\n", + physical_mem_end >> 10, (void *)0, (void *)physical_mem_end); + seq_printf(m, "kernel memory\t: %d kB (0x%p -> 0x%p)\n", + ((int)memory_end - (int)_stext) >> 10, + _stext, + (void *)memory_end); + return 0; } diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 8823e9ade58..afd044e78af 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -118,12 +118,14 @@ static int printk_address(unsigned long address) offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); write_unlock_irq(&tasklist_lock); + mmput(mm); return printk("<0x%p> [ %s + 0x%lx ]", (void *)address, name, offset); } vml = vml->next; } + mmput(mm); } write_unlock_irq(&tasklist_lock); diff --git a/arch/blackfin/lib/Makefile b/arch/blackfin/lib/Makefile index 635288fc5f5..bfdad52c570 100644 --- a/arch/blackfin/lib/Makefile +++ b/arch/blackfin/lib/Makefile @@ -4,7 +4,7 @@ lib-y := \ ashldi3.o ashrdi3.o lshrdi3.o \ - muldi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \ + muldi3.o divsi3.o udivsi3.o udivdi3.o modsi3.o umodsi3.o \ checksum.o memcpy.o memset.o memcmp.o memchr.o memmove.o \ strcmp.o strcpy.o strncmp.o strncpy.o \ umulsi3_highpart.o smulsi3_highpart.o \ diff --git a/arch/blackfin/lib/udivdi3.S b/arch/blackfin/lib/udivdi3.S new file mode 100644 index 00000000000..ad1ebee675e --- /dev/null +++ b/arch/blackfin/lib/udivdi3.S @@ -0,0 +1,375 @@ +/* + * udivdi3.S - unsigned long long division + * + * Copyright 2003-2007 Analog Devices Inc. + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPLv2 or later. + */ + +#include <linux/linkage.h> + +#define CARRY AC0 + +#ifdef CONFIG_ARITHMETIC_OPS_L1 +.section .l1.text +#else +.text +#endif + + +ENTRY(___udivdi3) + R3 = [SP + 12]; + [--SP] = (R7:4, P5:3); + + /* Attempt to use divide primitive first; these will handle + ** most cases, and they're quick - avoids stalls incurred by + ** testing for identities. + */ + + R4 = R2 | R3; + CC = R4 == 0; + IF CC JUMP .LDIV_BY_ZERO; + + R4.H = 0x8000; + R4 >>>= 16; // R4 now 0xFFFF8000 + R5 = R0 | R2; // If either dividend or + R4 = R5 & R4; // divisor have bits in + CC = R4; // top half or low half's sign + IF CC JUMP .LIDENTS; // bit, skip builtins. + R4 = R1 | R3; // Also check top halves + CC = R4; + IF CC JUMP .LIDENTS; + + /* Can use the builtins. */ + + AQ = CC; // Clear AQ (CC==0) + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + DIVQ(R0, R2); + R0 = R0.L (Z); + R1 = 0; + (R7:4, P5:3) = [SP++]; + RTS; + +.LIDENTS: + /* Test for common identities. Value to be returned is + ** placed in R6,R7. + */ + // Check for 0/y, return 0 + R4 = R0 | R1; + CC = R4 == 0; + IF CC JUMP .LRETURN_R0; + + // Check for x/x, return 1 + R6 = R0 - R2; // If x == y, then both R6 and R7 will be zero + R7 = R1 - R3; + R4 = R6 | R7; // making R4 zero. + R6 += 1; // which would now make R6:R7==1. + CC = R4 == 0; + IF CC JUMP .LRETURN_IDENT; + + // Check for x/1, return x + R6 = R0; + R7 = R1; + CC = R3 == 0; + IF !CC JUMP .Lnexttest; + CC = R2 == 1; + IF CC JUMP .LRETURN_IDENT; + +.Lnexttest: + R4.L = ONES R2; // check for div by power of two which + R5.L = ONES R3; // can be done using a shift + R6 = PACK (R5.L, R4.L); + CC = R6 == 1; + IF CC JUMP .Lpower_of_two_upper_zero; + R6 = PACK (R4.L, R5.L); + CC = R6 == 1; + IF CC JUMP .Lpower_of_two_lower_zero; + + // Check for x < y, return 0 + R6 = 0; + R7 = R6; + CC = R1 < R3 (IU); + IF CC JUMP .LRETURN_IDENT; + CC = R1 == R3; + IF !CC JUMP .Lno_idents; + CC = R0 < R2 (IU); + IF CC JUMP .LRETURN_IDENT; + +.Lno_idents: // Idents don't match. Go for the full operation + + + // If X, or X and Y have high bit set, it'll affect the + // results, so shift right one to stop this. Note: we've already + // checked that X >= Y, so Y's msb won't be set unless X's + // is. + + R4 = 0; + CC = R1 < 0; + IF !CC JUMP .Lx_msb_clear; + CC = !CC; // 1 -> 0; + R1 = ROT R1 BY -1; // Shift X >> 1 + R0 = ROT R0 BY -1; // lsb -> CC + BITSET(R4,31); // to record only x msb was set + CC = R3 < 0; + IF !CC JUMP .Ly_msb_clear; + CC = !CC; + R3 = ROT R3 BY -1; // Shift Y >> 1 + R2 = ROT R2 BY -1; + BITCLR(R4,31); // clear bit to record only x msb was set + +.Ly_msb_clear: +.Lx_msb_clear: + // Bit 31 in R4 indicates X msb set, but Y msb wasn't, and no bits + // were lost, so we should shift result left by one. + + [--SP] = R4; // save for later + + // In the loop that follows, each iteration we add + // either Y' or -Y' to the Remainder. We compute the + // negated Y', and store, for convenience. Y' goes + // into P0:P1, while -Y' goes into P2:P3. + + P0 = R2; + P1 = R3; + R2 = -R2; + CC = CARRY; + CC = !CC; + R4 = CC; + R3 = -R3; + R3 = R3 - R4; + + R6 = 0; // remainder = 0 + R7 = R6; + + [--SP] = R2; P2 = SP; + [--SP] = R3; P3 = SP; + [--SP] = R6; P5 = SP; // AQ = 0 + [--SP] = P1; + + /* In the loop that follows, we use the following + ** register assignments: + ** R0,R1 X, workspace + ** R2,R3 Y, workspace + ** R4,R5 partial Div + ** R6,R7 partial remainder + ** P5 AQ + ** The remainder and div form a 128-bit number, with + ** the remainder in the high 64-bits. + */ + R4 = R0; // Div = X' + R5 = R1; + R3 = 0; + + P4 = 64; // Iterate once per bit + LSETUP(.LULST,.LULEND) LC0 = P4; +.LULST: + /* Shift Div and remainder up by one. The bit shifted + ** out of the top of the quotient is shifted into the bottom + ** of the remainder. + */ + CC = R3; + R4 = ROT R4 BY 1; + R5 = ROT R5 BY 1 || // low q to high q + R2 = [P5]; // load saved AQ + R6 = ROT R6 BY 1 || // high q to low r + R0 = [P2]; // load -Y' + R7 = ROT R7 BY 1 || // low r to high r + R1 = [P3]; + + // Assume add -Y' + CC = R2 < 0; // But if AQ is set... + IF CC R0 = P0; // then add Y' instead + IF CC R1 = P1; + + R6 = R6 + R0; // Rem += (Y' or -Y') + CC = CARRY; + R0 = CC; + R7 = R7 + R1; + R7 = R7 + R0 (NS) || + R1 = [SP]; + // Set the next AQ bit + R1 = R7 ^ R1; // from Remainder and Y' + R1 = R1 >> 31 || // Negate AQ's value, and + [P5] = R1; // save next AQ + BITTGL(R1, 0); // add neg AQ to the Div +.LULEND: R4 = R4 + R1; + + R6 = [SP + 16]; + + R0 = R4; + R1 = R5; + CC = BITTST(R6,30); // Just set CC=0 + R4 = ROT R0 BY 1; // but if we had to shift X, + R5 = ROT R1 BY 1; // and didn't shift any bits out, + CC = BITTST(R6,31); // then the result will be half as + IF CC R0 = R4; // much as required, so shift left + IF CC R1 = R5; // one space. + + SP += 20; + (R7:4, P5:3) = [SP++]; + RTS; + +.Lpower_of_two: + /* Y has a single bit set, which means it's a power of two. + ** That means we can perform the division just by shifting + ** X to the right the appropriate number of bits + */ + + /* signbits returns the number of sign bits, minus one. + ** 1=>30, 2=>29, ..., 0x40000000=>0. Which means we need + ** to shift right n-signbits spaces. It also means 0x80000000 + ** is a special case, because that *also* gives a signbits of 0 + */ +.Lpower_of_two_lower_zero: + R7 = 0; + R6 = R1 >> 31; + CC = R3 < 0; + IF CC JUMP .LRETURN_IDENT; + + R2.L = SIGNBITS R3; + R2 = R2.L (Z); + R2 += -62; + (R7:4, P5:3) = [SP++]; + JUMP ___lshftli; + +.Lpower_of_two_upper_zero: + CC = R2 < 0; + IF CC JUMP .Lmaxint_shift; + + R2.L = SIGNBITS R2; + R2 = R2.L (Z); + R2 += -30; + (R7:4, P5:3) = [SP++]; + JUMP ___lshftli; + +.Lmaxint_shift: + R2 = -31; + (R7:4, P5:3) = [SP++]; + JUMP ___lshftli; + +.LRETURN_IDENT: + R0 = R6; + R1 = R7; +.LRETURN_R0: + (R7:4, P5:3) = [SP++]; + RTS; +.LDIV_BY_ZERO: + R0 = ~R2; + R1 = R0; + (R7:4, P5:3) = [SP++]; + RTS; + +ENDPROC(___udivdi3) + + +ENTRY(___lshftli) + CC = R2 == 0; + IF CC JUMP .Lfinished; // nothing to do + CC = R2 < 0; + IF CC JUMP .Lrshift; + R3 = 64; + CC = R2 < R3; + IF !CC JUMP .Lretzero; + + // We're shifting left, and it's less than 64 bits, so + // a valid result will be returned. + + R3 >>= 1; // R3 now 32 + CC = R2 < R3; + + IF !CC JUMP .Lzerohalf; + + // We're shifting left, between 1 and 31 bits, which means + // some of the low half will be shifted into the high half. + // Work out how much. + + R3 = R3 - R2; + + // Save that much data from the bottom half. + + P1 = R7; + R7 = R0; + R7 >>= R3; + + // Adjust both parts of the parameter. + + R0 <<= R2; + R1 <<= R2; + + // And include the bits moved across. + + R1 = R1 | R7; + R7 = P1; + RTS; + +.Lzerohalf: + // We're shifting left, between 32 and 63 bits, so the + // bottom half will become zero, and the top half will + // lose some bits. How many? + + R2 = R2 - R3; // N - 32 + R1 = LSHIFT R0 BY R2.L; + R0 = R0 - R0; + RTS; + +.Lretzero: + R0 = R0 - R0; + R1 = R0; +.Lfinished: + RTS; + +.Lrshift: + // We're shifting right, but by how much? + R2 = -R2; + R3 = 64; + CC = R2 < R3; + IF !CC JUMP .Lretzero; + + // Shifting right less than 64 bits, so some result bits will + // be retained. + + R3 >>= 1; // R3 now 32 + CC = R2 < R3; + IF !CC JUMP .Lsignhalf; + + // Shifting right between 1 and 31 bits, so need to copy + // data across words. + + P1 = R7; + R3 = R3 - R2; + R7 = R1; + R7 <<= R3; + R1 >>= R2; + R0 >>= R2; + R0 = R7 | R0; + R7 = P1; + RTS; + +.Lsignhalf: + // Shifting right between 32 and 63 bits, so the top half + // will become all zero-bits, and the bottom half is some + // of the top half. But how much? + + R2 = R2 - R3; + R0 = R1; + R0 >>= R2; + R1 = 0; + RTS; + +ENDPROC(___lshftli) diff --git a/arch/blackfin/mach-bf527/Kconfig b/arch/blackfin/mach-bf527/Kconfig new file mode 100644 index 00000000000..50321f723de --- /dev/null +++ b/arch/blackfin/mach-bf527/Kconfig @@ -0,0 +1,251 @@ +if (BF52x) + +menu "BF527 Specific Configuration" + +comment "Alternative Multiplexing Scheme" + +choice + prompt "SPORT0" + default BF527_SPORT0_PORTG + help + Select PORT used for SPORT0. See Hardware Reference Manual + +config BF527_SPORT0_PORTF + bool "PORT F" + help + PORT F + +config BF527_SPORT0_PORTG + bool "PORT G" + help + PORT G +endchoice + +choice + prompt "SPORT0 TSCLK Location" + depends on BF527_SPORT0_PORTG + default BF527_SPORT0_TSCLK_PG10 + help + Select PIN used for SPORT0_TSCLK. See Hardware Reference Manual + +config BF527_SPORT0_TSCLK_PG10 + bool "PORT PG10" + help + PORT PG10 + +config BF527_SPORT0_TSCLK_PG14 + bool "PORT PG14" + help + PORT PG14 +endchoice + +choice + prompt "UART1" + default BF527_UART1_PORTG + help + Select PORT used for UART1. See Hardware Reference Manual + +config BF527_UART1_PORTF + bool "PORT F" + help + PORT F + +config BF527_UART1_PORTG + bool "PORT G" + help + PORT G +endchoice + +choice + prompt "NAND (NFC) Data" + default BF527_NAND_D_PORTH + help + Select PORT used for NAND Data Bus. See Hardware Reference Manual + +config BF527_NAND_D_PORTF + bool "PORT F" + help + PORT F + +config BF527_NAND_D_PORTH + bool "PORT H" + help + PORT H +endchoice + +comment "Interrupt Priority Assignment" +menu "Priority" + +config IRQ_PLL_WAKEUP + int "IRQ_PLL_WAKEUP" + default 7 +config IRQ_DMA0_ERROR + int "IRQ_DMA0_ERROR" + default 7 +config IRQ_DMAR0_BLK + int "IRQ_DMAR0_BLK" + default 7 +config IRQ_DMAR1_BLK + int "IRQ_DMAR1_BLK" + default 7 +config IRQ_DMAR0_OVR + int "IRQ_DMAR0_OVR" + default 7 +config IRQ_DMAR1_OVR + int "IRQ_DMAR1_OVR" + default 7 +config IRQ_PPI_ERROR + int "IRQ_PPI_ERROR" + default 7 +config IRQ_MAC_ERROR + int "IRQ_MAC_ERROR" + default 7 +config IRQ_SPORT0_ERROR + int "IRQ_SPORT0_ERROR" + default 7 +config IRQ_SPORT1_ERROR + int "IRQ_SPORT1_ERROR" + default 7 +config IRQ_UART0_ERROR + int "IRQ_UART0_ERROR" + default 7 +config IRQ_UART1_ERROR + int "IRQ_UART1_ERROR" + default 7 +config IRQ_RTC + int "IRQ_RTC" + default 8 +config IRQ_PPI + int "IRQ_PPI" + default 8 +config IRQ_SPORT0_RX + int "IRQ_SPORT0_RX" + default 9 +config IRQ_SPORT0_TX + int "IRQ_SPORT0_TX" + default 9 +config IRQ_SPORT1_RX + int "IRQ_SPORT1_RX" + default 9 +config IRQ_SPORT1_TX + int "IRQ_SPORT1_TX" + default 9 +config IRQ_TWI + int "IRQ_TWI" + default 10 +config IRQ_SPI + int "IRQ_SPI" + default 10 +config IRQ_UART0_RX + int "IRQ_UART0_RX" + default 10 +config IRQ_UART0_TX + int "IRQ_UART0_TX" + default 10 +config IRQ_UART1_RX + int "IRQ_UART1_RX" + default 10 +config IRQ_UART1_TX + int "IRQ_UART1_TX" + default 10 +config IRQ_OPTSEC + int "IRQ_OPTSEC" + default 11 +config IRQ_CNT + int "IRQ_CNT" + default 11 +config IRQ_MAC_RX + int "IRQ_MAC_RX" + default 11 +config IRQ_PORTH_INTA + int "IRQ_PORTH_INTA" + default 11 +config IRQ_MAC_TX + int "IRQ_MAC_TX/NFC" + default 11 +config IRQ_PORTH_INTB + int "IRQ_PORTH_INTB" + default 11 +config IRQ_TMR0 + int "IRQ_TMR0" + default 12 +config IRQ_TMR1 + int "IRQ_TMR1" + default 12 +config IRQ_TMR2 + int "IRQ_TMR2" + default 12 +config IRQ_TMR3 + int "IRQ_TMR3" + default 12 +config IRQ_TMR4 + int "IRQ_TMR4" + default 12 +config IRQ_TMR5 + int "IRQ_TMR5" + default 12 +config IRQ_TMR6 + int "IRQ_TMR6" + default 12 +config IRQ_TMR7 + int "IRQ_TMR7" + default 12 +config IRQ_PORTG_INTA + int "IRQ_PORTG_INTA" + default 12 +config IRQ_PORTG_INTB + int "IRQ_PORTG_INTB" + default 12 +config IRQ_MEM_DMA0 + int "IRQ_MEM_DMA0" + default 13 +config IRQ_MEM_DMA1 + int "IRQ_MEM_DMA1" + default 13 +config IRQ_WATCH + int "IRQ_WATCH" + default 13 +config IRQ_PORTF_INTA + int "IRQ_PORTF_INTA" + default 13 +config IRQ_PORTF_INTB + int "IRQ_PORTF_INTB" + default 13 +config IRQ_SPI_ERROR + int "IRQ_SPI_ERROR" + default 7 +config IRQ_NFC_ERROR + int "IRQ_NFC_ERROR" + default 7 +config IRQ_HDMA_ERROR + int "IRQ_HDMA_ERROR" + default 7 +config IRQ_HDMA + int "IRQ_HDMA" + default 7 +config IRQ_USB_EINT + int "IRQ_USB_EINT" + default 10 +config IRQ_USB_INT0 + int "IRQ_USB_INT0" + default 10 +config IRQ_USB_INT1 + int "IRQ_USB_INT1" + default 10 +config IRQ_USB_INT2 + int "IRQ_USB_INT2" + default 10 +config IRQ_USB_DMA + int "IRQ_USB_DMA" + default 10 + + help + Enter the priority numbers between 7-13 ONLY. Others are Reserved. + This applies to all the above. It is not recommended to assign the + highest priority number 7 to UART or any other device. + +endmenu + +endmenu + +endif diff --git a/arch/blackfin/mach-bf527/Makefile b/arch/blackfin/mach-bf527/Makefile new file mode 100644 index 00000000000..9f99f5d0bcd --- /dev/null +++ b/arch/blackfin/mach-bf527/Makefile @@ -0,0 +1,9 @@ +# +# arch/blackfin/mach-bf527/Makefile +# + +extra-y := head.o + +obj-y := ints-priority.o dma.o + +obj-$(CONFIG_CPU_FREQ) += cpu.o diff --git a/arch/blackfin/mach-bf527/boards/Makefile b/arch/blackfin/mach-bf527/boards/Makefile new file mode 100644 index 00000000000..912ac8ebc88 --- /dev/null +++ b/arch/blackfin/mach-bf527/boards/Makefile @@ -0,0 +1,7 @@ +# +# arch/blackfin/mach-bf532/boards/Makefile +# + +obj-y += eth_mac.o +obj-$(CONFIG_BFIN527_EZKIT) += ezkit.o + diff --git a/arch/blackfin/mach-bf527/boards/eth_mac.c b/arch/blackfin/mach-bf527/boards/eth_mac.c new file mode 100644 index 00000000000..a725cc8a929 --- /dev/null +++ b/arch/blackfin/mach-bf527/boards/eth_mac.c @@ -0,0 +1,50 @@ +/* + * arch/blackfin/mach-bf537/board/eth_mac.c + * + * Copyright (C) 2007 Analog Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/module.h> +#include <asm/blackfin.h> + +#if defined(CONFIG_GENERIC_BOARD) || defined(CONFIG_BFIN537_STAMP) + +/* + * Currently the MAC address is saved in Flash by U-Boot + */ +#define FLASH_MAC 0x203f0000 + +void get_bf537_ether_addr(char *addr) +{ + unsigned int flash_mac = (unsigned int) FLASH_MAC; + *(u32 *)(&(addr[0])) = bfin_read32(flash_mac); + flash_mac += 4; + *(u16 *)(&(addr[4])) = bfin_read16(flash_mac); +} + +#else + +/* + * Provide MAC address function for other specific board setting + */ +void get_bf537_ether_addr(char *addr) +{ + printk(KERN_WARNING "%s: No valid Ethernet MAC address found\n", __FILE__); +} + +#endif + +EXPORT_SYMBOL(get_bf537_ether_addr); diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c new file mode 100644 index 00000000000..3e884f3a818 --- /dev/null +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -0,0 +1,737 @@ +/* + * File: arch/blackfin/mach-bf527/boards/ezkit.c + * Based on: arch/blackfin/mach-bf537/boards/stamp.c + * Author: Aidan Williams <aidan@nicta.com.au> + * + * Created: + * Description: + * + * Modified: + * Copyright 2005 National ICT Australia (NICTA) + * Copyright 2004-2007 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> +#include <linux/spi/spi.h> +#include <linux/spi/flash.h> +#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) +#include <linux/usb_isp1362.h> +#endif +#include <linux/pata_platform.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/usb_sl811.h> +#include <asm/dma.h> +#include <asm/bfin5xx_spi.h> +#include <asm/reboot.h> +#include <linux/spi/ad7877.h> + +/* + * Name the Board for the /proc/cpuinfo + */ +const char bfin_board_name[] = "ADDS-BF527-EZKIT"; + +/* + * Driver needs to know address, irq and flag pin. + */ + +#define ISP1761_BASE 0x203C0000 +#define ISP1761_IRQ IRQ_PF7 + +#if defined(CONFIG_USB_ISP1760_HCD) || defined(CONFIG_USB_ISP1760_HCD_MODULE) +static struct resource bfin_isp1761_resources[] = { + [0] = { + .name = "isp1761-regs", + .start = ISP1761_BASE + 0x00000000, + .end = ISP1761_BASE + 0x000fffff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = ISP1761_IRQ, + .end = ISP1761_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_isp1761_device = { + .name = "isp1761", + .id = 0, + .num_resources = ARRAY_SIZE(bfin_isp1761_resources), + .resource = bfin_isp1761_resources, +}; + +static struct platform_device *bfin_isp1761_devices[] = { + &bfin_isp1761_device, +}; + +int __init bfin_isp1761_init(void) +{ + unsigned int num_devices = ARRAY_SIZE(bfin_isp1761_devices); + + printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__); + set_irq_type(ISP1761_IRQ, IRQF_TRIGGER_FALLING); + + return platform_add_devices(bfin_isp1761_devices, num_devices); +} + +void __exit bfin_isp1761_exit(void) +{ + platform_device_unregister(&bfin_isp1761_device); +} + +arch_initcall(bfin_isp1761_init); +#endif + +#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE) +static struct resource bfin_pcmcia_cf_resources[] = { + { + .start = 0x20310000, /* IO PORT */ + .end = 0x20312000, + .flags = IORESOURCE_MEM, + }, { + .start = 0x20311000, /* Attribute Memory */ + .end = 0x20311FFF, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_PF4, + .end = IRQ_PF4, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, + }, { + .start = 6, /* Card Detect PF6 */ + .end = 6, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_pcmcia_cf_device = { + .name = "bfin_cf_pcmcia", + .id = -1, + .num_resources = ARRAY_SIZE(bfin_pcmcia_cf_resources), + .resource = bfin_pcmcia_cf_resources, +}; +#endif + +#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) +static struct platform_device rtc_device = { + .name = "rtc-bfin", + .id = -1, +}; +#endif + +#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) +static struct resource smc91x_resources[] = { + { + .name = "smc91x-regs", + .start = 0x20300300, + .end = 0x20300300 + 16, + .flags = IORESOURCE_MEM, + }, { + + .start = IRQ_PF7, + .end = IRQ_PF7, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, + }, +}; +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; +#endif + +#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) +static struct resource dm9000_resources[] = { + [0] = { + .start = 0x203FB800, + .end = 0x203FB800 + 8, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_PF9, + .end = IRQ_PF9, + .flags = (IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE), + }, +}; + +static struct platform_device dm9000_device = { + .name = "dm9000", + .id = -1, + .num_resources = ARRAY_SIZE(dm9000_resources), + .resource = dm9000_resources, +}; +#endif + +#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE) +static struct resource sl811_hcd_resources[] = { + { + .start = 0x20340000, + .end = 0x20340000, + .flags = IORESOURCE_MEM, + }, { + .start = 0x20340004, + .end = 0x20340004, + .flags = IORESOURCE_MEM, + }, { + .start = CONFIG_USB_SL811_BFIN_IRQ, + .end = CONFIG_USB_SL811_BFIN_IRQ, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, + }, +}; + +#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS) +void sl811_port_power(struct device *dev, int is_on) +{ + gpio_request(CONFIG_USB_SL811_BFIN_GPIO_VBUS, "usb:SL811_VBUS"); + gpio_direction_output(CONFIG_USB_SL811_BFIN_GPIO_VBUS); + + if (is_on) + gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 1); + else + gpio_set_value(CONFIG_USB_SL811_BFIN_GPIO_VBUS, 0); +} +#endif + +static struct sl811_platform_data sl811_priv = { + .potpg = 10, + .power = 250, /* == 500mA */ +#if defined(CONFIG_USB_SL811_BFIN_USE_VBUS) + .port_power = &sl811_port_power, +#endif +}; + +static struct platform_device sl811_hcd_device = { + .name = "sl811-hcd", + .id = 0, + .dev = { + .platform_data = &sl811_priv, + }, + .num_resources = ARRAY_SIZE(sl811_hcd_resources), + .resource = sl811_hcd_resources, +}; +#endif + +#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) +static struct resource isp1362_hcd_resources[] = { + { + .start = 0x20360000, + .end = 0x20360000, + .flags = IORESOURCE_MEM, + }, { + .start = 0x20360004, + .end = 0x20360004, + .flags = IORESOURCE_MEM, + }, { + .start = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ, + .end = CONFIG_USB_ISP1362_BFIN_GPIO_IRQ, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, + }, +}; + +static struct isp1362_platform_data isp1362_priv = { + .sel15Kres = 1, + .clknotstop = 0, + .oc_enable = 0, + .int_act_high = 0, + .int_edge_triggered = 0, + .remote_wakeup_connected = 0, + .no_power_switching = 1, + .power_switching_mode = 0, +}; + +static struct platform_device isp1362_hcd_device = { + .name = "isp1362-hcd", + .id = 0, + .dev = { + .platform_data = &isp1362_priv, + }, + .num_resources = ARRAY_SIZE(isp1362_hcd_resources), + .resource = isp1362_hcd_resources, +}; +#endif + +#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mac_device = { + .name = "bfin_mac", +}; +#endif + +#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE) +static struct resource net2272_bfin_resources[] = { + { + .start = 0x20300000, + .end = 0x20300000 + 0x100, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_PF7, + .end = IRQ_PF7, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL, + }, +}; + +static struct platform_device net2272_bfin_device = { + .name = "net2272", + .id = -1, + .num_resources = ARRAY_SIZE(net2272_bfin_resources), + .resource = net2272_bfin_resources, +}; +#endif + +#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) +/* all SPI peripherals info goes here */ + +#if defined(CONFIG_MTD_M25P80) \ + || defined(CONFIG_MTD_M25P80_MODULE) +static struct mtd_partition bfin_spi_flash_partitions[] = { + { + .name = "bootloader", + .size = 0x00020000, + .offset = 0, + .mask_flags = MTD_CAP_ROM + }, { + .name = "kernel", + .size = 0xe0000, + .offset = 0x20000 + }, { + .name = "file system", + .size = 0x700000, + .offset = 0x00100000, + } +}; + +static struct flash_platform_data bfin_spi_flash_data = { + .name = "m25p80", + .parts = bfin_spi_flash_partitions, + .nr_parts = ARRAY_SIZE(bfin_spi_flash_partitions), + .type = "m25p64", +}; + +/* SPI flash chip (m25p64) */ +static struct bfin5xx_spi_chip spi_flash_chip_info = { + .enable_dma = 0, /* use dma transfer with this chip*/ + .bits_per_word = 8, +}; +#endif + +#if defined(CONFIG_SPI_ADC_BF533) \ + || defined(CONFIG_SPI_ADC_BF533_MODULE) +/* SPI ADC chip */ +static struct bfin5xx_spi_chip spi_adc_chip_info = { + .enable_dma = 1, /* use dma transfer with this chip*/ + .bits_per_word = 16, +}; +#endif + +#if defined(CONFIG_SND_BLACKFIN_AD1836) \ + || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE) +static struct bfin5xx_spi_chip ad1836_spi_chip_info = { + .enable_dma = 0, + .bits_per_word = 16, +}; +#endif + +#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE) +static struct bfin5xx_spi_chip ad9960_spi_chip_info = { + .enable_dma = 0, + .bits_per_word = 16, +}; +#endif + +#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) +static struct bfin5xx_spi_chip spi_mmc_chip_info = { + .enable_dma = 1, + .bits_per_word = 8, +}; +#endif + +#if defined(CONFIG_PBX) +static struct bfin5xx_spi_chip spi_si3xxx_chip_info = { + .ctl_reg = 0x4, /* send zero */ + .enable_dma = 0, + .bits_per_word = 8, + .cs_change_per_word = 1, +}; +#endif + +#if defined(CONFIG_AD5304) || defined(CONFIG_AD5304_MODULE) +static struct bfin5xx_spi_chip ad5304_chip_info = { + .enable_dma = 0, + .bits_per_word = 16, +}; +#endif + +#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE) +static struct bfin5xx_spi_chip spi_ad7877_chip_info = { + .enable_dma = 0, + .bits_per_word = 16, +}; + +static const struct ad7877_platform_data bfin_ad7877_ts_info = { + .model = 7877, + .vref_delay_usecs = 50, /* internal, no capacitor */ + .x_plate_ohms = 419, + .y_plate_ohms = 486, + .pressure_max = 1000, + .pressure_min = 0, + .stopacq_polarity = 1, + .first_conversion_delay = 3, + .acquisition_time = 1, + .averaging = 1, + .pen_down_acc_interval = 1, +}; +#endif + +static struct spi_board_info bfin_spi_board_info[] __initdata = { +#if defined(CONFIG_MTD_M25P80) \ + || defined(CONFIG_MTD_M25P80_MODULE) + { + /* the modalias must be the same as spi device driver name */ + .modalias = "m25p80", /* Name of spi_driver for this device */ + .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, /* Framework bus number */ + .chip_select = 1, /* Framework chip select. On STAMP537 it is SPISSEL1*/ + .platform_data = &bfin_spi_flash_data, + .controller_data = &spi_flash_chip_info, + .mode = SPI_MODE_3, + }, +#endif + +#if defined(CONFIG_SPI_ADC_BF533) \ + || defined(CONFIG_SPI_ADC_BF533_MODULE) + { + .modalias = "bfin_spi_adc", /* Name of spi_driver for this device */ + .max_speed_hz = 6250000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, /* Framework bus number */ + .chip_select = 1, /* Framework chip select. */ + .platform_data = NULL, /* No spi_driver specific config */ + .controller_data = &spi_adc_chip_info, + }, +#endif + +#if defined(CONFIG_SND_BLACKFIN_AD1836) \ + || defined(CONFIG_SND_BLACKFIN_AD1836_MODULE) + { + .modalias = "ad1836-spi", + .max_speed_hz = 3125000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = CONFIG_SND_BLACKFIN_SPI_PFBIT, + .controller_data = &ad1836_spi_chip_info, + }, +#endif +#if defined(CONFIG_AD9960) || defined(CONFIG_AD9960_MODULE) + { + .modalias = "ad9960-spi", + .max_speed_hz = 10000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 1, + .controller_data = &ad9960_spi_chip_info, + }, +#endif +#if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) + { + .modalias = "spi_mmc_dummy", + .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 0, + .platform_data = NULL, + .controller_data = &spi_mmc_chip_info, + .mode = SPI_MODE_3, + }, + { + .modalias = "spi_mmc", + .max_speed_hz = 25000000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = CONFIG_SPI_MMC_CS_CHAN, + .platform_data = NULL, + .controller_data = &spi_mmc_chip_info, + .mode = SPI_MODE_3, + }, +#endif +#if defined(CONFIG_PBX) + { + .modalias = "fxs-spi", + .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 8 - CONFIG_J11_JUMPER, + .controller_data = &spi_si3xxx_chip_info, + .mode = SPI_MODE_3, + }, + { + .modalias = "fxo-spi", + .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 8 - CONFIG_J19_JUMPER, + .controller_data = &spi_si3xxx_chip_info, + .mode = SPI_MODE_3, + }, +#endif +#if defined(CONFIG_AD5304) || defined(CONFIG_AD5304_MODULE) + { + .modalias = "ad5304_spi", + .max_speed_hz = 1250000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 0, + .chip_select = 2, + .platform_data = NULL, + .controller_data = &ad5304_chip_info, + .mode = SPI_MODE_2, + }, +#endif +#if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE) + { + .modalias = "ad7877", + .platform_data = &bfin_ad7877_ts_info, + .irq = IRQ_PF6, + .max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */ + .bus_num = 1, + .chip_select = 1, + .controller_data = &spi_ad7877_chip_info, + }, +#endif +}; + +/* SPI controller data */ +static struct bfin5xx_spi_master bfin_spi0_info = { + .num_chipselect = 8, + .enable_dma = 1, /* master has the ability to do dma transfer */ +}; + +/* SPI (0) */ +static struct resource bfin_spi0_resource[] = { + [0] = { + .start = SPI0_REGBASE, + .end = SPI0_REGBASE + 0xFF, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = CH_SPI, + .end = CH_SPI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_spi0_device = { + .name = "bfin-spi", + .id = 0, /* Bus number */ + .num_resources = ARRAY_SIZE(bfin_spi0_resource), + .resource = bfin_spi0_resource, + .dev = { + .platform_data = &bfin_spi0_info, /* Passed to driver */ + }, +}; +#endif /* spi master and devices */ + +#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE) +static struct platform_device bfin_fb_device = { + .name = "bf537-lq035", +}; +#endif + +#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE) +static struct platform_device bfin_fb_adv7393_device = { + .name = "bfin-adv7393", +}; +#endif + +#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) +static struct resource bfin_uart_resources[] = { +#ifdef CONFIG_SERIAL_BFIN_UART0 + { + .start = 0xFFC00400, + .end = 0xFFC004FF, + .flags = IORESOURCE_MEM, + }, +#endif +#ifdef CONFIG_SERIAL_BFIN_UART1 + { + .start = 0xFFC02000, + .end = 0xFFC020FF, + .flags = IORESOURCE_MEM, + }, +#endif +}; + +static struct platform_device bfin_uart_device = { + .name = "bfin-uart", + .id = 1, + .num_resources = ARRAY_SIZE(bfin_uart_resources), + .resource = bfin_uart_resources, +}; +#endif + +#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE) +static struct resource bfin_twi0_resource[] = { + [0] = { + .start = TWI0_REGBASE, + .end = TWI0_REGBASE, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_TWI, + .end = IRQ_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device i2c_bfin_twi_device = { + .name = "i2c-bfin-twi", + .id = 0, + .num_resources = ARRAY_SIZE(bfin_twi0_resource), + .resource = bfin_twi0_resource, +}; +#endif + +#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) +static struct platform_device bfin_sport0_uart_device = { + .name = "bfin-sport-uart", + .id = 0, +}; + +static struct platform_device bfin_sport1_uart_device = { + .name = "bfin-sport-uart", + .id = 1, +}; +#endif + +#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE) +#define PATA_INT 55 + +static struct pata_platform_info bfin_pata_platform_data = { + .ioport_shift = 1, + .irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED, +}; + +static struct resource bfin_pata_resources[] = { + { + .start = 0x20314020, + .end = 0x2031403F, + .flags = IORESOURCE_MEM, + }, + { + .start = 0x2031401C, + .end = 0x2031401F, + .flags = IORESOURCE_MEM, + }, + { + .start = PATA_INT, + .end = PATA_INT, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device bfin_pata_device = { + .name = "pata_platform", + .id = -1, + .num_resources = ARRAY_SIZE(bfin_pata_resources), + .resource = bfin_pata_resources, + .dev = { + .platform_data = &bfin_pata_platform_data, + } +}; +#endif + +static struct platform_device *stamp_devices[] __initdata = { +#if defined(CONFIG_BFIN_CFPCMCIA) || defined(CONFIG_BFIN_CFPCMCIA_MODULE) + &bfin_pcmcia_cf_device, +#endif + +#if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) + &rtc_device, +#endif + +#if defined(CONFIG_USB_SL811_HCD) || defined(CONFIG_USB_SL811_HCD_MODULE) + &sl811_hcd_device, +#endif + +#if defined(CONFIG_USB_ISP1362_HCD) || defined(CONFIG_USB_ISP1362_HCD_MODULE) + &isp1362_hcd_device, +#endif + +#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) + &smc91x_device, +#endif + +#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) + &dm9000_device, +#endif + +#if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mac_device, +#endif + +#if defined(CONFIG_USB_NET2272) || defined(CONFIG_USB_NET2272_MODULE) + &net2272_bfin_device, +#endif + +#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) + &bfin_spi0_device, +#endif + +#if defined(CONFIG_FB_BF537_LQ035) || defined(CONFIG_FB_BF537_LQ035_MODULE) + &bfin_fb_device, +#endif + +#if defined(CONFIG_FB_BFIN_7393) || defined(CONFIG_FB_BFIN_7393_MODULE) + &bfin_fb_adv7393_device, +#endif + +#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE) + &bfin_uart_device, +#endif + +#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE) + &i2c_bfin_twi_device, +#endif + +#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) + &bfin_sport0_uart_device, + &bfin_sport1_uart_device, +#endif + +#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE) + &bfin_pata_device, +#endif +}; + +static int __init stamp_init(void) +{ + printk(KERN_INFO "%s(): registering device resources\n", __FUNCTION__); + platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); +#if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) + spi_register_board_info(bfin_spi_board_info, + ARRAY_SIZE(bfin_spi_board_info)); +#endif + +#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE) + irq_desc[PATA_INT].status |= IRQ_NOAUTOEN; +#endif + return 0; +} + +arch_initcall(stamp_init); + +void native_machine_restart(char *cmd) +{ + /* workaround reboot hang when booting from SPI */ + if ((bfin_read_SYSCR() & 0x7) == 0x3) + bfin_gpio_reset_spi0_ssel1(); +} diff --git a/arch/blackfin/mach-bf527/cpu.c b/arch/blackfin/mach-bf527/cpu.c new file mode 100644 index 00000000000..1975402b1db --- /dev/null +++ b/arch/blackfin/mach-bf527/cpu.c @@ -0,0 +1,161 @@ +/* + * File: arch/blackfin/mach-bf527/cpu.c + * Based on: arch/blackfin/mach-bf537/cpu.c + * Author: michael.kang@analog.com + * + * Created: + * Description: clock scaling for the bf527 + * + * Modified: + * Copyright 2004-2007 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/cpufreq.h> +#include <asm/dpmc.h> +#include <linux/fs.h> +#include <asm/bfin-global.h> + +/* CONFIG_CLKIN_HZ=11059200 */ +#define VCO5 (CONFIG_CLKIN_HZ*45) /*497664000 */ +#define VCO4 (CONFIG_CLKIN_HZ*36) /*398131200 */ +#define VCO3 (CONFIG_CLKIN_HZ*27) /*298598400 */ +#define VCO2 (CONFIG_CLKIN_HZ*18) /*199065600 */ +#define VCO1 (CONFIG_CLKIN_HZ*9) /*99532800 */ +#define VCO(x) VCO##x + +#define MFREQ(x) {VCO(x), VCO(x)/4}, {VCO(x), VCO(x)/2}, {VCO(x), VCO(x)} +/* frequency */ +static struct cpufreq_frequency_table bf527_freq_table[] = { + MFREQ(1), + MFREQ(3), + {VCO4, VCO4 / 2}, {VCO4, VCO4}, + MFREQ(5), + {0, CPUFREQ_TABLE_END}, +}; + +/* + * dpmc_fops->ioctl() + * static int dpmc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) + */ +static int bf527_getfreq(unsigned int cpu) +{ + unsigned long cclk_mhz; + + /* The driver only support single cpu */ + if (cpu == 0) + dpmc_fops.ioctl(NULL, NULL, IOCTL_GET_CORECLOCK, &cclk_mhz); + else + cclk_mhz = -1; + + return cclk_mhz; +} + +static int bf527_target(struct cpufreq_policy *policy, + unsigned int target_freq, unsigned int relation) +{ + unsigned long cclk_mhz; + unsigned long vco_mhz; + unsigned long flags; + unsigned int index; + struct cpufreq_freqs freqs; + + if (cpufreq_frequency_table_target + (policy, bf527_freq_table, target_freq, relation, &index)) + return -EINVAL; + + cclk_mhz = bf527_freq_table[index].frequency; + vco_mhz = bf527_freq_table[index].index; + + dpmc_fops.ioctl(NULL, NULL, IOCTL_CHANGE_FREQUENCY, &vco_mhz); + freqs.old = bf527_getfreq(0); + freqs.new = cclk_mhz; + freqs.cpu = 0; + + pr_debug + ("cclk begin change to cclk %d,vco=%d,index=%d,target=%d,oldfreq=%d\n", + cclk_mhz, vco_mhz, index, target_freq, freqs.old); + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + local_irq_save(flags); + dpmc_fops.ioctl(NULL, NULL, IOCTL_SET_CCLK, &cclk_mhz); + local_irq_restore(flags); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + vco_mhz = get_vco(); + cclk_mhz = get_cclk(); + return 0; +} + +/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on + * this platform, anyway. + */ +static int bf527_verify_speed(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, &bf527_freq_table); +} + +static int __init __bf527_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -EINVAL; + + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + /*Now ,only support one cpu */ + policy->cur = bf527_getfreq(0); + cpufreq_frequency_table_get_attr(bf527_freq_table, policy->cpu); + return cpufreq_frequency_table_cpuinfo(policy, bf527_freq_table); +} + +static struct freq_attr *bf527_freq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + +static struct cpufreq_driver bf527_driver = { + .verify = bf527_verify_speed, + .target = bf527_target, + .get = bf527_getfreq, + .init = __bf527_cpu_init, + .name = "bf527", + .owner = THIS_MODULE, + .attr = bf527_freq_attr, +}; + +static int __init bf527_cpu_init(void) +{ + return cpufreq_register_driver(&bf527_driver); +} + +static void __exit bf527_cpu_exit(void) +{ + cpufreq_unregister_driver(&bf527_driver); +} + +MODULE_AUTHOR("Mickael Kang"); +MODULE_DESCRIPTION("cpufreq driver for bf527 CPU"); +MODULE_LICENSE("GPL"); + +module_init(bf527_cpu_init); +module_exit(bf527_cpu_exit); diff --git a/arch/blackfin/mach-bf527/dma.c b/arch/blackfin/mach-bf527/dma.c new file mode 100644 index 00000000000..522de24cc39 --- /dev/null +++ b/arch/blackfin/mach-bf527/dma.c @@ -0,0 +1,115 @@ +/* + * File: arch/blackfin/mach-bf527/dma.c + * Based on: + * Author: + * + * Created: + * Description: This file contains the simple DMA Implementation for Blackfin + * + * Modified: + * Copyright 2004-2007 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <asm/blackfin.h> +#include <asm/dma.h> + +struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = { + (struct dma_register *) DMA0_NEXT_DESC_PTR, + (struct dma_register *) DMA1_NEXT_DESC_PTR, + (struct dma_register *) DMA2_NEXT_DESC_PTR, + (struct dma_register *) DMA3_NEXT_DESC_PTR, + (struct dma_register *) DMA4_NEXT_DESC_PTR, + (struct dma_register *) DMA5_NEXT_DESC_PTR, + (struct dma_register *) DMA6_NEXT_DESC_PTR, + (struct dma_register *) DMA7_NEXT_DESC_PTR, + (struct dma_register *) DMA8_NEXT_DESC_PTR, + (struct dma_register *) DMA9_NEXT_DESC_PTR, + (struct dma_register *) DMA10_NEXT_DESC_PTR, + (struct dma_register *) DMA11_NEXT_DESC_PTR, + (struct dma_register *) MDMA_D0_NEXT_DESC_PTR, + (struct dma_register *) MDMA_S0_NEXT_DESC_PTR, + (struct dma_register *) MDMA_D1_NEXT_DESC_PTR, + (struct dma_register *) MDMA_S1_NEXT_DESC_PTR, +}; + +int channel2irq(unsigned int channel) +{ + int ret_irq = -1; + + switch (channel) { + case CH_PPI: + ret_irq = IRQ_PPI; + break; + + case CH_EMAC_RX: + ret_irq = IRQ_MAC_RX; + break; + + case CH_EMAC_TX: + ret_irq = IRQ_MAC_TX; + break; + + case CH_UART1_RX: + ret_irq = IRQ_UART1_RX; + break; + + case CH_UART1_TX: + ret_irq = IRQ_UART1_TX; + break; + + case CH_SPORT0_RX: + ret_irq = IRQ_SPORT0_RX; + break; + + case CH_SPORT0_TX: + ret_irq = IRQ_SPORT0_TX; + break; + + case CH_SPORT1_RX: + ret_irq = IRQ_SPORT1_RX; + break; + + case CH_SPORT1_TX: + ret_irq = IRQ_SPORT1_TX; + break; + + case CH_SPI: + ret_irq = IRQ_SPI; + break; + + case CH_UART0_RX: + ret_irq = IRQ_UART0_RX; + break; + + case CH_UART0_TX: + ret_irq = IRQ_UART0_TX; + break; + + case CH_MEM_STREAM0_SRC: + case CH_MEM_STREAM0_DEST: + ret_irq = IRQ_MEM_DMA0; + break; + + case CH_MEM_STREAM1_SRC: + case CH_MEM_STREAM1_DEST: + ret_irq = IRQ_MEM_DMA1; + break; + } + return ret_irq; +} diff --git a/arch/blackfin/mach-bf527/head.S b/arch/blackfin/mach-bf527/head.S new file mode 100644 index 00000000000..cdb00a08496 --- /dev/null +++ b/arch/blackfin/mach-bf527/head.S @@ -0,0 +1,456 @@ +/* + * File: arch/blackfin/mach-bf527/head.S + * Based on: arch/blackfin/mach-bf533/head.S + * Author: Jeff Dionne <jeff@uclinux.org> COPYRIGHT 1998 D. Jeff Dionne + * + * Created: 1998 + * Description: Startup code for Blackfin BF537 + * + * Modified: + * Copyright 2004-2007 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/linkage.h> +#include <linux/init.h> +#include <asm/blackfin.h> +#include <asm/trace.h> + +#if CONFIG_BFIN_KERNEL_CLOCK +#include <asm/mach-common/clocks.h> +#include <asm/mach/mem_init.h> +#endif + +.global __rambase +.global __ramstart +.global __ramend +.extern ___bss_stop +.extern ___bss_start +.extern _bf53x_relocate_l1_mem + +#define INITIAL_STACK 0xFFB01000 + +__INIT + +ENTRY(__start) + /* R0: argument of command line string, passed from uboot, save it */ + R7 = R0; + /* Enable Cycle Counter and Nesting Of Interrupts */ +#ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES + R0 = SYSCFG_SNEN; +#else + R0 = SYSCFG_SNEN | SYSCFG_CCEN; +#endif + SYSCFG = R0; + R0 = 0; + + /* Clear Out All the data and pointer Registers */ + R1 = R0; + R2 = R0; + R3 = R0; + R4 = R0; + R5 = R0; + R6 = R0; + + P0 = R0; + P1 = R0; + P2 = R0; + P3 = R0; + P4 = R0; + P5 = R0; + + LC0 = r0; + LC1 = r0; + L0 = r0; + L1 = r0; + L2 = r0; + L3 = r0; + + /* Clear Out All the DAG Registers */ + B0 = r0; + B1 = r0; + B2 = r0; + B3 = r0; + + I0 = r0; + I1 = r0; + I2 = r0; + I3 = r0; + + M0 = r0; + M1 = r0; + M2 = r0; + M3 = r0; + + trace_buffer_init(p0,r0); + P0 = R1; + R0 = R1; + + /* Turn off the icache */ + p0.l = LO(IMEM_CONTROL); + p0.h = HI(IMEM_CONTROL); + R1 = [p0]; + R0 = ~ENICPLB; + R0 = R0 & R1; + + /* Anomaly 05000125 */ +#if ANOMALY_05000125 + CLI R2; + SSYNC; +#endif + [p0] = R0; + SSYNC; +#if ANOMALY_05000125 + STI R2; +#endif + + /* Turn off the dcache */ + p0.l = LO(DMEM_CONTROL); + p0.h = HI(DMEM_CONTROL); + R1 = [p0]; + R0 = ~ENDCPLB; + R0 = R0 & R1; + + /* Anomaly 05000125 */ +#if ANOMALY_05000125 + CLI R2; + SSYNC; +#endif + [p0] = R0; + SSYNC; +#if ANOMALY_05000125 + STI R2; +#endif + + +#if defined(CONFIG_BF527) + p0.h = hi(EMAC_SYSTAT); + p0.l = lo(EMAC_SYSTAT); + R0.h = 0xFFFF; /* Clear EMAC Interrupt Status bits */ + R0.l = 0xFFFF; + [P0] = R0; + SSYNC; +#endif + + /* Initialise UART - when booting from u-boot, the UART is not disabled + * so if we dont initalize here, our serial console gets hosed */ + p0.h = hi(UART1_LCR); + p0.l = lo(UART1_LCR); + r0 = 0x0(Z); + w[p0] = r0.L; /* To enable DLL writes */ + ssync; + + p0.h = hi(UART1_DLL); + p0.l = lo(UART1_DLL); + r0 = 0x0(Z); + w[p0] = r0.L; + ssync; + + p0.h = hi(UART1_DLH); + p0.l = lo(UART1_DLH); + r0 = 0x00(Z); + w[p0] = r0.L; + ssync; + + p0.h = hi(UART1_GCTL); + p0.l = lo(UART1_GCTL); + r0 = 0x0(Z); + w[p0] = r0.L; /* To enable UART clock */ + ssync; + + /* Initialize stack pointer */ + sp.l = lo(INITIAL_STACK); + sp.h = hi(INITIAL_STACK); + fp = sp; + usp = sp; + +#ifdef CONFIG_EARLY_PRINTK + SP += -12; + call _init_early_exception_vectors; + SP += 12; +#endif + + /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */ + call _bf53x_relocate_l1_mem; +#if CONFIG_BFIN_KERNEL_CLOCK + call _start_dma_code; +#endif + + /* Code for initializing Async memory banks */ + + p2.h = hi(EBIU_AMBCTL1); + p2.l = lo(EBIU_AMBCTL1); + r0.h = hi(AMBCTL1VAL); + r0.l = lo(AMBCTL1VAL); + [p2] = r0; + ssync; + + p2.h = hi(EBIU_AMBCTL0); + p2.l = lo(EBIU_AMBCTL0); + r0.h = hi(AMBCTL0VAL); + r0.l = lo(AMBCTL0VAL); + [p2] = r0; + ssync; + + p2.h = hi(EBIU_AMGCTL); + p2.l = lo(EBIU_AMGCTL); + r0 = AMGCTLVAL; + w[p2] = r0; + ssync; + + /* This section keeps the processor in supervisor mode + * during kernel boot. Switches to user mode at end of boot. + * See page 3-9 of Hardware Reference manual for documentation. + */ + + /* EVT15 = _real_start */ + + p0.l = lo(EVT15); + p0.h = hi(EVT15); + p1.l = _real_start; + p1.h = _real_start; + [p0] = p1; + csync; + + p0.l = lo(IMASK); + p0.h = hi(IMASK); + p1.l = IMASK_IVG15; + p1.h = 0x0; + [p0] = p1; + csync; + + raise 15; + p0.l = .LWAIT_HERE; + p0.h = .LWAIT_HERE; + reti = p0; +#if ANOMALY_05000281 + nop; nop; nop; +#endif + rti; + +.LWAIT_HERE: + jump .LWAIT_HERE; +ENDPROC(__start) + +ENTRY(_real_start) + [ -- sp ] = reti; + p0.l = lo(WDOG_CTL); + p0.h = hi(WDOG_CTL); + r0 = 0xAD6(z); + w[p0] = r0; /* watchdog off for now */ + ssync; + + /* Code update for BSS size == 0 + * Zero out the bss region. + */ + + p1.l = ___bss_start; + p1.h = ___bss_start; + p2.l = ___bss_stop; + p2.h = ___bss_stop; + r0 = 0; + p2 -= p1; + lsetup (.L_clear_bss, .L_clear_bss) lc0 = p2; +.L_clear_bss: + B[p1++] = r0; + + /* In case there is a NULL pointer reference + * Zero out region before stext + */ + + p1.l = 0x0; + p1.h = 0x0; + r0.l = __stext; + r0.h = __stext; + r0 = r0 >> 1; + p2 = r0; + r0 = 0; + lsetup (.L_clear_zero, .L_clear_zero) lc0 = p2; +.L_clear_zero: + W[p1++] = r0; + + /* pass the uboot arguments to the global value command line */ + R0 = R7; + call _cmdline_init; + + p1.l = __rambase; + p1.h = __rambase; + r0.l = __sdata; + r0.h = __sdata; + [p1] = r0; + + p1.l = __ramstart; + p1.h = __ramstart; + p3.l = ___bss_stop; + p3.h = ___bss_stop; + + r1 = p3; + [p1] = r1; + + /* + * load the current thread pointer and stack + */ + r1.l = _init_thread_union; + r1.h = _init_thread_union; + + r2.l = 0x2000; + r2.h = 0x0000; + r1 = r1 + r2; + sp = r1; + usp = sp; + fp = sp; + jump.l _start_kernel; +ENDPROC(_real_start) + +__FINIT + +.section .l1.text +#if CONFIG_BFIN_KERNEL_CLOCK +ENTRY(_start_dma_code) + + /* Enable PHY CLK buffer output */ + p0.h = hi(VR_CTL); + p0.l = lo(VR_CTL); + r0.l = w[p0]; + bitset(r0, 14); + w[p0] = r0.l; + ssync; + + p0.h = hi(SIC_IWR0); + p0.l = lo(SIC_IWR0); + r0.l = 0x1; + r0.h = 0x0; + [p0] = r0; + SSYNC; + + /* + * Set PLL_CTL + * - [14:09] = MSEL[5:0] : CLKIN / VCO multiplication factors + * - [8] = BYPASS : BYPASS the PLL, run CLKIN into CCLK/SCLK + * - [7] = output delay (add 200ps of delay to mem signals) + * - [6] = input delay (add 200ps of input delay to mem signals) + * - [5] = PDWN : 1=All Clocks off + * - [3] = STOPCK : 1=Core Clock off + * - [1] = PLL_OFF : 1=Disable Power to PLL + * - [0] = DF : 1=Pass CLKIN/2 to PLL / 0=Pass CLKIN to PLL + * all other bits set to zero + */ + + p0.h = hi(PLL_LOCKCNT); + p0.l = lo(PLL_LOCKCNT); + r0 = 0x300(Z); + w[p0] = r0.l; + ssync; + + P2.H = hi(EBIU_SDGCTL); + P2.L = lo(EBIU_SDGCTL); + R0 = [P2]; + BITSET (R0, 24); + [P2] = R0; + SSYNC; + + r0 = CONFIG_VCO_MULT & 63; /* Load the VCO multiplier */ + r0 = r0 << 9; /* Shift it over, */ + r1 = CLKIN_HALF; /* Do we need to divide CLKIN by 2?*/ + r0 = r1 | r0; + r1 = PLL_BYPASS; /* Bypass the PLL? */ + r1 = r1 << 8; /* Shift it over */ + r0 = r1 | r0; /* add them all together */ + + p0.h = hi(PLL_CTL); + p0.l = lo(PLL_CTL); /* Load the address */ + cli r2; /* Disable interrupts */ + ssync; + w[p0] = r0.l; /* Set the value */ + idle; /* Wait for the PLL to stablize */ + sti r2; /* Enable interrupts */ + +.Lcheck_again: + p0.h = hi(PLL_STAT); + p0.l = lo(PLL_STAT); + R0 = W[P0](Z); + CC = BITTST(R0,5); + if ! CC jump .Lcheck_again; + + /* Configure SCLK & CCLK Dividers */ + r0 = (CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV); + p0.h = hi(PLL_DIV); + p0.l = lo(PLL_DIV); + w[p0] = r0.l; + ssync; + + p0.l = lo(EBIU_SDRRC); + p0.h = hi(EBIU_SDRRC); + r0 = mem_SDRRC; + w[p0] = r0.l; + ssync; + + p0.l = LO(EBIU_SDBCTL); + p0.h = HI(EBIU_SDBCTL); /* SDRAM Memory Bank Control Register */ + r0 = mem_SDBCTL; + w[p0] = r0.l; + ssync; + + P2.H = hi(EBIU_SDGCTL); + P2.L = lo(EBIU_SDGCTL); + R0 = [P2]; + BITCLR (R0, 24); + p0.h = hi(EBIU_SDSTAT); + p0.l = lo(EBIU_SDSTAT); + r2.l = w[p0]; + cc = bittst(r2,3); + if !cc jump .Lskip; + NOP; + BITSET (R0, 23); +.Lskip: + [P2] = R0; + SSYNC; + + R0.L = lo(mem_SDGCTL); + R0.H = hi(mem_SDGCTL); + R1 = [p2]; + R1 = R1 | R0; + [P2] = R1; + SSYNC; + + p0.h = hi(SIC_IWR0); + p0.l = lo(SIC_IWR0); + r0.l = lo(IWR_ENABLE_ALL); + r0.h = hi(IWR_ENABLE_ALL); + [p0] = r0; + SSYNC; + + RTS; +ENDPROC(_start_dma_code) +#endif /* CONFIG_BFIN_KERNEL_CLOCK */ + +.data + +/* + * Set up the usable of RAM stuff. Size of RAM is determined then + * an initial stack set up at the end. + */ + +.align 4 +__rambase: +.long 0 +__ramstart: +.long 0 +__ramend: +.long 0 diff --git a/arch/blackfin/mach-bf527/ints-priority.c b/arch/blackfin/mach-bf527/ints-priority.c new file mode 100644 index 00000000000..1fa38979396 --- /dev/null +++ b/arch/blackfin/mach-bf527/ints-priority.c @@ -0,0 +1,100 @@ +/* + * File: arch/blackfin/mach-bf537/ints-priority.c + * Based on: arch/blackfin/mach-bf533/ints-priority.c + * Author: Michael Hennerich (michael.hennerich@analog.com) + * + * Created: + * Description: Set up the interrupt priorities + * + * Modified: + * Copyright 2004-2007 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <linux/module.h> +#include <linux/irq.h> +#include <asm/blackfin.h> + +void program_IAR(void) +{ + /* Program the IAR0 Register with the configured priority */ + bfin_write_SIC_IAR0(((CONFIG_IRQ_PLL_WAKEUP - 7) << IRQ_PLL_WAKEUP_POS) | + ((CONFIG_IRQ_DMA0_ERROR - 7) << IRQ_DMA0_ERROR_POS) | + ((CONFIG_IRQ_DMAR0_BLK - 7) << IRQ_DMAR0_BLK_POS) | + ((CONFIG_IRQ_DMAR1_BLK - 7) << IRQ_DMAR1_BLK_POS) | + ((CONFIG_IRQ_DMAR0_OVR - 7) << IRQ_DMAR0_OVR_POS) | + ((CONFIG_IRQ_DMAR1_OVR - 7) << IRQ_DMAR1_OVR_POS) | + ((CONFIG_IRQ_PPI_ERROR - 7) << IRQ_PPI_ERROR_POS) | + ((CONFIG_IRQ_MAC_ERROR - 7) << IRQ_MAC_ERROR_POS)); + + + bfin_write_SIC_IAR1(((CONFIG_IRQ_SPORT0_ERROR - 7) << IRQ_SPORT0_ERROR_POS) | + ((CONFIG_IRQ_SPORT1_ERROR - 7) << IRQ_SPORT1_ERROR_POS) | + ((CONFIG_IRQ_UART0_ERROR - 7) << IRQ_UART0_ERROR_POS) | + ((CONFIG_IRQ_UART1_ERROR - 7) << IRQ_UART1_ERROR_POS) | + ((CONFIG_IRQ_RTC - 7) << IRQ_RTC_POS) | + ((CONFIG_IRQ_PPI - 7) << IRQ_PPI_POS)); + + bfin_write_SIC_IAR2(((CONFIG_IRQ_SPORT0_RX - 7) << IRQ_SPORT0_RX_POS) | + ((CONFIG_IRQ_SPORT0_TX - 7) << IRQ_SPORT0_TX_POS) | + ((CONFIG_IRQ_SPORT1_RX - 7) << IRQ_SPORT1_RX_POS) | + ((CONFIG_IRQ_SPORT1_TX - 7) << IRQ_SPORT1_TX_POS) | + ((CONFIG_IRQ_TWI - 7) << IRQ_TWI_POS) | + ((CONFIG_IRQ_SPI - 7) << IRQ_SPI_POS) | + ((CONFIG_IRQ_UART0_RX - 7) << IRQ_UART0_RX_POS) | + ((CONFIG_IRQ_UART0_TX - 7) << IRQ_UART0_TX_POS)); + + bfin_write_SIC_IAR3(((CONFIG_IRQ_UART1_RX - 7) << IRQ_UART1_RX_POS) | + ((CONFIG_IRQ_UART1_TX - 7) << IRQ_UART1_TX_POS) | + ((CONFIG_IRQ_OPTSEC - 7) << IRQ_OPTSEC_POS) | + ((CONFIG_IRQ_CNT - 7) << IRQ_CNT_POS) | + ((CONFIG_IRQ_MAC_RX - 7) << IRQ_MAC_RX_POS) | + ((CONFIG_IRQ_PORTH_INTA - 7) << IRQ_PORTH_INTA_POS) | + ((CONFIG_IRQ_MAC_TX - 7) << IRQ_MAC_TX_POS) | + ((CONFIG_IRQ_PORTH_INTB - 7) << IRQ_PORTH_INTB_POS)); + + bfin_write_SIC_IAR4(((CONFIG_IRQ_TMR0 - 7) << IRQ_TMR0_POS) | + ((CONFIG_IRQ_TMR1 - 7) << IRQ_TMR1_POS) | + ((CONFIG_IRQ_TMR2 - 7) << IRQ_TMR2_POS) | + ((CONFIG_IRQ_TMR3 - 7) << IRQ_TMR3_POS) | + ((CONFIG_IRQ_TMR4 - 7) << IRQ_TMR4_POS) | + ((CONFIG_IRQ_TMR5 - 7) << IRQ_TMR5_POS) | + ((CONFIG_IRQ_TMR6 - 7) << IRQ_TMR6_POS) | + ((CONFIG_IRQ_TMR7 - 7) << IRQ_TMR7_POS)); + + bfin_write_SIC_IAR5(((CONFIG_IRQ_PORTG_INTA - 7) << IRQ_PORTG_INTA_POS) | + ((CONFIG_IRQ_PORTG_INTB - 7) << IRQ_PORTG_INTB_POS) | + ((CONFIG_IRQ_MEM_DMA0 - 7) << IRQ_MEM_DMA0_POS) | + ((CONFIG_IRQ_MEM_DMA1 - 7) << IRQ_MEM_DMA1_POS) | + ((CONFIG_IRQ_WATCH - 7) << IRQ_WATCH_POS) | + ((CONFIG_IRQ_PORTF_INTA - 7) << IRQ_PORTF_INTA_POS) | + ((CONFIG_IRQ_PORTF_INTB - 7) << IRQ_PORTF_INTB_POS) | + ((CONFIG_IRQ_SPI_ERROR - 7) << IRQ_SPI_ERROR_POS)); + + bfin_write_SIC_IAR6(((CONFIG_IRQ_NFC_ERROR - 7) << IRQ_NFC_ERROR_POS) | + ((CONFIG_IRQ_HDMA_ERROR - 7) << IRQ_HDMA_ERROR_POS) | + ((CONFIG_IRQ_HDMA - 7) << IRQ_HDMA_POS) | + ((CONFIG_IRQ_USB_EINT - 7) << IRQ_USB_EINT_POS) | + ((CONFIG_IRQ_USB_INT0 - 7) << IRQ_USB_INT0_POS) | + ((CONFIG_IRQ_USB_INT1 - 7) << IRQ_USB_INT1_POS) | + ((CONFIG_IRQ_USB_INT2 - 7) << IRQ_USB_INT2_POS) | + ((CONFIG_IRQ_USB_DMA - 7) << IRQ_USB_DMA_POS)); + + SSYNC(); +} diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c index a57b52d207c..1c5a86adfab 100644 --- a/arch/blackfin/mach-bf533/boards/cm_bf533.c +++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c @@ -42,7 +42,7 @@ /* * Name the Board for the /proc/cpuinfo */ -char *bfin_board_name = "Bluetechnix CM BF533"; +const char bfin_board_name[] = "Bluetechnix CM BF533"; #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) /* all SPI peripherals info goes here */ diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c index 5c1e35d3c01..34b63920e27 100644 --- a/arch/blackfin/mach-bf533/boards/ezkit.c +++ b/arch/blackfin/mach-bf533/boards/ezkit.c @@ -43,7 +43,7 @@ /* * Name the Board for the /proc/cpuinfo */ -char *bfin_board_name = "ADDS-BF533-EZKIT"; +const char bfin_board_name[] = "ADDS-BF533-EZKIT"; #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) static struct platform_device rtc_device = { diff --git a/arch/blackfin/mach-bf533/boards/generic_board.c b/arch/blackfin/mach-bf533/boards/generic_board.c index 9bc1f0d0ab5..310b7772c45 100644 --- a/arch/blackfin/mach-bf533/boards/generic_board.c +++ b/arch/blackfin/mach-bf533/boards/generic_board.c @@ -35,7 +35,7 @@ /* * Name the Board for the /proc/cpuinfo */ -char *bfin_board_name = "UNKNOWN BOARD"; +const char bfin_board_name[] = "UNKNOWN BOARD"; #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) static struct platform_device rtc_device = { diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index 8975e06ea15..f84be4eabfd 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c @@ -46,7 +46,7 @@ /* * Name the Board for the /proc/cpuinfo */ -char *bfin_board_name = "ADDS-BF533-STAMP"; +const char bfin_board_name[] = "ADDS-BF533-STAMP"; #if defined(CONFIG_RTC_DRV_BFIN) || defined(CONFIG_RTC_DRV_BFIN_MODULE) static struct platform_device rtc_device = { diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c index 44dea05e1d0..52e2320307d 100644 --- a/arch/blackfin/mach-bf537/boards/cm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c @@ -43,7 +43,7 @@ /* * Name the Board for the /proc/cpuinfo */ -char *bfin_board_name = "Bluetechnix CM BF537"; +const char bfin_board_name[] = "Bluetechnix CM BF537"; #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) /* all SPI peripherals info goes here */ diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c index 6668c8e4a3f..255da7a9848 100644 --- a/arch/blackfin/mach-bf537/boards/generic_board.c +++ b/arch/blackfin/mach-bf537/boards/generic_board.c @@ -49,7 +49,7 @@ /* * Name the Board for the /proc/cpuinfo */ -char *bfin_board_name = "GENERIC Board"; +const char bfin_board_name[] = "GENERIC Board"; /* * Driver needs to know address, irq and flag pin. diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c index f83a2544004..87b80892678 100644 --- a/arch/blackfin/mach-bf537/boards/pnav10.c +++ b/arch/blackfin/mach-bf537/boards/pnav10.c @@ -47,7 +47,7 @@ /* * Name the Board for the /proc/cpuinfo */ -char *bfin_board_name = "PNAV-1.0"; +const char bfin_board_name[] = "PNAV-1.0"; /* * Driver needs to know address, irq and flag pin. diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index f42ba3aa86d..cc41f6c2ef4 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -49,7 +49,7 @@ /* * Name the Board for the /proc/cpuinfo */ -char *bfin_board_name = "ADDS-BF537-STAMP"; +const char bfin_board_name[] = "ADDS-BF537-STAMP"; /* * Driver needs to know address, irq and flag pin. diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 046e6d84bbf..6b6490e66b3 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -49,7 +49,7 @@ /* * Name the Board for the /proc/cpuinfo */ -char *bfin_board_name = "ADSP-BF548-EZKIT"; +const char bfin_board_name[] = "ADSP-BF548-EZKIT"; /* * Driver needs to know address, irq and flag pin. @@ -560,7 +560,7 @@ static struct platform_device *ezkit_devices[] __initdata = { #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) &bf54x_spi_master0, -/* &bf54x_spi_master1,*/ + &bf54x_spi_master1, #endif #if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE) diff --git a/arch/blackfin/mach-bf548/dma.c b/arch/blackfin/mach-bf548/dma.c index a8184113be4..957bf1366ef 100644 --- a/arch/blackfin/mach-bf548/dma.c +++ b/arch/blackfin/mach-bf548/dma.c @@ -64,6 +64,7 @@ (struct dma_register *) MDMA_D3_NEXT_DESC_PTR, (struct dma_register *) MDMA_S3_NEXT_DESC_PTR, }; +EXPORT_SYMBOL(base_addr); int channel2irq(unsigned int channel) { diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c index cd827a1b6ba..97aeb43fd8b 100644 --- a/arch/blackfin/mach-bf561/boards/cm_bf561.c +++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c @@ -42,7 +42,7 @@ /* * Name the Board for the /proc/cpuinfo */ -char *bfin_board_name = "Bluetechnix CM BF561"; +const char bfin_board_name[] = "Bluetechnix CM BF561"; #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) /* all SPI peripherals info goes here */ diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c index 57e14edca8b..059d516cec2 100644 --- a/arch/blackfin/mach-bf561/boards/ezkit.c +++ b/arch/blackfin/mach-bf561/boards/ezkit.c @@ -39,7 +39,7 @@ /* * Name the Board for the /proc/cpuinfo */ -char *bfin_board_name = "ADDS-BF561-EZKIT"; +const char bfin_board_name[] = "ADDS-BF561-EZKIT"; #define ISP1761_BASE 0x2C0F0000 #define ISP1761_IRQ IRQ_PF10 diff --git a/arch/blackfin/mach-bf561/boards/generic_board.c b/arch/blackfin/mach-bf561/boards/generic_board.c index 4dfea5da674..46816be4b2b 100644 --- a/arch/blackfin/mach-bf561/boards/generic_board.c +++ b/arch/blackfin/mach-bf561/boards/generic_board.c @@ -32,7 +32,7 @@ #include <linux/platform_device.h> #include <linux/irq.h> -char *bfin_board_name = "UNKNOWN BOARD"; +const char bfin_board_name[] = "UNKNOWN BOARD"; /* * Driver needs to know address, irq and flag pin. diff --git a/arch/blackfin/mach-bf561/boards/tepla.c b/arch/blackfin/mach-bf561/boards/tepla.c index c442eb23db5..4a17c6da2a5 100644 --- a/arch/blackfin/mach-bf561/boards/tepla.c +++ b/arch/blackfin/mach-bf561/boards/tepla.c @@ -16,7 +16,7 @@ #include <linux/platform_device.h> #include <linux/irq.h> -char *bfin_board_name = "Tepla-BF561"; +const char bfin_board_name[] = "Tepla-BF561"; /* * Driver needs to know address, irq and flag pin. diff --git a/arch/blackfin/mach-common/ints-priority-dc.c b/arch/blackfin/mach-common/ints-priority-dc.c index 2db3546fc87..c2f05fabedc 100644 --- a/arch/blackfin/mach-common/ints-priority-dc.c +++ b/arch/blackfin/mach-common/ints-priority-dc.c @@ -52,7 +52,13 @@ * - */ -unsigned long irq_flags = 0; +/* Initialize this to an actual value to force it into the .data + * section so that we know it is properly initialized at entry into + * the kernel but before bss is initialized to zero (which is where + * it would live otherwise). The 0x1f magic represents the IRQs we + * cannot actually mask out in hardware. + */ +unsigned long irq_flags = 0x1f; /* The number of spurious interrupts */ atomic_t num_spurious; diff --git a/arch/blackfin/mach-common/ints-priority-sc.c b/arch/blackfin/mach-common/ints-priority-sc.c index d3b7672b2b9..2d2b63567b3 100644 --- a/arch/blackfin/mach-common/ints-priority-sc.c +++ b/arch/blackfin/mach-common/ints-priority-sc.c @@ -58,7 +58,13 @@ * - */ -unsigned long irq_flags = 0; +/* Initialize this to an actual value to force it into the .data + * section so that we know it is properly initialized at entry into + * the kernel but before bss is initialized to zero (which is where + * it would live otherwise). The 0x1f magic represents the IRQs we + * cannot actually mask out in hardware. + */ +unsigned long irq_flags = 0x1f; /* The number of spurious interrupts */ atomic_t num_spurious; @@ -92,10 +98,15 @@ static void __init search_IAR(void) for (irqn = 0; irqn < NR_PERI_INTS; irqn++) { int iar_shift = (irqn & 7) * 4; - if (ivg == + if (ivg == (0xf & +#ifndef CONFIG_BF52x bfin_read32((unsigned long *)SIC_IAR0 + (irqn >> 3)) >> iar_shift)) { +#else + bfin_read32((unsigned long *)SIC_IAR0 + + ((irqn%32) >> 3) + ((irqn / 32) * 16)) >> iar_shift)) { +#endif ivg_table[irq_pos].irqno = IVG7 + irqn; ivg_table[irq_pos].isrflag = 1 << (irqn % 32); ivg7_13[ivg].istop++; @@ -140,7 +151,7 @@ static void bfin_core_unmask_irq(unsigned int irq) static void bfin_internal_mask_irq(unsigned int irq) { -#ifndef CONFIG_BF54x +#ifdef CONFIG_BF53x bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() & ~(1 << (irq - (IRQ_CORETMR + 1)))); #else @@ -155,7 +166,7 @@ static void bfin_internal_mask_irq(unsigned int irq) static void bfin_internal_unmask_irq(unsigned int irq) { -#ifndef CONFIG_BF54x +#ifdef CONFIG_BF53x bfin_write_SIC_IMASK(bfin_read_SIC_IMASK() | (1 << (irq - (IRQ_CORETMR + 1)))); #else @@ -750,13 +761,15 @@ int __init init_arch_irq(void) int irq; unsigned long ilat = 0; /* Disable all the peripheral intrs - page 4-29 HW Ref manual */ -#ifdef CONFIG_BF54x +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) bfin_write_SIC_IMASK0(SIC_UNMASK_ALL); bfin_write_SIC_IMASK1(SIC_UNMASK_ALL); - bfin_write_SIC_IMASK2(SIC_UNMASK_ALL); bfin_write_SIC_IWR0(IWR_ENABLE_ALL); bfin_write_SIC_IWR1(IWR_ENABLE_ALL); +#ifdef CONFIG_BF54x + bfin_write_SIC_IMASK2(SIC_UNMASK_ALL); bfin_write_SIC_IWR2(IWR_ENABLE_ALL); +#endif #else bfin_write_SIC_IMASK(SIC_UNMASK_ALL); bfin_write_SIC_IWR(IWR_ENABLE_ALL); @@ -787,7 +800,7 @@ int __init init_arch_irq(void) switch (irq) { #ifdef CONFIG_IRQCHIP_DEMUX_GPIO -#ifndef CONFIG_BF54x +#if defined(CONFIG_BF53x) case IRQ_PROG_INTA: set_irq_chained_handler(irq, bfin_demux_gpio_irq); @@ -798,7 +811,7 @@ int __init init_arch_irq(void) bfin_demux_gpio_irq); break; #endif -#else +#elif defined(CONFIG_BF54x) case IRQ_PINT0: set_irq_chained_handler(irq, bfin_demux_gpio_irq); @@ -815,7 +828,20 @@ int __init init_arch_irq(void) set_irq_chained_handler(irq, bfin_demux_gpio_irq); break; -#endif /*CONFIG_BF54x */ +#elif defined(CONFIG_BF52x) + case IRQ_PORTF_INTA: + set_irq_chained_handler(irq, + bfin_demux_gpio_irq); + break; + case IRQ_PORTG_INTA: + set_irq_chained_handler(irq, + bfin_demux_gpio_irq); + break; + case IRQ_PORTH_INTA: + set_irq_chained_handler(irq, + bfin_demux_gpio_irq); + break; +#endif #endif default: set_irq_handler(irq, handle_simple_irq); @@ -880,14 +906,15 @@ void do_irq(int vec, struct pt_regs *fp) } else { struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst; struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop; -#ifdef CONFIG_BF54x +#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) unsigned long sic_status[3]; SSYNC(); - sic_status[0] = bfin_read_SIC_ISR(0) & bfin_read_SIC_IMASK(0); - sic_status[1] = bfin_read_SIC_ISR(1) & bfin_read_SIC_IMASK(1); - sic_status[2] = bfin_read_SIC_ISR(2) & bfin_read_SIC_IMASK(2); - + sic_status[0] = bfin_read_SIC_ISR0() & bfin_read_SIC_IMASK0(); + sic_status[1] = bfin_read_SIC_ISR1() & bfin_read_SIC_IMASK1(); +#ifdef CONFIG_BF54x + sic_status[2] = bfin_read_SIC_ISR2() & bfin_read_SIC_IMASK2(); +#endif for (;; ivg++) { if (ivg >= ivg_stop) { atomic_inc(&num_spurious); diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index 3c95f4184b9..bc859a311ea 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -246,7 +246,7 @@ static int reserve_sba_gart = 1; static SBA_INLINE void sba_mark_invalid(struct ioc *, dma_addr_t, size_t); static SBA_INLINE void sba_free_range(struct ioc *, dma_addr_t, size_t); -#define sba_sg_address(sg) (page_address((sg)->page) + (sg)->offset) +#define sba_sg_address(sg) sg_virt((sg)) #ifdef FULL_VALID_PDIR static u64 prefetch_spill_page; diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c index a3a558a0675..6ef9b521993 100644 --- a/arch/ia64/hp/sim/simscsi.c +++ b/arch/ia64/hp/sim/simscsi.c @@ -131,7 +131,7 @@ simscsi_sg_readwrite (struct scsi_cmnd *sc, int mode, unsigned long offset) stat.fd = desc[sc->device->id]; scsi_for_each_sg(sc, sl, scsi_sg_count(sc), i) { - req.addr = __pa(page_address(sl->page) + sl->offset); + req.addr = __pa(sg_virt(sl)); req.len = sl->length; if (DBG) printk("simscsi_sg_%s @ %lx (off %lx) use_sg=%d len=%d\n", @@ -212,7 +212,7 @@ static void simscsi_fillresult(struct scsi_cmnd *sc, char *buf, unsigned len) if (!len) break; thislen = min(len, slp->length); - memcpy(page_address(slp->page) + slp->offset, buf, thislen); + memcpy(sg_virt(slp), buf, thislen); len -= thislen; } } diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 8e4894b205e..3f7ea13358e 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -1090,7 +1090,8 @@ efi_memmap_init(unsigned long *s, unsigned long *e) void efi_initialize_iomem_resources(struct resource *code_resource, - struct resource *data_resource) + struct resource *data_resource, + struct resource *bss_resource) { struct resource *res; void *efi_map_start, *efi_map_end, *p; @@ -1171,6 +1172,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, */ insert_resource(res, code_resource); insert_resource(res, data_resource); + insert_resource(res, bss_resource); #ifdef CONFIG_KEXEC insert_resource(res, &efi_memmap_res); insert_resource(res, &boot_param_res); diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index cbf67f1aa29..ae6c3c02e11 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -90,7 +90,12 @@ static struct resource code_resource = { .name = "Kernel code", .flags = IORESOURCE_BUSY | IORESOURCE_MEM }; -extern char _text[], _end[], _etext[]; + +static struct resource bss_resource = { + .name = "Kernel bss", + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; +extern char _text[], _end[], _etext[], _edata[], _bss[]; unsigned long ia64_max_cacheline_size; @@ -200,8 +205,11 @@ static int __init register_memory(void) code_resource.start = ia64_tpa(_text); code_resource.end = ia64_tpa(_etext) - 1; data_resource.start = ia64_tpa(_etext); - data_resource.end = ia64_tpa(_end) - 1; - efi_initialize_iomem_resources(&code_resource, &data_resource); + data_resource.end = ia64_tpa(_edata) - 1; + bss_resource.start = ia64_tpa(_bss); + bss_resource.end = ia64_tpa(_end) - 1; + efi_initialize_iomem_resources(&code_resource, &data_resource, + &bss_resource); return 0; } diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index ecd8a52b9b9..511db2fd7bf 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -16,7 +16,7 @@ #include <asm/sn/pcidev.h> #include <asm/sn/sn_sal.h> -#define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset) +#define SG_ENT_VIRT_ADDRESS(sg) (sg_virt((sg))) #define SG_ENT_PHYS_ADDRESS(SG) virt_to_phys(SG_ENT_VIRT_ADDRESS(SG)) /** diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c index 9d4e4b5b6bd..ef490e1ce60 100644 --- a/arch/m68k/kernel/dma.c +++ b/arch/m68k/kernel/dma.c @@ -121,7 +121,7 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int i; for (i = 0; i < nents; sg++, i++) { - sg->dma_address = page_to_phys(sg->page) + sg->offset; + sg->dma_address = sg_phys(sg); dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); } return nents; diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 98b5e5bac02..b0b034c4654 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -165,12 +165,11 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, for (i = 0; i < nents; i++, sg++) { unsigned long addr; - addr = (unsigned long) page_address(sg->page); + addr = (unsigned long) sg_virt(sg); if (!plat_device_is_coherent(dev) && addr) - __dma_sync(addr + sg->offset, sg->length, direction); + __dma_sync(addr, sg->length, direction); sg->dma_address = plat_map_dma_mem(dev, - (void *)(addr + sg->offset), - sg->length); + (void *)addr, sg->length); } return nents; @@ -223,10 +222,9 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, for (i = 0; i < nhwentries; i++, sg++) { if (!plat_device_is_coherent(dev) && direction != DMA_TO_DEVICE) { - addr = (unsigned long) page_address(sg->page); + addr = (unsigned long) sg_virt(sg); if (addr) - __dma_sync(addr + sg->offset, sg->length, - direction); + __dma_sync(addr, sg->length, direction); } plat_unmap_dma_mem(sg->dma_address); } @@ -304,7 +302,7 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, /* Make sure that gcc doesn't leave the empty loop body. */ for (i = 0; i < nelems; i++, sg++) { if (cpu_is_noncoherent_r10000(dev)) - __dma_sync((unsigned long)page_address(sg->page), + __dma_sync((unsigned long)page_address(sg_page(sg)), sg->length, direction); plat_unmap_dma_mem(sg->dma_address); } @@ -322,7 +320,7 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nele /* Make sure that gcc doesn't leave the empty loop body. */ for (i = 0; i < nelems; i++, sg++) { if (!plat_device_is_coherent(dev)) - __dma_sync((unsigned long)page_address(sg->page), + __dma_sync((unsigned long)page_address(sg_page(sg)), sg->length, direction); plat_unmap_dma_mem(sg->dma_address); } diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index f3d0d7c7097..ae4a9b3d4fd 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -19,26 +19,27 @@ NM = sh $(srctree)/arch/parisc/nm CHECKFLAGS += -D__hppa__=1 +MACHINE := $(shell uname -m) +ifeq ($(MACHINE),parisc*) +NATIVE := 1 +endif + ifdef CONFIG_64BIT -CROSS_COMPILE := $(shell if [ -x /usr/bin/hppa64-linux-gnu-gcc ]; then \ - echo hppa64-linux-gnu-; else echo hppa64-linux-; fi) UTS_MACHINE := parisc64 CHECKFLAGS += -D__LP64__=1 -m64 -else -MACHINE := $(subst 64,,$(shell uname -m)) -ifneq ($(MACHINE),parisc) -CROSS_COMPILE := hppa-linux- -endif +WIDTH := 64 +CROSS_COMPILE := hppa64-linux-gnu- +else # 32-bit +WIDTH := endif -FINAL_LD=$(CROSS_COMPILE)ld --warn-common --warn-section-align +# attempt to help out folks who are cross-compiling +ifeq ($(NATIVE),1) +CROSS_COMPILE := hppa$(WIDTH)-linux- +endif OBJCOPY_FLAGS =-O binary -R .note -R .comment -S -ifneq ($(call cc-ifversion, -lt, 0303, "bad"),) -$(error Sorry, GCC v3.3 or above is required.) -endif - cflags-y := -pipe # These flags should be implied by an hppa-linux configuration, but they @@ -69,7 +70,7 @@ kernel-y := mm/ kernel/ math-emu/ kernel/init_task.o kernel-$(CONFIG_HPUX) += hpux/ core-y += $(addprefix arch/parisc/, $(kernel-y)) -libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name` +libs-y += arch/parisc/lib/ drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/ @@ -77,27 +78,27 @@ PALO := $(shell if which palo; then : ; \ elif [ -x /sbin/palo ]; then echo /sbin/palo; \ fi) +PALOCONF := $(shell if [ -f $(src)/palo.conf ]; then echo $(src)/palo.conf; \ + else echo $(obj)/palo.conf; \ + fi) + palo: vmlinux - @if [ -x $PALO ]; then \ + @if test ! -x "$(PALO)"; then \ echo 'ERROR: Please install palo first (apt-get install palo)';\ echo 'or build it from source and install it somewhere in your $$PATH';\ false; \ fi - @if [ ! -f ./palo.conf ]; then \ - cp arch/parisc/defpalo.conf palo.conf; \ - echo 'A generic palo config file (./palo.conf) has been created for you.'; \ + @if test ! -f "$(PALOCONF)"; then \ + cp $(src)/arch/parisc/defpalo.conf $(obj)/palo.conf; \ + echo 'A generic palo config file ($(obj)/palo.conf) has been created for you.'; \ echo 'You should check it and re-run "make palo".'; \ echo 'WARNING: the "lifimage" file is now placed in this directory by default!'; \ false; \ fi - $(PALO) -f ./palo.conf - -oldpalo: vmlinux - export TOPDIR=`pwd`; \ - unset STRIP LDFLAGS CPP CPPFLAGS AFLAGS CFLAGS CC LD; cd ../palo && make lifimage + $(PALO) -f $(PALOCONF) -# Shorthands for known targets not supported by parisc, use palo as default -Image zImage bzImage: palo +# Shorthands for known targets not supported by parisc, use vmlinux as default +Image zImage bzImage: vmlinux kernel_install: vmlinux sh $(src)/arch/parisc/install.sh \ @@ -116,3 +117,12 @@ define archhelp @echo ' (distribution) /sbin/installkernel or' @echo ' copy to $$(INSTALL_PATH)' endef + +# we require gcc 3.3 or above to compile the kernel +archprepare: checkbin +checkbin: + @if test "$(call cc-version)" -lt "0303"; then \ + echo -n "Sorry, GCC v3.3 or above is required to build " ; \ + echo "the kernel." ; \ + false ; \ + fi diff --git a/arch/parisc/configs/712_defconfig b/arch/parisc/configs/712_defconfig index 41fd0696bbe..9fc96e72716 100644 --- a/arch/parisc/configs/712_defconfig +++ b/arch/parisc/configs/712_defconfig @@ -1,39 +1,51 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-pa6 -# Sun Mar 26 19:59:51 2006 +# Linux kernel version: 2.6.23 +# Fri Oct 12 21:00:07 2007 # CONFIG_PARISC=y CONFIG_MMU=y CONFIG_STACK_GROWSUP=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_IRQ_PER_CPU=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set +# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -43,31 +55,29 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set - -# -# Loadable module support -# CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y - -# -# Block layer -# +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set # # IO Schedulers @@ -91,6 +101,9 @@ CONFIG_PA7100LC=y # CONFIG_PA7300LC is not set # CONFIG_PA8X00 is not set CONFIG_PA11=y +CONFIG_PARISC_PAGE_SIZE_4KB=y +# CONFIG_PARISC_PAGE_SIZE_16KB is not set +# CONFIG_PARISC_PAGE_SIZE_64KB is not set # CONFIG_SMP is not set CONFIG_ARCH_FLATMEM_ENABLE=y # CONFIG_PREEMPT_NONE is not set @@ -98,6 +111,7 @@ CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set # CONFIG_HZ_100 is not set CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 CONFIG_SELECT_MEMORY_MODEL=y @@ -108,6 +122,9 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y # CONFIG_HPUX is not set # @@ -120,6 +137,7 @@ CONFIG_GSC_LASI=y # CONFIG_GSC_WAX is not set # CONFIG_EISA is not set # CONFIG_PCI is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set # # PCCARD (PCMCIA/CardBus) support @@ -127,14 +145,11 @@ CONFIG_GSC_LASI=y # CONFIG_PCCARD is not set # -# PCI Hotplug Support -# - -# # PA-RISC specific drivers # CONFIG_CHASSIS_LCD_LED=y # CONFIG_PDC_CHASSIS is not set +CONFIG_PDC_CHASSIS_WARN=y CONFIG_PDC_STABLE=y # @@ -151,13 +166,15 @@ CONFIG_NET=y # # Networking options # -# CONFIG_NETDEBUG is not set CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y CONFIG_XFRM_USER=m +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set CONFIG_NET_KEY=m +# CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -174,17 +191,23 @@ CONFIG_IP_PNP_BOOTP=y CONFIG_INET_AH=m CONFIG_INET_ESP=m # CONFIG_INET_IPCOMP is not set -CONFIG_INET_TUNNEL=m +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=m CONFIG_INET_TCP_DIAG=m # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y - -# -# IP: Virtual Server Configuration -# +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -192,37 +215,18 @@ CONFIG_NETFILTER=y # Core Netfilter Configuration # # CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NF_CONNTRACK_ENABLED is not set +# CONFIG_NF_CONNTRACK is not set # CONFIG_NETFILTER_XTABLES is not set # # IP: Netfilter Configuration # -CONFIG_IP_NF_CONNTRACK=m -# CONFIG_IP_NF_CT_ACCT is not set -CONFIG_IP_NF_CONNTRACK_MARK=y -# CONFIG_IP_NF_CONNTRACK_EVENTS is not set -CONFIG_IP_NF_CT_PROTO_SCTP=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_NETBIOS_NS is not set -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_AMANDA=m -# CONFIG_IP_NF_PPTP is not set CONFIG_IP_NF_QUEUE=m - -# -# DCCP Configuration (EXPERIMENTAL) -# +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set # CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# # CONFIG_IP_SCTP is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set @@ -234,7 +238,6 @@ CONFIG_LLC2=m # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -250,7 +253,17 @@ CONFIG_NET_PKTGEN=m # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -259,39 +272,24 @@ CONFIG_NET_PKTGEN=m # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set - -# -# Connector - unified userspace <-> kernelspace linker -# +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# # CONFIG_MTD is not set - -# -# Parallel port support -# CONFIG_PARPORT=y CONFIG_PARPORT_PC=m # CONFIG_PARPORT_PC_FIFO is not set # CONFIG_PARPORT_PC_SUPERIO is not set -CONFIG_PARPORT_NOT_PC=y CONFIG_PARPORT_GSC=y +# CONFIG_PARPORT_AX88796 is not set # CONFIG_PARPORT_1284 is not set - -# -# Plug and Play support -# - -# -# Block devices -# +CONFIG_PARPORT_NOT_PC=y +CONFIG_BLK_DEV=y # CONFIG_PARIDE is not set # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y @@ -300,13 +298,11 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=6144 -CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_CDROM_PKTCDVD is not set CONFIG_ATA_OVER_ETH=m - -# -# ATA/ATAPI/MFM/RLL support -# +CONFIG_MISC_DEVICES=y +# CONFIG_EEPROM_93CX6 is not set # CONFIG_IDE is not set # @@ -314,6 +310,9 @@ CONFIG_ATA_OVER_ETH=m # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y # @@ -333,104 +332,61 @@ CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m # -# SCSI Transport Attributes +# SCSI Transports # CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set CONFIG_SCSI_ISCSI_ATTRS=m -# CONFIG_SCSI_SAS_ATTRS is not set - -# -# SCSI low-level drivers -# +# CONFIG_SCSI_SAS_LIBSAS is not set +CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set -# CONFIG_SCSI_SATA is not set # CONFIG_SCSI_PPA is not set # CONFIG_SCSI_IMM is not set CONFIG_SCSI_LASI700=y CONFIG_53C700_LE_ON_BE=y # CONFIG_SCSI_ZALON is not set CONFIG_SCSI_DEBUG=m - -# -# Multi-device support (RAID and LVM) -# +# CONFIG_ATA is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_RAID6 is not set +# CONFIG_MD_RAID456 is not set # CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set # CONFIG_BLK_DEV_DM is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Network device support -# CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m CONFIG_BONDING=m +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=m - -# -# PHY device support -# +# CONFIG_VETH is not set # CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y CONFIG_MII=m CONFIG_LASI_82596=y +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_B44 is not set # CONFIG_NET_POCKET is not set +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y # -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y - -# -# Obsolete Wireless cards support (pre-802.11) -# -# CONFIG_STRIP is not set -# CONFIG_ATMEL is not set -# CONFIG_HOSTAP is not set - -# -# Wan interfaces +# Wireless LAN # +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set # CONFIG_WAN is not set # CONFIG_PLIP is not set CONFIG_PPP=m @@ -442,26 +398,22 @@ CONFIG_PPP_DEFLATE=m CONFIG_PPP_BSDCOMP=m CONFIG_PPP_MPPE=m CONFIG_PPPOE=m +# CONFIG_PPPOL2TP is not set # CONFIG_SLIP is not set +CONFIG_SLHC=m # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# # CONFIG_ISDN is not set - -# -# Telephony Support -# # CONFIG_PHONE is not set # # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -486,14 +438,22 @@ CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_HIL_OLD is not set CONFIG_KEYBOARD_HIL=y CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set CONFIG_MOUSE_SERIAL=m # CONFIG_MOUSE_VSXXXAA is not set CONFIG_MOUSE_HIL=m # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -516,6 +476,7 @@ CONFIG_SERIO_LIBPS2=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -523,6 +484,7 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_GSC=y CONFIG_SERIAL_8250_NR_UARTS=17 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y @@ -545,36 +507,15 @@ CONFIG_PRINTER=m # CONFIG_LP_CONSOLE is not set CONFIG_PPDEV=m # CONFIG_TIPAR is not set - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# # CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set CONFIG_GEN_RTC=y CONFIG_GEN_RTC_X=y -# CONFIG_DTLK is not set # CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# CONFIG_RAW_DRIVER=y CONFIG_MAX_RAW_DEVS=256 - -# -# TPM devices -# # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set - -# -# I2C support -# # CONFIG_I2C is not set # @@ -582,46 +523,59 @@ CONFIG_MAX_RAW_DEVS=256 # # CONFIG_SPI is not set # CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# # CONFIG_W1 is not set - -# -# Hardware Monitoring support -# +# CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set # -# Misc devices +# Sonics Silicon Backplane # +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # -# Multimedia Capabilities Port drivers +# Multifunction device drivers # +# CONFIG_MFD_SM501 is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DAB is not set # -# Digital Video Broadcasting Devices +# Graphics support # -# CONFIG_DVB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # -# Graphics support +# Display device support # +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_SYS_FOPS is not set +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y CONFIG_FB_TILEBLITTING=y + +# +# Frame buffer hardware drivers +# CONFIG_FB_STI=y # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set @@ -633,6 +587,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=128 CONFIG_DUMMY_CONSOLE_ROWS=48 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set CONFIG_STI_CONSOLE=y CONFIG_FONTS=y @@ -646,16 +601,11 @@ CONFIG_FONT_8x16=y # CONFIG_FONT_SUN8x16 is not set # CONFIG_FONT_SUN12x22 is not set # CONFIG_FONT_10x18 is not set - -# -# Logo configuration -# CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set # CONFIG_LOGO_LINUX_CLUT224 is not set CONFIG_LOGO_PARISC_CLUT224=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -673,9 +623,11 @@ CONFIG_SND_SEQUENCER=y CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -685,8 +637,10 @@ CONFIG_SND_SUPPORT_OLD_API=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_VIRMIDI is not set # CONFIG_SND_MTPAV is not set +# CONFIG_SND_MTS64 is not set # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_MPU401 is not set +# CONFIG_SND_PORTMAN2X4 is not set # # GSC devices @@ -694,15 +648,25 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_HARMONY=y # -# Open Sound System +# System on Chip audio support # -# CONFIG_SOUND_PRIME is not set +# CONFIG_SND_SOC is not set # -# USB support +# SoC Audio support for SuperH # + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y +CONFIG_USB_SUPPORT=y # CONFIG_USB_ARCH_HAS_HCD is not set # CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set # # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' @@ -712,19 +676,28 @@ CONFIG_SND_HARMONY=y # USB Gadget Support # # CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_RTC_CLASS is not set # -# MMC/SD Card support +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients # -# CONFIG_MMC is not set # -# InfiniBand support +# DMA Devices # +# CONFIG_AUXDISPLAY is not set # -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# Userspace I/O # +# CONFIG_UIO is not set # # File systems @@ -734,6 +707,7 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set # CONFIG_REISERFS_FS is not set @@ -744,15 +718,16 @@ CONFIG_JFS_FS=m # CONFIG_JFS_STATISTICS is not set CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=m -CONFIG_XFS_EXPORT=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -783,11 +758,12 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -795,6 +771,7 @@ CONFIG_RAMFS=y # # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set # CONFIG_HFS_FS is not set # CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set @@ -806,6 +783,8 @@ CONFIG_RAMFS=y # CONFIG_QNX4FS_FS is not set # CONFIG_SYSV_FS is not set CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set # # Network File Systems @@ -827,6 +806,7 @@ CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_BIND34 is not set CONFIG_RPCSEC_GSS_KRB5=y CONFIG_RPCSEC_GSS_SPKM3=m CONFIG_SMB_FS=m @@ -834,12 +814,13 @@ CONFIG_SMB_NLS_DEFAULT=y CONFIG_SMB_NLS_REMOTE="cp437" CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set # CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set # # Partition Types @@ -892,6 +873,11 @@ CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=m # +# Distributed Lock Manager +# +# CONFIG_DLM is not set + +# # Profiling support # CONFIG_PROFILING=y @@ -901,21 +887,32 @@ CONFIG_OPROFILE=m # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y -CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_FAULT_INJECTION is not set CONFIG_DEBUG_RODATA=y # @@ -924,12 +921,13 @@ CONFIG_DEBUG_RODATA=y CONFIG_KEYS=y CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set - -# -# Cryptographic options -# CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y @@ -938,9 +936,18 @@ CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_TGR192=m +# CONFIG_CRYPTO_GF128MUL is not set +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m @@ -949,21 +956,28 @@ CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_KHAZAD=m CONFIG_CRYPTO_ANUBIS=m +# CONFIG_CRYPTO_SEED is not set CONFIG_CRYPTO_DEFLATE=m CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_CAMELLIA is not set CONFIG_CRYPTO_TEST=m - -# -# Hardware crypto devices -# +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_HW is not set # # Library routines # +CONFIG_BITREVERSE=y CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=m CONFIG_ZLIB_DEFLATE=m +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig index f3b812f0459..ea071218a3e 100644 --- a/arch/parisc/configs/a500_defconfig +++ b/arch/parisc/configs/a500_defconfig @@ -1,73 +1,98 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.14-rc5-pa1 -# Fri Oct 21 23:04:54 2005 +# Linux kernel version: 2.6.23 +# Fri Oct 12 21:12:44 2007 # CONFIG_PARISC=y CONFIG_MMU=y CONFIG_STACK_GROWSUP=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME=y +CONFIG_TIME_LOW_RES=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_IRQ_PER_CPU=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -CONFIG_BROKEN=y -CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set +# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set -CONFIG_HOTPLUG=y -CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 # CONFIG_CPUSETS is not set +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y +CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SIGNALFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 - -# -# Loadable module support -# CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" # # Processor type and features @@ -80,11 +105,23 @@ CONFIG_PA8X00=y CONFIG_PA20=y CONFIG_PREFETCH=y CONFIG_64BIT=y +CONFIG_PARISC_PAGE_SIZE_4KB=y +# CONFIG_PARISC_PAGE_SIZE_16KB is not set +# CONFIG_PARISC_PAGE_SIZE_64KB is not set CONFIG_SMP=y CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y +CONFIG_NODES_SHIFT=3 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y # CONFIG_HZ_100 is not set CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 CONFIG_SELECT_MEMORY_MODEL=y @@ -95,7 +132,10 @@ CONFIG_DISCONTIGMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_NEED_MULTIPLE_NODES=y # CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_PREEMPT is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y CONFIG_COMPAT=y CONFIG_NR_CPUS=8 @@ -104,7 +144,7 @@ CONFIG_NR_CPUS=8 # # CONFIG_GSC is not set CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y +# CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCI_DEBUG is not set CONFIG_PCI_LBA=y CONFIG_IOSAPIC=y @@ -124,13 +164,14 @@ CONFIG_CARDBUS=y # PC-card bridges # CONFIG_YENTA=m +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y CONFIG_PD6729=m CONFIG_I82092=m CONFIG_PCCARD_NONSTATIC=m - -# -# PCI Hotplug Support -# # CONFIG_HOTPLUG_PCI is not set # @@ -139,6 +180,7 @@ CONFIG_PCCARD_NONSTATIC=m # CONFIG_SUPERIO is not set # CONFIG_CHASSIS_LCD_LED is not set CONFIG_PDC_CHASSIS=y +CONFIG_PDC_CHASSIS_WARN=y CONFIG_PDC_STABLE=y # @@ -160,7 +202,10 @@ CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y CONFIG_XFRM_USER=m +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set CONFIG_NET_KEY=m +# CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -177,97 +222,97 @@ CONFIG_IP_PNP_BOOTP=y CONFIG_INET_AH=m CONFIG_INET_ESP=m # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y - -# -# IP: Virtual Server Configuration -# +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set # CONFIG_IP_VS is not set CONFIG_IPV6=m # CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m +# CONFIG_IPV6_MIP6 is not set +CONFIG_INET6_XFRM_TUNNEL=m CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m CONFIG_IPV6_TUNNEL=m +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set + +# +# Core Netfilter Configuration +# # CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NF_CONNTRACK_ENABLED is not set +# CONFIG_NF_CONNTRACK is not set +CONFIG_NETFILTER_XTABLES=m +# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_MARK is not set +# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set +# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set +# CONFIG_NETFILTER_XT_MATCH_MAC is not set +# CONFIG_NETFILTER_XT_MATCH_MARK is not set +# CONFIG_NETFILTER_XT_MATCH_POLICY is not set +# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set +# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set +# CONFIG_NETFILTER_XT_MATCH_STRING is not set +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +# CONFIG_NETFILTER_XT_MATCH_U32 is not set +# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set # # IP: Netfilter Configuration # -CONFIG_IP_NF_CONNTRACK=m -# CONFIG_IP_NF_CT_ACCT is not set -CONFIG_IP_NF_CONNTRACK_MARK=y -# CONFIG_IP_NF_CONNTRACK_EVENTS is not set -CONFIG_IP_NF_CT_PROTO_SCTP=m -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_NETBIOS_NS is not set -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_AMANDA=m -# CONFIG_IP_NF_PPTP is not set CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m -CONFIG_IP_NF_MATCH_LIMIT=m CONFIG_IP_NF_MATCH_IPRANGE=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_AH is not set 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_OWNER=m # CONFIG_IP_NF_MATCH_ADDRTYPE is not set -# CONFIG_IP_NF_MATCH_REALM is not set -CONFIG_IP_NF_MATCH_SCTP=m -# CONFIG_IP_NF_MATCH_DCCP is not set -CONFIG_IP_NF_MATCH_COMMENT=m -CONFIG_IP_NF_MATCH_CONNMARK=m -CONFIG_IP_NF_MATCH_HASHLIMIT=m -# CONFIG_IP_NF_MATCH_STRING is not set CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m -CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_TARGET_NFQUEUE is not set -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_TARGET_NETMAP=m -CONFIG_IP_NF_TARGET_SAME=m -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_NAT_AMANDA=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_CLASSIFY=m # CONFIG_IP_NF_TARGET_TTL is not set -CONFIG_IP_NF_TARGET_CONNMARK=m -CONFIG_IP_NF_TARGET_CLUSTERIP=m CONFIG_IP_NF_RAW=m -CONFIG_IP_NF_TARGET_NOTRACK=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_ARP_MANGLE=m @@ -277,48 +322,38 @@ CONFIG_IP_NF_ARP_MANGLE=m # # CONFIG_IP6_NF_QUEUE is not set CONFIG_IP6_NF_IPTABLES=m -# CONFIG_IP6_NF_MATCH_LIMIT is not set -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 is not set # CONFIG_IP6_NF_MATCH_OWNER is not set -# CONFIG_IP6_NF_MATCH_MARK is not set CONFIG_IP6_NF_MATCH_IPV6HEADER=m -# CONFIG_IP6_NF_MATCH_AHESP is not set -# CONFIG_IP6_NF_MATCH_LENGTH is not set +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_MH is not set # CONFIG_IP6_NF_MATCH_EUI64 is not set CONFIG_IP6_NF_FILTER=m CONFIG_IP6_NF_TARGET_LOG=m CONFIG_IP6_NF_TARGET_REJECT=m -# CONFIG_IP6_NF_TARGET_NFQUEUE is not set CONFIG_IP6_NF_MANGLE=m -# CONFIG_IP6_NF_TARGET_MARK is not set # CONFIG_IP6_NF_TARGET_HL is not set CONFIG_IP6_NF_RAW=m - -# -# DCCP Configuration (EXPERIMENTAL) -# CONFIG_IP_DCCP=m CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y # # DCCP CCIDs Configuration (EXPERIMENTAL) # +CONFIG_IP_DCCP_CCID2=m +# CONFIG_IP_DCCP_CCID2_DEBUG is not set # CONFIG_IP_DCCP_CCID3 is not set # # DCCP Kernel Hacking # # CONFIG_IP_DCCP_DEBUG is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# # CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -329,11 +364,13 @@ CONFIG_LLC2=m # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# # CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set # # Network testing @@ -342,7 +379,17 @@ CONFIG_NET_PKTGEN=m # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -351,34 +398,17 @@ CONFIG_NET_PKTGEN=m # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set - -# -# Connector - unified userspace <-> kernelspace linker -# +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# # CONFIG_MTD is not set - -# -# Parallel port support -# # CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV=y # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -391,21 +421,14 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=6144 -CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_CDROM_PKTCDVD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y # CONFIG_ATA_OVER_ETH is not set - -# -# ATA/ATAPI/MFM/RLL support -# +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set # CONFIG_IDE is not set # @@ -413,6 +436,9 @@ CONFIG_IOSCHED_CFQ=y # CONFIG_RAID_ATTRS=m CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y # @@ -432,18 +458,18 @@ CONFIG_CHR_DEV_SG=y CONFIG_SCSI_MULTI_LUN=y # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m # -# SCSI Transport Attributes +# SCSI Transports # CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=m CONFIG_SCSI_ISCSI_ATTRS=m -CONFIG_SCSI_SAS_ATTRS=m - -# -# SCSI low-level drivers -# +# CONFIG_SCSI_SAS_LIBSAS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set @@ -451,59 +477,40 @@ CONFIG_SCSI_SAS_ATTRS=m # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set -# CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set CONFIG_SCSI_SYM53C8XX_2=y 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_IPR is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -CONFIG_SCSI_QLOGIC_FC=m -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y CONFIG_SCSI_QLOGIC_1280=m -# CONFIG_SCSI_QLOGIC_1280_1040 is not set -CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA21XX is not set -# CONFIG_SCSI_QLA22XX is not set -CONFIG_SCSI_QLA2300=m -CONFIG_SCSI_QLA2322=m -# CONFIG_SCSI_QLA6312 is not set -# CONFIG_SCSI_QLA24XX is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set CONFIG_SCSI_DEBUG=m - -# -# PCMCIA SCSI adapter support -# -CONFIG_PCMCIA_FDOMAIN=m -CONFIG_PCMCIA_QLOGIC=m -CONFIG_PCMCIA_SYM53C500=m - -# -# Multi-device support (RAID and LVM) -# +# CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_ATA is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y # CONFIG_MD_RAID10 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_RAID6 is not set +# CONFIG_MD_RAID456 is not set # CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set # CONFIG_BLK_DEV_DM is not set @@ -517,39 +524,25 @@ CONFIG_FUSION_FC=m # CONFIG_FUSION_SAS is not set CONFIG_FUSION_MAX_SGE=128 CONFIG_FUSION_CTL=m +# CONFIG_FUSION_LOGGING is not set # # IEEE 1394 (FireWire) support # +# CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set - -# -# I2O device support -# # CONFIG_I2O is not set - -# -# Network device support -# CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m CONFIG_BONDING=m +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=m - -# -# ARCnet devices -# +# CONFIG_VETH is not set +# CONFIG_IP1000 is not set # CONFIG_ARCNET is not set - -# -# PHY device support -# # CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y CONFIG_MII=m # CONFIG_HAPPYMEAL is not set @@ -558,10 +551,6 @@ CONFIG_MII=m CONFIG_NET_VENDOR_3COM=y CONFIG_VORTEX=m CONFIG_TYPHOON=m - -# -# Tulip family network device support -# CONFIG_NET_TULIP=y CONFIG_DE2104X=m CONFIG_TULIP=y @@ -573,15 +562,18 @@ CONFIG_TULIP_MMIO=y # CONFIG_DM9102 is not set # CONFIG_ULI526X is not set CONFIG_PCMCIA_XIRCOM=m -# CONFIG_PCMCIA_XIRTULIP is not set CONFIG_HP100=m +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set CONFIG_NET_PCI=y CONFIG_PCNET32=m +# CONFIG_PCNET32_NAPI is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set CONFIG_E100=m # CONFIG_FEALNX is not set @@ -593,84 +585,46 @@ CONFIG_E100=m # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set - -# -# Ethernet (1000 Mbit) -# +# CONFIG_SC92031 is not set +CONFIG_NETDEV_1000=y CONFIG_ACENIC=m CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=m CONFIG_E1000_NAPI=y # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_E1000E is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set # CONFIG_SIS190 is not set # CONFIG_SKGE is not set +# CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=m # CONFIG_BNX2 is not set - -# -# Ethernet (10000 Mbit) -# +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set - -# -# Token Ring devices -# +# CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_NIU is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set # CONFIG_TR is not set # -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y - -# -# Obsolete Wireless cards support (pre-802.11) -# -# CONFIG_STRIP is not set -# CONFIG_PCMCIA_WAVELAN is not set -CONFIG_PCMCIA_NETWAVE=m - -# -# Wireless 802.11 Frequency Hopping cards support -# -CONFIG_PCMCIA_RAYCS=m - -# -# Wireless 802.11b ISA/PCI cards support -# -CONFIG_HERMES=m -CONFIG_PLX_HERMES=m -CONFIG_TMD_HERMES=m -# CONFIG_NORTEL_HERMES is not set -CONFIG_PCI_HERMES=m -# CONFIG_ATMEL is not set - -# -# Wireless 802.11b Pcmcia/Cardbus cards support -# -CONFIG_PCMCIA_HERMES=m -# CONFIG_PCMCIA_SPECTRUM is not set -CONFIG_AIRO_CS=m -CONFIG_PCMCIA_WL3501=m - -# -# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support -# -# CONFIG_PRISM54 is not set -# CONFIG_HOSTAP is not set -CONFIG_NET_WIRELESS=y - -# -# PCMCIA network device support +# Wireless LAN # +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set CONFIG_NET_PCMCIA=y CONFIG_PCMCIA_3C589=m CONFIG_PCMCIA_3C574=m @@ -680,10 +634,6 @@ CONFIG_PCMCIA_3C574=m CONFIG_PCMCIA_SMC91C92=m CONFIG_PCMCIA_XIRC2PS=m # CONFIG_PCMCIA_AXNET is not set - -# -# Wan interfaces -# # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -694,28 +644,25 @@ CONFIG_PPP_ASYNC=m CONFIG_PPP_SYNC_TTY=m CONFIG_PPP_DEFLATE=m CONFIG_PPP_BSDCOMP=m +# CONFIG_PPP_MPPE is not set # CONFIG_PPPOE is not set +# CONFIG_PPPOL2TP is not set # CONFIG_SLIP is not set +CONFIG_SLHC=m # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# # CONFIG_ISDN is not set - -# -# Telephony Support -# # CONFIG_PHONE is not set # # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -732,6 +679,7 @@ CONFIG_INPUT=y # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -747,6 +695,7 @@ CONFIG_INPUT=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -754,8 +703,10 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y CONFIG_SERIAL_8250_CS=m CONFIG_SERIAL_8250_NR_UARTS=17 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y @@ -765,83 +716,73 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y # # Non-8250 serial port support # -# CONFIG_SERIAL_MUX is not set CONFIG_PDC_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# # CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set CONFIG_GEN_RTC=y CONFIG_GEN_RTC_X=y -# CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# +CONFIG_AGP=y +CONFIG_AGP_PARISC=y # CONFIG_DRM is not set # # PCMCIA character devices # # CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set CONFIG_RAW_DRIVER=y CONFIG_MAX_RAW_DEVS=256 - -# -# TPM devices -# # CONFIG_TCG_TPM is not set - -# -# I2C support -# +CONFIG_DEVPORT=y # CONFIG_I2C is not set # -# Dallas's 1-wire bus +# SPI support # +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set # CONFIG_W1 is not set - -# -# Hardware Monitoring support -# +# CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set # -# Misc devices +# Sonics Silicon Backplane # +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # -# Multimedia Capabilities Port drivers +# Multifunction device drivers # +# CONFIG_MFD_SM501 is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DAB is not set # -# Digital Video Broadcasting Devices +# Graphics support # -# CONFIG_DVB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # -# Graphics support +# Display device support # +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set # CONFIG_FB is not set # @@ -856,34 +797,47 @@ CONFIG_DUMMY_CONSOLE_ROWS=64 # Sound # # CONFIG_SOUND is not set - -# -# USB support -# +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_USB is not set # +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# # USB Gadget Support # # CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_INFINIBAND is not set +# CONFIG_RTC_CLASS is not set # -# MMC/SD Card support +# DMA Engine support # -# CONFIG_MMC is not set +# CONFIG_DMA_ENGINE is not set # -# InfiniBand support +# DMA Clients # -# CONFIG_INFINIBAND is not set # -# SN Devices +# DMA Devices # # +# Userspace I/O +# +# CONFIG_UIO is not set + +# # File systems # CONFIG_EXT2_FS=y @@ -891,6 +845,7 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set # CONFIG_REISERFS_FS is not set @@ -901,14 +856,16 @@ CONFIG_JFS_FS=m # CONFIG_JFS_STATISTICS is not set CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=m -CONFIG_XFS_EXPORT=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -939,18 +896,20 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y -# CONFIG_HUGETLBFS is not set +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems # # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set # CONFIG_HFS_FS is not set # CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set @@ -963,6 +922,7 @@ CONFIG_RAMFS=y # CONFIG_SYSV_FS is not set CONFIG_UFS_FS=m # CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set # # Network File Systems @@ -983,6 +943,7 @@ CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m +# CONFIG_SUNRPC_BIND34 is not set CONFIG_RPCSEC_GSS_KRB5=m CONFIG_RPCSEC_GSS_SPKM3=m CONFIG_SMB_FS=m @@ -990,12 +951,13 @@ CONFIG_SMB_NLS_DEFAULT=y CONFIG_SMB_NLS_REMOTE="cp437" CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set # CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set # # Partition Types @@ -1048,6 +1010,11 @@ CONFIG_NLS_ISO8859_15=m CONFIG_NLS_UTF8=m # +# Distributed Lock Manager +# +# CONFIG_DLM is not set + +# # Profiling support # CONFIG_PROFILING=y @@ -1057,19 +1024,34 @@ CONFIG_OPROFILE=m # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y +CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y -CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +CONFIG_HEADERS_CHECK=y +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_IOREMAP is not set -# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_FAULT_INJECTION is not set # CONFIG_DEBUG_RWLOCK is not set +# CONFIG_DEBUG_RODATA is not set # # Security options @@ -1077,12 +1059,13 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_KEYS=y CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set - -# -# Cryptographic options -# CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set CONFIG_CRYPTO_NULL=m # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y @@ -1091,32 +1074,47 @@ CONFIG_CRYPTO_SHA1=m # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_ECB is not set +CONFIG_CRYPTO_CBC=m +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_FCRYPT is not set CONFIG_CRYPTO_BLOWFISH=m # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_AES is not set -# CONFIG_CRYPTO_CAST5 is not set +CONFIG_CRYPTO_CAST5=m # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set CONFIG_CRYPTO_DEFLATE=m # CONFIG_CRYPTO_MICHAEL_MIC is not set CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_CAMELLIA is not set CONFIG_CRYPTO_TEST=m - -# -# Hardware crypto devices -# +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_HW is not set # # Library routines # +CONFIG_BITREVERSE=y CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=m CONFIG_ZLIB_DEFLATE=m +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/parisc/configs/b180_defconfig b/arch/parisc/configs/b180_defconfig index 35093612ad2..1bf22c9a461 100644 --- a/arch/parisc/configs/b180_defconfig +++ b/arch/parisc/configs/b180_defconfig @@ -1,38 +1,47 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-rc1-pa0 -# Tue Jan 17 08:21:01 2006 +# Linux kernel version: 2.6.23 +# Fri Oct 12 21:16:46 2007 # CONFIG_PARISC=y CONFIG_MMU=y CONFIG_STACK_GROWSUP=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_IRQ_PER_CPU=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # # CONFIG_EXPERIMENTAL is not set -CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -CONFIG_INITRAMFS_SOURCE="" +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -42,30 +51,27 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set - -# -# Loadable module support -# CONFIG_MODULES=y # CONFIG_MODULE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y # CONFIG_MODULE_SRCVERSION_ALL is not set # CONFIG_KMOD is not set - -# -# Block layer -# +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set # # IO Schedulers @@ -89,16 +95,26 @@ CONFIG_PA7100LC=y # CONFIG_PA7300LC is not set # CONFIG_PA8X00 is not set CONFIG_PA11=y +CONFIG_PARISC_PAGE_SIZE_4KB=y +# CONFIG_PARISC_PAGE_SIZE_16KB is not set +# CONFIG_PARISC_PAGE_SIZE_64KB is not set # CONFIG_SMP is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set # CONFIG_HZ_100 is not set CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4096 -# CONFIG_PREEMPT is not set +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y # CONFIG_HPUX is not set # @@ -113,7 +129,7 @@ CONFIG_EISA=y CONFIG_EISA_NAMES=y CONFIG_ISA=y CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y +# CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCI_DEBUG is not set CONFIG_GSC_DINO=y # CONFIG_PCI_LBA is not set @@ -124,14 +140,11 @@ CONFIG_GSC_DINO=y # CONFIG_PCCARD is not set # -# PCI Hotplug Support -# - -# # PA-RISC specific drivers # CONFIG_CHASSIS_LCD_LED=y # CONFIG_PDC_CHASSIS is not set +CONFIG_PDC_CHASSIS_WARN=y CONFIG_PDC_STABLE=y # @@ -151,6 +164,8 @@ CONFIG_NET=y CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -167,18 +182,32 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +CONFIG_IPV6_SIT=y # CONFIG_IPV6_TUNNEL is not set +# CONFIG_NETLABEL is not set +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -199,7 +228,14 @@ CONFIG_IPV6=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set # CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set # # Device Drivers @@ -208,39 +244,24 @@ CONFIG_IPV6=y # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y # CONFIG_PREVENT_FIRMWARE_BUILD is not set # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set - -# -# Connector - unified userspace <-> kernelspace linker -# +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# # CONFIG_MTD is not set - -# -# Parallel port support -# CONFIG_PARPORT=y CONFIG_PARPORT_PC=y # CONFIG_PARPORT_SERIAL is not set -CONFIG_PARPORT_NOT_PC=y CONFIG_PARPORT_GSC=y +# CONFIG_PARPORT_AX88796 is not set # CONFIG_PARPORT_1284 is not set - -# -# Plug and Play support -# +CONFIG_PARPORT_NOT_PC=y # CONFIG_PNP is not set - -# -# Block devices -# +CONFIG_BLK_DEV=y # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set @@ -251,15 +272,13 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_RAM is not set -CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_CDROM_PKTCDVD=m CONFIG_CDROM_PKTCDVD_BUFFERS=8 -# CONFIG_CDROM_PKTCDVD_WCACHE is not set CONFIG_ATA_OVER_ETH=y - -# -# ATA/ATAPI/MFM/RLL support -# +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_SGI_IOC4 is not set # CONFIG_IDE is not set # @@ -267,6 +286,8 @@ CONFIG_ATA_OVER_ETH=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y # @@ -286,18 +307,17 @@ CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m # -# SCSI Transport Attributes +# SCSI Transports # CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_ATTRS is not set - -# -# SCSI low-level drivers -# +# CONFIG_SCSI_SAS_LIBSAS is not set +CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set @@ -308,12 +328,14 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set -# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set @@ -327,23 +349,22 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_NCR53C406A is not set CONFIG_SCSI_LASI700=y CONFIG_53C700_LE_ON_BE=y +# CONFIG_SCSI_STEX 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_MMIO=y -# CONFIG_SCSI_IPR is not set CONFIG_SCSI_ZALON=y 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_PAS16 is not set # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_SYM53C416 is not set @@ -351,22 +372,14 @@ CONFIG_SCSI_NCR53C8XX_SYNC=40 # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Multi-device support (RAID and LVM) -# +# CONFIG_SCSI_SRP is not set +# CONFIG_ATA is not set 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_RAID6=y +# CONFIG_MD_RAID456 is not set # CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set # CONFIG_BLK_DEV_DM is not set @@ -382,35 +395,21 @@ CONFIG_MD_RAID6=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # -# I2O device support +# An alternative FireWire stack is available with EXPERIMENTAL=y # +# CONFIG_IEEE1394 is not set # CONFIG_I2O is not set - -# -# Network device support -# CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set - -# -# ARCnet devices -# +# CONFIG_VETH is not set # CONFIG_ARCNET is not set - -# -# PHY device support -# # CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y # CONFIG_MII is not set CONFIG_LASI_82596=y @@ -420,10 +419,6 @@ CONFIG_LASI_82596=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set - -# -# Tulip family network device support -# CONFIG_NET_TULIP=y CONFIG_TULIP=y # CONFIG_TULIP_MMIO is not set @@ -435,62 +430,47 @@ CONFIG_TULIP=y # CONFIG_DEPCA is not set # CONFIG_HP100 is not set # CONFIG_NET_ISA is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set # CONFIG_NET_PCI is not set +# CONFIG_B44 is not set # CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# +CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set +# CONFIG_E1000E is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_R8169 is not set # CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set - -# -# Ethernet (10000 Mbit) -# +# CONFIG_QLA3XXX is not set +CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set - -# -# Token Ring devices -# +# CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_NIU is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set # CONFIG_TR is not set # -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y - -# -# Obsolete Wireless cards support (pre-802.11) -# -# CONFIG_STRIP is not set -# CONFIG_ARLAN is not set -# CONFIG_WAVELAN is not set - -# -# Wireless 802.11b ISA/PCI cards support -# -# CONFIG_HERMES is not set -# CONFIG_ATMEL is not set - -# -# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support -# -# CONFIG_HOSTAP is not set -CONFIG_NET_WIRELESS=y - -# -# Wan interfaces +# Wireless LAN # +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_PLIP is not set @@ -501,24 +481,19 @@ CONFIG_PPP=y # CONFIG_PPP_DEFLATE is not set # CONFIG_PPP_BSDCOMP is not set # CONFIG_SLIP is not set +CONFIG_SLHC=y # CONFIG_NET_FC is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# # CONFIG_ISDN is not set - -# -# Telephony Support -# # CONFIG_PHONE is not set # # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -543,19 +518,31 @@ CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_HIL_OLD is not set CONFIG_KEYBOARD_HIL=y CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set # CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set # CONFIG_MOUSE_INPORT is not set # CONFIG_MOUSE_LOGIBM is not set # CONFIG_MOUSE_PC110PAD is not set # CONFIG_MOUSE_VSXXXAA is not set CONFIG_MOUSE_HIL=y # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set CONFIG_INPUT_MISC=y +# CONFIG_INPUT_ATI_REMOTE is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_POWERMATE is not set # CONFIG_INPUT_UINPUT is not set # CONFIG_HP_SDC_RTC is not set @@ -579,6 +566,7 @@ CONFIG_SERIO_LIBPS2=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -586,17 +574,20 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_GSC=y +CONFIG_SERIAL_8250_PCI=y CONFIG_SERIAL_8250_NR_UARTS=13 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y -CONFIG_SERIAL_8250_SHARE_IRQ=y -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_RSA is not set # CONFIG_SERIAL_8250_FOURPORT is not set # CONFIG_SERIAL_8250_ACCENT is not set # CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set # CONFIG_SERIAL_8250_HUB6 is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set # # Non-8250 serial port support @@ -605,6 +596,7 @@ CONFIG_SERIAL_MUX=y CONFIG_SERIAL_MUX_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -612,35 +604,18 @@ CONFIG_PRINTER=y # CONFIG_LP_CONSOLE is not set # CONFIG_PPDEV is not set # CONFIG_TIPAR is not set - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# # CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set CONFIG_GEN_RTC=y # CONFIG_GEN_RTC_X is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# +# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# - -# -# I2C support -# +CONFIG_DEVPORT=y # CONFIG_I2C is not set # @@ -648,46 +623,59 @@ CONFIG_GEN_RTC=y # # CONFIG_SPI is not set # CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# # CONFIG_W1 is not set - -# -# Hardware Monitoring support -# +# CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set # -# Misc devices +# Sonics Silicon Backplane # +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # -# Multimedia Capabilities Port drivers +# Multifunction device drivers # +# CONFIG_MFD_SM501 is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DAB is not set # -# Digital Video Broadcasting Devices +# Graphics support # -# CONFIG_DVB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # -# Graphics support +# Display device support # +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_SYS_FOPS is not set +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set # CONFIG_FB_MODE_HELPERS is not set # CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# # CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set @@ -698,16 +686,18 @@ CONFIG_FB_STI=y # CONFIG_FB_NVIDIA is not set # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set # CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set # CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set # CONFIG_FB_VIRTUAL is not set # @@ -717,21 +707,17 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=160 CONFIG_DUMMY_CONSOLE_ROWS=64 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set CONFIG_STI_CONSOLE=y # CONFIG_FONTS is not set CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y - -# -# Logo configuration -# CONFIG_LOGO=y CONFIG_LOGO_LINUX_MONO=y CONFIG_LOGO_LINUX_VGA16=y CONFIG_LOGO_LINUX_CLUT224=y CONFIG_LOGO_PARISC_CLUT224=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -749,8 +735,11 @@ CONFIG_SND_SEQUENCER=y CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -760,13 +749,16 @@ CONFIG_SND_SUPPORT_OLD_API=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_VIRMIDI is not set # CONFIG_SND_MTPAV is not set +# CONFIG_SND_MTS64 is not set # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_MPU401 is not set +# CONFIG_SND_PORTMAN2X4 is not set # # PCI devices # # CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ATIIXP is not set # CONFIG_SND_ATIIXP_MODEM is not set @@ -778,6 +770,18 @@ CONFIG_SND_SUPPORT_OLD_API=y # CONFIG_SND_CMIPCI is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1X is not set # CONFIG_SND_ENS1370 is not set @@ -791,11 +795,13 @@ CONFIG_SND_SUPPORT_OLD_API=y # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set # CONFIG_SND_KORG1212 is not set # CONFIG_SND_MAESTRO3 is not set # CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set # CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set @@ -812,15 +818,25 @@ CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_HARMONY=y # -# Open Sound System +# System on Chip audio support # -# CONFIG_SOUND_PRIME is not set +# CONFIG_SND_SOC is not set # -# USB support +# SoC Audio support for SuperH +# + +# +# Open Sound System # +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y +CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y # CONFIG_USB is not set # @@ -831,20 +847,29 @@ CONFIG_USB_ARCH_HAS_OHCI=y # USB Gadget Support # # CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_INFINIBAND is not set +# CONFIG_RTC_CLASS is not set # -# MMC/SD Card support +# DMA Engine support # -# CONFIG_MMC is not set +# CONFIG_DMA_ENGINE is not set # -# InfiniBand support +# DMA Clients # -# CONFIG_INFINIBAND is not set # -# SN Devices +# DMA Devices # +# CONFIG_AUXDISPLAY is not set + +# +# Userspace I/O +# +# CONFIG_UIO is not set # # File systems @@ -860,9 +885,11 @@ CONFIG_JBD=y # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -889,11 +916,12 @@ CONFIG_JOLIET=y # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -912,6 +940,7 @@ CONFIG_RAMFS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_DIRECTIO is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y # CONFIG_NFSD_V3_ACL is not set @@ -982,22 +1011,32 @@ CONFIG_NLS_UTF8=m # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y -CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_IOREMAP is not set -# CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_FAULT_INJECTION is not set # CONFIG_DEBUG_RODATA is not set # @@ -1007,13 +1046,10 @@ CONFIG_FORCED_INLINING=y CONFIG_SECURITY=y # CONFIG_SECURITY_NETWORK is not set CONFIG_SECURITY_CAPABILITIES=y -# CONFIG_SECURITY_SECLVL is not set -# CONFIG_SECURITY_SELINUX is not set - -# -# Cryptographic options -# CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_MANAGER=y # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_MD4 is not set @@ -1023,7 +1059,12 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_ECB is not set +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_CRYPTD is not set # CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set @@ -1034,19 +1075,26 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_TEST is not set - -# -# Hardware crypto devices -# +# CONFIG_CRYPTO_AUTHENC is not set +CONFIG_CRYPTO_HW=y # # Library routines # +CONFIG_BITREVERSE=y # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set # CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig index eb2f9a3d515..c6def3c1d20 100644 --- a/arch/parisc/configs/c3000_defconfig +++ b/arch/parisc/configs/c3000_defconfig @@ -1,39 +1,50 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-pa6 -# Sun Mar 26 20:03:29 2006 +# Linux kernel version: 2.6.23 +# Fri Oct 12 21:24:00 2007 # CONFIG_PARISC=y CONFIG_MMU=y CONFIG_STACK_GROWSUP=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_IRQ_PER_CPU=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set +# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -CONFIG_INITRAMFS_SOURCE="" +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -43,31 +54,29 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set - -# -# Loadable module support -# CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y - -# -# Block layer -# +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set # # IO Schedulers @@ -93,6 +102,9 @@ CONFIG_PA8X00=y CONFIG_PA20=y CONFIG_PREFETCH=y # CONFIG_64BIT is not set +CONFIG_PARISC_PAGE_SIZE_4KB=y +# CONFIG_PARISC_PAGE_SIZE_16KB is not set +# CONFIG_PARISC_PAGE_SIZE_64KB is not set # CONFIG_SMP is not set CONFIG_ARCH_FLATMEM_ENABLE=y # CONFIG_PREEMPT_NONE is not set @@ -100,6 +112,7 @@ CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set # CONFIG_HZ_100 is not set CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 CONFIG_SELECT_MEMORY_MODEL=y @@ -110,6 +123,9 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y # CONFIG_HPUX is not set # @@ -117,7 +133,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # # CONFIG_GSC is not set CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y +# CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCI_DEBUG is not set CONFIG_PCI_LBA=y CONFIG_IOSAPIC=y @@ -127,10 +143,6 @@ CONFIG_IOMMU_SBA=y # PCCARD (PCMCIA/CardBus) support # # CONFIG_PCCARD is not set - -# -# PCI Hotplug Support -# # CONFIG_HOTPLUG_PCI is not set # @@ -139,6 +151,7 @@ CONFIG_IOMMU_SBA=y CONFIG_SUPERIO=y CONFIG_CHASSIS_LCD_LED=y # CONFIG_PDC_CHASSIS is not set +CONFIG_PDC_CHASSIS_WARN=y CONFIG_PDC_STABLE=y # @@ -155,13 +168,15 @@ CONFIG_NET=y # # Networking options # -# CONFIG_NETDEBUG is not set CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y CONFIG_XFRM_USER=m +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set CONFIG_NET_KEY=m +# CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -178,22 +193,36 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y - -# -# IP: Virtual Server Configuration -# +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set # CONFIG_IP_VS is not set CONFIG_IPV6=m # CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set CONFIG_INET6_IPCOMP=m +# CONFIG_IPV6_MIP6 is not set +CONFIG_INET6_XFRM_TUNNEL=m CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m CONFIG_IPV6_TUNNEL=m +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y CONFIG_NETFILTER_DEBUG=y @@ -201,42 +230,24 @@ CONFIG_NETFILTER_DEBUG=y # Core Netfilter Configuration # # CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NF_CONNTRACK_ENABLED is not set +# CONFIG_NF_CONNTRACK is not set # CONFIG_NETFILTER_XTABLES is not set # # IP: Netfilter Configuration # -CONFIG_IP_NF_CONNTRACK=m -# CONFIG_IP_NF_CT_ACCT is not set -# CONFIG_IP_NF_CONNTRACK_MARK is not set -# CONFIG_IP_NF_CONNTRACK_EVENTS is not set -# CONFIG_IP_NF_CT_PROTO_SCTP is not set -CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_NETBIOS_NS is not set -CONFIG_IP_NF_TFTP=m -CONFIG_IP_NF_AMANDA=m -# CONFIG_IP_NF_PPTP is not set CONFIG_IP_NF_QUEUE=m +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set # # IPv6: Netfilter Configuration (EXPERIMENTAL) # # CONFIG_IP6_NF_QUEUE is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# +# CONFIG_IP6_NF_IPTABLES is not set # CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# # CONFIG_IP_SCTP is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set @@ -247,7 +258,6 @@ CONFIG_IP_NF_QUEUE=m # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -263,7 +273,17 @@ CONFIG_NET_PKTGEN=m # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -272,33 +292,17 @@ CONFIG_NET_PKTGEN=m # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set - -# -# Connector - unified userspace <-> kernelspace linker -# +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# # CONFIG_MTD is not set - -# -# Parallel port support -# # CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# +CONFIG_BLK_DEV=y # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -310,14 +314,15 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m # CONFIG_BLK_DEV_SX8 is not set # CONFIG_BLK_DEV_UB is not set # CONFIG_BLK_DEV_RAM is not set -CONFIG_BLK_DEV_RAM_COUNT=16 # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set - -# -# ATA/ATAPI/MFM/RLL support -# +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set CONFIG_IDE=y +CONFIG_IDE_MAX_HWIFS=4 CONFIG_BLK_DEV_IDE=y # @@ -331,19 +336,26 @@ CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDEFLOPPY is not set CONFIG_BLK_DEV_IDESCSI=y # CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_PROC_FS=y # # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_PLATFORM is not set + +# +# PCI IDE chipsets support +# CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_IDEPCI_PCIBUS_ORDER=y # CONFIG_BLK_DEV_OFFBOARD is not set # CONFIG_BLK_DEV_GENERIC is not set # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set -# CONFIG_IDEDMA_PCI_AUTO is not set +CONFIG_IDEDMA_ONLYDISK=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set @@ -354,8 +366,10 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_CS5530 is not set # CONFIG_BLK_DEV_HPT34X is not set # CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_JMICRON is not set # CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT8213 is not set # CONFIG_BLK_DEV_IT821X is not set CONFIG_BLK_DEV_NS87415=y # CONFIG_BLK_DEV_PDC202XX_OLD is not set @@ -365,10 +379,10 @@ CONFIG_BLK_DEV_SIIMAGE=m # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_TC86C001 is not set # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set -# CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set # @@ -376,6 +390,9 @@ CONFIG_BLK_DEV_IDEDMA=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y # @@ -395,18 +412,17 @@ CONFIG_CHR_DEV_SG=y CONFIG_SCSI_MULTI_LUN=y # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m # -# SCSI Transport Attributes +# SCSI Transports # CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set CONFIG_SCSI_ISCSI_ATTRS=m -# CONFIG_SCSI_SAS_ATTRS is not set - -# -# SCSI low-level drivers -# +# CONFIG_SCSI_SAS_LIBSAS is not set +CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set @@ -415,66 +431,53 @@ CONFIG_SCSI_ISCSI_ATTRS=m # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set # CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set -CONFIG_SCSI_SATA=y -# CONFIG_SCSI_SATA_AHCI is not set -# CONFIG_SCSI_SATA_SVW is not set -CONFIG_SCSI_ATA_PIIX=m -# CONFIG_SCSI_SATA_MV is not set -# CONFIG_SCSI_SATA_NV is not set -# CONFIG_SCSI_PDC_ADMA is not set -# CONFIG_SCSI_SATA_QSTOR is not set -CONFIG_SCSI_SATA_PROMISE=m -# CONFIG_SCSI_SATA_SX4 is not set -CONFIG_SCSI_SATA_SIL=m -# CONFIG_SCSI_SATA_SIL24 is not set -# CONFIG_SCSI_SATA_SIS is not set -# CONFIG_SCSI_SATA_ULI is not set -CONFIG_SCSI_SATA_VIA=m -# CONFIG_SCSI_SATA_VITESSE is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX 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_MMIO=y -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_NSP32 is not set CONFIG_SCSI_DEBUG=m - -# -# Multi-device support (RAID and LVM) -# +# CONFIG_SCSI_SRP is not set +# CONFIG_ATA is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y # CONFIG_MD_RAID10 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_RAID6 is not set +# CONFIG_MD_RAID456 is not set # CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=m +# CONFIG_DM_DEBUG is not set CONFIG_DM_CRYPT=m CONFIG_DM_SNAPSHOT=m CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m # CONFIG_DM_MULTIPATH_EMC is not set +# CONFIG_DM_MULTIPATH_RDAC is not set +# CONFIG_DM_DELAY is not set # # Fusion MPT device support @@ -485,49 +488,31 @@ CONFIG_FUSION_SPI=m # CONFIG_FUSION_SAS is not set CONFIG_FUSION_MAX_SGE=128 CONFIG_FUSION_CTL=m +# CONFIG_FUSION_LOGGING is not set # # IEEE 1394 (FireWire) support # +# CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set - -# -# I2O device support -# # CONFIG_I2O is not set - -# -# Network device support -# CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m CONFIG_BONDING=m +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=m - -# -# ARCnet devices -# +# CONFIG_VETH is not set +# CONFIG_IP1000 is not set # CONFIG_ARCNET is not set - -# -# PHY device support -# # CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y CONFIG_MII=m # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# CONFIG_NET_TULIP=y CONFIG_DE2104X=m CONFIG_TULIP=y @@ -539,13 +524,16 @@ CONFIG_TULIP_MMIO=y # CONFIG_DM9102 is not set # CONFIG_ULI526X is not set # CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set CONFIG_E100=m # CONFIG_FEALNX is not set @@ -558,16 +546,15 @@ CONFIG_E100=m # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set - -# -# Ethernet (1000 Mbit) -# +# CONFIG_SC92031 is not set +CONFIG_NETDEV_1000=y CONFIG_ACENIC=m # CONFIG_ACENIC_OMIT_TIGON_I is not set # CONFIG_DL2K is not set CONFIG_E1000=m # CONFIG_E1000_NAPI is not set # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_E1000E is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -579,27 +566,36 @@ CONFIG_E1000=m # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=m # CONFIG_BNX2 is not set - -# -# Ethernet (10000 Mbit) -# +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set - -# -# Token Ring devices -# +# CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_NIU is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set # CONFIG_TR is not set # -# Wireless LAN (non-hamradio) +# Wireless LAN # -# CONFIG_NET_RADIO is not set +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set # -# Wan interfaces +# USB Network Adapters # +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -612,27 +608,23 @@ CONFIG_PPP_DEFLATE=m CONFIG_PPP_BSDCOMP=m # CONFIG_PPP_MPPE is not set CONFIG_PPPOE=m +# CONFIG_PPPOL2TP is not set # CONFIG_SLIP is not set +CONFIG_SLHC=m # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# # CONFIG_ISDN is not set - -# -# Telephony Support -# # CONFIG_PHONE is not set # # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -655,11 +647,14 @@ CONFIG_INPUT_KEYBOARD=y # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set CONFIG_INPUT_MOUSE=y # CONFIG_MOUSE_PS2 is not set # CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set # CONFIG_MOUSE_VSXXXAA is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -679,6 +674,7 @@ CONFIG_SERIO_LIBPS2=m CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -686,6 +682,7 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y CONFIG_SERIAL_8250_NR_UARTS=13 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y @@ -704,38 +701,19 @@ CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# # CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set CONFIG_GEN_RTC=y CONFIG_GEN_RTC_X=y -# CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# +# CONFIG_AGP is not set # CONFIG_DRM is not set CONFIG_RAW_DRIVER=y CONFIG_MAX_RAW_DEVS=256 - -# -# TPM devices -# # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set - -# -# I2C support -# +CONFIG_DEVPORT=y # CONFIG_I2C is not set # @@ -743,46 +721,59 @@ CONFIG_MAX_RAW_DEVS=256 # # CONFIG_SPI is not set # CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# # CONFIG_W1 is not set - -# -# Hardware Monitoring support -# +# CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set # -# Misc devices +# Sonics Silicon Backplane # +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # -# Multimedia Capabilities Port drivers +# Multifunction device drivers # +# CONFIG_MFD_SM501 is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DAB is not set # -# Digital Video Broadcasting Devices +# Graphics support # -# CONFIG_DVB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # -# Graphics support +# Display device support # +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_SYS_FOPS is not set +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set # CONFIG_FB_MODE_HELPERS is not set # CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# # CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set @@ -793,17 +784,20 @@ CONFIG_FB_STI=y # CONFIG_FB_NVIDIA is not set # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set # CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set # CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set # CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set # CONFIG_FB_VIRTUAL is not set # @@ -813,21 +807,17 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=160 CONFIG_DUMMY_CONSOLE_ROWS=64 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set CONFIG_STI_CONSOLE=y # CONFIG_FONTS is not set CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y - -# -# Logo configuration -# CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set # CONFIG_LOGO_LINUX_CLUT224 is not set CONFIG_LOGO_PARISC_CLUT224=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -845,9 +835,11 @@ CONFIG_SND_SEQUENCER=y CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -855,7 +847,6 @@ CONFIG_SND_SUPPORT_OLD_API=y # Generic devices # CONFIG_SND_AC97_CODEC=y -CONFIG_SND_AC97_BUS=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_VIRMIDI is not set # CONFIG_SND_MTPAV is not set @@ -866,7 +857,7 @@ CONFIG_SND_AC97_BUS=y # PCI devices # CONFIG_SND_AD1889=y -# CONFIG_SND_AD1889_OPL3 is not set +# CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ATIIXP is not set # CONFIG_SND_ATIIXP_MODEM is not set @@ -879,6 +870,18 @@ CONFIG_SND_AD1889=y # CONFIG_SND_CMIPCI is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1X is not set # CONFIG_SND_ENS1370 is not set @@ -898,6 +901,7 @@ CONFIG_SND_AD1889=y # CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set # CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set @@ -907,22 +911,43 @@ CONFIG_SND_AD1889=y # CONFIG_SND_VIA82XX_MODEM is not set # CONFIG_SND_VX222 is not set # CONFIG_SND_YMFPCI is not set +# CONFIG_SND_AC97_POWER_SAVE is not set # # USB devices # # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set + +# +# System on Chip audio support +# +# CONFIG_SND_SOC is not set + +# +# SoC Audio support for SuperH +# # # Open Sound System # # CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=y +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set # -# USB support +# USB Input Devices # +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +CONFIG_USB_HIDDEV=y +CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y CONFIG_USB_DEBUG=y @@ -930,7 +955,7 @@ CONFIG_USB_DEBUG=y # Miscellaneous USB options # CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set +CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_OTG is not set @@ -940,15 +965,16 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_EHCI_HCD is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y -# CONFIG_USB_OHCI_BIG_ENDIAN is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_UHCI_HCD is not set # CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set # # USB Device Class drivers # -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set # CONFIG_USB_ACM is not set CONFIG_USB_PRINTER=m @@ -970,54 +996,14 @@ CONFIG_USB_STORAGE_SDDR09=y CONFIG_USB_STORAGE_SDDR55=y CONFIG_USB_STORAGE_JUMPSHOT=y # CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_KARMA is not set # CONFIG_USB_LIBUSUAL is not set # -# USB Input Devices -# -CONFIG_USB_HID=y -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -CONFIG_USB_HIDDEV=y -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set -# CONFIG_USB_YEALINK is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATI_REMOTE2 is not set -# CONFIG_USB_KEYSPAN_REMOTE is not set -# CONFIG_USB_APPLETOUCH is not set - -# # USB Imaging devices # CONFIG_USB_MDC800=m CONFIG_USB_MICROTEK=m - -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set - -# -# Video4Linux support is needed for USB Multimedia device support -# - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set # CONFIG_USB_MON is not set # @@ -1034,16 +1020,22 @@ CONFIG_USB_MICROTEK=m # # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set # CONFIG_USB_AUERSWALD is not set # CONFIG_USB_RIO500 is not set CONFIG_USB_LEGOTOWER=m # CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETKIT is not set -# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_PHIDGET is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # @@ -1054,22 +1046,30 @@ CONFIG_USB_LEGOTOWER=m # USB Gadget Support # # CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_INFINIBAND is not set +# CONFIG_RTC_CLASS is not set # -# MMC/SD Card support +# DMA Engine support # -# CONFIG_MMC is not set +# CONFIG_DMA_ENGINE is not set # -# InfiniBand support +# DMA Clients # -# CONFIG_INFINIBAND is not set # -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# DMA Devices # # +# Userspace I/O +# +# CONFIG_UIO is not set + +# # File systems # CONFIG_EXT2_FS=y @@ -1077,21 +1077,23 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_XFS_FS=m -CONFIG_XFS_EXPORT=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -1121,11 +1123,12 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -1164,6 +1167,7 @@ CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y +# CONFIG_SUNRPC_BIND34 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set @@ -1171,7 +1175,6 @@ CONFIG_SUNRPC=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set # # Partition Types @@ -1224,6 +1227,11 @@ CONFIG_NLS_ISO8859_15=m CONFIG_NLS_UTF8=m # +# Distributed Lock Manager +# +# CONFIG_DLM is not set + +# # Profiling support # CONFIG_PROFILING=y @@ -1233,21 +1241,32 @@ CONFIG_OPROFILE=m # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y -CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_FAULT_INJECTION is not set CONFIG_DEBUG_RODATA=y # @@ -1255,12 +1274,12 @@ CONFIG_DEBUG_RODATA=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set - -# -# Cryptographic options -# CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_MANAGER=m # CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set CONFIG_CRYPTO_NULL=m # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=m @@ -1269,7 +1288,15 @@ CONFIG_CRYPTO_MD5=m # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_ECB is not set +CONFIG_CRYPTO_CBC=m +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_FCRYPT is not set CONFIG_CRYPTO_BLOWFISH=m # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set @@ -1280,21 +1307,28 @@ CONFIG_CRYPTO_BLOWFISH=m # CONFIG_CRYPTO_ARC4 is not set # CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set CONFIG_CRYPTO_DEFLATE=m # CONFIG_CRYPTO_MICHAEL_MIC is not set CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_CAMELLIA is not set CONFIG_CRYPTO_TEST=m - -# -# Hardware crypto devices -# +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_HW is not set # # Library routines # +CONFIG_BITREVERSE=y CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=m CONFIG_ZLIB_DEFLATE=m +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/parisc/defconfig b/arch/parisc/defconfig index b38b58eb9dc..448a757b06c 100644 --- a/arch/parisc/defconfig +++ b/arch/parisc/defconfig @@ -1,39 +1,51 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16-pa10 -# Sun Apr 2 15:26:38 2006 +# Linux kernel version: 2.6.23 +# Fri Oct 12 20:54:57 2007 # CONFIG_PARISC=y CONFIG_MMU=y CONFIG_STACK_GROWSUP=y CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_IRQ_PER_CPU=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set +# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -43,31 +55,29 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set - -# -# Loadable module support -# CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y - -# -# Block layer -# +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set # # IO Schedulers @@ -101,6 +111,7 @@ CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set # CONFIG_HZ_100 is not set CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 CONFIG_SELECT_MEMORY_MODEL=y @@ -111,6 +122,9 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y # CONFIG_HPUX is not set # @@ -125,7 +139,7 @@ CONFIG_EISA=y CONFIG_EISA_NAMES=y # CONFIG_ISA is not set CONFIG_PCI=y -CONFIG_PCI_LEGACY_PROC=y +# CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCI_DEBUG is not set CONFIG_GSC_DINO=y CONFIG_PCI_LBA=y @@ -154,10 +168,6 @@ CONFIG_YENTA_TOSHIBA=y CONFIG_PD6729=y CONFIG_I82092=y CONFIG_PCCARD_NONSTATIC=y - -# -# PCI Hotplug Support -# # CONFIG_HOTPLUG_PCI is not set # @@ -166,6 +176,7 @@ CONFIG_PCCARD_NONSTATIC=y CONFIG_SUPERIO=y CONFIG_CHASSIS_LCD_LED=y CONFIG_PDC_CHASSIS=y +CONFIG_PDC_CHASSIS_WARN=y CONFIG_PDC_STABLE=y # @@ -182,13 +193,15 @@ CONFIG_NET=y # # Networking options # -# CONFIG_NETDEBUG is not set CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y CONFIG_XFRM_USER=m +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set CONFIG_NET_KEY=m +# CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -205,33 +218,39 @@ CONFIG_IP_PNP_BOOTP=y CONFIG_INET_AH=m CONFIG_INET_ESP=m # CONFIG_INET_IPCOMP is not set -CONFIG_INET_TUNNEL=m +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=m CONFIG_INET_TCP_DIAG=m # CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set CONFIG_INET6_AH=y CONFIG_INET6_ESP=y CONFIG_INET6_IPCOMP=y +# CONFIG_IPV6_MIP6 is not set +CONFIG_INET6_XFRM_TUNNEL=y CONFIG_INET6_TUNNEL=y +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y # CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# # CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# # CONFIG_IP_SCTP is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set @@ -243,7 +262,6 @@ CONFIG_LLC2=m # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -259,7 +277,17 @@ CONFIG_LLC2=m # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -268,41 +296,26 @@ CONFIG_LLC2=m # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_STANDALONE is not set # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set - -# -# Connector - unified userspace <-> kernelspace linker -# +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# # CONFIG_MTD is not set - -# -# Parallel port support -# CONFIG_PARPORT=y CONFIG_PARPORT_PC=m # CONFIG_PARPORT_SERIAL is not set # CONFIG_PARPORT_PC_FIFO is not set # CONFIG_PARPORT_PC_SUPERIO is not set CONFIG_PARPORT_PC_PCMCIA=m -CONFIG_PARPORT_NOT_PC=y CONFIG_PARPORT_GSC=y +# CONFIG_PARPORT_AX88796 is not set CONFIG_PARPORT_1284=y - -# -# Plug and Play support -# - -# -# Block devices -# +CONFIG_PARPORT_NOT_PC=y +CONFIG_BLK_DEV=y # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set @@ -317,13 +330,14 @@ CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=6144 -CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set - -# -# ATA/ATAPI/MFM/RLL support -# +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set CONFIG_IDE=y CONFIG_BLK_DEV_IDE=y @@ -334,24 +348,32 @@ CONFIG_BLK_DEV_IDE=y CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDEDISK_MULTI_MODE=y CONFIG_BLK_DEV_IDECS=y +# CONFIG_BLK_DEV_DELKIN is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set CONFIG_BLK_DEV_IDESCSI=y # CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_PROC_FS=y # # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_PLATFORM is not set + +# +# PCI IDE chipsets support +# CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_IDEPCI_PCIBUS_ORDER=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set -# CONFIG_IDEDMA_PCI_AUTO is not set +CONFIG_IDEDMA_ONLYDISK=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set @@ -362,8 +384,10 @@ CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_CS5530 is not set # CONFIG_BLK_DEV_HPT34X is not set # CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_JMICRON is not set # CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT8213 is not set # CONFIG_BLK_DEV_IT821X is not set CONFIG_BLK_DEV_NS87415=y # CONFIG_BLK_DEV_PDC202XX_OLD is not set @@ -373,10 +397,10 @@ CONFIG_BLK_DEV_NS87415=y # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_TC86C001 is not set # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set -# CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set # @@ -384,6 +408,9 @@ CONFIG_BLK_DEV_IDEDMA=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y # @@ -403,18 +430,17 @@ CONFIG_CHR_DEV_SG=y # CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m # -# SCSI Transport Attributes +# SCSI Transports # CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_ATTRS is not set - -# -# SCSI low-level drivers -# +# CONFIG_SCSI_SAS_LIBSAS is not set +CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set @@ -424,11 +450,13 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set # CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ARCMSR is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set -# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -438,55 +466,45 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_IMM is not set CONFIG_SCSI_LASI700=y CONFIG_53C700_LE_ON_BE=y +# CONFIG_SCSI_STEX is not set CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 CONFIG_SCSI_SYM53C8XX_MMIO=y -# CONFIG_SCSI_IPR is not set CONFIG_SCSI_ZALON=y CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 CONFIG_SCSI_NCR53C8XX_SYNC=20 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set - -# -# PCMCIA SCSI adapter support -# -# CONFIG_PCMCIA_AHA152X is not set -# CONFIG_PCMCIA_FDOMAIN is not set -# CONFIG_PCMCIA_NINJA_SCSI is not set -# CONFIG_PCMCIA_QLOGIC is not set -# CONFIG_PCMCIA_SYM53C500 is not set - -# -# Multi-device support (RAID and LVM) -# +# CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_ATA is not set CONFIG_MD=y CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=y CONFIG_MD_RAID0=y CONFIG_MD_RAID1=y CONFIG_MD_RAID10=y -CONFIG_MD_RAID5=y -CONFIG_MD_RAID6=y +# CONFIG_MD_RAID456 is not set # CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set # CONFIG_DM_CRYPT is not set # CONFIG_DM_SNAPSHOT is not set # CONFIG_DM_MIRROR is not set # CONFIG_DM_ZERO is not set # CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set # # Fusion MPT device support @@ -499,35 +517,20 @@ CONFIG_BLK_DEV_DM=y # # IEEE 1394 (FireWire) support # +# CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set - -# -# I2O device support -# # CONFIG_I2O is not set - -# -# Network device support -# CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set CONFIG_DUMMY=m CONFIG_BONDING=m +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=m - -# -# ARCnet devices -# +# CONFIG_VETH is not set +# CONFIG_IP1000 is not set # CONFIG_ARCNET is not set - -# -# PHY device support -# # CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y CONFIG_MII=m CONFIG_LASI_82596=y @@ -536,10 +539,6 @@ CONFIG_LASI_82596=y # CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_SMC is not set - -# -# Tulip family network device support -# CONFIG_NET_TULIP=y # CONFIG_DE2104X is not set CONFIG_TULIP=y @@ -554,6 +553,10 @@ CONFIG_TULIP=y # CONFIG_PCMCIA_XIRTULIP is not set # CONFIG_DEPCA is not set # CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set @@ -561,7 +564,6 @@ CONFIG_NET_PCI=y # CONFIG_AC3200 is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set # CONFIG_E100 is not set # CONFIG_LNE390 is not set @@ -577,15 +579,14 @@ CONFIG_NET_PCI=y # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set +# CONFIG_SC92031 is not set # CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# +CONFIG_NETDEV_1000=y CONFIG_ACENIC=y # CONFIG_ACENIC_OMIT_TIGON_I is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set +# CONFIG_E1000E is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -597,64 +598,36 @@ CONFIG_ACENIC=y # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y # CONFIG_BNX2 is not set - -# -# Ethernet (10000 Mbit) -# +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set - -# -# Token Ring devices -# +# CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_NIU is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set # CONFIG_TR is not set # -# Wireless LAN (non-hamradio) -# -CONFIG_NET_RADIO=y - -# -# Obsolete Wireless cards support (pre-802.11) -# -# CONFIG_STRIP is not set -# CONFIG_PCMCIA_WAVELAN is not set -# CONFIG_PCMCIA_NETWAVE is not set - -# -# Wireless 802.11 Frequency Hopping cards support -# -# CONFIG_PCMCIA_RAYCS is not set - -# -# Wireless 802.11b ISA/PCI cards support -# -CONFIG_HERMES=y -# CONFIG_PLX_HERMES is not set -# CONFIG_TMD_HERMES is not set -# CONFIG_NORTEL_HERMES is not set -# CONFIG_PCI_HERMES is not set -# CONFIG_ATMEL is not set - -# -# Wireless 802.11b Pcmcia/Cardbus cards support +# Wireless LAN # -CONFIG_PCMCIA_HERMES=y -CONFIG_PCMCIA_SPECTRUM=y -# CONFIG_AIRO_CS is not set -# CONFIG_PCMCIA_WL3501 is not set +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set # -# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support -# -# CONFIG_PRISM54 is not set -# CONFIG_HOSTAP is not set -CONFIG_NET_WIRELESS=y - -# -# PCMCIA network device support +# USB Network Adapters # +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set CONFIG_NET_PCMCIA=y # CONFIG_PCMCIA_3C589 is not set # CONFIG_PCMCIA_3C574 is not set @@ -664,10 +637,6 @@ CONFIG_NET_PCMCIA=y # CONFIG_PCMCIA_SMC91C92 is not set # CONFIG_PCMCIA_XIRC2PS is not set # CONFIG_PCMCIA_AXNET is not set - -# -# Wan interfaces -# # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -681,27 +650,23 @@ CONFIG_PPP_DEFLATE=m CONFIG_PPP_BSDCOMP=m # CONFIG_PPP_MPPE is not set CONFIG_PPPOE=m +# CONFIG_PPPOL2TP is not set # CONFIG_SLIP is not set +CONFIG_SLHC=m # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# # CONFIG_ISDN is not set - -# -# Telephony Support -# # CONFIG_PHONE is not set # # Input device support # CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -726,14 +691,23 @@ CONFIG_KEYBOARD_ATKBD_HP_KEYCODES=y # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_HIL_OLD is not set CONFIG_KEYBOARD_HIL=y CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set CONFIG_MOUSE_SERIAL=y +# CONFIG_MOUSE_APPLETOUCH is not set # CONFIG_MOUSE_VSXXXAA is not set CONFIG_MOUSE_HIL=y # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -757,6 +731,7 @@ CONFIG_SERIO_LIBPS2=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -764,6 +739,8 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_GSC=y +CONFIG_SERIAL_8250_PCI=y CONFIG_SERIAL_8250_CS=y CONFIG_SERIAL_8250_NR_UARTS=17 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 @@ -788,25 +765,14 @@ CONFIG_PRINTER=m # CONFIG_LP_CONSOLE is not set CONFIG_PPDEV=m # CONFIG_TIPAR is not set - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# # CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set CONFIG_GEN_RTC=y CONFIG_GEN_RTC_X=y -# CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# +# CONFIG_AGP is not set # CONFIG_DRM is not set # @@ -816,16 +782,8 @@ CONFIG_GEN_RTC_X=y # CONFIG_CARDMAN_4000 is not set # CONFIG_CARDMAN_4040 is not set # CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set - -# -# I2C support -# +CONFIG_DEVPORT=y # CONFIG_I2C is not set # @@ -833,46 +791,59 @@ CONFIG_GEN_RTC_X=y # # CONFIG_SPI is not set # CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# # CONFIG_W1 is not set - -# -# Hardware Monitoring support -# +# CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set # -# Misc devices +# Sonics Silicon Backplane # +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # -# Multimedia Capabilities Port drivers +# Multifunction device drivers # +# CONFIG_MFD_SM501 is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DAB is not set # -# Digital Video Broadcasting Devices +# Graphics support # -# CONFIG_DVB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # -# Graphics support +# Display device support # +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_SYS_FOPS is not set +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y CONFIG_FB_TILEBLITTING=y + +# +# Frame buffer hardware drivers +# # CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set @@ -883,17 +854,20 @@ CONFIG_FB_STI=y # CONFIG_FB_NVIDIA is not set # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set # CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set # CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set # CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set # CONFIG_FB_VIRTUAL is not set # @@ -903,6 +877,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=128 CONFIG_DUMMY_CONSOLE_ROWS=48 CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set CONFIG_STI_CONSOLE=y CONFIG_FONTS=y @@ -916,16 +891,11 @@ CONFIG_FONT_8x16=y # CONFIG_FONT_SUN8x16 is not set # CONFIG_FONT_SUN12x22 is not set # CONFIG_FONT_10x18 is not set - -# -# Logo configuration -# CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set # CONFIG_LOGO_LINUX_CLUT224 is not set CONFIG_LOGO_PARISC_CLUT224=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -938,35 +908,36 @@ CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_TIMER=y CONFIG_SND_PCM=y -CONFIG_SND_HWDEP=y CONFIG_SND_SEQUENCER=y # CONFIG_SND_SEQ_DUMMY is not set CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y CONFIG_SND_DYNAMIC_MINORS=y CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set # # Generic devices # -CONFIG_SND_OPL3_LIB=y CONFIG_SND_AC97_CODEC=y -CONFIG_SND_AC97_BUS=y # CONFIG_SND_DUMMY is not set # CONFIG_SND_VIRMIDI is not set # CONFIG_SND_MTPAV is not set +# CONFIG_SND_MTS64 is not set # CONFIG_SND_SERIAL_U16550 is not set # CONFIG_SND_MPU401 is not set +# CONFIG_SND_PORTMAN2X4 is not set # # PCI devices # CONFIG_SND_AD1889=y -CONFIG_SND_AD1889_OPL3=y +# CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ATIIXP is not set # CONFIG_SND_ATIIXP_MODEM is not set @@ -979,6 +950,18 @@ CONFIG_SND_AD1889_OPL3=y # CONFIG_SND_CMIPCI is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1X is not set # CONFIG_SND_ENS1370 is not set @@ -998,6 +981,7 @@ CONFIG_SND_AD1889_OPL3=y # CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set # CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set @@ -1007,15 +991,19 @@ CONFIG_SND_AD1889_OPL3=y # CONFIG_SND_VIA82XX_MODEM is not set # CONFIG_SND_VX222 is not set # CONFIG_SND_YMFPCI is not set +# CONFIG_SND_AC97_POWER_SAVE is not set # # USB devices # # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_CAIAQ is not set # # PCMCIA devices # +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set # # GSC devices @@ -1023,15 +1011,34 @@ CONFIG_SND_AD1889_OPL3=y CONFIG_SND_HARMONY=y # +# System on Chip audio support +# +# CONFIG_SND_SOC is not set + +# +# SoC Audio support for SuperH +# + +# # Open Sound System # # CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=y +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y # -# USB support +# USB Input Devices # +CONFIG_USB_HID=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -1039,7 +1046,7 @@ CONFIG_USB=y # Miscellaneous USB options # CONFIG_USB_DEVICEFS=y -# CONFIG_USB_BANDWIDTH is not set +CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_OTG is not set @@ -1049,15 +1056,16 @@ CONFIG_USB_DEVICEFS=y # CONFIG_USB_EHCI_HCD is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y -# CONFIG_USB_OHCI_BIG_ENDIAN is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set # # USB Device Class drivers # -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set @@ -1072,52 +1080,10 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_LIBUSUAL is not set # -# USB Input Devices -# -CONFIG_USB_HID=y -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -# CONFIG_USB_HIDDEV is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set -# CONFIG_USB_YEALINK is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATI_REMOTE2 is not set -# CONFIG_USB_KEYSPAN_REMOTE is not set -# CONFIG_USB_APPLETOUCH is not set - -# # USB Imaging devices # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set - -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set - -# -# Video4Linux support is needed for USB Multimedia device support -# - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set -# CONFIG_USB_ZD1201 is not set CONFIG_USB_MON=y # @@ -1135,16 +1101,22 @@ CONFIG_USB_MON=y # # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set # CONFIG_USB_AUERSWALD is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set -# CONFIG_USB_PHIDGETKIT is not set -# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_PHIDGET is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # @@ -1155,20 +1127,29 @@ CONFIG_USB_MON=y # USB Gadget Support # # CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_INFINIBAND is not set +# CONFIG_RTC_CLASS is not set # -# MMC/SD Card support +# DMA Engine support # -# CONFIG_MMC is not set +# CONFIG_DMA_ENGINE is not set # -# InfiniBand support +# DMA Clients # -# CONFIG_INFINIBAND is not set # -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# DMA Devices +# +# CONFIG_AUXDISPLAY is not set + +# +# Userspace I/O # +# CONFIG_UIO is not set # # File systems @@ -1178,16 +1159,19 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y @@ -1217,11 +1201,12 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -1229,6 +1214,7 @@ CONFIG_RAMFS=y # # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set # CONFIG_HFS_FS is not set # CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set @@ -1261,6 +1247,7 @@ CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_BIND34 is not set CONFIG_RPCSEC_GSS_KRB5=y CONFIG_RPCSEC_GSS_SPKM3=m CONFIG_SMB_FS=m @@ -1268,12 +1255,13 @@ CONFIG_SMB_NLS_DEFAULT=y CONFIG_SMB_NLS_REMOTE="cp437" CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set # CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set # # Partition Types @@ -1326,6 +1314,11 @@ CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=y # +# Distributed Lock Manager +# +# CONFIG_DLM is not set + +# # Profiling support # CONFIG_PROFILING=y @@ -1335,21 +1328,32 @@ CONFIG_OPROFILE=m # Kernel hacking # # CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y -CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_FAULT_INJECTION is not set # CONFIG_DEBUG_RODATA is not set # @@ -1358,12 +1362,13 @@ CONFIG_FORCED_INLINING=y CONFIG_KEYS=y CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_SECURITY is not set - -# -# Cryptographic options -# CONFIG_CRYPTO=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD5=y @@ -1372,9 +1377,18 @@ CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_TGR192=m +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_ECB is not set +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_COMMON=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m @@ -1383,21 +1397,28 @@ CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_KHAZAD=m CONFIG_CRYPTO_ANUBIS=m +# CONFIG_CRYPTO_SEED is not set CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_CAMELLIA is not set CONFIG_CRYPTO_TEST=m - -# -# Hardware crypto devices -# +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_HW is not set # # Library routines # +CONFIG_BITREVERSE=y CONFIG_CRC_CCITT=m # CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/parisc/hpux/gate.S b/arch/parisc/hpux/gate.S index 0b9d5b1e4b3..38a1c1b8d4e 100644 --- a/arch/parisc/hpux/gate.S +++ b/arch/parisc/hpux/gate.S @@ -20,7 +20,7 @@ .import hpux_call_table .import hpux_syscall_exit,code - .align 4096 + .align PAGE_SIZE ENTRY(hpux_gateway_page) nop #ifdef CONFIG_64BIT @@ -103,5 +103,5 @@ syscall_nosys: ldo -ENOSYS(%r0),%r28 ENDPROC(hpux_gateway_page) - .align 4096 + .align PAGE_SIZE ENTRY(end_hpux_gateway_page) diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c index d3b7917a87c..eaa79bc14d9 100644 --- a/arch/parisc/kernel/asm-offsets.c +++ b/arch/parisc/kernel/asm-offsets.c @@ -290,9 +290,6 @@ int main(void) DEFINE(ASM_PTE_ENTRY_SIZE, PTE_ENTRY_SIZE); DEFINE(ASM_PFN_PTE_SHIFT, PFN_PTE_SHIFT); DEFINE(ASM_PT_INITIAL, PT_INITIAL); - DEFINE(ASM_PAGE_SIZE, PAGE_SIZE); - DEFINE(ASM_PAGE_SIZE_DIV64, PAGE_SIZE/64); - DEFINE(ASM_PAGE_SIZE_DIV128, PAGE_SIZE/128); BLANK(); DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip)); DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space)); diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 42598abf457..111d47284ea 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -98,7 +98,6 @@ * The "get_stack" macros are responsible for determining the * kernel stack value. * - * For Faults: * If sr7 == 0 * Already using a kernel stack, so call the * get_stack_use_r30 macro to push a pt_regs structure @@ -110,26 +109,6 @@ * task pointer pointed to by cr30. Set the stack * pointer to point to the end of the task structure. * - * For Interrupts: - * If sr7 == 0 - * Already using a kernel stack, check to see if r30 - * is already pointing to the per processor interrupt - * stack. If it is, call the get_stack_use_r30 macro - * to push a pt_regs structure on the stack, and store - * registers there. Otherwise, call get_stack_use_cr31 - * to get a pointer to the base of the interrupt stack - * and push a pt_regs structure on that stack. - * else - * Need to set up a kernel stack, so call the - * get_stack_use_cr30 macro to set up a pointer - * to the pt_regs structure contained within the - * task pointer pointed to by cr30. Set the stack - * pointer to point to the end of the task structure. - * N.B: We don't use the interrupt stack for the - * first interrupt from userland, because signals/ - * resched's are processed when returning to userland, - * and we can sleep in those cases. - * * Note that we use shadowed registers for temps until * we can save %r26 and %r29. %r26 is used to preserve * %r8 (a shadowed register) which temporarily contained @@ -652,7 +631,7 @@ .text - .align 4096 + .align PAGE_SIZE ENTRY(fault_vector_20) /* First vector is invalid (0) */ @@ -904,7 +883,7 @@ ENDPROC(_switch_to) * */ - .align 4096 + .align PAGE_SIZE ENTRY(syscall_exit_rfi) mfctl %cr30,%r16 @@ -1086,23 +1065,13 @@ intr_do_preempt: intr_extint: CMPIB=,n 0,%r16,1f + get_stack_use_cr30 - b,n 3f + b,n 2f 1: -#if 0 /* Interrupt Stack support not working yet! */ - mfctl %cr31,%r1 - copy %r30,%r17 - /* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/ - DEPI 0,31,15,%r17 - CMPB=,n %r1,%r17,2f - get_stack_use_cr31 - b,n 3f -#endif -2: get_stack_use_r30 - -3: +2: save_specials %r29 virt_map save_general %r29 diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S index 9676c486bb6..a7b8859488b 100644 --- a/arch/parisc/kernel/head.S +++ b/arch/parisc/kernel/head.S @@ -95,7 +95,7 @@ $bss_loop: 1: stw %r3,0(%r4) - ldo (ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3 + ldo (PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3 addib,> -1,%r1,1b #if PT_NLEVELS == 3 ldo ASM_PMD_ENTRY_SIZE(%r4),%r4 @@ -128,10 +128,6 @@ $pgt_fill_loop: /* And the stack pointer too */ ldo THREAD_SZ_ALGN(%r6),%sp - /* And the interrupt stack */ - load32 interrupt_stack,%r6 - mtctl %r6,%cr31 - #ifdef CONFIG_SMP /* Set the smp rendevous address into page zero. ** It would be safer to do this in init_smp_config() but diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S index 43b41df0b54..2cbf13b3ef1 100644 --- a/arch/parisc/kernel/hpmc.S +++ b/arch/parisc/kernel/hpmc.S @@ -55,13 +55,13 @@ * IODC requires 7K byte stack. That leaves 1K byte for os_hpmc. */ - .align 4096 + .align PAGE_SIZE hpmc_stack: .block 16384 #define HPMC_IODC_BUF_SIZE 0x8000 - .align 4096 + .align PAGE_SIZE hpmc_iodc_buf: .block HPMC_IODC_BUF_SIZE diff --git a/arch/parisc/kernel/init_task.c b/arch/parisc/kernel/init_task.c index 446f98d3fd7..26198a074d6 100644 --- a/arch/parisc/kernel/init_task.c +++ b/arch/parisc/kernel/init_task.c @@ -49,7 +49,6 @@ EXPORT_SYMBOL(init_mm); * way process stacks are handled. This is done by having a special * "init_task" linker map entry.. */ -unsigned char interrupt_stack[ISTACK_SIZE] __attribute__ ((section("init_istack"), aligned(4096))); union thread_union init_thread_union __attribute__((aligned(128))) __attribute__((__section__(".data.init_task"))) = { INIT_THREAD_INFO(init_task) }; diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 90b24087852..5901092e019 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S @@ -289,7 +289,7 @@ ENTRY(copy_user_page_asm) */ ldd 0(%r25), %r19 - ldi ASM_PAGE_SIZE_DIV128, %r1 + ldi (PAGE_SIZE / 128), %r1 ldw 64(%r25), %r0 /* prefetch 1 cacheline ahead */ ldw 128(%r25), %r0 /* prefetch 2 */ @@ -355,7 +355,7 @@ ENTRY(copy_user_page_asm) * use ldd/std on a 32 bit kernel. */ ldw 0(%r25), %r19 - ldi ASM_PAGE_SIZE_DIV64, %r1 + ldi (PAGE_SIZE / 64), %r1 1: ldw 4(%r25), %r20 @@ -553,7 +553,7 @@ ENTRY(__clear_user_page_asm) pdtlb 0(%r28) #ifdef CONFIG_64BIT - ldi ASM_PAGE_SIZE_DIV128, %r1 + ldi (PAGE_SIZE / 128), %r1 /* PREFETCH (Write) has not (yet) been proven to help here */ /* #define PREFETCHW_OP ldd 256(%0), %r0 */ @@ -578,7 +578,7 @@ ENTRY(__clear_user_page_asm) ldo 128(%r28), %r28 #else /* ! CONFIG_64BIT */ - ldi ASM_PAGE_SIZE_DIV64, %r1 + ldi (PAGE_SIZE / 64), %r1 1: stw %r0, 0(%r28) diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index 7aca704e96f..671ee5b9950 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c @@ -122,31 +122,9 @@ EXPORT_SYMBOL($$divI_12); EXPORT_SYMBOL($$divI_14); EXPORT_SYMBOL($$divI_15); -extern void __ashrdi3(void); -extern void __ashldi3(void); -extern void __lshrdi3(void); -extern void __muldi3(void); - -EXPORT_SYMBOL(__ashrdi3); -EXPORT_SYMBOL(__ashldi3); -EXPORT_SYMBOL(__lshrdi3); -EXPORT_SYMBOL(__muldi3); - asmlinkage void * __canonicalize_funcptr_for_compare(void *); EXPORT_SYMBOL(__canonicalize_funcptr_for_compare); -#ifdef CONFIG_64BIT -extern void __divdi3(void); -extern void __udivdi3(void); -extern void __umoddi3(void); -extern void __moddi3(void); - -EXPORT_SYMBOL(__divdi3); -EXPORT_SYMBOL(__udivdi3); -EXPORT_SYMBOL(__umoddi3); -EXPORT_SYMBOL(__moddi3); -#endif - #ifndef CONFIG_64BIT extern void $$dyncall(void); EXPORT_SYMBOL($$dyncall); diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index 23c1388df1f..41f8e321e34 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -569,11 +569,10 @@ static void *fail_alloc_consistent(struct device *dev, size_t size, static void *pa11_dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { - void *addr = NULL; + void *addr; - /* rely on kmalloc to be cacheline aligned */ - addr = kmalloc(size, flag); - if(addr) + addr = (void *)__get_free_pages(flag, get_order(size)); + if (addr) *dma_handle = (dma_addr_t)virt_to_phys(addr); return addr; @@ -582,7 +581,7 @@ static void *pa11_dma_alloc_noncoherent(struct device *dev, size_t size, static void pa11_dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, dma_addr_t iova) { - kfree(vaddr); + free_pages((unsigned long)vaddr, get_order(size)); return; } diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 563df0072de..507d0ac99f6 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -194,37 +194,13 @@ void __init pcibios_init_bus(struct pci_bus *bus) pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl); } - -/* KLUGE: Link the child and parent resources - generic PCI didn't */ -static void -pcibios_link_hba_resources( struct resource *hba_res, struct resource *r) -{ - if (!r->parent) { - printk(KERN_EMERG "PCI: resource not parented! [%p-%p]\n", - (void*) r->start, (void*) r->end); - r->parent = hba_res; - - /* reverse link is harder *sigh* */ - if (r->parent->child) { - if (r->parent->sibling) { - struct resource *next = r->parent->sibling; - while (next->sibling) - next = next->sibling; - next->sibling = r; - } else { - r->parent->sibling = r; - } - } else - r->parent->child = r; - } -} - /* called by drivers/pci/setup-bus.c:pci_setup_bridge(). */ void __devinit pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res) { - struct pci_bus *bus = dev->bus; - struct pci_hba_data *hba = HBA_DATA(bus->bridge->platform_data); +#ifdef CONFIG_64BIT + struct pci_hba_data *hba = HBA_DATA(dev->bus->bridge->platform_data); +#endif if (res->flags & IORESOURCE_IO) { /* @@ -243,23 +219,15 @@ void __devinit pcibios_resource_to_bus(struct pci_dev *dev, } DBG_RES("pcibios_resource_to_bus(%02x %s [%lx,%lx])\n", - bus->number, res->flags & IORESOURCE_IO ? "IO" : "MEM", + dev->bus->number, res->flags & IORESOURCE_IO ? "IO" : "MEM", region->start, region->end); - - /* KLUGE ALERT - ** if this resource isn't linked to a "parent", then it seems - ** to be a child of the HBA - lets link it in. - */ - pcibios_link_hba_resources(&hba->io_space, bus->resource[0]); - pcibios_link_hba_resources(&hba->lmmio_space, bus->resource[1]); } void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, struct pci_bus_region *region) { #ifdef CONFIG_64BIT - struct pci_bus *bus = dev->bus; - struct pci_hba_data *hba = HBA_DATA(bus->bridge->platform_data); + struct pci_hba_data *hba = HBA_DATA(dev->bus->bridge->platform_data); #endif if (res->flags & IORESOURCE_MEM) { diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index 549f5484342..370086fb833 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -82,7 +82,12 @@ static int __cpuinit processor_probe(struct parisc_device *dev) unsigned long cpuid; struct cpuinfo_parisc *p; -#ifndef CONFIG_SMP +#ifdef CONFIG_SMP + if (num_online_cpus() >= NR_CPUS) { + printk(KERN_INFO "num_online_cpus() >= NR_CPUS\n"); + return 1; + } +#else if (boot_cpu_data.cpu_count > 0) { printk(KERN_INFO "CONFIG_SMP=n ignoring additional CPUs\n"); return 1; diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index d7bc7bb42c9..85fc7754ec2 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -432,22 +432,10 @@ smp_cpu_init(int cpunum) void __init smp_callin(void) { int slave_id = cpu_now_booting; -#if 0 - void *istack; -#endif smp_cpu_init(slave_id); preempt_disable(); -#if 0 /* NOT WORKING YET - see entry.S */ - istack = (void *)__get_free_pages(GFP_KERNEL,ISTACK_ORDER); - if (istack == NULL) { - printk(KERN_CRIT "Failed to allocate interrupt stack for cpu %d\n",slave_id); - BUG(); - } - mtctl(istack,31); -#endif - flush_cache_all_local(); /* start with known state */ flush_tlb_all_local(NULL); diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index 2989c6682bf..50bbf33ee00 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -473,3 +473,10 @@ long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf, return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low, buf, len); } + +asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo, + u32 lenhi, u32 lenlo) +{ + return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo, + ((loff_t)lenhi << 32) | lenlo); +} diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 56f6231cb86..69b6eebc466 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -10,6 +10,7 @@ #include <asm/asm-offsets.h> #include <asm/unistd.h> #include <asm/errno.h> +#include <asm/page.h> #include <asm/psw.h> #include <asm/thread_info.h> #include <asm/assembly.h> @@ -38,7 +39,7 @@ * pointers. */ - .align ASM_PAGE_SIZE + .align PAGE_SIZE ENTRY(linux_gateway_page) /* ADDRESS 0x00 to 0xb0 = 176 bytes / 4 bytes per insn = 44 insns */ @@ -597,7 +598,7 @@ cas_action: /* Make sure nothing else is placed on this page */ - .align ASM_PAGE_SIZE + .align PAGE_SIZE END(linux_gateway_page) ENTRY(end_linux_gateway_page) @@ -608,7 +609,7 @@ ENTRY(end_linux_gateway_page) .section .rodata,"a" - .align ASM_PAGE_SIZE + .align PAGE_SIZE /* Light-weight-syscall table */ /* Start of lws table. */ ENTRY(lws_table) @@ -617,13 +618,13 @@ ENTRY(lws_table) END(lws_table) /* End of lws table */ - .align ASM_PAGE_SIZE + .align PAGE_SIZE ENTRY(sys_call_table) #include "syscall_table.S" END(sys_call_table) #ifdef CONFIG_64BIT - .align ASM_PAGE_SIZE + .align PAGE_SIZE ENTRY(sys_call_table64) #define SYSCALL_TABLE_64BIT #include "syscall_table.S" @@ -636,7 +637,7 @@ END(sys_call_table64) will use this set of locks */ .section .data - .align 4096 + .align PAGE_SIZE ENTRY(lws_lock_start) /* lws locks */ .align 16 diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 2540786a970..117438e9eb2 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -403,6 +403,7 @@ ENTRY_COMP(signalfd) ENTRY_COMP(timerfd) ENTRY_SAME(eventfd) + ENTRY_COMP(fallocate) /* 305 */ /* Nothing yet */ diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index 8b3062a5c81..24be86bba94 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c @@ -189,16 +189,14 @@ static struct clocksource clocksource_cr16 = { #ifdef CONFIG_SMP int update_cr16_clocksource(void) { - int change = 0; - /* since the cr16 cycle counters are not synchronized across CPUs, we'll check if we should switch to a safe clocksource: */ if (clocksource_cr16.rating != 0 && num_online_cpus() > 1) { clocksource_change_rating(&clocksource_cr16, 0); - change = 1; + return 1; } - return change; + return 0; } #else int update_cr16_clocksource(void) diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c index cf780cb3b91..701b2d2d888 100644 --- a/arch/parisc/kernel/unwind.c +++ b/arch/parisc/kernel/unwind.c @@ -209,8 +209,8 @@ static int unwind_init(void) static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size) { - void handle_interruption(int, struct pt_regs *); - static unsigned long *hi = (unsigned long)&handle_interruption; + extern void handle_interruption(int, struct pt_regs *); + static unsigned long *hi = (unsigned long *)&handle_interruption; if (pc == get_func_addr(hi)) { struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN); diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index ee7a16eb6fd..40d0ff9b81a 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S @@ -46,168 +46,211 @@ jiffies = jiffies_64; #endif SECTIONS { + . = KERNEL_BINARY_TEXT_START; - . = KERNEL_BINARY_TEXT_START; - - _text = .; /* Text and read-only data */ - .text ALIGN(16) : { - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - *(.text.do_softirq) - *(.text.sys_exit) - *(.text.do_sigaltstack) - *(.text.do_fork) - *(.text.*) - *(.fixup) - *(.lock.text) /* out-of-line lock text */ - *(.gnu.warning) + _text = .; /* Text and read-only data */ + .text ALIGN(16) : { + TEXT_TEXT + SCHED_TEXT + LOCK_TEXT + *(.text.do_softirq) + *(.text.sys_exit) + *(.text.do_sigaltstack) + *(.text.do_fork) + *(.text.*) + *(.fixup) + *(.lock.text) /* out-of-line lock text */ + *(.gnu.warning) } = 0 + /* End of text section */ + _etext = .; - _etext = .; /* End of text section */ + RODATA + BUG_TABLE - RODATA - - BUG_TABLE - - /* writeable */ - . = ALIGN(ASM_PAGE_SIZE); /* Make sure this is page aligned so - that we can properly leave these - as writable */ - data_start = .; - - . = ALIGN(16); /* Exception table */ - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; + /* writeable */ + /* Make sure this is page aligned so + * that we can properly leave these + * as writable + */ + . = ALIGN(PAGE_SIZE); + data_start = .; + . = ALIGN(16); + /* Exception table */ + __ex_table : { + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + } - NOTES + NOTES - __start___unwind = .; /* unwind info */ - .PARISC.unwind : { *(.PARISC.unwind) } - __stop___unwind = .; + /* unwind info */ + .PARISC.unwind : { + __start___unwind = .; + *(.PARISC.unwind) + __stop___unwind = .; + } - /* rarely changed data like cpu maps */ - . = ALIGN(16); - .data.read_mostly : { *(.data.read_mostly) } + /* rarely changed data like cpu maps */ + . = ALIGN(16); + .data.read_mostly : { + *(.data.read_mostly) + } - . = ALIGN(L1_CACHE_BYTES); - .data : { /* Data */ - DATA_DATA - CONSTRUCTORS + . = ALIGN(L1_CACHE_BYTES); + /* Data */ + .data : { + DATA_DATA + CONSTRUCTORS } - . = ALIGN(L1_CACHE_BYTES); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } + . = ALIGN(L1_CACHE_BYTES); + .data.cacheline_aligned : { + *(.data.cacheline_aligned) + } - /* PA-RISC locks requires 16-byte alignment */ - . = ALIGN(16); - .data.lock_aligned : { *(.data.lock_aligned) } + /* PA-RISC locks requires 16-byte alignment */ + . = ALIGN(16); + .data.lock_aligned : { + *(.data.lock_aligned) + } - . = ALIGN(ASM_PAGE_SIZE); - /* nosave data is really only used for software suspend...it's here - * just in case we ever implement it */ - __nosave_begin = .; - .data_nosave : { *(.data.nosave) } - . = ALIGN(ASM_PAGE_SIZE); - __nosave_end = .; + /* nosave data is really only used for software suspend...it's here + * just in case we ever implement it + */ + . = ALIGN(PAGE_SIZE); + __nosave_begin = .; + .data_nosave : { + *(.data.nosave) + } + . = ALIGN(PAGE_SIZE); + __nosave_end = .; - _edata = .; /* End of data section */ + /* End of data section */ + _edata = .; - __bss_start = .; /* BSS */ - /* page table entries need to be PAGE_SIZE aligned */ - . = ALIGN(ASM_PAGE_SIZE); - .data.vmpages : { - *(.data.vm0.pmd) - *(.data.vm0.pgd) - *(.data.vm0.pte) + /* BSS */ + __bss_start = .; + /* page table entries need to be PAGE_SIZE aligned */ + . = ALIGN(PAGE_SIZE); + .data.vmpages : { + *(.data.vm0.pmd) + *(.data.vm0.pgd) + *(.data.vm0.pte) } - .bss : { *(.bss) *(COMMON) } - __bss_stop = .; - + .bss : { + *(.bss) + *(COMMON) + } + __bss_stop = .; - /* assembler code expects init_task to be 16k aligned */ - . = ALIGN(16384); /* init_task */ - .data.init_task : { *(.data.init_task) } - /* The interrupt stack is currently partially coded, but not yet - * implemented */ - . = ALIGN(16384); - init_istack : { *(init_istack) } + /* assembler code expects init_task to be 16k aligned */ + . = ALIGN(16384); + /* init_task */ + .data.init_task : { + *(.data.init_task) + } #ifdef CONFIG_64BIT - . = ALIGN(16); /* Linkage tables */ - .opd : { *(.opd) } PROVIDE (__gp = .); - .plt : { *(.plt) } - .dlt : { *(.dlt) } + . = ALIGN(16); + /* Linkage tables */ + .opd : { + *(.opd) + } PROVIDE (__gp = .); + .plt : { + *(.plt) + } + .dlt : { + *(.dlt) + } #endif - /* reserve space for interrupt stack by aligning __init* to 16k */ - . = ALIGN(16384); - __init_begin = .; - .init.text : { - _sinittext = .; - *(.init.text) - _einittext = .; - } - .init.data : { *(.init.data) } - . = ALIGN(16); - __setup_start = .; - .init.setup : { *(.init.setup) } - __setup_end = .; - __initcall_start = .; - .initcall.init : { - INITCALLS - } - __initcall_end = .; - __con_initcall_start = .; - .con_initcall.init : { *(.con_initcall.init) } - __con_initcall_end = .; - SECURITY_INIT - /* alternate instruction replacement. This is a mechanism x86 uses - * to detect the CPU type and replace generic instruction sequences - * with CPU specific ones. We don't currently do this in PA, but - * it seems like a good idea... */ - . = ALIGN(4); - __alt_instructions = .; - .altinstructions : { *(.altinstructions) } - __alt_instructions_end = .; - .altinstr_replacement : { *(.altinstr_replacement) } - /* .exit.text is discard at runtime, not link time, to deal with references - from .altinstructions and .eh_frame */ - .exit.text : { *(.exit.text) } - .exit.data : { *(.exit.data) } + /* reserve space for interrupt stack by aligning __init* to 16k */ + . = ALIGN(16384); + __init_begin = .; + .init.text : { + _sinittext = .; + *(.init.text) + _einittext = .; + } + .init.data : { + *(.init.data) + } + . = ALIGN(16); + .init.setup : { + __setup_start = .; + *(.init.setup) + __setup_end = .; + } + .initcall.init : { + __initcall_start = .; + INITCALLS + __initcall_end = .; + } + .con_initcall.init : { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + } + SECURITY_INIT + + /* alternate instruction replacement. This is a mechanism x86 uses + * to detect the CPU type and replace generic instruction sequences + * with CPU specific ones. We don't currently do this in PA, but + * it seems like a good idea... + */ + . = ALIGN(4); + .altinstructions : { + __alt_instructions = .; + *(.altinstructions) + __alt_instructions_end = .; + } + .altinstr_replacement : { + *(.altinstr_replacement) + } + + /* .exit.text is discard at runtime, not link time, to deal with references + * from .altinstructions and .eh_frame + */ + .exit.text : { + *(.exit.text) + } + .exit.data : { + *(.exit.data) + } #ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(ASM_PAGE_SIZE); - __initramfs_start = .; - .init.ramfs : { *(.init.ramfs) } - __initramfs_end = .; + . = ALIGN(PAGE_SIZE); + .init.ramfs : { + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; + } #endif - PERCPU(ASM_PAGE_SIZE) + PERCPU(PAGE_SIZE) + . = ALIGN(PAGE_SIZE); + __init_end = .; + /* freed after init ends here */ + _end = . ; - . = ALIGN(ASM_PAGE_SIZE); - __init_end = .; - /* freed after init ends here */ - - _end = . ; - - /* Sections to be discarded */ - /DISCARD/ : { - *(.exitcall.exit) + /* Sections to be discarded */ + /DISCARD/ : { + *(.exitcall.exit) #ifdef CONFIG_64BIT - /* temporary hack until binutils is fixed to not emit these - for static binaries */ - *(.interp) - *(.dynsym) - *(.dynstr) - *(.dynamic) - *(.hash) - *(.gnu.hash) + /* temporary hack until binutils is fixed to not emit these + * for static binaries + */ + *(.interp) + *(.dynsym) + *(.dynstr) + *(.dynamic) + *(.hash) + *(.gnu.hash) #endif } - STABS_DEBUG - .note 0 : { *(.note) } - + STABS_DEBUG + .note 0 : { *(.note) } } diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile index 5f2e6904d14..7ce406c7daf 100644 --- a/arch/parisc/lib/Makefile +++ b/arch/parisc/lib/Makefile @@ -4,4 +4,4 @@ lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o -obj-y := iomap.o +obj-y := libgcc/ milli/ iomap.o diff --git a/arch/parisc/lib/libgcc/Makefile b/arch/parisc/lib/libgcc/Makefile new file mode 100644 index 00000000000..b67a85ad9c8 --- /dev/null +++ b/arch/parisc/lib/libgcc/Makefile @@ -0,0 +1,4 @@ +obj-y := __ashldi3.o __ashrdi3.o __clzsi2.o __divdi3.o __divsi3.o \ + __lshrdi3.o __moddi3.o __modsi3.o __udivdi3.o \ + __udivmoddi4.o __udivmodsi4.o __udivsi3.o \ + __umoddi3.o __umodsi3.o __muldi3.o __umulsidi3.o diff --git a/arch/parisc/lib/libgcc/__ashldi3.c b/arch/parisc/lib/libgcc/__ashldi3.c new file mode 100644 index 00000000000..a14a257abb2 --- /dev/null +++ b/arch/parisc/lib/libgcc/__ashldi3.c @@ -0,0 +1,19 @@ +#include "libgcc.h" + +u64 __ashldi3(u64 v, int cnt) +{ + int c = cnt & 31; + u32 vl = (u32) v; + u32 vh = (u32) (v >> 32); + + if (cnt & 32) { + vh = (vl << c); + vl = 0; + } else { + vh = (vh << c) + (vl >> (32 - c)); + vl = (vl << c); + } + + return ((u64) vh << 32) + vl; +} +EXPORT_SYMBOL(__ashldi3); diff --git a/arch/parisc/lib/libgcc/__ashrdi3.c b/arch/parisc/lib/libgcc/__ashrdi3.c new file mode 100644 index 00000000000..8636a5aa4f7 --- /dev/null +++ b/arch/parisc/lib/libgcc/__ashrdi3.c @@ -0,0 +1,19 @@ +#include "libgcc.h" + +u64 __ashrdi3(u64 v, int cnt) +{ + int c = cnt & 31; + u32 vl = (u32) v; + u32 vh = (u32) (v >> 32); + + if (cnt & 32) { + vl = ((s32) vh >> c); + vh = (s32) vh >> 31; + } else { + vl = (vl >> c) + (vh << (32 - c)); + vh = ((s32) vh >> c); + } + + return ((u64) vh << 32) + vl; +} +EXPORT_SYMBOL(__ashrdi3); diff --git a/arch/parisc/lib/libgcc/__clzsi2.c b/arch/parisc/lib/libgcc/__clzsi2.c new file mode 100644 index 00000000000..a7aa2f55a9c --- /dev/null +++ b/arch/parisc/lib/libgcc/__clzsi2.c @@ -0,0 +1,30 @@ +#include "libgcc.h" + +u32 __clzsi2(u32 v) +{ + int p = 31; + + if (v & 0xffff0000) { + p -= 16; + v >>= 16; + } + if (v & 0xff00) { + p -= 8; + v >>= 8; + } + if (v & 0xf0) { + p -= 4; + v >>= 4; + } + if (v & 0xc) { + p -= 2; + v >>= 2; + } + if (v & 0x2) { + p -= 1; + v >>= 1; + } + + return p; +} +EXPORT_SYMBOL(__clzsi2); diff --git a/arch/parisc/lib/libgcc/__divdi3.c b/arch/parisc/lib/libgcc/__divdi3.c new file mode 100644 index 00000000000..f23c6fe2838 --- /dev/null +++ b/arch/parisc/lib/libgcc/__divdi3.c @@ -0,0 +1,23 @@ +#include "libgcc.h" + +s64 __divdi3(s64 num, s64 den) +{ + int minus = 0; + s64 v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + v = __udivmoddi4(num, den, NULL); + if (minus) + v = -v; + + return v; +} +EXPORT_SYMBOL(__divdi3); diff --git a/arch/parisc/lib/libgcc/__divsi3.c b/arch/parisc/lib/libgcc/__divsi3.c new file mode 100644 index 00000000000..730fb530680 --- /dev/null +++ b/arch/parisc/lib/libgcc/__divsi3.c @@ -0,0 +1,23 @@ +#include "libgcc.h" + +s32 __divsi3(s32 num, s32 den) +{ + int minus = 0; + s32 v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + v = __udivmodsi4(num, den, NULL); + if (minus) + v = -v; + + return v; +} +EXPORT_SYMBOL(__divsi3); diff --git a/arch/parisc/lib/libgcc/__lshrdi3.c b/arch/parisc/lib/libgcc/__lshrdi3.c new file mode 100644 index 00000000000..4a820708ec5 --- /dev/null +++ b/arch/parisc/lib/libgcc/__lshrdi3.c @@ -0,0 +1,19 @@ +#include "libgcc.h" + +u64 __lshrdi3(u64 v, int cnt) +{ + int c = cnt & 31; + u32 vl = (u32) v; + u32 vh = (u32) (v >> 32); + + if (cnt & 32) { + vl = (vh >> c); + vh = 0; + } else { + vl = (vl >> c) + (vh << (32 - c)); + vh = (vh >> c); + } + + return ((u64) vh << 32) + vl; +} +EXPORT_SYMBOL(__lshrdi3); diff --git a/arch/parisc/lib/libgcc/__moddi3.c b/arch/parisc/lib/libgcc/__moddi3.c new file mode 100644 index 00000000000..ed64bbafc98 --- /dev/null +++ b/arch/parisc/lib/libgcc/__moddi3.c @@ -0,0 +1,23 @@ +#include "libgcc.h" + +s64 __moddi3(s64 num, s64 den) +{ + int minus = 0; + s64 v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + (void)__udivmoddi4(num, den, (u64 *) & v); + if (minus) + v = -v; + + return v; +} +EXPORT_SYMBOL(__moddi3); diff --git a/arch/parisc/lib/libgcc/__modsi3.c b/arch/parisc/lib/libgcc/__modsi3.c new file mode 100644 index 00000000000..62f773efaee --- /dev/null +++ b/arch/parisc/lib/libgcc/__modsi3.c @@ -0,0 +1,23 @@ +#include "libgcc.h" + +s32 __modsi3(s32 num, s32 den) +{ + int minus = 0; + s32 v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + (void)__udivmodsi4(num, den, (u32 *) & v); + if (minus) + v = -v; + + return v; +} +EXPORT_SYMBOL(__modsi3); diff --git a/arch/parisc/lib/libgcc/__muldi3.c b/arch/parisc/lib/libgcc/__muldi3.c new file mode 100644 index 00000000000..3308abdd558 --- /dev/null +++ b/arch/parisc/lib/libgcc/__muldi3.c @@ -0,0 +1,22 @@ +#include "libgcc.h" + +union DWunion { + struct { + s32 high; + s32 low; + } s; + s64 ll; +}; + +s64 __muldi3(s64 u, s64 v) +{ + const union DWunion uu = { .ll = u }; + const union DWunion vv = { .ll = v }; + union DWunion w = { .ll = __umulsidi3(uu.s.low, vv.s.low) }; + + w.s.high += ((u32)uu.s.low * (u32)vv.s.high + + (u32)uu.s.high * (u32)vv.s.low); + + return w.ll; +} +EXPORT_SYMBOL(__muldi3); diff --git a/arch/parisc/lib/libgcc/__udivdi3.c b/arch/parisc/lib/libgcc/__udivdi3.c new file mode 100644 index 00000000000..740023d690f --- /dev/null +++ b/arch/parisc/lib/libgcc/__udivdi3.c @@ -0,0 +1,7 @@ +#include "libgcc.h" + +u64 __udivdi3(u64 num, u64 den) +{ + return __udivmoddi4(num, den, NULL); +} +EXPORT_SYMBOL(__udivdi3); diff --git a/arch/parisc/lib/libgcc/__udivmoddi4.c b/arch/parisc/lib/libgcc/__udivmoddi4.c new file mode 100644 index 00000000000..2df0caa5a7d --- /dev/null +++ b/arch/parisc/lib/libgcc/__udivmoddi4.c @@ -0,0 +1,31 @@ +#include "libgcc.h" + +u64 __udivmoddi4(u64 num, u64 den, u64 * rem_p) +{ + u64 quot = 0, qbit = 1; + + if (den == 0) { + BUG(); + } + + /* Left-justify denominator and count shift */ + while ((s64) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} +EXPORT_SYMBOL(__udivmoddi4); diff --git a/arch/parisc/lib/libgcc/__udivmodsi4.c b/arch/parisc/lib/libgcc/__udivmodsi4.c new file mode 100644 index 00000000000..2a2fc28b202 --- /dev/null +++ b/arch/parisc/lib/libgcc/__udivmodsi4.c @@ -0,0 +1,31 @@ +#include "libgcc.h" + +u32 __udivmodsi4(u32 num, u32 den, u32 * rem_p) +{ + u32 quot = 0, qbit = 1; + + if (den == 0) { + BUG(); + } + + /* Left-justify denominator and count shift */ + while ((s32) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} +EXPORT_SYMBOL(__udivmodsi4); diff --git a/arch/parisc/lib/libgcc/__udivsi3.c b/arch/parisc/lib/libgcc/__udivsi3.c new file mode 100644 index 00000000000..756a44164e9 --- /dev/null +++ b/arch/parisc/lib/libgcc/__udivsi3.c @@ -0,0 +1,7 @@ +#include "libgcc.h" + +u32 __udivsi3(u32 num, u32 den) +{ + return __udivmodsi4(num, den, NULL); +} +EXPORT_SYMBOL(__udivsi3); diff --git a/arch/parisc/lib/libgcc/__umoddi3.c b/arch/parisc/lib/libgcc/__umoddi3.c new file mode 100644 index 00000000000..ac744e948bc --- /dev/null +++ b/arch/parisc/lib/libgcc/__umoddi3.c @@ -0,0 +1,10 @@ +#include "libgcc.h" + +u64 __umoddi3(u64 num, u64 den) +{ + u64 v; + + (void)__udivmoddi4(num, den, &v); + return v; +} +EXPORT_SYMBOL(__umoddi3); diff --git a/arch/parisc/lib/libgcc/__umodsi3.c b/arch/parisc/lib/libgcc/__umodsi3.c new file mode 100644 index 00000000000..51f55aa89f9 --- /dev/null +++ b/arch/parisc/lib/libgcc/__umodsi3.c @@ -0,0 +1,10 @@ +#include "libgcc.h" + +u32 __umodsi3(u32 num, u32 den) +{ + u32 v; + + (void)__udivmodsi4(num, den, &v); + return v; +} +EXPORT_SYMBOL(__umodsi3); diff --git a/arch/parisc/lib/libgcc/__umulsidi3.c b/arch/parisc/lib/libgcc/__umulsidi3.c new file mode 100644 index 00000000000..396f669164d --- /dev/null +++ b/arch/parisc/lib/libgcc/__umulsidi3.c @@ -0,0 +1,46 @@ +#include "libgcc.h" + +#define __ll_B ((u32) 1 << (32 / 2)) +#define __ll_lowpart(t) ((u32) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((u32) (t) >> 16) + +#define umul_ppmm(w1, w0, u, v) \ + do { \ + u32 __x0, __x1, __x2, __x3; \ + u16 __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (u32) __ul * __vl; \ + __x1 = (u32) __ul * __vh; \ + __x2 = (u32) __uh * __vl; \ + __x3 = (u32) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } while (0) + +union DWunion { + struct { + s32 high; + s32 low; + } s; + s64 ll; +}; + +u64 __umulsidi3(u32 u, u32 v) +{ + union DWunion __w; + + umul_ppmm(__w.s.high, __w.s.low, u, v); + + return __w.ll; +} diff --git a/arch/parisc/lib/libgcc/libgcc.h b/arch/parisc/lib/libgcc/libgcc.h new file mode 100644 index 00000000000..5a6f7a510fb --- /dev/null +++ b/arch/parisc/lib/libgcc/libgcc.h @@ -0,0 +1,32 @@ +#ifndef _PA_LIBGCC_H_ +#define _PA_LIBGCC_H_ + +#include <linux/types.h> +#include <linux/module.h> + +/* Cribbed from klibc/libgcc/ */ +u64 __ashldi3(u64 v, int cnt); +u64 __ashrdi3(u64 v, int cnt); + +u32 __clzsi2(u32 v); + +s64 __divdi3(s64 num, s64 den); +s32 __divsi3(s32 num, s32 den); + +u64 __lshrdi3(u64 v, int cnt); + +s64 __moddi3(s64 num, s64 den); +s32 __modsi3(s32 num, s32 den); + +u64 __udivdi3(u64 num, u64 den); +u32 __udivsi3(u32 num, u32 den); + +u64 __udivmoddi4(u64 num, u64 den, u64 * rem_p); +u32 __udivmodsi4(u32 num, u32 den, u32 * rem_p); + +u64 __umulsidi3(u32 u, u32 v); + +u64 __umoddi3(u64 num, u64 den); +u32 __umodsi3(u32 num, u32 den); + +#endif /*_PA_LIBGCC_H_*/ diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index 2c43ebe99a9..d22042d3310 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c @@ -139,12 +139,12 @@ DECLARE_PER_CPU(struct exception_data, exception_data); #define stw(_s,_t,_o,_a,_e) def_store_insn(stw,"r",_s,_t,_o,_a,_e) #ifdef CONFIG_PREFETCH -extern inline void prefetch_src(const void *addr) +static inline void prefetch_src(const void *addr) { __asm__("ldw 0(" s_space ",%0), %%r0" : : "r" (addr)); } -extern inline void prefetch_dst(const void *addr) +static inline void prefetch_dst(const void *addr) { __asm__("ldd 0(" d_space ",%0), %%r0" : : "r" (addr)); } diff --git a/arch/parisc/lib/milli/Makefile b/arch/parisc/lib/milli/Makefile new file mode 100644 index 00000000000..9b24e9b1f3c --- /dev/null +++ b/arch/parisc/lib/milli/Makefile @@ -0,0 +1 @@ +obj-y := dyncall.o divI.o divU.o remI.o remU.o div_const.o mulI.o diff --git a/arch/parisc/lib/milli/divI.S b/arch/parisc/lib/milli/divI.S new file mode 100644 index 00000000000..ac106b7b6f2 --- /dev/null +++ b/arch/parisc/lib/milli/divI.S @@ -0,0 +1,254 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame <bame@debian.org> + and Alan Modra <alan@linuxcare.com.au>. + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_divI +/* ROUTINES: $$divI, $$divoI + + Single precision divide for signed binary integers. + + The quotient is truncated towards zero. + The sign of the quotient is the XOR of the signs of the dividend and + divisor. + Divide by zero is trapped. + Divide of -2**31 by -1 is trapped for $$divoI but not for $$divI. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: + . divisor is zero (traps with ADDIT,= 0,25,0) + . dividend==-2**31 and divisor==-1 and routine is $$divoI + . (traps with ADDO 26,25,0) + . Changes memory at the following places: + . NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Branchs to other millicode routines using BE + . $$div_# for # being 2,3,4,5,6,7,8,9,10,12,14,15 + . + . For selected divisors, calls a divide by constant routine written by + . Karl Pettis. Eligible divisors are 1..15 excluding 11 and 13. + . + . The only overflow case is -2**31 divided by -1. + . Both routines return -2**31 but only $$divoI traps. */ + +RDEFINE(temp,r1) +RDEFINE(retreg,ret1) /* r29 */ +RDEFINE(temp1,arg0) + SUBSPA_MILLI_DIV + ATTR_MILLI + .import $$divI_2,millicode + .import $$divI_3,millicode + .import $$divI_4,millicode + .import $$divI_5,millicode + .import $$divI_6,millicode + .import $$divI_7,millicode + .import $$divI_8,millicode + .import $$divI_9,millicode + .import $$divI_10,millicode + .import $$divI_12,millicode + .import $$divI_14,millicode + .import $$divI_15,millicode + .export $$divI,millicode + .export $$divoI,millicode + .proc + .callinfo millicode + .entry +GSYM($$divoI) + comib,=,n -1,arg1,LREF(negative1) /* when divisor == -1 */ +GSYM($$divI) + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,<> arg1,temp,r0 /* if not, don't use power of 2 divide */ + addi,> 0,arg1,r0 /* if divisor > 0, use power of 2 divide */ + b,n LREF(neg_denom) +LSYM(pow2) + addi,>= 0,arg0,retreg /* if numerator is negative, add the */ + add arg0,temp,retreg /* (denominaotr -1) to correct for shifts */ + extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */ + extrs retreg,15,16,retreg /* retreg = retreg >> 16 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */ + ldi 0xcc,temp1 /* setup 0xcc in temp1 */ + extru,= arg1,23,8,temp /* test denominator with 0xff00 */ + extrs retreg,23,24,retreg /* retreg = retreg >> 8 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */ + ldi 0xaa,temp /* setup 0xaa in temp */ + extru,= arg1,27,4,r0 /* test denominator with 0xf0 */ + extrs retreg,27,28,retreg /* retreg = retreg >> 4 */ + and,= arg1,temp1,r0 /* test denominator with 0xcc */ + extrs retreg,29,30,retreg /* retreg = retreg >> 2 */ + and,= arg1,temp,r0 /* test denominator with 0xaa */ + extrs retreg,30,31,retreg /* retreg = retreg >> 1 */ + MILLIRETN +LSYM(neg_denom) + addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power of 2 */ + b,n LREF(regular_seq) + sub r0,arg1,temp /* make denominator positive */ + comb,=,n arg1,temp,LREF(regular_seq) /* test against 0x80000000 and 0 */ + ldo -1(temp),retreg /* is there at most one bit set ? */ + and,= temp,retreg,r0 /* if so, the denominator is power of 2 */ + b,n LREF(regular_seq) + sub r0,arg0,retreg /* negate numerator */ + comb,=,n arg0,retreg,LREF(regular_seq) /* test against 0x80000000 */ + copy retreg,arg0 /* set up arg0, arg1 and temp */ + copy temp,arg1 /* before branching to pow2 */ + b LREF(pow2) + ldo -1(arg1),temp +LSYM(regular_seq) + comib,>>=,n 15,arg1,LREF(small_divisor) + add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */ +LSYM(normal) + subi 0,retreg,retreg /* make it positive */ + sub 0,arg1,temp /* clear carry, */ + /* negate the divisor */ + ds 0,temp,0 /* set V-bit to the comple- */ + /* ment of the divisor sign */ + add retreg,retreg,retreg /* shift msb bit into carry */ + ds r0,arg1,temp /* 1st divide step, if no carry */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 32nd divide step, */ + addc retreg,retreg,retreg /* shift last retreg bit into retreg */ + xor,>= arg0,arg1,0 /* get correct sign of quotient */ + sub 0,retreg,retreg /* based on operand signs */ + MILLIRETN + nop + +LSYM(small_divisor) + +#if defined(CONFIG_64BIT) +/* Clear the upper 32 bits of the arg1 register. We are working with */ +/* small divisors (and 32-bit integers) We must not be mislead */ +/* by "1" bits left in the upper 32 bits. */ + depd %r0,31,32,%r25 +#endif + blr,n arg1,r0 + nop +/* table for divisor == 0,1, ... ,15 */ + addit,= 0,arg1,r0 /* trap if divisor == 0 */ + nop + MILLIRET /* divisor == 1 */ + copy arg0,retreg + MILLI_BEN($$divI_2) /* divisor == 2 */ + nop + MILLI_BEN($$divI_3) /* divisor == 3 */ + nop + MILLI_BEN($$divI_4) /* divisor == 4 */ + nop + MILLI_BEN($$divI_5) /* divisor == 5 */ + nop + MILLI_BEN($$divI_6) /* divisor == 6 */ + nop + MILLI_BEN($$divI_7) /* divisor == 7 */ + nop + MILLI_BEN($$divI_8) /* divisor == 8 */ + nop + MILLI_BEN($$divI_9) /* divisor == 9 */ + nop + MILLI_BEN($$divI_10) /* divisor == 10 */ + nop + b LREF(normal) /* divisor == 11 */ + add,>= 0,arg0,retreg + MILLI_BEN($$divI_12) /* divisor == 12 */ + nop + b LREF(normal) /* divisor == 13 */ + add,>= 0,arg0,retreg + MILLI_BEN($$divI_14) /* divisor == 14 */ + nop + MILLI_BEN($$divI_15) /* divisor == 15 */ + nop + +LSYM(negative1) + sub 0,arg0,retreg /* result is negation of dividend */ + MILLIRET + addo arg0,arg1,r0 /* trap iff dividend==0x80000000 && divisor==-1 */ + .exit + .procend + .end +#endif diff --git a/arch/parisc/lib/milli/divU.S b/arch/parisc/lib/milli/divU.S new file mode 100644 index 00000000000..9287fe2546f --- /dev/null +++ b/arch/parisc/lib/milli/divU.S @@ -0,0 +1,235 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame <bame@debian.org> + and Alan Modra <alan@linuxcare.com.au>. + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_divU +/* ROUTINE: $$divU + . + . Single precision divide for unsigned integers. + . + . Quotient is truncated towards zero. + . Traps on divide by zero. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: + . divisor is zero + . Changes memory at the following places: + . NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Branchs to other millicode routines using BE: + . $$divU_# for 3,5,6,7,9,10,12,14,15 + . + . For selected small divisors calls the special divide by constant + . routines written by Karl Pettis. These are: 3,5,6,7,9,10,12,14,15. */ + +RDEFINE(temp,r1) +RDEFINE(retreg,ret1) /* r29 */ +RDEFINE(temp1,arg0) + SUBSPA_MILLI_DIV + ATTR_MILLI + .export $$divU,millicode + .import $$divU_3,millicode + .import $$divU_5,millicode + .import $$divU_6,millicode + .import $$divU_7,millicode + .import $$divU_9,millicode + .import $$divU_10,millicode + .import $$divU_12,millicode + .import $$divU_14,millicode + .import $$divU_15,millicode + .proc + .callinfo millicode + .entry +GSYM($$divU) +/* The subtract is not nullified since it does no harm and can be used + by the two cases that branch back to "normal". */ + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,= arg1,temp,r0 /* if so, denominator is power of 2 */ + b LREF(regular_seq) + addit,= 0,arg1,0 /* trap for zero dvr */ + copy arg0,retreg + extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */ + extru retreg,15,16,retreg /* retreg = retreg >> 16 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */ + ldi 0xcc,temp1 /* setup 0xcc in temp1 */ + extru,= arg1,23,8,temp /* test denominator with 0xff00 */ + extru retreg,23,24,retreg /* retreg = retreg >> 8 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */ + ldi 0xaa,temp /* setup 0xaa in temp */ + extru,= arg1,27,4,r0 /* test denominator with 0xf0 */ + extru retreg,27,28,retreg /* retreg = retreg >> 4 */ + and,= arg1,temp1,r0 /* test denominator with 0xcc */ + extru retreg,29,30,retreg /* retreg = retreg >> 2 */ + and,= arg1,temp,r0 /* test denominator with 0xaa */ + extru retreg,30,31,retreg /* retreg = retreg >> 1 */ + MILLIRETN + nop +LSYM(regular_seq) + comib,>= 15,arg1,LREF(special_divisor) + subi 0,arg1,temp /* clear carry, negate the divisor */ + ds r0,temp,r0 /* set V-bit to 1 */ +LSYM(normal) + add arg0,arg0,retreg /* shift msb bit into carry */ + ds r0,arg1,temp /* 1st divide step, if no carry */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 32nd divide step, */ + MILLIRET + addc retreg,retreg,retreg /* shift last retreg bit into retreg */ + +/* Handle the cases where divisor is a small constant or has high bit on. */ +LSYM(special_divisor) +/* blr arg1,r0 */ +/* comib,>,n 0,arg1,LREF(big_divisor) ; nullify previous instruction */ + +/* Pratap 8/13/90. The 815 Stirling chip set has a bug that prevents us from + generating such a blr, comib sequence. A problem in nullification. So I + rewrote this code. */ + +#if defined(CONFIG_64BIT) +/* Clear the upper 32 bits of the arg1 register. We are working with + small divisors (and 32-bit unsigned integers) We must not be mislead + by "1" bits left in the upper 32 bits. */ + depd %r0,31,32,%r25 +#endif + comib,> 0,arg1,LREF(big_divisor) + nop + blr arg1,r0 + nop + +LSYM(zero_divisor) /* this label is here to provide external visibility */ + addit,= 0,arg1,0 /* trap for zero dvr */ + nop + MILLIRET /* divisor == 1 */ + copy arg0,retreg + MILLIRET /* divisor == 2 */ + extru arg0,30,31,retreg + MILLI_BEN($$divU_3) /* divisor == 3 */ + nop + MILLIRET /* divisor == 4 */ + extru arg0,29,30,retreg + MILLI_BEN($$divU_5) /* divisor == 5 */ + nop + MILLI_BEN($$divU_6) /* divisor == 6 */ + nop + MILLI_BEN($$divU_7) /* divisor == 7 */ + nop + MILLIRET /* divisor == 8 */ + extru arg0,28,29,retreg + MILLI_BEN($$divU_9) /* divisor == 9 */ + nop + MILLI_BEN($$divU_10) /* divisor == 10 */ + nop + b LREF(normal) /* divisor == 11 */ + ds r0,temp,r0 /* set V-bit to 1 */ + MILLI_BEN($$divU_12) /* divisor == 12 */ + nop + b LREF(normal) /* divisor == 13 */ + ds r0,temp,r0 /* set V-bit to 1 */ + MILLI_BEN($$divU_14) /* divisor == 14 */ + nop + MILLI_BEN($$divU_15) /* divisor == 15 */ + nop + +/* Handle the case where the high bit is on in the divisor. + Compute: if( dividend>=divisor) quotient=1; else quotient=0; + Note: dividend>==divisor iff dividend-divisor does not borrow + and not borrow iff carry. */ +LSYM(big_divisor) + sub arg0,arg1,r0 + MILLIRET + addc r0,r0,retreg + .exit + .procend + .end +#endif diff --git a/arch/parisc/lib/milli/div_const.S b/arch/parisc/lib/milli/div_const.S new file mode 100644 index 00000000000..dd660076e94 --- /dev/null +++ b/arch/parisc/lib/milli/div_const.S @@ -0,0 +1,682 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame <bame@debian.org> + and Alan Modra <alan@linuxcare.com.au>. + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_div_const +/* ROUTINE: $$divI_2 + . $$divI_3 $$divU_3 + . $$divI_4 + . $$divI_5 $$divU_5 + . $$divI_6 $$divU_6 + . $$divI_7 $$divU_7 + . $$divI_8 + . $$divI_9 $$divU_9 + . $$divI_10 $$divU_10 + . + . $$divI_12 $$divU_12 + . + . $$divI_14 $$divU_14 + . $$divI_15 $$divU_15 + . $$divI_16 + . $$divI_17 $$divU_17 + . + . Divide by selected constants for single precision binary integers. + + INPUT REGISTERS: + . arg0 == dividend + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: NONE + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Calls other millicode routines using mrp: NONE + . Calls other millicode routines: NONE */ + + +/* TRUNCATED DIVISION BY SMALL INTEGERS + + We are interested in q(x) = floor(x/y), where x >= 0 and y > 0 + (with y fixed). + + Let a = floor(z/y), for some choice of z. Note that z will be + chosen so that division by z is cheap. + + Let r be the remainder(z/y). In other words, r = z - ay. + + Now, our method is to choose a value for b such that + + q'(x) = floor((ax+b)/z) + + is equal to q(x) over as large a range of x as possible. If the + two are equal over a sufficiently large range, and if it is easy to + form the product (ax), and it is easy to divide by z, then we can + perform the division much faster than the general division algorithm. + + So, we want the following to be true: + + . For x in the following range: + . + . ky <= x < (k+1)y + . + . implies that + . + . k <= (ax+b)/z < (k+1) + + We want to determine b such that this is true for all k in the + range {0..K} for some maximum K. + + Since (ax+b) is an increasing function of x, we can take each + bound separately to determine the "best" value for b. + + (ax+b)/z < (k+1) implies + + (a((k+1)y-1)+b < (k+1)z implies + + b < a + (k+1)(z-ay) implies + + b < a + (k+1)r + + This needs to be true for all k in the range {0..K}. In + particular, it is true for k = 0 and this leads to a maximum + acceptable value for b. + + b < a+r or b <= a+r-1 + + Taking the other bound, we have + + k <= (ax+b)/z implies + + k <= (aky+b)/z implies + + k(z-ay) <= b implies + + kr <= b + + Clearly, the largest range for k will be achieved by maximizing b, + when r is not zero. When r is zero, then the simplest choice for b + is 0. When r is not 0, set + + . b = a+r-1 + + Now, by construction, q'(x) = floor((ax+b)/z) = q(x) = floor(x/y) + for all x in the range: + + . 0 <= x < (K+1)y + + We need to determine what K is. Of our two bounds, + + . b < a+(k+1)r is satisfied for all k >= 0, by construction. + + The other bound is + + . kr <= b + + This is always true if r = 0. If r is not 0 (the usual case), then + K = floor((a+r-1)/r), is the maximum value for k. + + Therefore, the formula q'(x) = floor((ax+b)/z) yields the correct + answer for q(x) = floor(x/y) when x is in the range + + (0,(K+1)y-1) K = floor((a+r-1)/r) + + To be most useful, we want (K+1)y-1 = (max x) >= 2**32-1 so that + the formula for q'(x) yields the correct value of q(x) for all x + representable by a single word in HPPA. + + We are also constrained in that computing the product (ax), adding + b, and dividing by z must all be done quickly, otherwise we will be + better off going through the general algorithm using the DS + instruction, which uses approximately 70 cycles. + + For each y, there is a choice of z which satisfies the constraints + for (K+1)y >= 2**32. We may not, however, be able to satisfy the + timing constraints for arbitrary y. It seems that z being equal to + a power of 2 or a power of 2 minus 1 is as good as we can do, since + it minimizes the time to do division by z. We want the choice of z + to also result in a value for (a) that minimizes the computation of + the product (ax). This is best achieved if (a) has a regular bit + pattern (so the multiplication can be done with shifts and adds). + The value of (a) also needs to be less than 2**32 so the product is + always guaranteed to fit in 2 words. + + In actual practice, the following should be done: + + 1) For negative x, you should take the absolute value and remember + . the fact so that the result can be negated. This obviously does + . not apply in the unsigned case. + 2) For even y, you should factor out the power of 2 that divides y + . and divide x by it. You can then proceed by dividing by the + . odd factor of y. + + Here is a table of some odd values of y, and corresponding choices + for z which are "good". + + y z r a (hex) max x (hex) + + 3 2**32 1 55555555 100000001 + 5 2**32 1 33333333 100000003 + 7 2**24-1 0 249249 (infinite) + 9 2**24-1 0 1c71c7 (infinite) + 11 2**20-1 0 1745d (infinite) + 13 2**24-1 0 13b13b (infinite) + 15 2**32 1 11111111 10000000d + 17 2**32 1 f0f0f0f 10000000f + + If r is 1, then b = a+r-1 = a. This simplifies the computation + of (ax+b), since you can compute (x+1)(a) instead. If r is 0, + then b = 0 is ok to use which simplifies (ax+b). + + The bit patterns for 55555555, 33333333, and 11111111 are obviously + very regular. The bit patterns for the other values of a above are: + + y (hex) (binary) + + 7 249249 001001001001001001001001 << regular >> + 9 1c71c7 000111000111000111000111 << regular >> + 11 1745d 000000010111010001011101 << irregular >> + 13 13b13b 000100111011000100111011 << irregular >> + + The bit patterns for (a) corresponding to (y) of 11 and 13 may be + too irregular to warrant using this method. + + When z is a power of 2 minus 1, then the division by z is slightly + more complicated, involving an iterative solution. + + The code presented here solves division by 1 through 17, except for + 11 and 13. There are algorithms for both signed and unsigned + quantities given. + + TIMINGS (cycles) + + divisor positive negative unsigned + + . 1 2 2 2 + . 2 4 4 2 + . 3 19 21 19 + . 4 4 4 2 + . 5 18 22 19 + . 6 19 22 19 + . 8 4 4 2 + . 10 18 19 17 + . 12 18 20 18 + . 15 16 18 16 + . 16 4 4 2 + . 17 16 18 16 + + Now, the algorithm for 7, 9, and 14 is an iterative one. That is, + a loop body is executed until the tentative quotient is 0. The + number of times the loop body is executed varies depending on the + dividend, but is never more than two times. If the dividend is + less than the divisor, then the loop body is not executed at all. + Each iteration adds 4 cycles to the timings. + + divisor positive negative unsigned + + . 7 19+4n 20+4n 20+4n n = number of iterations + . 9 21+4n 22+4n 21+4n + . 14 21+4n 22+4n 20+4n + + To give an idea of how the number of iterations varies, here is a + table of dividend versus number of iterations when dividing by 7. + + smallest largest required + dividend dividend iterations + + . 0 6 0 + . 7 0x6ffffff 1 + 0x1000006 0xffffffff 2 + + There is some overlap in the range of numbers requiring 1 and 2 + iterations. */ + +RDEFINE(t2,r1) +RDEFINE(x2,arg0) /* r26 */ +RDEFINE(t1,arg1) /* r25 */ +RDEFINE(x1,ret1) /* r29 */ + + SUBSPA_MILLI_DIV + ATTR_MILLI + + .proc + .callinfo millicode + .entry +/* NONE of these routines require a stack frame + ALL of these routines are unwindable from millicode */ + +GSYM($$divide_by_constant) + .export $$divide_by_constant,millicode +/* Provides a "nice" label for the code covered by the unwind descriptor + for things like gprof. */ + +/* DIVISION BY 2 (shift by 1) */ +GSYM($$divI_2) + .export $$divI_2,millicode + comclr,>= arg0,0,0 + addi 1,arg0,arg0 + MILLIRET + extrs arg0,30,31,ret1 + + +/* DIVISION BY 4 (shift by 2) */ +GSYM($$divI_4) + .export $$divI_4,millicode + comclr,>= arg0,0,0 + addi 3,arg0,arg0 + MILLIRET + extrs arg0,29,30,ret1 + + +/* DIVISION BY 8 (shift by 3) */ +GSYM($$divI_8) + .export $$divI_8,millicode + comclr,>= arg0,0,0 + addi 7,arg0,arg0 + MILLIRET + extrs arg0,28,29,ret1 + +/* DIVISION BY 16 (shift by 4) */ +GSYM($$divI_16) + .export $$divI_16,millicode + comclr,>= arg0,0,0 + addi 15,arg0,arg0 + MILLIRET + extrs arg0,27,28,ret1 + +/**************************************************************************** +* +* DIVISION BY DIVISORS OF FFFFFFFF, and powers of 2 times these +* +* includes 3,5,15,17 and also 6,10,12 +* +****************************************************************************/ + +/* DIVISION BY 3 (use z = 2**32; a = 55555555) */ + +GSYM($$divI_3) + .export $$divI_3,millicode + comb,<,N x2,0,LREF(neg3) + + addi 1,x2,x2 /* this cannot overflow */ + extru x2,1,2,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,0,x1 + +LSYM(neg3) + subi 1,x2,x2 /* this cannot overflow */ + extru x2,1,2,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_3) + .export $$divU_3,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,30,t1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,t1,x1 + +/* DIVISION BY 5 (use z = 2**32; a = 33333333) */ + +GSYM($$divI_5) + .export $$divI_5,millicode + comb,<,N x2,0,LREF(neg5) + + addi 3,x2,t1 /* this cannot overflow */ + sh1add x2,t1,x2 /* multiply by 3 to get started */ + b LREF(pos) + addc 0,0,x1 + +LSYM(neg5) + sub 0,x2,x2 /* negate x2 */ + addi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,31,x1 /* get top bit (can be 1) */ + sh1add x2,x2,x2 /* multiply by 3 to get started */ + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_5) + .export $$divU_5,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,31,t1 /* multiply by 3 to get started */ + sh1add x2,x2,x2 + b LREF(pos) + addc t1,x1,x1 + +/* DIVISION BY 6 (shift to divide by 2 then divide by 3) */ +GSYM($$divI_6) + .export $$divI_6,millicode + comb,<,N x2,0,LREF(neg6) + extru x2,30,31,x2 /* divide by 2 */ + addi 5,x2,t1 /* compute 5*(x2+1) = 5*x2+5 */ + sh2add x2,t1,x2 /* multiply by 5 to get started */ + b LREF(pos) + addc 0,0,x1 + +LSYM(neg6) + subi 2,x2,x2 /* negate, divide by 2, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,30,31,x2 + shd 0,x2,30,x1 + sh2add x2,x2,x2 /* multiply by 5 to get started */ + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_6) + .export $$divU_6,millicode + extru x2,30,31,x2 /* divide by 2 */ + addi 1,x2,x2 /* cannot carry */ + shd 0,x2,30,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,0,x1 + +/* DIVISION BY 10 (shift to divide by 2 then divide by 5) */ +GSYM($$divU_10) + .export $$divU_10,millicode + extru x2,30,31,x2 /* divide by 2 */ + addi 3,x2,t1 /* compute 3*(x2+1) = (3*x2)+3 */ + sh1add x2,t1,x2 /* multiply by 3 to get started */ + addc 0,0,x1 +LSYM(pos) + shd x1,x2,28,t1 /* multiply by 0x11 */ + shd x2,0,28,t2 + add x2,t2,x2 + addc x1,t1,x1 +LSYM(pos_for_17) + shd x1,x2,24,t1 /* multiply by 0x101 */ + shd x2,0,24,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,16,t1 /* multiply by 0x10001 */ + shd x2,0,16,t2 + add x2,t2,x2 + MILLIRET + addc x1,t1,x1 + +GSYM($$divI_10) + .export $$divI_10,millicode + comb,< x2,0,LREF(neg10) + copy 0,x1 + extru x2,30,31,x2 /* divide by 2 */ + addib,TR 1,x2,LREF(pos) /* add 1 (cannot overflow) */ + sh1add x2,x2,x2 /* multiply by 3 to get started */ + +LSYM(neg10) + subi 2,x2,x2 /* negate, divide by 2, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,30,31,x2 + sh1add x2,x2,x2 /* multiply by 3 to get started */ +LSYM(neg) + shd x1,x2,28,t1 /* multiply by 0x11 */ + shd x2,0,28,t2 + add x2,t2,x2 + addc x1,t1,x1 +LSYM(neg_for_17) + shd x1,x2,24,t1 /* multiply by 0x101 */ + shd x2,0,24,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,16,t1 /* multiply by 0x10001 */ + shd x2,0,16,t2 + add x2,t2,x2 + addc x1,t1,x1 + MILLIRET + sub 0,x1,x1 + +/* DIVISION BY 12 (shift to divide by 4 then divide by 3) */ +GSYM($$divI_12) + .export $$divI_12,millicode + comb,< x2,0,LREF(neg12) + copy 0,x1 + extru x2,29,30,x2 /* divide by 4 */ + addib,tr 1,x2,LREF(pos) /* compute 5*(x2+1) = 5*x2+5 */ + sh2add x2,x2,x2 /* multiply by 5 to get started */ + +LSYM(neg12) + subi 4,x2,x2 /* negate, divide by 4, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,29,30,x2 + b LREF(neg) + sh2add x2,x2,x2 /* multiply by 5 to get started */ + +GSYM($$divU_12) + .export $$divU_12,millicode + extru x2,29,30,x2 /* divide by 4 */ + addi 5,x2,t1 /* cannot carry */ + sh2add x2,t1,x2 /* multiply by 5 to get started */ + b LREF(pos) + addc 0,0,x1 + +/* DIVISION BY 15 (use z = 2**32; a = 11111111) */ +GSYM($$divI_15) + .export $$divI_15,millicode + comb,< x2,0,LREF(neg15) + copy 0,x1 + addib,tr 1,x2,LREF(pos)+4 + shd x1,x2,28,t1 + +LSYM(neg15) + b LREF(neg) + subi 1,x2,x2 + +GSYM($$divU_15) + .export $$divU_15,millicode + addi 1,x2,x2 /* this CAN overflow */ + b LREF(pos) + addc 0,0,x1 + +/* DIVISION BY 17 (use z = 2**32; a = f0f0f0f) */ +GSYM($$divI_17) + .export $$divI_17,millicode + comb,<,n x2,0,LREF(neg17) + addi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,28,t1 /* multiply by 0xf to get started */ + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(pos_for_17) + subb t1,0,x1 + +LSYM(neg17) + subi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,28,t1 /* multiply by 0xf to get started */ + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(neg_for_17) + subb t1,0,x1 + +GSYM($$divU_17) + .export $$divU_17,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,28,t1 /* multiply by 0xf to get started */ +LSYM(u17) + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(pos_for_17) + subb t1,x1,x1 + + +/* DIVISION BY DIVISORS OF FFFFFF, and powers of 2 times these + includes 7,9 and also 14 + + + z = 2**24-1 + r = z mod x = 0 + + so choose b = 0 + + Also, in order to divide by z = 2**24-1, we approximate by dividing + by (z+1) = 2**24 (which is easy), and then correcting. + + (ax) = (z+1)q' + r + . = zq' + (q'+r) + + So to compute (ax)/z, compute q' = (ax)/(z+1) and r = (ax) mod (z+1) + Then the true remainder of (ax)/z is (q'+r). Repeat the process + with this new remainder, adding the tentative quotients together, + until a tentative quotient is 0 (and then we are done). There is + one last correction to be done. It is possible that (q'+r) = z. + If so, then (q'+r)/(z+1) = 0 and it looks like we are done. But, + in fact, we need to add 1 more to the quotient. Now, it turns + out that this happens if and only if the original value x is + an exact multiple of y. So, to avoid a three instruction test at + the end, instead use 1 instruction to add 1 to x at the beginning. */ + +/* DIVISION BY 7 (use z = 2**24-1; a = 249249) */ +GSYM($$divI_7) + .export $$divI_7,millicode + comb,<,n x2,0,LREF(neg7) +LSYM(7) + addi 1,x2,x2 /* cannot overflow */ + shd 0,x2,29,x1 + sh3add x2,x2,x2 + addc x1,0,x1 +LSYM(pos7) + shd x1,x2,26,t1 + shd x2,0,26,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,20,t1 + shd x2,0,20,t2 + add x2,t2,x2 + addc x1,t1,t1 + + /* computed <t1,x2>. Now divide it by (2**24 - 1) */ + + copy 0,x1 + shd,= t1,x2,24,t1 /* tentative quotient */ +LSYM(1) + addb,tr t1,x1,LREF(2) /* add to previous quotient */ + extru x2,31,24,x2 /* new remainder (unadjusted) */ + + MILLIRETN + +LSYM(2) + addb,tr t1,x2,LREF(1) /* adjust remainder */ + extru,= x2,7,8,t1 /* new quotient */ + +LSYM(neg7) + subi 1,x2,x2 /* negate x2 and add 1 */ +LSYM(8) + shd 0,x2,29,x1 + sh3add x2,x2,x2 + addc x1,0,x1 + +LSYM(neg7_shift) + shd x1,x2,26,t1 + shd x2,0,26,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,20,t1 + shd x2,0,20,t2 + add x2,t2,x2 + addc x1,t1,t1 + + /* computed <t1,x2>. Now divide it by (2**24 - 1) */ + + copy 0,x1 + shd,= t1,x2,24,t1 /* tentative quotient */ +LSYM(3) + addb,tr t1,x1,LREF(4) /* add to previous quotient */ + extru x2,31,24,x2 /* new remainder (unadjusted) */ + + MILLIRET + sub 0,x1,x1 /* negate result */ + +LSYM(4) + addb,tr t1,x2,LREF(3) /* adjust remainder */ + extru,= x2,7,8,t1 /* new quotient */ + +GSYM($$divU_7) + .export $$divU_7,millicode + addi 1,x2,x2 /* can carry */ + addc 0,0,x1 + shd x1,x2,29,t1 + sh3add x2,x2,x2 + b LREF(pos7) + addc t1,x1,x1 + +/* DIVISION BY 9 (use z = 2**24-1; a = 1c71c7) */ +GSYM($$divI_9) + .export $$divI_9,millicode + comb,<,n x2,0,LREF(neg9) + addi 1,x2,x2 /* cannot overflow */ + shd 0,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(pos7) + subb t1,0,x1 + +LSYM(neg9) + subi 1,x2,x2 /* negate and add 1 */ + shd 0,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(neg7_shift) + subb t1,0,x1 + +GSYM($$divU_9) + .export $$divU_9,millicode + addi 1,x2,x2 /* can carry */ + addc 0,0,x1 + shd x1,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(pos7) + subb t1,x1,x1 + +/* DIVISION BY 14 (shift to divide by 2 then divide by 7) */ +GSYM($$divI_14) + .export $$divI_14,millicode + comb,<,n x2,0,LREF(neg14) +GSYM($$divU_14) + .export $$divU_14,millicode + b LREF(7) /* go to 7 case */ + extru x2,30,31,x2 /* divide by 2 */ + +LSYM(neg14) + subi 2,x2,x2 /* negate (and add 2) */ + b LREF(8) + extru x2,30,31,x2 /* divide by 2 */ + .exit + .procend + .end +#endif diff --git a/arch/parisc/lib/milli/dyncall.S b/arch/parisc/lib/milli/dyncall.S new file mode 100644 index 00000000000..27f9ca558d0 --- /dev/null +++ b/arch/parisc/lib/milli/dyncall.S @@ -0,0 +1,32 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame <bame@debian.org> + and Alan Modra <alan@linuxcare.com.au>. + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_dyncall + SUBSPA_MILLI + ATTR_DATA +GSYM($$dyncall) + .export $$dyncall,millicode + .proc + .callinfo millicode + .entry + bb,>=,n %r22,30,LREF(1) ; branch if not plabel address + depi 0,31,2,%r22 ; clear the two least significant bits + ldw 4(%r22),%r19 ; load new LTP value + ldw 0(%r22),%r22 ; load address of target +LSYM(1) + bv %r0(%r22) ; branch to the real target + stw %r2,-24(%r30) ; save return address into frame marker + .exit + .procend +#endif diff --git a/arch/parisc/lib/milli/milli.S b/arch/parisc/lib/milli/milli.S new file mode 100644 index 00000000000..47c6cde712e --- /dev/null +++ b/arch/parisc/lib/milli/milli.S @@ -0,0 +1,2071 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame <bame@debian.org> + and Alan Modra <alan@linuxcare.com.au>. + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#ifdef CONFIG_64BIT + .level 2.0w +#endif + +/* Hardware General Registers. */ +r0: .reg %r0 +r1: .reg %r1 +r2: .reg %r2 +r3: .reg %r3 +r4: .reg %r4 +r5: .reg %r5 +r6: .reg %r6 +r7: .reg %r7 +r8: .reg %r8 +r9: .reg %r9 +r10: .reg %r10 +r11: .reg %r11 +r12: .reg %r12 +r13: .reg %r13 +r14: .reg %r14 +r15: .reg %r15 +r16: .reg %r16 +r17: .reg %r17 +r18: .reg %r18 +r19: .reg %r19 +r20: .reg %r20 +r21: .reg %r21 +r22: .reg %r22 +r23: .reg %r23 +r24: .reg %r24 +r25: .reg %r25 +r26: .reg %r26 +r27: .reg %r27 +r28: .reg %r28 +r29: .reg %r29 +r30: .reg %r30 +r31: .reg %r31 + +/* Hardware Space Registers. */ +sr0: .reg %sr0 +sr1: .reg %sr1 +sr2: .reg %sr2 +sr3: .reg %sr3 +sr4: .reg %sr4 +sr5: .reg %sr5 +sr6: .reg %sr6 +sr7: .reg %sr7 + +/* Hardware Floating Point Registers. */ +fr0: .reg %fr0 +fr1: .reg %fr1 +fr2: .reg %fr2 +fr3: .reg %fr3 +fr4: .reg %fr4 +fr5: .reg %fr5 +fr6: .reg %fr6 +fr7: .reg %fr7 +fr8: .reg %fr8 +fr9: .reg %fr9 +fr10: .reg %fr10 +fr11: .reg %fr11 +fr12: .reg %fr12 +fr13: .reg %fr13 +fr14: .reg %fr14 +fr15: .reg %fr15 + +/* Hardware Control Registers. */ +cr11: .reg %cr11 +sar: .reg %cr11 /* Shift Amount Register */ + +/* Software Architecture General Registers. */ +rp: .reg r2 /* return pointer */ +#ifdef CONFIG_64BIT +mrp: .reg r2 /* millicode return pointer */ +#else +mrp: .reg r31 /* millicode return pointer */ +#endif +ret0: .reg r28 /* return value */ +ret1: .reg r29 /* return value (high part of double) */ +sp: .reg r30 /* stack pointer */ +dp: .reg r27 /* data pointer */ +arg0: .reg r26 /* argument */ +arg1: .reg r25 /* argument or high part of double argument */ +arg2: .reg r24 /* argument */ +arg3: .reg r23 /* argument or high part of double argument */ + +/* Software Architecture Space Registers. */ +/* sr0 ; return link from BLE */ +sret: .reg sr1 /* return value */ +sarg: .reg sr1 /* argument */ +/* sr4 ; PC SPACE tracker */ +/* sr5 ; process private data */ + +/* Frame Offsets (millicode convention!) Used when calling other + millicode routines. Stack unwinding is dependent upon these + definitions. */ +r31_slot: .equ -20 /* "current RP" slot */ +sr0_slot: .equ -16 /* "static link" slot */ +#if defined(CONFIG_64BIT) +mrp_slot: .equ -16 /* "current RP" slot */ +psp_slot: .equ -8 /* "previous SP" slot */ +#else +mrp_slot: .equ -20 /* "current RP" slot (replacing "r31_slot") */ +#endif + + +#define DEFINE(name,value)name: .EQU value +#define RDEFINE(name,value)name: .REG value +#ifdef milliext +#define MILLI_BE(lbl) BE lbl(sr7,r0) +#define MILLI_BEN(lbl) BE,n lbl(sr7,r0) +#define MILLI_BLE(lbl) BLE lbl(sr7,r0) +#define MILLI_BLEN(lbl) BLE,n lbl(sr7,r0) +#define MILLIRETN BE,n 0(sr0,mrp) +#define MILLIRET BE 0(sr0,mrp) +#define MILLI_RETN BE,n 0(sr0,mrp) +#define MILLI_RET BE 0(sr0,mrp) +#else +#define MILLI_BE(lbl) B lbl +#define MILLI_BEN(lbl) B,n lbl +#define MILLI_BLE(lbl) BL lbl,mrp +#define MILLI_BLEN(lbl) BL,n lbl,mrp +#define MILLIRETN BV,n 0(mrp) +#define MILLIRET BV 0(mrp) +#define MILLI_RETN BV,n 0(mrp) +#define MILLI_RET BV 0(mrp) +#endif + +#define CAT(a,b) a##b + +#define SUBSPA_MILLI .section .text +#define SUBSPA_MILLI_DIV .section .text.div,"ax",@progbits! .align 16 +#define SUBSPA_MILLI_MUL .section .text.mul,"ax",@progbits! .align 16 +#define ATTR_MILLI +#define SUBSPA_DATA .section .data +#define ATTR_DATA +#define GLOBAL $global$ +#define GSYM(sym) !sym: +#define LSYM(sym) !CAT(.L,sym:) +#define LREF(sym) CAT(.L,sym) + +#ifdef L_dyncall + SUBSPA_MILLI + ATTR_DATA +GSYM($$dyncall) + .export $$dyncall,millicode + .proc + .callinfo millicode + .entry + bb,>=,n %r22,30,LREF(1) ; branch if not plabel address + depi 0,31,2,%r22 ; clear the two least significant bits + ldw 4(%r22),%r19 ; load new LTP value + ldw 0(%r22),%r22 ; load address of target +LSYM(1) + bv %r0(%r22) ; branch to the real target + stw %r2,-24(%r30) ; save return address into frame marker + .exit + .procend +#endif + +#ifdef L_divI +/* ROUTINES: $$divI, $$divoI + + Single precision divide for signed binary integers. + + The quotient is truncated towards zero. + The sign of the quotient is the XOR of the signs of the dividend and + divisor. + Divide by zero is trapped. + Divide of -2**31 by -1 is trapped for $$divoI but not for $$divI. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: + . divisor is zero (traps with ADDIT,= 0,25,0) + . dividend==-2**31 and divisor==-1 and routine is $$divoI + . (traps with ADDO 26,25,0) + . Changes memory at the following places: + . NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Branchs to other millicode routines using BE + . $$div_# for # being 2,3,4,5,6,7,8,9,10,12,14,15 + . + . For selected divisors, calls a divide by constant routine written by + . Karl Pettis. Eligible divisors are 1..15 excluding 11 and 13. + . + . The only overflow case is -2**31 divided by -1. + . Both routines return -2**31 but only $$divoI traps. */ + +RDEFINE(temp,r1) +RDEFINE(retreg,ret1) /* r29 */ +RDEFINE(temp1,arg0) + SUBSPA_MILLI_DIV + ATTR_MILLI + .import $$divI_2,millicode + .import $$divI_3,millicode + .import $$divI_4,millicode + .import $$divI_5,millicode + .import $$divI_6,millicode + .import $$divI_7,millicode + .import $$divI_8,millicode + .import $$divI_9,millicode + .import $$divI_10,millicode + .import $$divI_12,millicode + .import $$divI_14,millicode + .import $$divI_15,millicode + .export $$divI,millicode + .export $$divoI,millicode + .proc + .callinfo millicode + .entry +GSYM($$divoI) + comib,=,n -1,arg1,LREF(negative1) /* when divisor == -1 */ +GSYM($$divI) + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,<> arg1,temp,r0 /* if not, don't use power of 2 divide */ + addi,> 0,arg1,r0 /* if divisor > 0, use power of 2 divide */ + b,n LREF(neg_denom) +LSYM(pow2) + addi,>= 0,arg0,retreg /* if numerator is negative, add the */ + add arg0,temp,retreg /* (denominaotr -1) to correct for shifts */ + extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */ + extrs retreg,15,16,retreg /* retreg = retreg >> 16 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */ + ldi 0xcc,temp1 /* setup 0xcc in temp1 */ + extru,= arg1,23,8,temp /* test denominator with 0xff00 */ + extrs retreg,23,24,retreg /* retreg = retreg >> 8 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */ + ldi 0xaa,temp /* setup 0xaa in temp */ + extru,= arg1,27,4,r0 /* test denominator with 0xf0 */ + extrs retreg,27,28,retreg /* retreg = retreg >> 4 */ + and,= arg1,temp1,r0 /* test denominator with 0xcc */ + extrs retreg,29,30,retreg /* retreg = retreg >> 2 */ + and,= arg1,temp,r0 /* test denominator with 0xaa */ + extrs retreg,30,31,retreg /* retreg = retreg >> 1 */ + MILLIRETN +LSYM(neg_denom) + addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power of 2 */ + b,n LREF(regular_seq) + sub r0,arg1,temp /* make denominator positive */ + comb,=,n arg1,temp,LREF(regular_seq) /* test against 0x80000000 and 0 */ + ldo -1(temp),retreg /* is there at most one bit set ? */ + and,= temp,retreg,r0 /* if so, the denominator is power of 2 */ + b,n LREF(regular_seq) + sub r0,arg0,retreg /* negate numerator */ + comb,=,n arg0,retreg,LREF(regular_seq) /* test against 0x80000000 */ + copy retreg,arg0 /* set up arg0, arg1 and temp */ + copy temp,arg1 /* before branching to pow2 */ + b LREF(pow2) + ldo -1(arg1),temp +LSYM(regular_seq) + comib,>>=,n 15,arg1,LREF(small_divisor) + add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */ +LSYM(normal) + subi 0,retreg,retreg /* make it positive */ + sub 0,arg1,temp /* clear carry, */ + /* negate the divisor */ + ds 0,temp,0 /* set V-bit to the comple- */ + /* ment of the divisor sign */ + add retreg,retreg,retreg /* shift msb bit into carry */ + ds r0,arg1,temp /* 1st divide step, if no carry */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 32nd divide step, */ + addc retreg,retreg,retreg /* shift last retreg bit into retreg */ + xor,>= arg0,arg1,0 /* get correct sign of quotient */ + sub 0,retreg,retreg /* based on operand signs */ + MILLIRETN + nop + +LSYM(small_divisor) + +#if defined(CONFIG_64BIT) +/* Clear the upper 32 bits of the arg1 register. We are working with */ +/* small divisors (and 32-bit integers) We must not be mislead */ +/* by "1" bits left in the upper 32 bits. */ + depd %r0,31,32,%r25 +#endif + blr,n arg1,r0 + nop +/* table for divisor == 0,1, ... ,15 */ + addit,= 0,arg1,r0 /* trap if divisor == 0 */ + nop + MILLIRET /* divisor == 1 */ + copy arg0,retreg + MILLI_BEN($$divI_2) /* divisor == 2 */ + nop + MILLI_BEN($$divI_3) /* divisor == 3 */ + nop + MILLI_BEN($$divI_4) /* divisor == 4 */ + nop + MILLI_BEN($$divI_5) /* divisor == 5 */ + nop + MILLI_BEN($$divI_6) /* divisor == 6 */ + nop + MILLI_BEN($$divI_7) /* divisor == 7 */ + nop + MILLI_BEN($$divI_8) /* divisor == 8 */ + nop + MILLI_BEN($$divI_9) /* divisor == 9 */ + nop + MILLI_BEN($$divI_10) /* divisor == 10 */ + nop + b LREF(normal) /* divisor == 11 */ + add,>= 0,arg0,retreg + MILLI_BEN($$divI_12) /* divisor == 12 */ + nop + b LREF(normal) /* divisor == 13 */ + add,>= 0,arg0,retreg + MILLI_BEN($$divI_14) /* divisor == 14 */ + nop + MILLI_BEN($$divI_15) /* divisor == 15 */ + nop + +LSYM(negative1) + sub 0,arg0,retreg /* result is negation of dividend */ + MILLIRET + addo arg0,arg1,r0 /* trap iff dividend==0x80000000 && divisor==-1 */ + .exit + .procend + .end +#endif + +#ifdef L_divU +/* ROUTINE: $$divU + . + . Single precision divide for unsigned integers. + . + . Quotient is truncated towards zero. + . Traps on divide by zero. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: + . divisor is zero + . Changes memory at the following places: + . NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Branchs to other millicode routines using BE: + . $$divU_# for 3,5,6,7,9,10,12,14,15 + . + . For selected small divisors calls the special divide by constant + . routines written by Karl Pettis. These are: 3,5,6,7,9,10,12,14,15. */ + +RDEFINE(temp,r1) +RDEFINE(retreg,ret1) /* r29 */ +RDEFINE(temp1,arg0) + SUBSPA_MILLI_DIV + ATTR_MILLI + .export $$divU,millicode + .import $$divU_3,millicode + .import $$divU_5,millicode + .import $$divU_6,millicode + .import $$divU_7,millicode + .import $$divU_9,millicode + .import $$divU_10,millicode + .import $$divU_12,millicode + .import $$divU_14,millicode + .import $$divU_15,millicode + .proc + .callinfo millicode + .entry +GSYM($$divU) +/* The subtract is not nullified since it does no harm and can be used + by the two cases that branch back to "normal". */ + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,= arg1,temp,r0 /* if so, denominator is power of 2 */ + b LREF(regular_seq) + addit,= 0,arg1,0 /* trap for zero dvr */ + copy arg0,retreg + extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */ + extru retreg,15,16,retreg /* retreg = retreg >> 16 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */ + ldi 0xcc,temp1 /* setup 0xcc in temp1 */ + extru,= arg1,23,8,temp /* test denominator with 0xff00 */ + extru retreg,23,24,retreg /* retreg = retreg >> 8 */ + or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */ + ldi 0xaa,temp /* setup 0xaa in temp */ + extru,= arg1,27,4,r0 /* test denominator with 0xf0 */ + extru retreg,27,28,retreg /* retreg = retreg >> 4 */ + and,= arg1,temp1,r0 /* test denominator with 0xcc */ + extru retreg,29,30,retreg /* retreg = retreg >> 2 */ + and,= arg1,temp,r0 /* test denominator with 0xaa */ + extru retreg,30,31,retreg /* retreg = retreg >> 1 */ + MILLIRETN + nop +LSYM(regular_seq) + comib,>= 15,arg1,LREF(special_divisor) + subi 0,arg1,temp /* clear carry, negate the divisor */ + ds r0,temp,r0 /* set V-bit to 1 */ +LSYM(normal) + add arg0,arg0,retreg /* shift msb bit into carry */ + ds r0,arg1,temp /* 1st divide step, if no carry */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds temp,arg1,temp /* 32nd divide step, */ + MILLIRET + addc retreg,retreg,retreg /* shift last retreg bit into retreg */ + +/* Handle the cases where divisor is a small constant or has high bit on. */ +LSYM(special_divisor) +/* blr arg1,r0 */ +/* comib,>,n 0,arg1,LREF(big_divisor) ; nullify previous instruction */ + +/* Pratap 8/13/90. The 815 Stirling chip set has a bug that prevents us from + generating such a blr, comib sequence. A problem in nullification. So I + rewrote this code. */ + +#if defined(CONFIG_64BIT) +/* Clear the upper 32 bits of the arg1 register. We are working with + small divisors (and 32-bit unsigned integers) We must not be mislead + by "1" bits left in the upper 32 bits. */ + depd %r0,31,32,%r25 +#endif + comib,> 0,arg1,LREF(big_divisor) + nop + blr arg1,r0 + nop + +LSYM(zero_divisor) /* this label is here to provide external visibility */ + addit,= 0,arg1,0 /* trap for zero dvr */ + nop + MILLIRET /* divisor == 1 */ + copy arg0,retreg + MILLIRET /* divisor == 2 */ + extru arg0,30,31,retreg + MILLI_BEN($$divU_3) /* divisor == 3 */ + nop + MILLIRET /* divisor == 4 */ + extru arg0,29,30,retreg + MILLI_BEN($$divU_5) /* divisor == 5 */ + nop + MILLI_BEN($$divU_6) /* divisor == 6 */ + nop + MILLI_BEN($$divU_7) /* divisor == 7 */ + nop + MILLIRET /* divisor == 8 */ + extru arg0,28,29,retreg + MILLI_BEN($$divU_9) /* divisor == 9 */ + nop + MILLI_BEN($$divU_10) /* divisor == 10 */ + nop + b LREF(normal) /* divisor == 11 */ + ds r0,temp,r0 /* set V-bit to 1 */ + MILLI_BEN($$divU_12) /* divisor == 12 */ + nop + b LREF(normal) /* divisor == 13 */ + ds r0,temp,r0 /* set V-bit to 1 */ + MILLI_BEN($$divU_14) /* divisor == 14 */ + nop + MILLI_BEN($$divU_15) /* divisor == 15 */ + nop + +/* Handle the case where the high bit is on in the divisor. + Compute: if( dividend>=divisor) quotient=1; else quotient=0; + Note: dividend>==divisor iff dividend-divisor does not borrow + and not borrow iff carry. */ +LSYM(big_divisor) + sub arg0,arg1,r0 + MILLIRET + addc r0,r0,retreg + .exit + .procend + .end +#endif + +#ifdef L_remI +/* ROUTINE: $$remI + + DESCRIPTION: + . $$remI returns the remainder of the division of two signed 32-bit + . integers. The sign of the remainder is the same as the sign of + . the dividend. + + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = destroyed + . arg1 = destroyed + . ret1 = remainder + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: DIVIDE BY ZERO + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable + . Does not create a stack frame + . Is usable for internal or external microcode + + DISCUSSION: + . Calls other millicode routines via mrp: NONE + . Calls other millicode routines: NONE */ + +RDEFINE(tmp,r1) +RDEFINE(retreg,ret1) + + SUBSPA_MILLI + ATTR_MILLI + .proc + .callinfo millicode + .entry +GSYM($$remI) +GSYM($$remoI) + .export $$remI,MILLICODE + .export $$remoI,MILLICODE + ldo -1(arg1),tmp /* is there at most one bit set ? */ + and,<> arg1,tmp,r0 /* if not, don't use power of 2 */ + addi,> 0,arg1,r0 /* if denominator > 0, use power */ + /* of 2 */ + b,n LREF(neg_denom) +LSYM(pow2) + comb,>,n 0,arg0,LREF(neg_num) /* is numerator < 0 ? */ + and arg0,tmp,retreg /* get the result */ + MILLIRETN +LSYM(neg_num) + subi 0,arg0,arg0 /* negate numerator */ + and arg0,tmp,retreg /* get the result */ + subi 0,retreg,retreg /* negate result */ + MILLIRETN +LSYM(neg_denom) + addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power */ + /* of 2 */ + b,n LREF(regular_seq) + sub r0,arg1,tmp /* make denominator positive */ + comb,=,n arg1,tmp,LREF(regular_seq) /* test against 0x80000000 and 0 */ + ldo -1(tmp),retreg /* is there at most one bit set ? */ + and,= tmp,retreg,r0 /* if not, go to regular_seq */ + b,n LREF(regular_seq) + comb,>,n 0,arg0,LREF(neg_num_2) /* if arg0 < 0, negate it */ + and arg0,retreg,retreg + MILLIRETN +LSYM(neg_num_2) + subi 0,arg0,tmp /* test against 0x80000000 */ + and tmp,retreg,retreg + subi 0,retreg,retreg + MILLIRETN +LSYM(regular_seq) + addit,= 0,arg1,0 /* trap if div by zero */ + add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */ + sub 0,retreg,retreg /* make it positive */ + sub 0,arg1, tmp /* clear carry, */ + /* negate the divisor */ + ds 0, tmp,0 /* set V-bit to the comple- */ + /* ment of the divisor sign */ + or 0,0, tmp /* clear tmp */ + add retreg,retreg,retreg /* shift msb bit into carry */ + ds tmp,arg1, tmp /* 1st divide step, if no carry */ + /* out, msb of quotient = 0 */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ +LSYM(t1) + ds tmp,arg1, tmp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 32nd divide step, */ + addc retreg,retreg,retreg /* shift last bit into retreg */ + movb,>=,n tmp,retreg,LREF(finish) /* branch if pos. tmp */ + add,< arg1,0,0 /* if arg1 > 0, add arg1 */ + add,tr tmp,arg1,retreg /* for correcting remainder tmp */ + sub tmp,arg1,retreg /* else add absolute value arg1 */ +LSYM(finish) + add,>= arg0,0,0 /* set sign of remainder */ + sub 0,retreg,retreg /* to sign of dividend */ + MILLIRET + nop + .exit + .procend +#ifdef milliext + .origin 0x00000200 +#endif + .end +#endif + +#ifdef L_remU +/* ROUTINE: $$remU + . Single precision divide for remainder with unsigned binary integers. + . + . The remainder must be dividend-(dividend/divisor)*divisor. + . Divide by zero is trapped. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = remainder + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: DIVIDE BY ZERO + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Calls other millicode routines using mrp: NONE + . Calls other millicode routines: NONE */ + + +RDEFINE(temp,r1) +RDEFINE(rmndr,ret1) /* r29 */ + SUBSPA_MILLI + ATTR_MILLI + .export $$remU,millicode + .proc + .callinfo millicode + .entry +GSYM($$remU) + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,= arg1,temp,r0 /* if not, don't use power of 2 */ + b LREF(regular_seq) + addit,= 0,arg1,r0 /* trap on div by zero */ + and arg0,temp,rmndr /* get the result for power of 2 */ + MILLIRETN +LSYM(regular_seq) + comib,>=,n 0,arg1,LREF(special_case) + subi 0,arg1,rmndr /* clear carry, negate the divisor */ + ds r0,rmndr,r0 /* set V-bit to 1 */ + add arg0,arg0,temp /* shift msb bit into carry */ + ds r0,arg1,rmndr /* 1st divide step, if no carry */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 2nd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 3rd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 4th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 5th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 6th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 7th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 8th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 9th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 10th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 11th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 12th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 13th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 14th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 15th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 16th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 17th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 18th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 19th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 20th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 21st divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 22nd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 23rd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 24th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 25th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 26th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 27th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 28th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 29th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 30th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 31st divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 32nd divide step, */ + comiclr,<= 0,rmndr,r0 + add rmndr,arg1,rmndr /* correction */ + MILLIRETN + nop + +/* Putting >= on the last DS and deleting COMICLR does not work! */ +LSYM(special_case) + sub,>>= arg0,arg1,rmndr + copy arg0,rmndr + MILLIRETN + nop + .exit + .procend + .end +#endif + +#ifdef L_div_const +/* ROUTINE: $$divI_2 + . $$divI_3 $$divU_3 + . $$divI_4 + . $$divI_5 $$divU_5 + . $$divI_6 $$divU_6 + . $$divI_7 $$divU_7 + . $$divI_8 + . $$divI_9 $$divU_9 + . $$divI_10 $$divU_10 + . + . $$divI_12 $$divU_12 + . + . $$divI_14 $$divU_14 + . $$divI_15 $$divU_15 + . $$divI_16 + . $$divI_17 $$divU_17 + . + . Divide by selected constants for single precision binary integers. + + INPUT REGISTERS: + . arg0 == dividend + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = quotient + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: NONE + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Calls other millicode routines using mrp: NONE + . Calls other millicode routines: NONE */ + + +/* TRUNCATED DIVISION BY SMALL INTEGERS + + We are interested in q(x) = floor(x/y), where x >= 0 and y > 0 + (with y fixed). + + Let a = floor(z/y), for some choice of z. Note that z will be + chosen so that division by z is cheap. + + Let r be the remainder(z/y). In other words, r = z - ay. + + Now, our method is to choose a value for b such that + + q'(x) = floor((ax+b)/z) + + is equal to q(x) over as large a range of x as possible. If the + two are equal over a sufficiently large range, and if it is easy to + form the product (ax), and it is easy to divide by z, then we can + perform the division much faster than the general division algorithm. + + So, we want the following to be true: + + . For x in the following range: + . + . ky <= x < (k+1)y + . + . implies that + . + . k <= (ax+b)/z < (k+1) + + We want to determine b such that this is true for all k in the + range {0..K} for some maximum K. + + Since (ax+b) is an increasing function of x, we can take each + bound separately to determine the "best" value for b. + + (ax+b)/z < (k+1) implies + + (a((k+1)y-1)+b < (k+1)z implies + + b < a + (k+1)(z-ay) implies + + b < a + (k+1)r + + This needs to be true for all k in the range {0..K}. In + particular, it is true for k = 0 and this leads to a maximum + acceptable value for b. + + b < a+r or b <= a+r-1 + + Taking the other bound, we have + + k <= (ax+b)/z implies + + k <= (aky+b)/z implies + + k(z-ay) <= b implies + + kr <= b + + Clearly, the largest range for k will be achieved by maximizing b, + when r is not zero. When r is zero, then the simplest choice for b + is 0. When r is not 0, set + + . b = a+r-1 + + Now, by construction, q'(x) = floor((ax+b)/z) = q(x) = floor(x/y) + for all x in the range: + + . 0 <= x < (K+1)y + + We need to determine what K is. Of our two bounds, + + . b < a+(k+1)r is satisfied for all k >= 0, by construction. + + The other bound is + + . kr <= b + + This is always true if r = 0. If r is not 0 (the usual case), then + K = floor((a+r-1)/r), is the maximum value for k. + + Therefore, the formula q'(x) = floor((ax+b)/z) yields the correct + answer for q(x) = floor(x/y) when x is in the range + + (0,(K+1)y-1) K = floor((a+r-1)/r) + + To be most useful, we want (K+1)y-1 = (max x) >= 2**32-1 so that + the formula for q'(x) yields the correct value of q(x) for all x + representable by a single word in HPPA. + + We are also constrained in that computing the product (ax), adding + b, and dividing by z must all be done quickly, otherwise we will be + better off going through the general algorithm using the DS + instruction, which uses approximately 70 cycles. + + For each y, there is a choice of z which satisfies the constraints + for (K+1)y >= 2**32. We may not, however, be able to satisfy the + timing constraints for arbitrary y. It seems that z being equal to + a power of 2 or a power of 2 minus 1 is as good as we can do, since + it minimizes the time to do division by z. We want the choice of z + to also result in a value for (a) that minimizes the computation of + the product (ax). This is best achieved if (a) has a regular bit + pattern (so the multiplication can be done with shifts and adds). + The value of (a) also needs to be less than 2**32 so the product is + always guaranteed to fit in 2 words. + + In actual practice, the following should be done: + + 1) For negative x, you should take the absolute value and remember + . the fact so that the result can be negated. This obviously does + . not apply in the unsigned case. + 2) For even y, you should factor out the power of 2 that divides y + . and divide x by it. You can then proceed by dividing by the + . odd factor of y. + + Here is a table of some odd values of y, and corresponding choices + for z which are "good". + + y z r a (hex) max x (hex) + + 3 2**32 1 55555555 100000001 + 5 2**32 1 33333333 100000003 + 7 2**24-1 0 249249 (infinite) + 9 2**24-1 0 1c71c7 (infinite) + 11 2**20-1 0 1745d (infinite) + 13 2**24-1 0 13b13b (infinite) + 15 2**32 1 11111111 10000000d + 17 2**32 1 f0f0f0f 10000000f + + If r is 1, then b = a+r-1 = a. This simplifies the computation + of (ax+b), since you can compute (x+1)(a) instead. If r is 0, + then b = 0 is ok to use which simplifies (ax+b). + + The bit patterns for 55555555, 33333333, and 11111111 are obviously + very regular. The bit patterns for the other values of a above are: + + y (hex) (binary) + + 7 249249 001001001001001001001001 << regular >> + 9 1c71c7 000111000111000111000111 << regular >> + 11 1745d 000000010111010001011101 << irregular >> + 13 13b13b 000100111011000100111011 << irregular >> + + The bit patterns for (a) corresponding to (y) of 11 and 13 may be + too irregular to warrant using this method. + + When z is a power of 2 minus 1, then the division by z is slightly + more complicated, involving an iterative solution. + + The code presented here solves division by 1 through 17, except for + 11 and 13. There are algorithms for both signed and unsigned + quantities given. + + TIMINGS (cycles) + + divisor positive negative unsigned + + . 1 2 2 2 + . 2 4 4 2 + . 3 19 21 19 + . 4 4 4 2 + . 5 18 22 19 + . 6 19 22 19 + . 8 4 4 2 + . 10 18 19 17 + . 12 18 20 18 + . 15 16 18 16 + . 16 4 4 2 + . 17 16 18 16 + + Now, the algorithm for 7, 9, and 14 is an iterative one. That is, + a loop body is executed until the tentative quotient is 0. The + number of times the loop body is executed varies depending on the + dividend, but is never more than two times. If the dividend is + less than the divisor, then the loop body is not executed at all. + Each iteration adds 4 cycles to the timings. + + divisor positive negative unsigned + + . 7 19+4n 20+4n 20+4n n = number of iterations + . 9 21+4n 22+4n 21+4n + . 14 21+4n 22+4n 20+4n + + To give an idea of how the number of iterations varies, here is a + table of dividend versus number of iterations when dividing by 7. + + smallest largest required + dividend dividend iterations + + . 0 6 0 + . 7 0x6ffffff 1 + 0x1000006 0xffffffff 2 + + There is some overlap in the range of numbers requiring 1 and 2 + iterations. */ + +RDEFINE(t2,r1) +RDEFINE(x2,arg0) /* r26 */ +RDEFINE(t1,arg1) /* r25 */ +RDEFINE(x1,ret1) /* r29 */ + + SUBSPA_MILLI_DIV + ATTR_MILLI + + .proc + .callinfo millicode + .entry +/* NONE of these routines require a stack frame + ALL of these routines are unwindable from millicode */ + +GSYM($$divide_by_constant) + .export $$divide_by_constant,millicode +/* Provides a "nice" label for the code covered by the unwind descriptor + for things like gprof. */ + +/* DIVISION BY 2 (shift by 1) */ +GSYM($$divI_2) + .export $$divI_2,millicode + comclr,>= arg0,0,0 + addi 1,arg0,arg0 + MILLIRET + extrs arg0,30,31,ret1 + + +/* DIVISION BY 4 (shift by 2) */ +GSYM($$divI_4) + .export $$divI_4,millicode + comclr,>= arg0,0,0 + addi 3,arg0,arg0 + MILLIRET + extrs arg0,29,30,ret1 + + +/* DIVISION BY 8 (shift by 3) */ +GSYM($$divI_8) + .export $$divI_8,millicode + comclr,>= arg0,0,0 + addi 7,arg0,arg0 + MILLIRET + extrs arg0,28,29,ret1 + +/* DIVISION BY 16 (shift by 4) */ +GSYM($$divI_16) + .export $$divI_16,millicode + comclr,>= arg0,0,0 + addi 15,arg0,arg0 + MILLIRET + extrs arg0,27,28,ret1 + +/**************************************************************************** +* +* DIVISION BY DIVISORS OF FFFFFFFF, and powers of 2 times these +* +* includes 3,5,15,17 and also 6,10,12 +* +****************************************************************************/ + +/* DIVISION BY 3 (use z = 2**32; a = 55555555) */ + +GSYM($$divI_3) + .export $$divI_3,millicode + comb,<,N x2,0,LREF(neg3) + + addi 1,x2,x2 /* this cannot overflow */ + extru x2,1,2,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,0,x1 + +LSYM(neg3) + subi 1,x2,x2 /* this cannot overflow */ + extru x2,1,2,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_3) + .export $$divU_3,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,30,t1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,t1,x1 + +/* DIVISION BY 5 (use z = 2**32; a = 33333333) */ + +GSYM($$divI_5) + .export $$divI_5,millicode + comb,<,N x2,0,LREF(neg5) + + addi 3,x2,t1 /* this cannot overflow */ + sh1add x2,t1,x2 /* multiply by 3 to get started */ + b LREF(pos) + addc 0,0,x1 + +LSYM(neg5) + sub 0,x2,x2 /* negate x2 */ + addi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,31,x1 /* get top bit (can be 1) */ + sh1add x2,x2,x2 /* multiply by 3 to get started */ + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_5) + .export $$divU_5,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,31,t1 /* multiply by 3 to get started */ + sh1add x2,x2,x2 + b LREF(pos) + addc t1,x1,x1 + +/* DIVISION BY 6 (shift to divide by 2 then divide by 3) */ +GSYM($$divI_6) + .export $$divI_6,millicode + comb,<,N x2,0,LREF(neg6) + extru x2,30,31,x2 /* divide by 2 */ + addi 5,x2,t1 /* compute 5*(x2+1) = 5*x2+5 */ + sh2add x2,t1,x2 /* multiply by 5 to get started */ + b LREF(pos) + addc 0,0,x1 + +LSYM(neg6) + subi 2,x2,x2 /* negate, divide by 2, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,30,31,x2 + shd 0,x2,30,x1 + sh2add x2,x2,x2 /* multiply by 5 to get started */ + b LREF(neg) + addc x1,0,x1 + +GSYM($$divU_6) + .export $$divU_6,millicode + extru x2,30,31,x2 /* divide by 2 */ + addi 1,x2,x2 /* cannot carry */ + shd 0,x2,30,x1 /* multiply by 5 to get started */ + sh2add x2,x2,x2 + b LREF(pos) + addc x1,0,x1 + +/* DIVISION BY 10 (shift to divide by 2 then divide by 5) */ +GSYM($$divU_10) + .export $$divU_10,millicode + extru x2,30,31,x2 /* divide by 2 */ + addi 3,x2,t1 /* compute 3*(x2+1) = (3*x2)+3 */ + sh1add x2,t1,x2 /* multiply by 3 to get started */ + addc 0,0,x1 +LSYM(pos) + shd x1,x2,28,t1 /* multiply by 0x11 */ + shd x2,0,28,t2 + add x2,t2,x2 + addc x1,t1,x1 +LSYM(pos_for_17) + shd x1,x2,24,t1 /* multiply by 0x101 */ + shd x2,0,24,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,16,t1 /* multiply by 0x10001 */ + shd x2,0,16,t2 + add x2,t2,x2 + MILLIRET + addc x1,t1,x1 + +GSYM($$divI_10) + .export $$divI_10,millicode + comb,< x2,0,LREF(neg10) + copy 0,x1 + extru x2,30,31,x2 /* divide by 2 */ + addib,TR 1,x2,LREF(pos) /* add 1 (cannot overflow) */ + sh1add x2,x2,x2 /* multiply by 3 to get started */ + +LSYM(neg10) + subi 2,x2,x2 /* negate, divide by 2, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,30,31,x2 + sh1add x2,x2,x2 /* multiply by 3 to get started */ +LSYM(neg) + shd x1,x2,28,t1 /* multiply by 0x11 */ + shd x2,0,28,t2 + add x2,t2,x2 + addc x1,t1,x1 +LSYM(neg_for_17) + shd x1,x2,24,t1 /* multiply by 0x101 */ + shd x2,0,24,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,16,t1 /* multiply by 0x10001 */ + shd x2,0,16,t2 + add x2,t2,x2 + addc x1,t1,x1 + MILLIRET + sub 0,x1,x1 + +/* DIVISION BY 12 (shift to divide by 4 then divide by 3) */ +GSYM($$divI_12) + .export $$divI_12,millicode + comb,< x2,0,LREF(neg12) + copy 0,x1 + extru x2,29,30,x2 /* divide by 4 */ + addib,tr 1,x2,LREF(pos) /* compute 5*(x2+1) = 5*x2+5 */ + sh2add x2,x2,x2 /* multiply by 5 to get started */ + +LSYM(neg12) + subi 4,x2,x2 /* negate, divide by 4, and add 1 */ + /* negation and adding 1 are done */ + /* at the same time by the SUBI */ + extru x2,29,30,x2 + b LREF(neg) + sh2add x2,x2,x2 /* multiply by 5 to get started */ + +GSYM($$divU_12) + .export $$divU_12,millicode + extru x2,29,30,x2 /* divide by 4 */ + addi 5,x2,t1 /* cannot carry */ + sh2add x2,t1,x2 /* multiply by 5 to get started */ + b LREF(pos) + addc 0,0,x1 + +/* DIVISION BY 15 (use z = 2**32; a = 11111111) */ +GSYM($$divI_15) + .export $$divI_15,millicode + comb,< x2,0,LREF(neg15) + copy 0,x1 + addib,tr 1,x2,LREF(pos)+4 + shd x1,x2,28,t1 + +LSYM(neg15) + b LREF(neg) + subi 1,x2,x2 + +GSYM($$divU_15) + .export $$divU_15,millicode + addi 1,x2,x2 /* this CAN overflow */ + b LREF(pos) + addc 0,0,x1 + +/* DIVISION BY 17 (use z = 2**32; a = f0f0f0f) */ +GSYM($$divI_17) + .export $$divI_17,millicode + comb,<,n x2,0,LREF(neg17) + addi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,28,t1 /* multiply by 0xf to get started */ + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(pos_for_17) + subb t1,0,x1 + +LSYM(neg17) + subi 1,x2,x2 /* this cannot overflow */ + shd 0,x2,28,t1 /* multiply by 0xf to get started */ + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(neg_for_17) + subb t1,0,x1 + +GSYM($$divU_17) + .export $$divU_17,millicode + addi 1,x2,x2 /* this CAN overflow */ + addc 0,0,x1 + shd x1,x2,28,t1 /* multiply by 0xf to get started */ +LSYM(u17) + shd x2,0,28,t2 + sub t2,x2,x2 + b LREF(pos_for_17) + subb t1,x1,x1 + + +/* DIVISION BY DIVISORS OF FFFFFF, and powers of 2 times these + includes 7,9 and also 14 + + + z = 2**24-1 + r = z mod x = 0 + + so choose b = 0 + + Also, in order to divide by z = 2**24-1, we approximate by dividing + by (z+1) = 2**24 (which is easy), and then correcting. + + (ax) = (z+1)q' + r + . = zq' + (q'+r) + + So to compute (ax)/z, compute q' = (ax)/(z+1) and r = (ax) mod (z+1) + Then the true remainder of (ax)/z is (q'+r). Repeat the process + with this new remainder, adding the tentative quotients together, + until a tentative quotient is 0 (and then we are done). There is + one last correction to be done. It is possible that (q'+r) = z. + If so, then (q'+r)/(z+1) = 0 and it looks like we are done. But, + in fact, we need to add 1 more to the quotient. Now, it turns + out that this happens if and only if the original value x is + an exact multiple of y. So, to avoid a three instruction test at + the end, instead use 1 instruction to add 1 to x at the beginning. */ + +/* DIVISION BY 7 (use z = 2**24-1; a = 249249) */ +GSYM($$divI_7) + .export $$divI_7,millicode + comb,<,n x2,0,LREF(neg7) +LSYM(7) + addi 1,x2,x2 /* cannot overflow */ + shd 0,x2,29,x1 + sh3add x2,x2,x2 + addc x1,0,x1 +LSYM(pos7) + shd x1,x2,26,t1 + shd x2,0,26,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,20,t1 + shd x2,0,20,t2 + add x2,t2,x2 + addc x1,t1,t1 + + /* computed <t1,x2>. Now divide it by (2**24 - 1) */ + + copy 0,x1 + shd,= t1,x2,24,t1 /* tentative quotient */ +LSYM(1) + addb,tr t1,x1,LREF(2) /* add to previous quotient */ + extru x2,31,24,x2 /* new remainder (unadjusted) */ + + MILLIRETN + +LSYM(2) + addb,tr t1,x2,LREF(1) /* adjust remainder */ + extru,= x2,7,8,t1 /* new quotient */ + +LSYM(neg7) + subi 1,x2,x2 /* negate x2 and add 1 */ +LSYM(8) + shd 0,x2,29,x1 + sh3add x2,x2,x2 + addc x1,0,x1 + +LSYM(neg7_shift) + shd x1,x2,26,t1 + shd x2,0,26,t2 + add x2,t2,x2 + addc x1,t1,x1 + + shd x1,x2,20,t1 + shd x2,0,20,t2 + add x2,t2,x2 + addc x1,t1,t1 + + /* computed <t1,x2>. Now divide it by (2**24 - 1) */ + + copy 0,x1 + shd,= t1,x2,24,t1 /* tentative quotient */ +LSYM(3) + addb,tr t1,x1,LREF(4) /* add to previous quotient */ + extru x2,31,24,x2 /* new remainder (unadjusted) */ + + MILLIRET + sub 0,x1,x1 /* negate result */ + +LSYM(4) + addb,tr t1,x2,LREF(3) /* adjust remainder */ + extru,= x2,7,8,t1 /* new quotient */ + +GSYM($$divU_7) + .export $$divU_7,millicode + addi 1,x2,x2 /* can carry */ + addc 0,0,x1 + shd x1,x2,29,t1 + sh3add x2,x2,x2 + b LREF(pos7) + addc t1,x1,x1 + +/* DIVISION BY 9 (use z = 2**24-1; a = 1c71c7) */ +GSYM($$divI_9) + .export $$divI_9,millicode + comb,<,n x2,0,LREF(neg9) + addi 1,x2,x2 /* cannot overflow */ + shd 0,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(pos7) + subb t1,0,x1 + +LSYM(neg9) + subi 1,x2,x2 /* negate and add 1 */ + shd 0,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(neg7_shift) + subb t1,0,x1 + +GSYM($$divU_9) + .export $$divU_9,millicode + addi 1,x2,x2 /* can carry */ + addc 0,0,x1 + shd x1,x2,29,t1 + shd x2,0,29,t2 + sub t2,x2,x2 + b LREF(pos7) + subb t1,x1,x1 + +/* DIVISION BY 14 (shift to divide by 2 then divide by 7) */ +GSYM($$divI_14) + .export $$divI_14,millicode + comb,<,n x2,0,LREF(neg14) +GSYM($$divU_14) + .export $$divU_14,millicode + b LREF(7) /* go to 7 case */ + extru x2,30,31,x2 /* divide by 2 */ + +LSYM(neg14) + subi 2,x2,x2 /* negate (and add 2) */ + b LREF(8) + extru x2,30,31,x2 /* divide by 2 */ + .exit + .procend + .end +#endif + +#ifdef L_mulI +/* VERSION "@(#)$$mulI $ Revision: 12.4 $ $ Date: 94/03/17 17:18:51 $" */ +/****************************************************************************** +This routine is used on PA2.0 processors when gcc -mno-fpregs is used + +ROUTINE: $$mulI + + +DESCRIPTION: + + $$mulI multiplies two single word integers, giving a single + word result. + + +INPUT REGISTERS: + + arg0 = Operand 1 + arg1 = Operand 2 + r31 == return pc + sr0 == return space when called externally + + +OUTPUT REGISTERS: + + arg0 = undefined + arg1 = undefined + ret1 = result + +OTHER REGISTERS AFFECTED: + + r1 = undefined + +SIDE EFFECTS: + + Causes a trap under the following conditions: NONE + Changes memory at the following places: NONE + +PERMISSIBLE CONTEXT: + + Unwindable + Does not create a stack frame + Is usable for internal or external microcode + +DISCUSSION: + + Calls other millicode routines via mrp: NONE + Calls other millicode routines: NONE + +***************************************************************************/ + + +#define a0 %arg0 +#define a1 %arg1 +#define t0 %r1 +#define r %ret1 + +#define a0__128a0 zdep a0,24,25,a0 +#define a0__256a0 zdep a0,23,24,a0 +#define a1_ne_0_b_l0 comb,<> a1,0,LREF(l0) +#define a1_ne_0_b_l1 comb,<> a1,0,LREF(l1) +#define a1_ne_0_b_l2 comb,<> a1,0,LREF(l2) +#define b_n_ret_t0 b,n LREF(ret_t0) +#define b_e_shift b LREF(e_shift) +#define b_e_t0ma0 b LREF(e_t0ma0) +#define b_e_t0 b LREF(e_t0) +#define b_e_t0a0 b LREF(e_t0a0) +#define b_e_t02a0 b LREF(e_t02a0) +#define b_e_t04a0 b LREF(e_t04a0) +#define b_e_2t0 b LREF(e_2t0) +#define b_e_2t0a0 b LREF(e_2t0a0) +#define b_e_2t04a0 b LREF(e2t04a0) +#define b_e_3t0 b LREF(e_3t0) +#define b_e_4t0 b LREF(e_4t0) +#define b_e_4t0a0 b LREF(e_4t0a0) +#define b_e_4t08a0 b LREF(e4t08a0) +#define b_e_5t0 b LREF(e_5t0) +#define b_e_8t0 b LREF(e_8t0) +#define b_e_8t0a0 b LREF(e_8t0a0) +#define r__r_a0 add r,a0,r +#define r__r_2a0 sh1add a0,r,r +#define r__r_4a0 sh2add a0,r,r +#define r__r_8a0 sh3add a0,r,r +#define r__r_t0 add r,t0,r +#define r__r_2t0 sh1add t0,r,r +#define r__r_4t0 sh2add t0,r,r +#define r__r_8t0 sh3add t0,r,r +#define t0__3a0 sh1add a0,a0,t0 +#define t0__4a0 sh2add a0,0,t0 +#define t0__5a0 sh2add a0,a0,t0 +#define t0__8a0 sh3add a0,0,t0 +#define t0__9a0 sh3add a0,a0,t0 +#define t0__16a0 zdep a0,27,28,t0 +#define t0__32a0 zdep a0,26,27,t0 +#define t0__64a0 zdep a0,25,26,t0 +#define t0__128a0 zdep a0,24,25,t0 +#define t0__t0ma0 sub t0,a0,t0 +#define t0__t0_a0 add t0,a0,t0 +#define t0__t0_2a0 sh1add a0,t0,t0 +#define t0__t0_4a0 sh2add a0,t0,t0 +#define t0__t0_8a0 sh3add a0,t0,t0 +#define t0__2t0_a0 sh1add t0,a0,t0 +#define t0__3t0 sh1add t0,t0,t0 +#define t0__4t0 sh2add t0,0,t0 +#define t0__4t0_a0 sh2add t0,a0,t0 +#define t0__5t0 sh2add t0,t0,t0 +#define t0__8t0 sh3add t0,0,t0 +#define t0__8t0_a0 sh3add t0,a0,t0 +#define t0__9t0 sh3add t0,t0,t0 +#define t0__16t0 zdep t0,27,28,t0 +#define t0__32t0 zdep t0,26,27,t0 +#define t0__256a0 zdep a0,23,24,t0 + + + SUBSPA_MILLI + ATTR_MILLI + .align 16 + .proc + .callinfo millicode + .export $$mulI,millicode +GSYM($$mulI) + combt,<<= a1,a0,LREF(l4) /* swap args if unsigned a1>a0 */ + copy 0,r /* zero out the result */ + xor a0,a1,a0 /* swap a0 & a1 using the */ + xor a0,a1,a1 /* old xor trick */ + xor a0,a1,a0 +LSYM(l4) + combt,<= 0,a0,LREF(l3) /* if a0>=0 then proceed like unsigned */ + zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */ + sub,> 0,a1,t0 /* otherwise negate both and */ + combt,<=,n a0,t0,LREF(l2) /* swap back if |a0|<|a1| */ + sub 0,a0,a1 + movb,tr,n t0,a0,LREF(l2) /* 10th inst. */ + +LSYM(l0) r__r_t0 /* add in this partial product */ +LSYM(l1) a0__256a0 /* a0 <<= 8 ****************** */ +LSYM(l2) zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */ +LSYM(l3) blr t0,0 /* case on these 8 bits ****** */ + extru a1,23,24,a1 /* a1 >>= 8 ****************** */ + +/*16 insts before this. */ +/* a0 <<= 8 ************************** */ +LSYM(x0) a1_ne_0_b_l2 ! a0__256a0 ! MILLIRETN ! nop +LSYM(x1) a1_ne_0_b_l1 ! r__r_a0 ! MILLIRETN ! nop +LSYM(x2) a1_ne_0_b_l1 ! r__r_2a0 ! MILLIRETN ! nop +LSYM(x3) a1_ne_0_b_l0 ! t0__3a0 ! MILLIRET ! r__r_t0 +LSYM(x4) a1_ne_0_b_l1 ! r__r_4a0 ! MILLIRETN ! nop +LSYM(x5) a1_ne_0_b_l0 ! t0__5a0 ! MILLIRET ! r__r_t0 +LSYM(x6) t0__3a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x7) t0__3a0 ! a1_ne_0_b_l0 ! r__r_4a0 ! b_n_ret_t0 +LSYM(x8) a1_ne_0_b_l1 ! r__r_8a0 ! MILLIRETN ! nop +LSYM(x9) a1_ne_0_b_l0 ! t0__9a0 ! MILLIRET ! r__r_t0 +LSYM(x10) t0__5a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x11) t0__3a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0 +LSYM(x12) t0__3a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x13) t0__5a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0 +LSYM(x14) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x15) t0__5a0 ! a1_ne_0_b_l0 ! t0__3t0 ! b_n_ret_t0 +LSYM(x16) t0__16a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x17) t0__9a0 ! a1_ne_0_b_l0 ! t0__t0_8a0 ! b_n_ret_t0 +LSYM(x18) t0__9a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x19) t0__9a0 ! a1_ne_0_b_l0 ! t0__2t0_a0 ! b_n_ret_t0 +LSYM(x20) t0__5a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x21) t0__5a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x22) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x23) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x24) t0__3a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x25) t0__5a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0 +LSYM(x26) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x27) t0__3a0 ! a1_ne_0_b_l0 ! t0__9t0 ! b_n_ret_t0 +LSYM(x28) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x29) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x30) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_2t0 +LSYM(x31) t0__32a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x32) t0__32a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x33) t0__8a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x34) t0__16a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x35) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__t0_8a0 +LSYM(x36) t0__9a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x37) t0__9a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x38) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x39) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x40) t0__5a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x41) t0__5a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0 +LSYM(x42) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x43) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x44) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x45) t0__9a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0 +LSYM(x46) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_a0 +LSYM(x47) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x48) t0__3a0 ! a1_ne_0_b_l0 ! t0__16t0 ! b_n_ret_t0 +LSYM(x49) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_4a0 +LSYM(x50) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_2t0 +LSYM(x51) t0__9a0 ! t0__t0_8a0 ! b_e_t0 ! t0__3t0 +LSYM(x52) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x53) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x54) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_2t0 +LSYM(x55) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x56) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x57) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x58) t0__3a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x59) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x60) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x61) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x62) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x63) t0__64a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x64) t0__64a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x65) t0__8a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0 +LSYM(x66) t0__32a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x67) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x68) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x69) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x70) t0__64a0 ! t0__t0_4a0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x71) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x72) t0__9a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x73) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_t0 +LSYM(x74) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x75) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x76) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x77) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x78) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x79) t0__16a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x80) t0__16a0 ! t0__5t0 ! b_e_shift ! r__r_t0 +LSYM(x81) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_t0 +LSYM(x82) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x83) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x84) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x85) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x86) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x87) t0__9a0 ! t0__9t0 ! b_e_t02a0 ! t0__t0_4a0 +LSYM(x88) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x89) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x90) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_2t0 +LSYM(x91) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x92) t0__5a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x93) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__3t0 +LSYM(x94) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__t0_2a0 +LSYM(x95) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x96) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x97) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x98) t0__32a0 ! t0__3t0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x99) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x100) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_4t0 +LSYM(x101) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x102) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0 +LSYM(x103) t0__5a0 ! t0__5t0 ! b_e_t02a0 ! t0__4t0_a0 +LSYM(x104) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x105) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x106) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x107) t0__9a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__8t0_a0 +LSYM(x108) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x109) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x110) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x111) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x112) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__16t0 +LSYM(x113) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x114) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x115) t0__9a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x116) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x117) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x118) t0__3a0 ! t0__4t0_a0 ! b_e_t0a0 ! t0__9t0 +LSYM(x119) t0__3a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__9t0 +LSYM(x120) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x121) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x122) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x123) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x124) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0 +LSYM(x125) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__5t0 +LSYM(x126) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x127) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x128) t0__128a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x129) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0_a0 ! b_n_ret_t0 +LSYM(x130) t0__64a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x131) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x132) t0__8a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x133) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x134) t0__8a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x135) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__3t0 +LSYM(x136) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x137) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x138) t0__8a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x139) t0__8a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__4t0_a0 +LSYM(x140) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__5t0 +LSYM(x141) t0__8a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x142) t0__9a0 ! t0__8t0 ! b_e_2t0 ! t0__t0ma0 +LSYM(x143) t0__16a0 ! t0__9t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x144) t0__9a0 ! t0__8t0 ! b_e_shift ! r__r_2t0 +LSYM(x145) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x146) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x147) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x148) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x149) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x150) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x151) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x152) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x153) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x154) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x155) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__5t0 +LSYM(x156) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x157) t0__32a0 ! t0__t0ma0 ! b_e_t02a0 ! t0__5t0 +LSYM(x158) t0__16a0 ! t0__5t0 ! b_e_2t0 ! t0__t0ma0 +LSYM(x159) t0__32a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x160) t0__5a0 ! t0__4t0 ! b_e_shift ! r__r_8t0 +LSYM(x161) t0__8a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x162) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_2t0 +LSYM(x163) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x164) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x165) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x166) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x167) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x168) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x169) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x170) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__5t0 +LSYM(x171) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x172) t0__5a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x173) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__9t0 +LSYM(x174) t0__32a0 ! t0__t0_2a0 ! b_e_t04a0 ! t0__5t0 +LSYM(x175) t0__8a0 ! t0__2t0_a0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x176) t0__5a0 ! t0__4t0_a0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x177) t0__5a0 ! t0__4t0_a0 ! b_e_8t0a0 ! t0__t0_a0 +LSYM(x178) t0__5a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__8t0_a0 +LSYM(x179) t0__5a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__8t0_a0 +LSYM(x180) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_4t0 +LSYM(x181) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x182) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x183) t0__9a0 ! t0__5t0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x184) t0__5a0 ! t0__9t0 ! b_e_4t0 ! t0__t0_a0 +LSYM(x185) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x186) t0__32a0 ! t0__t0ma0 ! b_e_2t0 ! t0__3t0 +LSYM(x187) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__5t0 +LSYM(x188) t0__9a0 ! t0__5t0 ! b_e_4t0 ! t0__t0_2a0 +LSYM(x189) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x190) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__5t0 +LSYM(x191) t0__64a0 ! t0__3t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x192) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x193) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x194) t0__8a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x195) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x196) t0__8a0 ! t0__3t0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x197) t0__8a0 ! t0__3t0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x198) t0__64a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0 +LSYM(x199) t0__8a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x200) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_8t0 +LSYM(x201) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x202) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x203) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__4t0_a0 +LSYM(x204) t0__8a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0 +LSYM(x205) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x206) t0__64a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x207) t0__8a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0 +LSYM(x208) t0__5a0 ! t0__5t0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x209) t0__5a0 ! t0__5t0 ! b_e_8t0a0 ! t0__t0_a0 +LSYM(x210) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__5t0 +LSYM(x211) t0__5a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__5t0 +LSYM(x212) t0__3a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x213) t0__3a0 ! t0__4t0_a0 ! b_e_4t0a0 ! t0__4t0_a0 +LSYM(x214) t0__9a0 ! t0__t0_4a0 ! b_e_2t04a0 ! t0__8t0_a0 +LSYM(x215) t0__5a0 ! t0__4t0_a0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x216) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x217) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x218) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x219) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x220) t0__3a0 ! t0__9t0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x221) t0__3a0 ! t0__9t0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x222) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x223) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x224) t0__9a0 ! t0__3t0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x225) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__5t0 +LSYM(x226) t0__3a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__32t0 +LSYM(x227) t0__9a0 ! t0__5t0 ! b_e_t02a0 ! t0__5t0 +LSYM(x228) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0 +LSYM(x229) t0__9a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__3t0 +LSYM(x230) t0__9a0 ! t0__5t0 ! b_e_5t0 ! t0__t0_a0 +LSYM(x231) t0__9a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0 +LSYM(x232) t0__3a0 ! t0__2t0_a0 ! b_e_8t0 ! t0__4t0_a0 +LSYM(x233) t0__3a0 ! t0__2t0_a0 ! b_e_8t0a0 ! t0__4t0_a0 +LSYM(x234) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__9t0 +LSYM(x235) t0__3a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__9t0 +LSYM(x236) t0__9a0 ! t0__2t0_a0 ! b_e_4t08a0 ! t0__3t0 +LSYM(x237) t0__16a0 ! t0__5t0 ! b_e_3t0 ! t0__t0ma0 +LSYM(x238) t0__3a0 ! t0__4t0_a0 ! b_e_2t04a0 ! t0__9t0 +LSYM(x239) t0__16a0 ! t0__5t0 ! b_e_t0ma0 ! t0__3t0 +LSYM(x240) t0__9a0 ! t0__t0_a0 ! b_e_8t0 ! t0__3t0 +LSYM(x241) t0__9a0 ! t0__t0_a0 ! b_e_8t0a0 ! t0__3t0 +LSYM(x242) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__8t0_a0 +LSYM(x243) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__3t0 +LSYM(x244) t0__5a0 ! t0__3t0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x245) t0__8a0 ! t0__3t0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x246) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x247) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x248) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_8t0 +LSYM(x249) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x250) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__5t0 +LSYM(x251) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__5t0 +LSYM(x252) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0 +LSYM(x253) t0__64a0 ! t0__t0ma0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x254) t0__128a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x255) t0__256a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +/*1040 insts before this. */ +LSYM(ret_t0) MILLIRET +LSYM(e_t0) r__r_t0 +LSYM(e_shift) a1_ne_0_b_l2 + a0__256a0 /* a0 <<= 8 *********** */ + MILLIRETN +LSYM(e_t0ma0) a1_ne_0_b_l0 + t0__t0ma0 + MILLIRET + r__r_t0 +LSYM(e_t0a0) a1_ne_0_b_l0 + t0__t0_a0 + MILLIRET + r__r_t0 +LSYM(e_t02a0) a1_ne_0_b_l0 + t0__t0_2a0 + MILLIRET + r__r_t0 +LSYM(e_t04a0) a1_ne_0_b_l0 + t0__t0_4a0 + MILLIRET + r__r_t0 +LSYM(e_2t0) a1_ne_0_b_l1 + r__r_2t0 + MILLIRETN +LSYM(e_2t0a0) a1_ne_0_b_l0 + t0__2t0_a0 + MILLIRET + r__r_t0 +LSYM(e2t04a0) t0__t0_2a0 + a1_ne_0_b_l1 + r__r_2t0 + MILLIRETN +LSYM(e_3t0) a1_ne_0_b_l0 + t0__3t0 + MILLIRET + r__r_t0 +LSYM(e_4t0) a1_ne_0_b_l1 + r__r_4t0 + MILLIRETN +LSYM(e_4t0a0) a1_ne_0_b_l0 + t0__4t0_a0 + MILLIRET + r__r_t0 +LSYM(e4t08a0) t0__t0_2a0 + a1_ne_0_b_l1 + r__r_4t0 + MILLIRETN +LSYM(e_5t0) a1_ne_0_b_l0 + t0__5t0 + MILLIRET + r__r_t0 +LSYM(e_8t0) a1_ne_0_b_l1 + r__r_8t0 + MILLIRETN +LSYM(e_8t0a0) a1_ne_0_b_l0 + t0__8t0_a0 + MILLIRET + r__r_t0 + + .procend + .end +#endif diff --git a/arch/parisc/lib/milli/milli.h b/arch/parisc/lib/milli/milli.h new file mode 100644 index 00000000000..19ac79f336d --- /dev/null +++ b/arch/parisc/lib/milli/milli.h @@ -0,0 +1,165 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame <bame@debian.org> + and Alan Modra <alan@linuxcare.com.au>. + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#ifndef _PA_MILLI_H_ +#define _PA_MILLI_H_ + +#define L_dyncall +#define L_divI +#define L_divU +#define L_remI +#define L_remU +#define L_div_const +#define L_mulI + +#ifdef CONFIG_64BIT + .level 2.0w +#endif + +/* Hardware General Registers. */ +r0: .reg %r0 +r1: .reg %r1 +r2: .reg %r2 +r3: .reg %r3 +r4: .reg %r4 +r5: .reg %r5 +r6: .reg %r6 +r7: .reg %r7 +r8: .reg %r8 +r9: .reg %r9 +r10: .reg %r10 +r11: .reg %r11 +r12: .reg %r12 +r13: .reg %r13 +r14: .reg %r14 +r15: .reg %r15 +r16: .reg %r16 +r17: .reg %r17 +r18: .reg %r18 +r19: .reg %r19 +r20: .reg %r20 +r21: .reg %r21 +r22: .reg %r22 +r23: .reg %r23 +r24: .reg %r24 +r25: .reg %r25 +r26: .reg %r26 +r27: .reg %r27 +r28: .reg %r28 +r29: .reg %r29 +r30: .reg %r30 +r31: .reg %r31 + +/* Hardware Space Registers. */ +sr0: .reg %sr0 +sr1: .reg %sr1 +sr2: .reg %sr2 +sr3: .reg %sr3 +sr4: .reg %sr4 +sr5: .reg %sr5 +sr6: .reg %sr6 +sr7: .reg %sr7 + +/* Hardware Floating Point Registers. */ +fr0: .reg %fr0 +fr1: .reg %fr1 +fr2: .reg %fr2 +fr3: .reg %fr3 +fr4: .reg %fr4 +fr5: .reg %fr5 +fr6: .reg %fr6 +fr7: .reg %fr7 +fr8: .reg %fr8 +fr9: .reg %fr9 +fr10: .reg %fr10 +fr11: .reg %fr11 +fr12: .reg %fr12 +fr13: .reg %fr13 +fr14: .reg %fr14 +fr15: .reg %fr15 + +/* Hardware Control Registers. */ +cr11: .reg %cr11 +sar: .reg %cr11 /* Shift Amount Register */ + +/* Software Architecture General Registers. */ +rp: .reg r2 /* return pointer */ +#ifdef CONFIG_64BIT +mrp: .reg r2 /* millicode return pointer */ +#else +mrp: .reg r31 /* millicode return pointer */ +#endif +ret0: .reg r28 /* return value */ +ret1: .reg r29 /* return value (high part of double) */ +sp: .reg r30 /* stack pointer */ +dp: .reg r27 /* data pointer */ +arg0: .reg r26 /* argument */ +arg1: .reg r25 /* argument or high part of double argument */ +arg2: .reg r24 /* argument */ +arg3: .reg r23 /* argument or high part of double argument */ + +/* Software Architecture Space Registers. */ +/* sr0 ; return link from BLE */ +sret: .reg sr1 /* return value */ +sarg: .reg sr1 /* argument */ +/* sr4 ; PC SPACE tracker */ +/* sr5 ; process private data */ + +/* Frame Offsets (millicode convention!) Used when calling other + millicode routines. Stack unwinding is dependent upon these + definitions. */ +r31_slot: .equ -20 /* "current RP" slot */ +sr0_slot: .equ -16 /* "static link" slot */ +#if defined(CONFIG_64BIT) +mrp_slot: .equ -16 /* "current RP" slot */ +psp_slot: .equ -8 /* "previous SP" slot */ +#else +mrp_slot: .equ -20 /* "current RP" slot (replacing "r31_slot") */ +#endif + + +#define DEFINE(name,value)name: .EQU value +#define RDEFINE(name,value)name: .REG value +#ifdef milliext +#define MILLI_BE(lbl) BE lbl(sr7,r0) +#define MILLI_BEN(lbl) BE,n lbl(sr7,r0) +#define MILLI_BLE(lbl) BLE lbl(sr7,r0) +#define MILLI_BLEN(lbl) BLE,n lbl(sr7,r0) +#define MILLIRETN BE,n 0(sr0,mrp) +#define MILLIRET BE 0(sr0,mrp) +#define MILLI_RETN BE,n 0(sr0,mrp) +#define MILLI_RET BE 0(sr0,mrp) +#else +#define MILLI_BE(lbl) B lbl +#define MILLI_BEN(lbl) B,n lbl +#define MILLI_BLE(lbl) BL lbl,mrp +#define MILLI_BLEN(lbl) BL,n lbl,mrp +#define MILLIRETN BV,n 0(mrp) +#define MILLIRET BV 0(mrp) +#define MILLI_RETN BV,n 0(mrp) +#define MILLI_RET BV 0(mrp) +#endif + +#define CAT(a,b) a##b + +#define SUBSPA_MILLI .section .text +#define SUBSPA_MILLI_DIV .section .text.div,"ax",@progbits! .align 16 +#define SUBSPA_MILLI_MUL .section .text.mul,"ax",@progbits! .align 16 +#define ATTR_MILLI +#define SUBSPA_DATA .section .data +#define ATTR_DATA +#define GLOBAL $global$ +#define GSYM(sym) !sym: +#define LSYM(sym) !CAT(.L,sym:) +#define LREF(sym) CAT(.L,sym) + +#endif /*_PA_MILLI_H_*/ diff --git a/arch/parisc/lib/milli/mulI.S b/arch/parisc/lib/milli/mulI.S new file mode 100644 index 00000000000..4c7e0c36d15 --- /dev/null +++ b/arch/parisc/lib/milli/mulI.S @@ -0,0 +1,474 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame <bame@debian.org> + and Alan Modra <alan@linuxcare.com.au>. + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_mulI +/* VERSION "@(#)$$mulI $ Revision: 12.4 $ $ Date: 94/03/17 17:18:51 $" */ +/****************************************************************************** +This routine is used on PA2.0 processors when gcc -mno-fpregs is used + +ROUTINE: $$mulI + + +DESCRIPTION: + + $$mulI multiplies two single word integers, giving a single + word result. + + +INPUT REGISTERS: + + arg0 = Operand 1 + arg1 = Operand 2 + r31 == return pc + sr0 == return space when called externally + + +OUTPUT REGISTERS: + + arg0 = undefined + arg1 = undefined + ret1 = result + +OTHER REGISTERS AFFECTED: + + r1 = undefined + +SIDE EFFECTS: + + Causes a trap under the following conditions: NONE + Changes memory at the following places: NONE + +PERMISSIBLE CONTEXT: + + Unwindable + Does not create a stack frame + Is usable for internal or external microcode + +DISCUSSION: + + Calls other millicode routines via mrp: NONE + Calls other millicode routines: NONE + +***************************************************************************/ + + +#define a0 %arg0 +#define a1 %arg1 +#define t0 %r1 +#define r %ret1 + +#define a0__128a0 zdep a0,24,25,a0 +#define a0__256a0 zdep a0,23,24,a0 +#define a1_ne_0_b_l0 comb,<> a1,0,LREF(l0) +#define a1_ne_0_b_l1 comb,<> a1,0,LREF(l1) +#define a1_ne_0_b_l2 comb,<> a1,0,LREF(l2) +#define b_n_ret_t0 b,n LREF(ret_t0) +#define b_e_shift b LREF(e_shift) +#define b_e_t0ma0 b LREF(e_t0ma0) +#define b_e_t0 b LREF(e_t0) +#define b_e_t0a0 b LREF(e_t0a0) +#define b_e_t02a0 b LREF(e_t02a0) +#define b_e_t04a0 b LREF(e_t04a0) +#define b_e_2t0 b LREF(e_2t0) +#define b_e_2t0a0 b LREF(e_2t0a0) +#define b_e_2t04a0 b LREF(e2t04a0) +#define b_e_3t0 b LREF(e_3t0) +#define b_e_4t0 b LREF(e_4t0) +#define b_e_4t0a0 b LREF(e_4t0a0) +#define b_e_4t08a0 b LREF(e4t08a0) +#define b_e_5t0 b LREF(e_5t0) +#define b_e_8t0 b LREF(e_8t0) +#define b_e_8t0a0 b LREF(e_8t0a0) +#define r__r_a0 add r,a0,r +#define r__r_2a0 sh1add a0,r,r +#define r__r_4a0 sh2add a0,r,r +#define r__r_8a0 sh3add a0,r,r +#define r__r_t0 add r,t0,r +#define r__r_2t0 sh1add t0,r,r +#define r__r_4t0 sh2add t0,r,r +#define r__r_8t0 sh3add t0,r,r +#define t0__3a0 sh1add a0,a0,t0 +#define t0__4a0 sh2add a0,0,t0 +#define t0__5a0 sh2add a0,a0,t0 +#define t0__8a0 sh3add a0,0,t0 +#define t0__9a0 sh3add a0,a0,t0 +#define t0__16a0 zdep a0,27,28,t0 +#define t0__32a0 zdep a0,26,27,t0 +#define t0__64a0 zdep a0,25,26,t0 +#define t0__128a0 zdep a0,24,25,t0 +#define t0__t0ma0 sub t0,a0,t0 +#define t0__t0_a0 add t0,a0,t0 +#define t0__t0_2a0 sh1add a0,t0,t0 +#define t0__t0_4a0 sh2add a0,t0,t0 +#define t0__t0_8a0 sh3add a0,t0,t0 +#define t0__2t0_a0 sh1add t0,a0,t0 +#define t0__3t0 sh1add t0,t0,t0 +#define t0__4t0 sh2add t0,0,t0 +#define t0__4t0_a0 sh2add t0,a0,t0 +#define t0__5t0 sh2add t0,t0,t0 +#define t0__8t0 sh3add t0,0,t0 +#define t0__8t0_a0 sh3add t0,a0,t0 +#define t0__9t0 sh3add t0,t0,t0 +#define t0__16t0 zdep t0,27,28,t0 +#define t0__32t0 zdep t0,26,27,t0 +#define t0__256a0 zdep a0,23,24,t0 + + + SUBSPA_MILLI + ATTR_MILLI + .align 16 + .proc + .callinfo millicode + .export $$mulI,millicode +GSYM($$mulI) + combt,<<= a1,a0,LREF(l4) /* swap args if unsigned a1>a0 */ + copy 0,r /* zero out the result */ + xor a0,a1,a0 /* swap a0 & a1 using the */ + xor a0,a1,a1 /* old xor trick */ + xor a0,a1,a0 +LSYM(l4) + combt,<= 0,a0,LREF(l3) /* if a0>=0 then proceed like unsigned */ + zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */ + sub,> 0,a1,t0 /* otherwise negate both and */ + combt,<=,n a0,t0,LREF(l2) /* swap back if |a0|<|a1| */ + sub 0,a0,a1 + movb,tr,n t0,a0,LREF(l2) /* 10th inst. */ + +LSYM(l0) r__r_t0 /* add in this partial product */ +LSYM(l1) a0__256a0 /* a0 <<= 8 ****************** */ +LSYM(l2) zdep a1,30,8,t0 /* t0 = (a1&0xff)<<1 ********* */ +LSYM(l3) blr t0,0 /* case on these 8 bits ****** */ + extru a1,23,24,a1 /* a1 >>= 8 ****************** */ + +/*16 insts before this. */ +/* a0 <<= 8 ************************** */ +LSYM(x0) a1_ne_0_b_l2 ! a0__256a0 ! MILLIRETN ! nop +LSYM(x1) a1_ne_0_b_l1 ! r__r_a0 ! MILLIRETN ! nop +LSYM(x2) a1_ne_0_b_l1 ! r__r_2a0 ! MILLIRETN ! nop +LSYM(x3) a1_ne_0_b_l0 ! t0__3a0 ! MILLIRET ! r__r_t0 +LSYM(x4) a1_ne_0_b_l1 ! r__r_4a0 ! MILLIRETN ! nop +LSYM(x5) a1_ne_0_b_l0 ! t0__5a0 ! MILLIRET ! r__r_t0 +LSYM(x6) t0__3a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x7) t0__3a0 ! a1_ne_0_b_l0 ! r__r_4a0 ! b_n_ret_t0 +LSYM(x8) a1_ne_0_b_l1 ! r__r_8a0 ! MILLIRETN ! nop +LSYM(x9) a1_ne_0_b_l0 ! t0__9a0 ! MILLIRET ! r__r_t0 +LSYM(x10) t0__5a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x11) t0__3a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0 +LSYM(x12) t0__3a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x13) t0__5a0 ! a1_ne_0_b_l0 ! r__r_8a0 ! b_n_ret_t0 +LSYM(x14) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x15) t0__5a0 ! a1_ne_0_b_l0 ! t0__3t0 ! b_n_ret_t0 +LSYM(x16) t0__16a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x17) t0__9a0 ! a1_ne_0_b_l0 ! t0__t0_8a0 ! b_n_ret_t0 +LSYM(x18) t0__9a0 ! a1_ne_0_b_l1 ! r__r_2t0 ! MILLIRETN +LSYM(x19) t0__9a0 ! a1_ne_0_b_l0 ! t0__2t0_a0 ! b_n_ret_t0 +LSYM(x20) t0__5a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x21) t0__5a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x22) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x23) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x24) t0__3a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x25) t0__5a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0 +LSYM(x26) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x27) t0__3a0 ! a1_ne_0_b_l0 ! t0__9t0 ! b_n_ret_t0 +LSYM(x28) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x29) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x30) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_2t0 +LSYM(x31) t0__32a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x32) t0__32a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x33) t0__8a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x34) t0__16a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x35) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__t0_8a0 +LSYM(x36) t0__9a0 ! a1_ne_0_b_l1 ! r__r_4t0 ! MILLIRETN +LSYM(x37) t0__9a0 ! a1_ne_0_b_l0 ! t0__4t0_a0 ! b_n_ret_t0 +LSYM(x38) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x39) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x40) t0__5a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x41) t0__5a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0 +LSYM(x42) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x43) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x44) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x45) t0__9a0 ! a1_ne_0_b_l0 ! t0__5t0 ! b_n_ret_t0 +LSYM(x46) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_a0 +LSYM(x47) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x48) t0__3a0 ! a1_ne_0_b_l0 ! t0__16t0 ! b_n_ret_t0 +LSYM(x49) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__t0_4a0 +LSYM(x50) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_2t0 +LSYM(x51) t0__9a0 ! t0__t0_8a0 ! b_e_t0 ! t0__3t0 +LSYM(x52) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x53) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x54) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_2t0 +LSYM(x55) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x56) t0__3a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x57) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x58) t0__3a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x59) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x60) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x61) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x62) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x63) t0__64a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x64) t0__64a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x65) t0__8a0 ! a1_ne_0_b_l0 ! t0__8t0_a0 ! b_n_ret_t0 +LSYM(x66) t0__32a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x67) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x68) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x69) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x70) t0__64a0 ! t0__t0_4a0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x71) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x72) t0__9a0 ! a1_ne_0_b_l1 ! r__r_8t0 ! MILLIRETN +LSYM(x73) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_t0 +LSYM(x74) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x75) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x76) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x77) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x78) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x79) t0__16a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x80) t0__16a0 ! t0__5t0 ! b_e_shift ! r__r_t0 +LSYM(x81) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_t0 +LSYM(x82) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x83) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x84) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x85) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x86) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x87) t0__9a0 ! t0__9t0 ! b_e_t02a0 ! t0__t0_4a0 +LSYM(x88) t0__5a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x89) t0__5a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x90) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_2t0 +LSYM(x91) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x92) t0__5a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x93) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__3t0 +LSYM(x94) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__t0_2a0 +LSYM(x95) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x96) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x97) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x98) t0__32a0 ! t0__3t0 ! b_e_t0 ! t0__t0_2a0 +LSYM(x99) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x100) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_4t0 +LSYM(x101) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x102) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0 +LSYM(x103) t0__5a0 ! t0__5t0 ! b_e_t02a0 ! t0__4t0_a0 +LSYM(x104) t0__3a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x105) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x106) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x107) t0__9a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__8t0_a0 +LSYM(x108) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_4t0 +LSYM(x109) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x110) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x111) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x112) t0__3a0 ! t0__2t0_a0 ! b_e_t0 ! t0__16t0 +LSYM(x113) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x114) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x115) t0__9a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x116) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x117) t0__3a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x118) t0__3a0 ! t0__4t0_a0 ! b_e_t0a0 ! t0__9t0 +LSYM(x119) t0__3a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__9t0 +LSYM(x120) t0__5a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x121) t0__5a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x122) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x123) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x124) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0 +LSYM(x125) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__5t0 +LSYM(x126) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x127) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +LSYM(x128) t0__128a0 ! a1_ne_0_b_l1 ! r__r_t0 ! MILLIRETN +LSYM(x129) t0__128a0 ! a1_ne_0_b_l0 ! t0__t0_a0 ! b_n_ret_t0 +LSYM(x130) t0__64a0 ! t0__t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x131) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x132) t0__8a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x133) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x134) t0__8a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x135) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__3t0 +LSYM(x136) t0__8a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x137) t0__8a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x138) t0__8a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x139) t0__8a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__4t0_a0 +LSYM(x140) t0__3a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__5t0 +LSYM(x141) t0__8a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x142) t0__9a0 ! t0__8t0 ! b_e_2t0 ! t0__t0ma0 +LSYM(x143) t0__16a0 ! t0__9t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x144) t0__9a0 ! t0__8t0 ! b_e_shift ! r__r_2t0 +LSYM(x145) t0__9a0 ! t0__8t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x146) t0__9a0 ! t0__8t0_a0 ! b_e_shift ! r__r_2t0 +LSYM(x147) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x148) t0__9a0 ! t0__4t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x149) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x150) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x151) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x152) t0__9a0 ! t0__2t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x153) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x154) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x155) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__5t0 +LSYM(x156) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x157) t0__32a0 ! t0__t0ma0 ! b_e_t02a0 ! t0__5t0 +LSYM(x158) t0__16a0 ! t0__5t0 ! b_e_2t0 ! t0__t0ma0 +LSYM(x159) t0__32a0 ! t0__5t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x160) t0__5a0 ! t0__4t0 ! b_e_shift ! r__r_8t0 +LSYM(x161) t0__8a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x162) t0__9a0 ! t0__9t0 ! b_e_shift ! r__r_2t0 +LSYM(x163) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__2t0_a0 +LSYM(x164) t0__5a0 ! t0__8t0_a0 ! b_e_shift ! r__r_4t0 +LSYM(x165) t0__8a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x166) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x167) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x168) t0__5a0 ! t0__4t0_a0 ! b_e_shift ! r__r_8t0 +LSYM(x169) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x170) t0__32a0 ! t0__t0_2a0 ! b_e_t0 ! t0__5t0 +LSYM(x171) t0__9a0 ! t0__2t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x172) t0__5a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x173) t0__9a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__9t0 +LSYM(x174) t0__32a0 ! t0__t0_2a0 ! b_e_t04a0 ! t0__5t0 +LSYM(x175) t0__8a0 ! t0__2t0_a0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x176) t0__5a0 ! t0__4t0_a0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x177) t0__5a0 ! t0__4t0_a0 ! b_e_8t0a0 ! t0__t0_a0 +LSYM(x178) t0__5a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__8t0_a0 +LSYM(x179) t0__5a0 ! t0__2t0_a0 ! b_e_2t0a0 ! t0__8t0_a0 +LSYM(x180) t0__9a0 ! t0__5t0 ! b_e_shift ! r__r_4t0 +LSYM(x181) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x182) t0__9a0 ! t0__5t0 ! b_e_2t0 ! t0__2t0_a0 +LSYM(x183) t0__9a0 ! t0__5t0 ! b_e_2t0a0 ! t0__2t0_a0 +LSYM(x184) t0__5a0 ! t0__9t0 ! b_e_4t0 ! t0__t0_a0 +LSYM(x185) t0__9a0 ! t0__4t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x186) t0__32a0 ! t0__t0ma0 ! b_e_2t0 ! t0__3t0 +LSYM(x187) t0__9a0 ! t0__4t0_a0 ! b_e_t02a0 ! t0__5t0 +LSYM(x188) t0__9a0 ! t0__5t0 ! b_e_4t0 ! t0__t0_2a0 +LSYM(x189) t0__5a0 ! t0__4t0_a0 ! b_e_t0 ! t0__9t0 +LSYM(x190) t0__9a0 ! t0__2t0_a0 ! b_e_2t0 ! t0__5t0 +LSYM(x191) t0__64a0 ! t0__3t0 ! b_e_t0 ! t0__t0ma0 +LSYM(x192) t0__8a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x193) t0__8a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x194) t0__8a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x195) t0__8a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x196) t0__8a0 ! t0__3t0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x197) t0__8a0 ! t0__3t0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x198) t0__64a0 ! t0__t0_2a0 ! b_e_t0 ! t0__3t0 +LSYM(x199) t0__8a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x200) t0__5a0 ! t0__5t0 ! b_e_shift ! r__r_8t0 +LSYM(x201) t0__5a0 ! t0__5t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x202) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x203) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__4t0_a0 +LSYM(x204) t0__8a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0 +LSYM(x205) t0__5a0 ! t0__8t0_a0 ! b_e_t0 ! t0__5t0 +LSYM(x206) t0__64a0 ! t0__t0_4a0 ! b_e_t02a0 ! t0__3t0 +LSYM(x207) t0__8a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0 +LSYM(x208) t0__5a0 ! t0__5t0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x209) t0__5a0 ! t0__5t0 ! b_e_8t0a0 ! t0__t0_a0 +LSYM(x210) t0__5a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__5t0 +LSYM(x211) t0__5a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__5t0 +LSYM(x212) t0__3a0 ! t0__4t0_a0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x213) t0__3a0 ! t0__4t0_a0 ! b_e_4t0a0 ! t0__4t0_a0 +LSYM(x214) t0__9a0 ! t0__t0_4a0 ! b_e_2t04a0 ! t0__8t0_a0 +LSYM(x215) t0__5a0 ! t0__4t0_a0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x216) t0__9a0 ! t0__3t0 ! b_e_shift ! r__r_8t0 +LSYM(x217) t0__9a0 ! t0__3t0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x218) t0__9a0 ! t0__3t0 ! b_e_2t0 ! t0__4t0_a0 +LSYM(x219) t0__9a0 ! t0__8t0_a0 ! b_e_t0 ! t0__3t0 +LSYM(x220) t0__3a0 ! t0__9t0 ! b_e_4t0 ! t0__2t0_a0 +LSYM(x221) t0__3a0 ! t0__9t0 ! b_e_4t0a0 ! t0__2t0_a0 +LSYM(x222) t0__9a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x223) t0__9a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x224) t0__9a0 ! t0__3t0 ! b_e_8t0 ! t0__t0_a0 +LSYM(x225) t0__9a0 ! t0__5t0 ! b_e_t0 ! t0__5t0 +LSYM(x226) t0__3a0 ! t0__2t0_a0 ! b_e_t02a0 ! t0__32t0 +LSYM(x227) t0__9a0 ! t0__5t0 ! b_e_t02a0 ! t0__5t0 +LSYM(x228) t0__9a0 ! t0__2t0_a0 ! b_e_4t0 ! t0__3t0 +LSYM(x229) t0__9a0 ! t0__2t0_a0 ! b_e_4t0a0 ! t0__3t0 +LSYM(x230) t0__9a0 ! t0__5t0 ! b_e_5t0 ! t0__t0_a0 +LSYM(x231) t0__9a0 ! t0__2t0_a0 ! b_e_3t0 ! t0__4t0_a0 +LSYM(x232) t0__3a0 ! t0__2t0_a0 ! b_e_8t0 ! t0__4t0_a0 +LSYM(x233) t0__3a0 ! t0__2t0_a0 ! b_e_8t0a0 ! t0__4t0_a0 +LSYM(x234) t0__3a0 ! t0__4t0_a0 ! b_e_2t0 ! t0__9t0 +LSYM(x235) t0__3a0 ! t0__4t0_a0 ! b_e_2t0a0 ! t0__9t0 +LSYM(x236) t0__9a0 ! t0__2t0_a0 ! b_e_4t08a0 ! t0__3t0 +LSYM(x237) t0__16a0 ! t0__5t0 ! b_e_3t0 ! t0__t0ma0 +LSYM(x238) t0__3a0 ! t0__4t0_a0 ! b_e_2t04a0 ! t0__9t0 +LSYM(x239) t0__16a0 ! t0__5t0 ! b_e_t0ma0 ! t0__3t0 +LSYM(x240) t0__9a0 ! t0__t0_a0 ! b_e_8t0 ! t0__3t0 +LSYM(x241) t0__9a0 ! t0__t0_a0 ! b_e_8t0a0 ! t0__3t0 +LSYM(x242) t0__5a0 ! t0__3t0 ! b_e_2t0 ! t0__8t0_a0 +LSYM(x243) t0__9a0 ! t0__9t0 ! b_e_t0 ! t0__3t0 +LSYM(x244) t0__5a0 ! t0__3t0 ! b_e_4t0 ! t0__4t0_a0 +LSYM(x245) t0__8a0 ! t0__3t0 ! b_e_5t0 ! t0__2t0_a0 +LSYM(x246) t0__5a0 ! t0__8t0_a0 ! b_e_2t0 ! t0__3t0 +LSYM(x247) t0__5a0 ! t0__8t0_a0 ! b_e_2t0a0 ! t0__3t0 +LSYM(x248) t0__32a0 ! t0__t0ma0 ! b_e_shift ! r__r_8t0 +LSYM(x249) t0__32a0 ! t0__t0ma0 ! b_e_t0 ! t0__8t0_a0 +LSYM(x250) t0__5a0 ! t0__5t0 ! b_e_2t0 ! t0__5t0 +LSYM(x251) t0__5a0 ! t0__5t0 ! b_e_2t0a0 ! t0__5t0 +LSYM(x252) t0__64a0 ! t0__t0ma0 ! b_e_shift ! r__r_4t0 +LSYM(x253) t0__64a0 ! t0__t0ma0 ! b_e_t0 ! t0__4t0_a0 +LSYM(x254) t0__128a0 ! t0__t0ma0 ! b_e_shift ! r__r_2t0 +LSYM(x255) t0__256a0 ! a1_ne_0_b_l0 ! t0__t0ma0 ! b_n_ret_t0 +/*1040 insts before this. */ +LSYM(ret_t0) MILLIRET +LSYM(e_t0) r__r_t0 +LSYM(e_shift) a1_ne_0_b_l2 + a0__256a0 /* a0 <<= 8 *********** */ + MILLIRETN +LSYM(e_t0ma0) a1_ne_0_b_l0 + t0__t0ma0 + MILLIRET + r__r_t0 +LSYM(e_t0a0) a1_ne_0_b_l0 + t0__t0_a0 + MILLIRET + r__r_t0 +LSYM(e_t02a0) a1_ne_0_b_l0 + t0__t0_2a0 + MILLIRET + r__r_t0 +LSYM(e_t04a0) a1_ne_0_b_l0 + t0__t0_4a0 + MILLIRET + r__r_t0 +LSYM(e_2t0) a1_ne_0_b_l1 + r__r_2t0 + MILLIRETN +LSYM(e_2t0a0) a1_ne_0_b_l0 + t0__2t0_a0 + MILLIRET + r__r_t0 +LSYM(e2t04a0) t0__t0_2a0 + a1_ne_0_b_l1 + r__r_2t0 + MILLIRETN +LSYM(e_3t0) a1_ne_0_b_l0 + t0__3t0 + MILLIRET + r__r_t0 +LSYM(e_4t0) a1_ne_0_b_l1 + r__r_4t0 + MILLIRETN +LSYM(e_4t0a0) a1_ne_0_b_l0 + t0__4t0_a0 + MILLIRET + r__r_t0 +LSYM(e4t08a0) t0__t0_2a0 + a1_ne_0_b_l1 + r__r_4t0 + MILLIRETN +LSYM(e_5t0) a1_ne_0_b_l0 + t0__5t0 + MILLIRET + r__r_t0 +LSYM(e_8t0) a1_ne_0_b_l1 + r__r_8t0 + MILLIRETN +LSYM(e_8t0a0) a1_ne_0_b_l0 + t0__8t0_a0 + MILLIRET + r__r_t0 + + .procend + .end +#endif diff --git a/arch/parisc/lib/milli/remI.S b/arch/parisc/lib/milli/remI.S new file mode 100644 index 00000000000..63bc094471e --- /dev/null +++ b/arch/parisc/lib/milli/remI.S @@ -0,0 +1,185 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame <bame@debian.org> + and Alan Modra <alan@linuxcare.com.au>. + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_remI +/* ROUTINE: $$remI + + DESCRIPTION: + . $$remI returns the remainder of the division of two signed 32-bit + . integers. The sign of the remainder is the same as the sign of + . the dividend. + + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = destroyed + . arg1 = destroyed + . ret1 = remainder + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: DIVIDE BY ZERO + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable + . Does not create a stack frame + . Is usable for internal or external microcode + + DISCUSSION: + . Calls other millicode routines via mrp: NONE + . Calls other millicode routines: NONE */ + +RDEFINE(tmp,r1) +RDEFINE(retreg,ret1) + + SUBSPA_MILLI + ATTR_MILLI + .proc + .callinfo millicode + .entry +GSYM($$remI) +GSYM($$remoI) + .export $$remI,MILLICODE + .export $$remoI,MILLICODE + ldo -1(arg1),tmp /* is there at most one bit set ? */ + and,<> arg1,tmp,r0 /* if not, don't use power of 2 */ + addi,> 0,arg1,r0 /* if denominator > 0, use power */ + /* of 2 */ + b,n LREF(neg_denom) +LSYM(pow2) + comb,>,n 0,arg0,LREF(neg_num) /* is numerator < 0 ? */ + and arg0,tmp,retreg /* get the result */ + MILLIRETN +LSYM(neg_num) + subi 0,arg0,arg0 /* negate numerator */ + and arg0,tmp,retreg /* get the result */ + subi 0,retreg,retreg /* negate result */ + MILLIRETN +LSYM(neg_denom) + addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power */ + /* of 2 */ + b,n LREF(regular_seq) + sub r0,arg1,tmp /* make denominator positive */ + comb,=,n arg1,tmp,LREF(regular_seq) /* test against 0x80000000 and 0 */ + ldo -1(tmp),retreg /* is there at most one bit set ? */ + and,= tmp,retreg,r0 /* if not, go to regular_seq */ + b,n LREF(regular_seq) + comb,>,n 0,arg0,LREF(neg_num_2) /* if arg0 < 0, negate it */ + and arg0,retreg,retreg + MILLIRETN +LSYM(neg_num_2) + subi 0,arg0,tmp /* test against 0x80000000 */ + and tmp,retreg,retreg + subi 0,retreg,retreg + MILLIRETN +LSYM(regular_seq) + addit,= 0,arg1,0 /* trap if div by zero */ + add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */ + sub 0,retreg,retreg /* make it positive */ + sub 0,arg1, tmp /* clear carry, */ + /* negate the divisor */ + ds 0, tmp,0 /* set V-bit to the comple- */ + /* ment of the divisor sign */ + or 0,0, tmp /* clear tmp */ + add retreg,retreg,retreg /* shift msb bit into carry */ + ds tmp,arg1, tmp /* 1st divide step, if no carry */ + /* out, msb of quotient = 0 */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ +LSYM(t1) + ds tmp,arg1, tmp /* 2nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 3rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 4th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 5th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 6th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 7th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 8th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 9th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 10th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 11th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 12th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 13th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 14th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 15th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 16th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 17th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 18th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 19th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 20th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 21st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 22nd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 23rd divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 24th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 25th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 26th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 27th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 28th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 29th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 30th divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 31st divide step */ + addc retreg,retreg,retreg /* shift retreg with/into carry */ + ds tmp,arg1, tmp /* 32nd divide step, */ + addc retreg,retreg,retreg /* shift last bit into retreg */ + movb,>=,n tmp,retreg,LREF(finish) /* branch if pos. tmp */ + add,< arg1,0,0 /* if arg1 > 0, add arg1 */ + add,tr tmp,arg1,retreg /* for correcting remainder tmp */ + sub tmp,arg1,retreg /* else add absolute value arg1 */ +LSYM(finish) + add,>= arg0,0,0 /* set sign of remainder */ + sub 0,retreg,retreg /* to sign of dividend */ + MILLIRET + nop + .exit + .procend +#ifdef milliext + .origin 0x00000200 +#endif + .end +#endif diff --git a/arch/parisc/lib/milli/remU.S b/arch/parisc/lib/milli/remU.S new file mode 100644 index 00000000000..c0a2d6e247c --- /dev/null +++ b/arch/parisc/lib/milli/remU.S @@ -0,0 +1,148 @@ +/* 32 and 64-bit millicode, original author Hewlett-Packard + adapted for gcc by Paul Bame <bame@debian.org> + and Alan Modra <alan@linuxcare.com.au>. + + Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + This file is part of GCC and is released under the terms of + of the GNU General Public License as published by the Free Software + Foundation; either version 2, or (at your option) any later version. + See the file COPYING in the top-level GCC source directory for a copy + of the license. */ + +#include "milli.h" + +#ifdef L_remU +/* ROUTINE: $$remU + . Single precision divide for remainder with unsigned binary integers. + . + . The remainder must be dividend-(dividend/divisor)*divisor. + . Divide by zero is trapped. + + INPUT REGISTERS: + . arg0 == dividend + . arg1 == divisor + . mrp == return pc + . sr0 == return space when called externally + + OUTPUT REGISTERS: + . arg0 = undefined + . arg1 = undefined + . ret1 = remainder + + OTHER REGISTERS AFFECTED: + . r1 = undefined + + SIDE EFFECTS: + . Causes a trap under the following conditions: DIVIDE BY ZERO + . Changes memory at the following places: NONE + + PERMISSIBLE CONTEXT: + . Unwindable. + . Does not create a stack frame. + . Suitable for internal or external millicode. + . Assumes the special millicode register conventions. + + DISCUSSION: + . Calls other millicode routines using mrp: NONE + . Calls other millicode routines: NONE */ + + +RDEFINE(temp,r1) +RDEFINE(rmndr,ret1) /* r29 */ + SUBSPA_MILLI + ATTR_MILLI + .export $$remU,millicode + .proc + .callinfo millicode + .entry +GSYM($$remU) + ldo -1(arg1),temp /* is there at most one bit set ? */ + and,= arg1,temp,r0 /* if not, don't use power of 2 */ + b LREF(regular_seq) + addit,= 0,arg1,r0 /* trap on div by zero */ + and arg0,temp,rmndr /* get the result for power of 2 */ + MILLIRETN +LSYM(regular_seq) + comib,>=,n 0,arg1,LREF(special_case) + subi 0,arg1,rmndr /* clear carry, negate the divisor */ + ds r0,rmndr,r0 /* set V-bit to 1 */ + add arg0,arg0,temp /* shift msb bit into carry */ + ds r0,arg1,rmndr /* 1st divide step, if no carry */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 2nd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 3rd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 4th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 5th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 6th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 7th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 8th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 9th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 10th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 11th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 12th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 13th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 14th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 15th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 16th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 17th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 18th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 19th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 20th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 21st divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 22nd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 23rd divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 24th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 25th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 26th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 27th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 28th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 29th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 30th divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 31st divide step */ + addc temp,temp,temp /* shift temp with/into carry */ + ds rmndr,arg1,rmndr /* 32nd divide step, */ + comiclr,<= 0,rmndr,r0 + add rmndr,arg1,rmndr /* correction */ + MILLIRETN + nop + +/* Putting >= on the last DS and deleting COMICLR does not work! */ +LSYM(special_case) + sub,>>= arg0,arg1,rmndr + copy arg0,rmndr + MILLIRETN + nop + .exit + .procend + .end +#endif diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index e724b362c49..aa875fa4348 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -607,7 +607,7 @@ void show_mem(void) printk("Zone list for zone %d on node %d: ", j, i); for (k = 0; zl->zones[k] != NULL; k++) - printk("[%ld/%s] ", zone_to_nid(zl->zones[k]), zl->zones[k]->name); + printk("[%d/%s] ", zone_to_nid(zl->zones[k]), zl->zones[k]->name); printk("\n"); } } diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c index 9001104b56b..14206e3f081 100644 --- a/arch/powerpc/kernel/dma_64.c +++ b/arch/powerpc/kernel/dma_64.c @@ -161,8 +161,7 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int i; for_each_sg(sgl, sg, nents, i) { - sg->dma_address = (page_to_phys(sg->page) + sg->offset) | - dma_direct_offset; + sg->dma_address = sg_phys(sg) | dma_direct_offset; sg->dma_length = sg->length; } diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 289d7e93591..72fd87156b2 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -102,8 +102,7 @@ static int ibmebus_map_sg(struct device *dev, int i; for_each_sg(sgl, sg, nents, i) { - sg->dma_address = (dma_addr_t)page_address(sg->page) - + sg->offset; + sg->dma_address = (dma_addr_t) sg_virt(sg); sg->dma_length = sg->length; } diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 306a6f75b6c..2d0c9ef555e 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -307,7 +307,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist, continue; } /* Allocate iommu entries for that segment */ - vaddr = (unsigned long)page_address(s->page) + s->offset; + vaddr = (unsigned long) sg_virt(s); npages = iommu_num_pages(vaddr, slen); entry = iommu_range_alloc(tbl, npages, &handle, mask >> IOMMU_PAGE_SHIFT, 0); diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 07e64b48e7f..6405f4a3676 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -628,9 +628,8 @@ static int ps3_sb_map_sg(struct device *_dev, struct scatterlist *sgl, int i; for_each_sg(sgl, sg, nents, i) { - int result = ps3_dma_map(dev->d_region, - page_to_phys(sg->page) + sg->offset, sg->length, - &sg->dma_address, 0); + int result = ps3_dma_map(dev->d_region, sg_phys(sg), + sg->length, &sg->dma_address, 0); if (result) { pr_debug("%s:%d: ps3_dma_map failed (%d)\n", diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 9c3ed88853f..97aa50d1e4a 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c @@ -727,9 +727,8 @@ int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, BUG_ON(direction == PCI_DMA_NONE); /* IIep is write-through, not flushing. */ for_each_sg(sgl, sg, nents, n) { - BUG_ON(page_address(sg->page) == NULL); - sg->dvma_address = - virt_to_phys(page_address(sg->page)) + sg->offset; + BUG_ON(page_address(sg_page(sg)) == NULL); + sg->dvma_address = virt_to_phys(sg_virt(sg)); sg->dvma_length = sg->length; } return nents; @@ -748,9 +747,9 @@ void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, BUG_ON(direction == PCI_DMA_NONE); if (direction != PCI_DMA_TODEVICE) { for_each_sg(sgl, sg, nents, n) { - BUG_ON(page_address(sg->page) == NULL); + BUG_ON(page_address(sg_page(sg)) == NULL); mmu_inval_dma_area( - (unsigned long) page_address(sg->page), + (unsigned long) page_address(sg_page(sg)), (sg->length + PAGE_SIZE-1) & PAGE_MASK); } } @@ -798,9 +797,9 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sgl, int BUG_ON(direction == PCI_DMA_NONE); if (direction != PCI_DMA_TODEVICE) { for_each_sg(sgl, sg, nents, n) { - BUG_ON(page_address(sg->page) == NULL); + BUG_ON(page_address(sg_page(sg)) == NULL); mmu_inval_dma_area( - (unsigned long) page_address(sg->page), + (unsigned long) page_address(sg_page(sg)), (sg->length + PAGE_SIZE-1) & PAGE_MASK); } } @@ -814,9 +813,9 @@ void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sgl, BUG_ON(direction == PCI_DMA_NONE); if (direction != PCI_DMA_TODEVICE) { for_each_sg(sgl, sg, nents, n) { - BUG_ON(page_address(sg->page) == NULL); + BUG_ON(page_address(sg_page(sg)) == NULL); mmu_inval_dma_area( - (unsigned long) page_address(sg->page), + (unsigned long) page_address(sg_page(sg)), (sg->length + PAGE_SIZE-1) & PAGE_MASK); } } diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index 375b4db6370..1666087c5b8 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -144,7 +144,7 @@ static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus spin_lock_irqsave(&iounit->lock, flags); while (sz != 0) { --sz; - sg->dvma_address = iounit_get_area(iounit, (unsigned long)page_address(sg->page) + sg->offset, sg->length); + sg->dvma_address = iounit_get_area(iounit, sg_virt(sg), sg->length); sg->dvma_length = sg->length; sg = sg_next(sg); } diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 283656d9f6e..4b934270f05 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -238,7 +238,7 @@ static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sb while (sz != 0) { --sz; n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; - sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; + sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset; sg->dvma_length = (__u32) sg->length; sg = sg_next(sg); } @@ -252,7 +252,7 @@ static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbu while (sz != 0) { --sz; n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; - sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; + sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset; sg->dvma_length = (__u32) sg->length; sg = sg_next(sg); } @@ -273,7 +273,7 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu * XXX Is this a good assumption? * XXX What if someone else unmaps it here and races us? */ - if ((page = (unsigned long) page_address(sg->page)) != 0) { + if ((page = (unsigned long) page_address(sg_page(sg))) != 0) { for (i = 0; i < n; i++) { if (page != oldpage) { /* Already flushed? */ flush_page_for_dma(page); @@ -283,7 +283,7 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu } } - sg->dvma_address = iommu_get_one(sg->page, n, sbus) + sg->offset; + sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset; sg->dvma_length = (__u32) sg->length; sg = sg_next(sg); } diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index ee6708fc449..a2cc141291c 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1228,7 +1228,7 @@ static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus * { while (sz != 0) { --sz; - sg->dvma_address = (__u32)sun4c_lockarea(page_address(sg->page) + sg->offset, sg->length); + sg->dvma_address = (__u32)sun4c_lockarea(sg_virt(sg), sg->length); sg->dvma_length = sg->length; sg = sg_next(sg); } diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c index 29af777d7ac..070a4846c0c 100644 --- a/arch/sparc64/kernel/iommu.c +++ b/arch/sparc64/kernel/iommu.c @@ -472,8 +472,7 @@ static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr, spin_unlock_irqrestore(&iommu->lock, flags); } -#define SG_ENT_PHYS_ADDRESS(SG) \ - (__pa(page_address((SG)->page)) + (SG)->offset) +#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG)))) static void fill_sg(iopte_t *iopte, struct scatterlist *sg, int nused, int nelems, @@ -565,9 +564,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist, /* Fast path single entry scatterlists. */ if (nelems == 1) { sglist->dma_address = - dma_4u_map_single(dev, - (page_address(sglist->page) + - sglist->offset), + dma_4u_map_single(dev, sg_virt(sglist), sglist->length, direction); if (unlikely(sglist->dma_address == DMA_ERROR_CODE)) return 0; diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c index d7ca900ec51..78e8277df65 100644 --- a/arch/sparc64/kernel/iommu_common.c +++ b/arch/sparc64/kernel/iommu_common.c @@ -73,7 +73,7 @@ static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, daddr = dma_sg->dma_address; sglen = sg->length; - sgaddr = (unsigned long) (page_address(sg->page) + sg->offset); + sgaddr = (unsigned long) sg_virt(sg); while (dlen > 0) { unsigned long paddr; @@ -123,7 +123,7 @@ static int verify_one_map(struct scatterlist *dma_sg, struct scatterlist **__sg, sg = sg_next(sg); if (--nents <= 0) break; - sgaddr = (unsigned long) (page_address(sg->page) + sg->offset); + sgaddr = (unsigned long) sg_virt(sg); sglen = sg->length; } if (dlen < 0) { @@ -191,7 +191,7 @@ void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int np printk("sg(%d): page_addr(%p) off(%x) length(%x) " "dma_address[%016x] dma_length[%016x]\n", i, - page_address(sg->page), sg->offset, + page_address(sg_page(sg)), sg->offset, sg->length, sg->dma_address, sg->dma_length); } @@ -207,15 +207,14 @@ unsigned long prepare_sg(struct scatterlist *sg, int nents) unsigned long prev; u32 dent_addr, dent_len; - prev = (unsigned long) (page_address(sg->page) + sg->offset); + prev = (unsigned long) sg_virt(sg); prev += (unsigned long) (dent_len = sg->length); - dent_addr = (u32) ((unsigned long)(page_address(sg->page) + sg->offset) - & (IO_PAGE_SIZE - 1UL)); + dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL)); while (--nents) { unsigned long addr; sg = sg_next(sg); - addr = (unsigned long) (page_address(sg->page) + sg->offset); + addr = (unsigned long) sg_virt(sg); if (! VCONTIG(prev, addr)) { dma_sg->dma_address = dent_addr; dma_sg->dma_length = dent_len; diff --git a/arch/sparc64/kernel/ldc.c b/arch/sparc64/kernel/ldc.c index 85a2be0b096..c8313cb60f0 100644 --- a/arch/sparc64/kernel/ldc.c +++ b/arch/sparc64/kernel/ldc.c @@ -2057,7 +2057,7 @@ static void fill_cookies(struct cookie_state *sp, unsigned long pa, static int sg_count_one(struct scatterlist *sg) { - unsigned long base = page_to_pfn(sg->page) << PAGE_SHIFT; + unsigned long base = page_to_pfn(sg_page(sg)) << PAGE_SHIFT; long len = sg->length; if ((sg->offset | len) & (8UL - 1)) diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index fe46ace3e59..8c4875bdb4a 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -365,8 +365,7 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr, spin_unlock_irqrestore(&iommu->lock, flags); } -#define SG_ENT_PHYS_ADDRESS(SG) \ - (__pa(page_address((SG)->page)) + (SG)->offset) +#define SG_ENT_PHYS_ADDRESS(SG) (__pa(sg_virt((SG)))) static long fill_sg(long entry, struct device *dev, struct scatterlist *sg, @@ -477,9 +476,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist, /* Fast path single entry scatterlists. */ if (nelems == 1) { sglist->dma_address = - dma_4v_map_single(dev, - (page_address(sglist->page) + - sglist->offset), + dma_4v_map_single(dev, sg_virt(sglist), sglist->length, direction); if (unlikely(sglist->dma_address == DMA_ERROR_CODE)) return 0; diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 25b248a0250..3a8cd3dfb51 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1115,7 +1115,7 @@ static void do_ubd_request(struct request_queue *q) } prepare_request(req, io_req, (unsigned long long) req->sector << 9, - sg->offset, sg->length, sg->page); + sg->offset, sg->length, sg_page(sg)); last_sectors = sg->length >> 9; n = os_write_file(thread_fd, &io_req, diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index f35ea223752..a0ae2e7f6ce 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -27,13 +27,22 @@ #include <asm/segment.h> #include <asm/page.h> #include <asm/boot.h> +#include <asm/asm-offsets.h> .section ".text.head","ax",@progbits .globl startup_32 startup_32: - cld - cli + /* check to see if KEEP_SEGMENTS flag is meaningful */ + cmpw $0x207, BP_version(%esi) + jb 1f + + /* test KEEP_SEGMENTS flag to see if the bootloader is asking + * us to not reload segments */ + testb $(1<<6), BP_loadflags(%esi) + jnz 2f + +1: cli movl $(__BOOT_DS),%eax movl %eax,%ds movl %eax,%es @@ -41,6 +50,8 @@ startup_32: movl %eax,%gs movl %eax,%ss +2: cld + /* Calculate the delta between where we were compiled to run * at and where we were actually loaded at. This can only be done * with a short local call on x86. Nothing else will tell us what diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c index 1dc1e19c0a9..b74d60d1b2f 100644 --- a/arch/x86/boot/compressed/misc_32.c +++ b/arch/x86/boot/compressed/misc_32.c @@ -247,6 +247,9 @@ static void putstr(const char *s) int x,y,pos; char c; + if (RM_SCREEN_INFO.orig_video_mode == 0 && lines == 0 && cols == 0) + return; + x = RM_SCREEN_INFO.orig_x; y = RM_SCREEN_INFO.orig_y; diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index f3140e596d4..8353c81c41c 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -119,7 +119,7 @@ _start: # Part 2 of the header, from the old setup.S .ascii "HdrS" # header signature - .word 0x0206 # header version number (>= 0x0105) + .word 0x0207 # header version number (>= 0x0105) # or else old loadlin-1.5 will fail) .globl realmode_swtch realmode_swtch: .word 0, 0 # default_switch, SETUPSEG @@ -214,6 +214,11 @@ cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, #added with boot protocol #version 2.06 +hardware_subarch: .long 0 # subarchitecture, added with 2.07 + # default to 0 for normal x86 PC + +hardware_subarch_data: .quad 0 + # End of setup header ##################################################### .section ".inittext", "ax" diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index f1b7cdda82b..f8764716b0c 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c @@ -15,6 +15,7 @@ #include <asm/fixmap.h> #include <asm/processor.h> #include <asm/thread_info.h> +#include <asm/bootparam.h> #include <asm/elf.h> #include <xen/interface/xen.h> @@ -146,4 +147,10 @@ void foo(void) OFFSET(LGUEST_PAGES_regs_errcode, lguest_pages, regs.errcode); OFFSET(LGUEST_PAGES_regs, lguest_pages, regs); #endif + + BLANK(); + OFFSET(BP_scratch, boot_params, scratch); + OFFSET(BP_loadflags, boot_params, hdr.loadflags); + OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch); + OFFSET(BP_version, boot_params, hdr.version); } diff --git a/arch/x86/kernel/e820_32.c b/arch/x86/kernel/e820_32.c index 58fd54eb557..18f500d185a 100644 --- a/arch/x86/kernel/e820_32.c +++ b/arch/x86/kernel/e820_32.c @@ -51,6 +51,13 @@ struct resource code_resource = { .flags = IORESOURCE_BUSY | IORESOURCE_MEM }; +struct resource bss_resource = { + .name = "Kernel bss", + .start = 0, + .end = 0, + .flags = IORESOURCE_BUSY | IORESOURCE_MEM +}; + static struct resource system_rom_resource = { .name = "System ROM", .start = 0xf0000, @@ -254,7 +261,9 @@ static void __init probe_roms(void) * and also for regions reported as reserved by the e820. */ static void __init -legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource) +legacy_init_iomem_resources(struct resource *code_resource, + struct resource *data_resource, + struct resource *bss_resource) { int i; @@ -287,6 +296,7 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat */ request_resource(res, code_resource); request_resource(res, data_resource); + request_resource(res, bss_resource); #ifdef CONFIG_KEXEC if (crashk_res.start != crashk_res.end) request_resource(res, &crashk_res); @@ -307,9 +317,11 @@ static int __init request_standard_resources(void) printk("Setting up standard PCI resources\n"); if (efi_enabled) - efi_initialize_iomem_resources(&code_resource, &data_resource); + efi_initialize_iomem_resources(&code_resource, + &data_resource, &bss_resource); else - legacy_init_iomem_resources(&code_resource, &data_resource); + legacy_init_iomem_resources(&code_resource, + &data_resource, &bss_resource); /* EFI systems may still have VGA */ request_resource(&iomem_resource, &video_ram_resource); diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c index 57616865d8a..04698e0b056 100644 --- a/arch/x86/kernel/e820_64.c +++ b/arch/x86/kernel/e820_64.c @@ -47,7 +47,7 @@ unsigned long end_pfn_map; */ static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT; -extern struct resource code_resource, data_resource; +extern struct resource code_resource, data_resource, bss_resource; /* Check for some hardcoded bad areas that early boot is not allowed to touch */ static inline int bad_addr(unsigned long *addrp, unsigned long size) @@ -225,6 +225,7 @@ void __init e820_reserve_resources(void) */ request_resource(res, &code_resource); request_resource(res, &data_resource); + request_resource(res, &bss_resource); #ifdef CONFIG_KEXEC if (crashk_res.start != crashk_res.end) request_resource(res, &crashk_res); @@ -729,3 +730,22 @@ __init void e820_setup_gap(void) printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n", pci_mem_start, gapstart, gapsize); } + +int __init arch_get_ram_range(int slot, u64 *addr, u64 *size) +{ + int i; + + if (slot < 0 || slot >= e820.nr_map) + return -1; + for (i = slot; i < e820.nr_map; i++) { + if (e820.map[i].type != E820_RAM) + continue; + break; + } + if (i == e820.nr_map || e820.map[i].addr > (max_pfn << PAGE_SHIFT)) + return -1; + *addr = e820.map[i].addr; + *size = min_t(u64, e820.map[i].size + e820.map[i].addr, + max_pfn << PAGE_SHIFT) - *addr; + return i + 1; +} diff --git a/arch/x86/kernel/efi_32.c b/arch/x86/kernel/efi_32.c index b42558c48e9..e2be78f4939 100644 --- a/arch/x86/kernel/efi_32.c +++ b/arch/x86/kernel/efi_32.c @@ -603,7 +603,8 @@ void __init efi_enter_virtual_mode(void) void __init efi_initialize_iomem_resources(struct resource *code_resource, - struct resource *data_resource) + struct resource *data_resource, + struct resource *bss_resource) { struct resource *res; efi_memory_desc_t *md; @@ -675,6 +676,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, if (md->type == EFI_CONVENTIONAL_MEMORY) { request_resource(res, code_resource); request_resource(res, data_resource); + request_resource(res, bss_resource); #ifdef CONFIG_KEXEC request_resource(res, &crashk_res); #endif diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 39677965e16..00b1c2c5645 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S @@ -79,22 +79,30 @@ INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_ */ .section .text.head,"ax",@progbits ENTRY(startup_32) + /* check to see if KEEP_SEGMENTS flag is meaningful */ + cmpw $0x207, BP_version(%esi) + jb 1f + + /* test KEEP_SEGMENTS flag to see if the bootloader is asking + us to not reload segments */ + testb $(1<<6), BP_loadflags(%esi) + jnz 2f /* * Set segments to known values. */ - cld - lgdt boot_gdt_descr - __PAGE_OFFSET +1: lgdt boot_gdt_descr - __PAGE_OFFSET movl $(__BOOT_DS),%eax movl %eax,%ds movl %eax,%es movl %eax,%fs movl %eax,%gs +2: /* * Clear BSS first so that there are no surprises... - * No need to cld as DF is already clear from cld above... */ + cld xorl %eax,%eax movl $__bss_start - __PAGE_OFFSET,%edi movl $__bss_stop - __PAGE_OFFSET,%ecx @@ -128,6 +136,35 @@ ENTRY(startup_32) movsl 1: +#ifdef CONFIG_PARAVIRT + cmpw $0x207, (boot_params + BP_version - __PAGE_OFFSET) + jb default_entry + + /* Paravirt-compatible boot parameters. Look to see what architecture + we're booting under. */ + movl (boot_params + BP_hardware_subarch - __PAGE_OFFSET), %eax + cmpl $num_subarch_entries, %eax + jae bad_subarch + + movl subarch_entries - __PAGE_OFFSET(,%eax,4), %eax + subl $__PAGE_OFFSET, %eax + jmp *%eax + +bad_subarch: +WEAK(lguest_entry) +WEAK(xen_entry) + /* Unknown implementation; there's really + nothing we can do at this point. */ + ud2a +.data +subarch_entries: + .long default_entry /* normal x86/PC */ + .long lguest_entry /* lguest hypervisor */ + .long xen_entry /* Xen hypervisor */ +num_subarch_entries = (. - subarch_entries) / 4 +.previous +#endif /* CONFIG_PARAVIRT */ + /* * Initialize page tables. This creates a PDE and a set of page * tables, which are located immediately beyond _end. The variable @@ -140,6 +177,7 @@ ENTRY(startup_32) */ page_pde_offset = (__PAGE_OFFSET >> 20); +default_entry: movl $(pg0 - __PAGE_OFFSET), %edi movl $(swapper_pg_dir - __PAGE_OFFSET), %edx movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */ diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index b3c2d268d70..953328b55a3 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -31,6 +31,7 @@ #include <linux/sysdev.h> #include <linux/msi.h> #include <linux/htirq.h> +#include <linux/dmar.h> #ifdef CONFIG_ACPI #include <acpi/acpi_bus.h> #endif @@ -2031,8 +2032,64 @@ void arch_teardown_msi_irq(unsigned int irq) destroy_irq(irq); } -#endif /* CONFIG_PCI_MSI */ +#ifdef CONFIG_DMAR +#ifdef CONFIG_SMP +static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask) +{ + struct irq_cfg *cfg = irq_cfg + irq; + struct msi_msg msg; + unsigned int dest; + cpumask_t tmp; + + cpus_and(tmp, mask, cpu_online_map); + if (cpus_empty(tmp)) + return; + + if (assign_irq_vector(irq, mask)) + return; + + cpus_and(tmp, cfg->domain, mask); + dest = cpu_mask_to_apicid(tmp); + + dmar_msi_read(irq, &msg); + + msg.data &= ~MSI_DATA_VECTOR_MASK; + msg.data |= MSI_DATA_VECTOR(cfg->vector); + msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK; + msg.address_lo |= MSI_ADDR_DEST_ID(dest); + + dmar_msi_write(irq, &msg); + irq_desc[irq].affinity = mask; +} +#endif /* CONFIG_SMP */ + +struct irq_chip dmar_msi_type = { + .name = "DMAR_MSI", + .unmask = dmar_msi_unmask, + .mask = dmar_msi_mask, + .ack = ack_apic_edge, +#ifdef CONFIG_SMP + .set_affinity = dmar_msi_set_affinity, +#endif + .retrigger = ioapic_retrigger_irq, +}; + +int arch_setup_dmar_msi(unsigned int irq) +{ + int ret; + struct msi_msg msg; + + ret = msi_compose_msg(NULL, irq, &msg); + if (ret < 0) + return ret; + dmar_msi_write(irq, &msg); + set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq, + "edge"); + return 0; +} +#endif +#endif /* CONFIG_PCI_MSI */ /* * Hypertransport interrupt support */ diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 5098f58063a..1a20fe31338 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -411,8 +411,10 @@ static int calgary_nontranslate_map_sg(struct device* dev, int i; for_each_sg(sg, s, nelems, i) { - BUG_ON(!s->page); - s->dma_address = virt_to_bus(page_address(s->page) +s->offset); + struct page *p = sg_page(s); + + BUG_ON(!p); + s->dma_address = virt_to_bus(sg_virt(s)); s->dma_length = s->length; } return nelems; @@ -432,9 +434,9 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg, return calgary_nontranslate_map_sg(dev, sg, nelems, direction); for_each_sg(sg, s, nelems, i) { - BUG_ON(!s->page); + BUG_ON(!sg_page(s)); - vaddr = (unsigned long)page_address(s->page) + s->offset; + vaddr = (unsigned long) sg_virt(s); npages = num_dma_pages(vaddr, s->length); entry = iommu_range_alloc(tbl, npages); diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c index afaf9f12c03..393e2725a6e 100644 --- a/arch/x86/kernel/pci-dma_64.c +++ b/arch/x86/kernel/pci-dma_64.c @@ -7,6 +7,7 @@ #include <linux/string.h> #include <linux/pci.h> #include <linux/module.h> +#include <linux/dmar.h> #include <asm/io.h> #include <asm/iommu.h> #include <asm/calgary.h> @@ -305,6 +306,8 @@ void __init pci_iommu_alloc(void) detect_calgary(); #endif + detect_intel_iommu(); + #ifdef CONFIG_SWIOTLB pci_swiotlb_init(); #endif @@ -316,6 +319,8 @@ static int __init pci_iommu_init(void) calgary_iommu_init(); #endif + intel_iommu_init(); + #ifdef CONFIG_IOMMU gart_iommu_init(); #endif diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index 5cdfab65e93..c56e9ee6496 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -302,7 +302,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, #endif for_each_sg(sg, s, nents, i) { - unsigned long addr = page_to_phys(s->page) + s->offset; + unsigned long addr = sg_phys(s); if (nonforced_iommu(dev, addr, s->length)) { addr = dma_map_area(dev, addr, s->length, dir); if (addr == bad_dma_address) { @@ -397,7 +397,7 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, start_sg = sgmap = sg; ps = NULL; /* shut up gcc */ for_each_sg(sg, s, nents, i) { - dma_addr_t addr = page_to_phys(s->page) + s->offset; + dma_addr_t addr = sg_phys(s); s->dma_address = addr; BUG_ON(s->length == 0); diff --git a/arch/x86/kernel/pci-nommu_64.c b/arch/x86/kernel/pci-nommu_64.c index e85d4360360..faf70bdca33 100644 --- a/arch/x86/kernel/pci-nommu_64.c +++ b/arch/x86/kernel/pci-nommu_64.c @@ -62,8 +62,8 @@ static int nommu_map_sg(struct device *hwdev, struct scatterlist *sg, int i; for_each_sg(sg, s, nents, i) { - BUG_ON(!s->page); - s->dma_address = virt_to_bus(page_address(s->page) +s->offset); + BUG_ON(!sg_page(s)); + s->dma_address = virt_to_bus(sg_virt(s)); if (!check_addr("map_sg", hwdev, s->dma_address, s->length)) return 0; s->dma_length = s->length; diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index ba2e165a8a0..cc0e91447b7 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -60,6 +60,7 @@ #include <asm/vmi.h> #include <setup_arch.h> #include <bios_ebda.h> +#include <asm/cacheflush.h> /* This value is set up by the early boot code to point to the value immediately after the boot time page tables. It contains a *physical* @@ -73,6 +74,7 @@ int disable_pse __devinitdata = 0; */ extern struct resource code_resource; extern struct resource data_resource; +extern struct resource bss_resource; /* cpu data as detected by the assembly code in head.S */ struct cpuinfo_x86 new_cpu_data __cpuinitdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; @@ -600,6 +602,8 @@ void __init setup_arch(char **cmdline_p) code_resource.end = virt_to_phys(_etext)-1; data_resource.start = virt_to_phys(_etext); data_resource.end = virt_to_phys(_edata)-1; + bss_resource.start = virt_to_phys(&__bss_start); + bss_resource.end = virt_to_phys(&__bss_stop)-1; parse_early_param(); diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 31322d42eaa..e7a9e36bd52 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -58,6 +58,7 @@ #include <asm/numa.h> #include <asm/sections.h> #include <asm/dmi.h> +#include <asm/cacheflush.h> /* * Machine setup.. @@ -133,6 +134,12 @@ struct resource code_resource = { .end = 0, .flags = IORESOURCE_RAM, }; +struct resource bss_resource = { + .name = "Kernel bss", + .start = 0, + .end = 0, + .flags = IORESOURCE_RAM, +}; #ifdef CONFIG_PROC_VMCORE /* elfcorehdr= specifies the location of elf core header @@ -276,6 +283,8 @@ void __init setup_arch(char **cmdline_p) code_resource.end = virt_to_phys(&_etext)-1; data_resource.start = virt_to_phys(&_etext); data_resource.end = virt_to_phys(&_edata)-1; + bss_resource.start = virt_to_phys(&__bss_start); + bss_resource.end = virt_to_phys(&__bss_stop)-1; early_identify_cpu(&boot_cpu_data); diff --git a/arch/x86/mm/pageattr_64.c b/arch/x86/mm/pageattr_64.c index c7b7dfe1d40..c40afbaaf93 100644 --- a/arch/x86/mm/pageattr_64.c +++ b/arch/x86/mm/pageattr_64.c @@ -61,10 +61,10 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot, return base; } -static void cache_flush_page(void *adr) +void clflush_cache_range(void *adr, int size) { int i; - for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) + for (i = 0; i < size; i += boot_cpu_data.x86_clflush_size) clflush(adr+i); } @@ -80,7 +80,7 @@ static void flush_kernel_map(void *arg) asm volatile("wbinvd" ::: "memory"); else list_for_each_entry(pg, l, lru) { void *adr = page_address(pg); - cache_flush_page(adr); + clflush_cache_range(adr, PAGE_SIZE); } __flush_tlb_all(); } diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index aab25f3ba3c..c2d24991bb2 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -750,6 +750,38 @@ config PCI_DOMAINS depends on PCI default y +config DMAR + bool "Support for DMA Remapping Devices (EXPERIMENTAL)" + depends on PCI_MSI && ACPI && EXPERIMENTAL + default y + help + DMA remapping (DMAR) devices support enables independent address + translations for Direct Memory Access (DMA) from devices. + These DMA remapping devices are reported via ACPI tables + and include PCI device scope covered by these DMA + remapping devices. + +config DMAR_GFX_WA + bool "Support for Graphics workaround" + depends on DMAR + default y + help + Current Graphics drivers tend to use physical address + for DMA and avoid using DMA APIs. Setting this config + option permits the IOMMU driver to set a unity map for + all the OS-visible memory. Hence the driver can continue + to use physical addresses for DMA. + +config DMAR_FLOPPY_WA + bool + depends on DMAR + default y + help + Floppy disk drivers are know to bypass DMA API calls + thereby failing to work when IOMMU is enabled. This + workaround will setup a 1:1 mapping for the first + 16M to make floppy (an ISA device) work. + source "drivers/pci/pcie/Kconfig" source "drivers/pci/Kconfig" diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 8025d646ab3..61c2e396f2f 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1354,8 +1354,9 @@ new_segment: else sg = sg_next(sg); - memset(sg, 0, sizeof(*sg)); - sg->page = bvec->bv_page; + sg_dma_len(sg) = 0; + sg_dma_address(sg) = 0; + sg_set_page(sg, bvec->bv_page); sg->length = nbytes; sg->offset = bvec->bv_offset; nsegs++; @@ -1363,6 +1364,9 @@ new_segment: bvprv = bvec; } /* segments in rq */ + if (sg) + __sg_mark_end(sg); + return nsegs; } diff --git a/crypto/digest.c b/crypto/digest.c index e56de6748b1..8871dec8cae 100644 --- a/crypto/digest.c +++ b/crypto/digest.c @@ -41,7 +41,7 @@ static int update2(struct hash_desc *desc, return 0; for (;;) { - struct page *pg = sg->page; + struct page *pg = sg_page(sg); unsigned int offset = sg->offset; unsigned int l = sg->length; diff --git a/crypto/hmac.c b/crypto/hmac.c index 8802fb6dd5a..e4eb6ac53b5 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -159,7 +159,8 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg, desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; sg_set_buf(sg1, ipad, bs); - sg1[1].page = (void *)sg; + + sg_set_page(&sg[1], (void *) sg); sg1[1].length = 0; sg_set_buf(sg2, opad, bs + ds); diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c index d6852c33cfb..b9bbda0bb9f 100644 --- a/crypto/scatterwalk.c +++ b/crypto/scatterwalk.c @@ -54,7 +54,7 @@ static void scatterwalk_pagedone(struct scatter_walk *walk, int out, if (out) { struct page *page; - page = walk->sg->page + ((walk->offset - 1) >> PAGE_SHIFT); + page = sg_page(walk->sg) + ((walk->offset - 1) >> PAGE_SHIFT); flush_dcache_page(page); } diff --git a/crypto/scatterwalk.h b/crypto/scatterwalk.h index 9c73e37a42c..87ed681cceb 100644 --- a/crypto/scatterwalk.h +++ b/crypto/scatterwalk.h @@ -22,13 +22,13 @@ static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg) { - return (++sg)->length ? sg : (void *)sg->page; + return (++sg)->length ? sg : (void *) sg_page(sg); } static inline unsigned long scatterwalk_samebuf(struct scatter_walk *walk_in, struct scatter_walk *walk_out) { - return !(((walk_in->sg->page - walk_out->sg->page) << PAGE_SHIFT) + + return !(((sg_page(walk_in->sg) - sg_page(walk_out->sg)) << PAGE_SHIFT) + (int)(walk_in->offset - walk_out->offset)); } @@ -60,7 +60,7 @@ static inline unsigned int scatterwalk_aligned(struct scatter_walk *walk, static inline struct page *scatterwalk_page(struct scatter_walk *walk) { - return walk->sg->page + (walk->offset >> PAGE_SHIFT); + return sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT); } static inline void scatterwalk_unmap(void *vaddr, int out) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 18d489c8b93..d741c63af42 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -317,7 +317,7 @@ static void test_cipher(char *algo, int enc, goto out; } - q = kmap(sg[0].page) + sg[0].offset; + q = kmap(sg_page(&sg[0])) + sg[0].offset; hexdump(q, cipher_tv[i].rlen); printk("%s\n", @@ -390,7 +390,7 @@ static void test_cipher(char *algo, int enc, temp = 0; for (k = 0; k < cipher_tv[i].np; k++) { printk("page %u\n", k); - q = kmap(sg[k].page) + sg[k].offset; + q = kmap(sg_page(&sg[k])) + sg[k].offset; hexdump(q, cipher_tv[i].tap[k]); printk("%s\n", memcmp(q, cipher_tv[i].result + temp, diff --git a/crypto/xcbc.c b/crypto/xcbc.c index 9f502b86e0e..ac68f3b62fd 100644 --- a/crypto/xcbc.c +++ b/crypto/xcbc.c @@ -120,7 +120,7 @@ static int crypto_xcbc_digest_update2(struct hash_desc *pdesc, do { - struct page *pg = sg[i].page; + struct page *pg = sg_page(&sg[i]); unsigned int offset = sg[i].offset; unsigned int slen = sg[i].length; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 629eadbd0ec..69092bce1ad 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4296,7 +4296,7 @@ void ata_sg_clean(struct ata_queued_cmd *qc) sg_last(sg, qc->orig_n_elem)->length += qc->pad_len; if (pad_buf) { struct scatterlist *psg = &qc->pad_sgent; - void *addr = kmap_atomic(psg->page, KM_IRQ0); + void *addr = kmap_atomic(sg_page(psg), KM_IRQ0); memcpy(addr + psg->offset, pad_buf, qc->pad_len); kunmap_atomic(addr, KM_IRQ0); } @@ -4686,11 +4686,11 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) * data in this function or read data in ata_sg_clean. */ offset = lsg->offset + lsg->length - qc->pad_len; - psg->page = nth_page(lsg->page, offset >> PAGE_SHIFT); + sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT)); psg->offset = offset_in_page(offset); if (qc->tf.flags & ATA_TFLAG_WRITE) { - void *addr = kmap_atomic(psg->page, KM_IRQ0); + void *addr = kmap_atomic(sg_page(psg), KM_IRQ0); memcpy(pad_buf, addr + psg->offset, qc->pad_len); kunmap_atomic(addr, KM_IRQ0); } @@ -4836,7 +4836,7 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) if (qc->curbytes == qc->nbytes - qc->sect_size) ap->hsm_task_state = HSM_ST_LAST; - page = qc->cursg->page; + page = sg_page(qc->cursg); offset = qc->cursg->offset + qc->cursg_ofs; /* get the current page and offset */ @@ -4988,7 +4988,7 @@ next_sg: sg = qc->cursg; - page = sg->page; + page = sg_page(sg); offset = sg->offset + qc->cursg_ofs; /* get the current page and offset */ diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 9fbb39cd0f5..5b758b9ad0b 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1544,7 +1544,7 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out) struct scatterlist *sg = scsi_sglist(cmd); if (sg) { - buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; buflen = sg->length; } else { buf = NULL; diff --git a/drivers/base/memory.c b/drivers/base/memory.c index c41d0728efe..7868707c7ed 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -137,7 +137,7 @@ static ssize_t show_mem_state(struct sys_device *dev, char *buf) return len; } -static inline int memory_notify(unsigned long val, void *v) +int memory_notify(unsigned long val, void *v) { return blocking_notifier_call_chain(&memory_chain, val, v); } @@ -183,7 +183,6 @@ memory_block_action(struct memory_block *mem, unsigned long action) break; case MEM_OFFLINE: mem->state = MEM_GOING_OFFLINE; - memory_notify(MEM_GOING_OFFLINE, NULL); start_paddr = page_to_pfn(first_page) << PAGE_SHIFT; ret = remove_memory(start_paddr, PAGES_PER_SECTION << PAGE_SHIFT); @@ -191,7 +190,6 @@ memory_block_action(struct memory_block *mem, unsigned long action) mem->state = old_state; break; } - memory_notify(MEM_MAPPING_INVALID, NULL); break; default: printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n", @@ -199,11 +197,6 @@ memory_block_action(struct memory_block *mem, unsigned long action) WARN_ON(1); ret = -EINVAL; } - /* - * For now, only notify on successful memory operations - */ - if (!ret) - memory_notify(action, NULL); return ret; } diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 84d6aa500e2..53505422867 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -345,6 +345,7 @@ static bool DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller) Command->V1.ScatterGatherList = (DAC960_V1_ScatterGatherSegment_T *)ScatterGatherCPU; Command->V1.ScatterGatherListDMA = ScatterGatherDMA; + sg_init_table(Command->cmd_sglist, DAC960_V1_ScatterGatherLimit); } else { Command->cmd_sglist = Command->V2.ScatterList; Command->V2.ScatterGatherList = @@ -353,6 +354,7 @@ static bool DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller) Command->V2.RequestSense = (DAC960_SCSI_RequestSense_T *)RequestSenseCPU; Command->V2.RequestSenseDMA = RequestSenseDMA; + sg_init_table(Command->cmd_sglist, DAC960_V2_ScatterGatherLimit); } } return true; diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 7c2cfde08f1..5a6fe17fc63 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2610,7 +2610,7 @@ static void do_cciss_request(struct request_queue *q) (int)creq->nr_sectors); #endif /* CCISS_DEBUG */ - memset(tmp_sg, 0, sizeof(tmp_sg)); + sg_init_table(tmp_sg, MAXSGENTRIES); seg = blk_rq_map_sg(q, creq, tmp_sg); /* get the DMA records for the setup */ @@ -2621,7 +2621,7 @@ static void do_cciss_request(struct request_queue *q) for (i = 0; i < seg; i++) { c->SG[i].Len = tmp_sg[i].length; - temp64.val = (__u64) pci_map_page(h->pdev, tmp_sg[i].page, + temp64.val = (__u64) pci_map_page(h->pdev, sg_page(&tmp_sg[i]), tmp_sg[i].offset, tmp_sg[i].length, dir); c->SG[i].Addr.lower = temp64.val32.lower; diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 568603d3043..efab27fa108 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -918,6 +918,7 @@ queue_next: DBGPX( printk("sector=%d, nr_sectors=%d\n", creq->sector, creq->nr_sectors); ); + sg_init_table(tmp_sg, SG_MAX); seg = blk_rq_map_sg(q, creq, tmp_sg); /* Now do all the DMA Mappings */ @@ -929,7 +930,7 @@ DBGPX( { c->req.sg[i].size = tmp_sg[i].length; c->req.sg[i].addr = (__u32) pci_map_page(h->pci_dev, - tmp_sg[i].page, + sg_page(&tmp_sg[i]), tmp_sg[i].offset, tmp_sg[i].length, dir); } diff --git a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c index 40535036e89..1b58b010797 100644 --- a/drivers/block/cryptoloop.c +++ b/drivers/block/cryptoloop.c @@ -26,6 +26,7 @@ #include <linux/crypto.h> #include <linux/blkdev.h> #include <linux/loop.h> +#include <linux/scatterlist.h> #include <asm/semaphore.h> #include <asm/uaccess.h> @@ -119,14 +120,17 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, .tfm = tfm, .flags = CRYPTO_TFM_REQ_MAY_SLEEP, }; - struct scatterlist sg_out = { NULL, }; - struct scatterlist sg_in = { NULL, }; + struct scatterlist sg_out; + struct scatterlist sg_in; encdec_cbc_t encdecfunc; struct page *in_page, *out_page; unsigned in_offs, out_offs; int err; + sg_init_table(&sg_out, 1); + sg_init_table(&sg_in, 1); + if (cmd == READ) { in_page = raw_page; in_offs = raw_off; @@ -146,11 +150,11 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, u32 iv[4] = { 0, }; iv[0] = cpu_to_le32(IV & 0xffffffff); - sg_in.page = in_page; + sg_set_page(&sg_in, in_page); sg_in.offset = in_offs; sg_in.length = sz; - sg_out.page = out_page; + sg_set_page(&sg_out, out_page); sg_out.offset = out_offs; sg_out.length = sz; diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 317a790c153..7276f7d207c 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -388,6 +388,7 @@ static int __send_request(struct request *req) op = VD_OP_BWRITE; } + sg_init_table(sg, port->ring_cookies); nsg = blk_rq_map_sg(req->q, req, sg); len = 0; diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index 402209fec59..282a69558e8 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c @@ -522,6 +522,7 @@ static struct carm_request *carm_get_request(struct carm_host *host) host->n_msgs++; assert(host->n_msgs <= CARM_MAX_REQ); + sg_init_table(crq->sg, CARM_MAX_REQ_SG); return crq; } diff --git a/drivers/block/ub.c b/drivers/block/ub.c index c57dd2b3a0c..14143f2c484 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -25,6 +25,7 @@ #include <linux/usb_usual.h> #include <linux/blkdev.h> #include <linux/timer.h> +#include <linux/scatterlist.h> #include <scsi/scsi.h> #define DRV_NAME "ub" @@ -656,6 +657,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) if ((cmd = ub_get_cmd(lun)) == NULL) return -1; memset(cmd, 0, sizeof(struct ub_scsi_cmd)); + sg_init_table(cmd->sgv, UB_MAX_REQ_SG); blkdev_dequeue_request(rq); @@ -1309,9 +1311,8 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) else pipe = sc->send_bulk_pipe; sc->last_pipe = pipe; - usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, - page_address(sg->page) + sg->offset, sg->length, - ub_urb_complete, sc); + usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg), + sg->length, ub_urb_complete, sc); sc->work_urb.actual_length = 0; sc->work_urb.error_count = 0; sc->work_urb.status = 0; @@ -1427,7 +1428,7 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) scmd->state = UB_CMDST_INIT; scmd->nsg = 1; sg = &scmd->sgv[0]; - sg->page = virt_to_page(sc->top_sense); + sg_set_page(sg, virt_to_page(sc->top_sense)); sg->offset = (unsigned long)sc->top_sense & (PAGE_SIZE-1); sg->length = UB_SENSE_SIZE; scmd->len = UB_SENSE_SIZE; @@ -1863,7 +1864,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, cmd->state = UB_CMDST_INIT; cmd->nsg = 1; sg = &cmd->sgv[0]; - sg->page = virt_to_page(p); + sg_set_page(sg, virt_to_page(p)); sg->offset = (unsigned long)p & (PAGE_SIZE-1); sg->length = 8; cmd->len = 8; diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index e824b672e05..ab5d404faa1 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -41,6 +41,7 @@ #include <linux/dma-mapping.h> #include <linux/completion.h> #include <linux/device.h> +#include <linux/scatterlist.h> #include <asm/uaccess.h> #include <asm/vio.h> @@ -270,6 +271,7 @@ static int send_request(struct request *req) d = req->rq_disk->private_data; /* Now build the scatter-gather list */ + sg_init_table(sg, VIOMAXBLOCKDMA); nsg = blk_rq_map_sg(req->q, req, sg); nsg = dma_map_sg(d->dev, sg, nsg, direction); diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 2f307c4df33..67588326ae5 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -606,7 +606,7 @@ static int at_context_queue_packet(struct context *ctx, struct fw_packet *packet) { struct fw_ohci *ohci = ctx->ohci; - dma_addr_t d_bus, payload_bus; + dma_addr_t d_bus, uninitialized_var(payload_bus); struct driver_data *driver_data; struct descriptor *d, *last; __le32 *header; @@ -1459,7 +1459,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) /* FIXME: We need a fallback for pre 1.1 OHCI. */ if (callback == handle_ir_dualbuffer_packet && ohci->version < OHCI_VERSION_1_1) - return ERR_PTR(-EINVAL); + return ERR_PTR(-ENOSYS); spin_lock_irqsave(&ohci->lock, flags); index = ffs(*mask) - 1; @@ -1778,7 +1778,7 @@ ohci_queue_iso(struct fw_iso_context *base, buffer, payload); else /* FIXME: Implement fallback for OHCI 1.0 controllers. */ - return -EINVAL; + return -ENOSYS; } static const struct fw_card_driver ohci_driver = { @@ -1898,7 +1898,12 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff); - + if (ohci->version < OHCI_VERSION_1_1) { + fw_notify(" Isochronous I/O is not yet implemented for " + "OHCI 1.0 chips.\n"); + fw_notify(" Cameras, audio devices etc. won't work on " + "this controller with this driver version.\n"); + } return 0; fail_self_id: diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c index ff20377b4c8..e196aefa207 100644 --- a/drivers/ide/cris/ide-cris.c +++ b/drivers/ide/cris/ide-cris.c @@ -935,11 +935,11 @@ static int cris_ide_build_dmatable (ide_drive_t *drive) * than two possibly non-adjacent physical 4kB pages. */ /* group sequential buffers into one large buffer */ - addr = page_to_phys(sg->page) + sg->offset; + addr = sg_phys(sg); size = sg_dma_len(sg); while (--i) { sg = sg_next(sg); - if ((addr + size) != page_to_phys(sg->page) + sg->offset) + if ((addr + size) != sg_phys(sg)) break; size += sg_dma_len(sg); } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index d5146c57e5b..ec55a173c08 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1317,12 +1317,14 @@ static int hwif_init(ide_hwif_t *hwif) if (!hwif->sg_max_nents) hwif->sg_max_nents = PRD_ENTRIES; - hwif->sg_table = kzalloc(sizeof(struct scatterlist)*hwif->sg_max_nents, + hwif->sg_table = kmalloc(sizeof(struct scatterlist)*hwif->sg_max_nents, GFP_KERNEL); if (!hwif->sg_table) { printk(KERN_ERR "%s: unable to allocate SG table.\n", hwif->name); goto out; } + + sg_init_table(hwif->sg_table, hwif->sg_max_nents); if (init_irq(hwif) == 0) goto done; diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 73ef6bf5fbc..d066546f283 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -261,7 +261,7 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write) hwif->cursg = sg; } - page = cursg->page; + page = sg_page(cursg); offset = cursg->offset + hwif->cursg_ofs * SECTOR_SIZE; /* get the current page and offset */ diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index 1de58566e5b..a4ce3ba15d6 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -276,8 +276,7 @@ static int auide_build_dmatable(ide_drive_t *drive) if (iswrite) { if(!put_source_flags(ahwif->tx_chan, - (void*)(page_address(sg->page) - + sg->offset), + (void*) sg_virt(sg), tc, flags)) { printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); @@ -285,8 +284,7 @@ static int auide_build_dmatable(ide_drive_t *drive) } else { if(!put_dest_flags(ahwif->rx_chan, - (void*)(page_address(sg->page) - + sg->offset), + (void*) sg_virt(sg), tc, flags)) { printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c index 45d60558192..25e113b50d8 100644 --- a/drivers/ieee1394/dma.c +++ b/drivers/ieee1394/dma.c @@ -111,7 +111,7 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, unsigned long va = (unsigned long)dma->kvirt + (i << PAGE_SHIFT); - dma->sglist[i].page = vmalloc_to_page((void *)va); + sg_set_page(&dma->sglist[i], vmalloc_to_page((void *)va)); dma->sglist[i].length = PAGE_SIZE; } diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 1b353b964b3..d5dfe11aa5c 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -1466,7 +1466,7 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, cmd->dma_size = sgpnt[0].length; cmd->dma_type = CMD_DMA_PAGE; cmd->cmd_dma = dma_map_page(hi->host->device.parent, - sgpnt[0].page, sgpnt[0].offset, + sg_page(&sgpnt[0]), sgpnt[0].offset, cmd->dma_size, cmd->dma_dir); orb->data_descriptor_lo = cmd->cmd_dma; diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index 2f54e29dc7a..14159ff2940 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -55,9 +55,11 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d ib_dma_unmap_sg(dev, chunk->page_list, chunk->nents, DMA_BIDIRECTIONAL); for (i = 0; i < chunk->nents; ++i) { + struct page *page = sg_page(&chunk->page_list[i]); + if (umem->writable && dirty) - set_page_dirty_lock(chunk->page_list[i].page); - put_page(chunk->page_list[i].page); + set_page_dirty_lock(page); + put_page(page); } kfree(chunk); @@ -164,11 +166,12 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, } chunk->nents = min_t(int, ret, IB_UMEM_MAX_PAGE_CHUNK); + sg_init_table(chunk->page_list, chunk->nents); for (i = 0; i < chunk->nents; ++i) { if (vma_list && !is_vm_hugetlb_page(vma_list[i + off])) umem->hugetlb = 0; - chunk->page_list[i].page = page_list[i + off]; + sg_set_page(&chunk->page_list[i], page_list[i + off]); chunk->page_list[i].offset = 0; chunk->page_list[i].length = PAGE_SIZE; } @@ -179,7 +182,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, DMA_BIDIRECTIONAL); if (chunk->nmap <= 0) { for (i = 0; i < chunk->nents; ++i) - put_page(chunk->page_list[i].page); + put_page(sg_page(&chunk->page_list[i])); kfree(chunk); ret = -ENOMEM; diff --git a/drivers/infiniband/hw/ipath/ipath_dma.c b/drivers/infiniband/hw/ipath/ipath_dma.c index 22709a4f8fc..e90a0ea538a 100644 --- a/drivers/infiniband/hw/ipath/ipath_dma.c +++ b/drivers/infiniband/hw/ipath/ipath_dma.c @@ -108,7 +108,7 @@ static int ipath_map_sg(struct ib_device *dev, struct scatterlist *sgl, BUG_ON(!valid_dma_direction(direction)); for_each_sg(sgl, sg, nents, i) { - addr = (u64) page_address(sg->page); + addr = (u64) page_address(sg_page(sg)); /* TODO: handle highmem pages */ if (!addr) { ret = 0; @@ -127,7 +127,7 @@ static void ipath_unmap_sg(struct ib_device *dev, static u64 ipath_sg_dma_address(struct ib_device *dev, struct scatterlist *sg) { - u64 addr = (u64) page_address(sg->page); + u64 addr = (u64) page_address(sg_page(sg)); if (addr) addr += sg->offset; diff --git a/drivers/infiniband/hw/ipath/ipath_mr.c b/drivers/infiniband/hw/ipath/ipath_mr.c index e442470a237..db4ba92f79f 100644 --- a/drivers/infiniband/hw/ipath/ipath_mr.c +++ b/drivers/infiniband/hw/ipath/ipath_mr.c @@ -225,7 +225,7 @@ struct ib_mr *ipath_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, for (i = 0; i < chunk->nents; i++) { void *vaddr; - vaddr = page_address(chunk->page_list[i].page); + vaddr = page_address(sg_page(&chunk->page_list[i])); if (!vaddr) { ret = ERR_PTR(-EINVAL); goto bail; diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index e61f3e62698..007b38157fc 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -71,7 +71,7 @@ static void mthca_free_icm_pages(struct mthca_dev *dev, struct mthca_icm_chunk * PCI_DMA_BIDIRECTIONAL); for (i = 0; i < chunk->npages; ++i) - __free_pages(chunk->mem[i].page, + __free_pages(sg_page(&chunk->mem[i]), get_order(chunk->mem[i].length)); } @@ -81,7 +81,7 @@ static void mthca_free_icm_coherent(struct mthca_dev *dev, struct mthca_icm_chun for (i = 0; i < chunk->npages; ++i) { dma_free_coherent(&dev->pdev->dev, chunk->mem[i].length, - lowmem_page_address(chunk->mem[i].page), + lowmem_page_address(sg_page(&chunk->mem[i])), sg_dma_address(&chunk->mem[i])); } } @@ -107,10 +107,13 @@ void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm, int coherent) static int mthca_alloc_icm_pages(struct scatterlist *mem, int order, gfp_t gfp_mask) { - mem->page = alloc_pages(gfp_mask, order); - if (!mem->page) + struct page *page; + + page = alloc_pages(gfp_mask, order); + if (!page) return -ENOMEM; + sg_set_page(mem, page); mem->length = PAGE_SIZE << order; mem->offset = 0; return 0; @@ -157,6 +160,7 @@ struct mthca_icm *mthca_alloc_icm(struct mthca_dev *dev, int npages, if (!chunk) goto fail; + sg_init_table(chunk->mem, MTHCA_ICM_CHUNK_LEN); chunk->npages = 0; chunk->nsg = 0; list_add_tail(&chunk->list, &icm->chunk_list); @@ -304,7 +308,7 @@ void *mthca_table_find(struct mthca_icm_table *table, int obj, dma_addr_t *dma_h * so if we found the page, dma_handle has already * been assigned to. */ if (chunk->mem[i].length > offset) { - page = chunk->mem[i].page; + page = sg_page(&chunk->mem[i]); goto out; } offset -= chunk->mem[i].length; @@ -445,6 +449,7 @@ static u64 mthca_uarc_virt(struct mthca_dev *dev, struct mthca_uar *uar, int pag int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, struct mthca_user_db_table *db_tab, int index, u64 uaddr) { + struct page *pages[1]; int ret = 0; u8 status; int i; @@ -472,16 +477,17 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, } ret = get_user_pages(current, current->mm, uaddr & PAGE_MASK, 1, 1, 0, - &db_tab->page[i].mem.page, NULL); + pages, NULL); if (ret < 0) goto out; + sg_set_page(&db_tab->page[i].mem, pages[0]); db_tab->page[i].mem.length = MTHCA_ICM_PAGE_SIZE; db_tab->page[i].mem.offset = uaddr & ~PAGE_MASK; ret = pci_map_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); if (ret < 0) { - put_page(db_tab->page[i].mem.page); + put_page(pages[0]); goto out; } @@ -491,7 +497,7 @@ int mthca_map_user_db(struct mthca_dev *dev, struct mthca_uar *uar, ret = -EINVAL; if (ret) { pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); - put_page(db_tab->page[i].mem.page); + put_page(sg_page(&db_tab->page[i].mem)); goto out; } @@ -557,7 +563,7 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar, if (db_tab->page[i].uvirt) { mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, uar, i), 1, &status); pci_unmap_sg(dev->pdev, &db_tab->page[i].mem, 1, PCI_DMA_TODEVICE); - put_page(db_tab->page[i].mem.page); + put_page(sg_page(&db_tab->page[i].mem)); } } diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c index f3529b6f0a3..d6879806179 100644 --- a/drivers/infiniband/ulp/iser/iser_memory.c +++ b/drivers/infiniband/ulp/iser/iser_memory.c @@ -131,7 +131,7 @@ static int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, p = mem; for_each_sg(sgl, sg, data->size, i) { - from = kmap_atomic(sg->page, KM_USER0); + from = kmap_atomic(sg_page(sg), KM_USER0); memcpy(p, from + sg->offset, sg->length); @@ -191,7 +191,7 @@ void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, p = mem; for_each_sg(sgl, sg, sg_size, i) { - to = kmap_atomic(sg->page, KM_SOFTIRQ0); + to = kmap_atomic(sg_page(sg), KM_SOFTIRQ0); memcpy(to + sg->offset, p, sg->length); @@ -300,7 +300,7 @@ static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data, for_each_sg(sgl, sg, data->dma_nents, i) { /* iser_dbg("Checking sg iobuf [%d]: phys=0x%08lX " "offset: %ld sz: %ld\n", i, - (unsigned long)page_to_phys(sg->page), + (unsigned long)sg_phys(sg), (unsigned long)sg->offset, (unsigned long)sg->length); */ end_addr = ib_sg_dma_address(ibdev, sg) + @@ -336,7 +336,7 @@ static void iser_data_buf_dump(struct iser_data_buf *data, iser_err("sg[%d] dma_addr:0x%lX page:0x%p " "off:0x%x sz:0x%x dma_len:0x%x\n", i, (unsigned long)ib_sg_dma_address(ibdev, sg), - sg->page, sg->offset, + sg_page(sg), sg->offset, sg->length, ib_sg_dma_len(ibdev, sg)); } diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 0eb5416798b..ac54f697c50 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -348,16 +348,17 @@ static int crypt_convert(struct crypt_config *cc, ctx->idx_out < ctx->bio_out->bi_vcnt) { struct bio_vec *bv_in = bio_iovec_idx(ctx->bio_in, ctx->idx_in); struct bio_vec *bv_out = bio_iovec_idx(ctx->bio_out, ctx->idx_out); - struct scatterlist sg_in = { - .page = bv_in->bv_page, - .offset = bv_in->bv_offset + ctx->offset_in, - .length = 1 << SECTOR_SHIFT - }; - struct scatterlist sg_out = { - .page = bv_out->bv_page, - .offset = bv_out->bv_offset + ctx->offset_out, - .length = 1 << SECTOR_SHIFT - }; + struct scatterlist sg_in, sg_out; + + sg_init_table(&sg_in, 1); + sg_set_page(&sg_in, bv_in->bv_page); + sg_in.offset = bv_in->bv_offset + ctx->offset_in; + sg_in.length = 1 << SECTOR_SHIFT; + + sg_init_table(&sg_out, 1); + sg_set_page(&sg_out, bv_out->bv_page); + sg_out.offset = bv_out->bv_offset + ctx->offset_out; + sg_out.length = 1 << SECTOR_SHIFT; ctx->offset_in += sg_in.length; if (ctx->offset_in >= bv_in->bv_len) { diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c index 365a22118a0..2b1f8b4be00 100644 --- a/drivers/media/common/saa7146_core.c +++ b/drivers/media/common/saa7146_core.c @@ -112,12 +112,13 @@ static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL); if (NULL == sglist) return NULL; + sg_init_table(sglist, nr_pages); for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) { pg = vmalloc_to_page(virt); if (NULL == pg) goto err; BUG_ON(PageHighMem(pg)); - sglist[i].page = pg; + sg_set_page(&sglist[i], pg); sglist[i].length = PAGE_SIZE; } return sglist; diff --git a/drivers/media/video/ivtv/ivtv-udma.c b/drivers/media/video/ivtv/ivtv-udma.c index c4626d1cdf4..912b424e520 100644 --- a/drivers/media/video/ivtv/ivtv-udma.c +++ b/drivers/media/video/ivtv/ivtv-udma.c @@ -63,10 +63,10 @@ int ivtv_udma_fill_sg_list (struct ivtv_user_dma *dma, struct ivtv_dma_page_info memcpy(page_address(dma->bouncemap[map_offset]) + offset, src, len); kunmap_atomic(src, KM_BOUNCE_READ); local_irq_restore(flags); - dma->SGlist[map_offset].page = dma->bouncemap[map_offset]; + sg_set_page(&dma->SGlist[map_offset], dma->bouncemap[map_offset]); } else { - dma->SGlist[map_offset].page = dma->map[map_offset]; + sg_set_page(&dma->SGlist[map_offset], dma->map[map_offset]); } offset = 0; map_offset++; diff --git a/drivers/media/video/videobuf-dma-sg.c b/drivers/media/video/videobuf-dma-sg.c index 3eb6123227b..0a18286279d 100644 --- a/drivers/media/video/videobuf-dma-sg.c +++ b/drivers/media/video/videobuf-dma-sg.c @@ -60,12 +60,13 @@ videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages) sglist = kcalloc(nr_pages, sizeof(struct scatterlist), GFP_KERNEL); if (NULL == sglist) return NULL; + sg_init_table(sglist, nr_pages); for (i = 0; i < nr_pages; i++, virt += PAGE_SIZE) { pg = vmalloc_to_page(virt); if (NULL == pg) goto err; BUG_ON(PageHighMem(pg)); - sglist[i].page = pg; + sg_set_page(&sglist[i], pg); sglist[i].length = PAGE_SIZE; } return sglist; @@ -86,13 +87,14 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) sglist = kcalloc(nr_pages, sizeof(*sglist), GFP_KERNEL); if (NULL == sglist) return NULL; + sg_init_table(sglist, nr_pages); if (NULL == pages[0]) goto nopage; if (PageHighMem(pages[0])) /* DMA to highmem pages might not work */ goto highmem; - sglist[0].page = pages[0]; + sg_set_page(&sglist[0], pages[0]); sglist[0].offset = offset; sglist[0].length = PAGE_SIZE - offset; for (i = 1; i < nr_pages; i++) { @@ -100,7 +102,7 @@ videobuf_pages_to_sg(struct page **pages, int nr_pages, int offset) goto nopage; if (PageHighMem(pages[i])) goto highmem; - sglist[i].page = pages[i]; + sg_set_page(&sglist[i], pages[i]); sglist[i].length = PAGE_SIZE; } return sglist; diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index a5d0354bbbd..9203a0b221b 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -13,6 +13,7 @@ #include <linux/blkdev.h> #include <linux/freezer.h> #include <linux/kthread.h> +#include <linux/scatterlist.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> @@ -153,19 +154,21 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock blk_queue_max_hw_segments(mq->queue, bouncesz / 512); blk_queue_max_segment_size(mq->queue, bouncesz); - mq->sg = kzalloc(sizeof(struct scatterlist), + mq->sg = kmalloc(sizeof(struct scatterlist), GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; goto cleanup_queue; } + sg_init_table(mq->sg, 1); - mq->bounce_sg = kzalloc(sizeof(struct scatterlist) * + mq->bounce_sg = kmalloc(sizeof(struct scatterlist) * bouncesz / 512, GFP_KERNEL); if (!mq->bounce_sg) { ret = -ENOMEM; goto cleanup_queue; } + sg_init_table(mq->bounce_sg, bouncesz / 512); } } #endif @@ -302,12 +305,12 @@ static void copy_sg(struct scatterlist *dst, unsigned int dst_len, BUG_ON(dst_len == 0); if (dst_size == 0) { - dst_buf = page_address(dst->page) + dst->offset; + dst_buf = sg_virt(dst); dst_size = dst->length; } if (src_size == 0) { - src_buf = page_address(src->page) + src->offset; + src_buf = sg_virt(dst); src_size = src->length; } @@ -353,9 +356,7 @@ unsigned int mmc_queue_map_sg(struct mmc_queue *mq) return 1; } - mq->sg[0].page = virt_to_page(mq->bounce_buf); - mq->sg[0].offset = offset_in_page(mq->bounce_buf); - mq->sg[0].length = 0; + sg_init_one(mq->sg, mq->bounce_buf, 0); while (sg_len) { mq->sg[0].length += mq->bounce_sg[sg_len - 1].length; diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 7a452c2ad1f..b1edcefdd4f 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c @@ -149,7 +149,7 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data sg = &data->sg[i]; - sgbuffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; + sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; amount = min(size, sg->length); size -= amount; @@ -226,7 +226,7 @@ static void at91_mci_pre_dma_read(struct at91mci_host *host) sg = &data->sg[host->transfer_index++]; pr_debug("sg = %p\n", sg); - sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE); + sg->dma_address = dma_map_page(NULL, sg_page(sg), sg->offset, sg->length, DMA_FROM_DEVICE); pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length); @@ -283,7 +283,7 @@ static void at91_mci_post_dma_read(struct at91mci_host *host) int index; /* Swap the contents of the buffer */ - buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset; + buffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; pr_debug("buffer = %p, length = %d\n", buffer, sg->length); for (index = 0; index < (sg->length / 4); index++) @@ -292,7 +292,7 @@ static void at91_mci_post_dma_read(struct at91mci_host *host) kunmap_atomic(buffer, KM_BIO_SRC_IRQ); } - flush_dcache_page(sg->page); + flush_dcache_page(sg_page(sg)); } /* Is there another transfer to trigger? */ diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index 92c4d0dfee4..bcbb6d247bf 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -340,7 +340,7 @@ static void au1xmmc_send_pio(struct au1xmmc_host *host) /* This is the pointer to the data buffer */ sg = &data->sg[host->pio.index]; - sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset; + sg_ptr = sg_virt(sg) + host->pio.offset; /* This is the space left inside the buffer */ sg_len = data->sg[host->pio.index].length - host->pio.offset; @@ -400,7 +400,7 @@ static void au1xmmc_receive_pio(struct au1xmmc_host *host) if (host->pio.index < host->dma.len) { sg = &data->sg[host->pio.index]; - sg_ptr = page_address(sg->page) + sg->offset + host->pio.offset; + sg_ptr = sg_virt(sg) + host->pio.offset; /* This is the space left inside the buffer */ sg_len = sg_dma_len(&data->sg[host->pio.index]) - host->pio.offset; @@ -613,14 +613,11 @@ au1xmmc_prepare_data(struct au1xmmc_host *host, struct mmc_data *data) if (host->flags & HOST_F_XMIT){ ret = au1xxx_dbdma_put_source_flags(channel, - (void *) (page_address(sg->page) + - sg->offset), - len, flags); + (void *) sg_virt(sg), len, flags); } else { ret = au1xxx_dbdma_put_dest_flags(channel, - (void *) (page_address(sg->page) + - sg->offset), + (void *) sg_virt(sg), len, flags); } diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index 6ebc41e7592..fc72e1fadb6 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c @@ -262,7 +262,7 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) } /* Convert back to virtual address */ - host->data_ptr = (u16*)(page_address(data->sg->page) + data->sg->offset); + host->data_ptr = (u16*)sg_virt(sg); host->data_cnt = 0; clear_bit(IMXMCI_PEND_DMA_DATA_b, &host->pending_events); diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 7ae18eaed6c..12c2d807c14 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -813,7 +813,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, && dir == DMA_FROM_DEVICE) dir = DMA_BIDIRECTIONAL; - dma_addr = dma_map_page(dma_dev, sg->page, 0, + dma_addr = dma_map_page(dma_dev, sg_page(sg), 0, PAGE_SIZE, dir); if (direction == DMA_TO_DEVICE) t->tx_dma = dma_addr + sg->offset; @@ -822,7 +822,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, } /* allow pio too; we don't allow highmem */ - kmap_addr = kmap(sg->page); + kmap_addr = kmap(sg_page(sg)); if (direction == DMA_TO_DEVICE) t->tx_buf = kmap_addr + sg->offset; else @@ -855,8 +855,8 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, /* discard mappings */ if (direction == DMA_FROM_DEVICE) - flush_kernel_dcache_page(sg->page); - kunmap(sg->page); + flush_kernel_dcache_page(sg_page(sg)); + kunmap(sg_page(sg)); if (dma_dev) dma_unmap_page(dma_dev, dma_addr, PAGE_SIZE, dir); diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 60a67dfcda6..971e18b91f4 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -24,10 +24,10 @@ #include <linux/mmc/host.h> #include <linux/mmc/card.h> #include <linux/clk.h> +#include <linux/scatterlist.h> #include <asm/io.h> #include <asm/irq.h> -#include <asm/scatterlist.h> #include <asm/mach-types.h> #include <asm/arch/board.h> @@ -383,7 +383,7 @@ mmc_omap_sg_to_buf(struct mmc_omap_host *host) sg = host->data->sg + host->sg_idx; host->buffer_bytes_left = sg->length; - host->buffer = page_address(sg->page) + sg->offset; + host->buffer = sg_virt(sg); if (host->buffer_bytes_left > host->total_bytes_left) host->buffer_bytes_left = host->total_bytes_left; } diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index b397121b947..0db837e44b7 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -231,7 +231,7 @@ static void sdhci_deactivate_led(struct sdhci_host *host) static inline char* sdhci_sg_to_buffer(struct sdhci_host* host) { - return page_address(host->cur_sg->page) + host->cur_sg->offset; + return sg_virt(host->cur_sg); } static inline int sdhci_next_sg(struct sdhci_host* host) diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index 9b904795eb7..c11a3d25605 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c @@ -192,7 +192,7 @@ static void tifm_sd_transfer_data(struct tifm_sd *host) } off = sg[host->sg_pos].offset + host->block_pos; - pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT); + pg = nth_page(sg_page(&sg[host->sg_pos]), off >> PAGE_SHIFT); p_off = offset_in_page(off); p_cnt = PAGE_SIZE - p_off; p_cnt = min(p_cnt, cnt); @@ -241,18 +241,18 @@ static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data) } off = sg[host->sg_pos].offset + host->block_pos; - pg = nth_page(sg[host->sg_pos].page, off >> PAGE_SHIFT); + pg = nth_page(sg_page(&sg[host->sg_pos]), off >> PAGE_SHIFT); p_off = offset_in_page(off); p_cnt = PAGE_SIZE - p_off; p_cnt = min(p_cnt, cnt); p_cnt = min(p_cnt, t_size); if (r_data->flags & MMC_DATA_WRITE) - tifm_sd_copy_page(host->bounce_buf.page, + tifm_sd_copy_page(sg_page(&host->bounce_buf), r_data->blksz - t_size, pg, p_off, p_cnt); else if (r_data->flags & MMC_DATA_READ) - tifm_sd_copy_page(pg, p_off, host->bounce_buf.page, + tifm_sd_copy_page(pg, p_off, sg_page(&host->bounce_buf), r_data->blksz - t_size, p_cnt); t_size -= p_cnt; diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index 80db11c05f2..fa4c8c53cc7 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -269,7 +269,7 @@ static inline int wbsd_next_sg(struct wbsd_host *host) static inline char *wbsd_sg_to_buffer(struct wbsd_host *host) { - return page_address(host->cur_sg->page) + host->cur_sg->offset; + return sg_virt(host->cur_sg); } static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) @@ -283,7 +283,7 @@ static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) len = data->sg_len; for (i = 0; i < len; i++) { - sgbuf = page_address(sg[i].page) + sg[i].offset; + sgbuf = sg_virt(&sg[i]); memcpy(dmabuf, sgbuf, sg[i].length); dmabuf += sg[i].length; } @@ -300,7 +300,7 @@ static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data) len = data->sg_len; for (i = 0; i < len; i++) { - sgbuf = page_address(sg[i].page) + sg[i].offset; + sgbuf = sg_virt(&sg[i]); memcpy(sgbuf, dmabuf, sg[i].length); dmabuf += sg[i].length; } diff --git a/drivers/net/mlx4/icm.c b/drivers/net/mlx4/icm.c index 4b3c109d5ea..887633b207d 100644 --- a/drivers/net/mlx4/icm.c +++ b/drivers/net/mlx4/icm.c @@ -60,7 +60,7 @@ static void mlx4_free_icm_pages(struct mlx4_dev *dev, struct mlx4_icm_chunk *chu PCI_DMA_BIDIRECTIONAL); for (i = 0; i < chunk->npages; ++i) - __free_pages(chunk->mem[i].page, + __free_pages(sg_page(&chunk->mem[i]), get_order(chunk->mem[i].length)); } @@ -70,7 +70,7 @@ static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk * for (i = 0; i < chunk->npages; ++i) dma_free_coherent(&dev->pdev->dev, chunk->mem[i].length, - lowmem_page_address(chunk->mem[i].page), + lowmem_page_address(sg_page(&chunk->mem[i])), sg_dma_address(&chunk->mem[i])); } @@ -95,10 +95,13 @@ void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent) static int mlx4_alloc_icm_pages(struct scatterlist *mem, int order, gfp_t gfp_mask) { - mem->page = alloc_pages(gfp_mask, order); - if (!mem->page) + struct page *page; + + page = alloc_pages(gfp_mask, order); + if (!page) return -ENOMEM; + sg_set_page(mem, page); mem->length = PAGE_SIZE << order; mem->offset = 0; return 0; @@ -145,6 +148,7 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages, if (!chunk) goto fail; + sg_init_table(chunk->mem, MLX4_ICM_CHUNK_LEN); chunk->npages = 0; chunk->nsg = 0; list_add_tail(&chunk->list, &icm->chunk_list); @@ -334,7 +338,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_han * been assigned to. */ if (chunk->mem[i].length > offset) { - page = chunk->mem[i].page; + page = sg_page(&chunk->mem[i]); goto out; } offset -= chunk->mem[i].length; diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp_mppe.c index c0b6d19d145..bcb0885011c 100644 --- a/drivers/net/ppp_mppe.c +++ b/drivers/net/ppp_mppe.c @@ -55,7 +55,7 @@ #include <linux/mm.h> #include <linux/ppp_defs.h> #include <linux/ppp-comp.h> -#include <asm/scatterlist.h> +#include <linux/scatterlist.h> #include "ppp_mppe.h" @@ -68,9 +68,7 @@ MODULE_VERSION("1.0.2"); static unsigned int setup_sg(struct scatterlist *sg, const void *address, unsigned int length) { - sg[0].page = virt_to_page(address); - sg[0].offset = offset_in_page(address); - sg[0].length = length; + sg_init_one(sg, address, length); return length; } diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 5b86ee5c1ee..5eace9e66e1 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -557,44 +557,6 @@ lba_bios_init(void) #ifdef CONFIG_64BIT /* -** Determine if a device is already configured. -** If so, reserve it resources. -** -** Read PCI cfg command register and see if I/O or MMIO is enabled. -** PAT has to enable the devices it's using. -** -** Note: resources are fixed up before we try to claim them. -*/ -static void -lba_claim_dev_resources(struct pci_dev *dev) -{ - u16 cmd; - int i, srch_flags; - - (void) pci_read_config_word(dev, PCI_COMMAND, &cmd); - - srch_flags = (cmd & PCI_COMMAND_IO) ? IORESOURCE_IO : 0; - if (cmd & PCI_COMMAND_MEMORY) - srch_flags |= IORESOURCE_MEM; - - if (!srch_flags) - return; - - for (i = 0; i <= PCI_ROM_RESOURCE; i++) { - if (dev->resource[i].flags & srch_flags) { - pci_claim_resource(dev, i); - DBG(" claimed %s %d [%lx,%lx]/%lx\n", - pci_name(dev), i, - dev->resource[i].start, - dev->resource[i].end, - dev->resource[i].flags - ); - } - } -} - - -/* * truncate_pat_collision: Deal with overlaps or outright collisions * between PAT PDC reported ranges. * @@ -653,7 +615,6 @@ truncate_pat_collision(struct resource *root, struct resource *new) } #else -#define lba_claim_dev_resources(dev) do { } while (0) #define truncate_pat_collision(r,n) (0) #endif @@ -684,8 +645,12 @@ lba_fixup_bus(struct pci_bus *bus) ** pci_alloc_primary_bus() mangles this. */ if (bus->self) { + int i; /* PCI-PCI Bridge */ pci_read_bridge_bases(bus); + for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { + pci_claim_resource(bus->self, i); + } } else { /* Host-PCI Bridge */ int err, i; @@ -803,6 +768,9 @@ lba_fixup_bus(struct pci_bus *bus) DBG("lba_fixup_bus() WTF? 0x%lx [%lx/%lx] XXX", res->flags, res->start, res->end); } + if ((i != PCI_ROM_RESOURCE) || + (res->flags & IORESOURCE_ROM_ENABLE)) + pci_claim_resource(dev, i); } #ifdef FBB_SUPPORT @@ -814,11 +782,6 @@ lba_fixup_bus(struct pci_bus *bus) bus->bridge_ctl &= ~(status & PCI_STATUS_FAST_BACK); #endif - if (is_pdc_pat()) { - /* Claim resources for PDC's devices */ - lba_claim_dev_resources(dev); - } - /* ** P2PB's have no IRQs. ignore them. */ diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index fc4bde259dc..ebb09e98d21 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -282,6 +282,7 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun unsigned short i; char in[count+1], *temp; struct device *dev; + int ret; if (!entry || !buf || !count) return -EINVAL; @@ -333,7 +334,9 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun /* Update the symlink to the real device */ sysfs_remove_link(&entry->kobj, "device"); - sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); + ret = sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); + WARN_ON(ret); + write_unlock(&entry->rw_lock); printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" path to \"%s\"\n", @@ -1003,8 +1006,10 @@ pdcs_register_pathentries(void) entry->ready = 2; /* Add a nice symlink to the real device */ - if (entry->dev) - sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); + if (entry->dev) { + err = sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); + WARN_ON(err); + } write_unlock(&entry->rw_lock); } diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index d044c48323e..e5c323936ea 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1909,8 +1909,8 @@ sba_driver_callback(struct parisc_device *dev) global_ioc_cnt *= 2; } - printk(KERN_INFO "%s found %s at 0x%lx\n", - MODULE_NAME, version, dev->hpa.start); + printk(KERN_INFO "%s found %s at 0x%llx\n", + MODULE_NAME, version, (unsigned long long)dev->hpa.start); sba_dev = kzalloc(sizeof(struct sba_device), GFP_KERNEL); if (!sba_dev) { diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 38cdf9fa36a..1e8d2d17f04 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -155,6 +155,7 @@ superio_init(struct pci_dev *pcidev) struct superio_device *sio = &sio_dev; struct pci_dev *pdev = sio->lio_pdev; u16 word; + int ret; if (sio->suckyio_irq_enabled) return; @@ -200,7 +201,8 @@ superio_init(struct pci_dev *pcidev) pci_write_config_word (pdev, PCI_COMMAND, word); pci_set_master (pdev); - pci_enable_device(pdev); + ret = pci_enable_device(pdev); + BUG_ON(ret < 0); /* not too much we can do about this... */ /* * Next project is programming the onboard interrupt controllers. diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 006054a4099..55505565073 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -20,6 +20,9 @@ obj-$(CONFIG_PCI_MSI) += msi.o # Build the Hypertransport interrupt support obj-$(CONFIG_HT_IRQ) += htirq.o +# Build Intel IOMMU support +obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o + # # Some architectures use the generic PCI setup functions # diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c new file mode 100644 index 00000000000..5dfdfdac92e --- /dev/null +++ b/drivers/pci/dmar.c @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Copyright (C) Ashok Raj <ashok.raj@intel.com> + * Copyright (C) Shaohua Li <shaohua.li@intel.com> + * Copyright (C) Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> + * + * This file implements early detection/parsing of DMA Remapping Devices + * reported to OS through BIOS via DMA remapping reporting (DMAR) ACPI + * tables. + */ + +#include <linux/pci.h> +#include <linux/dmar.h> + +#undef PREFIX +#define PREFIX "DMAR:" + +/* No locks are needed as DMA remapping hardware unit + * list is constructed at boot time and hotplug of + * these units are not supported by the architecture. + */ +LIST_HEAD(dmar_drhd_units); +LIST_HEAD(dmar_rmrr_units); + +static struct acpi_table_header * __initdata dmar_tbl; + +static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd) +{ + /* + * add INCLUDE_ALL at the tail, so scan the list will find it at + * the very end. + */ + if (drhd->include_all) + list_add_tail(&drhd->list, &dmar_drhd_units); + else + list_add(&drhd->list, &dmar_drhd_units); +} + +static void __init dmar_register_rmrr_unit(struct dmar_rmrr_unit *rmrr) +{ + list_add(&rmrr->list, &dmar_rmrr_units); +} + +static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope, + struct pci_dev **dev, u16 segment) +{ + struct pci_bus *bus; + struct pci_dev *pdev = NULL; + struct acpi_dmar_pci_path *path; + int count; + + bus = pci_find_bus(segment, scope->bus); + path = (struct acpi_dmar_pci_path *)(scope + 1); + count = (scope->length - sizeof(struct acpi_dmar_device_scope)) + / sizeof(struct acpi_dmar_pci_path); + + while (count) { + if (pdev) + pci_dev_put(pdev); + /* + * Some BIOSes list non-exist devices in DMAR table, just + * ignore it + */ + if (!bus) { + printk(KERN_WARNING + PREFIX "Device scope bus [%d] not found\n", + scope->bus); + break; + } + pdev = pci_get_slot(bus, PCI_DEVFN(path->dev, path->fn)); + if (!pdev) { + printk(KERN_WARNING PREFIX + "Device scope device [%04x:%02x:%02x.%02x] not found\n", + segment, bus->number, path->dev, path->fn); + break; + } + path ++; + count --; + bus = pdev->subordinate; + } + if (!pdev) { + printk(KERN_WARNING PREFIX + "Device scope device [%04x:%02x:%02x.%02x] not found\n", + segment, scope->bus, path->dev, path->fn); + *dev = NULL; + return 0; + } + if ((scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT && \ + pdev->subordinate) || (scope->entry_type == \ + ACPI_DMAR_SCOPE_TYPE_BRIDGE && !pdev->subordinate)) { + pci_dev_put(pdev); + printk(KERN_WARNING PREFIX + "Device scope type does not match for %s\n", + pci_name(pdev)); + return -EINVAL; + } + *dev = pdev; + return 0; +} + +static int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, + struct pci_dev ***devices, u16 segment) +{ + struct acpi_dmar_device_scope *scope; + void * tmp = start; + int index; + int ret; + + *cnt = 0; + while (start < end) { + scope = start; + if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || + scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) + (*cnt)++; + else + printk(KERN_WARNING PREFIX + "Unsupported device scope\n"); + start += scope->length; + } + if (*cnt == 0) + return 0; + + *devices = kcalloc(*cnt, sizeof(struct pci_dev *), GFP_KERNEL); + if (!*devices) + return -ENOMEM; + + start = tmp; + index = 0; + while (start < end) { + scope = start; + if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_ENDPOINT || + scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE) { + ret = dmar_parse_one_dev_scope(scope, + &(*devices)[index], segment); + if (ret) { + kfree(*devices); + return ret; + } + index ++; + } + start += scope->length; + } + + return 0; +} + +/** + * dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition + * structure which uniquely represent one DMA remapping hardware unit + * present in the platform + */ +static int __init +dmar_parse_one_drhd(struct acpi_dmar_header *header) +{ + struct acpi_dmar_hardware_unit *drhd; + struct dmar_drhd_unit *dmaru; + int ret = 0; + static int include_all; + + dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL); + if (!dmaru) + return -ENOMEM; + + drhd = (struct acpi_dmar_hardware_unit *)header; + dmaru->reg_base_addr = drhd->address; + dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ + + if (!dmaru->include_all) + ret = dmar_parse_dev_scope((void *)(drhd + 1), + ((void *)drhd) + header->length, + &dmaru->devices_cnt, &dmaru->devices, + drhd->segment); + else { + /* Only allow one INCLUDE_ALL */ + if (include_all) { + printk(KERN_WARNING PREFIX "Only one INCLUDE_ALL " + "device scope is allowed\n"); + ret = -EINVAL; + } + include_all = 1; + } + + if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) + kfree(dmaru); + else + dmar_register_drhd_unit(dmaru); + return ret; +} + +static int __init +dmar_parse_one_rmrr(struct acpi_dmar_header *header) +{ + struct acpi_dmar_reserved_memory *rmrr; + struct dmar_rmrr_unit *rmrru; + int ret = 0; + + rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL); + if (!rmrru) + return -ENOMEM; + + rmrr = (struct acpi_dmar_reserved_memory *)header; + rmrru->base_address = rmrr->base_address; + rmrru->end_address = rmrr->end_address; + ret = dmar_parse_dev_scope((void *)(rmrr + 1), + ((void *)rmrr) + header->length, + &rmrru->devices_cnt, &rmrru->devices, rmrr->segment); + + if (ret || (rmrru->devices_cnt == 0)) + kfree(rmrru); + else + dmar_register_rmrr_unit(rmrru); + return ret; +} + +static void __init +dmar_table_print_dmar_entry(struct acpi_dmar_header *header) +{ + struct acpi_dmar_hardware_unit *drhd; + struct acpi_dmar_reserved_memory *rmrr; + + switch (header->type) { + case ACPI_DMAR_TYPE_HARDWARE_UNIT: + drhd = (struct acpi_dmar_hardware_unit *)header; + printk (KERN_INFO PREFIX + "DRHD (flags: 0x%08x)base: 0x%016Lx\n", + drhd->flags, drhd->address); + break; + case ACPI_DMAR_TYPE_RESERVED_MEMORY: + rmrr = (struct acpi_dmar_reserved_memory *)header; + + printk (KERN_INFO PREFIX + "RMRR base: 0x%016Lx end: 0x%016Lx\n", + rmrr->base_address, rmrr->end_address); + break; + } +} + +/** + * parse_dmar_table - parses the DMA reporting table + */ +static int __init +parse_dmar_table(void) +{ + struct acpi_table_dmar *dmar; + struct acpi_dmar_header *entry_header; + int ret = 0; + + dmar = (struct acpi_table_dmar *)dmar_tbl; + if (!dmar) + return -ENODEV; + + if (!dmar->width) { + printk (KERN_WARNING PREFIX "Zero: Invalid DMAR haw\n"); + return -EINVAL; + } + + printk (KERN_INFO PREFIX "Host address width %d\n", + dmar->width + 1); + + entry_header = (struct acpi_dmar_header *)(dmar + 1); + while (((unsigned long)entry_header) < + (((unsigned long)dmar) + dmar_tbl->length)) { + dmar_table_print_dmar_entry(entry_header); + + switch (entry_header->type) { + case ACPI_DMAR_TYPE_HARDWARE_UNIT: + ret = dmar_parse_one_drhd(entry_header); + break; + case ACPI_DMAR_TYPE_RESERVED_MEMORY: + ret = dmar_parse_one_rmrr(entry_header); + break; + default: + printk(KERN_WARNING PREFIX + "Unknown DMAR structure type\n"); + ret = 0; /* for forward compatibility */ + break; + } + if (ret) + break; + + entry_header = ((void *)entry_header + entry_header->length); + } + return ret; +} + + +int __init dmar_table_init(void) +{ + + parse_dmar_table(); + if (list_empty(&dmar_drhd_units)) { + printk(KERN_INFO PREFIX "No DMAR devices found\n"); + return -ENODEV; + } + return 0; +} + +/** + * early_dmar_detect - checks to see if the platform supports DMAR devices + */ +int __init early_dmar_detect(void) +{ + acpi_status status = AE_OK; + + /* if we could find DMAR table, then there are DMAR devices */ + status = acpi_get_table(ACPI_SIG_DMAR, 0, + (struct acpi_table_header **)&dmar_tbl); + + if (ACPI_SUCCESS(status) && !dmar_tbl) { + printk (KERN_WARNING PREFIX "Unable to map DMAR\n"); + status = AE_NOT_FOUND; + } + + return (ACPI_SUCCESS(status) ? 1 : 0); +} diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c new file mode 100644 index 00000000000..b3d70310af4 --- /dev/null +++ b/drivers/pci/intel-iommu.c @@ -0,0 +1,2271 @@ +/* + * Copyright (c) 2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Copyright (C) Ashok Raj <ashok.raj@intel.com> + * Copyright (C) Shaohua Li <shaohua.li@intel.com> + * Copyright (C) Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> + */ + +#include <linux/init.h> +#include <linux/bitmap.h> +#include <linux/slab.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/sysdev.h> +#include <linux/spinlock.h> +#include <linux/pci.h> +#include <linux/dmar.h> +#include <linux/dma-mapping.h> +#include <linux/mempool.h> +#include "iova.h" +#include "intel-iommu.h" +#include <asm/proto.h> /* force_iommu in this header in x86-64*/ +#include <asm/cacheflush.h> +#include <asm/iommu.h> +#include "pci.h" + +#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) +#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) + +#define IOAPIC_RANGE_START (0xfee00000) +#define IOAPIC_RANGE_END (0xfeefffff) +#define IOVA_START_ADDR (0x1000) + +#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48 + +#define DMAR_OPERATION_TIMEOUT (HZ*60) /* 1m */ + +#define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) + +static void domain_remove_dev_info(struct dmar_domain *domain); + +static int dmar_disabled; +static int __initdata dmar_map_gfx = 1; +static int dmar_forcedac; + +#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1)) +static DEFINE_SPINLOCK(device_domain_lock); +static LIST_HEAD(device_domain_list); + +static int __init intel_iommu_setup(char *str) +{ + if (!str) + return -EINVAL; + while (*str) { + if (!strncmp(str, "off", 3)) { + dmar_disabled = 1; + printk(KERN_INFO"Intel-IOMMU: disabled\n"); + } else if (!strncmp(str, "igfx_off", 8)) { + dmar_map_gfx = 0; + printk(KERN_INFO + "Intel-IOMMU: disable GFX device mapping\n"); + } else if (!strncmp(str, "forcedac", 8)) { + printk (KERN_INFO + "Intel-IOMMU: Forcing DAC for PCI devices\n"); + dmar_forcedac = 1; + } + + str += strcspn(str, ","); + while (*str == ',') + str++; + } + return 0; +} +__setup("intel_iommu=", intel_iommu_setup); + +static struct kmem_cache *iommu_domain_cache; +static struct kmem_cache *iommu_devinfo_cache; +static struct kmem_cache *iommu_iova_cache; + +static inline void *iommu_kmem_cache_alloc(struct kmem_cache *cachep) +{ + unsigned int flags; + void *vaddr; + + /* trying to avoid low memory issues */ + flags = current->flags & PF_MEMALLOC; + current->flags |= PF_MEMALLOC; + vaddr = kmem_cache_alloc(cachep, GFP_ATOMIC); + current->flags &= (~PF_MEMALLOC | flags); + return vaddr; +} + + +static inline void *alloc_pgtable_page(void) +{ + unsigned int flags; + void *vaddr; + + /* trying to avoid low memory issues */ + flags = current->flags & PF_MEMALLOC; + current->flags |= PF_MEMALLOC; + vaddr = (void *)get_zeroed_page(GFP_ATOMIC); + current->flags &= (~PF_MEMALLOC | flags); + return vaddr; +} + +static inline void free_pgtable_page(void *vaddr) +{ + free_page((unsigned long)vaddr); +} + +static inline void *alloc_domain_mem(void) +{ + return iommu_kmem_cache_alloc(iommu_domain_cache); +} + +static inline void free_domain_mem(void *vaddr) +{ + kmem_cache_free(iommu_domain_cache, vaddr); +} + +static inline void * alloc_devinfo_mem(void) +{ + return iommu_kmem_cache_alloc(iommu_devinfo_cache); +} + +static inline void free_devinfo_mem(void *vaddr) +{ + kmem_cache_free(iommu_devinfo_cache, vaddr); +} + +struct iova *alloc_iova_mem(void) +{ + return iommu_kmem_cache_alloc(iommu_iova_cache); +} + +void free_iova_mem(struct iova *iova) +{ + kmem_cache_free(iommu_iova_cache, iova); +} + +static inline void __iommu_flush_cache( + struct intel_iommu *iommu, void *addr, int size) +{ + if (!ecap_coherent(iommu->ecap)) + clflush_cache_range(addr, size); +} + +/* Gets context entry for a given bus and devfn */ +static struct context_entry * device_to_context_entry(struct intel_iommu *iommu, + u8 bus, u8 devfn) +{ + struct root_entry *root; + struct context_entry *context; + unsigned long phy_addr; + unsigned long flags; + + spin_lock_irqsave(&iommu->lock, flags); + root = &iommu->root_entry[bus]; + context = get_context_addr_from_root(root); + if (!context) { + context = (struct context_entry *)alloc_pgtable_page(); + if (!context) { + spin_unlock_irqrestore(&iommu->lock, flags); + return NULL; + } + __iommu_flush_cache(iommu, (void *)context, PAGE_SIZE_4K); + phy_addr = virt_to_phys((void *)context); + set_root_value(root, phy_addr); + set_root_present(root); + __iommu_flush_cache(iommu, root, sizeof(*root)); + } + spin_unlock_irqrestore(&iommu->lock, flags); + return &context[devfn]; +} + +static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn) +{ + struct root_entry *root; + struct context_entry *context; + int ret; + unsigned long flags; + + spin_lock_irqsave(&iommu->lock, flags); + root = &iommu->root_entry[bus]; + context = get_context_addr_from_root(root); + if (!context) { + ret = 0; + goto out; + } + ret = context_present(context[devfn]); +out: + spin_unlock_irqrestore(&iommu->lock, flags); + return ret; +} + +static void clear_context_table(struct intel_iommu *iommu, u8 bus, u8 devfn) +{ + struct root_entry *root; + struct context_entry *context; + unsigned long flags; + + spin_lock_irqsave(&iommu->lock, flags); + root = &iommu->root_entry[bus]; + context = get_context_addr_from_root(root); + if (context) { + context_clear_entry(context[devfn]); + __iommu_flush_cache(iommu, &context[devfn], \ + sizeof(*context)); + } + spin_unlock_irqrestore(&iommu->lock, flags); +} + +static void free_context_table(struct intel_iommu *iommu) +{ + struct root_entry *root; + int i; + unsigned long flags; + struct context_entry *context; + + spin_lock_irqsave(&iommu->lock, flags); + if (!iommu->root_entry) { + goto out; + } + for (i = 0; i < ROOT_ENTRY_NR; i++) { + root = &iommu->root_entry[i]; + context = get_context_addr_from_root(root); + if (context) + free_pgtable_page(context); + } + free_pgtable_page(iommu->root_entry); + iommu->root_entry = NULL; +out: + spin_unlock_irqrestore(&iommu->lock, flags); +} + +/* page table handling */ +#define LEVEL_STRIDE (9) +#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1) + +static inline int agaw_to_level(int agaw) +{ + return agaw + 2; +} + +static inline int agaw_to_width(int agaw) +{ + return 30 + agaw * LEVEL_STRIDE; + +} + +static inline int width_to_agaw(int width) +{ + return (width - 30) / LEVEL_STRIDE; +} + +static inline unsigned int level_to_offset_bits(int level) +{ + return (12 + (level - 1) * LEVEL_STRIDE); +} + +static inline int address_level_offset(u64 addr, int level) +{ + return ((addr >> level_to_offset_bits(level)) & LEVEL_MASK); +} + +static inline u64 level_mask(int level) +{ + return ((u64)-1 << level_to_offset_bits(level)); +} + +static inline u64 level_size(int level) +{ + return ((u64)1 << level_to_offset_bits(level)); +} + +static inline u64 align_to_level(u64 addr, int level) +{ + return ((addr + level_size(level) - 1) & level_mask(level)); +} + +static struct dma_pte * addr_to_dma_pte(struct dmar_domain *domain, u64 addr) +{ + int addr_width = agaw_to_width(domain->agaw); + struct dma_pte *parent, *pte = NULL; + int level = agaw_to_level(domain->agaw); + int offset; + unsigned long flags; + + BUG_ON(!domain->pgd); + + addr &= (((u64)1) << addr_width) - 1; + parent = domain->pgd; + + spin_lock_irqsave(&domain->mapping_lock, flags); + while (level > 0) { + void *tmp_page; + + offset = address_level_offset(addr, level); + pte = &parent[offset]; + if (level == 1) + break; + + if (!dma_pte_present(*pte)) { + tmp_page = alloc_pgtable_page(); + + if (!tmp_page) { + spin_unlock_irqrestore(&domain->mapping_lock, + flags); + return NULL; + } + __iommu_flush_cache(domain->iommu, tmp_page, + PAGE_SIZE_4K); + dma_set_pte_addr(*pte, virt_to_phys(tmp_page)); + /* + * high level table always sets r/w, last level page + * table control read/write + */ + dma_set_pte_readable(*pte); + dma_set_pte_writable(*pte); + __iommu_flush_cache(domain->iommu, pte, sizeof(*pte)); + } + parent = phys_to_virt(dma_pte_addr(*pte)); + level--; + } + + spin_unlock_irqrestore(&domain->mapping_lock, flags); + return pte; +} + +/* return address's pte at specific level */ +static struct dma_pte *dma_addr_level_pte(struct dmar_domain *domain, u64 addr, + int level) +{ + struct dma_pte *parent, *pte = NULL; + int total = agaw_to_level(domain->agaw); + int offset; + + parent = domain->pgd; + while (level <= total) { + offset = address_level_offset(addr, total); + pte = &parent[offset]; + if (level == total) + return pte; + + if (!dma_pte_present(*pte)) + break; + parent = phys_to_virt(dma_pte_addr(*pte)); + total--; + } + return NULL; +} + +/* clear one page's page table */ +static void dma_pte_clear_one(struct dmar_domain *domain, u64 addr) +{ + struct dma_pte *pte = NULL; + + /* get last level pte */ + pte = dma_addr_level_pte(domain, addr, 1); + + if (pte) { + dma_clear_pte(*pte); + __iommu_flush_cache(domain->iommu, pte, sizeof(*pte)); + } +} + +/* clear last level pte, a tlb flush should be followed */ +static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) +{ + int addr_width = agaw_to_width(domain->agaw); + + start &= (((u64)1) << addr_width) - 1; + end &= (((u64)1) << addr_width) - 1; + /* in case it's partial page */ + start = PAGE_ALIGN_4K(start); + end &= PAGE_MASK_4K; + + /* we don't need lock here, nobody else touches the iova range */ + while (start < end) { + dma_pte_clear_one(domain, start); + start += PAGE_SIZE_4K; + } +} + +/* free page table pages. last level pte should already be cleared */ +static void dma_pte_free_pagetable(struct dmar_domain *domain, + u64 start, u64 end) +{ + int addr_width = agaw_to_width(domain->agaw); + struct dma_pte *pte; + int total = agaw_to_level(domain->agaw); + int level; + u64 tmp; + + start &= (((u64)1) << addr_width) - 1; + end &= (((u64)1) << addr_width) - 1; + + /* we don't need lock here, nobody else touches the iova range */ + level = 2; + while (level <= total) { + tmp = align_to_level(start, level); + if (tmp >= end || (tmp + level_size(level) > end)) + return; + + while (tmp < end) { + pte = dma_addr_level_pte(domain, tmp, level); + if (pte) { + free_pgtable_page( + phys_to_virt(dma_pte_addr(*pte))); + dma_clear_pte(*pte); + __iommu_flush_cache(domain->iommu, + pte, sizeof(*pte)); + } + tmp += level_size(level); + } + level++; + } + /* free pgd */ + if (start == 0 && end >= ((((u64)1) << addr_width) - 1)) { + free_pgtable_page(domain->pgd); + domain->pgd = NULL; + } +} + +/* iommu handling */ +static int iommu_alloc_root_entry(struct intel_iommu *iommu) +{ + struct root_entry *root; + unsigned long flags; + + root = (struct root_entry *)alloc_pgtable_page(); + if (!root) + return -ENOMEM; + + __iommu_flush_cache(iommu, root, PAGE_SIZE_4K); + + spin_lock_irqsave(&iommu->lock, flags); + iommu->root_entry = root; + spin_unlock_irqrestore(&iommu->lock, flags); + + return 0; +} + +#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \ +{\ + unsigned long start_time = jiffies;\ + while (1) {\ + sts = op (iommu->reg + offset);\ + if (cond)\ + break;\ + if (time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT))\ + panic("DMAR hardware is malfunctioning\n");\ + cpu_relax();\ + }\ +} + +static void iommu_set_root_entry(struct intel_iommu *iommu) +{ + void *addr; + u32 cmd, sts; + unsigned long flag; + + addr = iommu->root_entry; + + spin_lock_irqsave(&iommu->register_lock, flag); + dmar_writeq(iommu->reg + DMAR_RTADDR_REG, virt_to_phys(addr)); + + cmd = iommu->gcmd | DMA_GCMD_SRTP; + writel(cmd, iommu->reg + DMAR_GCMD_REG); + + /* Make sure hardware complete it */ + IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, + readl, (sts & DMA_GSTS_RTPS), sts); + + spin_unlock_irqrestore(&iommu->register_lock, flag); +} + +static void iommu_flush_write_buffer(struct intel_iommu *iommu) +{ + u32 val; + unsigned long flag; + + if (!cap_rwbf(iommu->cap)) + return; + val = iommu->gcmd | DMA_GCMD_WBF; + + spin_lock_irqsave(&iommu->register_lock, flag); + writel(val, iommu->reg + DMAR_GCMD_REG); + + /* Make sure hardware complete it */ + IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, + readl, (!(val & DMA_GSTS_WBFS)), val); + + spin_unlock_irqrestore(&iommu->register_lock, flag); +} + +/* return value determine if we need a write buffer flush */ +static int __iommu_flush_context(struct intel_iommu *iommu, + u16 did, u16 source_id, u8 function_mask, u64 type, + int non_present_entry_flush) +{ + u64 val = 0; + unsigned long flag; + + /* + * In the non-present entry flush case, if hardware doesn't cache + * non-present entry we do nothing and if hardware cache non-present + * entry, we flush entries of domain 0 (the domain id is used to cache + * any non-present entries) + */ + if (non_present_entry_flush) { + if (!cap_caching_mode(iommu->cap)) + return 1; + else + did = 0; + } + + switch (type) { + case DMA_CCMD_GLOBAL_INVL: + val = DMA_CCMD_GLOBAL_INVL; + break; + case DMA_CCMD_DOMAIN_INVL: + val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did); + break; + case DMA_CCMD_DEVICE_INVL: + val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did) + | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask); + break; + default: + BUG(); + } + val |= DMA_CCMD_ICC; + + spin_lock_irqsave(&iommu->register_lock, flag); + dmar_writeq(iommu->reg + DMAR_CCMD_REG, val); + + /* Make sure hardware complete it */ + IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG, + dmar_readq, (!(val & DMA_CCMD_ICC)), val); + + spin_unlock_irqrestore(&iommu->register_lock, flag); + + /* flush context entry will implictly flush write buffer */ + return 0; +} + +static int inline iommu_flush_context_global(struct intel_iommu *iommu, + int non_present_entry_flush) +{ + return __iommu_flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL, + non_present_entry_flush); +} + +static int inline iommu_flush_context_domain(struct intel_iommu *iommu, u16 did, + int non_present_entry_flush) +{ + return __iommu_flush_context(iommu, did, 0, 0, DMA_CCMD_DOMAIN_INVL, + non_present_entry_flush); +} + +static int inline iommu_flush_context_device(struct intel_iommu *iommu, + u16 did, u16 source_id, u8 function_mask, int non_present_entry_flush) +{ + return __iommu_flush_context(iommu, did, source_id, function_mask, + DMA_CCMD_DEVICE_INVL, non_present_entry_flush); +} + +/* return value determine if we need a write buffer flush */ +static int __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did, + u64 addr, unsigned int size_order, u64 type, + int non_present_entry_flush) +{ + int tlb_offset = ecap_iotlb_offset(iommu->ecap); + u64 val = 0, val_iva = 0; + unsigned long flag; + + /* + * In the non-present entry flush case, if hardware doesn't cache + * non-present entry we do nothing and if hardware cache non-present + * entry, we flush entries of domain 0 (the domain id is used to cache + * any non-present entries) + */ + if (non_present_entry_flush) { + if (!cap_caching_mode(iommu->cap)) + return 1; + else + did = 0; + } + + switch (type) { + case DMA_TLB_GLOBAL_FLUSH: + /* global flush doesn't need set IVA_REG */ + val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT; + break; + case DMA_TLB_DSI_FLUSH: + val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did); + break; + case DMA_TLB_PSI_FLUSH: + val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did); + /* Note: always flush non-leaf currently */ + val_iva = size_order | addr; + break; + default: + BUG(); + } + /* Note: set drain read/write */ +#if 0 + /* + * This is probably to be super secure.. Looks like we can + * ignore it without any impact. + */ + if (cap_read_drain(iommu->cap)) + val |= DMA_TLB_READ_DRAIN; +#endif + if (cap_write_drain(iommu->cap)) + val |= DMA_TLB_WRITE_DRAIN; + + spin_lock_irqsave(&iommu->register_lock, flag); + /* Note: Only uses first TLB reg currently */ + if (val_iva) + dmar_writeq(iommu->reg + tlb_offset, val_iva); + dmar_writeq(iommu->reg + tlb_offset + 8, val); + + /* Make sure hardware complete it */ + IOMMU_WAIT_OP(iommu, tlb_offset + 8, + dmar_readq, (!(val & DMA_TLB_IVT)), val); + + spin_unlock_irqrestore(&iommu->register_lock, flag); + + /* check IOTLB invalidation granularity */ + if (DMA_TLB_IAIG(val) == 0) + printk(KERN_ERR"IOMMU: flush IOTLB failed\n"); + if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type)) + pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n", + DMA_TLB_IIRG(type), DMA_TLB_IAIG(val)); + /* flush context entry will implictly flush write buffer */ + return 0; +} + +static int inline iommu_flush_iotlb_global(struct intel_iommu *iommu, + int non_present_entry_flush) +{ + return __iommu_flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH, + non_present_entry_flush); +} + +static int inline iommu_flush_iotlb_dsi(struct intel_iommu *iommu, u16 did, + int non_present_entry_flush) +{ + return __iommu_flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH, + non_present_entry_flush); +} + +static int iommu_flush_iotlb_psi(struct intel_iommu *iommu, u16 did, + u64 addr, unsigned int pages, int non_present_entry_flush) +{ + unsigned int mask; + + BUG_ON(addr & (~PAGE_MASK_4K)); + BUG_ON(pages == 0); + + /* Fallback to domain selective flush if no PSI support */ + if (!cap_pgsel_inv(iommu->cap)) + return iommu_flush_iotlb_dsi(iommu, did, + non_present_entry_flush); + + /* + * PSI requires page size to be 2 ^ x, and the base address is naturally + * aligned to the size + */ + mask = ilog2(__roundup_pow_of_two(pages)); + /* Fallback to domain selective flush if size is too big */ + if (mask > cap_max_amask_val(iommu->cap)) + return iommu_flush_iotlb_dsi(iommu, did, + non_present_entry_flush); + + return __iommu_flush_iotlb(iommu, did, addr, mask, + DMA_TLB_PSI_FLUSH, non_present_entry_flush); +} + +static int iommu_enable_translation(struct intel_iommu *iommu) +{ + u32 sts; + unsigned long flags; + + spin_lock_irqsave(&iommu->register_lock, flags); + writel(iommu->gcmd|DMA_GCMD_TE, iommu->reg + DMAR_GCMD_REG); + + /* Make sure hardware complete it */ + IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, + readl, (sts & DMA_GSTS_TES), sts); + + iommu->gcmd |= DMA_GCMD_TE; + spin_unlock_irqrestore(&iommu->register_lock, flags); + return 0; +} + +static int iommu_disable_translation(struct intel_iommu *iommu) +{ + u32 sts; + unsigned long flag; + + spin_lock_irqsave(&iommu->register_lock, flag); + iommu->gcmd &= ~DMA_GCMD_TE; + writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG); + + /* Make sure hardware complete it */ + IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, + readl, (!(sts & DMA_GSTS_TES)), sts); + + spin_unlock_irqrestore(&iommu->register_lock, flag); + return 0; +} + +/* iommu interrupt handling. Most stuff are MSI-like. */ + +static char *fault_reason_strings[] = +{ + "Software", + "Present bit in root entry is clear", + "Present bit in context entry is clear", + "Invalid context entry", + "Access beyond MGAW", + "PTE Write access is not set", + "PTE Read access is not set", + "Next page table ptr is invalid", + "Root table address invalid", + "Context table ptr is invalid", + "non-zero reserved fields in RTP", + "non-zero reserved fields in CTP", + "non-zero reserved fields in PTE", + "Unknown" +}; +#define MAX_FAULT_REASON_IDX ARRAY_SIZE(fault_reason_strings) + +char *dmar_get_fault_reason(u8 fault_reason) +{ + if (fault_reason > MAX_FAULT_REASON_IDX) + return fault_reason_strings[MAX_FAULT_REASON_IDX]; + else + return fault_reason_strings[fault_reason]; +} + +void dmar_msi_unmask(unsigned int irq) +{ + struct intel_iommu *iommu = get_irq_data(irq); + unsigned long flag; + + /* unmask it */ + spin_lock_irqsave(&iommu->register_lock, flag); + writel(0, iommu->reg + DMAR_FECTL_REG); + /* Read a reg to force flush the post write */ + readl(iommu->reg + DMAR_FECTL_REG); + spin_unlock_irqrestore(&iommu->register_lock, flag); +} + +void dmar_msi_mask(unsigned int irq) +{ + unsigned long flag; + struct intel_iommu *iommu = get_irq_data(irq); + + /* mask it */ + spin_lock_irqsave(&iommu->register_lock, flag); + writel(DMA_FECTL_IM, iommu->reg + DMAR_FECTL_REG); + /* Read a reg to force flush the post write */ + readl(iommu->reg + DMAR_FECTL_REG); + spin_unlock_irqrestore(&iommu->register_lock, flag); +} + +void dmar_msi_write(int irq, struct msi_msg *msg) +{ + struct intel_iommu *iommu = get_irq_data(irq); + unsigned long flag; + + spin_lock_irqsave(&iommu->register_lock, flag); + writel(msg->data, iommu->reg + DMAR_FEDATA_REG); + writel(msg->address_lo, iommu->reg + DMAR_FEADDR_REG); + writel(msg->address_hi, iommu->reg + DMAR_FEUADDR_REG); + spin_unlock_irqrestore(&iommu->register_lock, flag); +} + +void dmar_msi_read(int irq, struct msi_msg *msg) +{ + struct intel_iommu *iommu = get_irq_data(irq); + unsigned long flag; + + spin_lock_irqsave(&iommu->register_lock, flag); + msg->data = readl(iommu->reg + DMAR_FEDATA_REG); + msg->address_lo = readl(iommu->reg + DMAR_FEADDR_REG); + msg->address_hi = readl(iommu->reg + DMAR_FEUADDR_REG); + spin_unlock_irqrestore(&iommu->register_lock, flag); +} + +static int iommu_page_fault_do_one(struct intel_iommu *iommu, int type, + u8 fault_reason, u16 source_id, u64 addr) +{ + char *reason; + + reason = dmar_get_fault_reason(fault_reason); + + printk(KERN_ERR + "DMAR:[%s] Request device [%02x:%02x.%d] " + "fault addr %llx \n" + "DMAR:[fault reason %02d] %s\n", + (type ? "DMA Read" : "DMA Write"), + (source_id >> 8), PCI_SLOT(source_id & 0xFF), + PCI_FUNC(source_id & 0xFF), addr, fault_reason, reason); + return 0; +} + +#define PRIMARY_FAULT_REG_LEN (16) +static irqreturn_t iommu_page_fault(int irq, void *dev_id) +{ + struct intel_iommu *iommu = dev_id; + int reg, fault_index; + u32 fault_status; + unsigned long flag; + + spin_lock_irqsave(&iommu->register_lock, flag); + fault_status = readl(iommu->reg + DMAR_FSTS_REG); + + /* TBD: ignore advanced fault log currently */ + if (!(fault_status & DMA_FSTS_PPF)) + goto clear_overflow; + + fault_index = dma_fsts_fault_record_index(fault_status); + reg = cap_fault_reg_offset(iommu->cap); + while (1) { + u8 fault_reason; + u16 source_id; + u64 guest_addr; + int type; + u32 data; + + /* highest 32 bits */ + data = readl(iommu->reg + reg + + fault_index * PRIMARY_FAULT_REG_LEN + 12); + if (!(data & DMA_FRCD_F)) + break; + + fault_reason = dma_frcd_fault_reason(data); + type = dma_frcd_type(data); + + data = readl(iommu->reg + reg + + fault_index * PRIMARY_FAULT_REG_LEN + 8); + source_id = dma_frcd_source_id(data); + + guest_addr = dmar_readq(iommu->reg + reg + + fault_index * PRIMARY_FAULT_REG_LEN); + guest_addr = dma_frcd_page_addr(guest_addr); + /* clear the fault */ + writel(DMA_FRCD_F, iommu->reg + reg + + fault_index * PRIMARY_FAULT_REG_LEN + 12); + + spin_unlock_irqrestore(&iommu->register_lock, flag); + + iommu_page_fault_do_one(iommu, type, fault_reason, + source_id, guest_addr); + + fault_index++; + if (fault_index > cap_num_fault_regs(iommu->cap)) + fault_index = 0; + spin_lock_irqsave(&iommu->register_lock, flag); + } +clear_overflow: + /* clear primary fault overflow */ + fault_status = readl(iommu->reg + DMAR_FSTS_REG); + if (fault_status & DMA_FSTS_PFO) + writel(DMA_FSTS_PFO, iommu->reg + DMAR_FSTS_REG); + + spin_unlock_irqrestore(&iommu->register_lock, flag); + return IRQ_HANDLED; +} + +int dmar_set_interrupt(struct intel_iommu *iommu) +{ + int irq, ret; + + irq = create_irq(); + if (!irq) { + printk(KERN_ERR "IOMMU: no free vectors\n"); + return -EINVAL; + } + + set_irq_data(irq, iommu); + iommu->irq = irq; + + ret = arch_setup_dmar_msi(irq); + if (ret) { + set_irq_data(irq, NULL); + iommu->irq = 0; + destroy_irq(irq); + return 0; + } + + /* Force fault register is cleared */ + iommu_page_fault(irq, iommu); + + ret = request_irq(irq, iommu_page_fault, 0, iommu->name, iommu); + if (ret) + printk(KERN_ERR "IOMMU: can't request irq\n"); + return ret; +} + +static int iommu_init_domains(struct intel_iommu *iommu) +{ + unsigned long ndomains; + unsigned long nlongs; + + ndomains = cap_ndoms(iommu->cap); + pr_debug("Number of Domains supportd <%ld>\n", ndomains); + nlongs = BITS_TO_LONGS(ndomains); + + /* TBD: there might be 64K domains, + * consider other allocation for future chip + */ + iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL); + if (!iommu->domain_ids) { + printk(KERN_ERR "Allocating domain id array failed\n"); + return -ENOMEM; + } + iommu->domains = kcalloc(ndomains, sizeof(struct dmar_domain *), + GFP_KERNEL); + if (!iommu->domains) { + printk(KERN_ERR "Allocating domain array failed\n"); + kfree(iommu->domain_ids); + return -ENOMEM; + } + + /* + * if Caching mode is set, then invalid translations are tagged + * with domainid 0. Hence we need to pre-allocate it. + */ + if (cap_caching_mode(iommu->cap)) + set_bit(0, iommu->domain_ids); + return 0; +} + +static struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd) +{ + struct intel_iommu *iommu; + int ret; + int map_size; + u32 ver; + + iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); + if (!iommu) + return NULL; + iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K); + if (!iommu->reg) { + printk(KERN_ERR "IOMMU: can't map the region\n"); + goto error; + } + iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); + iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); + + /* the registers might be more than one page */ + map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap), + cap_max_fault_reg_offset(iommu->cap)); + map_size = PAGE_ALIGN_4K(map_size); + if (map_size > PAGE_SIZE_4K) { + iounmap(iommu->reg); + iommu->reg = ioremap(drhd->reg_base_addr, map_size); + if (!iommu->reg) { + printk(KERN_ERR "IOMMU: can't map the region\n"); + goto error; + } + } + + ver = readl(iommu->reg + DMAR_VER_REG); + pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", + drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), + iommu->cap, iommu->ecap); + ret = iommu_init_domains(iommu); + if (ret) + goto error_unmap; + spin_lock_init(&iommu->lock); + spin_lock_init(&iommu->register_lock); + + drhd->iommu = iommu; + return iommu; +error_unmap: + iounmap(iommu->reg); + iommu->reg = 0; +error: + kfree(iommu); + return NULL; +} + +static void domain_exit(struct dmar_domain *domain); +static void free_iommu(struct intel_iommu *iommu) +{ + struct dmar_domain *domain; + int i; + + if (!iommu) + return; + + i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap)); + for (; i < cap_ndoms(iommu->cap); ) { + domain = iommu->domains[i]; + clear_bit(i, iommu->domain_ids); + domain_exit(domain); + i = find_next_bit(iommu->domain_ids, + cap_ndoms(iommu->cap), i+1); + } + + if (iommu->gcmd & DMA_GCMD_TE) + iommu_disable_translation(iommu); + + if (iommu->irq) { + set_irq_data(iommu->irq, NULL); + /* This will mask the irq */ + free_irq(iommu->irq, iommu); + destroy_irq(iommu->irq); + } + + kfree(iommu->domains); + kfree(iommu->domain_ids); + + /* free context mapping */ + free_context_table(iommu); + + if (iommu->reg) + iounmap(iommu->reg); + kfree(iommu); +} + +static struct dmar_domain * iommu_alloc_domain(struct intel_iommu *iommu) +{ + unsigned long num; + unsigned long ndomains; + struct dmar_domain *domain; + unsigned long flags; + + domain = alloc_domain_mem(); + if (!domain) + return NULL; + + ndomains = cap_ndoms(iommu->cap); + + spin_lock_irqsave(&iommu->lock, flags); + num = find_first_zero_bit(iommu->domain_ids, ndomains); + if (num >= ndomains) { + spin_unlock_irqrestore(&iommu->lock, flags); + free_domain_mem(domain); + printk(KERN_ERR "IOMMU: no free domain ids\n"); + return NULL; + } + + set_bit(num, iommu->domain_ids); + domain->id = num; + domain->iommu = iommu; + iommu->domains[num] = domain; + spin_unlock_irqrestore(&iommu->lock, flags); + + return domain; +} + +static void iommu_free_domain(struct dmar_domain *domain) +{ + unsigned long flags; + + spin_lock_irqsave(&domain->iommu->lock, flags); + clear_bit(domain->id, domain->iommu->domain_ids); + spin_unlock_irqrestore(&domain->iommu->lock, flags); +} + +static struct iova_domain reserved_iova_list; + +static void dmar_init_reserved_ranges(void) +{ + struct pci_dev *pdev = NULL; + struct iova *iova; + int i; + u64 addr, size; + + init_iova_domain(&reserved_iova_list); + + /* IOAPIC ranges shouldn't be accessed by DMA */ + iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START), + IOVA_PFN(IOAPIC_RANGE_END)); + if (!iova) + printk(KERN_ERR "Reserve IOAPIC range failed\n"); + + /* Reserve all PCI MMIO to avoid peer-to-peer access */ + for_each_pci_dev(pdev) { + struct resource *r; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + r = &pdev->resource[i]; + if (!r->flags || !(r->flags & IORESOURCE_MEM)) + continue; + addr = r->start; + addr &= PAGE_MASK_4K; + size = r->end - addr; + size = PAGE_ALIGN_4K(size); + iova = reserve_iova(&reserved_iova_list, IOVA_PFN(addr), + IOVA_PFN(size + addr) - 1); + if (!iova) + printk(KERN_ERR "Reserve iova failed\n"); + } + } + +} + +static void domain_reserve_special_ranges(struct dmar_domain *domain) +{ + copy_reserved_iova(&reserved_iova_list, &domain->iovad); +} + +static inline int guestwidth_to_adjustwidth(int gaw) +{ + int agaw; + int r = (gaw - 12) % 9; + + if (r == 0) + agaw = gaw; + else + agaw = gaw + 9 - r; + if (agaw > 64) + agaw = 64; + return agaw; +} + +static int domain_init(struct dmar_domain *domain, int guest_width) +{ + struct intel_iommu *iommu; + int adjust_width, agaw; + unsigned long sagaw; + + init_iova_domain(&domain->iovad); + spin_lock_init(&domain->mapping_lock); + + domain_reserve_special_ranges(domain); + + /* calculate AGAW */ + iommu = domain->iommu; + if (guest_width > cap_mgaw(iommu->cap)) + guest_width = cap_mgaw(iommu->cap); + domain->gaw = guest_width; + adjust_width = guestwidth_to_adjustwidth(guest_width); + agaw = width_to_agaw(adjust_width); + sagaw = cap_sagaw(iommu->cap); + if (!test_bit(agaw, &sagaw)) { + /* hardware doesn't support it, choose a bigger one */ + pr_debug("IOMMU: hardware doesn't support agaw %d\n", agaw); + agaw = find_next_bit(&sagaw, 5, agaw); + if (agaw >= 5) + return -ENODEV; + } + domain->agaw = agaw; + INIT_LIST_HEAD(&domain->devices); + + /* always allocate the top pgd */ + domain->pgd = (struct dma_pte *)alloc_pgtable_page(); + if (!domain->pgd) + return -ENOMEM; + __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE_4K); + return 0; +} + +static void domain_exit(struct dmar_domain *domain) +{ + u64 end; + + /* Domain 0 is reserved, so dont process it */ + if (!domain) + return; + + domain_remove_dev_info(domain); + /* destroy iovas */ + put_iova_domain(&domain->iovad); + end = DOMAIN_MAX_ADDR(domain->gaw); + end = end & (~PAGE_MASK_4K); + + /* clear ptes */ + dma_pte_clear_range(domain, 0, end); + + /* free page tables */ + dma_pte_free_pagetable(domain, 0, end); + + iommu_free_domain(domain); + free_domain_mem(domain); +} + +static int domain_context_mapping_one(struct dmar_domain *domain, + u8 bus, u8 devfn) +{ + struct context_entry *context; + struct intel_iommu *iommu = domain->iommu; + unsigned long flags; + + pr_debug("Set context mapping for %02x:%02x.%d\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + BUG_ON(!domain->pgd); + context = device_to_context_entry(iommu, bus, devfn); + if (!context) + return -ENOMEM; + spin_lock_irqsave(&iommu->lock, flags); + if (context_present(*context)) { + spin_unlock_irqrestore(&iommu->lock, flags); + return 0; + } + + context_set_domain_id(*context, domain->id); + context_set_address_width(*context, domain->agaw); + context_set_address_root(*context, virt_to_phys(domain->pgd)); + context_set_translation_type(*context, CONTEXT_TT_MULTI_LEVEL); + context_set_fault_enable(*context); + context_set_present(*context); + __iommu_flush_cache(iommu, context, sizeof(*context)); + + /* it's a non-present to present mapping */ + if (iommu_flush_context_device(iommu, domain->id, + (((u16)bus) << 8) | devfn, DMA_CCMD_MASK_NOBIT, 1)) + iommu_flush_write_buffer(iommu); + else + iommu_flush_iotlb_dsi(iommu, 0, 0); + spin_unlock_irqrestore(&iommu->lock, flags); + return 0; +} + +static int +domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev) +{ + int ret; + struct pci_dev *tmp, *parent; + + ret = domain_context_mapping_one(domain, pdev->bus->number, + pdev->devfn); + if (ret) + return ret; + + /* dependent device mapping */ + tmp = pci_find_upstream_pcie_bridge(pdev); + if (!tmp) + return 0; + /* Secondary interface's bus number and devfn 0 */ + parent = pdev->bus->self; + while (parent != tmp) { + ret = domain_context_mapping_one(domain, parent->bus->number, + parent->devfn); + if (ret) + return ret; + parent = parent->bus->self; + } + if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */ + return domain_context_mapping_one(domain, + tmp->subordinate->number, 0); + else /* this is a legacy PCI bridge */ + return domain_context_mapping_one(domain, + tmp->bus->number, tmp->devfn); +} + +static int domain_context_mapped(struct dmar_domain *domain, + struct pci_dev *pdev) +{ + int ret; + struct pci_dev *tmp, *parent; + + ret = device_context_mapped(domain->iommu, + pdev->bus->number, pdev->devfn); + if (!ret) + return ret; + /* dependent device mapping */ + tmp = pci_find_upstream_pcie_bridge(pdev); + if (!tmp) + return ret; + /* Secondary interface's bus number and devfn 0 */ + parent = pdev->bus->self; + while (parent != tmp) { + ret = device_context_mapped(domain->iommu, parent->bus->number, + parent->devfn); + if (!ret) + return ret; + parent = parent->bus->self; + } + if (tmp->is_pcie) + return device_context_mapped(domain->iommu, + tmp->subordinate->number, 0); + else + return device_context_mapped(domain->iommu, + tmp->bus->number, tmp->devfn); +} + +static int +domain_page_mapping(struct dmar_domain *domain, dma_addr_t iova, + u64 hpa, size_t size, int prot) +{ + u64 start_pfn, end_pfn; + struct dma_pte *pte; + int index; + + if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0) + return -EINVAL; + iova &= PAGE_MASK_4K; + start_pfn = ((u64)hpa) >> PAGE_SHIFT_4K; + end_pfn = (PAGE_ALIGN_4K(((u64)hpa) + size)) >> PAGE_SHIFT_4K; + index = 0; + while (start_pfn < end_pfn) { + pte = addr_to_dma_pte(domain, iova + PAGE_SIZE_4K * index); + if (!pte) + return -ENOMEM; + /* We don't need lock here, nobody else + * touches the iova range + */ + BUG_ON(dma_pte_addr(*pte)); + dma_set_pte_addr(*pte, start_pfn << PAGE_SHIFT_4K); + dma_set_pte_prot(*pte, prot); + __iommu_flush_cache(domain->iommu, pte, sizeof(*pte)); + start_pfn++; + index++; + } + return 0; +} + +static void detach_domain_for_dev(struct dmar_domain *domain, u8 bus, u8 devfn) +{ + clear_context_table(domain->iommu, bus, devfn); + iommu_flush_context_global(domain->iommu, 0); + iommu_flush_iotlb_global(domain->iommu, 0); +} + +static void domain_remove_dev_info(struct dmar_domain *domain) +{ + struct device_domain_info *info; + unsigned long flags; + + spin_lock_irqsave(&device_domain_lock, flags); + while (!list_empty(&domain->devices)) { + info = list_entry(domain->devices.next, + struct device_domain_info, link); + list_del(&info->link); + list_del(&info->global); + if (info->dev) + info->dev->dev.archdata.iommu = NULL; + spin_unlock_irqrestore(&device_domain_lock, flags); + + detach_domain_for_dev(info->domain, info->bus, info->devfn); + free_devinfo_mem(info); + + spin_lock_irqsave(&device_domain_lock, flags); + } + spin_unlock_irqrestore(&device_domain_lock, flags); +} + +/* + * find_domain + * Note: we use struct pci_dev->dev.archdata.iommu stores the info + */ +struct dmar_domain * +find_domain(struct pci_dev *pdev) +{ + struct device_domain_info *info; + + /* No lock here, assumes no domain exit in normal case */ + info = pdev->dev.archdata.iommu; + if (info) + return info->domain; + return NULL; +} + +static int dmar_pci_device_match(struct pci_dev *devices[], int cnt, + struct pci_dev *dev) +{ + int index; + + while (dev) { + for (index = 0; index < cnt; index ++) + if (dev == devices[index]) + return 1; + + /* Check our parent */ + dev = dev->bus->self; + } + + return 0; +} + +static struct dmar_drhd_unit * +dmar_find_matched_drhd_unit(struct pci_dev *dev) +{ + struct dmar_drhd_unit *drhd = NULL; + + list_for_each_entry(drhd, &dmar_drhd_units, list) { + if (drhd->include_all || dmar_pci_device_match(drhd->devices, + drhd->devices_cnt, dev)) + return drhd; + } + + return NULL; +} + +/* domain is initialized */ +static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) +{ + struct dmar_domain *domain, *found = NULL; + struct intel_iommu *iommu; + struct dmar_drhd_unit *drhd; + struct device_domain_info *info, *tmp; + struct pci_dev *dev_tmp; + unsigned long flags; + int bus = 0, devfn = 0; + + domain = find_domain(pdev); + if (domain) + return domain; + + dev_tmp = pci_find_upstream_pcie_bridge(pdev); + if (dev_tmp) { + if (dev_tmp->is_pcie) { + bus = dev_tmp->subordinate->number; + devfn = 0; + } else { + bus = dev_tmp->bus->number; + devfn = dev_tmp->devfn; + } + spin_lock_irqsave(&device_domain_lock, flags); + list_for_each_entry(info, &device_domain_list, global) { + if (info->bus == bus && info->devfn == devfn) { + found = info->domain; + break; + } + } + spin_unlock_irqrestore(&device_domain_lock, flags); + /* pcie-pci bridge already has a domain, uses it */ + if (found) { + domain = found; + goto found_domain; + } + } + + /* Allocate new domain for the device */ + drhd = dmar_find_matched_drhd_unit(pdev); + if (!drhd) { + printk(KERN_ERR "IOMMU: can't find DMAR for device %s\n", + pci_name(pdev)); + return NULL; + } + iommu = drhd->iommu; + + domain = iommu_alloc_domain(iommu); + if (!domain) + goto error; + + if (domain_init(domain, gaw)) { + domain_exit(domain); + goto error; + } + + /* register pcie-to-pci device */ + if (dev_tmp) { + info = alloc_devinfo_mem(); + if (!info) { + domain_exit(domain); + goto error; + } + info->bus = bus; + info->devfn = devfn; + info->dev = NULL; + info->domain = domain; + /* This domain is shared by devices under p2p bridge */ + domain->flags |= DOMAIN_FLAG_MULTIPLE_DEVICES; + + /* pcie-to-pci bridge already has a domain, uses it */ + found = NULL; + spin_lock_irqsave(&device_domain_lock, flags); + list_for_each_entry(tmp, &device_domain_list, global) { + if (tmp->bus == bus && tmp->devfn == devfn) { + found = tmp->domain; + break; + } + } + if (found) { + free_devinfo_mem(info); + domain_exit(domain); + domain = found; + } else { + list_add(&info->link, &domain->devices); + list_add(&info->global, &device_domain_list); + } + spin_unlock_irqrestore(&device_domain_lock, flags); + } + +found_domain: + info = alloc_devinfo_mem(); + if (!info) + goto error; + info->bus = pdev->bus->number; + info->devfn = pdev->devfn; + info->dev = pdev; + info->domain = domain; + spin_lock_irqsave(&device_domain_lock, flags); + /* somebody is fast */ + found = find_domain(pdev); + if (found != NULL) { + spin_unlock_irqrestore(&device_domain_lock, flags); + if (found != domain) { + domain_exit(domain); + domain = found; + } + free_devinfo_mem(info); + return domain; + } + list_add(&info->link, &domain->devices); + list_add(&info->global, &device_domain_list); + pdev->dev.archdata.iommu = info; + spin_unlock_irqrestore(&device_domain_lock, flags); + return domain; +error: + /* recheck it here, maybe others set it */ + return find_domain(pdev); +} + +static int iommu_prepare_identity_map(struct pci_dev *pdev, u64 start, u64 end) +{ + struct dmar_domain *domain; + unsigned long size; + u64 base; + int ret; + + printk(KERN_INFO + "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", + pci_name(pdev), start, end); + /* page table init */ + domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); + if (!domain) + return -ENOMEM; + + /* The address might not be aligned */ + base = start & PAGE_MASK_4K; + size = end - base; + size = PAGE_ALIGN_4K(size); + if (!reserve_iova(&domain->iovad, IOVA_PFN(base), + IOVA_PFN(base + size) - 1)) { + printk(KERN_ERR "IOMMU: reserve iova failed\n"); + ret = -ENOMEM; + goto error; + } + + pr_debug("Mapping reserved region %lx@%llx for %s\n", + size, base, pci_name(pdev)); + /* + * RMRR range might have overlap with physical memory range, + * clear it first + */ + dma_pte_clear_range(domain, base, base + size); + + ret = domain_page_mapping(domain, base, base, size, + DMA_PTE_READ|DMA_PTE_WRITE); + if (ret) + goto error; + + /* context entry init */ + ret = domain_context_mapping(domain, pdev); + if (!ret) + return 0; +error: + domain_exit(domain); + return ret; + +} + +static inline int iommu_prepare_rmrr_dev(struct dmar_rmrr_unit *rmrr, + struct pci_dev *pdev) +{ + if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) + return 0; + return iommu_prepare_identity_map(pdev, rmrr->base_address, + rmrr->end_address + 1); +} + +#ifdef CONFIG_DMAR_GFX_WA +extern int arch_get_ram_range(int slot, u64 *addr, u64 *size); +static void __init iommu_prepare_gfx_mapping(void) +{ + struct pci_dev *pdev = NULL; + u64 base, size; + int slot; + int ret; + + for_each_pci_dev(pdev) { + if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO || + !IS_GFX_DEVICE(pdev)) + continue; + printk(KERN_INFO "IOMMU: gfx device %s 1-1 mapping\n", + pci_name(pdev)); + slot = arch_get_ram_range(0, &base, &size); + while (slot >= 0) { + ret = iommu_prepare_identity_map(pdev, + base, base + size); + if (ret) + goto error; + slot = arch_get_ram_range(slot, &base, &size); + } + continue; +error: + printk(KERN_ERR "IOMMU: mapping reserved region failed\n"); + } +} +#endif + +#ifdef CONFIG_DMAR_FLOPPY_WA +static inline void iommu_prepare_isa(void) +{ + struct pci_dev *pdev; + int ret; + + pdev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); + if (!pdev) + return; + + printk(KERN_INFO "IOMMU: Prepare 0-16M unity mapping for LPC\n"); + ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); + + if (ret) + printk("IOMMU: Failed to create 0-64M identity map, " + "floppy might not work\n"); + +} +#else +static inline void iommu_prepare_isa(void) +{ + return; +} +#endif /* !CONFIG_DMAR_FLPY_WA */ + +int __init init_dmars(void) +{ + struct dmar_drhd_unit *drhd; + struct dmar_rmrr_unit *rmrr; + struct pci_dev *pdev; + struct intel_iommu *iommu; + int ret, unit = 0; + + /* + * for each drhd + * allocate root + * initialize and program root entry to not present + * endfor + */ + for_each_drhd_unit(drhd) { + if (drhd->ignored) + continue; + iommu = alloc_iommu(drhd); + if (!iommu) { + ret = -ENOMEM; + goto error; + } + + /* + * TBD: + * we could share the same root & context tables + * amoung all IOMMU's. Need to Split it later. + */ + ret = iommu_alloc_root_entry(iommu); + if (ret) { + printk(KERN_ERR "IOMMU: allocate root entry failed\n"); + goto error; + } + } + + /* + * For each rmrr + * for each dev attached to rmrr + * do + * locate drhd for dev, alloc domain for dev + * allocate free domain + * allocate page table entries for rmrr + * if context not allocated for bus + * allocate and init context + * set present in root table for this bus + * init context with domain, translation etc + * endfor + * endfor + */ + for_each_rmrr_units(rmrr) { + int i; + for (i = 0; i < rmrr->devices_cnt; i++) { + pdev = rmrr->devices[i]; + /* some BIOS lists non-exist devices in DMAR table */ + if (!pdev) + continue; + ret = iommu_prepare_rmrr_dev(rmrr, pdev); + if (ret) + printk(KERN_ERR + "IOMMU: mapping reserved region failed\n"); + } + } + + iommu_prepare_gfx_mapping(); + + iommu_prepare_isa(); + + /* + * for each drhd + * enable fault log + * global invalidate context cache + * global invalidate iotlb + * enable translation + */ + for_each_drhd_unit(drhd) { + if (drhd->ignored) + continue; + iommu = drhd->iommu; + sprintf (iommu->name, "dmar%d", unit++); + + iommu_flush_write_buffer(iommu); + + ret = dmar_set_interrupt(iommu); + if (ret) + goto error; + + iommu_set_root_entry(iommu); + + iommu_flush_context_global(iommu, 0); + iommu_flush_iotlb_global(iommu, 0); + + ret = iommu_enable_translation(iommu); + if (ret) + goto error; + } + + return 0; +error: + for_each_drhd_unit(drhd) { + if (drhd->ignored) + continue; + iommu = drhd->iommu; + free_iommu(iommu); + } + return ret; +} + +static inline u64 aligned_size(u64 host_addr, size_t size) +{ + u64 addr; + addr = (host_addr & (~PAGE_MASK_4K)) + size; + return PAGE_ALIGN_4K(addr); +} + +struct iova * +iommu_alloc_iova(struct dmar_domain *domain, size_t size, u64 end) +{ + struct iova *piova; + + /* Make sure it's in range */ + end = min_t(u64, DOMAIN_MAX_ADDR(domain->gaw), end); + if (!size || (IOVA_START_ADDR + size > end)) + return NULL; + + piova = alloc_iova(&domain->iovad, + size >> PAGE_SHIFT_4K, IOVA_PFN(end), 1); + return piova; +} + +static struct iova * +__intel_alloc_iova(struct device *dev, struct dmar_domain *domain, + size_t size) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct iova *iova = NULL; + + if ((pdev->dma_mask <= DMA_32BIT_MASK) || (dmar_forcedac)) { + iova = iommu_alloc_iova(domain, size, pdev->dma_mask); + } else { + /* + * First try to allocate an io virtual address in + * DMA_32BIT_MASK and if that fails then try allocating + * from higer range + */ + iova = iommu_alloc_iova(domain, size, DMA_32BIT_MASK); + if (!iova) + iova = iommu_alloc_iova(domain, size, pdev->dma_mask); + } + + if (!iova) { + printk(KERN_ERR"Allocating iova for %s failed", pci_name(pdev)); + return NULL; + } + + return iova; +} + +static struct dmar_domain * +get_valid_domain_for_dev(struct pci_dev *pdev) +{ + struct dmar_domain *domain; + int ret; + + domain = get_domain_for_dev(pdev, + DEFAULT_DOMAIN_ADDRESS_WIDTH); + if (!domain) { + printk(KERN_ERR + "Allocating domain for %s failed", pci_name(pdev)); + return 0; + } + + /* make sure context mapping is ok */ + if (unlikely(!domain_context_mapped(domain, pdev))) { + ret = domain_context_mapping(domain, pdev); + if (ret) { + printk(KERN_ERR + "Domain context map for %s failed", + pci_name(pdev)); + return 0; + } + } + + return domain; +} + +static dma_addr_t intel_map_single(struct device *hwdev, void *addr, + size_t size, int dir) +{ + struct pci_dev *pdev = to_pci_dev(hwdev); + int ret; + struct dmar_domain *domain; + unsigned long start_addr; + struct iova *iova; + int prot = 0; + + BUG_ON(dir == DMA_NONE); + if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) + return virt_to_bus(addr); + + domain = get_valid_domain_for_dev(pdev); + if (!domain) + return 0; + + addr = (void *)virt_to_phys(addr); + size = aligned_size((u64)addr, size); + + iova = __intel_alloc_iova(hwdev, domain, size); + if (!iova) + goto error; + + start_addr = iova->pfn_lo << PAGE_SHIFT_4K; + + /* + * Check if DMAR supports zero-length reads on write only + * mappings.. + */ + if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \ + !cap_zlr(domain->iommu->cap)) + prot |= DMA_PTE_READ; + if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) + prot |= DMA_PTE_WRITE; + /* + * addr - (addr + size) might be partial page, we should map the whole + * page. Note: if two part of one page are separately mapped, we + * might have two guest_addr mapping to the same host addr, but this + * is not a big problem + */ + ret = domain_page_mapping(domain, start_addr, + ((u64)addr) & PAGE_MASK_4K, size, prot); + if (ret) + goto error; + + pr_debug("Device %s request: %lx@%llx mapping: %lx@%llx, dir %d\n", + pci_name(pdev), size, (u64)addr, + size, (u64)start_addr, dir); + + /* it's a non-present to present mapping */ + ret = iommu_flush_iotlb_psi(domain->iommu, domain->id, + start_addr, size >> PAGE_SHIFT_4K, 1); + if (ret) + iommu_flush_write_buffer(domain->iommu); + + return (start_addr + ((u64)addr & (~PAGE_MASK_4K))); + +error: + if (iova) + __free_iova(&domain->iovad, iova); + printk(KERN_ERR"Device %s request: %lx@%llx dir %d --- failed\n", + pci_name(pdev), size, (u64)addr, dir); + return 0; +} + +static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, + size_t size, int dir) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct dmar_domain *domain; + unsigned long start_addr; + struct iova *iova; + + if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) + return; + domain = find_domain(pdev); + BUG_ON(!domain); + + iova = find_iova(&domain->iovad, IOVA_PFN(dev_addr)); + if (!iova) + return; + + start_addr = iova->pfn_lo << PAGE_SHIFT_4K; + size = aligned_size((u64)dev_addr, size); + + pr_debug("Device %s unmapping: %lx@%llx\n", + pci_name(pdev), size, (u64)start_addr); + + /* clear the whole page */ + dma_pte_clear_range(domain, start_addr, start_addr + size); + /* free page tables */ + dma_pte_free_pagetable(domain, start_addr, start_addr + size); + + if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr, + size >> PAGE_SHIFT_4K, 0)) + iommu_flush_write_buffer(domain->iommu); + + /* free iova */ + __free_iova(&domain->iovad, iova); +} + +static void * intel_alloc_coherent(struct device *hwdev, size_t size, + dma_addr_t *dma_handle, gfp_t flags) +{ + void *vaddr; + int order; + + size = PAGE_ALIGN_4K(size); + order = get_order(size); + flags &= ~(GFP_DMA | GFP_DMA32); + + vaddr = (void *)__get_free_pages(flags, order); + if (!vaddr) + return NULL; + memset(vaddr, 0, size); + + *dma_handle = intel_map_single(hwdev, vaddr, size, DMA_BIDIRECTIONAL); + if (*dma_handle) + return vaddr; + free_pages((unsigned long)vaddr, order); + return NULL; +} + +static void intel_free_coherent(struct device *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + int order; + + size = PAGE_ALIGN_4K(size); + order = get_order(size); + + intel_unmap_single(hwdev, dma_handle, size, DMA_BIDIRECTIONAL); + free_pages((unsigned long)vaddr, order); +} + +#define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset) +static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, + int nelems, int dir) +{ + int i; + struct pci_dev *pdev = to_pci_dev(hwdev); + struct dmar_domain *domain; + unsigned long start_addr; + struct iova *iova; + size_t size = 0; + void *addr; + struct scatterlist *sg; + + if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) + return; + + domain = find_domain(pdev); + + iova = find_iova(&domain->iovad, IOVA_PFN(sglist[0].dma_address)); + if (!iova) + return; + for_each_sg(sglist, sg, nelems, i) { + addr = SG_ENT_VIRT_ADDRESS(sg); + size += aligned_size((u64)addr, sg->length); + } + + start_addr = iova->pfn_lo << PAGE_SHIFT_4K; + + /* clear the whole page */ + dma_pte_clear_range(domain, start_addr, start_addr + size); + /* free page tables */ + dma_pte_free_pagetable(domain, start_addr, start_addr + size); + + if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr, + size >> PAGE_SHIFT_4K, 0)) + iommu_flush_write_buffer(domain->iommu); + + /* free iova */ + __free_iova(&domain->iovad, iova); +} + +static int intel_nontranslate_map_sg(struct device *hddev, + struct scatterlist *sglist, int nelems, int dir) +{ + int i; + struct scatterlist *sg; + + for_each_sg(sglist, sg, nelems, i) { + BUG_ON(!sg->page); + sg->dma_address = virt_to_bus(SG_ENT_VIRT_ADDRESS(sg)); + sg->dma_length = sg->length; + } + return nelems; +} + +static int intel_map_sg(struct device *hwdev, struct scatterlist *sglist, + int nelems, int dir) +{ + void *addr; + int i; + struct pci_dev *pdev = to_pci_dev(hwdev); + struct dmar_domain *domain; + size_t size = 0; + int prot = 0; + size_t offset = 0; + struct iova *iova = NULL; + int ret; + struct scatterlist *sg; + unsigned long start_addr; + + BUG_ON(dir == DMA_NONE); + if (pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO) + return intel_nontranslate_map_sg(hwdev, sglist, nelems, dir); + + domain = get_valid_domain_for_dev(pdev); + if (!domain) + return 0; + + for_each_sg(sglist, sg, nelems, i) { + addr = SG_ENT_VIRT_ADDRESS(sg); + addr = (void *)virt_to_phys(addr); + size += aligned_size((u64)addr, sg->length); + } + + iova = __intel_alloc_iova(hwdev, domain, size); + if (!iova) { + sglist->dma_length = 0; + return 0; + } + + /* + * Check if DMAR supports zero-length reads on write only + * mappings.. + */ + if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \ + !cap_zlr(domain->iommu->cap)) + prot |= DMA_PTE_READ; + if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) + prot |= DMA_PTE_WRITE; + + start_addr = iova->pfn_lo << PAGE_SHIFT_4K; + offset = 0; + for_each_sg(sglist, sg, nelems, i) { + addr = SG_ENT_VIRT_ADDRESS(sg); + addr = (void *)virt_to_phys(addr); + size = aligned_size((u64)addr, sg->length); + ret = domain_page_mapping(domain, start_addr + offset, + ((u64)addr) & PAGE_MASK_4K, + size, prot); + if (ret) { + /* clear the page */ + dma_pte_clear_range(domain, start_addr, + start_addr + offset); + /* free page tables */ + dma_pte_free_pagetable(domain, start_addr, + start_addr + offset); + /* free iova */ + __free_iova(&domain->iovad, iova); + return 0; + } + sg->dma_address = start_addr + offset + + ((u64)addr & (~PAGE_MASK_4K)); + sg->dma_length = sg->length; + offset += size; + } + + /* it's a non-present to present mapping */ + if (iommu_flush_iotlb_psi(domain->iommu, domain->id, + start_addr, offset >> PAGE_SHIFT_4K, 1)) + iommu_flush_write_buffer(domain->iommu); + return nelems; +} + +static struct dma_mapping_ops intel_dma_ops = { + .alloc_coherent = intel_alloc_coherent, + .free_coherent = intel_free_coherent, + .map_single = intel_map_single, + .unmap_single = intel_unmap_single, + .map_sg = intel_map_sg, + .unmap_sg = intel_unmap_sg, +}; + +static inline int iommu_domain_cache_init(void) +{ + int ret = 0; + + iommu_domain_cache = kmem_cache_create("iommu_domain", + sizeof(struct dmar_domain), + 0, + SLAB_HWCACHE_ALIGN, + + NULL); + if (!iommu_domain_cache) { + printk(KERN_ERR "Couldn't create iommu_domain cache\n"); + ret = -ENOMEM; + } + + return ret; +} + +static inline int iommu_devinfo_cache_init(void) +{ + int ret = 0; + + iommu_devinfo_cache = kmem_cache_create("iommu_devinfo", + sizeof(struct device_domain_info), + 0, + SLAB_HWCACHE_ALIGN, + + NULL); + if (!iommu_devinfo_cache) { + printk(KERN_ERR "Couldn't create devinfo cache\n"); + ret = -ENOMEM; + } + + return ret; +} + +static inline int iommu_iova_cache_init(void) +{ + int ret = 0; + + iommu_iova_cache = kmem_cache_create("iommu_iova", + sizeof(struct iova), + 0, + SLAB_HWCACHE_ALIGN, + + NULL); + if (!iommu_iova_cache) { + printk(KERN_ERR "Couldn't create iova cache\n"); + ret = -ENOMEM; + } + + return ret; +} + +static int __init iommu_init_mempool(void) +{ + int ret; + ret = iommu_iova_cache_init(); + if (ret) + return ret; + + ret = iommu_domain_cache_init(); + if (ret) + goto domain_error; + + ret = iommu_devinfo_cache_init(); + if (!ret) + return ret; + + kmem_cache_destroy(iommu_domain_cache); +domain_error: + kmem_cache_destroy(iommu_iova_cache); + + return -ENOMEM; +} + +static void __init iommu_exit_mempool(void) +{ + kmem_cache_destroy(iommu_devinfo_cache); + kmem_cache_destroy(iommu_domain_cache); + kmem_cache_destroy(iommu_iova_cache); + +} + +void __init detect_intel_iommu(void) +{ + if (swiotlb || no_iommu || iommu_detected || dmar_disabled) + return; + if (early_dmar_detect()) { + iommu_detected = 1; + } +} + +static void __init init_no_remapping_devices(void) +{ + struct dmar_drhd_unit *drhd; + + for_each_drhd_unit(drhd) { + if (!drhd->include_all) { + int i; + for (i = 0; i < drhd->devices_cnt; i++) + if (drhd->devices[i] != NULL) + break; + /* ignore DMAR unit if no pci devices exist */ + if (i == drhd->devices_cnt) + drhd->ignored = 1; + } + } + + if (dmar_map_gfx) + return; + + for_each_drhd_unit(drhd) { + int i; + if (drhd->ignored || drhd->include_all) + continue; + + for (i = 0; i < drhd->devices_cnt; i++) + if (drhd->devices[i] && + !IS_GFX_DEVICE(drhd->devices[i])) + break; + + if (i < drhd->devices_cnt) + continue; + + /* bypass IOMMU if it is just for gfx devices */ + drhd->ignored = 1; + for (i = 0; i < drhd->devices_cnt; i++) { + if (!drhd->devices[i]) + continue; + drhd->devices[i]->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; + } + } +} + +int __init intel_iommu_init(void) +{ + int ret = 0; + + if (no_iommu || swiotlb || dmar_disabled) + return -ENODEV; + + if (dmar_table_init()) + return -ENODEV; + + iommu_init_mempool(); + dmar_init_reserved_ranges(); + + init_no_remapping_devices(); + + ret = init_dmars(); + if (ret) { + printk(KERN_ERR "IOMMU: dmar init failed\n"); + put_iova_domain(&reserved_iova_list); + iommu_exit_mempool(); + return ret; + } + printk(KERN_INFO + "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n"); + + force_iommu = 1; + dma_ops = &intel_dma_ops; + return 0; +} + diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h new file mode 100644 index 00000000000..ee88dd2400c --- /dev/null +++ b/drivers/pci/intel-iommu.h @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Copyright (C) Ashok Raj <ashok.raj@intel.com> + * Copyright (C) Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> + */ + +#ifndef _INTEL_IOMMU_H_ +#define _INTEL_IOMMU_H_ + +#include <linux/types.h> +#include <linux/msi.h> +#include "iova.h" +#include <linux/io.h> + +/* + * Intel IOMMU register specification per version 1.0 public spec. + */ + +#define DMAR_VER_REG 0x0 /* Arch version supported by this IOMMU */ +#define DMAR_CAP_REG 0x8 /* Hardware supported capabilities */ +#define DMAR_ECAP_REG 0x10 /* Extended capabilities supported */ +#define DMAR_GCMD_REG 0x18 /* Global command register */ +#define DMAR_GSTS_REG 0x1c /* Global status register */ +#define DMAR_RTADDR_REG 0x20 /* Root entry table */ +#define DMAR_CCMD_REG 0x28 /* Context command reg */ +#define DMAR_FSTS_REG 0x34 /* Fault Status register */ +#define DMAR_FECTL_REG 0x38 /* Fault control register */ +#define DMAR_FEDATA_REG 0x3c /* Fault event interrupt data register */ +#define DMAR_FEADDR_REG 0x40 /* Fault event interrupt addr register */ +#define DMAR_FEUADDR_REG 0x44 /* Upper address register */ +#define DMAR_AFLOG_REG 0x58 /* Advanced Fault control */ +#define DMAR_PMEN_REG 0x64 /* Enable Protected Memory Region */ +#define DMAR_PLMBASE_REG 0x68 /* PMRR Low addr */ +#define DMAR_PLMLIMIT_REG 0x6c /* PMRR low limit */ +#define DMAR_PHMBASE_REG 0x70 /* pmrr high base addr */ +#define DMAR_PHMLIMIT_REG 0x78 /* pmrr high limit */ + +#define OFFSET_STRIDE (9) +/* +#define dmar_readl(dmar, reg) readl(dmar + reg) +#define dmar_readq(dmar, reg) ({ \ + u32 lo, hi; \ + lo = readl(dmar + reg); \ + hi = readl(dmar + reg + 4); \ + (((u64) hi) << 32) + lo; }) +*/ +static inline u64 dmar_readq(void *addr) +{ + u32 lo, hi; + lo = readl(addr); + hi = readl(addr + 4); + return (((u64) hi) << 32) + lo; +} + +static inline void dmar_writeq(void __iomem *addr, u64 val) +{ + writel((u32)val, addr); + writel((u32)(val >> 32), addr + 4); +} + +#define DMAR_VER_MAJOR(v) (((v) & 0xf0) >> 4) +#define DMAR_VER_MINOR(v) ((v) & 0x0f) + +/* + * Decoding Capability Register + */ +#define cap_read_drain(c) (((c) >> 55) & 1) +#define cap_write_drain(c) (((c) >> 54) & 1) +#define cap_max_amask_val(c) (((c) >> 48) & 0x3f) +#define cap_num_fault_regs(c) ((((c) >> 40) & 0xff) + 1) +#define cap_pgsel_inv(c) (((c) >> 39) & 1) + +#define cap_super_page_val(c) (((c) >> 34) & 0xf) +#define cap_super_offset(c) (((find_first_bit(&cap_super_page_val(c), 4)) \ + * OFFSET_STRIDE) + 21) + +#define cap_fault_reg_offset(c) ((((c) >> 24) & 0x3ff) * 16) +#define cap_max_fault_reg_offset(c) \ + (cap_fault_reg_offset(c) + cap_num_fault_regs(c) * 16) + +#define cap_zlr(c) (((c) >> 22) & 1) +#define cap_isoch(c) (((c) >> 23) & 1) +#define cap_mgaw(c) ((((c) >> 16) & 0x3f) + 1) +#define cap_sagaw(c) (((c) >> 8) & 0x1f) +#define cap_caching_mode(c) (((c) >> 7) & 1) +#define cap_phmr(c) (((c) >> 6) & 1) +#define cap_plmr(c) (((c) >> 5) & 1) +#define cap_rwbf(c) (((c) >> 4) & 1) +#define cap_afl(c) (((c) >> 3) & 1) +#define cap_ndoms(c) (((unsigned long)1) << (4 + 2 * ((c) & 0x7))) +/* + * Extended Capability Register + */ + +#define ecap_niotlb_iunits(e) ((((e) >> 24) & 0xff) + 1) +#define ecap_iotlb_offset(e) ((((e) >> 8) & 0x3ff) * 16) +#define ecap_max_iotlb_offset(e) \ + (ecap_iotlb_offset(e) + ecap_niotlb_iunits(e) * 16) +#define ecap_coherent(e) ((e) & 0x1) + + +/* IOTLB_REG */ +#define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60) +#define DMA_TLB_DSI_FLUSH (((u64)2) << 60) +#define DMA_TLB_PSI_FLUSH (((u64)3) << 60) +#define DMA_TLB_IIRG(type) ((type >> 60) & 7) +#define DMA_TLB_IAIG(val) (((val) >> 57) & 7) +#define DMA_TLB_READ_DRAIN (((u64)1) << 49) +#define DMA_TLB_WRITE_DRAIN (((u64)1) << 48) +#define DMA_TLB_DID(id) (((u64)((id) & 0xffff)) << 32) +#define DMA_TLB_IVT (((u64)1) << 63) +#define DMA_TLB_IH_NONLEAF (((u64)1) << 6) +#define DMA_TLB_MAX_SIZE (0x3f) + +/* GCMD_REG */ +#define DMA_GCMD_TE (((u32)1) << 31) +#define DMA_GCMD_SRTP (((u32)1) << 30) +#define DMA_GCMD_SFL (((u32)1) << 29) +#define DMA_GCMD_EAFL (((u32)1) << 28) +#define DMA_GCMD_WBF (((u32)1) << 27) + +/* GSTS_REG */ +#define DMA_GSTS_TES (((u32)1) << 31) +#define DMA_GSTS_RTPS (((u32)1) << 30) +#define DMA_GSTS_FLS (((u32)1) << 29) +#define DMA_GSTS_AFLS (((u32)1) << 28) +#define DMA_GSTS_WBFS (((u32)1) << 27) + +/* CCMD_REG */ +#define DMA_CCMD_ICC (((u64)1) << 63) +#define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61) +#define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61) +#define DMA_CCMD_DEVICE_INVL (((u64)3) << 61) +#define DMA_CCMD_FM(m) (((u64)((m) & 0x3)) << 32) +#define DMA_CCMD_MASK_NOBIT 0 +#define DMA_CCMD_MASK_1BIT 1 +#define DMA_CCMD_MASK_2BIT 2 +#define DMA_CCMD_MASK_3BIT 3 +#define DMA_CCMD_SID(s) (((u64)((s) & 0xffff)) << 16) +#define DMA_CCMD_DID(d) ((u64)((d) & 0xffff)) + +/* FECTL_REG */ +#define DMA_FECTL_IM (((u32)1) << 31) + +/* FSTS_REG */ +#define DMA_FSTS_PPF ((u32)2) +#define DMA_FSTS_PFO ((u32)1) +#define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff) + +/* FRCD_REG, 32 bits access */ +#define DMA_FRCD_F (((u32)1) << 31) +#define dma_frcd_type(d) ((d >> 30) & 1) +#define dma_frcd_fault_reason(c) (c & 0xff) +#define dma_frcd_source_id(c) (c & 0xffff) +#define dma_frcd_page_addr(d) (d & (((u64)-1) << 12)) /* low 64 bit */ + +/* + * 0: Present + * 1-11: Reserved + * 12-63: Context Ptr (12 - (haw-1)) + * 64-127: Reserved + */ +struct root_entry { + u64 val; + u64 rsvd1; +}; +#define ROOT_ENTRY_NR (PAGE_SIZE_4K/sizeof(struct root_entry)) +static inline bool root_present(struct root_entry *root) +{ + return (root->val & 1); +} +static inline void set_root_present(struct root_entry *root) +{ + root->val |= 1; +} +static inline void set_root_value(struct root_entry *root, unsigned long value) +{ + root->val |= value & PAGE_MASK_4K; +} + +struct context_entry; +static inline struct context_entry * +get_context_addr_from_root(struct root_entry *root) +{ + return (struct context_entry *) + (root_present(root)?phys_to_virt( + root->val & PAGE_MASK_4K): + NULL); +} + +/* + * low 64 bits: + * 0: present + * 1: fault processing disable + * 2-3: translation type + * 12-63: address space root + * high 64 bits: + * 0-2: address width + * 3-6: aval + * 8-23: domain id + */ +struct context_entry { + u64 lo; + u64 hi; +}; +#define context_present(c) ((c).lo & 1) +#define context_fault_disable(c) (((c).lo >> 1) & 1) +#define context_translation_type(c) (((c).lo >> 2) & 3) +#define context_address_root(c) ((c).lo & PAGE_MASK_4K) +#define context_address_width(c) ((c).hi & 7) +#define context_domain_id(c) (((c).hi >> 8) & ((1 << 16) - 1)) + +#define context_set_present(c) do {(c).lo |= 1;} while (0) +#define context_set_fault_enable(c) \ + do {(c).lo &= (((u64)-1) << 2) | 1;} while (0) +#define context_set_translation_type(c, val) \ + do { \ + (c).lo &= (((u64)-1) << 4) | 3; \ + (c).lo |= ((val) & 3) << 2; \ + } while (0) +#define CONTEXT_TT_MULTI_LEVEL 0 +#define context_set_address_root(c, val) \ + do {(c).lo |= (val) & PAGE_MASK_4K;} while (0) +#define context_set_address_width(c, val) do {(c).hi |= (val) & 7;} while (0) +#define context_set_domain_id(c, val) \ + do {(c).hi |= ((val) & ((1 << 16) - 1)) << 8;} while (0) +#define context_clear_entry(c) do {(c).lo = 0; (c).hi = 0;} while (0) + +/* + * 0: readable + * 1: writable + * 2-6: reserved + * 7: super page + * 8-11: available + * 12-63: Host physcial address + */ +struct dma_pte { + u64 val; +}; +#define dma_clear_pte(p) do {(p).val = 0;} while (0) + +#define DMA_PTE_READ (1) +#define DMA_PTE_WRITE (2) + +#define dma_set_pte_readable(p) do {(p).val |= DMA_PTE_READ;} while (0) +#define dma_set_pte_writable(p) do {(p).val |= DMA_PTE_WRITE;} while (0) +#define dma_set_pte_prot(p, prot) \ + do {(p).val = ((p).val & ~3) | ((prot) & 3); } while (0) +#define dma_pte_addr(p) ((p).val & PAGE_MASK_4K) +#define dma_set_pte_addr(p, addr) do {\ + (p).val |= ((addr) & PAGE_MASK_4K); } while (0) +#define dma_pte_present(p) (((p).val & 3) != 0) + +struct intel_iommu; + +struct dmar_domain { + int id; /* domain id */ + struct intel_iommu *iommu; /* back pointer to owning iommu */ + + struct list_head devices; /* all devices' list */ + struct iova_domain iovad; /* iova's that belong to this domain */ + + struct dma_pte *pgd; /* virtual address */ + spinlock_t mapping_lock; /* page table lock */ + int gaw; /* max guest address width */ + + /* adjusted guest address width, 0 is level 2 30-bit */ + int agaw; + +#define DOMAIN_FLAG_MULTIPLE_DEVICES 1 + int flags; +}; + +/* PCI domain-device relationship */ +struct device_domain_info { + struct list_head link; /* link to domain siblings */ + struct list_head global; /* link to global list */ + u8 bus; /* PCI bus numer */ + u8 devfn; /* PCI devfn number */ + struct pci_dev *dev; /* it's NULL for PCIE-to-PCI bridge */ + struct dmar_domain *domain; /* pointer to domain */ +}; + +extern int init_dmars(void); + +struct intel_iommu { + void __iomem *reg; /* Pointer to hardware regs, virtual addr */ + u64 cap; + u64 ecap; + unsigned long *domain_ids; /* bitmap of domains */ + struct dmar_domain **domains; /* ptr to domains */ + int seg; + u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */ + spinlock_t lock; /* protect context, domain ids */ + spinlock_t register_lock; /* protect register handling */ + struct root_entry *root_entry; /* virtual address */ + + unsigned int irq; + unsigned char name[7]; /* Device Name */ + struct msi_msg saved_msg; + struct sys_device sysdev; +}; + +#ifndef CONFIG_DMAR_GFX_WA +static inline void iommu_prepare_gfx_mapping(void) +{ + return; +} +#endif /* !CONFIG_DMAR_GFX_WA */ + +#endif diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c new file mode 100644 index 00000000000..a84571c2936 --- /dev/null +++ b/drivers/pci/iova.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2006, Intel Corporation. + * + * This file is released under the GPLv2. + * + * Copyright (C) 2006 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> + */ + +#include "iova.h" + +void +init_iova_domain(struct iova_domain *iovad) +{ + spin_lock_init(&iovad->iova_alloc_lock); + spin_lock_init(&iovad->iova_rbtree_lock); + iovad->rbroot = RB_ROOT; + iovad->cached32_node = NULL; + +} + +static struct rb_node * +__get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn) +{ + if ((*limit_pfn != DMA_32BIT_PFN) || + (iovad->cached32_node == NULL)) + return rb_last(&iovad->rbroot); + else { + struct rb_node *prev_node = rb_prev(iovad->cached32_node); + struct iova *curr_iova = + container_of(iovad->cached32_node, struct iova, node); + *limit_pfn = curr_iova->pfn_lo - 1; + return prev_node; + } +} + +static void +__cached_rbnode_insert_update(struct iova_domain *iovad, + unsigned long limit_pfn, struct iova *new) +{ + if (limit_pfn != DMA_32BIT_PFN) + return; + iovad->cached32_node = &new->node; +} + +static void +__cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free) +{ + struct iova *cached_iova; + struct rb_node *curr; + + if (!iovad->cached32_node) + return; + curr = iovad->cached32_node; + cached_iova = container_of(curr, struct iova, node); + + if (free->pfn_lo >= cached_iova->pfn_lo) + iovad->cached32_node = rb_next(&free->node); +} + +/* Computes the padding size required, to make the + * the start address naturally aligned on its size + */ +static int +iova_get_pad_size(int size, unsigned int limit_pfn) +{ + unsigned int pad_size = 0; + unsigned int order = ilog2(size); + + if (order) + pad_size = (limit_pfn + 1) % (1 << order); + + return pad_size; +} + +static int __alloc_iova_range(struct iova_domain *iovad, unsigned long size, + unsigned long limit_pfn, struct iova *new, bool size_aligned) +{ + struct rb_node *curr = NULL; + unsigned long flags; + unsigned long saved_pfn; + unsigned int pad_size = 0; + + /* Walk the tree backwards */ + spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); + saved_pfn = limit_pfn; + curr = __get_cached_rbnode(iovad, &limit_pfn); + while (curr) { + struct iova *curr_iova = container_of(curr, struct iova, node); + if (limit_pfn < curr_iova->pfn_lo) + goto move_left; + else if (limit_pfn < curr_iova->pfn_hi) + goto adjust_limit_pfn; + else { + if (size_aligned) + pad_size = iova_get_pad_size(size, limit_pfn); + if ((curr_iova->pfn_hi + size + pad_size) <= limit_pfn) + break; /* found a free slot */ + } +adjust_limit_pfn: + limit_pfn = curr_iova->pfn_lo - 1; +move_left: + curr = rb_prev(curr); + } + + if (!curr) { + if (size_aligned) + pad_size = iova_get_pad_size(size, limit_pfn); + if ((IOVA_START_PFN + size + pad_size) > limit_pfn) { + spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); + return -ENOMEM; + } + } + + /* pfn_lo will point to size aligned address if size_aligned is set */ + new->pfn_lo = limit_pfn - (size + pad_size) + 1; + new->pfn_hi = new->pfn_lo + size - 1; + + spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); + return 0; +} + +static void +iova_insert_rbtree(struct rb_root *root, struct iova *iova) +{ + struct rb_node **new = &(root->rb_node), *parent = NULL; + /* Figure out where to put new node */ + while (*new) { + struct iova *this = container_of(*new, struct iova, node); + parent = *new; + + if (iova->pfn_lo < this->pfn_lo) + new = &((*new)->rb_left); + else if (iova->pfn_lo > this->pfn_lo) + new = &((*new)->rb_right); + else + BUG(); /* this should not happen */ + } + /* Add new node and rebalance tree. */ + rb_link_node(&iova->node, parent, new); + rb_insert_color(&iova->node, root); +} + +/** + * alloc_iova - allocates an iova + * @iovad - iova domain in question + * @size - size of page frames to allocate + * @limit_pfn - max limit address + * @size_aligned - set if size_aligned address range is required + * This function allocates an iova in the range limit_pfn to IOVA_START_PFN + * looking from limit_pfn instead from IOVA_START_PFN. If the size_aligned + * flag is set then the allocated address iova->pfn_lo will be naturally + * aligned on roundup_power_of_two(size). + */ +struct iova * +alloc_iova(struct iova_domain *iovad, unsigned long size, + unsigned long limit_pfn, + bool size_aligned) +{ + unsigned long flags; + struct iova *new_iova; + int ret; + + new_iova = alloc_iova_mem(); + if (!new_iova) + return NULL; + + /* If size aligned is set then round the size to + * to next power of two. + */ + if (size_aligned) + size = __roundup_pow_of_two(size); + + spin_lock_irqsave(&iovad->iova_alloc_lock, flags); + ret = __alloc_iova_range(iovad, size, limit_pfn, new_iova, + size_aligned); + + if (ret) { + spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags); + free_iova_mem(new_iova); + return NULL; + } + + /* Insert the new_iova into domain rbtree by holding writer lock */ + spin_lock(&iovad->iova_rbtree_lock); + iova_insert_rbtree(&iovad->rbroot, new_iova); + __cached_rbnode_insert_update(iovad, limit_pfn, new_iova); + spin_unlock(&iovad->iova_rbtree_lock); + + spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags); + + return new_iova; +} + +/** + * find_iova - find's an iova for a given pfn + * @iovad - iova domain in question. + * pfn - page frame number + * This function finds and returns an iova belonging to the + * given doamin which matches the given pfn. + */ +struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn) +{ + unsigned long flags; + struct rb_node *node; + + /* Take the lock so that no other thread is manipulating the rbtree */ + spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); + node = iovad->rbroot.rb_node; + while (node) { + struct iova *iova = container_of(node, struct iova, node); + + /* If pfn falls within iova's range, return iova */ + if ((pfn >= iova->pfn_lo) && (pfn <= iova->pfn_hi)) { + spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); + /* We are not holding the lock while this iova + * is referenced by the caller as the same thread + * which called this function also calls __free_iova() + * and it is by desing that only one thread can possibly + * reference a particular iova and hence no conflict. + */ + return iova; + } + + if (pfn < iova->pfn_lo) + node = node->rb_left; + else if (pfn > iova->pfn_lo) + node = node->rb_right; + } + + spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); + return NULL; +} + +/** + * __free_iova - frees the given iova + * @iovad: iova domain in question. + * @iova: iova in question. + * Frees the given iova belonging to the giving domain + */ +void +__free_iova(struct iova_domain *iovad, struct iova *iova) +{ + unsigned long flags; + + spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); + __cached_rbnode_delete_update(iovad, iova); + rb_erase(&iova->node, &iovad->rbroot); + spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); + free_iova_mem(iova); +} + +/** + * free_iova - finds and frees the iova for a given pfn + * @iovad: - iova domain in question. + * @pfn: - pfn that is allocated previously + * This functions finds an iova for a given pfn and then + * frees the iova from that domain. + */ +void +free_iova(struct iova_domain *iovad, unsigned long pfn) +{ + struct iova *iova = find_iova(iovad, pfn); + if (iova) + __free_iova(iovad, iova); + +} + +/** + * put_iova_domain - destroys the iova doamin + * @iovad: - iova domain in question. + * All the iova's in that domain are destroyed. + */ +void put_iova_domain(struct iova_domain *iovad) +{ + struct rb_node *node; + unsigned long flags; + + spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); + node = rb_first(&iovad->rbroot); + while (node) { + struct iova *iova = container_of(node, struct iova, node); + rb_erase(node, &iovad->rbroot); + free_iova_mem(iova); + node = rb_first(&iovad->rbroot); + } + spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); +} + +static int +__is_range_overlap(struct rb_node *node, + unsigned long pfn_lo, unsigned long pfn_hi) +{ + struct iova *iova = container_of(node, struct iova, node); + + if ((pfn_lo <= iova->pfn_hi) && (pfn_hi >= iova->pfn_lo)) + return 1; + return 0; +} + +static struct iova * +__insert_new_range(struct iova_domain *iovad, + unsigned long pfn_lo, unsigned long pfn_hi) +{ + struct iova *iova; + + iova = alloc_iova_mem(); + if (!iova) + return iova; + + iova->pfn_hi = pfn_hi; + iova->pfn_lo = pfn_lo; + iova_insert_rbtree(&iovad->rbroot, iova); + return iova; +} + +static void +__adjust_overlap_range(struct iova *iova, + unsigned long *pfn_lo, unsigned long *pfn_hi) +{ + if (*pfn_lo < iova->pfn_lo) + iova->pfn_lo = *pfn_lo; + if (*pfn_hi > iova->pfn_hi) + *pfn_lo = iova->pfn_hi + 1; +} + +/** + * reserve_iova - reserves an iova in the given range + * @iovad: - iova domain pointer + * @pfn_lo: - lower page frame address + * @pfn_hi:- higher pfn adderss + * This function allocates reserves the address range from pfn_lo to pfn_hi so + * that this address is not dished out as part of alloc_iova. + */ +struct iova * +reserve_iova(struct iova_domain *iovad, + unsigned long pfn_lo, unsigned long pfn_hi) +{ + struct rb_node *node; + unsigned long flags; + struct iova *iova; + unsigned int overlap = 0; + + spin_lock_irqsave(&iovad->iova_alloc_lock, flags); + spin_lock(&iovad->iova_rbtree_lock); + for (node = rb_first(&iovad->rbroot); node; node = rb_next(node)) { + if (__is_range_overlap(node, pfn_lo, pfn_hi)) { + iova = container_of(node, struct iova, node); + __adjust_overlap_range(iova, &pfn_lo, &pfn_hi); + if ((pfn_lo >= iova->pfn_lo) && + (pfn_hi <= iova->pfn_hi)) + goto finish; + overlap = 1; + + } else if (overlap) + break; + } + + /* We are here either becasue this is the first reserver node + * or need to insert remaining non overlap addr range + */ + iova = __insert_new_range(iovad, pfn_lo, pfn_hi); +finish: + + spin_unlock(&iovad->iova_rbtree_lock); + spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags); + return iova; +} + +/** + * copy_reserved_iova - copies the reserved between domains + * @from: - source doamin from where to copy + * @to: - destination domin where to copy + * This function copies reserved iova's from one doamin to + * other. + */ +void +copy_reserved_iova(struct iova_domain *from, struct iova_domain *to) +{ + unsigned long flags; + struct rb_node *node; + + spin_lock_irqsave(&from->iova_alloc_lock, flags); + spin_lock(&from->iova_rbtree_lock); + for (node = rb_first(&from->rbroot); node; node = rb_next(node)) { + struct iova *iova = container_of(node, struct iova, node); + struct iova *new_iova; + new_iova = reserve_iova(to, iova->pfn_lo, iova->pfn_hi); + if (!new_iova) + printk(KERN_ERR "Reserve iova range %lx@%lx failed\n", + iova->pfn_lo, iova->pfn_lo); + } + spin_unlock(&from->iova_rbtree_lock); + spin_unlock_irqrestore(&from->iova_alloc_lock, flags); +} diff --git a/drivers/pci/iova.h b/drivers/pci/iova.h new file mode 100644 index 00000000000..ae3028d5a94 --- /dev/null +++ b/drivers/pci/iova.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2006, Intel Corporation. + * + * This file is released under the GPLv2. + * + * Copyright (C) 2006 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> + * + */ + +#ifndef _IOVA_H_ +#define _IOVA_H_ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/rbtree.h> +#include <linux/dma-mapping.h> + +/* + * We need a fixed PAGE_SIZE of 4K irrespective of + * arch PAGE_SIZE for IOMMU page tables. + */ +#define PAGE_SHIFT_4K (12) +#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K) +#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K) +#define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K) + +/* IO virtual address start page frame number */ +#define IOVA_START_PFN (1) + +#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K) +#define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK) +#define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK) + +/* iova structure */ +struct iova { + struct rb_node node; + unsigned long pfn_hi; /* IOMMU dish out addr hi */ + unsigned long pfn_lo; /* IOMMU dish out addr lo */ +}; + +/* holds all the iova translations for a domain */ +struct iova_domain { + spinlock_t iova_alloc_lock;/* Lock to protect iova allocation */ + spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */ + struct rb_root rbroot; /* iova domain rbtree root */ + struct rb_node *cached32_node; /* Save last alloced node */ +}; + +struct iova *alloc_iova_mem(void); +void free_iova_mem(struct iova *iova); +void free_iova(struct iova_domain *iovad, unsigned long pfn); +void __free_iova(struct iova_domain *iovad, struct iova *iova); +struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size, + unsigned long limit_pfn, + bool size_aligned); +struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo, + unsigned long pfn_hi); +void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to); +void init_iova_domain(struct iova_domain *iovad); +struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn); +void put_iova_domain(struct iova_domain *iovad); + +#endif diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 6fda33de84e..fc87e14b50d 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -90,3 +90,4 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) return NULL; } +struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 5db6b6690b5..463a5a9d583 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -837,6 +837,19 @@ static void pci_release_dev(struct device *dev) kfree(pci_dev); } +static void set_pcie_port_type(struct pci_dev *pdev) +{ + int pos; + u16 reg16; + + pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); + if (!pos) + return; + pdev->is_pcie = 1; + pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); + pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; +} + /** * pci_cfg_space_size - get the configuration space size of the PCI device. * @dev: PCI device @@ -951,6 +964,7 @@ pci_scan_device(struct pci_bus *bus, int devfn) dev->device = (l >> 16) & 0xffff; dev->cfg_size = pci_cfg_space_size(dev); dev->error_state = pci_channel_io_normal; + set_pcie_port_type(dev); /* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer) set this higher, assuming the system even supports it. */ diff --git a/drivers/pci/search.c b/drivers/pci/search.c index c6e79d01ce3..b001b5922e3 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -14,6 +14,40 @@ #include "pci.h" DECLARE_RWSEM(pci_bus_sem); +/* + * find the upstream PCIE-to-PCI bridge of a PCI device + * if the device is PCIE, return NULL + * if the device isn't connected to a PCIE bridge (that is its parent is a + * legacy PCI bridge and the bridge is directly connected to bus 0), return its + * parent + */ +struct pci_dev * +pci_find_upstream_pcie_bridge(struct pci_dev *pdev) +{ + struct pci_dev *tmp = NULL; + + if (pdev->is_pcie) + return NULL; + while (1) { + if (!pdev->bus->self) + break; + pdev = pdev->bus->self; + /* a p2p bridge */ + if (!pdev->is_pcie) { + tmp = pdev; + continue; + } + /* PCI device should connect to a PCIE bridge */ + if (pdev->pcie_type != PCI_EXP_TYPE_PCI_BRIDGE) { + /* Busted hardware? */ + WARN_ON_ONCE(1); + return NULL; + } + return pdev; + } + + return tmp; +} static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr) { diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index e7a1642b2aa..d4f8fcded51 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c @@ -134,7 +134,7 @@ int init_vfc_hw(struct vfc_dev *dev) int init_vfc_devstruct(struct vfc_dev *dev, int instance) { dev->instance=instance; - init_MUTEX(&dev->device_lock_sem); + mutex_init(&dev->device_lock_mtx); dev->control_reg=0; dev->busy=0; return 0; diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index fb14014ee16..afb262b4be1 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -1840,7 +1840,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) { if (srb->sc_data_direction == DMA_TO_DEVICE || srb->sc_data_direction == DMA_BIDIRECTIONAL) { struct scatterlist *sg = scsi_sglist(srb); - char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + char *buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length); kunmap_atomic(buf - sg->offset, KM_IRQ0); } @@ -1919,7 +1919,7 @@ static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re char *buf; unsigned long flags = 0; local_irq_save(flags); - buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length); kunmap_atomic(buf - sg->offset, KM_IRQ0); local_irq_restore(flags); diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index a64153b9603..59716ebeb10 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -1469,7 +1469,7 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id, struct scatterlist *sg = scsi_sglist(cmd); local_irq_save(flags); - buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; transfer_len = min(sg->length, len); memcpy(buf, data, transfer_len); diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 988f0bc5eda..2597209183d 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -298,8 +298,7 @@ static __inline__ void initialize_SCp(Scsi_Cmnd * cmd) if (cmd->use_sg) { cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; - cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+ - cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length; } else { cmd->SCp.buffer = NULL; @@ -2143,8 +2142,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { ++cmd->SCp.buffer; --cmd->SCp.buffers_residual; cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+ - cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); dprintk(NDEBUG_INFORMATION, ("scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual)); } /* diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c index 96e8e29aa05..5b0efc90391 100644 --- a/drivers/scsi/NCR53C9x.c +++ b/drivers/scsi/NCR53C9x.c @@ -927,7 +927,7 @@ static void esp_get_dmabufs(struct NCR_ESP *esp, Scsi_Cmnd *sp) esp->dma_mmu_get_scsi_sgl(esp, sp); else sp->SCp.ptr = - (char *) virt_to_phys((page_address(sp->SCp.buffer->page) + sp->SCp.buffer->offset)); + (char *) virt_to_phys(sg_virt(sp->SCp.buffer)); } } @@ -1748,7 +1748,7 @@ static inline void advance_sg(struct NCR_ESP *esp, Scsi_Cmnd *sp) if (esp->dma_advance_sg) esp->dma_advance_sg (sp); else - sp->SCp.ptr = (char *) virt_to_phys((page_address(sp->SCp.buffer->page) + sp->SCp.buffer->offset)); + sp->SCp.ptr = (char *) virt_to_phys(sg_virt(sp->SCp.buffer)); } diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index 3168a179484..137d065db3d 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -875,8 +875,7 @@ static void NCR53c406a_intr(void *dev_id) outb(TRANSFER_INFO | DMA_OP, CMD_REG); #if USE_PIO scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) { - NCR53c406a_pio_write(page_address(sg->page) + sg->offset, - sg->length); + NCR53c406a_pio_write(sg_virt(sg), sg->length); } REG0; #endif /* USE_PIO */ @@ -897,8 +896,7 @@ static void NCR53c406a_intr(void *dev_id) outb(TRANSFER_INFO | DMA_OP, CMD_REG); #if USE_PIO scsi_for_each_sg(current_SC, sg, scsi_sg_count(current_SC), i) { - NCR53c406a_pio_read(page_address(sg->page) + sg->offset, - sg->length); + NCR53c406a_pio_read(sg_virt(sg), sg->length); } REG0; #endif /* USE_PIO */ diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 80e448d0f3d..a77ab8d693d 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -356,7 +356,7 @@ static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigne int transfer_len; struct scatterlist *sg = scsi_sglist(scsicmd); - buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; transfer_len = min(sg->length, len + offset); transfer_len -= offset; diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index a58c265dc8a..ea8c6994764 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -613,7 +613,7 @@ struct aha152x_scdata { #define SCNEXT(SCpnt) SCDATA(SCpnt)->next #define SCSEM(SCpnt) SCDATA(SCpnt)->done -#define SG_ADDRESS(buffer) ((char *) (page_address((buffer)->page)+(buffer)->offset)) +#define SG_ADDRESS(buffer) ((char *) sg_virt((buffer))) /* state handling */ static void seldi_run(struct Scsi_Host *shpnt); diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 961a1882cb7..bbcc2c52d79 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -49,7 +49,7 @@ #include "aha1542.h" #define SCSI_BUF_PA(address) isa_virt_to_bus(address) -#define SCSI_SG_PA(sgent) (isa_page_to_bus((sgent)->page) + (sgent)->offset) +#define SCSI_SG_PA(sgent) (isa_page_to_bus(sg_page((sgent))) + (sgent)->offset) static void BAD_DMA(void *address, unsigned int length) { @@ -66,8 +66,7 @@ static void BAD_SG_DMA(Scsi_Cmnd * SCpnt, int badseg) { printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%llx length %u\n", - badseg, nseg, - page_address(sgp->page) + sgp->offset, + badseg, nseg, sg_virt(sgp), (unsigned long long)SCSI_SG_PA(sgp), sgp->length); @@ -712,8 +711,7 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) printk(KERN_CRIT "Bad segment list supplied to aha1542.c (%d, %d)\n", SCpnt->use_sg, i); scsi_for_each_sg(SCpnt, sg, SCpnt->use_sg, i) { printk(KERN_CRIT "%d: %p %d\n", i, - (page_address(sg->page) + - sg->offset), sg->length); + sg_virt(sg), sg->length); }; printk(KERN_CRIT "cptr %x: ", (unsigned int) cptr); ptr = (unsigned char *) &cptr[i]; diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index f81777586b8..f7a252885a5 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -1343,7 +1343,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ /* 4 bytes: Areca io control code */ sg = scsi_sglist(cmd); - buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; if (scsi_sg_count(cmd) > 1) { retvalue = ARCMSR_MESSAGE_FAIL; goto message_out; @@ -1593,7 +1593,7 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, strncpy(&inqdata[32], "R001", 4); /* Product Revision */ sg = scsi_sglist(cmd); - buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; memcpy(buffer, inqdata, sizeof(inqdata)); sg = scsi_sglist(cmd); diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 52d0b87e9aa..d1780980fb2 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -515,8 +515,7 @@ static inline void initialize_SCp(Scsi_Cmnd *cmd) if (cmd->use_sg) { cmd->SCp.buffer = (struct scatterlist *)cmd->request_buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; - cmd->SCp.ptr = (char *)page_address(cmd->SCp.buffer->page) + - cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length; /* ++roman: Try to merge some scatter-buffers if they are at * contiguous physical addresses. @@ -2054,8 +2053,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) ++cmd->SCp.buffer; --cmd->SCp.buffers_residual; cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + - cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); /* ++roman: Try to merge some scatter-buffers if * they are at contiguous physical addresses. */ diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c index 96180bb47e4..982c5092be1 100644 --- a/drivers/scsi/eata_pio.c +++ b/drivers/scsi/eata_pio.c @@ -172,7 +172,7 @@ static void IncStat(struct scsi_pointer *SCp, unsigned int Increment) SCp->Status = 0; else { SCp->buffer++; - SCp->ptr = page_address(SCp->buffer->page) + SCp->buffer->offset; + SCp->ptr = sg_virt(SCp->buffer); SCp->this_residual = SCp->buffer->length; } } @@ -410,7 +410,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd, } else { cmd->SCp.buffer = cmd->request_buffer; cmd->SCp.buffers_residual = cmd->use_sg; - cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length; } cmd->SCp.Status = (cmd->SCp.this_residual != 0); /* TRUE as long as bytes diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c index 668569e8856..8335b608e57 100644 --- a/drivers/scsi/fd_mcs.c +++ b/drivers/scsi/fd_mcs.c @@ -973,7 +973,7 @@ static irqreturn_t fd_mcs_intr(int irq, void *dev_id) if (current_SC->SCp.buffers_residual) { --current_SC->SCp.buffers_residual; ++current_SC->SCp.buffer; - current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; + current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer); current_SC->SCp.this_residual = current_SC->SCp.buffer->length; } else break; @@ -1006,7 +1006,7 @@ static irqreturn_t fd_mcs_intr(int irq, void *dev_id) if (!current_SC->SCp.this_residual && current_SC->SCp.buffers_residual) { --current_SC->SCp.buffers_residual; ++current_SC->SCp.buffer; - current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; + current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer); current_SC->SCp.this_residual = current_SC->SCp.buffer->length; } } @@ -1109,7 +1109,7 @@ static int fd_mcs_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) if (current_SC->use_sg) { current_SC->SCp.buffer = (struct scatterlist *) current_SC->request_buffer; - current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; + current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer); current_SC->SCp.this_residual = current_SC->SCp.buffer->length; current_SC->SCp.buffers_residual = current_SC->use_sg - 1; } else { diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 5d282e6a6ae..2cd6b4959eb 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -1321,7 +1321,7 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id) if (current_SC->SCp.buffers_residual) { --current_SC->SCp.buffers_residual; ++current_SC->SCp.buffer; - current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; + current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer); current_SC->SCp.this_residual = current_SC->SCp.buffer->length; } else break; @@ -1354,7 +1354,7 @@ static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id) && current_SC->SCp.buffers_residual) { --current_SC->SCp.buffers_residual; ++current_SC->SCp.buffer; - current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) + current_SC->SCp.buffer->offset; + current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer); current_SC->SCp.this_residual = current_SC->SCp.buffer->length; } } @@ -1439,8 +1439,7 @@ static int fdomain_16x0_queue(struct scsi_cmnd *SCpnt, if (scsi_sg_count(current_SC)) { current_SC->SCp.buffer = scsi_sglist(current_SC); - current_SC->SCp.ptr = page_address(current_SC->SCp.buffer->page) - + current_SC->SCp.buffer->offset; + current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer); current_SC->SCp.this_residual = current_SC->SCp.buffer->length; current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1; } else { diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 3ac080ee6e2..5ab3ce76248 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -2374,18 +2374,18 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, if (cpsum+cpnow > cpcount) cpnow = cpcount - cpsum; cpsum += cpnow; - if (!sl->page) { + if (!sg_page(sl)) { printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n", ha->hanum); return; } local_irq_save(flags); - address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset; + address = kmap_atomic(sg_page(sl), KM_BIO_SRC_IRQ) + sl->offset; if (to_buffer) memcpy(buffer, address, cpnow); else memcpy(address, buffer, cpnow); - flush_dcache_page(sl->page); + flush_dcache_page(sg_page(sl)); kunmap_atomic(address, KM_BIO_SRC_IRQ); local_irq_restore(flags); if (cpsum == cpcount) diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 714e6273a70..db004a45073 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -1828,7 +1828,7 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) BUG_ON(scsi_sg_count(cmd) > 16); scsi_for_each_sg(cmd, sg, scsi_sg_count(cmd), i) { - ld(shpnt)[ldn].sge[i].address = (void *) (isa_page_to_bus(sg->page) + sg->offset); + ld(shpnt)[ldn].sge[i].address = (void *) (isa_page_to_bus(sg_page(sg)) + sg->offset); ld(shpnt)[ldn].sge[i].byte_length = sg->length; } scb->enable |= IM_POINTER_TO_LIST; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 252d1806467..8d0244c2e7d 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -175,18 +175,18 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne while (bcount) { count = min(pc->sg->length - pc->b_count, bcount); - if (PageHighMem(pc->sg->page)) { + if (PageHighMem(sg_page(pc->sg))) { unsigned long flags; local_irq_save(flags); - buf = kmap_atomic(pc->sg->page, KM_IRQ0) + + buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) + pc->sg->offset; drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count); kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); local_irq_restore(flags); } else { - buf = page_address(pc->sg->page) + pc->sg->offset; + buf = sg_virt(pc->sg); drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count); } @@ -212,18 +212,18 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign while (bcount) { count = min(pc->sg->length - pc->b_count, bcount); - if (PageHighMem(pc->sg->page)) { + if (PageHighMem(sg_page(pc->sg))) { unsigned long flags; local_irq_save(flags); - buf = kmap_atomic(pc->sg->page, KM_IRQ0) + + buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) + pc->sg->offset; drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count); kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); local_irq_restore(flags); } else { - buf = page_address(pc->sg->page) + pc->sg->offset; + buf = sg_virt(pc->sg); drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count); } diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 74cdc1f0a78..a3d0c6b1495 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -705,9 +705,7 @@ static int imm_completion(struct scsi_cmnd *cmd) cmd->SCp.buffer++; cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = - page_address(cmd->SCp.buffer->page) + - cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); /* * Make sure that we transfer even number of bytes @@ -844,9 +842,7 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *cmd) cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = - page_address(cmd->SCp.buffer->page) + - cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); } else { /* else fill the only available buffer */ cmd->SCp.buffer = NULL; diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index ab7cbf3449c..c8b452f2878 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c @@ -372,7 +372,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) if (cmd->use_sg) { cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; - cmd->SCp.ptr = (char *) page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length; } else { cmd->SCp.buffer = NULL; @@ -764,7 +764,7 @@ static void transfer_bytes(Scsi_Cmnd * cmd, int data_in_dir) ++cmd->SCp.buffer; --cmd->SCp.buffers_residual; cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); } /* Set up hardware registers */ diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index c316a0bcae6..439b97a6a26 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -2872,6 +2872,7 @@ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len) } scatterlist = sglist->scatterlist; + sg_init_table(scatterlist, num_elem); sglist->order = order; sglist->num_sg = num_elem; @@ -2884,12 +2885,12 @@ static struct ipr_sglist *ipr_alloc_ucode_buffer(int buf_len) /* Free up what we already allocated */ for (j = i - 1; j >= 0; j--) - __free_pages(scatterlist[j].page, order); + __free_pages(sg_page(&scatterlist[j]), order); kfree(sglist); return NULL; } - scatterlist[i].page = page; + sg_set_page(&scatterlist[i], page); } return sglist; @@ -2910,7 +2911,7 @@ static void ipr_free_ucode_buffer(struct ipr_sglist *sglist) int i; for (i = 0; i < sglist->num_sg; i++) - __free_pages(sglist->scatterlist[i].page, sglist->order); + __free_pages(sg_page(&sglist->scatterlist[i]), sglist->order); kfree(sglist); } @@ -2940,9 +2941,11 @@ static int ipr_copy_ucode_buffer(struct ipr_sglist *sglist, scatterlist = sglist->scatterlist; for (i = 0; i < (len / bsize_elem); i++, buffer += bsize_elem) { - kaddr = kmap(scatterlist[i].page); + struct page *page = sg_page(&scatterlist[i]); + + kaddr = kmap(page); memcpy(kaddr, buffer, bsize_elem); - kunmap(scatterlist[i].page); + kunmap(page); scatterlist[i].length = bsize_elem; @@ -2953,9 +2956,11 @@ static int ipr_copy_ucode_buffer(struct ipr_sglist *sglist, } if (len % bsize_elem) { - kaddr = kmap(scatterlist[i].page); + struct page *page = sg_page(&scatterlist[i]); + + kaddr = kmap(page); memcpy(kaddr, buffer, len % bsize_elem); - kunmap(scatterlist[i].page); + kunmap(page); scatterlist[i].length = len % bsize_elem; } diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index edaac2714c5..5c5a9b2628f 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -1515,7 +1515,7 @@ static int ips_is_passthru(struct scsi_cmnd *SC) /* kmap_atomic() ensures addressability of the user buffer.*/ /* local_irq_save() protects the KM_IRQ0 address slot. */ local_irq_save(flags); - buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + buffer = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; if (buffer && buffer[0] == 'C' && buffer[1] == 'O' && buffer[2] == 'P' && buffer[3] == 'P') { kunmap_atomic(buffer - sg->offset, KM_IRQ0); @@ -3523,7 +3523,7 @@ ips_scmd_buf_write(struct scsi_cmnd *scmd, void *data, unsigned int count) /* kmap_atomic() ensures addressability of the data buffer.*/ /* local_irq_save() protects the KM_IRQ0 address slot. */ local_irq_save(flags); - buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset; + buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset; memcpy(buffer, &cdata[xfer_cnt], min_cnt); kunmap_atomic(buffer - sg[i].offset, KM_IRQ0); local_irq_restore(flags); @@ -3556,7 +3556,7 @@ ips_scmd_buf_read(struct scsi_cmnd *scmd, void *data, unsigned int count) /* kmap_atomic() ensures addressability of the data buffer.*/ /* local_irq_save() protects the KM_IRQ0 address slot. */ local_irq_save(flags); - buffer = kmap_atomic(sg[i].page, KM_IRQ0) + sg[i].offset; + buffer = kmap_atomic(sg_page(&sg[i]), KM_IRQ0) + sg[i].offset; memcpy(&cdata[xfer_cnt], buffer, min_cnt); kunmap_atomic(buffer - sg[i].offset, KM_IRQ0); local_irq_restore(flags); diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index a21455d0274..6ce4109efdf 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -70,9 +70,7 @@ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); static inline void iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) { - ibuf->sg.page = virt_to_page(vbuf); - ibuf->sg.offset = offset_in_page(vbuf); - ibuf->sg.length = size; + sg_init_one(&ibuf->sg, vbuf, size); ibuf->sent = 0; ibuf->use_sendmsg = 1; } @@ -80,13 +78,14 @@ iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) static inline void iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) { - ibuf->sg.page = sg->page; + sg_init_table(&ibuf->sg, 1); + sg_set_page(&ibuf->sg, sg_page(sg)); ibuf->sg.offset = sg->offset; ibuf->sg.length = sg->length; /* * Fastpath: sg element fits into single page */ - if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page)) + if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg_page(sg))) ibuf->use_sendmsg = 0; else ibuf->use_sendmsg = 1; @@ -716,7 +715,7 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) for (i = tcp_ctask->sg_count; i < scsi_sg_count(sc); i++) { char *dest; - dest = kmap_atomic(sg[i].page, KM_SOFTIRQ0); + dest = kmap_atomic(sg_page(&sg[i]), KM_SOFTIRQ0); rc = iscsi_ctask_copy(tcp_conn, ctask, dest + sg[i].offset, sg[i].length, offset); kunmap_atomic(dest, KM_SOFTIRQ0); @@ -1103,9 +1102,9 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) * slab case. */ if (buf->use_sendmsg) - res = sock_no_sendpage(sk, buf->sg.page, offset, size, flags); + res = sock_no_sendpage(sk, sg_page(&buf->sg), offset, size, flags); else - res = tcp_conn->sendpage(sk, buf->sg.page, offset, size, flags); + res = tcp_conn->sendpage(sk, sg_page(&buf->sg), offset, size, flags); if (res >= 0) { conn->txdata_octets += res; diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 10d1aff9938..66c65203573 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -658,7 +658,7 @@ mega_build_cmd(adapter_t *adapter, Scsi_Cmnd *cmd, int *busy) struct scatterlist *sg; sg = scsi_sglist(cmd); - buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; memset(buf, 0, cmd->cmnd[4]); kunmap_atomic(buf - sg->offset, KM_IRQ0); @@ -1542,10 +1542,8 @@ mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status) if( cmd->cmnd[0] == INQUIRY && !islogical ) { sgl = scsi_sglist(cmd); - if( sgl->page ) { - c = *(unsigned char *) - page_address((&sgl[0])->page) + - (&sgl[0])->offset; + if( sg_page(sgl) ) { + c = *(unsigned char *) sg_virt(&sgl[0]); } else { printk(KERN_WARNING "megaraid: invalid sg.\n"); diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 78779209ac8..c8923108183 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -1584,10 +1584,8 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) caddr_t vaddr; sgl = scsi_sglist(scp); - if (sgl->page) { - vaddr = (caddr_t) - (page_address((&sgl[0])->page) - + (&sgl[0])->offset); + if (sg_page(sgl)) { + vaddr = (caddr_t) sg_virt(&sgl[0]); memset(vaddr, 0, scp->cmnd[4]); } @@ -2328,10 +2326,8 @@ megaraid_mbox_dpc(unsigned long devp) && IS_RAID_CH(raid_dev, scb->dev_channel)) { sgl = scsi_sglist(scp); - if (sgl->page) { - c = *(unsigned char *) - (page_address((&sgl[0])->page) + - (&sgl[0])->offset); + if (sg_page(sgl)) { + c = *(unsigned char *) sg_virt(&sgl[0]); } else { con_log(CL_ANN, (KERN_WARNING "megaraid mailbox: invalid sg:%d\n", diff --git a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c index 26a6d55faf3..8e5eadbd5c5 100644 --- a/drivers/scsi/oktagon_esp.c +++ b/drivers/scsi/oktagon_esp.c @@ -550,8 +550,7 @@ void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp) void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd *sp) { - sp->SCp.ptr = page_address(sp->SCp.buffer->page)+ - sp->SCp.buffer->offset; + sp->SCp.ptr = sg_virt(sp->SCp.buffer); } void dma_mmu_release_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd *sp) @@ -564,8 +563,7 @@ void dma_mmu_release_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd *sp) void dma_advance_sg(Scsi_Cmnd *sp) { - sp->SCp.ptr = page_address(sp->SCp.buffer->page)+ - sp->SCp.buffer->offset; + sp->SCp.ptr = sg_virt(sp->SCp.buffer); } diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 331b789937c..1c5c4b68f20 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -542,7 +542,7 @@ static int osst_verify_frame(struct osst_tape * STp, int frame_seq_number, int q if (STp->raw) { if (STp->buffer->syscall_result) { for (i=0; i < STp->buffer->sg_segs; i++) - memset(page_address(STp->buffer->sg[i].page), + memset(page_address(sg_page(&STp->buffer->sg[i])), 0, STp->buffer->sg[i].length); strcpy(STp->buffer->b_data, "READ ERROR ON FRAME"); } else @@ -4437,7 +4437,7 @@ static int os_scsi_tape_open(struct inode * inode, struct file * filp) for (i = 0, b_size = 0; (i < STp->buffer->sg_segs) && ((b_size + STp->buffer->sg[i].length) <= OS_DATA_SIZE); b_size += STp->buffer->sg[i++].length); - STp->buffer->aux = (os_aux_t *) (page_address(STp->buffer->sg[i].page) + OS_DATA_SIZE - b_size); + STp->buffer->aux = (os_aux_t *) (page_address(sg_page(&STp->buffer->sg[i])) + OS_DATA_SIZE - b_size); #if DEBUG printk(OSST_DEB_MSG "%s:D: b_data points to %p in segment 0 at %p\n", name, STp->buffer->b_data, page_address(STp->buffer->sg[0].page)); @@ -5252,25 +5252,26 @@ static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma) /* Try to allocate the first segment up to OS_DATA_SIZE and the others big enough to reach the goal (code assumes no segments in place) */ for (b_size = OS_DATA_SIZE, order = OSST_FIRST_ORDER; b_size >= PAGE_SIZE; order--, b_size /= 2) { - STbuffer->sg[0].page = alloc_pages(priority, order); + struct page *page = alloc_pages(priority, order); + STbuffer->sg[0].offset = 0; - if (STbuffer->sg[0].page != NULL) { + if (page != NULL) { + sg_set_page(&STbuffer->sg[0], page); STbuffer->sg[0].length = b_size; - STbuffer->b_data = page_address(STbuffer->sg[0].page); + STbuffer->b_data = page_address(page); break; } } - if (STbuffer->sg[0].page == NULL) { + if (sg_page(&STbuffer->sg[0]) == NULL) { printk(KERN_NOTICE "osst :I: Can't allocate tape buffer main segment.\n"); return 0; } /* Got initial segment of 'bsize,order', continue with same size if possible, except for AUX */ for (segs=STbuffer->sg_segs=1, got=b_size; segs < max_segs && got < OS_FRAME_SIZE; ) { - STbuffer->sg[segs].page = - alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order); + struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order); STbuffer->sg[segs].offset = 0; - if (STbuffer->sg[segs].page == NULL) { + if (page == NULL) { if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) { b_size /= 2; /* Large enough for the rest of the buffers */ order--; @@ -5284,6 +5285,7 @@ static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma) normalize_buffer(STbuffer); return 0; } + sg_set_page(&STbuffer->sg[segs], page); STbuffer->sg[segs].length = (OS_FRAME_SIZE - got <= PAGE_SIZE / 2) ? (OS_FRAME_SIZE - got) : b_size; got += STbuffer->sg[segs].length; STbuffer->buffer_size = got; @@ -5316,7 +5318,7 @@ static void normalize_buffer(struct osst_buffer *STbuffer) b_size < STbuffer->sg[i].length; b_size *= 2, order++); - __free_pages(STbuffer->sg[i].page, order); + __free_pages(sg_page(&STbuffer->sg[i]), order); STbuffer->buffer_size -= STbuffer->sg[i].length; } #if DEBUG @@ -5344,7 +5346,7 @@ static int append_to_buffer(const char __user *ubp, struct osst_buffer *st_bp, i for ( ; i < st_bp->sg_segs && do_count > 0; i++) { cnt = st_bp->sg[i].length - offset < do_count ? st_bp->sg[i].length - offset : do_count; - res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt); + res = copy_from_user(page_address(sg_page(&st_bp->sg[i])) + offset, ubp, cnt); if (res) return (-EFAULT); do_count -= cnt; @@ -5377,7 +5379,7 @@ static int from_buffer(struct osst_buffer *st_bp, char __user *ubp, int do_count for ( ; i < st_bp->sg_segs && do_count > 0; i++) { cnt = st_bp->sg[i].length - offset < do_count ? st_bp->sg[i].length - offset : do_count; - res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt); + res = copy_to_user(ubp, page_address(sg_page(&st_bp->sg[i])) + offset, cnt); if (res) return (-EFAULT); do_count -= cnt; @@ -5410,7 +5412,7 @@ static int osst_zero_buffer_tail(struct osst_buffer *st_bp) i < st_bp->sg_segs && do_count > 0; i++) { cnt = st_bp->sg[i].length - offset < do_count ? st_bp->sg[i].length - offset : do_count ; - memset(page_address(st_bp->sg[i].page) + offset, 0, cnt); + memset(page_address(sg_page(&st_bp->sg[i])) + offset, 0, cnt); do_count -= cnt; offset = 0; } @@ -5430,7 +5432,7 @@ static int osst_copy_to_buffer(struct osst_buffer *st_bp, unsigned char *ptr) for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) { cnt = st_bp->sg[i].length < do_count ? st_bp->sg[i].length : do_count ; - memcpy(page_address(st_bp->sg[i].page), ptr, cnt); + memcpy(page_address(sg_page(&st_bp->sg[i])), ptr, cnt); do_count -= cnt; ptr += cnt; } @@ -5451,7 +5453,7 @@ static int osst_copy_from_buffer(struct osst_buffer *st_bp, unsigned char *ptr) for (i = 0; i < st_bp->sg_segs && do_count > 0; i++) { cnt = st_bp->sg[i].length < do_count ? st_bp->sg[i].length : do_count ; - memcpy(ptr, page_address(st_bp->sg[i].page), cnt); + memcpy(ptr, page_address(sg_page(&st_bp->sg[i])), cnt); do_count -= cnt; ptr += cnt; } diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index 98397559c53..7db28cd4944 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -393,7 +393,7 @@ enum _burst_mode { #define MSG_EXT_SDTR 0x01 /* scatter-gather table */ -# define BUFFER_ADDR ((char *)((unsigned int)(SCpnt->SCp.buffer->page) + SCpnt->SCp.buffer->offset)) +# define BUFFER_ADDR ((char *)((sg_virt(SCpnt->SCp.buffer)))) #endif /*__nsp_cs__*/ /* end */ diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 190e2a7d706..969b9387a0c 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -443,8 +443,7 @@ SYM53C500_intr(int irq, void *dev_id) scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) { SYM53C500_pio_write(fast_pio, port_base, - page_address(sg->page) + sg->offset, - sg->length); + sg_virt(sg), sg->length); } REG0(port_base); } @@ -463,8 +462,7 @@ SYM53C500_intr(int irq, void *dev_id) scsi_for_each_sg(curSC, sg, scsi_sg_count(curSC), i) { SYM53C500_pio_read(fast_pio, port_base, - page_address(sg->page) + sg->offset, - sg->length); + sg_virt(sg), sg->length); } REG0(port_base); } diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 67b6d76a6c8..67ee51a3d7e 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -608,9 +608,7 @@ static int ppa_completion(struct scsi_cmnd *cmd) cmd->SCp.buffer++; cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = - page_address(cmd->SCp.buffer->page) + - cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); } } /* Now check to see if the drive is ready to comunicate */ @@ -756,8 +754,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) /* if many buffers are available, start filling the first */ cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + - cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); } else { /* else fill the only available buffer */ cmd->SCp.buffer = NULL; diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c index 0f43d1d046d..03f19b8d19c 100644 --- a/drivers/scsi/ps3rom.c +++ b/drivers/scsi/ps3rom.c @@ -111,14 +111,14 @@ static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf) req_len = act_len = 0; scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) { if (active) { - kaddr = kmap_atomic(sgpnt->page, KM_IRQ0); + kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0); len = sgpnt->length; if ((req_len + len) > buflen) { active = 0; len = buflen - req_len; } memcpy(kaddr + sgpnt->offset, buf + req_len, len); - flush_kernel_dcache_page(sgpnt->page); + flush_kernel_dcache_page(sg_page(sgpnt)); kunmap_atomic(kaddr, KM_IRQ0); act_len += len; } @@ -147,7 +147,7 @@ static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf) req_len = fin = 0; scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) { - kaddr = kmap_atomic(sgpnt->page, KM_IRQ0); + kaddr = kmap_atomic(sg_page(sgpnt->page), KM_IRQ0); len = sgpnt->length; if ((req_len + len) > buflen) { len = buflen - req_len; diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c index 2bfbf26c00e..de7b3bc2cbc 100644 --- a/drivers/scsi/qlogicfas408.c +++ b/drivers/scsi/qlogicfas408.c @@ -317,7 +317,7 @@ static unsigned int ql_pcmd(struct scsi_cmnd *cmd) return ((priv->qabort == 1 ? DID_ABORT : DID_RESET) << 16); } - buf = page_address(sg->page) + sg->offset; + buf = sg_virt(sg); if (ql_pdma(priv, phase, buf, sg->length)) break; } diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 72ee4c9cfb1..46cae5a212d 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -625,7 +625,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, scsi_for_each_sg(scp, sg, scp->use_sg, k) { if (active) { kaddr = (unsigned char *) - kmap_atomic(sg->page, KM_USER0); + kmap_atomic(sg_page(sg), KM_USER0); if (NULL == kaddr) return (DID_ERROR << 16); kaddr_off = (unsigned char *)kaddr + sg->offset; @@ -672,7 +672,7 @@ static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr, sg = scsi_sglist(scp); req_len = fin = 0; for (k = 0; k < scp->use_sg; ++k, sg = sg_next(sg)) { - kaddr = (unsigned char *)kmap_atomic(sg->page, KM_USER0); + kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0); if (NULL == kaddr) return -1; kaddr_off = (unsigned char *)kaddr + sg->offset; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index aac8a02cbe8..61fdaf02f25 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -295,7 +295,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, int i, err, nr_vecs = 0; for_each_sg(sgl, sg, nsegs, i) { - page = sg->page; + page = sg_page(sg); off = sg->offset; len = sg->length; data_len += len; @@ -764,7 +764,7 @@ struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) if (unlikely(!sgl)) goto enomem; - memset(sgl, 0, sizeof(*sgl) * sgp->size); + sg_init_table(sgl, sgp->size); /* * first loop through, set initial index and return value @@ -781,6 +781,13 @@ struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) sg_chain(prev, SCSI_MAX_SG_SEGMENTS, sgl); /* + * if we have nothing left, mark the last segment as + * end-of-list + */ + if (!left) + sg_mark_end(sgl, this); + + /* * don't allow subsequent mempool allocs to sleep, it would * violate the mempool principle. */ @@ -2353,7 +2360,7 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sgl, int sg_count, *offset = *offset - len_complete + sg->offset; /* Assumption: contiguous pages can be accessed as "page + i" */ - page = nth_page(sg->page, (*offset >> PAGE_SHIFT)); + page = nth_page(sg_page(sg), (*offset >> PAGE_SHIFT)); *offset &= ~PAGE_MASK; /* Bytes in this sg-entry from *offset to the end of the page */ diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c index ce80fa9ad81..b11324479b5 100644 --- a/drivers/scsi/seagate.c +++ b/drivers/scsi/seagate.c @@ -999,14 +999,14 @@ connect_loop: for (i = 0; i < nobuffs; ++i) printk("scsi%d : buffer %d address = %p length = %d\n", hostno, i, - page_address(buffer[i].page) + buffer[i].offset, + sg_virt(&buffer[i]), buffer[i].length); } #endif buffer = (struct scatterlist *) SCint->request_buffer; len = buffer->length; - data = page_address(buffer->page) + buffer->offset; + data = sg_virt(buffer); } else { DPRINTK (DEBUG_SG, "scsi%d : scatter gather not requested.\n", hostno); buffer = NULL; @@ -1239,7 +1239,7 @@ connect_loop: --nobuffs; ++buffer; len = buffer->length; - data = page_address(buffer->page) + buffer->offset; + data = sg_virt(buffer); DPRINTK (DEBUG_SG, "scsi%d : next scatter-gather buffer len = %d address = %08x\n", hostno, len, data); @@ -1396,7 +1396,7 @@ connect_loop: --nobuffs; ++buffer; len = buffer->length; - data = page_address(buffer->page) + buffer->offset; + data = sg_virt(buffer); DPRINTK (DEBUG_SG, "scsi%d : next scatter-gather buffer len = %d address = %08x\n", hostno, len, data); } break; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 7238b2dfc49..cc197100284 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1169,7 +1169,7 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type) len = vma->vm_end - sa; len = (len < sg->length) ? len : sg->length; if (offset < len) { - page = virt_to_page(page_address(sg->page) + offset); + page = virt_to_page(page_address(sg_page(sg)) + offset); get_page(page); /* increment page count */ break; } @@ -1717,13 +1717,13 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, goto out_unlock; */ } - sgl[0].page = pages[0]; + sg_set_page(sgl, pages[0]); sgl[0].offset = uaddr & ~PAGE_MASK; if (nr_pages > 1) { sgl[0].length = PAGE_SIZE - sgl[0].offset; count -= sgl[0].length; for (i=1; i < nr_pages ; i++) { - sgl[i].page = pages[i]; + sg_set_page(&sgl[i], pages[i]); sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE; count -= PAGE_SIZE; } @@ -1754,7 +1754,7 @@ st_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages, int i; for (i=0; i < nr_pages; i++) { - struct page *page = sgl[i].page; + struct page *page = sg_page(&sgl[i]); if (dirtied) SetPageDirty(page); @@ -1854,7 +1854,7 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) scatter_elem_sz_prev = ret_sz; } } - sg->page = p; + sg_set_page(sg, p); sg->length = (ret_sz > num) ? num : ret_sz; SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, " @@ -1907,14 +1907,14 @@ sg_write_xfer(Sg_request * srp) onum = 1; ksglen = sg->length; - p = page_address(sg->page); + p = page_address(sg_page(sg)); for (j = 0, k = 0; j < onum; ++j) { res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up); if (res) return res; for (; p; sg = sg_next(sg), ksglen = sg->length, - p = page_address(sg->page)) { + p = page_address(sg_page(sg))) { if (usglen <= 0) break; if (ksglen > usglen) { @@ -1991,12 +1991,12 @@ sg_remove_scat(Sg_scatter_hold * schp) } else { int k; - for (k = 0; (k < schp->k_use_sg) && sg->page; + for (k = 0; (k < schp->k_use_sg) && sg_page(sg); ++k, sg = sg_next(sg)) { SCSI_LOG_TIMEOUT(5, printk( "sg_remove_scat: k=%d, pg=0x%p, len=%d\n", - k, sg->page, sg->length)); - sg_page_free(sg->page, sg->length); + k, sg_page(sg), sg->length)); + sg_page_free(sg_page(sg), sg->length); } } kfree(schp->buffer); @@ -2038,7 +2038,7 @@ sg_read_xfer(Sg_request * srp) } else onum = 1; - p = page_address(sg->page); + p = page_address(sg_page(sg)); ksglen = sg->length; for (j = 0, k = 0; j < onum; ++j) { res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up); @@ -2046,7 +2046,7 @@ sg_read_xfer(Sg_request * srp) return res; for (; p; sg = sg_next(sg), ksglen = sg->length, - p = page_address(sg->page)) { + p = page_address(sg_page(sg))) { if (usglen <= 0) break; if (ksglen > usglen) { @@ -2092,15 +2092,15 @@ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer) if ((!outp) || (num_read_xfer <= 0)) return 0; - for (k = 0; (k < schp->k_use_sg) && sg->page; ++k, sg = sg_next(sg)) { + for (k = 0; (k < schp->k_use_sg) && sg_page(sg); ++k, sg = sg_next(sg)) { num = sg->length; if (num > num_read_xfer) { - if (__copy_to_user(outp, page_address(sg->page), + if (__copy_to_user(outp, page_address(sg_page(sg)), num_read_xfer)) return -EFAULT; break; } else { - if (__copy_to_user(outp, page_address(sg->page), + if (__copy_to_user(outp, page_address(sg_page(sg)), num)) return -EFAULT; num_read_xfer -= num; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 73c44cbdea4..ce69b9efc10 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3797,7 +3797,7 @@ static void buf_to_sg(struct st_buffer *STbp, unsigned int length) sg = &(STbp->sg[0]); frp = STbp->frp; for (i=count=0; count < length; i++) { - sg[i].page = frp[i].page; + sg_set_page(&sg[i], frp[i].page); if (length - count > frp[i].length) sg[i].length = frp[i].length; else @@ -4446,14 +4446,14 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa } /* Populate the scatter/gather list */ - sgl[0].page = pages[0]; + sg_set_page(&sgl[0], pages[0]); sgl[0].offset = uaddr & ~PAGE_MASK; if (nr_pages > 1) { sgl[0].length = PAGE_SIZE - sgl[0].offset; count -= sgl[0].length; for (i=1; i < nr_pages ; i++) { + sg_set_page(&sgl[i], pages[i]);; sgl[i].offset = 0; - sgl[i].page = pages[i]; sgl[i].length = count < PAGE_SIZE ? count : PAGE_SIZE; count -= PAGE_SIZE; } @@ -4483,7 +4483,7 @@ static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_p int i; for (i=0; i < nr_pages; i++) { - struct page *page = sgl[i].page; + struct page *page = sg_page(&sgl[i]); if (dirtied) SetPageDirty(page); diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 4aafe89b557..2dcde373b20 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -272,8 +272,7 @@ static struct scsi_host_template *the_template = NULL; #define HOSTNO instance->host_no #define H_NO(cmd) (cmd)->device->host->host_no -#define SGADDR(buffer) (void *)(((unsigned long)page_address((buffer)->page)) + \ - (buffer)->offset) +#define SGADDR(buffer) (void *)(((unsigned long)sg_virt(((buffer))))) #ifdef SUPPORT_TAGS diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c index 8befab7e983..90cee94d952 100644 --- a/drivers/scsi/sym53c416.c +++ b/drivers/scsi/sym53c416.c @@ -196,7 +196,7 @@ static unsigned int sym53c416_base_3[2] = {0,0}; #define MAXHOSTS 4 -#define SG_ADDRESS(buffer) ((char *) (page_address((buffer)->page)+(buffer)->offset)) +#define SG_ADDRESS(buffer) ((char *) sg_virt((buffer))) enum phases { diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 5c72ca31a47..44193049c4a 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -430,10 +430,7 @@ static __inline__ void dc390_Going_remove (struct dc390_dcb* pDCB, struct dc390_ static struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length) { - memset(sg, 0, sizeof(struct scatterlist)); - sg->page = virt_to_page(addr); - sg->length = length; - sg->offset = (unsigned long)addr & ~PAGE_MASK; + sg_init_one(sg, addr, length); return sg; } diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index ea72bbeb8f9..6d1f0edd798 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -681,7 +681,7 @@ static inline void build_sg_list(struct mscp *mscp, struct scsi_cmnd *SCpnt) max = scsi_sg_count(SCpnt); scsi_for_each_sg(SCpnt, sg, max, i) { - mscp->sglist[i].address = isa_page_to_bus(sg->page) + sg->offset; + mscp->sglist[i].address = isa_page_to_bus(sg_page(sg)) + sg->offset; mscp->sglist[i].num_bytes = sg->length; transfer_length += sg->length; } diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index 0e8e642fd3b..fdbb92d1f72 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -410,8 +410,7 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd, if (cmd->use_sg) { cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer; cmd->SCp.buffers_residual = cmd->use_sg - 1; - cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + - cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length; } else { cmd->SCp.buffer = NULL; @@ -745,8 +744,7 @@ transfer_bytes(const wd33c93_regs regs, struct scsi_cmnd *cmd, ++cmd->SCp.buffer; --cmd->SCp.buffers_residual; cmd->SCp.this_residual = cmd->SCp.buffer->length; - cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + - cmd->SCp.buffer->offset; + cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); } if (!cmd->SCp.this_residual) /* avoid bogus setups */ return; diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c index 255c611e78b..03cd44f231d 100644 --- a/drivers/scsi/wd7000.c +++ b/drivers/scsi/wd7000.c @@ -1123,7 +1123,7 @@ static int wd7000_queuecommand(struct scsi_cmnd *SCpnt, any2scsi(scb->maxlen, nseg * sizeof(Sgb)); scsi_for_each_sg(SCpnt, sg, nseg, i) { - any2scsi(sgb[i].ptr, isa_page_to_bus(sg->page) + sg->offset); + any2scsi(sgb[i].ptr, isa_page_to_bus(sg_page(sg)) + sg->offset); any2scsi(sgb[i].len, sg->length); } } else { diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 87665d7df6f..ed438bc7e98 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -624,7 +624,7 @@ choice config SERIAL_BFIN_DMA bool "DMA mode" - depends on DMA_UNCACHED_1M && !KGDB_UART + depends on !DMA_UNCACHED_NONE && !KGDB_UART help This driver works under DMA mode. If this option is selected, the blackfin simple dma driver is also enabled. diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 8dd5a6afd51..90d64a80846 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -437,13 +437,11 @@ int usb_sg_init ( #if defined(CONFIG_HIGHMEM) || defined(CONFIG_IOMMU) io->urbs[i]->transfer_buffer = NULL; #else - io->urbs[i]->transfer_buffer = - page_address(sg[i].page) + sg[i].offset; + io->urbs[i]->transfer_buffer = sg_virt(&sg[i]); #endif } else { /* hc may use _only_ transfer_buffer */ - io->urbs [i]->transfer_buffer = - page_address (sg [i].page) + sg [i].offset; + io->urbs [i]->transfer_buffer = sg_virt(&sg[i]); len = sg [i].length; } diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index e7d982a7154..91e999c9f68 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -519,8 +519,7 @@ static void mts_do_sg (struct urb* transfer) context->fragment++; mts_int_submit_urb(transfer, context->data_pipe, - page_address(sg[context->fragment].page) + - sg[context->fragment].offset, + sg_virt(&sg[context->fragment]), sg[context->fragment].length, context->fragment + 1 == scsi_sg_count(context->srb) ? mts_data_done : mts_do_sg); @@ -557,7 +556,7 @@ mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc) return; } else { sg = scsi_sglist(srb); - desc->context.data = page_address(sg[0].page) + sg[0].offset; + desc->context.data = sg_virt(&sg[0]); desc->context.data_length = sg[0].length; } diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index e901d31e051..ea316214648 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -360,9 +360,9 @@ static void free_sglist (struct scatterlist *sg, int nents) if (!sg) return; for (i = 0; i < nents; i++) { - if (!sg [i].page) + if (!sg_page(&sg[i])) continue; - kfree (page_address (sg [i].page) + sg [i].offset); + kfree (sg_virt(&sg[i])); } kfree (sg); } diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index cc8f7c52c72..889622baac2 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -195,7 +195,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, * the *offset and *index values for the next loop. */ cnt = 0; while (cnt < buflen) { - struct page *page = sg->page + + struct page *page = sg_page(sg) + ((sg->offset + *offset) >> PAGE_SHIFT); unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE-1); diff --git a/fs/buffer.c b/fs/buffer.c index 76403b1764c..7249e014819 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2563,7 +2563,7 @@ int nobh_write_end(struct file *file, struct address_space *mapping, struct page *page, void *fsdata) { struct inode *inode = page->mapping->host; - struct buffer_head *head = NULL; + struct buffer_head *head = fsdata; struct buffer_head *bh; if (!PageMappedToDisk(page)) { @@ -2584,7 +2584,6 @@ int nobh_write_end(struct file *file, struct address_space *mapping, unlock_page(page); page_cache_release(page); - head = fsdata; while (head) { bh = head; head = head->b_this_page; diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 0a3ee5a322b..5574ba3ab1f 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -103,7 +103,7 @@ extern int cifs_ioctl(struct inode *inode, struct file *filep, unsigned int command, unsigned long arg); #ifdef CONFIG_CIFS_EXPERIMENTAL -extern struct export_operations cifs_export_ops; +extern const struct export_operations cifs_export_ops; #endif /* EXPERIMENTAL */ #define CIFS_VERSION "1.51" diff --git a/fs/cifs/export.c b/fs/cifs/export.c index d614b91caec..75949d6a5f1 100644 --- a/fs/cifs/export.c +++ b/fs/cifs/export.c @@ -53,7 +53,7 @@ static struct dentry *cifs_get_parent(struct dentry *dentry) return ERR_PTR(-EACCES); } -struct export_operations cifs_export_ops = { +const struct export_operations cifs_export_ops = { .get_parent = cifs_get_parent, /* Following five export operations are unneeded so far and can default: .get_dentry = diff --git a/fs/dcache.c b/fs/dcache.c index 5489b2d98a0..d9ca1e5ceb9 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -38,7 +38,7 @@ int sysctl_vfs_cache_pressure __read_mostly = 100; EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock); -static __cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); +__cacheline_aligned_in_smp DEFINE_SEQLOCK(rename_lock); EXPORT_SYMBOL(dcache_lock); @@ -1479,6 +1479,8 @@ static void switch_names(struct dentry *dentry, struct dentry *target) * dentry:internal, target:external. Steal target's * storage and make target internal. */ + memcpy(target->d_iname, dentry->d_name.name, + dentry->d_name.len + 1); dentry->d_name.name = target->d_name.name; target->d_name.name = target->d_iname; } diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 11be8a325e2..6a713b33992 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -413,7 +413,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry, d_move(old_dentry, dentry); fsnotify_move(old_dir->d_inode, new_dir->d_inode, old_name, old_dentry->d_name.name, S_ISDIR(old_dentry->d_inode->i_mode), - NULL, old_dentry->d_inode); + NULL, old_dentry); fsnotify_oldname_free(old_name); unlock_rename(new_dir, old_dir); dput(dentry); diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 1ae90ef2c74..0a9882edf56 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -283,7 +283,7 @@ int virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg, pg = virt_to_page(addr); offset = offset_in_page(addr); if (sg) { - sg[i].page = pg; + sg_set_page(&sg[i], pg); sg[i].offset = offset; } remainder_of_page = PAGE_CACHE_SIZE - offset; @@ -713,10 +713,13 @@ ecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, { struct scatterlist src_sg, dst_sg; - src_sg.page = src_page; + sg_init_table(&src_sg, 1); + sg_init_table(&dst_sg, 1); + + sg_set_page(&src_sg, src_page); src_sg.offset = src_offset; src_sg.length = size; - dst_sg.page = dst_page; + sg_set_page(&dst_sg, dst_page); dst_sg.offset = dst_offset; dst_sg.length = size; return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); @@ -742,10 +745,13 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, { struct scatterlist src_sg, dst_sg; - src_sg.page = src_page; + sg_init_table(&src_sg, 1); + sg_init_table(&dst_sg, 1); + + sg_set_page(&src_sg, src_page); src_sg.offset = src_offset; src_sg.length = size; - dst_sg.page = dst_page; + sg_set_page(&dst_sg, dst_page); dst_sg.offset = dst_offset; dst_sg.length = size; return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv); diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 89d9710dd63..263fed88c0c 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -1040,6 +1040,9 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok, }; int rc = 0; + sg_init_table(&dst_sg, 1); + sg_init_table(&src_sg, 1); + if (unlikely(ecryptfs_verbosity > 0)) { ecryptfs_printk( KERN_DEBUG, "Session key encryption key (size [%d]):\n", diff --git a/fs/efs/namei.c b/fs/efs/namei.c index 5276b19423c..f7f407075be 100644 --- a/fs/efs/namei.c +++ b/fs/efs/namei.c @@ -10,6 +10,8 @@ #include <linux/string.h> #include <linux/efs_fs.h> #include <linux/smp_lock.h> +#include <linux/exportfs.h> + static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) { struct buffer_head *bh; @@ -75,13 +77,10 @@ struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct namei return NULL; } -struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp) +static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, + u32 generation) { - __u32 *objp = vobjp; - unsigned long ino = objp[0]; - __u32 generation = objp[1]; struct inode *inode; - struct dentry *result; if (ino == 0) return ERR_PTR(-ESTALE); @@ -91,20 +90,25 @@ struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp) if (is_bad_inode(inode) || (generation && inode->i_generation != generation)) { - result = ERR_PTR(-ESTALE); - goto out_iput; + iput(inode); + return ERR_PTR(-ESTALE); } - result = d_alloc_anon(inode); - if (!result) { - result = ERR_PTR(-ENOMEM); - goto out_iput; - } - return result; + return inode; +} - out_iput: - iput(inode); - return result; +struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, + efs_nfs_get_inode); +} + +struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_parent(sb, fid, fh_len, fh_type, + efs_nfs_get_inode); } struct dentry *efs_get_parent(struct dentry *child) diff --git a/fs/efs/super.c b/fs/efs/super.c index 25d0326c5f1..c79bc627f10 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -113,8 +113,9 @@ static const struct super_operations efs_superblock_operations = { .remount_fs = efs_remount, }; -static struct export_operations efs_export_ops = { - .get_dentry = efs_get_dentry, +static const struct export_operations efs_export_ops = { + .fh_to_dentry = efs_fh_to_dentry, + .fh_to_parent = efs_fh_to_parent, .get_parent = efs_get_parent, }; diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index 8adb32a9387..109ab5e44ec 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -1,4 +1,13 @@ - +/* + * Copyright (C) Neil Brown 2002 + * Copyright (C) Christoph Hellwig 2007 + * + * This file contains the code mapping from inodes to NFS file handles, + * and for mapping back from file handles to dentries. + * + * For details on why we do all the strange and hairy things in here + * take a look at Documentation/filesystems/Exporting. + */ #include <linux/exportfs.h> #include <linux/fs.h> #include <linux/file.h> @@ -9,32 +18,19 @@ #define dprintk(fmt, args...) do{}while(0) -static int get_name(struct dentry *dentry, char *name, +static int get_name(struct vfsmount *mnt, struct dentry *dentry, char *name, struct dentry *child); -static struct dentry *exportfs_get_dentry(struct super_block *sb, void *obj) +static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir, + char *name, struct dentry *child) { - struct dentry *result = ERR_PTR(-ESTALE); - - if (sb->s_export_op->get_dentry) { - result = sb->s_export_op->get_dentry(sb, obj); - if (!result) - result = ERR_PTR(-ESTALE); - } - - return result; -} - -static int exportfs_get_name(struct dentry *dir, char *name, - struct dentry *child) -{ - struct export_operations *nop = dir->d_sb->s_export_op; + const struct export_operations *nop = dir->d_sb->s_export_op; if (nop->get_name) return nop->get_name(dir, name, child); else - return get_name(dir, name, child); + return get_name(mnt, dir, name, child); } /* @@ -98,7 +94,7 @@ find_disconnected_root(struct dentry *dentry) * It may already be, as the flag isn't always updated when connection happens. */ static int -reconnect_path(struct super_block *sb, struct dentry *target_dir) +reconnect_path(struct vfsmount *mnt, struct dentry *target_dir) { char nbuf[NAME_MAX+1]; int noprogress = 0; @@ -121,7 +117,7 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) pd->d_flags &= ~DCACHE_DISCONNECTED; spin_unlock(&pd->d_lock); noprogress = 0; - } else if (pd == sb->s_root) { + } else if (pd == mnt->mnt_sb->s_root) { printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n"); spin_lock(&pd->d_lock); pd->d_flags &= ~DCACHE_DISCONNECTED; @@ -147,8 +143,8 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) struct dentry *npd; mutex_lock(&pd->d_inode->i_mutex); - if (sb->s_export_op->get_parent) - ppd = sb->s_export_op->get_parent(pd); + if (mnt->mnt_sb->s_export_op->get_parent) + ppd = mnt->mnt_sb->s_export_op->get_parent(pd); mutex_unlock(&pd->d_inode->i_mutex); if (IS_ERR(ppd)) { @@ -161,7 +157,7 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) dprintk("%s: find name of %lu in %lu\n", __FUNCTION__, pd->d_inode->i_ino, ppd->d_inode->i_ino); - err = exportfs_get_name(ppd, nbuf, pd); + err = exportfs_get_name(mnt, ppd, nbuf, pd); if (err) { dput(ppd); dput(pd); @@ -214,125 +210,6 @@ reconnect_path(struct super_block *sb, struct dentry *target_dir) return 0; } -/** - * find_exported_dentry - helper routine to implement export_operations->decode_fh - * @sb: The &super_block identifying the filesystem - * @obj: An opaque identifier of the object to be found - passed to - * get_inode - * @parent: An optional opqaue identifier of the parent of the object. - * @acceptable: A function used to test possible &dentries to see if they are - * acceptable - * @context: A parameter to @acceptable so that it knows on what basis to - * judge. - * - * find_exported_dentry is the central helper routine to enable file systems - * to provide the decode_fh() export_operation. It's main task is to take - * an &inode, find or create an appropriate &dentry structure, and possibly - * splice this into the dcache in the correct place. - * - * The decode_fh() operation provided by the filesystem should call - * find_exported_dentry() with the same parameters that it received except - * that instead of the file handle fragment, pointers to opaque identifiers - * for the object and optionally its parent are passed. The default decode_fh - * routine passes one pointer to the start of the filehandle fragment, and - * one 8 bytes into the fragment. It is expected that most filesystems will - * take this approach, though the offset to the parent identifier may well be - * different. - * - * find_exported_dentry() will call get_dentry to get an dentry pointer from - * the file system. If any &dentry in the d_alias list is acceptable, it will - * be returned. Otherwise find_exported_dentry() will attempt to splice a new - * &dentry into the dcache using get_name() and get_parent() to find the - * appropriate place. - */ - -struct dentry * -find_exported_dentry(struct super_block *sb, void *obj, void *parent, - int (*acceptable)(void *context, struct dentry *de), - void *context) -{ - struct dentry *result, *alias; - int err = -ESTALE; - - /* - * Attempt to find the inode. - */ - result = exportfs_get_dentry(sb, obj); - if (IS_ERR(result)) - return result; - - if (S_ISDIR(result->d_inode->i_mode)) { - if (!(result->d_flags & DCACHE_DISCONNECTED)) { - if (acceptable(context, result)) - return result; - err = -EACCES; - goto err_result; - } - - err = reconnect_path(sb, result); - if (err) - goto err_result; - } else { - struct dentry *target_dir, *nresult; - char nbuf[NAME_MAX+1]; - - alias = find_acceptable_alias(result, acceptable, context); - if (alias) - return alias; - - if (parent == NULL) - goto err_result; - - target_dir = exportfs_get_dentry(sb,parent); - if (IS_ERR(target_dir)) { - err = PTR_ERR(target_dir); - goto err_result; - } - - err = reconnect_path(sb, target_dir); - if (err) { - dput(target_dir); - goto err_result; - } - - /* - * As we weren't after a directory, have one more step to go. - */ - err = exportfs_get_name(target_dir, nbuf, result); - if (!err) { - mutex_lock(&target_dir->d_inode->i_mutex); - nresult = lookup_one_len(nbuf, target_dir, - strlen(nbuf)); - mutex_unlock(&target_dir->d_inode->i_mutex); - if (!IS_ERR(nresult)) { - if (nresult->d_inode) { - dput(result); - result = nresult; - } else - dput(nresult); - } - } - dput(target_dir); - } - - alias = find_acceptable_alias(result, acceptable, context); - if (alias) - return alias; - - /* drat - I just cannot find anything acceptable */ - dput(result); - /* It might be justifiable to return ESTALE here, - * but the filehandle at-least looks reasonable good - * and it may just be a permission problem, so returning - * -EACCESS is safer - */ - return ERR_PTR(-EACCES); - - err_result: - dput(result); - return ERR_PTR(err); -} - struct getdents_callback { char *name; /* name that was found. It already points to a buffer NAME_MAX+1 is size */ @@ -370,8 +247,8 @@ static int filldir_one(void * __buf, const char * name, int len, * calls readdir on the parent until it finds an entry with * the same inode number as the child, and returns that. */ -static int get_name(struct dentry *dentry, char *name, - struct dentry *child) +static int get_name(struct vfsmount *mnt, struct dentry *dentry, + char *name, struct dentry *child) { struct inode *dir = dentry->d_inode; int error; @@ -387,7 +264,7 @@ static int get_name(struct dentry *dentry, char *name, /* * Open the directory ... */ - file = dentry_open(dget(dentry), NULL, O_RDONLY); + file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY); error = PTR_ERR(file); if (IS_ERR(file)) goto out; @@ -434,100 +311,177 @@ out: * can be used to check that it is still valid. It places them in the * filehandle fragment where export_decode_fh expects to find them. */ -static int export_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, - int connectable) +static int export_encode_fh(struct dentry *dentry, struct fid *fid, + int *max_len, int connectable) { struct inode * inode = dentry->d_inode; int len = *max_len; - int type = 1; + int type = FILEID_INO32_GEN; if (len < 2 || (connectable && len < 4)) return 255; len = 2; - fh[0] = inode->i_ino; - fh[1] = inode->i_generation; + fid->i32.ino = inode->i_ino; + fid->i32.gen = inode->i_generation; if (connectable && !S_ISDIR(inode->i_mode)) { struct inode *parent; spin_lock(&dentry->d_lock); parent = dentry->d_parent->d_inode; - fh[2] = parent->i_ino; - fh[3] = parent->i_generation; + fid->i32.parent_ino = parent->i_ino; + fid->i32.parent_gen = parent->i_generation; spin_unlock(&dentry->d_lock); len = 4; - type = 2; + type = FILEID_INO32_GEN_PARENT; } *max_len = len; return type; } - -/** - * export_decode_fh - default export_operations->decode_fh function - * @sb: The superblock - * @fh: pointer to the file handle fragment - * @fh_len: length of file handle fragment - * @acceptable: function for testing acceptability of dentrys - * @context: context for @acceptable - * - * This is the default decode_fh() function. - * a fileid_type of 1 indicates that the filehandlefragment - * just contains an object identifier understood by get_dentry. - * a fileid_type of 2 says that there is also a directory - * identifier 8 bytes in to the filehandlefragement. - */ -static struct dentry *export_decode_fh(struct super_block *sb, __u32 *fh, int fh_len, - int fileid_type, - int (*acceptable)(void *context, struct dentry *de), - void *context) -{ - __u32 parent[2]; - parent[0] = parent[1] = 0; - if (fh_len < 2 || fileid_type > 2) - return NULL; - if (fileid_type == 2) { - if (fh_len > 2) parent[0] = fh[2]; - if (fh_len > 3) parent[1] = fh[3]; - } - return find_exported_dentry(sb, fh, parent, - acceptable, context); -} - -int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, +int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len, int connectable) { - struct export_operations *nop = dentry->d_sb->s_export_op; + const struct export_operations *nop = dentry->d_sb->s_export_op; int error; if (nop->encode_fh) - error = nop->encode_fh(dentry, fh, max_len, connectable); + error = nop->encode_fh(dentry, fid->raw, max_len, connectable); else - error = export_encode_fh(dentry, fh, max_len, connectable); + error = export_encode_fh(dentry, fid, max_len, connectable); return error; } EXPORT_SYMBOL_GPL(exportfs_encode_fh); -struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh, int fh_len, - int fileid_type, int (*acceptable)(void *, struct dentry *), - void *context) +struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, + int fh_len, int fileid_type, + int (*acceptable)(void *, struct dentry *), void *context) { - struct export_operations *nop = mnt->mnt_sb->s_export_op; - struct dentry *result; + const struct export_operations *nop = mnt->mnt_sb->s_export_op; + struct dentry *result, *alias; + int err; - if (nop->decode_fh) { - result = nop->decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type, - acceptable, context); + /* + * Try to get any dentry for the given file handle from the filesystem. + */ + result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type); + if (!result) + result = ERR_PTR(-ESTALE); + if (IS_ERR(result)) + return result; + + if (S_ISDIR(result->d_inode->i_mode)) { + /* + * This request is for a directory. + * + * On the positive side there is only one dentry for each + * directory inode. On the negative side this implies that we + * to ensure our dentry is connected all the way up to the + * filesystem root. + */ + if (result->d_flags & DCACHE_DISCONNECTED) { + err = reconnect_path(mnt, result); + if (err) + goto err_result; + } + + if (!acceptable(context, result)) { + err = -EACCES; + goto err_result; + } + + return result; } else { - result = export_decode_fh(mnt->mnt_sb, fh, fh_len, fileid_type, - acceptable, context); + /* + * It's not a directory. Life is a little more complicated. + */ + struct dentry *target_dir, *nresult; + char nbuf[NAME_MAX+1]; + + /* + * See if either the dentry we just got from the filesystem + * or any alias for it is acceptable. This is always true + * if this filesystem is exported without the subtreecheck + * option. If the filesystem is exported with the subtree + * check option there's a fair chance we need to look at + * the parent directory in the file handle and make sure + * it's connected to the filesystem root. + */ + alias = find_acceptable_alias(result, acceptable, context); + if (alias) + return alias; + + /* + * Try to extract a dentry for the parent directory from the + * file handle. If this fails we'll have to give up. + */ + err = -ESTALE; + if (!nop->fh_to_parent) + goto err_result; + + target_dir = nop->fh_to_parent(mnt->mnt_sb, fid, + fh_len, fileid_type); + if (!target_dir) + goto err_result; + err = PTR_ERR(target_dir); + if (IS_ERR(target_dir)) + goto err_result; + + /* + * And as usual we need to make sure the parent directory is + * connected to the filesystem root. The VFS really doesn't + * like disconnected directories.. + */ + err = reconnect_path(mnt, target_dir); + if (err) { + dput(target_dir); + goto err_result; + } + + /* + * Now that we've got both a well-connected parent and a + * dentry for the inode we're after, make sure that our + * inode is actually connected to the parent. + */ + err = exportfs_get_name(mnt, target_dir, nbuf, result); + if (!err) { + mutex_lock(&target_dir->d_inode->i_mutex); + nresult = lookup_one_len(nbuf, target_dir, + strlen(nbuf)); + mutex_unlock(&target_dir->d_inode->i_mutex); + if (!IS_ERR(nresult)) { + if (nresult->d_inode) { + dput(result); + result = nresult; + } else + dput(nresult); + } + } + + /* + * At this point we are done with the parent, but it's pinned + * by the child dentry anyway. + */ + dput(target_dir); + + /* + * And finally make sure the dentry is actually acceptable + * to NFSD. + */ + alias = find_acceptable_alias(result, acceptable, context); + if (!alias) { + err = -EACCES; + goto err_result; + } + + return alias; } - return result; + err_result: + dput(result); + return ERR_PTR(err); } EXPORT_SYMBOL_GPL(exportfs_decode_fh); -EXPORT_SYMBOL(find_exported_dentry); - MODULE_LICENSE("GPL"); diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 05d9342bb64..d868e26c15e 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -28,6 +28,24 @@ typedef struct ext2_dir_entry_2 ext2_dirent; +static inline unsigned ext2_rec_len_from_disk(__le16 dlen) +{ + unsigned len = le16_to_cpu(dlen); + + if (len == EXT2_MAX_REC_LEN) + return 1 << 16; + return len; +} + +static inline __le16 ext2_rec_len_to_disk(unsigned len) +{ + if (len == (1 << 16)) + return cpu_to_le16(EXT2_MAX_REC_LEN); + else if (len > (1 << 16)) + BUG(); + return cpu_to_le16(len); +} + /* * ext2 uses block-sized chunks. Arguably, sector-sized ones would be * more robust, but we have what we have @@ -106,7 +124,7 @@ static void ext2_check_page(struct page *page) } for (offs = 0; offs <= limit - EXT2_DIR_REC_LEN(1); offs += rec_len) { p = (ext2_dirent *)(kaddr + offs); - rec_len = le16_to_cpu(p->rec_len); + rec_len = ext2_rec_len_from_disk(p->rec_len); if (rec_len < EXT2_DIR_REC_LEN(1)) goto Eshort; @@ -204,7 +222,8 @@ static inline int ext2_match (int len, const char * const name, */ static inline ext2_dirent *ext2_next_entry(ext2_dirent *p) { - return (ext2_dirent *)((char*)p + le16_to_cpu(p->rec_len)); + return (ext2_dirent *)((char *)p + + ext2_rec_len_from_disk(p->rec_len)); } static inline unsigned @@ -316,7 +335,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) return 0; } } - filp->f_pos += le16_to_cpu(de->rec_len); + filp->f_pos += ext2_rec_len_from_disk(de->rec_len); } ext2_put_page(page); } @@ -425,7 +444,7 @@ void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de, { loff_t pos = page_offset(page) + (char *) de - (char *) page_address(page); - unsigned len = le16_to_cpu(de->rec_len); + unsigned len = ext2_rec_len_from_disk(de->rec_len); int err; lock_page(page); @@ -482,7 +501,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) /* We hit i_size */ name_len = 0; rec_len = chunk_size; - de->rec_len = cpu_to_le16(chunk_size); + de->rec_len = ext2_rec_len_to_disk(chunk_size); de->inode = 0; goto got_it; } @@ -496,7 +515,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) if (ext2_match (namelen, name, de)) goto out_unlock; name_len = EXT2_DIR_REC_LEN(de->name_len); - rec_len = le16_to_cpu(de->rec_len); + rec_len = ext2_rec_len_from_disk(de->rec_len); if (!de->inode && rec_len >= reclen) goto got_it; if (rec_len >= name_len + reclen) @@ -518,8 +537,8 @@ got_it: goto out_unlock; if (de->inode) { ext2_dirent *de1 = (ext2_dirent *) ((char *) de + name_len); - de1->rec_len = cpu_to_le16(rec_len - name_len); - de->rec_len = cpu_to_le16(name_len); + de1->rec_len = ext2_rec_len_to_disk(rec_len - name_len); + de->rec_len = ext2_rec_len_to_disk(name_len); de = de1; } de->name_len = namelen; @@ -550,7 +569,8 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) struct inode *inode = mapping->host; char *kaddr = page_address(page); unsigned from = ((char*)dir - kaddr) & ~(ext2_chunk_size(inode)-1); - unsigned to = ((char*)dir - kaddr) + le16_to_cpu(dir->rec_len); + unsigned to = ((char *)dir - kaddr) + + ext2_rec_len_from_disk(dir->rec_len); loff_t pos; ext2_dirent * pde = NULL; ext2_dirent * de = (ext2_dirent *) (kaddr + from); @@ -574,7 +594,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) &page, NULL); BUG_ON(err); if (pde) - pde->rec_len = cpu_to_le16(to - from); + pde->rec_len = ext2_rec_len_to_disk(to - from); dir->inode = 0; err = ext2_commit_chunk(page, pos, to - from); inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; @@ -610,14 +630,14 @@ int ext2_make_empty(struct inode *inode, struct inode *parent) memset(kaddr, 0, chunk_size); de = (struct ext2_dir_entry_2 *)kaddr; de->name_len = 1; - de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(1)); + de->rec_len = ext2_rec_len_to_disk(EXT2_DIR_REC_LEN(1)); memcpy (de->name, ".\0\0", 4); de->inode = cpu_to_le32(inode->i_ino); ext2_set_de_type (de, inode); de = (struct ext2_dir_entry_2 *)(kaddr + EXT2_DIR_REC_LEN(1)); de->name_len = 2; - de->rec_len = cpu_to_le16(chunk_size - EXT2_DIR_REC_LEN(1)); + de->rec_len = ext2_rec_len_to_disk(chunk_size - EXT2_DIR_REC_LEN(1)); de->inode = cpu_to_le32(parent->i_ino); memcpy (de->name, "..\0", 4); ext2_set_de_type (de, inode); diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 77bd5f9262f..154e25f13d7 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -311,13 +311,10 @@ static const struct super_operations ext2_sops = { #endif }; -static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) +static struct inode *ext2_nfs_get_inode(struct super_block *sb, + u64 ino, u32 generation) { - __u32 *objp = vobjp; - unsigned long ino = objp[0]; - __u32 generation = objp[1]; struct inode *inode; - struct dentry *result; if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO) return ERR_PTR(-ESTALE); @@ -338,15 +335,21 @@ static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) iput(inode); return ERR_PTR(-ESTALE); } - /* now to find a dentry. - * If possible, get a well-connected one - */ - result = d_alloc_anon(inode); - if (!result) { - iput(inode); - return ERR_PTR(-ENOMEM); - } - return result; + return inode; +} + +static struct dentry *ext2_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, + ext2_nfs_get_inode); +} + +static struct dentry *ext2_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_parent(sb, fid, fh_len, fh_type, + ext2_nfs_get_inode); } /* Yes, most of these are left as NULL!! @@ -354,9 +357,10 @@ static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) * systems, but can be improved upon. * Currently only get_parent is required. */ -static struct export_operations ext2_export_ops = { +static const struct export_operations ext2_export_ops = { + .fh_to_dentry = ext2_fh_to_dentry, + .fh_to_parent = ext2_fh_to_parent, .get_parent = ext2_get_parent, - .get_dentry = ext2_get_dentry, }; static unsigned long get_sb_block(void **data) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 81868c0bc40..de55da9e28b 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -631,13 +631,10 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs) } -static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp) +static struct inode *ext3_nfs_get_inode(struct super_block *sb, + u64 ino, u32 generation) { - __u32 *objp = vobjp; - unsigned long ino = objp[0]; - __u32 generation = objp[1]; struct inode *inode; - struct dentry *result; if (ino < EXT3_FIRST_INO(sb) && ino != EXT3_ROOT_INO) return ERR_PTR(-ESTALE); @@ -660,15 +657,22 @@ static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp) iput(inode); return ERR_PTR(-ESTALE); } - /* now to find a dentry. - * If possible, get a well-connected one - */ - result = d_alloc_anon(inode); - if (!result) { - iput(inode); - return ERR_PTR(-ENOMEM); - } - return result; + + return inode; +} + +static struct dentry *ext3_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, + ext3_nfs_get_inode); +} + +static struct dentry *ext3_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_parent(sb, fid, fh_len, fh_type, + ext3_nfs_get_inode); } #ifdef CONFIG_QUOTA @@ -737,9 +741,10 @@ static const struct super_operations ext3_sops = { #endif }; -static struct export_operations ext3_export_ops = { +static const struct export_operations ext3_export_ops = { + .fh_to_dentry = ext3_fh_to_dentry, + .fh_to_parent = ext3_fh_to_parent, .get_parent = ext3_get_parent, - .get_dentry = ext3_get_dentry, }; enum { diff --git a/fs/ext4/super.c b/fs/ext4/super.c index b11e9e2bcd0..8031dc0e24e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -686,13 +686,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) } -static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp) +static struct inode *ext4_nfs_get_inode(struct super_block *sb, + u64 ino, u32 generation) { - __u32 *objp = vobjp; - unsigned long ino = objp[0]; - __u32 generation = objp[1]; struct inode *inode; - struct dentry *result; if (ino < EXT4_FIRST_INO(sb) && ino != EXT4_ROOT_INO) return ERR_PTR(-ESTALE); @@ -715,15 +712,22 @@ static struct dentry *ext4_get_dentry(struct super_block *sb, void *vobjp) iput(inode); return ERR_PTR(-ESTALE); } - /* now to find a dentry. - * If possible, get a well-connected one - */ - result = d_alloc_anon(inode); - if (!result) { - iput(inode); - return ERR_PTR(-ENOMEM); - } - return result; + + return inode; +} + +static struct dentry *ext4_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, + ext4_nfs_get_inode); +} + +static struct dentry *ext4_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_parent(sb, fid, fh_len, fh_type, + ext4_nfs_get_inode); } #ifdef CONFIG_QUOTA @@ -792,9 +796,10 @@ static const struct super_operations ext4_sops = { #endif }; -static struct export_operations ext4_export_ops = { +static const struct export_operations ext4_export_ops = { + .fh_to_dentry = ext4_fh_to_dentry, + .fh_to_parent = ext4_fh_to_parent, .get_parent = ext4_get_parent, - .get_dentry = ext4_get_dentry, }; enum { diff --git a/fs/fat/inode.c b/fs/fat/inode.c index c0c5e9c55b5..920a576e1c2 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -653,24 +653,15 @@ static const struct super_operations fat_sops = { * of i_logstart is used to store the directory entry offset. */ -static struct dentry * -fat_decode_fh(struct super_block *sb, __u32 *fh, int len, int fhtype, - int (*acceptable)(void *context, struct dentry *de), - void *context) -{ - if (fhtype != 3) - return ERR_PTR(-ESTALE); - if (len < 5) - return ERR_PTR(-ESTALE); - - return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, context); -} - -static struct dentry *fat_get_dentry(struct super_block *sb, void *inump) +static struct dentry *fat_fh_to_dentry(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type) { struct inode *inode = NULL; struct dentry *result; - __u32 *fh = inump; + u32 *fh = fid->raw; + + if (fh_len < 5 || fh_type != 3) + return NULL; inode = iget(sb, fh[0]); if (!inode || is_bad_inode(inode) || inode->i_generation != fh[1]) { @@ -783,10 +774,9 @@ out: return parent; } -static struct export_operations fat_export_ops = { - .decode_fh = fat_decode_fh, +static const struct export_operations fat_export_ops = { .encode_fh = fat_encode_fh, - .get_dentry = fat_get_dentry, + .fh_to_dentry = fat_fh_to_dentry, .get_parent = fat_get_parent, }; diff --git a/fs/gfs2/ops_export.c b/fs/gfs2/ops_export.c index e2d1347796a..b9da62348a8 100644 --- a/fs/gfs2/ops_export.c +++ b/fs/gfs2/ops_export.c @@ -31,40 +31,6 @@ #define GFS2_LARGE_FH_SIZE 8 #define GFS2_OLD_FH_SIZE 10 -static struct dentry *gfs2_decode_fh(struct super_block *sb, - __u32 *p, - int fh_len, - int fh_type, - int (*acceptable)(void *context, - struct dentry *dentry), - void *context) -{ - __be32 *fh = (__force __be32 *)p; - struct gfs2_inum_host inum, parent; - - memset(&parent, 0, sizeof(struct gfs2_inum)); - - switch (fh_len) { - case GFS2_LARGE_FH_SIZE: - case GFS2_OLD_FH_SIZE: - parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; - parent.no_formal_ino |= be32_to_cpu(fh[5]); - parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; - parent.no_addr |= be32_to_cpu(fh[7]); - case GFS2_SMALL_FH_SIZE: - inum.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; - inum.no_formal_ino |= be32_to_cpu(fh[1]); - inum.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; - inum.no_addr |= be32_to_cpu(fh[3]); - break; - default: - return NULL; - } - - return gfs2_export_ops.find_exported_dentry(sb, &inum, &parent, - acceptable, context); -} - static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len, int connectable) { @@ -189,10 +155,10 @@ static struct dentry *gfs2_get_parent(struct dentry *child) return dentry; } -static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj) +static struct dentry *gfs2_get_dentry(struct super_block *sb, + struct gfs2_inum_host *inum) { struct gfs2_sbd *sdp = sb->s_fs_info; - struct gfs2_inum_host *inum = inum_obj; struct gfs2_holder i_gh, ri_gh, rgd_gh; struct gfs2_rgrpd *rgd; struct inode *inode; @@ -289,11 +255,50 @@ fail: return ERR_PTR(error); } -struct export_operations gfs2_export_ops = { - .decode_fh = gfs2_decode_fh, +static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + struct gfs2_inum_host this; + __be32 *fh = (__force __be32 *)fid->raw; + + switch (fh_type) { + case GFS2_SMALL_FH_SIZE: + case GFS2_LARGE_FH_SIZE: + case GFS2_OLD_FH_SIZE: + this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; + this.no_formal_ino |= be32_to_cpu(fh[1]); + this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; + this.no_addr |= be32_to_cpu(fh[3]); + return gfs2_get_dentry(sb, &this); + default: + return NULL; + } +} + +static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + struct gfs2_inum_host parent; + __be32 *fh = (__force __be32 *)fid->raw; + + switch (fh_type) { + case GFS2_LARGE_FH_SIZE: + case GFS2_OLD_FH_SIZE: + parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; + parent.no_formal_ino |= be32_to_cpu(fh[5]); + parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; + parent.no_addr |= be32_to_cpu(fh[7]); + return gfs2_get_dentry(sb, &parent); + default: + return NULL; + } +} + +const struct export_operations gfs2_export_ops = { .encode_fh = gfs2_encode_fh, + .fh_to_dentry = gfs2_fh_to_dentry, + .fh_to_parent = gfs2_fh_to_parent, .get_name = gfs2_get_name, .get_parent = gfs2_get_parent, - .get_dentry = gfs2_get_dentry, }; diff --git a/fs/gfs2/ops_fstype.h b/fs/gfs2/ops_fstype.h index 407029b3b2b..da849051183 100644 --- a/fs/gfs2/ops_fstype.h +++ b/fs/gfs2/ops_fstype.h @@ -14,6 +14,6 @@ extern struct file_system_type gfs2_fs_type; extern struct file_system_type gfs2meta_fs_type; -extern struct export_operations gfs2_export_ops; +extern const struct export_operations gfs2_export_ops; #endif /* __OPS_FSTYPE_DOT_H__ */ diff --git a/fs/inotify.c b/fs/inotify.c index 7457501b956..2c5b9215287 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -667,6 +667,49 @@ out: EXPORT_SYMBOL_GPL(inotify_add_watch); /** + * inotify_clone_watch - put the watch next to existing one + * @old: already installed watch + * @new: new watch + * + * Caller must hold the inotify_mutex of inode we are dealing with; + * it is expected to remove the old watch before unlocking the inode. + */ +s32 inotify_clone_watch(struct inotify_watch *old, struct inotify_watch *new) +{ + struct inotify_handle *ih = old->ih; + int ret = 0; + + new->mask = old->mask; + new->ih = ih; + + mutex_lock(&ih->mutex); + + /* Initialize a new watch */ + ret = inotify_handle_get_wd(ih, new); + if (unlikely(ret)) + goto out; + ret = new->wd; + + get_inotify_handle(ih); + + new->inode = igrab(old->inode); + + list_add(&new->h_list, &ih->watches); + list_add(&new->i_list, &old->inode->inotify_watches); +out: + mutex_unlock(&ih->mutex); + return ret; +} + +void inotify_evict_watch(struct inotify_watch *watch) +{ + get_inotify_watch(watch); + mutex_lock(&watch->ih->mutex); + inotify_remove_watch_locked(watch->ih, watch); + mutex_unlock(&watch->ih->mutex); +} + +/** * inotify_rm_wd - remove a watch from an inotify instance * @ih: inotify handle * @wd: watch descriptor to remove diff --git a/fs/isofs/export.c b/fs/isofs/export.c index 4af856a7fda..29f9753ae5e 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c @@ -42,16 +42,6 @@ isofs_export_iget(struct super_block *sb, return result; } -static struct dentry * -isofs_export_get_dentry(struct super_block *sb, void *vobjp) -{ - __u32 *objp = vobjp; - unsigned long block = objp[0]; - unsigned long offset = objp[1]; - __u32 generation = objp[2]; - return isofs_export_iget(sb, block, offset, generation); -} - /* This function is surprisingly simple. The trick is understanding * that "child" is always a directory. So, to find its parent, you * simply need to find its ".." entry, normalize its block and offset, @@ -182,43 +172,44 @@ isofs_export_encode_fh(struct dentry *dentry, return type; } +struct isofs_fid { + u32 block; + u16 offset; + u16 parent_offset; + u32 generation; + u32 parent_block; + u32 parent_generation; +}; -static struct dentry * -isofs_export_decode_fh(struct super_block *sb, - __u32 *fh32, - int fh_len, - int fileid_type, - int (*acceptable)(void *context, struct dentry *de), - void *context) +static struct dentry *isofs_fh_to_dentry(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type) { - __u16 *fh16 = (__u16*)fh32; - __u32 child[3]; /* The child is what triggered all this. */ - __u32 parent[3]; /* The parent is just along for the ride. */ + struct isofs_fid *ifid = (struct isofs_fid *)fid; - if (fh_len < 3 || fileid_type > 2) + if (fh_len < 3 || fh_type > 2) return NULL; - child[0] = fh32[0]; - child[1] = fh16[2]; /* fh16 [sic] */ - child[2] = fh32[2]; - - parent[0] = 0; - parent[1] = 0; - parent[2] = 0; - if (fileid_type == 2) { - if (fh_len > 2) parent[0] = fh32[3]; - parent[1] = fh16[3]; /* fh16 [sic] */ - if (fh_len > 4) parent[2] = fh32[4]; - } - - return sb->s_export_op->find_exported_dentry(sb, child, parent, - acceptable, context); + return isofs_export_iget(sb, ifid->block, ifid->offset, + ifid->generation); } +static struct dentry *isofs_fh_to_parent(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type) +{ + struct isofs_fid *ifid = (struct isofs_fid *)fid; + + if (fh_type != 2) + return NULL; + + return isofs_export_iget(sb, + fh_len > 2 ? ifid->parent_block : 0, + ifid->parent_offset, + fh_len > 4 ? ifid->parent_generation : 0); +} -struct export_operations isofs_export_ops = { - .decode_fh = isofs_export_decode_fh, +const struct export_operations isofs_export_ops = { .encode_fh = isofs_export_encode_fh, - .get_dentry = isofs_export_get_dentry, + .fh_to_dentry = isofs_fh_to_dentry, + .fh_to_parent = isofs_fh_to_parent, .get_parent = isofs_export_get_parent, }; diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index a07e67b1ea7..f3213f9f89a 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h @@ -178,4 +178,4 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de, extern const struct inode_operations isofs_dir_inode_operations; extern const struct file_operations isofs_dir_operations; extern const struct address_space_operations isofs_symlink_aops; -extern struct export_operations isofs_export_ops; +extern const struct export_operations isofs_export_ops; diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index f0ec72b263f..8e2cf2cde18 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h @@ -18,6 +18,8 @@ #ifndef _H_JFS_INODE #define _H_JFS_INODE +struct fid; + extern struct inode *ialloc(struct inode *, umode_t); extern int jfs_fsync(struct file *, struct dentry *, int); extern int jfs_ioctl(struct inode *, struct file *, @@ -32,7 +34,10 @@ extern void jfs_truncate_nolock(struct inode *, loff_t); extern void jfs_free_zero_link(struct inode *); extern struct dentry *jfs_get_parent(struct dentry *dentry); extern void jfs_get_inode_flags(struct jfs_inode_info *); -extern struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp); +extern struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type); +extern struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type); extern void jfs_set_inode_flags(struct inode *); extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 932797ba433..4e0a8493cef 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -20,6 +20,7 @@ #include <linux/fs.h> #include <linux/ctype.h> #include <linux/quotaops.h> +#include <linux/exportfs.h> #include "jfs_incore.h" #include "jfs_superblock.h" #include "jfs_inode.h" @@ -1477,13 +1478,10 @@ static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struc return dentry; } -struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp) +static struct inode *jfs_nfs_get_inode(struct super_block *sb, + u64 ino, u32 generation) { - __u32 *objp = vobjp; - unsigned long ino = objp[0]; - __u32 generation = objp[1]; struct inode *inode; - struct dentry *result; if (ino == 0) return ERR_PTR(-ESTALE); @@ -1493,20 +1491,25 @@ struct dentry *jfs_get_dentry(struct super_block *sb, void *vobjp) if (is_bad_inode(inode) || (generation && inode->i_generation != generation)) { - result = ERR_PTR(-ESTALE); - goto out_iput; + iput(inode); + return ERR_PTR(-ESTALE); } - result = d_alloc_anon(inode); - if (!result) { - result = ERR_PTR(-ENOMEM); - goto out_iput; - } - return result; + return inode; +} - out_iput: - iput(inode); - return result; +struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, + jfs_nfs_get_inode); +} + +struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_parent(sb, fid, fh_len, fh_type, + jfs_nfs_get_inode); } struct dentry *jfs_get_parent(struct dentry *dentry) diff --git a/fs/jfs/super.c b/fs/jfs/super.c index cff60c17194..314bb4ff1ba 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -48,7 +48,7 @@ MODULE_LICENSE("GPL"); static struct kmem_cache * jfs_inode_cachep; static const struct super_operations jfs_super_operations; -static struct export_operations jfs_export_operations; +static const struct export_operations jfs_export_operations; static struct file_system_type jfs_fs_type; #define MAX_COMMIT_THREADS 64 @@ -737,8 +737,9 @@ static const struct super_operations jfs_super_operations = { #endif }; -static struct export_operations jfs_export_operations = { - .get_dentry = jfs_get_dentry, +static const struct export_operations jfs_export_operations = { + .fh_to_dentry = jfs_fh_to_dentry, + .fh_to_parent = jfs_fh_to_parent, .get_parent = jfs_get_parent, }; diff --git a/fs/libfs.c b/fs/libfs.c index ae51481e45e..6e68b700958 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -8,6 +8,7 @@ #include <linux/mount.h> #include <linux/vfs.h> #include <linux/mutex.h> +#include <linux/exportfs.h> #include <asm/uaccess.h> @@ -678,6 +679,93 @@ out: return ret; } +/* + * This is what d_alloc_anon should have been. Once the exportfs + * argument transition has been finished I will update d_alloc_anon + * to this prototype and this wrapper will go away. --hch + */ +static struct dentry *exportfs_d_alloc(struct inode *inode) +{ + struct dentry *dentry; + + if (!inode) + return NULL; + if (IS_ERR(inode)) + return ERR_PTR(PTR_ERR(inode)); + + dentry = d_alloc_anon(inode); + if (!dentry) { + iput(inode); + dentry = ERR_PTR(-ENOMEM); + } + return dentry; +} + +/** + * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation + * @sb: filesystem to do the file handle conversion on + * @fid: file handle to convert + * @fh_len: length of the file handle in bytes + * @fh_type: type of file handle + * @get_inode: filesystem callback to retrieve inode + * + * This function decodes @fid as long as it has one of the well-known + * Linux filehandle types and calls @get_inode on it to retrieve the + * inode for the object specified in the file handle. + */ +struct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type, struct inode *(*get_inode) + (struct super_block *sb, u64 ino, u32 gen)) +{ + struct inode *inode = NULL; + + if (fh_len < 2) + return NULL; + + switch (fh_type) { + case FILEID_INO32_GEN: + case FILEID_INO32_GEN_PARENT: + inode = get_inode(sb, fid->i32.ino, fid->i32.gen); + break; + } + + return exportfs_d_alloc(inode); +} +EXPORT_SYMBOL_GPL(generic_fh_to_dentry); + +/** + * generic_fh_to_dentry - generic helper for the fh_to_parent export operation + * @sb: filesystem to do the file handle conversion on + * @fid: file handle to convert + * @fh_len: length of the file handle in bytes + * @fh_type: type of file handle + * @get_inode: filesystem callback to retrieve inode + * + * This function decodes @fid as long as it has one of the well-known + * Linux filehandle types and calls @get_inode on it to retrieve the + * inode for the _parent_ object specified in the file handle if it + * is specified in the file handle, or NULL otherwise. + */ +struct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type, struct inode *(*get_inode) + (struct super_block *sb, u64 ino, u32 gen)) +{ + struct inode *inode = NULL; + + if (fh_len <= 2) + return NULL; + + switch (fh_type) { + case FILEID_INO32_GEN_PARENT: + inode = get_inode(sb, fid->i32.parent_ino, + (fh_len > 3 ? fid->i32.parent_gen : 0)); + break; + } + + return exportfs_d_alloc(inode); +} +EXPORT_SYMBOL_GPL(generic_fh_to_parent); + EXPORT_SYMBOL(dcache_dir_close); EXPORT_SYMBOL(dcache_dir_lseek); EXPORT_SYMBOL(dcache_dir_open); diff --git a/fs/namei.c b/fs/namei.c index 1e5c7166916..3b993db26ce 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1174,7 +1174,7 @@ static int fastcall do_path_lookup(int dfd, const char *name, out: if (unlikely(!retval && !audit_dummy_context() && nd->dentry && nd->dentry->d_inode)) - audit_inode(name, nd->dentry->d_inode); + audit_inode(name, nd->dentry); out_fail: return retval; @@ -1214,7 +1214,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, retval = path_walk(name, nd); if (unlikely(!retval && !audit_dummy_context() && nd->dentry && nd->dentry->d_inode)) - audit_inode(name, nd->dentry->d_inode); + audit_inode(name, nd->dentry); return retval; @@ -1469,7 +1469,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) return -ENOENT; BUG_ON(victim->d_parent->d_inode != dir); - audit_inode_child(victim->d_name.name, victim->d_inode, dir); + audit_inode_child(victim->d_name.name, victim, dir); error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); if (error) @@ -1783,7 +1783,7 @@ do_last: * It already exists. */ mutex_unlock(&dir->d_inode->i_mutex); - audit_inode(pathname, path.dentry->d_inode); + audit_inode(pathname, path.dentry); error = -EEXIST; if (flag & O_EXCL) @@ -2562,7 +2562,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, if (!error) { const char *new_name = old_dentry->d_name.name; fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir, - new_dentry->d_inode, old_dentry->d_inode); + new_dentry->d_inode, old_dentry); } fsnotify_oldname_free(old_name); diff --git a/fs/namespace.c b/fs/namespace.c index 860752998fb..06083885b21 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -246,7 +246,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, list_add(&mnt->mnt_slave, &old->mnt_slave_list); mnt->mnt_master = old; CLEAR_MNT_SHARED(mnt); - } else { + } else if (!(flag & CL_PRIVATE)) { if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) list_add(&mnt->mnt_share, &old->mnt_share); if (IS_MNT_SLAVE(old)) @@ -746,6 +746,26 @@ Enomem: return NULL; } +struct vfsmount *collect_mounts(struct vfsmount *mnt, struct dentry *dentry) +{ + struct vfsmount *tree; + down_read(&namespace_sem); + tree = copy_tree(mnt, dentry, CL_COPY_ALL | CL_PRIVATE); + up_read(&namespace_sem); + return tree; +} + +void drop_collected_mounts(struct vfsmount *mnt) +{ + LIST_HEAD(umount_list); + down_read(&namespace_sem); + spin_lock(&vfsmount_lock); + umount_tree(mnt, 0, &umount_list); + spin_unlock(&vfsmount_lock); + up_read(&namespace_sem); + release_mounts(&umount_list); +} + /* * @source_mnt : mount tree to be attached * @nd : place the mount tree @source_mnt is attached diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 97669ed0550..4f80d88e9fe 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -211,6 +211,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, nfs_fattr_init(&fattr); dprintk("NFS call create %s\n", dentry->d_name.name); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); + nfs_mark_for_revalidate(dir); if (status == 0) status = nfs_instantiate(dentry, &fhandle, &fattr); dprintk("NFS reply create: %d\n", status); diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index ce558c2e4d5..233ad38161f 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -171,7 +171,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data) if (parent == NULL) goto out_free; dir = parent->d_inode; - if (nfs_copy_dname(dentry, data) == 0) + if (nfs_copy_dname(dentry, data) != 0) goto out_dput; /* Non-exclusive lock protects against concurrent lookup() calls */ spin_lock(&dir->i_lock); diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 04b26672980..66d0aeb32a4 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -386,15 +386,13 @@ static int check_export(struct inode *inode, int flags, unsigned char *uuid) dprintk("exp_export: export of non-dev fs without fsid\n"); return -EINVAL; } - if (!inode->i_sb->s_export_op) { + + if (!inode->i_sb->s_export_op || + !inode->i_sb->s_export_op->fh_to_dentry) { dprintk("exp_export: export of invalid fs type.\n"); return -EINVAL; } - /* Ok, we can export it */; - if (!inode->i_sb->s_export_op->find_exported_dentry) - inode->i_sb->s_export_op->find_exported_dentry = - find_exported_dentry; return 0; } diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index ebd03cc0747..6f03918018a 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -88,7 +88,7 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) { struct xdr_netobj cksum; struct hash_desc desc; - struct scatterlist sg[1]; + struct scatterlist sg; __be32 status = nfserr_resource; dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", @@ -102,11 +102,9 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) if (cksum.data == NULL) goto out; - sg[0].page = virt_to_page(clname->data); - sg[0].offset = offset_in_page(clname->data); - sg[0].length = clname->len; + sg_init_one(&sg, clname->data, clname->len); - if (crypto_hash_digest(&desc, sg, sg->length, cksum.data)) + if (crypto_hash_digest(&desc, &sg, sg.length, cksum.data)) goto out; md5_to_hex(dname, cksum.data); diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 7011d62acfc..4f712e97058 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -115,8 +115,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp)); if (!fhp->fh_dentry) { - __u32 *datap=NULL; - __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */ + struct fid *fid = NULL, sfid; int fileid_type; int data_left = fh->fh_size/4; @@ -128,7 +127,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) if (fh->fh_version == 1) { int len; - datap = fh->fh_auth; if (--data_left<0) goto out; switch (fh->fh_auth_type) { case 0: break; @@ -144,9 +142,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) fh->fh_fsid[1] = fh->fh_fsid[2]; } if ((data_left -= len)<0) goto out; - exp = rqst_exp_find(rqstp, fh->fh_fsid_type, datap); - datap += len; + exp = rqst_exp_find(rqstp, fh->fh_fsid_type, + fh->fh_auth); + fid = (struct fid *)(fh->fh_auth + len); } else { + __u32 tfh[2]; dev_t xdev; ino_t xino; if (fh->fh_size != NFS_FHSIZE) @@ -190,22 +190,22 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) error = nfserr_badhandle; if (fh->fh_version != 1) { - tfh[0] = fh->ofh_ino; - tfh[1] = fh->ofh_generation; - tfh[2] = fh->ofh_dirino; - datap = tfh; + sfid.i32.ino = fh->ofh_ino; + sfid.i32.gen = fh->ofh_generation; + sfid.i32.parent_ino = fh->ofh_dirino; + fid = &sfid; data_left = 3; if (fh->ofh_dirino == 0) - fileid_type = 1; + fileid_type = FILEID_INO32_GEN; else - fileid_type = 2; + fileid_type = FILEID_INO32_GEN_PARENT; } else fileid_type = fh->fh_fileid_type; - if (fileid_type == 0) + if (fileid_type == FILEID_ROOT) dentry = dget(exp->ex_dentry); else { - dentry = exportfs_decode_fh(exp->ex_mnt, datap, + dentry = exportfs_decode_fh(exp->ex_mnt, fid, data_left, fileid_type, nfsd_acceptable, exp); } @@ -286,16 +286,21 @@ out: * an inode. In this case a call to fh_update should be made * before the fh goes out on the wire ... */ -static inline int _fh_update(struct dentry *dentry, struct svc_export *exp, - __u32 *datap, int *maxsize) +static void _fh_update(struct svc_fh *fhp, struct svc_export *exp, + struct dentry *dentry) { - if (dentry == exp->ex_dentry) { - *maxsize = 0; - return 0; - } + if (dentry != exp->ex_dentry) { + struct fid *fid = (struct fid *) + (fhp->fh_handle.fh_auth + fhp->fh_handle.fh_size/4 - 1); + int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; + int subtreecheck = !(exp->ex_flags & NFSEXP_NOSUBTREECHECK); - return exportfs_encode_fh(dentry, datap, maxsize, - !(exp->ex_flags & NFSEXP_NOSUBTREECHECK)); + fhp->fh_handle.fh_fileid_type = + exportfs_encode_fh(dentry, fid, &maxsize, subtreecheck); + fhp->fh_handle.fh_size += maxsize * 4; + } else { + fhp->fh_handle.fh_fileid_type = FILEID_ROOT; + } } /* @@ -457,12 +462,8 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, datap += len/4; fhp->fh_handle.fh_size = 4 + len; - if (inode) { - int size = (fhp->fh_maxsize-len-4)/4; - fhp->fh_handle.fh_fileid_type = - _fh_update(dentry, exp, datap, &size); - fhp->fh_handle.fh_size += size*4; - } + if (inode) + _fh_update(fhp, exp, dentry); if (fhp->fh_handle.fh_fileid_type == 255) return nfserr_opnotsupp; } @@ -479,7 +480,6 @@ __be32 fh_update(struct svc_fh *fhp) { struct dentry *dentry; - __u32 *datap; if (!fhp->fh_dentry) goto out_bad; @@ -490,15 +490,10 @@ fh_update(struct svc_fh *fhp) if (fhp->fh_handle.fh_version != 1) { _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle); } else { - int size; - if (fhp->fh_handle.fh_fileid_type != 0) + if (fhp->fh_handle.fh_fileid_type != FILEID_ROOT) goto out; - datap = fhp->fh_handle.fh_auth+ - fhp->fh_handle.fh_size/4 -1; - size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; - fhp->fh_handle.fh_fileid_type = - _fh_update(dentry, fhp->fh_export, datap, &size); - fhp->fh_handle.fh_size += size*4; + + _fh_update(fhp, fhp->fh_export, dentry); if (fhp->fh_handle.fh_fileid_type == 255) return nfserr_opnotsupp; } diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index e93c6142b23..e1781c8b165 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c @@ -450,58 +450,40 @@ try_next: return parent_dent; } -/** - * ntfs_get_dentry - find a dentry for the inode from a file handle sub-fragment - * @sb: super block identifying the mounted ntfs volume - * @fh: the file handle sub-fragment - * - * Find a dentry for the inode given a file handle sub-fragment. This function - * is called from fs/exportfs/expfs.c::find_exported_dentry() which in turn is - * called from the default ->decode_fh() which is export_decode_fh() in the - * same file. The code is closely based on the default ->get_dentry() helper - * fs/exportfs/expfs.c::get_object(). - * - * The @fh contains two 32-bit unsigned values, the first one is the inode - * number and the second one is the inode generation. - * - * Return the dentry on success or the error code on error (IS_ERR() is true). - */ -static struct dentry *ntfs_get_dentry(struct super_block *sb, void *fh) +static struct inode *ntfs_nfs_get_inode(struct super_block *sb, + u64 ino, u32 generation) { - struct inode *vi; - struct dentry *dent; - unsigned long ino = ((u32 *)fh)[0]; - u32 gen = ((u32 *)fh)[1]; + struct inode *inode; - ntfs_debug("Entering for inode 0x%lx, generation 0x%x.", ino, gen); - vi = ntfs_iget(sb, ino); - if (IS_ERR(vi)) { - ntfs_error(sb, "Failed to get inode 0x%lx.", ino); - return (struct dentry *)vi; - } - if (unlikely(is_bad_inode(vi) || vi->i_generation != gen)) { - /* We didn't find the right inode. */ - ntfs_error(sb, "Inode 0x%lx, bad count: %d %d or version 0x%x " - "0x%x.", vi->i_ino, vi->i_nlink, - atomic_read(&vi->i_count), vi->i_generation, - gen); - iput(vi); - return ERR_PTR(-ESTALE); - } - /* Now find a dentry. If possible, get a well-connected one. */ - dent = d_alloc_anon(vi); - if (unlikely(!dent)) { - iput(vi); - return ERR_PTR(-ENOMEM); + inode = ntfs_iget(sb, ino); + if (!IS_ERR(inode)) { + if (is_bad_inode(inode) || inode->i_generation != generation) { + iput(inode); + inode = ERR_PTR(-ESTALE); + } } - ntfs_debug("Done for inode 0x%lx, generation 0x%x.", ino, gen); - return dent; + + return inode; +} + +static struct dentry *ntfs_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, + ntfs_nfs_get_inode); +} + +static struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_parent(sb, fid, fh_len, fh_type, + ntfs_nfs_get_inode); } /** * Export operations allowing NFS exporting of mounted NTFS partitions. * - * We use the default ->decode_fh() and ->encode_fh() for now. Note that they + * We use the default ->encode_fh() for now. Note that they * use 32 bits to store the inode number which is an unsigned long so on 64-bit * architectures is usually 64 bits so it would all fail horribly on huge * volumes. I guess we need to define our own encode and decode fh functions @@ -517,10 +499,9 @@ static struct dentry *ntfs_get_dentry(struct super_block *sb, void *fh) * allowing the inode number 0 which is used in NTFS for the system file $MFT * and due to using iget() whereas NTFS needs ntfs_iget(). */ -struct export_operations ntfs_export_ops = { +const struct export_operations ntfs_export_ops = { .get_parent = ntfs_get_parent, /* Find the parent of a given directory. */ - .get_dentry = ntfs_get_dentry, /* Find a dentry for the inode - given a file handle - sub-fragment. */ + .fh_to_dentry = ntfs_fh_to_dentry, + .fh_to_parent = ntfs_fh_to_parent, }; diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h index d73f5a9ac34..d6a340bf80f 100644 --- a/fs/ntfs/ntfs.h +++ b/fs/ntfs/ntfs.h @@ -69,7 +69,7 @@ extern const struct inode_operations ntfs_dir_inode_ops; extern const struct file_operations ntfs_empty_file_ops; extern const struct inode_operations ntfs_empty_inode_ops; -extern struct export_operations ntfs_export_ops; +extern const struct export_operations ntfs_export_ops; /** * NTFS_SB - return the ntfs volume given a vfs super block diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c index c3bbc198f9c..535bfa9568a 100644 --- a/fs/ocfs2/export.c +++ b/fs/ocfs2/export.c @@ -45,9 +45,9 @@ struct ocfs2_inode_handle u32 ih_generation; }; -static struct dentry *ocfs2_get_dentry(struct super_block *sb, void *vobjp) +static struct dentry *ocfs2_get_dentry(struct super_block *sb, + struct ocfs2_inode_handle *handle) { - struct ocfs2_inode_handle *handle = vobjp; struct inode *inode; struct dentry *result; @@ -194,54 +194,37 @@ bail: return type; } -static struct dentry *ocfs2_decode_fh(struct super_block *sb, u32 *fh_in, - int fh_len, int fileid_type, - int (*acceptable)(void *context, - struct dentry *de), - void *context) +static struct dentry *ocfs2_fh_to_dentry(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type) { - struct ocfs2_inode_handle handle, parent; - struct dentry *ret = NULL; - __le32 *fh = (__force __le32 *) fh_in; - - mlog_entry("(0x%p, 0x%p, %d, %d, 0x%p, 0x%p)\n", - sb, fh, fh_len, fileid_type, acceptable, context); - - if (fh_len < 3 || fileid_type > 2) - goto bail; - - if (fileid_type == 2) { - if (fh_len < 6) - goto bail; - - parent.ih_blkno = (u64)le32_to_cpu(fh[3]) << 32; - parent.ih_blkno |= (u64)le32_to_cpu(fh[4]); - parent.ih_generation = le32_to_cpu(fh[5]); + struct ocfs2_inode_handle handle; - mlog(0, "Decoding parent: blkno: %llu, generation: %u\n", - (unsigned long long)parent.ih_blkno, - parent.ih_generation); - } + if (fh_len < 3 || fh_type > 2) + return NULL; - handle.ih_blkno = (u64)le32_to_cpu(fh[0]) << 32; - handle.ih_blkno |= (u64)le32_to_cpu(fh[1]); - handle.ih_generation = le32_to_cpu(fh[2]); + handle.ih_blkno = (u64)le32_to_cpu(fid->raw[0]) << 32; + handle.ih_blkno |= (u64)le32_to_cpu(fid->raw[1]); + handle.ih_generation = le32_to_cpu(fid->raw[2]); + return ocfs2_get_dentry(sb, &handle); +} - mlog(0, "Encoding fh: blkno: %llu, generation: %u\n", - (unsigned long long)handle.ih_blkno, handle.ih_generation); +static struct dentry *ocfs2_fh_to_parent(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type) +{ + struct ocfs2_inode_handle parent; - ret = ocfs2_export_ops.find_exported_dentry(sb, &handle, &parent, - acceptable, context); + if (fh_type != 2 || fh_len < 6) + return NULL; -bail: - mlog_exit_ptr(ret); - return ret; + parent.ih_blkno = (u64)le32_to_cpu(fid->raw[3]) << 32; + parent.ih_blkno |= (u64)le32_to_cpu(fid->raw[4]); + parent.ih_generation = le32_to_cpu(fid->raw[5]); + return ocfs2_get_dentry(sb, &parent); } -struct export_operations ocfs2_export_ops = { - .decode_fh = ocfs2_decode_fh, +const struct export_operations ocfs2_export_ops = { .encode_fh = ocfs2_encode_fh, - + .fh_to_dentry = ocfs2_fh_to_dentry, + .fh_to_parent = ocfs2_fh_to_parent, .get_parent = ocfs2_get_parent, - .get_dentry = ocfs2_get_dentry, }; diff --git a/fs/ocfs2/export.h b/fs/ocfs2/export.h index e08bed9e45a..41a738678c3 100644 --- a/fs/ocfs2/export.h +++ b/fs/ocfs2/export.h @@ -28,6 +28,6 @@ #include <linux/exportfs.h> -extern struct export_operations ocfs2_export_ops; +extern const struct export_operations ocfs2_export_ops; #endif /* OCFS2_EXPORT_H */ diff --git a/fs/open.c b/fs/open.c index 75385144df7..3b69c53e183 100644 --- a/fs/open.c +++ b/fs/open.c @@ -569,7 +569,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) dentry = file->f_path.dentry; inode = dentry->d_inode; - audit_inode(NULL, inode); + audit_inode(NULL, dentry); err = -EROFS; if (IS_RDONLY(inode)) @@ -727,7 +727,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) goto out; dentry = file->f_path.dentry; - audit_inode(NULL, dentry->d_inode); + audit_inode(NULL, dentry); error = chown_common(dentry, user, group); fput(file); out: diff --git a/fs/pnode.h b/fs/pnode.h index d45bd8ec36b..f249be2fee7 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -22,6 +22,7 @@ #define CL_COPY_ALL 0x04 #define CL_MAKE_SHARED 0x08 #define CL_PROPAGATION 0x10 +#define CL_PRIVATE 0x20 static inline void set_mnt_shared(struct vfsmount *mnt) { diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index a991af96f3f..231fd5ccadc 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1515,19 +1515,20 @@ struct inode *reiserfs_iget(struct super_block *s, const struct cpu_key *key) return inode; } -struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp) +static struct dentry *reiserfs_get_dentry(struct super_block *sb, + u32 objectid, u32 dir_id, u32 generation) + { - __u32 *data = vobjp; struct cpu_key key; struct dentry *result; struct inode *inode; - key.on_disk_key.k_objectid = data[0]; - key.on_disk_key.k_dir_id = data[1]; + key.on_disk_key.k_objectid = objectid; + key.on_disk_key.k_dir_id = dir_id; reiserfs_write_lock(sb); inode = reiserfs_iget(sb, &key); - if (inode && !IS_ERR(inode) && data[2] != 0 && - data[2] != inode->i_generation) { + if (inode && !IS_ERR(inode) && generation != 0 && + generation != inode->i_generation) { iput(inode); inode = NULL; } @@ -1544,14 +1545,9 @@ struct dentry *reiserfs_get_dentry(struct super_block *sb, void *vobjp) return result; } -struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data, - int len, int fhtype, - int (*acceptable) (void *contect, - struct dentry * de), - void *context) +struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) { - __u32 obj[3], parent[3]; - /* fhtype happens to reflect the number of u32s encoded. * due to a bug in earlier code, fhtype might indicate there * are more u32s then actually fitted. @@ -1564,32 +1560,28 @@ struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data, * 6 - as above plus generation of directory * 6 does not fit in NFSv2 handles */ - if (fhtype > len) { - if (fhtype != 6 || len != 5) + if (fh_type > fh_len) { + if (fh_type != 6 || fh_len != 5) reiserfs_warning(sb, - "nfsd/reiserfs, fhtype=%d, len=%d - odd", - fhtype, len); - fhtype = 5; + "nfsd/reiserfs, fhtype=%d, len=%d - odd", + fh_type, fh_len); + fh_type = 5; } - obj[0] = data[0]; - obj[1] = data[1]; - if (fhtype == 3 || fhtype >= 5) - obj[2] = data[2]; - else - obj[2] = 0; /* generation number */ + return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1], + (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0); +} - if (fhtype >= 4) { - parent[0] = data[fhtype >= 5 ? 3 : 2]; - parent[1] = data[fhtype >= 5 ? 4 : 3]; - if (fhtype == 6) - parent[2] = data[5]; - else - parent[2] = 0; - } - return sb->s_export_op->find_exported_dentry(sb, obj, - fhtype < 4 ? NULL : parent, - acceptable, context); +struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + if (fh_type < 4) + return NULL; + + return reiserfs_get_dentry(sb, + (fh_type >= 5) ? fid->raw[3] : fid->raw[2], + (fh_type >= 5) ? fid->raw[4] : fid->raw[3], + (fh_type == 6) ? fid->raw[5] : 0); } int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 98c3781bc06..5cd85fe5df5 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -661,11 +661,11 @@ static struct quotactl_ops reiserfs_qctl_operations = { }; #endif -static struct export_operations reiserfs_export_ops = { +static const struct export_operations reiserfs_export_ops = { .encode_fh = reiserfs_encode_fh, - .decode_fh = reiserfs_decode_fh, + .fh_to_dentry = reiserfs_fh_to_dentry, + .fh_to_parent = reiserfs_fh_to_parent, .get_parent = reiserfs_get_parent, - .get_dentry = reiserfs_get_dentry, }; /* this struct is used in reiserfs_getopt () for containing the value for those diff --git a/fs/xattr.c b/fs/xattr.c index a44fd92caca..6645b7313b3 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -267,7 +267,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value, if (!f) return error; dentry = f->f_path.dentry; - audit_inode(NULL, dentry->d_inode); + audit_inode(NULL, dentry); error = setxattr(dentry, name, value, size, flags); fput(f); return error; @@ -349,7 +349,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size) f = fget(fd); if (!f) return error; - audit_inode(NULL, f->f_path.dentry->d_inode); + audit_inode(NULL, f->f_path.dentry); error = getxattr(f->f_path.dentry, name, value, size); fput(f); return error; @@ -422,7 +422,7 @@ sys_flistxattr(int fd, char __user *list, size_t size) f = fget(fd); if (!f) return error; - audit_inode(NULL, f->f_path.dentry->d_inode); + audit_inode(NULL, f->f_path.dentry); error = listxattr(f->f_path.dentry, list, size); fput(f); return error; @@ -485,7 +485,7 @@ sys_fremovexattr(int fd, char __user *name) if (!f) return error; dentry = f->f_path.dentry; - audit_inode(NULL, dentry->d_inode); + audit_inode(NULL, dentry); error = removexattr(dentry, name); fput(f); return error; diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index 3586c7a28d2..15bd4948832 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -33,62 +33,25 @@ static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, }; /* - * XFS encodes and decodes the fileid portion of NFS filehandles - * itself instead of letting the generic NFS code do it. This - * allows filesystems with 64 bit inode numbers to be exported. - * - * Note that a side effect is that xfs_vget() won't be passed a - * zero inode/generation pair under normal circumstances. As - * however a malicious client could send us such data, the check - * remains in that code. + * Note that we only accept fileids which are long enough rather than allow + * the parent generation number to default to zero. XFS considers zero a + * valid generation number not an invalid/wildcard value. */ - -STATIC struct dentry * -xfs_fs_decode_fh( - struct super_block *sb, - __u32 *fh, - int fh_len, - int fileid_type, - int (*acceptable)( - void *context, - struct dentry *de), - void *context) +static int xfs_fileid_length(int fileid_type) { - xfs_fid_t ifid; - xfs_fid_t pfid; - void *parent = NULL; - int is64 = 0; - __u32 *p = fh; - -#if XFS_BIG_INUMS - is64 = (fileid_type & XFS_FILEID_TYPE_64FLAG); - fileid_type &= ~XFS_FILEID_TYPE_64FLAG; -#endif - - /* - * Note that we only accept fileids which are long enough - * rather than allow the parent generation number to default - * to zero. XFS considers zero a valid generation number not - * an invalid/wildcard value. There's little point printk'ing - * a warning here as we don't have the client information - * which would make such a warning useful. - */ - if (fileid_type > 2 || - fh_len < xfs_fileid_length((fileid_type == 2), is64)) - return NULL; - - p = xfs_fileid_decode_fid2(p, &ifid, is64); - - if (fileid_type == 2) { - p = xfs_fileid_decode_fid2(p, &pfid, is64); - parent = &pfid; + switch (fileid_type) { + case FILEID_INO32_GEN: + return 2; + case FILEID_INO32_GEN_PARENT: + return 4; + case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: + return 3; + case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: + return 6; } - - fh = (__u32 *)&ifid; - return sb->s_export_op->find_exported_dentry(sb, fh, parent, acceptable, context); + return 255; /* invalid */ } - STATIC int xfs_fs_encode_fh( struct dentry *dentry, @@ -96,21 +59,21 @@ xfs_fs_encode_fh( int *max_len, int connectable) { + struct fid *fid = (struct fid *)fh; + struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fh; struct inode *inode = dentry->d_inode; - int type = 1; - __u32 *p = fh; + int fileid_type; int len; - int is64 = 0; -#if XFS_BIG_INUMS - if (!(XFS_M(inode->i_sb)->m_flags & XFS_MOUNT_SMALL_INUMS)) { - /* filesystem may contain 64bit inode numbers */ - is64 = XFS_FILEID_TYPE_64FLAG; - } -#endif /* Directories don't need their parent encoded, they have ".." */ if (S_ISDIR(inode->i_mode)) - connectable = 0; + fileid_type = FILEID_INO32_GEN; + else + fileid_type = FILEID_INO32_GEN_PARENT; + + /* filesystem may contain 64bit inode numbers */ + if (!(XFS_M(inode->i_sb)->m_flags & XFS_MOUNT_SMALL_INUMS)) + fileid_type |= XFS_FILEID_TYPE_64FLAG; /* * Only encode if there is enough space given. In practice @@ -118,39 +81,118 @@ xfs_fs_encode_fh( * over NFSv2 with the subtree_check export option; the other * seven combinations work. The real answer is "don't use v2". */ - len = xfs_fileid_length(connectable, is64); + len = xfs_fileid_length(fileid_type); if (*max_len < len) return 255; *max_len = len; - p = xfs_fileid_encode_inode(p, inode, is64); - if (connectable) { + switch (fileid_type) { + case FILEID_INO32_GEN_PARENT: spin_lock(&dentry->d_lock); - p = xfs_fileid_encode_inode(p, dentry->d_parent->d_inode, is64); + fid->i32.parent_ino = dentry->d_parent->d_inode->i_ino; + fid->i32.parent_gen = dentry->d_parent->d_inode->i_generation; spin_unlock(&dentry->d_lock); - type = 2; + /*FALLTHRU*/ + case FILEID_INO32_GEN: + fid->i32.ino = inode->i_ino; + fid->i32.gen = inode->i_generation; + break; + case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: + spin_lock(&dentry->d_lock); + fid64->parent_ino = dentry->d_parent->d_inode->i_ino; + fid64->parent_gen = dentry->d_parent->d_inode->i_generation; + spin_unlock(&dentry->d_lock); + /*FALLTHRU*/ + case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: + fid64->ino = inode->i_ino; + fid64->gen = inode->i_generation; + break; } - BUG_ON((p - fh) != len); - return type | is64; + + return fileid_type; } -STATIC struct dentry * -xfs_fs_get_dentry( +STATIC struct inode * +xfs_nfs_get_inode( struct super_block *sb, - void *data) -{ + u64 ino, + u32 generation) + { + xfs_fid_t xfid; bhv_vnode_t *vp; - struct inode *inode; - struct dentry *result; int error; - error = xfs_vget(XFS_M(sb), &vp, data); - if (error || vp == NULL) - return ERR_PTR(-ESTALE) ; + xfid.fid_len = sizeof(xfs_fid_t) - sizeof(xfid.fid_len); + xfid.fid_pad = 0; + xfid.fid_ino = ino; + xfid.fid_gen = generation; - inode = vn_to_inode(vp); + error = xfs_vget(XFS_M(sb), &vp, &xfid); + if (error) + return ERR_PTR(-error); + + return vp ? vn_to_inode(vp) : NULL; +} + +STATIC struct dentry * +xfs_fs_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fileid_type) +{ + struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; + struct inode *inode = NULL; + struct dentry *result; + + if (fh_len < xfs_fileid_length(fileid_type)) + return NULL; + + switch (fileid_type) { + case FILEID_INO32_GEN_PARENT: + case FILEID_INO32_GEN: + inode = xfs_nfs_get_inode(sb, fid->i32.ino, fid->i32.gen); + break; + case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: + case FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG: + inode = xfs_nfs_get_inode(sb, fid64->ino, fid64->gen); + break; + } + + if (!inode) + return NULL; + if (IS_ERR(inode)) + return ERR_PTR(PTR_ERR(inode)); + result = d_alloc_anon(inode); + if (!result) { + iput(inode); + return ERR_PTR(-ENOMEM); + } + return result; +} + +STATIC struct dentry * +xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fileid_type) +{ + struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; + struct inode *inode = NULL; + struct dentry *result; + + switch (fileid_type) { + case FILEID_INO32_GEN_PARENT: + inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino, + fid->i32.parent_gen); + break; + case FILEID_INO32_GEN_PARENT | XFS_FILEID_TYPE_64FLAG: + inode = xfs_nfs_get_inode(sb, fid64->parent_ino, + fid64->parent_gen); + break; + } + + if (!inode) + return NULL; + if (IS_ERR(inode)) + return ERR_PTR(PTR_ERR(inode)); result = d_alloc_anon(inode); - if (!result) { + if (!result) { iput(inode); return ERR_PTR(-ENOMEM); } @@ -178,9 +220,9 @@ xfs_fs_get_parent( return parent; } -struct export_operations xfs_export_operations = { - .decode_fh = xfs_fs_decode_fh, +const struct export_operations xfs_export_operations = { .encode_fh = xfs_fs_encode_fh, + .fh_to_dentry = xfs_fs_fh_to_dentry, + .fh_to_parent = xfs_fs_fh_to_parent, .get_parent = xfs_fs_get_parent, - .get_dentry = xfs_fs_get_dentry, }; diff --git a/fs/xfs/linux-2.6/xfs_export.h b/fs/xfs/linux-2.6/xfs_export.h index 2f36071a86f..3272b6ae7a3 100644 --- a/fs/xfs/linux-2.6/xfs_export.h +++ b/fs/xfs/linux-2.6/xfs_export.h @@ -59,50 +59,14 @@ * a subdirectory) or use the "fsid" export option. */ +struct xfs_fid64 { + u64 ino; + u32 gen; + u64 parent_ino; + u32 parent_gen; +} __attribute__((packed)); + /* This flag goes on the wire. Don't play with it. */ #define XFS_FILEID_TYPE_64FLAG 0x80 /* NFS fileid has 64bit inodes */ -/* Calculate the length in u32 units of the fileid data */ -static inline int -xfs_fileid_length(int hasparent, int is64) -{ - return hasparent ? (is64 ? 6 : 4) : (is64 ? 3 : 2); -} - -/* - * Decode encoded inode information (either for the inode itself - * or the parent) into an xfs_fid_t structure. Advances and - * returns the new data pointer - */ -static inline __u32 * -xfs_fileid_decode_fid2(__u32 *p, xfs_fid_t *fid, int is64) -{ - fid->fid_len = sizeof(xfs_fid_t) - sizeof(fid->fid_len); - fid->fid_pad = 0; - fid->fid_ino = *p++; -#if XFS_BIG_INUMS - if (is64) - fid->fid_ino |= (((__u64)(*p++)) << 32); -#endif - fid->fid_gen = *p++; - return p; -} - -/* - * Encode inode information (either for the inode itself or the - * parent) into a fileid buffer. Advances and returns the new - * data pointer. - */ -static inline __u32 * -xfs_fileid_encode_inode(__u32 *p, struct inode *inode, int is64) -{ - *p++ = (__u32)inode->i_ino; -#if XFS_BIG_INUMS - if (is64) - *p++ = (__u32)(inode->i_ino >> 32); -#endif - *p++ = inode->i_generation; - return p; -} - #endif /* __XFS_EXPORT_H__ */ diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index c78c23310fe..3efcf45b14a 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h @@ -118,7 +118,7 @@ extern int xfs_blkdev_get(struct xfs_mount *, const char *, extern void xfs_blkdev_put(struct block_device *); extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); -extern struct export_operations xfs_export_operations; +extern const struct export_operations xfs_export_operations; #define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info)) diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 4e5d3ca53a8..a1b1b2ee3e5 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -257,7 +257,8 @@ struct acpi_table_dbgp { struct acpi_table_dmar { struct acpi_table_header header; /* Common ACPI table header */ u8 width; /* Host Address Width */ - u8 reserved[11]; + u8 flags; + u8 reserved[10]; }; /* DMAR subtable header */ @@ -265,8 +266,6 @@ struct acpi_table_dmar { struct acpi_dmar_header { u16 type; u16 length; - u8 flags; - u8 reserved[3]; }; /* Values for subtable type in struct acpi_dmar_header */ @@ -274,13 +273,15 @@ struct acpi_dmar_header { enum acpi_dmar_type { ACPI_DMAR_TYPE_HARDWARE_UNIT = 0, ACPI_DMAR_TYPE_RESERVED_MEMORY = 1, - ACPI_DMAR_TYPE_RESERVED = 2 /* 2 and greater are reserved */ + ACPI_DMAR_TYPE_ATSR = 2, + ACPI_DMAR_TYPE_RESERVED = 3 /* 3 and greater are reserved */ }; struct acpi_dmar_device_scope { u8 entry_type; u8 length; - u8 segment; + u16 reserved; + u8 enumeration_id; u8 bus; }; @@ -290,7 +291,14 @@ enum acpi_dmar_scope_type { ACPI_DMAR_SCOPE_TYPE_NOT_USED = 0, ACPI_DMAR_SCOPE_TYPE_ENDPOINT = 1, ACPI_DMAR_SCOPE_TYPE_BRIDGE = 2, - ACPI_DMAR_SCOPE_TYPE_RESERVED = 3 /* 3 and greater are reserved */ + ACPI_DMAR_SCOPE_TYPE_IOAPIC = 3, + ACPI_DMAR_SCOPE_TYPE_HPET = 4, + ACPI_DMAR_SCOPE_TYPE_RESERVED = 5 /* 5 and greater are reserved */ +}; + +struct acpi_dmar_pci_path { + u8 dev; + u8 fn; }; /* @@ -301,6 +309,9 @@ enum acpi_dmar_scope_type { struct acpi_dmar_hardware_unit { struct acpi_dmar_header header; + u8 flags; + u8 reserved; + u16 segment; u64 address; /* Register Base Address */ }; @@ -312,7 +323,9 @@ struct acpi_dmar_hardware_unit { struct acpi_dmar_reserved_memory { struct acpi_dmar_header header; - u64 address; /* 4_k aligned base address */ + u16 reserved; + u16 segment; + u64 base_address; /* 4_k aligned base address */ u64 end_address; /* 4_k aligned limit address */ }; diff --git a/include/asm-alpha/scatterlist.h b/include/asm-alpha/scatterlist.h index 917365405e8..440747ca634 100644 --- a/include/asm-alpha/scatterlist.h +++ b/include/asm-alpha/scatterlist.h @@ -5,7 +5,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; unsigned int length; diff --git a/include/asm-arm/scatterlist.h b/include/asm-arm/scatterlist.h index de2f65eb42e..ca0a37d0340 100644 --- a/include/asm-arm/scatterlist.h +++ b/include/asm-arm/scatterlist.h @@ -5,7 +5,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; /* buffer page */ +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; /* buffer offset */ dma_addr_t dma_address; /* dma address */ unsigned int length; /* length */ diff --git a/include/asm-avr32/scatterlist.h b/include/asm-avr32/scatterlist.h index c6d5ce3b3a2..377320e3bd1 100644 --- a/include/asm-avr32/scatterlist.h +++ b/include/asm-avr32/scatterlist.h @@ -4,7 +4,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; dma_addr_t dma_address; unsigned int length; diff --git a/include/asm-blackfin/bf5xx_timers.h b/include/asm-blackfin/bf5xx_timers.h deleted file mode 100644 index 86c770321b6..00000000000 --- a/include/asm-blackfin/bf5xx_timers.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * include/asm/bf5xx_timers.h - * - * This file contains the major Data structures and constants - * used for General Purpose Timer Implementation in BF5xx - * - * Copyright (C) 2005 John DeHority - * Copyright (C) 2006 Hella Aglaia GmbH (awe@aglaia-gmbh.de) - * - */ - -#ifndef _BLACKFIN_TIMERS_H_ -#define _BLACKFIN_TIMERS_H_ - -#undef MAX_BLACKFIN_GPTIMERS -/* - * BF537: 8 timers: - */ -#if defined(CONFIG_BF537) -# define MAX_BLACKFIN_GPTIMERS 8 -# define TIMER0_GROUP_REG TIMER_ENABLE -#endif -/* - * BF561: 12 timers: - */ -#if defined(CONFIG_BF561) -# define MAX_BLACKFIN_GPTIMERS 12 -# define TIMER0_GROUP_REG TMRS8_ENABLE -# define TIMER8_GROUP_REG TMRS4_ENABLE -#endif -/* - * All others: 3 timers: - */ -#if !defined(MAX_BLACKFIN_GPTIMERS) -# define MAX_BLACKFIN_GPTIMERS 3 -# define TIMER0_GROUP_REG TIMER_ENABLE -#endif - -#define BLACKFIN_GPTIMER_IDMASK ((1UL << MAX_BLACKFIN_GPTIMERS) - 1) -#define BFIN_TIMER_OCTET(x) ((x) >> 3) - -/* used in masks for timer_enable() and timer_disable() */ -#define TIMER0bit 0x0001 /* 0001b */ -#define TIMER1bit 0x0002 /* 0010b */ -#define TIMER2bit 0x0004 /* 0100b */ - -#if (MAX_BLACKFIN_GPTIMERS > 3) -# define TIMER3bit 0x0008 -# define TIMER4bit 0x0010 -# define TIMER5bit 0x0020 -# define TIMER6bit 0x0040 -# define TIMER7bit 0x0080 -#endif - -#if (MAX_BLACKFIN_GPTIMERS > 8) -# define TIMER8bit 0x0100 -# define TIMER9bit 0x0200 -# define TIMER10bit 0x0400 -# define TIMER11bit 0x0800 -#endif - -#define TIMER0_id 0 -#define TIMER1_id 1 -#define TIMER2_id 2 - -#if (MAX_BLACKFIN_GPTIMERS > 3) -# define TIMER3_id 3 -# define TIMER4_id 4 -# define TIMER5_id 5 -# define TIMER6_id 6 -# define TIMER7_id 7 -#endif - -#if (MAX_BLACKFIN_GPTIMERS > 8) -# define TIMER8_id 8 -# define TIMER9_id 9 -# define TIMER10_id 10 -# define TIMER11_id 11 -#endif - -/* associated timers for ppi framesync: */ - -#if defined(CONFIG_BF561) -# define FS0_1_TIMER_ID TIMER8_id -# define FS0_2_TIMER_ID TIMER9_id -# define FS1_1_TIMER_ID TIMER10_id -# define FS1_2_TIMER_ID TIMER11_id -# define FS0_1_TIMER_BIT TIMER8bit -# define FS0_2_TIMER_BIT TIMER9bit -# define FS1_1_TIMER_BIT TIMER10bit -# define FS1_2_TIMER_BIT TIMER11bit -# undef FS1_TIMER_ID -# undef FS2_TIMER_ID -# undef FS1_TIMER_BIT -# undef FS2_TIMER_BIT -#else -# define FS1_TIMER_ID TIMER0_id -# define FS2_TIMER_ID TIMER1_id -# define FS1_TIMER_BIT TIMER0bit -# define FS2_TIMER_BIT TIMER1bit -#endif - -/* -** Timer Configuration Register Bits -*/ -#define TIMER_ERR 0xC000 -#define TIMER_ERR_OVFL 0x4000 -#define TIMER_ERR_PROG_PER 0x8000 -#define TIMER_ERR_PROG_PW 0xC000 -#define TIMER_EMU_RUN 0x0200 -#define TIMER_TOGGLE_HI 0x0100 -#define TIMER_CLK_SEL 0x0080 -#define TIMER_OUT_DIS 0x0040 -#define TIMER_TIN_SEL 0x0020 -#define TIMER_IRQ_ENA 0x0010 -#define TIMER_PERIOD_CNT 0x0008 -#define TIMER_PULSE_HI 0x0004 -#define TIMER_MODE 0x0003 -#define TIMER_MODE_PWM 0x0001 -#define TIMER_MODE_WDTH 0x0002 -#define TIMER_MODE_EXT_CLK 0x0003 - -/* -** Timer Status Register Bits -*/ -#define TIMER_STATUS_TIMIL0 0x0001 -#define TIMER_STATUS_TIMIL1 0x0002 -#define TIMER_STATUS_TIMIL2 0x0004 -#if (MAX_BLACKFIN_GPTIMERS > 3) -# define TIMER_STATUS_TIMIL3 0x00000008 -# define TIMER_STATUS_TIMIL4 0x00010000 -# define TIMER_STATUS_TIMIL5 0x00020000 -# define TIMER_STATUS_TIMIL6 0x00040000 -# define TIMER_STATUS_TIMIL7 0x00080000 -# if (MAX_BLACKFIN_GPTIMERS > 8) -# define TIMER_STATUS_TIMIL8 0x0001 -# define TIMER_STATUS_TIMIL9 0x0002 -# define TIMER_STATUS_TIMIL10 0x0004 -# define TIMER_STATUS_TIMIL11 0x0008 -# endif -# define TIMER_STATUS_INTR 0x000F000F -#else -# define TIMER_STATUS_INTR 0x0007 /* any timer interrupt */ -#endif - -#define TIMER_STATUS_TOVF0 0x0010 /* timer 0 overflow error */ -#define TIMER_STATUS_TOVF1 0x0020 -#define TIMER_STATUS_TOVF2 0x0040 -#if (MAX_BLACKFIN_GPTIMERS > 3) -# define TIMER_STATUS_TOVF3 0x00000080 -# define TIMER_STATUS_TOVF4 0x00100000 -# define TIMER_STATUS_TOVF5 0x00200000 -# define TIMER_STATUS_TOVF6 0x00400000 -# define TIMER_STATUS_TOVF7 0x00800000 -# if (MAX_BLACKFIN_GPTIMERS > 8) -# define TIMER_STATUS_TOVF8 0x0010 -# define TIMER_STATUS_TOVF9 0x0020 -# define TIMER_STATUS_TOVF10 0x0040 -# define TIMER_STATUS_TOVF11 0x0080 -# endif -# define TIMER_STATUS_OFLOW 0x00F000F0 -#else -# define TIMER_STATUS_OFLOW 0x0070 /* any timer overflow */ -#endif - -/* -** Timer Slave Enable Status : write 1 to clear -*/ -#define TIMER_STATUS_TRUN0 0x1000 -#define TIMER_STATUS_TRUN1 0x2000 -#define TIMER_STATUS_TRUN2 0x4000 -#if (MAX_BLACKFIN_GPTIMERS > 3) -# define TIMER_STATUS_TRUN3 0x00008000 -# define TIMER_STATUS_TRUN4 0x10000000 -# define TIMER_STATUS_TRUN5 0x20000000 -# define TIMER_STATUS_TRUN6 0x40000000 -# define TIMER_STATUS_TRUN7 0x80000000 -# define TIMER_STATUS_TRUN 0xF000F000 -# if (MAX_BLACKFIN_GPTIMERS > 8) -# define TIMER_STATUS_TRUN8 0x1000 -# define TIMER_STATUS_TRUN9 0x2000 -# define TIMER_STATUS_TRUN10 0x4000 -# define TIMER_STATUS_TRUN11 0x8000 -# endif -#else -# define TIMER_STATUS_TRUN 0x7000 -#endif - -/******************************************************************************* -* GP_TIMER API's -*******************************************************************************/ - -void set_gptimer_pwidth (int timer_id, int width); -int get_gptimer_pwidth (int timer_id); -void set_gptimer_period (int timer_id, int period); -int get_gptimer_period (int timer_id); -int get_gptimer_count (int timer_id); -short get_gptimer_intr (int timer_id); -void set_gptimer_config (int timer_id, short config); -short get_gptimer_config (int timer_id); -void set_gptimer_pulse_hi (int timer_id); -void clear_gptimer_pulse_hi(int timer_id); -void enable_gptimers (short mask); -void disable_gptimers (short mask); -short get_enabled_timers (void); -int get_gptimer_status (int octet); -void set_gptimer_status (int octet, int value); - -#endif diff --git a/include/asm-blackfin/bfin-global.h b/include/asm-blackfin/bfin-global.h index a970781a0f9..14cb8d35924 100644 --- a/include/asm-blackfin/bfin-global.h +++ b/include/asm-blackfin/bfin-global.h @@ -47,6 +47,8 @@ extern unsigned long get_cclk(void); extern unsigned long get_sclk(void); +extern unsigned long sclk_to_usecs(unsigned long sclk); +extern unsigned long usecs_to_sclk(unsigned long usecs); extern void dump_thread(struct pt_regs *regs, struct user *dump); extern void dump_bfin_regs(struct pt_regs *fp, void *retaddr); @@ -105,7 +107,7 @@ extern void led_disp_num(int); extern void led_toggle_num(int); extern void init_leds(void); -extern char *bfin_board_name __attribute__ ((weak)); +extern const char bfin_board_name[]; extern unsigned long wall_jiffies; extern unsigned long ipdt_table[]; extern unsigned long dpdt_table[]; diff --git a/include/asm-blackfin/dma.h b/include/asm-blackfin/dma.h index b42a531e7a1..b469505af36 100644 --- a/include/asm-blackfin/dma.h +++ b/include/asm-blackfin/dma.h @@ -109,9 +109,7 @@ struct dma_register { unsigned long curr_desc_ptr; /* DMA Current Descriptor Pointer register */ - unsigned short curr_addr_ptr_lo; /* DMA Current Address Pointer - register */ - unsigned short curr_addr_ptr_hi; /* DMA Current Address Pointer + unsigned long curr_addr_ptr; /* DMA Current Address Pointer register */ unsigned short irq_status; /* DMA irq status register */ unsigned short dummy6; @@ -166,6 +164,9 @@ void set_dma_curr_addr(unsigned int channel, unsigned long addr); unsigned short get_dma_curr_irqstat(unsigned int channel); unsigned short get_dma_curr_xcount(unsigned int channel); unsigned short get_dma_curr_ycount(unsigned int channel); +unsigned long get_dma_next_desc_ptr(unsigned int channel); +unsigned long get_dma_curr_desc_ptr(unsigned int channel); +unsigned long get_dma_curr_addr(unsigned int channel); /* set large DMA mode descriptor */ void set_dma_sg(unsigned int channel, struct dmasg *sg, int nr_sg); diff --git a/include/asm-blackfin/gpio.h b/include/asm-blackfin/gpio.h index dd203cd9379..33ce98ef7e0 100644 --- a/include/asm-blackfin/gpio.h +++ b/include/asm-blackfin/gpio.h @@ -29,6 +29,7 @@ /* * Number BF537/6/4 BF561 BF533/2/1 +* BF527/5/2 * * GPIO_0 PF0 PF0 PF0 * GPIO_1 PF1 PF1 PF1 @@ -164,7 +165,7 @@ #endif -#ifdef BF537_FAMILY +#if defined(BF527_FAMILY) || defined(BF537_FAMILY) #define MAX_BLACKFIN_GPIOS 48 #define GPIO_PF0 0 diff --git a/include/asm-blackfin/gptimers.h b/include/asm-blackfin/gptimers.h new file mode 100644 index 00000000000..c97ab03e43a --- /dev/null +++ b/include/asm-blackfin/gptimers.h @@ -0,0 +1,210 @@ +/* + * include/asm/bf5xx_timers.h + * + * This file contains the major Data structures and constants + * used for General Purpose Timer Implementation in BF5xx + * + * Copyright (C) 2005 John DeHority + * Copyright (C) 2006 Hella Aglaia GmbH (awe@aglaia-gmbh.de) + * + */ + +#ifndef _BLACKFIN_TIMERS_H_ +#define _BLACKFIN_TIMERS_H_ + +#include <linux/types.h> +#include <asm/blackfin.h> + +/* + * BF537/BF527: 8 timers: + */ +#if defined(BF527_FAMILY) || defined(BF537_FAMILY) +# define MAX_BLACKFIN_GPTIMERS 8 +# define TIMER0_GROUP_REG TIMER_ENABLE +#endif +/* + * BF561: 12 timers: + */ +#if defined(CONFIG_BF561) +# define MAX_BLACKFIN_GPTIMERS 12 +# define TIMER0_GROUP_REG TMRS8_ENABLE +# define TIMER8_GROUP_REG TMRS4_ENABLE +#endif +/* + * All others: 3 timers: + */ +#if !defined(MAX_BLACKFIN_GPTIMERS) +# define MAX_BLACKFIN_GPTIMERS 3 +# define TIMER0_GROUP_REG TIMER_ENABLE +#endif + +#define BLACKFIN_GPTIMER_IDMASK ((1UL << MAX_BLACKFIN_GPTIMERS) - 1) +#define BFIN_TIMER_OCTET(x) ((x) >> 3) + +/* used in masks for timer_enable() and timer_disable() */ +#define TIMER0bit 0x0001 /* 0001b */ +#define TIMER1bit 0x0002 /* 0010b */ +#define TIMER2bit 0x0004 /* 0100b */ + +#if (MAX_BLACKFIN_GPTIMERS > 3) +# define TIMER3bit 0x0008 +# define TIMER4bit 0x0010 +# define TIMER5bit 0x0020 +# define TIMER6bit 0x0040 +# define TIMER7bit 0x0080 +#endif + +#if (MAX_BLACKFIN_GPTIMERS > 8) +# define TIMER8bit 0x0100 +# define TIMER9bit 0x0200 +# define TIMER10bit 0x0400 +# define TIMER11bit 0x0800 +#endif + +#define TIMER0_id 0 +#define TIMER1_id 1 +#define TIMER2_id 2 + +#if (MAX_BLACKFIN_GPTIMERS > 3) +# define TIMER3_id 3 +# define TIMER4_id 4 +# define TIMER5_id 5 +# define TIMER6_id 6 +# define TIMER7_id 7 +#endif + +#if (MAX_BLACKFIN_GPTIMERS > 8) +# define TIMER8_id 8 +# define TIMER9_id 9 +# define TIMER10_id 10 +# define TIMER11_id 11 +#endif + +/* associated timers for ppi framesync: */ + +#if defined(CONFIG_BF561) +# define FS0_1_TIMER_ID TIMER8_id +# define FS0_2_TIMER_ID TIMER9_id +# define FS1_1_TIMER_ID TIMER10_id +# define FS1_2_TIMER_ID TIMER11_id +# define FS0_1_TIMER_BIT TIMER8bit +# define FS0_2_TIMER_BIT TIMER9bit +# define FS1_1_TIMER_BIT TIMER10bit +# define FS1_2_TIMER_BIT TIMER11bit +# undef FS1_TIMER_ID +# undef FS2_TIMER_ID +# undef FS1_TIMER_BIT +# undef FS2_TIMER_BIT +#else +# define FS1_TIMER_ID TIMER0_id +# define FS2_TIMER_ID TIMER1_id +# define FS1_TIMER_BIT TIMER0bit +# define FS2_TIMER_BIT TIMER1bit +#endif + +/* + * Timer Configuration Register Bits + */ +#define TIMER_ERR 0xC000 +#define TIMER_ERR_OVFL 0x4000 +#define TIMER_ERR_PROG_PER 0x8000 +#define TIMER_ERR_PROG_PW 0xC000 +#define TIMER_EMU_RUN 0x0200 +#define TIMER_TOGGLE_HI 0x0100 +#define TIMER_CLK_SEL 0x0080 +#define TIMER_OUT_DIS 0x0040 +#define TIMER_TIN_SEL 0x0020 +#define TIMER_IRQ_ENA 0x0010 +#define TIMER_PERIOD_CNT 0x0008 +#define TIMER_PULSE_HI 0x0004 +#define TIMER_MODE 0x0003 +#define TIMER_MODE_PWM 0x0001 +#define TIMER_MODE_WDTH 0x0002 +#define TIMER_MODE_EXT_CLK 0x0003 + +/* + * Timer Status Register Bits + */ +#define TIMER_STATUS_TIMIL0 0x0001 +#define TIMER_STATUS_TIMIL1 0x0002 +#define TIMER_STATUS_TIMIL2 0x0004 +#if (MAX_BLACKFIN_GPTIMERS > 3) +# define TIMER_STATUS_TIMIL3 0x00000008 +# define TIMER_STATUS_TIMIL4 0x00010000 +# define TIMER_STATUS_TIMIL5 0x00020000 +# define TIMER_STATUS_TIMIL6 0x00040000 +# define TIMER_STATUS_TIMIL7 0x00080000 +# if (MAX_BLACKFIN_GPTIMERS > 8) +# define TIMER_STATUS_TIMIL8 0x0001 +# define TIMER_STATUS_TIMIL9 0x0002 +# define TIMER_STATUS_TIMIL10 0x0004 +# define TIMER_STATUS_TIMIL11 0x0008 +# endif +# define TIMER_STATUS_INTR 0x000F000F +#else +# define TIMER_STATUS_INTR 0x0007 /* any timer interrupt */ +#endif + +#define TIMER_STATUS_TOVF0 0x0010 /* timer 0 overflow error */ +#define TIMER_STATUS_TOVF1 0x0020 +#define TIMER_STATUS_TOVF2 0x0040 +#if (MAX_BLACKFIN_GPTIMERS > 3) +# define TIMER_STATUS_TOVF3 0x00000080 +# define TIMER_STATUS_TOVF4 0x00100000 +# define TIMER_STATUS_TOVF5 0x00200000 +# define TIMER_STATUS_TOVF6 0x00400000 +# define TIMER_STATUS_TOVF7 0x00800000 +# if (MAX_BLACKFIN_GPTIMERS > 8) +# define TIMER_STATUS_TOVF8 0x0010 +# define TIMER_STATUS_TOVF9 0x0020 +# define TIMER_STATUS_TOVF10 0x0040 +# define TIMER_STATUS_TOVF11 0x0080 +# endif +# define TIMER_STATUS_OFLOW 0x00F000F0 +#else +# define TIMER_STATUS_OFLOW 0x0070 /* any timer overflow */ +#endif + +/* + * Timer Slave Enable Status : write 1 to clear + */ +#define TIMER_STATUS_TRUN0 0x1000 +#define TIMER_STATUS_TRUN1 0x2000 +#define TIMER_STATUS_TRUN2 0x4000 +#if (MAX_BLACKFIN_GPTIMERS > 3) +# define TIMER_STATUS_TRUN3 0x00008000 +# define TIMER_STATUS_TRUN4 0x10000000 +# define TIMER_STATUS_TRUN5 0x20000000 +# define TIMER_STATUS_TRUN6 0x40000000 +# define TIMER_STATUS_TRUN7 0x80000000 +# define TIMER_STATUS_TRUN 0xF000F000 +# if (MAX_BLACKFIN_GPTIMERS > 8) +# define TIMER_STATUS_TRUN8 0x1000 +# define TIMER_STATUS_TRUN9 0x2000 +# define TIMER_STATUS_TRUN10 0x4000 +# define TIMER_STATUS_TRUN11 0x8000 +# endif +#else +# define TIMER_STATUS_TRUN 0x7000 +#endif + +/* The actual gptimer API */ + +void set_gptimer_pwidth (int timer_id, uint32_t width); +uint32_t get_gptimer_pwidth (int timer_id); +void set_gptimer_period (int timer_id, uint32_t period); +uint32_t get_gptimer_period (int timer_id); +uint32_t get_gptimer_count (int timer_id); +uint16_t get_gptimer_intr (int timer_id); +void clear_gptimer_intr (int timer_id); +void set_gptimer_config (int timer_id, uint16_t config); +uint16_t get_gptimer_config (int timer_id); +void set_gptimer_pulse_hi (int timer_id); +void clear_gptimer_pulse_hi(int timer_id); +void enable_gptimers (uint16_t mask); +void disable_gptimers (uint16_t mask); +uint16_t get_enabled_gptimers (void); +uint32_t get_gptimer_status (int group); +void set_gptimer_status (int group, uint32_t value); + +#endif diff --git a/include/asm-blackfin/mach-bf527/anomaly.h b/include/asm-blackfin/mach-bf527/anomaly.h index 991db986cd4..a89120445be 100644 --- a/include/asm-blackfin/mach-bf527/anomaly.h +++ b/include/asm-blackfin/mach-bf527/anomaly.h @@ -38,4 +38,12 @@ /* Anomalies that don't exist on this proc */ #define ANOMALY_05000323 (0) +#define ANOMALY_05000244 (0) +#define ANOMALY_05000198 (0) +#define ANOMALY_05000125 (0) +#define ANOMALY_05000158 (0) +#define ANOMALY_05000273 (0) +#define ANOMALY_05000263 (0) +#define ANOMALY_05000311 (0) +#define ANOMALY_05000230 (0) #endif diff --git a/include/asm-blackfin/mach-bf527/bf527.h b/include/asm-blackfin/mach-bf527/bf527.h new file mode 100644 index 00000000000..056eb4b9cd2 --- /dev/null +++ b/include/asm-blackfin/mach-bf527/bf527.h @@ -0,0 +1,127 @@ +/* + * File: include/asm-blackfin/mach-bf527/bf527.h + * Based on: include/asm-blackfin/mach-bf537/bf537.h + * Author: Michael Hennerich (michael.hennerich@analog.com) + * + * Created: + * Description: SYSTEM MMR REGISTER AND MEMORY MAP FOR ADSP-BF527 + * + * Modified: + * Copyright 2004-2007 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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, see the file COPYING, or write + * to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MACH_BF527_H__ +#define __MACH_BF527_H__ + +#define SUPPORTED_REVID 2 + +#define OFFSET_(x) ((x) & 0x0000FFFF) + +/*some misc defines*/ +#define IMASK_IVG15 0x8000 +#define IMASK_IVG14 0x4000 +#define IMASK_IVG13 0x2000 +#define IMASK_IVG12 0x1000 + +#define IMASK_IVG11 0x0800 +#define IMASK_IVG10 0x0400 +#define IMASK_IVG9 0x0200 +#define IMASK_IVG8 0x0100 + +#define IMASK_IVG7 0x0080 +#define IMASK_IVGTMR 0x0040 +#define IMASK_IVGHW 0x0020 + +/***************************/ + +#define BFIN_DSUBBANKS 4 +#define BFIN_DWAYS 2 +#define BFIN_DLINES 64 +#define BFIN_ISUBBANKS 4 +#define BFIN_IWAYS 4 +#define BFIN_ILINES 32 + +#define WAY0_L 0x1 +#define WAY1_L 0x2 +#define WAY01_L 0x3 +#define WAY2_L 0x4 +#define WAY02_L 0x5 +#define WAY12_L 0x6 +#define WAY012_L 0x7 + +#define WAY3_L 0x8 +#define WAY03_L 0x9 +#define WAY13_L 0xA +#define WAY013_L 0xB + +#define WAY32_L 0xC +#define WAY320_L 0xD +#define WAY321_L 0xE +#define WAYALL_L 0xF + +#define DMC_ENABLE (2<<2) /*yes, 2, not 1 */ + +/********************************* EBIU Settings ************************************/ +#define AMBCTL0VAL ((CONFIG_BANK_1 << 16) | CONFIG_BANK_0) +#define AMBCTL1VAL ((CONFIG_BANK_3 << 16) | CONFIG_BANK_2) + +#ifdef CONFIG_C_AMBEN_ALL +#define V_AMBEN AMBEN_ALL +#endif +#ifdef CONFIG_C_AMBEN +#define V_AMBEN 0x0 +#endif +#ifdef CONFIG_C_AMBEN_B0 +#define V_AMBEN AMBEN_B0 +#endif +#ifdef CONFIG_C_AMBEN_B0_B1 +#define V_AMBEN AMBEN_B0_B1 +#endif +#ifdef CONFIG_C_AMBEN_B0_B1_B2 +#define V_AMBEN AMBEN_B0_B1_B2 +#endif +#ifdef CONFIG_C_AMCKEN +#define V_AMCKEN AMCKEN +#else +#define V_AMCKEN 0x0 +#endif +#ifdef CONFIG_C_CDPRIO +#define V_CDPRIO 0x100 +#else +#define V_CDPRIO 0x0 +#endif + +#define AMGCTLVAL (V_AMBEN | V_AMCKEN | V_CDPRIO) + +#ifdef CONFIG_BF527 +#define CPU "BF527" +#endif +#ifdef CONFIG_BF525 +#define CPU "BF525" +#endif +#ifdef CONFIG_BF522 +#define CPU "BF522" +#endif +#ifndef CPU +#define CPU "UNKNOWN" +#define CPUID 0x0 +#endif + +#endif /* __MACH_BF527_H__ */ diff --git a/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h new file mode 100644 index 00000000000..0b867e6a76c --- /dev/null +++ b/include/asm-blackfin/mach-bf527/bfin_serial_5xx.h @@ -0,0 +1,152 @@ +#include <linux/serial.h> +#include <asm/dma.h> +#include <asm/portmux.h> + +#define NR_PORTS 2 + +#define OFFSET_THR 0x00 /* Transmit Holding register */ +#define OFFSET_RBR 0x00 /* Receive Buffer register */ +#define OFFSET_DLL 0x00 /* Divisor Latch (Low-Byte) */ +#define OFFSET_IER 0x04 /* Interrupt Enable Register */ +#define OFFSET_DLH 0x04 /* Divisor Latch (High-Byte) */ +#define OFFSET_IIR 0x08 /* Interrupt Identification Register */ +#define OFFSET_LCR 0x0C /* Line Control Register */ +#define OFFSET_MCR 0x10 /* Modem Control Register */ +#define OFFSET_LSR 0x14 /* Line Status Register */ +#define OFFSET_MSR 0x18 /* Modem Status Register */ +#define OFFSET_SCR 0x1C /* SCR Scratch Register */ +#define OFFSET_GCTL 0x24 /* Global Control Register */ + +#define UART_GET_CHAR(uart) bfin_read16(((uart)->port.membase + OFFSET_RBR)) +#define UART_GET_DLL(uart) bfin_read16(((uart)->port.membase + OFFSET_DLL)) +#define UART_GET_IER(uart) bfin_read16(((uart)->port.membase + OFFSET_IER)) +#define UART_GET_DLH(uart) bfin_read16(((uart)->port.membase + OFFSET_DLH)) +#define UART_GET_IIR(uart) bfin_read16(((uart)->port.membase + OFFSET_IIR)) +#define UART_GET_LCR(uart) bfin_read16(((uart)->port.membase + OFFSET_LCR)) +#define UART_GET_LSR(uart) bfin_read16(((uart)->port.membase + OFFSET_LSR)) +#define UART_GET_GCTL(uart) bfin_read16(((uart)->port.membase + OFFSET_GCTL)) + +#define UART_PUT_CHAR(uart, v) bfin_write16(((uart)->port.membase + OFFSET_THR), v) +#define UART_PUT_DLL(uart, v) bfin_write16(((uart)->port.membase + OFFSET_DLL), v) +#define UART_PUT_IER(uart, v) bfin_write16(((uart)->port.membase + OFFSET_IER), v) +#define UART_PUT_DLH(uart, v) bfin_write16(((uart)->port.membase + OFFSET_DLH), v) +#define UART_PUT_LCR(uart, v) bfin_write16(((uart)->port.membase + OFFSET_LCR), v) +#define UART_PUT_GCTL(uart, v) bfin_write16(((uart)->port.membase + OFFSET_GCTL), v) + +#if defined(CONFIG_BFIN_UART0_CTSRTS) || defined(CONFIG_BFIN_UART1_CTSRTS) +# define CONFIG_SERIAL_BFIN_CTSRTS + +# ifndef CONFIG_UART0_CTS_PIN +# define CONFIG_UART0_CTS_PIN -1 +# endif + +# ifndef CONFIG_UART0_RTS_PIN +# define CONFIG_UART0_RTS_PIN -1 +# endif + +# ifndef CONFIG_UART1_CTS_PIN +# define CONFIG_UART1_CTS_PIN -1 +# endif + +# ifndef CONFIG_UART1_RTS_PIN +# define CONFIG_UART1_RTS_PIN -1 +# endif +#endif +/* + * The pin configuration is different from schematic + */ +struct bfin_serial_port { + struct uart_port port; + unsigned int old_status; +#ifdef CONFIG_SERIAL_BFIN_DMA + int tx_done; + int tx_count; + struct circ_buf rx_dma_buf; + struct timer_list rx_dma_timer; + int rx_dma_nrows; + unsigned int tx_dma_channel; + unsigned int rx_dma_channel; + struct work_struct tx_dma_workqueue; +#else + struct work_struct cts_workqueue; +#endif +#ifdef CONFIG_SERIAL_BFIN_CTSRTS + int cts_pin; + int rts_pin; +#endif +}; + +struct bfin_serial_port bfin_serial_ports[NR_PORTS]; +struct bfin_serial_res { + unsigned long uart_base_addr; + int uart_irq; +#ifdef CONFIG_SERIAL_BFIN_DMA + unsigned int uart_tx_dma_channel; + unsigned int uart_rx_dma_channel; +#endif +#ifdef CONFIG_SERIAL_BFIN_CTSRTS + int uart_cts_pin; + int uart_rts_pin; +#endif +}; + +struct bfin_serial_res bfin_serial_resource[] = { +#ifdef CONFIG_SERIAL_BFIN_UART0 + { + 0xFFC00400, + IRQ_UART0_RX, +#ifdef CONFIG_SERIAL_BFIN_DMA + CH_UART0_TX, + CH_UART0_RX, +#endif +#ifdef CONFIG_BFIN_UART0_CTSRTS + CONFIG_UART0_CTS_PIN, + CONFIG_UART0_RTS_PIN, +#endif + }, +#endif +#ifdef CONFIG_SERIAL_BFIN_UART1 + { + 0xFFC02000, + IRQ_UART1_RX, +#ifdef CONFIG_SERIAL_BFIN_DMA + CH_UART1_TX, + CH_UART1_RX, +#endif +#ifdef CONFIG_BFIN_UART1_CTSRTS + CONFIG_UART1_CTS_PIN, + CONFIG_UART1_RTS_PIN, +#endif + }, +#endif +}; + +int nr_ports = ARRAY_SIZE(bfin_serial_resource); + +#define DRIVER_NAME "bfin-uart" + +static void bfin_serial_hw_init(struct bfin_serial_port *uart) +{ + +#ifdef CONFIG_SERIAL_BFIN_UART0 + peripheral_request(P_UART0_TX, DRIVER_NAME); + peripheral_request(P_UART0_RX, DRIVER_NAME); +#endif + +#ifdef CONFIG_SERIAL_BFIN_UART1 + peripheral_request(P_UART1_TX, DRIVER_NAME); + peripheral_request(P_UART1_RX, DRIVER_NAME); +#endif + +#ifdef CONFIG_SERIAL_BFIN_CTSRTS + if (uart->cts_pin >= 0) { + gpio_request(uart->cts_pin, DRIVER_NAME); + gpio_direction_input(uart->cts_pin); + } + + if (uart->rts_pin >= 0) { + gpio_request(uart->rts_pin, DRIVER_NAME); + gpio_direction_output(uart->rts_pin); + } +#endif +} diff --git a/include/asm-blackfin/mach-bf527/blackfin.h b/include/asm-blackfin/mach-bf527/blackfin.h new file mode 100644 index 00000000000..1bd07e30781 --- /dev/null +++ b/include/asm-blackfin/mach-bf527/blackfin.h @@ -0,0 +1,78 @@ +/* + * File: include/asm-blackfin/mach-bf527/blackfin.h + * Based on: + * Author: + * + * Created: + * Description: + * + * Rev: + * + * Modified: + * + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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, 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; see the file COPYING. + * If not, write to the Free Software Foundation, + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _MACH_BLACKFIN_H_ +#define _MACH_BLACKFIN_H_ + +#define BF527_FAMILY + +#include "bf527.h" +#include "mem_map.h" +#include "defBF522.h" +#include "anomaly.h" + +#if defined(CONFIG_BF527) +#include "defBF527.h" +#endif + +#if defined(CONFIG_BF525) +#include "defBF525.h" +#endif + +#if !defined(__ASSEMBLY__) +#include "cdefBF522.h" + +#if defined(CONFIG_BF527) +#include "cdefBF527.h" +#endif + +#if defined(CONFIG_BF525) +#include "cdefBF525.h" +#endif +#endif + +/* UART_IIR Register */ +#define STATUS(x) ((x << 1) & 0x06) +#define STATUS_P1 0x02 +#define STATUS_P0 0x01 + +/* DPMC*/ +#define bfin_read_STOPCK_OFF() bfin_read_STOPCK() +#define bfin_write_STOPCK_OFF(val) bfin_write_STOPCK(val) +#define STOPCK_OFF STOPCK + +/* PLL_DIV Masks */ +#define CCLK_DIV1 CSEL_DIV1 /* CCLK = VCO / 1 */ +#define CCLK_DIV2 CSEL_DIV2 /* CCLK = VCO / 2 */ +#define CCLK_DIV4 CSEL_DIV4 /* CCLK = VCO / 4 */ +#define CCLK_DIV8 CSEL_DIV8 /* CCLK = VCO / 8 */ + +#endif diff --git a/include/asm-blackfin/mach-bf527/cdefBF52x_base.h b/include/asm-blackfin/mach-bf527/cdefBF52x_base.h index 5f801a0ef79..3f4de5d9d4c 100644 --- a/include/asm-blackfin/mach-bf527/cdefBF52x_base.h +++ b/include/asm-blackfin/mach-bf527/cdefBF52x_base.h @@ -45,8 +45,8 @@ #define bfin_write_PLL_STAT(val) bfin_write16(PLL_STAT, val) #define bfin_read_PLL_LOCKCNT() bfin_read16(PLL_LOCKCNT) #define bfin_write_PLL_LOCKCNT(val) bfin_write16(PLL_LOCKCNT, val) -#define bfin_read_CHIPID() bfin_read16(CHIPID) -#define bfin_write_CHIPID(val) bfin_write16(CHIPID, val) +#define bfin_read_CHIPID() bfin_read32(CHIPID) +#define bfin_write_CHIPID(val) bfin_write32(CHIPID, val) /* System Interrupt Controller (0xFFC00100 - 0xFFC001FF) */ @@ -59,9 +59,8 @@ #define bfin_write_SIC_RVECT(val) bfin_write32(SIC_RVECT, val) #define bfin_read_SIC_IMASK0() bfin_read32(SIC_IMASK0) #define bfin_write_SIC_IMASK0(val) bfin_write32(SIC_IMASK0, val) -/* legacy register name (below) provided for backwards code compatibility */ -#define bfin_read_SIC_IMASK() bfin_read32(SIC_IMASK) -#define bfin_write_SIC_IMASK(val) bfin_write32(SIC_IMASK, val) +#define bfin_read_SIC_IMASK(x) bfin_read32(SIC_IMASK0 + (x << 6)) +#define bfin_write_SIC_IMASK(x, val) bfin_write32((SIC_IMASK0 + (x << 6)), val) #define bfin_read_SIC_IAR0() bfin_read32(SIC_IAR0) #define bfin_write_SIC_IAR0(val) bfin_write32(SIC_IAR0, val) @@ -74,15 +73,13 @@ #define bfin_read_SIC_ISR0() bfin_read32(SIC_ISR0) #define bfin_write_SIC_ISR0(val) bfin_write32(SIC_ISR0, val) -/* legacy register name (below) provided for backwards code compatibility */ -#define bfin_read_SIC_ISR() bfin_read32(SIC_ISR) -#define bfin_write_SIC_ISR(val) bfin_write32(SIC_ISR, val) +#define bfin_read_SIC_ISR(x) bfin_read32(SIC_ISR0 + (x << 6)) +#define bfin_write_SIC_ISR(x, val) bfin_write32((SIC_ISR0 + (x << 6)), val) #define bfin_read_SIC_IWR0() bfin_read32(SIC_IWR0) #define bfin_write_SIC_IWR0(val) bfin_write32(SIC_IWR0, val) -/* legacy register name (below) provided for backwards code compatibility */ -#define bfin_read_SIC_IWR() bfin_read32(SIC_IWR) -#define bfin_write_SIC_IWR(val) bfin_write32(SIC_IWR, val) +#define bfin_read_SIC_IWR(x) bfin_read32(SIC_IWR0 + (x << 6)) +#define bfin_write_SIC_IWR(x, val) bfin_write32((SIC_IWR0 + (x << 6)), val) /* SIC Additions to ADSP-BF52x (0xFFC0014C - 0xFFC00162) */ diff --git a/include/asm-blackfin/mach-bf527/defBF527.h b/include/asm-blackfin/mach-bf527/defBF527.h index 2be3293f9e2..82134f578f3 100644 --- a/include/asm-blackfin/mach-bf527/defBF527.h +++ b/include/asm-blackfin/mach-bf527/defBF527.h @@ -32,12 +32,12 @@ #define _DEF_BF527_H /* Include all Core registers and bit definitions */ -#include <def_LPBlackfin.h> +#include <asm/mach-common/def_LPBlackfin.h> /* SYSTEM & MMR ADDRESS DEFINITIONS FOR ADSP-BF527 */ /* Include defBF52x_base.h for the set of #defines that are common to all ADSP-BF52x processors */ -#include <defBF52x_base.h> +#include "defBF52x_base.h" /* The following are the #defines needed by ADSP-BF527 that are not in the common header */ /* 10/100 Ethernet Controller (0xFFC03000 - 0xFFC031FF) */ diff --git a/include/asm-blackfin/mach-bf527/defBF52x_base.h b/include/asm-blackfin/mach-bf527/defBF52x_base.h index b1ff67db01f..d6c24c54699 100644 --- a/include/asm-blackfin/mach-bf527/defBF52x_base.h +++ b/include/asm-blackfin/mach-bf527/defBF52x_base.h @@ -52,13 +52,13 @@ #define SYSCR 0xFFC00104 /* System Configuration Register */ #define SIC_RVECT 0xFFC00108 /* Interrupt Reset Vector Address Register */ -#define SIC_IMASK 0xFFC0010C /* Interrupt Mask Register */ +#define SIC_IMASK0 0xFFC0010C /* Interrupt Mask Register */ #define SIC_IAR0 0xFFC00110 /* Interrupt Assignment Register 0 */ #define SIC_IAR1 0xFFC00114 /* Interrupt Assignment Register 1 */ #define SIC_IAR2 0xFFC00118 /* Interrupt Assignment Register 2 */ #define SIC_IAR3 0xFFC0011C /* Interrupt Assignment Register 3 */ -#define SIC_ISR 0xFFC00120 /* Interrupt Status Register */ -#define SIC_IWR 0xFFC00124 /* Interrupt Wakeup Register */ +#define SIC_ISR0 0xFFC00120 /* Interrupt Status Register */ +#define SIC_IWR0 0xFFC00124 /* Interrupt Wakeup Register */ /* SIC Additions to ADSP-BF52x (0xFFC0014C - 0xFFC00162) */ #define SIC_IMASK1 0xFFC0014C /* Interrupt Mask register of SIC2 */ @@ -691,6 +691,8 @@ /* ************* SYSTEM INTERRUPT CONTROLLER MASKS *************************************/ /* Peripheral Masks For SIC_ISR, SIC_IWR, SIC_IMASK */ + +#if 0 #define IRQ_PLL_WAKEUP 0x00000001 /* PLL Wakeup Interrupt */ #define IRQ_ERROR1 0x00000002 /* Error Interrupt (DMA, DMARx Block, DMARx Overflow) */ @@ -732,6 +734,7 @@ #define IRQ_DMA15 0x40000000 /* DMA Channels 15 (MDMA0 Destination) TX Interrupt */ #define IRQ_WDOG 0x80000000 /* Software Watchdog Timer Interrupt */ #define IRQ_PFB_PORTG 0x10000000 /* PF Port G (PF31:16) Interrupt B */ +#endif /* SIC_IAR0 Macros */ #define P0_IVG(x) (((x)&0xF)-7) /* Peripheral #0 assigned IVG #x */ diff --git a/include/asm-blackfin/mach-bf527/dma.h b/include/asm-blackfin/mach-bf527/dma.h new file mode 100644 index 00000000000..a41627ae913 --- /dev/null +++ b/include/asm-blackfin/mach-bf527/dma.h @@ -0,0 +1,60 @@ +/* + * file: include/asm-blackfin/mach-bf527/dma.h + * based on: include/asm-blackfin/mach-bf537/dma.h + * author: Michael Hennerich (michael.hennerich@analog.com) + * + * created: + * description: + * system DMA map + * rev: + * + * modified: + * + * + * bugs: enter bugs at http://blackfin.uclinux.org/ + * + * 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, 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; see the file copying. + * if not, write to the free software foundation, + * 59 temple place - suite 330, boston, ma 02111-1307, usa. + */ + +#ifndef _MACH_DMA_H_ +#define _MACH_DMA_H_ + +#define MAX_BLACKFIN_DMA_CHANNEL 16 + +#define CH_PPI 0 /* PPI receive/transmit or NFC */ +#define CH_NFC 0 /* PPI receive/transmit or NFC */ +#define CH_EMAC_RX 1 /* Ethernet MAC receive or HOSTDP */ +#define CH_EMAC_HOSTDP 1 /* Ethernet MAC receive or HOSTDP */ +#define CH_EMAC_TX 2 /* Ethernet MAC transmit or NFC */ +#define CH_SPORT0_RX 3 /* SPORT0 receive */ +#define CH_SPORT0_TX 4 /* SPORT0 transmit */ +#define CH_SPORT1_RX 5 /* SPORT1 receive */ +#define CH_SPORT1_TX 6 /* SPORT1 transmit */ +#define CH_SPI 7 /* SPI transmit/receive */ +#define CH_UART0_RX 8 /* UART0 receive */ +#define CH_UART0_TX 9 /* UART0 transmit */ +#define CH_UART1_RX 10 /* UART1 receive */ +#define CH_UART1_TX 11 /* UART1 transmit */ + +#define CH_MEM_STREAM0_DEST 12 /* TX */ +#define CH_MEM_STREAM0_SRC 13 /* RX */ +#define CH_MEM_STREAM1_DEST 14 /* TX */ +#define CH_MEM_STREAM1_SRC 15 /* RX */ + +extern int channel2irq(unsigned int channel); +extern struct dma_register *base_addr[]; + +#endif diff --git a/include/asm-blackfin/mach-bf527/irq.h b/include/asm-blackfin/mach-bf527/irq.h new file mode 100644 index 00000000000..304f5bcfebe --- /dev/null +++ b/include/asm-blackfin/mach-bf527/irq.h @@ -0,0 +1,263 @@ +/* + * file: include/asm-blackfin/mach-bf527/irq.h + * based on: include/asm-blackfin/mach-bf537/irq.h + * author: Michael Hennerich (michael.hennerich@analog.com) + * + * created: + * description: + * system mmr register map + * rev: + * + * modified: + * + * + * bugs: enter bugs at http://blackfin.uclinux.org/ + * + * 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, 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; see the file copying. + * if not, write to the free software foundation, + * 59 temple place - suite 330, boston, ma 02111-1307, usa. + */ + +#ifndef _BF527_IRQ_H_ +#define _BF527_IRQ_H_ + +/* + * Interrupt source definitions + Event Source Core Event Name + Core Emulation ** + Events (highest priority) EMU 0 + Reset RST 1 + NMI NMI 2 + Exception EVX 3 + Reserved -- 4 + Hardware Error IVHW 5 + Core Timer IVTMR 6 * + + ..... + + Software Interrupt 1 IVG14 31 + Software Interrupt 2 -- + (lowest priority) IVG15 32 * +*/ + +#define NR_PERI_INTS (2 * 32) + +/* The ABSTRACT IRQ definitions */ +/** the first seven of the following are fixed, the rest you change if you need to **/ +#define IRQ_EMU 0 /* Emulation */ +#define IRQ_RST 1 /* reset */ +#define IRQ_NMI 2 /* Non Maskable */ +#define IRQ_EVX 3 /* Exception */ +#define IRQ_UNUSED 4 /* - unused interrupt */ +#define IRQ_HWERR 5 /* Hardware Error */ +#define IRQ_CORETMR 6 /* Core timer */ + +#define BFIN_IRQ(x) ((x) + 7) + +#define IRQ_PLL_WAKEUP BFIN_IRQ(0) /* PLL Wakeup Interrupt */ +#define IRQ_DMA0_ERROR BFIN_IRQ(1) /* DMA Error 0 (generic) */ +#define IRQ_DMAR0_BLK BFIN_IRQ(2) /* DMAR0 Block Interrupt */ +#define IRQ_DMAR1_BLK BFIN_IRQ(3) /* DMAR1 Block Interrupt */ +#define IRQ_DMAR0_OVR BFIN_IRQ(4) /* DMAR0 Overflow Error */ +#define IRQ_DMAR1_OVR BFIN_IRQ(5) /* DMAR1 Overflow Error */ +#define IRQ_PPI_ERROR BFIN_IRQ(6) /* PPI Error */ +#define IRQ_MAC_ERROR BFIN_IRQ(7) /* MAC Status */ +#define IRQ_SPORT0_ERROR BFIN_IRQ(8) /* SPORT0 Status */ +#define IRQ_SPORT1_ERROR BFIN_IRQ(9) /* SPORT1 Status */ +#define IRQ_UART0_ERROR BFIN_IRQ(12) /* UART0 Status */ +#define IRQ_UART1_ERROR BFIN_IRQ(13) /* UART1 Status */ +#define IRQ_RTC BFIN_IRQ(14) /* RTC */ +#define IRQ_PPI BFIN_IRQ(15) /* DMA Channel 0 (PPI/NAND) */ +#define IRQ_SPORT0_RX BFIN_IRQ(16) /* DMA 3 Channel (SPORT0 RX) */ +#define IRQ_SPORT0_TX BFIN_IRQ(17) /* DMA 4 Channel (SPORT0 TX) */ +#define IRQ_SPORT1_RX BFIN_IRQ(18) /* DMA 5 Channel (SPORT1 RX) */ +#define IRQ_SPORT1_TX BFIN_IRQ(19) /* DMA 6 Channel (SPORT1 TX) */ +#define IRQ_TWI BFIN_IRQ(20) /* TWI */ +#define IRQ_SPI BFIN_IRQ(21) /* DMA 7 Channel (SPI) */ +#define IRQ_UART0_RX BFIN_IRQ(22) /* DMA8 Channel (UART0 RX) */ +#define IRQ_UART0_TX BFIN_IRQ(23) /* DMA9 Channel (UART0 TX) */ +#define IRQ_UART1_RX BFIN_IRQ(24) /* DMA10 Channel (UART1 RX) */ +#define IRQ_UART1_TX BFIN_IRQ(25) /* DMA11 Channel (UART1 TX) */ +#define IRQ_OPTSEC BFIN_IRQ(26) /* OTPSEC Interrupt */ +#define IRQ_CNT BFIN_IRQ(27) /* GP Counter */ +#define IRQ_MAC_RX BFIN_IRQ(28) /* DMA1 Channel (MAC RX/HDMA) */ +#define IRQ_PORTH_INTA BFIN_IRQ(29) /* Port H Interrupt A */ +#define IRQ_MAC_TX BFIN_IRQ(30) /* DMA2 Channel (MAC TX/NAND) */ +#define IRQ_NFC BFIN_IRQ(30) /* DMA2 Channel (MAC TX/NAND) */ +#define IRQ_PORTH_INTB BFIN_IRQ(31) /* Port H Interrupt B */ +#define IRQ_TMR0 BFIN_IRQ(32) /* Timer 0 */ +#define IRQ_TMR1 BFIN_IRQ(33) /* Timer 1 */ +#define IRQ_TMR2 BFIN_IRQ(34) /* Timer 2 */ +#define IRQ_TMR3 BFIN_IRQ(35) /* Timer 3 */ +#define IRQ_TMR4 BFIN_IRQ(36) /* Timer 4 */ +#define IRQ_TMR5 BFIN_IRQ(37) /* Timer 5 */ +#define IRQ_TMR6 BFIN_IRQ(38) /* Timer 6 */ +#define IRQ_TMR7 BFIN_IRQ(39) /* Timer 7 */ +#define IRQ_PORTG_INTA BFIN_IRQ(40) /* Port G Interrupt A */ +#define IRQ_PORTG_INTB BFIN_IRQ(41) /* Port G Interrupt B */ +#define IRQ_MEM_DMA0 BFIN_IRQ(42) /* MDMA Stream 0 */ +#define IRQ_MEM_DMA1 BFIN_IRQ(43) /* MDMA Stream 1 */ +#define IRQ_WATCH BFIN_IRQ(44) /* Software Watchdog Timer */ +#define IRQ_PORTF_INTA BFIN_IRQ(45) /* Port F Interrupt A */ +#define IRQ_PORTF_INTB BFIN_IRQ(46) /* Port F Interrupt B */ +#define IRQ_SPI_ERROR BFIN_IRQ(47) /* SPI Status */ +#define IRQ_NFC_ERROR BFIN_IRQ(48) /* NAND Error */ +#define IRQ_HDMA_ERROR BFIN_IRQ(49) /* HDMA Error */ +#define IRQ_HDMA BFIN_IRQ(50) /* HDMA (TFI) */ +#define IRQ_USB_EINT BFIN_IRQ(51) /* USB_EINT Interrupt */ +#define IRQ_USB_INT0 BFIN_IRQ(52) /* USB_INT0 Interrupt */ +#define IRQ_USB_INT1 BFIN_IRQ(53) /* USB_INT1 Interrupt */ +#define IRQ_USB_INT2 BFIN_IRQ(54) /* USB_INT2 Interrupt */ +#define IRQ_USB_DMA BFIN_IRQ(55) /* USB_DMAINT Interrupt */ + +#define SYS_IRQS BFIN_IRQ(63) /* 70 */ + +#define IRQ_PF0 71 +#define IRQ_PF1 72 +#define IRQ_PF2 73 +#define IRQ_PF3 74 +#define IRQ_PF4 75 +#define IRQ_PF5 76 +#define IRQ_PF6 77 +#define IRQ_PF7 78 +#define IRQ_PF8 79 +#define IRQ_PF9 80 +#define IRQ_PF10 81 +#define IRQ_PF11 82 +#define IRQ_PF12 83 +#define IRQ_PF13 84 +#define IRQ_PF14 85 +#define IRQ_PF15 86 + +#define IRQ_PG0 87 +#define IRQ_PG1 88 +#define IRQ_PG2 89 +#define IRQ_PG3 90 +#define IRQ_PG4 91 +#define IRQ_PG5 92 +#define IRQ_PG6 93 +#define IRQ_PG7 94 +#define IRQ_PG8 95 +#define IRQ_PG9 96 +#define IRQ_PG10 97 +#define IRQ_PG11 98 +#define IRQ_PG12 99 +#define IRQ_PG13 100 +#define IRQ_PG14 101 +#define IRQ_PG15 102 + +#define IRQ_PH0 103 +#define IRQ_PH1 104 +#define IRQ_PH2 105 +#define IRQ_PH3 106 +#define IRQ_PH4 107 +#define IRQ_PH5 108 +#define IRQ_PH6 109 +#define IRQ_PH7 110 +#define IRQ_PH8 111 +#define IRQ_PH9 112 +#define IRQ_PH10 113 +#define IRQ_PH11 114 +#define IRQ_PH12 115 +#define IRQ_PH13 116 +#define IRQ_PH14 117 +#define IRQ_PH15 118 + +#define GPIO_IRQ_BASE IRQ_PF0 + +#ifdef CONFIG_IRQCHIP_DEMUX_GPIO +#define NR_IRQS (IRQ_PH15+1) +#else +#define NR_IRQS (SYS_IRQS+1) +#endif + +#define IVG7 7 +#define IVG8 8 +#define IVG9 9 +#define IVG10 10 +#define IVG11 11 +#define IVG12 12 +#define IVG13 13 +#define IVG14 14 +#define IVG15 15 + +/* IAR0 BIT FIELDS */ +#define IRQ_PLL_WAKEUP_POS 0 +#define IRQ_DMA0_ERROR_POS 4 +#define IRQ_DMAR0_BLK_POS 8 +#define IRQ_DMAR1_BLK_POS 12 +#define IRQ_DMAR0_OVR_POS 16 +#define IRQ_DMAR1_OVR_POS 20 +#define IRQ_PPI_ERROR_POS 24 +#define IRQ_MAC_ERROR_POS 28 + +/* IAR1 BIT FIELDS */ +#define IRQ_SPORT0_ERROR_POS 0 +#define IRQ_SPORT1_ERROR_POS 4 +#define IRQ_UART0_ERROR_POS 16 +#define IRQ_UART1_ERROR_POS 20 +#define IRQ_RTC_POS 24 +#define IRQ_PPI_POS 28 + +/* IAR2 BIT FIELDS */ +#define IRQ_SPORT0_RX_POS 0 +#define IRQ_SPORT0_TX_POS 4 +#define IRQ_SPORT1_RX_POS 8 +#define IRQ_SPORT1_TX_POS 12 +#define IRQ_TWI_POS 16 +#define IRQ_SPI_POS 20 +#define IRQ_UART0_RX_POS 24 +#define IRQ_UART0_TX_POS 28 + +/* IAR3 BIT FIELDS */ +#define IRQ_UART1_RX_POS 0 +#define IRQ_UART1_TX_POS 4 +#define IRQ_OPTSEC_POS 8 +#define IRQ_CNT_POS 12 +#define IRQ_MAC_RX_POS 16 +#define IRQ_PORTH_INTA_POS 20 +#define IRQ_MAC_TX_POS 24 +#define IRQ_PORTH_INTB_POS 28 + +/* IAR4 BIT FIELDS */ +#define IRQ_TMR0_POS 0 +#define IRQ_TMR1_POS 4 +#define IRQ_TMR2_POS 8 +#define IRQ_TMR3_POS 12 +#define IRQ_TMR4_POS 16 +#define IRQ_TMR5_POS 20 +#define IRQ_TMR6_POS 24 +#define IRQ_TMR7_POS 28 + +/* IAR5 BIT FIELDS */ +#define IRQ_PORTG_INTA_POS 0 +#define IRQ_PORTG_INTB_POS 4 +#define IRQ_MEM_DMA0_POS 8 +#define IRQ_MEM_DMA1_POS 12 +#define IRQ_WATCH_POS 16 +#define IRQ_PORTF_INTA_POS 20 +#define IRQ_PORTF_INTB_POS 24 +#define IRQ_SPI_ERROR_POS 28 + +/* IAR6 BIT FIELDS */ +#define IRQ_NFC_ERROR_POS 0 +#define IRQ_HDMA_ERROR_POS 4 +#define IRQ_HDMA_POS 8 +#define IRQ_USB_EINT_POS 12 +#define IRQ_USB_INT0_POS 16 +#define IRQ_USB_INT1_POS 20 +#define IRQ_USB_INT2_POS 24 +#define IRQ_USB_DMA_POS 28 + +#endif /* _BF527_IRQ_H_ */ diff --git a/include/asm-blackfin/mach-bf527/mem_init.h b/include/asm-blackfin/mach-bf527/mem_init.h new file mode 100644 index 00000000000..008ca66719e --- /dev/null +++ b/include/asm-blackfin/mach-bf527/mem_init.h @@ -0,0 +1,337 @@ +/* + * File: include/asm-blackfin/mach-bf527/mem_init.h + * Based on: + * Author: + * + * Created: + * Description: + * + * Rev: + * + * Modified: + * Copyright 2004-2007 Analog Devices Inc. + * + * Bugs: Enter bugs at http://blackfin.uclinux.org/ + * + * 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, 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; see the file COPYING. + * If not, write to the Free Software Foundation, + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#if (CONFIG_MEM_MT48LC16M16A2TG_75 || CONFIG_MEM_MT48LC64M4A2FB_7E || CONFIG_MEM_MT48LC16M8A2TG_75 || CONFIG_MEM_GENERIC_BOARD || CONFIG_MEM_MT48LC32M8A2_75 || CONFIG_MEM_MT48LC32M16A2TG_75) +#if (CONFIG_SCLK_HZ > 119402985) +#define SDRAM_tRP TRP_2 +#define SDRAM_tRP_num 2 +#define SDRAM_tRAS TRAS_7 +#define SDRAM_tRAS_num 7 +#define SDRAM_tRCD TRCD_2 +#define SDRAM_tWR TWR_2 +#endif +#if (CONFIG_SCLK_HZ > 104477612) && (CONFIG_SCLK_HZ <= 119402985) +#define SDRAM_tRP TRP_2 +#define SDRAM_tRP_num 2 +#define SDRAM_tRAS TRAS_6 +#define SDRAM_tRAS_num 6 +#define SDRAM_tRCD TRCD_2 +#define SDRAM_tWR TWR_2 +#endif +#if (CONFIG_SCLK_HZ > 89552239) && (CONFIG_SCLK_HZ <= 104477612) +#define SDRAM_tRP TRP_2 +#define SDRAM_tRP_num 2 +#define SDRAM_tRAS TRAS_5 +#define SDRAM_tRAS_num 5 +#define SDRAM_tRCD TRCD_2 +#define SDRAM_tWR TWR_2 +#endif +#if (CONFIG_SCLK_HZ > 74626866) && (CONFIG_SCLK_HZ <= 89552239) +#define SDRAM_tRP TRP_2 +#define SDRAM_tRP_num 2 +#define SDRAM_tRAS TRAS_4 +#define SDRAM_tRAS_num 4 +#define SDRAM_tRCD TRCD_2 +#define SDRAM_tWR TWR_2 +#endif +#if (CONFIG_SCLK_HZ > 66666667) && (CONFIG_SCLK_HZ <= 74626866) +#define SDRAM_tRP TRP_2 +#define SDRAM_tRP_num 2 +#define SDRAM_tRAS TRAS_3 +#define SDRAM_tRAS_num 3 +#define SDRAM_tRCD TRCD_2 +#define SDRAM_tWR TWR_2 +#endif +#if (CONFIG_SCLK_HZ > 59701493) && (CONFIG_SCLK_HZ <= 66666667) +#define SDRAM_tRP TRP_1 +#define SDRAM_tRP_num 1 +#define SDRAM_tRAS TRAS_4 +#define SDRAM_tRAS_num 3 +#define SDRAM_tRCD TRCD_1 +#define SDRAM_tWR TWR_2 +#endif +#if (CONFIG_SCLK_HZ > 44776119) && (CONFIG_SCLK_HZ <= 59701493) +#define SDRAM_tRP TRP_1 +#define SDRAM_tRP_num 1 +#define SDRAM_tRAS TRAS_3 +#define SDRAM_tRAS_num 3 +#define SDRAM_tRCD TRCD_1 +#define SDRAM_tWR TWR_2 +#endif +#if (CONFIG_SCLK_HZ > 29850746) && (CONFIG_SCLK_HZ <= 44776119) +#define SDRAM_tRP TRP_1 +#define SDRAM_tRP_num 1 +#define SDRAM_tRAS TRAS_2 +#define SDRAM_tRAS_num 2 +#define SDRAM_tRCD TRCD_1 +#define SDRAM_tWR TWR_2 +#endif +#if (CONFIG_SCLK_HZ <= 29850746) +#define SDRAM_tRP TRP_1 +#define SDRAM_tRP_num 1 +#define SDRAM_tRAS TRAS_1 +#define SDRAM_tRAS_num 1 +#define SDRAM_tRCD TRCD_1 +#define SDRAM_tWR TWR_2 +#endif +#endif + +#if (CONFIG_MEM_MT48LC16M16A2TG_75) + /*SDRAM INFORMATION: */ +#define SDRAM_Tref 64 /* Refresh period in milliseconds */ +#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */ +#define SDRAM_CL CL_3 +#endif + +#if (CONFIG_MEM_MT48LC16M8A2TG_75) + /*SDRAM INFORMATION: */ +#define SDRAM_Tref 64 /* Refresh period in milliseconds */ +#define SDRAM_NRA 4096 /* Number of row addresses in SDRAM */ +#define SDRAM_CL CL_3 +#endif + +#if (CONFIG_MEM_MT48LC32M8A2_75) + /*SDRAM INFORMATION: */ +#define SDRAM_Tref 64 /* Refresh period in milliseconds */ +#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */ +#define SDRAM_CL CL_3 +#endif + +#if (CONFIG_MEM_MT48LC64M4A2FB_7E) + /*SDRAM INFORMATION: */ +#define SDRAM_Tref 64 /* Refresh period in milliseconds */ +#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */ +#define SDRAM_CL CL_3 +#endif + +#if (CONFIG_MEM_GENERIC_BOARD) + /*SDRAM INFORMATION: Modify this for your board */ +#define SDRAM_Tref 64 /* Refresh period in milliseconds */ +#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */ +#define SDRAM_CL CL_3 +#endif + +#if (CONFIG_MEM_MT48LC32M16A2TG_75) + /*SDRAM INFORMATION: */ +#define SDRAM_Tref 64 /* Refresh period in milliseconds */ +#define SDRAM_NRA 8192 /* Number of row addresses in SDRAM */ +#define SDRAM_CL CL_3 +#endif + +#if (CONFIG_MEM_SIZE == 128) +#define SDRAM_SIZE EBSZ_128 +#endif +#if (CONFIG_MEM_SIZE == 64) +#define SDRAM_SIZE EBSZ_64 +#endif +#if (CONFIG_MEM_SIZE == 32) +#define SDRAM_SIZE EBSZ_32 +#endif +#if (CONFIG_MEM_SIZE == 16) +#define SDRAM_SIZE EBSZ_16 +#endif +#if (CONFIG_MEM_ADD_WIDTH == 11) +#define SDRAM_WIDTH EBCAW_11 +#endif +#if (CONFIG_MEM_ADD_WIDTH == 10) +#define SDRAM_WIDTH EBCAW_10 +#endif +#if (CONFIG_MEM_ADD_WIDTH == 9) +#define SDRAM_WIDTH EBCAW_9 +#endif +#if (CONFIG_MEM_ADD_WIDTH == 8) +#define SDRAM_WIDTH EBCAW_8 +#endif + +#define mem_SDBCTL (SDRAM_WIDTH | SDRAM_SIZE | EBE) + +/* Equation from section 17 (p17-46) of BF533 HRM */ +#define mem_SDRRC (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num) + +/* Enable SCLK Out */ +#define mem_SDGCTL (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS) + +#if defined CONFIG_CLKIN_HALF +#define CLKIN_HALF 1 +#else +#define CLKIN_HALF 0 +#endif + +#if defined CONFIG_PLL_BYPASS +#define PLL_BYPASS 1 +#else +#define PLL_BYPASS 0 +#endif + +/***************************************Currently Not Being Used *********************************/ +#define flash_EBIU_AMBCTL_WAT ((CONFIG_FLASH_SPEED_BWAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1 +#define flash_EBIU_AMBCTL_RAT ((CONFIG_FLASH_SPEED_BRAT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1 +#define flash_EBIU_AMBCTL_HT ((CONFIG_FLASH_SPEED_BHT * 4) / (4000000000 / CONFIG_SCLK_HZ)) +#define flash_EBIU_AMBCTL_ST ((CONFIG_FLASH_SPEED_BST * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1 +#define flash_EBIU_AMBCTL_TT ((CONFIG_FLASH_SPEED_BTT * 4) / (4000000000 / CONFIG_SCLK_HZ)) + 1 + +#if (flash_EBIU_AMBCTL_TT > 3) +#define flash_EBIU_AMBCTL0_TT B0TT_4 +#endif +#if (flash_EBIU_AMBCTL_TT == 3) +#define flash_EBIU_AMBCTL0_TT B0TT_3 +#endif +#if (flash_EBIU_AMBCTL_TT == 2) +#define flash_EBIU_AMBCTL0_TT B0TT_2 +#endif +#if (flash_EBIU_AMBCTL_TT < 2) +#define flash_EBIU_AMBCTL0_TT B0TT_1 +#endif + +#if (flash_EBIU_AMBCTL_ST > 3) +#define flash_EBIU_AMBCTL0_ST B0ST_4 +#endif +#if (flash_EBIU_AMBCTL_ST == 3) +#define flash_EBIU_AMBCTL0_ST B0ST_3 +#endif +#if (flash_EBIU_AMBCTL_ST == 2) +#define flash_EBIU_AMBCTL0_ST B0ST_2 +#endif +#if (flash_EBIU_AMBCTL_ST < 2) +#define flash_EBIU_AMBCTL0_ST B0ST_1 +#endif + +#if (flash_EBIU_AMBCTL_HT > 2) +#define flash_EBIU_AMBCTL0_HT B0HT_3 +#endif +#if (flash_EBIU_AMBCTL_HT == 2) +#define flash_EBIU_AMBCTL0_HT B0HT_2 +#endif +#if (flash_EBIU_AMBCTL_HT == 1) +#define flash_EBIU_AMBCTL0_HT B0HT_1 +#endif +#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT == 0) +#define flash_EBIU_AMBCTL0_HT B0HT_0 +#endif +#if (flash_EBIU_AMBCTL_HT == 0 && CONFIG_FLASH_SPEED_BHT != 0) +#define flash_EBIU_AMBCTL0_HT B0HT_1 +#endif + +#if (flash_EBIU_AMBCTL_WAT > 14) +#define flash_EBIU_AMBCTL0_WAT B0WAT_15 +#endif +#if (flash_EBIU_AMBCTL_WAT == 14) +#define flash_EBIU_AMBCTL0_WAT B0WAT_14 +#endif +#if (flash_EBIU_AMBCTL_WAT == 13) +#define flash_EBIU_AMBCTL0_WAT B0WAT_13 +#endif +#if (flash_EBIU_AMBCTL_WAT == 12) +#define flash_EBIU_AMBCTL0_WAT B0WAT_12 +#endif +#if (flash_EBIU_AMBCTL_WAT == 11) +#define flash_EBIU_AMBCTL0_WAT B0WAT_11 +#endif +#if (flash_EBIU_AMBCTL_WAT == 10) +#define flash_EBIU_AMBCTL0_WAT B0WAT_10 +#endif +#if (flash_EBIU_AMBCTL_WAT == 9) +#define flash_EBIU_AMBCTL0_WAT B0WAT_9 +#endif +#if (flash_EBIU_AMBCTL_WAT == 8) +#define flash_EBIU_AMBCTL0_WAT B0WAT_8 +#endif +#if (flash_EBIU_AMBCTL_WAT == 7) +#define flash_EBIU_AMBCTL0_WAT B0WAT_7 +#endif +#if (flash_EBIU_AMBCTL_WAT == 6) +#define flash_EBIU_AMBCTL0_WAT B0WAT_6 +#endif +#if (flash_EBIU_AMBCTL_WAT == 5) +#define flash_EBIU_AMBCTL0_WAT B0WAT_5 +#endif +#if (flash_EBIU_AMBCTL_WAT == 4) +#define flash_EBIU_AMBCTL0_WAT B0WAT_4 +#endif +#if (flash_EBIU_AMBCTL_WAT == 3) +#define flash_EBIU_AMBCTL0_WAT B0WAT_3 +#endif +#if (flash_EBIU_AMBCTL_WAT == 2) +#define flash_EBIU_AMBCTL0_WAT B0WAT_2 +#endif +#if (flash_EBIU_AMBCTL_WAT == 1) +#define flash_EBIU_AMBCTL0_WAT B0WAT_1 +#endif + +#if (flash_EBIU_AMBCTL_RAT > 14) +#define flash_EBIU_AMBCTL0_RAT B0RAT_15 +#endif +#if (flash_EBIU_AMBCTL_RAT == 14) +#define flash_EBIU_AMBCTL0_RAT B0RAT_14 +#endif +#if (flash_EBIU_AMBCTL_RAT == 13) +#define flash_EBIU_AMBCTL0_RAT B0RAT_13 +#endif +#if (flash_EBIU_AMBCTL_RAT == 12) +#define flash_EBIU_AMBCTL0_RAT B0RAT_12 +#endif +#if (flash_EBIU_AMBCTL_RAT == 11) +#define flash_EBIU_AMBCTL0_RAT B0RAT_11 +#endif +#if (flash_EBIU_AMBCTL_RAT == 10) +#define flash_EBIU_AMBCTL0_RAT B0RAT_10 +#endif +#if (flash_EBIU_AMBCTL_RAT == 9) +#define flash_EBIU_AMBCTL0_RAT B0RAT_9 +#endif +#if (flash_EBIU_AMBCTL_RAT == 8) +#define flash_EBIU_AMBCTL0_RAT B0RAT_8 +#endif +#if (flash_EBIU_AMBCTL_RAT == 7) +#define flash_EBIU_AMBCTL0_RAT B0RAT_7 +#endif +#if (flash_EBIU_AMBCTL_RAT == 6) +#define flash_EBIU_AMBCTL0_RAT B0RAT_6 +#endif +#if (flash_EBIU_AMBCTL_RAT == 5) +#define flash_EBIU_AMBCTL0_RAT B0RAT_5 +#endif +#if (flash_EBIU_AMBCTL_RAT == 4) +#define flash_EBIU_AMBCTL0_RAT B0RAT_4 +#endif +#if (flash_EBIU_AMBCTL_RAT == 3) +#define flash_EBIU_AMBCTL0_RAT B0RAT_3 +#endif +#if (flash_EBIU_AMBCTL_RAT == 2) +#define flash_EBIU_AMBCTL0_RAT B0RAT_2 +#endif +#if (flash_EBIU_AMBCTL_RAT == 1) +#define flash_EBIU_AMBCTL0_RAT B0RAT_1 +#endif + +#define flash_EBIU_AMBCTL0 \ + (flash_EBIU_AMBCTL0_WAT | flash_EBIU_AMBCTL0_RAT | flash_EBIU_AMBCTL0_HT | \ + flash_EBIU_AMBCTL0_ST | flash_EBIU_AMBCTL0_TT | CONFIG_FLASH_SPEED_RDYEN) diff --git a/include/asm-blackfin/mach-bf527/mem_map.h b/include/asm-blackfin/mach-bf527/mem_map.h new file mode 100644 index 00000000000..c5aa20102b2 --- /dev/null +++ b/include/asm-blackfin/mach-bf527/mem_map.h @@ -0,0 +1,98 @@ +/* + * file: include/asm-blackfin/mach-bf527/mem_map.h + * based on: include/asm-blackfin/mach-bf537/mem_map.h + * author: Michael Hennerich (michael.hennerich@analog.com) + * + * created: + * description: + * Memory MAP Common header file for blackfin BF527/5/2 of processors. + * rev: + * + * modified: + * + * bugs: enter bugs at http://blackfin.uclinux.org/ + * + * 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, 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; see the file copying. + * if not, write to the free software foundation, + * 59 temple place - suite 330, boston, ma 02111-1307, usa. + */ + +#ifndef _MEM_MAP_527_H_ +#define _MEM_MAP_527_H_ + +#define COREMMR_BASE 0xFFE00000 /* Core MMRs */ +#define SYSMMR_BASE 0xFFC00000 /* System MMRs */ + +/* Async Memory Banks */ +#define ASYNC_BANK3_BASE 0x20300000 /* Async Bank 3 */ +#define ASYNC_BANK3_SIZE 0x00100000 /* 1M */ +#define ASYNC_BANK2_BASE 0x20200000 /* Async Bank 2 */ +#define ASYNC_BANK2_SIZE 0x00100000 /* 1M */ +#define ASYNC_BANK1_BASE 0x20100000 /* Async Bank 1 */ +#define ASYNC_BANK1_SIZE 0x00100000 /* 1M */ +#define ASYNC_BANK0_BASE 0x20000000 /* Async Bank 0 */ +#define ASYNC_BANK0_SIZE 0x00100000 /* 1M */ + +/* Boot ROM Memory */ + +#define BOOT_ROM_START 0xEF000000 + +/* Level 1 Memory */ + +/* Memory Map for ADSP-BF527 ADSP-BF525 ADSP-BF522 processors */ + +#ifdef CONFIG_BFIN_ICACHE +#define BFIN_ICACHESIZE (16*1024) +#else +#define BFIN_ICACHESIZE (0*1024) +#endif + +#define L1_CODE_START 0xFFA00000 +#define L1_DATA_A_START 0xFF800000 +#define L1_DATA_B_START 0xFF900000 + +#define L1_CODE_LENGTH 0xC000 + +#ifdef CONFIG_BFIN_DCACHE + +#ifdef CONFIG_BFIN_DCACHE_BANKA +#define DMEM_CNTR (ACACHE_BSRAM | ENDCPLB | PORT_PREF0) +#define L1_DATA_A_LENGTH (0x8000 - 0x4000) +#define L1_DATA_B_LENGTH 0x8000 +#define BFIN_DCACHESIZE (16*1024) +#define BFIN_DSUPBANKS 1 +#else +#define DMEM_CNTR (ACACHE_BCACHE | ENDCPLB | PORT_PREF0) +#define L1_DATA_A_LENGTH (0x8000 - 0x4000) +#define L1_DATA_B_LENGTH (0x8000 - 0x4000) +#define BFIN_DCACHESIZE (32*1024) +#define BFIN_DSUPBANKS 2 +#endif + +#else +#define DMEM_CNTR (ASRAM_BSRAM | ENDCPLB | PORT_PREF0) +#define L1_DATA_A_LENGTH 0x8000 +#define L1_DATA_B_LENGTH 0x8000 +#define BFIN_DCACHESIZE (0*1024) +#define BFIN_DSUPBANKS 0 +#endif /*CONFIG_BFIN_DCACHE */ + +/* Scratch Pad Memory */ + +#if defined(CONFIG_BF527) || defined(CONFIG_BF536) || defined(CONFIG_BF534) +#define L1_SCRATCH_START 0xFFB00000 +#define L1_SCRATCH_LENGTH 0x1000 +#endif + +#endif /* _MEM_MAP_527_H_ */ diff --git a/include/asm-blackfin/mach-bf527/portmux.h b/include/asm-blackfin/mach-bf527/portmux.h new file mode 100644 index 00000000000..dcf001adc63 --- /dev/null +++ b/include/asm-blackfin/mach-bf527/portmux.h @@ -0,0 +1,205 @@ +#ifndef _MACH_PORTMUX_H_ +#define _MACH_PORTMUX_H_ + +#define P_PPI0_D0 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(0)) +#define P_PPI0_D1 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(0)) +#define P_PPI0_D2 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(0)) +#define P_PPI0_D3 (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(0)) +#define P_PPI0_D4 (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(0)) +#define P_PPI0_D5 (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(0)) +#define P_PPI0_D6 (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(0)) +#define P_PPI0_D7 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(0)) +#define P_PPI0_D8 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(0)) +#define P_PPI0_D9 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(0)) +#define P_PPI0_D10 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(0)) +#define P_PPI0_D11 (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(0)) +#define P_PPI0_D12 (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(0)) +#define P_PPI0_D13 (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(0)) +#define P_PPI0_D14 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(0)) +#define P_PPI0_D15 (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(0)) + +#if defined(CONFIG_BF527_SPORT0_PORTF) +#define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1)) +#define P_SPORT0_RFS (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1)) +#define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1)) +#define P_SPORT0_DTPRI (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1)) +#define P_SPORT0_TFS (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1)) +#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1)) +#define P_SPORT0_DTSEC (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1)) +#define P_SPORT0_DRSEC (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1)) +#elif defined(CONFIG_BF527_SPORT0_PORTG) +#define P_SPORT0_DTPRI (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(0)) +#define P_SPORT0_DRSEC (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(1)) +#define P_SPORT0_DTSEC (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(1)) +#define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(1)) +#define P_SPORT0_RFS (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(1)) +#define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(1)) +#if defined(CONFIG_BF527_SPORT0_TSCLK_PG10) +#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(1)) +#elif defined(CONFIG_BF527_SPORT0_TSCLK_PG14) +#define P_SPORT0_TSCLK (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0)) +#endif +#define P_SPORT0_TFS (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0)) +#endif + +#define P_SPORT1_DRPRI (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1)) +#define P_SPORT1_RSCLK (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1)) +#define P_SPORT1_RFS (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(1)) +#define P_SPORT1_TFS (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(1)) +#define P_SPORT1_DTPRI (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(1)) +#define P_SPORT1_TSCLK (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(1)) +#define P_SPORT1_DTSEC (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1)) +#define P_SPORT1_DRSEC (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1)) + +#define P_SPI0_SSEL6 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(2)) +#define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(2)) + +#define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(2)) +#define P_SPI0_SSEL3 (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(2)) + +#if defined(CONFIG_BF527_UART1_PORTF) +#define P_UART1_TX (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(2)) +#define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(2)) +#elif defined(CONFIG_BF527_UART1_PORTG) +#define P_UART1_TX (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(1)) +#define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(1)) +#endif + +#define P_HWAIT (P_DONTCARE) + +#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0)) +#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2)) +#define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2)) +#define P_SPI0_MISO (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(2)) +#define P_SPI0_MOSI (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(2)) +#define P_TMR1 (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0)) +#define P_PPI0_FS2 (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0)) +#define P_TMR3 (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(0)) +#define P_TMR4 (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(0)) +#define P_TMR5 (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(0)) +#define P_TMR6 (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(0)) +/* #define P_TMR7 (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(0)) */ +#define P_DMAR1 (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(0)) +#define P_DMAR0 (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0)) +#define P_TMR2 (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(1)) +#define P_TMR7 (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(1)) +#define P_MDC (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(1)) +#define P_RMII0_MDINT (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(1)) +#define P_MII0_PHYINT (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(1)) + +#define P_PPI0_FS3 (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(2)) +#define P_UART0_TX (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(2)) +#define P_UART0_RX (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(2)) + +#define P_HOST_WR (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(2)) +#define P_HOST_ACK (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(2)) +#define P_HOST_ADDR (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(2)) +#define P_HOST_RD (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(2)) +#define P_HOST_CE (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(2)) + +#if defined(CONFIG_BF527_NAND_D_PORTF) +#define P_NAND_D0 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(2)) +#define P_NAND_D1 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(2)) +#define P_NAND_D2 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(2)) +#define P_NAND_D3 (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(2)) +#define P_NAND_D4 (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(2)) +#define P_NAND_D5 (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(2)) +#define P_NAND_D6 (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(2)) +#define P_NAND_D7 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(2)) +#elif defined(CONFIG_BF527_NAND_D_PORTH) +#define P_NAND_D0 (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(0)) +#define P_NAND_D1 (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(0)) +#define P_NAND_D2 (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(0)) +#define P_NAND_D3 (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(0)) +#define P_NAND_D4 (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(0)) +#define P_NAND_D5 (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(0)) +#define P_NAND_D6 (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(0)) +#define P_NAND_D7 (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(0)) +#endif + +#define P_SPI0_SSEL4 (P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(0)) +#define P_SPI0_SSEL5 (P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(0)) +#define P_NAND_CE (P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(0)) +#define P_NAND_WE (P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(0)) +#define P_NAND_RE (P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(0)) +#define P_NAND_RB (P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(0)) +#define P_NAND_CLE (P_DEFINED | P_IDENT(GPIO_PH14) | P_FUNCT(0)) +#define P_NAND_ALE (P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(0)) + +#define P_HOST_D0 (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(2)) +#define P_HOST_D1 (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(2)) +#define P_HOST_D2 (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(2)) +#define P_HOST_D3 (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(2)) +#define P_HOST_D4 (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(2)) +#define P_HOST_D5 (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(2)) +#define P_HOST_D6 (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(2)) +#define P_HOST_D7 (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(2)) +#define P_HOST_D8 (P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(2)) +#define P_HOST_D9 (P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(2)) +#define P_HOST_D10 (P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(2)) +#define P_HOST_D11 (P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(2)) +#define P_HOST_D12 (P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(2)) +#define P_HOST_D13 (P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(2)) +#define P_HOST_D14 (P_DEFINED | P_IDENT(GPIO_PH14) | P_FUNCT(2)) +#define P_HOST_D15 (P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(2)) + +#define P_MII0_ETxD0 (P_DEFINED | P_IDENT(GPIO_PH5) | P_FUNCT(1)) +#define P_MII0_ETxD1 (P_DEFINED | P_IDENT(GPIO_PH7) | P_FUNCT(1)) +#define P_MII0_ETxD2 (P_DEFINED | P_IDENT(GPIO_PH9) | P_FUNCT(1)) +#define P_MII0_ETxD3 (P_DEFINED | P_IDENT(GPIO_PH11) | P_FUNCT(1)) +#define P_MII0_ETxEN (P_DEFINED | P_IDENT(GPIO_PH3) | P_FUNCT(1)) +#define P_MII0_TxCLK (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(1)) +#define P_MII0_COL (P_DEFINED | P_IDENT(GPIO_PH15) | P_FUNCT(1)) +#define P_MII0_ERxD0 (P_DEFINED | P_IDENT(GPIO_PH6) | P_FUNCT(1)) +#define P_MII0_ERxD1 (P_DEFINED | P_IDENT(GPIO_PH8) | P_FUNCT(1)) +#define P_MII0_ERxD2 (P_DEFINED | P_IDENT(GPIO_PH10) | P_FUNCT(1)) +#define P_MII0_ERxD3 (P_DEFINED | P_IDENT(GPIO_PH12) | P_FUNCT(1)) +#define P_MII0_ERxDV (P_DEFINED | P_IDENT(GPIO_PH14) | P_FUNCT(1)) +#define P_MII0_ERxCLK (P_DEFINED | P_IDENT(GPIO_PH13) | P_FUNCT(1)) +#define P_MII0_ERxER (P_DEFINED | P_IDENT(GPIO_PH1) | P_FUNCT(1)) +#define P_MII0_CRS (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(1)) +#define P_RMII0_REF_CLK (P_DEFINED | P_IDENT(GPIO_PH4) | P_FUNCT(1)) +#define P_RMII0_CRS_DV (P_DEFINED | P_IDENT(GPIO_PH0) | P_FUNCT(1)) +#define P_MDIO (P_DEFINED | P_IDENT(GPIO_PH2) | P_FUNCT(1)) + +#define P_TWI0_SCL (P_DONTCARE) +#define P_TWI0_SDA (P_DONTCARE) +#define P_PPI0_FS1 (P_DONTCARE) +#define P_TMR0 (P_DONTCARE) +#define P_TMRCLK (P_DONTCARE) +#define P_PPI0_CLK (P_DONTCARE) + +#define P_MII0 {\ + P_MII0_ETxD0, \ + P_MII0_ETxD1, \ + P_MII0_ETxD2, \ + P_MII0_ETxD3, \ + P_MII0_ETxEN, \ + P_MII0_TxCLK, \ + P_MII0_PHYINT, \ + P_MII0_COL, \ + P_MII0_ERxD0, \ + P_MII0_ERxD1, \ + P_MII0_ERxD2, \ + P_MII0_ERxD3, \ + P_MII0_ERxDV, \ + P_MII0_ERxCLK, \ + P_MII0_ERxER, \ + P_MII0_CRS, \ + P_MDC, \ + P_MDIO, 0} + +#define P_RMII0 {\ + P_MII0_ETxD0, \ + P_MII0_ETxD1, \ + P_MII0_ETxEN, \ + P_MII0_ERxD0, \ + P_MII0_ERxD1, \ + P_MII0_ERxER, \ + P_RMII0_REF_CLK, \ + P_RMII0_MDINT, \ + P_RMII0_CRS_DV, \ + P_MDC, \ + P_MDIO, 0} + +#endif /* _MACH_PORTMUX_H_ */ diff --git a/include/asm-blackfin/mach-bf548/defBF549.h b/include/asm-blackfin/mach-bf548/defBF549.h index 50b3fe55ef0..4e46d657e50 100644 --- a/include/asm-blackfin/mach-bf548/defBF549.h +++ b/include/asm-blackfin/mach-bf548/defBF549.h @@ -1178,7 +1178,7 @@ /* Bit masks for HOST_STATUS */ -#define READY 0x1 /* DMA Ready */ +#define DMA_READY 0x1 /* DMA Ready */ #define FIFOFULL 0x2 /* FIFO Full */ #define FIFOEMPTY 0x4 /* FIFO Empty */ #define DMA_COMPLETE 0x8 /* DMA Complete */ diff --git a/include/asm-blackfin/mach-bf548/defBF54x_base.h b/include/asm-blackfin/mach-bf548/defBF54x_base.h index e2632db74ba..1d365c844ff 100644 --- a/include/asm-blackfin/mach-bf548/defBF54x_base.h +++ b/include/asm-blackfin/mach-bf548/defBF54x_base.h @@ -47,6 +47,10 @@ /* Debug/MP/Emulation Registers (0xFFC00014 - 0xFFC00014) */ #define CHIPID 0xffc00014 +/* CHIPID Masks */ +#define CHIPID_VERSION 0xF0000000 +#define CHIPID_FAMILY 0x0FFFF000 +#define CHIPID_MANUFACTURE 0x00000FFE /* System Reset and Interrupt Controller (0xFFC00100 - 0xFFC00104) */ @@ -3299,7 +3303,7 @@ #define MFD 0xf000 /* Multi channel Frame Delay */ #define FSDR 0x80 /* Frame Sync to Data Relationship */ -#define MCMEM 0x10 /* Multi channel Frame Mode Enable */ +#define MCMEN 0x10 /* Multi channel Frame Mode Enable */ #define MCDRXPE 0x8 /* Multi channel DMA Receive Packing */ #define MCDTXPE 0x4 /* Multi channel DMA Transmit Packing */ #define MCCRM 0x3 /* 2X Clock Recovery Mode */ diff --git a/include/asm-blackfin/mach-bf548/dma.h b/include/asm-blackfin/mach-bf548/dma.h index 14cb10cc24a..4d97d3aa97c 100644 --- a/include/asm-blackfin/mach-bf548/dma.h +++ b/include/asm-blackfin/mach-bf548/dma.h @@ -70,5 +70,5 @@ #define MAX_BLACKFIN_DMA_CHANNEL 32 extern int channel2irq(unsigned int channel); -extern struct dma_register *base_addr[]; +extern struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL]; #endif diff --git a/include/asm-blackfin/scatterlist.h b/include/asm-blackfin/scatterlist.h index 60e07b92044..32128d53469 100644 --- a/include/asm-blackfin/scatterlist.h +++ b/include/asm-blackfin/scatterlist.h @@ -4,7 +4,10 @@ #include <linux/mm.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; dma_addr_t dma_address; unsigned int length; diff --git a/include/asm-cris/scatterlist.h b/include/asm-cris/scatterlist.h index 4bdc44c4ac3..faff53ad1f9 100644 --- a/include/asm-cris/scatterlist.h +++ b/include/asm-cris/scatterlist.h @@ -2,11 +2,14 @@ #define __ASM_CRIS_SCATTERLIST_H struct scatterlist { +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif char * address; /* Location data is to be transferred to */ unsigned int length; /* The following is i386 highmem junk - not used by us */ - struct page * page; /* Location for highmem page, if any */ + unsigned long page_link; unsigned int offset;/* for highmem, page offset */ }; diff --git a/include/asm-frv/scatterlist.h b/include/asm-frv/scatterlist.h index 8e827fa853f..f7da007b763 100644 --- a/include/asm-frv/scatterlist.h +++ b/include/asm-frv/scatterlist.h @@ -22,7 +22,10 @@ * and that's it. There's no excuse for not highmem enabling YOUR driver. /jens */ struct scatterlist { - struct page *page; /* Location for highmem page, if any */ +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; /* for highmem, page offset */ dma_addr_t dma_address; diff --git a/include/asm-h8300/scatterlist.h b/include/asm-h8300/scatterlist.h index 985fdf54eac..d3ecdd87ac9 100644 --- a/include/asm-h8300/scatterlist.h +++ b/include/asm-h8300/scatterlist.h @@ -4,7 +4,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; dma_addr_t dma_address; unsigned int length; diff --git a/include/asm-ia64/scatterlist.h b/include/asm-ia64/scatterlist.h index 7d5234d5031..d6f57874041 100644 --- a/include/asm-ia64/scatterlist.h +++ b/include/asm-ia64/scatterlist.h @@ -9,7 +9,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; unsigned int length; /* buffer length */ diff --git a/include/asm-m32r/scatterlist.h b/include/asm-m32r/scatterlist.h index 352415ff5eb..1ed372c73d0 100644 --- a/include/asm-m32r/scatterlist.h +++ b/include/asm-m32r/scatterlist.h @@ -4,9 +4,12 @@ #include <asm/types.h> struct scatterlist { +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif char * address; /* Location data is to be transferred to, NULL for * highmem page */ - struct page * page; /* Location for highmem page, if any */ + unsigned long page_link; unsigned int offset;/* for highmem, page offset */ dma_addr_t dma_address; diff --git a/include/asm-m68k/scatterlist.h b/include/asm-m68k/scatterlist.h index 24887a2d9c7..d3a7a0edfec 100644 --- a/include/asm-m68k/scatterlist.h +++ b/include/asm-m68k/scatterlist.h @@ -4,7 +4,10 @@ #include <linux/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; unsigned int length; diff --git a/include/asm-m68knommu/scatterlist.h b/include/asm-m68knommu/scatterlist.h index 4da79d3d3f3..10942840e88 100644 --- a/include/asm-m68knommu/scatterlist.h +++ b/include/asm-m68knommu/scatterlist.h @@ -5,7 +5,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; dma_addr_t dma_address; unsigned int length; diff --git a/include/asm-mips/scatterlist.h b/include/asm-mips/scatterlist.h index 7af104c95b2..83d69fe17c9 100644 --- a/include/asm-mips/scatterlist.h +++ b/include/asm-mips/scatterlist.h @@ -4,7 +4,10 @@ #include <asm/types.h> struct scatterlist { - struct page * page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; dma_addr_t dma_address; unsigned int length; diff --git a/include/asm-parisc/Kbuild b/include/asm-parisc/Kbuild index c68e1680da0..f88b252e419 100644 --- a/include/asm-parisc/Kbuild +++ b/include/asm-parisc/Kbuild @@ -1 +1,3 @@ include include/asm-generic/Kbuild.asm + +unifdef-y += pdc.h diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h index 95f00e11c7b..55ddb184210 100644 --- a/include/asm-parisc/io.h +++ b/include/asm-parisc/io.h @@ -138,7 +138,7 @@ extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsign /* Most machines react poorly to I/O-space being cacheable... Instead let's * define ioremap() in terms of ioremap_nocache(). */ -extern inline void __iomem * ioremap(unsigned long offset, unsigned long size) +static inline void __iomem * ioremap(unsigned long offset, unsigned long size) { return __ioremap(offset, size, _PAGE_NO_CACHE); } diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h index f6bba4c1366..b59a1504fc7 100644 --- a/include/asm-parisc/page.h +++ b/include/asm-parisc/page.h @@ -3,6 +3,8 @@ #ifdef __KERNEL__ +#include <linux/const.h> + #if defined(CONFIG_PARISC_PAGE_SIZE_4KB) # define PAGE_SHIFT 12 #elif defined(CONFIG_PARISC_PAGE_SIZE_16KB) @@ -12,7 +14,7 @@ #else # error "unknown default kernel page size" #endif -#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h index 61fbd57a832..4ba868f44a5 100644 --- a/include/asm-parisc/pci.h +++ b/include/asm-parisc/pci.h @@ -207,7 +207,7 @@ extern struct pci_bios_ops *pci_bios; extern void pcibios_register_hba(struct pci_hba_data *); extern void pcibios_set_master(struct pci_dev *); #else -extern inline void pcibios_register_hba(struct pci_hba_data *x) +static inline void pcibios_register_hba(struct pci_hba_data *x) { } #endif diff --git a/include/asm-parisc/pdc.h b/include/asm-parisc/pdc.h index 876fd8116d4..5e0c3ca5450 100644 --- a/include/asm-parisc/pdc.h +++ b/include/asm-parisc/pdc.h @@ -1,7 +1,6 @@ #ifndef _PARISC_PDC_H #define _PARISC_PDC_H - /* * PDC return values ... * All PDC calls return a subset of these errors. @@ -20,7 +19,6 @@ #define PDC_BUS_POW_WARN -12 /* Call could not complete in allowed power budget */ #define PDC_NOT_NARROW -17 /* Narrow mode not supported */ - /* * PDC entry points... */ @@ -50,6 +48,12 @@ #define PDC_MODEL_DISPEC 5 /* disable specific option */ #define PDC_MODEL_CPU_ID 6 /* returns cpu-id (only newer machines!) */ #define PDC_MODEL_CAPABILITIES 7 /* returns OS32/OS64-flags */ +/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */ +#define PDC_MODEL_IOPDIR_FDC (1 << 2) +#define PDC_MODEL_NVA_MASK (3 << 4) +#define PDC_MODEL_NVA_SUPPORTED (0 << 4) +#define PDC_MODEL_NVA_SLOW (1 << 4) +#define PDC_MODEL_NVA_UNSUPPORTED (3 << 4) #define PDC_MODEL_GET_BOOT__OP 8 /* returns boot test options */ #define PDC_MODEL_SET_BOOT__OP 9 /* set boot test options */ @@ -91,7 +95,7 @@ #define PDC_TOD 9 /* time-of-day clock (TOD) */ #define PDC_TOD_READ 0 /* read TOD */ #define PDC_TOD_WRITE 1 /* write TOD */ -#define PDC_TOD_ITIMER 2 /* calibrate Interval Timer (CR16) */ + #define PDC_STABLE 10 /* stable storage (sprockets) */ #define PDC_STABLE_READ 0 @@ -143,15 +147,6 @@ #define PDC_MEM_RET_PDT_FULL -11 #define PDC_MEM_RET_INVALID_PHYSICAL_LOCATION ~0ULL -#ifndef __ASSEMBLY__ -typedef struct { - unsigned long long baseAddr; - unsigned int pages; - unsigned int reserved; -} MemAddrTable_t; -#endif - - #define PDC_PSW 21 /* Get/Set default System Mask */ #define PDC_PSW_MASK 0 /* Return mask */ #define PDC_PSW_GET_DEFAULTS 1 /* Return defaults */ @@ -274,6 +269,43 @@ typedef struct { #define PDC_LINK_PCI_ENTRY_POINTS 0 /* list (Arg1) = 0 */ #define PDC_LINK_USB_ENTRY_POINTS 1 /* list (Arg1) = 1 */ +/* cl_class + * page 3-33 of IO-Firmware ARS + * IODC ENTRY_INIT(Search first) RET[1] + */ +#define CL_NULL 0 /* invalid */ +#define CL_RANDOM 1 /* random access (as disk) */ +#define CL_SEQU 2 /* sequential access (as tape) */ +#define CL_DUPLEX 7 /* full-duplex point-to-point (RS-232, Net) */ +#define CL_KEYBD 8 /* half-duplex console (HIL Keyboard) */ +#define CL_DISPL 9 /* half-duplex console (display) */ +#define CL_FC 10 /* FiberChannel access media */ + +/* IODC ENTRY_INIT() */ +#define ENTRY_INIT_SRCH_FRST 2 +#define ENTRY_INIT_SRCH_NEXT 3 +#define ENTRY_INIT_MOD_DEV 4 +#define ENTRY_INIT_DEV 5 +#define ENTRY_INIT_MOD 6 +#define ENTRY_INIT_MSG 9 + +/* IODC ENTRY_IO() */ +#define ENTRY_IO_BOOTIN 0 +#define ENTRY_IO_BOOTOUT 1 +#define ENTRY_IO_CIN 2 +#define ENTRY_IO_COUT 3 +#define ENTRY_IO_CLOSE 4 +#define ENTRY_IO_GETMSG 9 +#define ENTRY_IO_BBLOCK_IN 16 +#define ENTRY_IO_BBLOCK_OUT 17 + +/* IODC ENTRY_SPA() */ + +/* IODC ENTRY_CONFIG() */ + +/* IODC ENTRY_TEST() */ + +/* IODC ENTRY_TLB() */ /* constants for OS (NVM...) */ #define OS_ID_NONE 0 /* Undefined OS ID */ @@ -295,7 +327,13 @@ typedef struct { #define OSTAT_RUN 6 #define OSTAT_ON 7 -#ifndef __ASSEMBLY__ +/* Page Zero constant offsets used by the HPMC handler */ +#define BOOT_CONSOLE_HPA_OFFSET 0x3c0 +#define BOOT_CONSOLE_SPA_OFFSET 0x3c4 +#define BOOT_CONSOLE_PATH_OFFSET 0x3a8 + +#if !defined(__ASSEMBLY__) +#ifdef __KERNEL__ #include <linux/types.h> @@ -331,14 +369,6 @@ struct pdc_model { /* for PDC_MODEL */ unsigned long curr_key; }; -/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */ - -#define PDC_MODEL_IOPDIR_FDC (1 << 2) /* see sba_iommu.c */ -#define PDC_MODEL_NVA_MASK (3 << 4) -#define PDC_MODEL_NVA_SUPPORTED (0 << 4) -#define PDC_MODEL_NVA_SLOW (1 << 4) -#define PDC_MODEL_NVA_UNSUPPORTED (3 << 4) - struct pdc_cache_cf { /* for PDC_CACHE (I/D-caches) */ unsigned long #ifdef CONFIG_64BIT @@ -558,15 +588,97 @@ struct pdc_hpmc_pim_20 { /* PDC_PIM */ __u64 fr[32]; }; -#endif /* __ASSEMBLY__ */ +void pdc_console_init(void); /* in pdc_console.c */ +void pdc_console_restart(void); + +void setup_pdc(void); /* in inventory.c */ + +/* wrapper-functions from pdc.c */ + +int pdc_add_valid(unsigned long address); +int pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len); +int pdc_chassis_disp(unsigned long disp); +int pdc_chassis_warn(unsigned long *warn); +int pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info); +int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index, + void *iodc_data, unsigned int iodc_data_size); +int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info, + struct pdc_module_path *mod_path, long mod_index); +int pdc_system_map_find_addrs(struct pdc_system_map_addr_info *pdc_addr_info, + long mod_index, long addr_index); +int pdc_model_info(struct pdc_model *model); +int pdc_model_sysmodel(char *name); +int pdc_model_cpuid(unsigned long *cpu_id); +int pdc_model_versions(unsigned long *versions, int id); +int pdc_model_capabilities(unsigned long *capabilities); +int pdc_cache_info(struct pdc_cache_info *cache); +int pdc_spaceid_bits(unsigned long *space_bits); +#ifndef CONFIG_PA20 +int pdc_btlb_info(struct pdc_btlb_info *btlb); +int pdc_mem_map_hpa(struct pdc_memory_map *r_addr, struct pdc_module_path *mod_path); +#endif /* !CONFIG_PA20 */ +int pdc_lan_station_id(char *lan_addr, unsigned long net_hpa); + +int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count); +int pdc_stable_write(unsigned long staddr, void *memaddr, unsigned long count); +int pdc_stable_get_size(unsigned long *size); +int pdc_stable_verify_contents(void); +int pdc_stable_initialize(void); + +int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa); +int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl); + +int pdc_get_initiator(struct hardware_path *, struct pdc_initiator *); +int pdc_tod_read(struct pdc_tod *tod); +int pdc_tod_set(unsigned long sec, unsigned long usec); + +#ifdef CONFIG_64BIT +int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr, + struct pdc_memory_table *tbl, unsigned long entries); +#endif + +void set_firmware_width(void); +int pdc_do_firm_test_reset(unsigned long ftc_bitmap); +int pdc_do_reset(void); +int pdc_soft_power_info(unsigned long *power_reg); +int pdc_soft_power_button(int sw_control); +void pdc_io_reset(void); +void pdc_io_reset_devices(void); +int pdc_iodc_getc(void); +void pdc_iodc_putc(unsigned char c); +void pdc_iodc_outc(unsigned char c); +void pdc_printf(const char *fmt, ...); + +void pdc_emergency_unlock(void); +int pdc_sti_call(unsigned long func, unsigned long flags, + unsigned long inptr, unsigned long outputr, + unsigned long glob_cfg); + +static inline char * os_id_to_string(u16 os_id) { + switch(os_id) { + case OS_ID_NONE: return "No OS"; + case OS_ID_HPUX: return "HP-UX"; + case OS_ID_MPEXL: return "MPE-iX"; + case OS_ID_OSF: return "OSF"; + case OS_ID_HPRT: return "HP-RT"; + case OS_ID_NOVEL: return "Novell Netware"; + case OS_ID_LINUX: return "Linux"; + default: return "Unknown"; + } +} + +#endif /* __KERNEL__ */ + +#define PAGE0 ((struct zeropage *)__PAGE_OFFSET) + +/* DEFINITION OF THE ZERO-PAGE (PAG0) */ +/* based on work by Jason Eckhardt (jason@equator.com) */ -/* flags of the device_path (see below) */ +/* flags of the device_path */ #define PF_AUTOBOOT 0x80 #define PF_AUTOSEARCH 0x40 #define PF_TIMER 0x0F -#ifndef __ASSEMBLY__ - struct device_path { /* page 1-69 */ unsigned char flags; /* flags see above! */ unsigned char bc[6]; /* bus converter routing info */ @@ -586,63 +698,6 @@ struct pz_device { unsigned short cl_class;/* see below */ } __attribute__((aligned(8))) ; -#endif /* __ASSEMBLY__ */ - -/* cl_class - * page 3-33 of IO-Firmware ARS - * IODC ENTRY_INIT(Search first) RET[1] - */ -#define CL_NULL 0 /* invalid */ -#define CL_RANDOM 1 /* random access (as disk) */ -#define CL_SEQU 2 /* sequential access (as tape) */ -#define CL_DUPLEX 7 /* full-duplex point-to-point (RS-232, Net) */ -#define CL_KEYBD 8 /* half-duplex console (HIL Keyboard) */ -#define CL_DISPL 9 /* half-duplex console (display) */ -#define CL_FC 10 /* FiberChannel access media */ - -#if 0 -/* FIXME: DEVCLASS_* duplicates CL_* (above). Delete DEVCLASS_*? */ -#define DEVCLASS_RANDOM 1 -#define DEVCLASS_SEQU 2 -#define DEVCLASS_DUPLEX 7 -#define DEVCLASS_KEYBD 8 -#define DEVCLASS_DISP 9 -#endif - -/* IODC ENTRY_INIT() */ -#define ENTRY_INIT_SRCH_FRST 2 -#define ENTRY_INIT_SRCH_NEXT 3 -#define ENTRY_INIT_MOD_DEV 4 -#define ENTRY_INIT_DEV 5 -#define ENTRY_INIT_MOD 6 -#define ENTRY_INIT_MSG 9 - -/* IODC ENTRY_IO() */ -#define ENTRY_IO_BOOTIN 0 -#define ENTRY_IO_BOOTOUT 1 -#define ENTRY_IO_CIN 2 -#define ENTRY_IO_COUT 3 -#define ENTRY_IO_CLOSE 4 -#define ENTRY_IO_GETMSG 9 -#define ENTRY_IO_BBLOCK_IN 16 -#define ENTRY_IO_BBLOCK_OUT 17 - -/* IODC ENTRY_SPA() */ - -/* IODC ENTRY_CONFIG() */ - -/* IODC ENTRY_TEST() */ - -/* IODC ENTRY_TLB() */ - - -/* DEFINITION OF THE ZERO-PAGE (PAG0) */ -/* based on work by Jason Eckhardt (jason@equator.com) */ - -#ifndef __ASSEMBLY__ - -#define PAGE0 ((struct zeropage *)__PAGE_OFFSET) - struct zeropage { /* [0x000] initialize vectors (VEC) */ unsigned int vec_special; /* must be zero */ @@ -699,93 +754,6 @@ struct zeropage { __u32 pad608[126]; }; -#endif /* __ASSEMBLY__ */ - -/* Page Zero constant offsets used by the HPMC handler */ - -#define BOOT_CONSOLE_HPA_OFFSET 0x3c0 -#define BOOT_CONSOLE_SPA_OFFSET 0x3c4 -#define BOOT_CONSOLE_PATH_OFFSET 0x3a8 - -#ifndef __ASSEMBLY__ -void pdc_console_init(void); /* in pdc_console.c */ -void pdc_console_restart(void); - -void setup_pdc(void); /* in inventory.c */ - -/* wrapper-functions from pdc.c */ - -int pdc_add_valid(unsigned long address); -int pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len); -int pdc_chassis_disp(unsigned long disp); -int pdc_chassis_warn(unsigned long *warn); -int pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info); -int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index, - void *iodc_data, unsigned int iodc_data_size); -int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info, - struct pdc_module_path *mod_path, long mod_index); -int pdc_system_map_find_addrs(struct pdc_system_map_addr_info *pdc_addr_info, - long mod_index, long addr_index); -int pdc_model_info(struct pdc_model *model); -int pdc_model_sysmodel(char *name); -int pdc_model_cpuid(unsigned long *cpu_id); -int pdc_model_versions(unsigned long *versions, int id); -int pdc_model_capabilities(unsigned long *capabilities); -int pdc_cache_info(struct pdc_cache_info *cache); -int pdc_spaceid_bits(unsigned long *space_bits); -#ifndef CONFIG_PA20 -int pdc_btlb_info(struct pdc_btlb_info *btlb); -int pdc_mem_map_hpa(struct pdc_memory_map *r_addr, struct pdc_module_path *mod_path); -#endif /* !CONFIG_PA20 */ -int pdc_lan_station_id(char *lan_addr, unsigned long net_hpa); - -int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count); -int pdc_stable_write(unsigned long staddr, void *memaddr, unsigned long count); -int pdc_stable_get_size(unsigned long *size); -int pdc_stable_verify_contents(void); -int pdc_stable_initialize(void); - -int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa); -int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl); - -int pdc_get_initiator(struct hardware_path *, struct pdc_initiator *); -int pdc_tod_read(struct pdc_tod *tod); -int pdc_tod_set(unsigned long sec, unsigned long usec); - -#ifdef CONFIG_64BIT -int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr, - struct pdc_memory_table *tbl, unsigned long entries); -#endif - -void set_firmware_width(void); -int pdc_do_firm_test_reset(unsigned long ftc_bitmap); -int pdc_do_reset(void); -int pdc_soft_power_info(unsigned long *power_reg); -int pdc_soft_power_button(int sw_control); -void pdc_io_reset(void); -void pdc_io_reset_devices(void); -int pdc_iodc_getc(void); -void pdc_iodc_putc(unsigned char c); -void pdc_iodc_outc(unsigned char c); -void pdc_printf(const char *fmt, ...); - -void pdc_emergency_unlock(void); -int pdc_sti_call(unsigned long func, unsigned long flags, - unsigned long inptr, unsigned long outputr, - unsigned long glob_cfg); - -static inline char * os_id_to_string(u16 os_id) { - switch(os_id) { - case OS_ID_NONE: return "No OS"; - case OS_ID_HPUX: return "HP-UX"; - case OS_ID_MPEXL: return "MPE-iX"; - case OS_ID_OSF: return "OSF"; - case OS_ID_HPRT: return "HP-RT"; - case OS_ID_NOVEL: return "Novell Netware"; - case OS_ID_LINUX: return "Linux"; - default: return "Unknown"; - } -} -#endif /* __ASSEMBLY__ */ +#endif /* !defined(__ASSEMBLY__) */ #endif /* _PARISC_PDC_H */ diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h index 9ab79c8e5a4..cd0fa4f7332 100644 --- a/include/asm-parisc/pgtable.h +++ b/include/asm-parisc/pgtable.h @@ -49,14 +49,6 @@ #define pgd_ERROR(e) \ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, (unsigned long)pgd_val(e)) - /* Note: If you change ISTACK_SIZE, you need to change the corresponding - * values in vmlinux.lds and vmlinux64.lds (init_istack section). Also, - * the "order" and size need to agree. - */ - -#define ISTACK_SIZE 32768 /* Interrupt Stack Size */ -#define ISTACK_ORDER 3 - /* This is the size of the initially mapped kernel memory */ #ifdef CONFIG_64BIT #define KERNEL_INITIAL_ORDER 24 /* 0 to 1<<24 = 16MB */ @@ -325,27 +317,27 @@ static inline void pgd_clear(pgd_t *pgd) { * setup: the pgd is never bad, and a pmd always exists (as it's folded * into the pgd entry) */ -extern inline int pgd_none(pgd_t pgd) { return 0; } -extern inline int pgd_bad(pgd_t pgd) { return 0; } -extern inline int pgd_present(pgd_t pgd) { return 1; } -extern inline void pgd_clear(pgd_t * pgdp) { } +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) { } #endif /* * The following only work if pte_present() is true. * Undefined behaviour if not.. */ -extern inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } -extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } -extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } -extern inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } - -extern inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; } -extern inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; } -extern inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_WRITE; return pte; } -extern inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; } -extern inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; } -extern inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_WRITE; return pte; } +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_write(pte_t pte) { return pte_val(pte) & _PAGE_WRITE; } +static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } + +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_WRITE; return 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_WRITE; return pte; } /* * Conversion functions: convert a page and protection to a page entry, @@ -369,7 +361,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) return pte; } -extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; } /* Permanent address of a page. On parisc we don't have highmem. */ diff --git a/include/asm-parisc/prefetch.h b/include/asm-parisc/prefetch.h index 5d021726fa3..c5edc60c059 100644 --- a/include/asm-parisc/prefetch.h +++ b/include/asm-parisc/prefetch.h @@ -19,7 +19,7 @@ #ifdef CONFIG_PREFETCH #define ARCH_HAS_PREFETCH -extern inline void prefetch(const void *addr) +static inline void prefetch(const void *addr) { __asm__("ldw 0(%0), %%r0" : : "r" (addr)); } @@ -27,7 +27,7 @@ extern inline void prefetch(const void *addr) /* LDD is a PA2.0 addition. */ #ifdef CONFIG_PA20 #define ARCH_HAS_PREFETCHW -extern inline void prefetchw(const void *addr) +static inline void prefetchw(const void *addr) { __asm__("ldd 0(%0), %%r0" : : "r" (addr)); } diff --git a/include/asm-parisc/rtc.h b/include/asm-parisc/rtc.h index f4ebff11dcb..099d641a42c 100644 --- a/include/asm-parisc/rtc.h +++ b/include/asm-parisc/rtc.h @@ -50,10 +50,10 @@ static inline unsigned int get_rtc_time(struct rtc_time *wtime) long int days, rem, y; const unsigned short int *ip; - if(pdc_tod_read(&tod_data) < 0) + memset(wtime, 0, sizeof(*wtime)); + if (pdc_tod_read(&tod_data) < 0) return RTC_24H | RTC_BATT_BAD; - // most of the remainder of this function is: // Copyright (C) 1991, 1993, 1997, 1998 Free Software Foundation, Inc. // This was originally a part of the GNU C Library. diff --git a/include/asm-parisc/scatterlist.h b/include/asm-parisc/scatterlist.h index e7211c74844..cd3cfdf8228 100644 --- a/include/asm-parisc/scatterlist.h +++ b/include/asm-parisc/scatterlist.h @@ -5,7 +5,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; unsigned int length; diff --git a/include/asm-parisc/semaphore.h b/include/asm-parisc/semaphore.h index b771dcfcfdd..a16271cdc74 100644 --- a/include/asm-parisc/semaphore.h +++ b/include/asm-parisc/semaphore.h @@ -54,7 +54,7 @@ struct semaphore { #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) -extern inline void sema_init (struct semaphore *sem, int val) +static inline void sema_init (struct semaphore *sem, int val) { *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val); } @@ -82,7 +82,7 @@ asmlinkage void __up(struct semaphore * sem); * interrupts while we're messing with the semaphore. Sorry. */ -extern __inline__ void down(struct semaphore * sem) +static inline void down(struct semaphore * sem) { might_sleep(); spin_lock_irq(&sem->sentry); @@ -94,7 +94,7 @@ extern __inline__ void down(struct semaphore * sem) spin_unlock_irq(&sem->sentry); } -extern __inline__ int down_interruptible(struct semaphore * sem) +static inline int down_interruptible(struct semaphore * sem) { int ret = 0; might_sleep(); @@ -112,7 +112,7 @@ extern __inline__ int down_interruptible(struct semaphore * sem) * down_trylock returns 0 on success, 1 if we failed to get the lock. * May not sleep, but must preserve irq state */ -extern __inline__ int down_trylock(struct semaphore * sem) +static inline int down_trylock(struct semaphore * sem) { unsigned long flags; int count; @@ -129,7 +129,7 @@ extern __inline__ int down_trylock(struct semaphore * sem) * Note! This is subtle. We jump to wake people up only if * the semaphore was negative (== somebody was waiting on it). */ -extern __inline__ void up(struct semaphore * sem) +static inline void up(struct semaphore * sem) { unsigned long flags; diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h index f74099bdca3..081b4ae6186 100644 --- a/include/asm-parisc/unistd.h +++ b/include/asm-parisc/unistd.h @@ -797,8 +797,9 @@ #define __NR_signalfd (__NR_Linux + 302) #define __NR_timerfd (__NR_Linux + 303) #define __NR_eventfd (__NR_Linux + 304) +#define __NR_fallocate (__NR_Linux + 305) -#define __NR_Linux_syscalls (__NR_eventfd + 1) +#define __NR_Linux_syscalls (__NR_fallocate + 1) #define __IGNORE_select /* newselect */ diff --git a/include/asm-powerpc/scatterlist.h b/include/asm-powerpc/scatterlist.h index b075f619c3b..fcf7d55afe4 100644 --- a/include/asm-powerpc/scatterlist.h +++ b/include/asm-powerpc/scatterlist.h @@ -14,7 +14,10 @@ #include <asm/dma.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; unsigned int length; diff --git a/include/asm-s390/scatterlist.h b/include/asm-s390/scatterlist.h index a43b3afc5e2..29ec8e28c8d 100644 --- a/include/asm-s390/scatterlist.h +++ b/include/asm-s390/scatterlist.h @@ -2,7 +2,10 @@ #define _ASMS390_SCATTERLIST_H struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; unsigned int length; }; diff --git a/include/asm-sh/scatterlist.h b/include/asm-sh/scatterlist.h index b9ae53c3836..a7d0d1856a9 100644 --- a/include/asm-sh/scatterlist.h +++ b/include/asm-sh/scatterlist.h @@ -4,7 +4,10 @@ #include <asm/types.h> struct scatterlist { - struct page * page; /* Location for highmem page, if any */ +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset;/* for highmem, page offset */ dma_addr_t dma_address; unsigned int length; diff --git a/include/asm-sh64/scatterlist.h b/include/asm-sh64/scatterlist.h index 1c723f2d7a9..5109251970e 100644 --- a/include/asm-sh64/scatterlist.h +++ b/include/asm-sh64/scatterlist.h @@ -14,7 +14,10 @@ #include <asm/types.h> struct scatterlist { - struct page * page; /* Location for highmem page, if any */ +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset;/* for highmem, page offset */ dma_addr_t dma_address; unsigned int length; diff --git a/include/asm-sparc/scatterlist.h b/include/asm-sparc/scatterlist.h index 4055af90ad7..e08d3d775b0 100644 --- a/include/asm-sparc/scatterlist.h +++ b/include/asm-sparc/scatterlist.h @@ -5,7 +5,10 @@ #include <linux/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; unsigned int length; diff --git a/include/asm-sparc64/scatterlist.h b/include/asm-sparc64/scatterlist.h index 703c5bbe6c8..6df23f070b1 100644 --- a/include/asm-sparc64/scatterlist.h +++ b/include/asm-sparc64/scatterlist.h @@ -6,7 +6,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; unsigned int length; diff --git a/include/asm-v850/scatterlist.h b/include/asm-v850/scatterlist.h index 56f402920db..02d27b3fb06 100644 --- a/include/asm-v850/scatterlist.h +++ b/include/asm-v850/scatterlist.h @@ -17,7 +17,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned offset; dma_addr_t dma_address; unsigned length; diff --git a/include/asm-x86/bootparam.h b/include/asm-x86/bootparam.h index ef67b59dbdb..dc031cf4463 100644 --- a/include/asm-x86/bootparam.h +++ b/include/asm-x86/bootparam.h @@ -28,8 +28,9 @@ struct setup_header { u16 kernel_version; u8 type_of_loader; u8 loadflags; -#define LOADED_HIGH 0x01 -#define CAN_USE_HEAP 0x80 +#define LOADED_HIGH (1<<0) +#define KEEP_SEGMENTS (1<<6) +#define CAN_USE_HEAP (1<<7) u16 setup_move_size; u32 code32_start; u32 ramdisk_image; @@ -41,6 +42,10 @@ struct setup_header { u32 initrd_addr_max; u32 kernel_alignment; u8 relocatable_kernel; + u8 _pad2[3]; + u32 cmdline_size; + u32 hardware_subarch; + u64 hardware_subarch_data; } __attribute__((packed)); struct sys_desc_table { diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h index b3d43de44c5..9411a2d3f19 100644 --- a/include/asm-x86/cacheflush.h +++ b/include/asm-x86/cacheflush.h @@ -27,6 +27,7 @@ void global_flush_tlb(void); int change_page_attr(struct page *page, int numpages, pgprot_t prot); int change_page_attr_addr(unsigned long addr, int numpages, pgprot_t prot); +void clflush_cache_range(void *addr, int size); #ifdef CONFIG_DEBUG_PAGEALLOC /* internal debugging function */ diff --git a/include/asm-x86/device.h b/include/asm-x86/device.h index d9ee5e52e91..87a715367a1 100644 --- a/include/asm-x86/device.h +++ b/include/asm-x86/device.h @@ -5,6 +5,9 @@ struct dev_archdata { #ifdef CONFIG_ACPI void *acpi_handle; #endif +#ifdef CONFIG_DMAR + void *iommu; /* hook for IOMMU specific extension */ +#endif }; #endif /* _ASM_X86_DEVICE_H */ diff --git a/include/asm-x86/dma-mapping_32.h b/include/asm-x86/dma-mapping_32.h index 6a2d26cb5da..55f01bd9e55 100644 --- a/include/asm-x86/dma-mapping_32.h +++ b/include/asm-x86/dma-mapping_32.h @@ -45,9 +45,9 @@ dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents, WARN_ON(nents == 0 || sglist[0].length == 0); for_each_sg(sglist, sg, nents, i) { - BUG_ON(!sg->page); + BUG_ON(!sg_page(sg)); - sg->dma_address = page_to_phys(sg->page) + sg->offset; + sg->dma_address = sg_phys(sg); } flush_write_buffers(); diff --git a/include/asm-x86/scatterlist_32.h b/include/asm-x86/scatterlist_32.h index bd5164aa8f6..0e7d997a34b 100644 --- a/include/asm-x86/scatterlist_32.h +++ b/include/asm-x86/scatterlist_32.h @@ -4,7 +4,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; dma_addr_t dma_address; unsigned int length; diff --git a/include/asm-x86/scatterlist_64.h b/include/asm-x86/scatterlist_64.h index ef3986ba4b7..1847c72befe 100644 --- a/include/asm-x86/scatterlist_64.h +++ b/include/asm-x86/scatterlist_64.h @@ -4,7 +4,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; unsigned int length; dma_addr_t dma_address; diff --git a/include/asm-xtensa/scatterlist.h b/include/asm-xtensa/scatterlist.h index ca337a29429..810080bb0a2 100644 --- a/include/asm-xtensa/scatterlist.h +++ b/include/asm-xtensa/scatterlist.h @@ -14,7 +14,10 @@ #include <asm/types.h> struct scatterlist { - struct page *page; +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; unsigned int offset; dma_addr_t dma_address; unsigned int length; diff --git a/include/linux/audit.h b/include/linux/audit.h index 9ae740936a6..c6878169283 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -63,6 +63,8 @@ #define AUDIT_ADD_RULE 1011 /* Add syscall filtering rule */ #define AUDIT_DEL_RULE 1012 /* Delete syscall filtering rule */ #define AUDIT_LIST_RULES 1013 /* List syscall filtering rules */ +#define AUDIT_TRIM 1014 /* Trim junk from watched tree */ +#define AUDIT_MAKE_EQUIV 1015 /* Append to watched tree */ #define AUDIT_TTY_GET 1016 /* Get TTY auditing status */ #define AUDIT_TTY_SET 1017 /* Set TTY auditing status */ @@ -203,6 +205,7 @@ #define AUDIT_SUCCESS 104 /* exit >= 0; value ignored */ #define AUDIT_WATCH 105 #define AUDIT_PERM 106 +#define AUDIT_DIR 107 #define AUDIT_ARG0 200 #define AUDIT_ARG1 (AUDIT_ARG0+1) @@ -366,8 +369,8 @@ extern void audit_syscall_entry(int arch, extern void audit_syscall_exit(int failed, long return_code); extern void __audit_getname(const char *name); extern void audit_putname(const char *name); -extern void __audit_inode(const char *name, const struct inode *inode); -extern void __audit_inode_child(const char *dname, const struct inode *inode, +extern void __audit_inode(const char *name, const struct dentry *dentry); +extern void __audit_inode_child(const char *dname, const struct dentry *dentry, const struct inode *parent); extern void __audit_ptrace(struct task_struct *t); @@ -381,15 +384,15 @@ static inline void audit_getname(const char *name) if (unlikely(!audit_dummy_context())) __audit_getname(name); } -static inline void audit_inode(const char *name, const struct inode *inode) { +static inline void audit_inode(const char *name, const struct dentry *dentry) { if (unlikely(!audit_dummy_context())) - __audit_inode(name, inode); + __audit_inode(name, dentry); } static inline void audit_inode_child(const char *dname, - const struct inode *inode, + const struct dentry *dentry, const struct inode *parent) { if (unlikely(!audit_dummy_context())) - __audit_inode_child(dname, inode, parent); + __audit_inode_child(dname, dentry, parent); } void audit_core_dumps(long signr); @@ -477,9 +480,9 @@ extern int audit_signals; #define audit_dummy_context() 1 #define audit_getname(n) do { ; } while (0) #define audit_putname(n) do { ; } while (0) -#define __audit_inode(n,i) do { ; } while (0) +#define __audit_inode(n,d) do { ; } while (0) #define __audit_inode_child(d,i,p) do { ; } while (0) -#define audit_inode(n,i) do { ; } while (0) +#define audit_inode(n,d) do { ; } while (0) #define audit_inode_child(d,i,p) do { ; } while (0) #define audit_core_dumps(i) do { ; } while (0) #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) diff --git a/include/linux/capability.h b/include/linux/capability.h index 7a8d7ade28a..bb017edffd5 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -56,10 +56,8 @@ typedef struct __user_cap_data_struct { struct vfs_cap_data { __u32 magic_etc; /* Little endian */ - struct { - __u32 permitted; /* Little endian */ - __u32 inheritable; /* Little endian */ - } data[1]; + __u32 permitted; /* Little endian */ + __u32 inheritable; /* Little endian */ }; #ifdef __KERNEL__ diff --git a/include/linux/dcache.h b/include/linux/dcache.h index aab53df4faf..c2c153f97e8 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -178,6 +178,7 @@ d_iput: no no no yes #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */ extern spinlock_t dcache_lock; +extern seqlock_t rename_lock; /** * d_drop - drop a dentry diff --git a/include/linux/dmar.h b/include/linux/dmar.h new file mode 100644 index 00000000000..ffb6439cb5e --- /dev/null +++ b/include/linux/dmar.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Copyright (C) Ashok Raj <ashok.raj@intel.com> + * Copyright (C) Shaohua Li <shaohua.li@intel.com> + */ + +#ifndef __DMAR_H__ +#define __DMAR_H__ + +#include <linux/acpi.h> +#include <linux/types.h> +#include <linux/msi.h> + +#ifdef CONFIG_DMAR +struct intel_iommu; + +extern char *dmar_get_fault_reason(u8 fault_reason); + +/* Can't use the common MSI interrupt functions + * since DMAR is not a pci device + */ +extern void dmar_msi_unmask(unsigned int irq); +extern void dmar_msi_mask(unsigned int irq); +extern void dmar_msi_read(int irq, struct msi_msg *msg); +extern void dmar_msi_write(int irq, struct msi_msg *msg); +extern int dmar_set_interrupt(struct intel_iommu *iommu); +extern int arch_setup_dmar_msi(unsigned int irq); + +/* Intel IOMMU detection and initialization functions */ +extern void detect_intel_iommu(void); +extern int intel_iommu_init(void); + +extern int dmar_table_init(void); +extern int early_dmar_detect(void); + +extern struct list_head dmar_drhd_units; +extern struct list_head dmar_rmrr_units; + +struct dmar_drhd_unit { + struct list_head list; /* list of drhd units */ + u64 reg_base_addr; /* register base address*/ + struct pci_dev **devices; /* target device array */ + int devices_cnt; /* target device count */ + u8 ignored:1; /* ignore drhd */ + u8 include_all:1; + struct intel_iommu *iommu; +}; + +struct dmar_rmrr_unit { + struct list_head list; /* list of rmrr units */ + u64 base_address; /* reserved base address*/ + u64 end_address; /* reserved end address */ + struct pci_dev **devices; /* target devices */ + int devices_cnt; /* target device count */ +}; + +#define for_each_drhd_unit(drhd) \ + list_for_each_entry(drhd, &dmar_drhd_units, list) +#define for_each_rmrr_units(rmrr) \ + list_for_each_entry(rmrr, &dmar_rmrr_units, list) +#else +static inline void detect_intel_iommu(void) +{ + return; +} +static inline int intel_iommu_init(void) +{ + return -ENODEV; +} + +#endif /* !CONFIG_DMAR */ +#endif /* __DMAR_H__ */ diff --git a/include/linux/efi.h b/include/linux/efi.h index 0b9579a4cd4..14813b59580 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -298,7 +298,7 @@ extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, u64 attr); extern int __init efi_uart_console_only (void); extern void efi_initialize_iomem_resources(struct resource *code_resource, - struct resource *data_resource); + struct resource *data_resource, struct resource *bss_resource); extern unsigned long efi_get_time(void); extern int efi_set_rtc_mmss(unsigned long nowtime); extern int is_available_memory(efi_memory_desc_t * md); diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h index 16cb25cbf7c..dd57fe523e9 100644 --- a/include/linux/efs_fs.h +++ b/include/linux/efs_fs.h @@ -35,6 +35,7 @@ static inline struct efs_sb_info *SUPER_INFO(struct super_block *sb) } struct statfs; +struct fid; extern const struct inode_operations efs_dir_inode_operations; extern const struct file_operations efs_dir_operations; @@ -45,7 +46,10 @@ extern efs_block_t efs_map_block(struct inode *, efs_block_t); extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int); extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *); -extern struct dentry *efs_get_dentry(struct super_block *sb, void *vobjp); +extern struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type); +extern struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type); extern struct dentry *efs_get_parent(struct dentry *); extern int efs_bmap(struct inode *, int); diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index 8872fe8392d..51d21413881 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -4,9 +4,48 @@ #include <linux/types.h> struct dentry; +struct inode; struct super_block; struct vfsmount; +/* + * The fileid_type identifies how the file within the filesystem is encoded. + * In theory this is freely set and parsed by the filesystem, but we try to + * stick to conventions so we can share some generic code and don't confuse + * sniffers like ethereal/wireshark. + * + * The filesystem must not use the value '0' or '0xff'. + */ +enum fid_type { + /* + * The root, or export point, of the filesystem. + * (Never actually passed down to the filesystem. + */ + FILEID_ROOT = 0, + + /* + * 32bit inode number, 32 bit generation number. + */ + FILEID_INO32_GEN = 1, + + /* + * 32bit inode number, 32 bit generation number, + * 32 bit parent directory inode number. + */ + FILEID_INO32_GEN_PARENT = 2, +}; + +struct fid { + union { + struct { + u32 ino; + u32 gen; + u32 parent_ino; + u32 parent_gen; + } i32; + __u32 raw[6]; + }; +}; /** * struct export_operations - for nfsd to communicate with file systems @@ -15,43 +54,9 @@ struct vfsmount; * @get_name: find the name for a given inode in a given directory * @get_parent: find the parent of a given directory * @get_dentry: find a dentry for the inode given a file handle sub-fragment - * @find_exported_dentry: - * set by the exporting module to a standard helper function. - * - * Description: - * The export_operations structure provides a means for nfsd to communicate - * with a particular exported file system - particularly enabling nfsd and - * the filesystem to co-operate when dealing with file handles. - * - * export_operations contains two basic operation for dealing with file - * handles, decode_fh() and encode_fh(), and allows for some other - * operations to be defined which standard helper routines use to get - * specific information from the filesystem. - * - * nfsd encodes information use to determine which filesystem a filehandle - * applies to in the initial part of the file handle. The remainder, termed - * a file handle fragment, is controlled completely by the filesystem. The - * standard helper routines assume that this fragment will contain one or - * two sub-fragments, one which identifies the file, and one which may be - * used to identify the (a) directory containing the file. * - * In some situations, nfsd needs to get a dentry which is connected into a - * specific part of the file tree. To allow for this, it passes the - * function acceptable() together with a @context which can be used to see - * if the dentry is acceptable. As there can be multiple dentrys for a - * given file, the filesystem should check each one for acceptability before - * looking for the next. As soon as an acceptable one is found, it should - * be returned. - * - * decode_fh: - * @decode_fh is given a &struct super_block (@sb), a file handle fragment - * (@fh, @fh_len) and an acceptability testing function (@acceptable, - * @context). It should return a &struct dentry which refers to the same - * file that the file handle fragment refers to, and which passes the - * acceptability test. If it cannot, it should return a %NULL pointer if - * the file was found but no acceptable &dentries were available, or a - * %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or - * %ENOMEM). + * See Documentation/filesystems/Exporting for details on how to use + * this interface correctly. * * encode_fh: * @encode_fh should store in the file handle fragment @fh (using at most @@ -63,6 +68,21 @@ struct vfsmount; * the filehandle fragment. encode_fh() should return the number of bytes * stored or a negative error code such as %-ENOSPC * + * fh_to_dentry: + * @fh_to_dentry is given a &struct super_block (@sb) and a file handle + * fragment (@fh, @fh_len). It should return a &struct dentry which refers + * to the same file that the file handle fragment refers to. If it cannot, + * it should return a %NULL pointer if the file was found but no acceptable + * &dentries were available, or an %ERR_PTR error code indicating why it + * couldn't be found (e.g. %ENOENT or %ENOMEM). Any suitable dentry can be + * returned including, if necessary, a new dentry created with d_alloc_root. + * The caller can then find any other extant dentries by following the + * d_alias links. + * + * fh_to_parent: + * Same as @fh_to_dentry, except that it returns a pointer to the parent + * dentry if it was encoded into the filehandle fragment by @encode_fh. + * * get_name: * @get_name should find a name for the given @child in the given @parent * directory. The name should be stored in the @name (with the @@ -75,52 +95,37 @@ struct vfsmount; * is also a directory. In the event that it cannot be found, or storage * space cannot be allocated, a %ERR_PTR should be returned. * - * get_dentry: - * Given a &super_block (@sb) and a pointer to a file-system specific inode - * identifier, possibly an inode number, (@inump) get_dentry() should find - * the identified inode and return a dentry for that inode. Any suitable - * dentry can be returned including, if necessary, a new dentry created with - * d_alloc_root. The caller can then find any other extant dentrys by - * following the d_alias links. If a new dentry was created using - * d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry - * should be d_rehash()ed. - * - * If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code - * can be returned. The @inump will be whatever was passed to - * nfsd_find_fh_dentry() in either the @obj or @parent parameters. - * * Locking rules: * get_parent is called with child->d_inode->i_mutex down * get_name is not (which is possibly inconsistent) */ struct export_operations { - struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh, - int fh_len, int fh_type, - int (*acceptable)(void *context, struct dentry *de), - void *context); int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len, int connectable); + struct dentry * (*fh_to_dentry)(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type); + struct dentry * (*fh_to_parent)(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type); int (*get_name)(struct dentry *parent, char *name, struct dentry *child); struct dentry * (*get_parent)(struct dentry *child); - struct dentry * (*get_dentry)(struct super_block *sb, void *inump); - - /* This is set by the exporting module to a standard helper */ - struct dentry * (*find_exported_dentry)( - struct super_block *sb, void *obj, void *parent, - int (*acceptable)(void *context, struct dentry *de), - void *context); }; -extern struct dentry *find_exported_dentry(struct super_block *sb, void *obj, - void *parent, int (*acceptable)(void *context, struct dentry *de), - void *context); - -extern int exportfs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, - int connectable); -extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, __u32 *fh, +extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, + int *max_len, int connectable); +extern struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid, int fh_len, int fileid_type, int (*acceptable)(void *, struct dentry *), void *context); +/* + * Generic helpers for filesystems. + */ +extern struct dentry *generic_fh_to_dentry(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type, + struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen)); +extern struct dentry *generic_fh_to_parent(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type, + struct inode *(*get_inode) (struct super_block *sb, u64 ino, u32 gen)); + #endif /* LINUX_EXPORTFS_H */ diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h index c77c3bbfe4b..0f6c86c634f 100644 --- a/include/linux/ext2_fs.h +++ b/include/linux/ext2_fs.h @@ -561,6 +561,7 @@ enum { #define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) #define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ ~EXT2_DIR_ROUND) +#define EXT2_MAX_REC_LEN ((1<<16)-1) static inline ext2_fsblk_t ext2_group_first_block_no(struct super_block *sb, unsigned long group_no) diff --git a/include/linux/fs.h b/include/linux/fs.h index 1bcce660cf0..b3ec4a496d6 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -987,7 +987,7 @@ struct super_block { const struct super_operations *s_op; struct dquot_operations *dq_op; struct quotactl_ops *s_qcop; - struct export_operations *s_export_op; + const struct export_operations *s_export_op; unsigned long s_flags; unsigned long s_magic; struct dentry *s_root; @@ -1470,6 +1470,8 @@ extern long do_mount(char *, char *, char *, unsigned long, void *); extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, struct vfsmount *); +extern struct vfsmount *collect_mounts(struct vfsmount *, struct dentry *); +extern void drop_collected_mounts(struct vfsmount *); extern int vfs_statfs(struct dentry *, struct kstatfs *); diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index dfc4e4f68da..2bd31fa623b 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -41,8 +41,9 @@ static inline void fsnotify_d_move(struct dentry *entry) */ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, const char *old_name, const char *new_name, - int isdir, struct inode *target, struct inode *source) + int isdir, struct inode *target, struct dentry *moved) { + struct inode *source = moved->d_inode; u32 cookie = inotify_get_cookie(); if (old_dir == new_dir) @@ -67,7 +68,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, if (source) { inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL); } - audit_inode_child(new_name, source, new_dir); + audit_inode_child(new_name, moved, new_dir); } /* @@ -98,7 +99,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) inode_dir_notify(inode, DN_CREATE); inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name, dentry->d_inode); - audit_inode_child(dentry->d_name.name, dentry->d_inode, inode); + audit_inode_child(dentry->d_name.name, dentry, inode); } /* @@ -109,7 +110,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) inode_dir_notify(inode, DN_CREATE); inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, dentry->d_name.name, dentry->d_inode); - audit_inode_child(dentry->d_name.name, dentry->d_inode, inode); + audit_inode_child(dentry->d_name.name, dentry, inode); } /* diff --git a/include/linux/inotify.h b/include/linux/inotify.h index d4f48c6402e..742b917e7d1 100644 --- a/include/linux/inotify.h +++ b/include/linux/inotify.h @@ -120,6 +120,8 @@ extern __s32 inotify_find_update_watch(struct inotify_handle *, struct inode *, u32); extern __s32 inotify_add_watch(struct inotify_handle *, struct inotify_watch *, struct inode *, __u32); +extern __s32 inotify_clone_watch(struct inotify_watch *, struct inotify_watch *); +extern void inotify_evict_watch(struct inotify_watch *); extern int inotify_rm_watch(struct inotify_handle *, struct inotify_watch *); extern int inotify_rm_wd(struct inotify_handle *, __u32); extern void inotify_remove_watch_locked(struct inotify_handle *, diff --git a/include/linux/linkage.h b/include/linux/linkage.h index 6c9873f8828..ff203dd0291 100644 --- a/include/linux/linkage.h +++ b/include/linux/linkage.h @@ -34,6 +34,12 @@ name: #endif +#ifndef WEAK +#define WEAK(name) \ + .weak name; \ + name: +#endif + #define KPROBE_ENTRY(name) \ .pushsection .kprobes.text, "ax"; \ ENTRY(name) diff --git a/include/linux/memory.h b/include/linux/memory.h index 654ef554487..33f0ff0cf63 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -41,18 +41,15 @@ struct memory_block { #define MEM_ONLINE (1<<0) /* exposed to userspace */ #define MEM_GOING_OFFLINE (1<<1) /* exposed to userspace */ #define MEM_OFFLINE (1<<2) /* exposed to userspace */ +#define MEM_GOING_ONLINE (1<<3) +#define MEM_CANCEL_ONLINE (1<<4) +#define MEM_CANCEL_OFFLINE (1<<5) -/* - * All of these states are currently kernel-internal for notifying - * kernel components and architectures. - * - * For MEM_MAPPING_INVALID, all notifier chains with priority >0 - * are called before pfn_to_page() becomes invalid. The priority=0 - * entry is reserved for the function that actually makes - * pfn_to_page() stop working. Any notifiers that want to be called - * after that should have priority <0. - */ -#define MEM_MAPPING_INVALID (1<<3) +struct memory_notify { + unsigned long start_pfn; + unsigned long nr_pages; + int status_change_nid; +}; struct notifier_block; struct mem_section; @@ -69,21 +66,31 @@ static inline int register_memory_notifier(struct notifier_block *nb) static inline void unregister_memory_notifier(struct notifier_block *nb) { } +static inline int memory_notify(unsigned long val, void *v) +{ + return 0; +} #else +extern int register_memory_notifier(struct notifier_block *nb); +extern void unregister_memory_notifier(struct notifier_block *nb); extern int register_new_memory(struct mem_section *); extern int unregister_memory_section(struct mem_section *); extern int memory_dev_init(void); extern int remove_memory_block(unsigned long, struct mem_section *, int); - +extern int memory_notify(unsigned long val, void *v); #define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT) #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ +#ifdef CONFIG_MEMORY_HOTPLUG #define hotplug_memory_notifier(fn, pri) { \ static struct notifier_block fn##_mem_nb = \ { .notifier_call = fn, .priority = pri }; \ register_memory_notifier(&fn##_mem_nb); \ } +#else +#define hotplug_memory_notifier(fn, pri) do { } while (0) +#endif #endif /* _LINUX_MEMORY_H_ */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 768b93359f9..5d2281f661f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -141,6 +141,7 @@ struct pci_dev { unsigned int class; /* 3 bytes: (base,sub,prog-if) */ u8 revision; /* PCI revision, low byte of class word */ u8 hdr_type; /* PCI header type (`multi' flag masked out) */ + u8 pcie_type; /* PCI-E device/port type */ u8 rom_base_reg; /* which config register controls the ROM */ u8 pin; /* which interrupt pin this device uses */ @@ -183,6 +184,7 @@ struct pci_dev { unsigned int msi_enabled:1; unsigned int msix_enabled:1; unsigned int is_managed:1; + unsigned int is_pcie:1; atomic_t enable_cnt; /* pci_enable_device has been called */ u32 saved_config_space[16]; /* config space saved at suspend time */ diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 72bfccd3da2..422eab4958a 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -28,6 +28,8 @@ #include <linux/reiserfs_fs_sb.h> #endif +struct fid; + /* * include/linux/reiser_fs.h * @@ -1877,12 +1879,10 @@ void reiserfs_delete_inode(struct inode *inode); int reiserfs_write_inode(struct inode *inode, int); int reiserfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create); -struct dentry *reiserfs_get_dentry(struct super_block *, void *); -struct dentry *reiserfs_decode_fh(struct super_block *sb, __u32 * data, - int len, int fhtype, - int (*acceptable) (void *contect, - struct dentry * de), - void *context); +struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type); +struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type); int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp, int connectable); diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h index 2dc7464cce5..42daf5e1526 100644 --- a/include/linux/scatterlist.h +++ b/include/linux/scatterlist.h @@ -4,47 +4,95 @@ #include <asm/scatterlist.h> #include <linux/mm.h> #include <linux/string.h> +#include <asm/io.h> +/* + * Notes on SG table design. + * + * Architectures must provide an unsigned long page_link field in the + * scatterlist struct. We use that to place the page pointer AND encode + * information about the sg table as well. The two lower bits are reserved + * for this information. + * + * If bit 0 is set, then the page_link contains a pointer to the next sg + * table list. Otherwise the next entry is at sg + 1. + * + * If bit 1 is set, then this sg entry is the last element in a list. + * + * See sg_next(). + * + */ + +#define SG_MAGIC 0x87654321 + +/** + * sg_set_page - Set sg entry to point at given page + * @sg: SG entry + * @page: The page + * + * Description: + * Use this function to set an sg entry pointing at a page, never assign + * the page directly. We encode sg table information in the lower bits + * of the page pointer. See sg_page() for looking up the page belonging + * to an sg entry. + * + **/ +static inline void sg_set_page(struct scatterlist *sg, struct page *page) +{ + unsigned long page_link = sg->page_link & 0x3; + +#ifdef CONFIG_DEBUG_SG + BUG_ON(sg->sg_magic != SG_MAGIC); +#endif + sg->page_link = page_link | (unsigned long) page; +} + +#define sg_page(sg) ((struct page *) ((sg)->page_link & ~0x3)) + +/** + * sg_set_buf - Set sg entry to point at given data + * @sg: SG entry + * @buf: Data + * @buflen: Data length + * + **/ static inline void sg_set_buf(struct scatterlist *sg, const void *buf, unsigned int buflen) { - sg->page = virt_to_page(buf); + sg_set_page(sg, virt_to_page(buf)); sg->offset = offset_in_page(buf); sg->length = buflen; } -static inline void sg_init_one(struct scatterlist *sg, const void *buf, - unsigned int buflen) -{ - memset(sg, 0, sizeof(*sg)); - sg_set_buf(sg, buf, buflen); -} - /* * We overload the LSB of the page pointer to indicate whether it's * a valid sg entry, or whether it points to the start of a new scatterlist. * Those low bits are there for everyone! (thanks mason :-) */ -#define sg_is_chain(sg) ((unsigned long) (sg)->page & 0x01) +#define sg_is_chain(sg) ((sg)->page_link & 0x01) +#define sg_is_last(sg) ((sg)->page_link & 0x02) #define sg_chain_ptr(sg) \ - ((struct scatterlist *) ((unsigned long) (sg)->page & ~0x01)) + ((struct scatterlist *) ((sg)->page_link & ~0x03)) /** * sg_next - return the next scatterlist entry in a list * @sg: The current sg entry * - * Usually the next entry will be @sg@ + 1, but if this sg element is part - * of a chained scatterlist, it could jump to the start of a new - * scatterlist array. - * - * Note that the caller must ensure that there are further entries after - * the current entry, this function will NOT return NULL for an end-of-list. + * Description: + * Usually the next entry will be @sg@ + 1, but if this sg element is part + * of a chained scatterlist, it could jump to the start of a new + * scatterlist array. * - */ + **/ static inline struct scatterlist *sg_next(struct scatterlist *sg) { - sg++; +#ifdef CONFIG_DEBUG_SG + BUG_ON(sg->sg_magic != SG_MAGIC); +#endif + if (sg_is_last(sg)) + return NULL; + sg++; if (unlikely(sg_is_chain(sg))) sg = sg_chain_ptr(sg); @@ -62,14 +110,15 @@ static inline struct scatterlist *sg_next(struct scatterlist *sg) * @sgl: First entry in the scatterlist * @nents: Number of entries in the scatterlist * - * Should only be used casually, it (currently) scan the entire list - * to get the last entry. + * Description: + * Should only be used casually, it (currently) scan the entire list + * to get the last entry. * - * Note that the @sgl@ pointer passed in need not be the first one, - * the important bit is that @nents@ denotes the number of entries that - * exist from @sgl@. + * Note that the @sgl@ pointer passed in need not be the first one, + * the important bit is that @nents@ denotes the number of entries that + * exist from @sgl@. * - */ + **/ static inline struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents) { @@ -83,6 +132,10 @@ static inline struct scatterlist *sg_last(struct scatterlist *sgl, ret = sg; #endif +#ifdef CONFIG_DEBUG_SG + BUG_ON(sgl[0].sg_magic != SG_MAGIC); + BUG_ON(!sg_is_last(ret)); +#endif return ret; } @@ -92,16 +145,111 @@ static inline struct scatterlist *sg_last(struct scatterlist *sgl, * @prv_nents: Number of entries in prv * @sgl: Second scatterlist * - * Links @prv@ and @sgl@ together, to form a longer scatterlist. + * Description: + * Links @prv@ and @sgl@ together, to form a longer scatterlist. * - */ + **/ static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, struct scatterlist *sgl) { #ifndef ARCH_HAS_SG_CHAIN BUG(); #endif - prv[prv_nents - 1].page = (struct page *) ((unsigned long) sgl | 0x01); + prv[prv_nents - 1].page_link = (unsigned long) sgl | 0x01; +} + +/** + * sg_mark_end - Mark the end of the scatterlist + * @sgl: Scatterlist + * @nents: Number of entries in sgl + * + * Description: + * Marks the last entry as the termination point for sg_next() + * + **/ +static inline void sg_mark_end(struct scatterlist *sgl, unsigned int nents) +{ + sgl[nents - 1].page_link = 0x02; +} + +static inline void __sg_mark_end(struct scatterlist *sg) +{ + sg->page_link |= 0x02; +} + +/** + * sg_init_one - Initialize a single entry sg list + * @sg: SG entry + * @buf: Virtual address for IO + * @buflen: IO length + * + * Notes: + * This should not be used on a single entry that is part of a larger + * table. Use sg_init_table() for that. + * + **/ +static inline void sg_init_one(struct scatterlist *sg, const void *buf, + unsigned int buflen) +{ + memset(sg, 0, sizeof(*sg)); +#ifdef CONFIG_DEBUG_SG + sg->sg_magic = SG_MAGIC; +#endif + sg_mark_end(sg, 1); + sg_set_buf(sg, buf, buflen); +} + +/** + * sg_init_table - Initialize SG table + * @sgl: The SG table + * @nents: Number of entries in table + * + * Notes: + * If this is part of a chained sg table, sg_mark_end() should be + * used only on the last table part. + * + **/ +static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents) +{ + memset(sgl, 0, sizeof(*sgl) * nents); + sg_mark_end(sgl, nents); +#ifdef CONFIG_DEBUG_SG + { + int i; + for (i = 0; i < nents; i++) + sgl[i].sg_magic = SG_MAGIC; + } +#endif +} + +/** + * sg_phys - Return physical address of an sg entry + * @sg: SG entry + * + * Description: + * This calls page_to_phys() on the page in this sg entry, and adds the + * sg offset. The caller must know that it is legal to call page_to_phys() + * on the sg page. + * + **/ +static inline unsigned long sg_phys(struct scatterlist *sg) +{ + return page_to_phys(sg_page(sg)) + sg->offset; +} + +/** + * sg_virt - Return virtual address of an sg entry + * @sg: SG entry + * + * Description: + * This calls page_address() on the page in this sg entry, and adds the + * sg offset. The caller must know that the sg page has a valid virtual + * mapping. + * + **/ +static inline void *sg_virt(struct scatterlist *sg) +{ + return page_address(sg_page(sg)) + sg->offset; } #endif /* _LINUX_SCATTERLIST_H */ diff --git a/init/Kconfig b/init/Kconfig index 541382d539a..b7dffa83792 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -234,6 +234,10 @@ config AUDITSYSCALL such as SELinux. To use audit's filesystem watch feature, please ensure that INOTIFY is configured. +config AUDIT_TREE + def_bool y + depends on AUDITSYSCALL && INOTIFY + config IKCONFIG tristate "Kernel .config support" ---help--- diff --git a/ipc/mqueue.c b/ipc/mqueue.c index c0b26dc4617..bfa274ba9ed 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -676,7 +676,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, if (oflag & O_CREAT) { if (dentry->d_inode) { /* entry already exists */ - audit_inode(name, dentry->d_inode); + audit_inode(name, dentry); error = -EEXIST; if (oflag & O_EXCL) goto out; @@ -689,7 +689,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, error = -ENOENT; if (!dentry->d_inode) goto out; - audit_inode(name, dentry->d_inode); + audit_inode(name, dentry); filp = do_open(dentry, oflag); } @@ -837,7 +837,7 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, if (unlikely(filp->f_op != &mqueue_file_operations)) goto out_fput; info = MQUEUE_I(inode); - audit_inode(NULL, inode); + audit_inode(NULL, filp->f_path.dentry); if (unlikely(!(filp->f_mode & FMODE_WRITE))) goto out_fput; @@ -921,7 +921,7 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, if (unlikely(filp->f_op != &mqueue_file_operations)) goto out_fput; info = MQUEUE_I(inode); - audit_inode(NULL, inode); + audit_inode(NULL, filp->f_path.dentry); if (unlikely(!(filp->f_mode & FMODE_READ))) goto out_fput; diff --git a/kernel/Makefile b/kernel/Makefile index 79f017e09fb..f60afe74259 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -46,6 +46,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o +obj-$(CONFIG_AUDIT_TREE) += audit_tree.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_SYSFS) += ksysfs.o obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o diff --git a/kernel/audit.c b/kernel/audit.c index 6977ea57a7e..f93c2713017 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -468,6 +468,21 @@ int audit_send_list(void *_dest) return 0; } +#ifdef CONFIG_AUDIT_TREE +static int prune_tree_thread(void *unused) +{ + mutex_lock(&audit_cmd_mutex); + audit_prune_trees(); + mutex_unlock(&audit_cmd_mutex); + return 0; +} + +void audit_schedule_prune(void) +{ + kthread_run(prune_tree_thread, NULL, "audit_prune_tree"); +} +#endif + struct sk_buff *audit_make_reply(int pid, int seq, int type, int done, int multi, void *payload, int size) { @@ -540,6 +555,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) case AUDIT_SIGNAL_INFO: case AUDIT_TTY_GET: case AUDIT_TTY_SET: + case AUDIT_TRIM: + case AUDIT_MAKE_EQUIV: if (security_netlink_recv(skb, CAP_AUDIT_CONTROL)) err = -EPERM; break; @@ -756,6 +773,76 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) uid, seq, data, nlmsg_len(nlh), loginuid, sid); break; + case AUDIT_TRIM: + audit_trim_trees(); + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + if (!ab) + break; + audit_log_format(ab, "auid=%u", loginuid); + if (sid) { + u32 len; + ctx = NULL; + if (selinux_sid_to_string(sid, &ctx, &len)) + audit_log_format(ab, " ssid=%u", sid); + else + audit_log_format(ab, " subj=%s", ctx); + kfree(ctx); + } + audit_log_format(ab, " op=trim res=1"); + audit_log_end(ab); + break; + case AUDIT_MAKE_EQUIV: { + void *bufp = data; + u32 sizes[2]; + size_t len = nlmsg_len(nlh); + char *old, *new; + + err = -EINVAL; + if (len < 2 * sizeof(u32)) + break; + memcpy(sizes, bufp, 2 * sizeof(u32)); + bufp += 2 * sizeof(u32); + len -= 2 * sizeof(u32); + old = audit_unpack_string(&bufp, &len, sizes[0]); + if (IS_ERR(old)) { + err = PTR_ERR(old); + break; + } + new = audit_unpack_string(&bufp, &len, sizes[1]); + if (IS_ERR(new)) { + err = PTR_ERR(new); + kfree(old); + break; + } + /* OK, here comes... */ + err = audit_tag_tree(old, new); + + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + if (!ab) { + kfree(old); + kfree(new); + break; + } + audit_log_format(ab, "auid=%u", loginuid); + if (sid) { + u32 len; + ctx = NULL; + if (selinux_sid_to_string(sid, &ctx, &len)) + audit_log_format(ab, " ssid=%u", sid); + else + audit_log_format(ab, " subj=%s", ctx); + kfree(ctx); + } + audit_log_format(ab, " op=make_equiv old="); + audit_log_untrustedstring(ab, old); + audit_log_format(ab, " new="); + audit_log_untrustedstring(ab, new); + audit_log_format(ab, " res=%d", !err); + audit_log_end(ab); + kfree(old); + kfree(new); + break; + } case AUDIT_SIGNAL_INFO: err = selinux_sid_to_string(audit_sig_sid, &ctx, &len); if (err) diff --git a/kernel/audit.h b/kernel/audit.h index 95877435c34..2554bd524fd 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -73,6 +73,9 @@ struct audit_field { struct selinux_audit_rule *se_rule; }; +struct audit_tree; +struct audit_chunk; + struct audit_krule { int vers_ops; u32 flags; @@ -86,7 +89,8 @@ struct audit_krule { struct audit_field *arch_f; /* quick access to arch field */ struct audit_field *inode_f; /* quick access to an inode field */ struct audit_watch *watch; /* associated watch */ - struct list_head rlist; /* entry in audit_watch.rules list */ + struct audit_tree *tree; /* associated watched tree */ + struct list_head rlist; /* entry in audit_{watch,tree}.rules list */ }; struct audit_entry { @@ -130,6 +134,34 @@ extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32, const char *, struct inode *); extern int selinux_audit_rule_update(void); +extern struct mutex audit_filter_mutex; +extern void audit_free_rule_rcu(struct rcu_head *); + +#ifdef CONFIG_AUDIT_TREE +extern struct audit_chunk *audit_tree_lookup(const struct inode *); +extern void audit_put_chunk(struct audit_chunk *); +extern int audit_tree_match(struct audit_chunk *, struct audit_tree *); +extern int audit_make_tree(struct audit_krule *, char *, u32); +extern int audit_add_tree_rule(struct audit_krule *); +extern int audit_remove_tree_rule(struct audit_krule *); +extern void audit_trim_trees(void); +extern int audit_tag_tree(char *old, char *new); +extern void audit_schedule_prune(void); +extern void audit_prune_trees(void); +extern const char *audit_tree_path(struct audit_tree *); +extern void audit_put_tree(struct audit_tree *); +#else +#define audit_remove_tree_rule(rule) BUG() +#define audit_add_tree_rule(rule) -EINVAL +#define audit_make_tree(rule, str, op) -EINVAL +#define audit_trim_trees() (void)0 +#define audit_put_tree(tree) (void)0 +#define audit_tag_tree(old, new) -EINVAL +#define audit_tree_path(rule) "" /* never called */ +#endif + +extern char *audit_unpack_string(void **, size_t *, size_t); + #ifdef CONFIG_AUDITSYSCALL extern int __audit_signal_info(int sig, struct task_struct *t); static inline int audit_signal_info(int sig, struct task_struct *t) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c new file mode 100644 index 00000000000..f4fcf58f20f --- /dev/null +++ b/kernel/audit_tree.c @@ -0,0 +1,903 @@ +#include "audit.h" +#include <linux/inotify.h> +#include <linux/namei.h> +#include <linux/mount.h> + +struct audit_tree; +struct audit_chunk; + +struct audit_tree { + atomic_t count; + int goner; + struct audit_chunk *root; + struct list_head chunks; + struct list_head rules; + struct list_head list; + struct list_head same_root; + struct rcu_head head; + char pathname[]; +}; + +struct audit_chunk { + struct list_head hash; + struct inotify_watch watch; + struct list_head trees; /* with root here */ + int dead; + int count; + struct rcu_head head; + struct node { + struct list_head list; + struct audit_tree *owner; + unsigned index; /* index; upper bit indicates 'will prune' */ + } owners[]; +}; + +static LIST_HEAD(tree_list); +static LIST_HEAD(prune_list); + +/* + * One struct chunk is attached to each inode of interest. + * We replace struct chunk on tagging/untagging. + * Rules have pointer to struct audit_tree. + * Rules have struct list_head rlist forming a list of rules over + * the same tree. + * References to struct chunk are collected at audit_inode{,_child}() + * time and used in AUDIT_TREE rule matching. + * These references are dropped at the same time we are calling + * audit_free_names(), etc. + * + * Cyclic lists galore: + * tree.chunks anchors chunk.owners[].list hash_lock + * tree.rules anchors rule.rlist audit_filter_mutex + * chunk.trees anchors tree.same_root hash_lock + * chunk.hash is a hash with middle bits of watch.inode as + * a hash function. RCU, hash_lock + * + * tree is refcounted; one reference for "some rules on rules_list refer to + * it", one for each chunk with pointer to it. + * + * chunk is refcounted by embedded inotify_watch. + * + * node.index allows to get from node.list to containing chunk. + * MSB of that sucker is stolen to mark taggings that we might have to + * revert - several operations have very unpleasant cleanup logics and + * that makes a difference. Some. + */ + +static struct inotify_handle *rtree_ih; + +static struct audit_tree *alloc_tree(const char *s) +{ + struct audit_tree *tree; + + tree = kmalloc(sizeof(struct audit_tree) + strlen(s) + 1, GFP_KERNEL); + if (tree) { + atomic_set(&tree->count, 1); + tree->goner = 0; + INIT_LIST_HEAD(&tree->chunks); + INIT_LIST_HEAD(&tree->rules); + INIT_LIST_HEAD(&tree->list); + INIT_LIST_HEAD(&tree->same_root); + tree->root = NULL; + strcpy(tree->pathname, s); + } + return tree; +} + +static inline void get_tree(struct audit_tree *tree) +{ + atomic_inc(&tree->count); +} + +static void __put_tree(struct rcu_head *rcu) +{ + struct audit_tree *tree = container_of(rcu, struct audit_tree, head); + kfree(tree); +} + +static inline void put_tree(struct audit_tree *tree) +{ + if (atomic_dec_and_test(&tree->count)) + call_rcu(&tree->head, __put_tree); +} + +/* to avoid bringing the entire thing in audit.h */ +const char *audit_tree_path(struct audit_tree *tree) +{ + return tree->pathname; +} + +static struct audit_chunk *alloc_chunk(int count) +{ + struct audit_chunk *chunk; + size_t size; + int i; + + size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node); + chunk = kzalloc(size, GFP_KERNEL); + if (!chunk) + return NULL; + + INIT_LIST_HEAD(&chunk->hash); + INIT_LIST_HEAD(&chunk->trees); + chunk->count = count; + for (i = 0; i < count; i++) { + INIT_LIST_HEAD(&chunk->owners[i].list); + chunk->owners[i].index = i; + } + inotify_init_watch(&chunk->watch); + return chunk; +} + +static void __free_chunk(struct rcu_head *rcu) +{ + struct audit_chunk *chunk = container_of(rcu, struct audit_chunk, head); + int i; + + for (i = 0; i < chunk->count; i++) { + if (chunk->owners[i].owner) + put_tree(chunk->owners[i].owner); + } + kfree(chunk); +} + +static inline void free_chunk(struct audit_chunk *chunk) +{ + call_rcu(&chunk->head, __free_chunk); +} + +void audit_put_chunk(struct audit_chunk *chunk) +{ + put_inotify_watch(&chunk->watch); +} + +enum {HASH_SIZE = 128}; +static struct list_head chunk_hash_heads[HASH_SIZE]; +static __cacheline_aligned_in_smp DEFINE_SPINLOCK(hash_lock); + +static inline struct list_head *chunk_hash(const struct inode *inode) +{ + unsigned long n = (unsigned long)inode / L1_CACHE_BYTES; + return chunk_hash_heads + n % HASH_SIZE; +} + +/* hash_lock is held by caller */ +static void insert_hash(struct audit_chunk *chunk) +{ + struct list_head *list = chunk_hash(chunk->watch.inode); + list_add_rcu(&chunk->hash, list); +} + +/* called under rcu_read_lock */ +struct audit_chunk *audit_tree_lookup(const struct inode *inode) +{ + struct list_head *list = chunk_hash(inode); + struct list_head *pos; + + list_for_each_rcu(pos, list) { + struct audit_chunk *p = container_of(pos, struct audit_chunk, hash); + if (p->watch.inode == inode) { + get_inotify_watch(&p->watch); + return p; + } + } + return NULL; +} + +int audit_tree_match(struct audit_chunk *chunk, struct audit_tree *tree) +{ + int n; + for (n = 0; n < chunk->count; n++) + if (chunk->owners[n].owner == tree) + return 1; + return 0; +} + +/* tagging and untagging inodes with trees */ + +static void untag_chunk(struct audit_chunk *chunk, struct node *p) +{ + struct audit_chunk *new; + struct audit_tree *owner; + int size = chunk->count - 1; + int i, j; + + mutex_lock(&chunk->watch.inode->inotify_mutex); + if (chunk->dead) { + mutex_unlock(&chunk->watch.inode->inotify_mutex); + return; + } + + owner = p->owner; + + if (!size) { + chunk->dead = 1; + spin_lock(&hash_lock); + list_del_init(&chunk->trees); + if (owner->root == chunk) + owner->root = NULL; + list_del_init(&p->list); + list_del_rcu(&chunk->hash); + spin_unlock(&hash_lock); + inotify_evict_watch(&chunk->watch); + mutex_unlock(&chunk->watch.inode->inotify_mutex); + put_inotify_watch(&chunk->watch); + return; + } + + new = alloc_chunk(size); + if (!new) + goto Fallback; + if (inotify_clone_watch(&chunk->watch, &new->watch) < 0) { + free_chunk(new); + goto Fallback; + } + + chunk->dead = 1; + spin_lock(&hash_lock); + list_replace_init(&chunk->trees, &new->trees); + if (owner->root == chunk) { + list_del_init(&owner->same_root); + owner->root = NULL; + } + + for (i = j = 0; i < size; i++, j++) { + struct audit_tree *s; + if (&chunk->owners[j] == p) { + list_del_init(&p->list); + i--; + continue; + } + s = chunk->owners[j].owner; + new->owners[i].owner = s; + new->owners[i].index = chunk->owners[j].index - j + i; + if (!s) /* result of earlier fallback */ + continue; + get_tree(s); + list_replace_init(&chunk->owners[i].list, &new->owners[j].list); + } + + list_replace_rcu(&chunk->hash, &new->hash); + list_for_each_entry(owner, &new->trees, same_root) + owner->root = new; + spin_unlock(&hash_lock); + inotify_evict_watch(&chunk->watch); + mutex_unlock(&chunk->watch.inode->inotify_mutex); + put_inotify_watch(&chunk->watch); + return; + +Fallback: + // do the best we can + spin_lock(&hash_lock); + if (owner->root == chunk) { + list_del_init(&owner->same_root); + owner->root = NULL; + } + list_del_init(&p->list); + p->owner = NULL; + put_tree(owner); + spin_unlock(&hash_lock); + mutex_unlock(&chunk->watch.inode->inotify_mutex); +} + +static int create_chunk(struct inode *inode, struct audit_tree *tree) +{ + struct audit_chunk *chunk = alloc_chunk(1); + if (!chunk) + return -ENOMEM; + + if (inotify_add_watch(rtree_ih, &chunk->watch, inode, IN_IGNORED | IN_DELETE_SELF) < 0) { + free_chunk(chunk); + return -ENOSPC; + } + + mutex_lock(&inode->inotify_mutex); + spin_lock(&hash_lock); + if (tree->goner) { + spin_unlock(&hash_lock); + chunk->dead = 1; + inotify_evict_watch(&chunk->watch); + mutex_unlock(&inode->inotify_mutex); + put_inotify_watch(&chunk->watch); + return 0; + } + chunk->owners[0].index = (1U << 31); + chunk->owners[0].owner = tree; + get_tree(tree); + list_add(&chunk->owners[0].list, &tree->chunks); + if (!tree->root) { + tree->root = chunk; + list_add(&tree->same_root, &chunk->trees); + } + insert_hash(chunk); + spin_unlock(&hash_lock); + mutex_unlock(&inode->inotify_mutex); + return 0; +} + +/* the first tagged inode becomes root of tree */ +static int tag_chunk(struct inode *inode, struct audit_tree *tree) +{ + struct inotify_watch *watch; + struct audit_tree *owner; + struct audit_chunk *chunk, *old; + struct node *p; + int n; + + if (inotify_find_watch(rtree_ih, inode, &watch) < 0) + return create_chunk(inode, tree); + + old = container_of(watch, struct audit_chunk, watch); + + /* are we already there? */ + spin_lock(&hash_lock); + for (n = 0; n < old->count; n++) { + if (old->owners[n].owner == tree) { + spin_unlock(&hash_lock); + put_inotify_watch(watch); + return 0; + } + } + spin_unlock(&hash_lock); + + chunk = alloc_chunk(old->count + 1); + if (!chunk) + return -ENOMEM; + + mutex_lock(&inode->inotify_mutex); + if (inotify_clone_watch(&old->watch, &chunk->watch) < 0) { + mutex_unlock(&inode->inotify_mutex); + free_chunk(chunk); + return -ENOSPC; + } + spin_lock(&hash_lock); + if (tree->goner) { + spin_unlock(&hash_lock); + chunk->dead = 1; + inotify_evict_watch(&chunk->watch); + mutex_unlock(&inode->inotify_mutex); + put_inotify_watch(&chunk->watch); + return 0; + } + list_replace_init(&old->trees, &chunk->trees); + for (n = 0, p = chunk->owners; n < old->count; n++, p++) { + struct audit_tree *s = old->owners[n].owner; + p->owner = s; + p->index = old->owners[n].index; + if (!s) /* result of fallback in untag */ + continue; + get_tree(s); + list_replace_init(&old->owners[n].list, &p->list); + } + p->index = (chunk->count - 1) | (1U<<31); + p->owner = tree; + get_tree(tree); + list_add(&p->list, &tree->chunks); + list_replace_rcu(&old->hash, &chunk->hash); + list_for_each_entry(owner, &chunk->trees, same_root) + owner->root = chunk; + old->dead = 1; + if (!tree->root) { + tree->root = chunk; + list_add(&tree->same_root, &chunk->trees); + } + spin_unlock(&hash_lock); + inotify_evict_watch(&old->watch); + mutex_unlock(&inode->inotify_mutex); + put_inotify_watch(&old->watch); + return 0; +} + +static struct audit_chunk *find_chunk(struct node *p) +{ + int index = p->index & ~(1U<<31); + p -= index; + return container_of(p, struct audit_chunk, owners[0]); +} + +static void kill_rules(struct audit_tree *tree) +{ + struct audit_krule *rule, *next; + struct audit_entry *entry; + struct audit_buffer *ab; + + list_for_each_entry_safe(rule, next, &tree->rules, rlist) { + entry = container_of(rule, struct audit_entry, rule); + + list_del_init(&rule->rlist); + if (rule->tree) { + /* not a half-baked one */ + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); + audit_log_format(ab, "op=remove rule dir="); + audit_log_untrustedstring(ab, rule->tree->pathname); + if (rule->filterkey) { + audit_log_format(ab, " key="); + audit_log_untrustedstring(ab, rule->filterkey); + } else + audit_log_format(ab, " key=(null)"); + audit_log_format(ab, " list=%d res=1", rule->listnr); + audit_log_end(ab); + rule->tree = NULL; + list_del_rcu(&entry->list); + call_rcu(&entry->rcu, audit_free_rule_rcu); + } + } +} + +/* + * finish killing struct audit_tree + */ +static void prune_one(struct audit_tree *victim) +{ + spin_lock(&hash_lock); + while (!list_empty(&victim->chunks)) { + struct node *p; + struct audit_chunk *chunk; + + p = list_entry(victim->chunks.next, struct node, list); + chunk = find_chunk(p); + get_inotify_watch(&chunk->watch); + spin_unlock(&hash_lock); + + untag_chunk(chunk, p); + + put_inotify_watch(&chunk->watch); + spin_lock(&hash_lock); + } + spin_unlock(&hash_lock); + put_tree(victim); +} + +/* trim the uncommitted chunks from tree */ + +static void trim_marked(struct audit_tree *tree) +{ + struct list_head *p, *q; + spin_lock(&hash_lock); + if (tree->goner) { + spin_unlock(&hash_lock); + return; + } + /* reorder */ + for (p = tree->chunks.next; p != &tree->chunks; p = q) { + struct node *node = list_entry(p, struct node, list); + q = p->next; + if (node->index & (1U<<31)) { + list_del_init(p); + list_add(p, &tree->chunks); + } + } + + while (!list_empty(&tree->chunks)) { + struct node *node; + struct audit_chunk *chunk; + + node = list_entry(tree->chunks.next, struct node, list); + + /* have we run out of marked? */ + if (!(node->index & (1U<<31))) + break; + + chunk = find_chunk(node); + get_inotify_watch(&chunk->watch); + spin_unlock(&hash_lock); + + untag_chunk(chunk, node); + + put_inotify_watch(&chunk->watch); + spin_lock(&hash_lock); + } + if (!tree->root && !tree->goner) { + tree->goner = 1; + spin_unlock(&hash_lock); + mutex_lock(&audit_filter_mutex); + kill_rules(tree); + list_del_init(&tree->list); + mutex_unlock(&audit_filter_mutex); + prune_one(tree); + } else { + spin_unlock(&hash_lock); + } +} + +/* called with audit_filter_mutex */ +int audit_remove_tree_rule(struct audit_krule *rule) +{ + struct audit_tree *tree; + tree = rule->tree; + if (tree) { + spin_lock(&hash_lock); + list_del_init(&rule->rlist); + if (list_empty(&tree->rules) && !tree->goner) { + tree->root = NULL; + list_del_init(&tree->same_root); + tree->goner = 1; + list_move(&tree->list, &prune_list); + rule->tree = NULL; + spin_unlock(&hash_lock); + audit_schedule_prune(); + return 1; + } + rule->tree = NULL; + spin_unlock(&hash_lock); + return 1; + } + return 0; +} + +void audit_trim_trees(void) +{ + struct list_head cursor; + + mutex_lock(&audit_filter_mutex); + list_add(&cursor, &tree_list); + while (cursor.next != &tree_list) { + struct audit_tree *tree; + struct nameidata nd; + struct vfsmount *root_mnt; + struct node *node; + struct list_head list; + int err; + + tree = container_of(cursor.next, struct audit_tree, list); + get_tree(tree); + list_del(&cursor); + list_add(&cursor, &tree->list); + mutex_unlock(&audit_filter_mutex); + + err = path_lookup(tree->pathname, 0, &nd); + if (err) + goto skip_it; + + root_mnt = collect_mounts(nd.mnt, nd.dentry); + path_release(&nd); + if (!root_mnt) + goto skip_it; + + list_add_tail(&list, &root_mnt->mnt_list); + spin_lock(&hash_lock); + list_for_each_entry(node, &tree->chunks, list) { + struct audit_chunk *chunk = find_chunk(node); + struct inode *inode = chunk->watch.inode; + struct vfsmount *mnt; + node->index |= 1U<<31; + list_for_each_entry(mnt, &list, mnt_list) { + if (mnt->mnt_root->d_inode == inode) { + node->index &= ~(1U<<31); + break; + } + } + } + spin_unlock(&hash_lock); + trim_marked(tree); + put_tree(tree); + list_del_init(&list); + drop_collected_mounts(root_mnt); +skip_it: + mutex_lock(&audit_filter_mutex); + } + list_del(&cursor); + mutex_unlock(&audit_filter_mutex); +} + +static int is_under(struct vfsmount *mnt, struct dentry *dentry, + struct nameidata *nd) +{ + if (mnt != nd->mnt) { + for (;;) { + if (mnt->mnt_parent == mnt) + return 0; + if (mnt->mnt_parent == nd->mnt) + break; + mnt = mnt->mnt_parent; + } + dentry = mnt->mnt_mountpoint; + } + return is_subdir(dentry, nd->dentry); +} + +int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) +{ + + if (pathname[0] != '/' || + rule->listnr != AUDIT_FILTER_EXIT || + op & ~AUDIT_EQUAL || + rule->inode_f || rule->watch || rule->tree) + return -EINVAL; + rule->tree = alloc_tree(pathname); + if (!rule->tree) + return -ENOMEM; + return 0; +} + +void audit_put_tree(struct audit_tree *tree) +{ + put_tree(tree); +} + +/* called with audit_filter_mutex */ +int audit_add_tree_rule(struct audit_krule *rule) +{ + struct audit_tree *seed = rule->tree, *tree; + struct nameidata nd; + struct vfsmount *mnt, *p; + struct list_head list; + int err; + + list_for_each_entry(tree, &tree_list, list) { + if (!strcmp(seed->pathname, tree->pathname)) { + put_tree(seed); + rule->tree = tree; + list_add(&rule->rlist, &tree->rules); + return 0; + } + } + tree = seed; + list_add(&tree->list, &tree_list); + list_add(&rule->rlist, &tree->rules); + /* do not set rule->tree yet */ + mutex_unlock(&audit_filter_mutex); + + err = path_lookup(tree->pathname, 0, &nd); + if (err) + goto Err; + mnt = collect_mounts(nd.mnt, nd.dentry); + path_release(&nd); + if (!mnt) { + err = -ENOMEM; + goto Err; + } + list_add_tail(&list, &mnt->mnt_list); + + get_tree(tree); + list_for_each_entry(p, &list, mnt_list) { + err = tag_chunk(p->mnt_root->d_inode, tree); + if (err) + break; + } + + list_del(&list); + drop_collected_mounts(mnt); + + if (!err) { + struct node *node; + spin_lock(&hash_lock); + list_for_each_entry(node, &tree->chunks, list) + node->index &= ~(1U<<31); + spin_unlock(&hash_lock); + } else { + trim_marked(tree); + goto Err; + } + + mutex_lock(&audit_filter_mutex); + if (list_empty(&rule->rlist)) { + put_tree(tree); + return -ENOENT; + } + rule->tree = tree; + put_tree(tree); + + return 0; +Err: + mutex_lock(&audit_filter_mutex); + list_del_init(&tree->list); + list_del_init(&tree->rules); + put_tree(tree); + return err; +} + +int audit_tag_tree(char *old, char *new) +{ + struct list_head cursor, barrier; + int failed = 0; + struct nameidata nd; + struct vfsmount *tagged; + struct list_head list; + struct vfsmount *mnt; + struct dentry *dentry; + int err; + + err = path_lookup(new, 0, &nd); + if (err) + return err; + tagged = collect_mounts(nd.mnt, nd.dentry); + path_release(&nd); + if (!tagged) + return -ENOMEM; + + err = path_lookup(old, 0, &nd); + if (err) { + drop_collected_mounts(tagged); + return err; + } + mnt = mntget(nd.mnt); + dentry = dget(nd.dentry); + path_release(&nd); + + if (dentry == tagged->mnt_root && dentry == mnt->mnt_root) + follow_up(&mnt, &dentry); + + list_add_tail(&list, &tagged->mnt_list); + + mutex_lock(&audit_filter_mutex); + list_add(&barrier, &tree_list); + list_add(&cursor, &barrier); + + while (cursor.next != &tree_list) { + struct audit_tree *tree; + struct vfsmount *p; + + tree = container_of(cursor.next, struct audit_tree, list); + get_tree(tree); + list_del(&cursor); + list_add(&cursor, &tree->list); + mutex_unlock(&audit_filter_mutex); + + err = path_lookup(tree->pathname, 0, &nd); + if (err) { + put_tree(tree); + mutex_lock(&audit_filter_mutex); + continue; + } + + spin_lock(&vfsmount_lock); + if (!is_under(mnt, dentry, &nd)) { + spin_unlock(&vfsmount_lock); + path_release(&nd); + put_tree(tree); + mutex_lock(&audit_filter_mutex); + continue; + } + spin_unlock(&vfsmount_lock); + path_release(&nd); + + list_for_each_entry(p, &list, mnt_list) { + failed = tag_chunk(p->mnt_root->d_inode, tree); + if (failed) + break; + } + + if (failed) { + put_tree(tree); + mutex_lock(&audit_filter_mutex); + break; + } + + mutex_lock(&audit_filter_mutex); + spin_lock(&hash_lock); + if (!tree->goner) { + list_del(&tree->list); + list_add(&tree->list, &tree_list); + } + spin_unlock(&hash_lock); + put_tree(tree); + } + + while (barrier.prev != &tree_list) { + struct audit_tree *tree; + + tree = container_of(barrier.prev, struct audit_tree, list); + get_tree(tree); + list_del(&tree->list); + list_add(&tree->list, &barrier); + mutex_unlock(&audit_filter_mutex); + + if (!failed) { + struct node *node; + spin_lock(&hash_lock); + list_for_each_entry(node, &tree->chunks, list) + node->index &= ~(1U<<31); + spin_unlock(&hash_lock); + } else { + trim_marked(tree); + } + + put_tree(tree); + mutex_lock(&audit_filter_mutex); + } + list_del(&barrier); + list_del(&cursor); + list_del(&list); + mutex_unlock(&audit_filter_mutex); + dput(dentry); + mntput(mnt); + drop_collected_mounts(tagged); + return failed; +} + +/* + * That gets run when evict_chunk() ends up needing to kill audit_tree. + * Runs from a separate thread, with audit_cmd_mutex held. + */ +void audit_prune_trees(void) +{ + mutex_lock(&audit_filter_mutex); + + while (!list_empty(&prune_list)) { + struct audit_tree *victim; + + victim = list_entry(prune_list.next, struct audit_tree, list); + list_del_init(&victim->list); + + mutex_unlock(&audit_filter_mutex); + + prune_one(victim); + + mutex_lock(&audit_filter_mutex); + } + + mutex_unlock(&audit_filter_mutex); +} + +/* + * Here comes the stuff asynchronous to auditctl operations + */ + +/* inode->inotify_mutex is locked */ +static void evict_chunk(struct audit_chunk *chunk) +{ + struct audit_tree *owner; + int n; + + if (chunk->dead) + return; + + chunk->dead = 1; + mutex_lock(&audit_filter_mutex); + spin_lock(&hash_lock); + while (!list_empty(&chunk->trees)) { + owner = list_entry(chunk->trees.next, + struct audit_tree, same_root); + owner->goner = 1; + owner->root = NULL; + list_del_init(&owner->same_root); + spin_unlock(&hash_lock); + kill_rules(owner); + list_move(&owner->list, &prune_list); + audit_schedule_prune(); + spin_lock(&hash_lock); + } + list_del_rcu(&chunk->hash); + for (n = 0; n < chunk->count; n++) + list_del_init(&chunk->owners[n].list); + spin_unlock(&hash_lock); + mutex_unlock(&audit_filter_mutex); +} + +static void handle_event(struct inotify_watch *watch, u32 wd, u32 mask, + u32 cookie, const char *dname, struct inode *inode) +{ + struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch); + + if (mask & IN_IGNORED) { + evict_chunk(chunk); + put_inotify_watch(watch); + } +} + +static void destroy_watch(struct inotify_watch *watch) +{ + struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch); + free_chunk(chunk); +} + +static const struct inotify_operations rtree_inotify_ops = { + .handle_event = handle_event, + .destroy_watch = destroy_watch, +}; + +static int __init audit_tree_init(void) +{ + int i; + + rtree_ih = inotify_init(&rtree_inotify_ops); + if (IS_ERR(rtree_ih)) + audit_panic("cannot initialize inotify handle for rectree watches"); + + for (i = 0; i < HASH_SIZE; i++) + INIT_LIST_HEAD(&chunk_hash_heads[i]); + + return 0; +} +__initcall(audit_tree_init); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index df66a21fb36..5d96f2cc7be 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -87,7 +87,7 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = { #endif }; -static DEFINE_MUTEX(audit_filter_mutex); +DEFINE_MUTEX(audit_filter_mutex); /* Inotify handle */ extern struct inotify_handle *audit_ih; @@ -145,7 +145,7 @@ static inline void audit_free_rule(struct audit_entry *e) kfree(e); } -static inline void audit_free_rule_rcu(struct rcu_head *head) +void audit_free_rule_rcu(struct rcu_head *head) { struct audit_entry *e = container_of(head, struct audit_entry, rcu); audit_free_rule(e); @@ -217,7 +217,7 @@ static inline struct audit_entry *audit_init_entry(u32 field_count) /* Unpack a filter field's string representation from user-space * buffer. */ -static char *audit_unpack_string(void **bufp, size_t *remain, size_t len) +char *audit_unpack_string(void **bufp, size_t *remain, size_t len) { char *str; @@ -247,7 +247,7 @@ static inline int audit_to_inode(struct audit_krule *krule, struct audit_field *f) { if (krule->listnr != AUDIT_FILTER_EXIT || - krule->watch || krule->inode_f) + krule->watch || krule->inode_f || krule->tree) return -EINVAL; krule->inode_f = f; @@ -266,7 +266,7 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len, if (path[0] != '/' || path[len-1] == '/' || krule->listnr != AUDIT_FILTER_EXIT || op & ~AUDIT_EQUAL || - krule->inode_f || krule->watch) /* 1 inode # per rule, for hash */ + krule->inode_f || krule->watch || krule->tree) return -EINVAL; watch = audit_init_watch(path); @@ -622,6 +622,17 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, goto exit_free; } break; + case AUDIT_DIR: + str = audit_unpack_string(&bufp, &remain, f->val); + if (IS_ERR(str)) + goto exit_free; + entry->rule.buflen += f->val; + + err = audit_make_tree(&entry->rule, str, f->op); + kfree(str); + if (err) + goto exit_free; + break; case AUDIT_INODE: err = audit_to_inode(&entry->rule, f); if (err) @@ -668,7 +679,7 @@ exit_free: } /* Pack a filter field's string representation into data block. */ -static inline size_t audit_pack_string(void **bufp, char *str) +static inline size_t audit_pack_string(void **bufp, const char *str) { size_t len = strlen(str); @@ -747,6 +758,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) data->buflen += data->values[i] = audit_pack_string(&bufp, krule->watch->path); break; + case AUDIT_DIR: + data->buflen += data->values[i] = + audit_pack_string(&bufp, + audit_tree_path(krule->tree)); + break; case AUDIT_FILTERKEY: data->buflen += data->values[i] = audit_pack_string(&bufp, krule->filterkey); @@ -795,6 +811,11 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) if (strcmp(a->watch->path, b->watch->path)) return 1; break; + case AUDIT_DIR: + if (strcmp(audit_tree_path(a->tree), + audit_tree_path(b->tree))) + return 1; + break; case AUDIT_FILTERKEY: /* both filterkeys exist based on above type compare */ if (strcmp(a->filterkey, b->filterkey)) @@ -897,6 +918,14 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old, new->inode_f = old->inode_f; new->watch = NULL; new->field_count = old->field_count; + /* + * note that we are OK with not refcounting here; audit_match_tree() + * never dereferences tree and we can't get false positives there + * since we'd have to have rule gone from the list *and* removed + * before the chunks found by lookup had been allocated, i.e. before + * the beginning of list scan. + */ + new->tree = old->tree; memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount); /* deep copy this information, updating the se_rule fields, because @@ -1217,6 +1246,7 @@ static inline int audit_add_rule(struct audit_entry *entry, struct audit_entry *e; struct audit_field *inode_f = entry->rule.inode_f; struct audit_watch *watch = entry->rule.watch; + struct audit_tree *tree = entry->rule.tree; struct nameidata *ndp = NULL, *ndw = NULL; int h, err; #ifdef CONFIG_AUDITSYSCALL @@ -1238,6 +1268,9 @@ static inline int audit_add_rule(struct audit_entry *entry, mutex_unlock(&audit_filter_mutex); if (e) { err = -EEXIST; + /* normally audit_add_tree_rule() will free it on failure */ + if (tree) + audit_put_tree(tree); goto error; } @@ -1259,6 +1292,13 @@ static inline int audit_add_rule(struct audit_entry *entry, h = audit_hash_ino((u32)watch->ino); list = &audit_inode_hash[h]; } + if (tree) { + err = audit_add_tree_rule(&entry->rule); + if (err) { + mutex_unlock(&audit_filter_mutex); + goto error; + } + } if (entry->rule.flags & AUDIT_FILTER_PREPEND) { list_add_rcu(&entry->list, list); @@ -1292,6 +1332,7 @@ static inline int audit_del_rule(struct audit_entry *entry, struct audit_entry *e; struct audit_field *inode_f = entry->rule.inode_f; struct audit_watch *watch, *tmp_watch = entry->rule.watch; + struct audit_tree *tree = entry->rule.tree; LIST_HEAD(inotify_list); int h, ret = 0; #ifdef CONFIG_AUDITSYSCALL @@ -1336,6 +1377,9 @@ static inline int audit_del_rule(struct audit_entry *entry, } } + if (e->rule.tree) + audit_remove_tree_rule(&e->rule); + list_del_rcu(&e->list); call_rcu(&e->rcu, audit_free_rule_rcu); @@ -1354,6 +1398,8 @@ static inline int audit_del_rule(struct audit_entry *entry, out: if (tmp_watch) audit_put_watch(tmp_watch); /* match initial get */ + if (tree) + audit_put_tree(tree); /* that's the temporary one */ return ret; } @@ -1737,6 +1783,7 @@ int selinux_audit_rule_update(void) { struct audit_entry *entry, *n, *nentry; struct audit_watch *watch; + struct audit_tree *tree; int i, err = 0; /* audit_filter_mutex synchronizes the writers */ @@ -1748,6 +1795,7 @@ int selinux_audit_rule_update(void) continue; watch = entry->rule.watch; + tree = entry->rule.tree; nentry = audit_dupe_rule(&entry->rule, watch); if (unlikely(IS_ERR(nentry))) { /* save the first error encountered for the @@ -1763,7 +1811,9 @@ int selinux_audit_rule_update(void) list_add(&nentry->rule.rlist, &watch->rules); list_del(&entry->rule.rlist); - } + } else if (tree) + list_replace_init(&entry->rule.rlist, + &nentry->rule.rlist); list_replace_rcu(&entry->list, &nentry->list); } call_rcu(&entry->rcu, audit_free_rule_rcu); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index e19b5a33aed..80ecab0942e 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -65,6 +65,7 @@ #include <linux/binfmts.h> #include <linux/highmem.h> #include <linux/syscalls.h> +#include <linux/inotify.h> #include "audit.h" @@ -179,6 +180,11 @@ struct audit_aux_data_pids { int pid_count; }; +struct audit_tree_refs { + struct audit_tree_refs *next; + struct audit_chunk *c[31]; +}; + /* The per-task audit context. */ struct audit_context { int dummy; /* must be the first element */ @@ -211,6 +217,9 @@ struct audit_context { pid_t target_pid; u32 target_sid; + struct audit_tree_refs *trees, *first_trees; + int tree_count; + #if AUDIT_DEBUG int put_count; int ino_count; @@ -265,6 +274,117 @@ static int audit_match_perm(struct audit_context *ctx, int mask) } } +/* + * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *; + * ->first_trees points to its beginning, ->trees - to the current end of data. + * ->tree_count is the number of free entries in array pointed to by ->trees. + * Original condition is (NULL, NULL, 0); as soon as it grows we never revert to NULL, + * "empty" becomes (p, p, 31) afterwards. We don't shrink the list (and seriously, + * it's going to remain 1-element for almost any setup) until we free context itself. + * References in it _are_ dropped - at the same time we free/drop aux stuff. + */ + +#ifdef CONFIG_AUDIT_TREE +static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk) +{ + struct audit_tree_refs *p = ctx->trees; + int left = ctx->tree_count; + if (likely(left)) { + p->c[--left] = chunk; + ctx->tree_count = left; + return 1; + } + if (!p) + return 0; + p = p->next; + if (p) { + p->c[30] = chunk; + ctx->trees = p; + ctx->tree_count = 30; + return 1; + } + return 0; +} + +static int grow_tree_refs(struct audit_context *ctx) +{ + struct audit_tree_refs *p = ctx->trees; + ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL); + if (!ctx->trees) { + ctx->trees = p; + return 0; + } + if (p) + p->next = ctx->trees; + else + ctx->first_trees = ctx->trees; + ctx->tree_count = 31; + return 1; +} +#endif + +static void unroll_tree_refs(struct audit_context *ctx, + struct audit_tree_refs *p, int count) +{ +#ifdef CONFIG_AUDIT_TREE + struct audit_tree_refs *q; + int n; + if (!p) { + /* we started with empty chain */ + p = ctx->first_trees; + count = 31; + /* if the very first allocation has failed, nothing to do */ + if (!p) + return; + } + n = count; + for (q = p; q != ctx->trees; q = q->next, n = 31) { + while (n--) { + audit_put_chunk(q->c[n]); + q->c[n] = NULL; + } + } + while (n-- > ctx->tree_count) { + audit_put_chunk(q->c[n]); + q->c[n] = NULL; + } + ctx->trees = p; + ctx->tree_count = count; +#endif +} + +static void free_tree_refs(struct audit_context *ctx) +{ + struct audit_tree_refs *p, *q; + for (p = ctx->first_trees; p; p = q) { + q = p->next; + kfree(p); + } +} + +static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree) +{ +#ifdef CONFIG_AUDIT_TREE + struct audit_tree_refs *p; + int n; + if (!tree) + return 0; + /* full ones */ + for (p = ctx->first_trees; p != ctx->trees; p = p->next) { + for (n = 0; n < 31; n++) + if (audit_tree_match(p->c[n], tree)) + return 1; + } + /* partial */ + if (p) { + for (n = ctx->tree_count; n < 31; n++) + if (audit_tree_match(p->c[n], tree)) + return 1; + } +#endif + return 0; +} + /* Determine if any context name data matches a rule's watch data */ /* Compare a task_struct with an audit_rule. Return 1 on match, 0 * otherwise. */ @@ -379,6 +499,10 @@ static int audit_filter_rules(struct task_struct *tsk, result = (name->dev == rule->watch->dev && name->ino == rule->watch->ino); break; + case AUDIT_DIR: + if (ctx) + result = match_tree_refs(ctx, rule->tree); + break; case AUDIT_LOGINUID: result = 0; if (ctx) @@ -727,6 +851,8 @@ static inline void audit_free_context(struct audit_context *context) context->name_count, count); } audit_free_names(context); + unroll_tree_refs(context, NULL, 0); + free_tree_refs(context); audit_free_aux(context); kfree(context->filterkey); kfree(context); @@ -1270,6 +1396,7 @@ void audit_syscall_exit(int valid, long return_code) tsk->audit_context = new_context; } else { audit_free_names(context); + unroll_tree_refs(context, NULL, 0); audit_free_aux(context); context->aux = NULL; context->aux_pids = NULL; @@ -1281,6 +1408,95 @@ void audit_syscall_exit(int valid, long return_code) } } +static inline void handle_one(const struct inode *inode) +{ +#ifdef CONFIG_AUDIT_TREE + struct audit_context *context; + struct audit_tree_refs *p; + struct audit_chunk *chunk; + int count; + if (likely(list_empty(&inode->inotify_watches))) + return; + context = current->audit_context; + p = context->trees; + count = context->tree_count; + rcu_read_lock(); + chunk = audit_tree_lookup(inode); + rcu_read_unlock(); + if (!chunk) + return; + if (likely(put_tree_ref(context, chunk))) + return; + if (unlikely(!grow_tree_refs(context))) { + printk(KERN_WARNING "out of memory, audit has lost a tree reference"); + audit_set_auditable(context); + audit_put_chunk(chunk); + unroll_tree_refs(context, p, count); + return; + } + put_tree_ref(context, chunk); +#endif +} + +static void handle_path(const struct dentry *dentry) +{ +#ifdef CONFIG_AUDIT_TREE + struct audit_context *context; + struct audit_tree_refs *p; + const struct dentry *d, *parent; + struct audit_chunk *drop; + unsigned long seq; + int count; + + context = current->audit_context; + p = context->trees; + count = context->tree_count; +retry: + drop = NULL; + d = dentry; + rcu_read_lock(); + seq = read_seqbegin(&rename_lock); + for(;;) { + struct inode *inode = d->d_inode; + if (inode && unlikely(!list_empty(&inode->inotify_watches))) { + struct audit_chunk *chunk; + chunk = audit_tree_lookup(inode); + if (chunk) { + if (unlikely(!put_tree_ref(context, chunk))) { + drop = chunk; + break; + } + } + } + parent = d->d_parent; + if (parent == d) + break; + d = parent; + } + if (unlikely(read_seqretry(&rename_lock, seq) || drop)) { /* in this order */ + rcu_read_unlock(); + if (!drop) { + /* just a race with rename */ + unroll_tree_refs(context, p, count); + goto retry; + } + audit_put_chunk(drop); + if (grow_tree_refs(context)) { + /* OK, got more space */ + unroll_tree_refs(context, p, count); + goto retry; + } + /* too bad */ + printk(KERN_WARNING + "out of memory, audit has lost a tree reference"); + unroll_tree_refs(context, p, count); + audit_set_auditable(context); + return; + } + rcu_read_unlock(); +#endif +} + /** * audit_getname - add a name to the list * @name: name to add @@ -1403,10 +1619,11 @@ static void audit_copy_inode(struct audit_names *name, const struct inode *inode * * Called from fs/namei.c:path_lookup(). */ -void __audit_inode(const char *name, const struct inode *inode) +void __audit_inode(const char *name, const struct dentry *dentry) { int idx; struct audit_context *context = current->audit_context; + const struct inode *inode = dentry->d_inode; if (!context->in_syscall) return; @@ -1426,6 +1643,7 @@ void __audit_inode(const char *name, const struct inode *inode) idx = context->name_count - 1; context->names[idx].name = NULL; } + handle_path(dentry); audit_copy_inode(&context->names[idx], inode); } @@ -1443,17 +1661,20 @@ void __audit_inode(const char *name, const struct inode *inode) * must be hooked prior, in order to capture the target inode during * unsuccessful attempts. */ -void __audit_inode_child(const char *dname, const struct inode *inode, +void __audit_inode_child(const char *dname, const struct dentry *dentry, const struct inode *parent) { int idx; struct audit_context *context = current->audit_context; const char *found_parent = NULL, *found_child = NULL; + const struct inode *inode = dentry->d_inode; int dirlen = 0; if (!context->in_syscall) return; + if (inode) + handle_one(inode); /* determine matching parent */ if (!dname) goto add_names; diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c index 3c9ef5a7d57..ed6fe51df77 100644 --- a/kernel/sysctl_check.c +++ b/kernel/sysctl_check.c @@ -731,7 +731,7 @@ static struct trans_ctl_table trans_net_table[] = { { NET_UNIX, "unix", trans_net_unix_table }, { NET_IPV4, "ipv4", trans_net_ipv4_table }, { NET_IPX, "ipx", trans_net_ipx_table }, - { NET_ATALK, "atalk", trans_net_atalk_table }, + { NET_ATALK, "appletalk", trans_net_atalk_table }, { NET_NETROM, "netrom", trans_net_netrom_table }, { NET_AX25, "ax25", trans_net_ax25_table }, { NET_BRIDGE, "bridge", trans_net_bridge_table }, diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index c567f219191..1faa5087dc8 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -389,6 +389,16 @@ config DEBUG_LIST If unsure, say N. +config DEBUG_SG + bool "Debug SG table operations" + depends on DEBUG_KERNEL + help + Enable this to turn on checks on scatter-gather tables. This can + help find problems with drivers that do not properly initialize + their sg tables. + + If unsure, say N. + config FRAME_POINTER bool "Compile the kernel with frame pointers" depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH || BFIN) diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 752fd95323f..1a8050ade86 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -35,7 +35,7 @@ #define OFFSET(val,align) ((unsigned long) \ ( (val) & ( (align) - 1))) -#define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset) +#define SG_ENT_VIRT_ADDRESS(sg) (sg_virt((sg))) #define SG_ENT_PHYS_ADDRESS(sg) virt_to_bus(SG_ENT_VIRT_ADDRESS(sg)) /* diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 1833879f843..3a47871a29d 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -187,7 +187,24 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) unsigned long onlined_pages = 0; struct zone *zone; int need_zonelists_rebuild = 0; + int nid; + int ret; + struct memory_notify arg; + + arg.start_pfn = pfn; + arg.nr_pages = nr_pages; + arg.status_change_nid = -1; + + nid = page_to_nid(pfn_to_page(pfn)); + if (node_present_pages(nid) == 0) + arg.status_change_nid = nid; + ret = memory_notify(MEM_GOING_ONLINE, &arg); + ret = notifier_to_errno(ret); + if (ret) { + memory_notify(MEM_CANCEL_ONLINE, &arg); + return ret; + } /* * This doesn't need a lock to do pfn_to_page(). * The section can't be removed here because of the @@ -222,6 +239,10 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) build_all_zonelists(); vm_total_pages = nr_free_pagecache_pages(); writeback_set_ratelimit(); + + if (onlined_pages) + memory_notify(MEM_ONLINE, &arg); + return 0; } #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ @@ -467,8 +488,9 @@ int offline_pages(unsigned long start_pfn, { unsigned long pfn, nr_pages, expire; long offlined_pages; - int ret, drain, retry_max; + int ret, drain, retry_max, node; struct zone *zone; + struct memory_notify arg; BUG_ON(start_pfn >= end_pfn); /* at least, alignment against pageblock is necessary */ @@ -480,11 +502,27 @@ int offline_pages(unsigned long start_pfn, we assume this for now. .*/ if (!test_pages_in_a_zone(start_pfn, end_pfn)) return -EINVAL; + + zone = page_zone(pfn_to_page(start_pfn)); + node = zone_to_nid(zone); + nr_pages = end_pfn - start_pfn; + /* set above range as isolated */ ret = start_isolate_page_range(start_pfn, end_pfn); if (ret) return ret; - nr_pages = end_pfn - start_pfn; + + arg.start_pfn = start_pfn; + arg.nr_pages = nr_pages; + arg.status_change_nid = -1; + if (nr_pages >= node_present_pages(node)) + arg.status_change_nid = node; + + ret = memory_notify(MEM_GOING_OFFLINE, &arg); + ret = notifier_to_errno(ret); + if (ret) + goto failed_removal; + pfn = start_pfn; expire = jiffies + timeout; drain = 0; @@ -539,20 +577,24 @@ repeat: /* reset pagetype flags */ start_isolate_page_range(start_pfn, end_pfn); /* removal success */ - zone = page_zone(pfn_to_page(start_pfn)); zone->present_pages -= offlined_pages; zone->zone_pgdat->node_present_pages -= offlined_pages; totalram_pages -= offlined_pages; num_physpages -= offlined_pages; + vm_total_pages = nr_free_pagecache_pages(); writeback_set_ratelimit(); + + memory_notify(MEM_OFFLINE, &arg); return 0; failed_removal: printk(KERN_INFO "memory offlining %lx to %lx failed\n", start_pfn, end_pfn); + memory_notify(MEM_CANCEL_OFFLINE, &arg); /* pushback to free area */ undo_isolate_page_range(start_pfn, end_pfn); + return ret; } #else diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 824cade0782..91a081a82f5 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -496,7 +496,7 @@ retry: panic("Out of memory and no killable processes...\n"); } - if (oom_kill_process(p, points, gfp_mask, order, + if (oom_kill_process(p, gfp_mask, order, points, "Out of memory")) goto retry; diff --git a/mm/shmem.c b/mm/shmem.c index 289dbb0a6fd..404e53bb212 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2020,33 +2020,25 @@ static int shmem_match(struct inode *ino, void *vfh) return ino->i_ino == inum && fh[0] == ino->i_generation; } -static struct dentry *shmem_get_dentry(struct super_block *sb, void *vfh) +static struct dentry *shmem_fh_to_dentry(struct super_block *sb, + struct fid *fid, int fh_len, int fh_type) { - struct dentry *de = NULL; struct inode *inode; - __u32 *fh = vfh; - __u64 inum = fh[2]; - inum = (inum << 32) | fh[1]; + struct dentry *dentry = NULL; + u64 inum = fid->raw[2]; + inum = (inum << 32) | fid->raw[1]; + + if (fh_len < 3) + return NULL; - inode = ilookup5(sb, (unsigned long)(inum+fh[0]), shmem_match, vfh); + inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]), + shmem_match, fid->raw); if (inode) { - de = d_find_alias(inode); + dentry = d_find_alias(inode); iput(inode); } - return de? de: ERR_PTR(-ESTALE); -} - -static struct dentry *shmem_decode_fh(struct super_block *sb, __u32 *fh, - int len, int type, - int (*acceptable)(void *context, struct dentry *de), - void *context) -{ - if (len < 3) - return ERR_PTR(-ESTALE); - - return sb->s_export_op->find_exported_dentry(sb, fh, NULL, acceptable, - context); + return dentry; } static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len, @@ -2079,11 +2071,10 @@ static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len, return 1; } -static struct export_operations shmem_export_ops = { +static const struct export_operations shmem_export_ops = { .get_parent = shmem_get_parent, - .get_dentry = shmem_get_dentry, .encode_fh = shmem_encode_fh, - .decode_fh = shmem_decode_fh, + .fh_to_dentry = shmem_fh_to_dentry, }; static int shmem_parse_options(char *options, int *mode, uid_t *uid, diff --git a/mm/slub.c b/mm/slub.c index e29a42988c7..aac1dd3c657 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -20,6 +20,7 @@ #include <linux/mempolicy.h> #include <linux/ctype.h> #include <linux/kallsyms.h> +#include <linux/memory.h> /* * Lock order: @@ -2694,6 +2695,121 @@ int kmem_cache_shrink(struct kmem_cache *s) } EXPORT_SYMBOL(kmem_cache_shrink); +#if defined(CONFIG_NUMA) && defined(CONFIG_MEMORY_HOTPLUG) +static int slab_mem_going_offline_callback(void *arg) +{ + struct kmem_cache *s; + + down_read(&slub_lock); + list_for_each_entry(s, &slab_caches, list) + kmem_cache_shrink(s); + up_read(&slub_lock); + + return 0; +} + +static void slab_mem_offline_callback(void *arg) +{ + struct kmem_cache_node *n; + struct kmem_cache *s; + struct memory_notify *marg = arg; + int offline_node; + + offline_node = marg->status_change_nid; + + /* + * If the node still has available memory. we need kmem_cache_node + * for it yet. + */ + if (offline_node < 0) + return; + + down_read(&slub_lock); + list_for_each_entry(s, &slab_caches, list) { + n = get_node(s, offline_node); + if (n) { + /* + * if n->nr_slabs > 0, slabs still exist on the node + * that is going down. We were unable to free them, + * and offline_pages() function shoudn't call this + * callback. So, we must fail. + */ + BUG_ON(atomic_read(&n->nr_slabs)); + + s->node[offline_node] = NULL; + kmem_cache_free(kmalloc_caches, n); + } + } + up_read(&slub_lock); +} + +static int slab_mem_going_online_callback(void *arg) +{ + struct kmem_cache_node *n; + struct kmem_cache *s; + struct memory_notify *marg = arg; + int nid = marg->status_change_nid; + int ret = 0; + + /* + * If the node's memory is already available, then kmem_cache_node is + * already created. Nothing to do. + */ + if (nid < 0) + return 0; + + /* + * We are bringing a node online. No memory is availabe yet. We must + * allocate a kmem_cache_node structure in order to bring the node + * online. + */ + down_read(&slub_lock); + list_for_each_entry(s, &slab_caches, list) { + /* + * XXX: kmem_cache_alloc_node will fallback to other nodes + * since memory is not yet available from the node that + * is brought up. + */ + n = kmem_cache_alloc(kmalloc_caches, GFP_KERNEL); + if (!n) { + ret = -ENOMEM; + goto out; + } + init_kmem_cache_node(n); + s->node[nid] = n; + } +out: + up_read(&slub_lock); + return ret; +} + +static int slab_memory_callback(struct notifier_block *self, + unsigned long action, void *arg) +{ + int ret = 0; + + switch (action) { + case MEM_GOING_ONLINE: + ret = slab_mem_going_online_callback(arg); + break; + case MEM_GOING_OFFLINE: + ret = slab_mem_going_offline_callback(arg); + break; + case MEM_OFFLINE: + case MEM_CANCEL_ONLINE: + slab_mem_offline_callback(arg); + break; + case MEM_ONLINE: + case MEM_CANCEL_OFFLINE: + break; + } + + ret = notifier_from_errno(ret); + return ret; +} + +#endif /* CONFIG_MEMORY_HOTPLUG */ + /******************************************************************** * Basic setup of slabs *******************************************************************/ @@ -2715,6 +2831,8 @@ void __init kmem_cache_init(void) sizeof(struct kmem_cache_node), GFP_KERNEL); kmalloc_caches[0].refcount = -1; caches++; + + hotplug_memory_notifier(slab_memory_callback, 1); #endif /* Able to allocate the per node structures */ diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 70d9b5da96a..4e2c84fcf27 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2045,7 +2045,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) if (copy > 0) { if (copy > len) copy = len; - sg[elt].page = virt_to_page(skb->data + offset); + sg_set_page(&sg[elt], virt_to_page(skb->data + offset)); sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; sg[elt].length = copy; elt++; @@ -2065,7 +2065,7 @@ skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) if (copy > len) copy = len; - sg[elt].page = frag->page; + sg_set_page(&sg[elt], frag->page); sg[elt].offset = frag->page_offset+offset-start; sg[elt].length = copy; elt++; diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c index 72e6ab66834..c796661a021 100644 --- a/net/ieee80211/ieee80211_crypt_tkip.c +++ b/net/ieee80211/ieee80211_crypt_tkip.c @@ -390,9 +390,7 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[3] = crc >> 24; crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); - sg.page = virt_to_page(pos); - sg.offset = offset_in_page(pos); - sg.length = len + 4; + sg_init_one(&sg, pos, len + 4); return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); } @@ -485,9 +483,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 12; crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); - sg.page = virt_to_page(pos); - sg.offset = offset_in_page(pos); - sg.length = plen + 4; + sg_init_one(&sg, pos, plen + 4); if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { if (net_ratelimit()) { printk(KERN_DEBUG ": TKIP: failed to decrypt " @@ -539,11 +535,12 @@ static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr, printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); return -1; } - sg[0].page = virt_to_page(hdr); + sg_init_table(sg, 2); + sg_set_page(&sg[0], virt_to_page(hdr)); sg[0].offset = offset_in_page(hdr); sg[0].length = 16; - sg[1].page = virt_to_page(data); + sg_set_page(&sg[1], virt_to_page(data)); sg[1].offset = offset_in_page(data); sg[1].length = data_len; diff --git a/net/ieee80211/ieee80211_crypt_wep.c b/net/ieee80211/ieee80211_crypt_wep.c index 8d182459344..0af6103d715 100644 --- a/net/ieee80211/ieee80211_crypt_wep.c +++ b/net/ieee80211/ieee80211_crypt_wep.c @@ -170,9 +170,7 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[3] = crc >> 24; crypto_blkcipher_setkey(wep->tx_tfm, key, klen); - sg.page = virt_to_page(pos); - sg.offset = offset_in_page(pos); - sg.length = len + 4; + sg_init_one(&sg, pos, len + 4); return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); } @@ -212,9 +210,7 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 8; crypto_blkcipher_setkey(wep->rx_tfm, key, klen); - sg.page = virt_to_page(pos); - sg.offset = offset_in_page(pos); - sg.length = plen + 4; + sg_init_one(&sg, pos, plen + 4); if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) return -7; diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 6675261e958..cc806d640f7 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -138,9 +138,7 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, *icv = cpu_to_le32(~crc32_le(~0, data, data_len)); crypto_blkcipher_setkey(tfm, rc4key, klen); - sg.page = virt_to_page(data); - sg.offset = offset_in_page(data); - sg.length = data_len + WEP_ICV_LEN; + sg_init_one(&sg, data, data_len + WEP_ICV_LEN); crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length); } @@ -204,9 +202,7 @@ int ieee80211_wep_decrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, __le32 crc; crypto_blkcipher_setkey(tfm, rc4key, klen); - sg.page = virt_to_page(data); - sg.offset = offset_in_page(data); - sg.length = data_len + WEP_ICV_LEN; + sg_init_one(&sg, data, data_len + WEP_ICV_LEN); crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length); crc = cpu_to_le32(~crc32_le(~0, data, data_len)); diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 78181072471..cbd64b216cc 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -726,7 +726,8 @@ void sctp_auth_calculate_hmac(const struct sctp_association *asoc, /* set up scatter list */ end = skb_tail_pointer(skb); - sg.page = virt_to_page(auth); + sg_init_table(&sg, 1); + sg_set_page(&sg, virt_to_page(auth)); sg.offset = (unsigned long)(auth) % PAGE_SIZE; sg.length = end - (unsigned char *)auth; diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index f983a369d4e..d5a9785a158 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1513,7 +1513,8 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, struct hash_desc desc; /* Sign the message. */ - sg.page = virt_to_page(&cookie->c); + sg_init_table(&sg, 1); + sg_set_page(&sg, virt_to_page(&cookie->c)); sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE; sg.length = bodysize; keylen = SCTP_SECRET_SIZE; @@ -1585,7 +1586,8 @@ struct sctp_association *sctp_unpack_cookie( /* Check the signature. */ keylen = SCTP_SECRET_SIZE; - sg.page = virt_to_page(bear_cookie); + sg_init_table(&sg, 1); + sg_set_page(&sg, virt_to_page(bear_cookie)); sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE; sg.length = bodysize; key = (char *)ep->secret_key[ep->current_key]; diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index bfb6a29633d..32be431affc 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -197,9 +197,9 @@ encryptor(struct scatterlist *sg, void *data) int i = (page_pos + outbuf->page_base) >> PAGE_CACHE_SHIFT; in_page = desc->pages[i]; } else { - in_page = sg->page; + in_page = sg_page(sg); } - desc->infrags[desc->fragno].page = in_page; + sg_set_page(&desc->infrags[desc->fragno], in_page); desc->fragno++; desc->fraglen += sg->length; desc->pos += sg->length; @@ -215,11 +215,11 @@ encryptor(struct scatterlist *sg, void *data) if (ret) return ret; if (fraglen) { - desc->outfrags[0].page = sg->page; + sg_set_page(&desc->outfrags[0], sg_page(sg)); desc->outfrags[0].offset = sg->offset + sg->length - fraglen; desc->outfrags[0].length = fraglen; desc->infrags[0] = desc->outfrags[0]; - desc->infrags[0].page = in_page; + sg_set_page(&desc->infrags[0], in_page); desc->fragno = 1; desc->fraglen = fraglen; } else { @@ -287,7 +287,7 @@ decryptor(struct scatterlist *sg, void *data) if (ret) return ret; if (fraglen) { - desc->frags[0].page = sg->page; + sg_set_page(&desc->frags[0], sg_page(sg)); desc->frags[0].offset = sg->offset + sg->length - fraglen; desc->frags[0].length = fraglen; desc->fragno = 1; diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 6a59180e166..3d1f7cdf9dd 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -1059,7 +1059,7 @@ xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, do { if (thislen > page_len) thislen = page_len; - sg->page = buf->pages[i]; + sg_set_page(sg, buf->pages[i]); sg->offset = page_offset; sg->length = thislen; ret = actor(sg, data); diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 5ced62c19c6..fb2220a719b 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -552,7 +552,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, if (copy > len) copy = len; - sg.page = virt_to_page(skb->data + offset); + sg_set_page(&sg, virt_to_page(skb->data + offset)); sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; sg.length = copy; @@ -577,7 +577,7 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, if (copy > len) copy = len; - sg.page = frag->page; + sg_set_page(&sg, frag->page); sg.offset = frag->page_offset + offset-start; sg.length = copy; diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl index 28e480c8100..d716b76098b 100755 --- a/scripts/checkstack.pl +++ b/scripts/checkstack.pl @@ -13,6 +13,7 @@ # Random bits by Matt Mackall <mpm@selenic.com> # M68k port by Geert Uytterhoeven and Andreas Schwab # AVR32 port by Haavard Skinnemoen <hskinnemoen@atmel.com> +# PARISC port by Kyle McMartin <kyle@parisc-linux.org> # # Usage: # objdump -d vmlinux | scripts/checkstack.pl [arch] @@ -61,6 +62,8 @@ my (@stack, $re, $x, $xs); } elsif ($arch eq 'mips') { #88003254: 27bdffe0 addiu sp,sp,-32 $re = qr/.*addiu.*sp,sp,-(([0-9]{2}|[3-9])[0-9]{2})/o; + } elsif ($arch eq 'parisc' || $arch eq 'parisc64') { + $re = qr/.*ldo ($x{1,8})\(sp\),sp/o; } elsif ($arch eq 'ppc') { #c00029f4: 94 21 ff 30 stwu r1,-208(r1) $re = qr/.*stwu.*r1,-($x{1,8})\(r1\)/o; diff --git a/security/commoncap.c b/security/commoncap.c index 43f902750a1..bf67871173e 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -190,7 +190,8 @@ int cap_inode_killpriv(struct dentry *dentry) return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); } -static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm, +static inline int cap_from_disk(struct vfs_cap_data *caps, + struct linux_binprm *bprm, int size) { __u32 magic_etc; @@ -198,7 +199,7 @@ static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm, if (size != XATTR_CAPS_SZ) return -EINVAL; - magic_etc = le32_to_cpu(caps[0]); + magic_etc = le32_to_cpu(caps->magic_etc); switch ((magic_etc & VFS_CAP_REVISION_MASK)) { case VFS_CAP_REVISION: @@ -206,8 +207,8 @@ static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm, bprm->cap_effective = true; else bprm->cap_effective = false; - bprm->cap_permitted = to_cap_t( le32_to_cpu(caps[1]) ); - bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[2]) ); + bprm->cap_permitted = to_cap_t(le32_to_cpu(caps->permitted)); + bprm->cap_inheritable = to_cap_t(le32_to_cpu(caps->inheritable)); return 0; default: return -EINVAL; @@ -219,7 +220,7 @@ static int get_file_caps(struct linux_binprm *bprm) { struct dentry *dentry; int rc = 0; - __le32 v1caps[XATTR_CAPS_SZ]; + struct vfs_cap_data incaps; struct inode *inode; if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) { @@ -232,8 +233,14 @@ static int get_file_caps(struct linux_binprm *bprm) if (!inode->i_op || !inode->i_op->getxattr) goto out; - rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &v1caps, - XATTR_CAPS_SZ); + rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0); + if (rc > 0) { + if (rc == XATTR_CAPS_SZ) + rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, + &incaps, XATTR_CAPS_SZ); + else + rc = -EINVAL; + } if (rc == -ENODATA || rc == -EOPNOTSUPP) { /* no data, that's ok */ rc = 0; @@ -242,7 +249,7 @@ static int get_file_caps(struct linux_binprm *bprm) if (rc < 0) goto out; - rc = cap_from_disk(v1caps, bprm, rc); + rc = cap_from_disk(&incaps, bprm, rc); if (rc) printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", __FUNCTION__, rc, bprm->filename); |