diff options
384 files changed, 24087 insertions, 2390 deletions
diff --git a/Documentation/ABI/testing/debugfs-pktcdvd b/Documentation/ABI/testing/debugfs-pktcdvd index bf9c16b64c3..cf11736acb7 100644 --- a/Documentation/ABI/testing/debugfs-pktcdvd +++ b/Documentation/ABI/testing/debugfs-pktcdvd @@ -1,4 +1,4 @@ -What: /debug/pktcdvd/pktcdvd[0-7] +What: /sys/kernel/debug/pktcdvd/pktcdvd[0-7] Date: Oct. 2006 KernelVersion: 2.6.20 Contact: Thomas Maier <balagi@justmail.de> @@ -10,10 +10,10 @@ debugfs interface The pktcdvd module (packet writing driver) creates these files in debugfs: -/debug/pktcdvd/pktcdvd[0-7]/ +/sys/kernel/debug/pktcdvd/pktcdvd[0-7]/ info (0444) Lots of driver statistics and infos. Example: ------- -cat /debug/pktcdvd/pktcdvd0/info +cat /sys/kernel/debug/pktcdvd/pktcdvd0/info diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index a3a83d38f96..8918a32c6b3 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -31,7 +31,7 @@ PS_METHOD = $(prefer-db2x) ### # The targets that may be used. -PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs +PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs BOOKS := $(addprefix $(obj)/,$(DOCBOOKS)) xmldocs: $(BOOKS) @@ -213,11 +213,12 @@ silent_gen_xml = : dochelp: @echo ' Linux kernel internal documentation in different formats:' @echo ' htmldocs - HTML' - @echo ' installmandocs - install man pages generated by mandocs' - @echo ' mandocs - man pages' @echo ' pdfdocs - PDF' @echo ' psdocs - Postscript' @echo ' xmldocs - XML DocBook' + @echo ' mandocs - man pages' + @echo ' installmandocs - install man pages generated by mandocs' + @echo ' cleandocs - clean all generated DocBook files' ### # Temporary files left by various tools @@ -235,6 +236,10 @@ clean-files := $(DOCBOOKS) \ clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man +cleandocs: + $(Q)rm -f $(call objectify, $(clean-files)) + $(Q)rm -rf $(call objectify, $(clean-dirs)) + # Declare the contents of the .PHONY variable as phony. We keep that # information in a variable se we can use it in if_changed and friends. diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index a98a7fe7aab..1a608877b14 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -6,15 +6,14 @@ used here with the memory controller that is used in hardware. Salient features -a. Enable control of both RSS (mapped) and Page Cache (unmapped) pages +a. Enable control of Anonymous, Page Cache (mapped and unmapped) and + Swap Cache memory pages. b. The infrastructure allows easy addition of other types of memory to control c. Provides *zero overhead* for non memory controller users d. Provides a double LRU: global memory pressure causes reclaim from the global LRU; a cgroup on hitting a limit, reclaims from the per cgroup LRU -NOTE: Swap Cache (unmapped) is not accounted now. - Benefits and Purpose of the memory controller The memory controller isolates the memory behaviour of a group of tasks @@ -290,34 +289,44 @@ will be charged as a new owner of it. moved to the parent. If you want to avoid that, force_empty will be useful. 5.2 stat file - memory.stat file includes following statistics (now) - cache - # of pages from page-cache and shmem. - rss - # of pages from anonymous memory. - pgpgin - # of event of charging - pgpgout - # of event of uncharging - active_anon - # of pages on active lru of anon, shmem. - inactive_anon - # of pages on active lru of anon, shmem - active_file - # of pages on active lru of file-cache - inactive_file - # of pages on inactive lru of file cache - unevictable - # of pages cannot be reclaimed.(mlocked etc) - - Below is depend on CONFIG_DEBUG_VM. - inactive_ratio - VM internal parameter. (see mm/page_alloc.c) - recent_rotated_anon - VM internal parameter. (see mm/vmscan.c) - recent_rotated_file - VM internal parameter. (see mm/vmscan.c) - recent_scanned_anon - VM internal parameter. (see mm/vmscan.c) - recent_scanned_file - VM internal parameter. (see mm/vmscan.c) - - Memo: + +memory.stat file includes following statistics + +cache - # of bytes of page cache memory. +rss - # of bytes of anonymous and swap cache memory. +pgpgin - # of pages paged in (equivalent to # of charging events). +pgpgout - # of pages paged out (equivalent to # of uncharging events). +active_anon - # of bytes of anonymous and swap cache memory on active + lru list. +inactive_anon - # of bytes of anonymous memory and swap cache memory on + inactive lru list. +active_file - # of bytes of file-backed memory on active lru list. +inactive_file - # of bytes of file-backed memory on inactive lru list. +unevictable - # of bytes of memory that cannot be reclaimed (mlocked etc). + +The following additional stats are dependent on CONFIG_DEBUG_VM. + +inactive_ratio - VM internal parameter. (see mm/page_alloc.c) +recent_rotated_anon - VM internal parameter. (see mm/vmscan.c) +recent_rotated_file - VM internal parameter. (see mm/vmscan.c) +recent_scanned_anon - VM internal parameter. (see mm/vmscan.c) +recent_scanned_file - VM internal parameter. (see mm/vmscan.c) + +Memo: recent_rotated means recent frequency of lru rotation. recent_scanned means recent # of scans to lru. showing for better debug please see the code for meanings. +Note: + Only anonymous and swap cache memory is listed as part of 'rss' stat. + This should not be confused with the true 'resident set size' or the + amount of physical memory used by the cgroup. Per-cgroup rss + accounting is not done yet. 5.3 swappiness Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only. - Following cgroup's swapiness can't be changed. + Following cgroups' swapiness can't be changed. - root cgroup (uses /proc/sys/vm/swappiness). - a cgroup which uses hierarchy and it has child cgroup. - a cgroup which uses hierarchy and not the root of hierarchy. diff --git a/Documentation/cgroups/resource_counter.txt b/Documentation/cgroups/resource_counter.txt index f196ac1d7d2..95b24d766ea 100644 --- a/Documentation/cgroups/resource_counter.txt +++ b/Documentation/cgroups/resource_counter.txt @@ -47,13 +47,18 @@ to work with it. 2. Basic accounting routines - a. void res_counter_init(struct res_counter *rc) + a. void res_counter_init(struct res_counter *rc, + struct res_counter *rc_parent) Initializes the resource counter. As usual, should be the first routine called for a new counter. - b. int res_counter_charge[_locked] - (struct res_counter *rc, unsigned long val) + The struct res_counter *parent can be used to define a hierarchical + child -> parent relationship directly in the res_counter structure, + NULL can be used to define no relationship. + + c. int res_counter_charge(struct res_counter *rc, unsigned long val, + struct res_counter **limit_fail_at) When a resource is about to be allocated it has to be accounted with the appropriate resource counter (controller should determine @@ -67,15 +72,25 @@ to work with it. * if the charging is performed first, then it should be uncharged on error path (if the one is called). - c. void res_counter_uncharge[_locked] + If the charging fails and a hierarchical dependency exists, the + limit_fail_at parameter is set to the particular res_counter element + where the charging failed. + + d. int res_counter_charge_locked + (struct res_counter *rc, unsigned long val) + + The same as res_counter_charge(), but it must not acquire/release the + res_counter->lock internally (it must be called with res_counter->lock + held). + + e. void res_counter_uncharge[_locked] (struct res_counter *rc, unsigned long val) When a resource is released (freed) it should be de-accounted from the resource counter it was accounted to. This is called "uncharging". - The _locked routines imply that the res_counter->lock is taken. - + The _locked routines imply that the res_counter->lock is taken. 2.1 Other accounting routines diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 7e2af10e826..de491a3e231 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -428,3 +428,12 @@ Why: In 2.6.27, the semantics of /sys/bus/pci/slots was redefined to After a reasonable transition period, we will remove the legacy fakephp interface. Who: Alex Chiang <achiang@hp.com> + +--------------------------- + +What: i2c-voodoo3 driver +When: October 2009 +Why: Superseded by tdfxfb. I2C/DDC support used to live in a separate + driver but this caused driver conflicts. +Who: Jean Delvare <khali@linux-fr.org> + Krzysztof Helt <krzysztof.h1@wp.pl> diff --git a/Documentation/input/rotary-encoder.txt b/Documentation/input/rotary-encoder.txt new file mode 100644 index 00000000000..435102a26d9 --- /dev/null +++ b/Documentation/input/rotary-encoder.txt @@ -0,0 +1,101 @@ +rotary-encoder - a generic driver for GPIO connected devices +Daniel Mack <daniel@caiaq.de>, Feb 2009 + +0. Function +----------- + +Rotary encoders are devices which are connected to the CPU or other +peripherals with two wires. The outputs are phase-shifted by 90 degrees +and by triggering on falling and rising edges, the turn direction can +be determined. + +The phase diagram of these two outputs look like this: + + _____ _____ _____ + | | | | | | + Channel A ____| |_____| |_____| |____ + + : : : : : : : : : : : : + __ _____ _____ _____ + | | | | | | | + Channel B |_____| |_____| |_____| |__ + + : : : : : : : : : : : : + Event a b c d a b c d a b c d + + |<-------->| + one step + + +For more information, please see + http://en.wikipedia.org/wiki/Rotary_encoder + + +1. Events / state machine +------------------------- + +a) Rising edge on channel A, channel B in low state + This state is used to recognize a clockwise turn + +b) Rising edge on channel B, channel A in high state + When entering this state, the encoder is put into 'armed' state, + meaning that there it has seen half the way of a one-step transition. + +c) Falling edge on channel A, channel B in high state + This state is used to recognize a counter-clockwise turn + +d) Falling edge on channel B, channel A in low state + Parking position. If the encoder enters this state, a full transition + should have happend, unless it flipped back on half the way. The + 'armed' state tells us about that. + +2. Platform requirements +------------------------ + +As there is no hardware dependent call in this driver, the platform it is +used with must support gpiolib. Another requirement is that IRQs must be +able to fire on both edges. + + +3. Board integration +-------------------- + +To use this driver in your system, register a platform_device with the +name 'rotary-encoder' and associate the IRQs and some specific platform +data with it. + +struct rotary_encoder_platform_data is declared in +include/linux/rotary-encoder.h and needs to be filled with the number of +steps the encoder has and can carry information about externally inverted +signals (because of used invertig buffer or other reasons). + +Because GPIO to IRQ mapping is platform specific, this information must +be given in seperately to the driver. See the example below. + +---------<snip>--------- + +/* board support file example */ + +#include <linux/input.h> +#include <linux/rotary_encoder.h> + +#define GPIO_ROTARY_A 1 +#define GPIO_ROTARY_B 2 + +static struct rotary_encoder_platform_data my_rotary_encoder_info = { + .steps = 24, + .axis = ABS_X, + .gpio_a = GPIO_ROTARY_A, + .gpio_b = GPIO_ROTARY_B, + .inverted_a = 0, + .inverted_b = 0, +}; + +static struct platform_device rotary_encoder_device = { + .name = "rotary-encoder", + .id = 0, + .dev = { + .platform_data = &my_rotary_encoder_info, + } +}; + diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 51104f9194a..d4b05672f9f 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -40,10 +40,16 @@ This document describes the Linux kernel Makefiles. --- 6.7 Custom kbuild commands --- 6.8 Preprocessing linker scripts - === 7 Kbuild Variables - === 8 Makefile language - === 9 Credits - === 10 TODO + === 7 Kbuild syntax for exported headers + --- 7.1 header-y + --- 7.2 objhdr-y + --- 7.3 destination-y + --- 7.4 unifdef-y (deprecated) + + === 8 Kbuild Variables + === 9 Makefile language + === 10 Credits + === 11 TODO === 1 Overview @@ -1143,8 +1149,69 @@ When kbuild executes, the following steps are followed (roughly): The kbuild infrastructure for *lds file are used in several architecture-specific files. +=== 7 Kbuild syntax for exported headers + +The kernel include a set of headers that is exported to userspace. +Many headers can be exported as-is but other headers requires a +minimal pre-processing before they are ready for user-space. +The pre-processing does: +- drop kernel specific annotations +- drop include of compiler.h +- drop all sections that is kernel internat (guarded by ifdef __KERNEL__) + +Each relevant directory contain a file name "Kbuild" which specify the +headers to be exported. +See subsequent chapter for the syntax of the Kbuild file. + + --- 7.1 header-y + + header-y specify header files to be exported. + + Example: + #include/linux/Kbuild + header-y += usb/ + header-y += aio_abi.h + + The convention is to list one file per line and + preferably in alphabetic order. + + header-y also specify which subdirectories to visit. + A subdirectory is identified by a trailing '/' which + can be seen in the example above for the usb subdirectory. + + Subdirectories are visited before their parent directories. + + --- 7.2 objhdr-y + + objhdr-y specifies generated files to be exported. + Generated files are special as they need to be looked + up in another directory when doing 'make O=...' builds. + + Example: + #include/linux/Kbuild + objhdr-y += version.h + + --- 7.3 destination-y + + When an architecture have a set of exported headers that needs to be + exported to a different directory destination-y is used. + destination-y specify the destination directory for all exported + headers in the file where it is present. + + Example: + #arch/xtensa/platforms/s6105/include/platform/Kbuild + destination-y := include/linux + + In the example above all exported headers in the Kbuild file + will be located in the directory "include/linux" when exported. + + + --- 7.4 unifdef-y (deprecated) + + unifdef-y is deprecated. A direct replacement is header-y. + -=== 7 Kbuild Variables +=== 8 Kbuild Variables The top Makefile exports the following variables: @@ -1206,7 +1273,7 @@ The top Makefile exports the following variables: INSTALL_MOD_STRIP will used as the option(s) to the strip command. -=== 8 Makefile language +=== 9 Makefile language The kernel Makefiles are designed to be run with GNU Make. The Makefiles use only the documented features of GNU Make, but they do use many @@ -1225,14 +1292,14 @@ time the left-hand side is used. There are some cases where "=" is appropriate. Usually, though, ":=" is the right choice. -=== 9 Credits +=== 10 Credits Original version made by Michael Elizabeth Chastain, <mailto:mec@shout.net> Updates by Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de> Updates by Sam Ravnborg <sam@ravnborg.org> Language QA by Jan Engelhardt <jengelh@gmx.de> -=== 10 TODO +=== 11 TODO - Describe how kbuild supports shipped files with _shipped. - Generating offset header files. diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt index 42f43fa59f2..34c76a55bc0 100644 --- a/Documentation/sparse.txt +++ b/Documentation/sparse.txt @@ -42,6 +42,14 @@ sure that bitwise types don't get mixed up (little-endian vs big-endian vs cpu-endian vs whatever), and there the constant "0" really _is_ special. +__bitwise__ - to be used for relatively compact stuff (gfp_t, etc.) that +is mostly warning-free and is supposed to stay that way. Warnings will +be generated without __CHECK_ENDIAN__. + +__bitwise - noisy stuff; in particular, __le*/__be* are that. We really +don't want to drown in noise unless we'd explicitly asked for it. + + Getting sparse ~~~~~~~~~~~~~~ diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt index a34d55b6544..df38ef046f8 100644 --- a/Documentation/sysctl/net.txt +++ b/Documentation/sysctl/net.txt @@ -95,7 +95,7 @@ of struct cmsghdr structures with appended data. There is only one file in this directory. unix_dgram_qlen limits the max number of datagrams queued in Unix domain -socket's buffer. It will not take effect unless PF_UNIX flag is spicified. +socket's buffer. It will not take effect unless PF_UNIX flag is specified. 3. /proc/sys/net/ipv4 - IPV4 settings diff --git a/Documentation/tomoyo.txt b/Documentation/tomoyo.txt new file mode 100644 index 00000000000..b3a232cae7f --- /dev/null +++ b/Documentation/tomoyo.txt @@ -0,0 +1,55 @@ +--- What is TOMOYO? --- + +TOMOYO is a name-based MAC extension (LSM module) for the Linux kernel. + +LiveCD-based tutorials are available at +http://tomoyo.sourceforge.jp/en/1.6.x/1st-step/ubuntu8.04-live/ +http://tomoyo.sourceforge.jp/en/1.6.x/1st-step/centos5-live/ . +Though these tutorials use non-LSM version of TOMOYO, they are useful for you +to know what TOMOYO is. + +--- How to enable TOMOYO? --- + +Build the kernel with CONFIG_SECURITY_TOMOYO=y and pass "security=tomoyo" on +kernel's command line. + +Please see http://tomoyo.sourceforge.jp/en/2.2.x/ for details. + +--- Where is documentation? --- + +User <-> Kernel interface documentation is available at +http://tomoyo.sourceforge.jp/en/2.2.x/policy-reference.html . + +Materials we prepared for seminars and symposiums are available at +http://sourceforge.jp/projects/tomoyo/docs/?category_id=532&language_id=1 . +Below lists are chosen from three aspects. + +What is TOMOYO? + TOMOYO Linux Overview + http://sourceforge.jp/projects/tomoyo/docs/lca2009-takeda.pdf + TOMOYO Linux: pragmatic and manageable security for Linux + http://sourceforge.jp/projects/tomoyo/docs/freedomhectaipei-tomoyo.pdf + TOMOYO Linux: A Practical Method to Understand and Protect Your Own Linux Box + http://sourceforge.jp/projects/tomoyo/docs/PacSec2007-en-no-demo.pdf + +What can TOMOYO do? + Deep inside TOMOYO Linux + http://sourceforge.jp/projects/tomoyo/docs/lca2009-kumaneko.pdf + The role of "pathname based access control" in security. + http://sourceforge.jp/projects/tomoyo/docs/lfj2008-bof.pdf + +History of TOMOYO? + Realities of Mainlining + http://sourceforge.jp/projects/tomoyo/docs/lfj2008.pdf + +--- What is future plan? --- + +We believe that inode based security and name based security are complementary +and both should be used together. But unfortunately, so far, we cannot enable +multiple LSM modules at the same time. We feel sorry that you have to give up +SELinux/SMACK/AppArmor etc. when you want to use TOMOYO. + +We hope that LSM becomes stackable in future. Meanwhile, you can use non-LSM +version of TOMOYO, available at http://tomoyo.sourceforge.jp/en/1.6.x/ . +LSM version of TOMOYO is a subset of non-LSM version of TOMOYO. We are planning +to port non-LSM version's functionalities to LSM versions. diff --git a/Documentation/vm/00-INDEX b/Documentation/vm/00-INDEX index 2131b00b63f..2f77ced35df 100644 --- a/Documentation/vm/00-INDEX +++ b/Documentation/vm/00-INDEX @@ -1,5 +1,7 @@ 00-INDEX - this file. +active_mm.txt + - An explanation from Linus about tsk->active_mm vs tsk->mm. balance - various information on memory balancing. hugetlbpage.txt diff --git a/Documentation/vm/active_mm.txt b/Documentation/vm/active_mm.txt new file mode 100644 index 00000000000..4ee1f643d89 --- /dev/null +++ b/Documentation/vm/active_mm.txt @@ -0,0 +1,83 @@ +List: linux-kernel +Subject: Re: active_mm +From: Linus Torvalds <torvalds () transmeta ! com> +Date: 1999-07-30 21:36:24 + +Cc'd to linux-kernel, because I don't write explanations all that often, +and when I do I feel better about more people reading them. + +On Fri, 30 Jul 1999, David Mosberger wrote: +> +> Is there a brief description someplace on how "mm" vs. "active_mm" in +> the task_struct are supposed to be used? (My apologies if this was +> discussed on the mailing lists---I just returned from vacation and +> wasn't able to follow linux-kernel for a while). + +Basically, the new setup is: + + - we have "real address spaces" and "anonymous address spaces". The + difference is that an anonymous address space doesn't care about the + user-level page tables at all, so when we do a context switch into an + anonymous address space we just leave the previous address space + active. + + The obvious use for a "anonymous address space" is any thread that + doesn't need any user mappings - all kernel threads basically fall into + this category, but even "real" threads can temporarily say that for + some amount of time they are not going to be interested in user space, + and that the scheduler might as well try to avoid wasting time on + switching the VM state around. Currently only the old-style bdflush + sync does that. + + - "tsk->mm" points to the "real address space". For an anonymous process, + tsk->mm will be NULL, for the logical reason that an anonymous process + really doesn't _have_ a real address space at all. + + - however, we obviously need to keep track of which address space we + "stole" for such an anonymous user. For that, we have "tsk->active_mm", + which shows what the currently active address space is. + + The rule is that for a process with a real address space (ie tsk->mm is + non-NULL) the active_mm obviously always has to be the same as the real + one. + + For a anonymous process, tsk->mm == NULL, and tsk->active_mm is the + "borrowed" mm while the anonymous process is running. When the + anonymous process gets scheduled away, the borrowed address space is + returned and cleared. + +To support all that, the "struct mm_struct" now has two counters: a +"mm_users" counter that is how many "real address space users" there are, +and a "mm_count" counter that is the number of "lazy" users (ie anonymous +users) plus one if there are any real users. + +Usually there is at least one real user, but it could be that the real +user exited on another CPU while a lazy user was still active, so you do +actually get cases where you have a address space that is _only_ used by +lazy users. That is often a short-lived state, because once that thread +gets scheduled away in favour of a real thread, the "zombie" mm gets +released because "mm_users" becomes zero. + +Also, a new rule is that _nobody_ ever has "init_mm" as a real MM any +more. "init_mm" should be considered just a "lazy context when no other +context is available", and in fact it is mainly used just at bootup when +no real VM has yet been created. So code that used to check + + if (current->mm == &init_mm) + +should generally just do + + if (!current->mm) + +instead (which makes more sense anyway - the test is basically one of "do +we have a user context", and is generally done by the page fault handler +and things like that). + +Anyway, I put a pre-patch-2.3.13-1 on ftp.kernel.org just a moment ago, +because it slightly changes the interfaces to accomodate the alpha (who +would have thought it, but the alpha actually ends up having one of the +ugliest context switch codes - unlike the other architectures where the MM +and register state is separate, the alpha PALcode joins the two, and you +need to switch both together). + +(From http://marc.info/?l=linux-kernel&m=93337278602211&w=2) diff --git a/Documentation/vm/unevictable-lru.txt b/Documentation/vm/unevictable-lru.txt index 0706a7282a8..2d70d0d9510 100644 --- a/Documentation/vm/unevictable-lru.txt +++ b/Documentation/vm/unevictable-lru.txt @@ -1,588 +1,691 @@ - -This document describes the Linux memory management "Unevictable LRU" -infrastructure and the use of this infrastructure to manage several types -of "unevictable" pages. The document attempts to provide the overall -rationale behind this mechanism and the rationale for some of the design -decisions that drove the implementation. The latter design rationale is -discussed in the context of an implementation description. Admittedly, one -can obtain the implementation details--the "what does it do?"--by reading the -code. One hopes that the descriptions below add value by provide the answer -to "why does it do that?". - -Unevictable LRU Infrastructure: - -The Unevictable LRU adds an additional LRU list to track unevictable pages -and to hide these pages from vmscan. This mechanism is based on a patch by -Larry Woodman of Red Hat to address several scalability problems with page + ============================== + UNEVICTABLE LRU INFRASTRUCTURE + ============================== + +======== +CONTENTS +======== + + (*) The Unevictable LRU + + - The unevictable page list. + - Memory control group interaction. + - Marking address spaces unevictable. + - Detecting Unevictable Pages. + - vmscan's handling of unevictable pages. + + (*) mlock()'d pages. + + - History. + - Basic management. + - mlock()/mlockall() system call handling. + - Filtering special vmas. + - munlock()/munlockall() system call handling. + - Migrating mlocked pages. + - mmap(MAP_LOCKED) system call handling. + - munmap()/exit()/exec() system call handling. + - try_to_unmap(). + - try_to_munlock() reverse map scan. + - Page reclaim in shrink_*_list(). + + +============ +INTRODUCTION +============ + +This document describes the Linux memory manager's "Unevictable LRU" +infrastructure and the use of this to manage several types of "unevictable" +pages. + +The document attempts to provide the overall rationale behind this mechanism +and the rationale for some of the design decisions that drove the +implementation. The latter design rationale is discussed in the context of an +implementation description. Admittedly, one can obtain the implementation +details - the "what does it do?" - by reading the code. One hopes that the +descriptions below add value by provide the answer to "why does it do that?". + + +=================== +THE UNEVICTABLE LRU +=================== + +The Unevictable LRU facility adds an additional LRU list to track unevictable +pages and to hide these pages from vmscan. This mechanism is based on a patch +by Larry Woodman of Red Hat to address several scalability problems with page reclaim in Linux. The problems have been observed at customer sites on large -memory x86_64 systems. For example, a non-numal x86_64 platform with 128GB -of main memory will have over 32 million 4k pages in a single zone. When a -large fraction of these pages are not evictable for any reason [see below], -vmscan will spend a lot of time scanning the LRU lists looking for the small -fraction of pages that are evictable. This can result in a situation where -all cpus are spending 100% of their time in vmscan for hours or days on end, -with the system completely unresponsive. - -The Unevictable LRU infrastructure addresses the following classes of -unevictable pages: - -+ page owned by ramfs -+ page mapped into SHM_LOCKed shared memory regions -+ page mapped into VM_LOCKED [mlock()ed] vmas - -The infrastructure might be able to handle other conditions that make pages +memory x86_64 systems. + +To illustrate this with an example, a non-NUMA x86_64 platform with 128GB of +main memory will have over 32 million 4k pages in a single zone. When a large +fraction of these pages are not evictable for any reason [see below], vmscan +will spend a lot of time scanning the LRU lists looking for the small fraction +of pages that are evictable. This can result in a situation where all CPUs are +spending 100% of their time in vmscan for hours or days on end, with the system +completely unresponsive. + +The unevictable list addresses the following classes of unevictable pages: + + (*) Those owned by ramfs. + + (*) Those mapped into SHM_LOCK'd shared memory regions. + + (*) Those mapped into VM_LOCKED [mlock()ed] VMAs. + +The infrastructure may also be able to handle other conditions that make pages unevictable, either by definition or by circumstance, in the future. -The Unevictable LRU List +THE UNEVICTABLE PAGE LIST +------------------------- The Unevictable LRU infrastructure consists of an additional, per-zone, LRU list called the "unevictable" list and an associated page flag, PG_unevictable, to -indicate that the page is being managed on the unevictable list. The -PG_unevictable flag is analogous to, and mutually exclusive with, the PG_active -flag in that it indicates on which LRU list a page resides when PG_lru is set. -The unevictable LRU list is source configurable based on the UNEVICTABLE_LRU -Kconfig option. +indicate that the page is being managed on the unevictable list. + +The PG_unevictable flag is analogous to, and mutually exclusive with, the +PG_active flag in that it indicates on which LRU list a page resides when +PG_lru is set. The unevictable list is compile-time configurable based on the +UNEVICTABLE_LRU Kconfig option. The Unevictable LRU infrastructure maintains unevictable pages on an additional LRU list for a few reasons: -1) We get to "treat unevictable pages just like we treat other pages in the - system, which means we get to use the same code to manipulate them, the - same code to isolate them (for migrate, etc.), the same code to keep track - of the statistics, etc..." [Rik van Riel] + (1) We get to "treat unevictable pages just like we treat other pages in the + system - which means we get to use the same code to manipulate them, the + same code to isolate them (for migrate, etc.), the same code to keep track + of the statistics, etc..." [Rik van Riel] + + (2) We want to be able to migrate unevictable pages between nodes for memory + defragmentation, workload management and memory hotplug. The linux kernel + can only migrate pages that it can successfully isolate from the LRU + lists. If we were to maintain pages elsewhere than on an LRU-like list, + where they can be found by isolate_lru_page(), we would prevent their + migration, unless we reworked migration code to find the unevictable pages + itself. -2) We want to be able to migrate unevictable pages between nodes--for memory - defragmentation, workload management and memory hotplug. The linux kernel - can only migrate pages that it can successfully isolate from the lru lists. - If we were to maintain pages elsewise than on an lru-like list, where they - can be found by isolate_lru_page(), we would prevent their migration, unless - we reworked migration code to find the unevictable pages. +The unevictable list does not differentiate between file-backed and anonymous, +swap-backed pages. This differentiation is only important while the pages are, +in fact, evictable. -The unevictable LRU list does not differentiate between file backed and swap -backed [anon] pages. This differentiation is only important while the pages -are, in fact, evictable. +The unevictable list benefits from the "arrayification" of the per-zone LRU +lists and statistics originally proposed and posted by Christoph Lameter. -The unevictable LRU list benefits from the "arrayification" of the per-zone -LRU lists and statistics originally proposed and posted by Christoph Lameter. +The unevictable list does not use the LRU pagevec mechanism. Rather, +unevictable pages are placed directly on the page's zone's unevictable list +under the zone lru_lock. This allows us to prevent the stranding of pages on +the unevictable list when one task has the page isolated from the LRU and other +tasks are changing the "evictability" state of the page. -The unevictable list does not use the lru pagevec mechanism. Rather, -unevictable pages are placed directly on the page's zone's unevictable -list under the zone lru_lock. The reason for this is to prevent stranding -of pages on the unevictable list when one task has the page isolated from the -lru and other tasks are changing the "evictability" state of the page. +MEMORY CONTROL GROUP INTERACTION +-------------------------------- -Unevictable LRU and Memory Controller Interaction +The unevictable LRU facility interacts with the memory control group [aka +memory controller; see Documentation/cgroups/memory.txt] by extending the +lru_list enum. + +The memory controller data structure automatically gets a per-zone unevictable +list as a result of the "arrayification" of the per-zone LRU lists (one per +lru_list enum element). The memory controller tracks the movement of pages to +and from the unevictable list. -The memory controller data structure automatically gets a per zone unevictable -lru list as a result of the "arrayification" of the per-zone LRU lists. The -memory controller tracks the movement of pages to and from the unevictable list. When a memory control group comes under memory pressure, the controller will not attempt to reclaim pages on the unevictable list. This has a couple of -effects. Because the pages are "hidden" from reclaim on the unevictable list, -the reclaim process can be more efficient, dealing only with pages that have -a chance of being reclaimed. On the other hand, if too many of the pages -charged to the control group are unevictable, the evictable portion of the -working set of the tasks in the control group may not fit into the available -memory. This can cause the control group to thrash or to oom-kill tasks. - - -Unevictable LRU: Detecting Unevictable Pages - -The function page_evictable(page, vma) in vmscan.c determines whether a -page is evictable or not. For ramfs pages and pages in SHM_LOCKed regions, -page_evictable() tests a new address space flag, AS_UNEVICTABLE, in the page's -address space using a wrapper function. Wrapper functions are used to set, -clear and test the flag to reduce the requirement for #ifdef's throughout the -source code. AS_UNEVICTABLE is set on ramfs inode/mapping when it is created. -This flag remains for the life of the inode. - -For shared memory regions, AS_UNEVICTABLE is set when an application -successfully SHM_LOCKs the region and is removed when the region is -SHM_UNLOCKed. Note that shmctl(SHM_LOCK, ...) does not populate the page -tables for the region as does, for example, mlock(). So, we make no special -effort to push any pages in the SHM_LOCKed region to the unevictable list. -Vmscan will do this when/if it encounters the pages during reclaim. On -SHM_UNLOCK, shmctl() scans the pages in the region and "rescues" them from the -unevictable list if no other condition keeps them unevictable. If a SHM_LOCKed -region is destroyed, the pages are also "rescued" from the unevictable list in -the process of freeing them. - -page_evictable() detects mlock()ed pages by testing an additional page flag, -PG_mlocked via the PageMlocked() wrapper. If the page is NOT mlocked, and a -non-NULL vma is supplied, page_evictable() will check whether the vma is +effects: + + (1) Because the pages are "hidden" from reclaim on the unevictable list, the + reclaim process can be more efficient, dealing only with pages that have a + chance of being reclaimed. + + (2) On the other hand, if too many of the pages charged to the control group + are unevictable, the evictable portion of the working set of the tasks in + the control group may not fit into the available memory. This can cause + the control group to thrash or to OOM-kill tasks. + + +MARKING ADDRESS SPACES UNEVICTABLE +---------------------------------- + +For facilities such as ramfs none of the pages attached to the address space +may be evicted. To prevent eviction of any such pages, the AS_UNEVICTABLE +address space flag is provided, and this can be manipulated by a filesystem +using a number of wrapper functions: + + (*) void mapping_set_unevictable(struct address_space *mapping); + + Mark the address space as being completely unevictable. + + (*) void mapping_clear_unevictable(struct address_space *mapping); + + Mark the address space as being evictable. + + (*) int mapping_unevictable(struct address_space *mapping); + + Query the address space, and return true if it is completely + unevictable. + +These are currently used in two places in the kernel: + + (1) By ramfs to mark the address spaces of its inodes when they are created, + and this mark remains for the life of the inode. + + (2) By SYSV SHM to mark SHM_LOCK'd address spaces until SHM_UNLOCK is called. + + Note that SHM_LOCK is not required to page in the locked pages if they're + swapped out; the application must touch the pages manually if it wants to + ensure they're in memory. + + +DETECTING UNEVICTABLE PAGES +--------------------------- + +The function page_evictable() in vmscan.c determines whether a page is +evictable or not using the query function outlined above [see section "Marking +address spaces unevictable"] to check the AS_UNEVICTABLE flag. + +For address spaces that are so marked after being populated (as SHM regions +might be), the lock action (eg: SHM_LOCK) can be lazy, and need not populate +the page tables for the region as does, for example, mlock(), nor need it make +any special effort to push any pages in the SHM_LOCK'd area to the unevictable +list. Instead, vmscan will do this if and when it encounters the pages during +a reclamation scan. + +On an unlock action (such as SHM_UNLOCK), the unlocker (eg: shmctl()) must scan +the pages in the region and "rescue" them from the unevictable list if no other +condition is keeping them unevictable. If an unevictable region is destroyed, +the pages are also "rescued" from the unevictable list in the process of +freeing them. + +page_evictable() also checks for mlocked pages by testing an additional page +flag, PG_mlocked (as wrapped by PageMlocked()). If the page is NOT mlocked, +and a non-NULL VMA is supplied, page_evictable() will check whether the VMA is VM_LOCKED via is_mlocked_vma(). is_mlocked_vma() will SetPageMlocked() and update the appropriate statistics if the vma is VM_LOCKED. This method allows efficient "culling" of pages in the fault path that are being faulted in to -VM_LOCKED vmas. +VM_LOCKED VMAs. -Unevictable Pages and Vmscan [shrink_*_list()] +VMSCAN'S HANDLING OF UNEVICTABLE PAGES +-------------------------------------- If unevictable pages are culled in the fault path, or moved to the unevictable -list at mlock() or mmap() time, vmscan will never encounter the pages until -they have become evictable again, for example, via munlock() and have been -"rescued" from the unevictable list. However, there may be situations where we -decide, for the sake of expediency, to leave a unevictable page on one of the -regular active/inactive LRU lists for vmscan to deal with. Vmscan checks for -such pages in all of the shrink_{active|inactive|page}_list() functions and -will "cull" such pages that it encounters--that is, it diverts those pages to -the unevictable list for the zone being scanned. - -There may be situations where a page is mapped into a VM_LOCKED vma, but the -page is not marked as PageMlocked. Such pages will make it all the way to +list at mlock() or mmap() time, vmscan will not encounter the pages until they +have become evictable again (via munlock() for example) and have been "rescued" +from the unevictable list. However, there may be situations where we decide, +for the sake of expediency, to leave a unevictable page on one of the regular +active/inactive LRU lists for vmscan to deal with. vmscan checks for such +pages in all of the shrink_{active|inactive|page}_list() functions and will +"cull" such pages that it encounters: that is, it diverts those pages to the +unevictable list for the zone being scanned. + +There may be situations where a page is mapped into a VM_LOCKED VMA, but the +page is not marked as PG_mlocked. Such pages will make it all the way to shrink_page_list() where they will be detected when vmscan walks the reverse -map in try_to_unmap(). If try_to_unmap() returns SWAP_MLOCK, shrink_page_list() -will cull the page at that point. +map in try_to_unmap(). If try_to_unmap() returns SWAP_MLOCK, +shrink_page_list() will cull the page at that point. -To "cull" an unevictable page, vmscan simply puts the page back on the lru -list using putback_lru_page()--the inverse operation to isolate_lru_page()-- -after dropping the page lock. Because the condition which makes the page -unevictable may change once the page is unlocked, putback_lru_page() will -recheck the unevictable state of a page that it places on the unevictable lru -list. If the page has become unevictable, putback_lru_page() removes it from -the list and retries, including the page_unevictable() test. Because such a -race is a rare event and movement of pages onto the unevictable list should be -rare, these extra evictabilty checks should not occur in the majority of calls -to putback_lru_page(). +To "cull" an unevictable page, vmscan simply puts the page back on the LRU list +using putback_lru_page() - the inverse operation to isolate_lru_page() - after +dropping the page lock. Because the condition which makes the page unevictable +may change once the page is unlocked, putback_lru_page() will recheck the +unevictable state of a page that it places on the unevictable list. If the +page has become unevictable, putback_lru_page() removes it from the list and +retries, including the page_unevictable() test. Because such a race is a rare +event and movement of pages onto the unevictable list should be rare, these +extra evictabilty checks should not occur in the majority of calls to +putback_lru_page(). -Mlocked Page: Prior Work +============= +MLOCKED PAGES +============= -The "Unevictable Mlocked Pages" infrastructure is based on work originally +The unevictable page list is also useful for mlock(), in addition to ramfs and +SYSV SHM. Note that mlock() is only available in CONFIG_MMU=y situations; in +NOMMU situations, all mappings are effectively mlocked. + + +HISTORY +------- + +The "Unevictable mlocked Pages" infrastructure is based on work originally posted by Nick Piggin in an RFC patch entitled "mm: mlocked pages off LRU". -Nick posted his patch as an alternative to a patch posted by Christoph -Lameter to achieve the same objective--hiding mlocked pages from vmscan. -In Nick's patch, he used one of the struct page lru list link fields as a count -of VM_LOCKED vmas that map the page. This use of the link field for a count -prevented the management of the pages on an LRU list. Thus, mlocked pages were -not migratable as isolate_lru_page() could not find them and the lru list link -field was not available to the migration subsystem. Nick resolved this by -putting mlocked pages back on the lru list before attempting to isolate them, -thus abandoning the count of VM_LOCKED vmas. When Nick's patch was integrated -with the Unevictable LRU work, the count was replaced by walking the reverse -map to determine whether any VM_LOCKED vmas mapped the page. More on this -below. - - -Mlocked Pages: Basic Management - -Mlocked pages--pages mapped into a VM_LOCKED vma--represent one class of -unevictable pages. When such a page has been "noticed" by the memory -management subsystem, the page is marked with the PG_mlocked [PageMlocked()] -flag. A PageMlocked() page will be placed on the unevictable LRU list when -it is added to the LRU. Pages can be "noticed" by memory management in -several places: - -1) in the mlock()/mlockall() system call handlers. -2) in the mmap() system call handler when mmap()ing a region with the - MAP_LOCKED flag, or mmap()ing a region in a task that has called - mlockall() with the MCL_FUTURE flag. Both of these conditions result - in the VM_LOCKED flag being set for the vma. -3) in the fault path, if mlocked pages are "culled" in the fault path, - and when a VM_LOCKED stack segment is expanded. -4) as mentioned above, in vmscan:shrink_page_list() when attempting to - reclaim a page in a VM_LOCKED vma via try_to_unmap(). - -Mlocked pages become unlocked and rescued from the unevictable list when: - -1) mapped in a range unlocked via the munlock()/munlockall() system calls. -2) munmapped() out of the last VM_LOCKED vma that maps the page, including - unmapping at task exit. -3) when the page is truncated from the last VM_LOCKED vma of an mmap()ed file. -4) before a page is COWed in a VM_LOCKED vma. - - -Mlocked Pages: mlock()/mlockall() System Call Handling +Nick posted his patch as an alternative to a patch posted by Christoph Lameter +to achieve the same objective: hiding mlocked pages from vmscan. + +In Nick's patch, he used one of the struct page LRU list link fields as a count +of VM_LOCKED VMAs that map the page. This use of the link field for a count +prevented the management of the pages on an LRU list, and thus mlocked pages +were not migratable as isolate_lru_page() could not find them, and the LRU list +link field was not available to the migration subsystem. + +Nick resolved this by putting mlocked pages back on the lru list before +attempting to isolate them, thus abandoning the count of VM_LOCKED VMAs. When +Nick's patch was integrated with the Unevictable LRU work, the count was +replaced by walking the reverse map to determine whether any VM_LOCKED VMAs +mapped the page. More on this below. + + +BASIC MANAGEMENT +---------------- + +mlocked pages - pages mapped into a VM_LOCKED VMA - are a class of unevictable +pages. When such a page has been "noticed" by the memory management subsystem, +the page is marked with the PG_mlocked flag. This can be manipulated using the +PageMlocked() functions. + +A PG_mlocked page will be placed on the unevictable list when it is added to +the LRU. Such pages can be "noticed" by memory management in several places: + + (1) in the mlock()/mlockall() system call handlers; + + (2) in the mmap() system call handler when mmapping a region with the + MAP_LOCKED flag; + + (3) mmapping a region in a task that has called mlockall() with the MCL_FUTURE + flag + + (4) in the fault path, if mlocked pages are "culled" in the fault path, + and when a VM_LOCKED stack segment is expanded; or + + (5) as mentioned above, in vmscan:shrink_page_list() when attempting to + reclaim a page in a VM_LOCKED VMA via try_to_unmap() + +all of which result in the VM_LOCKED flag being set for the VMA if it doesn't +already have it set. + +mlocked pages become unlocked and rescued from the unevictable list when: + + (1) mapped in a range unlocked via the munlock()/munlockall() system calls; + + (2) munmap()'d out of the last VM_LOCKED VMA that maps the page, including + unmapping at task exit; + + (3) when the page is truncated from the last VM_LOCKED VMA of an mmapped file; + or + + (4) before a page is COW'd in a VM_LOCKED VMA. + + +mlock()/mlockall() SYSTEM CALL HANDLING +--------------------------------------- Both [do_]mlock() and [do_]mlockall() system call handlers call mlock_fixup() -for each vma in the range specified by the call. In the case of mlockall(), +for each VMA in the range specified by the call. In the case of mlockall(), this is the entire active address space of the task. Note that mlock_fixup() -is used for both mlock()ing and munlock()ing a range of memory. A call to -mlock() an already VM_LOCKED vma, or to munlock() a vma that is not VM_LOCKED -is treated as a no-op--mlock_fixup() simply returns. - -If the vma passes some filtering described in "Mlocked Pages: Filtering Vmas" -below, mlock_fixup() will attempt to merge the vma with its neighbors or split -off a subset of the vma if the range does not cover the entire vma. Once the -vma has been merged or split or neither, mlock_fixup() will call -__mlock_vma_pages_range() to fault in the pages via get_user_pages() and -to mark the pages as mlocked via mlock_vma_page(). - -Note that the vma being mlocked might be mapped with PROT_NONE. In this case, -get_user_pages() will be unable to fault in the pages. That's OK. If pages -do end up getting faulted into this VM_LOCKED vma, we'll handle them in the +is used for both mlocking and munlocking a range of memory. A call to mlock() +an already VM_LOCKED VMA, or to munlock() a VMA that is not VM_LOCKED is +treated as a no-op, and mlock_fixup() simply returns. + +If the VMA passes some filtering as described in "Filtering Special Vmas" +below, mlock_fixup() will attempt to merge the VMA with its neighbors or split +off a subset of the VMA if the range does not cover the entire VMA. Once the +VMA has been merged or split or neither, mlock_fixup() will call +__mlock_vma_pages_range() to fault in the pages via get_user_pages() and to +mark the pages as mlocked via mlock_vma_page(). + +Note that the VMA being mlocked might be mapped with PROT_NONE. In this case, +get_user_pages() will be unable to fault in the pages. That's okay. If pages +do end up getting faulted into this VM_LOCKED VMA, we'll handle them in the fault path or in vmscan. Also note that a page returned by get_user_pages() could be truncated or -migrated out from under us, while we're trying to mlock it. To detect -this, __mlock_vma_pages_range() tests the page_mapping after acquiring -the page lock. If the page is still associated with its mapping, we'll -go ahead and call mlock_vma_page(). If the mapping is gone, we just -unlock the page and move on. Worse case, this results in page mapped -in a VM_LOCKED vma remaining on a normal LRU list without being -PageMlocked(). Again, vmscan will detect and cull such pages. - -mlock_vma_page(), called with the page locked [N.B., not "mlocked"], will -TestSetPageMlocked() for each page returned by get_user_pages(). We use -TestSetPageMlocked() because the page might already be mlocked by another -task/vma and we don't want to do extra work. We especially do not want to -count an mlocked page more than once in the statistics. If the page was -already mlocked, mlock_vma_page() is done. +migrated out from under us, while we're trying to mlock it. To detect this, +__mlock_vma_pages_range() checks page_mapping() after acquiring the page lock. +If the page is still associated with its mapping, we'll go ahead and call +mlock_vma_page(). If the mapping is gone, we just unlock the page and move on. +In the worst case, this will result in a page mapped in a VM_LOCKED VMA +remaining on a normal LRU list without being PageMlocked(). Again, vmscan will +detect and cull such pages. + +mlock_vma_page() will call TestSetPageMlocked() for each page returned by +get_user_pages(). We use TestSetPageMlocked() because the page might already +be mlocked by another task/VMA and we don't want to do extra work. We +especially do not want to count an mlocked page more than once in the +statistics. If the page was already mlocked, mlock_vma_page() need do nothing +more. If the page was NOT already mlocked, mlock_vma_page() attempts to isolate the page from the LRU, as it is likely on the appropriate active or inactive list -at that time. If the isolate_lru_page() succeeds, mlock_vma_page() will -putback the page--putback_lru_page()--which will notice that the page is now -mlocked and divert the page to the zone's unevictable LRU list. If +at that time. If the isolate_lru_page() succeeds, mlock_vma_page() will put +back the page - by calling putback_lru_page() - which will notice that the page +is now mlocked and divert the page to the zone's unevictable list. If mlock_vma_page() is unable to isolate the page from the LRU, vmscan will handle -it later if/when it attempts to reclaim the page. +it later if and when it attempts to reclaim the page. -Mlocked Pages: Filtering Special Vmas +FILTERING SPECIAL VMAS +---------------------- -mlock_fixup() filters several classes of "special" vmas: +mlock_fixup() filters several classes of "special" VMAs: -1) vmas with VM_IO|VM_PFNMAP set are skipped entirely. The pages behind +1) VMAs with VM_IO or VM_PFNMAP set are skipped entirely. The pages behind these mappings are inherently pinned, so we don't need to mark them as - mlocked. In any case, most of the pages have no struct page in which to - so mark the page. Because of this, get_user_pages() will fail for these - vmas, so there is no sense in attempting to visit them. - -2) vmas mapping hugetlbfs page are already effectively pinned into memory. - We don't need nor want to mlock() these pages. However, to preserve the - prior behavior of mlock()--before the unevictable/mlock changes-- - mlock_fixup() will call make_pages_present() in the hugetlbfs vma range - to allocate the huge pages and populate the ptes. - -3) vmas with VM_DONTEXPAND|VM_RESERVED are generally user space mappings of - kernel pages, such as the vdso page, relay channel pages, etc. These pages + mlocked. In any case, most of the pages have no struct page in which to so + mark the page. Because of this, get_user_pages() will fail for these VMAs, + so there is no sense in attempting to visit them. + +2) VMAs mapping hugetlbfs page are already effectively pinned into memory. We + neither need nor want to mlock() these pages. However, to preserve the + prior behavior of mlock() - before the unevictable/mlock changes - + mlock_fixup() will call make_pages_present() in the hugetlbfs VMA range to + allocate the huge pages and populate the ptes. + +3) VMAs with VM_DONTEXPAND or VM_RESERVED are generally userspace mappings of + kernel pages, such as the VDSO page, relay channel pages, etc. These pages are inherently unevictable and are not managed on the LRU lists. - mlock_fixup() treats these vmas the same as hugetlbfs vmas. It calls + mlock_fixup() treats these VMAs the same as hugetlbfs VMAs. It calls make_pages_present() to populate the ptes. -Note that for all of these special vmas, mlock_fixup() does not set the +Note that for all of these special VMAs, mlock_fixup() does not set the VM_LOCKED flag. Therefore, we won't have to deal with them later during -munlock() or munmap()--for example, at task exit. Neither does mlock_fixup() -account these vmas against the task's "locked_vm". - -Mlocked Pages: Downgrading the Mmap Semaphore. - -mlock_fixup() must be called with the mmap semaphore held for write, because -it may have to merge or split vmas. However, mlocking a large region of -memory can take a long time--especially if vmscan must reclaim pages to -satisfy the regions requirements. Faulting in a large region with the mmap -semaphore held for write can hold off other faults on the address space, in -the case of a multi-threaded task. It can also hold off scans of the task's -address space via /proc. While testing under heavy load, it was observed that -the ps(1) command could be held off for many minutes while a large segment was -mlock()ed down. - -To address this issue, and to make the system more responsive during mlock()ing -of large segments, mlock_fixup() downgrades the mmap semaphore to read mode -during the call to __mlock_vma_pages_range(). This works fine. However, the -callers of mlock_fixup() expect the semaphore to be returned in write mode. -So, mlock_fixup() "upgrades" the semphore to write mode. Linux does not -support an atomic upgrade_sem() call, so mlock_fixup() must drop the semaphore -and reacquire it in write mode. In a multi-threaded task, it is possible for -the task memory map to change while the semaphore is dropped. Therefore, -mlock_fixup() looks up the vma at the range start address after reacquiring -the semaphore in write mode and verifies that it still covers the original -range. If not, mlock_fixup() returns an error [-EAGAIN]. All callers of -mlock_fixup() have been changed to deal with this new error condition. - -Note: when munlocking a region, all of the pages should already be resident-- -unless we have racing threads mlocking() and munlocking() regions. So, -unlocking should not have to wait for page allocations nor faults of any kind. -Therefore mlock_fixup() does not downgrade the semaphore for munlock(). - - -Mlocked Pages: munlock()/munlockall() System Call Handling - -The munlock() and munlockall() system calls are handled by the same functions-- -do_mlock[all]()--as the mlock() and mlockall() system calls with the unlock -vs lock operation indicated by an argument. So, these system calls are also -handled by mlock_fixup(). Again, if called for an already munlock()ed vma, -mlock_fixup() simply returns. Because of the vma filtering discussed above, -VM_LOCKED will not be set in any "special" vmas. So, these vmas will be +munlock(), munmap() or task exit. Neither does mlock_fixup() account these +VMAs against the task's "locked_vm". + + +munlock()/munlockall() SYSTEM CALL HANDLING +------------------------------------------- + +The munlock() and munlockall() system calls are handled by the same functions - +do_mlock[all]() - as the mlock() and mlockall() system calls with the unlock vs +lock operation indicated by an argument. So, these system calls are also +handled by mlock_fixup(). Again, if called for an already munlocked VMA, +mlock_fixup() simply returns. Because of the VMA filtering discussed above, +VM_LOCKED will not be set in any "special" VMAs. So, these VMAs will be ignored for munlock. -If the vma is VM_LOCKED, mlock_fixup() again attempts to merge or split off -the specified range. The range is then munlocked via the function -__mlock_vma_pages_range()--the same function used to mlock a vma range-- +If the VMA is VM_LOCKED, mlock_fixup() again attempts to merge or split off the +specified range. The range is then munlocked via the function +__mlock_vma_pages_range() - the same function used to mlock a VMA range - passing a flag to indicate that munlock() is being performed. -Because the vma access protections could have been changed to PROT_NONE after +Because the VMA access protections could have been changed to PROT_NONE after faulting in and mlocking pages, get_user_pages() was unreliable for visiting -these pages for munlocking. Because we don't want to leave pages mlocked(), +these pages for munlocking. Because we don't want to leave pages mlocked, get_user_pages() was enhanced to accept a flag to ignore the permissions when -fetching the pages--all of which should be resident as a result of previous -mlock()ing. +fetching the pages - all of which should be resident as a result of previous +mlocking. For munlock(), __mlock_vma_pages_range() unlocks individual pages by calling munlock_vma_page(). munlock_vma_page() unconditionally clears the PG_mlocked -flag using TestClearPageMlocked(). As with mlock_vma_page(), munlock_vma_page() -use the Test*PageMlocked() function to handle the case where the page might -have already been unlocked by another task. If the page was mlocked, -munlock_vma_page() updates that zone statistics for the number of mlocked -pages. Note, however, that at this point we haven't checked whether the page -is mapped by other VM_LOCKED vmas. - -We can't call try_to_munlock(), the function that walks the reverse map to check -for other VM_LOCKED vmas, without first isolating the page from the LRU. +flag using TestClearPageMlocked(). As with mlock_vma_page(), +munlock_vma_page() use the Test*PageMlocked() function to handle the case where +the page might have already been unlocked by another task. If the page was +mlocked, munlock_vma_page() updates that zone statistics for the number of +mlocked pages. Note, however, that at this point we haven't checked whether +the page is mapped by other VM_LOCKED VMAs. + +We can't call try_to_munlock(), the function that walks the reverse map to +check for other VM_LOCKED VMAs, without first isolating the page from the LRU. try_to_munlock() is a variant of try_to_unmap() and thus requires that the page -not be on an lru list. [More on these below.] However, the call to -isolate_lru_page() could fail, in which case we couldn't try_to_munlock(). -So, we go ahead and clear PG_mlocked up front, as this might be the only chance -we have. If we can successfully isolate the page, we go ahead and +not be on an LRU list [more on these below]. However, the call to +isolate_lru_page() could fail, in which case we couldn't try_to_munlock(). So, +we go ahead and clear PG_mlocked up front, as this might be the only chance we +have. If we can successfully isolate the page, we go ahead and try_to_munlock(), which will restore the PG_mlocked flag and update the zone -page statistics if it finds another vma holding the page mlocked. If we fail +page statistics if it finds another VMA holding the page mlocked. If we fail to isolate the page, we'll have left a potentially mlocked page on the LRU. -This is fine, because we'll catch it later when/if vmscan tries to reclaim the -page. This should be relatively rare. - -Mlocked Pages: Migrating Them... - -A page that is being migrated has been isolated from the lru lists and is -held locked across unmapping of the page, updating the page's mapping -[address_space] entry and copying the contents and state, until the -page table entry has been replaced with an entry that refers to the new -page. Linux supports migration of mlocked pages and other unevictable -pages. This involves simply moving the PageMlocked and PageUnevictable states -from the old page to the new page. - -Note that page migration can race with mlocking or munlocking of the same -page. This has been discussed from the mlock/munlock perspective in the -respective sections above. Both processes [migration, m[un]locking], hold -the page locked. This provides the first level of synchronization. Page -migration zeros out the page_mapping of the old page before unlocking it, -so m[un]lock can skip these pages by testing the page mapping under page -lock. - -When completing page migration, we place the new and old pages back onto the -lru after dropping the page lock. The "unneeded" page--old page on success, -new page on failure--will be freed when the reference count held by the -migration process is released. To ensure that we don't strand pages on the -unevictable list because of a race between munlock and migration, page -migration uses the putback_lru_page() function to add migrated pages back to -the lru. - - -Mlocked Pages: mmap(MAP_LOCKED) System Call Handling +This is fine, because we'll catch it later if and if vmscan tries to reclaim +the page. This should be relatively rare. + + +MIGRATING MLOCKED PAGES +----------------------- + +A page that is being migrated has been isolated from the LRU lists and is held +locked across unmapping of the page, updating the page's address space entry +and copying the contents and state, until the page table entry has been +replaced with an entry that refers to the new page. Linux supports migration +of mlocked pages and other unevictable pages. This involves simply moving the +PG_mlocked and PG_unevictable states from the old page to the new page. + +Note that page migration can race with mlocking or munlocking of the same page. +This has been discussed from the mlock/munlock perspective in the respective +sections above. Both processes (migration and m[un]locking) hold the page +locked. This provides the first level of synchronization. Page migration +zeros out the page_mapping of the old page before unlocking it, so m[un]lock +can skip these pages by testing the page mapping under page lock. + +To complete page migration, we place the new and old pages back onto the LRU +after dropping the page lock. The "unneeded" page - old page on success, new +page on failure - will be freed when the reference count held by the migration +process is released. To ensure that we don't strand pages on the unevictable +list because of a race between munlock and migration, page migration uses the +putback_lru_page() function to add migrated pages back to the LRU. + + +mmap(MAP_LOCKED) SYSTEM CALL HANDLING +------------------------------------- In addition the the mlock()/mlockall() system calls, an application can request -that a region of memory be mlocked using the MAP_LOCKED flag with the mmap() +that a region of memory be mlocked supplying the MAP_LOCKED flag to the mmap() call. Furthermore, any mmap() call or brk() call that expands the heap by a task that has previously called mlockall() with the MCL_FUTURE flag will result -in the newly mapped memory being mlocked. Before the unevictable/mlock changes, -the kernel simply called make_pages_present() to allocate pages and populate -the page table. +in the newly mapped memory being mlocked. Before the unevictable/mlock +changes, the kernel simply called make_pages_present() to allocate pages and +populate the page table. To mlock a range of memory under the unevictable/mlock infrastructure, the mmap() handler and task address space expansion functions call mlock_vma_pages_range() specifying the vma and the address range to mlock. -mlock_vma_pages_range() filters vmas like mlock_fixup(), as described above in -"Mlocked Pages: Filtering Vmas". It will clear the VM_LOCKED flag, which will -have already been set by the caller, in filtered vmas. Thus these vma's need -not be visited for munlock when the region is unmapped. +mlock_vma_pages_range() filters VMAs like mlock_fixup(), as described above in +"Filtering Special VMAs". It will clear the VM_LOCKED flag, which will have +already been set by the caller, in filtered VMAs. Thus these VMA's need not be +visited for munlock when the region is unmapped. -For "normal" vmas, mlock_vma_pages_range() calls __mlock_vma_pages_range() to +For "normal" VMAs, mlock_vma_pages_range() calls __mlock_vma_pages_range() to fault/allocate the pages and mlock them. Again, like mlock_fixup(), mlock_vma_pages_range() downgrades the mmap semaphore to read mode before -attempting to fault/allocate and mlock the pages; and "upgrades" the semaphore +attempting to fault/allocate and mlock the pages and "upgrades" the semaphore back to write mode before returning. -The callers of mlock_vma_pages_range() will have already added the memory -range to be mlocked to the task's "locked_vm". To account for filtered vmas, +The callers of mlock_vma_pages_range() will have already added the memory range +to be mlocked to the task's "locked_vm". To account for filtered VMAs, mlock_vma_pages_range() returns the number of pages NOT mlocked. All of the -callers then subtract a non-negative return value from the task's locked_vm. -A negative return value represent an error--for example, from get_user_pages() -attempting to fault in a vma with PROT_NONE access. In this case, we leave -the memory range accounted as locked_vm, as the protections could be changed -later and pages allocated into that region. +callers then subtract a non-negative return value from the task's locked_vm. A +negative return value represent an error - for example, from get_user_pages() +attempting to fault in a VMA with PROT_NONE access. In this case, we leave the +memory range accounted as locked_vm, as the protections could be changed later +and pages allocated into that region. -Mlocked Pages: munmap()/exit()/exec() System Call Handling +munmap()/exit()/exec() SYSTEM CALL HANDLING +------------------------------------------- When unmapping an mlocked region of memory, whether by an explicit call to munmap() or via an internal unmap from exit() or exec() processing, we must -munlock the pages if we're removing the last VM_LOCKED vma that maps the pages. +munlock the pages if we're removing the last VM_LOCKED VMA that maps the pages. Before the unevictable/mlock changes, mlocking did not mark the pages in any way, so unmapping them required no processing. To munlock a range of memory under the unevictable/mlock infrastructure, the -munmap() hander and task address space tear down function call +munmap() handler and task address space call tear down function munlock_vma_pages_all(). The name reflects the observation that one always -specifies the entire vma range when munlock()ing during unmap of a region. -Because of the vma filtering when mlocking() regions, only "normal" vmas that +specifies the entire VMA range when munlock()ing during unmap of a region. +Because of the VMA filtering when mlocking() regions, only "normal" VMAs that actually contain mlocked pages will be passed to munlock_vma_pages_all(). -munlock_vma_pages_all() clears the VM_LOCKED vma flag and, like mlock_fixup() +munlock_vma_pages_all() clears the VM_LOCKED VMA flag and, like mlock_fixup() for the munlock case, calls __munlock_vma_pages_range() to walk the page table -for the vma's memory range and munlock_vma_page() each resident page mapped by -the vma. This effectively munlocks the page, only if this is the last -VM_LOCKED vma that maps the page. - +for the VMA's memory range and munlock_vma_page() each resident page mapped by +the VMA. This effectively munlocks the page, only if this is the last +VM_LOCKED VMA that maps the page. -Mlocked Page: try_to_unmap() -[Note: the code changes represented by this section are really quite small -compared to the text to describe what happening and why, and to discuss the -implications.] +try_to_unmap() +-------------- -Pages can, of course, be mapped into multiple vmas. Some of these vmas may +Pages can, of course, be mapped into multiple VMAs. Some of these VMAs may have VM_LOCKED flag set. It is possible for a page mapped into one or more -VM_LOCKED vmas not to have the PG_mlocked flag set and therefore reside on one -of the active or inactive LRU lists. This could happen if, for example, a -task in the process of munlock()ing the page could not isolate the page from -the LRU. As a result, vmscan/shrink_page_list() might encounter such a page -as described in "Unevictable Pages and Vmscan [shrink_*_list()]". To -handle this situation, try_to_unmap() has been enhanced to check for VM_LOCKED -vmas while it is walking a page's reverse map. +VM_LOCKED VMAs not to have the PG_mlocked flag set and therefore reside on one +of the active or inactive LRU lists. This could happen if, for example, a task +in the process of munlocking the page could not isolate the page from the LRU. +As a result, vmscan/shrink_page_list() might encounter such a page as described +in section "vmscan's handling of unevictable pages". To handle this situation, +try_to_unmap() checks for VM_LOCKED VMAs while it is walking a page's reverse +map. try_to_unmap() is always called, by either vmscan for reclaim or for page -migration, with the argument page locked and isolated from the LRU. BUG_ON() -assertions enforce this requirement. Separate functions handle anonymous and -mapped file pages, as these types of pages have different reverse map -mechanisms. - - try_to_unmap_anon() - -To unmap anonymous pages, each vma in the list anchored in the anon_vma must be -visited--at least until a VM_LOCKED vma is encountered. If the page is being -unmapped for migration, VM_LOCKED vmas do not stop the process because mlocked -pages are migratable. However, for reclaim, if the page is mapped into a -VM_LOCKED vma, the scan stops. try_to_unmap() attempts to acquire the mmap -semphore of the mm_struct to which the vma belongs in read mode. If this is -successful, try_to_unmap() will mlock the page via mlock_vma_page()--we -wouldn't have gotten to try_to_unmap() if the page were already mlocked--and -will return SWAP_MLOCK, indicating that the page is unevictable. If the -mmap semaphore cannot be acquired, we are not sure whether the page is really -unevictable or not. In this case, try_to_unmap() will return SWAP_AGAIN. - - try_to_unmap_file() -- linear mappings - -Unmapping of a mapped file page works the same, except that the scan visits -all vmas that maps the page's index/page offset in the page's mapping's -reverse map priority search tree. It must also visit each vma in the page's -mapping's non-linear list, if the list is non-empty. As for anonymous pages, -on encountering a VM_LOCKED vma for a mapped file page, try_to_unmap() will -attempt to acquire the associated mm_struct's mmap semaphore to mlock the page, -returning SWAP_MLOCK if this is successful, and SWAP_AGAIN, if not. - - try_to_unmap_file() -- non-linear mappings - -If a page's mapping contains a non-empty non-linear mapping vma list, then -try_to_un{map|lock}() must also visit each vma in that list to determine -whether the page is mapped in a VM_LOCKED vma. Again, the scan must visit -all vmas in the non-linear list to ensure that the pages is not/should not be -mlocked. If a VM_LOCKED vma is found in the list, the scan could terminate. -However, there is no easy way to determine whether the page is actually mapped -in a given vma--either for unmapping or testing whether the VM_LOCKED vma -actually pins the page. - -So, try_to_unmap_file() handles non-linear mappings by scanning a certain -number of pages--a "cluster"--in each non-linear vma associated with the page's -mapping, for each file mapped page that vmscan tries to unmap. If this happens -to unmap the page we're trying to unmap, try_to_unmap() will notice this on -return--(page_mapcount(page) == 0)--and return SWAP_SUCCESS. Otherwise, it -will return SWAP_AGAIN, causing vmscan to recirculate this page. We take -advantage of the cluster scan in try_to_unmap_cluster() as follows: - -For each non-linear vma, try_to_unmap_cluster() attempts to acquire the mmap -semaphore of the associated mm_struct for read without blocking. If this -attempt is successful and the vma is VM_LOCKED, try_to_unmap_cluster() will -retain the mmap semaphore for the scan; otherwise it drops it here. Then, -for each page in the cluster, if we're holding the mmap semaphore for a locked -vma, try_to_unmap_cluster() calls mlock_vma_page() to mlock the page. This -call is a no-op if the page is already locked, but will mlock any pages in -the non-linear mapping that happen to be unlocked. If one of the pages so -mlocked is the page passed in to try_to_unmap(), try_to_unmap_cluster() will -return SWAP_MLOCK, rather than the default SWAP_AGAIN. This will allow vmscan -to cull the page, rather than recirculating it on the inactive list. Again, -if try_to_unmap_cluster() cannot acquire the vma's mmap sem, it returns -SWAP_AGAIN, indicating that the page is mapped by a VM_LOCKED vma, but -couldn't be mlocked. - - -Mlocked pages: try_to_munlock() Reverse Map Scan - -TODO/FIXME: a better name might be page_mlocked()--analogous to the -page_referenced() reverse map walker. - -When munlock_vma_page()--see "Mlocked Pages: munlock()/munlockall() -System Call Handling" above--tries to munlock a page, it needs to -determine whether or not the page is mapped by any VM_LOCKED vma, without -actually attempting to unmap all ptes from the page. For this purpose, the -unevictable/mlock infrastructure introduced a variant of try_to_unmap() called -try_to_munlock(). +migration, with the argument page locked and isolated from the LRU. Separate +functions handle anonymous and mapped file pages, as these types of pages have +different reverse map mechanisms. + + (*) try_to_unmap_anon() + + To unmap anonymous pages, each VMA in the list anchored in the anon_vma + must be visited - at least until a VM_LOCKED VMA is encountered. If the + page is being unmapped for migration, VM_LOCKED VMAs do not stop the + process because mlocked pages are migratable. However, for reclaim, if + the page is mapped into a VM_LOCKED VMA, the scan stops. + + try_to_unmap_anon() attempts to acquire in read mode the mmap semphore of + the mm_struct to which the VMA belongs. If this is successful, it will + mlock the page via mlock_vma_page() - we wouldn't have gotten to + try_to_unmap_anon() if the page were already mlocked - and will return + SWAP_MLOCK, indicating that the page is unevictable. + + If the mmap semaphore cannot be acquired, we are not sure whether the page + is really unevictable or not. In this case, try_to_unmap_anon() will + return SWAP_AGAIN. + + (*) try_to_unmap_file() - linear mappings + + Unmapping of a mapped file page works the same as for anonymous mappings, + except that the scan visits all VMAs that map the page's index/page offset + in the page's mapping's reverse map priority search tree. It also visits + each VMA in the page's mapping's non-linear list, if the list is + non-empty. + + As for anonymous pages, on encountering a VM_LOCKED VMA for a mapped file + page, try_to_unmap_file() will attempt to acquire the associated + mm_struct's mmap semaphore to mlock the page, returning SWAP_MLOCK if this + is successful, and SWAP_AGAIN, if not. + + (*) try_to_unmap_file() - non-linear mappings + + If a page's mapping contains a non-empty non-linear mapping VMA list, then + try_to_un{map|lock}() must also visit each VMA in that list to determine + whether the page is mapped in a VM_LOCKED VMA. Again, the scan must visit + all VMAs in the non-linear list to ensure that the pages is not/should not + be mlocked. + + If a VM_LOCKED VMA is found in the list, the scan could terminate. + However, there is no easy way to determine whether the page is actually + mapped in a given VMA - either for unmapping or testing whether the + VM_LOCKED VMA actually pins the page. + + try_to_unmap_file() handles non-linear mappings by scanning a certain + number of pages - a "cluster" - in each non-linear VMA associated with the + page's mapping, for each file mapped page that vmscan tries to unmap. If + this happens to unmap the page we're trying to unmap, try_to_unmap() will + notice this on return (page_mapcount(page) will be 0) and return + SWAP_SUCCESS. Otherwise, it will return SWAP_AGAIN, causing vmscan to + recirculate this page. We take advantage of the cluster scan in + try_to_unmap_cluster() as follows: + + For each non-linear VMA, try_to_unmap_cluster() attempts to acquire the + mmap semaphore of the associated mm_struct for read without blocking. + + If this attempt is successful and the VMA is VM_LOCKED, + try_to_unmap_cluster() will retain the mmap semaphore for the scan; + otherwise it drops it here. + + Then, for each page in the cluster, if we're holding the mmap semaphore + for a locked VMA, try_to_unmap_cluster() calls mlock_vma_page() to + mlock the page. This call is a no-op if the page is already locked, + but will mlock any pages in the non-linear mapping that happen to be + unlocked. + + If one of the pages so mlocked is the page passed in to try_to_unmap(), + try_to_unmap_cluster() will return SWAP_MLOCK, rather than the default + SWAP_AGAIN. This will allow vmscan to cull the page, rather than + recirculating it on the inactive list. + + Again, if try_to_unmap_cluster() cannot acquire the VMA's mmap sem, it + returns SWAP_AGAIN, indicating that the page is mapped by a VM_LOCKED + VMA, but couldn't be mlocked. + + +try_to_munlock() REVERSE MAP SCAN +--------------------------------- + + [!] TODO/FIXME: a better name might be page_mlocked() - analogous to the + page_referenced() reverse map walker. + +When munlock_vma_page() [see section "munlock()/munlockall() System Call +Handling" above] tries to munlock a page, it needs to determine whether or not +the page is mapped by any VM_LOCKED VMA without actually attempting to unmap +all PTEs from the page. For this purpose, the unevictable/mlock infrastructure +introduced a variant of try_to_unmap() called try_to_munlock(). try_to_munlock() calls the same functions as try_to_unmap() for anonymous and mapped file pages with an additional argument specifing unlock versus unmap processing. Again, these functions walk the respective reverse maps looking -for VM_LOCKED vmas. When such a vma is found for anonymous pages and file +for VM_LOCKED VMAs. When such a VMA is found for anonymous pages and file pages mapped in linear VMAs, as in the try_to_unmap() case, the functions attempt to acquire the associated mmap semphore, mlock the page via mlock_vma_page() and return SWAP_MLOCK. This effectively undoes the pre-clearing of the page's PG_mlocked done by munlock_vma_page. -If try_to_unmap() is unable to acquire a VM_LOCKED vma's associated mmap -semaphore, it will return SWAP_AGAIN. This will allow shrink_page_list() -to recycle the page on the inactive list and hope that it has better luck -with the page next time. - -For file pages mapped into non-linear vmas, the try_to_munlock() logic works -slightly differently. On encountering a VM_LOCKED non-linear vma that might -map the page, try_to_munlock() returns SWAP_AGAIN without actually mlocking -the page. munlock_vma_page() will just leave the page unlocked and let -vmscan deal with it--the usual fallback position. - -Note that try_to_munlock()'s reverse map walk must visit every vma in a pages' -reverse map to determine that a page is NOT mapped into any VM_LOCKED vma. -However, the scan can terminate when it encounters a VM_LOCKED vma and can -successfully acquire the vma's mmap semphore for read and mlock the page. -Although try_to_munlock() can be called many [very many!] times when -munlock()ing a large region or tearing down a large address space that has been -mlocked via mlockall(), overall this is a fairly rare event. - -Mlocked Page: Page Reclaim in shrink_*_list() - -shrink_active_list() culls any obviously unevictable pages--i.e., -!page_evictable(page, NULL)--diverting these to the unevictable lru -list. However, shrink_active_list() only sees unevictable pages that -made it onto the active/inactive lru lists. Note that these pages do not -have PageUnevictable set--otherwise, they would be on the unevictable list and -shrink_active_list would never see them. +If try_to_unmap() is unable to acquire a VM_LOCKED VMA's associated mmap +semaphore, it will return SWAP_AGAIN. This will allow shrink_page_list() to +recycle the page on the inactive list and hope that it has better luck with the +page next time. + +For file pages mapped into non-linear VMAs, the try_to_munlock() logic works +slightly differently. On encountering a VM_LOCKED non-linear VMA that might +map the page, try_to_munlock() returns SWAP_AGAIN without actually mlocking the +page. munlock_vma_page() will just leave the page unlocked and let vmscan deal +with it - the usual fallback position. + +Note that try_to_munlock()'s reverse map walk must visit every VMA in a page's +reverse map to determine that a page is NOT mapped into any VM_LOCKED VMA. +However, the scan can terminate when it encounters a VM_LOCKED VMA and can +successfully acquire the VMA's mmap semphore for read and mlock the page. +Although try_to_munlock() might be called a great many times when munlocking a +large region or tearing down a large address space that has been mlocked via +mlockall(), overall this is a fairly rare event. + + +PAGE RECLAIM IN shrink_*_list() +------------------------------- + +shrink_active_list() culls any obviously unevictable pages - i.e. +!page_evictable(page, NULL) - diverting these to the unevictable list. +However, shrink_active_list() only sees unevictable pages that made it onto the +active/inactive lru lists. Note that these pages do not have PageUnevictable +set - otherwise they would be on the unevictable list and shrink_active_list +would never see them. Some examples of these unevictable pages on the LRU lists are: -1) ramfs pages that have been placed on the lru lists when first allocated. + (1) ramfs pages that have been placed on the LRU lists when first allocated. + + (2) SHM_LOCK'd shared memory pages. shmctl(SHM_LOCK) does not attempt to + allocate or fault in the pages in the shared memory region. This happens + when an application accesses the page the first time after SHM_LOCK'ing + the segment. -2) SHM_LOCKed shared memory pages. shmctl(SHM_LOCK) does not attempt to - allocate or fault in the pages in the shared memory region. This happens - when an application accesses the page the first time after SHM_LOCKing - the segment. + (3) mlocked pages that could not be isolated from the LRU and moved to the + unevictable list in mlock_vma_page(). -3) Mlocked pages that could not be isolated from the lru and moved to the - unevictable list in mlock_vma_page(). + (4) Pages mapped into multiple VM_LOCKED VMAs, but try_to_munlock() couldn't + acquire the VMA's mmap semaphore to test the flags and set PageMlocked. + munlock_vma_page() was forced to let the page back on to the normal LRU + list for vmscan to handle. -3) Pages mapped into multiple VM_LOCKED vmas, but try_to_munlock() couldn't - acquire the vma's mmap semaphore to test the flags and set PageMlocked. - munlock_vma_page() was forced to let the page back on to the normal - LRU list for vmscan to handle. +shrink_inactive_list() also diverts any unevictable pages that it finds on the +inactive lists to the appropriate zone's unevictable list. -shrink_inactive_list() also culls any unevictable pages that it finds on -the inactive lists, again diverting them to the appropriate zone's unevictable -lru list. shrink_inactive_list() should only see SHM_LOCKed pages that became -SHM_LOCKed after shrink_active_list() had moved them to the inactive list, or -pages mapped into VM_LOCKED vmas that munlock_vma_page() couldn't isolate from -the lru to recheck via try_to_munlock(). shrink_inactive_list() won't notice -the latter, but will pass on to shrink_page_list(). +shrink_inactive_list() should only see SHM_LOCK'd pages that became SHM_LOCK'd +after shrink_active_list() had moved them to the inactive list, or pages mapped +into VM_LOCKED VMAs that munlock_vma_page() couldn't isolate from the LRU to +recheck via try_to_munlock(). shrink_inactive_list() won't notice the latter, +but will pass on to shrink_page_list(). shrink_page_list() again culls obviously unevictable pages that it could encounter for similar reason to shrink_inactive_list(). Pages mapped into -VM_LOCKED vmas but without PG_mlocked set will make it all the way to +VM_LOCKED VMAs but without PG_mlocked set will make it all the way to try_to_unmap(). shrink_page_list() will divert them to the unevictable list when try_to_unmap() returns SWAP_MLOCK, as discussed above. diff --git a/MAINTAINERS b/MAINTAINERS index 5d843588e1d..0cb20d82169 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -72,7 +72,6 @@ M: Mail patches to L: Mailing list that is relevant to this area W: Web-page with status/info T: SCM tree type and location. Type is one of: git, hg, quilt. -F: Applicable files and/or directories S: Status, one of the following: Supported: Someone is actually paid to look after this. @@ -85,23 +84,40 @@ S: Status, one of the following: it has been replaced by a better system and you should be using that. +F: Files and directories with wildcard patterns. + A trailing slash includes all files and subdirectory files. + F: drivers/net/ all files in and below drivers/net + F: drivers/net/* all files in drivers/net, but not below + F: */net/* all files in "any top level directory"/net + One pattern per line. Multiple F: lines acceptable. +X: Files and directories that are NOT maintained, same rules as F: + Files exclusions are tested before file matches. + Can be useful for excluding a specific subdirectory, for instance: + F: net/ + X: net/ipv6/ + matches all files in and below net excluding net/ipv6/ + 3C505 NETWORK DRIVER P: Philip Blundell M: philb@gnu.org L: netdev@vger.kernel.org S: Maintained +F: drivers/net/3c505* 3C59X NETWORK DRIVER P: Steffen Klassert M: klassert@mathematik.tu-chemnitz.de L: netdev@vger.kernel.org S: Maintained +F: Documentation/networking/vortex.txt +F: drivers/net/3c59x.c 3CR990 NETWORK DRIVER P: David Dillow M: dave@thedillows.org L: netdev@vger.kernel.org S: Maintained +F: drivers/net/typhoon* 3W-9XXX SATA-RAID CONTROLLER DRIVER P: Adam Radford @@ -109,6 +125,7 @@ M: linuxraid@amcc.com L: linux-scsi@vger.kernel.org W: http://www.amcc.com S: Supported +F: drivers/scsi/3w-9xxx* 3W-XXXX ATA-RAID CONTROLLER DRIVER P: Adam Radford @@ -116,35 +133,43 @@ M: linuxraid@amcc.com L: linux-scsi@vger.kernel.org W: http://www.amcc.com S: Supported +F: drivers/scsi/3w-xxxx* 53C700 AND 53C700-66 SCSI DRIVER P: James E.J. Bottomley M: James.Bottomley@HansenPartnership.com L: linux-scsi@vger.kernel.org S: Maintained +F: drivers/scsi/53c700* 6PACK NETWORK DRIVER FOR AX.25 P: Andreas Koensgen M: ajk@iehk.rwth-aachen.de L: linux-hams@vger.kernel.org S: Maintained +F: drivers/net/hamradio/6pack.c 8169 10/100/1000 GIGABIT ETHERNET DRIVER P: Francois Romieu M: romieu@fr.zoreil.com L: netdev@vger.kernel.org S: Maintained +F: drivers/net/r8169.c 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER L: linux-serial@vger.kernel.org W: http://serial.sourceforge.net S: Orphan +F: drivers/serial/8250* +F: include/linux/serial_8250.h 8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.] P: Paul Gortmaker M: p_gortmaker@yahoo.com L: netdev@vger.kernel.org S: Maintained +F: drivers/net/*8390* +F: drivers/net/ax88796.c 9P FILE SYSTEM P: Eric Van Hensbergen @@ -155,14 +180,17 @@ P: Latchesar Ionkov M: lucho@ionkov.net L: v9fs-developer@lists.sourceforge.net W: http://swik.net/v9fs -T: git kernel.org:/pub/scm/linux/kernel/ericvh/v9fs.git +T: git git://git.kernel.org/pub/scm/linux/kernel/ericvh/v9fs.git S: Maintained +F: Documentation/filesystems/9p.txt +F: fs/9p/ A2232 SERIAL BOARD DRIVER P: Enver Haase M: A2232@gmx.net L: linux-m68k@lists.linux-m68k.org S: Maintained +F: drivers/char/ser_a2232* AACRAID SCSI RAID DRIVER P: Adaptec OEM Raid Solutions @@ -170,24 +198,29 @@ M: aacraid@adaptec.com L: linux-scsi@vger.kernel.org W: http://www.adaptec.com/ S: Supported +F: Documentation/scsi/aacraid.txt +F: drivers/scsi/aacraid/ ABIT UGURU 1,2 HARDWARE MONITOR DRIVER P: Hans de Goede M: j.w.r.degoede@hhs.nl L: lm-sensors@lm-sensors.org S: Maintained +F: drivers/hwmon/abituguru.c ABIT UGURU 3 HARDWARE MONITOR DRIVER P: Alistair John Strachan M: alistair@devzero.co.uk L: lm-sensors@lm-sensors.org S: Maintained +F: drivers/hwmon/abituguru3.c ACENIC DRIVER P: Jes Sorensen M: jes@trained-monkey.org L: linux-acenic@sunsite.dk S: Maintained +F: drivers/net/acenic* ACER WMI LAPTOP EXTRAS P: Carlos Corbacho @@ -195,14 +228,18 @@ M: carlos@strangeworlds.co.uk L: aceracpi@googlegroups.com (subscribers-only) W: http://code.google.com/p/aceracpi S: Maintained +F: drivers/platform/x86/acer-wmi.c ACPI P: Len Brown M: lenb@kernel.org L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ -T: git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git S: Supported +F: drivers/acpi/ +F: drivers/pnp/pnpacpi/ +F: include/linux/acpi.h ACPI BATTERY DRIVERS P: Alexey Starikovskiy @@ -210,6 +247,8 @@ M: astarikovskiy@suse.de L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported +F: drivers/acpi/battery.c +F: drivers/acpi/*sbs* ACPI EC DRIVER P: Alexey Starikovskiy @@ -217,6 +256,7 @@ M: astarikovskiy@suse.de L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported +F: drivers/acpi/ec.c ACPI FAN DRIVER P: Zhang Rui @@ -224,12 +264,14 @@ M: rui.zhang@intel.com L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported +F: drivers/acpi/fan.c ACPI PCI HOTPLUG DRIVER P: Kristen Carlson Accardi M: kristen.c.accardi@intel.com L: linux-pci@vger.kernel.org S: Supported +F: drivers/pci/hotplug/acpi* ACPI THERMAL DRIVER P: Zhang Rui @@ -237,6 +279,7 @@ M: rui.zhang@intel.com L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported +F: drivers/acpi/*thermal* ACPI VIDEO DRIVER P: Zhang Rui @@ -244,6 +287,7 @@ M: rui.zhang@intel.com L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported +F: drivers/acpi/video.c ACPI WMI DRIVER P: Carlos Corbacho @@ -251,6 +295,7 @@ M: carlos@strangeworlds.co.uk L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Maintained +F: drivers/platform/x86/wmi.c AD1889 ALSA SOUND DRIVER P: Kyle McMartin @@ -260,77 +305,99 @@ M: T-Bone@parisc-linux.org W: http://wiki.parisc-linux.org/AD1889 L: linux-parisc@vger.kernel.org S: Maintained +F: sound/pci/ad1889.* ADM1025 HARDWARE MONITOR DRIVER P: Jean Delvare M: khali@linux-fr.org L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/adm1025 +F: drivers/hwmon/adm1025.c ADM1029 HARDWARE MONITOR DRIVER P: Corentin Labbe M: corentin.labbe@geomatys.fr L: lm-sensors@lm-sensors.org S: Maintained +F: drivers/hwmon/adm1029.c ADM8211 WIRELESS DRIVER P: Michael Wu M: flamingice@sourmilk.net L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git S: Maintained +F: drivers/net/wireless/adm8211.* ADT746X FAN DRIVER P: Colin Leroy M: colin@colino.net S: Maintained +F: drivers/macintosh/therm_adt746x.c ADVANSYS SCSI DRIVER P: Matthew Wilcox M: matthew@wil.cx L: linux-scsi@vger.kernel.org S: Maintained +F: Documentation/scsi/advansys.txt +F: drivers/scsi/advansys.c AEDSP16 DRIVER P: Riccardo Facchetti M: fizban@tin.it S: Maintained +F: sound/oss/aedsp16.c AFFS FILE SYSTEM P: Roman Zippel M: zippel@linux-m68k.org S: Maintained +F: Documentation/filesystems/affs.txt +F: fs/affs/ AFS FILESYSTEM & AF_RXRPC SOCKET DOMAIN P: David Howells M: dhowells@redhat.com L: linux-afs@lists.infradead.org S: Supported +F: fs/afs/ +F: include/net/af_rxrpc.h +F: net/rxrpc/af_rxrpc.c AGPGART DRIVER P: David Airlie M: airlied@linux.ie -T: git kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git S: Maintained +F: drivers/char/agp/ +F: include/linux/agp* AHA152X SCSI DRIVER P: Juergen E. Fischer -M: Juergen Fischer <fischer@norbit.de> +M: fischer@norbit.de L: linux-scsi@vger.kernel.org S: Maintained +F: drivers/scsi/aha152x* +F: drivers/scsi/pcmcia/aha152x* AIC7XXX / AIC79XX SCSI DRIVER P: Hannes Reinecke M: hare@suse.de L: linux-scsi@vger.kernel.org S: Maintained +F: drivers/scsi/aic7xxx/ +F: drivers/scsi/aic7xxx_old/ AIO P: Benjamin LaHaise M: bcrl@kvack.org L: linux-aio@kvack.org S: Supported +F: fs/aio.c +F: include/linux/*aio*.h ALCATEL SPEEDTOUCH USB DRIVER P: Duncan Sands @@ -338,17 +405,22 @@ M: duncan.sands@free.fr L: linux-usb@vger.kernel.org W: http://www.linux-usb.org/SpeedTouch/ S: Maintained +F: drivers/usb/atm/speedtch.c +F: drivers/usb/atm/usbatm.c ALCHEMY AU1XX0 MMC DRIVER P: Manuel Lauss M: manuel.lauss@gmail.com S: Maintained +F: drivers/mmc/host/au1xmmc.c ALI1563 I2C DRIVER P: Rudolf Marek M: r.marek@assembler.cz L: linux-i2c@vger.kernel.org S: Maintained +F: Documentation/i2c/busses/i2c-ali1563 +F: drivers/i2c/busses/i2c-ali1563.c ALPHA PORT P: Richard Henderson @@ -358,31 +430,41 @@ P: Ivan Kokshaysky M: ink@jurassic.park.msu.ru S: Maintained for 2.4; PCI support for 2.6. L: linux-alpha@vger.kernel.org +F: arch/alpha/ AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER P: Thomas Dahlmann M: thomas.dahlmann@amd.com L: linux-geode@lists.infradead.org (moderated for non-subscribers) S: Supported +F: drivers/usb/gadget/amd5536udc.* AMD GEODE PROCESSOR/CHIPSET SUPPORT P: Jordan Crouse L: linux-geode@lists.infradead.org (moderated for non-subscribers) W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html S: Supported +F: arch/x86/kernel/geode_32.c +F: drivers/char/hw_random/geode-rng.c +F: drivers/crypto/geode* +F: drivers/video/geode/ +F: arch/x86/include/asm/geode.h AMD IOMMU (AMD-VI) P: Joerg Roedel M: joerg.roedel@amd.com L: iommu@lists.linux-foundation.org -T: git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/joro/linux-2.6-iommu.git S: Supported +F: arch/x86/kernel/amd_iommu*.c +F: arch/x86/include/asm/amd_iommu*.h AMD MICROCODE UPDATE SUPPORT -P: Andreas Herrmann -M: andeas.herrmann3@amd.com -L: amd64-microcode@amd64.org -S: Supported +P: Andreas Herrmann +M: andreas.herrmann3@amd.com +L: amd64-microcode@amd64.org +S: Supported +F: arch/x86/kernel/microcode_amd.c AMS (Apple Motion Sensor) DRIVER P: Stelian Pop @@ -390,6 +472,7 @@ M: stelian@popies.net P: Michael Hanselmann M: linux-kernel@hansmi.ch S: Supported +F: drivers/hwmon/ams/ AMSO1100 RNIC DRIVER P: Tom Tucker @@ -398,6 +481,7 @@ P: Steve Wise M: swise@opengridcomputing.com L: general@lists.openfabrics.org S: Maintained +F: drivers/infiniband/hw/amso1100/ AOA (Apple Onboard Audio) ALSA DRIVER P: Johannes Berg @@ -405,6 +489,7 @@ M: johannes@sipsolutions.net L: linuxppc-dev@ozlabs.org L: alsa-devel@alsa-project.org (subscribers-only) S: Maintained +F: sound/aoa/ APM DRIVER P: Stephen Rothwell @@ -412,48 +497,63 @@ M: sfr@canb.auug.org.au L: linux-laptop@vger.kernel.org W: http://www.canb.auug.org.au/~sfr/ S: Supported +F: arch/x86/kernel/apm_32.c +F: include/linux/apm_bios.h APPLE BCM5974 MULTITOUCH DRIVER P: Henrik Rydberg M: rydberg@euromail.se L: linux-input@vger.kernel.org S: Maintained +F: drivers/input/mouse/bcm5974.c APPLE SMC DRIVER P: Nicolas Boichat M: nicolas@boichat.ch L: mactel-linux-devel@lists.sourceforge.net S: Maintained +F: drivers/hwmon/applesmc.c APPLETALK NETWORK LAYER P: Arnaldo Carvalho de Melo M: acme@ghostprotocols.net S: Maintained +F: drivers/net/appletalk/ +F: net/appletalk/ APPLETOUCH TOUCHPAD DRIVER P: Johannes Berg M: johannes@sipsolutions.net L: linux-input@vger.kernel.org S: Maintained +F: Documentation/input/appletouch.txt +F: drivers/input/mouse/appletouch.c ARC FRAMEBUFFER DRIVER P: Jaya Kumar M: jayalk@intworks.biz S: Maintained +F: drivers/video/arcfb.c +F: drivers/video/fb_defio.c ARM MFM AND FLOPPY DRIVERS P: Ian Molton M: spyro@f2s.com S: Maintained +F: arch/arm/lib/floppydma.S +F: arch/arm/include/asm/floppy.h ARM PRIMECELL MMCI PL180/1 DRIVER S: Orphan +F: drivers/mmc/host/mmci.* ARM/ADI ROADRUNNER MACHINE SUPPORT P: Lennert Buytenhek M: kernel@wantstofly.org L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained +F: arch/arm/mach-ixp23xx/ +F: arch/arm/mach-ixp23xx/include/mach/ ARM/ADS SPHERE MACHINE SUPPORT P: Lennert Buytenhek @@ -507,7 +607,7 @@ ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE P: Paulius Zaleckas M: paulius.zaleckas@teltonika.lt L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) -T: git gitorious.org/linux-gemini/mainline.git +T: git git://gitorious.org/linux-gemini/mainline.git S: Maintained ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6) @@ -643,10 +743,10 @@ W: http://hackndev.com S: Maintained ARM/PALMZ72 SUPPORT -P: Sergey Lapin -M: slapin@ossfans.org -W: http://hackndev.com -S: Maintained +P: Sergey Lapin +M: slapin@ossfans.org +W: http://hackndev.com +S: Maintained ARM/PLEB SUPPORT P: Peter Chubb @@ -707,16 +807,17 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained ARM/NUVOTON W90X900 ARM ARCHITECTURE -P: Wan ZongShun -M: mcuos.com@gmail.com -L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) -W: http://www.mcuos.com -S: Maintained +P: Wan ZongShun +M: mcuos.com@gmail.com +L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) +W: http://www.mcuos.com +S: Maintained ARPD SUPPORT P: Jonathan Layes L: netdev@vger.kernel.org S: Maintained +F: net/ipv4/arp.c ASUS ACPI EXTRAS DRIVER P: Corentin Chary @@ -727,12 +828,15 @@ L: acpi4asus-user@lists.sourceforge.net W: http://sourceforge.net/projects/acpi4asus W: http://xf.iksaif.net/acpi4asus S: Maintained +F: arch/x86/kernel/acpi/boot.c +F: drivers/platform/x86/asus_acpi.c ASUS ASB100 HARDWARE MONITOR DRIVER P: Mark M. Hoffman M: mhoffman@lightlink.com L: lm-sensors@lm-sensors.org S: Maintained +F: drivers/hwmon/asb100.c ASUS LAPTOP EXTRAS DRIVER P: Corentin Chary @@ -741,6 +845,7 @@ L: acpi4asus-user@lists.sourceforge.net W: http://sourceforge.net/projects/acpi4asus W: http://xf.iksaif.net/acpi4asus S: Maintained +F: drivers/platform/x86/asus-laptop.c ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API P: Dan Williams @@ -750,12 +855,19 @@ M: maciej.sosnowski@intel.com L: linux-kernel@vger.kernel.org W: http://sourceforge.net/projects/xscaleiop S: Supported +F: Documentation/crypto/async-tx-api.txt +F: crypto/async_tx/ +F: drivers/dma/ +F: include/linux/dmaengine.h +F: include/linux/async_tx.h ATA OVER ETHERNET (AOE) DRIVER P: Ed L. Cashin M: ecashin@coraid.com W: http://www.coraid.com/support/linux S: Supported +F: Documentation/aoe/ +F: drivers/block/aoe/ ATHEROS ATH5K WIRELESS DRIVER P: Jiri Slaby @@ -769,6 +881,7 @@ M: me@bobcopeland.com L: linux-wireless@vger.kernel.org L: ath5k-devel@lists.ath5k.org S: Maintained +F: drivers/net/wireless/ath5k/ ATHEROS ATH9K WIRELESS DRIVER P: Luis R. Rodriguez @@ -778,6 +891,7 @@ M: jmalinen@atheros.com L: linux-wireless@vger.kernel.org L: ath9k-devel@lists.ath9k.org S: Supported +F: drivers/net/wireless/ath9k/ ATHEROS AR9170 WIRELESS DRIVER P: Christian Lamparter @@ -791,6 +905,7 @@ ATI_REMOTE2 DRIVER P: Ville Syrjala M: syrjala@sci.fi S: Maintained +F: drivers/input/misc/ati_remote2.c ATLX ETHERNET DRIVERS P: Jay Cliburn @@ -803,6 +918,7 @@ L: atl1-devel@lists.sourceforge.net W: http://sourceforge.net/projects/atl1 W: http://atl1.sourceforge.net S: Maintained +F: drivers/net/atlx/ ATM P: Chas Williams @@ -811,6 +927,8 @@ L: linux-atm-general@lists.sourceforge.net (subscribers-only) L: netdev@vger.kernel.org W: http://linux-atm.sourceforge.net S: Maintained +F: drivers/atm/ +F: include/linux/atm* ATMEL AT91 MCI DRIVER P: Nicolas Ferre @@ -819,28 +937,34 @@ L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) W: http://www.atmel.com/products/AT91/ W: http://www.at91.com/ S: Maintained +F: drivers/mmc/host/at91_mci.c ATMEL AT91 / AT32 SERIAL DRIVER P: Haavard Skinnemoen M: hskinnemoen@atmel.com L: linux-kernel@vger.kernel.org S: Supported +F: drivers/serial/atmel_serial.c ATMEL LCDFB DRIVER P: Nicolas Ferre M: nicolas.ferre@atmel.com L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained +F: drivers/video/atmel_lcdfb.c +F: include/video/atmel_lcdc.h ATMEL MACB ETHERNET DRIVER P: Haavard Skinnemoen M: hskinnemoen@atmel.com S: Supported +F: drivers/net/macb.* ATMEL SPI DRIVER P: Haavard Skinnemoen M: hskinnemoen@atmel.com S: Supported +F: drivers/spi/atmel_spi.* ATMEL USBA UDC DRIVER P: Haavard Skinnemoen @@ -848,6 +972,7 @@ M: hskinnemoen@atmel.com L: kernel@avr32linux.org W: http://avr32linux.org/twiki/bin/view/Main/AtmelUsbDeviceDriver S: Supported +F: drivers/usb/gadget/atmel_usba_udc.* ATMEL WIRELESS DRIVER P: Simon Kelley @@ -856,6 +981,7 @@ L: linux-wireless@vger.kernel.org W: http://www.thekelleys.org.uk/atmel W: http://atmelwlandriver.sourceforge.net/ S: Maintained +F: drivers/net/wireless/atmel* AUDIT SUBSYSTEM P: Al Viro @@ -864,8 +990,10 @@ P: Eric Paris M: eparis@redhat.com L: linux-audit@redhat.com (subscribers-only) W: http://people.redhat.com/sgrubb/audit/ -T: git git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git S: Maintained +F: include/linux/audit.h +F: kernel/audit* AUXILIARY DISPLAY DRIVERS P: Miguel Ojeda Sandonis @@ -874,6 +1002,8 @@ L: linux-kernel@vger.kernel.org W: http://miguelojeda.es/auxdisplay.htm W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained +F: drivers/auxdisplay/ +F: include/linux/cfag12864b.h AVR32 ARCHITECTURE P: Haavard Skinnemoen @@ -882,11 +1012,13 @@ W: http://www.atmel.com/products/AVR32/ W: http://avr32linux.org/ W: http://avrfreaks.net/ S: Supported +F: arch/avr32/ AVR32/AT32AP MACHINE SUPPORT P: Haavard Skinnemoen M: hskinnemoen@atmel.com S: Supported +F: arch/avr32/mach-at32ap/ AX.25 NETWORK LAYER P: Ralf Baechle @@ -894,6 +1026,9 @@ M: ralf@linux-mips.org L: linux-hams@vger.kernel.org W: http://www.linux-ax25.org/ S: Maintained +F: include/linux/ax25.h +F: include/net/ax25.h +F: net/ax25/ B43 WIRELESS DRIVER P: Michael Buesch @@ -903,6 +1038,7 @@ M: stefano.brivio@polimi.it L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/en/users/Drivers/b43 S: Maintained +F: drivers/net/wireless/b43/ B43LEGACY WIRELESS DRIVER P: Larry Finger @@ -912,11 +1048,14 @@ M: stefano.brivio@polimi.it L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/en/users/Drivers/b43 S: Maintained +F: drivers/net/wireless/b43legacy/ BACKLIGHT CLASS/SUBSYSTEM P: Richard Purdie M: rpurdie@rpsys.net S: Maintained +F: drivers/video/backlight/ +F: include/linux/backlight.h BAYCOM/HDLCDRV DRIVERS FOR AX.25 P: Thomas Sailer @@ -924,18 +1063,24 @@ M: t.sailer@alumni.ethz.ch L: linux-hams@vger.kernel.org W: http://www.baycom.org/~tom/ham/ham.html S: Maintained +F: drivers/net/hamradio/baycom* BEFS FILE SYSTEM P: Sergey S. Kostyliov M: rathamahata@php4.ru L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/filesystems/befs.txt +F: fs/befs/ BFS FILE SYSTEM P: Tigran A. Aivazian M: tigran@aivazian.fsnet.co.uk L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/filesystems/bfs.txt +F: fs/bfs/ +F: include/linux/bfs_fs.h BLACKFIN ARCHITECTURE P: Bryan Wu @@ -943,6 +1088,7 @@ M: cooloney@kernel.org L: uclinux-dist-devel@blackfin.uclinux.org W: http://blackfin.uclinux.org S: Supported +F: arch/blackfin/ BLACKFIN EMAC DRIVER P: Bryan Wu @@ -950,6 +1096,7 @@ M: cooloney@kernel.org L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only) W: http://blackfin.uclinux.org S: Supported +F: drivers/net/bfin_mac.* BLACKFIN RTC DRIVER P: Mike Frysinger @@ -957,6 +1104,7 @@ M: vapier.adi@gmail.com L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only) W: http://blackfin.uclinux.org S: Supported +F: drivers/rtc/rtc-bfin.c BLACKFIN SERIAL DRIVER P: Sonic Zhang @@ -964,6 +1112,7 @@ M: sonic.zhang@analog.com L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only) W: http://blackfin.uclinux.org S: Supported +F: drivers/serial/bfin_5xx.c BLACKFIN WATCHDOG DRIVER P: Mike Frysinger @@ -971,6 +1120,7 @@ M: vapier.adi@gmail.com L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only) W: http://blackfin.uclinux.org S: Supported +F: drivers/watchdog/bfin_wdt.c BLACKFIN I2C TWI DRIVER P: Sonic Zhang @@ -978,19 +1128,22 @@ M: sonic.zhang@analog.com L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only) W: http://blackfin.uclinux.org/ S: Supported +F: drivers/i2c/busses/i2c-bfin-twi.c BLOCK LAYER P: Jens Axboe M: axboe@kernel.dk L: linux-kernel@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git S: Maintained +F: block/ BLOCK2MTD DRIVER P: Joern Engel M: joern@lazybastard.org L: linux-mtd@lists.infradead.org S: Maintained +F: drivers/mtd/devices/block2mtd.c BLUETOOTH DRIVERS P: Marcel Holtmann @@ -998,14 +1151,17 @@ M: marcel@holtmann.org L: linux-bluetooth@vger.kernel.org W: http://www.bluez.org/ S: Maintained +F: drivers/bluetooth/ BLUETOOTH SUBSYSTEM P: Marcel Holtmann M: marcel@holtmann.org L: linux-bluetooth@vger.kernel.org W: http://www.bluez.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git S: Maintained +F: net/bluetooth/ +F: include/net/bluetooth/ BONDING DRIVER P: Jay Vosburgh @@ -1013,24 +1169,30 @@ M: fubar@us.ibm.com L: bonding-devel@lists.sourceforge.net W: http://sourceforge.net/projects/bonding/ S: Supported +F: drivers/net/bonding/ +F: include/linux/if_bonding.h BROADCOM B44 10/100 ETHERNET DRIVER P: Gary Zambrano M: zambrano@broadcom.com L: netdev@vger.kernel.org S: Supported +F: drivers/net/b44.* BROADCOM BNX2 GIGABIT ETHERNET DRIVER P: Michael Chan M: mchan@broadcom.com L: netdev@vger.kernel.org S: Supported +F: drivers/net/bnx2.* +F: drivers/net/bnx2_* BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER P: Eilon Greenstein M: eilong@broadcom.com L: netdev@vger.kernel.org S: Supported +F: drivers/net/bnx2x* BROADCOM TG3 GIGABIT ETHERNET DRIVER P: Matt Carlson @@ -1039,41 +1201,51 @@ P: Michael Chan M: mchan@broadcom.com L: netdev@vger.kernel.org S: Supported +F: drivers/net/tg3.* BSG (block layer generic sg v4 driver) P: FUJITA Tomonori M: fujita.tomonori@lab.ntt.co.jp L: linux-scsi@vger.kernel.org S: Supported +F: block/bsg.c +F: include/linux/bsg.h BT8XXGPIO DRIVER P: Michael Buesch M: mb@bu3sch.de W: http://bu3sch.de/btgpio.php S: Maintained +F: drivers/gpio/bt8xxgpio.c BTRFS FILE SYSTEM P: Chris Mason M: chris.mason@oracle.com L: linux-btrfs@vger.kernel.org W: http://btrfs.wiki.kernel.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/mason/btrfs-unstable.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable.git S: Maintained +F: Documentation/filesystems/btrfs.txt +F: fs/btrfs/ BTTV VIDEO4LINUX DRIVER P: Mauro Carvalho Chehab M: mchehab@infradead.org L: linux-media@vger.kernel.org W: http://linuxtv.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained +F: Documentation/video4linux/bttv/ +F: drivers/media/video/bt8xx/bttv* CAFE CMOS INTEGRATED CAMERA CONTROLLER DRIVER P: Jonathan Corbet M: corbet@lwn.net L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained +F: Documentation/video4linux/cafe_ccic +F: drivers/media/video/cafe_ccic* CALGARY x86-64 IOMMU P: Muli Ben-Yehuda @@ -1083,6 +1255,10 @@ M: jdmason@kudzu.us L: linux-kernel@vger.kernel.org L: discuss@x86-64.org S: Maintained +F: arch/x86/kernel/pci-calgary_64.c +F: arch/x86/kernel/tce_64.c +F: arch/x86/include/asm/calgary.h +F: arch/x86/include/asm/tce.h CAN NETWORK LAYER P: Urs Thuermann @@ -1092,6 +1268,9 @@ M: oliver.hartkopp@volkswagen.de L: socketcan-core@lists.berlios.de (subscribers-only) W: http://developer.berlios.de/projects/socketcan/ S: Maintained +F: drivers/net/can/ +F: include/linux/can/ +F: include/linux/can.h CELL BROADBAND ENGINE ARCHITECTURE P: Arnd Bergmann @@ -1100,12 +1279,23 @@ L: linuxppc-dev@ozlabs.org L: cbe-oss-dev@ozlabs.org W: http://www.ibm.com/developerworks/power/cell/ S: Supported +F: arch/powerpc/include/asm/cell*.h +F: arch/powerpc/include/asm/lv1call.h +F: arch/powerpc/include/asm/ps3*.h +F: arch/powerpc/include/asm/spu*.h +F: arch/powerpc/oprofile/*cell* +F: arch/powerpc/platforms/cell/ +F: arch/powerpc/platforms/ps3/ CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: P: David Vrabel M: david.vrabel@csr.com L: linux-usb@vger.kernel.org S: Supported +F: Documentation/usb/WUSB-Design-overview.txt +F: Documentation/usb/wusb-cbaf +F: drivers/usb/wusbcore/ +F: include/linux/usb/wusb* CFAG12864B LCD DRIVER P: Miguel Ojeda Sandonis @@ -1114,6 +1304,8 @@ L: linux-kernel@vger.kernel.org W: http://miguelojeda.es/auxdisplay.htm W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained +F: drivers/auxdisplay/cfag12864b.c +F: include/linux/cfag12864b.h CFAG12864BFB LCD FRAMEBUFFER DRIVER P: Miguel Ojeda Sandonis @@ -1122,18 +1314,25 @@ L: linux-kernel@vger.kernel.org W: http://miguelojeda.es/auxdisplay.htm W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained +F: drivers/auxdisplay/cfag12864bfb.c +F: include/linux/cfag12864b.h CFG80211 and NL80211 P: Johannes Berg M: johannes@sipsolutions.net L: linux-wireless@vger.kernel.org S: Maintained +F: include/linux/nl80211.h +F: include/net/cfg80211.h +F: net/wireless/* +X: net/wireless/wext* CHECKPATCH P: Andy Whitcroft M: apw@canonical.com L: linux-kernel@vger.kernel.org S: Supported +F: scripts/checkpatch.pl CISCO 10G ETHERNET DRIVER P: Scott Feldman @@ -1141,24 +1340,28 @@ M: scofeldm@cisco.com P: Joe Eykholt M: jeykholt@cisco.com S: Supported +F: drivers/net/enic/ CIRRUS LOGIC EP93XX ETHERNET DRIVER P: Lennert Buytenhek M: kernel@wantstofly.org L: netdev@vger.kernel.org S: Maintained +F: drivers/net/arm/ep93xx_eth.c CIRRUS LOGIC EP93XX OHCI USB HOST DRIVER P: Lennert Buytenhek M: kernel@wantstofly.org L: linux-usb@vger.kernel.org S: Maintained +F: drivers/usb/host/ohci-ep93xx.c CIRRUS LOGIC CS4270 SOUND DRIVER P: Timur Tabi M: timur@freescale.com L: alsa-devel@alsa-project.org S: Supported +F: sound/soc/codecs/cs4270* CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER P: Cirrus Logic Corporation (kernel 2.2 driver) @@ -1166,6 +1369,8 @@ M: Cirrus Logic Corporation, Thomas Woller <twoller@crystal.cirrus.com> P: Nils Faerber (port to kernel 2.4) M: Nils Faerber <nils@kernelconcepts.de> S: Maintained +F: Documentation/input/cs461x.txt +F: sound/pci/cs46xx/ CODA FILE SYSTEM P: Jan Harkes @@ -1174,6 +1379,9 @@ M: coda@cs.cmu.edu L: codalist@coda.cs.cmu.edu W: http://www.coda.cs.cmu.edu/ S: Maintained +F: Documentation/filesystems/coda.txt +F: fs/coda/ +F: include/linux/coda*.h COMMON INTERNET FILE SYSTEM (CIFS) P: Steve French @@ -1181,8 +1389,10 @@ M: sfrench@samba.org L: linux-cifs-client@lists.samba.org L: samba-technical@lists.samba.org W: http://linux-cifs.samba.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git S: Supported +F: Documentation/filesystems/cifs.txt +F: fs/cifs/ COMPACTPCI HOTPLUG CORE P: Scott Murray @@ -1190,6 +1400,7 @@ M: scottm@somanetworks.com M: scott@spiteful.org L: linux-pci@vger.kernel.org S: Supported +F: drivers/pci/hotplug/cpci_hotplug* COMPACTPCI HOTPLUG ZIATECH ZT5550 DRIVER P: Scott Murray @@ -1197,6 +1408,7 @@ M: scottm@somanetworks.com M: scott@spiteful.org L: linux-pci@vger.kernel.org S: Supported +F: drivers/pci/hotplug/cpcihp_zt5550.* COMPACTPCI HOTPLUG GENERIC DRIVER P: Scott Murray @@ -1204,17 +1416,21 @@ M: scottm@somanetworks.com M: scott@spiteful.org L: linux-pci@vger.kernel.org S: Supported +F: drivers/pci/hotplug/cpcihp_generic.c COMPAL LAPTOP SUPPORT P: Cezary Jackiewicz M: cezary.jackiewicz@gmail.com S: Maintained +F: drivers/platform/x86/compal-laptop.c COMPUTONE INTELLIPORT MULTIPORT CARD P: Michael H. Warfield M: mhw@wittsend.com W: http://www.wittsend.com/computone.html S: Maintained +F: Documentation/serial/computone.txt +F: drivers/char/ip2/ CONEXANT ACCESSRUNNER USB DRIVER P: Simon Arlott @@ -1222,12 +1438,15 @@ M: cxacru@fire.lp0.eu L: accessrunner-general@lists.sourceforge.net W: http://accessrunner.sourceforge.net/ S: Maintained +F: drivers/usb/atm/cxacru.c CONFIGFS P: Joel Becker M: joel.becker@oracle.com L: linux-kernel@vger.kernel.org S: Supported +F: fs/configfs/ +F: include/linux/configfs.h CONTROL GROUPS (CGROUPS) P: Paul Menage @@ -1236,31 +1455,41 @@ P: Li Zefan M: lizf@cn.fujitsu.com L: containers@lists.linux-foundation.org S: Maintained +F: include/linux/cgroup* +F: kernel/cgroup* CORETEMP HARDWARE MONITORING DRIVER P: Rudolf Marek M: r.marek@assembler.cz L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/coretemp +F: drivers/hwmon/coretemp.c COSA/SRP SYNC SERIAL DRIVER P: Jan "Yenya" Kasprzak M: kas@fi.muni.cz W: http://www.fi.muni.cz/~kas/cosa/ S: Maintained +F: drivers/net/wan/cosa* CPU FREQUENCY DRIVERS P: Dave Jones M: davej@redhat.com L: cpufreq@vger.kernel.org W: http://www.codemonkey.org.uk/projects/cpufreq/ -T: git kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git S: Maintained +F: arch/x86/kernel/cpu/cpufreq/ +F: drivers/cpufreq/ +F: include/linux/cpufreq.h CPUID/MSR DRIVER P: H. Peter Anvin M: hpa@zytor.com S: Maintained +F: arch/x86/kernel/cpuid.c +F: arch/x86/kernel/msr.c CPUSETS P: Paul Menage @@ -1269,10 +1498,15 @@ L: linux-kernel@vger.kernel.org W: http://www.bullopensource.org/cpuset/ W: http://oss.sgi.com/projects/cpusets/ S: Supported +F: Documentation/cgroups/cpusets.txt +F: include/linux/cpuset.h +F: kernel/cpuset.c CRAMFS FILESYSTEM W: http://sourceforge.net/projects/cramfs/ S: Orphan +F: Documentation/filesystems/cramfs.txt +F: fs/cramfs/ CRIS PORT P: Mikael Starvik @@ -1282,6 +1516,7 @@ M: jesper.nilsson@axis.com L: dev-etrax@axis.com W: http://developer.axis.com S: Maintained +F: arch/cris/ CRYPTO API P: Herbert Xu @@ -1289,8 +1524,13 @@ M: herbert@gondor.apana.org.au P: David S. Miller M: davem@davemloft.net L: linux-crypto@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6.git S: Maintained +F: Documentation/crypto/ +F: arch/*/crypto/ +F: crypto/ +F: drivers/crypto/ +F: include/crypto/ CRYPTOGRAPHIC RANDOM NUMBER GENERATOR P: Neil Horman @@ -1302,16 +1542,21 @@ CS5535 Audio ALSA driver P: Jaya Kumar M: jayakumar.alsa@gmail.com S: Maintained +F: sound/pci/cs5535audio/ CX18 VIDEO4LINUX DRIVER -P: Hans Verkuil, Andy Walls -M: hverkuil@xs4all.nl, awalls@radix.net +P: Hans Verkuil +M: hverkuil@xs4all.nl +P: Andy Walls +M: awalls@radix.net L: ivtv-devel@ivtvdriver.org L: ivtv-users@ivtvdriver.org L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://linuxtv.org S: Maintained +F: Documentation/video4linux/cx18.txt +F: drivers/media/video/cx18/ CXGB3 ETHERNET DRIVER (CXGB3) P: Divy Le Ray @@ -1319,6 +1564,7 @@ M: divy@chelsio.com L: netdev@vger.kernel.org W: http://www.chelsio.com S: Supported +F: drivers/net/cxgb3/ CXGB3 IWARP RNIC DRIVER (IW_CXGB3) P: Steve Wise @@ -1326,32 +1572,32 @@ M: swise@chelsio.com L: general@lists.openfabrics.org W: http://www.openfabrics.org S: Supported +F: drivers/infiniband/hw/cxgb3/ CYBERPRO FB DRIVER P: Russell King M: rmk@arm.linux.org.uk W: http://www.arm.linux.org.uk/ S: Maintained - -CYBLAFB FRAMEBUFFER DRIVER -P: Knut Petersen -M: Knut_Petersen@t-online.de -L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) -S: Maintained +F: drivers/video/cyber2000fb.* CYCLADES 2X SYNC CARD DRIVER P: Arnaldo Carvalho de Melo M: acme@ghostprotocols.net W: http://oops.ghostprotocols.net:81/blog S: Maintained +F: drivers/net/wan/cycx* CYCLADES ASYNC MUX DRIVER W: http://www.cyclades.com/ S: Orphan +F: drivers/char/cyclades.c +F: include/linux/cyclades.h CYCLADES PC300 DRIVER W: http://www.cyclades.com/ S: Orphan +F: drivers/net/wan/pc300* DAMA SLAVE for AX.25 P: Joerg Reuter @@ -1360,12 +1606,21 @@ W: http://yaina.de/jreuter/ W: http://www.qsl.net/dl1bke/ L: linux-hams@vger.kernel.org S: Maintained +F: net/ax25/af_ax25.c +F: net/ax25/ax25_dev.c +F: net/ax25/ax25_ds_* +F: net/ax25/ax25_in.c +F: net/ax25/ax25_out.c +F: net/ax25/ax25_timer.c +F: net/ax25/sysctl_net_ax25.c DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER P: Tobias Ringstrom M: tori@unhappy.mine.nu L: netdev@vger.kernel.org S: Maintained +F: Documentation/networking/dmfe.txt +F: drivers/net/tulip/dmfe.c DC390/AM53C974 SCSI driver P: Kurt Garloff @@ -1374,6 +1629,7 @@ W: http://www.garloff.de/kurt/linux/dc390/ P: Guennadi Liakhovetski M: g.liakhovetski@gmx.de S: Maintained +F: drivers/scsi/tmscsim.* DC395x SCSI driver P: Oliver Neukum @@ -1386,6 +1642,8 @@ W: http://twibble.org/dist/dc395x/ L: dc395x@twibble.org L: http://lists.twibble.org/mailman/listinfo/dc395x/ S: Maintained +F: Documentation/scsi/dc395x.txt +F: drivers/scsi/dc395x.* DCCP PROTOCOL P: Arnaldo Carvalho de Melo @@ -1393,6 +1651,9 @@ M: acme@ghostprotocols.net L: dccp@vger.kernel.org W: http://linux-net.osdl.org/index.php/DCCP S: Maintained +F: include/linux/dccp.h +F: include/linux/tfrc.h +F: net/dccp/ DECnet NETWORK LAYER P: Christine Caulfield @@ -1400,27 +1661,35 @@ M: christine.caulfield@googlemail.com W: http://linux-decnet.sourceforge.net L: linux-decnet-user@lists.sourceforge.net S: Maintained +F: Documentation/networking/decnet.txt +F: net/decnet/ DEFXX FDDI NETWORK DRIVER P: Maciej W. Rozycki M: macro@linux-mips.org S: Maintained +F: drivers/net/defxx.* DELL LAPTOP DRIVER P: Matthew Garrett M: mjg59@srcf.ucam.org S: Maintained +F: drivers/platform/x86/dell-laptop.c DELL LAPTOP SMM DRIVER P: Massimo Dal Zotto M: dz@debian.org W: http://www.debian.org/~dz/i8k/ S: Maintained +F: drivers/char/i8k.c +F: include/linux/i8k.h DELL SYSTEMS MANAGEMENT BASE DRIVER (dcdbas) P: Doug Warzecha M: Douglas_Warzecha@dell.com S: Maintained +F: Documentation/dcdbas.txt +F: drivers/firmware/dcdbas.* DELL WMI EXTRAS DRIVER P: Matthew Garrett @@ -1439,6 +1708,10 @@ P: Alasdair Kergon L: dm-devel@redhat.com W: http://sources.redhat.com/dm S: Maintained +F: Documentation/device-mapper/ +F: drivers/md/dm* +F: include/linux/device-mapper.h +F: include/linux/dm-*.h DIGI INTL. EPCA DRIVER P: Digi International, Inc @@ -1446,12 +1719,18 @@ M: Eng.Linux@digi.com L: Eng.Linux@digi.com W: http://www.digi.com S: Orphan +F: Documentation/serial/digiepca.txt +F: drivers/char/epca* +F: drivers/char/digi* DIRECTORY NOTIFICATION (DNOTIFY) P: Stephen Rothwell M: sfr@canb.auug.org.au L: linux-kernel@vger.kernel.org S: Supported +F: Documentation/filesystems/dnotify.txt +F: fs/notify/dnotify/ +F: include/linux/dnotify.h DISK GEOMETRY AND PARTITION HANDLING P: Andries Brouwer @@ -1466,6 +1745,9 @@ P: Jan Kara M: jack@suse.cz L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/filesystems/quota.txt +F: fs/quota/ +F: include/linux/quota*.h DISTRIBUTED LOCK MANAGER (DLM) P: Christine Caulfield @@ -1474,8 +1756,9 @@ P: David Teigland M: teigland@redhat.com L: cluster-devel@redhat.com W: http://sources.redhat.com/cluster/ -T: git kernel.org:/pub/scm/linux/kernel/git/teigland/dlm.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm.git S: Supported +F: fs/dlm/ DMA GENERIC OFFLOAD ENGINE SUBSYSTEM P: Maciej Sosnowski @@ -1484,12 +1767,16 @@ P: Dan Williams M: dan.j.williams@intel.com L: linux-kernel@vger.kernel.org S: Supported +F: drivers/dma/ +F: include/linux/dma* DME1737 HARDWARE MONITOR DRIVER P: Juerg Haefliger M: juergh@gmail.com L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/dme1737 +F: drivers/hwmon/dme1737.c DOCBOOK FOR DOCUMENTATION P: Randy Dunlap @@ -1501,18 +1788,22 @@ P: Shaohua Li M: shaohua.li@intel.com L: linux-acpi@vger.kernel.org S: Supported +F: drivers/acpi/dock.c -DOCUMENTATION (/Documentation directory) +DOCUMENTATION P: Randy Dunlap M: rdunlap@xenotime.net L: linux-doc@vger.kernel.org S: Maintained +F: Documentation/ DOUBLETALK DRIVER P: James R. Van Zandt M: jrv@vanzandt.mv.com L: blinux-list@redhat.com S: Maintained +F: drivers/char/dtlk.c +F: include/linux/dtlk.h DPT_I2O SCSI RAID DRIVER P: Adaptec OEM Raid Solutions @@ -1520,6 +1811,8 @@ M: aacraid@adaptec.com L: linux-scsi@vger.kernel.org W: http://www.adaptec.com/ S: Maintained +F: drivers/scsi/dpt* +F: drivers/scsi/dpt/ DRIVER CORE, KOBJECTS, AND SYSFS P: Greg Kroah-Hartman @@ -1527,48 +1820,55 @@ M: gregkh@suse.de L: linux-kernel@vger.kernel.org T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ S: Supported +F: Documentation/kobject.txt +F: drivers/base/ +F: fs/sysfs/ +F: include/linux/kobj* +F: lib/kobj* DRM DRIVERS P: David Airlie M: airlied@linux.ie L: dri-devel@lists.sourceforge.net -T: git kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6.git S: Maintained +F: drivers/gpu/drm/ DSCC4 DRIVER P: Francois Romieu M: romieu@fr.zoreil.com L: netdev@vger.kernel.org S: Maintained - -DVB SUBSYSTEM AND DRIVERS -P: LinuxTV.org Project -M: linux-media@vger.kernel.org -W: http://linuxtv.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git -S: Maintained +F: drivers/net/wan/dscc4.c DZ DECSTATION DZ11 SERIAL DRIVER P: Maciej W. Rozycki M: macro@linux-mips.org S: Maintained +F: drivers/serial/dz.* EATA-DMA SCSI DRIVER P: Michael Neuffer -L: linux-eata@i-connect.net, linux-scsi@vger.kernel.org +M: mike@i-Connect.Net +L: linux-eata@i-connect.net +L: linux-scsi@vger.kernel.org S: Maintained +F: drivers/scsi/eata* EATA ISA/EISA/PCI SCSI DRIVER P: Dario Ballabio M: ballabio_dario@emc.com L: linux-scsi@vger.kernel.org S: Maintained +F: drivers/scsi/eata.c EATA-PIO SCSI DRIVER P: Michael Neuffer M: mike@i-Connect.Net -L: linux-eata@i-connect.net, linux-scsi@vger.kernel.org +L: linux-eata@i-connect.net +L: linux-scsi@vger.kernel.org S: Maintained +F: drivers/scsi/eata_pio.* EBTABLES P: Bart De Schuymer @@ -1577,87 +1877,105 @@ L: ebtables-user@lists.sourceforge.net L: ebtables-devel@lists.sourceforge.net W: http://ebtables.sourceforge.net/ S: Maintained +F: include/linux/netfilter_bridge/ebt_*.h +F: net/bridge/netfilter/ebt*.c ECRYPT FILE SYSTEM -P: Tyler Hicks, Dustin Kirkland -M: tyhicks@linux.vnet.ibm.com, kirkland@canonical.com +P: Tyler Hicks +M: tyhicks@linux.vnet.ibm.com +M: Dustin Kirkland +P: kirkland@canonical.com L: ecryptfs-devel@lists.launchpad.net W: https://launchpad.net/ecryptfs S: Supported +F: Documentation/filesystems/ecryptfs.txt +F: fs/ecryptfs/ EDAC-CORE P: Doug Thompson M: dougthompson@xmission.com -L: bluesmoke-devel@lists.sourceforge.net +L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Supported +F: Documentation/edac.txt +F: drivers/edac/edac_* +F: include/linux/edac.h EDAC-E752X P: Mark Gross P: Doug Thompson M: mark.gross@intel.com M: dougthompson@xmission.com -L: bluesmoke-devel@lists.sourceforge.net +L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained +F: drivers/edac/e752x_edac.c EDAC-E7XXX P: Doug Thompson M: dougthompson@xmission.com -L: bluesmoke-devel@lists.sourceforge.net +L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained +F: drivers/edac/e7xxx_edac.c EDAC-I82443BXGX P: Tim Small M: tim@buttersideup.com -L: bluesmoke-devel@lists.sourceforge.net +L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained +F: drivers/edac/i82443bxgx_edac.c EDAC-I3000 P: Jason Uhlenkott M: juhlenko@akamai.com -L: bluesmoke-devel@lists.sourceforge.net +L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained +F: drivers/edac/i3000_edac.c EDAC-I5000 P: Doug Thompson M: dougthompson@xmission.com -L: bluesmoke-devel@lists.sourceforge.net +L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained +F: drivers/edac/i5000_edac.c EDAC-I5400 P: Mauro Carvalho Chehab M: mchehab@redhat.com -L: bluesmoke-devel@lists.sourceforge.net +L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained +F: drivers/edac/i5400_edac.c EDAC-I82975X P: Ranganathan Desikan P: Arvind R. M: rdesikan@jetzbroadband.com M: arvind@acarlab.com -L: bluesmoke-devel@lists.sourceforge.net +L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained +F: drivers/edac/i82975x_edac.c EDAC-PASEMI P: Egor Martovetsky M: egor@pasemi.com -L: bluesmoke-devel@lists.sourceforge.net +L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained +F: drivers/edac/pasemi_edac.c EDAC-R82600 P: Tim Small M: tim@buttersideup.com -L: bluesmoke-devel@lists.sourceforge.net +L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers) W: bluesmoke.sourceforge.net S: Maintained +F: drivers/edac/r82600_edac.c EEEPC LAPTOP EXTRAS DRIVER P: Corentin Chary @@ -1665,10 +1983,12 @@ M: corentincj@iksaif.net L: acpi4asus-user@lists.sourceforge.net W: http://sourceforge.net/projects/acpi4asus S: Maintained +F: drivers/platform/x86/eeepc-laptop.c EFS FILESYSTEM W: http://aeschi.ch.eu.org/efs/ S: Orphan +F: fs/efs/ EHCA (IBM GX bus InfiniBand adapter) DRIVER P: Hoang-Nam Nguyen @@ -1677,6 +1997,7 @@ P: Christoph Raisch M: raisch@de.ibm.com L: general@lists.openfabrics.org S: Supported +F: drivers/infiniband/hw/ehca/ EMBEDDED LINUX P: Paul Gortmaker @@ -1692,22 +2013,29 @@ M: james.smart@emulex.com L: linux-scsi@vger.kernel.org W: http://sourceforge.net/projects/lpfcxxxx S: Supported +F: drivers/scsi/lpfc/ EPSON 1355 FRAMEBUFFER DRIVER P: Christopher Hoover -M: ch@murgatroid.com, ch@hpl.hp.com +M: ch@murgatroid.com +P: Christopher Hoover +M: ch@hpl.hp.com S: Maintained +F: drivers/video/epson1355fb.c EPSON S1D13XXX FRAMEBUFFER DRIVER P: Kristoffer Ericson M: kristoffer.ericson@gmail.com S: Maintained +F: drivers/video/s1d13xxxfb.c +F: include/video/s1d13xxxfb.h ETHEREXPRESS-16 NETWORK DRIVER P: Philip Blundell M: philb@gnu.org L: netdev@vger.kernel.org S: Maintained +F: drivers/net/eexpress.* ETHERNET BRIDGE P: Stephen Hemminger @@ -1715,87 +2043,126 @@ M: shemminger@linux-foundation.org L: bridge@lists.linux-foundation.org W: http://www.linux-foundation.org/en/Net:Bridge S: Maintained +F: include/linux/netfilter_bridge/ +F: net/bridge/ ETHERTEAM 16I DRIVER P: Mika Kuoppala M: miku@iki.fi S: Maintained +F: drivers/net/eth16i.c EXT2 FILE SYSTEM L: linux-ext4@vger.kernel.org S: Maintained +F: Documentation/filesystems/ext2.txt +F: fs/ext2/ +F: include/linux/ext2* EXT3 FILE SYSTEM -P: Stephen Tweedie, Andrew Morton -M: sct@redhat.com, akpm@linux-foundation.org, adilger@sun.com +P: Stephen Tweedie +M: sct@redhat.com +P: Andrew Morton +M: akpm@linux-foundation.org +P: Andreas Dilger +M: adilger@sun.com L: linux-ext4@vger.kernel.org S: Maintained +F: Documentation/filesystems/ext3.txt +F: fs/ext3/ +F: include/linux/ext3* EXT4 FILE SYSTEM P: Theodore Ts'o -M: tytso@mit.edu, adilger@sun.com +M: tytso@mit.edu +P: Andreas Dilger +M: adilger@sun.com L: linux-ext4@vger.kernel.org W: http://ext4.wiki.kernel.org S: Maintained +F: Documentation/filesystems/ext4.txt +F: fs/ext4/ F71805F HARDWARE MONITORING DRIVER P: Jean Delvare M: khali@linux-fr.org L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/f71805f +F: drivers/hwmon/f71805f.c FARSYNC SYNCHRONOUS DRIVER P: Kevin Curtis M: kevin.curtis@farsite.co.uk W: http://www.farsite.co.uk/ S: Supported +F: drivers/net/wan/farsync.* FAULT INJECTION SUPPORT P: Akinobu Mita M: akinobu.mita@gmail.com S: Supported +F: Documentation/fault-injection/ +F: lib/fault-inject.c FILE LOCKING (flock() and fcntl()/lockf()) P: Matthew Wilcox M: matthew@wil.cx L: linux-fsdevel@vger.kernel.org S: Maintained +F: include/linux/fcntl.h +F: include/linux/fs.h +F: fs/fcntl.c +F: fs/locks.c FILESYSTEMS (VFS and infrastructure) P: Alexander Viro M: viro@zeniv.linux.org.uk L: linux-fsdevel@vger.kernel.org S: Maintained +F: fs/* FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER P: Riku Voipio M: riku.vipio@iki.fi L: lm-sensors@lm-sensors.org S: Maintained +F: drivers/hwmon/f75375s.c +F: include/linux/f75375s.h -FIREWIRE SUBSYSTEM (drivers/firewire, <linux/firewire*.h>) -P: Kristian Hoegsberg, Stefan Richter -M: krh@redhat.com, stefanr@s5r6.in-berlin.de +FIREWIRE SUBSYSTEM +P: Kristian Hoegsberg +M: krh@redhat.com +P: Stefan Richter +M: stefanr@s5r6.in-berlin.de L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git S: Maintained +F: drivers/firewire/ +F: include/linux/firewire*.h FIRMWARE LOADER (request_firmware) L: linux-kernel@vger.kernel.org S: Orphan +F: Documentation/firmware_class/ +F: drivers/base/firmware*.c +F: include/linux/firmware.h FPU EMULATOR P: Bill Metzenthen -M: billm@suburbia.net -W: http://suburbia.net/~billm/floating-point/emulator/ +M: billm@melbpc.org.au +W: http://floatingpoint.sourceforge.net/emulator/index.html S: Maintained +F: arch/x86/math-emu/ FRAME RELAY DLCI/FRAD (Sangoma drivers too) P: Mike McLagan M: mike.mclagan@linux.org L: netdev@vger.kernel.org S: Maintained +F: drivers/net/wan/dlci.c +F: drivers/net/wan/sdla.c FRAMEBUFFER LAYER P: Antonino Daplas @@ -1803,6 +2170,9 @@ M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) W: http://linux-fbdev.sourceforge.net/ S: Maintained +F: Documentation/fb/ +F: drivers/video/fb* +F: include/linux/fb.h FREESCALE DMA DRIVER P: Li Yang @@ -1812,6 +2182,7 @@ M: zw@zh-kernel.org L: linuxppc-embedded@ozlabs.org L: linux-kernel@vger.kernel.org S: Maintained +F: drivers/dma/fsldma.* FREESCALE I2C CPM DRIVER P: Jochen Friedrich @@ -1819,6 +2190,7 @@ M: jochen@scram.de L: linuxppc-dev@ozlabs.org L: linux-i2c@vger.kernel.org S: Maintained +F: drivers/i2c/busses/i2c-cpm.c FREESCALE IMX / MXC FRAMEBUFFER DRIVER P: Sascha Hauer @@ -1826,6 +2198,8 @@ M: kernel@pengutronix.de L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained +F: arch/arm/plat-mxc/include/mach/imxfb.h +F: drivers/video/imxfb.c FREESCALE SOC FS_ENET DRIVER P: Pantelis Antoniou @@ -1835,12 +2209,16 @@ M: vbordug@ru.mvista.com L: linuxppc-dev@ozlabs.org L: netdev@vger.kernel.org S: Maintained +F: drivers/net/fs_enet/ +F: include/linux/fs_enet_pd.h FREESCALE QUICC ENGINE LIBRARY P: Timur Tabi M: timur@freescale.com L: linuxppc-dev@ozlabs.org S: Supported +F: arch/powerpc/sysdev/qe_lib/ +F: arch/powerpc/include/asm/*qe.h FREESCALE HIGHSPEED USB DEVICE DRIVER P: Li Yang @@ -1848,6 +2226,7 @@ M: leoli@freescale.com L: linux-usb@vger.kernel.org L: linuxppc-dev@ozlabs.org S: Maintained +F: drivers/usb/gadget/fsl_usb2_udc.c FREESCALE QUICC ENGINE UCC ETHERNET DRIVER P: Li Yang @@ -1855,12 +2234,14 @@ M: leoli@freescale.com L: netdev@vger.kernel.org L: linuxppc-dev@ozlabs.org S: Maintained +F: drivers/net/ucc_geth* FREESCALE QUICC ENGINE UCC UART DRIVER P: Timur Tabi M: timur@freescale.com L: linuxppc-dev@ozlabs.org S: Supported +F: drivers/serial/ucc_uart.c FREESCALE SOC SOUND DRIVERS P: Timur Tabi @@ -1868,12 +2249,15 @@ M: timur@freescale.com L: alsa-devel@alsa-project.org L: linuxppc-dev@ozlabs.org S: Supported +F: sound/soc/fsl/fsl* +F: sound/soc/fsl/mpc8610_hpcd.c FREEVXFS FILESYSTEM P: Christoph Hellwig M: hch@infradead.org W: ftp://ftp.openlinux.org/pub/people/hch/vxfs S: Maintained +F: fs/freevxfs/ FREEZER P: Pavel Machek @@ -1882,22 +2266,32 @@ P: Rafael J. Wysocki M: rjw@sisk.pl L: linux-pm@lists.linux-foundation.org S: Supported +F: Documentation/power/freezing-of-tasks.txt +F: include/linux/freezer.h +F: kernel/freezer.c FTRACE P: Steven Rostedt M: rostedt@goodmis.org S: Maintained +F: Documentation/ftrace.txt +F: arch/*/*/*/ftrace.h +F: arch/*/kernel/ftrace.c +F: include/*/ftrace.h +F: kernel/trace/ FUJITSU FR-V (FRV) PORT P: David Howells M: dhowells@redhat.com S: Maintained +F: arch/frv/ FUJITSU LAPTOP EXTRAS P: Jonathan Woithe M: jwoithe@physics.adelaide.edu.au L: linux-acpi@vger.kernel.org S: Maintained +F: drivers/platform/x86/fujitsu-laptop.c FUSE: FILESYSTEM IN USERSPACE P: Miklos Szeredi @@ -1905,12 +2299,15 @@ M: miklos@szeredi.hu L: fuse-devel@lists.sourceforge.net W: http://fuse.sourceforge.net/ S: Maintained +F: fs/fuse/ +F: include/linux/fuse.h FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit) P: Rik Faith M: faith@cs.unc.edu L: linux-scsi@vger.kernel.org S: Odd Fixes (e.g., new signatures) +F: drivers/scsi/fdomain.* GDT SCSI DISK ARRAY CONTROLLER DRIVER P: Achim Leubner @@ -1918,26 +2315,39 @@ M: achim_leubner@adaptec.com L: linux-scsi@vger.kernel.org W: http://www.icp-vortex.com/ S: Supported +F: drivers/scsi/gdt* GENERIC GPIO I2C DRIVER P: Haavard Skinnemoen M: hskinnemoen@atmel.com S: Supported +F: drivers/i2c/busses/i2c-gpio.c +F: include/linux/i2c-gpio.h GENERIC HDLC (WAN) DRIVERS P: Krzysztof Halasa M: khc@pm.waw.pl W: http://www.kernel.org/pub/linux/utils/net/hdlc/ S: Maintained +F: drivers/net/wan/c101.c +F: drivers/net/wan/hd6457* +F: drivers/net/wan/hdlc* +F: drivers/net/wan/n2.c +F: drivers/net/wan/pc300too.c +F: drivers/net/wan/pci200syn.c +F: drivers/net/wan/wanxl* GFS2 FILE SYSTEM P: Steven Whitehouse M: swhiteho@redhat.com L: cluster-devel@redhat.com W: http://sources.redhat.com/cluster/ -T: git kernel.org:/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes.git -T: git kernel.org:/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw.git S: Supported +F: Documentation/filesystems/gfs2*.txt +F: fs/gfs2/ +F: include/linux/gfs2_ondisk.h GIGASET ISDN DRIVERS P: Hansjoerg Lipp @@ -1947,6 +2357,9 @@ M: tilman@imap.cc L: gigaset307x-common@lists.sourceforge.net W: http://gigaset307x.sourceforge.net/ S: Maintained +F: Documentation/isdn/README.gigaset +F: drivers/isdn/gigaset/ +F: include/linux/gigaset_dev.h HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER P: Frank Seidel @@ -1954,6 +2367,7 @@ M: frank@f-seidel.de L: lm-sensors@lm-sensors.org W: http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/ S: Maintained +F: drivers/hwmon/hdaps.c HYPERVISOR VIRTUAL CONSOLE DRIVER L: linuxppc-dev@ozlabs.org @@ -1965,51 +2379,61 @@ GSPCA FINEPIX SUBDRIVER P: Frank Zago M: frank@zago.net L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained +F: drivers/media/video/gspca/finepix.c GSPCA M5602 SUBDRIVER P: Erik Andren M: erik.andren@gmail.com L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained +F: drivers/media/video/gspca/m5602/ GSPCA PAC207 SONIXB SUBDRIVER P: Hans de Goede M: hdegoede@redhat.com L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained +F: drivers/media/video/gspca/pac207.c GSPCA T613 SUBDRIVER P: Leandro Costantino M: lcostantino@gmail.com L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained +F: drivers/media/video/gspca/t613.c GSPCA USB WEBCAM DRIVER P: Jean-Francois Moine M: moinejf@free.fr W: http://moinejf.free.fr L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained +F: drivers/media/video/gspca/ HARDWARE MONITORING L: lm-sensors@lm-sensors.org W: http://www.lm-sensors.org/ S: Orphan +F: drivers/hwmon/ HARDWARE RANDOM NUMBER GENERATOR CORE S: Orphan +F: Documentation/hw_random.txt +F: drivers/char/hw_random/ +F: include/linux/hw_random.h HARMONY SOUND DRIVER P: Kyle McMartin M: kyle@mcmartin.ca L: linux-parisc@vger.kernel.org S: Maintained +F: sound/parisc/harmony.* HAYES ESP SERIAL DRIVER P: Andrew J. Robinson @@ -2017,30 +2441,33 @@ M: arobinso@nyx.net L: linux-kernel@vger.kernel.org W: http://www.nyx.net/~arobinso S: Maintained - -HEWLETT-PACKARD FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA -P: Chirag Kantharia -M: chirag.kantharia@hp.com -L: iss_storagedev@hp.com -S: Maintained +F: Documentation/serial/hayes-esp.txt +F: drivers/char/esp.c HEWLETT-PACKARD SMART2 RAID DRIVER P: Chirag Kantharia M: chirag.kantharia@hp.com L: iss_storagedev@hp.com S: Maintained +F: Documentation/blockdev/cpqarray.txt +F: drivers/block/cpqarray.* HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss) P: Mike Miller M: mike.miller@hp.com L: iss_storagedev@hp.com S: Supported +F: Documentation/blockdev/cciss.txt +F: drivers/block/cciss* +F: include/linux/cciss_ioctl.h HFS FILESYSTEM P: Roman Zippel M: zippel@linux-m68k.org L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/filesystems/hfs.txt +F: fs/hfs/ HGA FRAMEBUFFER DRIVER P: Ferenc Bakonyi @@ -2048,6 +2475,7 @@ M: fero@drama.obuda.kando.hu L: linux-nvidia@lists.surfsouth.com W: http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml S: Maintained +F: drivers/video/hgafb.c HIBERNATION (aka Software Suspend, aka swsusp) P: Pavel Machek @@ -2056,19 +2484,32 @@ P: Rafael J. Wysocki M: rjw@sisk.pl L: linux-pm@lists.linux-foundation.org S: Supported +F: arch/x86/power/ +F: drivers/base/power/ +F: kernel/power/ +F: include/linux/suspend.h +F: include/linux/freezer.h +F: include/linux/pm.h +F: include/asm-*/suspend*.h +F: arch/*/include/asm/suspend*.h HID CORE LAYER P: Jiri Kosina M: jkosina@suse.cz L: linux-input@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained +F: drivers/hid/ +F: include/linux/hid* HIGH-RESOLUTION TIMERS, CLOCKEVENTS, DYNTICKS P: Thomas Gleixner M: tglx@linutronix.de L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/timers/ +F: kernel/hrtimer.c +F: include/linux/hrtimer.h HIGH-SPEED SCC DRIVER FOR AX.25 P: Klaus Kudielka @@ -2076,18 +2517,25 @@ M: klaus.kudielka@ieee.org L: linux-hams@vger.kernel.org W: http://www.nt.tuwien.ac.at/~kkudielk/Linux/ S: Maintained +F: drivers/net/hamradio/dmascc.c +F: drivers/net/hamradio/scc.c HIGHPOINT ROCKETRAID 3xxx RAID DRIVER P: HighPoint Linux Team M: linux@highpoint-tech.com W: http://www.highpoint-tech.com S: Supported +F: Documentation/scsi/hptiop.txt +F: drivers/scsi/hptiop.c HIPPI P: Jes Sorensen M: jes@trained-monkey.org L: linux-hippi@sunsite.dk S: Maintained +F: include/linux/hippidevice.h +F: include/linux/if_hippi.h +F: net/802/hippi.c HOST AP DRIVER P: Jouni Malinen @@ -2096,65 +2544,79 @@ L: hostap@shmoo.com (subscribers-only) L: linux-wireless@vger.kernel.org W: http://hostap.epitest.fi/ S: Maintained +F: drivers/net/wireless/hostap/ HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER P: Carlos Corbacho M: carlos@strangeworlds.co.uk S: Odd Fixes +F: drivers/platform/x86/tc1100-wmi.c HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series P: Jaroslav Kysela M: perex@perex.cz S: Maintained +F: drivers/net/hp100.* -HPET: High Precision Event Timers driver (drivers/char/hpet.c) +HPET: High Precision Event Timers driver P: Clemens Ladisch M: clemens@ladisch.de S: Maintained +F: Documentation/timers/hpet.txt +F: drivers/char/hpet.c +F: include/linux/hpet.h HPET: i386 P: Venkatesh Pallipadi (Venki) M: venkatesh.pallipadi@intel.com S: Maintained +F: arch/x86/kernel/hpet.c +F: arch/x86/include/asm/hpet.h HPET: x86_64 P: Vojtech Pavlik M: vojtech@suse.cz S: Maintained -HPET: ACPI hpet.c +HPET: ACPI P: Bob Picco M: bob.picco@hp.com S: Maintained +F: drivers/char/hpet.c HPFS FILESYSTEM P: Mikulas Patocka M: mikulas@artax.karlin.mff.cuni.cz W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi S: Maintained +F: fs/hpfs/ -HSO 3G Modem Driver (hso.c) -P: Denis Joseph Barrow -M: d.barow@option.com +HSO 3G MODEM DRIVER +P: Jan Dumon +M: j.dumon@option.com W: http://www.pharscape.org S: Maintained +F: drivers/net/usb/hso.c HTCPEN TOUCHSCREEN DRIVER P: Pau Oliva Fora M: pof@eslack.org L: linux-input@vger.kernel.org S: Maintained +F: drivers/input/touchscreen/htcpen.c HUGETLB FILESYSTEM P: William Irwin M: wli@holomorphy.com S: Maintained +F: fs/hugetlbfs/ I2C/SMBUS STUB DRIVER P: Mark M. Hoffman M: mhoffman@lightlink.com L: linux-i2c@vger.kernel.org S: Maintained +F: drivers/i2c/busses/i2c-stub.c I2C SUBSYSTEM P: Jean Delvare (PC drivers, core) @@ -2165,24 +2627,31 @@ L: linux-i2c@vger.kernel.org W: http://i2c.wiki.kernel.org/ T: quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/ S: Maintained +F: Documentation/i2c/ +F: drivers/i2c/ +F: include/linux/i2c.h +F: include/linux/i2c-dev.h +F: include/linux/i2c-id.h I2C-TINY-USB DRIVER P: Till Harbaum M: till@harbaum.org L: linux-i2c@vger.kernel.org -T: http://www.harbaum.org/till/i2c_tiny_usb +W: http://www.harbaum.org/till/i2c_tiny_usb S: Maintained +F: drivers/i2c/busses/i2c-tiny-usb.c i386 BOOT CODE P: H. Peter Anvin M: hpa@zytor.com L: Linux-Kernel@vger.kernel.org S: Maintained +F: arch/x86/boot/ i386 SETUP CODE / CPU ERRATA WORKAROUNDS P: H. Peter Anvin M: hpa@zytor.com -T: git.kernel.org:/pub/scm/linux/kernel/git/hpa/linux-2.6-x86setup.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-x86setup.git S: Maintained IA64 (Itanium) PLATFORM @@ -2190,19 +2659,22 @@ P: Tony Luck M: tony.luck@intel.com L: linux-ia64@vger.kernel.org W: http://www.ia64-linux.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6.git S: Maintained +F: arch/ia64/ IBM MCA SCSI SUBSYSTEM DRIVER P: Michael Lang M: langa2@kph.uni-mainz.de W: http://www.uni-mainz.de/~langm000/linux.html S: Maintained +F: drivers/scsi/ibmmca.c IBM Power Linux RAID adapter P: Brian King M: brking@us.ibm.com S: Supported +F: drivers/scsi/ipr.* IBM ServeRAID RAID DRIVER P: Jack Hammer @@ -2210,6 +2682,7 @@ P: Dave Jeffery M: ipslinux@adaptec.com W: http://www.developer.ibm.com/welcome/netfinity/serveraid.html S: Supported +F: drivers/scsi/ips.* IDE SUBSYSTEM P: Bartlomiej Zolnierkiewicz @@ -2217,45 +2690,55 @@ M: bzolnier@gmail.com L: linux-ide@vger.kernel.org T: quilt kernel.org/pub/linux/kernel/people/bart/pata-2.6/ S: Maintained +F: Documentation/ide/ +F: drivers/ide/ +F: include/linux/ide.h IDE/ATAPI DRIVERS P: Borislav Petkov M: petkovbb@gmail.com L: linux-ide@vger.kernel.org S: Maintained +F: Documentation/cdrom/ide-cd +F: drivers/ide/ide-cd* IDLE-I7300 P: Andy Henroid M: andrew.d.henroid@intel.com L: linux-pm@lists.linux-foundation.org S: Supported +F: drivers/idle/i7300_idle.c -IEEE 1394 SUBSYSTEM (drivers/ieee1394) +IEEE 1394 SUBSYSTEM P: Ben Collins M: ben.collins@ubuntu.com P: Stefan Richter M: stefanr@s5r6.in-berlin.de L: linux1394-devel@lists.sourceforge.net W: http://www.linux1394.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git S: Maintained +F: drivers/ieee1394/ -IEEE 1394 RAW I/O DRIVER (raw1394) +IEEE 1394 RAW I/O DRIVER P: Dan Dennedy M: dan@dennedy.org P: Stefan Richter M: stefanr@s5r6.in-berlin.de L: linux1394-devel@lists.sourceforge.net S: Maintained +F: drivers/ieee1394/raw1394* INTEGRITY MEASUREMENT ARCHITECTURE (IMA) P: Mimi Zohar M: zohar@us.ibm.com S: Supported +F: security/integrity/ima/ IMS TWINTURBO FRAMEBUFFER DRIVER L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Orphan +F: drivers/video/imsttfb.c INFINIBAND SUBSYSTEM P: Roland Dreier @@ -2266,8 +2749,11 @@ P: Hal Rosenstock M: hal.rosenstock@gmail.com L: general@lists.openfabrics.org (moderated for non-subscribers) W: http://www.openib.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git S: Supported +F: Documentation/infiniband/ +F: drivers/infiniband/ +F: include/linux/if_infiniband.h INOTIFY P: John McCutchan @@ -2276,26 +2762,33 @@ P: Robert Love M: rlove@rlove.org L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/filesystems/inotify.txt +F: fs/notify/inotify/ +F: include/linux/inotify.h INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS P: Dmitry Torokhov M: dmitry.torokhov@gmail.com M: dtor@mail.ru L: linux-input@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git S: Maintained +F: drivers/input/ INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) P: Sylvain Meyer M: sylvain.meyer@worldonline.fr L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained +F: Documentation/fb/intelfb.txt +F: drivers/video/intelfb/ INTEL 810/815 FRAMEBUFFER DRIVER P: Antonino Daplas M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained +F: drivers/video/i810/ INTEL MENLOW THERMAL DRIVER P: Sujith Thomas @@ -2303,46 +2796,61 @@ M: sujith.thomas@intel.com L: linux-acpi@vger.kernel.org W: http://www.lesswatts.org/projects/acpi/ S: Supported +F: drivers/platform/x86/intel_menlow.c INTEL IA32 MICROCODE UPDATE SUPPORT P: Tigran Aivazian M: tigran@aivazian.fsnet.co.uk S: Maintained +F: arch/x86/kernel/microcode_core.c +F: arch/x86/kernel/microcode_intel.c INTEL I/OAT DMA DRIVER P: Maciej Sosnowski M: maciej.sosnowski@intel.com L: linux-kernel@vger.kernel.org S: Supported +F: drivers/dma/ioat* INTEL IOMMU (VT-d) P: David Woodhouse M: dwmw2@infradead.org L: iommu@lists.linux-foundation.org -T: git://git.infradead.org/iommu-2.6.git +T: git git://git.infradead.org/iommu-2.6.git S: Supported +F: drivers/pci/intel-iommu.c +F: include/linux/intel-iommu.h INTEL IOP-ADMA DMA DRIVER P: Dan Williams M: dan.j.williams@intel.com L: linux-kernel@vger.kernel.org S: Supported +F: drivers/dma/iop-adma.c INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT P: Krzysztof Halasa M: khc@pm.waw.pl S: Maintained +F: arch/arm/mach-ixp4xx/include/mach/qmgr.h +F: arch/arm/mach-ixp4xx/include/mach/npe.h +F: arch/arm/mach-ixp4xx/ixp4xx_qmgr.c +F: arch/arm/mach-ixp4xx/ixp4xx_npe.c +F: drivers/net/arm/ixp4xx_eth.c +F: drivers/net/wan/ixp4xx_hss.c INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT P: Deepak Saxena M: dsaxena@plexity.net S: Maintained +F: drivers/char/hw_random/ixp4xx-rng.c INTEL IXP2000 ETHERNET DRIVER P: Lennert Buytenhek M: kernel@wantstofly.org L: netdev@vger.kernel.org S: Maintained +F: drivers/net/ixp2000/ INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/ixgb/ixgbe) P: Jeff Kirsher @@ -2358,6 +2866,12 @@ M: john.ronciak@intel.com L: e1000-devel@lists.sourceforge.net W: http://e1000.sourceforge.net/ S: Supported +F: drivers/net/e100.c +F: drivers/net/e1000/ +F: drivers/net/e1000e/ +F: drivers/net/igb/ +F: drivers/net/ixgb/ +F: drivers/net/ixgbe/ INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT P: Zhu Yi @@ -2371,6 +2885,8 @@ L: ipw2100-devel@lists.sourceforge.net W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel W: http://ipw2100.sourceforge.net S: Supported +F: Documentation/networking/README.ipw2100 +F: drivers/net/wireless/ipw2x00/ipw2100.* INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT P: Zhu Yi @@ -2384,6 +2900,8 @@ L: ipw2100-devel@lists.sourceforge.net W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel W: http://ipw2200.sourceforge.net S: Supported +F: Documentation/networking/README.ipw2200 +F: drivers/net/wireless/ipw2x00/ipw2200.* INTEL WIRELESS WIMAX CONNECTION 2400 P: Inaky Perez-Gonzalez @@ -2392,6 +2910,9 @@ M: linux-wimax@intel.com L: wimax@linuxwimax.org S: Supported W: http://linuxwimax.org +F: Documentation/wimax/README.i2400m +F: drivers/net/wimax/i2400m/ +F: include/linux/wimax/i2400m.h INTEL WIRELESS WIFI LINK (iwlwifi) P: Zhu Yi @@ -2401,25 +2922,29 @@ M: reinette.chatre@intel.com L: linux-wireless@vger.kernel.org L: ipw3945-devel@lists.sourceforge.net W: http://intellinuxwireless.org -T: git kernel.org:/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git S: Supported +F: drivers/net/wireless/iwlwifi/ IOC3 ETHERNET DRIVER P: Ralf Baechle M: ralf@linux-mips.org L: linux-mips@linux-mips.org S: Maintained +F: drivers/net/ioc3-eth.c IOC3 SERIAL DRIVER P: Pat Gefre M: pfg@sgi.com L: linux-mips@linux-mips.org S: Maintained +F: drivers/serial/ioc3_serial.c IP MASQUERADING P: Juanjo Ciarlante M: jjciarla@raiz.uncu.edu.ar S: Maintained +F: net/ipv4/netfilter/ipt_MASQUERADE.c IP1000A 10/100/1000 GIGABIT ETHERNET DRIVER P: Francois Romieu @@ -2430,6 +2955,7 @@ P: Jesse Huang M: jesse@icplus.com.tw L: netdev@vger.kernel.org S: Maintained +F: drivers/net/ipg.c IPATH DRIVER P: Ralph Campbell @@ -2437,6 +2963,7 @@ M: infinipath@qlogic.com L: general@lists.openfabrics.org T: git git://git.qlogic.com/ipath-linux-2.6 S: Supported +F: drivers/infiniband/hw/ipath/ IPMI SUBSYSTEM P: Corey Minyard @@ -2444,6 +2971,9 @@ M: minyard@acm.org L: openipmi-developer@lists.sourceforge.net W: http://openipmi.sourceforge.net/ S: Supported +F: Documentation/IPMI.txt +F: drivers/char/ipmi/ +F: include/linux/ipmi* IPS SCSI RAID DRIVER P: Adaptec OEM Raid Solutions @@ -2451,6 +2981,7 @@ M: aacraid@adaptec.com L: linux-scsi@vger.kernel.org W: http://www.adaptec.com/ S: Maintained +F: drivers/scsi/ips* IPVS P: Wensong Zhang @@ -2462,6 +2993,8 @@ M: ja@ssi.bg L: netdev@vger.kernel.org L: lvs-devel@vger.kernel.org S: Maintained +F: Documentation/networking/ipvs-sysctl.txt +F: net/netfilter/ipvs/ IPWIRELESS DRIVER P: Jiri Kosina @@ -2469,13 +3002,17 @@ M: jkosina@suse.cz P: David Sterba M: dsterba@suse.cz S: Maintained -T: git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git +F: drivers/char/pcmcia/ipwireless/ IPX NETWORK LAYER P: Arnaldo Carvalho de Melo M: acme@ghostprotocols.net L: netdev@vger.kernel.org S: Maintained +F: include/linux/ipx.h +F: include/net/ipx.h +F: net/ipx/ IRDA SUBSYSTEM P: Samuel Ortiz @@ -2483,27 +3020,40 @@ M: samuel@sortiz.org L: irda-users@lists.sourceforge.net (subscribers-only) W: http://irda.sourceforge.net/ S: Maintained +F: Documentation/networking/irda.txt +F: drivers/net/irda/ +F: include/net/irda/ +F: net/irda/ ISAPNP P: Jaroslav Kysela M: perex@perex.cz S: Maintained +F: Documentation/isapnp.txt +F: drivers/pnp/isapnp/ +F: include/linux/isapnp.h ISCSI P: Mike Christie M: michaelc@cs.wisc.edu L: open-iscsi@googlegroups.com W: www.open-iscsi.org -T: git kernel.org:/pub/scm/linux/kernel/mnc/linux-2.6-iscsi.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mnc/linux-2.6-iscsi.git S: Maintained +F: drivers/scsi/*iscsi* +F: include/scsi/*iscsi* ISDN SUBSYSTEM P: Karsten Keil M: isdn@linux-pingi.de L: isdn4linux@listserv.isdn4linux.de (subscribers-only) W: http://www.isdn4linux.de -T: git kernel.org:/pub/scm/linux/kernel/kkeil/isdn-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/isdn-2.6.git S: Maintained +F: Documentation/isdn/ +F: drivers/isdn/ +F: include/linux/isdn.h +F: include/linux/isdn/ ISDN SUBSYSTEM (Eicon active card driver) P: Armin Schindler @@ -2511,6 +3061,7 @@ M: mac@melware.de L: isdn4linux@listserv.isdn4linux.de (subscribers-only) W: http://www.melware.de S: Maintained +F: drivers/isdn/hardware/eicon/ IVTV VIDEO4LINUX DRIVER P: Hans Verkuil @@ -2518,23 +3069,29 @@ M: hverkuil@xs4all.nl L: ivtv-devel@ivtvdriver.org L: ivtv-users@ivtvdriver.org L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://www.ivtvdriver.org S: Maintained +F: Documentation/video4linux/*.ivtv +F: drivers/media/video/ivtv/ +F: include/linux/ivtv* JFS FILESYSTEM P: Dave Kleikamp M: shaggy@austin.ibm.com L: jfs-discussion@lists.sourceforge.net W: http://jfs.sourceforge.net/ -T: git kernel.org:/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git S: Supported +F: Documentation/filesystems/jfs.txt +F: fs/jfs/ JME NETWORK DRIVER P: Guo-Fu Tseng M: cooldavid@cooldavid.org L: netdev@vger.kernel.org S: Maintained +F: drivers/net/jme.* JOURNALLING FLASH FILE SYSTEM V2 (JFFS2) P: David Woodhouse @@ -2542,24 +3099,36 @@ M: dwmw2@infradead.org L: linux-mtd@lists.infradead.org W: http://www.linux-mtd.infradead.org/doc/jffs2.html S: Maintained +F: fs/jffs2/ +F: include/linux/jffs2.h +F: include/mtd/jffs2-user.h JOURNALLING LAYER FOR BLOCK DEVICES (JBD) -P: Stephen Tweedie, Andrew Morton -M: sct@redhat.com, akpm@linux-foundation.org +P: Stephen Tweedie +M: sct@redhat.com +P: Andrew Morton +M: akpm@linux-foundation.org L: linux-ext4@vger.kernel.org S: Maintained +F: fs/jbd*/ +F: include/linux/ext*jbd*.h +F: include/linux/jbd*.h K8TEMP HARDWARE MONITORING DRIVER P: Rudolf Marek M: r.marek@assembler.cz L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/k8temp +F: drivers/hwmon/k8temp.c KCONFIG P: Roman Zippel M: zippel@linux-m68k.org L: linux-kbuild@vger.kernel.org S: Maintained +F: Documentation/kbuild/kconfig-language.txt +F: scripts/kconfig/ KDUMP P: Vivek Goyal @@ -2570,26 +3139,32 @@ L: kexec@lists.infradead.org L: linux-kernel@vger.kernel.org W: http://lse.sourceforge.net/kdump/ S: Maintained +F: Documentation/kdump/ KERNEL AUTOMOUNTER (AUTOFS) P: H. Peter Anvin M: hpa@zytor.com L: autofs@linux.kernel.org S: Odd Fixes +F: fs/autofs/ KERNEL AUTOMOUNTER v4 (AUTOFS4) P: Ian Kent M: raven@themaw.net L: autofs@linux.kernel.org S: Maintained +F: fs/autofs4/ -KERNEL BUILD (kbuild: Makefile, scripts/Makefile.*) +KERNEL BUILD P: Sam Ravnborg M: sam@ravnborg.org -T: git kernel.org:/pub/scm/linux/kernel/git/sam/kbuild-next.git -T: git kernel.org:/pub/scm/linux/kernel/git/sam/kbuild-fixes.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-next.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fixes.git L: linux-kbuild@vger.kernel.org S: Maintained +F: Documentation/kbuild/ +F: Makefile +F: scripts/Makefile.* KERNEL JANITORS P: Several @@ -2605,6 +3180,13 @@ M: neilb@suse.de L: linux-nfs@vger.kernel.org W: http://nfs.sourceforge.net/ S: Supported +F: fs/nfsd/ +F: include/linux/nfsd/ +F: fs/lockd/ +F: fs/nfs_common/ +F: net/sunrpc/ +F: include/linux/lockd/ +F: include/linux/sunrpc/ KERNEL VIRTUAL MACHINE (KVM) P: Avi Kivity @@ -2612,6 +3194,11 @@ M: avi@redhat.com L: kvm@vger.kernel.org W: http://kvm.qumranet.com S: Supported +F: Documentation/*/kvm.txt +F: arch/*/kvm/ +F: arch/*/include/asm/kvm* +F: include/linux/kvm* +F: virt/kvm/ KERNEL VIRTUAL MACHINE (KVM) FOR AMD-V P: Joerg Roedel @@ -2619,6 +3206,9 @@ M: joerg.roedel@amd.com L: kvm@vger.kernel.org W: http://kvm.qumranet.com S: Supported +F: arch/x86/include/asm/svm.h +F: arch/x86/kvm/kvm_svm.h +F: arch/x86/kvm/svm.c KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC P: Hollis Blanchard @@ -2626,6 +3216,8 @@ M: hollisb@us.ibm.com L: kvm-ppc@vger.kernel.org W: http://kvm.qumranet.com S: Supported +F: arch/powerpc/include/asm/kvm* +F: arch/powerpc/kvm/ KERNEL VIRTUAL MACHINE For Itanium (KVM/IA64) P: Xiantao Zhang @@ -2633,6 +3225,9 @@ M: xiantao.zhang@intel.com L: kvm-ia64@vger.kernel.org W: http://kvm.qumranet.com S: Supported +F: Documentation/ia64/kvm.txt +F: arch/ia64/include/asm/kvm* +F: arch/ia64/kvm/ KERNEL VIRTUAL MACHINE for s390 (KVM/s390) P: Carsten Otte @@ -2643,6 +3238,9 @@ M: linux390@de.ibm.com L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported +F: Documentation/s390/kvm.txt +F: arch/s390/include/asm/kvm* +F: arch/s390/kvm/ KEXEC P: Eric Biederman @@ -2651,18 +3249,28 @@ W: http://ftp.kernel.org/pub/linux/kernel/people/horms/kexec-tools/ L: linux-kernel@vger.kernel.org L: kexec@lists.infradead.org S: Maintained +F: include/linux/kexec.h +F: kernel/kexec.c KGDB P: Jason Wessel M: jason.wessel@windriver.com L: kgdb-bugreport@lists.sourceforge.net S: Maintained +F: Documentation/DocBook/kgdb.tmpl +F: drivers/misc/kgdbts.c +F: drivers/serial/kgdboc.c +F: include/linux/kgdb.h +F: kernel/kgdb.c KMEMTRACE P: Eduard - Gabriel Munteanu M: eduard.munteanu@linux360.ro L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/vm/kmemtrace.txt +F: include/trace/kmemtrace.h +F: kernel/trace/kmemtrace.c KPROBES P: Ananth N Mavinakayanahalli @@ -2675,6 +3283,9 @@ P: Masami Hiramatsu M: mhiramat@redhat.com L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/kprobes.txt +F: include/linux/kprobes.h +F: kernel/kprobes.c KS0108 LCD CONTROLLER DRIVER P: Miguel Ojeda Sandonis @@ -2683,21 +3294,31 @@ L: linux-kernel@vger.kernel.org W: http://miguelojeda.es/auxdisplay.htm W: http://jair.lab.fi.uva.es/~migojed/auxdisplay.htm S: Maintained +F: Documentation/auxdisplay/ks0108 +F: drivers/auxdisplay/ks0108.c +F: include/linux/ks0108.h LAPB module L: linux-x25@vger.kernel.org S: Orphan +F: Documentation/networking/lapb-module.txt +F: include/*/lapb.h +F: net/lapb/ LASI 53c700 driver for PARISC P: James E.J. Bottomley M: James.Bottomley@HansenPartnership.com L: linux-scsi@vger.kernel.org S: Maintained +F: Documentation/scsi/53c700.txt +F: drivers/scsi/53c700* LED SUBSYSTEM P: Richard Purdie M: rpurdie@rpsys.net S: Maintained +F: drivers/leds/ +F: include/linux/leds.h LEGO USB Tower driver P: Juergen Stuber @@ -2705,6 +3326,7 @@ M: starblue@users.sourceforge.net L: legousb-devel@lists.sourceforge.net W: http://legousb.sourceforge.net/ S: Maintained +F: drivers/usb/misc/legousbtower.c LGUEST P: Rusty Russell @@ -2712,6 +3334,11 @@ M: rusty@rustcorp.com.au L: lguest@ozlabs.org W: http://lguest.ozlabs.org/ S: Maintained +F: Documentation/lguest/ +F: arch/x86/lguest/ +F: drivers/lguest/ +F: include/linux/lguest*.h +F: arch/x86/include/asm/lguest*.h LINUX FOR IBM pSERIES (RS/6000) P: Paul Mackerras @@ -2719,12 +3346,6 @@ M: paulus@au.ibm.com W: http://www.ibm.com/linux/ltc/projects/ppc S: Supported -LINUX FOR NCR VOYAGER -P: James Bottomley -M: James.Bottomley@HansenPartnership.com -W: http://www.hansenpartnership.com/voyager -S: Maintained - LINUX FOR POWERPC (32-BIT AND 64-BIT) P: Benjamin Herrenschmidt M: benh@kernel.crashing.org @@ -2732,7 +3353,7 @@ P: Paul Mackerras M: paulus@samba.org W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org -T: git kernel.org:/pub/scm/linux/kernel/git/benh/powerpc.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git S: Supported LINUX FOR POWER MACINTOSH @@ -2757,7 +3378,7 @@ P: Matt Porter M: mporter@kernel.crashing.org W: http://www.penguinppc.org/ L: linuxppc-dev@ozlabs.org -T: git kernel.org:/pub/scm/linux/kernel/git/jwboyer/powerpc.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jwboyer/powerpc.git S: Maintained LINUX FOR POWERPC EMBEDDED XILINX VIRTEX @@ -2794,30 +3415,39 @@ LINUX SECURITY MODULE (LSM) FRAMEWORK P: Chris Wright M: chrisw@sous-sol.org L: linux-security-module@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/chrisw/lsm-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/chrisw/lsm-2.6.git S: Supported LLC (802.2) P: Arnaldo Carvalho de Melo M: acme@ghostprotocols.net S: Maintained +F: include/linux/llc.h +F: include/net/llc* +F: net/llc/ LIS3LV02D ACCELEROMETER DRIVER P: Eric Piel M: eric.piel@tremplin-utc.net S: Maintained +F: Documentation/hwmon/lis3lv02d +F: drivers/hwmon/lis3lv02d.* LM83 HARDWARE MONITOR DRIVER P: Jean Delvare M: khali@linux-fr.org L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/lm83 +F: drivers/hwmon/lm83.c LM90 HARDWARE MONITOR DRIVER P: Jean Delvare M: khali@linux-fr.org L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/lm90 +F: drivers/hwmon/lm90.c LOCKDEP AND LOCKSTAT P: Peter Zijlstra @@ -2825,8 +3455,12 @@ M: peterz@infradead.org P: Ingo Molnar M: mingo@redhat.com L: linux-kernel@vger.kernel.org -T: git://git.kernel.org/pub/scm/linux/kernel/git/peterz/linux-2.6-lockdep.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/peterz/linux-2.6-lockdep.git S: Maintained +F: Documentation/lockdep*.txt +F: Documentation/lockstat.txt +F: include/linux/lockdep.h +F: kernel/lockdep* LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP/Vista Dynamic Disks) P: Richard Russon (FlatCap) @@ -2834,6 +3468,8 @@ M: ldm@flatcap.org L: linux-ntfs-dev@lists.sourceforge.net W: http://www.linux-ntfs.org/content/view/19/37/ S: Maintained +F: Documentation/ldm.txt +F: fs/partitions/ldm.* LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) P: Eric Moore @@ -2843,12 +3479,14 @@ L: DL-MPTFusionLinux@lsi.com L: linux-scsi@vger.kernel.org W: http://www.lsilogic.com/support S: Supported +F: drivers/message/fusion/ LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers P: Matthew Wilcox M: matthew@wil.cx L: linux-scsi@vger.kernel.org S: Maintained +F: drivers/scsi/sym53c8xx_2/ LTP (Linux Test Project) P: Subrata Modak @@ -2857,7 +3495,7 @@ P: Mike Frysinger M: vapier@gentoo.org L: ltp-list@lists.sourceforge.net (subscribers-only) W: http://ltp.sourceforge.net/ -T: git kernel.org/pub/scm/linux/kernel/git/galak/ltp.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/galak/ltp.git S: Maintained M32R ARCHITECTURE @@ -2867,6 +3505,8 @@ L: linux-m32r@ml.linux-m32r.org L: linux-m32r-ja@ml.linux-m32r.org (in Japanese) W: http://www.linux-m32r.org/ S: Maintained +F: arch/m32r/ +F: include/asm-m32r/ M68K ARCHITECTURE P: Geert Uytterhoeven @@ -2875,8 +3515,10 @@ P: Roman Zippel M: zippel@linux-m68k.org L: linux-m68k@lists.linux-m68k.org W: http://www.linux-m68k.org/ -T: git git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k.git S: Maintained +F: arch/m68k/ +F: drivers/zorro/ M68K ON APPLE MACINTOSH P: Joshua Thompson @@ -2884,20 +3526,25 @@ M: funaho@jurai.org W: http://www.mac.linux-m68k.org/ L: linux-m68k@lists.linux-m68k.org S: Maintained +F: arch/m68k/mac/ M68K ON HP9000/300 P: Philip Blundell M: philb@gnu.org W: http://www.tazenda.demon.co.uk/phil/linux-hp S: Maintained +F: arch/m68k/hp300/ MAC80211 P: Johannes Berg M: johannes@sipsolutions.net L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git S: Maintained +F: Documentation/networking/mac80211-injection.txt +F: include/net/mac80211.h +F: net/mac80211/ MAC80211 PID RATE CONTROL P: Stefano Brivio @@ -2906,14 +3553,17 @@ P: Mattias Nissler M: mattias.nissler@gmx.de L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/en/developers/Documentation/mac80211/RateControl/PID -T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git S: Maintained +F: net/mac80211/rc80211_pid* MACVLAN DRIVER P: Patrick McHardy M: kaber@trash.net L: netdev@vger.kernel.org S: Maintained +F: drivers/net/macvlan.c +F: include/linux/if_macvlan.h MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7 P: Michael Kerrisk @@ -2927,12 +3577,15 @@ P: Dan Williams M: dcbw@redhat.com L: libertas-dev@lists.infradead.org S: Maintained +F: drivers/net/wireless/libertas/ MARVELL MV643XX ETHERNET DRIVER P: Lennert Buytenhek M: buytenh@marvell.com L: netdev@vger.kernel.org S: Supported +F: drivers/net/mv643xx_eth.* +F: include/linux/mv643xx.h MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER P: Nicolas Pitre @@ -2953,12 +3606,31 @@ P: Petr Vandrovec M: vandrove@vc.cvut.cz L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained +F: drivers/video/matrox/matroxfb_* +F: include/linux/matroxfb.h MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER P: Hans J. Koch M: hjk@linutronix.de L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/max6650 +F: drivers/hwmon/max6650.c + +MEDIA INPUT INFRASTRUCTURE (V4L/DVB) +P: Mauro Carvalho Chehab +M: mchehab@infradead.org +P: LinuxTV.org Project +L: linux-media@vger.kernel.org +W: http://linuxtv.org +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +S: Maintained +F: Documentation/dvb/ +F: Documentation/video4linux/ +F: drivers/media/ +F: include/media/ +F: include/linux/dvb/ +F: include/linux/videodev*.h MEGARAID SCSI DRIVERS P: Neela Syam Kolli @@ -2966,12 +3638,17 @@ M: megaraidlinux@lsi.com L: linux-scsi@vger.kernel.org W: http://megaraid.lsilogic.com S: Maintained +F: Documentation/scsi/megaraid.txt +F: drivers/scsi/megaraid.* +F: drivers/scsi/megaraid/ MEMORY MANAGEMENT L: linux-mm@kvack.org L: linux-kernel@vger.kernel.org W: http://www.linux-mm.org S: Maintained +F: include/linux/mm.h +F: mm/ MEMORY RESOURCE CONTROLLER P: Balbir Singh @@ -2983,6 +3660,7 @@ M: kamezawa.hiroyu@jp.fujitsu.com L: linux-mm@kvack.org L: linux-kernel@vger.kernel.org S: Maintained +F: mm/memcontrol.c MEMORY TECHNOLOGY DEVICES (MTD) P: David Woodhouse @@ -2991,55 +3669,84 @@ W: http://www.linux-mtd.infradead.org/ L: linux-mtd@lists.infradead.org T: git git://git.infradead.org/mtd-2.6.git S: Maintained +F: drivers/mtd/ +F: include/linux/mtd/ +F: include/mtd/ + +MICROBLAZE ARCHITECTURE +P: Michal Simek +M: monstr@monstr.eu +L: microblaze-uclinux@itee.uq.edu.au +W: http://www.monstr.eu/fdt/ +T: git git://git.monstr.eu/linux-2.6-microblaze.git +S: Supported +F: arch/microblaze/ MICROTEK X6 SCANNER P: Oliver Neukum M: oliver@neukum.name S: Maintained +F: drivers/usb/image/microtek.* MIPS P: Ralf Baechle M: ralf@linux-mips.org W: http://www.linux-mips.org/ L: linux-mips@linux-mips.org -T: git www.linux-mips.org:/pub/scm/linux.git +T: git git://git.linux-mips.org/pub/scm/linux.git S: Supported +F: Documentation/mips/ +F: arch/mips/ MISCELLANEOUS MCA-SUPPORT P: James Bottomley M: James.Bottomley@HansenPartnership.com L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/ia64/mca.txt +F: Documentation/mca.txt +F: drivers/mca/ +F: include/linux/mca* MODULE SUPPORT P: Rusty Russell M: rusty@rustcorp.com.au L: linux-kernel@vger.kernel.org S: Maintained +F: include/linux/module.h +F: kernel/module.c MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER P: Stelian Pop M: stelian@popies.net W: http://popies.net/meye/ S: Maintained +F: Documentation/video4linux/meye.txt +F: drivers/media/video/meye.* +F: include/linux/meye.h MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER P: Pavel Pisa M: ppisa@pikron.com L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained +F: drivers/mmc/host/imxmmc.* MOUSE AND MISC DEVICES [GENERAL] P: Alessandro Rubini M: rubini@ipvvis.unipv.it L: linux-kernel@vger.kernel.org S: Maintained +F: drivers/input/mouse/ +F: include/linux/gpio_mouse.h MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD P: Jiri Slaby M: jirislaby@gmail.com L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/serial/moxa-smartio +F: drivers/char/mxser.* MSI LAPTOP SUPPORT P: Lennart Poettering @@ -3047,43 +3754,54 @@ M: mzxreary@0pointer.de W: https://tango.0pointer.de/mailman/listinfo/s270-linux W: http://0pointer.de/lennart/tchibo.html S: Maintained +F: drivers/platform/x86/msi-laptop.c MULTIFUNCTION DEVICES (MFD) P: Samuel Ortiz M: sameo@linux.intel.com L: linux-kernel@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/sameo/mfd-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6.git S: Supported +F: drivers/mfd/ MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM P: Pierre Ossman M: pierre@ossman.eu L: linux-kernel@vger.kernel.org S: Maintained +F: drivers/mmc/ +F: include/linux/mmc/ MULTIMEDIA CARD (MMC) ETC. OVER SPI P: David Brownell M: dbrownell@users.sourceforge.net L: linux-kernel@vger.kernel.org S: Odd Fixes +F: drivers/mmc/host/mmc_spi.c +F: include/linux/spi/mmc_spi.h MULTISOUND SOUND DRIVER P: Andrew Veliath M: andrewtv@usa.net S: Maintained +F: Documentation/sound/oss/MultiSound +F: sound/oss/msnd* MULTITECH MULTIPORT CARD (ISICOM) P: Jiri Slaby M: jirislaby@gmail.com L: linux-kernel@vger.kernel.org S: Maintained +F: drivers/char/isicom.c +F: include/linux/isicom.h MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER P: Felipe Balbi M: felipe.balbi@nokia.com L: linux-usb@vger.kernel.org -T: git gitorious.org:/musb/mainline.git +T: git git://gitorious.org/musb/mainline.git S: Maintained +F: drivers/usb/musb/ MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE) P: Andrew Gallatin @@ -3093,23 +3811,27 @@ M: brice@myri.com L: netdev@vger.kernel.org W: http://www.myri.com/scs/download-Myri10GE.html S: Supported +F: drivers/net/myri10ge/ NATSEMI ETHERNET DRIVER (DP8381x) P: Tim Hockin M: thockin@hockin.org S: Maintained +F: drivers/net/natsemi.c NCP FILESYSTEM P: Petr Vandrovec M: vandrove@vc.cvut.cz L: linware@sh.cvut.cz S: Maintained +F: fs/ncpfs/ NCR DUAL 700 SCSI DRIVER (MICROCHANNEL) P: James E.J. Bottomley M: James.Bottomley@HansenPartnership.com L: linux-scsi@vger.kernel.org S: Maintained +F: drivers/scsi/NCR_D700.* NETEFFECT IWARP RNIC DRIVER (IW_NES) P: Faisal Latif @@ -3126,6 +3848,7 @@ P: Stephen Hemminger M: shemminger@linux-foundation.org L: netem@lists.linux-foundation.org S: Maintained +F: net/sched/sch_netem.c NETERION (S2IO) 10GbE DRIVER (xframe/vxge) P: Ramkrishna Vepa @@ -3142,6 +3865,8 @@ L: netdev@vger.kernel.org W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/Linux?Anonymous W: http://trac.neterion.com/cgi-bin/trac.cgi/wiki/X3100Linux?Anonymous S: Supported +F: Documentation/networking/s2io.txt +F: drivers/net/s2io* NETFILTER/IPTABLES/IPCHAINS P: Rusty Russell @@ -3157,6 +3882,12 @@ L: coreteam@netfilter.org W: http://www.netfilter.org/ W: http://www.iptables.org/ S: Supported +F: include/linux/netfilter* +F: include/linux/netfilter/ +F: include/net/netfilter/ +F: net/*/netfilter.c +F: net/*/netfilter/ +F: net/netfilter/ NETLABEL P: Paul Moore @@ -3164,6 +3895,9 @@ M: paul.moore@hp.com W: http://netlabel.sf.net L: netdev@vger.kernel.org S: Supported +F: Documentation/netlabel/ +F: include/net/netlabel.h +F: net/netlabel/ NETROM NETWORK LAYER P: Ralf Baechle @@ -3171,18 +3905,25 @@ M: ralf@linux-mips.org L: linux-hams@vger.kernel.org W: http://www.linux-ax25.org/ S: Maintained +F: include/linux/netrom.h +F: include/net/netrom.h +F: net/netrom/ NETWORK BLOCK DEVICE (NBD) P: Paul Clements M: Paul.Clements@steeleye.com S: Maintained +F: Documentation/blockdev/nbd.txt +F: drivers/block/nbd.c +F: include/linux/nbd.h NETWORK DEVICE DRIVERS P: Jeff Garzik M: jgarzik@pobox.com L: netdev@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git S: Maintained +F: drivers/net/ NETWORKING [GENERAL] P: Networking Team @@ -3190,6 +3931,8 @@ M: netdev@vger.kernel.org L: netdev@vger.kernel.org W: http://linux-net.osdl.org/ S: Maintained +F: net/ +F: include/net/ NETWORKING [IPv4/IPv6] P: David S. Miller @@ -3205,8 +3948,11 @@ M: yoshfuji@linux-ipv6.org P: Patrick McHardy M: kaber@trash.net L: netdev@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6.git S: Maintained +F: net/ipv4/ +F: net/ipv6/ +F: include/net/ip* NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK) P: Paul Moore @@ -3218,8 +3964,11 @@ NETWORKING [WIRELESS] P: John W. Linville M: linville@tuxdriver.com L: linux-wireless@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git S: Maintained +F: net/wireless/ +F: include/net/ieee80211* +F: include/net/wireless.h NETXEN (1/10) GbE SUPPORT P: Dhananjay Phadke @@ -3227,6 +3976,7 @@ M: dhananjay@netxen.com L: netdev@vger.kernel.org W: http://www.netxen.com S: Supported +F: drivers/net/netxen/ NFS, SUNRPC, AND LOCKD CLIENTS P: Trond Myklebust @@ -3235,6 +3985,13 @@ L: linux-nfs@vger.kernel.org W: http://client.linux-nfs.org T: git git://git.linux-nfs.org/pub/linux/nfs-2.6.git S: Maintained +F: fs/lockd/ +F: fs/nfs/ +F: fs/nfs_common/ +F: net/sunrpc/ +F: include/linux/lockd/ +F: include/linux/nfs* +F: include/linux/sunrpc/ NI5010 NETWORK DRIVER P: Jan-Pascal van Best @@ -3243,6 +4000,7 @@ P: Andreas Mohr M: andi@lisas.de L: netdev@vger.kernel.org S: Maintained +F: drivers/net/ni5010.* NILFS2 FILESYSTEM P: KONISHI Ryusuke @@ -3250,12 +4008,17 @@ M: konishi.ryusuke@lab.ntt.co.jp L: users@nilfs.org W: http://www.nilfs.org/en/ S: Supported +F: Documentation/filesystems/nilfs2.txt +F: fs/nilfs2/ +F: include/linux/nilfs2_fs.h NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER P: YOKOTA Hiroshi M: yokota@netlab.is.tsukuba.ac.jp W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/ S: Maintained +F: Documentation/scsi/NinjaSCSI.txt +F: drivers/scsi/pcmcia/nsp_* NINJA SCSI-32Bi/UDE PCI/CARDBUS SCSI HOST ADAPTER DRIVER P: GOTO Masanori @@ -3264,6 +4027,8 @@ P: YOKOTA Hiroshi M: yokota@netlab.is.tsukuba.ac.jp W: http://www.netlab.is.tsukuba.ac.jp/~yokota/izumi/ninja/ S: Maintained +F: Documentation/scsi/NinjaSCSI.txt +F: drivers/scsi/nsp32* NTFS FILESYSTEM P: Anton Altaparmakov @@ -3271,43 +4036,55 @@ M: aia21@cantab.net L: linux-ntfs-dev@lists.sourceforge.net L: linux-kernel@vger.kernel.org W: http://www.linux-ntfs.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/aia21/ntfs-2.6.git S: Maintained +F: Documentation/filesystems/ntfs.txt +F: fs/ntfs/ NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER P: Antonino Daplas M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained +F: drivers/video/riva/ +F: drivers/video/nvidia/ OMFS FILESYSTEM P: Bob Copeland M: me@bobcopeland.com L: linux-karma-devel@lists.sourceforge.net S: Maintained +F: Documentation/filesystems/omfs.txt +F: fs/omfs/ OMNIKEY CARDMAN 4000 DRIVER P: Harald Welte M: laforge@gnumonks.org S: Maintained +F: drivers/char/pcmcia/cm4000_cs.c +F: include/linux/cm4000_cs.h OMNIKEY CARDMAN 4040 DRIVER P: Harald Welte M: laforge@gnumonks.org S: Maintained +F: drivers/char/pcmcia/cm4040_cs.* OMNIVISION OV7670 SENSOR DRIVER P: Jonathan Corbet M: corbet@lwn.net L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained +F: drivers/media/video/ov7670.c ONENAND FLASH DRIVER P: Kyungmin Park M: kyungmin.park@samsung.com L: linux-mtd@lists.infradead.org S: Maintained +F: drivers/mtd/onenand/ +F: include/linux/mtd/onenand*.h ONSTREAM SCSI TAPE DRIVER P: Willem Riede @@ -3315,18 +4092,25 @@ M: osst@riede.org L: osst-users@lists.sourceforge.net L: linux-scsi@vger.kernel.org S: Maintained +F: drivers/scsi/osst* +F: drivers/scsi/st* OPENCORES I2C BUS DRIVER P: Peter Korsgaard M: jacmet@sunsite.dk L: linux-i2c@vger.kernel.org S: Maintained +F: Documentation/i2c/busses/i2c-ocores +F: drivers/i2c/busses/i2c-ocores.c OPROFILE P: Robert Richter M: robert.richter@amd.com L: oprofile-list@lists.sf.net S: Maintained +F: arch/*/oprofile/ +F: drivers/oprofile/ +F: include/linux/oprofile.h ORACLE CLUSTER FILESYSTEM 2 (OCFS2) P: Mark Fasheh @@ -3337,6 +4121,9 @@ L: ocfs2-devel@oss.oracle.com (moderated for non-subscribers) W: http://oss.oracle.com/projects/ocfs2/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2.git S: Supported +F: Documentation/filesystems/ocfs2.txt +F: Documentation/filesystems/dlmfs.txt +F: fs/ocfs2/ ORINOCO DRIVER P: Pavel Roskin @@ -3348,6 +4135,7 @@ L: orinoco-users@lists.sourceforge.net L: orinoco-devel@lists.sourceforge.net W: http://www.nongnu.org/orinoco/ S: Maintained +F: drivers/net/wireless/orinoco/ OSD LIBRARY P: Boaz Harrosh @@ -3356,7 +4144,7 @@ P: Benny Halevy M: bhalevy@panasas.com L: osd-dev@open-osd.org W: http://open-osd.org -T: git://git.open-osd.org/open-osd.git +T: git git://git.open-osd.org/open-osd.git S: Maintained P54 WIRELESS DRIVER @@ -3364,25 +4152,29 @@ P: Michael Wu M: flamingice@sourmilk.net L: linux-wireless@vger.kernel.org W: http://prism54.org -T: git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git S: Maintained +F: drivers/net/wireless/p54/ PA SEMI ETHERNET DRIVER P: Olof Johansson M: olof@lixom.net L: netdev@vger.kernel.org S: Maintained +F: drivers/net/pasemi_mac.* PA SEMI SMBUS DRIVER P: Olof Johansson M: olof@lixom.net L: linux-i2c@vger.kernel.org S: Maintained +F: drivers/i2c/busses/i2c-pasemi.c PANASONIC LAPTOP ACPI EXTRAS DRIVER P: Harald Welte M: laforge@gnumonks.org S: Maintained +F: drivers/platform/x86/panasonic-laptop.c PANASONIC MN10300/AM33 PORT P: David Howells @@ -3392,10 +4184,16 @@ M: yasutake.koichi@jp.panasonic.com L: linux-am33-list@redhat.com (moderated for non-subscribers) W: ftp://ftp.redhat.com/pub/redhat/gnupro/AM33/ S: Maintained +F: Documentation/mn10300/ +F: arch/mn10300/ PARALLEL PORT SUPPORT L: linux-parport@lists.infradead.org (subscribers-only) S: Orphan +F: drivers/parport/ +F: include/linux/parport*.h +F: drivers/char/ppdev.c +F: include/linux/ppdev.h PARAVIRT_OPS INTERFACE P: Jeremy Fitzhardinge @@ -3409,6 +4207,9 @@ M: rusty@rustcorp.com.au L: virtualization@lists.osdl.org L: linux-kernel@vger.kernel.org S: Supported +F: Documentation/ia64/paravirt_ops.txt +F: arch/*/kernel/paravirt* +F: arch/*/include/asm/paravirt.h PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES P: Tim Waugh @@ -3416,6 +4217,8 @@ M: tim@cyberelk.net L: linux-parport@lists.infradead.org (subscribers-only) W: http://www.torque.net/linux-pp.html S: Maintained +F: Documentation/blockdev/paride.txt +F: drivers/block/paride/ PARISC ARCHITECTURE P: Kyle McMartin @@ -3424,24 +4227,31 @@ P: Helge Deller M: deller@gmx.de L: linux-parisc@vger.kernel.org W: http://www.parisc-linux.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6.git S: Maintained +F: arch/parisc/ +F: drivers/parisc/ PC87360 HARDWARE MONITORING DRIVER P: Jim Cromie M: jim.cromie@gmail.com L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/pc87360 +F: drivers/hwmon/pc87360.c PC8736x GPIO DRIVER P: Jim Cromie M: jim.cromie@gmail.com S: Maintained +F: drivers/char/pc8736x_gpio.c PCA9532 LED DRIVER P: Riku Voipio M: riku.voipio@iki.fi S: Maintained +F: drivers/leds/leds-pca9532.c +F: include/linux/leds-pca9532.h PCI ERROR RECOVERY P: Linas Vepstas @@ -3449,63 +4259,82 @@ M: linas@austin.ibm.com L: linux-kernel@vger.kernel.org L: linux-pci@vger.kernel.org S: Supported +F: Documentation/PCI/pci-error-recovery.txt +F: Documentation/powerpc/eeh-pci-error-recovery.txt PCI SUBSYSTEM P: Jesse Barnes M: jbarnes@virtuousgeek.org L: linux-kernel@vger.kernel.org L: linux-pci@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git S: Supported +F: Documentation/PCI/ +F: drivers/pci/ +F: include/linux/pci* PCIE HOTPLUG DRIVER P: Kristen Carlson Accardi M: kristen.c.accardi@intel.com L: linux-pci@vger.kernel.org S: Supported +F: drivers/pci/pcie/ PCMCIA SUBSYSTEM P: Linux PCMCIA Team L: linux-pcmcia@lists.infradead.org W: http://lists.infradead.org/mailman/listinfo/linux-pcmcia -T: git kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git S: Maintained +F: Documentation/pcmcia/ +F: drivers/pcmcia/ +F: include/pcmcia/ PCNET32 NETWORK DRIVER P: Don Fry M: pcnet32@verizon.net L: netdev@vger.kernel.org S: Maintained +F: drivers/net/pcnet32.c PER-TASK DELAY ACCOUNTING P: Balbir Singh M: balbir@linux.vnet.ibm.com L: linux-kernel@vger.kernel.org S: Maintained +F: include/linux/delayacct.h +F: kernel/delayacct.c PERSONALITY HANDLING P: Christoph Hellwig M: hch@infradead.org L: linux-abi-devel@lists.sourceforge.net S: Maintained +F: include/linux/personality.h PHRAM MTD DRIVER P: Joern Engel M: joern@lazybastard.org L: linux-mtd@lists.infradead.org S: Maintained +F: drivers/mtd/devices/phram.c PKTCDVD DRIVER P: Peter Osterlund M: petero2@telia.com L: linux-kernel@vger.kernel.org S: Maintained +F: drivers/block/pktcdvd.c +F: include/linux/pktcdvd.h POSIX CLOCKS and TIMERS P: Thomas Gleixner M: tglx@linutronix.de L: linux-kernel@vger.kernel.org S: Supported +F: fs/timerfd.c +F: include/linux/timer* +F: kernel/*timer* POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS P: Anton Vorontsov @@ -3513,8 +4342,10 @@ M: cbou@mail.ru P: David Woodhouse M: dwmw2@infradead.org L: linux-kernel@vger.kernel.org -T: git git.infradead.org/battery-2.6.git +T: git git://git.infradead.org/battery-2.6.git S: Maintained +F: include/linux/power_supply.h +F: drivers/power/power_supply* PNP SUPPORT P: Adam Belay @@ -3522,33 +4353,42 @@ M: abelay@mit.edu P: Bjorn Helgaas M: bjorn.helgaas@hp.com S: Maintained +F: drivers/pnp/ PNXxxxx I2C DRIVER P: Vitaly Wool M: vitalywool@gmail.com L: linux-i2c@vger.kernel.org S: Maintained +F: drivers/i2c/busses/i2c-pnx.c PPP PROTOCOL DRIVERS AND COMPRESSORS P: Paul Mackerras M: paulus@samba.org L: linux-ppp@vger.kernel.org S: Maintained +F: drivers/net/ppp_* PPP OVER ATM (RFC 2364) P: Mitchell Blank Jr M: mitch@sfgoth.com S: Maintained +F: net/atm/pppoatm.c +F: include/linux/atmppp.h PPP OVER ETHERNET P: Michal Ostrowski M: mostrows@earthlink.net S: Maintained +F: drivers/net/pppoe.c +F: drivers/net/pppox.c PPP OVER L2TP P: James Chapman M: jchapman@katalix.com S: Maintained +F: drivers/net/pppol2tp.c +F: include/linux/if_pppol2tp.h PREEMPTIBLE KERNEL P: Robert Love @@ -3557,6 +4397,8 @@ L: linux-kernel@vger.kernel.org L: kpreempt-tech@lists.sourceforge.net W: ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel S: Supported +F: Documentation/preempt-locking.txt +F: include/linux/preempt.h PRISM54 WIRELESS DRIVER P: Luis R. Rodriguez @@ -3564,6 +4406,7 @@ M: mcgrof@gmail.com L: linux-wireless@vger.kernel.org W: http://prism54.org S: Maintained +F: drivers/net/wireless/prism54/ PROMISE DC4030 CACHING DISK CONTROLLER DRIVER P: Peter Denison @@ -3576,6 +4419,7 @@ P: Mikael Pettersson M: mikpe@it.uu.se L: linux-ide@vger.kernel.org S: Maintained +F: drivers/ata/sata_promise.* PS3 NETWORK SUPPORT P: Masakazu Mokuno @@ -3583,6 +4427,7 @@ M: mokuno@sm.sony.co.jp L: netdev@vger.kernel.org L: cbe-oss-dev@ozlabs.org S: Supported +F: drivers/net/ps3_gelic_net.* PS3 PLATFORM SUPPORT P: Geoff Levand @@ -3590,6 +4435,13 @@ M: geoffrey.levand@am.sony.com L: linuxppc-dev@ozlabs.org L: cbe-oss-dev@ozlabs.org S: Supported +F: arch/powerpc/boot/ps3* +F: arch/powerpc/include/asm/lv1call.h +F: arch/powerpc/include/asm/ps3*.h +F: arch/powerpc/platforms/ps3/ +F: drivers/*/ps3* +F: drivers/ps3/ +F: drivers/usb/host/*ps3.c PS3VRAM DRIVER P: Jim Paris @@ -3603,8 +4455,10 @@ M: isely@pobox.com L: pvrusb2@isely.net (subscribers-only) L: linux-media@vger.kernel.org W: http://www.isely.net/pvrusb2/ -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained +F: Documentation/video4linux/README.pvrusb2 +F: drivers/media/video/pvrusb2/ PXA2xx/PXA3xx SUPPORT P: Eric Miao @@ -3613,6 +4467,12 @@ P: Russell King M: linux@arm.linux.org.uk L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained +F: arch/arm/mach-pxa/ +F: drivers/pcmcia/pxa2xx* +F: drivers/spi/pxa2xx* +F: drivers/usb/gadget/pxa2* +F: include/sound/pxa2xx-lib.h +F: sound/soc/pxa/pxa2xx* PXA168 SUPPORT P: Eric Miao @@ -3620,14 +4480,14 @@ M: eric.miao@marvell.com P: Jason Chagas M: jason.chagas@marvell.com L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) -T: git kernel.org:/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git S: Supported PXA910 SUPPORT P: Eric Miao M: eric.miao@marvell.com L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) -T: git kernel.org:/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/ycmiao/pxa-linux-2.6.git S: Supported PXA MMCI DRIVER @@ -3644,12 +4504,16 @@ P: Andrew Vasquez M: linux-driver@qlogic.com L: linux-scsi@vger.kernel.org S: Supported +F: Documentation/scsi/LICENSE.qla2xxx +F: drivers/scsi/qla2xxx/ QLOGIC QLA3XXX NETWORK DRIVER P: Ron Mercer M: linux-driver@qlogic.com L: netdev@vger.kernel.org S: Supported +F: Documentation/networking/LICENSE.qla3xxx +F: drivers/net/qla3xxx.* QLOGIC QLGE 10Gb ETHERNET DRIVER P: Ron Mercer @@ -3657,6 +4521,7 @@ M: linux-driver@qlogic.com M: ron.mercer@qlogic.com L: netdev@vger.kernel.org S: Supported +F: drivers/net/qlge/ QNX4 FILESYSTEM P: Anders Larsen @@ -3664,18 +4529,24 @@ M: al@alarsen.net L: linux-kernel@vger.kernel.org W: http://www.alarsen.net/linux/qnx4fs/ S: Maintained +F: fs/qnx4/ +F: include/linux/qnx4_fs.h +F: include/linux/qnxtypes.h RADEON FRAMEBUFFER DISPLAY DRIVER P: Benjamin Herrenschmidt M: benh@kernel.crashing.org L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained +F: drivers/video/aty/radeon* +F: include/linux/radeonfb.h RAGE128 FRAMEBUFFER DISPLAY DRIVER P: Paul Mackerras M: paulus@samba.org L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained +F: drivers/video/aty/aty128fb.c RALINK RT2X00 WIRELESS LAN DRIVER P: rt2x00 project @@ -3683,36 +4554,43 @@ L: linux-wireless@vger.kernel.org L: users@rt2x00.serialmonkey.com W: http://rt2x00.serialmonkey.com/ S: Maintained -T: git kernel.org:/pub/scm/linux/kernel/git/ivd/rt2x00.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/ivd/rt2x00.git F: drivers/net/wireless/rt2x00/ RAMDISK RAM BLOCK DEVICE DRIVER P: Nick Piggin M: npiggin@suse.de S: Maintained +F: Documentation/blockdev/ramdisk.txt +F: drivers/block/brd.c RANDOM NUMBER DRIVER P: Matt Mackall M: mpm@selenic.com S: Maintained +F: drivers/char/random.c RAPIDIO SUBSYSTEM P: Matt Porter M: mporter@kernel.crashing.org L: linux-kernel@vger.kernel.org S: Maintained +F: drivers/rapidio/ RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER P: Corey Thomas M: coreythomas@charter.net L: linux-wireless@vger.kernel.org S: Maintained +F: drivers/net/wireless/ray* RCUTORTURE MODULE P: Josh Triplett M: josh@freedesktop.org L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/RCU/torture.txt +F: kernel/rcutorture.c RDC R-321X SoC P: Florian Fainelli @@ -3725,12 +4603,14 @@ P: Florian Fainelli M: florian.fainelli@telecomint.eu L: netdev@vger.kernel.org S: Maintained +F: drivers/net/r6040.c RDS - RELIABLE DATAGRAM SOCKETS P: Andy Grover M: andy.grover@oracle.com L: rds-devel@oss.oracle.com S: Supported +F: net/rds/ READ-COPY UPDATE (RCU) P: Dipankar Sarma @@ -3738,37 +4618,54 @@ M: dipankar@in.ibm.com W: http://www.rdrop.com/users/paulmck/rclock/ L: linux-kernel@vger.kernel.org S: Supported +F: Documentation/RCU/rcu.txt +F: Documentation/RCU/rcuref.txt +F: include/linux/rcupdate.h +F: include/linux/srcu.h +F: kernel/rcupdate.c REAL TIME CLOCK DRIVER P: Paul Gortmaker M: p_gortmaker@yahoo.com L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/rtc.txt +F: drivers/rtc/ +F: include/linux/rtc.h REAL TIME CLOCK (RTC) SUBSYSTEM P: Alessandro Zummo M: a.zummo@towertech.it L: rtc-linux@googlegroups.com S: Maintained +F: Documentation/rtc.txt +F: drivers/rtc/ +F: include/linux/rtc.h REISERFS FILE SYSTEM L: reiserfs-devel@vger.kernel.org S: Supported +F: fs/reiserfs/ RFKILL P: Ivo van Doorn M: IvDoorn@gmail.com L: netdev@vger.kernel.org S: Maintained -F: net/rfkill +F Documentation/rfkill.txt +F: net/rfkill/ RISCOM8 DRIVER S: Orphan +F: Documentation/serial/riscom8.txt +F: drivers/char/riscom8* ROCKETPORT DRIVER P: Comtrol Corp. W: http://www.comtrol.com S: Maintained +F: Documentation/serial/rocket.txt +F: drivers/char/rocket* ROSE NETWORK LAYER P: Ralf Baechle @@ -3776,32 +4673,38 @@ M: ralf@linux-mips.org L: linux-hams@vger.kernel.org W: http://www.linux-ax25.org/ S: Maintained +F: include/linux/rose.h +F: include/net/rose.h +F: net/rose/ RTL8180 WIRELESS DRIVER P: John W. Linville M: linville@tuxdriver.com L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-testing.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git S: Maintained +F: drivers/net/wireless/rtl818* RTL8187 WIRELESS DRIVER -P: Herton Ronaldo Krzesinski -M: herton@mandriva.com.br -P: Hin-Tak Leung -M htl10@users.sourceforge.net -P: Larry Finger -M: Larry.Finger@lwfinger.net -L: linux-wireless@vger.kernel.org -W: http://linuxwireless.org/ -T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-testing.git -S: Maintained +P: Herton Ronaldo Krzesinski +M: herton@mandriva.com.br +P: Hin-Tak Leung +M: htl10@users.sourceforge.net +P: Larry Finger +M: Larry.Finger@lwfinger.net +L: linux-wireless@vger.kernel.org +W: http://linuxwireless.org/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git +S: Maintained +F: drivers/net/wireless/rtl818x/rtl8187* S3 SAVAGE FRAMEBUFFER DRIVER P: Antonino Daplas M: adaplas@gmail.com L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained +F: drivers/video/savage/ S390 P: Martin Schwidefsky @@ -3812,6 +4715,7 @@ M: linux390@de.ibm.com L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported +F: arch/s390/ S390 NETWORK DRIVERS P: Ursula Braun @@ -3822,6 +4726,7 @@ M: linux390@de.ibm.com L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported +F: drivers/s390/net/ S390 ZCRYPT DRIVER P: Felix Beck @@ -3831,6 +4736,7 @@ M: ralph.wuerthner@de.ibm.com M: linux390@de.ibm.com L: linux-s390@vger.kernel.org S: Supported +F: drivers/s390/crypto/ S390 ZFCP DRIVER P: Christof Schmitt @@ -3841,6 +4747,8 @@ M: linux390@de.ibm.com L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported +F: Documentation/s390/zfcpdump.txt +F: drivers/s390/scsi/zfcp_* S390 IUCV NETWORK LAYER P: Ursula Braun @@ -3849,6 +4757,9 @@ M: linux390@de.ibm.com L: linux-s390@vger.kernel.org W: http://www.ibm.com/developerworks/linux/linux390/ S: Supported +F: drivers/s390/net/*iucv* +F: include/net/iucv/ +F: net/iucv/ S3C24XX SD/MMC Driver P: Ben Dooks @@ -3856,19 +4767,24 @@ M: ben-linux@fluff.org L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) L: linux-kernel@vger.kernel.org S: Supported +F: drivers/mmc/host/s3cmci.* SAA7146 VIDEO4LINUX-2 DRIVER P: Michael Hunold M: michael@mihu.de L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://www.mihu.de/linux/saa7146 S: Maintained +F: drivers/media/common/saa7146* +F: drivers/media/video/*7146* +F: include/media/*7146* SC1200 WDT DRIVER P: Zwane Mwaikambo M: zwane@arm.linux.org.uk S: Maintained +F: drivers/watchdog/sc1200wdt.c SCHEDULER P: Ingo Molnar @@ -3877,6 +4793,8 @@ P: Peter Zijlstra M: peterz@infradead.org L: linux-kernel@vger.kernel.org S: Maintained +F: kernel/sched* +F: include/linux/sched.h SCSI CDROM DRIVER P: Jens Axboe @@ -3884,6 +4802,7 @@ M: axboe@kernel.dk L: linux-scsi@vger.kernel.org W: http://www.kernel.dk S: Maintained +F: drivers/scsi/sr* SCSI SG DRIVER P: Doug Gilbert @@ -3891,21 +4810,27 @@ M: dgilbert@interlog.com L: linux-scsi@vger.kernel.org W: http://www.torque.net/sg S: Maintained +F: drivers/scsi/sg.c +F: include/scsi/sg.h SCSI SUBSYSTEM P: James E.J. Bottomley M: James.Bottomley@HansenPartnership.com L: linux-scsi@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git -T: git kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git -T: git kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-pending-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-pending-2.6.git S: Maintained +F: drivers/scsi/ +F: include/scsi/ SCSI TAPE DRIVER P: Kai Mäkisara M: Kai.Makisara@kolumbus.fi L: linux-scsi@vger.kernel.org S: Maintained +F: Documentation/scsi/st.txt +F: drivers/scsi/st* SCTP PROTOCOL P: Vlad Yasevich @@ -3915,27 +4840,41 @@ M: sri@us.ibm.com L: linux-sctp@vger.kernel.org W: http://lksctp.sourceforge.net S: Supported +F: Documentation/networking/sctp.txt +F: include/linux/sctp.h +F: include/net/sctp/ +F: net/sctp/ SCx200 CPU SUPPORT P: Jim Cromie M: jim.cromie@gmail.com S: Odd Fixes +F: Documentation/i2c/busses/scx200_acb +F: arch/x86/kernel/scx200_32.c +F: drivers/watchdog/scx200_wdt.c +F: drivers/i2c/busses/scx200* +F: drivers/mtd/maps/scx200_docflash.c +F: include/linux/scx200.h SCx200 GPIO DRIVER P: Jim Cromie M: jim.cromie@gmail.com S: Maintained +F: drivers/char/scx200_gpio.c +F: include/linux/scx200_gpio.h SCx200 HRT CLOCKSOURCE DRIVER P: Jim Cromie M: jim.cromie@gmail.com S: Maintained +F: drivers/clocksource/scx200_hrt.c SDRICOH_CS MMC/SD HOST CONTROLLER INTERFACE DRIVER P: Sascha Sommer M: saschasommer@freenet.de L: sdricohcs-devel@lists.sourceforge.net (subscribers-only) S: Maintained +F: drivers/mmc/host/sdricoh_cs.c SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER P: Pierre Ossman @@ -3949,16 +4888,17 @@ M: avorontsov@ru.mvista.com L: linuxppc-dev@ozlabs.org L: sdhci-devel@lists.ossman.eu S: Maintained +F: drivers/mmc/host/sdhci.* SECURITY SUBSYSTEM -F: security/ P: James Morris M: jmorris@namei.org L: linux-kernel@vger.kernel.org L: linux-security-module@vger.kernel.org (suggested Cc:) -T: git kernel.org:pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git +T: git git://www.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git W: http://security.wiki.kernel.org/ S: Supported +F: security/ SECURITY CONTACT P: Security Officers @@ -3973,31 +4913,39 @@ M: jmorris@namei.org P: Eric Paris M: eparis@parisplace.org L: linux-kernel@vger.kernel.org (kernel issues) -L: selinux@tycho.nsa.gov (subscribers-only, general discussion) +L: selinux@tycho.nsa.gov (subscribers-only, general discussion) W: http://selinuxproject.org -T: git kernel.org:pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git S: Supported +F: include/linux/selinux* +F: security/selinux/ SENSABLE PHANTOM P: Jiri Slaby M: jirislaby@gmail.com S: Maintained +F: drivers/misc/phantom.c +F: include/linux/phantom.h SERIAL ATA (SATA) SUBSYSTEM P: Jeff Garzik M: jgarzik@pobox.com L: linux-ide@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git S: Supported +F: drivers/ata/ +F: include/linux/ata.h +F: include/linux/libata.h SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER P: Sathya Perla M: sathyap@serverengines.com -P: Subbu Seetharaman -M: subbus@serverengines.com -L: netdev@vger.kernel.org -W: http://www.serverengines.com -S: Supported +P: Subbu Seetharaman +M: subbus@serverengines.com +L: netdev@vger.kernel.org +W: http://www.serverengines.com +S: Supported +F: drivers/net/benet/ SFC NETWORK DRIVER P: Steve Hodgson @@ -4005,17 +4953,22 @@ P: Ben Hutchings P: Robert Stonehouse M: linux-net-drivers@solarflare.com S: Supported +F: drivers/net/sfc/ SGI GRU DRIVER P: Jack Steiner M: steiner@sgi.com S: Maintained +F: drivers/misc/sgi-gru/ SGI SN-IA64 (Altix) SERIAL CONSOLE DRIVER P: Pat Gefre M: pfg@sgi.com L: linux-ia64@vger.kernel.org S: Supported +F: Documentation/ia64/serial.txt +F: drivers/serial/ioc?_serial.c +F: include/linux/ioc?.h SGI VISUAL WORKSTATION 320 AND 540 P: Andrey Panin @@ -4023,11 +4976,13 @@ M: pazke@donpac.ru L: linux-visws-devel@lists.sf.net W: http://linux-visws.sf.net S: Maintained for 2.6. +F: Documentation/sgi-visws.txt SGI XP/XPC/XPNET DRIVER -P: Dean Nelson -M: dcn@sgi.com +P: Robin Holt +M: holt@sgi.com S: Maintained +F: drivers/misc/sgi-xp/ SHARP LH SUPPORT (LH7952X & LH7A40X) P: Marc Singer @@ -4035,12 +4990,18 @@ M: elf@buici.com W: http://projects.buici.com/arm L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) S: Maintained +F: Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen +F: arch/arm/mach-lh7a40x/ +F: drivers/serial/serial_lh7a40x.c +F: drivers/usb/gadget/lh7a40* +F: drivers/usb/host/ohci-lh7a40* SHPC HOTPLUG DRIVER P: Kristen Carlson Accardi M: kristen.c.accardi@intel.com L: linux-pci@vger.kernel.org S: Supported +F: drivers/pci/hotplug/shpchp* SIMTEC EB110ATX (Chalice CATS) P: Ben Dooks @@ -4048,6 +5009,7 @@ P: Vincent Sanders M: support@simtec.co.uk W: http://www.simtec.co.uk/products/EB110ATX/ S: Supported +F: arch/arm/mach-ebsa110/ SIMTEC EB2410ITX (BAST) P: Ben Dooks @@ -4055,12 +5017,16 @@ P: Vincent Sanders M: support@simtec.co.uk W: http://www.simtec.co.uk/products/EB2410ITX/ S: Supported +F: arch/arm/mach-s3c2410/ +F: drivers/*/*s3c2410* +F: drivers/*/*/*s3c2410* SIS 190 ETHERNET DRIVER P: Francois Romieu M: romieu@fr.zoreil.com L: netdev@vger.kernel.org S: Maintained +F: drivers/net/sis190.c SIS 900/7016 FAST ETHERNET DRIVER P: Daniele Venzano @@ -4068,30 +5034,39 @@ M: venza@brownhat.org W: http://www.brownhat.org/sis900.html L: netdev@vger.kernel.org S: Maintained +F: drivers/net/sis900.* SIS 96X I2C/SMBUS DRIVER P: Mark M. Hoffman M: mhoffman@lightlink.com L: linux-i2c@vger.kernel.org S: Maintained +F: Documentation/i2c/busses/i2c-sis96x +F: drivers/i2c/busses/i2c-sis96x.c SIS FRAMEBUFFER DRIVER P: Thomas Winischhofer M: thomas@winischhofer.net W: http://www.winischhofer.net/linuxsisvga.shtml S: Maintained +F: Documentation/fb/sisfb.txt +F: drivers/video/sis/ +F: include/video/sisfb.h SIS USB2VGA DRIVER P: Thomas Winischhofer M: thomas@winischhofer.net W: http://www.winischhofer.at/linuxsisusbvga.shtml S: Maintained +F: drivers/usb/misc/sisusbvga/ SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS P: Stephen Hemminger M: shemminger@linux-foundation.org L: netdev@vger.kernel.org S: Maintained +F: drivers/net/skge.* +F: drivers/net/sky2.* SLAB ALLOCATOR P: Christoph Lameter @@ -4102,34 +5077,43 @@ P: Matt Mackall M: mpm@selenic.com L: linux-mm@kvack.org S: Maintained +F: include/linux/sl?b*.h +F: mm/sl?b.c SMC91x ETHERNET DRIVER P: Nicolas Pitre M: nico@cam.org S: Maintained +F: drivers/net/smc91x.* SMSC47B397 HARDWARE MONITOR DRIVER P: Mark M. Hoffman M: mhoffman@lightlink.com L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/smsc47b397 +F: drivers/hwmon/smsc47b397.c SMSC911x ETHERNET DRIVER P: Steve Glendinning M: steve.glendinning@smsc.com L: netdev@vger.kernel.org S: Supported +F: include/linux/smsc911x.h +F: drivers/net/smsc911x.* SMSC9420 PCI ETHERNET DRIVER P: Steve Glendinning M: steve.glendinning@smsc.com L: netdev@vger.kernel.org S: Supported +F: drivers/net/smsc9420.* SMX UIO Interface P: Ben Nizette M: bn@niasdigital.com S: Maintained +F: drivers/uio/uio_smx.c SN-IA64 (Itanium) SUB-PLATFORM P: Jes Sorensen @@ -4138,36 +5122,45 @@ L: linux-altix@sgi.com L: linux-ia64@vger.kernel.org W: http://www.sgi.com/altix S: Maintained +F: arch/ia64/sn/ SOC-CAMERA V4L2 SUBSYSTEM P: Guennadi Liakhovetski M: g.liakhovetski@gmx.de L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained +F: include/media/v4l2* +F: drivers/media/video/v4l2* SOEKRIS NET48XX LED SUPPORT P: Chris Boot M: bootc@bootc.net S: Maintained +F: drivers/leds/leds-net48xx.c SOFTWARE RAID (Multiple Disks) SUPPORT P: Neil Brown M: neilb@suse.de L: linux-raid@vger.kernel.org S: Supported +F: drivers/md/ +F: include/linux/raid/ SONIC NETWORK DRIVER P: Thomas Bogendoerfer M: tsbogend@alpha.franken.de L: netdev@vger.kernel.org S: Maintained +F: drivers/net/sonic.* SONICS SILICON BACKPLANE DRIVER (SSB) P: Michael Buesch M: mb@bu3sch.de L: netdev@vger.kernel.org S: Maintained +F: drivers/ssb/ +F: include/linux/ssb/ SONY VAIO CONTROL DEVICE DRIVER P: Mattia Dongili @@ -4175,6 +5168,10 @@ M: malattia@linux.it L: linux-acpi@vger.kernel.org W: http://www.linux.it/~malattia/wiki/index.php/Sony_drivers S: Maintained +F: Documentation/laptops/sony-laptop.txt +F: drivers/char/sonypi.c +F: drivers/platform/x86/sony-laptop.c +F: include/linux/sony-laptop.h SONY MEMORYSTICK CARD SUPPORT P: Alex Dubov @@ -4182,6 +5179,7 @@ M: oakad@yahoo.com L: linux-kernel@vger.kernel.org W: http://tifmxx.berlios.de/ S: Maintained +F: drivers/memstick/host/tifm_ms.c SOUND P: Jaroslav Kysela @@ -4190,36 +5188,44 @@ P: Takashi Iwai M: tiwai@suse.de L: alsa-devel@alsa-project.org (subscribers-only) S: Maintained +F: sound/ SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) P: Liam Girdwood M: lrg@slimlogic.co.uk P: Mark Brown M: broonie@opensource.wolfsonmicro.com -T: git opensource.wolfsonmicro.com/linux-2.6-asoc +T: git git://opensource.wolfsonmicro.com/linux-2.6-asoc L: alsa-devel@alsa-project.org (subscribers-only) W: http://alsa-project.org/main/index.php/ASoC S: Supported +F: sound/soc/ SPARC + UltraSPARC (sparc/sparc64) P: David S. Miller M: davem@davemloft.net L: sparclinux@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6.git -T: git kernel.org:/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git S: Maintained +F: arch/sparc/ SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER P: Roger Wolff M: R.E.Wolff@BitWizard.nl -L: linux-kernel@vger.kernel.org ? +L: linux-kernel@vger.kernel.org S: Supported +F: Documentation/serial/specialix.txt +F: drivers/char/specialix* SPI SUBSYSTEM P: David Brownell M: dbrownell@users.sourceforge.net L: spi-devel-general@lists.sourceforge.net S: Maintained +F: Documentation/spi/ +F: drivers/spi/ +F: include/linux/spi/ SPIDERNET NETWORK DRIVER for CELL P: Ishizaki Kou @@ -4228,6 +5234,8 @@ P: Jens Osterkamp M: jens@de.ibm.com L: netdev@vger.kernel.org S: Supported +F: Documentation/networking/spider_net.txt +F: drivers/net/spider_net* SPU FILE SYSTEM P: Jeremy Kerr @@ -4236,6 +5244,8 @@ L: linuxppc-dev@ozlabs.org L: cbe-oss-dev@ozlabs.org W: http://www.ibm.com/developerworks/power/cell/ S: Supported +F: Documentation/filesystems/spufs.txt +F: arch/powerpc/platforms/cell/spufs/ SQUASHFS FILE SYSTEM P: Phillip Lougher @@ -4243,12 +5253,15 @@ M: phillip@lougher.demon.co.uk L: squashfs-devel@lists.sourceforge.net (subscribers-only) W: http://squashfs.org.uk S: Maintained +F: Documentation/filesystems/squashfs.txt +F: fs/squashfs/ SRM (Alpha) environment access P: Jan-Benedict Glaw M: jbglaw@lug-owl.de L: linux-kernel@vger.kernel.org S: Maintained +F: arch/alpha/kernel/srm_env.c STABLE BRANCH P: Greg Kroah-Hartman @@ -4264,35 +5277,46 @@ M: gregkh@suse.de L: linux-kernel@vger.kernel.org T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ S: Maintained +F: drivers/staging/ STARFIRE/DURALAN NETWORK DRIVER P: Ion Badulescu M: ionut@cs.columbia.edu S: Maintained +F: drivers/net/starfire* STARMODE RADIO IP (STRIP) PROTOCOL DRIVER W: http://mosquitonet.Stanford.EDU/strip.html S: Orphan +F: drivers/net/wireless/strip.c +F: include/linux/if_strip.h STRADIS MPEG-2 DECODER DRIVER P: Nathan Laredo M: laredo@gnu.org W: http://www.stradis.com/ S: Maintained +F: drivers/media/video/stradis.c SUN3/3X P: Sam Creasey M: sammy@sammy.net W: http://sammy.net/sun3/ S: Maintained +F: arch/m68k/kernel/*sun3* +F: arch/m68k/sun3*/ +F: arch/m68k/include/asm/sun3* SUPERH P: Paul Mundt M: lethal@linux-sh.org L: linux-sh@vger.kernel.org W: http://www.linux-sh.org -T: git kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git S: Supported +F: Documentation/sh/ +F: arch/sh/ +F: drivers/sh/ SUSPEND TO RAM P: Len Brown @@ -4303,29 +5327,48 @@ P: Rafael J. Wysocki M: rjw@sisk.pl L: linux-pm@lists.linux-foundation.org S: Supported +F: Documentation/power/ +F: arch/x86/kernel/acpi/ +F: drivers/base/power/ +F: kernel/power/ +F: include/linux/suspend.h +F: include/linux/freezer.h +F: include/linux/pm.h +F: include/asm-*/suspend.h SVGA HANDLING P: Martin Mares M: mj@ucw.cz L: linux-video@atrey.karlin.mff.cuni.cz S: Maintained +F: Documentation/svga.txt +F: arch/x86/boot/video* SYSV FILESYSTEM P: Christoph Hellwig M: hch@infradead.org S: Maintained +F: Documentation/filesystems/sysv-fs.txt +F: fs/sysv/ +F: include/linux/sysv_fs.h TASKSTATS STATISTICS INTERFACE P: Balbir Singh M: balbir@linux.vnet.ibm.com L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/accounting/taskstats* +F: include/linux/taskstats* +F: kernel/taskstats.c TC CLASSIFIER P: Jamal Hadi Salim M: hadi@cyberus.ca L: netdev@vger.kernel.org S: Maintained +F: include/linux/pkt_cls.h +F: include/net/pkt_cls.h +F: net/sched/ TCP LOW PRIORITY MODULE P: Wong Hoi Sing, Edison @@ -4334,6 +5377,7 @@ P: Hung Hing Lun, Mike M: hlhung3i@gmail.com W: http://tcp-lp-mod.sourceforge.net/ S: Maintained +F: net/ipv4/tcp_lp.c TEHUTI ETHERNET DRIVER P: Alexander Indenbaum @@ -4342,16 +5386,19 @@ P: Andy Gospodarek M: andy@greyhouse.net L: netdev@vger.kernel.org S: Supported +F: drivers/net/tehuti* Telecom Clock Driver for MCPL0010 P: Mark Gross M: mark.gross@intel.com S: Supported +F: drivers/char/tlclk.c TENSILICA XTENSA PORT (xtensa) P: Chris Zankel M: chris@zankel.net S: Maintained +F: arch/xtensa/ THINKPAD ACPI EXTRAS DRIVER P: Henrique de Moraes Holschuh @@ -4359,13 +5406,17 @@ M: ibm-acpi@hmh.eng.br L: ibm-acpi-devel@lists.sourceforge.net W: http://ibm-acpi.sourceforge.net W: http://thinkwiki.org/wiki/Ibm-acpi -T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git +T: git git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git S: Maintained +F: drivers/platform/x86/thinkpad_acpi.c TI FLASH MEDIA INTERFACE DRIVER P: Alex Dubov M: oakad@yahoo.com S: Maintained +F: drivers/misc/tifm* +F: drivers/mmc/host/tifm_sd.c +F: include/linux/tifm.h TI OMAP MMC INTERFACE DRIVER P: Carlos Aguiar, Anderson Briglia and Syed Khasim @@ -4373,11 +5424,13 @@ M: linux-omap@vger.kernel.org W: http://linux.omap.com W: http://www.muru.com/linux/omap/ S: Maintained +F: drivers/mmc/host/omap.c TI OMAP RANDOM NUMBER GENERATOR SUPPORT P: Deepak Saxena M: dsaxena@plexity.net S: Maintained +F: drivers/char/hw_random/omap-rng.c TIPC NETWORK LAYER P: Per Liden @@ -4389,8 +5442,11 @@ M: allan.stephens@windriver.com L: tipc-discussion@lists.sourceforge.net W: http://tipc.sourceforge.net/ W: http://tipc.cslab.ericsson.net/ -T: git tipc.cslab.ericsson.net:/pub/git/tipc.git +T: git git://tipc.cslab.ericsson.net/pub/git/tipc.git S: Maintained +F: include/linux/tipc*.h +F: include/net/tipc/ +F: net/tipc/ TLAN NETWORK DRIVER P: Samuel Chessman @@ -4398,6 +5454,8 @@ M: chessman@tux.org L: tlan-devel@lists.sourceforge.net (subscribers-only) W: http://sourceforge.net/projects/tlan/ S: Maintained +F: Documentation/networking/tlan.txt +F: drivers/net/tlan.* TOMOYO SECURITY MODULE P: Kentaro Takeda @@ -4411,9 +5469,11 @@ L: tomoyo-users@lists.sourceforge.jp (subscribers-only, for users in Japanese) W: http://tomoyo.sourceforge.jp/ T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.2.x/tomoyo-lsm/patches/ S: Maintained +F: security/tomoyo/ TOSHIBA ACPI EXTRAS DRIVER S: Orphan +F: drivers/platform/x86/toshiba_acpi.c TOSHIBA SMM DRIVER P: Jonathan Buzzard @@ -4421,11 +5481,14 @@ M: jonathan@buzzard.org.uk L: tlinux-users@tce.toshiba-dme.co.jp W: http://www.buzzard.org.uk/toshiba/ S: Maintained +F: drivers/char/toshiba.c +F: include/linux/toshiba.h TMIO MMC DRIVER P: Ian Molton M: ian@mnementh.co.uk S: Maintained +F: drivers/mmc/host/tmio_mmc.* TPM DEVICE DRIVER P: Debora Velarde @@ -4438,12 +5501,13 @@ M: m.selhorst@sirrix.com W: http://www.sirrix.com L: tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained +F: drivers/char/tpm/ TRIVIAL PATCHES P: Jiri Kosina M: trivial@kernel.org L: linux-kernel@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/jikos/trivial.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial.git S: Maintained TTY LAYER @@ -4459,6 +5523,7 @@ P: Kyle McMartin M: kyle@mcmartin.ca L: netdev@vger.kernel.org S: Maintained +F: drivers/net/tulip/ TUN/TAP driver P: Maxim Krasnyansky @@ -4466,17 +5531,22 @@ M: maxk@qualcomm.com L: vtun@office.satix.net W: http://vtun.sourceforge.net/tun S: Maintained +F: Documentation/networking/tuntap.txt +F: arch/um/os-Linux/drivers/ TURBOCHANNEL SUBSYSTEM P: Maciej W. Rozycki M: macro@linux-mips.org S: Maintained +F: drivers/tc/ +F: include/linux/tc.h U14-34F SCSI DRIVER P: Dario Ballabio M: ballabio_dario@emc.com L: linux-scsi@vger.kernel.org S: Maintained +F: drivers/scsi/u14-34f.c UBI FILE SYSTEM (UBIFS) P: Artem Bityutskiy @@ -4487,6 +5557,8 @@ L: linux-mtd@lists.infradead.org T: git git://git.infradead.org/ubifs-2.6.git W: http://www.linux-mtd.infradead.org/doc/ubifs.html S: Maintained +F: Documentation/filesystems/ubifs.txt +F: fs/ubifs/ UCLINUX (AND M68KNOMMU) P: Greg Ungerer @@ -4494,6 +5566,7 @@ M: gerg@uclinux.org W: http://www.uclinux.org/ L: uclinux-dev@uclinux.org (subscribers-only) S: Maintained +F: arch/m68knommu/ UCLINUX FOR RENESAS H8/300 P: Yoshinori Sato @@ -4506,18 +5579,25 @@ P: Jan Kara M: jack@suse.cz W: http://linux-udf.sourceforge.net S: Maintained +F: Documentation/filesystems/udf.txt +F: fs/udf/ UFS FILESYSTEM P: Evgeniy Dushistov M: dushistov@mail.ru L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/filesystems/ufs.txt +F: fs/ufs/ ULTRA-WIDEBAND (UWB) SUBSYSTEM: P: David Vrabel M: david.vrabel@csr.com L: linux-usb@vger.kernel.org S: Supported +F: drivers/uwb/* +F: include/linux/uwb.h +F: include/linux/uwb/ UNIFORM CDROM DRIVER P: Jens Axboe @@ -4525,6 +5605,9 @@ M: axboe@kernel.dk L: linux-kernel@vger.kernel.org W: http://www.kernel.dk S: Maintained +F: Documentation/cdrom/ +F: drivers/cdrom/cdrom.c +F: include/linux/cdrom.h UNSORTED BLOCK IMAGES (UBI) P: Artem Bityutskiy @@ -4533,12 +5616,17 @@ W: http://www.linux-mtd.infradead.org/ L: linux-mtd@lists.infradead.org T: git git://git.infradead.org/ubi-2.6.git S: Maintained +F: drivers/mtd/ubi/ +F: include/linux/mtd/ubi.h +F: include/mtd/ubi-user.h USB ACM DRIVER P: Oliver Neukum M: oliver@neukum.name L: linux-usb@vger.kernel.org S: Maintained +F: Documentation/usb/acm.txt +F: drivers/usb/class/cdc-acm.* USB BLOCK DRIVER (UB ub) P: Pete Zaitcev @@ -4546,6 +5634,7 @@ M: zaitcev@redhat.com L: linux-kernel@vger.kernel.org L: linux-usb@vger.kernel.org S: Supported +F: drivers/block/ub.c USB CDC ETHERNET DRIVER P: Greg Kroah-Hartman @@ -4553,12 +5642,15 @@ M: greg@kroah.com L: linux-usb@vger.kernel.org S: Maintained W: http://www.kroah.com/linux-usb/ +F: drivers/net/usb/cdc_*.c +F: include/linux/usb/cdc.h USB CYPRESS C67X00 DRIVER P: Peter Korsgaard M: jacmet@sunsite.dk L: linux-usb@vger.kernel.org S: Maintained +F: drivers/usb/c67x00/ USB DAVICOM DM9601 DRIVER P: Peter Korsgaard @@ -4566,6 +5658,7 @@ M: jacmet@sunsite.dk L: netdev@vger.kernel.org W: http://www.linux-usb.org/usbnet S: Maintained +F: drivers/net/usb/dm9601.c USB DIAMOND RIO500 DRIVER P: Cesar Miquel @@ -4573,21 +5666,25 @@ M: miquel@df.uba.ar L: rio500-users@lists.sourceforge.net W: http://rio500.sourceforge.net S: Maintained +F: drivers/usb/misc/rio500* USB EHCI DRIVER P: David Brownell M: dbrownell@users.sourceforge.net L: linux-usb@vger.kernel.org S: Odd Fixes +F: Documentation/usb/ehci.txt +F: drivers/usb/host/ehci* USB ET61X[12]51 DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it L: linux-usb@vger.kernel.org L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://www.linux-projects.org S: Maintained +F: drivers/media/video/et61x251/ USB GADGET/PERIPHERAL SUBSYSTEM P: David Brownell @@ -4595,25 +5692,32 @@ M: dbrownell@users.sourceforge.net L: linux-usb@vger.kernel.org W: http://www.linux-usb.org/gadget S: Maintained +F: drivers/usb/gadget/ +F: include/linux/usb/gadget* USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...) P: Jiri Kosina M: jkosina@suse.cz L: linux-usb@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/jikos/hid.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git S: Maintained +F: Documentation/usb/hiddev.txt +F: drivers/hid/usbhid/ USB ISP116X DRIVER P: Olav Kongas M: ok@artecdesign.ee L: linux-usb@vger.kernel.org S: Maintained +F: drivers/usb/host/isp116x* +F: include/linux/usb/isp116x.h USB KAWASAKI LSI DRIVER P: Oliver Neukum M: oliver@neukum.name L: linux-usb@vger.kernel.org S: Maintained +F: drivers/usb/serial/kl5kusb105.* USB MASS STORAGE DRIVER P: Matthew Dharm @@ -4622,18 +5726,22 @@ L: linux-usb@vger.kernel.org L: usb-storage@lists.one-eyed-alien.net S: Maintained W: http://www.one-eyed-alien.net/~mdharm/linux-usb/ +F: drivers/usb/storage/ USB OHCI DRIVER P: David Brownell M: dbrownell@users.sourceforge.net L: linux-usb@vger.kernel.org S: Odd Fixes +F: Documentation/usb/ohci.txt +F: drivers/usb/host/ohci* USB OPTION-CARD DRIVER P: Matthias Urlichs M: smurf@smurf.noris.de L: linux-usb@vger.kernel.org S: Maintained +F: drivers/usb/serial/option.c USB OV511 DRIVER P: Mark McClelland @@ -4641,6 +5749,7 @@ M: mmcclell@bigfoot.com L: linux-usb@vger.kernel.org W: http://alpha.dyndns.org/ov511/ S: Maintained +F: drivers/media/video/ov511.* USB PEGASUS DRIVER P: Petko Manolov @@ -4649,12 +5758,14 @@ L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ S: Maintained +F: drivers/net/usb/pegasus.* USB PRINTER DRIVER (usblp) P: Pete Zaitcev M: zaitcev@redhat.com L: linux-usb@vger.kernel.org S: Supported +F: drivers/usb/class/usblp.c USB RTL8150 DRIVER P: Petko Manolov @@ -4663,6 +5774,7 @@ L: linux-usb@vger.kernel.org L: netdev@vger.kernel.org W: http://pegasus2.sourceforge.net/ S: Maintained +F: drivers/net/usb/rtl8150.c USB SE401 DRIVER P: Jeroen Vreeken @@ -4670,12 +5782,15 @@ M: pe1rxq@amsat.org L: linux-usb@vger.kernel.org W: http://www.chello.nl/~j.vreeken/se401/ S: Maintained +F: Documentation/video4linux/se401.txt +F: drivers/media/video/se401.* USB SERIAL BELKIN F5U103 DRIVER P: William Greathouse M: wgreathouse@smva.com L: linux-usb@vger.kernel.org S: Maintained +F: drivers/usb/serial/belkin_sa.* USB SERIAL CYPRESS M8 DRIVER P: Lonnie Mendez @@ -4684,12 +5799,14 @@ L: linux-usb@vger.kernel.org S: Maintained W: http://geocities.com/i0xox0i W: http://firstlight.net/cvs +F: drivers/usb/serial/cypress_m8.* USB SERIAL CYBERJACK DRIVER P: Matthias Bruestle and Harald Welte M: support@reiner-sct.com W: http://www.reiner-sct.de/support/treiber_cyberjack.php S: Maintained +F: drivers/usb/serial/cyberjack.c USB SERIAL DIGI ACCELEPORT DRIVER P: Peter Berger and Al Borchers @@ -4697,18 +5814,24 @@ M: pberger@brimson.com M: alborchers@steinerpoint.com L: linux-usb@vger.kernel.org S: Maintained +F: drivers/usb/serial/digi_acceleport.c USB SERIAL DRIVER P: Greg Kroah-Hartman M: gregkh@suse.de L: linux-usb@vger.kernel.org S: Supported +F: Documentation/usb/usb-serial.txt +F: drivers/usb/serial/generic.c +F: drivers/usb/serial/usb-serial.c +F: include/linux/usb/serial.h USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER P: Gary Brubaker M: xavyer@ix.netcom.com L: linux-usb@vger.kernel.org S: Maintained +F: drivers/usb/serial/empeg.c USB SERIAL KEYSPAN DRIVER P: Greg Kroah-Hartman @@ -4716,6 +5839,7 @@ M: greg@kroah.com L: linux-usb@vger.kernel.org W: http://www.kroah.com/linux/ S: Maintained +F: drivers/usb/serial/*keyspan* USB SERIAL WHITEHEAT DRIVER P: Support Department @@ -4723,21 +5847,25 @@ M: support@connecttech.com L: linux-usb@vger.kernel.org W: http://www.connecttech.com S: Supported +F: drivers/usb/serial/whiteheat* USB SMSC95XX ETHERNET DRIVER P: Steve Glendinning M: steve.glendinning@smsc.com L: netdev@vger.kernel.org S: Supported +F: drivers/net/usb/smsc95xx.* USB SN9C1xx DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it L: linux-usb@vger.kernel.org L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://www.linux-projects.org S: Maintained +F: Documentation/video4linux/sn9c102.txt +F: drivers/media/video/sn9c102/ USB SUBSYSTEM P: Greg Kroah-Hartman @@ -4746,12 +5874,18 @@ L: linux-usb@vger.kernel.org W: http://www.linux-usb.org T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ S: Supported +F: Documentation/usb/ +F: drivers/net/usb/ +F: drivers/usb/ +F: include/linux/usb.h +F: include/linux/usb/ USB UHCI DRIVER P: Alan Stern M: stern@rowland.harvard.edu L: linux-usb@vger.kernel.org S: Maintained +F: drivers/usb/host/uhci* USB "USBNET" DRIVER FRAMEWORK P: David Brownell @@ -4759,39 +5893,47 @@ M: dbrownell@users.sourceforge.net L: netdev@vger.kernel.org W: http://www.linux-usb.org/usbnet S: Maintained +F: drivers/net/usb/usbnet.c +F: include/linux/usb/usbnet.h USB VIDEO CLASS P: Laurent Pinchart M: laurent.pinchart@skynet.be L: linux-uvc-devel@lists.berlios.de (subscribers-only) L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://linux-uvc.berlios.de S: Maintained +F: drivers/media/video/uvc/ USB W996[87]CF DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it L: linux-usb@vger.kernel.org L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://www.linux-projects.org S: Maintained +F: Documentation/video4linux/w9968cf.txt +F: drivers/media/video/w996* USB WIRELESS RNDIS DRIVER (rndis_wlan) P: Jussi Kivilinna M: jussi.kivilinna@mbnet.fi L: linux-wireless@vger.kernel.org S: Maintained +F: drivers/net/wireless/rndis_wlan.c USB ZC0301 DRIVER P: Luca Risolia M: luca.risolia@studio.unibo.it L: linux-usb@vger.kernel.org L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://www.linux-projects.org S: Maintained +F: Documentation/video4linux/zc0301.txt +F: drivers/media/video/zc0301/ USB ZD1201 DRIVER P: Jeroen Vreeken @@ -4799,15 +5941,18 @@ M: pe1rxq@amsat.org L: linux-usb@vger.kernel.org W: http://linux-lc100020.sourceforge.net S: Maintained +F: drivers/net/wireless/zd1201.* USB ZR364XX DRIVER P: Antoine Jacquet M: royale@zerezo.com L: linux-usb@vger.kernel.org L: linux-media@vger.kernel.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git W: http://royale.zerezo.com/zr364xx/ S: Maintained +F: Documentation/video4linux/zr364xx.txt +F: drivers/media/video/zr364xx.c USER-MODE LINUX (UML) P: Jeff Dike @@ -4816,6 +5961,10 @@ L: user-mode-linux-devel@lists.sourceforge.net L: user-mode-linux-user@lists.sourceforge.net W: http://user-mode-linux.sourceforge.net S: Maintained +F: Documentation/uml/ +F: arch/um/ +F: fs/hostfs/ +F: fs/hppfs/ USERSPACE I/O (UIO) P: Hans J. Koch @@ -4824,13 +5973,16 @@ P: Greg Kroah-Hartman M: gregkh@suse.de L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/DocBook/uio-howto.tmpl +F: drivers/uio/ +F: include/linux/uio*.h UTIL-LINUX-NG PACKAGE P: Karel Zak M: kzak@redhat.com L: util-linux-ng@vger.kernel.org W: http://kernel.org/~kzak/util-linux-ng/ -T: git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git +T: git git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git S: Maintained UVESAFB DRIVER @@ -4839,23 +5991,30 @@ M: spock@gentoo.org L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) W: http://dev.gentoo.org/~spock/projects/uvesafb/ S: Maintained +F: Documentation/fb/uvesafb.txt +F: drivers/video/uvesafb.* VFAT/FAT/MSDOS FILESYSTEM P: OGAWA Hirofumi M: hirofumi@mail.parknet.co.jp L: linux-kernel@vger.kernel.org S: Maintained +F: Documentation/filesystems/vfat.txt +F: fs/fat/ VIA RHINE NETWORK DRIVER P: Roger Luethi M: rl@hellgate.ch S: Maintained +F: drivers/net/via-rhine.c VIAPRO SMBUS DRIVER P: Jean Delvare M: khali@linux-fr.org L: linux-i2c@vger.kernel.org S: Maintained +F: Documentation/i2c/busses/i2c-viapro +F: drivers/i2c/busses/i2c-viapro.c VIA UNICHROME(PRO)/CHROME9 FRAMEBUFFER DRIVER P: Joseph Chan @@ -4864,26 +6023,23 @@ P: Scott Fang M: ScottFang@viatech.com.cn L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) S: Maintained +F: drivers/video/via/ VIA VELOCITY NETWORK DRIVER P: Francois Romieu M: romieu@fr.zoreil.com L: netdev@vger.kernel.org S: Maintained - -VIDEO FOR LINUX (V4L) -P: Mauro Carvalho Chehab -M: mchehab@infradead.org -L: linux-media@vger.kernel.org -W: http://linuxtv.org -T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/linux-2.6.git -S: Maintained +F: drivers/net/via-velocity.* VLAN (802.1Q) P: Patrick McHardy M: kaber@trash.net L: netdev@vger.kernel.org S: Maintained +F: drivers/net/macvlan.c +F: include/linux/if_*vlan.h +F: net/8021q/ VOLTAGE AND CURRENT REGULATOR FRAMEWORK P: Liam Girdwood @@ -4892,49 +6048,64 @@ P: Mark Brown M: broonie@opensource.wolfsonmicro.com W: http://opensource.wolfsonmicro.com/node/15 W: http://www.slimlogic.co.uk/?p=48 -T: git kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6.git S: Supported +F: drivers/regulator/ +F: include/linux/regulator/ VT1211 HARDWARE MONITOR DRIVER P: Juerg Haefliger M: juergh@gmail.com L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/vt1211 +F: drivers/hwmon/vt1211.c VT8231 HARDWARE MONITOR DRIVER P: Roger Lucas M: vt8231@hiddenengine.co.uk L: lm-sensors@lm-sensors.org S: Maintained +F: drivers/hwmon/vt8231.c W1 DALLAS'S 1-WIRE BUS P: Evgeniy Polyakov M: johnpol@2ka.mipt.ru S: Maintained +F: Documentation/w1/ +F: drivers/w1/ W83791D HARDWARE MONITORING DRIVER P: Marc Hulsman M: m.hulsman@tudelft.nl L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/w83791d +F: drivers/hwmon/w83791d.c W83793 HARDWARE MONITORING DRIVER P: Rudolf Marek M: r.marek@assembler.cz L: lm-sensors@lm-sensors.org S: Maintained +F: Documentation/hwmon/w83793 +F: drivers/hwmon/w83793.c W83L51xD SD/MMC CARD INTERFACE DRIVER P: Pierre Ossman M: pierre@ossman.eu L: linux-kernel@vger.kernel.org S: Maintained +F: drivers/mmc/host/wbsd.* WATCHDOG DEVICE DRIVERS P: Wim Van Sebroeck M: wim@iguana.be -T: git kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog.git S: Maintained +F: Documentation/watchdog/ +F: drivers/watchdog/ +F: include/linux/watchdog.h WAVELAN NETWORK DRIVER & WIRELESS EXTENSIONS P: Jean Tourrilhes @@ -4942,12 +6113,15 @@ M: jt@hpl.hp.com L: linux-wireless@vger.kernel.org W: http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/ S: Maintained +F: Documentation/networking/wavelan.txt +F: drivers/net/wireless/wavelan* WD7000 SCSI DRIVER P: Miroslav Zagorac M: zaga@fly.cc.fer.hr L: linux-scsi@vger.kernel.org S: Maintained +F: drivers/scsi/wd7000.c WIMAX STACK P: Inaky Perez-Gonzalez @@ -4961,11 +6135,14 @@ WIMEDIA LLC PROTOCOL (WLP) SUBSYSTEM P: David Vrabel M: david.vrabel@csr.com S: Maintained +F: include/linux/wlp.h +F: drivers/uwb/wlp/ WISTRON LAPTOP BUTTON DRIVER P: Miloslav Trmac M: mitr@volny.cz S: Maintained +F: drivers/input/misc/wistron_btns.c WL3501 WIRELESS PCMCIA CARD DRIVER P: Arnaldo Carvalho de Melo @@ -4973,6 +6150,7 @@ M: acme@ghostprotocols.net L: linux-wireless@vger.kernel.org W: http://oops.ghostprotocols.net:81/blog S: Maintained +F: drivers/net/wireless/wl3501* WM97XX TOUCHSCREEN DRIVERS P: Mark Brown @@ -4983,12 +6161,17 @@ L: linux-input@vger.kernel.org T: git git://opensource.wolfsonmicro.com/linux-2.6-touch W: http://opensource.wolfsonmicro.com/node/7 S: Supported +F: drivers/input/touchscreen/*wm97* +F: include/linux/wm97xx.h X.25 NETWORK LAYER P: Henner Eisen M: eis@baty.hanse.de L: linux-x25@vger.kernel.org S: Maintained +F: Documentation/networking/x25* +F: include/net/x25* +F: net/x25/ X86 ARCHITECTURE (32-BIT AND 64-BIT) P: Thomas Gleixner @@ -4999,8 +6182,10 @@ P: H. Peter Anvin M: hpa@zytor.com M: x86@kernel.org L: linux-kernel@vger.kernel.org -T: git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git S: Maintained +F: Documentation/x86/ +F: arch/x86/ XEN HYPERVISOR INTERFACE P: Jeremy Fitzhardinge @@ -5010,6 +6195,11 @@ M: chrisw@sous-sol.org L: virtualization@lists.osdl.org L: xen-devel@lists.xensource.com S: Supported +F: arch/x86/xen/ +F: drivers/*/xen-*front.c +F: drivers/xen/ +F: arch/x86/include/asm/xen/ +F: include/xen/ XFS FILESYSTEM P: Silicon Graphics Inc @@ -5018,8 +6208,10 @@ M: felixb@sgi.com M: xfs-masters@oss.sgi.com L: xfs@oss.sgi.com W: http://oss.sgi.com/projects/xfs -T: git://oss.sgi.com/xfs/xfs.git +T: git git://oss.sgi.com/xfs/xfs.git S: Supported +F: Documentation/filesystems/xfs.txt +F: fs/xfs/ XILINX SYSTEMACE DRIVER P: Grant Likely @@ -5027,24 +6219,30 @@ M: grant.likely@secretlab.ca W: http://www.secretlab.ca/ L: linux-kernel@vger.kernel.org S: Maintained +F: drivers/block/xsysace.c XILINX UARTLITE SERIAL DRIVER P: Peter Korsgaard M: jacmet@sunsite.dk L: linux-serial@vger.kernel.org S: Maintained +F: drivers/serial/uartlite.c YAM DRIVER FOR AX.25 P: Jean-Paul Roubelat M: jpr@f6fbb.org L: linux-hams@vger.kernel.org S: Maintained +F: drivers/net/hamradio/yam* +F: include/linux/yam.h YEALINK PHONE DRIVER P: Henk Vergonet M: Henk.Vergonet@gmail.com L: usbb2k-api-dev@nongnu.org S: Maintained +F: Documentation/input/yealink.txt +F: drivers/input/misc/yealink.* Z8530 DRIVER FOR AX.25 P: Joerg Reuter @@ -5053,6 +6251,9 @@ W: http://yaina.de/jreuter/ W: http://www.qsl.net/dl1bke/ L: linux-hams@vger.kernel.org S: Maintained +F: Documentation/networking/z8530drv.txt +F: drivers/net/hamradio/*scc.c +F: drivers/net/hamradio/z8530.h ZD1211RW WIRELESS DRIVER P: Daniel Drake @@ -5063,6 +6264,7 @@ W: http://zd1211.ath.cx/wiki/DriverRewrite L: linux-wireless@vger.kernel.org L: zd1211-devs@lists.sourceforge.net (subscribers-only) S: Maintained +F: drivers/net/wireless/zd1211rw/ ZR36067 VIDEO FOR LINUX DRIVER L: mjpeg-users@lists.sourceforge.net @@ -5070,12 +6272,15 @@ L: linux-media@vger.kernel.org W: http://mjpeg.sourceforge.net/driver-zoran/ T: Mercurial http://linuxtv.org/hg/v4l-dvb S: Odd Fixes +F: drivers/media/video/zoran/ ZS DECSTATION Z85C30 SERIAL DRIVER P: Maciej W. Rozycki M: macro@linux-mips.org S: Maintained +F: drivers/serial/zs.* THE REST P: Linus Torvalds +T: git git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git S: Buried alive in reporters @@ -169,7 +169,7 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ -e s/arm.*/arm/ -e s/sa110/arm/ \ -e s/s390x/s390/ -e s/parisc64/parisc/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ - -e s/sh.*/sh/ ) + -e s/sh[234].*/sh/ ) # Cross compiling and selecting different set of gcc/bin-utils # --------------------------------------------------------------------------- @@ -210,6 +210,11 @@ ifeq ($(ARCH),sparc64) SRCARCH := sparc endif +# Additional ARCH settings for sh +ifeq ($(ARCH),sh64) + SRCARCH := sh +endif + # Where to locate arch specific headers hdr-arch := $(SRCARCH) @@ -567,7 +572,7 @@ KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) # disable pointer signed / unsigned warnings in gcc 4.0 KBUILD_CFLAGS += $(call cc-option,-Wno-pointer-sign,) -# disable invalid "can't wrap" optimzations for signed / pointers +# disable invalid "can't wrap" optimizations for signed / pointers KBUILD_CFLAGS += $(call cc-option,-fwrapv) # revert to pre-gcc-4.4 behaviour of .eh_frame @@ -597,6 +602,10 @@ LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\ LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID) LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID) +ifeq ($(CONFIG_STRIP_ASM_SYMS),y) +LDFLAGS_vmlinux += -X +endif + # Default kernel image to build when no specific target is given. # KBUILD_IMAGE may be overruled on the command line or # set in the environment @@ -1587,5 +1596,5 @@ PHONY += FORCE FORCE: # Declare the contents of the .PHONY variable as phony. We keep that -# information in a variable se we can use it in if_changed and friends. +# information in a variable so we can use it in if_changed and friends. .PHONY: $(PHONY) diff --git a/arch/Kconfig b/arch/Kconfig index dc81b34c5d8..78a35e9dc10 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -109,3 +109,6 @@ config HAVE_CLK config HAVE_DMA_API_DEBUG bool + +config HAVE_DEFAULT_NO_SPIN_MUTEXES + bool diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index fc74e913c41..34a56a136ef 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -131,14 +131,14 @@ static struct musb_hdrc_platform_data musb_plat = { .power = 50, /* up to 100 mA */ }; -static u64 musb_dmamask = DMA_32BIT_MASK; +static u64 musb_dmamask = DMA_BIT_MASK(32); static struct platform_device musb_device = { .name = "musb_hdrc", .id = -1, .dev = { .dma_mask = &musb_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, + .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = &musb_plat, }, .num_resources = ARRAY_SIZE(musb_resources), @@ -146,14 +146,14 @@ static struct platform_device musb_device = { }; #ifdef CONFIG_NOP_USB_XCEIV -static u64 nop_xceiv_dmamask = DMA_32BIT_MASK; +static u64 nop_xceiv_dmamask = DMA_BIT_MASK(32); static struct platform_device nop_xceiv_device = { .name = "nop_usb_xceiv", .id = -1, .dev = { .dma_mask = &nop_xceiv_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, + .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = NULL, }, }; diff --git a/arch/ia64/kernel/pci-swiotlb.c b/arch/ia64/kernel/pci-swiotlb.c index 573f02c39a0..285aae8431c 100644 --- a/arch/ia64/kernel/pci-swiotlb.c +++ b/arch/ia64/kernel/pci-swiotlb.c @@ -16,7 +16,7 @@ EXPORT_SYMBOL(swiotlb); static void *ia64_swiotlb_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) { - if (dev->coherent_dma_mask != DMA_64BIT_MASK) + if (dev->coherent_dma_mask != DMA_BIT_MASK(64)) gfp |= GFP_DMA; return swiotlb_alloc_coherent(dev, size, dma_handle, gfp); } diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig new file mode 100644 index 00000000000..8cc312b5d4d --- /dev/null +++ b/arch/microblaze/Kconfig @@ -0,0 +1,141 @@ +# For a description of the syntax of this configuration file, +# see Documentation/kbuild/kconfig-language.txt. + +mainmenu "Linux/Microblaze Kernel Configuration" + +config MICROBLAZE + def_bool y + select HAVE_LMB + +config SWAP + def_bool n + +config RWSEM_GENERIC_SPINLOCK + def_bool y + +config RWSEM_XCHGADD_ALGORITHM + bool + +config ARCH_HAS_ILOG2_U32 + def_bool n + +config ARCH_HAS_ILOG2_U64 + def_bool n + +config GENERIC_FIND_NEXT_BIT + def_bool y + +config GENERIC_HWEIGHT + def_bool y + +config GENERIC_HARDIRQS + def_bool y + +config GENERIC_IRQ_PROBE + def_bool y + +config GENERIC_CALIBRATE_DELAY + def_bool y + +config GENERIC_TIME + def_bool y + +config GENERIC_TIME_VSYSCALL + def_bool n + +config GENERIC_CLOCKEVENTS + def_bool y + +config GENERIC_HARDIRQS_NO__DO_IRQ + def_bool y + +config PCI + depends on !MMU + def_bool n + +config NO_DMA + depends on !MMU + def_bool n + +source "init/Kconfig" + +source "kernel/Kconfig.freezer" + +source "arch/microblaze/platform/Kconfig.platform" + +menu "Processor type and features" + +source kernel/time/Kconfig + +source "kernel/Kconfig.preempt" + +source "kernel/Kconfig.hz" + +config MMU + def_bool n + +config NO_MMU + bool + depends on !MMU + default y + +comment "Boot options" + +config CMDLINE_BOOL + bool "Default bootloader kernel arguments" + +config CMDLINE + string "Default kernel command string" + depends on CMDLINE_BOOL + default "console=ttyUL0,115200" + help + On some architectures there is currently no way for the boot loader + to pass arguments to the kernel. For these architectures, you should + supply some command-line options at build time by entering them + here. + +config CMDLINE_FORCE + bool "Force default kernel command string" + depends on CMDLINE_BOOL + default n + help + Set this to have arguments from the default kernel command string + override those passed by the boot loader. + +config OF + def_bool y + +config OF_DEVICE + def_bool y + +config PROC_DEVICETREE + bool "Support for device tree in /proc" + depends on PROC_FS + help + This option adds a device-tree directory under /proc which contains + an image of the device tree that the kernel copies from Open + Firmware or other boot firmware. If unsure, say Y here. + +endmenu + +source "mm/Kconfig" + +menu "Exectuable file formats" + +source "fs/Kconfig.binfmt" + +endmenu + +source "net/Kconfig" + +source "drivers/Kconfig" + +source "fs/Kconfig" + +source "arch/microblaze/Kconfig.debug" + +source "security/Kconfig" + +source "crypto/Kconfig" + +source "lib/Kconfig" diff --git a/arch/microblaze/Kconfig.debug b/arch/microblaze/Kconfig.debug new file mode 100644 index 00000000000..242cd35bdb4 --- /dev/null +++ b/arch/microblaze/Kconfig.debug @@ -0,0 +1,26 @@ +# For a description of the syntax of this configuration file, +# see Documentation/kbuild/kconfig-language.txt. + +menu "Kernel hacking" + +source "lib/Kconfig.debug" + +config EARLY_PRINTK + bool "Early printk function for kernel" + default n + help + This option turns on/off early printk messages to console. + First Uartlite node is taken. + +config HEART_BEAT + bool "Heart beat function for kernel" + default n + help + This option turns on/off heart beat kernel functionality. + First GPIO node is taken. + +config DEBUG_BOOTMEM + depends on DEBUG_KERNEL + bool "Debug BOOTMEM initialization" + +endmenu diff --git a/arch/microblaze/Makefile b/arch/microblaze/Makefile new file mode 100644 index 00000000000..0dcbb983297 --- /dev/null +++ b/arch/microblaze/Makefile @@ -0,0 +1,69 @@ +UTS_SYSNAME = -DUTS_SYSNAME=\"uClinux\" + +# What CPU vesion are we building for, and crack it open +# as major.minor.rev +CPU_VER=$(subst ",,$(CONFIG_XILINX_MICROBLAZE0_HW_VER) ) +CPU_MAJOR=$(shell echo $(CPU_VER) | cut -d '.' -f 1) +CPU_MINOR=$(shell echo $(CPU_VER) | cut -d '.' -f 2) +CPU_REV=$(shell echo $(CPU_VER) | cut -d '.' -f 3) + +export CPU_VER CPU_MAJOR CPU_MINOR CPU_REV + +# Use cpu-related CONFIG_ vars to set compile options. + +# Work out HW multipler support. This is icky. +# 1. Spartan2 has no HW multiplers. +# 2. MicroBlaze v3.x always uses them, except in Spartan 2 +# 3. All other FPGa/CPU ver combos, we can trust the CONFIG_ settings +ifeq (,$(findstring spartan2,$(CONFIG_XILINX_MICROBLAZE0_FAMILY))) + ifeq ($(CPU_MAJOR),3) + CPUFLAGS-1 += -mno-xl-soft-mul + else + # USE_HW_MUL can be 0, 1, or 2, defining a heirarchy of HW Mul support. + CPUFLAGS-$(subst 1,,$(CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL)) += -mxl-multiply-high + CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL) += -mno-xl-soft-mul + endif +endif +CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_DIV) += -mno-xl-soft-div +CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_BARREL) += -mxl-barrel-shift +CPUFLAGS-$(CONFIG_XILINX_MICROBLAZE0_USE_PCMP) += -mxl-pattern-compare + +CPUFLAGS-1 += $(call cc-option,-mcpu=v$(CPU_VER)) + +# The various CONFIG_XILINX cpu features options are integers 0/1/2... +# rather than bools y/n +CFLAGS += $(CPUFLAGS-1) +CFLAGS += $(CPUFLAGS-2) + +# r31 holds current when in kernel mode +CFLAGS += -ffixed-r31 + +LDFLAGS_BLOB := --format binary --oformat elf32-microblaze + +LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) + +head-y := arch/microblaze/kernel/head.o +libs-y += arch/microblaze/lib/ $(LIBGCC) +core-y += arch/microblaze/kernel/ arch/microblaze/mm/ \ + arch/microblaze/platform/ + +boot := arch/$(ARCH)/boot + +# defines filename extension depending memory management type +ifeq ($(CONFIG_MMU),) +MMUEXT := -nommu +endif +export MMUEXT + +all: linux.bin + +archclean: + $(Q)$(MAKE) $(clean)=$(boot) + +linux.bin linux.bin.gz: vmlinux + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ + +define archhelp + echo '* linux.bin - Create raw binary' + echo ' linux.bin.gz - Create compressed raw binary' +endef diff --git a/arch/microblaze/boot/Makefile b/arch/microblaze/boot/Makefile new file mode 100644 index 00000000000..844edf406d3 --- /dev/null +++ b/arch/microblaze/boot/Makefile @@ -0,0 +1,17 @@ +# +# arch/microblaze/boot/Makefile +# + +targets := linux.bin linux.bin.gz + +OBJCOPYFLAGS_linux.bin := -O binary + +$(obj)/linux.bin: vmlinux FORCE + $(call if_changed,objcopy) + @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' + +$(obj)/linux.bin.gz: $(obj)/linux.bin FORCE + $(call if_changed,gzip) + @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' + +clean-kernel += linux.bin linux.bin.gz diff --git a/arch/microblaze/configs/nommu_defconfig b/arch/microblaze/configs/nommu_defconfig new file mode 100644 index 00000000000..beb7ecd7279 --- /dev/null +++ b/arch/microblaze/configs/nommu_defconfig @@ -0,0 +1,804 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29 +# Tue Mar 24 10:23:20 2009 +# +CONFIG_MICROBLAZE=y +# CONFIG_SWAP is not set +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_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME=y +# CONFIG_GENERIC_TIME_VSYSCALL is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +# CONFIG_PCI is not set +# CONFIG_NO_DMA is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_KALLSYMS_EXTRA_PASS=y +# CONFIG_HOTPLUG is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +# CONFIG_BASE_FULL is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=1 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# Platform options +# +CONFIG_PLATFORM_GENERIC=y +# CONFIG_SELFMOD is not set +# CONFIG_OPT_LIB_FUNCTION is not set +# CONFIG_ALLOW_EDIT_AUTO is not set +CONFIG_KERNEL_BASE_ADDR=0x90000000 +CONFIG_XILINX_MICROBLAZE0_FAMILY="virtex5" +CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 +CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 +CONFIG_XILINX_MICROBLAZE0_USE_DIV=1 +CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=2 +CONFIG_XILINX_MICROBLAZE0_USE_FPU=2 +CONFIG_XILINX_MICROBLAZE0_HW_VER="7.10.d" + +# +# Processor type and features +# +CONFIG_TICK_ONESHOT=y +# CONFIG_NO_HZ is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=100 +CONFIG_SCHED_HRTICK=y +# CONFIG_MMU is not set +CONFIG_NO_MMU=y + +# +# Boot options +# +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyUL0,115200" +# CONFIG_CMDLINE_FORCE is not set +CONFIG_OF=y +CONFIG_OF_DEVICE=y +CONFIG_PROC_DEVICETREE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y + +# +# Exectuable file formats +# +CONFIG_BINFMT_FLAT=y +# CONFIG_BINFMT_ZFLAT is not set +# CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +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_XFRM_STATISTICS 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 is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# 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_LRO is not set +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_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_NET_DSA 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 +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y +# CONFIG_WIRELESS_EXT is not set +# CONFIG_LIB80211 is not set +# CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +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 +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# 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=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_UCLINUX=y +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# 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 is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_NBD=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_DNET 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_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 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_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_UARTLITE=y +CONFIG_SERIAL_UARTLITE_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +CONFIG_DAB=y + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=y +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_SOUND is not set +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 +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set + +# +# Enable Host or Gadget support to see Inventra options +# + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; +# +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_UIO is not set +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA 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_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# 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_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_REGISTER_V4 is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS 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 + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_UNUSED_SYMBOLS=y +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_SHIRQ=y +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_SELFTEST=y +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 +# 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_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_NOMMU_REGIONS is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_DEBUG_LIST=y +CONFIG_DEBUG_SG=y +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_TRACE_BRANCH_PROFILING is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_EARLY_PRINTK=y +CONFIG_HEART_BEAT=y +# CONFIG_DEBUG_BOOTMEM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y + +# +# Library routines +# +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC32 is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_HAVE_LMB=y diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild new file mode 100644 index 00000000000..31820dfef56 --- /dev/null +++ b/arch/microblaze/include/asm/Kbuild @@ -0,0 +1,26 @@ +include include/asm-generic/Kbuild.asm + +header-y += auxvec.h +header-y += errno.h +header-y += fcntl.h +header-y += ioctl.h +header-y += ioctls.h +header-y += ipcbuf.h +header-y += linkage.h +header-y += msgbuf.h +header-y += poll.h +header-y += resource.h +header-y += sembuf.h +header-y += shmbuf.h +header-y += sigcontext.h +header-y += siginfo.h +header-y += socket.h +header-y += sockios.h +header-y += statfs.h +header-y += stat.h +header-y += termbits.h +header-y += ucontext.h + +unifdef-y += cputable.h +unifdef-y += elf.h +unifdef-y += termios.h diff --git a/arch/microblaze/include/asm/atomic.h b/arch/microblaze/include/asm/atomic.h new file mode 100644 index 00000000000..a448d94ab72 --- /dev/null +++ b/arch/microblaze/include/asm/atomic.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_ATOMIC_H +#define _ASM_MICROBLAZE_ATOMIC_H + +#include <linux/types.h> +#include <linux/compiler.h> /* likely */ +#include <asm/system.h> /* local_irq_XXX and friends */ + +#define ATOMIC_INIT(i) { (i) } +#define atomic_read(v) ((v)->counter) +#define atomic_set(v, i) (((v)->counter) = (i)) + +#define atomic_inc(v) (atomic_add_return(1, (v))) +#define atomic_dec(v) (atomic_sub_return(1, (v))) + +#define atomic_add(i, v) (atomic_add_return(i, (v))) +#define atomic_sub(i, v) (atomic_sub_return(i, (v))) + +#define atomic_inc_return(v) (atomic_add_return(1, (v))) +#define atomic_dec_return(v) (atomic_sub_return(1, (v))) + +#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0) +#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) + +#define atomic_inc_not_zero(v) (atomic_add_unless((v), 1, 0)) + +#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0) + +static inline int atomic_cmpxchg(atomic_t *v, int old, int new) +{ + int ret; + unsigned long flags; + + local_irq_save(flags); + ret = v->counter; + if (likely(ret == old)) + v->counter = new; + local_irq_restore(flags); + + return ret; +} + +static inline int atomic_add_unless(atomic_t *v, int a, int u) +{ + int c, old; + + c = atomic_read(v); + while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c) + c = old; + return c != u; +} + +static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) +{ + unsigned long flags; + + local_irq_save(flags); + *addr &= ~mask; + local_irq_restore(flags); +} + +/** + * atomic_add_return - add and return + * @i: integer value to add + * @v: pointer of type atomic_t + * + * Atomically adds @i to @v and returns @i + @v + */ +static inline int atomic_add_return(int i, atomic_t *v) +{ + unsigned long flags; + int val; + + local_irq_save(flags); + val = v->counter; + v->counter = val += i; + local_irq_restore(flags); + + return val; +} + +static inline int atomic_sub_return(int i, atomic_t *v) +{ + return atomic_add_return(-i, v); +} + +/* + * Atomically test *v and decrement if it is greater than 0. + * The function returns the old value of *v minus 1. + */ +static inline int atomic_dec_if_positive(atomic_t *v) +{ + unsigned long flags; + int res; + + local_irq_save(flags); + res = v->counter - 1; + if (res >= 0) + v->counter = res; + local_irq_restore(flags); + + return res; +} + +#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) + +/* Atomic operations are already serializing */ +#define smp_mb__before_atomic_dec() barrier() +#define smp_mb__after_atomic_dec() barrier() +#define smp_mb__before_atomic_inc() barrier() +#define smp_mb__after_atomic_inc() barrier() + +#include <asm-generic/atomic.h> + +#endif /* _ASM_MICROBLAZE_ATOMIC_H */ diff --git a/arch/microblaze/include/asm/auxvec.h b/arch/microblaze/include/asm/auxvec.h new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/arch/microblaze/include/asm/auxvec.h @@ -0,0 +1 @@ + diff --git a/arch/microblaze/include/asm/bitops.h b/arch/microblaze/include/asm/bitops.h new file mode 100644 index 00000000000..d6df1fd4e1e --- /dev/null +++ b/arch/microblaze/include/asm/bitops.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_BITOPS_H +#define _ASM_MICROBLAZE_BITOPS_H + +/* + * Copyright 1992, Linus Torvalds. + */ + +#include <asm/byteorder.h> /* swab32 */ +#include <asm/system.h> /* save_flags */ + +/* + * clear_bit() doesn't provide any barrier for the compiler. + */ +#define smp_mb__before_clear_bit() barrier() +#define smp_mb__after_clear_bit() barrier() +#include <asm-generic/bitops.h> +#include <asm-generic/bitops/__fls.h> + +#endif /* _ASM_MICROBLAZE_BITOPS_H */ diff --git a/arch/microblaze/include/asm/bug.h b/arch/microblaze/include/asm/bug.h new file mode 100644 index 00000000000..8eb2cdde11d --- /dev/null +++ b/arch/microblaze/include/asm/bug.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_BUG_H +#define _ASM_MICROBLAZE_BUG_H + +#include <linux/kernel.h> +#include <asm-generic/bug.h> + +#endif /* _ASM_MICROBLAZE_BUG_H */ diff --git a/arch/microblaze/include/asm/bugs.h b/arch/microblaze/include/asm/bugs.h new file mode 100644 index 00000000000..f2c6593653f --- /dev/null +++ b/arch/microblaze/include/asm/bugs.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_BUGS_H +#define _ASM_MICROBLAZE_BUGS_H + +static inline void check_bugs(void) +{ + /* nothing to do */ +} + +#endif /* _ASM_MICROBLAZE_BUGS_H */ diff --git a/arch/microblaze/include/asm/byteorder.h b/arch/microblaze/include/asm/byteorder.h new file mode 100644 index 00000000000..ce9c58732ff --- /dev/null +++ b/arch/microblaze/include/asm/byteorder.h @@ -0,0 +1,6 @@ +#ifndef _ASM_MICROBLAZE_BYTEORDER_H +#define _ASM_MICROBLAZE_BYTEORDER_H + +#include <linux/byteorder/big_endian.h> + +#endif /* _ASM_MICROBLAZE_BYTEORDER_H */ diff --git a/arch/microblaze/include/asm/cache.h b/arch/microblaze/include/asm/cache.h new file mode 100644 index 00000000000..c4c64b43c07 --- /dev/null +++ b/arch/microblaze/include/asm/cache.h @@ -0,0 +1,45 @@ +/* + * Cache operations + * + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2003 John Williams <jwilliams@itee.uq.edu.au> + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_CACHE_H +#define _ASM_MICROBLAZE_CACHE_H + +#include <asm/registers.h> + +#define L1_CACHE_SHIFT 2 +/* word-granular cache in microblaze */ +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) + +#define SMP_CACHE_BYTES L1_CACHE_BYTES + +void _enable_icache(void); +void _disable_icache(void); +void _invalidate_icache(unsigned int addr); + +#define __enable_icache() _enable_icache() +#define __disable_icache() _disable_icache() +#define __invalidate_icache(addr) _invalidate_icache(addr) + +void _enable_dcache(void); +void _disable_dcache(void); +void _invalidate_dcache(unsigned int addr); + +#define __enable_dcache() _enable_dcache() +#define __disable_dcache() _disable_dcache() +#define __invalidate_dcache(addr) _invalidate_dcache(addr) + +/* FIXME - I don't think this is right */ +#ifdef CONFIG_XILINX_UNCACHED_SHADOW +#define UNCACHED_SHADOW_MASK (CONFIG_XILINX_ERAM_SIZE) +#endif + +#endif /* _ASM_MICROBLAZE_CACHE_H */ diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h new file mode 100644 index 00000000000..3300b785049 --- /dev/null +++ b/arch/microblaze/include/asm/cacheflush.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007 PetaLogix + * Copyright (C) 2007 John Williams <john.williams@petalogix.com> + * based on v850 version which was + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> + * + * 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. + * + */ + +#ifndef _ASM_MICROBLAZE_CACHEFLUSH_H +#define _ASM_MICROBLAZE_CACHEFLUSH_H + +/* Somebody depends on this; sigh... */ +#include <linux/mm.h> + +/* + * Cache handling functions. + * Microblaze has a write-through data cache, meaning that the data cache + * never needs to be flushed. The only flushing operations that are + * implemented are to invalidate the instruction cache. These are called + * after loading a user application into memory, we must invalidate the + * instruction cache to make sure we don't fetch old, bad code. + */ + +/* FIXME for LL-temac driver */ +#define invalidate_dcache_range(start, end) \ + __invalidate_dcache_range(start, end) + +#define flush_cache_all() __invalidate_cache_all() +#define flush_cache_mm(mm) do { } while (0) +#define flush_cache_range(vma, start, end) __invalidate_cache_all() +#define flush_cache_page(vma, vmaddr, pfn) do { } while (0) + +#define flush_dcache_range(start, end) __invalidate_dcache_range(start, end) +#define flush_dcache_page(page) do { } while (0) +#define flush_dcache_mmap_lock(mapping) do { } while (0) +#define flush_dcache_mmap_unlock(mapping) do { } while (0) + +#define flush_icache_range(start, len) __invalidate_icache_range(start, len) +#define flush_icache_page(vma, pg) do { } while (0) + +#define flush_cache_vmap(start, end) do { } while (0) +#define flush_cache_vunmap(start, end) do { } while (0) + +struct page; +struct mm_struct; +struct vm_area_struct; + +/* see arch/microblaze/kernel/cache.c */ +extern void __invalidate_icache_all(void); +extern void __invalidate_icache_range(unsigned long start, unsigned long end); +extern void __invalidate_icache_page(struct vm_area_struct *vma, + struct page *page); +extern void __invalidate_icache_user_range(struct vm_area_struct *vma, + struct page *page, + unsigned long adr, int len); +extern void __invalidate_cache_sigtramp(unsigned long addr); + +extern void __invalidate_dcache_all(void); +extern void __invalidate_dcache_range(unsigned long start, unsigned long end); +extern void __invalidate_dcache_page(struct vm_area_struct *vma, + struct page *page); +extern void __invalidate_dcache_user_range(struct vm_area_struct *vma, + struct page *page, + unsigned long adr, int len); + +extern inline void __invalidate_cache_all(void) +{ + __invalidate_icache_all(); + __invalidate_dcache_all(); +} + +#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ +do { memcpy((dst), (src), (len)); \ + flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ +} while (0) + +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ + memcpy((dst), (src), (len)) + +#endif /* _ASM_MICROBLAZE_CACHEFLUSH_H */ diff --git a/arch/microblaze/include/asm/checksum.h b/arch/microblaze/include/asm/checksum.h new file mode 100644 index 00000000000..92b30762ce5 --- /dev/null +++ b/arch/microblaze/include/asm/checksum.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2008 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_CHECKSUM_H +#define _ASM_MICROBLAZE_CHECKSUM_H + +#include <linux/in6.h> + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +static inline __wsum +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, + unsigned short proto, __wsum sum) +{ + __asm__("add %0, %0, %1\n\t" + "addc %0, %0, %2\n\t" + "addc %0, %0, %3\n\t" + "addc %0, %0, r0\n\t" + : "+&d" (sum) + : "d" (saddr), "d" (daddr), "d" (len + proto)); + + return sum; +} + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +extern __wsum csum_partial(const void *buff, int len, __wsum sum); + +/* + * the same as csum_partial, but copies from src while it + * checksums + * + * here even more important to align src and dst on a 32-bit (or even + * better 64-bit) boundary + */ +extern __wsum csum_partial_copy(const char *src, char *dst, int len, int sum); + +/* + * the same as csum_partial_copy, but copies from user space. + * + * here even more important to align src and dst on a 32-bit (or even + * better 64-bit) boundary + */ +extern __wsum csum_partial_copy_from_user(const char *src, char *dst, + int len, int sum, int *csum_err); + +#define csum_partial_copy_nocheck(src, dst, len, sum) \ + csum_partial_copy((src), (dst), (len), (sum)) + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + * + */ +extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl); + +/* + * Fold a partial checksum + */ +static inline __sum16 csum_fold(unsigned int sum) +{ + sum = (sum & 0xffff) + (sum >> 16); + sum = (sum & 0xffff) + (sum >> 16); + return ~sum; +} + +static inline __sum16 +csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, + unsigned short proto, __wsum sum) +{ + return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +extern __sum16 ip_compute_csum(const unsigned char *buff, int len); + +#endif /* _ASM_MICROBLAZE_CHECKSUM_H */ diff --git a/arch/microblaze/include/asm/clinkage.h b/arch/microblaze/include/asm/clinkage.h new file mode 100644 index 00000000000..9e218435a55 --- /dev/null +++ b/arch/microblaze/include/asm/clinkage.h @@ -0,0 +1 @@ +#include <linux/linkage.h> diff --git a/arch/microblaze/include/asm/cpuinfo.h b/arch/microblaze/include/asm/cpuinfo.h new file mode 100644 index 00000000000..52f28f6dc4e --- /dev/null +++ b/arch/microblaze/include/asm/cpuinfo.h @@ -0,0 +1,102 @@ +/* + * Generic support for queying CPU info + * + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2007 John Williams <jwilliams@itee.uq.edu.au> + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_CPUINFO_H +#define _ASM_MICROBLAZE_CPUINFO_H + +#include <asm/prom.h> + +/* CPU Version and FPGA Family code conversion table type */ +struct cpu_ver_key { + const char *s; + const unsigned k; +}; + +extern const struct cpu_ver_key cpu_ver_lookup[]; + +struct family_string_key { + const char *s; + const unsigned k; +}; + +extern const struct family_string_key family_string_lookup[]; + +struct cpuinfo { + /* Core CPU configuration */ + u32 use_instr; + u32 use_mult; + u32 use_fpu; + u32 use_exc; + u32 ver_code; + u32 mmu; + + /* CPU caches */ + u32 use_icache; + u32 icache_tagbits; + u32 icache_write; + u32 icache_line; + u32 icache_size; + unsigned long icache_base; + unsigned long icache_high; + + u32 use_dcache; + u32 dcache_tagbits; + u32 dcache_write; + u32 dcache_line; + u32 dcache_size; + unsigned long dcache_base; + unsigned long dcache_high; + + /* Bus connections */ + u32 use_dopb; + u32 use_iopb; + u32 use_dlmb; + u32 use_ilmb; + u32 num_fsl; + + /* CPU interrupt line info */ + u32 irq_edge; + u32 irq_positive; + + u32 area_optimised; + + /* HW debug support */ + u32 hw_debug; + u32 num_pc_brk; + u32 num_rd_brk; + u32 num_wr_brk; + u32 cpu_clock_freq; /* store real freq of cpu */ + u32 freq_div_hz; /* store freq/HZ */ + + /* FPGA family */ + u32 fpga_family_code; + + /* User define */ + u32 pvr_user1; + u32 pvr_user2; +}; + +extern struct cpuinfo cpuinfo; + +/* fwd declarations of the various CPUinfo populators */ +void setup_cpuinfo(void); + +void set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu); +void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu); + +static inline unsigned int fcpu(struct device_node *cpu, char *n) +{ + int *val; + return (val = (int *) of_get_property(cpu, n, NULL)) ? *val : 0; +} + +#endif /* _ASM_MICROBLAZE_CPUINFO_H */ diff --git a/arch/microblaze/include/asm/cputable.h b/arch/microblaze/include/asm/cputable.h new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/arch/microblaze/include/asm/cputable.h @@ -0,0 +1 @@ + diff --git a/arch/microblaze/include/asm/cputime.h b/arch/microblaze/include/asm/cputime.h new file mode 100644 index 00000000000..6d68ad7e0ea --- /dev/null +++ b/arch/microblaze/include/asm/cputime.h @@ -0,0 +1 @@ +#include <asm-generic/cputime.h> diff --git a/arch/microblaze/include/asm/current.h b/arch/microblaze/include/asm/current.h new file mode 100644 index 00000000000..8375ea991e2 --- /dev/null +++ b/arch/microblaze/include/asm/current.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_CURRENT_H +#define _ASM_MICROBLAZE_CURRENT_H + +# ifndef __ASSEMBLY__ +/* + * Dedicate r31 to keeping the current task pointer + */ +register struct task_struct *current asm("r31"); + +# define get_current() current +# endif /* __ASSEMBLY__ */ + +#endif /* _ASM_MICROBLAZE_CURRENT_H */ diff --git a/arch/microblaze/include/asm/delay.h b/arch/microblaze/include/asm/delay.h new file mode 100644 index 00000000000..05b7d39e439 --- /dev/null +++ b/arch/microblaze/include/asm/delay.h @@ -0,0 +1,72 @@ +/* + * include/asm-microblaze/delay.h + * + * 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) 2008 Michal Simek + * Copyright (C) 2007 John Williams + * Copyright (C) 2006 Atmark Techno, Inc. + */ + +#ifndef _ASM_MICROBLAZE_DELAY_H +#define _ASM_MICROBLAZE_DELAY_H + +extern inline void __delay(unsigned long loops) +{ + asm volatile ("# __delay \n\t" \ + "1: addi %0, %0, -1\t\n" \ + "bneid %0, 1b \t\n" \ + "nop \t\n" + : "=r" (loops) + : "0" (loops)); +} + +/* + * Note that 19 * 226 == 4294 ==~ 2^32 / 10^6, so + * loops = (4294 * usecs * loops_per_jiffy * HZ) / 2^32. + * + * The mul instruction gives us loops = (a * b) / 2^32. + * We choose a = usecs * 19 * HZ and b = loops_per_jiffy * 226 + * because this lets us support a wide range of HZ and + * loops_per_jiffy values without either a or b overflowing 2^32. + * Thus we need usecs * HZ <= (2^32 - 1) / 19 = 226050910 and + * loops_per_jiffy <= (2^32 - 1) / 226 = 19004280 + * (which corresponds to ~3800 bogomips at HZ = 100). + * -- paulus + */ +#define __MAX_UDELAY (226050910UL/HZ) /* maximum udelay argument */ +#define __MAX_NDELAY (4294967295UL/HZ) /* maximum ndelay argument */ + +extern unsigned long loops_per_jiffy; + +extern inline void __udelay(unsigned int x) +{ + + unsigned long long tmp = + (unsigned long long)x * (unsigned long long)loops_per_jiffy \ + * 226LL; + unsigned loops = tmp >> 32; + +/* + __asm__("mulxuu %0,%1,%2" : "=r" (loops) : + "r" (x), "r" (loops_per_jiffy * 226)); +*/ + __delay(loops); +} + +extern void __bad_udelay(void); /* deliberately undefined */ +extern void __bad_ndelay(void); /* deliberately undefined */ + +#define udelay(n) (__builtin_constant_p(n) ? \ + ((n) > __MAX_UDELAY ? __bad_udelay() : __udelay((n) * (19 * HZ))) : \ + __udelay((n) * (19 * HZ))) + +#define ndelay(n) (__builtin_constant_p(n) ? \ + ((n) > __MAX_NDELAY ? __bad_ndelay() : __udelay((n) * HZ)) : \ + __udelay((n) * HZ)) + +#define muldiv(a, b, c) (((a)*(b))/(c)) + +#endif /* _ASM_MICROBLAZE_DELAY_H */ diff --git a/arch/microblaze/include/asm/device.h b/arch/microblaze/include/asm/device.h new file mode 100644 index 00000000000..c042830793e --- /dev/null +++ b/arch/microblaze/include/asm/device.h @@ -0,0 +1,21 @@ +/* + * Arch specific extensions to struct device + * + * This file is subject to the terms and conditions of the GNU General Public + * License v2. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#ifndef _ASM_MICROBLAZE_DEVICE_H +#define _ASM_MICROBLAZE_DEVICE_H + +struct device_node; + +struct dev_archdata { + /* Optional pointer to an OF device node */ + struct device_node *of_node; +}; + +#endif /* _ASM_MICROBLAZE_DEVICE_H */ + + diff --git a/arch/microblaze/include/asm/div64.h b/arch/microblaze/include/asm/div64.h new file mode 100644 index 00000000000..6cd978cefb2 --- /dev/null +++ b/arch/microblaze/include/asm/div64.h @@ -0,0 +1 @@ +#include <asm-generic/div64.h> diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h new file mode 100644 index 00000000000..17336252a9b --- /dev/null +++ b/arch/microblaze/include/asm/dma-mapping.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_DMA_MAPPING_H +#define _ASM_MICROBLAZE_DMA_MAPPING_H + +#include <asm/cacheflush.h> +#include <linux/io.h> +#include <linux/bug.h> + +struct scatterlist; + +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) + +/* FIXME */ +static inline int +dma_supported(struct device *dev, u64 mask) +{ + return 1; +} + +static inline dma_addr_t +dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + BUG(); + return 0; +} + +static inline void +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline int +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) +{ + BUG(); + return 0; +} + +static inline void +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline void +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline void +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, + size_t size, enum dma_data_direction direction) +{ + BUG(); +} + +static inline void +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline void +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ + return 0; +} + +static inline void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, int flag) +{ + return NULL; /* consistent_alloc(flag, size, dma_handle); */ +} + +static inline void dma_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + BUG(); +} + +static inline dma_addr_t +dma_map_single(struct device *dev, void *ptr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + + return virt_to_bus(ptr); +} + +static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, + size_t size, + enum dma_data_direction direction) +{ + switch (direction) { + case DMA_FROM_DEVICE: + flush_dcache_range((unsigned)dma_addr, + (unsigned)dma_addr + size); + /* Fall through */ + case DMA_TO_DEVICE: + break; + default: + BUG(); + } +} + +#endif /* _ASM_MICROBLAZE_DMA_MAPPING_H */ diff --git a/arch/microblaze/include/asm/dma.h b/arch/microblaze/include/asm/dma.h new file mode 100644 index 00000000000..0967fa04fc5 --- /dev/null +++ b/arch/microblaze/include/asm/dma.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_DMA_H +#define _ASM_MICROBLAZE_DMA_H + +/* we don't have dma address limit. define it as zero to be + * unlimited. */ +#define MAX_DMA_ADDRESS (0) + +#endif /* _ASM_MICROBLAZE_DMA_H */ diff --git a/arch/microblaze/include/asm/elf.h b/arch/microblaze/include/asm/elf.h new file mode 100644 index 00000000000..81337f24134 --- /dev/null +++ b/arch/microblaze/include/asm/elf.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_ELF_H +#define _ASM_MICROBLAZE_ELF_H + +/* + * Note there is no "official" ELF designation for Microblaze. + * I've snaffled the value from the microblaze binutils source code + * /binutils/microblaze/include/elf/microblaze.h + */ +#define EM_XILINX_MICROBLAZE 0xbaab +#define ELF_ARCH EM_XILINX_MICROBLAZE + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ((x)->e_machine == EM_XILINX_MICROBLAZE) + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 + +#endif /* _ASM_MICROBLAZE_ELF_H */ diff --git a/arch/microblaze/include/asm/emergency-restart.h b/arch/microblaze/include/asm/emergency-restart.h new file mode 100644 index 00000000000..3711bd9d50b --- /dev/null +++ b/arch/microblaze/include/asm/emergency-restart.h @@ -0,0 +1 @@ +#include <asm-generic/emergency-restart.h> diff --git a/arch/microblaze/include/asm/entry.h b/arch/microblaze/include/asm/entry.h new file mode 100644 index 00000000000..7f57e42ee46 --- /dev/null +++ b/arch/microblaze/include/asm/entry.h @@ -0,0 +1,35 @@ +/* + * Definitions used by low-level trap handlers + * + * Copyright (C) 2008 Michal Simek + * Copyright (C) 2007 - 2008 PetaLogix + * Copyright (C) 2007 John Williams <john.williams@petalogix.com> + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_ENTRY_H +#define _ASM_MICROBLAZE_ENTRY_H + +#include <asm/percpu.h> +#include <asm/ptrace.h> + +/* + * These are per-cpu variables required in entry.S, among other + * places + */ + +#define PER_CPU(var) per_cpu__##var + +# ifndef __ASSEMBLY__ +DECLARE_PER_CPU(unsigned int, KSP); /* Saved kernel stack pointer */ +DECLARE_PER_CPU(unsigned int, KM); /* Kernel/user mode */ +DECLARE_PER_CPU(unsigned int, ENTRY_SP); /* Saved SP on kernel entry */ +DECLARE_PER_CPU(unsigned int, R11_SAVE); /* Temp variable for entry */ +DECLARE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */ +DECLARE_PER_CPU(unsigned int, SYSCALL_SAVE); /* Saved syscall number */ +# endif /* __ASSEMBLY__ */ + +#endif /* _ASM_MICROBLAZE_ENTRY_H */ diff --git a/arch/microblaze/include/asm/errno.h b/arch/microblaze/include/asm/errno.h new file mode 100644 index 00000000000..4c82b503d92 --- /dev/null +++ b/arch/microblaze/include/asm/errno.h @@ -0,0 +1 @@ +#include <asm-generic/errno.h> diff --git a/arch/microblaze/include/asm/exceptions.h b/arch/microblaze/include/asm/exceptions.h new file mode 100644 index 00000000000..4cdd2159f47 --- /dev/null +++ b/arch/microblaze/include/asm/exceptions.h @@ -0,0 +1,96 @@ +/* + * Preliminary support for HW exception handing for Microblaze + * + * Copyright (C) 2008 Michal Simek + * Copyright (C) 2008 PetaLogix + * Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au> + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_EXCEPTIONS_H +#define _ASM_MICROBLAZE_EXCEPTIONS_H + +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ + +/* Macros to enable and disable HW exceptions in the MSR */ +/* Define MSR enable bit for HW exceptions */ +#define HWEX_MSR_BIT (1 << 8) + +#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR +#define __enable_hw_exceptions() \ + __asm__ __volatile__ (" msrset r0, %0; \ + nop;" \ + : \ + : "i" (HWEX_MSR_BIT) \ + : "memory") + +#define __disable_hw_exceptions() \ + __asm__ __volatile__ (" msrclr r0, %0; \ + nop;" \ + : \ + : "i" (HWEX_MSR_BIT) \ + : "memory") +#else /* !CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */ +#define __enable_hw_exceptions() \ + __asm__ __volatile__ (" \ + mfs r12, rmsr; \ + nop; \ + ori r12, r12, %0; \ + mts rmsr, r12; \ + nop;" \ + : \ + : "i" (HWEX_MSR_BIT) \ + : "memory", "r12") + +#define __disable_hw_exceptions() \ + __asm__ __volatile__ (" \ + mfs r12, rmsr; \ + nop; \ + andi r12, r12, ~%0; \ + mts rmsr, r12; \ + nop;" \ + : \ + : "i" (HWEX_MSR_BIT) \ + : "memory", "r12") +#endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */ + +asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, + int fsr, int addr); + +#if defined(CONFIG_XMON) +extern void xmon(struct pt_regs *regs); +extern int xmon_bpt(struct pt_regs *regs); +extern int xmon_sstep(struct pt_regs *regs); +extern int xmon_iabr_match(struct pt_regs *regs); +extern int xmon_dabr_match(struct pt_regs *regs); +extern void (*xmon_fault_handler)(struct pt_regs *regs); + +void (*debugger)(struct pt_regs *regs) = xmon; +int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt; +int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep; +int (*debugger_iabr_match)(struct pt_regs *regs) = xmon_iabr_match; +int (*debugger_dabr_match)(struct pt_regs *regs) = xmon_dabr_match; +void (*debugger_fault_handler)(struct pt_regs *regs); +#elif defined(CONFIG_KGDB) +void (*debugger)(struct pt_regs *regs); +int (*debugger_bpt)(struct pt_regs *regs); +int (*debugger_sstep)(struct pt_regs *regs); +int (*debugger_iabr_match)(struct pt_regs *regs); +int (*debugger_dabr_match)(struct pt_regs *regs); +void (*debugger_fault_handler)(struct pt_regs *regs); +#else +#define debugger(regs) do { } while (0) +#define debugger_bpt(regs) 0 +#define debugger_sstep(regs) 0 +#define debugger_iabr_match(regs) 0 +#define debugger_dabr_match(regs) 0 +#define debugger_fault_handler ((void (*)(struct pt_regs *))0) +#endif + +#endif /*__ASSEMBLY__ */ +#endif /* __KERNEL__ */ +#endif /* _ASM_MICROBLAZE_EXCEPTIONS_H */ diff --git a/arch/microblaze/include/asm/fcntl.h b/arch/microblaze/include/asm/fcntl.h new file mode 100644 index 00000000000..46ab12db573 --- /dev/null +++ b/arch/microblaze/include/asm/fcntl.h @@ -0,0 +1 @@ +#include <asm-generic/fcntl.h> diff --git a/arch/microblaze/include/asm/flat.h b/arch/microblaze/include/asm/flat.h new file mode 100644 index 00000000000..acf0da543ef --- /dev/null +++ b/arch/microblaze/include/asm/flat.h @@ -0,0 +1,90 @@ +/* + * uClinux flat-format executables + * + * Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au> + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_FLAT_H +#define _ASM_MICROBLAZE_FLAT_H + +#include <asm/unaligned.h> + +#define flat_stack_align(sp) /* nothing needed */ +#define flat_argvp_envp_on_stack() 0 +#define flat_old_ram_flag(flags) (flags) +#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) +#define flat_set_persistent(relval, p) 0 + +/* + * Microblaze works a little differently from other arches, because + * of the MICROBLAZE_64 reloc type. Here, a 32 bit address is split + * over two instructions, an 'imm' instruction which provides the top + * 16 bits, then the instruction "proper" which provides the low 16 + * bits. + */ + +/* + * Crack open a symbol reference and extract the address to be + * relocated. rp is a potentially unaligned pointer to the + * reference + */ + +static inline unsigned long +flat_get_addr_from_rp(unsigned long *rp, unsigned long relval, + unsigned long flags, unsigned long *persistent) +{ + unsigned long addr; + (void)flags; + + /* Is it a split 64/32 reference? */ + if (relval & 0x80000000) { + /* Grab the two halves of the reference */ + unsigned long val_hi, val_lo; + + val_hi = get_unaligned(rp); + val_lo = get_unaligned(rp+1); + + /* Crack the address out */ + addr = ((val_hi & 0xffff) << 16) + (val_lo & 0xffff); + } else { + /* Get the address straight out */ + addr = get_unaligned(rp); + } + + return addr; +} + +/* + * Insert an address into the symbol reference at rp. rp is potentially + * unaligned. + */ + +static inline void +flat_put_addr_at_rp(unsigned long *rp, unsigned long addr, unsigned long relval) +{ + /* Is this a split 64/32 reloc? */ + if (relval & 0x80000000) { + /* Get the two "halves" */ + unsigned long val_hi = get_unaligned(rp); + unsigned long val_lo = get_unaligned(rp + 1); + + /* insert the address */ + val_hi = (val_hi & 0xffff0000) | addr >> 16; + val_lo = (val_lo & 0xffff0000) | (addr & 0xffff); + + /* store the two halves back into memory */ + put_unaligned(val_hi, rp); + put_unaligned(val_lo, rp+1); + } else { + /* Put it straight in, no messing around */ + put_unaligned(addr, rp); + } +} + +#define flat_get_relocate_addr(rel) (rel & 0x7fffffff) + +#endif /* _ASM_MICROBLAZE_FLAT_H */ diff --git a/arch/microblaze/include/asm/ftrace.h b/arch/microblaze/include/asm/ftrace.h new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/arch/microblaze/include/asm/ftrace.h @@ -0,0 +1 @@ + diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h new file mode 100644 index 00000000000..0b745828f42 --- /dev/null +++ b/arch/microblaze/include/asm/futex.h @@ -0,0 +1 @@ +#include <asm-generic/futex.h> diff --git a/arch/microblaze/include/asm/gpio.h b/arch/microblaze/include/asm/gpio.h new file mode 100644 index 00000000000..ea04632399d --- /dev/null +++ b/arch/microblaze/include/asm/gpio.h @@ -0,0 +1,56 @@ +/* + * Generic GPIO API implementation for PowerPC. + * + * Copyright (c) 2007-2008 MontaVista Software, Inc. + * + * Author: Anton Vorontsov <avorontsov@ru.mvista.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __ASM_POWERPC_GPIO_H +#define __ASM_POWERPC_GPIO_H + +#include <linux/errno.h> +#include <asm-generic/gpio.h> + +#ifdef CONFIG_GPIOLIB + +/* + * We don't (yet) implement inlined/rapid versions for on-chip gpios. + * Just call gpiolib. + */ +static inline int gpio_get_value(unsigned int gpio) +{ + return __gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned int gpio, int value) +{ + __gpio_set_value(gpio, value); +} + +static inline int gpio_cansleep(unsigned int gpio) +{ + return __gpio_cansleep(gpio); +} + +/* + * Not implemented, yet. + */ +static inline int gpio_to_irq(unsigned int gpio) +{ + return -ENOSYS; +} + +static inline int irq_to_gpio(unsigned int irq) +{ + return -EINVAL; +} + +#endif /* CONFIG_GPIOLIB */ + +#endif /* __ASM_POWERPC_GPIO_H */ diff --git a/arch/microblaze/include/asm/hardirq.h b/arch/microblaze/include/asm/hardirq.h new file mode 100644 index 00000000000..0f2d6b013e1 --- /dev/null +++ b/arch/microblaze/include/asm/hardirq.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_HARDIRQ_H +#define _ASM_MICROBLAZE_HARDIRQ_H + +#include <linux/cache.h> +#include <linux/irq.h> +#include <asm/irq.h> +#include <asm/current.h> +#include <linux/ptrace.h> + +/* should be defined in each interrupt controller driver */ +extern unsigned int get_irq(struct pt_regs *regs); + +typedef struct { + unsigned int __softirq_pending; +} ____cacheline_aligned irq_cpustat_t; + +void ack_bad_irq(unsigned int irq); + +#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ + +#endif /* _ASM_MICROBLAZE_HARDIRQ_H */ diff --git a/arch/microblaze/include/asm/hw_irq.h b/arch/microblaze/include/asm/hw_irq.h new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/arch/microblaze/include/asm/hw_irq.h @@ -0,0 +1 @@ + diff --git a/arch/microblaze/include/asm/io.h b/arch/microblaze/include/asm/io.h new file mode 100644 index 00000000000..8b5853ee6b5 --- /dev/null +++ b/arch/microblaze/include/asm/io.h @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_IO_H +#define _ASM_MICROBLAZE_IO_H + +#include <asm/byteorder.h> +#include <asm/page.h> +#include <linux/types.h> + +#define IO_SPACE_LIMIT (0xFFFFFFFF) + +static inline unsigned char __raw_readb(const volatile void __iomem *addr) +{ + return *(volatile unsigned char __force *)addr; +} +static inline unsigned short __raw_readw(const volatile void __iomem *addr) +{ + return *(volatile unsigned short __force *)addr; +} +static inline unsigned int __raw_readl(const volatile void __iomem *addr) +{ + return *(volatile unsigned int __force *)addr; +} +static inline unsigned long __raw_readq(const volatile void __iomem *addr) +{ + return *(volatile unsigned long __force *)addr; +} +static inline void __raw_writeb(unsigned char v, volatile void __iomem *addr) +{ + *(volatile unsigned char __force *)addr = v; +} +static inline void __raw_writew(unsigned short v, volatile void __iomem *addr) +{ + *(volatile unsigned short __force *)addr = v; +} +static inline void __raw_writel(unsigned int v, volatile void __iomem *addr) +{ + *(volatile unsigned int __force *)addr = v; +} +static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) +{ + *(volatile unsigned long __force *)addr = v; +} + +/* + * read (readb, readw, readl, readq) and write (writeb, writew, + * writel, writeq) accessors are for PCI and thus littel endian. + * Linux 2.4 for Microblaze had this wrong. + */ +static inline unsigned char readb(const volatile void __iomem *addr) +{ + return *(volatile unsigned char __force *)addr; +} +static inline unsigned short readw(const volatile void __iomem *addr) +{ + return le16_to_cpu(*(volatile unsigned short __force *)addr); +} +static inline unsigned int readl(const volatile void __iomem *addr) +{ + return le32_to_cpu(*(volatile unsigned int __force *)addr); +} +static inline void writeb(unsigned char v, volatile void __iomem *addr) +{ + *(volatile unsigned char __force *)addr = v; +} +static inline void writew(unsigned short v, volatile void __iomem *addr) +{ + *(volatile unsigned short __force *)addr = cpu_to_le16(v); +} +static inline void writel(unsigned int v, volatile void __iomem *addr) +{ + *(volatile unsigned int __force *)addr = cpu_to_le32(v); +} + +/* ioread and iowrite variants. thease are for now same as __raw_ + * variants of accessors. we might check for endianess in the feature + */ +#define ioread8(addr) __raw_readb((u8 *)(addr)) +#define ioread16(addr) __raw_readw((u16 *)(addr)) +#define ioread32(addr) __raw_readl((u32 *)(addr)) +#define iowrite8(v, addr) __raw_writeb((u8)(v), (u8 *)(addr)) +#define iowrite16(v, addr) __raw_writew((u16)(v), (u16 *)(addr)) +#define iowrite32(v, addr) __raw_writel((u32)(v), (u32 *)(addr)) + +/* These are the definitions for the x86 IO instructions + * inb/inw/inl/outb/outw/outl, the "string" versions + * insb/insw/insl/outsb/outsw/outsl, and the "pausing" versions + * inb_p/inw_p/... + * The macros don't do byte-swapping. + */ +#define inb(port) readb((u8 *)((port))) +#define outb(val, port) writeb((val), (u8 *)((unsigned long)(port))) +#define inw(port) readw((u16 *)((port))) +#define outw(val, port) writew((val), (u16 *)((unsigned long)(port))) +#define inl(port) readl((u32 *)((port))) +#define outl(val, port) writel((val), (u32 *)((unsigned long)(port))) + +#define inb_p(port) inb((port)) +#define outb_p(val, port) outb((val), (port)) +#define inw_p(port) inw((port)) +#define outw_p(val, port) outw((val), (port)) +#define inl_p(port) inl((port)) +#define outl_p(val, port) outl((val), (port)) + +#define memset_io(a, b, c) memset((void *)(a), (b), (c)) +#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c)) +#define memcpy_toio(a, b, c) memcpy((void *)(a), (b), (c)) + +/** + * virt_to_phys - map virtual addresses to physical + * @address: address to remap + * + * The returned physical address is the physical (CPU) mapping for + * the memory address given. It is only valid to use this function on + * addresses directly mapped or allocated via kmalloc. + * + * This function does not give bus mappings for DMA transfers. In + * almost all conceivable cases a device driver should not be using + * this function + */ +static inline unsigned long __iomem virt_to_phys(volatile void *address) +{ + return __pa((unsigned long)address); +} + +#define virt_to_bus virt_to_phys + +/** + * phys_to_virt - map physical address to virtual + * @address: address to remap + * + * The returned virtual address is a current CPU mapping for + * the memory address given. It is only valid to use this function on + * addresses that have a kernel mapping + * + * This function does not handle bus mappings for DMA transfers. In + * almost all conceivable cases a device driver should not be using + * this function + */ +static inline void *phys_to_virt(unsigned long address) +{ + return (void *)__va(address); +} + +#define bus_to_virt(a) phys_to_virt(a) + +static inline void __iomem *__ioremap(phys_addr_t address, unsigned long size, + unsigned long flags) +{ + return (void *)address; +} + +#define ioremap(physaddr, size) ((void __iomem *)(unsigned long)(physaddr)) +#define iounmap(addr) ((void)0) +#define ioremap_nocache(physaddr, size) ioremap(physaddr, size) + +/* + * Convert a physical pointer to a virtual kernel pointer for /dev/mem + * access + */ +#define xlate_dev_mem_ptr(p) __va(p) + +/* + * Convert a virtual cached pointer to an uncached pointer + */ +#define xlate_dev_kmem_ptr(p) p + +/* + * Big Endian + */ +#define out_be32(a, v) __raw_writel((v), (void __iomem __force *)(a)) +#define out_be16(a, v) __raw_writew((v), (a)) + +#define in_be32(a) __raw_readl((const void __iomem __force *)(a)) +#define in_be16(a) __raw_readw(a) + +/* + * Little endian + */ + +#define out_le32(a, v) __raw_writel(__cpu_to_le32(v), (a)); +#define out_le16(a, v) __raw_writew(__cpu_to_le16(v), (a)) + +#define in_le32(a) __le32_to_cpu(__raw_readl(a)) +#define in_le16(a) __le16_to_cpu(__raw_readw(a)) + +/* Byte ops */ +#define out_8(a, v) __raw_writeb((v), (a)) +#define in_8(a) __raw_readb(a) + +/* FIXME */ +static inline void __iomem *ioport_map(unsigned long port, unsigned int len) +{ + return (void __iomem *) (port); +} + +static inline void ioport_unmap(void __iomem *addr) +{ + /* Nothing to do */ +} + +#endif /* _ASM_MICROBLAZE_IO_H */ diff --git a/arch/microblaze/include/asm/ioctl.h b/arch/microblaze/include/asm/ioctl.h new file mode 100644 index 00000000000..b279fe06dfe --- /dev/null +++ b/arch/microblaze/include/asm/ioctl.h @@ -0,0 +1 @@ +#include <asm-generic/ioctl.h> diff --git a/arch/microblaze/include/asm/ioctls.h b/arch/microblaze/include/asm/ioctls.h new file mode 100644 index 00000000000..03582b24920 --- /dev/null +++ b/arch/microblaze/include/asm/ioctls.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_IOCTLS_H +#define _ASM_MICROBLAZE_IOCTLS_H + +#include <linux/ioctl.h> + +/* 0x54 is just a magic number to make these relatively unique ('T') */ + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +#define FIONBIO 0x5421 +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCGSID 0x5429 /* Return the session ID of FD */ +/* Get Pty Number (of pty-mux device) */ +#define TIOCGPTN _IOR('T', 0x30, unsigned int) +#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ + +#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ +#define FIOCLEX 0x5451 +#define FIOASYNC 0x5452 +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ + +#define FIOQSIZE 0x545E + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 + +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +#endif /* _ASM_MICROBLAZE_IOCTLS_H */ diff --git a/arch/microblaze/include/asm/ipc.h b/arch/microblaze/include/asm/ipc.h new file mode 100644 index 00000000000..a46e3d9c2a3 --- /dev/null +++ b/arch/microblaze/include/asm/ipc.h @@ -0,0 +1 @@ +#include <asm-generic/ipc.h> diff --git a/arch/microblaze/include/asm/ipcbuf.h b/arch/microblaze/include/asm/ipcbuf.h new file mode 100644 index 00000000000..b056fa42065 --- /dev/null +++ b/arch/microblaze/include/asm/ipcbuf.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_IPCBUF_H +#define _ASM_MICROBLAZE_IPCBUF_H + +/* + * The user_ipc_perm structure for microblaze architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 32-bit mode_t and seq + * - 2 miscellaneous 32-bit values + */ + +struct ipc64_perm { + __kernel_key_t key; + __kernel_uid32_t uid; + __kernel_gid32_t gid; + __kernel_uid32_t cuid; + __kernel_gid32_t cgid; + __kernel_mode_t mode; + unsigned short __pad1; + unsigned short seq; + unsigned short __pad2; + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* _ASM_MICROBLAZE_IPCBUF_H */ diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h new file mode 100644 index 00000000000..db515deaa72 --- /dev/null +++ b/arch/microblaze/include/asm/irq.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_IRQ_H +#define _ASM_MICROBLAZE_IRQ_H + +#define NR_IRQS 32 + +#include <linux/interrupt.h> + +extern unsigned int nr_irq; + +#define NO_IRQ (-1) + +static inline int irq_canonicalize(int irq) +{ + return irq; +} + +struct pt_regs; +extern void do_IRQ(struct pt_regs *regs); + +/* irq_of_parse_and_map - Parse and Map an interrupt into linux virq space + * @device: Device node of the device whose interrupt is to be mapped + * @index: Index of the interrupt to map + * + * This function is a wrapper that chains of_irq_map_one() and + * irq_create_of_mapping() to make things easier to callers + */ +struct device_node; +extern unsigned int irq_of_parse_and_map(struct device_node *dev, int index); + +/** FIXME - not implement + * irq_dispose_mapping - Unmap an interrupt + * @virq: linux virq number of the interrupt to unmap + */ +static inline void irq_dispose_mapping(unsigned int virq) +{ + return; +} + +#endif /* _ASM_MICROBLAZE_IRQ_H */ diff --git a/arch/microblaze/include/asm/irq_regs.h b/arch/microblaze/include/asm/irq_regs.h new file mode 100644 index 00000000000..3dd9c0b7027 --- /dev/null +++ b/arch/microblaze/include/asm/irq_regs.h @@ -0,0 +1 @@ +#include <asm-generic/irq_regs.h> diff --git a/arch/microblaze/include/asm/irqflags.h b/arch/microblaze/include/asm/irqflags.h new file mode 100644 index 00000000000..dea65645a4f --- /dev/null +++ b/arch/microblaze/include/asm/irqflags.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_IRQFLAGS_H +#define _ASM_MICROBLAZE_IRQFLAGS_H + +#include <linux/irqflags.h> + +# if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR + +# define local_irq_save(flags) \ + do { \ + asm volatile ("# local_irq_save \n\t" \ + "msrclr %0, %1 \n\t" \ + "nop \n\t" \ + : "=r"(flags) \ + : "i"(MSR_IE) \ + : "memory"); \ + } while (0) + +# define local_irq_disable() \ + do { \ + asm volatile ("# local_irq_disable \n\t" \ + "msrclr r0, %0 \n\t" \ + "nop \n\t" \ + : \ + : "i"(MSR_IE) \ + : "memory"); \ + } while (0) + +# define local_irq_enable() \ + do { \ + asm volatile ("# local_irq_enable \n\t" \ + "msrset r0, %0 \n\t" \ + "nop \n\t" \ + : \ + : "i"(MSR_IE) \ + : "memory"); \ + } while (0) + +# else /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR == 0 */ + +# define local_irq_save(flags) \ + do { \ + register unsigned tmp; \ + asm volatile ("# local_irq_save \n\t" \ + "mfs %0, rmsr \n\t" \ + "nop \n\t" \ + "andi %1, %0, %2 \n\t" \ + "mts rmsr, %1 \n\t" \ + "nop \n\t" \ + : "=r"(flags), "=r" (tmp) \ + : "i"(~MSR_IE) \ + : "memory"); \ + } while (0) + +# define local_irq_disable() \ + do { \ + register unsigned tmp; \ + asm volatile ("# local_irq_disable \n\t" \ + "mfs %0, rmsr \n\t" \ + "nop \n\t" \ + "andi %0, %0, %1 \n\t" \ + "mts rmsr, %0 \n\t" \ + "nop \n\t" \ + : "=r"(tmp) \ + : "i"(~MSR_IE) \ + : "memory"); \ + } while (0) + +# define local_irq_enable() \ + do { \ + register unsigned tmp; \ + asm volatile ("# local_irq_enable \n\t" \ + "mfs %0, rmsr \n\t" \ + "nop \n\t" \ + "ori %0, %0, %1 \n\t" \ + "mts rmsr, %0 \n\t" \ + "nop \n\t" \ + : "=r"(tmp) \ + : "i"(MSR_IE) \ + : "memory"); \ + } while (0) + +# endif /* CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR */ + +#define local_save_flags(flags) \ + do { \ + asm volatile ("# local_save_flags \n\t" \ + "mfs %0, rmsr \n\t" \ + "nop \n\t" \ + : "=r"(flags) \ + : \ + : "memory"); \ + } while (0) + +#define local_irq_restore(flags) \ + do { \ + asm volatile ("# local_irq_restore \n\t"\ + "mts rmsr, %0 \n\t" \ + "nop \n\t" \ + : \ + : "r"(flags) \ + : "memory"); \ + } while (0) + +static inline int irqs_disabled(void) +{ + unsigned long flags; + + local_save_flags(flags); + return ((flags & MSR_IE) == 0); +} + +#define raw_irqs_disabled irqs_disabled +#define raw_irqs_disabled_flags(flags) ((flags) == 0) + +#endif /* _ASM_MICROBLAZE_IRQFLAGS_H */ diff --git a/arch/microblaze/include/asm/kdebug.h b/arch/microblaze/include/asm/kdebug.h new file mode 100644 index 00000000000..6ece1b03766 --- /dev/null +++ b/arch/microblaze/include/asm/kdebug.h @@ -0,0 +1 @@ +#include <asm-generic/kdebug.h> diff --git a/arch/microblaze/include/asm/kmap_types.h b/arch/microblaze/include/asm/kmap_types.h new file mode 100644 index 00000000000..4d7e222f5dd --- /dev/null +++ b/arch/microblaze/include/asm/kmap_types.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_KMAP_TYPES_H +#define _ASM_MICROBLAZE_KMAP_TYPES_H + +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BIO_SRC_IRQ, + KM_BIO_DST_IRQ, + KM_PTE0, + KM_PTE1, + KM_IRQ0, + KM_IRQ1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_TYPE_NR, +}; + +#endif /* _ASM_MICROBLAZE_KMAP_TYPES_H */ diff --git a/arch/microblaze/include/asm/linkage.h b/arch/microblaze/include/asm/linkage.h new file mode 100644 index 00000000000..3a8e36d057e --- /dev/null +++ b/arch/microblaze/include/asm/linkage.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_LINKAGE_H +#define _ASM_MICROBLAZE_LINKAGE_H + +#define __ALIGN .align 4 +#define __ALIGN_STR ".align 4" + +#endif /* _ASM_MICROBLAZE_LINKAGE_H */ diff --git a/arch/microblaze/include/asm/lmb.h b/arch/microblaze/include/asm/lmb.h new file mode 100644 index 00000000000..a0a0a929c29 --- /dev/null +++ b/arch/microblaze/include/asm/lmb.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2008 Michal Simek <monstr@monstr.eu> + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_LMB_H +#define _ASM_MICROBLAZE_LMB_H + +/* LMB limit is OFF */ +#define LMB_REAL_LIMIT 0xFFFFFFFF + +#endif /* _ASM_MICROBLAZE_LMB_H */ + + diff --git a/arch/microblaze/include/asm/local.h b/arch/microblaze/include/asm/local.h new file mode 100644 index 00000000000..c11c530f74d --- /dev/null +++ b/arch/microblaze/include/asm/local.h @@ -0,0 +1 @@ +#include <asm-generic/local.h> diff --git a/arch/microblaze/include/asm/mman.h b/arch/microblaze/include/asm/mman.h new file mode 100644 index 00000000000..4914b132944 --- /dev/null +++ b/arch/microblaze/include/asm/mman.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_MMAN_H +#define _ASM_MICROBLAZE_MMAN_H + +#include <asm-generic/mman.h> + +#define MAP_GROWSDOWN 0x0100 /* stack-like segment */ +#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ +#define MAP_LOCKED 0x2000 /* pages are locked */ +#define MAP_NORESERVE 0x4000 /* don't check for reservations */ +#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ +#define MAP_NONBLOCK 0x10000 /* do not block on IO */ + +#define MCL_CURRENT 1 /* lock all current mappings */ +#define MCL_FUTURE 2 /* lock all future mappings */ + +#endif /* _ASM_MICROBLAZE_MMAN_H */ diff --git a/arch/microblaze/include/asm/mmu.h b/arch/microblaze/include/asm/mmu.h new file mode 100644 index 00000000000..0e0431d6163 --- /dev/null +++ b/arch/microblaze/include/asm/mmu.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_MMU_H +#define _ASM_MICROBLAZE_MMU_H + +#ifndef __ASSEMBLY__ +typedef struct { + struct vm_list_struct *vmlist; + unsigned long end_brk; +} mm_context_t; +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_MICROBLAZE_MMU_H */ diff --git a/arch/microblaze/include/asm/mmu_context.h b/arch/microblaze/include/asm/mmu_context.h new file mode 100644 index 00000000000..150ca01b74b --- /dev/null +++ b/arch/microblaze/include/asm/mmu_context.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H +#define _ASM_MICROBLAZE_MMU_CONTEXT_H + +# define init_new_context(tsk, mm) ({ 0; }) + +# define enter_lazy_tlb(mm, tsk) do {} while (0) +# define change_mm_context(old, ctx, _pml4) do {} while (0) +# define destroy_context(mm) do {} while (0) +# define deactivate_mm(tsk, mm) do {} while (0) +# define switch_mm(prev, next, tsk) do {} while (0) +# define activate_mm(prev, next) do {} while (0) + +#endif /* _ASM_MICROBLAZE_MMU_CONTEXT_H */ diff --git a/arch/microblaze/include/asm/module.h b/arch/microblaze/include/asm/module.h new file mode 100644 index 00000000000..914565a9031 --- /dev/null +++ b/arch/microblaze/include/asm/module.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_MODULE_H +#define _ASM_MICROBLAZE_MODULE_H + +/* Microblaze Relocations */ +#define R_MICROBLAZE_NONE 0 +#define R_MICROBLAZE_32 1 +#define R_MICROBLAZE_32_PCREL 2 +#define R_MICROBLAZE_64_PCREL 3 +#define R_MICROBLAZE_32_PCREL_LO 4 +#define R_MICROBLAZE_64 5 +#define R_MICROBLAZE_32_LO 6 +#define R_MICROBLAZE_SRO32 7 +#define R_MICROBLAZE_SRW32 8 +#define R_MICROBLAZE_64_NONE 9 +#define R_MICROBLAZE_32_SYM_OP_SYM 10 +/* Keep this the last entry. */ +#define R_MICROBLAZE_NUM 11 + +struct mod_arch_specific { + int foo; +}; + +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define Elf_Ehdr Elf32_Ehdr + +typedef struct { volatile int counter; } module_t; + +#endif /* _ASM_MICROBLAZE_MODULE_H */ diff --git a/arch/microblaze/include/asm/msgbuf.h b/arch/microblaze/include/asm/msgbuf.h new file mode 100644 index 00000000000..09dd9709721 --- /dev/null +++ b/arch/microblaze/include/asm/msgbuf.h @@ -0,0 +1,31 @@ +#ifndef _ASM_MICROBLAZE_MSGBUF_H +#define _ASM_MICROBLAZE_MSGBUF_H + +/* + * The msqid64_ds structure for microblaze architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 64-bit time_t to solve y2038 problem + * - 2 miscellaneous 32-bit values + */ + +struct msqid64_ds { + struct ipc64_perm msg_perm; + __kernel_time_t msg_stime; /* last msgsnd time */ + unsigned long __unused1; + __kernel_time_t msg_rtime; /* last msgrcv time */ + unsigned long __unused2; + __kernel_time_t msg_ctime; /* last change time */ + unsigned long __unused3; + unsigned long msg_cbytes; /* current number of bytes on queue */ + unsigned long msg_qnum; /* number of messages in queue */ + unsigned long msg_qbytes; /* max number of bytes on queue */ + __kernel_pid_t msg_lspid; /* pid of last msgsnd */ + __kernel_pid_t msg_lrpid; /* last receive pid */ + unsigned long __unused4; + unsigned long __unused5; +}; + +#endif /* _ASM_MICROBLAZE_MSGBUF_H */ diff --git a/arch/microblaze/include/asm/mutex.h b/arch/microblaze/include/asm/mutex.h new file mode 100644 index 00000000000..ff6101aa2c7 --- /dev/null +++ b/arch/microblaze/include/asm/mutex.h @@ -0,0 +1 @@ +#include <asm-generic/mutex-dec.h> diff --git a/arch/microblaze/include/asm/namei.h b/arch/microblaze/include/asm/namei.h new file mode 100644 index 00000000000..61d60b8a07d --- /dev/null +++ b/arch/microblaze/include/asm/namei.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_NAMEI_H +#define _ASM_MICROBLAZE_NAMEI_H + +#ifdef __KERNEL__ + +/* This dummy routine maybe changed to something useful + * for /usr/gnemul/ emulation stuff. + * Look at asm-sparc/namei.h for details. + */ +#define __emul_prefix() NULL + +#endif /* __KERNEL__ */ + +#endif /* _ASM_MICROBLAZE_NAMEI_H */ diff --git a/arch/microblaze/include/asm/of_device.h b/arch/microblaze/include/asm/of_device.h new file mode 100644 index 00000000000..ba917cfaefe --- /dev/null +++ b/arch/microblaze/include/asm/of_device.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu> + * + * based on PowerPC of_device.h + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_OF_DEVICE_H +#define _ASM_MICROBLAZE_OF_DEVICE_H +#ifdef __KERNEL__ + +#include <linux/device.h> +#include <linux/of.h> + +/* + * The of_device is a kind of "base class" that is a superset of + * struct device for use by devices attached to an OF node and + * probed using OF properties. + */ +struct of_device { + struct device_node *node; /* to be obsoleted */ + u64 dma_mask; /* DMA mask */ + struct device dev; /* Generic device interface */ +}; + +extern ssize_t of_device_get_modalias(struct of_device *ofdev, + char *str, ssize_t len); + +extern struct of_device *of_device_alloc(struct device_node *np, + const char *bus_id, + struct device *parent); + +extern int of_device_uevent(struct device *dev, + struct kobj_uevent_env *env); + +extern void of_device_make_bus_id(struct of_device *dev); + +/* This is just here during the transition */ +#include <linux/of_device.h> + +#endif /* __KERNEL__ */ +#endif /* _ASM_MICROBLAZE_OF_DEVICE_H */ diff --git a/arch/microblaze/include/asm/of_platform.h b/arch/microblaze/include/asm/of_platform.h new file mode 100644 index 00000000000..187c0eedaec --- /dev/null +++ b/arch/microblaze/include/asm/of_platform.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.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. + */ + +#ifndef _ASM_MICROBLAZE_OF_PLATFORM_H +#define _ASM_MICROBLAZE_OF_PLATFORM_H + +/* This is just here during the transition */ +#include <linux/of_platform.h> + +/* + * The list of OF IDs below is used for matching bus types in the + * system whose devices are to be exposed as of_platform_devices. + * + * This is the default list valid for most platforms. This file provides + * functions who can take an explicit list if necessary though + * + * The search is always performed recursively looking for children of + * the provided device_node and recursively if such a children matches + * a bus type in the list + */ + +static const struct of_device_id of_default_bus_ids[] = { + { .type = "soc", }, + { .compatible = "soc", }, + { .type = "plb5", }, + { .type = "plb4", }, + { .type = "opb", }, + { .type = "simple", }, + {}, +}; + +/* Platform drivers register/unregister */ +static inline int of_register_platform_driver(struct of_platform_driver *drv) +{ + return of_register_driver(drv, &of_platform_bus_type); +} +static inline void of_unregister_platform_driver(struct of_platform_driver *drv) +{ + of_unregister_driver(drv); +} + +/* Platform devices and busses creation */ +extern struct of_device *of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent); +/* pseudo "matches" value to not do deep probe */ +#define OF_NO_DEEP_PROBE ((struct of_device_id *)-1) + +extern int of_platform_bus_probe(struct device_node *root, + const struct of_device_id *matches, + struct device *parent); + +extern struct of_device *of_find_device_by_phandle(phandle ph); + +extern void of_instantiate_rtc(void); + +#endif /* _ASM_MICROBLAZE_OF_PLATFORM_H */ diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h new file mode 100644 index 00000000000..7238dcfcc51 --- /dev/null +++ b/arch/microblaze/include/asm/page.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2008 Michal Simek + * Copyright (C) 2008 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * Changes for MMU support: + * Copyright (C) 2007 Xilinx, Inc. All rights reserved. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_PAGE_H +#define _ASM_MICROBLAZE_PAGE_H + +#include <linux/pfn.h> +#include <asm/setup.h> + +/* PAGE_SHIFT determines the page size */ +#define PAGE_SHIFT (12) +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +#define PAGE_UP(addr) (((addr)+((PAGE_SIZE)-1))&(~((PAGE_SIZE)-1))) +#define PAGE_DOWN(addr) ((addr)&(~((PAGE_SIZE)-1))) + +/* align addr on a size boundary - adjust address up/down if needed */ +#define _ALIGN_UP(addr, size) (((addr)+((size)-1))&(~((size)-1))) +#define _ALIGN_DOWN(addr, size) ((addr)&(~((size)-1))) + +/* align addr on a size boundary - adjust address up if needed */ +#define _ALIGN(addr, size) _ALIGN_UP(addr, size) + +/* + * PAGE_OFFSET -- the first address of the first page of memory. When not + * using MMU this corresponds to the first free page in physical memory (aligned + * on a page boundary). + */ +extern unsigned int __page_offset; +#define PAGE_OFFSET __page_offset + +#define copy_page(to, from) memcpy((to), (from), PAGE_SIZE) +#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) +#define free_user_page(page, addr) free_page(addr) + +#define clear_page(pgaddr) memset((pgaddr), 0, PAGE_SIZE) + + +#define clear_user_page(pgaddr, vaddr, page) memset((pgaddr), 0, PAGE_SIZE) +#define copy_user_page(vto, vfrom, vaddr, topg) \ + memcpy((vto), (vfrom), PAGE_SIZE) + +/* + * These are used to make use of C type-checking.. + */ +typedef struct page *pgtable_t; +typedef struct { unsigned long pte; } pte_t; +typedef struct { unsigned long pgprot; } pgprot_t; +typedef struct { unsigned long ste[64]; } pmd_t; +typedef struct { pmd_t pue[1]; } pud_t; +typedef struct { pud_t pge[1]; } pgd_t; + + +#define pte_val(x) ((x).pte) +#define pgprot_val(x) ((x).pgprot) +#define pmd_val(x) ((x).ste[0]) +#define pud_val(x) ((x).pue[0]) +#define pgd_val(x) ((x).pge[0]) + +#define __pte(x) ((pte_t) { (x) }) +#define __pmd(x) ((pmd_t) { (x) }) +#define __pgd(x) ((pgd_t) { (x) }) +#define __pgprot(x) ((pgprot_t) { (x) }) + +/** + * Conversions for virtual address, physical address, pfn, and struct + * page are defined in the following files. + * + * virt -+ + * | asm-microblaze/page.h + * phys -+ + * | linux/pfn.h + * pfn -+ + * | asm-generic/memory_model.h + * page -+ + * + */ + +extern unsigned long max_low_pfn; +extern unsigned long min_low_pfn; +extern unsigned long max_pfn; + +#define __pa(vaddr) ((unsigned long) (vaddr)) +#define __va(paddr) ((void *) (paddr)) + +#define phys_to_pfn(phys) (PFN_DOWN(phys)) +#define pfn_to_phys(pfn) (PFN_PHYS(pfn)) + +#define virt_to_pfn(vaddr) (phys_to_pfn((__pa(vaddr)))) +#define pfn_to_virt(pfn) __va(pfn_to_phys((pfn))) + +#define virt_to_page(vaddr) (pfn_to_page(virt_to_pfn(vaddr))) +#define page_to_virt(page) (pfn_to_virt(page_to_pfn(page))) + +#define page_to_phys(page) (pfn_to_phys(page_to_pfn(page))) +#define page_to_bus(page) (page_to_phys(page)) +#define phys_to_page(paddr) (pfn_to_page(phys_to_pfn(paddr))) + +extern unsigned int memory_start; +extern unsigned int memory_end; +extern unsigned int memory_size; + +#define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) < max_mapnr) + +#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) + +#else +#define tophys(rd, rs) (addik rd, rs, 0) +#define tovirt(rd, rs) (addik rd, rs, 0) +#endif /* __ASSEMBLY__ */ + +#define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr))) + +/* Convert between virtual and physical address for MMU. */ +/* Handle MicroBlaze processor with virtual memory. */ +#define __virt_to_phys(addr) addr +#define __phys_to_virt(addr) addr + +#define TOPHYS(addr) __virt_to_phys(addr) + +#endif /* __KERNEL__ */ + +#include <asm-generic/memory_model.h> +#include <asm-generic/page.h> + +#endif /* _ASM_MICROBLAZE_PAGE_H */ diff --git a/arch/microblaze/include/asm/param.h b/arch/microblaze/include/asm/param.h new file mode 100644 index 00000000000..8c538a49616 --- /dev/null +++ b/arch/microblaze/include/asm/param.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_PARAM_H +#define _ASM_MICROBLAZE_PARAM_H + +#ifdef __KERNEL__ +#define HZ CONFIG_HZ /* internal kernel timer frequency */ +#define USER_HZ 100 /* for user interfaces in "ticks" */ +#define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ +#endif /* __KERNEL__ */ + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 4096 + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif /* _ASM_MICROBLAZE_PARAM_H */ diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h new file mode 100644 index 00000000000..7ad28f6f5f1 --- /dev/null +++ b/arch/microblaze/include/asm/pci-bridge.h @@ -0,0 +1 @@ +#include <linux/pci.h> diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h new file mode 100644 index 00000000000..ca03794cf3f --- /dev/null +++ b/arch/microblaze/include/asm/pci.h @@ -0,0 +1 @@ +#include <linux/io.h> diff --git a/arch/microblaze/include/asm/percpu.h b/arch/microblaze/include/asm/percpu.h new file mode 100644 index 00000000000..06a959d6723 --- /dev/null +++ b/arch/microblaze/include/asm/percpu.h @@ -0,0 +1 @@ +#include <asm-generic/percpu.h> diff --git a/arch/microblaze/include/asm/pgalloc.h b/arch/microblaze/include/asm/pgalloc.h new file mode 100644 index 00000000000..2a4b3548401 --- /dev/null +++ b/arch/microblaze/include/asm/pgalloc.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_PGALLOC_H +#define _ASM_MICROBLAZE_PGALLOC_H + +#define check_pgt_cache() do {} while (0) + +#endif /* _ASM_MICROBLAZE_PGALLOC_H */ diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h new file mode 100644 index 00000000000..4df31e46568 --- /dev/null +++ b/arch/microblaze/include/asm/pgtable.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_PGTABLE_H +#define _ASM_MICROBLAZE_PGTABLE_H + +#include <asm/setup.h> + +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ + remap_pfn_range(vma, vaddr, pfn, size, prot) + +#define pgd_present(pgd) (1) /* pages are always present on non MMU */ +#define pgd_none(pgd) (0) +#define pgd_bad(pgd) (0) +#define pgd_clear(pgdp) +#define kern_addr_valid(addr) (1) +#define pmd_offset(a, b) ((void *) 0) + +#define PAGE_NONE __pgprot(0) /* these mean nothing to non MMU */ +#define PAGE_SHARED __pgprot(0) /* these mean nothing to non MMU */ +#define PAGE_COPY __pgprot(0) /* these mean nothing to non MMU */ +#define PAGE_READONLY __pgprot(0) /* these mean nothing to non MMU */ +#define PAGE_KERNEL __pgprot(0) /* these mean nothing to non MMU */ + +#define __swp_type(x) (0) +#define __swp_offset(x) (0) +#define __swp_entry(typ, off) ((swp_entry_t) { ((typ) | ((off) << 7)) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) + +#ifndef __ASSEMBLY__ +static inline int pte_file(pte_t pte) { return 0; } +#endif /* __ASSEMBLY__ */ + +#define ZERO_PAGE(vaddr) ({ BUG(); NULL; }) + +#define swapper_pg_dir ((pgd_t *) NULL) + +#define pgtable_cache_init() do {} while (0) + +#define arch_enter_lazy_cpu_mode() do {} while (0) + +#ifndef __ASSEMBLY__ +#include <asm-generic/pgtable.h> + +void setup_memory(void); +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_MICROBLAZE_PGTABLE_H */ diff --git a/arch/microblaze/include/asm/poll.h b/arch/microblaze/include/asm/poll.h new file mode 100644 index 00000000000..c98509d3149 --- /dev/null +++ b/arch/microblaze/include/asm/poll.h @@ -0,0 +1 @@ +#include <asm-generic/poll.h> diff --git a/arch/microblaze/include/asm/posix_types.h b/arch/microblaze/include/asm/posix_types.h new file mode 100644 index 00000000000..b4df41c5dde --- /dev/null +++ b/arch/microblaze/include/asm/posix_types.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_POSIX_TYPES_H +#define _ASM_MICROBLAZE_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef int __kernel_daddr_t; +typedef char *__kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned int __kernel_old_uid_t; +typedef unsigned int __kernel_old_gid_t; +typedef unsigned int __kernel_old_dev_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#if defined(__KERNEL__) || defined(__USE_ALL) + int val[2]; +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ + int __val[2]; +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ +} __kernel_fsid_t; + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) + +#undef __FD_SET +#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) + +#undef __FD_CLR +#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d)) + +#undef __FD_ISSET +#define __FD_ISSET(d, set) (!!((set)->fds_bits[__FDELT(d)] & __FDMASK(d))) + +#undef __FD_ZERO +#define __FD_ZERO(fdsetp) (memset(fdsetp, 0, sizeof(*(fd_set *)fdsetp))) + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ + +#endif /* _ASM_MICROBLAZE_POSIX_TYPES_H */ diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h new file mode 100644 index 00000000000..d8e15434ba2 --- /dev/null +++ b/arch/microblaze/include/asm/processor.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2008 Michal Simek + * Copyright (C) 2008 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_PROCESSOR_H +#define _ASM_MICROBLAZE_PROCESSOR_H + +#include <asm/ptrace.h> +#include <asm/setup.h> +#include <asm/registers.h> +#include <asm/segment.h> + +# ifndef __ASSEMBLY__ +/* from kernel/cpu/mb.c */ +extern const struct seq_operations cpuinfo_op; + +# define cpu_relax() barrier() +# define cpu_sleep() do {} while (0) +# define prepare_to_copy(tsk) do {} while (0) + +# endif /* __ASSEMBLY__ */ + +/* + * User space process size: memory size + * + * TASK_SIZE on MMU cpu is usually 1GB. However, on no-MMU arch, both + * user processes and the kernel is on the same memory region. They + * both share the memory space and that is limited by the amount of + * physical memory. thus, we set TASK_SIZE == amount of total memory. + */ +# define TASK_SIZE (0x81000000 - 0x80000000) + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +# define current_text_addr() ({ __label__ _l; _l: &&_l; }) + +/* + * This decides where the kernel will search for a free chunk of vm + * space during mmap's. We won't be using it + */ +# define TASK_UNMAPPED_BASE 0 + +/* definition in include/linux/sched.h */ +struct task_struct; + +/* thread_struct is gone. use thread_info instead. */ +struct thread_struct { }; +# define INIT_THREAD { } + +/* Do necessary setup to start up a newly executed thread. */ +static inline void start_thread(struct pt_regs *regs, + unsigned long pc, + unsigned long usp) +{ + regs->pc = pc; + regs->r1 = usp; + regs->kernel_mode = 0; +} + +/* Free all resources held by a thread. */ +static inline void release_thread(struct task_struct *dead_task) +{ +} + +/* Free all resources held by a thread. */ +static inline void exit_thread(void) +{ +} + +extern unsigned long thread_saved_pc(struct task_struct *t); + +extern unsigned long get_wchan(struct task_struct *p); + +/* + * create a kernel thread without removing it from tasklists + */ +extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); + +# define task_pt_regs(tsk) \ + (((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1) + +# define KSTK_EIP(tsk) (0) +# define KSTK_ESP(tsk) (0) + +#endif /* _ASM_MICROBLAZE_PROCESSOR_H */ diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h new file mode 100644 index 00000000000..20f7b3a926e --- /dev/null +++ b/arch/microblaze/include/asm/prom.h @@ -0,0 +1,313 @@ +/* + * Definitions for talking to the Open Firmware PROM on + * Power Macintosh computers. + * + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_PROM_H +#define _ASM_MICROBLAZE_PROM_H +#ifdef __KERNEL__ + +#include <linux/types.h> +#include <linux/proc_fs.h> +#include <linux/platform_device.h> +#include <asm/irq.h> +#include <asm/atomic.h> + +#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 1 +#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 + +#define of_compat_cmp(s1, s2, l) strncasecmp((s1), (s2), (l)) +#define of_prop_cmp(s1, s2) strcmp((s1), (s2)) +#define of_node_cmp(s1, s2) strcasecmp((s1), (s2)) + +/* Definitions used by the flattened device tree */ +#define OF_DT_HEADER 0xd00dfeed /* marker */ +#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */ +#define OF_DT_END_NODE 0x2 /* End node */ +#define OF_DT_PROP 0x3 /* Property: name off, size, content */ +#define OF_DT_NOP 0x4 /* nop */ +#define OF_DT_END 0x9 + +#define OF_DT_VERSION 0x10 + +/* + * This is what gets passed to the kernel by prom_init or kexec + * + * The dt struct contains the device tree structure, full pathes and + * property contents. The dt strings contain a separate block with just + * the strings for the property names, and is fully page aligned and + * self contained in a page, so that it can be kept around by the kernel, + * each property name appears only once in this page (cheap compression) + * + * the mem_rsvmap contains a map of reserved ranges of physical memory, + * passing it here instead of in the device-tree itself greatly simplifies + * the job of everybody. It's just a list of u64 pairs (base/size) that + * ends when size is 0 + */ +struct boot_param_header { + u32 magic; /* magic word OF_DT_HEADER */ + u32 totalsize; /* total size of DT block */ + u32 off_dt_struct; /* offset to structure */ + u32 off_dt_strings; /* offset to strings */ + u32 off_mem_rsvmap; /* offset to memory reserve map */ + u32 version; /* format version */ + u32 last_comp_version; /* last compatible version */ + /* version 2 fields below */ + u32 boot_cpuid_phys; /* Physical CPU id we're booting on */ + /* version 3 fields below */ + u32 dt_strings_size; /* size of the DT strings block */ + /* version 17 fields below */ + u32 dt_struct_size; /* size of the DT structure block */ +}; + +typedef u32 phandle; +typedef u32 ihandle; + +struct property { + char *name; + int length; + void *value; + struct property *next; +}; + +struct device_node { + const char *name; + const char *type; + phandle node; + phandle linux_phandle; + char *full_name; + + struct property *properties; + struct property *deadprops; /* removed properties */ + struct device_node *parent; + struct device_node *child; + struct device_node *sibling; + struct device_node *next; /* next device of same type */ + struct device_node *allnext; /* next in list of all nodes */ + struct proc_dir_entry *pde; /* this node's proc directory */ + struct kref kref; + unsigned long _flags; + void *data; +}; + +extern struct device_node *of_chosen; + +static inline int of_node_check_flag(struct device_node *n, unsigned long flag) +{ + return test_bit(flag, &n->_flags); +} + +static inline void of_node_set_flag(struct device_node *n, unsigned long flag) +{ + set_bit(flag, &n->_flags); +} + +#define HAVE_ARCH_DEVTREE_FIXUPS + +static inline void set_node_proc_entry(struct device_node *dn, + struct proc_dir_entry *de) +{ + dn->pde = de; +} + +extern struct device_node *allnodes; /* temporary while merging */ +extern rwlock_t devtree_lock; /* temporary while merging */ + +extern struct device_node *of_find_all_nodes(struct device_node *prev); +extern struct device_node *of_node_get(struct device_node *node); +extern void of_node_put(struct device_node *node); + +/* For scanning the flat device-tree at boot time */ +extern int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data); +extern void *__init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size); +extern int __init + of_flat_dt_is_compatible(unsigned long node, const char *name); +extern unsigned long __init of_get_flat_dt_root(void); + +/* For updating the device tree at runtime */ +extern void of_attach_node(struct device_node *); +extern void of_detach_node(struct device_node *); + +/* Other Prototypes */ +extern void finish_device_tree(void); +extern void unflatten_device_tree(void); +extern int early_uartlite_console(void); +extern void early_init_devtree(void *); +extern int machine_is_compatible(const char *compat); +extern void print_properties(struct device_node *node); +extern int prom_n_intr_cells(struct device_node *np); +extern void prom_get_irq_senses(unsigned char *senses, int off, int max); +extern int prom_add_property(struct device_node *np, struct property *prop); +extern int prom_remove_property(struct device_node *np, struct property *prop); +extern int prom_update_property(struct device_node *np, + struct property *newprop, + struct property *oldprop); + +extern struct resource *request_OF_resource(struct device_node *node, + int index, const char *name_postfix); +extern int release_OF_resource(struct device_node *node, int index); + +/* + * OF address retreival & translation + */ + +/* Helper to read a big number; size is in cells (not bytes) */ +static inline u64 of_read_number(const u32 *cell, int size) +{ + u64 r = 0; + while (size--) + r = (r << 32) | *(cell++); + return r; +} + +/* Like of_read_number, but we want an unsigned long result */ +#define of_read_ulong(cell, size) of_read_number(cell, size) + +/* Translate an OF address block into a CPU physical address + */ +extern u64 of_translate_address(struct device_node *np, const u32 *addr); + +/* Extract an address from a device, returns the region size and + * the address space flags too. The PCI version uses a BAR number + * instead of an absolute index + */ +extern const u32 *of_get_address(struct device_node *dev, int index, + u64 *size, unsigned int *flags); +extern const u32 *of_get_pci_address(struct device_node *dev, int bar_no, + u64 *size, unsigned int *flags); + +/* Get an address as a resource. Note that if your address is + * a PIO address, the conversion will fail if the physical address + * can't be internally converted to an IO token with + * pci_address_to_pio(), that is because it's either called to early + * or it can't be matched to any host bridge IO space + */ +extern int of_address_to_resource(struct device_node *dev, int index, + struct resource *r); +extern int of_pci_address_to_resource(struct device_node *dev, int bar, + struct resource *r); + +/* Parse the ibm,dma-window property of an OF node into the busno, phys and + * size parameters. + */ +void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, + unsigned long *busno, unsigned long *phys, unsigned long *size); + +extern void kdump_move_device_tree(void); + +/* CPU OF node matching */ +struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); + +/* Get the MAC address */ +extern const void *of_get_mac_address(struct device_node *np); + +/* + * OF interrupt mapping + */ + +/* This structure is returned when an interrupt is mapped. The controller + * field needs to be put() after use + */ + +#define OF_MAX_IRQ_SPEC 4 /* We handle specifiers of at most 4 cells */ + +struct of_irq { + struct device_node *controller; /* Interrupt controller node */ + u32 size; /* Specifier size */ + u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */ +}; + +/** + * of_irq_map_init - Initialize the irq remapper + * @flags: flags defining workarounds to enable + * + * Some machines have bugs in the device-tree which require certain workarounds + * to be applied. Call this before any interrupt mapping attempts to enable + * those workarounds. + */ +#define OF_IMAP_OLDWORLD_MAC 0x00000001 +#define OF_IMAP_NO_PHANDLE 0x00000002 + +extern void of_irq_map_init(unsigned int flags); + +/** + * of_irq_map_raw - Low level interrupt tree parsing + * @parent: the device interrupt parent + * @intspec: interrupt specifier ("interrupts" property of the device) + * @ointsize: size of the passed in interrupt specifier + * @addr: address specifier (start of "reg" property of the device) + * @out_irq: structure of_irq filled by this function + * + * Returns 0 on success and a negative number on error + * + * This function is a low-level interrupt tree walking function. It + * can be used to do a partial walk with synthetized reg and interrupts + * properties, for example when resolving PCI interrupts when no device + * node exist for the parent. + * + */ + +extern int of_irq_map_raw(struct device_node *parent, const u32 *intspec, + u32 ointsize, const u32 *addr, + struct of_irq *out_irq); + +/** + * of_irq_map_one - Resolve an interrupt for a device + * @device: the device whose interrupt is to be resolved + * @index: index of the interrupt to resolve + * @out_irq: structure of_irq filled by this function + * + * This function resolves an interrupt, walking the tree, for a given + * device-tree node. It's the high level pendant to of_irq_map_raw(). + * It also implements the workarounds for OldWolrd Macs. + */ +extern int of_irq_map_one(struct device_node *device, int index, + struct of_irq *out_irq); + +/** + * of_irq_map_pci - Resolve the interrupt for a PCI device + * @pdev: the device whose interrupt is to be resolved + * @out_irq: structure of_irq filled by this function + * + * This function resolves the PCI interrupt for a given PCI device. If a + * device-node exists for a given pci_dev, it will use normal OF tree + * walking. If not, it will implement standard swizzling and walk up the + * PCI tree until an device-node is found, at which point it will finish + * resolving using the OF tree walking. + */ +struct pci_dev; +extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); + +extern int of_irq_to_resource(struct device_node *dev, int index, + struct resource *r); + +/** + * of_iomap - Maps the memory mapped IO for a given device_node + * @device: the device whose io range will be mapped + * @index: index of the io range + * + * Returns a pointer to the mapped memory + */ +extern void __iomem *of_iomap(struct device_node *device, int index); + +/* + * NB: This is here while we transition from using asm/prom.h + * to linux/of.h + */ +#include <linux/of.h> + +#endif /* __KERNEL__ */ +#endif /* _ASM_MICROBLAZE_PROM_H */ diff --git a/arch/microblaze/include/asm/ptrace.h b/arch/microblaze/include/asm/ptrace.h new file mode 100644 index 00000000000..f1f03486428 --- /dev/null +++ b/arch/microblaze/include/asm/ptrace.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_PTRACE_H +#define _ASM_MICROBLAZE_PTRACE_H + +#ifndef __ASSEMBLY__ +#include <linux/types.h> + +typedef unsigned long microblaze_reg_t; + +struct pt_regs { + microblaze_reg_t r0; + microblaze_reg_t r1; + microblaze_reg_t r2; + microblaze_reg_t r3; + microblaze_reg_t r4; + microblaze_reg_t r5; + microblaze_reg_t r6; + microblaze_reg_t r7; + microblaze_reg_t r8; + microblaze_reg_t r9; + microblaze_reg_t r10; + microblaze_reg_t r11; + microblaze_reg_t r12; + microblaze_reg_t r13; + microblaze_reg_t r14; + microblaze_reg_t r15; + microblaze_reg_t r16; + microblaze_reg_t r17; + microblaze_reg_t r18; + microblaze_reg_t r19; + microblaze_reg_t r20; + microblaze_reg_t r21; + microblaze_reg_t r22; + microblaze_reg_t r23; + microblaze_reg_t r24; + microblaze_reg_t r25; + microblaze_reg_t r26; + microblaze_reg_t r27; + microblaze_reg_t r28; + microblaze_reg_t r29; + microblaze_reg_t r30; + microblaze_reg_t r31; + microblaze_reg_t pc; + microblaze_reg_t msr; + microblaze_reg_t ear; + microblaze_reg_t esr; + microblaze_reg_t fsr; + int kernel_mode; +}; + +#define kernel_mode(regs) ((regs)->kernel_mode) +#define user_mode(regs) (!kernel_mode(regs)) + +#define instruction_pointer(regs) ((regs)->pc) +#define profile_pc(regs) instruction_pointer(regs) + +void show_regs(struct pt_regs *); + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_MICROBLAZE_PTRACE_H */ diff --git a/arch/microblaze/include/asm/pvr.h b/arch/microblaze/include/asm/pvr.h new file mode 100644 index 00000000000..66f1b30dd09 --- /dev/null +++ b/arch/microblaze/include/asm/pvr.h @@ -0,0 +1,209 @@ +/* + * Support for the MicroBlaze PVR (Processor Version Register) + * + * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007 John Williams <john.williams@petalogix.com> + * Copyright (C) 2007 - 2009 PetaLogix + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_PVR_H +#define _ASM_MICROBLAZE_PVR_H + +#define PVR_MSR_BIT 0x400 + +struct pvr_s { + unsigned pvr[16]; +}; + +/* The following taken from Xilinx's standalone BSP pvr.h */ + +/* Basic PVR mask */ +#define PVR0_PVR_FULL_MASK 0x80000000 +#define PVR0_USE_BARREL_MASK 0x40000000 +#define PVR0_USE_DIV_MASK 0x20000000 +#define PVR0_USE_HW_MUL_MASK 0x10000000 +#define PVR0_USE_FPU_MASK 0x08000000 +#define PVR0_USE_EXC_MASK 0x04000000 +#define PVR0_USE_ICACHE_MASK 0x02000000 +#define PVR0_USE_DCACHE_MASK 0x01000000 +#define PVR0_USE_MMU 0x00800000 /* new */ +#define PVR0_VERSION_MASK 0x0000FF00 +#define PVR0_USER1_MASK 0x000000FF + +/* User 2 PVR mask */ +#define PVR1_USER2_MASK 0xFFFFFFFF + +/* Configuration PVR masks */ +#define PVR2_D_OPB_MASK 0x80000000 +#define PVR2_D_LMB_MASK 0x40000000 +#define PVR2_I_OPB_MASK 0x20000000 +#define PVR2_I_LMB_MASK 0x10000000 +#define PVR2_INTERRUPT_IS_EDGE_MASK 0x08000000 +#define PVR2_EDGE_IS_POSITIVE_MASK 0x04000000 +#define PVR2_D_PLB_MASK 0x02000000 /* new */ +#define PVR2_I_PLB_MASK 0x01000000 /* new */ +#define PVR2_INTERCONNECT 0x00800000 /* new */ +#define PVR2_USE_EXTEND_FSL 0x00080000 /* new */ +#define PVR2_USE_FSL_EXC 0x00040000 /* new */ +#define PVR2_USE_MSR_INSTR 0x00020000 +#define PVR2_USE_PCMP_INSTR 0x00010000 +#define PVR2_AREA_OPTIMISED 0x00008000 +#define PVR2_USE_BARREL_MASK 0x00004000 +#define PVR2_USE_DIV_MASK 0x00002000 +#define PVR2_USE_HW_MUL_MASK 0x00001000 +#define PVR2_USE_FPU_MASK 0x00000800 +#define PVR2_USE_MUL64_MASK 0x00000400 +#define PVR2_USE_FPU2_MASK 0x00000200 /* new */ +#define PVR2_USE_IPLBEXC 0x00000100 +#define PVR2_USE_DPLBEXC 0x00000080 +#define PVR2_OPCODE_0x0_ILL_MASK 0x00000040 +#define PVR2_UNALIGNED_EXC_MASK 0x00000020 +#define PVR2_ILL_OPCODE_EXC_MASK 0x00000010 +#define PVR2_IOPB_BUS_EXC_MASK 0x00000008 +#define PVR2_DOPB_BUS_EXC_MASK 0x00000004 +#define PVR2_DIV_ZERO_EXC_MASK 0x00000002 +#define PVR2_FPU_EXC_MASK 0x00000001 + +/* Debug and exception PVR masks */ +#define PVR3_DEBUG_ENABLED_MASK 0x80000000 +#define PVR3_NUMBER_OF_PC_BRK_MASK 0x1E000000 +#define PVR3_NUMBER_OF_RD_ADDR_BRK_MASK 0x00380000 +#define PVR3_NUMBER_OF_WR_ADDR_BRK_MASK 0x0000E000 +#define PVR3_FSL_LINKS_MASK 0x00000380 + +/* ICache config PVR masks */ +#define PVR4_USE_ICACHE_MASK 0x80000000 +#define PVR4_ICACHE_ADDR_TAG_BITS_MASK 0x7C000000 +#define PVR4_ICACHE_USE_FSL_MASK 0x02000000 +#define PVR4_ICACHE_ALLOW_WR_MASK 0x01000000 +#define PVR4_ICACHE_LINE_LEN_MASK 0x00E00000 +#define PVR4_ICACHE_BYTE_SIZE_MASK 0x001F0000 + +/* DCache config PVR masks */ +#define PVR5_USE_DCACHE_MASK 0x80000000 +#define PVR5_DCACHE_ADDR_TAG_BITS_MASK 0x7C000000 +#define PVR5_DCACHE_USE_FSL_MASK 0x02000000 +#define PVR5_DCACHE_ALLOW_WR_MASK 0x01000000 +#define PVR5_DCACHE_LINE_LEN_MASK 0x00E00000 +#define PVR5_DCACHE_BYTE_SIZE_MASK 0x001F0000 + +/* ICache base address PVR mask */ +#define PVR6_ICACHE_BASEADDR_MASK 0xFFFFFFFF + +/* ICache high address PVR mask */ +#define PVR7_ICACHE_HIGHADDR_MASK 0xFFFFFFFF + +/* DCache base address PVR mask */ +#define PVR8_DCACHE_BASEADDR_MASK 0xFFFFFFFF + +/* DCache high address PVR mask */ +#define PVR9_DCACHE_HIGHADDR_MASK 0xFFFFFFFF + +/* Target family PVR mask */ +#define PVR10_TARGET_FAMILY_MASK 0xFF000000 + +/* MMU descrtiption */ +#define PVR11_USE_MMU 0xC0000000 +#define PVR11_MMU_ITLB_SIZE 0x38000000 +#define PVR11_MMU_DTLB_SIZE 0x07000000 +#define PVR11_MMU_TLB_ACCESS 0x00C00000 +#define PVR11_MMU_ZONES 0x003C0000 +/* MSR Reset value PVR mask */ +#define PVR11_MSR_RESET_VALUE_MASK 0x000007FF + + +/* PVR access macros */ +#define PVR_IS_FULL(pvr) (pvr.pvr[0] & PVR0_PVR_FULL_MASK) +#define PVR_USE_BARREL(pvr) (pvr.pvr[0] & PVR0_USE_BARREL_MASK) +#define PVR_USE_DIV(pvr) (pvr.pvr[0] & PVR0_USE_DIV_MASK) +#define PVR_USE_HW_MUL(pvr) (pvr.pvr[0] & PVR0_USE_HW_MUL_MASK) +#define PVR_USE_FPU(pvr) (pvr.pvr[0] & PVR0_USE_FPU_MASK) +#define PVR_USE_FPU2(pvr) (pvr.pvr[2] & PVR2_USE_FPU2_MASK) +#define PVR_USE_ICACHE(pvr) (pvr.pvr[0] & PVR0_USE_ICACHE_MASK) +#define PVR_USE_DCACHE(pvr) (pvr.pvr[0] & PVR0_USE_DCACHE_MASK) +#define PVR_VERSION(pvr) ((pvr.pvr[0] & PVR0_VERSION_MASK) >> 8) +#define PVR_USER1(pvr) (pvr.pvr[0] & PVR0_USER1_MASK) +#define PVR_USER2(pvr) (pvr.pvr[1] & PVR1_USER2_MASK) + +#define PVR_D_OPB(pvr) (pvr.pvr[2] & PVR2_D_OPB_MASK) +#define PVR_D_LMB(pvr) (pvr.pvr[2] & PVR2_D_LMB_MASK) +#define PVR_I_OPB(pvr) (pvr.pvr[2] & PVR2_I_OPB_MASK) +#define PVR_I_LMB(pvr) (pvr.pvr[2] & PVR2_I_LMB_MASK) +#define PVR_INTERRUPT_IS_EDGE(pvr) \ + (pvr.pvr[2] & PVR2_INTERRUPT_IS_EDGE_MASK) +#define PVR_EDGE_IS_POSITIVE(pvr) \ + (pvr.pvr[2] & PVR2_EDGE_IS_POSITIVE_MASK) +#define PVR_USE_MSR_INSTR(pvr) (pvr.pvr[2] & PVR2_USE_MSR_INSTR) +#define PVR_USE_PCMP_INSTR(pvr) (pvr.pvr[2] & PVR2_USE_PCMP_INSTR) +#define PVR_AREA_OPTIMISED(pvr) (pvr.pvr[2] & PVR2_AREA_OPTIMISED) +#define PVR_USE_MUL64(pvr) (pvr.pvr[2] & PVR2_USE_MUL64_MASK) +#define PVR_OPCODE_0x0_ILLEGAL(pvr) \ + (pvr.pvr[2] & PVR2_OPCODE_0x0_ILL_MASK) +#define PVR_UNALIGNED_EXCEPTION(pvr) \ + (pvr.pvr[2] & PVR2_UNALIGNED_EXC_MASK) +#define PVR_ILL_OPCODE_EXCEPTION(pvr) \ + (pvr.pvr[2] & PVR2_ILL_OPCODE_EXC_MASK) +#define PVR_IOPB_BUS_EXCEPTION(pvr) \ + (pvr.pvr[2] & PVR2_IOPB_BUS_EXC_MASK) +#define PVR_DOPB_BUS_EXCEPTION(pvr) \ + (pvr.pvr[2] & PVR2_DOPB_BUS_EXC_MASK) +#define PVR_DIV_ZERO_EXCEPTION(pvr) \ + (pvr.pvr[2] & PVR2_DIV_ZERO_EXC_MASK) +#define PVR_FPU_EXCEPTION(pvr) (pvr.pvr[2] & PVR2_FPU_EXC_MASK) +#define PVR_FSL_EXCEPTION(pvr) (pvr.pvr[2] & PVR2_USE_EXTEND_FSL) + +#define PVR_DEBUG_ENABLED(pvr) (pvr.pvr[3] & PVR3_DEBUG_ENABLED_MASK) +#define PVR_NUMBER_OF_PC_BRK(pvr) \ + ((pvr.pvr[3] & PVR3_NUMBER_OF_PC_BRK_MASK) >> 25) +#define PVR_NUMBER_OF_RD_ADDR_BRK(pvr) \ + ((pvr.pvr[3] & PVR3_NUMBER_OF_RD_ADDR_BRK_MASK) >> 19) +#define PVR_NUMBER_OF_WR_ADDR_BRK(pvr) \ + ((pvr.pvr[3] & PVR3_NUMBER_OF_WR_ADDR_BRK_MASK) >> 13) +#define PVR_FSL_LINKS(pvr) ((pvr.pvr[3] & PVR3_FSL_LINKS_MASK) >> 7) + +#define PVR_ICACHE_ADDR_TAG_BITS(pvr) \ + ((pvr.pvr[4] & PVR4_ICACHE_ADDR_TAG_BITS_MASK) >> 26) +#define PVR_ICACHE_USE_FSL(pvr) (pvr.pvr[4] & PVR4_ICACHE_USE_FSL_MASK) +#define PVR_ICACHE_ALLOW_WR(pvr) (pvr.pvr[4] & PVR4_ICACHE_ALLOW_WR_MASK) +#define PVR_ICACHE_LINE_LEN(pvr) \ + (1 << ((pvr.pvr[4] & PVR4_ICACHE_LINE_LEN_MASK) >> 21)) +#define PVR_ICACHE_BYTE_SIZE(pvr) \ + (1 << ((pvr.pvr[4] & PVR4_ICACHE_BYTE_SIZE_MASK) >> 16)) + +#define PVR_DCACHE_ADDR_TAG_BITS(pvr) \ + ((pvr.pvr[5] & PVR5_DCACHE_ADDR_TAG_BITS_MASK) >> 26) +#define PVR_DCACHE_USE_FSL(pvr) (pvr.pvr[5] & PVR5_DCACHE_USE_FSL_MASK) +#define PVR_DCACHE_ALLOW_WR(pvr) (pvr.pvr[5] & PVR5_DCACHE_ALLOW_WR_MASK) +#define PVR_DCACHE_LINE_LEN(pvr) \ + (1 << ((pvr.pvr[5] & PVR5_DCACHE_LINE_LEN_MASK) >> 21)) +#define PVR_DCACHE_BYTE_SIZE(pvr) \ + (1 << ((pvr.pvr[5] & PVR5_DCACHE_BYTE_SIZE_MASK) >> 16)) + + +#define PVR_ICACHE_BASEADDR(pvr) (pvr.pvr[6] & PVR6_ICACHE_BASEADDR_MASK) +#define PVR_ICACHE_HIGHADDR(pvr) (pvr.pvr[7] & PVR7_ICACHE_HIGHADDR_MASK) + +#define PVR_DCACHE_BASEADDR(pvr) (pvr.pvr[8] & PVR8_DCACHE_BASEADDR_MASK) +#define PVR_DCACHE_HIGHADDR(pvr) (pvr.pvr[9] & PVR9_DCACHE_HIGHADDR_MASK) + +#define PVR_TARGET_FAMILY(pvr) ((pvr.pvr[10] & PVR10_TARGET_FAMILY_MASK) >> 24) + +#define PVR_MSR_RESET_VALUE(pvr) \ + (pvr.pvr[11] & PVR11_MSR_RESET_VALUE_MASK) + +/* mmu */ +#define PVR_USE_MMU(pvr) ((pvr.pvr[11] & PVR11_USE_MMU) >> 30) +#define PVR_MMU_ITLB_SIZE(pvr) (pvr.pvr[11] & PVR11_MMU_ITLB_SIZE) +#define PVR_MMU_DTLB_SIZE(pvr) (pvr.pvr[11] & PVR11_MMU_DTLB_SIZE) +#define PVR_MMU_TLB_ACCESS(pvr) (pvr.pvr[11] & PVR11_MMU_TLB_ACCESS) +#define PVR_MMU_ZONES(pvr) (pvr.pvr[11] & PVR11_MMU_ZONES) + + +int cpu_has_pvr(void); +void get_pvr(struct pvr_s *pvr); + +#endif /* _ASM_MICROBLAZE_PVR_H */ diff --git a/arch/microblaze/include/asm/registers.h b/arch/microblaze/include/asm/registers.h new file mode 100644 index 00000000000..834142d9356 --- /dev/null +++ b/arch/microblaze/include/asm/registers.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2008 Michal Simek + * Copyright (C) 2008 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_REGISTERS_H +#define _ASM_MICROBLAZE_REGISTERS_H + +#define MSR_BE (1<<0) /* 0x001 */ +#define MSR_IE (1<<1) /* 0x002 */ +#define MSR_C (1<<2) /* 0x004 */ +#define MSR_BIP (1<<3) /* 0x008 */ +#define MSR_FSL (1<<4) /* 0x010 */ +#define MSR_ICE (1<<5) /* 0x020 */ +#define MSR_DZ (1<<6) /* 0x040 */ +#define MSR_DCE (1<<7) /* 0x080 */ +#define MSR_EE (1<<8) /* 0x100 */ +#define MSR_EIP (1<<9) /* 0x200 */ +#define MSR_CC (1<<31) + +/* Floating Point Status Register (FSR) Bits */ +#define FSR_IO (1<<4) /* Invalid operation */ +#define FSR_DZ (1<<3) /* Divide-by-zero */ +#define FSR_OF (1<<2) /* Overflow */ +#define FSR_UF (1<<1) /* Underflow */ +#define FSR_DO (1<<0) /* Denormalized operand error */ + +#endif /* _ASM_MICROBLAZE_REGISTERS_H */ diff --git a/arch/microblaze/include/asm/resource.h b/arch/microblaze/include/asm/resource.h new file mode 100644 index 00000000000..04bc4db8921 --- /dev/null +++ b/arch/microblaze/include/asm/resource.h @@ -0,0 +1 @@ +#include <asm-generic/resource.h> diff --git a/arch/microblaze/include/asm/scatterlist.h b/arch/microblaze/include/asm/scatterlist.h new file mode 100644 index 00000000000..08ff1d049b4 --- /dev/null +++ b/arch/microblaze/include/asm/scatterlist.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2008 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SCATTERLIST_H +#define _ASM_MICROBLAZE_SCATTERLIST_H + +struct scatterlist { +#ifdef CONFIG_DEBUG_SG + unsigned long sg_magic; +#endif + unsigned long page_link; + dma_addr_t dma_address; + unsigned int offset; + unsigned int length; +}; + +#define sg_dma_address(sg) ((sg)->dma_address) +#define sg_dma_len(sg) ((sg)->length) + +#define ISA_DMA_THRESHOLD (~0UL) + +#endif /* _ASM_MICROBLAZE_SCATTERLIST_H */ diff --git a/arch/microblaze/include/asm/sections.h b/arch/microblaze/include/asm/sections.h new file mode 100644 index 00000000000..8434a43e542 --- /dev/null +++ b/arch/microblaze/include/asm/sections.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SECTIONS_H +#define _ASM_MICROBLAZE_SECTIONS_H + +#include <asm-generic/sections.h> + +# ifndef __ASSEMBLY__ +extern char _ssbss[], _esbss[]; +extern unsigned long __ivt_start[], __ivt_end[]; + +# ifdef CONFIG_MTD_UCLINUX +extern char *_ebss; +# endif + +extern u32 _fdt_start[], _fdt_end[]; + +# endif /* !__ASSEMBLY__ */ +#endif /* _ASM_MICROBLAZE_SECTIONS_H */ diff --git a/arch/microblaze/include/asm/segment.h b/arch/microblaze/include/asm/segment.h new file mode 100644 index 00000000000..7f5dcc56eea --- /dev/null +++ b/arch/microblaze/include/asm/segment.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008 Michal Simek + * Copyright (C) 2008 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SEGMENT_H +#define _ASM_MICROBLAZE_SEGMENT_H + +#ifndef __ASSEMBLY__ + +typedef struct { + unsigned long seg; +} mm_segment_t; + +/* + * On Microblaze the fs value is actually the top of the corresponding + * address space. + * + * The fs value determines whether argument validity checking should be + * performed or not. If get_fs() == USER_DS, checking is performed, with + * get_fs() == KERNEL_DS, checking is bypassed. + * + * For historical reasons, these macros are grossly misnamed. + * + * For non-MMU arch like Microblaze, KERNEL_DS and USER_DS is equal. + */ +# define KERNEL_DS ((mm_segment_t){0}) +# define USER_DS KERNEL_DS + +# define get_ds() (KERNEL_DS) +# define get_fs() (current_thread_info()->addr_limit) +# define set_fs(x) \ + do { current_thread_info()->addr_limit = (x); } while (0) + +# define segment_eq(a, b) ((a).seg == (b).seg) + +# endif /* __ASSEMBLY__ */ +#endif /* _ASM_MICROBLAZE_SEGMENT_H */ diff --git a/arch/microblaze/include/asm/selfmod.h b/arch/microblaze/include/asm/selfmod.h new file mode 100644 index 00000000000..c42aff2e6cd --- /dev/null +++ b/arch/microblaze/include/asm/selfmod.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu> + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SELFMOD_H +#define _ASM_MICROBLAZE_SELFMOD_H + +/* + * BARRIER_BASE_ADDR is constant address for selfmod function. + * do not change this value - selfmod function is in + * arch/microblaze/kernel/selfmod.c: selfmod_function() + * + * last 16 bits is used for storing register offset + */ + +#define BARRIER_BASE_ADDR 0x1234ff00 + +void selfmod_function(const int *arr_fce, const unsigned int base); + +#endif /* _ASM_MICROBLAZE_SELFMOD_H */ diff --git a/arch/microblaze/include/asm/sembuf.h b/arch/microblaze/include/asm/sembuf.h new file mode 100644 index 00000000000..b804ed71a57 --- /dev/null +++ b/arch/microblaze/include/asm/sembuf.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SEMBUF_H +#define _ASM_MICROBLAZE_SEMBUF_H + +/* + * The semid64_ds structure for microblaze architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 64-bit time_t to solve y2038 problem + * - 2 miscellaneous 32-bit values + */ + +struct semid64_ds { + struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ + __kernel_time_t sem_otime; /* last semop time */ + unsigned long __unused1; + __kernel_time_t sem_ctime; /* last change time */ + unsigned long __unused2; + unsigned long sem_nsems; /* no. of semaphores in array */ + unsigned long __unused3; + unsigned long __unused4; +}; + + +#endif /* _ASM_MICROBLAZE_SEMBUF_H */ diff --git a/arch/microblaze/include/asm/serial.h b/arch/microblaze/include/asm/serial.h new file mode 100644 index 00000000000..39bfc8ce6af --- /dev/null +++ b/arch/microblaze/include/asm/serial.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SERIAL_H +#define _ASM_MICROBLAZE_SERIAL_H + +# define BASE_BAUD (1843200 / 16) + +#endif /* _ASM_MICROBLAZE_SERIAL_H */ diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h new file mode 100644 index 00000000000..9b98e8e6aba --- /dev/null +++ b/arch/microblaze/include/asm/setup.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SETUP_H +#define _ASM_MICROBLAZE_SETUP_H + +#define COMMAND_LINE_SIZE 256 + +# ifndef __ASSEMBLY__ + +# ifdef __KERNEL__ +extern unsigned int boot_cpuid; /* move to smp.h */ + +extern char cmd_line[COMMAND_LINE_SIZE]; +# endif/* __KERNEL__ */ + +void early_printk(const char *fmt, ...); + +int setup_early_printk(char *opt); +void disable_early_printk(void); + +void heartbeat(void); +void setup_heartbeat(void); + +unsigned long long sched_clock(void); + +void time_init(void); +void init_IRQ(void); +void machine_early_init(const char *cmdline, unsigned int ram, + unsigned int fdt); + +void machine_restart(char *cmd); +void machine_shutdown(void); +void machine_halt(void); +void machine_power_off(void); + +# endif /* __ASSEMBLY__ */ +#endif /* _ASM_MICROBLAZE_SETUP_H */ diff --git a/arch/microblaze/include/asm/shmbuf.h b/arch/microblaze/include/asm/shmbuf.h new file mode 100644 index 00000000000..f829c584361 --- /dev/null +++ b/arch/microblaze/include/asm/shmbuf.h @@ -0,0 +1,42 @@ +#ifndef _ASM_MICROBLAZE_SHMBUF_H +#define _ASM_MICROBLAZE_SHMBUF_H + +/* + * The shmid64_ds structure for microblaze architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 64-bit time_t to solve y2038 problem + * - 2 miscellaneous 32-bit values + */ + +struct shmid64_ds { + struct ipc64_perm shm_perm; /* operation perms */ + size_t shm_segsz; /* size of segment (bytes) */ + __kernel_time_t shm_atime; /* last attach time */ + unsigned long __unused1; + __kernel_time_t shm_dtime; /* last detach time */ + unsigned long __unused2; + __kernel_time_t shm_ctime; /* last change time */ + unsigned long __unused3; + __kernel_pid_t shm_cpid; /* pid of creator */ + __kernel_pid_t shm_lpid; /* pid of last operator */ + unsigned long shm_nattch; /* no. of current attaches */ + unsigned long __unused4; + unsigned long __unused5; +}; + +struct shminfo64 { + unsigned long shmmax; + unsigned long shmmin; + unsigned long shmmni; + unsigned long shmseg; + unsigned long shmall; + unsigned long __unused1; + unsigned long __unused2; + unsigned long __unused3; + unsigned long __unused4; +}; + +#endif /* _ASM_MICROBLAZE_SHMBUF_H */ diff --git a/arch/microblaze/include/asm/shmparam.h b/arch/microblaze/include/asm/shmparam.h new file mode 100644 index 00000000000..9f5fc2b3b6a --- /dev/null +++ b/arch/microblaze/include/asm/shmparam.h @@ -0,0 +1,6 @@ +#ifndef _ASM_MICROBLAZE_SHMPARAM_H +#define _ASM_MICROBLAZE_SHMPARAM_H + +#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ + +#endif /* _ASM_MICROBLAZE_SHMPARAM_H */ diff --git a/arch/microblaze/include/asm/sigcontext.h b/arch/microblaze/include/asm/sigcontext.h new file mode 100644 index 00000000000..55873c80c91 --- /dev/null +++ b/arch/microblaze/include/asm/sigcontext.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SIGCONTEXT_H +#define _ASM_MICROBLAZE_SIGCONTEXT_H + +/* FIXME should be linux/ptrace.h */ +#include <asm/ptrace.h> + +struct sigcontext { + struct pt_regs regs; + unsigned long oldmask; +}; + +#endif /* _ASM_MICROBLAZE_SIGCONTEXT_H */ diff --git a/arch/microblaze/include/asm/siginfo.h b/arch/microblaze/include/asm/siginfo.h new file mode 100644 index 00000000000..f162911a8f5 --- /dev/null +++ b/arch/microblaze/include/asm/siginfo.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SIGINFO_H +#define _ASM_MICROBLAZE_SIGINFO_H + +#include <linux/types.h> +#include <asm-generic/siginfo.h> + +#endif /* _ASM_MICROBLAZE_SIGINFO_H */ diff --git a/arch/microblaze/include/asm/signal.h b/arch/microblaze/include/asm/signal.h new file mode 100644 index 00000000000..9676fad3486 --- /dev/null +++ b/arch/microblaze/include/asm/signal.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * Yasushi SHOJI <yashi@atmark-techno.com> + * Tetsuya OHKAWA <tetsuya@atmark-techno.com> + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SIGNAL_H +#define _ASM_MICROBLAZE_SIGNAL_H + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL SIGIO +/* +#define SIGLOST 29 +*/ +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED 31 + +/* These should not be considered constants from userland. */ +#define SIGRTMIN 32 +#define SIGRTMAX _NSIG + +/* + * SA_FLAGS values: + * + * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_NOCLDSTOP 0x00000001 +#define SA_NOCLDWAIT 0x00000002 +#define SA_SIGINFO 0x00000004 +#define SA_ONSTACK 0x08000000 +#define SA_RESTART 0x10000000 +#define SA_NODEFER 0x40000000 +#define SA_RESETHAND 0x80000000 + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND + +#define SA_RESTORER 0x04000000 + +/* + * sigaltstack controls + */ +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 + +# ifndef __ASSEMBLY__ +# include <linux/types.h> +# include <asm-generic/signal.h> + +/* Avoid too many header ordering problems. */ +struct siginfo; + +# ifdef __KERNEL__ +/* + * Most things should be clean enough to redefine this at will, if care + * is taken to make libc match. + */ +# define _NSIG 64 +# define _NSIG_BPW 32 +# define _NSIG_WORDS (_NSIG / _NSIG_BPW) + +typedef unsigned long old_sigset_t; /* at least 32 bits */ + +typedef struct { + unsigned long sig[_NSIG_WORDS]; +} sigset_t; + +struct old_sigaction { + __sighandler_t sa_handler; + old_sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; + +struct sigaction { + __sighandler_t sa_handler; + unsigned long sa_flags; + void (*sa_restorer)(void); + sigset_t sa_mask; /* mask last for extensibility */ +}; + +struct k_sigaction { + struct sigaction sa; +}; + +# include <asm/sigcontext.h> +# undef __HAVE_ARCH_SIG_BITOPS + +# define ptrace_signal_deliver(regs, cookie) do { } while (0) + +# else /* !__KERNEL__ */ + +/* Here we must cater to libcs that poke about in kernel headers. */ + +# define NSIG 32 +typedef unsigned long sigset_t; + +struct sigaction { + union { + __sighandler_t _sa_handler; + void (*_sa_sigaction)(int, struct siginfo *, void *); + } _u; + sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; + +# define sa_handler _u._sa_handler +# define sa_sigaction _u._sa_sigaction + +# endif /* __KERNEL__ */ + +typedef struct sigaltstack { + void *ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; + +# endif /* __ASSEMBLY__ */ +#endif /* _ASM_MICROBLAZE_SIGNAL_H */ diff --git a/arch/microblaze/include/asm/socket.h b/arch/microblaze/include/asm/socket.h new file mode 100644 index 00000000000..82593686031 --- /dev/null +++ b/arch/microblaze/include/asm/socket.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SOCKET_H +#define _ASM_MICROBLAZE_SOCKET_H + +#include <asm/sockios.h> + +/* For setsockoptions(2) */ +#define SOL_SOCKET 1 + +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_SNDBUFFORCE 32 +#define SO_RCVBUFFORCE 33 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +/* To add :#define SO_REUSEPORT 15 */ +#define SO_PASSCRED 16 +#define SO_PEERCRED 17 +#define SO_RCVLOWAT 18 +#define SO_SNDLOWAT 19 +#define SO_RCVTIMEO 20 +#define SO_SNDTIMEO 21 + +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 + +#define SO_PEERNAME 28 +#define SO_TIMESTAMP 29 +#define SCM_TIMESTAMP SO_TIMESTAMP + +#define SO_ACCEPTCONN 30 + +#define SO_PEERSEC 31 +#define SO_PASSSEC 34 + +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS + +#define SO_MARK 36 + +#define SO_TIMESTAMPING 37 +#define SCM_TIMESTAMPING SO_TIMESTAMPING + +#endif /* _ASM_MICROBLAZE_SOCKET_H */ diff --git a/arch/microblaze/include/asm/sockios.h b/arch/microblaze/include/asm/sockios.h new file mode 100644 index 00000000000..9fff57a701e --- /dev/null +++ b/arch/microblaze/include/asm/sockios.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SOCKIOS_H +#define _ASM_MICROBLAZE_SOCKIOS_H + +#include <linux/ioctl.h> + +/* Socket-level I/O control calls. */ +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ +#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ + +#endif /* _ASM_MICROBLAZE_SOCKIOS_H */ diff --git a/arch/microblaze/include/asm/stat.h b/arch/microblaze/include/asm/stat.h new file mode 100644 index 00000000000..5f18b8aed22 --- /dev/null +++ b/arch/microblaze/include/asm/stat.h @@ -0,0 +1,73 @@ +/* + * Microblaze stat structure + * + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> + * + * 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. + * + * Written by Miles Bader <miles@gnu.org> + */ + +#ifndef _ASM_MICROBLAZE_STAT_H +#define _ASM_MICROBLAZE_STAT_H + +#include <linux/posix_types.h> + +struct stat { + unsigned int st_dev; + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_rdev; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long __unused1; /* unsigned long st_atime_nsec */ + unsigned long st_mtime; + unsigned long __unused2; /* unsigned long st_mtime_nsec */ + unsigned long st_ctime; + unsigned long __unused3; /* unsigned long st_ctime_nsec */ + unsigned long __unused4; + unsigned long __unused5; +}; + +struct stat64 { + unsigned long long st_dev; + unsigned long __unused1; + + unsigned long long st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned int st_uid; + unsigned int st_gid; + + unsigned long long st_rdev; + unsigned long __unused3; + + long long st_size; + unsigned long st_blksize; + + unsigned long st_blocks; /* No. of 512-byte blocks allocated */ + unsigned long __unused4; /* future possible st_blocks high bits */ + + unsigned long st_atime; + unsigned long st_atime_nsec; + + unsigned long st_mtime; + unsigned long st_mtime_nsec; + + unsigned long st_ctime; + unsigned long st_ctime_nsec; + + unsigned long __unused8; +}; + +#endif /* _ASM_MICROBLAZE_STAT_H */ diff --git a/arch/microblaze/include/asm/statfs.h b/arch/microblaze/include/asm/statfs.h new file mode 100644 index 00000000000..0b91fe198c2 --- /dev/null +++ b/arch/microblaze/include/asm/statfs.h @@ -0,0 +1 @@ +#include <asm-generic/statfs.h> diff --git a/arch/microblaze/include/asm/string.h b/arch/microblaze/include/asm/string.h new file mode 100644 index 00000000000..f7728c90fc1 --- /dev/null +++ b/arch/microblaze/include/asm/string.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_STRING_H +#define _ASM_MICROBLAZE_STRING_H + +#ifndef __KERNEL__ + +#define __HAVE_ARCH_MEMSET +#define __HAVE_ARCH_MEMCPY +#define __HAVE_ARCH_MEMMOVE + +extern void *memset(void *, int, __kernel_size_t); +extern void *memcpy(void *, const void *, __kernel_size_t); +extern void *memmove(void *, const void *, __kernel_size_t); + +#endif /* __KERNEL__ */ + +#endif /* _ASM_MICROBLAZE_STRING_H */ diff --git a/arch/microblaze/include/asm/swab.h b/arch/microblaze/include/asm/swab.h new file mode 100644 index 00000000000..b375d7b65ad --- /dev/null +++ b/arch/microblaze/include/asm/swab.h @@ -0,0 +1,8 @@ +#ifndef _ASM_MICROBLAZE_SWAB_H +#define _ASM_MICROBLAZE_SWAB_H + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__) +#define __SWAB_64_THRU_32__ +#endif + +#endif /* _ASM_MICROBLAZE_SWAB_H */ diff --git a/arch/microblaze/include/asm/syscalls.h b/arch/microblaze/include/asm/syscalls.h new file mode 100644 index 00000000000..9cb4ff0edeb --- /dev/null +++ b/arch/microblaze/include/asm/syscalls.h @@ -0,0 +1,45 @@ +#ifndef __ASM_MICROBLAZE_SYSCALLS_H +#define __ASM_MICROBLAZE_SYSCALLS_H +#ifdef __KERNEL__ + +#include <linux/compiler.h> +#include <linux/linkage.h> +#include <linux/types.h> +#include <linux/signal.h> + +/* FIXME will be removed */ +asmlinkage int sys_ipc(uint call, int first, int second, + int third, void *ptr, long fifth); + +struct pt_regs; +asmlinkage int sys_vfork(struct pt_regs *regs); +asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs); +asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv, + char __user *__user *envp, struct pt_regs *regs); + +asmlinkage unsigned long sys_mmap2(unsigned long addr, size_t len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff); + +asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, + unsigned long prot, unsigned long flags, + unsigned long fd, off_t offset); + +/* from signal.c */ +asmlinkage int sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs); + +asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, + struct pt_regs *regs); + +asmlinkage int sys_sigaction(int sig, const struct old_sigaction *act, + struct old_sigaction *oact); + +asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, + struct pt_regs *regs); + +asmlinkage int sys_sigreturn(struct pt_regs *regs); + +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs); + +#endif /* __KERNEL__ */ +#endif /* __ASM_MICROBLAZE_SYSCALLS_H */ diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h new file mode 100644 index 00000000000..c4e308850b5 --- /dev/null +++ b/arch/microblaze/include/asm/system.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_SYSTEM_H +#define _ASM_MICROBLAZE_SYSTEM_H + +#include <asm/registers.h> +#include <asm/setup.h> +#include <asm/irqflags.h> + +struct task_struct; +struct thread_info; + +extern struct task_struct *_switch_to(struct thread_info *prev, + struct thread_info *next); + +#define switch_to(prev, next, last) \ + do { \ + (last) = _switch_to(task_thread_info(prev), \ + task_thread_info(next)); \ + } while (0) + +#define smp_read_barrier_depends() do {} while (0) +#define read_barrier_depends() do {} while (0) + +#define nop() asm volatile ("nop") +#define mb() barrier() +#define rmb() mb() +#define wmb() mb() +#define set_mb(var, value) do { var = value; mb(); } while (0) +#define set_wmb(var, value) do { var = value; wmb(); } while (0) + +#define smp_mb() mb() +#define smp_rmb() rmb() +#define smp_wmb() wmb() + +void show_trace(struct task_struct *task, unsigned long *stack); +void __bad_xchg(volatile void *ptr, int size); + +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, + int size) +{ + unsigned long ret; + unsigned long flags; + + switch (size) { + case 1: + local_irq_save(flags); + ret = *(volatile unsigned char *)ptr; + *(volatile unsigned char *)ptr = x; + local_irq_restore(flags); + break; + + case 4: + local_irq_save(flags); + ret = *(volatile unsigned long *)ptr; + *(volatile unsigned long *)ptr = x; + local_irq_restore(flags); + break; + default: + __bad_xchg(ptr, size), ret = 0; + break; + } + + return ret; +} + +void disable_hlt(void); +void enable_hlt(void); +void default_idle(void); + +#define xchg(ptr, x) \ + ((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) + +void free_init_pages(char *what, unsigned long begin, unsigned long end); +void free_initmem(void); +extern char *klimit; +extern void ret_from_fork(void); + +#ifdef CONFIG_DEBUG_FS +extern struct dentry *of_debugfs_root; +#endif + +#define arch_align_stack(x) (x) + +#endif /* _ASM_MICROBLAZE_SYSTEM_H */ diff --git a/arch/microblaze/include/asm/termbits.h b/arch/microblaze/include/asm/termbits.h new file mode 100644 index 00000000000..a1b64bc4724 --- /dev/null +++ b/arch/microblaze/include/asm/termbits.h @@ -0,0 +1,203 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_TERMBITS_H +#define _ASM_MICROBLAZE_TERMBITS_H + +#include <linux/posix_types.h> + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 19 +struct termios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ +}; + +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + +/* c_cc characters */ + +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +/* c_iflag bits */ + +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ + +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#define NLDLY 0000400 +#define NL0 0000000 +#define NL1 0000400 +#define CRDLY 0003000 +#define CR0 0000000 +#define CR1 0001000 +#define CR2 0002000 +#define CR3 0003000 +#define TABDLY 0014000 +#define TAB0 0000000 +#define TAB1 0004000 +#define TAB2 0010000 +#define TAB3 0014000 +#define XTABS 0014000 +#define BSDLY 0020000 +#define BS0 0000000 +#define BS1 0020000 +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 +#define FFDLY 0100000 +#define FF0 0000000 +#define FF1 0100000 + +/* c_cflag bit meaning */ + +#define CBAUD 0010017 +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#define EXTA B19200 +#define EXTB B38400 +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#define CBAUDEX 0010000 +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define BOTHER 0010000 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#define CIBAUD 002003600000 /* input baud rate (not used) */ +#define CMSPAR 010000000000 /* mark or space (stick) parity */ +#define CRTSCTS 020000000000 /* flow control */ + +#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ + +/* c_lflag bits */ + +#define ISIG 0000001 +#define ICANON 0000002 +#define XCASE 0000004 +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#define ECHOCTL 0001000 +#define ECHOPRT 0002000 +#define ECHOKE 0004000 +#define FLUSHO 0010000 +#define PENDIN 0040000 +#define IEXTEN 0100000 + +/* tcflow() and TCXONC use these */ + +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ + +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ + +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +#endif /* _ASM_MICROBLAZE_TERMBITS_H */ diff --git a/arch/microblaze/include/asm/termios.h b/arch/microblaze/include/asm/termios.h new file mode 100644 index 00000000000..102d7725866 --- /dev/null +++ b/arch/microblaze/include/asm/termios.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_TERMIOS_H +#define _ASM_MICROBLAZE_TERMIOS_H + +#include <linux/string.h> +#include <asm/termbits.h> +#include <asm/ioctls.h> + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define NCC 8 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + +#ifdef __KERNEL__ +/* intr=^C quit=^| erase=del kill=^U + eof=^D vtime=\0 vmin=\1 sxtc=\0 + start=^Q stop=^S susp=^Z eol=\0 + reprint=^R discard=^U werase=^W lnext=^V + eol2=\0 +*/ +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" +#endif + +/* Modem lines */ + +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ + +/* Line disciplines */ + +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 +#define N_STRIP 4 +#define N_AX25 5 +#define N_X25 6 /* X.25 async */ +#define N_6PACK 7 +#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */ +#define N_R3964 9 /* Reserved for Simatic R3964 module */ +#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */ +#define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */ +#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards + about SMS messages */ +#define N_HDLC 13 /* synchronous HDLC */ +#define N_SYNC_PPP 14 +#define N_HCI 15 /* Bluetooth HCI UART */ + +#ifdef __KERNEL__ + +#include <asm-generic/termios.h> + +#endif /* __KERNEL__ */ + +#endif /* _ASM_MICROBLAZE_TERMIOS_H */ diff --git a/arch/microblaze/include/asm/thread_info.h b/arch/microblaze/include/asm/thread_info.h new file mode 100644 index 00000000000..4c3943e3f40 --- /dev/null +++ b/arch/microblaze/include/asm/thread_info.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_THREAD_INFO_H +#define _ASM_MICROBLAZE_THREAD_INFO_H + +#ifdef __KERNEL__ + +/* we have 8k stack */ +#define THREAD_SHIFT 13 +#define THREAD_SIZE (1 << THREAD_SHIFT) +#define THREAD_SIZE_ORDER 1 + +#ifndef __ASSEMBLY__ +# include <linux/types.h> +# include <asm/processor.h> +# include <asm/segment.h> + +/* + * low level task data that entry.S needs immediate access to + * - this struct should fit entirely inside of one cache line + * - this struct shares the supervisor stack pages + * - if the contents of this structure are changed, the assembly constants + * must also be changed + */ + +struct cpu_context { + __u32 r1; /* stack pointer */ + __u32 r2; + /* dedicated registers */ + __u32 r13; + __u32 r14; + __u32 r15; + __u32 r16; + __u32 r17; + __u32 r18; + /* non-volatile registers */ + __u32 r19; + __u32 r20; + __u32 r21; + __u32 r22; + __u32 r23; + __u32 r24; + __u32 r25; + __u32 r26; + __u32 r27; + __u32 r28; + __u32 r29; + __u32 r30; + /* r31 is used as current task pointer */ + /* special purpose registers */ + __u32 msr; + __u32 ear; + __u32 esr; + __u32 fsr; +}; + +struct thread_info { + struct task_struct *task; /* main task structure */ + struct exec_domain *exec_domain; /* execution domain */ + unsigned long flags; /* low level flags */ + unsigned long status; /* thread-synchronous flags */ + __u32 cpu; /* current CPU */ + __s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/ + mm_segment_t addr_limit; /* thread address space */ + struct restart_block restart_block; + + struct cpu_context cpu_context; +}; + +/* + * macros/functions for gaining access to the thread information structure + * + * preempt_count needs to be 1 initially, until the scheduler is functional. + */ +#define INIT_THREAD_INFO(tsk) \ +{ \ + .task = &tsk, \ + .exec_domain = &default_exec_domain, \ + .flags = 0, \ + .cpu = 0, \ + .preempt_count = 1, \ + .addr_limit = KERNEL_DS, \ + .restart_block = { \ + .fn = do_no_restart_syscall, \ + }, \ +} + +#define init_thread_info (init_thread_union.thread_info) +#define init_stack (init_thread_union.stack) + +/* how to get the thread information struct from C */ +static inline struct thread_info *current_thread_info(void) +{ + register unsigned long sp asm("r1"); + + return (struct thread_info *)(sp & ~(THREAD_SIZE-1)); +} + +/* thread information allocation */ +#endif /* __ASSEMBLY__ */ + +#define PREEMPT_ACTIVE 0x10000000 + +/* + * thread information flags + * - these are process state flags that various assembly files may + * need to access + * - pending work-to-be-done flags are in LSW + * - other flags in MSW + */ +#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ +#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */ +#define TIF_SIGPENDING 2 /* signal pending */ +#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ +/* restore singlestep on return to user mode */ +#define TIF_SINGLESTEP 4 +#define TIF_IRET 5 /* return with iret */ +#define TIF_MEMDIE 6 +#define TIF_FREEZE 14 /* Freezing for suspend */ + +/* FIXME change in entry.S */ +#define TIF_KERNEL_TRACE 8 /* kernel trace active */ + +/* true if poll_idle() is polling TIF_NEED_RESCHED */ +#define TIF_POLLING_NRFLAG 16 + +#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) +#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) +#define _TIF_SIGPENDING (1<<TIF_SIGPENDING) +#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) +#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) +#define _TIF_IRET (1<<TIF_IRET) +#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) +#define _TIF_FREEZE (1<<TIF_FREEZE) +#define _TIF_KERNEL_TRACE (1 << TIF_KERNEL_TRACE) + +/* work to do on interrupt/exception return */ +#define _TIF_WORK_MASK 0x0000FFFE +/* work to do on any return to u-space */ +#define _TIF_ALLWORK_MASK 0x0000FFFF + +/* + * Thread-synchronous status. + * + * This is different from the flags in that nobody else + * ever touches our thread-synchronous status, so we don't + * have to worry about atomic accesses. + */ +/* FPU was used by this task this quantum (SMP) */ +#define TS_USEDFPU 0x0001 + +#endif /* __KERNEL__ */ +#endif /* _ASM_MICROBLAZE_THREAD_INFO_H */ diff --git a/arch/microblaze/include/asm/timex.h b/arch/microblaze/include/asm/timex.h new file mode 100644 index 00000000000..678525dc6d0 --- /dev/null +++ b/arch/microblaze/include/asm/timex.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_TIMEX_H +#define _ASM_MICROBLAZE_TIMEX_H + +#define CLOCK_TICK_RATE 1000 /* Timer input freq. */ + +typedef unsigned long cycles_t; + +#define get_cycles() (0) + +#endif /* _ASM_TIMEX_H */ diff --git a/arch/microblaze/include/asm/tlb.h b/arch/microblaze/include/asm/tlb.h new file mode 100644 index 00000000000..d1dfe379112 --- /dev/null +++ b/arch/microblaze/include/asm/tlb.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_TLB_H +#define _ASM_MICROBLAZE_TLB_H + +#define tlb_flush(tlb) do {} while (0) + +#include <asm-generic/tlb.h> + +#endif /* _ASM_MICROBLAZE_TLB_H */ diff --git a/arch/microblaze/include/asm/tlbflush.h b/arch/microblaze/include/asm/tlbflush.h new file mode 100644 index 00000000000..d7fe7629001 --- /dev/null +++ b/arch/microblaze/include/asm/tlbflush.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_TLBFLUSH_H +#define _ASM_MICROBLAZE_TLBFLUSH_H + +#define flush_tlb() BUG() +#define flush_tlb_all() BUG() +#define flush_tlb_mm(mm) BUG() +#define flush_tlb_page(vma, addr) BUG() +#define flush_tlb_range(mm, start, end) BUG() +#define flush_tlb_pgtables(mm, start, end) BUG() +#define flush_tlb_kernel_range(start, end) BUG() + +#endif /* _ASM_MICROBLAZE_TLBFLUSH_H */ diff --git a/arch/microblaze/include/asm/topology.h b/arch/microblaze/include/asm/topology.h new file mode 100644 index 00000000000..96bcea5a992 --- /dev/null +++ b/arch/microblaze/include/asm/topology.h @@ -0,0 +1,11 @@ +#include <asm-generic/topology.h> + +#ifndef _ASM_MICROBLAZE_TOPOLOGY_H +#define _ASM_MICROBLAZE_TOPOLOGY_H + +struct device_node; +static inline int of_node_to_nid(struct device_node *device) +{ + return 0; +} +#endif /* _ASM_MICROBLAZE_TOPOLOGY_H */ diff --git a/arch/microblaze/include/asm/types.h b/arch/microblaze/include/asm/types.h new file mode 100644 index 00000000000..bebc018318f --- /dev/null +++ b/arch/microblaze/include/asm/types.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_TYPES_H +#define _ASM_MICROBLAZE_TYPES_H + +/* + * This file is never included by application software unless + * explicitly requested (e.g., via linux/types.h) in which case the + * application is Linux specific so (user-) name space pollution is + * not a major issue. However, for interoperability, libraries still + * need to be careful to avoid a name clashes. + */ + +#include <asm-generic/int-ll64.h> + +# ifndef __ASSEMBLY__ + +typedef unsigned short umode_t; + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +# ifdef __KERNEL__ +# define BITS_PER_LONG 32 + +/* Dma addresses are 32-bits wide. */ + +typedef u32 dma_addr_t; + +# endif/* __KERNEL__ */ +# endif /* __ASSEMBLY__ */ +#endif /* _ASM_MICROBLAZE_TYPES_H */ diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h new file mode 100644 index 00000000000..5a3ffc308e1 --- /dev/null +++ b/arch/microblaze/include/asm/uaccess.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_UACCESS_H +#define _ASM_MICROBLAZE_UACCESS_H + +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/sched.h> /* RLIMIT_FSIZE */ +#include <linux/mm.h> + +#include <asm/mmu.h> +#include <asm/page.h> +#include <asm/pgtable.h> +#include <asm/segment.h> +#include <linux/string.h> + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +extern int ___range_ok(unsigned long addr, unsigned long size); + +#define __range_ok(addr, size) \ + ___range_ok((unsigned long)(addr), (unsigned long)(size)) + +#define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0) +#define __access_ok(add, size) (__range_ok((addr), (size)) == 0) + +extern inline int bad_user_access_length(void) +{ + return 0; +} +/* FIXME this is function for optimalization -> memcpy */ +#define __get_user(var, ptr) \ + ({ \ + int __gu_err = 0; \ + switch (sizeof(*(ptr))) { \ + case 1: \ + case 2: \ + case 4: \ + (var) = *(ptr); \ + break; \ + case 8: \ + memcpy((void *) &(var), (ptr), 8); \ + break; \ + default: \ + (var) = 0; \ + __gu_err = __get_user_bad(); \ + break; \ + } \ + __gu_err; \ + }) + +#define __get_user_bad() (bad_user_access_length(), (-EFAULT)) + +#define __put_user(var, ptr) \ + ({ \ + int __pu_err = 0; \ + switch (sizeof(*(ptr))) { \ + case 1: \ + case 2: \ + case 4: \ + *(ptr) = (var); \ + break; \ + case 8: { \ + typeof(*(ptr)) __pu_val = var; \ + memcpy(ptr, &__pu_val, sizeof(__pu_val));\ + } \ + break; \ + default: \ + __pu_err = __put_user_bad(); \ + break; \ + } \ + __pu_err; \ + }) + +#define __put_user_bad() (bad_user_access_length(), (-EFAULT)) + +#define put_user(x, ptr) __put_user(x, ptr) +#define get_user(x, ptr) __get_user(x, ptr) + +#define copy_to_user(to, from, n) (memcpy(to, from, n), 0) +#define copy_from_user(to, from, n) (memcpy(to, from, n), 0) + +#define __copy_to_user(to, from, n) (copy_to_user(to, from, n)) +#define __copy_from_user(to, from, n) (copy_from_user(to, from, n)) +#define __copy_to_user_inatomic(to, from, n) (__copy_to_user(to, from, n)) +#define __copy_from_user_inatomic(to, from, n) (__copy_from_user(to, from, n)) + +#define __clear_user(addr, n) (memset((void *)addr, 0, n), 0) + +static inline unsigned long clear_user(void *addr, unsigned long size) +{ + if (access_ok(VERIFY_WRITE, addr, size)) + size = __clear_user(addr, size); + return size; +} + +/* Returns 0 if exception not found and fixup otherwise. */ +extern unsigned long search_exception_table(unsigned long); + + +extern long strncpy_from_user(char *dst, const char __user *src, long count); +extern long strnlen_user(const char __user *src, long count); +extern long __strncpy_from_user(char *dst, const char __user *src, long count); + +/* + * The exception table consists of pairs of addresses: the first is the + * address of an instruction that is allowed to fault, and the second is + * the address at which the program should continue. No registers are + * modified, so it is entirely up to the continuation code to figure out + * what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ +struct exception_table_entry { + unsigned long insn, fixup; +}; + +#endif /* __ASSEMBLY__ */ +#endif /* __KERNEL__ */ + +#endif /* _ASM_MICROBLAZE_UACCESS_H */ diff --git a/arch/microblaze/include/asm/ucontext.h b/arch/microblaze/include/asm/ucontext.h new file mode 100644 index 00000000000..11f6bb3ae3a --- /dev/null +++ b/arch/microblaze/include/asm/ucontext.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_UCONTEXT_H +#define _ASM_MICROBLAZE_UCONTEXT_H + +#include <asm/sigcontext.h> + +struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; /* mask last for extensibility */ +}; + +#endif /* _ASM_MICROBLAZE_UCONTEXT_H */ diff --git a/arch/microblaze/include/asm/unaligned.h b/arch/microblaze/include/asm/unaligned.h new file mode 100644 index 00000000000..9d66b640c91 --- /dev/null +++ b/arch/microblaze/include/asm/unaligned.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2008 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_UNALIGNED_H +#define _ASM_MICROBLAZE_UNALIGNED_H + +# ifdef __KERNEL__ + +# include <linux/unaligned/access_ok.h> +# include <linux/unaligned/generic.h> + +# define get_unaligned __get_unaligned_be +# define put_unaligned __put_unaligned_be + +# endif /* __KERNEL__ */ +#endif /* _ASM_MICROBLAZE_UNALIGNED_H */ diff --git a/arch/microblaze/include/asm/unistd.h b/arch/microblaze/include/asm/unistd.h new file mode 100644 index 00000000000..d9d3903fde3 --- /dev/null +++ b/arch/microblaze/include/asm/unistd.h @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#ifndef _ASM_MICROBLAZE_UNISTD_H +#define _ASM_MICROBLAZE_UNISTD_H + +#define __NR_restart_syscall 0 /* ok */ +#define __NR_exit 1 /* ok */ +#define __NR_fork 2 /* not for no MMU - weird */ +#define __NR_read 3 /* ok */ +#define __NR_write 4 /* ok */ +#define __NR_open 5 /* openat */ +#define __NR_close 6 /* ok */ +#define __NR_waitpid 7 /* waitid */ +#define __NR_creat 8 /* openat */ +#define __NR_link 9 /* linkat */ +#define __NR_unlink 10 /* unlinkat */ +#define __NR_execve 11 /* ok */ +#define __NR_chdir 12 /* ok */ +#define __NR_time 13 /* obsolete -> sys_gettimeofday */ +#define __NR_mknod 14 /* mknodat */ +#define __NR_chmod 15 /* fchmodat */ +#define __NR_lchown 16 /* ok */ +#define __NR_break 17 /* don't know */ +#define __NR_oldstat 18 /* remove */ +#define __NR_lseek 19 /* ok */ +#define __NR_getpid 20 /* ok */ +#define __NR_mount 21 /* ok */ +#define __NR_umount 22 /* ok */ /* use only umount2 */ +#define __NR_setuid 23 /* ok */ +#define __NR_getuid 24 /* ok */ +#define __NR_stime 25 /* obsolete -> sys_settimeofday */ +#define __NR_ptrace 26 /* ok */ +#define __NR_alarm 27 /* obsolete -> sys_setitimer */ +#define __NR_oldfstat 28 /* remove */ +#define __NR_pause 29 /* obsolete -> sys_rt_sigtimedwait */ +#define __NR_utime 30 /* obsolete -> sys_utimesat */ +#define __NR_stty 31 /* remove */ +#define __NR_gtty 32 /* remove */ +#define __NR_access 33 /* faccessat */ +/* can be implemented by sys_setpriority */ +#define __NR_nice 34 +#define __NR_ftime 35 /* remove */ +#define __NR_sync 36 /* ok */ +#define __NR_kill 37 /* ok */ +#define __NR_rename 38 /* renameat */ +#define __NR_mkdir 39 /* mkdirat */ +#define __NR_rmdir 40 /* unlinkat */ +#define __NR_dup 41 /* ok */ +#define __NR_pipe 42 /* ok */ +#define __NR_times 43 /* ok */ +#define __NR_prof 44 /* remove */ +#define __NR_brk 45 /* ok -mmu, nommu specific */ +#define __NR_setgid 46 /* ok */ +#define __NR_getgid 47 /* ok */ +#define __NR_signal 48 /* obsolete -> sys_rt_sigaction */ +#define __NR_geteuid 49 /* ok */ +#define __NR_getegid 50 /* ok */ +#define __NR_acct 51 /* add it and then I can disable it */ +#define __NR_umount2 52 /* remove */ +#define __NR_lock 53 /* remove */ +#define __NR_ioctl 54 /* ok */ +#define __NR_fcntl 55 /* ok -> 64bit version*/ +#define __NR_mpx 56 /* remove */ +#define __NR_setpgid 57 /* ok */ +#define __NR_ulimit 58 /* remove */ +#define __NR_oldolduname 59 /* remove */ +#define __NR_umask 60 /* ok */ +#define __NR_chroot 61 /* ok */ +#define __NR_ustat 62 /* obsolete -> statfs64 */ +#define __NR_dup2 63 /* ok */ +#define __NR_getppid 64 /* ok */ +#define __NR_getpgrp 65 /* obsolete -> sys_getpgid */ +#define __NR_setsid 66 /* ok */ +#define __NR_sigaction 67 /* obsolete -> rt_sigaction */ +#define __NR_sgetmask 68 /* obsolete -> sys_rt_sigprocmask */ +#define __NR_ssetmask 69 /* obsolete ->sys_rt_sigprocmask */ +#define __NR_setreuid 70 /* ok */ +#define __NR_setregid 71 /* ok */ +#define __NR_sigsuspend 72 /* obsolete -> rt_sigsuspend */ +#define __NR_sigpending 73 /* obsolete -> sys_rt_sigpending */ +#define __NR_sethostname 74 /* ok */ +#define __NR_setrlimit 75 /* ok */ +#define __NR_getrlimit 76 /* ok Back compatible 2G limited rlimit */ +#define __NR_getrusage 77 /* ok */ +#define __NR_gettimeofday 78 /* ok */ +#define __NR_settimeofday 79 /* ok */ +#define __NR_getgroups 80 /* ok */ +#define __NR_setgroups 81 /* ok */ +#define __NR_select 82 /* obsolete -> sys_pselect7 */ +#define __NR_symlink 83 /* symlinkat */ +#define __NR_oldlstat 84 /* remove */ +#define __NR_readlink 85 /* obsolete -> sys_readlinkat */ +#define __NR_uselib 86 /* remove */ +#define __NR_swapon 87 /* ok */ +#define __NR_reboot 88 /* ok */ +#define __NR_readdir 89 /* remove ? */ +#define __NR_mmap 90 /* obsolete -> sys_mmap2 */ +#define __NR_munmap 91 /* ok - mmu and nommu */ +#define __NR_truncate 92 /* ok or truncate64 */ +#define __NR_ftruncate 93 /* ok or ftruncate64 */ +#define __NR_fchmod 94 /* ok */ +#define __NR_fchown 95 /* ok */ +#define __NR_getpriority 96 /* ok */ +#define __NR_setpriority 97 /* ok */ +#define __NR_profil 98 /* remove */ +#define __NR_statfs 99 /* ok or statfs64 */ +#define __NR_fstatfs 100 /* ok or fstatfs64 */ +#define __NR_ioperm 101 /* remove */ +#define __NR_socketcall 102 /* remove */ +#define __NR_syslog 103 /* ok */ +#define __NR_setitimer 104 /* ok */ +#define __NR_getitimer 105 /* ok */ +#define __NR_stat 106 /* remove */ +#define __NR_lstat 107 /* remove */ +#define __NR_fstat 108 /* remove */ +#define __NR_olduname 109 /* remove */ +#define __NR_iopl 110 /* remove */ +#define __NR_vhangup 111 /* ok */ +#define __NR_idle 112 /* remove */ +#define __NR_vm86old 113 /* remove */ +#define __NR_wait4 114 /* obsolete -> waitid */ +#define __NR_swapoff 115 /* ok */ +#define __NR_sysinfo 116 /* ok */ +#define __NR_ipc 117 /* remove - direct call */ +#define __NR_fsync 118 /* ok */ +#define __NR_sigreturn 119 /* obsolete -> sys_rt_sigreturn */ +#define __NR_clone 120 /* ok */ +#define __NR_setdomainname 121 /* ok */ +#define __NR_uname 122 /* remove */ +#define __NR_modify_ldt 123 /* remove */ +#define __NR_adjtimex 124 /* ok */ +#define __NR_mprotect 125 /* remove */ +#define __NR_sigprocmask 126 /* obsolete -> sys_rt_sigprocmask */ +#define __NR_create_module 127 /* remove */ +#define __NR_init_module 128 /* ok */ +#define __NR_delete_module 129 /* ok */ +#define __NR_get_kernel_syms 130 /* remove */ +#define __NR_quotactl 131 /* ok */ +#define __NR_getpgid 132 /* ok */ +#define __NR_fchdir 133 /* ok */ +#define __NR_bdflush 134 /* remove */ +#define __NR_sysfs 135 /* needed for busybox */ +#define __NR_personality 136 /* ok */ +#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ +#define __NR_setfsuid 138 /* ok */ +#define __NR_setfsgid 139 /* ok */ +#define __NR__llseek 140 /* remove only lseek */ +#define __NR_getdents 141 /* ok or getdents64 */ +#define __NR__newselect 142 /* remove */ +#define __NR_flock 143 /* ok */ +#define __NR_msync 144 /* remove */ +#define __NR_readv 145 /* ok */ +#define __NR_writev 146 /* ok */ +#define __NR_getsid 147 /* ok */ +#define __NR_fdatasync 148 /* ok */ +#define __NR__sysctl 149 /* remove */ +#define __NR_mlock 150 /* ok - nommu or mmu */ +#define __NR_munlock 151 /* ok - nommu or mmu */ +#define __NR_mlockall 152 /* ok - nommu or mmu */ +#define __NR_munlockall 153 /* ok - nommu or mmu */ +#define __NR_sched_setparam 154 /* ok */ +#define __NR_sched_getparam 155 /* ok */ +#define __NR_sched_setscheduler 156 /* ok */ +#define __NR_sched_getscheduler 157 /* ok */ +#define __NR_sched_yield 158 /* ok */ +#define __NR_sched_get_priority_max 159 /* ok */ +#define __NR_sched_get_priority_min 160 /* ok */ +#define __NR_sched_rr_get_interval 161 /* ok */ +#define __NR_nanosleep 162 /* ok */ +#define __NR_mremap 163 /* ok - nommu or mmu */ +#define __NR_setresuid 164 /* ok */ +#define __NR_getresuid 165 /* ok */ +#define __NR_vm86 166 /* remove */ +#define __NR_query_module 167 /* ok */ +#define __NR_poll 168 /* obsolete -> sys_ppoll */ +#define __NR_nfsservctl 169 /* ok */ +#define __NR_setresgid 170 /* ok */ +#define __NR_getresgid 171 /* ok */ +#define __NR_prctl 172 /* ok */ +#define __NR_rt_sigreturn 173 /* ok */ +#define __NR_rt_sigaction 174 /* ok */ +#define __NR_rt_sigprocmask 175 /* ok */ +#define __NR_rt_sigpending 176 /* ok */ +#define __NR_rt_sigtimedwait 177 /* ok */ +#define __NR_rt_sigqueueinfo 178 /* ok */ +#define __NR_rt_sigsuspend 179 /* ok */ +#define __NR_pread64 180 /* ok */ +#define __NR_pwrite64 181 /* ok */ +#define __NR_chown 182 /* obsolete -> fchownat */ +#define __NR_getcwd 183 /* ok */ +#define __NR_capget 184 /* ok */ +#define __NR_capset 185 /* ok */ +#define __NR_sigaltstack 186 /* remove */ +#define __NR_sendfile 187 /* ok -> exist 64bit version*/ +#define __NR_getpmsg 188 /* remove */ +/* remove - some people actually want streams */ +#define __NR_putpmsg 189 +/* for noMMU - group with clone -> maybe remove */ +#define __NR_vfork 190 +#define __NR_ugetrlimit 191 /* remove - SuS compliant getrlimit */ +#define __NR_mmap2 192 /* ok */ +#define __NR_truncate64 193 /* ok */ +#define __NR_ftruncate64 194 /* ok */ +#define __NR_stat64 195 /* remove _ARCH_WANT_STAT64 */ +#define __NR_lstat64 196 /* remove _ARCH_WANT_STAT64 */ +#define __NR_fstat64 197 /* remove _ARCH_WANT_STAT64 */ +#define __NR_lchown32 198 /* ok - without 32 */ +#define __NR_getuid32 199 /* ok - without 32 */ +#define __NR_getgid32 200 /* ok - without 32 */ +#define __NR_geteuid32 201 /* ok - without 32 */ +#define __NR_getegid32 202 /* ok - without 32 */ +#define __NR_setreuid32 203 /* ok - without 32 */ +#define __NR_setregid32 204 /* ok - without 32 */ +#define __NR_getgroups32 205 /* ok - without 32 */ +#define __NR_setgroups32 206 /* ok - without 32 */ +#define __NR_fchown32 207 /* ok - without 32 */ +#define __NR_setresuid32 208 /* ok - without 32 */ +#define __NR_getresuid32 209 /* ok - without 32 */ +#define __NR_setresgid32 210 /* ok - without 32 */ +#define __NR_getresgid32 211 /* ok - without 32 */ +#define __NR_chown32 212 /* ok - without 32 -obsolete -> fchownat */ +#define __NR_setuid32 213 /* ok - without 32 */ +#define __NR_setgid32 214 /* ok - without 32 */ +#define __NR_setfsuid32 215 /* ok - without 32 */ +#define __NR_setfsgid32 216 /* ok - without 32 */ +#define __NR_pivot_root 217 /* ok */ +#define __NR_mincore 218 /* ok */ +#define __NR_madvise 219 /* ok */ +#define __NR_getdents64 220 /* ok */ +#define __NR_fcntl64 221 /* ok */ +/* 223 is unused */ +#define __NR_gettid 224 /* ok */ +#define __NR_readahead 225 /* ok */ +#define __NR_setxattr 226 /* ok */ +#define __NR_lsetxattr 227 /* ok */ +#define __NR_fsetxattr 228 /* ok */ +#define __NR_getxattr 229 /* ok */ +#define __NR_lgetxattr 230 /* ok */ +#define __NR_fgetxattr 231 /* ok */ +#define __NR_listxattr 232 /* ok */ +#define __NR_llistxattr 233 /* ok */ +#define __NR_flistxattr 234 /* ok */ +#define __NR_removexattr 235 /* ok */ +#define __NR_lremovexattr 236 /* ok */ +#define __NR_fremovexattr 237 /* ok */ +#define __NR_tkill 238 /* ok */ +#define __NR_sendfile64 239 /* ok */ +#define __NR_futex 240 /* ok */ +#define __NR_sched_setaffinity 241 /* ok */ +#define __NR_sched_getaffinity 242 /* ok */ +#define __NR_set_thread_area 243 /* remove */ +#define __NR_get_thread_area 244 /* remove */ +#define __NR_io_setup 245 /* ok */ +#define __NR_io_destroy 246 /* ok */ +#define __NR_io_getevents 247 /* ok */ +#define __NR_io_submit 248 /* ok */ +#define __NR_io_cancel 249 /* ok */ +#define __NR_fadvise64 250 /* remove -> sys_fadvise64_64 */ +/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */ +#define __NR_exit_group 252 /* ok */ +#define __NR_lookup_dcookie 253 /* ok */ +#define __NR_epoll_create 254 /* ok */ +#define __NR_epoll_ctl 255 /* ok */ +#define __NR_epoll_wait 256 /* obsolete -> sys_epoll_pwait */ +#define __NR_remap_file_pages 257 /* only for mmu */ +#define __NR_set_tid_address 258 /* ok */ +#define __NR_timer_create 259 /* ok */ +#define __NR_timer_settime (__NR_timer_create+1) /* 260 */ /* ok */ +#define __NR_timer_gettime (__NR_timer_create+2) /* 261 */ /* ok */ +#define __NR_timer_getoverrun (__NR_timer_create+3) /* 262 */ /* ok */ +#define __NR_timer_delete (__NR_timer_create+4) /* 263 */ /* ok */ +#define __NR_clock_settime (__NR_timer_create+5) /* 264 */ /* ok */ +#define __NR_clock_gettime (__NR_timer_create+6) /* 265 */ /* ok */ +#define __NR_clock_getres (__NR_timer_create+7) /* 266 */ /* ok */ +#define __NR_clock_nanosleep (__NR_timer_create+8) /* 267 */ /* ok */ +#define __NR_statfs64 268 /* ok */ +#define __NR_fstatfs64 269 /* ok */ +#define __NR_tgkill 270 /* ok */ +#define __NR_utimes 271 /* obsolete -> sys_futimesat */ +#define __NR_fadvise64_64 272 /* ok */ +#define __NR_vserver 273 /* ok */ +#define __NR_mbind 274 /* only for mmu */ +#define __NR_get_mempolicy 275 /* only for mmu */ +#define __NR_set_mempolicy 276 /* only for mmu */ +#define __NR_mq_open 277 /* ok */ +#define __NR_mq_unlink (__NR_mq_open+1) /* 278 */ /* ok */ +#define __NR_mq_timedsend (__NR_mq_open+2) /* 279 */ /* ok */ +#define __NR_mq_timedreceive (__NR_mq_open+3) /* 280 */ /* ok */ +#define __NR_mq_notify (__NR_mq_open+4) /* 281 */ /* ok */ +#define __NR_mq_getsetattr (__NR_mq_open+5) /* 282 */ /* ok */ +#define __NR_kexec_load 283 /* ok */ +#define __NR_waitid 284 /* ok */ +/* #define __NR_sys_setaltroot 285 */ +#define __NR_add_key 286 /* ok */ +#define __NR_request_key 287 /* ok */ +#define __NR_keyctl 288 /* ok */ +#define __NR_ioprio_set 289 /* ok */ +#define __NR_ioprio_get 290 /* ok */ +#define __NR_inotify_init 291 /* ok */ +#define __NR_inotify_add_watch 292 /* ok */ +#define __NR_inotify_rm_watch 293 /* ok */ +#define __NR_migrate_pages 294 /* mmu */ +#define __NR_openat 295 /* ok */ +#define __NR_mkdirat 296 /* ok */ +#define __NR_mknodat 297 /* ok */ +#define __NR_fchownat 298 /* ok */ +#define __NR_futimesat 299 /* obsolete -> sys_utimesat */ +#define __NR_fstatat64 300 /* stat64 */ +#define __NR_unlinkat 301 /* ok */ +#define __NR_renameat 302 /* ok */ +#define __NR_linkat 303 /* ok */ +#define __NR_symlinkat 304 /* ok */ +#define __NR_readlinkat 305 /* ok */ +#define __NR_fchmodat 306 /* ok */ +#define __NR_faccessat 307 /* ok */ +#define __NR_pselect6 308 /* obsolete -> sys_pselect7 */ +#define __NR_ppoll 309 /* ok */ +#define __NR_unshare 310 /* ok */ +#define __NR_set_robust_list 311 /* ok */ +#define __NR_get_robust_list 312 /* ok */ +#define __NR_splice 313 /* ok */ +#define __NR_sync_file_range 314 /* ok */ +#define __NR_tee 315 /* ok */ +#define __NR_vmsplice 316 /* ok */ +#define __NR_move_pages 317 /* mmu */ +#define __NR_getcpu 318 /* ok */ +#define __NR_epoll_pwait 319 /* ok */ +#define __NR_utimensat 320 /* ok */ +#define __NR_signalfd 321 /* ok */ +#define __NR_timerfd_create 322 /* ok */ +#define __NR_eventfd 323 /* ok */ +#define __NR_fallocate 324 /* ok */ +#define __NR_semtimedop 325 /* ok - semaphore group */ +#define __NR_timerfd_settime 326 /* ok */ +#define __NR_timerfd_gettime 327 /* ok */ +/* sysv ipc syscalls */ +#define __NR_semctl 328 /* ok */ +#define __NR_semget 329 /* ok */ +#define __NR_semop 330 /* ok */ +#define __NR_msgctl 331 /* ok */ +#define __NR_msgget 332 /* ok */ +#define __NR_msgrcv 333 /* ok */ +#define __NR_msgsnd 334 /* ok */ +#define __NR_shmat 335 /* ok */ +#define __NR_shmctl 336 /* ok */ +#define __NR_shmdt 337 /* ok */ +#define __NR_shmget 338 /* ok */ + + +#define __NR_signalfd4 339 /* new */ +#define __NR_eventfd2 340 /* new */ +#define __NR_epoll_create1 341 /* new */ +#define __NR_dup3 342 /* new */ +#define __NR_pipe2 343 /* new */ +#define __NR_inotify_init1 344 /* new */ +#define __NR_socket 345 /* new */ +#define __NR_socketpair 346 /* new */ +#define __NR_bind 347 /* new */ +#define __NR_listen 348 /* new */ +#define __NR_accept 349 /* new */ +#define __NR_connect 350 /* new */ +#define __NR_getsockname 351 /* new */ +#define __NR_getpeername 352 /* new */ +#define __NR_sendto 353 /* new */ +#define __NR_send 354 /* new */ +#define __NR_recvfrom 355 /* new */ +#define __NR_recv 356 /* new */ +#define __NR_setsockopt 357 /* new */ +#define __NR_getsockopt 358 /* new */ +#define __NR_shutdown 359 /* new */ +#define __NR_sendmsg 360 /* new */ +#define __NR_recvmsg 361 /* new */ +#define __NR_accept04 362 /* new */ + +#define __NR_syscalls 363 + +#ifdef __KERNEL__ +#ifndef __ASSEMBLY__ + +#define __ARCH_WANT_IPC_PARSE_VERSION +/* #define __ARCH_WANT_OLD_READDIR */ +/* #define __ARCH_WANT_OLD_STAT */ +#define __ARCH_WANT_STAT64 +#define __ARCH_WANT_SYS_ALARM +#define __ARCH_WANT_SYS_GETHOSTNAME +#define __ARCH_WANT_SYS_PAUSE +#define __ARCH_WANT_SYS_SGETMASK +#define __ARCH_WANT_SYS_SIGNAL +#define __ARCH_WANT_SYS_TIME +#define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_WAITPID +#define __ARCH_WANT_SYS_SOCKETCALL +#define __ARCH_WANT_SYS_FADVISE64 +#define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK +#define __ARCH_WANT_SYS_NICE +/* #define __ARCH_WANT_SYS_OLD_GETRLIMIT */ +#define __ARCH_WANT_SYS_OLDUMOUNT +#define __ARCH_WANT_SYS_SIGPENDING +#define __ARCH_WANT_SYS_SIGPROCMASK +#define __ARCH_WANT_SYS_RT_SIGACTION +/* #define __ARCH_WANT_SYS_RT_SIGSUSPEND */ + +/* + * "Conditional" syscalls + * + * What we want is __attribute__((weak,alias("sys_ni_syscall"))), + * but it doesn't work on all toolchains, so we just do it by hand + */ +#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall"); + +#endif /* __ASSEMBLY__ */ +#endif /* __KERNEL__ */ +#endif /* _ASM_MICROBLAZE_UNISTD_H */ diff --git a/arch/microblaze/include/asm/user.h b/arch/microblaze/include/asm/user.h new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/arch/microblaze/include/asm/user.h @@ -0,0 +1 @@ + diff --git a/arch/microblaze/include/asm/vga.h b/arch/microblaze/include/asm/vga.h new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/arch/microblaze/include/asm/vga.h @@ -0,0 +1 @@ + diff --git a/arch/microblaze/include/asm/xor.h b/arch/microblaze/include/asm/xor.h new file mode 100644 index 00000000000..c82eb12a5b1 --- /dev/null +++ b/arch/microblaze/include/asm/xor.h @@ -0,0 +1 @@ +#include <asm-generic/xor.h> diff --git a/arch/microblaze/kernel/Makefile b/arch/microblaze/kernel/Makefile new file mode 100644 index 00000000000..da94bec4ecb --- /dev/null +++ b/arch/microblaze/kernel/Makefile @@ -0,0 +1,19 @@ +# +# Makefile +# + +extra-y := head.o vmlinux.lds + +obj-y += exceptions.o \ + hw_exception_handler.o init_task.o intc.o irq.o of_device.o \ + of_platform.o process.o prom.o prom_parse.o ptrace.o \ + setup.o signal.o sys_microblaze.o timer.o traps.o + +obj-y += cpu/ + +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +obj-$(CONFIG_SELFMOD) += selfmod.o +obj-$(CONFIG_HEART_BEAT) += heartbeat.o +obj-$(CONFIG_MODULES) += microblaze_ksyms.o module.o + +obj-y += entry$(MMUEXT).o diff --git a/arch/microblaze/kernel/asm-offsets.c b/arch/microblaze/kernel/asm-offsets.c new file mode 100644 index 00000000000..38e1a2e8ad0 --- /dev/null +++ b/arch/microblaze/kernel/asm-offsets.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/init.h> +#include <linux/stddef.h> +#include <linux/sched.h> +#include <linux/kernel_stat.h> +#include <linux/ptrace.h> +#include <linux/hardirq.h> +#include <linux/thread_info.h> +#include <linux/kbuild.h> + +int main(int argc, char *argv[]) +{ + /* struct pt_regs */ + DEFINE(PT_SIZE, sizeof(struct pt_regs)); + DEFINE(PT_MSR, offsetof(struct pt_regs, msr)); + DEFINE(PT_EAR, offsetof(struct pt_regs, ear)); + DEFINE(PT_ESR, offsetof(struct pt_regs, esr)); + DEFINE(PT_FSR, offsetof(struct pt_regs, fsr)); + DEFINE(PT_PC, offsetof(struct pt_regs, pc)); + DEFINE(PT_R0, offsetof(struct pt_regs, r0)); + DEFINE(PT_R1, offsetof(struct pt_regs, r1)); + DEFINE(PT_R2, offsetof(struct pt_regs, r2)); + DEFINE(PT_R3, offsetof(struct pt_regs, r3)); + DEFINE(PT_R4, offsetof(struct pt_regs, r4)); + DEFINE(PT_R5, offsetof(struct pt_regs, r5)); + DEFINE(PT_R6, offsetof(struct pt_regs, r6)); + DEFINE(PT_R7, offsetof(struct pt_regs, r7)); + DEFINE(PT_R8, offsetof(struct pt_regs, r8)); + DEFINE(PT_R9, offsetof(struct pt_regs, r9)); + DEFINE(PT_R10, offsetof(struct pt_regs, r10)); + DEFINE(PT_R11, offsetof(struct pt_regs, r11)); + DEFINE(PT_R12, offsetof(struct pt_regs, r12)); + DEFINE(PT_R13, offsetof(struct pt_regs, r13)); + DEFINE(PT_R14, offsetof(struct pt_regs, r14)); + DEFINE(PT_R15, offsetof(struct pt_regs, r15)); + DEFINE(PT_R16, offsetof(struct pt_regs, r16)); + DEFINE(PT_R17, offsetof(struct pt_regs, r17)); + DEFINE(PT_R18, offsetof(struct pt_regs, r18)); + DEFINE(PT_R19, offsetof(struct pt_regs, r19)); + DEFINE(PT_R20, offsetof(struct pt_regs, r20)); + DEFINE(PT_R21, offsetof(struct pt_regs, r21)); + DEFINE(PT_R22, offsetof(struct pt_regs, r22)); + DEFINE(PT_R23, offsetof(struct pt_regs, r23)); + DEFINE(PT_R24, offsetof(struct pt_regs, r24)); + DEFINE(PT_R25, offsetof(struct pt_regs, r25)); + DEFINE(PT_R26, offsetof(struct pt_regs, r26)); + DEFINE(PT_R27, offsetof(struct pt_regs, r27)); + DEFINE(PT_R28, offsetof(struct pt_regs, r28)); + DEFINE(PT_R29, offsetof(struct pt_regs, r29)); + DEFINE(PT_R30, offsetof(struct pt_regs, r30)); + DEFINE(PT_R31, offsetof(struct pt_regs, r31)); + DEFINE(PT_MODE, offsetof(struct pt_regs, kernel_mode)); + BLANK(); + + /* Magic offsets for PTRACE PEEK/POKE etc */ + DEFINE(PT_TEXT_ADDR, sizeof(struct pt_regs) + 1); + DEFINE(PT_TEXT_LEN, sizeof(struct pt_regs) + 2); + DEFINE(PT_DATA_ADDR, sizeof(struct pt_regs) + 3); + BLANK(); + + /* struct task_struct */ + DEFINE(TS_THREAD_INFO, offsetof(struct task_struct, stack)); + + /* struct thread_info */ + DEFINE(TI_TASK, offsetof(struct thread_info, task)); + DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); + DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); + DEFINE(TI_STATUS, offsetof(struct thread_info, status)); + DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); + DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); + DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); + DEFINE(TI_RESTART_BLOCK, offsetof(struct thread_info, restart_block)); + DEFINE(TI_CPU_CONTEXT, offsetof(struct thread_info, cpu_context)); + BLANK(); + + /* struct cpu_context */ + DEFINE(CC_R1, offsetof(struct cpu_context, r1)); /* r1 */ + DEFINE(CC_R2, offsetof(struct cpu_context, r2)); + /* dedicated registers */ + DEFINE(CC_R13, offsetof(struct cpu_context, r13)); + DEFINE(CC_R14, offsetof(struct cpu_context, r14)); + DEFINE(CC_R15, offsetof(struct cpu_context, r15)); + DEFINE(CC_R16, offsetof(struct cpu_context, r16)); + DEFINE(CC_R17, offsetof(struct cpu_context, r17)); + DEFINE(CC_R18, offsetof(struct cpu_context, r18)); + /* non-volatile registers */ + DEFINE(CC_R19, offsetof(struct cpu_context, r19)); + DEFINE(CC_R20, offsetof(struct cpu_context, r20)); + DEFINE(CC_R21, offsetof(struct cpu_context, r21)); + DEFINE(CC_R22, offsetof(struct cpu_context, r22)); + DEFINE(CC_R23, offsetof(struct cpu_context, r23)); + DEFINE(CC_R24, offsetof(struct cpu_context, r24)); + DEFINE(CC_R25, offsetof(struct cpu_context, r25)); + DEFINE(CC_R26, offsetof(struct cpu_context, r26)); + DEFINE(CC_R27, offsetof(struct cpu_context, r27)); + DEFINE(CC_R28, offsetof(struct cpu_context, r28)); + DEFINE(CC_R29, offsetof(struct cpu_context, r29)); + DEFINE(CC_R30, offsetof(struct cpu_context, r30)); + /* special purpose registers */ + DEFINE(CC_MSR, offsetof(struct cpu_context, msr)); + DEFINE(CC_EAR, offsetof(struct cpu_context, ear)); + DEFINE(CC_ESR, offsetof(struct cpu_context, esr)); + DEFINE(CC_FSR, offsetof(struct cpu_context, fsr)); + BLANK(); + + return 0; +} diff --git a/arch/microblaze/kernel/cpu/Makefile b/arch/microblaze/kernel/cpu/Makefile new file mode 100644 index 00000000000..20646e54927 --- /dev/null +++ b/arch/microblaze/kernel/cpu/Makefile @@ -0,0 +1,8 @@ +# +# Build the appropriate CPU version support +# + +EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \ + -DCPU_REV=$(CPU_REV) + +obj-y += cache.o cpuinfo.o cpuinfo-pvr-full.o cpuinfo-static.o mb.o pvr.o diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c new file mode 100644 index 00000000000..be9fecca4f9 --- /dev/null +++ b/arch/microblaze/kernel/cpu/cache.c @@ -0,0 +1,258 @@ +/* + * Cache control for MicroBlaze cache memories + * + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2007 John Williams <john.williams@petalogix.com> + * + * 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. + */ + +#include <asm/cacheflush.h> +#include <linux/cache.h> +#include <asm/cpuinfo.h> + +/* Exported functions */ + +void _enable_icache(void) +{ + if (cpuinfo.use_icache) { +#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR + __asm__ __volatile__ (" \ + msrset r0, %0; \ + nop; " \ + : \ + : "i" (MSR_ICE) \ + : "memory"); +#else + __asm__ __volatile__ (" \ + mfs r12, rmsr; \ + nop; \ + ori r12, r12, %0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_ICE) \ + : "memory", "r12"); +#endif + } +} + +void _disable_icache(void) +{ + if (cpuinfo.use_icache) { +#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR + __asm__ __volatile__ (" \ + msrclr r0, %0; \ + nop; " \ + : \ + : "i" (MSR_ICE) \ + : "memory"); +#else + __asm__ __volatile__ (" \ + mfs r12, rmsr; \ + nop; \ + andi r12, r12, ~%0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_ICE) \ + : "memory", "r12"); +#endif + } +} + +void _invalidate_icache(unsigned int addr) +{ + if (cpuinfo.use_icache) { + __asm__ __volatile__ (" \ + wic %0, r0" \ + : \ + : "r" (addr)); + } +} + +void _enable_dcache(void) +{ + if (cpuinfo.use_dcache) { +#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR + __asm__ __volatile__ (" \ + msrset r0, %0; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ + : "memory"); +#else + __asm__ __volatile__ (" \ + mfs r12, rmsr; \ + nop; \ + ori r12, r12, %0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ + : "memory", "r12"); +#endif + } +} + +void _disable_dcache(void) +{ + if (cpuinfo.use_dcache) { +#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR + __asm__ __volatile__ (" \ + msrclr r0, %0; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ + : "memory"); +#else + __asm__ __volatile__ (" \ + mfs r12, rmsr; \ + nop; \ + andi r12, r12, ~%0; \ + mts rmsr, r12; \ + nop; " \ + : \ + : "i" (MSR_DCE) \ + : "memory", "r12"); +#endif + } +} + +void _invalidate_dcache(unsigned int addr) +{ + if (cpuinfo.use_dcache) + __asm__ __volatile__ (" \ + wdc %0, r0" \ + : \ + : "r" (addr)); +} + +void __invalidate_icache_all(void) +{ + unsigned int i; + unsigned flags; + + if (cpuinfo.use_icache) { + local_irq_save(flags); + __disable_icache(); + + /* Just loop through cache size and invalidate, no need to add + CACHE_BASE address */ + for (i = 0; i < cpuinfo.icache_size; + i += cpuinfo.icache_line) + __invalidate_icache(i); + + __enable_icache(); + local_irq_restore(flags); + } +} + +void __invalidate_icache_range(unsigned long start, unsigned long end) +{ + unsigned int i; + unsigned flags; + unsigned int align; + + if (cpuinfo.use_icache) { + /* + * No need to cover entire cache range, + * just cover cache footprint + */ + end = min(start + cpuinfo.icache_size, end); + align = ~(cpuinfo.icache_line - 1); + start &= align; /* Make sure we are aligned */ + /* Push end up to the next cache line */ + end = ((end & align) + cpuinfo.icache_line); + + local_irq_save(flags); + __disable_icache(); + + for (i = start; i < end; i += cpuinfo.icache_line) + __invalidate_icache(i); + + __enable_icache(); + local_irq_restore(flags); + } +} + +void __invalidate_icache_page(struct vm_area_struct *vma, struct page *page) +{ + __invalidate_icache_all(); +} + +void __invalidate_icache_user_range(struct vm_area_struct *vma, + struct page *page, unsigned long adr, + int len) +{ + __invalidate_icache_all(); +} + +void __invalidate_cache_sigtramp(unsigned long addr) +{ + __invalidate_icache_range(addr, addr + 8); +} + +void __invalidate_dcache_all(void) +{ + unsigned int i; + unsigned flags; + + if (cpuinfo.use_dcache) { + local_irq_save(flags); + __disable_dcache(); + + /* + * Just loop through cache size and invalidate, + * no need to add CACHE_BASE address + */ + for (i = 0; i < cpuinfo.dcache_size; + i += cpuinfo.dcache_line) + __invalidate_dcache(i); + + __enable_dcache(); + local_irq_restore(flags); + } +} + +void __invalidate_dcache_range(unsigned long start, unsigned long end) +{ + unsigned int i; + unsigned flags; + unsigned int align; + + if (cpuinfo.use_dcache) { + /* + * No need to cover entire cache range, + * just cover cache footprint + */ + end = min(start + cpuinfo.dcache_size, end); + align = ~(cpuinfo.dcache_line - 1); + start &= align; /* Make sure we are aligned */ + /* Push end up to the next cache line */ + end = ((end & align) + cpuinfo.dcache_line); + local_irq_save(flags); + __disable_dcache(); + + for (i = start; i < end; i += cpuinfo.dcache_line) + __invalidate_dcache(i); + + __enable_dcache(); + local_irq_restore(flags); + } +} + +void __invalidate_dcache_page(struct vm_area_struct *vma, struct page *page) +{ + __invalidate_dcache_all(); +} + +void __invalidate_dcache_user_range(struct vm_area_struct *vma, + struct page *page, unsigned long adr, + int len) +{ + __invalidate_dcache_all(); +} diff --git a/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c new file mode 100644 index 00000000000..cf7424a6bb8 --- /dev/null +++ b/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c @@ -0,0 +1,101 @@ +/* + * Support for MicroBlaze PVR (processor version register) + * + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2007 John Williams <john.williams@petalogix.com> + * + * 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. + */ + +#include <linux/init.h> +#include <linux/string.h> +#include <asm/pvr.h> +#include <asm/cpuinfo.h> + +/* + * Helper macro to map between fields in our struct cpuinfo, and + * the PVR macros in pvr.h. + */ + +#define CI(c, p) { ci->c = PVR_##p(pvr); } +#define err_printk(x) \ + early_printk("ERROR: Microblaze " x " - different for PVR and DTS\n"); + +void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) +{ + struct pvr_s pvr; + int temp; /* for saving temp value */ + get_pvr(&pvr); + + temp = PVR_USE_BARREL(pvr) | PVR_USE_MSR_INSTR(pvr) |\ + PVR_USE_PCMP_INSTR(pvr) | PVR_USE_DIV(pvr); + if (ci->use_instr != temp) + err_printk("BARREL, MSR, PCMP or DIV"); + ci->use_instr = temp; + + temp = PVR_USE_HW_MUL(pvr) | PVR_USE_MUL64(pvr); + if (ci->use_mult != temp) + err_printk("HW_MUL"); + ci->use_mult = temp; + + temp = PVR_USE_FPU(pvr) | PVR_USE_FPU2(pvr); + if (ci->use_fpu != temp) + err_printk("HW_FPU"); + ci->use_fpu = temp; + + ci->use_exc = PVR_OPCODE_0x0_ILLEGAL(pvr) |\ + PVR_UNALIGNED_EXCEPTION(pvr) |\ + PVR_ILL_OPCODE_EXCEPTION(pvr) |\ + PVR_IOPB_BUS_EXCEPTION(pvr) |\ + PVR_DOPB_BUS_EXCEPTION(pvr) |\ + PVR_DIV_ZERO_EXCEPTION(pvr) |\ + PVR_FPU_EXCEPTION(pvr) |\ + PVR_FSL_EXCEPTION(pvr); + + CI(pvr_user1, USER1); + CI(pvr_user2, USER2); + + CI(mmu, USE_MMU); + + CI(ver_code, VERSION); + + CI(use_icache, USE_ICACHE); + CI(icache_tagbits, ICACHE_ADDR_TAG_BITS); + CI(icache_write, ICACHE_ALLOW_WR); + CI(icache_line, ICACHE_LINE_LEN); + CI(icache_size, ICACHE_BYTE_SIZE); + CI(icache_base, ICACHE_BASEADDR); + CI(icache_high, ICACHE_HIGHADDR); + + CI(use_dcache, USE_DCACHE); + CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS); + CI(dcache_write, DCACHE_ALLOW_WR); + CI(dcache_line, DCACHE_LINE_LEN); + CI(dcache_size, DCACHE_BYTE_SIZE); + CI(dcache_base, DCACHE_BASEADDR); + CI(dcache_high, DCACHE_HIGHADDR); + + CI(use_dopb, D_OPB); + CI(use_iopb, I_OPB); + CI(use_dlmb, D_LMB); + CI(use_ilmb, I_LMB); + CI(num_fsl, FSL_LINKS); + + CI(irq_edge, INTERRUPT_IS_EDGE); + CI(irq_positive, EDGE_IS_POSITIVE); + + CI(area_optimised, AREA_OPTIMISED); + + CI(hw_debug, DEBUG_ENABLED); + CI(num_pc_brk, NUMBER_OF_PC_BRK); + CI(num_rd_brk, NUMBER_OF_RD_ADDR_BRK); + CI(num_wr_brk, NUMBER_OF_WR_ADDR_BRK); + + CI(fpga_family_code, TARGET_FAMILY); + + /* take timebase-frequency from DTS */ + ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency"); +} diff --git a/arch/microblaze/kernel/cpu/cpuinfo-static.c b/arch/microblaze/kernel/cpu/cpuinfo-static.c new file mode 100644 index 00000000000..cfe44effdb7 --- /dev/null +++ b/arch/microblaze/kernel/cpu/cpuinfo-static.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2007 John Williams <john.williams@petalogix.com> + * + * 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. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/string.h> +#include <asm/cpuinfo.h> +#include <asm/pvr.h> + +const static char family_string[] = CONFIG_XILINX_MICROBLAZE0_FAMILY; +const static char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER; + +#define err_printk(x) \ + early_printk("ERROR: Microblaze " x "- different for kernel and DTS\n"); + +void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu) +{ + int i = 0; + + ci->use_instr = + (fcpu(cpu, "xlnx,use-barrel") ? PVR0_USE_BARREL_MASK : 0) | + (fcpu(cpu, "xlnx,use-msr-instr") ? PVR2_USE_MSR_INSTR : 0) | + (fcpu(cpu, "xlnx,use-pcmp-instr") ? PVR2_USE_PCMP_INSTR : 0) | + (fcpu(cpu, "xlnx,use-div") ? PVR0_USE_DIV_MASK : 0); + if (CONFIG_XILINX_MICROBLAZE0_USE_BARREL) + i |= PVR0_USE_BARREL_MASK; + if (CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR) + i |= PVR2_USE_MSR_INSTR; + if (CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR) + i |= PVR2_USE_PCMP_INSTR; + if (CONFIG_XILINX_MICROBLAZE0_USE_DIV) + i |= PVR0_USE_DIV_MASK; + if (ci->use_instr != i) + err_printk("BARREL, MSR, PCMP or DIV"); + + ci->use_mult = fcpu(cpu, "xlnx,use-hw-mul"); + if (ci->use_mult != CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL) + err_printk("HW_MUL"); + ci->use_mult = + (ci->use_mult > 1 ? + (PVR2_USE_MUL64_MASK | PVR0_USE_HW_MUL_MASK) : + (ci->use_mult == 1 ? PVR0_USE_HW_MUL_MASK : 0)); + + ci->use_fpu = fcpu(cpu, "xlnx,use-fpu"); + if (ci->use_fpu != CONFIG_XILINX_MICROBLAZE0_USE_FPU) + err_printk("HW_FPU"); + ci->use_fpu = (ci->use_fpu > 1 ? + (PVR2_USE_FPU2_MASK | PVR0_USE_FPU_MASK) : + (ci->use_fpu == 1 ? PVR0_USE_FPU_MASK : 0)); + + ci->use_exc = + (fcpu(cpu, "xlnx,unaligned-exceptions") ? + PVR2_UNALIGNED_EXC_MASK : 0) | + (fcpu(cpu, "xlnx,ill-opcode-exception") ? + PVR2_ILL_OPCODE_EXC_MASK : 0) | + (fcpu(cpu, "xlnx,iopb-bus-exception") ? + PVR2_IOPB_BUS_EXC_MASK : 0) | + (fcpu(cpu, "xlnx,dopb-bus-exception") ? + PVR2_DOPB_BUS_EXC_MASK : 0) | + (fcpu(cpu, "xlnx,div-zero-exception") ? + PVR2_DIV_ZERO_EXC_MASK : 0) | + (fcpu(cpu, "xlnx,fpu-exception") ? PVR2_FPU_EXC_MASK : 0) | + (fcpu(cpu, "xlnx,fsl-exception") ? PVR2_USE_EXTEND_FSL : 0); + + ci->use_icache = fcpu(cpu, "xlnx,use-icache"); + ci->icache_tagbits = fcpu(cpu, "xlnx,addr-tag-bits"); + ci->icache_write = fcpu(cpu, "xlnx,allow-icache-wr"); + ci->icache_line = fcpu(cpu, "xlnx,icache-line-len") << 2; + if (!ci->icache_line) { + if (fcpu(cpu, "xlnx,icache-use-fsl")) + ci->icache_line = 4 << 2; + else + ci->icache_line = 1 << 2; + } + ci->icache_size = fcpu(cpu, "i-cache-size"); + ci->icache_base = fcpu(cpu, "i-cache-baseaddr"); + ci->icache_high = fcpu(cpu, "i-cache-highaddr"); + + ci->use_dcache = fcpu(cpu, "xlnx,use-dcache"); + ci->dcache_tagbits = fcpu(cpu, "xlnx,dcache-addr-tag"); + ci->dcache_write = fcpu(cpu, "xlnx,allow-dcache-wr"); + ci->dcache_line = fcpu(cpu, "xlnx,dcache-line-len") << 2; + if (!ci->dcache_line) { + if (fcpu(cpu, "xlnx,dcache-use-fsl")) + ci->dcache_line = 4 << 2; + else + ci->dcache_line = 1 << 2; + } + ci->dcache_size = fcpu(cpu, "d-cache-size"); + ci->dcache_base = fcpu(cpu, "d-cache-baseaddr"); + ci->dcache_high = fcpu(cpu, "d-cache-highaddr"); + + ci->use_dopb = fcpu(cpu, "xlnx,d-opb"); + ci->use_iopb = fcpu(cpu, "xlnx,i-opb"); + ci->use_dlmb = fcpu(cpu, "xlnx,d-lmb"); + ci->use_ilmb = fcpu(cpu, "xlnx,i-lmb"); + + ci->num_fsl = fcpu(cpu, "xlnx,fsl-links"); + ci->irq_edge = fcpu(cpu, "xlnx,interrupt-is-edge"); + ci->irq_positive = fcpu(cpu, "xlnx,edge-is-positive"); + ci->area_optimised = 0; + + ci->hw_debug = fcpu(cpu, "xlnx,debug-enabled"); + ci->num_pc_brk = fcpu(cpu, "xlnx,number-of-pc-brk"); + ci->num_rd_brk = fcpu(cpu, "xlnx,number-of-rd-addr-brk"); + ci->num_wr_brk = fcpu(cpu, "xlnx,number-of-wr-addr-brk"); + + ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency"); + + ci->pvr_user1 = fcpu(cpu, "xlnx,pvr-user1"); + ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2"); + + ci->mmu = fcpu(cpu, "xlnx,use-mmu"); + + ci->ver_code = 0; + ci->fpga_family_code = 0; + + /* Do various fixups based on CPU version and FPGA family strings */ + + /* Resolved the CPU version code */ + for (i = 0; cpu_ver_lookup[i].s != NULL; i++) { + if (strcmp(cpu_ver_lookup[i].s, cpu_ver_string) == 0) + ci->ver_code = cpu_ver_lookup[i].k; + } + + /* Resolved the fpga family code */ + for (i = 0; family_string_lookup[i].s != NULL; i++) { + if (strcmp(family_string_lookup[i].s, family_string) == 0) + ci->fpga_family_code = family_string_lookup[i].k; + } + + /* FIXME - mb3 and spartan2 do not exist in PVR */ + /* This is mb3 and on a non Spartan2 */ + if (ci->ver_code == 0x20 && ci->fpga_family_code != 0xf0) + /* Hardware Multiplier in use */ + ci->use_mult = 1; +} diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c new file mode 100644 index 00000000000..4a740dfcf6d --- /dev/null +++ b/arch/microblaze/kernel/cpu/cpuinfo.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2007 John Williams <john.williams@petalogix.com> + * + * 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. + */ + +#include <linux/init.h> +#include <linux/slab.h> +#include <asm/cpuinfo.h> +#include <asm/pvr.h> + +const struct cpu_ver_key cpu_ver_lookup[] = { + /* These key value are as per MBV field in PVR0 */ + {"5.00.a", 0x01}, + {"5.00.b", 0x02}, + {"5.00.c", 0x03}, + {"6.00.a", 0x04}, + {"6.00.b", 0x06}, + {"7.00.a", 0x05}, + {"7.00.b", 0x07}, + {"7.10.a", 0x08}, + {"7.10.b", 0x09}, + {"7.10.c", 0x0a}, + {"7.10.d", 0x0b}, + /* FIXME There is no keycode defined in MBV for these versions */ + {"2.10.a", 0x10}, + {"3.00.a", 0x20}, + {"4.00.a", 0x30}, + {"4.00.b", 0x40}, + {NULL, 0}, +}; + +/* + * FIXME Not sure if the actual key is defined by Xilinx in the PVR + */ +const struct family_string_key family_string_lookup[] = { + {"virtex2", 0x4}, + {"virtex2pro", 0x5}, + {"spartan3", 0x6}, + {"virtex4", 0x7}, + {"virtex5", 0x8}, + {"spartan3e", 0x9}, + {"spartan3a", 0xa}, + {"spartan3an", 0xb}, + {"spartan3adsp", 0xc}, + /* FIXME There is no key code defined for spartan2 */ + {"spartan2", 0xf0}, + {NULL, 0}, +}; + +struct cpuinfo cpuinfo; + +void __init setup_cpuinfo(void) +{ + struct device_node *cpu = NULL; + + cpu = (struct device_node *) of_find_node_by_type(NULL, "cpu"); + if (!cpu) + printk(KERN_ERR "You don't have cpu!!!\n"); + + printk(KERN_INFO "%s: initialising\n", __func__); + + switch (cpu_has_pvr()) { + case 0: + printk(KERN_WARNING + "%s: No PVR support. Using static CPU info from FDT\n", + __func__); + set_cpuinfo_static(&cpuinfo, cpu); + break; +/* FIXME I found weird behavior with MB 7.00.a/b + * please do not use FULL PVR with MMU */ + case 1: + printk(KERN_INFO "%s: Using full CPU PVR support\n", + __func__); + set_cpuinfo_static(&cpuinfo, cpu); + set_cpuinfo_pvr_full(&cpuinfo, cpu); + break; + default: + printk(KERN_WARNING "%s: Unsupported PVR setting\n", __func__); + set_cpuinfo_static(&cpuinfo, cpu); + } +} diff --git a/arch/microblaze/kernel/cpu/mb.c b/arch/microblaze/kernel/cpu/mb.c new file mode 100644 index 00000000000..3b6212bdc8d --- /dev/null +++ b/arch/microblaze/kernel/cpu/mb.c @@ -0,0 +1,148 @@ +/* + * CPU-version specific code + * + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2006-2009 PetaLogix + * + * 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. + */ + +#include <linux/init.h> +#include <linux/string.h> +#include <linux/seq_file.h> +#include <linux/cpu.h> +#include <linux/initrd.h> + +#include <linux/bug.h> +#include <asm/cpuinfo.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <asm/page.h> +#include <linux/param.h> +#include <asm/pvr.h> +#include <asm/sections.h> +#include <asm/setup.h> + +static int show_cpuinfo(struct seq_file *m, void *v) +{ + int count = 0; + char *fpga_family = "Unknown"; + char *cpu_ver = "Unknown"; + int i; + + /* Denormalised to get the fpga family string */ + for (i = 0; family_string_lookup[i].s != NULL; i++) { + if (cpuinfo.fpga_family_code == family_string_lookup[i].k) { + fpga_family = (char *)family_string_lookup[i].s; + break; + } + } + + /* Denormalised to get the hw version string */ + for (i = 0; cpu_ver_lookup[i].s != NULL; i++) { + if (cpuinfo.ver_code == cpu_ver_lookup[i].k) { + cpu_ver = (char *)cpu_ver_lookup[i].s; + break; + } + } + + count = seq_printf(m, + "CPU-Family: MicroBlaze\n" + "FPGA-Arch: %s\n" + "CPU-Ver: %s\n" + "CPU-MHz: %d.%02d\n" + "BogoMips: %lu.%02lu\n", + fpga_family, + cpu_ver, + cpuinfo.cpu_clock_freq / + 1000000, + cpuinfo.cpu_clock_freq % + 1000000, + loops_per_jiffy / (500000 / HZ), + (loops_per_jiffy / (5000 / HZ)) % 100); + + count += seq_printf(m, + "HW:\n Shift:\t\t%s\n" + " MSR:\t\t%s\n" + " PCMP:\t\t%s\n" + " DIV:\t\t%s\n", + (cpuinfo.use_instr & PVR0_USE_BARREL_MASK) ? "yes" : "no", + (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) ? "yes" : "no", + (cpuinfo.use_instr & PVR2_USE_PCMP_INSTR) ? "yes" : "no", + (cpuinfo.use_instr & PVR0_USE_DIV_MASK) ? "yes" : "no"); + + count += seq_printf(m, + " MMU:\t\t%x\n", + cpuinfo.mmu); + + count += seq_printf(m, + " MUL:\t\t%s\n" + " FPU:\t\t%s\n", + (cpuinfo.use_mult & PVR2_USE_MUL64_MASK) ? "v2" : + (cpuinfo.use_mult & PVR0_USE_HW_MUL_MASK) ? "v1" : "no", + (cpuinfo.use_fpu & PVR2_USE_FPU2_MASK) ? "v2" : + (cpuinfo.use_fpu & PVR0_USE_FPU_MASK) ? "v1" : "no"); + + count += seq_printf(m, + " Exc:\t\t%s%s%s%s%s%s%s%s\n", + (cpuinfo.use_exc & PVR2_OPCODE_0x0_ILL_MASK) ? "op0x0 " : "", + (cpuinfo.use_exc & PVR2_UNALIGNED_EXC_MASK) ? "unal " : "", + (cpuinfo.use_exc & PVR2_ILL_OPCODE_EXC_MASK) ? "ill " : "", + (cpuinfo.use_exc & PVR2_IOPB_BUS_EXC_MASK) ? "iopb " : "", + (cpuinfo.use_exc & PVR2_DOPB_BUS_EXC_MASK) ? "dopb " : "", + (cpuinfo.use_exc & PVR2_DIV_ZERO_EXC_MASK) ? "zero " : "", + (cpuinfo.use_exc & PVR2_FPU_EXC_MASK) ? "fpu " : "", + (cpuinfo.use_exc & PVR2_USE_FSL_EXC) ? "fsl " : ""); + + if (cpuinfo.use_icache) + count += seq_printf(m, + "Icache:\t\t%ukB\n", + cpuinfo.icache_size >> 10); + else + count += seq_printf(m, "Icache:\t\tno\n"); + + if (cpuinfo.use_dcache) + count += seq_printf(m, + "Dcache:\t\t%ukB\n", + cpuinfo.dcache_size >> 10); + else + count += seq_printf(m, "Dcache:\t\tno\n"); + + count += seq_printf(m, + "HW-Debug:\t%s\n", + cpuinfo.hw_debug ? "yes" : "no"); + + count += seq_printf(m, + "PVR-USR1:\t%x\n" + "PVR-USR2:\t%x\n", + cpuinfo.pvr_user1, + cpuinfo.pvr_user2); + + return 0; +} + +static void *c_start(struct seq_file *m, loff_t *pos) +{ + int i = *pos; + + return i < NR_CPUS ? (void *) (i + 1) : NULL; +} + +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ + ++*pos; + return c_start(m, pos); +} + +static void c_stop(struct seq_file *m, void *v) +{ +} + +const struct seq_operations cpuinfo_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo, +}; diff --git a/arch/microblaze/kernel/cpu/pvr.c b/arch/microblaze/kernel/cpu/pvr.c new file mode 100644 index 00000000000..c9a4340ddd5 --- /dev/null +++ b/arch/microblaze/kernel/cpu/pvr.c @@ -0,0 +1,81 @@ +/* + * Support for MicroBlaze PVR (processor version register) + * + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2007 John Williams <john.williams@petalogix.com> + * + * 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. + */ + +#include <linux/kernel.h> +#include <linux/compiler.h> +#include <asm/system.h> +#include <asm/exceptions.h> +#include <asm/pvr.h> + +/* + * Until we get an assembler that knows about the pvr registers, + * this horrible cruft will have to do. + * That hardcoded opcode is mfs r3, rpvrNN + */ + +#define get_single_pvr(pvrid, val) \ +{ \ + register unsigned tmp __asm__("r3"); \ + tmp = 0x0; /* Prevent warning about unused */ \ + __asm__ __volatile__ ( \ + ".byte 0x94,0x60,0xa0, " #pvrid "\n\t" \ + : "=r" (tmp) : : "memory"); \ + val = tmp; \ +} + +/* + * Does the CPU support the PVR register? + * return value: + * 0: no PVR + * 1: simple PVR + * 2: full PVR + * + * This must work on all CPU versions, including those before the + * PVR was even an option. + */ + +int cpu_has_pvr(void) +{ + unsigned flags; + unsigned pvr0; + + local_save_flags(flags); + + /* PVR bit in MSR tells us if there is any support */ + if (!(flags & PVR_MSR_BIT)) + return 0; + + get_single_pvr(0x00, pvr0); + pr_debug("%s: pvr0 is 0x%08x\n", __func__, pvr0); + + if (pvr0 & PVR0_PVR_FULL_MASK) + return 1; + + /* for partial PVR use static cpuinfo */ + return 2; +} + +void get_pvr(struct pvr_s *p) +{ + get_single_pvr(0, p->pvr[0]); + get_single_pvr(1, p->pvr[1]); + get_single_pvr(2, p->pvr[2]); + get_single_pvr(3, p->pvr[3]); + get_single_pvr(4, p->pvr[4]); + get_single_pvr(5, p->pvr[5]); + get_single_pvr(6, p->pvr[6]); + get_single_pvr(7, p->pvr[7]); + get_single_pvr(8, p->pvr[8]); + get_single_pvr(9, p->pvr[9]); + get_single_pvr(10, p->pvr[10]); + get_single_pvr(11, p->pvr[11]); +} diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c new file mode 100644 index 00000000000..62cc78993f4 --- /dev/null +++ b/arch/microblaze/kernel/early_printk.c @@ -0,0 +1,107 @@ +/* + * Early printk support for Microblaze. + * + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2003-2006 Yasushi SHOJI <yashi@atmark-techno.com> + * + * 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. + */ + +#include <linux/console.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/string.h> +#include <linux/tty.h> +#include <linux/io.h> +#include <asm/processor.h> +#include <linux/fcntl.h> +#include <asm/setup.h> +#include <asm/prom.h> + +static u32 early_console_initialized; +static u32 base_addr; + +static void early_printk_putc(char c) +{ + /* + * Limit how many times we'll spin waiting for TX FIFO status. + * This will prevent lockups if the base address is incorrectly + * set, or any other issue on the UARTLITE. + * This limit is pretty arbitrary, unless we are at about 10 baud + * we'll never timeout on a working UART. + */ + + unsigned retries = 10000; + /* read status bit - 0x8 offset */ + while (retries-- && (in_be32(base_addr + 8) & (1 << 3))) + ; + + /* Only attempt the iowrite if we didn't timeout */ + /* write to TX_FIFO - 0x4 offset */ + if (retries) + out_be32(base_addr + 4, c & 0xff); +} + +static void early_printk_write(struct console *unused, + const char *s, unsigned n) +{ + while (*s && n-- > 0) { + early_printk_putc(*s); + if (*s == '\n') + early_printk_putc('\r'); + s++; + } +} + +static struct console early_serial_console = { + .name = "earlyser", + .write = early_printk_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +static struct console *early_console = &early_serial_console; + +void early_printk(const char *fmt, ...) +{ + char buf[512]; + int n; + va_list ap; + + if (early_console_initialized) { + va_start(ap, fmt); + n = vscnprintf(buf, 512, fmt, ap); + early_console->write(early_console, buf, n); + va_end(ap); + } +} + +int __init setup_early_printk(char *opt) +{ + if (early_console_initialized) + return 1; + + base_addr = early_uartlite_console(); + if (base_addr) { + early_console_initialized = 1; + early_printk("early_printk_console is enabled at 0x%08x\n", + base_addr); + + /* register_console(early_console); */ + + return 0; + } else + return 1; +} + +void __init disable_early_printk(void) +{ + if (!early_console_initialized || !early_console) + return; + printk(KERN_WARNING "disabling early console\n"); + unregister_console(early_console); + early_console_initialized = 0; +} diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S new file mode 100644 index 00000000000..f24b1268baa --- /dev/null +++ b/arch/microblaze/kernel/entry-nommu.S @@ -0,0 +1,596 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/linkage.h> +#include <asm/thread_info.h> +#include <asm/errno.h> +#include <asm/entry.h> +#include <asm/asm-offsets.h> +#include <asm/registers.h> +#include <asm/unistd.h> +#include <asm/percpu.h> +#include <asm/signal.h> + +#if CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR + .macro disable_irq + msrclr r0, MSR_IE + .endm + + .macro enable_irq + msrset r0, MSR_IE + .endm + + .macro clear_bip + msrclr r0, MSR_BIP + .endm +#else + .macro disable_irq + mfs r11, rmsr + andi r11, r11, ~MSR_IE + mts rmsr, r11 + .endm + + .macro enable_irq + mfs r11, rmsr + ori r11, r11, MSR_IE + mts rmsr, r11 + .endm + + .macro clear_bip + mfs r11, rmsr + andi r11, r11, ~MSR_BIP + mts rmsr, r11 + .endm +#endif + +ENTRY(_interrupt) + swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */ + swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */ + lwi r11, r0, PER_CPU(KM) /* load mode indicator */ + beqid r11, 1f + nop + brid 2f /* jump over */ + addik r1, r1, (-PT_SIZE) /* room for pt_regs (delay slot) */ +1: /* switch to kernel stack */ + lwi r1, r0, PER_CPU(CURRENT_SAVE) /* get the saved current */ + lwi r1, r1, TS_THREAD_INFO /* get the thread info */ + /* calculate kernel stack pointer */ + addik r1, r1, THREAD_SIZE - PT_SIZE +2: + swi r11, r1, PT_MODE /* store the mode */ + lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */ + swi r2, r1, PT_R2 + swi r3, r1, PT_R3 + swi r4, r1, PT_R4 + swi r5, r1, PT_R5 + swi r6, r1, PT_R6 + swi r7, r1, PT_R7 + swi r8, r1, PT_R8 + swi r9, r1, PT_R9 + swi r10, r1, PT_R10 + swi r11, r1, PT_R11 + swi r12, r1, PT_R12 + swi r13, r1, PT_R13 + swi r14, r1, PT_R14 + swi r14, r1, PT_PC + swi r15, r1, PT_R15 + swi r16, r1, PT_R16 + swi r17, r1, PT_R17 + swi r18, r1, PT_R18 + swi r19, r1, PT_R19 + swi r20, r1, PT_R20 + swi r21, r1, PT_R21 + swi r22, r1, PT_R22 + swi r23, r1, PT_R23 + swi r24, r1, PT_R24 + swi r25, r1, PT_R25 + swi r26, r1, PT_R26 + swi r27, r1, PT_R27 + swi r28, r1, PT_R28 + swi r29, r1, PT_R29 + swi r30, r1, PT_R30 + swi r31, r1, PT_R31 + /* special purpose registers */ + mfs r11, rmsr + swi r11, r1, PT_MSR + mfs r11, rear + swi r11, r1, PT_EAR + mfs r11, resr + swi r11, r1, PT_ESR + mfs r11, rfsr + swi r11, r1, PT_FSR + /* reload original stack pointer and save it */ + lwi r11, r0, PER_CPU(ENTRY_SP) + swi r11, r1, PT_R1 + /* update mode indicator we are in kernel mode */ + addik r11, r0, 1 + swi r11, r0, PER_CPU(KM) + /* restore r31 */ + lwi r31, r0, PER_CPU(CURRENT_SAVE) + /* prepare the link register, the argument and jump */ + la r15, r0, ret_from_intr - 8 + addk r6, r0, r15 + braid do_IRQ + add r5, r0, r1 + +ret_from_intr: + lwi r11, r1, PT_MODE + bneid r11, 3f + + lwi r6, r31, TS_THREAD_INFO /* get thread info */ + lwi r19, r6, TI_FLAGS /* get flags in thread info */ + /* do an extra work if any bits are set */ + + andi r11, r19, _TIF_NEED_RESCHED + beqi r11, 1f + bralid r15, schedule + nop +1: andi r11, r19, _TIF_SIGPENDING + beqid r11, no_intr_reshed + addk r5, r1, r0 + addk r7, r0, r0 + bralid r15, do_signal + addk r6, r0, r0 + +no_intr_reshed: + /* save mode indicator */ + lwi r11, r1, PT_MODE +3: + swi r11, r0, PER_CPU(KM) + + /* save r31 */ + swi r31, r0, PER_CPU(CURRENT_SAVE) +restore_context: + /* special purpose registers */ + lwi r11, r1, PT_FSR + mts rfsr, r11 + lwi r11, r1, PT_ESR + mts resr, r11 + lwi r11, r1, PT_EAR + mts rear, r11 + lwi r11, r1, PT_MSR + mts rmsr, r11 + + lwi r31, r1, PT_R31 + lwi r30, r1, PT_R30 + lwi r29, r1, PT_R29 + lwi r28, r1, PT_R28 + lwi r27, r1, PT_R27 + lwi r26, r1, PT_R26 + lwi r25, r1, PT_R25 + lwi r24, r1, PT_R24 + lwi r23, r1, PT_R23 + lwi r22, r1, PT_R22 + lwi r21, r1, PT_R21 + lwi r20, r1, PT_R20 + lwi r19, r1, PT_R19 + lwi r18, r1, PT_R18 + lwi r17, r1, PT_R17 + lwi r16, r1, PT_R16 + lwi r15, r1, PT_R15 + lwi r14, r1, PT_PC + lwi r13, r1, PT_R13 + lwi r12, r1, PT_R12 + lwi r11, r1, PT_R11 + lwi r10, r1, PT_R10 + lwi r9, r1, PT_R9 + lwi r8, r1, PT_R8 + lwi r7, r1, PT_R7 + lwi r6, r1, PT_R6 + lwi r5, r1, PT_R5 + lwi r4, r1, PT_R4 + lwi r3, r1, PT_R3 + lwi r2, r1, PT_R2 + lwi r1, r1, PT_R1 + rtid r14, 0 + nop + +ENTRY(_reset) + brai 0; + +ENTRY(_user_exception) + swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */ + swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */ + lwi r11, r0, PER_CPU(KM) /* load mode indicator */ + beqid r11, 1f /* Already in kernel mode? */ + nop + brid 2f /* jump over */ + addik r1, r1, (-PT_SIZE) /* Room for pt_regs (delay slot) */ +1: /* Switch to kernel stack */ + lwi r1, r0, PER_CPU(CURRENT_SAVE) /* get the saved current */ + lwi r1, r1, TS_THREAD_INFO /* get the thread info */ + /* calculate kernel stack pointer */ + addik r1, r1, THREAD_SIZE - PT_SIZE + swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */ + lwi r11, r0, PER_CPU(KM) /* load mode indicator */ +2: + swi r11, r1, PT_MODE /* store the mode */ + lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */ + /* save them on stack */ + swi r2, r1, PT_R2 + swi r3, r1, PT_R3 /* r3: _always_ in clobber list; see unistd.h */ + swi r4, r1, PT_R4 /* r4: _always_ in clobber list; see unistd.h */ + swi r5, r1, PT_R5 + swi r6, r1, PT_R6 + swi r7, r1, PT_R7 + swi r8, r1, PT_R8 + swi r9, r1, PT_R9 + swi r10, r1, PT_R10 + swi r11, r1, PT_R11 + /* r12: _always_ in clobber list; see unistd.h */ + swi r12, r1, PT_R12 + swi r13, r1, PT_R13 + /* r14: _always_ in clobber list; see unistd.h */ + swi r14, r1, PT_R14 + /* but we want to return to the next inst. */ + addik r14, r14, 0x4 + swi r14, r1, PT_PC /* increment by 4 and store in pc */ + swi r15, r1, PT_R15 + swi r16, r1, PT_R16 + swi r17, r1, PT_R17 + swi r18, r1, PT_R18 + swi r19, r1, PT_R19 + swi r20, r1, PT_R20 + swi r21, r1, PT_R21 + swi r22, r1, PT_R22 + swi r23, r1, PT_R23 + swi r24, r1, PT_R24 + swi r25, r1, PT_R25 + swi r26, r1, PT_R26 + swi r27, r1, PT_R27 + swi r28, r1, PT_R28 + swi r29, r1, PT_R29 + swi r30, r1, PT_R30 + swi r31, r1, PT_R31 + + disable_irq + nop /* make sure IE bit is in effect */ + clear_bip /* once IE is in effect it is safe to clear BIP */ + nop + + /* special purpose registers */ + mfs r11, rmsr + swi r11, r1, PT_MSR + mfs r11, rear + swi r11, r1, PT_EAR + mfs r11, resr + swi r11, r1, PT_ESR + mfs r11, rfsr + swi r11, r1, PT_FSR + /* reload original stack pointer and save it */ + lwi r11, r0, PER_CPU(ENTRY_SP) + swi r11, r1, PT_R1 + /* update mode indicator we are in kernel mode */ + addik r11, r0, 1 + swi r11, r0, PER_CPU(KM) + /* restore r31 */ + lwi r31, r0, PER_CPU(CURRENT_SAVE) + /* re-enable interrupts now we are in kernel mode */ + enable_irq + + /* See if the system call number is valid. */ + addi r11, r12, -__NR_syscalls + bgei r11, 1f /* return to user if not valid */ + /* Figure out which function to use for this system call. */ + /* Note Microblaze barrel shift is optional, so don't rely on it */ + add r12, r12, r12 /* convert num -> ptr */ + add r12, r12, r12 + lwi r12, r12, sys_call_table /* Get function pointer */ + la r15, r0, ret_to_user-8 /* set return address */ + bra r12 /* Make the system call. */ + bri 0 /* won't reach here */ +1: + brid ret_to_user /* jump to syscall epilogue */ + addi r3, r0, -ENOSYS /* set errno in delay slot */ + +/* + * Debug traps are like a system call, but entered via brki r14, 0x60 + * All we need to do is send the SIGTRAP signal to current, ptrace and do_signal + * will handle the rest + */ +ENTRY(_debug_exception) + swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */ + lwi r1, r0, PER_CPU(CURRENT_SAVE) /* get the saved current */ + lwi r1, r1, TS_THREAD_INFO /* get the thread info */ + addik r1, r1, THREAD_SIZE - PT_SIZE /* get the kernel stack */ + swi r11, r0, PER_CPU(R11_SAVE) /* temporarily save r11 */ + lwi r11, r0, PER_CPU(KM) /* load mode indicator */ +//save_context: + swi r11, r1, PT_MODE /* store the mode */ + lwi r11, r0, PER_CPU(R11_SAVE) /* reload r11 */ + /* save them on stack */ + swi r2, r1, PT_R2 + swi r3, r1, PT_R3 /* r3: _always_ in clobber list; see unistd.h */ + swi r4, r1, PT_R4 /* r4: _always_ in clobber list; see unistd.h */ + swi r5, r1, PT_R5 + swi r6, r1, PT_R6 + swi r7, r1, PT_R7 + swi r8, r1, PT_R8 + swi r9, r1, PT_R9 + swi r10, r1, PT_R10 + swi r11, r1, PT_R11 + /* r12: _always_ in clobber list; see unistd.h */ + swi r12, r1, PT_R12 + swi r13, r1, PT_R13 + /* r14: _always_ in clobber list; see unistd.h */ + swi r14, r1, PT_R14 + swi r14, r1, PT_PC /* Will return to interrupted instruction */ + swi r15, r1, PT_R15 + swi r16, r1, PT_R16 + swi r17, r1, PT_R17 + swi r18, r1, PT_R18 + swi r19, r1, PT_R19 + swi r20, r1, PT_R20 + swi r21, r1, PT_R21 + swi r22, r1, PT_R22 + swi r23, r1, PT_R23 + swi r24, r1, PT_R24 + swi r25, r1, PT_R25 + swi r26, r1, PT_R26 + swi r27, r1, PT_R27 + swi r28, r1, PT_R28 + swi r29, r1, PT_R29 + swi r30, r1, PT_R30 + swi r31, r1, PT_R31 + + disable_irq + nop /* make sure IE bit is in effect */ + clear_bip /* once IE is in effect it is safe to clear BIP */ + nop + + /* special purpose registers */ + mfs r11, rmsr + swi r11, r1, PT_MSR + mfs r11, rear + swi r11, r1, PT_EAR + mfs r11, resr + swi r11, r1, PT_ESR + mfs r11, rfsr + swi r11, r1, PT_FSR + /* reload original stack pointer and save it */ + lwi r11, r0, PER_CPU(ENTRY_SP) + swi r11, r1, PT_R1 + /* update mode indicator we are in kernel mode */ + addik r11, r0, 1 + swi r11, r0, PER_CPU(KM) + /* restore r31 */ + lwi r31, r0, PER_CPU(CURRENT_SAVE) + /* re-enable interrupts now we are in kernel mode */ + enable_irq + + addi r5, r0, SIGTRAP /* sending the trap signal */ + add r6, r0, r31 /* to current */ + bralid r15, send_sig + add r7, r0, r0 /* 3rd param zero */ + + /* Restore r3/r4 to work around how ret_to_user works */ + lwi r3, r1, PT_R3 + lwi r4, r1, PT_R4 + bri ret_to_user + +ENTRY(_break) + bri 0 + +/* struct task_struct *_switch_to(struct thread_info *prev, + struct thread_info *next); */ +ENTRY(_switch_to) + /* prepare return value */ + addk r3, r0, r31 + + /* save registers in cpu_context */ + /* use r11 and r12, volatile registers, as temp register */ + addik r11, r5, TI_CPU_CONTEXT + swi r1, r11, CC_R1 + swi r2, r11, CC_R2 + /* skip volatile registers. + * they are saved on stack when we jumped to _switch_to() */ + /* dedicated registers */ + swi r13, r11, CC_R13 + swi r14, r11, CC_R14 + swi r15, r11, CC_R15 + swi r16, r11, CC_R16 + swi r17, r11, CC_R17 + swi r18, r11, CC_R18 + /* save non-volatile registers */ + swi r19, r11, CC_R19 + swi r20, r11, CC_R20 + swi r21, r11, CC_R21 + swi r22, r11, CC_R22 + swi r23, r11, CC_R23 + swi r24, r11, CC_R24 + swi r25, r11, CC_R25 + swi r26, r11, CC_R26 + swi r27, r11, CC_R27 + swi r28, r11, CC_R28 + swi r29, r11, CC_R29 + swi r30, r11, CC_R30 + /* special purpose registers */ + mfs r12, rmsr + swi r12, r11, CC_MSR + mfs r12, rear + swi r12, r11, CC_EAR + mfs r12, resr + swi r12, r11, CC_ESR + mfs r12, rfsr + swi r12, r11, CC_FSR + + /* update r31, the current */ + lwi r31, r6, TI_TASK + swi r31, r0, PER_CPU(CURRENT_SAVE) + + /* get new process' cpu context and restore */ + addik r11, r6, TI_CPU_CONTEXT + + /* special purpose registers */ + lwi r12, r11, CC_FSR + mts rfsr, r12 + lwi r12, r11, CC_ESR + mts resr, r12 + lwi r12, r11, CC_EAR + mts rear, r12 + lwi r12, r11, CC_MSR + mts rmsr, r12 + /* non-volatile registers */ + lwi r30, r11, CC_R30 + lwi r29, r11, CC_R29 + lwi r28, r11, CC_R28 + lwi r27, r11, CC_R27 + lwi r26, r11, CC_R26 + lwi r25, r11, CC_R25 + lwi r24, r11, CC_R24 + lwi r23, r11, CC_R23 + lwi r22, r11, CC_R22 + lwi r21, r11, CC_R21 + lwi r20, r11, CC_R20 + lwi r19, r11, CC_R19 + /* dedicated registers */ + lwi r18, r11, CC_R18 + lwi r17, r11, CC_R17 + lwi r16, r11, CC_R16 + lwi r15, r11, CC_R15 + lwi r14, r11, CC_R14 + lwi r13, r11, CC_R13 + /* skip volatile registers */ + lwi r2, r11, CC_R2 + lwi r1, r11, CC_R1 + + rtsd r15, 8 + nop + +ENTRY(ret_from_fork) + addk r5, r0, r3 + addk r6, r0, r1 + brlid r15, schedule_tail + nop + swi r31, r1, PT_R31 /* save r31 in user context. */ + /* will soon be restored to r31 in ret_to_user */ + addk r3, r0, r0 + brid ret_to_user + nop + +work_pending: + andi r11, r19, _TIF_NEED_RESCHED + beqi r11, 1f + bralid r15, schedule + nop +1: andi r11, r19, _TIF_SIGPENDING + beqi r11, no_work_pending + addk r5, r1, r0 + addik r7, r0, 1 + bralid r15, do_signal + addk r6, r0, r0 + bri no_work_pending + +ENTRY(ret_to_user) + disable_irq + + swi r4, r1, PT_R4 /* return val */ + swi r3, r1, PT_R3 /* return val */ + + lwi r6, r31, TS_THREAD_INFO /* get thread info */ + lwi r19, r6, TI_FLAGS /* get flags in thread info */ + bnei r19, work_pending /* do an extra work if any bits are set */ +no_work_pending: + disable_irq + + /* save r31 */ + swi r31, r0, PER_CPU(CURRENT_SAVE) + /* save mode indicator */ + lwi r18, r1, PT_MODE + swi r18, r0, PER_CPU(KM) +//restore_context: + /* special purpose registers */ + lwi r18, r1, PT_FSR + mts rfsr, r18 + lwi r18, r1, PT_ESR + mts resr, r18 + lwi r18, r1, PT_EAR + mts rear, r18 + lwi r18, r1, PT_MSR + mts rmsr, r18 + + lwi r31, r1, PT_R31 + lwi r30, r1, PT_R30 + lwi r29, r1, PT_R29 + lwi r28, r1, PT_R28 + lwi r27, r1, PT_R27 + lwi r26, r1, PT_R26 + lwi r25, r1, PT_R25 + lwi r24, r1, PT_R24 + lwi r23, r1, PT_R23 + lwi r22, r1, PT_R22 + lwi r21, r1, PT_R21 + lwi r20, r1, PT_R20 + lwi r19, r1, PT_R19 + lwi r18, r1, PT_R18 + lwi r17, r1, PT_R17 + lwi r16, r1, PT_R16 + lwi r15, r1, PT_R15 + lwi r14, r1, PT_PC + lwi r13, r1, PT_R13 + lwi r12, r1, PT_R12 + lwi r11, r1, PT_R11 + lwi r10, r1, PT_R10 + lwi r9, r1, PT_R9 + lwi r8, r1, PT_R8 + lwi r7, r1, PT_R7 + lwi r6, r1, PT_R6 + lwi r5, r1, PT_R5 + lwi r4, r1, PT_R4 /* return val */ + lwi r3, r1, PT_R3 /* return val */ + lwi r2, r1, PT_R2 + lwi r1, r1, PT_R1 + + rtid r14, 0 + nop + +sys_vfork_wrapper: + brid sys_vfork + addk r5, r1, r0 + +sys_clone_wrapper: + brid sys_clone + addk r7, r1, r0 + +sys_execve_wrapper: + brid sys_execve + addk r8, r1, r0 + +sys_sigreturn_wrapper: + brid sys_sigreturn + addk r5, r1, r0 + +sys_rt_sigreturn_wrapper: + brid sys_rt_sigreturn + addk r5, r1, r0 + +sys_sigsuspend_wrapper: + brid sys_rt_sigsuspend + addk r6, r1, r0 + +sys_rt_sigsuspend_wrapper: + brid sys_rt_sigsuspend + addk r7, r1, r0 + + /* Interrupt vector table */ + .section .init.ivt, "ax" + .org 0x0 + brai _reset + brai _user_exception + brai _interrupt + brai _break + brai _hw_exception_handler + .org 0x60 + brai _debug_exception + +.section .rodata,"a" +#include "syscall_table.S" + +syscall_table_size=(.-sys_call_table) diff --git a/arch/microblaze/kernel/exceptions.c b/arch/microblaze/kernel/exceptions.c new file mode 100644 index 00000000000..4a8a4064c7e --- /dev/null +++ b/arch/microblaze/kernel/exceptions.c @@ -0,0 +1,124 @@ +/* + * HW exception handling + * + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2008 PetaLogix + * + * 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. + */ + +/* + * This file handles the architecture-dependent parts of hardware exceptions + */ + +#include <linux/kernel.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/kallsyms.h> +#include <linux/module.h> + +#include <asm/exceptions.h> +#include <asm/entry.h> /* For KM CPU var */ +#include <asm/uaccess.h> +#include <asm/errno.h> +#include <asm/ptrace.h> +#include <asm/current.h> + +#define MICROBLAZE_ILL_OPCODE_EXCEPTION 0x02 +#define MICROBLAZE_IBUS_EXCEPTION 0x03 +#define MICROBLAZE_DBUS_EXCEPTION 0x04 +#define MICROBLAZE_DIV_ZERO_EXCEPTION 0x05 +#define MICROBLAZE_FPU_EXCEPTION 0x06 +#define MICROBLAZE_PRIVILEG_EXCEPTION 0x07 + +static DEFINE_SPINLOCK(die_lock); + +void die(const char *str, struct pt_regs *fp, long err) +{ + console_verbose(); + spin_lock_irq(&die_lock); + printk(KERN_WARNING "Oops: %s, sig: %ld\n", str, err); + show_regs(fp); + spin_unlock_irq(&die_lock); + /* do_exit() should take care of panic'ing from an interrupt + * context so we don't handle it here + */ + do_exit(err); +} + +void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) +{ + siginfo_t info; + + if (kernel_mode(regs)) { + debugger(regs); + die("Exception in kernel mode", regs, signr); + } + info.si_signo = signr; + info.si_errno = 0; + info.si_code = code; + info.si_addr = (void __user *) addr; + force_sig_info(signr, &info, current); +} + +asmlinkage void full_exception(struct pt_regs *regs, unsigned int type, + int fsr, int addr) +{ +#if 0 + printk(KERN_WARNING "Exception %02x in %s mode, FSR=%08x PC=%08x ESR=%08x\n", + type, user_mode(regs) ? "user" : "kernel", fsr, + (unsigned int) regs->pc, (unsigned int) regs->esr); +#endif + + switch (type & 0x1F) { + case MICROBLAZE_ILL_OPCODE_EXCEPTION: + _exception(SIGILL, regs, ILL_ILLOPC, addr); + break; + case MICROBLAZE_IBUS_EXCEPTION: + if (user_mode(regs)) { + printk(KERN_WARNING "Instruction bus error exception in user mode.\n"); + _exception(SIGBUS, regs, BUS_ADRERR, addr); + return; + } + printk(KERN_WARNING "Instruction bus error exception in kernel mode.\n"); + die("bus exception", regs, SIGBUS); + break; + case MICROBLAZE_DBUS_EXCEPTION: + if (user_mode(regs)) { + printk(KERN_WARNING "Data bus error exception in user mode.\n"); + _exception(SIGBUS, regs, BUS_ADRERR, addr); + return; + } + printk(KERN_WARNING "Data bus error exception in kernel mode.\n"); + die("bus exception", regs, SIGBUS); + break; + case MICROBLAZE_DIV_ZERO_EXCEPTION: + printk(KERN_WARNING "Divide by zero exception\n"); + _exception(SIGILL, regs, ILL_ILLOPC, addr); + break; + + case MICROBLAZE_FPU_EXCEPTION: + /* IEEE FP exception */ + /* I removed fsr variable and use code var for storing fsr */ + if (fsr & FSR_IO) + fsr = FPE_FLTINV; + else if (fsr & FSR_OF) + fsr = FPE_FLTOVF; + else if (fsr & FSR_UF) + fsr = FPE_FLTUND; + else if (fsr & FSR_DZ) + fsr = FPE_FLTDIV; + else if (fsr & FSR_DO) + fsr = FPE_FLTRES; + _exception(SIGFPE, regs, fsr, addr); + break; + + default: + printk(KERN_WARNING "Unexpected exception %02x " + "PC=%08x in %s mode\n", type, (unsigned int) addr, + kernel_mode(regs) ? "kernel" : "user"); + } + return; +} diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S new file mode 100644 index 00000000000..319dc35fc92 --- /dev/null +++ b/arch/microblaze/kernel/head.S @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/linkage.h> +#include <asm/thread_info.h> +#include <asm/page.h> + + .text +ENTRY(_start) + mfs r1, rmsr + andi r1, r1, ~2 + mts rmsr, r1 + +/* save fdt to kernel location */ +/* r7 stores pointer to fdt blob */ + beqi r7, no_fdt_arg + or r11, r0, r0 /* incremment */ + ori r4, r0, TOPHYS(_fdt_start) /* save bram context */ + ori r3, r0, (0x4000 - 4) +_copy_fdt: + lw r12, r7, r11 /* r12 = r7 + r11 */ + sw r12, r4, r11 /* addr[r4 + r11] = r12 */ + addik r11, r11, 4 /* increment counting */ + bgtid r3, _copy_fdt /* loop for all entries */ + addik r3, r3, -4 /* descrement loop */ +no_fdt_arg: + + /* Initialize small data anchors */ + la r13, r0, _KERNEL_SDA_BASE_ + la r2, r0, _KERNEL_SDA2_BASE_ + + /* Initialize stack pointer */ + la r1, r0, init_thread_union + THREAD_SIZE - 4 + + /* Initialize r31 with current task address */ + la r31, r0, init_task + + /* + * Call platform dependent initialize function. + * Please see $(ARCH)/mach-$(SUBARCH)/setup.c for + * the function. + */ + la r8, r0, machine_early_init + brald r15, r8 + nop + + la r15, r0, machine_halt + braid start_kernel + nop diff --git a/arch/microblaze/kernel/heartbeat.c b/arch/microblaze/kernel/heartbeat.c new file mode 100644 index 00000000000..1bdf20222b9 --- /dev/null +++ b/arch/microblaze/kernel/heartbeat.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/sched.h> +#include <linux/io.h> + +#include <asm/setup.h> +#include <asm/page.h> +#include <asm/prom.h> + +static unsigned int base_addr; + +void heartbeat(void) +{ + static unsigned int cnt, period, dist; + + if (base_addr) { + if (cnt == 0 || cnt == dist) + out_be32(base_addr, 1); + else if (cnt == 7 || cnt == dist + 7) + out_be32(base_addr, 0); + + if (++cnt > period) { + cnt = 0; + /* + * The hyperbolic function below modifies the heartbeat + * period length in dependency of the current (5min) + * load. It goes through the points f(0)=126, f(1)=86, + * f(5)=51, f(inf)->30. + */ + period = ((672 << FSHIFT) / (5 * avenrun[0] + + (7 << FSHIFT))) + 30; + dist = period / 4; + } + } +} + +void setup_heartbeat(void) +{ + struct device_node *gpio = NULL; + int j; + char *gpio_list[] = { + "xlnx,xps-gpio-1.00.a", + "xlnx,opb-gpio-1.00.a", + NULL + }; + + for (j = 0; gpio_list[j] != NULL; j++) { + gpio = of_find_compatible_node(NULL, NULL, gpio_list[j]); + if (gpio) + break; + } + + base_addr = *(int *) of_get_property(gpio, "reg", NULL); + base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE); + printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr); + + if (*(int *) of_get_property(gpio, "xlnx,is-bidir", NULL)) + out_be32(base_addr + 4, 0); /* GPIO is configured as output */ +} diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S new file mode 100644 index 00000000000..cf9486d9983 --- /dev/null +++ b/arch/microblaze/kernel/hw_exception_handler.S @@ -0,0 +1,458 @@ +/* + * Exception handling for Microblaze + * + * Rewriten interrupt handling + * + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2008-2009 PetaLogix + * + * uClinux customisation (C) 2005 John Williams + * + * MMU code derived from arch/ppc/kernel/head_4xx.S: + * Copyright (C) 1995-1996 Gary Thomas <gdt@linuxppc.org> + * Initial PowerPC version. + * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> + * Rewritten for PReP + * Copyright (C) 1996 Paul Mackerras <paulus@cs.anu.edu.au> + * Low-level exception handers, MMU support, and rewrite. + * Copyright (C) 1997 Dan Malek <dmalek@jlc.net> + * PowerPC 8xx modifications. + * Copyright (C) 1998-1999 TiVo, Inc. + * PowerPC 403GCX modifications. + * Copyright (C) 1999 Grant Erickson <grant@lcse.umn.edu> + * PowerPC 403GCX/405GP modifications. + * Copyright 2000 MontaVista Software Inc. + * PPC405 modifications + * PowerPC 403GCX/405GP modifications. + * Author: MontaVista Software, Inc. + * frank_rowand@mvista.com or source@mvista.com + * debbie_chu@mvista.com + * + * Original code + * Copyright (C) 2004 Xilinx, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +/* + * Here are the handlers which don't require enabling translation + * and calling other kernel code thus we can keep their design very simple + * and do all processing in real mode. All what they need is a valid current + * (that is an issue for the CONFIG_REGISTER_TASK_PTR case) + * This handlers use r3,r4,r5,r6 and optionally r[current] to work therefore + * these registers are saved/restored + * The handlers which require translation are in entry.S --KAA + * + * Microblaze HW Exception Handler + * - Non self-modifying exception handler for the following exception conditions + * - Unalignment + * - Instruction bus error + * - Data bus error + * - Illegal instruction opcode + * - Divide-by-zero + * + * Note we disable interrupts during exception handling, otherwise we will + * possibly get multiple re-entrancy if interrupt handles themselves cause + * exceptions. JW + */ + +#include <asm/exceptions.h> +#include <asm/unistd.h> +#include <asm/page.h> + +#include <asm/entry.h> +#include <asm/current.h> +#include <linux/linkage.h> + +#include <asm/mmu.h> +#include <asm/pgtable.h> +#include <asm/asm-offsets.h> + +/* Helpful Macros */ +#define EX_HANDLER_STACK_SIZ (4*19) +#define NUM_TO_REG(num) r ## num + +#define LWREG_NOP \ + bri ex_handler_unhandled; \ + nop; + +#define SWREG_NOP \ + bri ex_handler_unhandled; \ + nop; + +/* FIXME this is weird - for noMMU kernel is not possible to use brid + * instruction which can shorten executed time + */ + +/* r3 is the source */ +#define R3_TO_LWREG_V(regnum) \ + swi r3, r1, 4 * regnum; \ + bri ex_handler_done; + +/* r3 is the source */ +#define R3_TO_LWREG(regnum) \ + or NUM_TO_REG (regnum), r0, r3; \ + bri ex_handler_done; + +/* r3 is the target */ +#define SWREG_TO_R3_V(regnum) \ + lwi r3, r1, 4 * regnum; \ + bri ex_sw_tail; + +/* r3 is the target */ +#define SWREG_TO_R3(regnum) \ + or r3, r0, NUM_TO_REG (regnum); \ + bri ex_sw_tail; + +.extern other_exception_handler /* Defined in exception.c */ + +/* + * hw_exception_handler - Handler for exceptions + * + * Exception handler notes: + * - Handles all exceptions + * - Does not handle unaligned exceptions during load into r17, r1, r0. + * - Does not handle unaligned exceptions during store from r17 (cannot be + * done) and r1 (slows down common case) + * + * Relevant register structures + * + * EAR - |----|----|----|----|----|----|----|----| + * - < ## 32 bit faulting address ## > + * + * ESR - |----|----|----|----|----| - | - |-----|-----| + * - W S REG EXC + * + * + * STACK FRAME STRUCTURE (for NO_MMU) + * --------------------------------- + * + * +-------------+ + 0 + * | MSR | + * +-------------+ + 4 + * | r1 | + * | . | + * | . | + * | . | + * | . | + * | r18 | + * +-------------+ + 76 + * | . | + * | . | + * + * NO_MMU kernel use the same r0_ram pointed space - look to vmlinux.lds.S + * which is used for storing register values - old style was, that value were + * stored in stack but in case of failure you lost information about register. + * Currently you can see register value in memory in specific place. + * In compare to with previous solution the speed should be the same. + * + * MMU exception handler has different handling compare to no MMU kernel. + * Exception handler use jump table for directing of what happen. For MMU kernel + * is this approach better because MMU relate exception are handled by asm code + * in this file. In compare to with MMU expect of unaligned exception + * is everything handled by C code. + */ + +/* + * every of these handlers is entered having R3/4/5/6/11/current saved on stack + * and clobbered so care should be taken to restore them if someone is going to + * return from exception + */ + +/* wrappers to restore state before coming to entry.S */ + +.global _hw_exception_handler +.section .text +.align 4 +.ent _hw_exception_handler +_hw_exception_handler: + addik r1, r1, -(EX_HANDLER_STACK_SIZ); /* Create stack frame */ + swi r3, r1, PT_R3 + swi r4, r1, PT_R4 + swi r5, r1, PT_R5 + swi r6, r1, PT_R6 + + mfs r5, rmsr; + nop + swi r5, r1, 0; + mfs r4, rbtr /* Save BTR before jumping to handler */ + nop + mfs r3, resr + nop + + andi r5, r3, 0x1000; /* Check ESR[DS] */ + beqi r5, not_in_delay_slot; /* Branch if ESR[DS] not set */ + mfs r17, rbtr; /* ESR[DS] set - return address in BTR */ + nop +not_in_delay_slot: + swi r17, r1, PT_R17 + + andi r5, r3, 0x1F; /* Extract ESR[EXC] */ + + /* Exceptions enabled here. This will allow nested exceptions */ + mfs r6, rmsr; + nop + swi r6, r1, 0; /* RMSR_OFFSET */ + ori r6, r6, 0x100; /* Turn ON the EE bit */ + andi r6, r6, ~2; /* Disable interrupts */ + mts rmsr, r6; + nop + + xori r6, r5, 1; /* 00001 = Unaligned Exception */ + /* Jump to unalignment exception handler */ + beqi r6, handle_unaligned_ex; + +handle_other_ex: /* Handle Other exceptions here */ + /* Save other volatiles before we make procedure calls below */ + swi r7, r1, PT_R7 + swi r8, r1, PT_R8 + swi r9, r1, PT_R9 + swi r10, r1, PT_R10 + swi r11, r1, PT_R11 + swi r12, r1, PT_R12 + swi r14, r1, PT_R14 + swi r15, r1, PT_R15 + swi r18, r1, PT_R18 + + or r5, r1, r0 + andi r6, r3, 0x1F; /* Load ESR[EC] */ + lwi r7, r0, PER_CPU(KM) /* MS: saving current kernel mode to regs */ + swi r7, r1, PT_MODE + mfs r7, rfsr + nop + addk r8, r17, r0; /* Load exception address */ + bralid r15, full_exception; /* Branch to the handler */ + nop; + + /* + * Trigger execution of the signal handler by enabling + * interrupts and calling an invalid syscall. + */ + mfs r5, rmsr; + nop + ori r5, r5, 2; + mts rmsr, r5; /* enable interrupt */ + nop + addi r12, r0, __NR_syscalls; + brki r14, 0x08; + mfs r5, rmsr; /* disable interrupt */ + nop + andi r5, r5, ~2; + mts rmsr, r5; + nop + + lwi r7, r1, PT_R7 + lwi r8, r1, PT_R8 + lwi r9, r1, PT_R9 + lwi r10, r1, PT_R10 + lwi r11, r1, PT_R11 + lwi r12, r1, PT_R12 + lwi r14, r1, PT_R14 + lwi r15, r1, PT_R15 + lwi r18, r1, PT_R18 + + bri ex_handler_done; /* Complete exception handling */ + +/* 0x01 - Unaligned data access exception + * This occurs when a word access is not aligned on a word boundary, + * or when a 16-bit access is not aligned on a 16-bit boundary. + * This handler perform the access, and returns, except for MMU when + * the unaligned address is last on a 4k page or the physical address is + * not found in the page table, in which case unaligned_data_trap is called. + */ +handle_unaligned_ex: + /* Working registers already saved: R3, R4, R5, R6 + * R3 = ESR + * R4 = BTR + */ + mfs r4, rear; + nop + + andi r6, r3, 0x3E0; /* Mask and extract the register operand */ + srl r6, r6; /* r6 >> 5 */ + srl r6, r6; + srl r6, r6; + srl r6, r6; + srl r6, r6; + /* Store the register operand in a temporary location */ + sbi r6, r0, TOPHYS(ex_reg_op); + + andi r6, r3, 0x400; /* Extract ESR[S] */ + bnei r6, ex_sw; +ex_lw: + andi r6, r3, 0x800; /* Extract ESR[W] */ + beqi r6, ex_lhw; + lbui r5, r4, 0; /* Exception address in r4 */ + /* Load a word, byte-by-byte from destination address + and save it in tmp space */ + sbi r5, r0, TOPHYS(ex_tmp_data_loc_0); + lbui r5, r4, 1; + sbi r5, r0, TOPHYS(ex_tmp_data_loc_1); + lbui r5, r4, 2; + sbi r5, r0, TOPHYS(ex_tmp_data_loc_2); + lbui r5, r4, 3; + sbi r5, r0, TOPHYS(ex_tmp_data_loc_3); + /* Get the destination register value into r3 */ + lwi r3, r0, TOPHYS(ex_tmp_data_loc_0); + bri ex_lw_tail; +ex_lhw: + lbui r5, r4, 0; /* Exception address in r4 */ + /* Load a half-word, byte-by-byte from destination + address and save it in tmp space */ + sbi r5, r0, TOPHYS(ex_tmp_data_loc_0); + lbui r5, r4, 1; + sbi r5, r0, TOPHYS(ex_tmp_data_loc_1); + /* Get the destination register value into r3 */ + lhui r3, r0, TOPHYS(ex_tmp_data_loc_0); +ex_lw_tail: + /* Get the destination register number into r5 */ + lbui r5, r0, TOPHYS(ex_reg_op); + /* Form load_word jump table offset (lw_table + (8 * regnum)) */ + la r6, r0, TOPHYS(lw_table); + addk r5, r5, r5; + addk r5, r5, r5; + addk r5, r5, r5; + addk r5, r5, r6; + bra r5; +ex_lw_end: /* Exception handling of load word, ends */ +ex_sw: + /* Get the destination register number into r5 */ + lbui r5, r0, TOPHYS(ex_reg_op); + /* Form store_word jump table offset (sw_table + (8 * regnum)) */ + la r6, r0, TOPHYS(sw_table); + add r5, r5, r5; + add r5, r5, r5; + add r5, r5, r5; + add r5, r5, r6; + bra r5; +ex_sw_tail: + mfs r6, resr; + nop + andi r6, r6, 0x800; /* Extract ESR[W] */ + beqi r6, ex_shw; + /* Get the word - delay slot */ + swi r3, r0, TOPHYS(ex_tmp_data_loc_0); + /* Store the word, byte-by-byte into destination address */ + lbui r3, r0, TOPHYS(ex_tmp_data_loc_0); + sbi r3, r4, 0; + lbui r3, r0, TOPHYS(ex_tmp_data_loc_1); + sbi r3, r4, 1; + lbui r3, r0, TOPHYS(ex_tmp_data_loc_2); + sbi r3, r4, 2; + lbui r3, r0, TOPHYS(ex_tmp_data_loc_3); + sbi r3, r4, 3; + bri ex_handler_done; + +ex_shw: + /* Store the lower half-word, byte-by-byte into destination address */ + swi r3, r0, TOPHYS(ex_tmp_data_loc_0); + lbui r3, r0, TOPHYS(ex_tmp_data_loc_2); + sbi r3, r4, 0; + lbui r3, r0, TOPHYS(ex_tmp_data_loc_3); + sbi r3, r4, 1; +ex_sw_end: /* Exception handling of store word, ends. */ + +ex_handler_done: + lwi r5, r1, 0 /* RMSR */ + mts rmsr, r5 + nop + lwi r3, r1, PT_R3 + lwi r4, r1, PT_R4 + lwi r5, r1, PT_R5 + lwi r6, r1, PT_R6 + lwi r17, r1, PT_R17 + + rted r17, 0 + addik r1, r1, (EX_HANDLER_STACK_SIZ); /* Restore stack frame */ + +.end _hw_exception_handler + +ex_handler_unhandled: +/* FIXME add handle function for unhandled exception - dump register */ + bri 0 + +.section .text +.align 4 +lw_table: +lw_r0: R3_TO_LWREG (0); +lw_r1: LWREG_NOP; +lw_r2: R3_TO_LWREG (2); +lw_r3: R3_TO_LWREG_V (3); +lw_r4: R3_TO_LWREG_V (4); +lw_r5: R3_TO_LWREG_V (5); +lw_r6: R3_TO_LWREG_V (6); +lw_r7: R3_TO_LWREG (7); +lw_r8: R3_TO_LWREG (8); +lw_r9: R3_TO_LWREG (9); +lw_r10: R3_TO_LWREG (10); +lw_r11: R3_TO_LWREG (11); +lw_r12: R3_TO_LWREG (12); +lw_r13: R3_TO_LWREG (13); +lw_r14: R3_TO_LWREG (14); +lw_r15: R3_TO_LWREG (15); +lw_r16: R3_TO_LWREG (16); +lw_r17: LWREG_NOP; +lw_r18: R3_TO_LWREG (18); +lw_r19: R3_TO_LWREG (19); +lw_r20: R3_TO_LWREG (20); +lw_r21: R3_TO_LWREG (21); +lw_r22: R3_TO_LWREG (22); +lw_r23: R3_TO_LWREG (23); +lw_r24: R3_TO_LWREG (24); +lw_r25: R3_TO_LWREG (25); +lw_r26: R3_TO_LWREG (26); +lw_r27: R3_TO_LWREG (27); +lw_r28: R3_TO_LWREG (28); +lw_r29: R3_TO_LWREG (29); +lw_r30: R3_TO_LWREG (30); +lw_r31: R3_TO_LWREG (31); + +sw_table: +sw_r0: SWREG_TO_R3 (0); +sw_r1: SWREG_NOP; +sw_r2: SWREG_TO_R3 (2); +sw_r3: SWREG_TO_R3_V (3); +sw_r4: SWREG_TO_R3_V (4); +sw_r5: SWREG_TO_R3_V (5); +sw_r6: SWREG_TO_R3_V (6); +sw_r7: SWREG_TO_R3 (7); +sw_r8: SWREG_TO_R3 (8); +sw_r9: SWREG_TO_R3 (9); +sw_r10: SWREG_TO_R3 (10); +sw_r11: SWREG_TO_R3 (11); +sw_r12: SWREG_TO_R3 (12); +sw_r13: SWREG_TO_R3 (13); +sw_r14: SWREG_TO_R3 (14); +sw_r15: SWREG_TO_R3 (15); +sw_r16: SWREG_TO_R3 (16); +sw_r17: SWREG_NOP; +sw_r18: SWREG_TO_R3 (18); +sw_r19: SWREG_TO_R3 (19); +sw_r20: SWREG_TO_R3 (20); +sw_r21: SWREG_TO_R3 (21); +sw_r22: SWREG_TO_R3 (22); +sw_r23: SWREG_TO_R3 (23); +sw_r24: SWREG_TO_R3 (24); +sw_r25: SWREG_TO_R3 (25); +sw_r26: SWREG_TO_R3 (26); +sw_r27: SWREG_TO_R3 (27); +sw_r28: SWREG_TO_R3 (28); +sw_r29: SWREG_TO_R3 (29); +sw_r30: SWREG_TO_R3 (30); +sw_r31: SWREG_TO_R3 (31); + +/* Temporary data structures used in the handler */ +.section .data +.align 4 +ex_tmp_data_loc_0: + .byte 0 +ex_tmp_data_loc_1: + .byte 0 +ex_tmp_data_loc_2: + .byte 0 +ex_tmp_data_loc_3: + .byte 0 +ex_reg_op: + .byte 0 diff --git a/arch/microblaze/kernel/init_task.c b/arch/microblaze/kernel/init_task.c new file mode 100644 index 00000000000..48eb9fb255f --- /dev/null +++ b/arch/microblaze/kernel/init_task.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/init_task.h> +#include <linux/fs.h> +#include <linux/mqueue.h> + +#include <asm/pgtable.h> + +static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); +struct mm_struct init_mm = INIT_MM(init_mm); +EXPORT_SYMBOL(init_mm); + +union thread_union init_thread_union + __attribute__((__section__(".data.init_task"))) = +{ INIT_THREAD_INFO(init_task) }; + +struct task_struct init_task = INIT_TASK(init_task); +EXPORT_SYMBOL(init_task); diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c new file mode 100644 index 00000000000..a69d3e3c2fd --- /dev/null +++ b/arch/microblaze/kernel/intc.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/init.h> +#include <linux/irq.h> +#include <asm/page.h> +#include <linux/io.h> + +#include <asm/prom.h> +#include <asm/irq.h> + +#ifdef CONFIG_SELFMOD_INTC +#include <asm/selfmod.h> +#define INTC_BASE BARRIER_BASE_ADDR +#else +static unsigned int intc_baseaddr; +#define INTC_BASE intc_baseaddr +#endif + +unsigned int nr_irq; + +/* No one else should require these constants, so define them locally here. */ +#define ISR 0x00 /* Interrupt Status Register */ +#define IPR 0x04 /* Interrupt Pending Register */ +#define IER 0x08 /* Interrupt Enable Register */ +#define IAR 0x0c /* Interrupt Acknowledge Register */ +#define SIE 0x10 /* Set Interrupt Enable bits */ +#define CIE 0x14 /* Clear Interrupt Enable bits */ +#define IVR 0x18 /* Interrupt Vector Register */ +#define MER 0x1c /* Master Enable Register */ + +#define MER_ME (1<<0) +#define MER_HIE (1<<1) + +static void intc_enable_or_unmask(unsigned int irq) +{ + pr_debug("enable_or_unmask: %d\n", irq); + out_be32(INTC_BASE + SIE, 1 << irq); +} + +static void intc_disable_or_mask(unsigned int irq) +{ + pr_debug("disable: %d\n", irq); + out_be32(INTC_BASE + CIE, 1 << irq); +} + +static void intc_ack(unsigned int irq) +{ + pr_debug("ack: %d\n", irq); + out_be32(INTC_BASE + IAR, 1 << irq); +} + +static void intc_mask_ack(unsigned int irq) +{ + unsigned long mask = 1 << irq; + pr_debug("disable_and_ack: %d\n", irq); + out_be32(INTC_BASE + CIE, mask); + out_be32(INTC_BASE + IAR, mask); +} + +static void intc_end(unsigned int irq) +{ + unsigned long mask = 1 << irq; + pr_debug("end: %d\n", irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + out_be32(INTC_BASE + SIE, mask); + /* ack level sensitive intr */ + if (irq_desc[irq].status & IRQ_LEVEL) + out_be32(INTC_BASE + IAR, mask); + } +} + +static struct irq_chip intc_dev = { + .name = "Xilinx INTC", + .unmask = intc_enable_or_unmask, + .mask = intc_disable_or_mask, + .ack = intc_ack, + .mask_ack = intc_mask_ack, + .end = intc_end, +}; + +unsigned int get_irq(struct pt_regs *regs) +{ + int irq; + + /* + * NOTE: This function is the one that needs to be improved in + * order to handle multiple interrupt controllers. It currently + * is hardcoded to check for interrupts only on the first INTC. + */ + irq = in_be32(INTC_BASE + IVR); + pr_debug("get_irq: %d\n", irq); + + return irq; +} + +void __init init_IRQ(void) +{ + u32 i, j, intr_type; + struct device_node *intc = NULL; +#ifdef CONFIG_SELFMOD_INTC + unsigned int intc_baseaddr = 0; + static int arr_func[] = { + (int)&get_irq, + (int)&intc_enable_or_unmask, + (int)&intc_disable_or_mask, + (int)&intc_mask_ack, + (int)&intc_ack, + (int)&intc_end, + 0 + }; +#endif + static char *intc_list[] = { + "xlnx,xps-intc-1.00.a", + "xlnx,opb-intc-1.00.c", + "xlnx,opb-intc-1.00.b", + "xlnx,opb-intc-1.00.a", + NULL + }; + + for (j = 0; intc_list[j] != NULL; j++) { + intc = of_find_compatible_node(NULL, NULL, intc_list[j]); + if (intc) + break; + } + + intc_baseaddr = *(int *) of_get_property(intc, "reg", NULL); + intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE); + nr_irq = *(int *) of_get_property(intc, "xlnx,num-intr-inputs", NULL); + + intr_type = + *(int *) of_get_property(intc, "xlnx,kind-of-intr", NULL); + if (intr_type >= (1 << nr_irq)) + printk(KERN_INFO " ERROR: Mishmash in king-of-intr param\n"); + +#ifdef CONFIG_SELFMOD_INTC + selfmod_function((int *) arr_func, intc_baseaddr); +#endif + printk(KERN_INFO "%s #0 at 0x%08x, num_irq=%d, edge=0x%x\n", + intc_list[j], intc_baseaddr, nr_irq, intr_type); + + /* + * Disable all external interrupts until they are + * explicity requested. + */ + out_be32(intc_baseaddr + IER, 0); + + /* Acknowledge any pending interrupts just in case. */ + out_be32(intc_baseaddr + IAR, 0xffffffff); + + /* Turn on the Master Enable. */ + out_be32(intc_baseaddr + MER, MER_HIE | MER_ME); + + for (i = 0; i < nr_irq; ++i) { + if (intr_type & (0x00000001 << i)) { + set_irq_chip_and_handler_name(i, &intc_dev, + handle_edge_irq, intc_dev.name); + irq_desc[i].status &= ~IRQ_LEVEL; + } else { + set_irq_chip_and_handler_name(i, &intc_dev, + handle_level_irq, intc_dev.name); + irq_desc[i].status |= IRQ_LEVEL; + } + } +} diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c new file mode 100644 index 00000000000..f688ee93e3b --- /dev/null +++ b/arch/microblaze/kernel/irq.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/hardirq.h> +#include <linux/interrupt.h> +#include <linux/irqflags.h> +#include <linux/seq_file.h> +#include <linux/kernel_stat.h> +#include <linux/irq.h> + +#include <asm/prom.h> + +unsigned int irq_of_parse_and_map(struct device_node *dev, int index) +{ + struct of_irq oirq; + + if (of_irq_map_one(dev, index, &oirq)) + return NO_IRQ; + + return oirq.specifier[0]; +} +EXPORT_SYMBOL_GPL(irq_of_parse_and_map); + +/* + * 'what should we do if we get a hw irq event on an illegal vector'. + * each architecture has to answer this themselves. + */ +void ack_bad_irq(unsigned int irq) +{ + printk(KERN_WARNING "unexpected IRQ trap at vector %02x\n", irq); +} + +static u32 concurrent_irq; + +void do_IRQ(struct pt_regs *regs) +{ + unsigned int irq; + struct pt_regs *old_regs = set_irq_regs(regs); + + irq_enter(); + irq = get_irq(regs); +next_irq: + BUG_ON(irq == -1U); + generic_handle_irq(irq); + + irq = get_irq(regs); + if (irq != -1U) { + pr_debug("next irq: %d\n", irq); + ++concurrent_irq; + goto next_irq; + } + + irq_exit(); + set_irq_regs(old_regs); +} + +int show_interrupts(struct seq_file *p, void *v) +{ + int i = *(loff_t *) v, j; + struct irqaction *action; + unsigned long flags; + + if (i == 0) { + seq_printf(p, " "); + for_each_online_cpu(j) + seq_printf(p, "CPU%-8d", j); + seq_putc(p, '\n'); + } + + if (i < nr_irq) { + spin_lock_irqsave(&irq_desc[i].lock, flags); + action = irq_desc[i].action; + if (!action) + goto skip; + seq_printf(p, "%3d: ", i); +#ifndef CONFIG_SMP + seq_printf(p, "%10u ", kstat_irqs(i)); +#else + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); +#endif + seq_printf(p, " %8s", irq_desc[i].status & + IRQ_LEVEL ? "level" : "edge"); + seq_printf(p, " %8s", irq_desc[i].chip->name); + seq_printf(p, " %s", action->name); + + for (action = action->next; action; action = action->next) + seq_printf(p, ", %s", action->name); + + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } + return 0; +} diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c new file mode 100644 index 00000000000..5f71790e3c3 --- /dev/null +++ b/arch/microblaze/kernel/microblaze_ksyms.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2008-2009 PetaLogix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/string.h> +#include <linux/cryptohash.h> +#include <linux/delay.h> +#include <linux/in6.h> +#include <linux/syscalls.h> + +#include <asm/checksum.h> +#include <linux/io.h> +#include <asm/page.h> +#include <asm/system.h> +#include <linux/uaccess.h> + +/* + * libgcc functions - functions that are used internally by the + * compiler... (prototypes are not correct though, but that + * doesn't really matter since they're not versioned). + */ +extern void __ashldi3(void); +EXPORT_SYMBOL(__ashldi3); +extern void __ashrdi3(void); +EXPORT_SYMBOL(__ashrdi3); +extern void __divsi3(void); +EXPORT_SYMBOL(__divsi3); +extern void __lshrdi3(void); +EXPORT_SYMBOL(__lshrdi3); +extern void __modsi3(void); +EXPORT_SYMBOL(__modsi3); +extern void __mulsi3(void); +EXPORT_SYMBOL(__mulsi3); +extern void __muldi3(void); +EXPORT_SYMBOL(__muldi3); +extern void __ucmpdi2(void); +EXPORT_SYMBOL(__ucmpdi2); +extern void __udivsi3(void); +EXPORT_SYMBOL(__udivsi3); +extern void __umodsi3(void); +EXPORT_SYMBOL(__umodsi3); diff --git a/arch/microblaze/kernel/module.c b/arch/microblaze/kernel/module.c new file mode 100644 index 00000000000..51414171326 --- /dev/null +++ b/arch/microblaze/kernel/module.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/moduleloader.h> +#include <linux/kernel.h> +#include <linux/elf.h> +#include <linux/vmalloc.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/string.h> + +#include <asm/pgtable.h> + +void *module_alloc(unsigned long size) +{ + void *ret; + ret = (size == 0) ? NULL : vmalloc(size); + pr_debug("module_alloc (%08lx@%08lx)\n", size, (unsigned long int)ret); + return ret; +} + +void module_free(struct module *module, void *region) +{ + pr_debug("module_free(%s,%08lx)\n", module->name, + (unsigned long)region); + vfree(region); +} + +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, + struct module *mod) +{ + return 0; +} + +int apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, + unsigned int symindex, unsigned int relsec, struct module *module) +{ + printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", + module->name); + return -ENOEXEC; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, + unsigned int symindex, unsigned int relsec, struct module *module) +{ + + unsigned int i; + Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + unsigned long int *location; + unsigned long int locoffs; + unsigned long int value; +#if __GNUC__ < 4 + unsigned long int old_value; +#endif + + pr_debug("Applying add relocation section %u to %u\n", + relsec, sechdrs[relsec].sh_info); + + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { + + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rela[i].r_offset; + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rela[i].r_info); + value = sym->st_value + rela[i].r_addend; + + switch (ELF32_R_TYPE(rela[i].r_info)) { + + /* + * Be careful! mb-gcc / mb-ld splits the relocs between the + * text and the reloc table. In general this means we must + * read the current contents of (*location), add any offset + * then store the result back in + */ + + case R_MICROBLAZE_32: +#if __GNUC__ < 4 + old_value = *location; + *location = value + old_value; + + pr_debug("R_MICROBLAZE_32 (%08lx->%08lx)\n", + old_value, value); +#else + *location = value; +#endif + break; + + case R_MICROBLAZE_64: +#if __GNUC__ < 4 + /* Split relocs only required/used pre gcc4.1.1 */ + old_value = ((location[0] & 0x0000FFFF) << 16) | + (location[1] & 0x0000FFFF); + value += old_value; +#endif + location[0] = (location[0] & 0xFFFF0000) | + (value >> 16); + location[1] = (location[1] & 0xFFFF0000) | + (value & 0xFFFF); +#if __GNUC__ < 4 + pr_debug("R_MICROBLAZE_64 (%08lx->%08lx)\n", + old_value, value); +#endif + break; + + case R_MICROBLAZE_64_PCREL: + locoffs = (location[0] & 0xFFFF) << 16 | + (location[1] & 0xFFFF); + value -= (unsigned long int)(location) + 4 + + locoffs; + location[0] = (location[0] & 0xFFFF0000) | + (value >> 16); + location[1] = (location[1] & 0xFFFF0000) | + (value & 0xFFFF); + pr_debug("R_MICROBLAZE_64_PCREL (%08lx)\n", + value); + break; + + case R_MICROBLAZE_NONE: + pr_debug("R_MICROBLAZE_NONE\n"); + break; + + default: + printk(KERN_ERR "module %s: " + "Unknown relocation: %u\n", + module->name, + ELF32_R_TYPE(rela->r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, + struct module *module) +{ + return 0; +} + +void module_arch_cleanup(struct module *mod) +{ +} diff --git a/arch/microblaze/kernel/of_device.c b/arch/microblaze/kernel/of_device.c new file mode 100644 index 00000000000..9a0f7632c47 --- /dev/null +++ b/arch/microblaze/kernel/of_device.c @@ -0,0 +1,113 @@ +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/of.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/slab.h> +#include <linux/of_device.h> + +#include <linux/errno.h> + +void of_device_make_bus_id(struct of_device *dev) +{ + static atomic_t bus_no_reg_magic; + struct device_node *node = dev->node; + const u32 *reg; + u64 addr; + int magic; + + /* + * For MMIO, get the physical address + */ + reg = of_get_property(node, "reg", NULL); + if (reg) { + addr = of_translate_address(node, reg); + if (addr != OF_BAD_ADDR) { + dev_set_name(&dev->dev, "%llx.%s", + (unsigned long long)addr, node->name); + return; + } + } + + /* + * No BusID, use the node name and add a globally incremented + * counter (and pray...) + */ + magic = atomic_add_return(1, &bus_no_reg_magic); + dev_set_name(&dev->dev, "%s.%d", node->name, magic - 1); +} +EXPORT_SYMBOL(of_device_make_bus_id); + +struct of_device *of_device_alloc(struct device_node *np, + const char *bus_id, + struct device *parent) +{ + struct of_device *dev; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + + dev->node = of_node_get(np); + dev->dev.dma_mask = &dev->dma_mask; + dev->dev.parent = parent; + dev->dev.release = of_release_dev; + dev->dev.archdata.of_node = np; + + if (bus_id) + dev_set_name(&dev->dev, bus_id); + else + of_device_make_bus_id(dev); + + return dev; +} +EXPORT_SYMBOL(of_device_alloc); + +int of_device_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + struct of_device *ofdev; + const char *compat; + int seen = 0, cplen, sl; + + if (!dev) + return -ENODEV; + + ofdev = to_of_device(dev); + + if (add_uevent_var(env, "OF_NAME=%s", ofdev->node->name)) + return -ENOMEM; + + if (add_uevent_var(env, "OF_TYPE=%s", ofdev->node->type)) + return -ENOMEM; + + /* Since the compatible field can contain pretty much anything + * it's not really legal to split it out with commas. We split it + * up using a number of environment variables instead. */ + + compat = of_get_property(ofdev->node, "compatible", &cplen); + while (compat && *compat && cplen > 0) { + if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat)) + return -ENOMEM; + + sl = strlen(compat) + 1; + compat += sl; + cplen -= sl; + seen++; + } + + if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen)) + return -ENOMEM; + + /* modalias is trickier, we add it in 2 steps */ + if (add_uevent_var(env, "MODALIAS=")) + return -ENOMEM; + sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1], + sizeof(env->buf) - env->buflen); + if (sl >= (sizeof(env->buf) - env->buflen)) + return -ENOMEM; + env->buflen += sl; + + return 0; +} +EXPORT_SYMBOL(of_device_uevent); diff --git a/arch/microblaze/kernel/of_platform.c b/arch/microblaze/kernel/of_platform.c new file mode 100644 index 00000000000..acf4574d0f1 --- /dev/null +++ b/arch/microblaze/kernel/of_platform.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * and Arnd Bergmann, IBM Corp. + * + * 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. + * + */ + +#undef DEBUG + +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/slab.h> +#include <linux/pci.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> + +#include <linux/errno.h> +#include <linux/topology.h> +#include <asm/atomic.h> + +struct bus_type of_platform_bus_type = { + .uevent = of_device_uevent, +}; +EXPORT_SYMBOL(of_platform_bus_type); + +static int __init of_bus_driver_init(void) +{ + return of_bus_type_init(&of_platform_bus_type, "of_platform"); +} +postcore_initcall(of_bus_driver_init); + +struct of_device *of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent) +{ + struct of_device *dev; + + dev = of_device_alloc(np, bus_id, parent); + if (!dev) + return NULL; + + dev->dma_mask = 0xffffffffUL; + dev->dev.bus = &of_platform_bus_type; + + /* We do not fill the DMA ops for platform devices by default. + * This is currently the responsibility of the platform code + * to do such, possibly using a device notifier + */ + + if (of_device_register(dev) != 0) { + of_device_free(dev); + return NULL; + } + + return dev; +} +EXPORT_SYMBOL(of_platform_device_create); + +/** + * of_platform_bus_create - Create an OF device for a bus node and all its + * children. Optionally recursively instanciate matching busses. + * @bus: device node of the bus to instanciate + * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to + * disallow recursive creation of child busses + */ +static int of_platform_bus_create(const struct device_node *bus, + const struct of_device_id *matches, + struct device *parent) +{ + struct device_node *child; + struct of_device *dev; + int rc = 0; + + for_each_child_of_node(bus, child) { + pr_debug(" create child: %s\n", child->full_name); + dev = of_platform_device_create(child, NULL, parent); + if (dev == NULL) + rc = -ENOMEM; + else if (!of_match_node(matches, child)) + continue; + if (rc == 0) { + pr_debug(" and sub busses\n"); + rc = of_platform_bus_create(child, matches, &dev->dev); + } + if (rc) { + of_node_put(child); + break; + } + } + return rc; +} + + +/** + * of_platform_bus_probe - Probe the device-tree for platform busses + * @root: parent of the first level to probe or NULL for the root of the tree + * @matches: match table, NULL to use the default + * @parent: parent to hook devices from, NULL for toplevel + * + * Note that children of the provided root are not instanciated as devices + * unless the specified root itself matches the bus list and is not NULL. + */ + +int of_platform_bus_probe(struct device_node *root, + const struct of_device_id *matches, + struct device *parent) +{ + struct device_node *child; + struct of_device *dev; + int rc = 0; + + if (matches == NULL) + matches = of_default_bus_ids; + if (matches == OF_NO_DEEP_PROBE) + return -EINVAL; + if (root == NULL) + root = of_find_node_by_path("/"); + else + of_node_get(root); + + pr_debug("of_platform_bus_probe()\n"); + pr_debug(" starting at: %s\n", root->full_name); + + /* Do a self check of bus type, if there's a match, create + * children + */ + if (of_match_node(matches, root)) { + pr_debug(" root match, create all sub devices\n"); + dev = of_platform_device_create(root, NULL, parent); + if (dev == NULL) { + rc = -ENOMEM; + goto bail; + } + pr_debug(" create all sub busses\n"); + rc = of_platform_bus_create(root, matches, &dev->dev); + goto bail; + } + for_each_child_of_node(root, child) { + if (!of_match_node(matches, child)) + continue; + + pr_debug(" match: %s\n", child->full_name); + dev = of_platform_device_create(child, NULL, parent); + if (dev == NULL) + rc = -ENOMEM; + else + rc = of_platform_bus_create(child, matches, &dev->dev); + if (rc) { + of_node_put(child); + break; + } + } + bail: + of_node_put(root); + return rc; +} +EXPORT_SYMBOL(of_platform_bus_probe); + +static int of_dev_node_match(struct device *dev, void *data) +{ + return to_of_device(dev)->node == data; +} + +struct of_device *of_find_device_by_node(struct device_node *np) +{ + struct device *dev; + + dev = bus_find_device(&of_platform_bus_type, + NULL, np, of_dev_node_match); + if (dev) + return to_of_device(dev); + return NULL; +} +EXPORT_SYMBOL(of_find_device_by_node); + +static int of_dev_phandle_match(struct device *dev, void *data) +{ + phandle *ph = data; + return to_of_device(dev)->node->linux_phandle == *ph; +} + +struct of_device *of_find_device_by_phandle(phandle ph) +{ + struct device *dev; + + dev = bus_find_device(&of_platform_bus_type, + NULL, &ph, of_dev_phandle_match); + if (dev) + return to_of_device(dev); + return NULL; +} +EXPORT_SYMBOL(of_find_device_by_phandle); diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c new file mode 100644 index 00000000000..436f26ccbfa --- /dev/null +++ b/arch/microblaze/kernel/process.c @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2008-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/pm.h> +#include <linux/tick.h> +#include <linux/bitops.h> +#include <asm/system.h> +#include <asm/pgalloc.h> + +void show_regs(struct pt_regs *regs) +{ + printk(KERN_INFO " Registers dump: mode=%X\r\n", regs->kernel_mode); + printk(KERN_INFO " r1=%08lX, r2=%08lX, r3=%08lX, r4=%08lX\n", + regs->r1, regs->r2, regs->r3, regs->r4); + printk(KERN_INFO " r5=%08lX, r6=%08lX, r7=%08lX, r8=%08lX\n", + regs->r5, regs->r6, regs->r7, regs->r8); + printk(KERN_INFO " r9=%08lX, r10=%08lX, r11=%08lX, r12=%08lX\n", + regs->r9, regs->r10, regs->r11, regs->r12); + printk(KERN_INFO " r13=%08lX, r14=%08lX, r15=%08lX, r16=%08lX\n", + regs->r13, regs->r14, regs->r15, regs->r16); + printk(KERN_INFO " r17=%08lX, r18=%08lX, r19=%08lX, r20=%08lX\n", + regs->r17, regs->r18, regs->r19, regs->r20); + printk(KERN_INFO " r21=%08lX, r22=%08lX, r23=%08lX, r24=%08lX\n", + regs->r21, regs->r22, regs->r23, regs->r24); + printk(KERN_INFO " r25=%08lX, r26=%08lX, r27=%08lX, r28=%08lX\n", + regs->r25, regs->r26, regs->r27, regs->r28); + printk(KERN_INFO " r29=%08lX, r30=%08lX, r31=%08lX, rPC=%08lX\n", + regs->r29, regs->r30, regs->r31, regs->pc); + printk(KERN_INFO " msr=%08lX, ear=%08lX, esr=%08lX, fsr=%08lX\n", + regs->msr, regs->ear, regs->esr, regs->fsr); + while (1) + ; +} + +void (*pm_idle)(void); +void (*pm_power_off)(void) = NULL; +EXPORT_SYMBOL(pm_power_off); + +static int hlt_counter = 1; + +void disable_hlt(void) +{ + hlt_counter++; +} +EXPORT_SYMBOL(disable_hlt); + +void enable_hlt(void) +{ + hlt_counter--; +} +EXPORT_SYMBOL(enable_hlt); + +static int __init nohlt_setup(char *__unused) +{ + hlt_counter = 1; + return 1; +} +__setup("nohlt", nohlt_setup); + +static int __init hlt_setup(char *__unused) +{ + hlt_counter = 0; + return 1; +} +__setup("hlt", hlt_setup); + +void default_idle(void) +{ + if (!hlt_counter) { + clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb__after_clear_bit(); + local_irq_disable(); + while (!need_resched()) + cpu_sleep(); + local_irq_enable(); + set_thread_flag(TIF_POLLING_NRFLAG); + } else + while (!need_resched()) + cpu_relax(); +} + +void cpu_idle(void) +{ + set_thread_flag(TIF_POLLING_NRFLAG); + + /* endless idle loop with no priority at all */ + while (1) { + void (*idle)(void) = pm_idle; + + if (!idle) + idle = default_idle; + + tick_nohz_stop_sched_tick(1); + while (!need_resched()) + idle(); + tick_nohz_restart_sched_tick(); + + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + check_pgt_cache(); + } +} + +void flush_thread(void) +{ +} + +int copy_thread(unsigned long clone_flags, unsigned long usp, + unsigned long unused, + struct task_struct *p, struct pt_regs *regs) +{ + struct pt_regs *childregs = task_pt_regs(p); + struct thread_info *ti = task_thread_info(p); + + *childregs = *regs; + if (user_mode(regs)) + childregs->r1 = usp; + else + childregs->r1 = ((unsigned long) ti) + THREAD_SIZE; + + memset(&ti->cpu_context, 0, sizeof(struct cpu_context)); + ti->cpu_context.r1 = (unsigned long)childregs; + ti->cpu_context.msr = (unsigned long)childregs->msr; + ti->cpu_context.r15 = (unsigned long)ret_from_fork - 8; + + if (clone_flags & CLONE_SETTLS) + ; + + return 0; +} + +/* + * Return saved PC of a blocked thread. + */ +unsigned long thread_saved_pc(struct task_struct *tsk) +{ + struct cpu_context *ctx = + &(((struct thread_info *)(tsk->stack))->cpu_context); + + /* Check whether the thread is blocked in resume() */ + if (in_sched_functions(ctx->r15)) + return (unsigned long)ctx->r15; + else + return ctx->r14; +} + +static void kernel_thread_helper(int (*fn)(void *), void *arg) +{ + fn(arg); + do_exit(-1); +} + +int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) +{ + struct pt_regs regs; + int ret; + + memset(®s, 0, sizeof(regs)); + /* store them in non-volatile registers */ + regs.r5 = (unsigned long)fn; + regs.r6 = (unsigned long)arg; + local_save_flags(regs.msr); + regs.pc = (unsigned long)kernel_thread_helper; + regs.kernel_mode = 1; + + ret = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, + ®s, 0, NULL, NULL); + + return ret; +} + +unsigned long get_wchan(struct task_struct *p) +{ +/* TBD (used by procfs) */ + return 0; +} diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c new file mode 100644 index 00000000000..34c48718061 --- /dev/null +++ b/arch/microblaze/kernel/prom.c @@ -0,0 +1,1146 @@ +/* + * Procedures for creating, accessing and interpreting the device tree. + * + * Paul Mackerras August 1996. + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. + * {engebret|bergner}@us.ibm.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <stdarg.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/init.h> +#include <linux/threads.h> +#include <linux/spinlock.h> +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/stringify.h> +#include <linux/delay.h> +#include <linux/initrd.h> +#include <linux/bitops.h> +#include <linux/module.h> +#include <linux/kexec.h> +#include <linux/debugfs.h> +#include <linux/irq.h> +#include <linux/lmb.h> + +#include <asm/prom.h> +#include <asm/page.h> +#include <asm/processor.h> +#include <asm/irq.h> +#include <linux/io.h> +#include <asm/system.h> +#include <asm/mmu.h> +#include <asm/pgtable.h> +#include <asm/sections.h> +#include <asm/pci-bridge.h> + +static int __initdata dt_root_addr_cells; +static int __initdata dt_root_size_cells; + +typedef u32 cell_t; + +static struct boot_param_header *initial_boot_params; + +/* export that to outside world */ +struct device_node *of_chosen; + +static inline char *find_flat_dt_string(u32 offset) +{ + return ((char *)initial_boot_params) + + initial_boot_params->off_dt_strings + offset; +} + +/** + * This function is used to scan the flattened device-tree, it is + * used to extract the memory informations at boot before we can + * unflatten the tree + */ +int __init of_scan_flat_dt(int (*it)(unsigned long node, + const char *uname, int depth, + void *data), + void *data) +{ + unsigned long p = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + int rc = 0; + int depth = -1; + + do { + u32 tag = *((u32 *)p); + char *pathp; + + p += 4; + if (tag == OF_DT_END_NODE) { + depth--; + continue; + } + if (tag == OF_DT_NOP) + continue; + if (tag == OF_DT_END) + break; + if (tag == OF_DT_PROP) { + u32 sz = *((u32 *)p); + p += 8; + if (initial_boot_params->version < 0x10) + p = _ALIGN(p, sz >= 8 ? 8 : 4); + p += sz; + p = _ALIGN(p, 4); + continue; + } + if (tag != OF_DT_BEGIN_NODE) { + printk(KERN_WARNING "Invalid tag %x scanning flattened" + " device tree !\n", tag); + return -EINVAL; + } + depth++; + pathp = (char *)p; + p = _ALIGN(p + strlen(pathp) + 1, 4); + if ((*pathp) == '/') { + char *lp, *np; + for (lp = NULL, np = pathp; *np; np++) + if ((*np) == '/') + lp = np+1; + if (lp != NULL) + pathp = lp; + } + rc = it(p, pathp, depth, data); + if (rc != 0) + break; + } while (1); + + return rc; +} + +unsigned long __init of_get_flat_dt_root(void) +{ + unsigned long p = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + + while (*((u32 *)p) == OF_DT_NOP) + p += 4; + BUG_ON(*((u32 *)p) != OF_DT_BEGIN_NODE); + p += 4; + return _ALIGN(p + strlen((char *)p) + 1, 4); +} + +/** + * This function can be used within scan_flattened_dt callback to get + * access to properties + */ +void *__init of_get_flat_dt_prop(unsigned long node, const char *name, + unsigned long *size) +{ + unsigned long p = node; + + do { + u32 tag = *((u32 *)p); + u32 sz, noff; + const char *nstr; + + p += 4; + if (tag == OF_DT_NOP) + continue; + if (tag != OF_DT_PROP) + return NULL; + + sz = *((u32 *)p); + noff = *((u32 *)(p + 4)); + p += 8; + if (initial_boot_params->version < 0x10) + p = _ALIGN(p, sz >= 8 ? 8 : 4); + + nstr = find_flat_dt_string(noff); + if (nstr == NULL) { + printk(KERN_WARNING "Can't find property index" + " name !\n"); + return NULL; + } + if (strcmp(name, nstr) == 0) { + if (size) + *size = sz; + return (void *)p; + } + p += sz; + p = _ALIGN(p, 4); + } while (1); +} + +int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) +{ + const char *cp; + unsigned long cplen, l; + + cp = of_get_flat_dt_prop(node, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + if (strncasecmp(cp, compat, strlen(compat)) == 0) + return 1; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} + +static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, + unsigned long align) +{ + void *res; + + *mem = _ALIGN(*mem, align); + res = (void *)*mem; + *mem += size; + + return res; +} + +static unsigned long __init unflatten_dt_node(unsigned long mem, + unsigned long *p, + struct device_node *dad, + struct device_node ***allnextpp, + unsigned long fpsize) +{ + struct device_node *np; + struct property *pp, **prev_pp = NULL; + char *pathp; + u32 tag; + unsigned int l, allocl; + int has_name = 0; + int new_format = 0; + + tag = *((u32 *)(*p)); + if (tag != OF_DT_BEGIN_NODE) { + printk("Weird tag at start of node: %x\n", tag); + return mem; + } + *p += 4; + pathp = (char *)*p; + l = allocl = strlen(pathp) + 1; + *p = _ALIGN(*p + l, 4); + + /* version 0x10 has a more compact unit name here instead of the full + * path. we accumulate the full path size using "fpsize", we'll rebuild + * it later. We detect this because the first character of the name is + * not '/'. + */ + if ((*pathp) != '/') { + new_format = 1; + if (fpsize == 0) { + /* root node: special case. fpsize accounts for path + * plus terminating zero. root node only has '/', so + * fpsize should be 2, but we want to avoid the first + * level nodes to have two '/' so we use fpsize 1 here + */ + fpsize = 1; + allocl = 2; + } else { + /* account for '/' and path size minus terminal 0 + * already in 'l' + */ + fpsize += l; + allocl = fpsize; + } + } + + np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, + __alignof__(struct device_node)); + if (allnextpp) { + memset(np, 0, sizeof(*np)); + np->full_name = ((char *)np) + sizeof(struct device_node); + if (new_format) { + char *p2 = np->full_name; + /* rebuild full path for new format */ + if (dad && dad->parent) { + strcpy(p2, dad->full_name); +#ifdef DEBUG + if ((strlen(p2) + l + 1) != allocl) { + pr_debug("%s: p: %d, l: %d, a: %d\n", + pathp, (int)strlen(p2), + l, allocl); + } +#endif + p2 += strlen(p2); + } + *(p2++) = '/'; + memcpy(p2, pathp, l); + } else + memcpy(np->full_name, pathp, l); + prev_pp = &np->properties; + **allnextpp = np; + *allnextpp = &np->allnext; + if (dad != NULL) { + np->parent = dad; + /* we temporarily use the next field as `last_child'*/ + if (dad->next == NULL) + dad->child = np; + else + dad->next->sibling = np; + dad->next = np; + } + kref_init(&np->kref); + } + while (1) { + u32 sz, noff; + char *pname; + + tag = *((u32 *)(*p)); + if (tag == OF_DT_NOP) { + *p += 4; + continue; + } + if (tag != OF_DT_PROP) + break; + *p += 4; + sz = *((u32 *)(*p)); + noff = *((u32 *)((*p) + 4)); + *p += 8; + if (initial_boot_params->version < 0x10) + *p = _ALIGN(*p, sz >= 8 ? 8 : 4); + + pname = find_flat_dt_string(noff); + if (pname == NULL) { + printk(KERN_INFO + "Can't find property name in list !\n"); + break; + } + if (strcmp(pname, "name") == 0) + has_name = 1; + l = strlen(pname) + 1; + pp = unflatten_dt_alloc(&mem, sizeof(struct property), + __alignof__(struct property)); + if (allnextpp) { + if (strcmp(pname, "linux,phandle") == 0) { + np->node = *((u32 *)*p); + if (np->linux_phandle == 0) + np->linux_phandle = np->node; + } + if (strcmp(pname, "ibm,phandle") == 0) + np->linux_phandle = *((u32 *)*p); + pp->name = pname; + pp->length = sz; + pp->value = (void *)*p; + *prev_pp = pp; + prev_pp = &pp->next; + } + *p = _ALIGN((*p) + sz, 4); + } + /* with version 0x10 we may not have the name property, recreate + * it here from the unit name if absent + */ + if (!has_name) { + char *p1 = pathp, *ps = pathp, *pa = NULL; + int sz; + + while (*p1) { + if ((*p1) == '@') + pa = p1; + if ((*p1) == '/') + ps = p1 + 1; + p1++; + } + if (pa < ps) + pa = p1; + sz = (pa - ps) + 1; + pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, + __alignof__(struct property)); + if (allnextpp) { + pp->name = "name"; + pp->length = sz; + pp->value = pp + 1; + *prev_pp = pp; + prev_pp = &pp->next; + memcpy(pp->value, ps, sz - 1); + ((char *)pp->value)[sz - 1] = 0; + pr_debug("fixed up name for %s -> %s\n", pathp, + (char *)pp->value); + } + } + if (allnextpp) { + *prev_pp = NULL; + np->name = of_get_property(np, "name", NULL); + np->type = of_get_property(np, "device_type", NULL); + + if (!np->name) + np->name = "<NULL>"; + if (!np->type) + np->type = "<NULL>"; + } + while (tag == OF_DT_BEGIN_NODE) { + mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); + tag = *((u32 *)(*p)); + } + if (tag != OF_DT_END_NODE) { + printk(KERN_INFO "Weird tag at end of node: %x\n", tag); + return mem; + } + *p += 4; + return mem; +} + +/** + * unflattens the device-tree passed by the firmware, creating the + * tree of struct device_node. It also fills the "name" and "type" + * pointers of the nodes so the normal device-tree walking functions + * can be used (this used to be done by finish_device_tree) + */ +void __init unflatten_device_tree(void) +{ + unsigned long start, mem, size; + struct device_node **allnextp = &allnodes; + + pr_debug(" -> unflatten_device_tree()\n"); + + /* First pass, scan for size */ + start = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + size = unflatten_dt_node(0, &start, NULL, NULL, 0); + size = (size | 3) + 1; + + pr_debug(" size is %lx, allocating...\n", size); + + /* Allocate memory for the expanded device tree */ + mem = lmb_alloc(size + 4, __alignof__(struct device_node)); + mem = (unsigned long) __va(mem); + + ((u32 *)mem)[size / 4] = 0xdeadbeef; + + pr_debug(" unflattening %lx...\n", mem); + + /* Second pass, do actual unflattening */ + start = ((unsigned long)initial_boot_params) + + initial_boot_params->off_dt_struct; + unflatten_dt_node(mem, &start, NULL, &allnextp, 0); + if (*((u32 *)start) != OF_DT_END) + printk(KERN_WARNING "Weird tag at end of tree: %08x\n", + *((u32 *)start)); + if (((u32 *)mem)[size / 4] != 0xdeadbeef) + printk(KERN_WARNING "End of tree marker overwritten: %08x\n", + ((u32 *)mem)[size / 4]); + *allnextp = NULL; + + /* Get pointer to OF "/chosen" node for use everywhere */ + of_chosen = of_find_node_by_path("/chosen"); + if (of_chosen == NULL) + of_chosen = of_find_node_by_path("/chosen@0"); + + pr_debug(" <- unflatten_device_tree()\n"); +} + +#define early_init_dt_scan_drconf_memory(node) 0 + +static int __init early_init_dt_scan_cpus(unsigned long node, + const char *uname, int depth, + void *data) +{ + static int logical_cpuid; + char *type = of_get_flat_dt_prop(node, "device_type", NULL); + const u32 *intserv; + int i, nthreads; + int found = 0; + + /* We are scanning "cpu" nodes only */ + if (type == NULL || strcmp(type, "cpu") != 0) + return 0; + + /* Get physical cpuid */ + intserv = of_get_flat_dt_prop(node, "reg", NULL); + nthreads = 1; + + /* + * Now see if any of these threads match our boot cpu. + * NOTE: This must match the parsing done in smp_setup_cpu_maps. + */ + for (i = 0; i < nthreads; i++) { + /* + * version 2 of the kexec param format adds the phys cpuid of + * booted proc. + */ + if (initial_boot_params && initial_boot_params->version >= 2) { + if (intserv[i] == + initial_boot_params->boot_cpuid_phys) { + found = 1; + break; + } + } else { + /* + * Check if it's the boot-cpu, set it's hw index now, + * unfortunately this format did not support booting + * off secondary threads. + */ + if (of_get_flat_dt_prop(node, + "linux,boot-cpu", NULL) != NULL) { + found = 1; + break; + } + } + +#ifdef CONFIG_SMP + /* logical cpu id is always 0 on UP kernels */ + logical_cpuid++; +#endif + } + + if (found) { + pr_debug("boot cpu: logical %d physical %d\n", logical_cpuid, + intserv[i]); + boot_cpuid = logical_cpuid; + } + + return 0; +} + +#ifdef CONFIG_BLK_DEV_INITRD +static void __init early_init_dt_check_for_initrd(unsigned long node) +{ + unsigned long l; + u32 *prop; + + pr_debug("Looking for initrd properties... "); + + prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); + if (prop) { + initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4)); + + prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); + if (prop) { + initrd_end = (unsigned long) + __va(of_read_ulong(prop, l/4)); + initrd_below_start_ok = 1; + } else { + initrd_start = 0; + } + } + + pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n", + initrd_start, initrd_end); +} +#else +static inline void early_init_dt_check_for_initrd(unsigned long node) +{ +} +#endif /* CONFIG_BLK_DEV_INITRD */ + +static int __init early_init_dt_scan_chosen(unsigned long node, + const char *uname, int depth, void *data) +{ + unsigned long l; + char *p; + + pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); + + if (depth != 1 || + (strcmp(uname, "chosen") != 0 && + strcmp(uname, "chosen@0") != 0)) + return 0; + +#ifdef CONFIG_KEXEC + lprop = (u64 *)of_get_flat_dt_prop(node, + "linux,crashkernel-base", NULL); + if (lprop) + crashk_res.start = *lprop; + + lprop = (u64 *)of_get_flat_dt_prop(node, + "linux,crashkernel-size", NULL); + if (lprop) + crashk_res.end = crashk_res.start + *lprop - 1; +#endif + + early_init_dt_check_for_initrd(node); + + /* Retreive command line */ + p = of_get_flat_dt_prop(node, "bootargs", &l); + if (p != NULL && l > 0) + strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); + +#ifdef CONFIG_CMDLINE + if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) + strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#endif /* CONFIG_CMDLINE */ + + pr_debug("Command line is: %s\n", cmd_line); + + /* break now */ + return 1; +} + +static int __init early_init_dt_scan_root(unsigned long node, + const char *uname, int depth, void *data) +{ + u32 *prop; + + if (depth != 0) + return 0; + + prop = of_get_flat_dt_prop(node, "#size-cells", NULL); + dt_root_size_cells = (prop == NULL) ? 1 : *prop; + pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells); + + prop = of_get_flat_dt_prop(node, "#address-cells", NULL); + dt_root_addr_cells = (prop == NULL) ? 2 : *prop; + pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells); + + /* break now */ + return 1; +} + +static u64 __init dt_mem_next_cell(int s, cell_t **cellp) +{ + cell_t *p = *cellp; + + *cellp = p + s; + return of_read_number(p, s); +} + +static int __init early_init_dt_scan_memory(unsigned long node, + const char *uname, int depth, void *data) +{ + char *type = of_get_flat_dt_prop(node, "device_type", NULL); + cell_t *reg, *endp; + unsigned long l; + + /* Look for the ibm,dynamic-reconfiguration-memory node */ +/* if (depth == 1 && + strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) + return early_init_dt_scan_drconf_memory(node); +*/ + /* We are scanning "memory" nodes only */ + if (type == NULL) { + /* + * The longtrail doesn't have a device_type on the + * /memory node, so look for the node called /memory@0. + */ + if (depth != 1 || strcmp(uname, "memory@0") != 0) + return 0; + } else if (strcmp(type, "memory") != 0) + return 0; + + reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l); + if (reg == NULL) + reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); + if (reg == NULL) + return 0; + + endp = reg + (l / sizeof(cell_t)); + + pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", + uname, l, reg[0], reg[1], reg[2], reg[3]); + + while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { + u64 base, size; + + base = dt_mem_next_cell(dt_root_addr_cells, ®); + size = dt_mem_next_cell(dt_root_size_cells, ®); + + if (size == 0) + continue; + pr_debug(" - %llx , %llx\n", (unsigned long long)base, + (unsigned long long)size); + + lmb_add(base, size); + } + return 0; +} + +#ifdef CONFIG_PHYP_DUMP +/** + * phyp_dump_calculate_reserve_size() - reserve variable boot area 5% or arg + * + * Function to find the largest size we need to reserve + * during early boot process. + * + * It either looks for boot param and returns that OR + * returns larger of 256 or 5% rounded down to multiples of 256MB. + * + */ +static inline unsigned long phyp_dump_calculate_reserve_size(void) +{ + unsigned long tmp; + + if (phyp_dump_info->reserve_bootvar) + return phyp_dump_info->reserve_bootvar; + + /* divide by 20 to get 5% of value */ + tmp = lmb_end_of_DRAM(); + do_div(tmp, 20); + + /* round it down in multiples of 256 */ + tmp = tmp & ~0x0FFFFFFFUL; + + return (tmp > PHYP_DUMP_RMR_END ? tmp : PHYP_DUMP_RMR_END); +} + +/** + * phyp_dump_reserve_mem() - reserve all not-yet-dumped mmemory + * + * This routine may reserve memory regions in the kernel only + * if the system is supported and a dump was taken in last + * boot instance or if the hardware is supported and the + * scratch area needs to be setup. In other instances it returns + * without reserving anything. The memory in case of dump being + * active is freed when the dump is collected (by userland tools). + */ +static void __init phyp_dump_reserve_mem(void) +{ + unsigned long base, size; + unsigned long variable_reserve_size; + + if (!phyp_dump_info->phyp_dump_configured) { + printk(KERN_ERR "Phyp-dump not supported on this hardware\n"); + return; + } + + if (!phyp_dump_info->phyp_dump_at_boot) { + printk(KERN_INFO "Phyp-dump disabled at boot time\n"); + return; + } + + variable_reserve_size = phyp_dump_calculate_reserve_size(); + + if (phyp_dump_info->phyp_dump_is_active) { + /* Reserve *everything* above RMR.Area freed by userland tools*/ + base = variable_reserve_size; + size = lmb_end_of_DRAM() - base; + + /* XXX crashed_ram_end is wrong, since it may be beyond + * the memory_limit, it will need to be adjusted. */ + lmb_reserve(base, size); + + phyp_dump_info->init_reserve_start = base; + phyp_dump_info->init_reserve_size = size; + } else { + size = phyp_dump_info->cpu_state_size + + phyp_dump_info->hpte_region_size + + variable_reserve_size; + base = lmb_end_of_DRAM() - size; + lmb_reserve(base, size); + phyp_dump_info->init_reserve_start = base; + phyp_dump_info->init_reserve_size = size; + } +} +#else +static inline void __init phyp_dump_reserve_mem(void) {} +#endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */ + +#ifdef CONFIG_EARLY_PRINTK +/* MS this is Microblaze specifig function */ +static int __init early_init_dt_scan_serial(unsigned long node, + const char *uname, int depth, void *data) +{ + unsigned long l; + char *p; + int *addr; + + pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); + +/* find all serial nodes */ + if (strncmp(uname, "serial", 6) != 0) + return 0; + + early_init_dt_check_for_initrd(node); + +/* find compatible node with uartlite */ + p = of_get_flat_dt_prop(node, "compatible", &l); + if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) && + (strncmp(p, "xlnx,opb-uartlite", 17) != 0)) + return 0; + + addr = of_get_flat_dt_prop(node, "reg", &l); + return *addr; /* return address */ +} + +/* this function is looking for early uartlite console - Microblaze specific */ +int __init early_uartlite_console(void) +{ + return of_scan_flat_dt(early_init_dt_scan_serial, NULL); +} +#endif + +void __init early_init_devtree(void *params) +{ + pr_debug(" -> early_init_devtree(%p)\n", params); + + /* Setup flat device-tree pointer */ + initial_boot_params = params; + +#ifdef CONFIG_PHYP_DUMP + /* scan tree to see if dump occured during last boot */ + of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL); +#endif + + /* Retrieve various informations from the /chosen node of the + * device-tree, including the platform type, initrd location and + * size, TCE reserve, and more ... + */ + of_scan_flat_dt(early_init_dt_scan_chosen, NULL); + + /* Scan memory nodes and rebuild LMBs */ + lmb_init(); + of_scan_flat_dt(early_init_dt_scan_root, NULL); + of_scan_flat_dt(early_init_dt_scan_memory, NULL); + + /* Save command line for /proc/cmdline and then parse parameters */ + strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); + parse_early_param(); + + lmb_analyze(); + + pr_debug("Phys. mem: %lx\n", (unsigned long) lmb_phys_mem_size()); + + pr_debug("Scanning CPUs ...\n"); + + /* Retreive CPU related informations from the flat tree + * (altivec support, boot CPU ID, ...) + */ + of_scan_flat_dt(early_init_dt_scan_cpus, NULL); + + pr_debug(" <- early_init_devtree()\n"); +} + +/** + * Indicates whether the root node has a given value in its + * compatible property. + */ +int machine_is_compatible(const char *compat) +{ + struct device_node *root; + int rc = 0; + + root = of_find_node_by_path("/"); + if (root) { + rc = of_device_is_compatible(root, compat); + of_node_put(root); + } + return rc; +} +EXPORT_SYMBOL(machine_is_compatible); + +/******* + * + * New implementation of the OF "find" APIs, return a refcounted + * object, call of_node_put() when done. The device tree and list + * are protected by a rw_lock. + * + * Note that property management will need some locking as well, + * this isn't dealt with yet. + * + *******/ + +/** + * of_find_node_by_phandle - Find a node given a phandle + * @handle: phandle of the node to find + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_phandle(phandle handle) +{ + struct device_node *np; + + read_lock(&devtree_lock); + for (np = allnodes; np != NULL; np = np->allnext) + if (np->linux_phandle == handle) + break; + of_node_get(np); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_node_by_phandle); + +/** + * of_find_all_nodes - Get next node in global list + * @prev: Previous node or NULL to start iteration + * of_node_put() will be called on it + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_all_nodes(struct device_node *prev) +{ + struct device_node *np; + + read_lock(&devtree_lock); + np = prev ? prev->allnext : allnodes; + for (; np != NULL; np = np->allnext) + if (of_node_get(np)) + break; + of_node_put(prev); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_all_nodes); + +/** + * of_node_get - Increment refcount of a node + * @node: Node to inc refcount, NULL is supported to + * simplify writing of callers + * + * Returns node. + */ +struct device_node *of_node_get(struct device_node *node) +{ + if (node) + kref_get(&node->kref); + return node; +} +EXPORT_SYMBOL(of_node_get); + +static inline struct device_node *kref_to_device_node(struct kref *kref) +{ + return container_of(kref, struct device_node, kref); +} + +/** + * of_node_release - release a dynamically allocated node + * @kref: kref element of the node to be released + * + * In of_node_put() this function is passed to kref_put() + * as the destructor. + */ +static void of_node_release(struct kref *kref) +{ + struct device_node *node = kref_to_device_node(kref); + struct property *prop = node->properties; + + /* We should never be releasing nodes that haven't been detached. */ + if (!of_node_check_flag(node, OF_DETACHED)) { + printk(KERN_INFO "WARNING: Bad of_node_put() on %s\n", + node->full_name); + dump_stack(); + kref_init(&node->kref); + return; + } + + if (!of_node_check_flag(node, OF_DYNAMIC)) + return; + + while (prop) { + struct property *next = prop->next; + kfree(prop->name); + kfree(prop->value); + kfree(prop); + prop = next; + + if (!prop) { + prop = node->deadprops; + node->deadprops = NULL; + } + } + kfree(node->full_name); + kfree(node->data); + kfree(node); +} + +/** + * of_node_put - Decrement refcount of a node + * @node: Node to dec refcount, NULL is supported to + * simplify writing of callers + * + */ +void of_node_put(struct device_node *node) +{ + if (node) + kref_put(&node->kref, of_node_release); +} +EXPORT_SYMBOL(of_node_put); + +/* + * Plug a device node into the tree and global list. + */ +void of_attach_node(struct device_node *np) +{ + unsigned long flags; + + write_lock_irqsave(&devtree_lock, flags); + np->sibling = np->parent->child; + np->allnext = allnodes; + np->parent->child = np; + allnodes = np; + write_unlock_irqrestore(&devtree_lock, flags); +} + +/* + * "Unplug" a node from the device tree. The caller must hold + * a reference to the node. The memory associated with the node + * is not freed until its refcount goes to zero. + */ +void of_detach_node(struct device_node *np) +{ + struct device_node *parent; + unsigned long flags; + + write_lock_irqsave(&devtree_lock, flags); + + parent = np->parent; + if (!parent) + goto out_unlock; + + if (allnodes == np) + allnodes = np->allnext; + else { + struct device_node *prev; + for (prev = allnodes; + prev->allnext != np; + prev = prev->allnext) + ; + prev->allnext = np->allnext; + } + + if (parent->child == np) + parent->child = np->sibling; + else { + struct device_node *prevsib; + for (prevsib = np->parent->child; + prevsib->sibling != np; + prevsib = prevsib->sibling) + ; + prevsib->sibling = np->sibling; + } + + of_node_set_flag(np, OF_DETACHED); + +out_unlock: + write_unlock_irqrestore(&devtree_lock, flags); +} + +/* + * Add a property to a node + */ +int prom_add_property(struct device_node *np, struct property *prop) +{ + struct property **next; + unsigned long flags; + + prop->next = NULL; + write_lock_irqsave(&devtree_lock, flags); + next = &np->properties; + while (*next) { + if (strcmp(prop->name, (*next)->name) == 0) { + /* duplicate ! don't insert it */ + write_unlock_irqrestore(&devtree_lock, flags); + return -1; + } + next = &(*next)->next; + } + *next = prop; + write_unlock_irqrestore(&devtree_lock, flags); + +#ifdef CONFIG_PROC_DEVICETREE + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_add_prop(np->pde, prop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} + +/* + * Remove a property from a node. Note that we don't actually + * remove it, since we have given out who-knows-how-many pointers + * to the data using get-property. Instead we just move the property + * to the "dead properties" list, so it won't be found any more. + */ +int prom_remove_property(struct device_node *np, struct property *prop) +{ + struct property **next; + unsigned long flags; + int found = 0; + + write_lock_irqsave(&devtree_lock, flags); + next = &np->properties; + while (*next) { + if (*next == prop) { + /* found the node */ + *next = prop->next; + prop->next = np->deadprops; + np->deadprops = prop; + found = 1; + break; + } + next = &(*next)->next; + } + write_unlock_irqrestore(&devtree_lock, flags); + + if (!found) + return -ENODEV; + +#ifdef CONFIG_PROC_DEVICETREE + /* try to remove the proc node as well */ + if (np->pde) + proc_device_tree_remove_prop(np->pde, prop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} + +/* + * Update a property in a node. Note that we don't actually + * remove it, since we have given out who-knows-how-many pointers + * to the data using get-property. Instead we just move the property + * to the "dead properties" list, and add the new property to the + * property list + */ +int prom_update_property(struct device_node *np, + struct property *newprop, + struct property *oldprop) +{ + struct property **next; + unsigned long flags; + int found = 0; + + write_lock_irqsave(&devtree_lock, flags); + next = &np->properties; + while (*next) { + if (*next == oldprop) { + /* found the node */ + newprop->next = oldprop->next; + *next = newprop; + oldprop->next = np->deadprops; + np->deadprops = oldprop; + found = 1; + break; + } + next = &(*next)->next; + } + write_unlock_irqrestore(&devtree_lock, flags); + + if (!found) + return -ENODEV; + +#ifdef CONFIG_PROC_DEVICETREE + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_update_prop(np->pde, newprop, oldprop); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} + +#if defined(CONFIG_DEBUG_FS) && defined(DEBUG) +static struct debugfs_blob_wrapper flat_dt_blob; + +static int __init export_flat_device_tree(void) +{ + struct dentry *d; + + flat_dt_blob.data = initial_boot_params; + flat_dt_blob.size = initial_boot_params->totalsize; + + d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR, + of_debugfs_root, &flat_dt_blob); + if (!d) + return 1; + + return 0; +} +device_initcall(export_flat_device_tree); +#endif diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c new file mode 100644 index 00000000000..ae0352ecd5a --- /dev/null +++ b/arch/microblaze/kernel/prom_parse.c @@ -0,0 +1,1025 @@ +#undef DEBUG + +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/pci_regs.h> +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/etherdevice.h> +#include <asm/prom.h> +#include <asm/pci-bridge.h> + +#define PRu64 "%llx" + +/* Max address size we deal with */ +#define OF_MAX_ADDR_CELLS 4 +#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \ + (ns) > 0) + +static struct of_bus *of_match_bus(struct device_node *np); +static int __of_address_to_resource(struct device_node *dev, + const u32 *addrp, u64 size, unsigned int flags, + struct resource *r); + +/* Debug utility */ +#ifdef DEBUG +static void of_dump_addr(const char *s, const u32 *addr, int na) +{ + printk(KERN_INFO "%s", s); + while (na--) + printk(KERN_INFO " %08x", *(addr++)); + printk(KERN_INFO "\n"); +} +#else +static void of_dump_addr(const char *s, const u32 *addr, int na) { } +#endif + +/* Callbacks for bus specific translators */ +struct of_bus { + const char *name; + const char *addresses; + int (*match)(struct device_node *parent); + void (*count_cells)(struct device_node *child, + int *addrc, int *sizec); + u64 (*map)(u32 *addr, const u32 *range, + int na, int ns, int pna); + int (*translate)(u32 *addr, u64 offset, int na); + unsigned int (*get_flags)(const u32 *addr); +}; + +/* + * Default translator (generic bus) + */ + +static void of_bus_default_count_cells(struct device_node *dev, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = of_n_addr_cells(dev); + if (sizec) + *sizec = of_n_size_cells(dev); +} + +static u64 of_bus_default_map(u32 *addr, const u32 *range, + int na, int ns, int pna) +{ + u64 cp, s, da; + + cp = of_read_number(range, na); + s = of_read_number(range + na + pna, ns); + da = of_read_number(addr, na); + + pr_debug("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n", + cp, s, da); + + if (da < cp || da >= (cp + s)) + return OF_BAD_ADDR; + return da - cp; +} + +static int of_bus_default_translate(u32 *addr, u64 offset, int na) +{ + u64 a = of_read_number(addr, na); + memset(addr, 0, na * 4); + a += offset; + if (na > 1) + addr[na - 2] = a >> 32; + addr[na - 1] = a & 0xffffffffu; + + return 0; +} + +static unsigned int of_bus_default_get_flags(const u32 *addr) +{ + return IORESOURCE_MEM; +} + +#ifdef CONFIG_PCI +/* + * PCI bus specific translator + */ + +static int of_bus_pci_match(struct device_node *np) +{ + /* "vci" is for the /chaos bridge on 1st-gen PCI powermacs */ + return !strcmp(np->type, "pci") || !strcmp(np->type, "vci"); +} + +static void of_bus_pci_count_cells(struct device_node *np, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = 3; + if (sizec) + *sizec = 2; +} + +static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna) +{ + u64 cp, s, da; + + /* Check address type match */ + if ((addr[0] ^ range[0]) & 0x03000000) + return OF_BAD_ADDR; + + /* Read address values, skipping high cell */ + cp = of_read_number(range + 1, na - 1); + s = of_read_number(range + na + pna, ns); + da = of_read_number(addr + 1, na - 1); + + pr_debug("OF: PCI map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da); + + if (da < cp || da >= (cp + s)) + return OF_BAD_ADDR; + return da - cp; +} + +static int of_bus_pci_translate(u32 *addr, u64 offset, int na) +{ + return of_bus_default_translate(addr + 1, offset, na - 1); +} + +static unsigned int of_bus_pci_get_flags(const u32 *addr) +{ + unsigned int flags = 0; + u32 w = addr[0]; + + switch ((w >> 24) & 0x03) { + case 0x01: + flags |= IORESOURCE_IO; + break; + case 0x02: /* 32 bits */ + case 0x03: /* 64 bits */ + flags |= IORESOURCE_MEM; + break; + } + if (w & 0x40000000) + flags |= IORESOURCE_PREFETCH; + return flags; +} + +const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, + unsigned int *flags) +{ + const u32 *prop; + unsigned int psize; + struct device_node *parent; + struct of_bus *bus; + int onesize, i, na, ns; + + /* Get parent & match bus type */ + parent = of_get_parent(dev); + if (parent == NULL) + return NULL; + bus = of_match_bus(parent); + if (strcmp(bus->name, "pci")) { + of_node_put(parent); + return NULL; + } + bus->count_cells(dev, &na, &ns); + of_node_put(parent); + if (!OF_CHECK_COUNTS(na, ns)) + return NULL; + + /* Get "reg" or "assigned-addresses" property */ + prop = of_get_property(dev, bus->addresses, &psize); + if (prop == NULL) + return NULL; + psize /= 4; + + onesize = na + ns; + for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) + if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { + if (size) + *size = of_read_number(prop + na, ns); + if (flags) + *flags = bus->get_flags(prop); + return prop; + } + return NULL; +} +EXPORT_SYMBOL(of_get_pci_address); + +int of_pci_address_to_resource(struct device_node *dev, int bar, + struct resource *r) +{ + const u32 *addrp; + u64 size; + unsigned int flags; + + addrp = of_get_pci_address(dev, bar, &size, &flags); + if (addrp == NULL) + return -EINVAL; + return __of_address_to_resource(dev, addrp, size, flags, r); +} +EXPORT_SYMBOL_GPL(of_pci_address_to_resource); + +static u8 of_irq_pci_swizzle(u8 slot, u8 pin) +{ + return (((pin - 1) + slot) % 4) + 1; +} + +int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) +{ + struct device_node *dn, *ppnode; + struct pci_dev *ppdev; + u32 lspec; + u32 laddr[3]; + u8 pin; + int rc; + + /* Check if we have a device node, if yes, fallback to standard OF + * parsing + */ + dn = pci_device_to_OF_node(pdev); + if (dn) + return of_irq_map_one(dn, 0, out_irq); + + /* Ok, we don't, time to have fun. Let's start by building up an + * interrupt spec. we assume #interrupt-cells is 1, which is standard + * for PCI. If you do different, then don't use that routine. + */ + rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); + if (rc != 0) + return rc; + /* No pin, exit */ + if (pin == 0) + return -ENODEV; + + /* Now we walk up the PCI tree */ + lspec = pin; + for (;;) { + /* Get the pci_dev of our parent */ + ppdev = pdev->bus->self; + + /* Ouch, it's a host bridge... */ + if (ppdev == NULL) { + struct pci_controller *host; + host = pci_bus_to_host(pdev->bus); + ppnode = host ? host->arch_data : NULL; + /* No node for host bridge ? give up */ + if (ppnode == NULL) + return -EINVAL; + } else + /* We found a P2P bridge, check if it has a node */ + ppnode = pci_device_to_OF_node(ppdev); + + /* Ok, we have found a parent with a device-node, hand over to + * the OF parsing code. + * We build a unit address from the linux device to be used for + * resolution. Note that we use the linux bus number which may + * not match your firmware bus numbering. + * Fortunately, in most cases, interrupt-map-mask doesn't + * include the bus number as part of the matching. + * You should still be careful about that though if you intend + * to rely on this function (you ship a firmware that doesn't + * create device nodes for all PCI devices). + */ + if (ppnode) + break; + + /* We can only get here if we hit a P2P bridge with no node, + * let's do standard swizzling and try again + */ + lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec); + pdev = ppdev; + } + + laddr[0] = (pdev->bus->number << 16) + | (pdev->devfn << 8); + laddr[1] = laddr[2] = 0; + return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq); +} +EXPORT_SYMBOL_GPL(of_irq_map_pci); +#endif /* CONFIG_PCI */ + +/* + * ISA bus specific translator + */ + +static int of_bus_isa_match(struct device_node *np) +{ + return !strcmp(np->name, "isa"); +} + +static void of_bus_isa_count_cells(struct device_node *child, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = 2; + if (sizec) + *sizec = 1; +} + +static u64 of_bus_isa_map(u32 *addr, const u32 *range, int na, int ns, int pna) +{ + u64 cp, s, da; + + /* Check address type match */ + if ((addr[0] ^ range[0]) & 0x00000001) + return OF_BAD_ADDR; + + /* Read address values, skipping high cell */ + cp = of_read_number(range + 1, na - 1); + s = of_read_number(range + na + pna, ns); + da = of_read_number(addr + 1, na - 1); + + pr_debug("OF: ISA map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da); + + if (da < cp || da >= (cp + s)) + return OF_BAD_ADDR; + return da - cp; +} + +static int of_bus_isa_translate(u32 *addr, u64 offset, int na) +{ + return of_bus_default_translate(addr + 1, offset, na - 1); +} + +static unsigned int of_bus_isa_get_flags(const u32 *addr) +{ + unsigned int flags = 0; + u32 w = addr[0]; + + if (w & 1) + flags |= IORESOURCE_IO; + else + flags |= IORESOURCE_MEM; + return flags; +} + +/* + * Array of bus specific translators + */ + +static struct of_bus of_busses[] = { +#ifdef CONFIG_PCI + /* PCI */ + { + .name = "pci", + .addresses = "assigned-addresses", + .match = of_bus_pci_match, + .count_cells = of_bus_pci_count_cells, + .map = of_bus_pci_map, + .translate = of_bus_pci_translate, + .get_flags = of_bus_pci_get_flags, + }, +#endif /* CONFIG_PCI */ + /* ISA */ + { + .name = "isa", + .addresses = "reg", + .match = of_bus_isa_match, + .count_cells = of_bus_isa_count_cells, + .map = of_bus_isa_map, + .translate = of_bus_isa_translate, + .get_flags = of_bus_isa_get_flags, + }, + /* Default */ + { + .name = "default", + .addresses = "reg", + .match = NULL, + .count_cells = of_bus_default_count_cells, + .map = of_bus_default_map, + .translate = of_bus_default_translate, + .get_flags = of_bus_default_get_flags, + }, +}; + +static struct of_bus *of_match_bus(struct device_node *np) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(of_busses); i++) + if (!of_busses[i].match || of_busses[i].match(np)) + return &of_busses[i]; + BUG(); + return NULL; +} + +static int of_translate_one(struct device_node *parent, struct of_bus *bus, + struct of_bus *pbus, u32 *addr, + int na, int ns, int pna) +{ + const u32 *ranges; + unsigned int rlen; + int rone; + u64 offset = OF_BAD_ADDR; + + /* Normally, an absence of a "ranges" property means we are + * crossing a non-translatable boundary, and thus the addresses + * below the current not cannot be converted to CPU physical ones. + * Unfortunately, while this is very clear in the spec, it's not + * what Apple understood, and they do have things like /uni-n or + * /ht nodes with no "ranges" property and a lot of perfectly + * useable mapped devices below them. Thus we treat the absence of + * "ranges" as equivalent to an empty "ranges" property which means + * a 1:1 translation at that level. It's up to the caller not to try + * to translate addresses that aren't supposed to be translated in + * the first place. --BenH. + */ + ranges = of_get_property(parent, "ranges", (int *) &rlen); + if (ranges == NULL || rlen == 0) { + offset = of_read_number(addr, na); + memset(addr, 0, pna * 4); + pr_debug("OF: no ranges, 1:1 translation\n"); + goto finish; + } + + pr_debug("OF: walking ranges...\n"); + + /* Now walk through the ranges */ + rlen /= 4; + rone = na + pna + ns; + for (; rlen >= rone; rlen -= rone, ranges += rone) { + offset = bus->map(addr, ranges, na, ns, pna); + if (offset != OF_BAD_ADDR) + break; + } + if (offset == OF_BAD_ADDR) { + pr_debug("OF: not found !\n"); + return 1; + } + memcpy(addr, ranges + na, 4 * pna); + + finish: + of_dump_addr("OF: parent translation for:", addr, pna); + pr_debug("OF: with offset: "PRu64"\n", offset); + + /* Translate it into parent bus space */ + return pbus->translate(addr, offset, pna); +} + +/* + * Translate an address from the device-tree into a CPU physical address, + * this walks up the tree and applies the various bus mappings on the + * way. + * + * Note: We consider that crossing any level with #size-cells == 0 to mean + * that translation is impossible (that is we are not dealing with a value + * that can be mapped to a cpu physical address). This is not really specified + * that way, but this is traditionally the way IBM at least do things + */ +u64 of_translate_address(struct device_node *dev, const u32 *in_addr) +{ + struct device_node *parent = NULL; + struct of_bus *bus, *pbus; + u32 addr[OF_MAX_ADDR_CELLS]; + int na, ns, pna, pns; + u64 result = OF_BAD_ADDR; + + pr_debug("OF: ** translation for device %s **\n", dev->full_name); + + /* Increase refcount at current level */ + of_node_get(dev); + + /* Get parent & match bus type */ + parent = of_get_parent(dev); + if (parent == NULL) + goto bail; + bus = of_match_bus(parent); + + /* Cound address cells & copy address locally */ + bus->count_cells(dev, &na, &ns); + if (!OF_CHECK_COUNTS(na, ns)) { + printk(KERN_ERR "prom_parse: Bad cell count for %s\n", + dev->full_name); + goto bail; + } + memcpy(addr, in_addr, na * 4); + + pr_debug("OF: bus is %s (na=%d, ns=%d) on %s\n", + bus->name, na, ns, parent->full_name); + of_dump_addr("OF: translating address:", addr, na); + + /* Translate */ + for (;;) { + /* Switch to parent bus */ + of_node_put(dev); + dev = parent; + parent = of_get_parent(dev); + + /* If root, we have finished */ + if (parent == NULL) { + pr_debug("OF: reached root node\n"); + result = of_read_number(addr, na); + break; + } + + /* Get new parent bus and counts */ + pbus = of_match_bus(parent); + pbus->count_cells(dev, &pna, &pns); + if (!OF_CHECK_COUNTS(pna, pns)) { + printk(KERN_ERR "prom_parse: Bad cell count for %s\n", + dev->full_name); + break; + } + + pr_debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n", + pbus->name, pna, pns, parent->full_name); + + /* Apply bus translation */ + if (of_translate_one(dev, bus, pbus, addr, na, ns, pna)) + break; + + /* Complete the move up one level */ + na = pna; + ns = pns; + bus = pbus; + + of_dump_addr("OF: one level translation:", addr, na); + } + bail: + of_node_put(parent); + of_node_put(dev); + + return result; +} +EXPORT_SYMBOL(of_translate_address); + +const u32 *of_get_address(struct device_node *dev, int index, u64 *size, + unsigned int *flags) +{ + const u32 *prop; + unsigned int psize; + struct device_node *parent; + struct of_bus *bus; + int onesize, i, na, ns; + + /* Get parent & match bus type */ + parent = of_get_parent(dev); + if (parent == NULL) + return NULL; + bus = of_match_bus(parent); + bus->count_cells(dev, &na, &ns); + of_node_put(parent); + if (!OF_CHECK_COUNTS(na, ns)) + return NULL; + + /* Get "reg" or "assigned-addresses" property */ + prop = of_get_property(dev, bus->addresses, (int *) &psize); + if (prop == NULL) + return NULL; + psize /= 4; + + onesize = na + ns; + for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) + if (i == index) { + if (size) + *size = of_read_number(prop + na, ns); + if (flags) + *flags = bus->get_flags(prop); + return prop; + } + return NULL; +} +EXPORT_SYMBOL(of_get_address); + +static int __of_address_to_resource(struct device_node *dev, const u32 *addrp, + u64 size, unsigned int flags, + struct resource *r) +{ + u64 taddr; + + if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0) + return -EINVAL; + taddr = of_translate_address(dev, addrp); + if (taddr == OF_BAD_ADDR) + return -EINVAL; + memset(r, 0, sizeof(struct resource)); + if (flags & IORESOURCE_IO) { + unsigned long port; + port = -1; /* pci_address_to_pio(taddr); */ + if (port == (unsigned long)-1) + return -EINVAL; + r->start = port; + r->end = port + size - 1; + } else { + r->start = taddr; + r->end = taddr + size - 1; + } + r->flags = flags; + r->name = dev->name; + return 0; +} + +int of_address_to_resource(struct device_node *dev, int index, + struct resource *r) +{ + const u32 *addrp; + u64 size; + unsigned int flags; + + addrp = of_get_address(dev, index, &size, &flags); + if (addrp == NULL) + return -EINVAL; + return __of_address_to_resource(dev, addrp, size, flags, r); +} +EXPORT_SYMBOL_GPL(of_address_to_resource); + +void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, + unsigned long *busno, unsigned long *phys, unsigned long *size) +{ + const u32 *dma_window; + u32 cells; + const unsigned char *prop; + + dma_window = dma_window_prop; + + /* busno is always one cell */ + *busno = *(dma_window++); + + prop = of_get_property(dn, "ibm,#dma-address-cells", NULL); + if (!prop) + prop = of_get_property(dn, "#address-cells", NULL); + + cells = prop ? *(u32 *)prop : of_n_addr_cells(dn); + *phys = of_read_number(dma_window, cells); + + dma_window += cells; + + prop = of_get_property(dn, "ibm,#dma-size-cells", NULL); + cells = prop ? *(u32 *)prop : of_n_size_cells(dn); + *size = of_read_number(dma_window, cells); +} + +/* + * Interrupt remapper + */ + +static unsigned int of_irq_workarounds; +static struct device_node *of_irq_dflt_pic; + +static struct device_node *of_irq_find_parent(struct device_node *child) +{ + struct device_node *p; + const phandle *parp; + + if (!of_node_get(child)) + return NULL; + + do { + parp = of_get_property(child, "interrupt-parent", NULL); + if (parp == NULL) + p = of_get_parent(child); + else { + if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) + p = of_node_get(of_irq_dflt_pic); + else + p = of_find_node_by_phandle(*parp); + } + of_node_put(child); + child = p; + } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL); + + return p; +} + +/* This doesn't need to be called if you don't have any special workaround + * flags to pass + */ +void of_irq_map_init(unsigned int flags) +{ + of_irq_workarounds = flags; + + /* OldWorld, don't bother looking at other things */ + if (flags & OF_IMAP_OLDWORLD_MAC) + return; + + /* If we don't have phandles, let's try to locate a default interrupt + * controller (happens when booting with BootX). We do a first match + * here, hopefully, that only ever happens on machines with one + * controller. + */ + if (flags & OF_IMAP_NO_PHANDLE) { + struct device_node *np; + + for (np = NULL; (np = of_find_all_nodes(np)) != NULL;) { + if (of_get_property(np, "interrupt-controller", NULL) + == NULL) + continue; + /* Skip /chosen/interrupt-controller */ + if (strcmp(np->name, "chosen") == 0) + continue; + /* It seems like at least one person on this planet + * wants to use BootX on a machine with an AppleKiwi + * controller which happens to pretend to be an + * interrupt controller too. + */ + if (strcmp(np->name, "AppleKiwi") == 0) + continue; + /* I think we found one ! */ + of_irq_dflt_pic = np; + break; + } + } + +} + +int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize, + const u32 *addr, struct of_irq *out_irq) +{ + struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; + const u32 *tmp, *imap, *imask; + u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; + int imaplen, match, i; + + pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...]," + "ointsize=%d\n", + parent->full_name, intspec[0], intspec[1], ointsize); + + ipar = of_node_get(parent); + + /* First get the #interrupt-cells property of the current cursor + * that tells us how to interpret the passed-in intspec. If there + * is none, we are nice and just walk up the tree + */ + do { + tmp = of_get_property(ipar, "#interrupt-cells", NULL); + if (tmp != NULL) { + intsize = *tmp; + break; + } + tnode = ipar; + ipar = of_irq_find_parent(ipar); + of_node_put(tnode); + } while (ipar); + if (ipar == NULL) { + pr_debug(" -> no parent found !\n"); + goto fail; + } + + pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", + ipar->full_name, intsize); + + if (ointsize != intsize) + return -EINVAL; + + /* Look for this #address-cells. We have to implement the old linux + * trick of looking for the parent here as some device-trees rely on it + */ + old = of_node_get(ipar); + do { + tmp = of_get_property(old, "#address-cells", NULL); + tnode = of_get_parent(old); + of_node_put(old); + old = tnode; + } while (old && tmp == NULL); + of_node_put(old); + old = NULL; + addrsize = (tmp == NULL) ? 2 : *tmp; + + pr_debug(" -> addrsize=%d\n", addrsize); + + /* Now start the actual "proper" walk of the interrupt tree */ + while (ipar != NULL) { + /* Now check if cursor is an interrupt-controller and if it is + * then we are done + */ + if (of_get_property(ipar, "interrupt-controller", NULL) != + NULL) { + pr_debug(" -> got it !\n"); + memcpy(out_irq->specifier, intspec, + intsize * sizeof(u32)); + out_irq->size = intsize; + out_irq->controller = ipar; + of_node_put(old); + return 0; + } + + /* Now look for an interrupt-map */ + imap = of_get_property(ipar, "interrupt-map", &imaplen); + /* No interrupt map, check for an interrupt parent */ + if (imap == NULL) { + pr_debug(" -> no map, getting parent\n"); + newpar = of_irq_find_parent(ipar); + goto skiplevel; + } + imaplen /= sizeof(u32); + + /* Look for a mask */ + imask = of_get_property(ipar, "interrupt-map-mask", NULL); + + /* If we were passed no "reg" property and we attempt to parse + * an interrupt-map, then #address-cells must be 0. + * Fail if it's not. + */ + if (addr == NULL && addrsize != 0) { + pr_debug(" -> no reg passed in when needed !\n"); + goto fail; + } + + /* Parse interrupt-map */ + match = 0; + while (imaplen > (addrsize + intsize + 1) && !match) { + /* Compare specifiers */ + match = 1; + for (i = 0; i < addrsize && match; ++i) { + u32 mask = imask ? imask[i] : 0xffffffffu; + match = ((addr[i] ^ imap[i]) & mask) == 0; + } + for (; i < (addrsize + intsize) && match; ++i) { + u32 mask = imask ? imask[i] : 0xffffffffu; + match = + ((intspec[i-addrsize] ^ imap[i]) + & mask) == 0; + } + imap += addrsize + intsize; + imaplen -= addrsize + intsize; + + pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen); + + /* Get the interrupt parent */ + if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) + newpar = of_node_get(of_irq_dflt_pic); + else + newpar = + of_find_node_by_phandle((phandle)*imap); + imap++; + --imaplen; + + /* Check if not found */ + if (newpar == NULL) { + pr_debug(" -> imap parent not found !\n"); + goto fail; + } + + /* Get #interrupt-cells and #address-cells of new + * parent + */ + tmp = of_get_property(newpar, "#interrupt-cells", NULL); + if (tmp == NULL) { + pr_debug(" -> parent lacks " + "#interrupt-cells!\n"); + goto fail; + } + newintsize = *tmp; + tmp = of_get_property(newpar, "#address-cells", NULL); + newaddrsize = (tmp == NULL) ? 0 : *tmp; + + pr_debug(" -> newintsize=%d, newaddrsize=%d\n", + newintsize, newaddrsize); + + /* Check for malformed properties */ + if (imaplen < (newaddrsize + newintsize)) + goto fail; + + imap += newaddrsize + newintsize; + imaplen -= newaddrsize + newintsize; + + pr_debug(" -> imaplen=%d\n", imaplen); + } + if (!match) + goto fail; + + of_node_put(old); + old = of_node_get(newpar); + addrsize = newaddrsize; + intsize = newintsize; + intspec = imap - intsize; + addr = intspec - addrsize; + +skiplevel: + /* Iterate again with new parent */ + pr_debug(" -> new parent: %s\n", + newpar ? newpar->full_name : "<>"); + of_node_put(ipar); + ipar = newpar; + newpar = NULL; + } +fail: + of_node_put(ipar); + of_node_put(old); + of_node_put(newpar); + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(of_irq_map_raw); + +int of_irq_map_one(struct device_node *device, + int index, struct of_irq *out_irq) +{ + struct device_node *p; + const u32 *intspec, *tmp, *addr; + u32 intsize, intlen; + int res; + + pr_debug("of_irq_map_one: dev=%s, index=%d\n", + device->full_name, index); + + /* Get the interrupts property */ + intspec = of_get_property(device, "interrupts", (int *) &intlen); + if (intspec == NULL) + return -EINVAL; + intlen /= sizeof(u32); + + pr_debug(" intspec=%d intlen=%d\n", *intspec, intlen); + + /* Get the reg property (if any) */ + addr = of_get_property(device, "reg", NULL); + + /* Look for the interrupt parent. */ + p = of_irq_find_parent(device); + if (p == NULL) + return -EINVAL; + + /* Get size of interrupt specifier */ + tmp = of_get_property(p, "#interrupt-cells", NULL); + if (tmp == NULL) { + of_node_put(p); + return -EINVAL; + } + intsize = *tmp; + + pr_debug(" intsize=%d intlen=%d\n", intsize, intlen); + + /* Check index */ + if ((index + 1) * intsize > intlen) + return -EINVAL; + + /* Get new specifier and map it */ + res = of_irq_map_raw(p, intspec + index * intsize, intsize, + addr, out_irq); + of_node_put(p); + return res; +} +EXPORT_SYMBOL_GPL(of_irq_map_one); + +/** + * Search the device tree for the best MAC address to use. 'mac-address' is + * checked first, because that is supposed to contain to "most recent" MAC + * address. If that isn't set, then 'local-mac-address' is checked next, + * because that is the default address. If that isn't set, then the obsolete + * 'address' is checked, just in case we're using an old device tree. + * + * Note that the 'address' property is supposed to contain a virtual address of + * the register set, but some DTS files have redefined that property to be the + * MAC address. + * + * All-zero MAC addresses are rejected, because those could be properties that + * exist in the device tree, but were not set by U-Boot. For example, the + * DTS could define 'mac-address' and 'local-mac-address', with zero MAC + * addresses. Some older U-Boots only initialized 'local-mac-address'. In + * this case, the real MAC is in 'local-mac-address', and 'mac-address' exists + * but is all zeros. +*/ +const void *of_get_mac_address(struct device_node *np) +{ + struct property *pp; + + pp = of_find_property(np, "mac-address", NULL); + if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) + return pp->value; + + pp = of_find_property(np, "local-mac-address", NULL); + if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) + return pp->value; + + pp = of_find_property(np, "address", NULL); + if (pp && (pp->length == 6) && is_valid_ether_addr(pp->value)) + return pp->value; + + return NULL; +} +EXPORT_SYMBOL(of_get_mac_address); + +int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) +{ + struct of_irq out_irq; + int irq; + int res; + + res = of_irq_map_one(dev, index, &out_irq); + + /* Get irq for the device */ + if (res) { + pr_debug("IRQ not found... code = %d", res); + return NO_IRQ; + } + /* Assuming single interrupt controller... */ + irq = out_irq.specifier[0]; + + pr_debug("IRQ found = %d", irq); + + /* Only dereference the resource if both the + * resource and the irq are valid. */ + if (r && irq != NO_IRQ) { + r->start = r->end = irq; + r->flags = IORESOURCE_IRQ; + } + + return irq; +} +EXPORT_SYMBOL_GPL(of_irq_to_resource); + +void __iomem *of_iomap(struct device_node *np, int index) +{ + struct resource res; + + if (of_address_to_resource(np, index, &res)) + return NULL; + + return ioremap(res.start, 1 + res.end - res.start); +} +EXPORT_SYMBOL(of_iomap); diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c new file mode 100644 index 00000000000..b86aa623e36 --- /dev/null +++ b/arch/microblaze/kernel/ptrace.c @@ -0,0 +1,181 @@ +/* + * `ptrace' system call + * + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2004-2007 John Williams <john.williams@petalogix.com> + * + * derived from arch/v850/kernel/ptrace.c + * + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader <miles@gnu.org> + * + * Derived from arch/mips/kernel/ptrace.c: + * + * Copyright (C) 1992 Ross Biro + * Copyright (C) Linus Torvalds + * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle + * Copyright (C) 1996 David S. Miller + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999 MIPS Technologies, Inc. + * + * 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. + */ + +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/smp_lock.h> +#include <linux/ptrace.h> +#include <linux/signal.h> + +#include <linux/errno.h> +#include <asm/processor.h> +#include <linux/uaccess.h> +#include <asm/asm-offsets.h> + +/* Returns the address where the register at REG_OFFS in P is stashed away. */ +static microblaze_reg_t *reg_save_addr(unsigned reg_offs, + struct task_struct *t) +{ + struct pt_regs *regs; + + /* + * Three basic cases: + * + * (1) A register normally saved before calling the scheduler, is + * available in the kernel entry pt_regs structure at the top + * of the kernel stack. The kernel trap/irq exit path takes + * care to save/restore almost all registers for ptrace'd + * processes. + * + * (2) A call-clobbered register, where the process P entered the + * kernel via [syscall] trap, is not stored anywhere; that's + * OK, because such registers are not expected to be preserved + * when the trap returns anyway (so we don't actually bother to + * test for this case). + * + * (3) A few registers not used at all by the kernel, and so + * normally never saved except by context-switches, are in the + * context switch state. + */ + + /* Register saved during kernel entry (or not available). */ + regs = task_pt_regs(t); + + return (microblaze_reg_t *)((char *)regs + reg_offs); +} + +long arch_ptrace(struct task_struct *child, long request, long addr, long data) +{ + int rval; + unsigned long val = 0; + unsigned long copied; + + switch (request) { + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: + pr_debug("PEEKTEXT/PEEKDATA at %08lX\n", addr); + copied = access_process_vm(child, addr, &val, sizeof(val), 0); + rval = -EIO; + if (copied != sizeof(val)) + break; + rval = put_user(val, (unsigned long *)data); + break; + + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + pr_debug("POKETEXT/POKEDATA to %08lX\n", addr); + rval = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) + == sizeof(data)) + break; + rval = -EIO; + break; + + /* Read/write the word at location ADDR in the registers. */ + case PTRACE_PEEKUSR: + case PTRACE_POKEUSR: + pr_debug("PEEKUSR/POKEUSR : 0x%08lx\n", addr); + rval = 0; + if (addr >= PT_SIZE && request == PTRACE_PEEKUSR) { + /* + * Special requests that don't actually correspond + * to offsets in struct pt_regs. + */ + if (addr == PT_TEXT_ADDR) { + val = child->mm->start_code; + } else if (addr == PT_DATA_ADDR) { + val = child->mm->start_data; + } else if (addr == PT_TEXT_LEN) { + val = child->mm->end_code + - child->mm->start_code; + } else { + rval = -EIO; + } + } else if (addr >= 0 && addr < PT_SIZE && (addr & 0x3) == 0) { + microblaze_reg_t *reg_addr = reg_save_addr(addr, child); + if (request == PTRACE_PEEKUSR) + val = *reg_addr; + else + *reg_addr = data; + } else + rval = -EIO; + + if (rval == 0 && request == PTRACE_PEEKUSR) + rval = put_user(val, (unsigned long *)data); + break; + /* Continue and stop at next (return from) syscall */ + case PTRACE_SYSCALL: + pr_debug("PTRACE_SYSCALL\n"); + case PTRACE_SINGLESTEP: + pr_debug("PTRACE_SINGLESTEP\n"); + /* Restart after a signal. */ + case PTRACE_CONT: + pr_debug("PTRACE_CONT\n"); + rval = -EIO; + if (!valid_signal(data)) + break; + + if (request == PTRACE_SYSCALL) + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + else + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + + child->exit_code = data; + pr_debug("wakeup_process\n"); + wake_up_process(child); + rval = 0; + break; + + /* + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to + * exit. + */ + case PTRACE_KILL: + pr_debug("PTRACE_KILL\n"); + rval = 0; + if (child->exit_state == EXIT_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + wake_up_process(child); + break; + + case PTRACE_DETACH: /* detach a process that was attached. */ + pr_debug("PTRACE_DETACH\n"); + rval = ptrace_detach(child, data); + break; + default: + /* rval = ptrace_request(child, request, addr, data); noMMU */ + rval = -EIO; + } + return rval; +} + +void ptrace_disable(struct task_struct *child) +{ + /* nothing to do */ +} diff --git a/arch/microblaze/kernel/selfmod.c b/arch/microblaze/kernel/selfmod.c new file mode 100644 index 00000000000..89508bdc9f3 --- /dev/null +++ b/arch/microblaze/kernel/selfmod.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2009 PetaLogix + * + * 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. + */ + +#include <linux/interrupt.h> +#include <asm/selfmod.h> + +#undef DEBUG + +#if __GNUC__ > 3 +#error GCC 4 unsupported SELFMOD. Please disable SELFMOD from menuconfig. +#endif + +#define OPCODE_IMM 0xB0000000 +#define OPCODE_LWI 0xE8000000 +#define OPCODE_LWI_MASK 0xEC000000 +#define OPCODE_RTSD 0xB60F0008 /* return from func: rtsd r15, 8 */ +#define OPCODE_ADDIK 0x30000000 +#define OPCODE_ADDIK_MASK 0xFC000000 + +#define IMM_BASE (OPCODE_IMM | (BARRIER_BASE_ADDR >> 16)) +#define LWI_BASE (OPCODE_LWI | (BARRIER_BASE_ADDR & 0x0000ff00)) +#define LWI_BASE_MASK (OPCODE_LWI_MASK | (BARRIER_BASE_ADDR & 0x0000ff00)) +#define ADDIK_BASE (OPCODE_ADDIK | (BARRIER_BASE_ADDR & 0x0000ff00)) +#define ADDIK_BASE_MASK (OPCODE_ADDIK_MASK | (BARRIER_BASE_ADDR & 0x0000ff00)) + +#define MODIFY_INSTR { \ + pr_debug("%s: curr instr, (%d):0x%x, next(%d):0x%x\n", \ + __func__, i, addr[i], i + 1, addr[i + 1]); \ + addr[i] = OPCODE_IMM + (base >> 16); \ + /* keep instruction opcode and add only last 16bits */ \ + addr[i + 1] = (addr[i + 1] & 0xffff00ff) + (base & 0xffff); \ + __invalidate_icache(addr[i]); \ + __invalidate_icache(addr[i + 1]); \ + pr_debug("%s: hack instr, (%d):0x%x, next(%d):0x%x\n", \ + __func__, i, addr[i], i + 1, addr[i + 1]); } + +/* NOTE + * self-modified part of code for improvement of interrupt controller + * save instruction in interrupt rutine + */ +void selfmod_function(const int *arr_fce, const unsigned int base) +{ + unsigned int flags, i, j, *addr = NULL; + + local_irq_save(flags); + __disable_icache(); + + /* zero terminated array */ + for (j = 0; arr_fce[j] != 0; j++) { + /* get start address of function */ + addr = (unsigned int *) arr_fce[j]; + pr_debug("%s: func(%d) at 0x%x\n", + __func__, j, (unsigned int) addr); + for (i = 0; ; i++) { + pr_debug("%s: instruction code at %d: 0x%x\n", + __func__, i, addr[i]); + if (addr[i] == IMM_BASE) { + /* detecting of lwi (0xE8) or swi (0xF8) instr + * I can detect both opcode with one mask */ + if ((addr[i + 1] & LWI_BASE_MASK) == LWI_BASE) { + MODIFY_INSTR; + } else /* detection addik for ack */ + if ((addr[i + 1] & ADDIK_BASE_MASK) == + ADDIK_BASE) { + MODIFY_INSTR; + } + } else if (addr[i] == OPCODE_RTSD) { + /* return from function means end of function */ + pr_debug("%s: end of array %d\n", __func__, i); + break; + } + } + } + local_irq_restore(flags); +} /* end of self-modified code */ diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c new file mode 100644 index 00000000000..eb6b41758e2 --- /dev/null +++ b/arch/microblaze/kernel/setup.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/init.h> +#include <linux/string.h> +#include <linux/seq_file.h> +#include <linux/cpu.h> +#include <linux/initrd.h> +#include <linux/console.h> +#include <linux/debugfs.h> + +#include <asm/setup.h> +#include <asm/sections.h> +#include <asm/page.h> +#include <linux/io.h> +#include <linux/bug.h> +#include <linux/param.h> +#include <linux/cache.h> +#include <asm/cacheflush.h> +#include <asm/entry.h> +#include <asm/cpuinfo.h> + +#include <asm/system.h> +#include <asm/prom.h> +#include <asm/pgtable.h> + +DEFINE_PER_CPU(unsigned int, KSP); /* Saved kernel stack pointer */ +DEFINE_PER_CPU(unsigned int, KM); /* Kernel/user mode */ +DEFINE_PER_CPU(unsigned int, ENTRY_SP); /* Saved SP on kernel entry */ +DEFINE_PER_CPU(unsigned int, R11_SAVE); /* Temp variable for entry */ +DEFINE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */ + +unsigned int boot_cpuid; +char cmd_line[COMMAND_LINE_SIZE]; + +void __init setup_arch(char **cmdline_p) +{ +#ifdef CONFIG_CMDLINE_FORCE + strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); + strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); +#endif + *cmdline_p = cmd_line; + + console_verbose(); + + unflatten_device_tree(); + + /* NOTE I think that this function is not necessary to call */ + /* irq_early_init(); */ + setup_cpuinfo(); + + __invalidate_icache_all(); + __enable_icache(); + + __invalidate_dcache_all(); + __enable_dcache(); + + panic_timeout = 120; + + setup_memory(); + +#if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER) + printk(KERN_NOTICE "Self modified code enable\n"); +#endif + +#ifdef CONFIG_VT +#if defined(CONFIG_XILINX_CONSOLE) + conswitchp = &xil_con; +#elif defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif +#endif +} + +#ifdef CONFIG_MTD_UCLINUX +/* Handle both romfs and cramfs types, without generating unnecessary + code (ie no point checking for CRAMFS if it's not even enabled) */ +inline unsigned get_romfs_len(unsigned *addr) +{ +#ifdef CONFIG_ROMFS_FS + if (memcmp(&addr[0], "-rom1fs-", 8) == 0) /* romfs */ + return be32_to_cpu(addr[2]); +#endif + +#ifdef CONFIG_CRAMFS + if (addr[0] == le32_to_cpu(0x28cd3d45)) /* cramfs */ + return le32_to_cpu(addr[1]); +#endif + return 0; +} +#endif /* CONFIG_MTD_UCLINUX_EBSS */ + +void __init machine_early_init(const char *cmdline, unsigned int ram, + unsigned int fdt) +{ + unsigned long *src, *dst = (unsigned long *)0x0; + +/* clearing bss section */ + memset(__bss_start, 0, __bss_stop-__bss_start); + memset(_ssbss, 0, _esbss-_ssbss); + + /* + * Copy command line passed from bootloader, or use default + * if none provided, or forced + */ +#ifndef CONFIG_CMDLINE_BOOL + if (cmdline && cmdline[0] != '\0') + strlcpy(cmd_line, cmdline, COMMAND_LINE_SIZE); +#endif + +/* initialize device tree for usage in early_printk */ + early_init_devtree((void *)_fdt_start); + +#ifdef CONFIG_EARLY_PRINTK + setup_early_printk(NULL); +#endif + + early_printk("Ramdisk addr 0x%08x, FDT 0x%08x\n", ram, fdt); + printk(KERN_NOTICE "Found FDT at 0x%08x\n", fdt); + +#ifdef CONFIG_MTD_UCLINUX + { + int size; + unsigned int romfs_base; + romfs_base = (ram ? ram : (unsigned int)&__init_end); + /* if CONFIG_MTD_UCLINUX_EBSS is defined, assume ROMFS is at the + * end of kernel, which is ROMFS_LOCATION defined above. */ + size = PAGE_ALIGN(get_romfs_len((unsigned *)romfs_base)); + early_printk("Found romfs @ 0x%08x (0x%08x)\n", + romfs_base, size); + early_printk("#### klimit %p ####\n", klimit); + BUG_ON(size < 0); /* What else can we do? */ + + /* Use memmove to handle likely case of memory overlap */ + early_printk("Moving 0x%08x bytes from 0x%08x to 0x%08x\n", + size, romfs_base, (unsigned)&_ebss); + memmove(&_ebss, (int *)romfs_base, size); + + /* update klimit */ + klimit += PAGE_ALIGN(size); + early_printk("New klimit: 0x%08x\n", (unsigned)klimit); + } +#endif + + for (src = __ivt_start; src < __ivt_end; src++, dst++) + *dst = *src; + + /* Initialize global data */ + per_cpu(KM, 0) = 0x1; /* We start in kernel mode */ + per_cpu(CURRENT_SAVE, 0) = (unsigned long)current; +} + +#ifdef CONFIG_DEBUG_FS +struct dentry *of_debugfs_root; + +static int microblaze_debugfs_init(void) +{ + of_debugfs_root = debugfs_create_dir("microblaze", NULL); + + return of_debugfs_root == NULL; +} +arch_initcall(microblaze_debugfs_init); +#endif + +void machine_restart(char *cmd) +{ + printk(KERN_NOTICE "Machine restart...\n"); + dump_stack(); + while (1) + ; +} + +void machine_shutdown(void) +{ + printk(KERN_NOTICE "Machine shutdown...\n"); + while (1) + ; +} + +void machine_halt(void) +{ + printk(KERN_NOTICE "Machine halt...\n"); + while (1) + ; +} + +void machine_power_off(void) +{ + printk(KERN_NOTICE "Machine power off...\n"); + while (1) + ; +} diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c new file mode 100644 index 00000000000..3889cf45fa7 --- /dev/null +++ b/arch/microblaze/kernel/signal.c @@ -0,0 +1,537 @@ +/* + * Signal handling + * + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2008-2009 PetaLogix + * Copyright (C) 2003,2004 John Williams <jwilliams@itee.uq.edu.au> + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader <miles@gnu.org> + * Copyright (C) 1999,2000 Niibe Yutaka & Kaz Kojima + * Copyright (C) 1991,1992 Linus Torvalds + * + * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson + * + * This file was was derived from the sh version, arch/sh/kernel/signal.c + * + * 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. + */ + +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> +#include <linux/kernel.h> +#include <linux/signal.h> +#include <linux/errno.h> +#include <linux/wait.h> +#include <linux/ptrace.h> +#include <linux/unistd.h> +#include <linux/stddef.h> +#include <linux/personality.h> +#include <linux/percpu.h> +#include <linux/linkage.h> +#include <asm/entry.h> +#include <asm/ucontext.h> +#include <linux/uaccess.h> +#include <asm/pgtable.h> +#include <asm/pgalloc.h> +#include <linux/syscalls.h> +#include <asm/cacheflush.h> +#include <asm/syscalls.h> + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + +asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); + +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +asmlinkage int +sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs) +{ + sigset_t saveset; + + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sighand->siglock); + saveset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + regs->r3 = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(regs, &saveset, 1)) + return -EINTR; + } +} + +asmlinkage int +sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, + struct pt_regs *regs) +{ + sigset_t saveset, newset; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (copy_from_user(&newset, unewset, sizeof(newset))) + return -EFAULT; + sigdelsetmask(&newset, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + saveset = current->blocked; + current->blocked = newset; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + regs->r3 = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(regs, &saveset, 1)) + return -EINTR; + } +} + +asmlinkage int +sys_sigaction(int sig, const struct old_sigaction *act, + struct old_sigaction *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (!access_ok(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + +asmlinkage int +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, + struct pt_regs *regs) +{ + return do_sigaltstack(uss, uoss, regs->r1); +} + +/* + * Do a signal return; undo the signal stack. + */ + +struct sigframe { + struct sigcontext sc; + unsigned long extramask[_NSIG_WORDS-1]; + unsigned long tramp[2]; /* signal trampoline */ +}; + +struct rt_sigframe { + struct siginfo info; + struct ucontext uc; + unsigned long tramp[2]; /* signal trampoline */ +}; + +static int +restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p) +{ + unsigned int err = 0; + +#define COPY(x) {err |= __get_user(regs->x, &sc->regs.x); } + COPY(r0); + COPY(r1); + COPY(r2); COPY(r3); COPY(r4); COPY(r5); + COPY(r6); COPY(r7); COPY(r8); COPY(r9); + COPY(r10); COPY(r11); COPY(r12); COPY(r13); + COPY(r14); COPY(r15); COPY(r16); COPY(r17); + COPY(r18); COPY(r19); COPY(r20); COPY(r21); + COPY(r22); COPY(r23); COPY(r24); COPY(r25); + COPY(r26); COPY(r27); COPY(r28); COPY(r29); + COPY(r30); COPY(r31); + COPY(pc); COPY(ear); COPY(esr); COPY(fsr); +#undef COPY + + *rval_p = regs->r3; + + return err; +} + +asmlinkage int sys_sigreturn(struct pt_regs *regs) +{ + struct sigframe *frame = (struct sigframe *)regs->r1; + sigset_t set; + int rval; + + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + + if (__get_user(set.sig[0], &frame->sc.oldmask) + || (_NSIG_WORDS > 1 + && __copy_from_user(&set.sig[1], &frame->extramask, + sizeof(frame->extramask)))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + + spin_lock_irq(¤t->sighand->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + if (restore_sigcontext(regs, &frame->sc, &rval)) + goto badframe; + return rval; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) +{ + struct rt_sigframe *frame = (struct rt_sigframe *)regs->r1; + sigset_t set; + stack_t st; + int rval; + + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + current->blocked = set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval)) + goto badframe; + + if (__copy_from_user((void *)&st, &frame->uc.uc_stack, sizeof(st))) + goto badframe; + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ + do_sigaltstack(&st, NULL, regs->r1); + + return rval; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +/* + * Set up a signal frame. + */ + +static int +setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, + unsigned long mask) +{ + int err = 0; + +#define COPY(x) {err |= __put_user(regs->x, &sc->regs.x); } + COPY(r0); + COPY(r1); + COPY(r2); COPY(r3); COPY(r4); COPY(r5); + COPY(r6); COPY(r7); COPY(r8); COPY(r9); + COPY(r10); COPY(r11); COPY(r12); COPY(r13); + COPY(r14); COPY(r15); COPY(r16); COPY(r17); + COPY(r18); COPY(r19); COPY(r20); COPY(r21); + COPY(r22); COPY(r23); COPY(r24); COPY(r25); + COPY(r26); COPY(r27); COPY(r28); COPY(r29); + COPY(r30); COPY(r31); + COPY(pc); COPY(ear); COPY(esr); COPY(fsr); +#undef COPY + + err |= __put_user(mask, &sc->oldmask); + + return err; +} + +/* + * Determine which stack to use.. + */ +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +{ + /* Default to using normal stack */ + unsigned long sp = regs->r1; + + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp)) + sp = current->sas_ss_sp + current->sas_ss_size; + + return (void *)((sp - frame_size) & -8UL); +} + +static void setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs) +{ + struct sigframe *frame; + int err = 0; + int signal; + + frame = get_sigframe(ka, regs, sizeof(*frame)); + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + signal = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); + + if (_NSIG_WORDS > 1) { + err |= __copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); + } + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + /* minus 8 is offset to cater for "rtsd r15,8" offset */ + if (ka->sa.sa_flags & SA_RESTORER) { + regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8; + } else { + /* Note, these encodings are _big endian_! */ + + /* addi r12, r0, __NR_sigreturn */ + err |= __put_user(0x31800000 | __NR_sigreturn , + frame->tramp + 0); + /* brki r14, 0x8 */ + err |= __put_user(0xb9cc0008, frame->tramp + 1); + + /* Return from sighandler will jump to the tramp. + Negative 8 offset because return is rtsd r15, 8 */ + regs->r15 = ((unsigned long)frame->tramp)-8; + + __invalidate_cache_sigtramp((unsigned long)frame->tramp); + } + + if (err) + goto give_sigsegv; + + /* Set up registers for signal handler */ + regs->r1 = (unsigned long) frame; + /* Signal handler args: */ + regs->r5 = signal; /* Arg 0: signum */ + regs->r6 = (unsigned long) &frame->sc; /* arg 1: sigcontext */ + + /* Offset of 4 to handle microblaze rtid r14, 0 */ + regs->pc = (unsigned long)ka->sa.sa_handler; + + set_fs(USER_DS); + +#ifdef DEBUG_SIG + printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n", + current->comm, current->pid, frame, regs->pc); +#endif + + return; + +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); +} + +static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) +{ + struct rt_sigframe *frame; + int err = 0; + int signal; + + frame = get_sigframe(ka, regs, sizeof(*frame)); + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + signal = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= copy_siginfo_to_user(&frame->info, info); + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user((void *)current->sas_ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->r1), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, + regs, set->sig[0]); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + /* minus 8 is offset to cater for "rtsd r15,8" */ + if (ka->sa.sa_flags & SA_RESTORER) { + regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8; + } else { + /* addi r12, r0, __NR_sigreturn */ + err |= __put_user(0x31800000 | __NR_rt_sigreturn , + frame->tramp + 0); + /* brki r14, 0x8 */ + err |= __put_user(0xb9cc0008, frame->tramp + 1); + + /* Return from sighandler will jump to the tramp. + Negative 8 offset because return is rtsd r15, 8 */ + regs->r15 = ((unsigned long)frame->tramp)-8; + + __invalidate_cache_sigtramp((unsigned long)frame->tramp); + } + + if (err) + goto give_sigsegv; + + /* Set up registers for signal handler */ + regs->r1 = (unsigned long) frame; + /* Signal handler args: */ + regs->r5 = signal; /* arg 0: signum */ + regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */ + regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */ + /* Offset to handle microblaze rtid r14, 0 */ + regs->pc = (unsigned long)ka->sa.sa_handler; + + set_fs(USER_DS); + +#ifdef DEBUG_SIG + printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n", + current->comm, current->pid, frame, regs->pc); +#endif + + return; + +give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); +} + +/* Handle restarting system calls */ +static inline void +handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) +{ + switch (regs->r3) { + case -ERESTART_RESTARTBLOCK: + case -ERESTARTNOHAND: + if (!has_handler) + goto do_restart; + regs->r3 = -EINTR; + break; + case -ERESTARTSYS: + if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { + regs->r3 = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: +do_restart: + /* offset of 4 bytes to re-execute trap (brki) instruction */ + regs->pc -= 4; + break; + } +} + +/* + * OK, we're invoking a handler + */ + +static void +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) +{ + /* Set up the stack frame */ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(sig, ka, info, oldset, regs); + else + setup_frame(sig, ka, oldset, regs); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked, + ¤t->blocked, &ka->sa.sa_mask); + sigaddset(¤t->blocked, sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } +} + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + * + * Note that we go through the signals twice: once to check the signals that + * the kernel can handle, and then we build all the user-level signal handling + * stack-frames in one go after that. + */ +int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) +{ + siginfo_t info; + int signr; + struct k_sigaction ka; +#ifdef DEBUG_SIG + printk(KERN_INFO "do signal: %p %p %d\n", regs, oldset, in_syscall); + printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1, + regs->r12, current_thread_info()->flags); +#endif + /* + * We want the common case to go fast, which + * is why we may in certain cases get here from + * kernel mode. Just return without doing anything + * if so. + */ + if (kernel_mode(regs)) + return 1; + + if (!oldset) + oldset = ¤t->blocked; + + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + if (signr > 0) { + /* Whee! Actually deliver the signal. */ + if (in_syscall) + handle_restart(regs, &ka, 1); + handle_signal(signr, &ka, &info, oldset, regs); + return 1; + } + + if (in_syscall) + handle_restart(regs, NULL, 0); + + /* Did we come from a system call? */ + return 0; +} diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c new file mode 100644 index 00000000000..ba0568c2cc1 --- /dev/null +++ b/arch/microblaze/kernel/sys_microblaze.c @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2007 John Williams <john.williams@petalogix.com> + * + * Copyright (C) 2006 Atmark Techno, Inc. + * Yasushi SHOJI <yashi@atmark-techno.com> + * Tetsuya OHKAWA <tetsuya@atmark-techno.com> + * + * 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. + */ + +#include <linux/errno.h> +#include <linux/mm.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> +#include <linux/syscalls.h> +#include <linux/sem.h> +#include <linux/msg.h> +#include <linux/shm.h> +#include <linux/stat.h> +#include <linux/mman.h> +#include <linux/sys.h> +#include <linux/ipc.h> +#include <linux/utsname.h> +#include <linux/file.h> +#include <linux/module.h> +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/semaphore.h> +#include <linux/uaccess.h> +#include <linux/unistd.h> + +#include <asm/syscalls.h> +/* + * sys_ipc() is the de-multiplexer for the SysV IPC calls.. + * + * This is really horribly ugly. This will be remove with new toolchain. + */ +asmlinkage int +sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth) +{ + int version, ret; + + version = call >> 16; /* hack for backward compatibility */ + call &= 0xffff; + + ret = -EINVAL; + switch (call) { + case SEMOP: + ret = sys_semop(first, (struct sembuf *)ptr, second); + break; + case SEMGET: + ret = sys_semget(first, second, third); + break; + case SEMCTL: + { + union semun fourth; + + if (!ptr) + break; + ret = (access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT) + || (get_user(fourth.__pad, (void **)ptr)) ; + if (ret) + break; + ret = sys_semctl(first, second, third, fourth); + break; + } + case MSGSND: + ret = sys_msgsnd(first, (struct msgbuf *) ptr, second, third); + break; + case MSGRCV: + switch (version) { + case 0: { + struct ipc_kludge tmp; + + if (!ptr) + break; + ret = (access_ok(VERIFY_READ, ptr, sizeof(tmp)) + ? 0 : -EFAULT) || copy_from_user(&tmp, + (struct ipc_kludge *) ptr, sizeof(tmp)); + if (ret) + break; + ret = sys_msgrcv(first, tmp.msgp, second, tmp.msgtyp, + third); + break; + } + default: + ret = sys_msgrcv(first, (struct msgbuf *) ptr, + second, fifth, third); + break; + } + break; + case MSGGET: + ret = sys_msgget((key_t) first, second); + break; + case MSGCTL: + ret = sys_msgctl(first, second, (struct msqid_ds *) ptr); + break; + case SHMAT: + switch (version) { + default: { + ulong raddr; + ret = access_ok(VERIFY_WRITE, (ulong *) third, + sizeof(ulong)) ? 0 : -EFAULT; + if (ret) + break; + ret = do_shmat(first, (char *) ptr, second, &raddr); + if (ret) + break; + ret = put_user(raddr, (ulong *) third); + break; + } + case 1: /* iBCS2 emulator entry point */ + if (!segment_eq(get_fs(), get_ds())) + break; + ret = do_shmat(first, (char *) ptr, second, + (ulong *) third); + break; + } + break; + case SHMDT: + ret = sys_shmdt((char *)ptr); + break; + case SHMGET: + ret = sys_shmget(first, second, third); + break; + case SHMCTL: + ret = sys_shmctl(first, second, (struct shmid_ds *) ptr); + break; + } + return -EINVAL; +} + +asmlinkage int sys_vfork(struct pt_regs *regs) +{ + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1, + regs, 0, NULL, NULL); +} + +asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs) +{ + if (!stack) + stack = regs->r1; + return do_fork(flags, stack, regs, 0, NULL, NULL); +} + +asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv, + char __user *__user *envp, struct pt_regs *regs) +{ + int error; + char *filename; + + filename = getname(filenamei); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename, argv, envp, regs); + putname(filename); +out: + return error; +} + +asmlinkage unsigned long +sys_mmap2(unsigned long addr, size_t len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + struct file *file = NULL; + int ret = -EBADF; + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + if (!(flags & MAP_ANONYMOUS)) { + file = fget(fd); + if (!file) { + printk(KERN_INFO "no fd in mmap\r\n"); + goto out; + } + } + + down_write(¤t->mm->mmap_sem); + ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + up_write(¤t->mm->mmap_sem); + if (file) + fput(file); +out: + return ret; +} + +asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, + unsigned long prot, unsigned long flags, + unsigned long fd, off_t offset) +{ + int err = -EINVAL; + + if (offset & ~PAGE_MASK) { + printk(KERN_INFO "no pagemask in mmap\r\n"); + goto out; + } + + err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); +out: + return err; +} + +/* + * Do a system call from kernel instead of calling sys_execve so we + * end up with proper pt_regs. + */ +int kernel_execve(const char *filename, char *const argv[], char *const envp[]) +{ + register const char *__a __asm__("r5") = filename; + register const void *__b __asm__("r6") = argv; + register const void *__c __asm__("r7") = envp; + register unsigned long __syscall __asm__("r12") = __NR_execve; + register unsigned long __ret __asm__("r3"); + __asm__ __volatile__ ("brki r14, 0x8" + : "=r" (__ret), "=r" (__syscall) + : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c) + : "r4", "r8", "r9", + "r10", "r11", "r14", "cc", "memory"); + return __ret; +} diff --git a/arch/microblaze/kernel/syscall_table.S b/arch/microblaze/kernel/syscall_table.S new file mode 100644 index 00000000000..529b0dbf4fe --- /dev/null +++ b/arch/microblaze/kernel/syscall_table.S @@ -0,0 +1,365 @@ +ENTRY(sys_call_table) + .long sys_restart_syscall /* 0 - old "setup()" system call, + * used for restarting */ + .long sys_exit + .long sys_ni_syscall /* was fork */ + .long sys_read + .long sys_write + .long sys_open /* 5 */ + .long sys_close + .long sys_waitpid + .long sys_creat + .long sys_link + .long sys_unlink /* 10 */ + .long sys_execve_wrapper + .long sys_chdir + .long sys_time + .long sys_mknod + .long sys_chmod /* 15 */ + .long sys_lchown + .long sys_ni_syscall /* old break syscall holder */ + .long sys_ni_syscall /* old stat */ + .long sys_lseek + .long sys_getpid /* 20 */ + .long sys_mount + .long sys_oldumount + .long sys_setuid + .long sys_getuid + .long sys_stime /* 25 */ + .long sys_ptrace + .long sys_alarm + .long sys_ni_syscall /* oldfstat */ + .long sys_pause + .long sys_utime /* 30 */ + .long sys_ni_syscall /* old stty syscall holder */ + .long sys_ni_syscall /* old gtty syscall holder */ + .long sys_access + .long sys_nice + .long sys_ni_syscall /* 35 - old ftime syscall holder */ + .long sys_sync + .long sys_kill + .long sys_rename + .long sys_mkdir + .long sys_rmdir /* 40 */ + .long sys_dup + .long sys_pipe + .long sys_times + .long sys_ni_syscall /* old prof syscall holder */ + .long sys_brk /* 45 */ + .long sys_setgid + .long sys_getgid + .long sys_signal + .long sys_geteuid + .long sys_getegid /* 50 */ + .long sys_acct + .long sys_umount /* recycled never used phys() */ + .long sys_ni_syscall /* old lock syscall holder */ + .long sys_ioctl + .long sys_fcntl /* 55 */ + .long sys_ni_syscall /* old mpx syscall holder */ + .long sys_setpgid + .long sys_ni_syscall /* old ulimit syscall holder */ + .long sys_ni_syscall /* olduname */ + .long sys_umask /* 60 */ + .long sys_chroot + .long sys_ustat + .long sys_dup2 + .long sys_getppid + .long sys_getpgrp /* 65 */ + .long sys_setsid + .long sys_sigaction + .long sys_sgetmask + .long sys_ssetmask + .long sys_setreuid /* 70 */ + .long sys_setregid + .long sys_sigsuspend_wrapper + .long sys_sigpending + .long sys_sethostname + .long sys_setrlimit /* 75 */ + .long sys_ni_syscall /* old_getrlimit */ + .long sys_getrusage + .long sys_gettimeofday + .long sys_settimeofday + .long sys_getgroups /* 80 */ + .long sys_setgroups + .long sys_ni_syscall /* old_select */ + .long sys_symlink + .long sys_ni_syscall /* oldlstat */ + .long sys_readlink /* 85 */ + .long sys_uselib + .long sys_swapon + .long sys_reboot + .long sys_ni_syscall /* old_readdir */ + .long sys_mmap /* 90 */ /* old_mmap */ + .long sys_munmap + .long sys_truncate + .long sys_ftruncate + .long sys_fchmod + .long sys_fchown /* 95 */ + .long sys_getpriority + .long sys_setpriority + .long sys_ni_syscall /* old profil syscall holder */ + .long sys_statfs + .long sys_fstatfs /* 100 */ + .long sys_ni_syscall /* ioperm */ + .long sys_socketcall + .long sys_syslog /* operation with system console */ + .long sys_setitimer + .long sys_getitimer /* 105 */ + .long sys_newstat + .long sys_newlstat + .long sys_newfstat + .long sys_ni_syscall /* uname */ + .long sys_ni_syscall /* 110 */ /* iopl */ + .long sys_vhangup + .long sys_ni_syscall /* old "idle" system call */ + .long sys_ni_syscall /* old sys_vm86old */ + .long sys_wait4 + .long sys_swapoff /* 115 */ + .long sys_sysinfo + .long sys_ipc + .long sys_fsync + .long sys_sigreturn_wrapper + .long sys_clone_wrapper /* 120 */ + .long sys_setdomainname + .long sys_newuname + .long sys_ni_syscall /* modify_ldt */ + .long sys_adjtimex + .long sys_mprotect /* 125: sys_mprotect */ + .long sys_sigprocmask + .long sys_ni_syscall /* old "create_module" */ + .long sys_init_module + .long sys_delete_module + .long sys_ni_syscall /* 130: old "get_kernel_syms" */ + .long sys_quotactl + .long sys_getpgid + .long sys_fchdir + .long sys_bdflush + .long sys_sysfs /* 135 */ + .long sys_personality + .long sys_ni_syscall /* reserved for afs_syscall */ + .long sys_setfsuid + .long sys_setfsgid + .long sys_llseek /* 140 */ + .long sys_getdents + .long sys_select + .long sys_flock + .long sys_msync + .long sys_readv /* 145 */ + .long sys_writev + .long sys_getsid + .long sys_fdatasync + .long sys_sysctl + .long sys_mlock /* 150: sys_mlock */ + .long sys_munlock + .long sys_mlockall + .long sys_munlockall + .long sys_sched_setparam + .long sys_sched_getparam /* 155 */ + .long sys_sched_setscheduler + .long sys_sched_getscheduler + .long sys_sched_yield + .long sys_sched_get_priority_max + .long sys_sched_get_priority_min /* 160 */ + .long sys_sched_rr_get_interval + .long sys_nanosleep + .long sys_mremap + .long sys_setresuid + .long sys_getresuid /* 165 */ + .long sys_ni_syscall /* sys_vm86 */ + .long sys_ni_syscall /* Old sys_query_module */ + .long sys_poll + .long sys_nfsservctl + .long sys_setresgid /* 170 */ + .long sys_getresgid + .long sys_prctl + .long sys_rt_sigreturn_wrapper + .long sys_rt_sigaction + .long sys_rt_sigprocmask /* 175 */ + .long sys_rt_sigpending + .long sys_rt_sigtimedwait + .long sys_rt_sigqueueinfo + .long sys_rt_sigsuspend_wrapper + .long sys_pread64 /* 180 */ + .long sys_pwrite64 + .long sys_chown + .long sys_getcwd + .long sys_capget + .long sys_capset /* 185 */ + .long sys_ni_syscall /* sigaltstack */ + .long sys_sendfile + .long sys_ni_syscall /* reserved for streams1 */ + .long sys_ni_syscall /* reserved for streams2 */ + .long sys_vfork_wrapper /* 190 */ + .long sys_getrlimit + .long sys_mmap2 /* mmap2 */ + .long sys_truncate64 + .long sys_ftruncate64 + .long sys_stat64 /* 195 */ + .long sys_lstat64 + .long sys_fstat64 + .long sys_lchown + .long sys_getuid + .long sys_getgid /* 200 */ + .long sys_geteuid + .long sys_getegid + .long sys_setreuid + .long sys_setregid + .long sys_getgroups /* 205 */ + .long sys_setgroups + .long sys_fchown + .long sys_setresuid + .long sys_getresuid + .long sys_setresgid /* 210 */ + .long sys_getresgid + .long sys_chown + .long sys_setuid + .long sys_setgid + .long sys_setfsuid /* 215 */ + .long sys_setfsgid + .long sys_pivot_root + .long sys_mincore + .long sys_madvise + .long sys_getdents64 /* 220 */ + .long sys_fcntl64 + .long sys_ni_syscall /* reserved for TUX */ + .long sys_ni_syscall + .long sys_gettid + .long sys_readahead /* 225 */ + .long sys_setxattr + .long sys_lsetxattr + .long sys_fsetxattr + .long sys_getxattr + .long sys_lgetxattr /* 230 */ + .long sys_fgetxattr + .long sys_listxattr + .long sys_llistxattr + .long sys_flistxattr + .long sys_removexattr /* 235 */ + .long sys_lremovexattr + .long sys_fremovexattr + .long sys_tkill + .long sys_sendfile64 + .long sys_futex /* 240 */ + .long sys_sched_setaffinity + .long sys_sched_getaffinity + .long sys_ni_syscall /* set_thread_area */ + .long sys_ni_syscall /* get_thread_area */ + .long sys_io_setup /* 245 */ + .long sys_io_destroy + .long sys_io_getevents + .long sys_io_submit + .long sys_io_cancel + .long sys_fadvise64 /* 250 */ + .long sys_ni_syscall + .long sys_exit_group + .long sys_lookup_dcookie + .long sys_epoll_create + .long sys_epoll_ctl /* 255 */ + .long sys_epoll_wait + .long sys_remap_file_pages + .long sys_set_tid_address + .long sys_timer_create + .long sys_timer_settime /* 260 */ + .long sys_timer_gettime + .long sys_timer_getoverrun + .long sys_timer_delete + .long sys_clock_settime + .long sys_clock_gettime /* 265 */ + .long sys_clock_getres + .long sys_clock_nanosleep + .long sys_statfs64 + .long sys_fstatfs64 + .long sys_tgkill /* 270 */ + .long sys_utimes + .long sys_fadvise64_64 + .long sys_ni_syscall /* sys_vserver */ + .long sys_mbind + .long sys_get_mempolicy + .long sys_set_mempolicy + .long sys_mq_open + .long sys_mq_unlink + .long sys_mq_timedsend + .long sys_mq_timedreceive /* 280 */ + .long sys_mq_notify + .long sys_mq_getsetattr + .long sys_kexec_load + .long sys_waitid + .long sys_ni_syscall /* 285 */ /* available */ + .long sys_add_key + .long sys_request_key + .long sys_keyctl + .long sys_ioprio_set + .long sys_ioprio_get /* 290 */ + .long sys_inotify_init + .long sys_inotify_add_watch + .long sys_inotify_rm_watch + .long sys_ni_syscall /* sys_migrate_pages */ + .long sys_openat /* 295 */ + .long sys_mkdirat + .long sys_mknodat + .long sys_fchownat + .long sys_ni_syscall + .long sys_fstatat64 /* 300 */ + .long sys_unlinkat + .long sys_renameat + .long sys_linkat + .long sys_symlinkat + .long sys_readlinkat /* 305 */ + .long sys_fchmodat + .long sys_faccessat + .long sys_ni_syscall /* pselect6 */ + .long sys_ni_syscall /* sys_ppoll */ + .long sys_unshare /* 310 */ + .long sys_set_robust_list + .long sys_get_robust_list + .long sys_splice + .long sys_sync_file_range + .long sys_tee /* 315 */ + .long sys_vmsplice + .long sys_move_pages + .long sys_getcpu + .long sys_epoll_pwait + .long sys_utimensat /* 320 */ + .long sys_signalfd + .long sys_timerfd_create + .long sys_eventfd + .long sys_fallocate + .long sys_semtimedop /* 325 */ + .long sys_timerfd_settime + .long sys_timerfd_gettime + .long sys_semctl + .long sys_semget + .long sys_semop /* 330 */ + .long sys_msgctl + .long sys_msgget + .long sys_msgrcv + .long sys_msgsnd + .long sys_shmat /* 335 */ + .long sys_shmctl + .long sys_shmdt + .long sys_shmget + .long sys_signalfd4 /* new syscall */ + .long sys_eventfd2 /* 340 */ + .long sys_epoll_create1 + .long sys_dup3 + .long sys_pipe2 + .long sys_inotify_init1 + .long sys_socket /* 345 */ + .long sys_socketpair + .long sys_bind + .long sys_listen + .long sys_accept + .long sys_connect /* 350 */ + .long sys_getsockname + .long sys_getpeername + .long sys_sendto + .long sys_send + .long sys_recvfrom /* 355 */ + .long sys_recv + .long sys_setsockopt + .long sys_getsockopt + .long sys_shutdown + .long sys_sendmsg /* 360 */ + .long sys_recvmsg + .long sys_ni_syscall diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c new file mode 100644 index 00000000000..05a497eefd7 --- /dev/null +++ b/arch/microblaze/kernel/timer.c @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/param.h> +#include <linux/interrupt.h> +#include <linux/profile.h> +#include <linux/irq.h> +#include <linux/delay.h> +#include <linux/sched.h> +#include <linux/spinlock.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/io.h> +#include <asm/cpuinfo.h> +#include <asm/setup.h> +#include <asm/prom.h> +#include <asm/irq.h> +#include <asm/system.h> + +#ifdef CONFIG_SELFMOD_TIMER +#include <asm/selfmod.h> +#define TIMER_BASE BARRIER_BASE_ADDR +#else +static unsigned int timer_baseaddr; +#define TIMER_BASE timer_baseaddr +#endif + +#define TCSR0 (0x00) +#define TLR0 (0x04) +#define TCR0 (0x08) +#define TCSR1 (0x10) +#define TLR1 (0x14) +#define TCR1 (0x18) + +#define TCSR_MDT (1<<0) +#define TCSR_UDT (1<<1) +#define TCSR_GENT (1<<2) +#define TCSR_CAPT (1<<3) +#define TCSR_ARHT (1<<4) +#define TCSR_LOAD (1<<5) +#define TCSR_ENIT (1<<6) +#define TCSR_ENT (1<<7) +#define TCSR_TINT (1<<8) +#define TCSR_PWMA (1<<9) +#define TCSR_ENALL (1<<10) + +static inline void microblaze_timer0_stop(void) +{ + out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0) & ~TCSR_ENT); +} + +static inline void microblaze_timer0_start_periodic(unsigned long load_val) +{ + if (!load_val) + load_val = 1; + out_be32(TIMER_BASE + TLR0, load_val); /* loading value to timer reg */ + + /* load the initial value */ + out_be32(TIMER_BASE + TCSR0, TCSR_LOAD); + + /* see timer data sheet for detail + * !ENALL - don't enable 'em all + * !PWMA - disable pwm + * TINT - clear interrupt status + * ENT- enable timer itself + * EINT - enable interrupt + * !LOAD - clear the bit to let go + * ARHT - auto reload + * !CAPT - no external trigger + * !GENT - no external signal + * UDT - set the timer as down counter + * !MDT0 - generate mode + */ + out_be32(TIMER_BASE + TCSR0, + TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT); +} + +static inline void microblaze_timer0_start_oneshot(unsigned long load_val) +{ + if (!load_val) + load_val = 1; + out_be32(TIMER_BASE + TLR0, load_val); /* loading value to timer reg */ + + /* load the initial value */ + out_be32(TIMER_BASE + TCSR0, TCSR_LOAD); + + out_be32(TIMER_BASE + TCSR0, + TCSR_TINT|TCSR_ENIT|TCSR_ENT|TCSR_ARHT|TCSR_UDT); +} + +static int microblaze_timer_set_next_event(unsigned long delta, + struct clock_event_device *dev) +{ + pr_debug("%s: next event, delta %x\n", __func__, (u32)delta); + microblaze_timer0_start_oneshot(delta); + return 0; +} + +static void microblaze_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + printk(KERN_INFO "%s: periodic\n", __func__); + microblaze_timer0_start_periodic(cpuinfo.freq_div_hz); + break; + case CLOCK_EVT_MODE_ONESHOT: + printk(KERN_INFO "%s: oneshot\n", __func__); + break; + case CLOCK_EVT_MODE_UNUSED: + printk(KERN_INFO "%s: unused\n", __func__); + break; + case CLOCK_EVT_MODE_SHUTDOWN: + printk(KERN_INFO "%s: shutdown\n", __func__); + microblaze_timer0_stop(); + break; + case CLOCK_EVT_MODE_RESUME: + printk(KERN_INFO "%s: resume\n", __func__); + break; + } +} + +static struct clock_event_device clockevent_microblaze_timer = { + .name = "microblaze_clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, + .shift = 24, + .rating = 300, + .set_next_event = microblaze_timer_set_next_event, + .set_mode = microblaze_timer_set_mode, +}; + +static inline void timer_ack(void) +{ + out_be32(TIMER_BASE + TCSR0, in_be32(TIMER_BASE + TCSR0)); +} + +static irqreturn_t timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = &clockevent_microblaze_timer; +#ifdef CONFIG_HEART_BEAT + heartbeat(); +#endif + timer_ack(); + evt->event_handler(evt); + return IRQ_HANDLED; +} + +static struct irqaction timer_irqaction = { + .handler = timer_interrupt, + .flags = IRQF_DISABLED | IRQF_TIMER, + .name = "timer", + .dev_id = &clockevent_microblaze_timer, +}; + +static __init void microblaze_clockevent_init(void) +{ + clockevent_microblaze_timer.mult = + div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC, + clockevent_microblaze_timer.shift); + clockevent_microblaze_timer.max_delta_ns = + clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer); + clockevent_microblaze_timer.min_delta_ns = + clockevent_delta2ns(1, &clockevent_microblaze_timer); + clockevent_microblaze_timer.cpumask = cpumask_of(0); + clockevents_register_device(&clockevent_microblaze_timer); +} + +static cycle_t microblaze_read(void) +{ + /* reading actual value of timer 1 */ + return (cycle_t) (in_be32(TIMER_BASE + TCR1)); +} + +static struct clocksource clocksource_microblaze = { + .name = "microblaze_clocksource", + .rating = 300, + .read = microblaze_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 24, /* I can shift it */ + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static int __init microblaze_clocksource_init(void) +{ + clocksource_microblaze.mult = + clocksource_hz2mult(cpuinfo.cpu_clock_freq, + clocksource_microblaze.shift); + if (clocksource_register(&clocksource_microblaze)) + panic("failed to register clocksource"); + + /* stop timer1 */ + out_be32(TIMER_BASE + TCSR1, in_be32(TIMER_BASE + TCSR1) & ~TCSR_ENT); + /* start timer1 - up counting without interrupt */ + out_be32(TIMER_BASE + TCSR1, TCSR_TINT|TCSR_ENT|TCSR_ARHT); + return 0; +} + +void __init time_init(void) +{ + u32 irq, i = 0; + u32 timer_num = 1; + struct device_node *timer = NULL; +#ifdef CONFIG_SELFMOD_TIMER + unsigned int timer_baseaddr = 0; + int arr_func[] = { + (int)µblaze_read, + (int)&timer_interrupt, + (int)µblaze_clocksource_init, + (int)µblaze_timer_set_mode, + (int)µblaze_timer_set_next_event, + 0 + }; +#endif + char *timer_list[] = { + "xlnx,xps-timer-1.00.a", + "xlnx,opb-timer-1.00.b", + "xlnx,opb-timer-1.00.a", + NULL + }; + + for (i = 0; timer_list[i] != NULL; i++) { + timer = of_find_compatible_node(NULL, NULL, timer_list[i]); + if (timer) + break; + } + + timer_baseaddr = *(int *) of_get_property(timer, "reg", NULL); + timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE); + irq = *(int *) of_get_property(timer, "interrupts", NULL); + timer_num = + *(int *) of_get_property(timer, "xlnx,one-timer-only", NULL); + if (timer_num) { + printk(KERN_EMERG "Please enable two timers in HW\n"); + BUG(); + } + +#ifdef CONFIG_SELFMOD_TIMER + selfmod_function((int *) arr_func, timer_baseaddr); +#endif + printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n", + timer_list[i], timer_baseaddr, irq); + + cpuinfo.freq_div_hz = cpuinfo.cpu_clock_freq / HZ; + + setup_irq(irq, &timer_irqaction); +#ifdef CONFIG_HEART_BEAT + setup_heartbeat(); +#endif + microblaze_clocksource_init(); + microblaze_clockevent_init(); +} diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c new file mode 100644 index 00000000000..fbdc533c61e --- /dev/null +++ b/arch/microblaze/kernel/traps.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2007-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/kernel.h> +#include <linux/kallsyms.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/debug_locks.h> + +#include <asm/exceptions.h> +#include <asm/system.h> + +void trap_init(void) +{ + __enable_hw_exceptions(); +} + +void __bad_xchg(volatile void *ptr, int size) +{ + printk(KERN_INFO "xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n", + __builtin_return_address(0), ptr, size); + BUG(); +} +EXPORT_SYMBOL(__bad_xchg); + +static int kstack_depth_to_print = 24; + +static int __init kstack_setup(char *s) +{ + kstack_depth_to_print = strict_strtoul(s, 0, 0); + + return 1; +} +__setup("kstack=", kstack_setup); + +void show_trace(struct task_struct *task, unsigned long *stack) +{ + unsigned long addr; + + if (!stack) + stack = (unsigned long *)&stack; + + printk(KERN_NOTICE "Call Trace: "); +#ifdef CONFIG_KALLSYMS + printk(KERN_NOTICE "\n"); +#endif + while (!kstack_end(stack)) { + addr = *stack++; + /* + * If the address is either in the text segment of the + * kernel, or in the region which contains vmalloc'ed + * memory, it *may* be the address of a calling + * routine; if so, print it so that someone tracing + * down the cause of the crash will be able to figure + * out the call path that was taken. + */ + if (kernel_text_address(addr)) + print_ip_sym(addr); + } + printk(KERN_NOTICE "\n"); + + if (!task) + task = current; + + debug_show_held_locks(task); +} + +void show_stack(struct task_struct *task, unsigned long *sp) +{ + unsigned long *stack; + int i; + + if (sp == NULL) { + if (task) + sp = (unsigned long *) ((struct thread_info *) + (task->stack))->cpu_context.r1; + else + sp = (unsigned long *)&sp; + } + + stack = sp; + + printk(KERN_INFO "\nStack:\n "); + + for (i = 0; i < kstack_depth_to_print; i++) { + if (kstack_end(sp)) + break; + if (i && ((i % 8) == 0)) + printk("\n "); + printk("%08lx ", *sp++); + } + printk("\n"); + show_trace(task, stack); +} + +void dump_stack(void) +{ + show_stack(NULL, NULL); +} +EXPORT_SYMBOL(dump_stack); diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S new file mode 100644 index 00000000000..840385e5129 --- /dev/null +++ b/arch/microblaze/kernel/vmlinux.lds.S @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2008-2009 PetaLogix + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +OUTPUT_FORMAT("elf32-microblaze", "elf32-microblaze", "elf32-microblaze") +OUTPUT_ARCH(microblaze) +ENTRY(_start) + +#include <asm-generic/vmlinux.lds.h> + +jiffies = jiffies_64 + 4; + +SECTIONS { + . = CONFIG_KERNEL_BASE_ADDR; + + .text : { + _text = . ; + _stext = . ; + *(.text .text.*) + *(.fixup) + + *(.exitcall.exit) + SCHED_TEXT + LOCK_TEXT + KPROBES_TEXT + . = ALIGN (4) ; + _etext = . ; + } + + . = ALIGN (4) ; + _fdt_start = . ; /* place for fdt blob */ + . = . + 0x4000; + _fdt_end = . ; + + . = ALIGN(16); + RODATA + . = ALIGN(16); + __ex_table : { + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + } + + /* + * sdata2 section can go anywhere, but must be word aligned + * and SDA2_BASE must point to the middle of it + */ + .sdata2 : { + _ssrw = .; + . = ALIGN(4096); /* page aligned when MMU used - origin 0x8 */ + *(.sdata2) + . = ALIGN(8); + _essrw = .; + _ssrw_size = _essrw - _ssrw; + _KERNEL_SDA2_BASE_ = _ssrw + (_ssrw_size / 2); + } + + _sdata = . ; + .data ALIGN (4096) : { /* page aligned when MMU used - origin 0x4 */ + *(.data) + } + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + _edata = . ; + + /* Reserve some low RAM for r0 based memory references */ + . = ALIGN(0x4) ; + r0_ram = . ; + . = . + 4096; /* a page should be enough */ + + /* The initial task */ + . = ALIGN(8192); + .data.init_task : { *(.data.init_task) } + + /* Under the microblaze ABI, .sdata and .sbss must be contiguous */ + . = ALIGN(8); + .sdata : { + _ssro = .; + *(.sdata) + } + + .sbss : { + _ssbss = .; + *(.sbss) + _esbss = .; + _essro = .; + _ssro_size = _essro - _ssro ; + _KERNEL_SDA_BASE_ = _ssro + (_ssro_size / 2) ; + } + + __init_begin = .; + + . = ALIGN(4096); + .init.text : { + _sinittext = . ; + *(.init.text) + *(.exit.text) + *(.exit.data) + _einittext = .; + } + + .init.data : { *(.init.data) } + + . = ALIGN(4); + .init.ivt : { + __ivt_start = .; + *(.init.ivt) + __ivt_end = .; + } + + .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 = .; + } + + __init_end_before_initramfs = .; + + .init.ramfs ALIGN(4096) : { + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; + . = ALIGN(4); + LONG(0); +/* + * FIXME this can break initramfs for MMU. + * Pad init.ramfs up to page boundary, + * so that __init_end == __bss_start. This will make image.elf + * consistent with the image.bin + */ + /* . = ALIGN(4096); */ + } + __init_end = .; + + .bss ALIGN (4096) : { /* page aligned when MMU used */ + __bss_start = . ; + *(.bss*) + *(COMMON) + . = ALIGN (4) ; + __bss_stop = . ; + _ebss = . ; + } + . = ALIGN(4096); + _end = .; +} diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile new file mode 100644 index 00000000000..d27126bf306 --- /dev/null +++ b/arch/microblaze/lib/Makefile @@ -0,0 +1,13 @@ +# +# Makefile +# + +lib-y := memset.o checksum.o + +ifeq ($(CONFIG_OPT_LIB_ASM),y) +lib-y += fastcopy.o +else +lib-y += memcpy.o memmove.o +endif + +lib-y += uaccess.o diff --git a/arch/microblaze/lib/checksum.c b/arch/microblaze/lib/checksum.c new file mode 100644 index 00000000000..809340070a1 --- /dev/null +++ b/arch/microblaze/lib/checksum.c @@ -0,0 +1,163 @@ +/* + * + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * IP/TCP/UDP checksumming routines + * + * Authors: Jorge Cwik, <jorge@laser.satlink.net> + * Arnt Gulbrandsen, <agulbra@nvg.unit.no> + * Tom May, <ftom@netcom.com> + * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de> + * Lots of code moved from tcp.c and ip.c; see those files + * for more names. + * + * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek: + * Fixed some nasty bugs, causing some horrible crashes. + * A: At some points, the sum (%0) was used as + * length-counter instead of the length counter + * (%1). Thanks to Roman Hodek for pointing this out. + * B: GCC seems to mess up if one uses too many + * data-registers to hold input values and one tries to + * specify d0 and d1 as scratch registers. Letting gcc + * choose these registers itself solves the problem. + * + * 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. + */ + +/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access + kills, so most of the assembly has to go. */ + +#include <net/checksum.h> +#include <asm/checksum.h> +#include <linux/module.h> + +static inline unsigned short from32to16(unsigned long x) +{ + /* add up 16-bit and 16-bit for 16+c bit */ + x = (x & 0xffff) + (x >> 16); + /* add up carry.. */ + x = (x & 0xffff) + (x >> 16); + return x; +} + +static unsigned int do_csum(const unsigned char *buff, int len) +{ + int odd, count; + unsigned long result = 0; + + if (len <= 0) + goto out; + odd = 1 & (unsigned long) buff; + if (odd) { + result = *buff; + len--; + buff++; + } + count = len >> 1; /* nr of 16-bit words.. */ + if (count) { + if (2 & (unsigned long) buff) { + result += *(unsigned short *) buff; + count--; + len -= 2; + buff += 2; + } + count >>= 1; /* nr of 32-bit words.. */ + if (count) { + unsigned long carry = 0; + do { + unsigned long w = *(unsigned long *) buff; + count--; + buff += 4; + result += carry; + result += w; + carry = (w > result); + } while (count); + result += carry; + result = (result & 0xffff) + (result >> 16); + } + if (len & 2) { + result += *(unsigned short *) buff; + buff += 2; + } + } + if (len & 1) + result += (*buff << 8); + result = from32to16(result); + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); +out: + return result; +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + */ +__sum16 ip_fast_csum(const void *iph, unsigned int ihl) +{ + return (__force __sum16)~do_csum(iph, ihl*4); +} + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +__wsum csum_partial(const void *buff, int len, __wsum sum) +{ + unsigned int result = do_csum(buff, len); + + /* add in old sum, and carry.. */ + result += sum; + if (sum > result) + result += 1; + return result; +} +EXPORT_SYMBOL(csum_partial); + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +__sum16 ip_compute_csum(const unsigned char *buff, int len) +{ + return ~do_csum(buff, len); +} +EXPORT_SYMBOL(ip_compute_csum); + +/* + * copy from fs while checksumming, otherwise like csum_partial + */ +__wsum +csum_partial_copy_from_user(const char __user *src, char *dst, int len, + int sum, int *csum_err) +{ + if (csum_err) + *csum_err = 0; + memcpy(dst, src, len); + return csum_partial(dst, len, sum); +} +EXPORT_SYMBOL(csum_partial_copy_from_user); + +/* + * copy from ds while checksumming, otherwise like csum_partial + */ +__wsum +csum_partial_copy(const char *src, char *dst, int len, int sum) +{ + memcpy(dst, src, len); + return csum_partial(dst, len, sum); +} +EXPORT_SYMBOL(csum_partial_copy); diff --git a/arch/microblaze/lib/fastcopy.S b/arch/microblaze/lib/fastcopy.S new file mode 100644 index 00000000000..02e3ab4eddf --- /dev/null +++ b/arch/microblaze/lib/fastcopy.S @@ -0,0 +1,662 @@ +/* + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2008-2009 PetaLogix + * Copyright (C) 2008 Jim Law - Iris LP All rights reserved. + * + * 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. + * + * Written by Jim Law <jlaw@irispower.com> + * + * intended to replace: + * memcpy in memcpy.c and + * memmove in memmove.c + * ... in arch/microblaze/lib + * + * + * assly_fastcopy.S + * + * Attempt at quicker memcpy and memmove for MicroBlaze + * Input : Operand1 in Reg r5 - destination address + * Operand2 in Reg r6 - source address + * Operand3 in Reg r7 - number of bytes to transfer + * Output: Result in Reg r3 - starting destinaition address + * + * + * Explanation: + * Perform (possibly unaligned) copy of a block of memory + * between mem locations with size of xfer spec'd in bytes + */ + +#include <linux/linkage.h> + + .globl memcpy + .ent memcpy + +memcpy: +fast_memcpy_ascending: + /* move d to return register as value of function */ + addi r3, r5, 0 + + addi r4, r0, 4 /* n = 4 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + blti r4, a_xfer_end /* if n < 0, less than one word to transfer */ + + /* transfer first 0~3 bytes to get aligned dest address */ + andi r4, r5, 3 /* n = d & 3 */ + /* if zero, destination already aligned */ + beqi r4, a_dalign_done + /* n = 4 - n (yields 3, 2, 1 transfers for 1, 2, 3 addr offset) */ + rsubi r4, r4, 4 + rsub r7, r4, r7 /* c = c - n adjust c */ + +a_xfer_first_loop: + /* if no bytes left to transfer, transfer the bulk */ + beqi r4, a_dalign_done + lbui r11, r6, 0 /* h = *s */ + sbi r11, r5, 0 /* *d = h */ + addi r6, r6, 1 /* s++ */ + addi r5, r5, 1 /* d++ */ + brid a_xfer_first_loop /* loop */ + addi r4, r4, -1 /* n-- (IN DELAY SLOT) */ + +a_dalign_done: + addi r4, r0, 32 /* n = 32 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + /* if n < 0, less than one block to transfer */ + blti r4, a_block_done + +a_block_xfer: + andi r4, r7, 0xffffffe0 /* n = c & ~31 */ + rsub r7, r4, r7 /* c = c - n */ + + andi r9, r6, 3 /* t1 = s & 3 */ + /* if temp != 0, unaligned transfers needed */ + bnei r9, a_block_unaligned + +a_block_aligned: + lwi r9, r6, 0 /* t1 = *(s + 0) */ + lwi r10, r6, 4 /* t2 = *(s + 4) */ + lwi r11, r6, 8 /* t3 = *(s + 8) */ + lwi r12, r6, 12 /* t4 = *(s + 12) */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + swi r10, r5, 4 /* *(d + 4) = t2 */ + swi r11, r5, 8 /* *(d + 8) = t3 */ + swi r12, r5, 12 /* *(d + 12) = t4 */ + lwi r9, r6, 16 /* t1 = *(s + 16) */ + lwi r10, r6, 20 /* t2 = *(s + 20) */ + lwi r11, r6, 24 /* t3 = *(s + 24) */ + lwi r12, r6, 28 /* t4 = *(s + 28) */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + swi r10, r5, 20 /* *(d + 20) = t2 */ + swi r11, r5, 24 /* *(d + 24) = t3 */ + swi r12, r5, 28 /* *(d + 28) = t4 */ + addi r6, r6, 32 /* s = s + 32 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, a_block_aligned /* while (n) loop */ + addi r5, r5, 32 /* d = d + 32 (IN DELAY SLOT) */ + bri a_block_done + +a_block_unaligned: + andi r8, r6, 0xfffffffc /* as = s & ~3 */ + add r6, r6, r4 /* s = s + n */ + lwi r11, r8, 0 /* h = *(as + 0) */ + + addi r9, r9, -1 + beqi r9, a_block_u1 /* t1 was 1 => 1 byte offset */ + addi r9, r9, -1 + beqi r9, a_block_u2 /* t1 was 2 => 2 byte offset */ + +a_block_u3: + bslli r11, r11, 24 /* h = h << 24 */ +a_bu3_loop: + lwi r12, r8, 4 /* v = *(as + 4) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 12) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 32 /* v = *(as + 32) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + addi r8, r8, 32 /* as = as + 32 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, a_bu3_loop /* while (n) loop */ + addi r5, r5, 32 /* d = d + 32 (IN DELAY SLOT) */ + bri a_block_done + +a_block_u1: + bslli r11, r11, 8 /* h = h << 8 */ +a_bu1_loop: + lwi r12, r8, 4 /* v = *(as + 4) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 12) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 32 /* v = *(as + 32) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + addi r8, r8, 32 /* as = as + 32 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, a_bu1_loop /* while (n) loop */ + addi r5, r5, 32 /* d = d + 32 (IN DELAY SLOT) */ + bri a_block_done + +a_block_u2: + bslli r11, r11, 16 /* h = h << 16 */ +a_bu2_loop: + lwi r12, r8, 4 /* v = *(as + 4) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 12) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 32 /* v = *(as + 32) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + addi r8, r8, 32 /* as = as + 32 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, a_bu2_loop /* while (n) loop */ + addi r5, r5, 32 /* d = d + 32 (IN DELAY SLOT) */ + +a_block_done: + addi r4, r0, 4 /* n = 4 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + blti r4, a_xfer_end /* if n < 0, less than one word to transfer */ + +a_word_xfer: + andi r4, r7, 0xfffffffc /* n = c & ~3 */ + addi r10, r0, 0 /* offset = 0 */ + + andi r9, r6, 3 /* t1 = s & 3 */ + /* if temp != 0, unaligned transfers needed */ + bnei r9, a_word_unaligned + +a_word_aligned: + lw r9, r6, r10 /* t1 = *(s+offset) */ + sw r9, r5, r10 /* *(d+offset) = t1 */ + addi r4, r4,-4 /* n-- */ + bneid r4, a_word_aligned /* loop */ + addi r10, r10, 4 /* offset++ (IN DELAY SLOT) */ + + bri a_word_done + +a_word_unaligned: + andi r8, r6, 0xfffffffc /* as = s & ~3 */ + lwi r11, r8, 0 /* h = *(as + 0) */ + addi r8, r8, 4 /* as = as + 4 */ + + addi r9, r9, -1 + beqi r9, a_word_u1 /* t1 was 1 => 1 byte offset */ + addi r9, r9, -1 + beqi r9, a_word_u2 /* t1 was 2 => 2 byte offset */ + +a_word_u3: + bslli r11, r11, 24 /* h = h << 24 */ +a_wu3_loop: + lw r12, r8, r10 /* v = *(as + offset) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r10 /* *(d + offset) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + addi r4, r4,-4 /* n = n - 4 */ + bneid r4, a_wu3_loop /* while (n) loop */ + addi r10, r10, 4 /* offset = ofset + 4 (IN DELAY SLOT) */ + + bri a_word_done + +a_word_u1: + bslli r11, r11, 8 /* h = h << 8 */ +a_wu1_loop: + lw r12, r8, r10 /* v = *(as + offset) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r10 /* *(d + offset) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + addi r4, r4,-4 /* n = n - 4 */ + bneid r4, a_wu1_loop /* while (n) loop */ + addi r10, r10, 4 /* offset = ofset + 4 (IN DELAY SLOT) */ + + bri a_word_done + +a_word_u2: + bslli r11, r11, 16 /* h = h << 16 */ +a_wu2_loop: + lw r12, r8, r10 /* v = *(as + offset) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r10 /* *(d + offset) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + addi r4, r4,-4 /* n = n - 4 */ + bneid r4, a_wu2_loop /* while (n) loop */ + addi r10, r10, 4 /* offset = ofset + 4 (IN DELAY SLOT) */ + +a_word_done: + add r5, r5, r10 /* d = d + offset */ + add r6, r6, r10 /* s = s + offset */ + rsub r7, r10, r7 /* c = c - offset */ + +a_xfer_end: +a_xfer_end_loop: + beqi r7, a_done /* while (c) */ + lbui r9, r6, 0 /* t1 = *s */ + addi r6, r6, 1 /* s++ */ + sbi r9, r5, 0 /* *d = t1 */ + addi r7, r7, -1 /* c-- */ + brid a_xfer_end_loop /* loop */ + addi r5, r5, 1 /* d++ (IN DELAY SLOT) */ + +a_done: + rtsd r15, 8 + nop + +.end memcpy +/*----------------------------------------------------------------------------*/ + .globl memmove + .ent memmove + +memmove: + cmpu r4, r5, r6 /* n = s - d */ + bgei r4,fast_memcpy_ascending + +fast_memcpy_descending: + /* move d to return register as value of function */ + addi r3, r5, 0 + + add r5, r5, r7 /* d = d + c */ + add r6, r6, r7 /* s = s + c */ + + addi r4, r0, 4 /* n = 4 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + blti r4,d_xfer_end /* if n < 0, less than one word to transfer */ + + /* transfer first 0~3 bytes to get aligned dest address */ + andi r4, r5, 3 /* n = d & 3 */ + /* if zero, destination already aligned */ + beqi r4,d_dalign_done + rsub r7, r4, r7 /* c = c - n adjust c */ + +d_xfer_first_loop: + /* if no bytes left to transfer, transfer the bulk */ + beqi r4,d_dalign_done + addi r6, r6, -1 /* s-- */ + addi r5, r5, -1 /* d-- */ + lbui r11, r6, 0 /* h = *s */ + sbi r11, r5, 0 /* *d = h */ + brid d_xfer_first_loop /* loop */ + addi r4, r4, -1 /* n-- (IN DELAY SLOT) */ + +d_dalign_done: + addi r4, r0, 32 /* n = 32 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + /* if n < 0, less than one block to transfer */ + blti r4, d_block_done + +d_block_xfer: + andi r4, r7, 0xffffffe0 /* n = c & ~31 */ + rsub r7, r4, r7 /* c = c - n */ + + andi r9, r6, 3 /* t1 = s & 3 */ + /* if temp != 0, unaligned transfers needed */ + bnei r9, d_block_unaligned + +d_block_aligned: + addi r6, r6, -32 /* s = s - 32 */ + addi r5, r5, -32 /* d = d - 32 */ + lwi r9, r6, 28 /* t1 = *(s + 28) */ + lwi r10, r6, 24 /* t2 = *(s + 24) */ + lwi r11, r6, 20 /* t3 = *(s + 20) */ + lwi r12, r6, 16 /* t4 = *(s + 16) */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + swi r10, r5, 24 /* *(d + 24) = t2 */ + swi r11, r5, 20 /* *(d + 20) = t3 */ + swi r12, r5, 16 /* *(d + 16) = t4 */ + lwi r9, r6, 12 /* t1 = *(s + 12) */ + lwi r10, r6, 8 /* t2 = *(s + 8) */ + lwi r11, r6, 4 /* t3 = *(s + 4) */ + lwi r12, r6, 0 /* t4 = *(s + 0) */ + swi r9, r5, 12 /* *(d + 12) = t1 */ + swi r10, r5, 8 /* *(d + 8) = t2 */ + swi r11, r5, 4 /* *(d + 4) = t3 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, d_block_aligned /* while (n) loop */ + swi r12, r5, 0 /* *(d + 0) = t4 (IN DELAY SLOT) */ + bri d_block_done + +d_block_unaligned: + andi r8, r6, 0xfffffffc /* as = s & ~3 */ + rsub r6, r4, r6 /* s = s - n */ + lwi r11, r8, 0 /* h = *(as + 0) */ + + addi r9, r9, -1 + beqi r9,d_block_u1 /* t1 was 1 => 1 byte offset */ + addi r9, r9, -1 + beqi r9,d_block_u2 /* t1 was 2 => 2 byte offset */ + +d_block_u3: + bsrli r11, r11, 8 /* h = h >> 8 */ +d_bu3_loop: + addi r8, r8, -32 /* as = as - 32 */ + addi r5, r5, -32 /* d = d - 32 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 112) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 4 /* v = *(as + 4) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 0 /* v = *(as + 0) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, d_bu3_loop /* while (n) loop */ + bsrli r11, r12, 8 /* h = v >> 8 (IN DELAY SLOT) */ + bri d_block_done + +d_block_u1: + bsrli r11, r11, 24 /* h = h >> 24 */ +d_bu1_loop: + addi r8, r8, -32 /* as = as - 32 */ + addi r5, r5, -32 /* d = d - 32 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 112) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 4 /* v = *(as + 4) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 0 /* v = *(as + 0) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, d_bu1_loop /* while (n) loop */ + bsrli r11, r12, 24 /* h = v >> 24 (IN DELAY SLOT) */ + bri d_block_done + +d_block_u2: + bsrli r11, r11, 16 /* h = h >> 16 */ +d_bu2_loop: + addi r8, r8, -32 /* as = as - 32 */ + addi r5, r5, -32 /* d = d - 32 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 112) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 4 /* v = *(as + 4) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 0 /* v = *(as + 0) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, d_bu2_loop /* while (n) loop */ + bsrli r11, r12, 16 /* h = v >> 16 (IN DELAY SLOT) */ + +d_block_done: + addi r4, r0, 4 /* n = 4 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + blti r4,d_xfer_end /* if n < 0, less than one word to transfer */ + +d_word_xfer: + andi r4, r7, 0xfffffffc /* n = c & ~3 */ + rsub r5, r4, r5 /* d = d - n */ + rsub r6, r4, r6 /* s = s - n */ + rsub r7, r4, r7 /* c = c - n */ + + andi r9, r6, 3 /* t1 = s & 3 */ + /* if temp != 0, unaligned transfers needed */ + bnei r9, d_word_unaligned + +d_word_aligned: + addi r4, r4,-4 /* n-- */ + lw r9, r6, r4 /* t1 = *(s+n) */ + bneid r4, d_word_aligned /* loop */ + sw r9, r5, r4 /* *(d+n) = t1 (IN DELAY SLOT) */ + + bri d_word_done + +d_word_unaligned: + andi r8, r6, 0xfffffffc /* as = s & ~3 */ + lw r11, r8, r4 /* h = *(as + n) */ + + addi r9, r9, -1 + beqi r9,d_word_u1 /* t1 was 1 => 1 byte offset */ + addi r9, r9, -1 + beqi r9,d_word_u2 /* t1 was 2 => 2 byte offset */ + +d_word_u3: + bsrli r11, r11, 8 /* h = h >> 8 */ +d_wu3_loop: + addi r4, r4,-4 /* n = n - 4 */ + lw r12, r8, r4 /* v = *(as + n) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r4 /* *(d + n) = t1 */ + bneid r4, d_wu3_loop /* while (n) loop */ + bsrli r11, r12, 8 /* h = v >> 8 (IN DELAY SLOT) */ + + bri d_word_done + +d_word_u1: + bsrli r11, r11, 24 /* h = h >> 24 */ +d_wu1_loop: + addi r4, r4,-4 /* n = n - 4 */ + lw r12, r8, r4 /* v = *(as + n) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r4 /* *(d + n) = t1 */ + bneid r4, d_wu1_loop /* while (n) loop */ + bsrli r11, r12, 24 /* h = v >> 24 (IN DELAY SLOT) */ + + bri d_word_done + +d_word_u2: + bsrli r11, r11, 16 /* h = h >> 16 */ +d_wu2_loop: + addi r4, r4,-4 /* n = n - 4 */ + lw r12, r8, r4 /* v = *(as + n) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r4 /* *(d + n) = t1 */ + bneid r4, d_wu2_loop /* while (n) loop */ + bsrli r11, r12, 16 /* h = v >> 16 (IN DELAY SLOT) */ + +d_word_done: + +d_xfer_end: +d_xfer_end_loop: + beqi r7, a_done /* while (c) */ + addi r6, r6, -1 /* s-- */ + lbui r9, r6, 0 /* t1 = *s */ + addi r5, r5, -1 /* d-- */ + sbi r9, r5, 0 /* *d = t1 */ + brid d_xfer_end_loop /* loop */ + addi r7, r7, -1 /* c-- (IN DELAY SLOT) */ + +d_done: + rtsd r15, 8 + nop + +.end memmove diff --git a/arch/microblaze/lib/memcpy.c b/arch/microblaze/lib/memcpy.c new file mode 100644 index 00000000000..5880119c448 --- /dev/null +++ b/arch/microblaze/lib/memcpy.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2008-2009 PetaLogix + * Copyright (C) 2007 John Williams + * + * Reasonably optimised generic C-code for memcpy on Microblaze + * This is generic C code to do efficient, alignment-aware memcpy. + * + * It is based on demo code originally Copyright 2001 by Intel Corp, taken from + * http://www.embedded.com/showArticle.jhtml?articleID=19205567 + * + * Attempts were made, unsuccesfully, to contact the original + * author of this code (Michael Morrow, Intel). Below is the original + * copyright notice. + * + * This software has been developed by Intel Corporation. + * Intel specifically disclaims all warranties, express or + * implied, and all liability, including consequential and + * other indirect damages, for the use of this program, including + * liability for infringement of any proprietary rights, + * and including the warranties of merchantability and fitness + * for a particular purpose. Intel does not assume any + * responsibility for and errors which may appear in this program + * not any responsibility to update it. + */ + +#include <linux/types.h> +#include <linux/stddef.h> +#include <linux/compiler.h> +#include <linux/module.h> + +#include <linux/string.h> +#include <asm/system.h> + +#ifdef __HAVE_ARCH_MEMCPY +void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c) +{ + const char *src = v_src; + char *dst = v_dst; +#ifndef CONFIG_OPT_LIB_FUNCTION + /* Simple, byte oriented memcpy. */ + while (c--) + *dst++ = *src++; + + return v_dst; +#else + /* The following code tries to optimize the copy by using unsigned + * alignment. This will work fine if both source and destination are + * aligned on the same boundary. However, if they are aligned on + * different boundaries shifts will be necessary. This might result in + * bad performance on MicroBlaze systems without a barrel shifter. + */ + const uint32_t *i_src; + uint32_t *i_dst; + + if (c >= 4) { + unsigned value, buf_hold; + + /* Align the dstination to a word boundry. */ + /* This is done in an endian independant manner. */ + switch ((unsigned long)dst & 3) { + case 1: + *dst++ = *src++; + --c; + case 2: + *dst++ = *src++; + --c; + case 3: + *dst++ = *src++; + --c; + } + + i_dst = (void *)dst; + + /* Choose a copy scheme based on the source */ + /* alignment relative to dstination. */ + switch ((unsigned long)src & 3) { + case 0x0: /* Both byte offsets are aligned */ + i_src = (const void *)src; + + for (; c >= 4; c -= 4) + *i_dst++ = *i_src++; + + src = (const void *)i_src; + break; + case 0x1: /* Unaligned - Off by 1 */ + /* Word align the source */ + i_src = (const void *) ((unsigned)src & ~3); + + /* Load the holding buffer */ + buf_hold = *i_src++ << 8; + + for (; c >= 4; c -= 4) { + value = *i_src++; + *i_dst++ = buf_hold | value >> 24; + buf_hold = value << 8; + } + + /* Realign the source */ + src = (const void *)i_src; + src -= 3; + break; + case 0x2: /* Unaligned - Off by 2 */ + /* Word align the source */ + i_src = (const void *) ((unsigned)src & ~3); + + /* Load the holding buffer */ + buf_hold = *i_src++ << 16; + + for (; c >= 4; c -= 4) { + value = *i_src++; + *i_dst++ = buf_hold | value >> 16; + buf_hold = value << 16; + } + + /* Realign the source */ + src = (const void *)i_src; + src -= 2; + break; + case 0x3: /* Unaligned - Off by 3 */ + /* Word align the source */ + i_src = (const void *) ((unsigned)src & ~3); + + /* Load the holding buffer */ + buf_hold = *i_src++ << 24; + + for (; c >= 4; c -= 4) { + value = *i_src++; + *i_dst++ = buf_hold | value >> 8; + buf_hold = value << 24; + } + + /* Realign the source */ + src = (const void *)i_src; + src -= 1; + break; + } + dst = (void *)i_dst; + } + + /* Finish off any remaining bytes */ + /* simple fast copy, ... unless a cache boundry is crossed */ + switch (c) { + case 3: + *dst++ = *src++; + case 2: + *dst++ = *src++; + case 1: + *dst++ = *src++; + } + + return v_dst; +#endif +} +EXPORT_SYMBOL(memcpy); +#endif /* __HAVE_ARCH_MEMCPY */ + +void *cacheable_memcpy(void *d, const void *s, __kernel_size_t c) +{ + return memcpy(d, s, c); +} diff --git a/arch/microblaze/lib/memmove.c b/arch/microblaze/lib/memmove.c new file mode 100644 index 00000000000..d4e9f49a71f --- /dev/null +++ b/arch/microblaze/lib/memmove.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2008-2009 PetaLogix + * Copyright (C) 2007 John Williams + * + * Reasonably optimised generic C-code for memcpy on Microblaze + * This is generic C code to do efficient, alignment-aware memmove. + * + * It is based on demo code originally Copyright 2001 by Intel Corp, taken from + * http://www.embedded.com/showArticle.jhtml?articleID=19205567 + * + * Attempts were made, unsuccesfully, to contact the original + * author of this code (Michael Morrow, Intel). Below is the original + * copyright notice. + * + * This software has been developed by Intel Corporation. + * Intel specifically disclaims all warranties, express or + * implied, and all liability, including consequential and + * other indirect damages, for the use of this program, including + * liability for infringement of any proprietary rights, + * and including the warranties of merchantability and fitness + * for a particular purpose. Intel does not assume any + * responsibility for and errors which may appear in this program + * not any responsibility to update it. + */ + +#include <linux/types.h> +#include <linux/stddef.h> +#include <linux/compiler.h> +#include <linux/module.h> +#include <linux/string.h> + +#ifdef __HAVE_ARCH_MEMMOVE +void *memmove(void *v_dst, const void *v_src, __kernel_size_t c) +{ + const char *src = v_src; + char *dst = v_dst; + +#ifdef CONFIG_OPT_LIB_FUNCTION + const uint32_t *i_src; + uint32_t *i_dst; +#endif + + if (!c) + return v_dst; + + /* Use memcpy when source is higher than dest */ + if (v_dst <= v_src) + return memcpy(v_dst, v_src, c); + +#ifndef CONFIG_OPT_LIB_FUNCTION + /* copy backwards, from end to beginning */ + src += c; + dst += c; + + /* Simple, byte oriented memmove. */ + while (c--) + *--dst = *--src; + + return v_dst; +#else + /* The following code tries to optimize the copy by using unsigned + * alignment. This will work fine if both source and destination are + * aligned on the same boundary. However, if they are aligned on + * different boundaries shifts will be necessary. This might result in + * bad performance on MicroBlaze systems without a barrel shifter. + */ + /* FIXME this part needs more test */ + /* Do a descending copy - this is a bit trickier! */ + dst += c; + src += c; + + if (c >= 4) { + unsigned value, buf_hold; + + /* Align the destination to a word boundry. */ + /* This is done in an endian independant manner. */ + + switch ((unsigned long)dst & 3) { + case 3: + *--dst = *--src; + --c; + case 2: + *--dst = *--src; + --c; + case 1: + *--dst = *--src; + --c; + } + + i_dst = (void *)dst; + /* Choose a copy scheme based on the source */ + /* alignment relative to dstination. */ + switch ((unsigned long)src & 3) { + case 0x0: /* Both byte offsets are aligned */ + + i_src = (const void *)src; + + for (; c >= 4; c -= 4) + *--i_dst = *--i_src; + + src = (const void *)i_src; + break; + case 0x1: /* Unaligned - Off by 1 */ + /* Word align the source */ + i_src = (const void *) (((unsigned)src + 4) & ~3); + + /* Load the holding buffer */ + buf_hold = *--i_src >> 24; + + for (; c >= 4; c -= 4) { + value = *--i_src; + *--i_dst = buf_hold << 8 | value; + buf_hold = value >> 24; + } + + /* Realign the source */ + src = (const void *)i_src; + src += 1; + break; + case 0x2: /* Unaligned - Off by 2 */ + /* Word align the source */ + i_src = (const void *) (((unsigned)src + 4) & ~3); + + /* Load the holding buffer */ + buf_hold = *--i_src >> 16; + + for (; c >= 4; c -= 4) { + value = *--i_src; + *--i_dst = buf_hold << 16 | value; + buf_hold = value >> 16; + } + + /* Realign the source */ + src = (const void *)i_src; + src += 2; + break; + case 0x3: /* Unaligned - Off by 3 */ + /* Word align the source */ + i_src = (const void *) (((unsigned)src + 4) & ~3); + + /* Load the holding buffer */ + buf_hold = *--i_src >> 8; + + for (; c >= 4; c -= 4) { + value = *--i_src; + *--i_dst = buf_hold << 24 | value; + buf_hold = value >> 8; + } + + /* Realign the source */ + src = (const void *)i_src; + src += 3; + break; + } + dst = (void *)i_dst; + } + + /* simple fast copy, ... unless a cache boundry is crossed */ + /* Finish off any remaining bytes */ + switch (c) { + case 4: + *--dst = *--src; + case 3: + *--dst = *--src; + case 2: + *--dst = *--src; + case 1: + *--dst = *--src; + } + return v_dst; +#endif +} +EXPORT_SYMBOL(memmove); +#endif /* __HAVE_ARCH_MEMMOVE */ diff --git a/arch/microblaze/lib/memset.c b/arch/microblaze/lib/memset.c new file mode 100644 index 00000000000..941dc8f94b0 --- /dev/null +++ b/arch/microblaze/lib/memset.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2008-2009 PetaLogix + * Copyright (C) 2007 John Williams + * + * Reasonably optimised generic C-code for memset on Microblaze + * This is generic C code to do efficient, alignment-aware memcpy. + * + * It is based on demo code originally Copyright 2001 by Intel Corp, taken from + * http://www.embedded.com/showArticle.jhtml?articleID=19205567 + * + * Attempts were made, unsuccesfully, to contact the original + * author of this code (Michael Morrow, Intel). Below is the original + * copyright notice. + * + * This software has been developed by Intel Corporation. + * Intel specifically disclaims all warranties, express or + * implied, and all liability, including consequential and + * other indirect damages, for the use of this program, including + * liability for infringement of any proprietary rights, + * and including the warranties of merchantability and fitness + * for a particular purpose. Intel does not assume any + * responsibility for and errors which may appear in this program + * not any responsibility to update it. + */ + +#include <linux/types.h> +#include <linux/stddef.h> +#include <linux/compiler.h> +#include <linux/module.h> +#include <linux/string.h> + +#ifdef __HAVE_ARCH_MEMSET +void *memset(void *v_src, int c, __kernel_size_t n) +{ + + char *src = v_src; +#ifdef CONFIG_OPT_LIB_FUNCTION + uint32_t *i_src; + uint32_t w32; +#endif + /* Truncate c to 8 bits */ + c = (c & 0xFF); + +#ifdef CONFIG_OPT_LIB_FUNCTION + /* Make a repeating word out of it */ + w32 = c; + w32 |= w32 << 8; + w32 |= w32 << 16; + + if (n >= 4) { + /* Align the destination to a word boundary */ + /* This is done in an endian independant manner */ + switch ((unsigned) src & 3) { + case 1: + *src++ = c; + --n; + case 2: + *src++ = c; + --n; + case 3: + *src++ = c; + --n; + } + + i_src = (void *)src; + + /* Do as many full-word copies as we can */ + for (; n >= 4; n -= 4) + *i_src++ = w32; + + src = (void *)i_src; + } +#endif + /* Simple, byte oriented memset or the rest of count. */ + while (n--) + *src++ = c; + + return v_src; +} +EXPORT_SYMBOL(memset); +#endif /* __HAVE_ARCH_MEMSET */ diff --git a/arch/microblaze/lib/uaccess.c b/arch/microblaze/lib/uaccess.c new file mode 100644 index 00000000000..8eb9df5a26c --- /dev/null +++ b/arch/microblaze/lib/uaccess.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/string.h> +#include <asm/uaccess.h> + +#include <asm/bug.h> + +long strnlen_user(const char __user *src, long count) +{ + return strlen(src) + 1; +} + +#define __do_strncpy_from_user(dst, src, count, res) \ + do { \ + char *tmp; \ + strncpy(dst, src, count); \ + for (tmp = dst; *tmp && count > 0; tmp++, count--) \ + ; \ + res = (tmp - dst); \ + } while (0) + +long __strncpy_from_user(char *dst, const char __user *src, long count) +{ + long res; + __do_strncpy_from_user(dst, src, count, res); + return res; +} + +long strncpy_from_user(char *dst, const char __user *src, long count) +{ + long res = -EFAULT; + if (access_ok(VERIFY_READ, src, 1)) + __do_strncpy_from_user(dst, src, count, res); + return res; +} diff --git a/arch/microblaze/mm/Makefile b/arch/microblaze/mm/Makefile new file mode 100644 index 00000000000..bf9e4479a1f --- /dev/null +++ b/arch/microblaze/mm/Makefile @@ -0,0 +1,5 @@ +# +# Makefile +# + +obj-y := init.o diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c new file mode 100644 index 00000000000..b0c8213cd6c --- /dev/null +++ b/arch/microblaze/mm/init.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu> + * Copyright (C) 2006 Atmark Techno, Inc. + * + * 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. + */ + +#include <linux/bootmem.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/lmb.h> +#include <linux/mm.h> /* mem_init */ +#include <linux/initrd.h> +#include <linux/pagemap.h> +#include <linux/pfn.h> +#include <linux/swap.h> + +#include <asm/page.h> +#include <asm/mmu_context.h> +#include <asm/pgalloc.h> +#include <asm/sections.h> +#include <asm/tlb.h> + +unsigned int __page_offset; +/* EXPORT_SYMBOL(__page_offset); */ + +char *klimit = _end; + +/* + * Initialize the bootmem system and give it all the memory we + * have available. + */ +unsigned int memory_start; +unsigned int memory_end; /* due to mm/nommu.c */ +unsigned int memory_size; + +/* + * paging_init() sets up the page tables - in fact we've already done this. + */ +static void __init paging_init(void) +{ + int i; + unsigned long zones_size[MAX_NR_ZONES]; + + /* + * old: we can DMA to/from any address.put all page into ZONE_DMA + * We use only ZONE_NORMAL + */ + zones_size[ZONE_NORMAL] = max_mapnr; + + /* every other zones are empty */ + for (i = 1; i < MAX_NR_ZONES; i++) + zones_size[i] = 0; + + free_area_init(zones_size); +} + +void __init setup_memory(void) +{ + int i; + unsigned long map_size; + u32 kernel_align_start, kernel_align_size; + + /* Find main memory where is the kernel */ + for (i = 0; i < lmb.memory.cnt; i++) { + memory_start = (u32) lmb.memory.region[i].base; + memory_end = (u32) lmb.memory.region[i].base + + (u32) lmb.memory.region[i].size; + if ((memory_start <= (u32)_text) && + ((u32)_text <= memory_end)) { + memory_size = memory_end - memory_start; + PAGE_OFFSET = memory_start; + printk(KERN_INFO "%s: Main mem: 0x%x-0x%x, " + "size 0x%08x\n", __func__, memory_start, + memory_end, memory_size); + break; + } + } + + if (!memory_start || !memory_end) { + panic("%s: Missing memory setting 0x%08x-0x%08x\n", + __func__, memory_start, memory_end); + } + + /* reservation of region where is the kernel */ + kernel_align_start = PAGE_DOWN((u32)_text); + /* ALIGN can be remove because _end in vmlinux.lds.S is align */ + kernel_align_size = PAGE_UP((u32)klimit) - kernel_align_start; + lmb_reserve(kernel_align_start, kernel_align_size); + printk(KERN_INFO "%s: kernel addr=0x%08x-0x%08x size=0x%08x\n", + __func__, kernel_align_start, kernel_align_start + + kernel_align_size, kernel_align_size); + + /* + * Kernel: + * start: base phys address of kernel - page align + * end: base phys address of kernel - page align + * + * min_low_pfn - the first page (mm/bootmem.c - node_boot_start) + * max_low_pfn + * max_mapnr - the first unused page (mm/bootmem.c - node_low_pfn) + * num_physpages - number of all pages + */ + + /* memory start is from the kernel end (aligned) to higher addr */ + min_low_pfn = memory_start >> PAGE_SHIFT; /* minimum for allocation */ + /* RAM is assumed contiguous */ + num_physpages = max_mapnr = memory_size >> PAGE_SHIFT; + max_pfn = max_low_pfn = memory_end >> PAGE_SHIFT; + + printk(KERN_INFO "%s: max_mapnr: %#lx\n", __func__, max_mapnr); + printk(KERN_INFO "%s: min_low_pfn: %#lx\n", __func__, min_low_pfn); + printk(KERN_INFO "%s: max_low_pfn: %#lx\n", __func__, max_low_pfn); + + /* + * Find an area to use for the bootmem bitmap. + * We look for the first area which is at least + * 128kB in length (128kB is enough for a bitmap + * for 4GB of memory, using 4kB pages), plus 1 page + * (in case the address isn't page-aligned). + */ + map_size = init_bootmem_node(NODE_DATA(0), PFN_UP(TOPHYS((u32)_end)), + min_low_pfn, max_low_pfn); + + lmb_reserve(PFN_UP(TOPHYS((u32)_end)) << PAGE_SHIFT, map_size); + + /* free bootmem is whole main memory */ + free_bootmem(memory_start, memory_size); + + /* reserve allocate blocks */ + for (i = 0; i < lmb.reserved.cnt; i++) { + pr_debug("reserved %d - 0x%08x-0x%08x\n", i, + (u32) lmb.reserved.region[i].base, + (u32) lmb_size_bytes(&lmb.reserved, i)); + reserve_bootmem(lmb.reserved.region[i].base, + lmb_size_bytes(&lmb.reserved, i) - 1, BOOTMEM_DEFAULT); + } + paging_init(); +} + +void free_init_pages(char *what, unsigned long begin, unsigned long end) +{ + unsigned long addr; + + for (addr = begin; addr < end; addr += PAGE_SIZE) { + ClearPageReserved(virt_to_page(addr)); + init_page_count(virt_to_page(addr)); + memset((void *)addr, 0xcc, PAGE_SIZE); + free_page(addr); + totalram_pages++; + } + printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10); +} + +#ifdef CONFIG_BLK_DEV_INITRD +void free_initrd_mem(unsigned long start, unsigned long end) +{ + int pages = 0; + for (; start < end; start += PAGE_SIZE) { + ClearPageReserved(virt_to_page(start)); + init_page_count(virt_to_page(start)); + free_page(start); + totalram_pages++; + pages++; + } + printk(KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages); +} +#endif + +void free_initmem(void) +{ + free_init_pages("unused kernel memory", + (unsigned long)(&__init_begin), + (unsigned long)(&__init_end)); +} + +/* FIXME from arch/powerpc/mm/mem.c*/ +void show_mem(void) +{ + printk(KERN_NOTICE "%s\n", __func__); +} + +void __init mem_init(void) +{ + high_memory = (void *)__va(memory_end); + /* this will put all memory onto the freelists */ + totalram_pages += free_all_bootmem(); + + printk(KERN_INFO "Memory: %luk/%luk available\n", + (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), + num_physpages << (PAGE_SHIFT-10)); +} + +/* Check against bounds of physical memory */ +int ___range_ok(unsigned long addr, unsigned long size) +{ + return ((addr < memory_start) || + ((addr + size) > memory_end)); +} diff --git a/arch/microblaze/platform/Kconfig.platform b/arch/microblaze/platform/Kconfig.platform new file mode 100644 index 00000000000..8e9b4752d3f --- /dev/null +++ b/arch/microblaze/platform/Kconfig.platform @@ -0,0 +1,85 @@ +# For a description of the syntax of this configuration file, +# see Documentation/kbuild/kconfig-language.txt. +# +# Platform selection Kconfig menu for MicroBlaze targets +# + +menu "Platform options" +choice + prompt "Platform" + default PLATFORM_MICROBLAZE_AUTO + help + Choose which hardware board/platform you are targeting. + +config PLATFORM_GENERIC + bool "Generic" + help + Choose this option for the Generic platform. + +endchoice + +config SELFMOD + bool "Use self modified code for intc/timer" + depends on EXPERIMENTAL && NO_MMU + default n + help + This choice enables self-modified code for interrupt controller + and timer. + +config SELFMOD_INTC + bool "Use self modified code for intc" + depends on SELFMOD + default y + help + This choice enables self-modified code for interrupt controller. + +config SELFMOD_TIMER + bool "Use self modified code for timer" + depends on SELFMOD + default y + help + This choice enables self-modified code for timer. + +config OPT_LIB_FUNCTION + bool "Optimalized lib function" + default y + help + Allows turn on optimalized library function (memcpy and memmove). + They are optimized by using word alignment. This will work + fine if both source and destination are aligned on the same + boundary. However, if they are aligned on different boundaries + shifts will be necessary. This might result in bad performance + on MicroBlaze systems without a barrel shifter. + +config OPT_LIB_ASM + bool "Optimalized lib function ASM" + depends on OPT_LIB_FUNCTION + default n + help + Allows turn on optimalized library function (memcpy and memmove). + Function are written in asm code. + +# This is still a bit broken - disabling for now JW 20070504 +config ALLOW_EDIT_AUTO + bool "Permit Display/edit of Kconfig.auto platform settings" + default n + help + Allows the editing of auto-generated platform settings from + the Kconfig.auto file. Obviously this does not change the + underlying hardware, so be very careful if you go editing + these settings. + + Also, if you enable this, and edit various Kconfig.auto + settings, YOUR CHANGES WILL BE LOST if you then disable it + again. You have been warned! + + If unsure, say no. + +comment "Automatic platform settings from Kconfig.auto" + depends on ALLOW_EDIT_AUTO + +if PLATFORM_GENERIC=y + source "arch/microblaze/platform/generic/Kconfig.auto" +endif + +endmenu diff --git a/arch/microblaze/platform/Makefile b/arch/microblaze/platform/Makefile new file mode 100644 index 00000000000..ea1b75cc577 --- /dev/null +++ b/arch/microblaze/platform/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for arch/microblaze/platform directory +# +#obj-$(CONFIG_PLATFORM_GENERIC) += generic/ + +obj-y += platform.o diff --git a/arch/microblaze/platform/generic/Kconfig.auto b/arch/microblaze/platform/generic/Kconfig.auto new file mode 100644 index 00000000000..fbca22d9c8b --- /dev/null +++ b/arch/microblaze/platform/generic/Kconfig.auto @@ -0,0 +1,62 @@ +# +# (C) Copyright 2007 Michal Simek +# +# Michal SIMEK <monstr@monstr.eu> +# +# 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 +# + +# Definitions for MICROBLAZE0 +comment "Definitions for MICROBLAZE0" + depends on ALLOW_EDIT_AUTO + +config KERNEL_BASE_ADDR + hex "Physical address where Linux Kernel is" + default "0x90000000" + help + BASE Address for kernel + +config XILINX_MICROBLAZE0_FAMILY + string "Targetted FPGA family" if ALLOW_EDIT_AUTO + default "virtex5" + +config XILINX_MICROBLAZE0_USE_MSR_INSTR + int "USE_MSR_INSTR range (0:1)" if ALLOW_EDIT_AUTO + default 1 + +config XILINX_MICROBLAZE0_USE_PCMP_INSTR + int "USE_PCMP_INSTR range (0:1)" if ALLOW_EDIT_AUTO + default 1 + +config XILINX_MICROBLAZE0_USE_BARREL + int "USE_BARREL range (0:1)" if ALLOW_EDIT_AUTO + default 1 + +config XILINX_MICROBLAZE0_USE_DIV + int "USE_DIV range (0:1)" if ALLOW_EDIT_AUTO + default 1 + +config XILINX_MICROBLAZE0_USE_HW_MUL + int "USE_HW_MUL values (0=NONE, 1=MUL32, 2=MUL64)" if ALLOW_EDIT_AUTO + default 2 + +config XILINX_MICROBLAZE0_USE_FPU + int "USE_FPU values (0=NONE, 1=BASIC, 2=EXTENDED)" if ALLOW_EDIT_AUTO + default 2 + +config XILINX_MICROBLAZE0_HW_VER + string "Core version number" if ALLOW_EDIT_AUTO + default 7.10.d diff --git a/arch/microblaze/platform/generic/Makefile b/arch/microblaze/platform/generic/Makefile new file mode 100644 index 00000000000..9a8b1bd3fa6 --- /dev/null +++ b/arch/microblaze/platform/generic/Makefile @@ -0,0 +1,3 @@ +# +# Empty Makefile to keep make clean happy +# diff --git a/arch/microblaze/platform/generic/system.dts b/arch/microblaze/platform/generic/system.dts new file mode 100644 index 00000000000..29993f62b30 --- /dev/null +++ b/arch/microblaze/platform/generic/system.dts @@ -0,0 +1,332 @@ +/* + * Device Tree Generator version: 1.1 + * + * (C) Copyright 2007-2008 Xilinx, Inc. + * (C) Copyright 2007-2009 Michal Simek + * + * Michal SIMEK <monstr@monstr.eu> + * + * 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 + * + * CAUTION: This file is automatically generated by libgen. + * Version: Xilinx EDK 10.1.03 EDK_K_SP3.6 + * + * XPS project directory: Xilinx-ML505-ll_temac-sgdma-MMU-FDT-edk101 + */ + +/dts-v1/; +/ { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,microblaze"; + model = "testing"; + DDR2_SDRAM: memory@90000000 { + device_type = "memory"; + reg = < 0x90000000 0x10000000 >; + } ; + chosen { + bootargs = "console=ttyUL0,115200 highres=on"; + linux,stdout-path = "/plb@0/serial@84000000"; + } ; + cpus { + #address-cells = <1>; + #cpus = <0x1>; + #size-cells = <0>; + microblaze_0: cpu@0 { + clock-frequency = <125000000>; + compatible = "xlnx,microblaze-7.10.d"; + d-cache-baseaddr = <0x90000000>; + d-cache-highaddr = <0x9fffffff>; + d-cache-line-size = <0x10>; + d-cache-size = <0x2000>; + device_type = "cpu"; + i-cache-baseaddr = <0x90000000>; + i-cache-highaddr = <0x9fffffff>; + i-cache-line-size = <0x10>; + i-cache-size = <0x2000>; + model = "microblaze,7.10.d"; + reg = <0>; + timebase-frequency = <125000000>; + xlnx,addr-tag-bits = <0xf>; + xlnx,allow-dcache-wr = <0x1>; + xlnx,allow-icache-wr = <0x1>; + xlnx,area-optimized = <0x0>; + xlnx,cache-byte-size = <0x2000>; + xlnx,d-lmb = <0x1>; + xlnx,d-opb = <0x0>; + xlnx,d-plb = <0x1>; + xlnx,data-size = <0x20>; + xlnx,dcache-addr-tag = <0xf>; + xlnx,dcache-always-used = <0x1>; + xlnx,dcache-byte-size = <0x2000>; + xlnx,dcache-line-len = <0x4>; + xlnx,dcache-use-fsl = <0x1>; + xlnx,debug-enabled = <0x1>; + xlnx,div-zero-exception = <0x1>; + xlnx,dopb-bus-exception = <0x0>; + xlnx,dynamic-bus-sizing = <0x1>; + xlnx,edge-is-positive = <0x1>; + xlnx,family = "virtex5"; + xlnx,fpu-exception = <0x1>; + xlnx,fsl-data-size = <0x20>; + xlnx,fsl-exception = <0x0>; + xlnx,fsl-links = <0x0>; + xlnx,i-lmb = <0x1>; + xlnx,i-opb = <0x0>; + xlnx,i-plb = <0x1>; + xlnx,icache-always-used = <0x1>; + xlnx,icache-line-len = <0x4>; + xlnx,icache-use-fsl = <0x1>; + xlnx,ill-opcode-exception = <0x1>; + xlnx,instance = "microblaze_0"; + xlnx,interconnect = <0x1>; + xlnx,interrupt-is-edge = <0x0>; + xlnx,iopb-bus-exception = <0x0>; + xlnx,mmu-dtlb-size = <0x4>; + xlnx,mmu-itlb-size = <0x2>; + xlnx,mmu-tlb-access = <0x3>; + xlnx,mmu-zones = <0x10>; + xlnx,number-of-pc-brk = <0x1>; + xlnx,number-of-rd-addr-brk = <0x0>; + xlnx,number-of-wr-addr-brk = <0x0>; + xlnx,opcode-0x0-illegal = <0x1>; + xlnx,pvr = <0x2>; + xlnx,pvr-user1 = <0x0>; + xlnx,pvr-user2 = <0x0>; + xlnx,reset-msr = <0x0>; + xlnx,sco = <0x0>; + xlnx,unaligned-exceptions = <0x1>; + xlnx,use-barrel = <0x1>; + xlnx,use-dcache = <0x1>; + xlnx,use-div = <0x1>; + xlnx,use-ext-brk = <0x1>; + xlnx,use-ext-nm-brk = <0x1>; + xlnx,use-extended-fsl-instr = <0x0>; + xlnx,use-fpu = <0x2>; + xlnx,use-hw-mul = <0x2>; + xlnx,use-icache = <0x1>; + xlnx,use-interrupt = <0x1>; + xlnx,use-mmu = <0x3>; + xlnx,use-msr-instr = <0x1>; + xlnx,use-pcmp-instr = <0x1>; + } ; + } ; + mb_plb: plb@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,plb-v46-1.03.a", "simple-bus"; + ranges ; + FLASH: flash@a0000000 { + bank-width = <2>; + compatible = "xlnx,xps-mch-emc-2.00.a", "cfi-flash"; + reg = < 0xa0000000 0x2000000 >; + xlnx,family = "virtex5"; + xlnx,include-datawidth-matching-0 = <0x1>; + xlnx,include-datawidth-matching-1 = <0x0>; + xlnx,include-datawidth-matching-2 = <0x0>; + xlnx,include-datawidth-matching-3 = <0x0>; + xlnx,include-negedge-ioregs = <0x0>; + xlnx,include-plb-ipif = <0x1>; + xlnx,include-wrbuf = <0x1>; + xlnx,max-mem-width = <0x10>; + xlnx,mch-native-dwidth = <0x20>; + xlnx,mch-plb-clk-period-ps = <0x1f40>; + xlnx,mch-splb-awidth = <0x20>; + xlnx,mch0-accessbuf-depth = <0x10>; + xlnx,mch0-protocol = <0x0>; + xlnx,mch0-rddatabuf-depth = <0x10>; + xlnx,mch1-accessbuf-depth = <0x10>; + xlnx,mch1-protocol = <0x0>; + xlnx,mch1-rddatabuf-depth = <0x10>; + xlnx,mch2-accessbuf-depth = <0x10>; + xlnx,mch2-protocol = <0x0>; + xlnx,mch2-rddatabuf-depth = <0x10>; + xlnx,mch3-accessbuf-depth = <0x10>; + xlnx,mch3-protocol = <0x0>; + xlnx,mch3-rddatabuf-depth = <0x10>; + xlnx,mem0-width = <0x10>; + xlnx,mem1-width = <0x20>; + xlnx,mem2-width = <0x20>; + xlnx,mem3-width = <0x20>; + xlnx,num-banks-mem = <0x1>; + xlnx,num-channels = <0x0>; + xlnx,priority-mode = <0x0>; + xlnx,synch-mem-0 = <0x0>; + xlnx,synch-mem-1 = <0x0>; + xlnx,synch-mem-2 = <0x0>; + xlnx,synch-mem-3 = <0x0>; + xlnx,synch-pipedelay-0 = <0x2>; + xlnx,synch-pipedelay-1 = <0x2>; + xlnx,synch-pipedelay-2 = <0x2>; + xlnx,synch-pipedelay-3 = <0x2>; + xlnx,tavdv-ps-mem-0 = <0x1adb0>; + xlnx,tavdv-ps-mem-1 = <0x3a98>; + xlnx,tavdv-ps-mem-2 = <0x3a98>; + xlnx,tavdv-ps-mem-3 = <0x3a98>; + xlnx,tcedv-ps-mem-0 = <0x1adb0>; + xlnx,tcedv-ps-mem-1 = <0x3a98>; + xlnx,tcedv-ps-mem-2 = <0x3a98>; + xlnx,tcedv-ps-mem-3 = <0x3a98>; + xlnx,thzce-ps-mem-0 = <0x88b8>; + xlnx,thzce-ps-mem-1 = <0x1b58>; + xlnx,thzce-ps-mem-2 = <0x1b58>; + xlnx,thzce-ps-mem-3 = <0x1b58>; + xlnx,thzoe-ps-mem-0 = <0x1b58>; + xlnx,thzoe-ps-mem-1 = <0x1b58>; + xlnx,thzoe-ps-mem-2 = <0x1b58>; + xlnx,thzoe-ps-mem-3 = <0x1b58>; + xlnx,tlzwe-ps-mem-0 = <0x88b8>; + xlnx,tlzwe-ps-mem-1 = <0x0>; + xlnx,tlzwe-ps-mem-2 = <0x0>; + xlnx,tlzwe-ps-mem-3 = <0x0>; + xlnx,twc-ps-mem-0 = <0x2af8>; + xlnx,twc-ps-mem-1 = <0x3a98>; + xlnx,twc-ps-mem-2 = <0x3a98>; + xlnx,twc-ps-mem-3 = <0x3a98>; + xlnx,twp-ps-mem-0 = <0x11170>; + xlnx,twp-ps-mem-1 = <0x2ee0>; + xlnx,twp-ps-mem-2 = <0x2ee0>; + xlnx,twp-ps-mem-3 = <0x2ee0>; + xlnx,xcl0-linesize = <0x4>; + xlnx,xcl0-writexfer = <0x1>; + xlnx,xcl1-linesize = <0x4>; + xlnx,xcl1-writexfer = <0x1>; + xlnx,xcl2-linesize = <0x4>; + xlnx,xcl2-writexfer = <0x1>; + xlnx,xcl3-linesize = <0x4>; + xlnx,xcl3-writexfer = <0x1>; + } ; + Hard_Ethernet_MAC: xps-ll-temac@81c00000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,compound"; + ethernet@81c00000 { + compatible = "xlnx,xps-ll-temac-1.01.b"; + device_type = "network"; + interrupt-parent = <&xps_intc_0>; + interrupts = < 5 2 >; + llink-connected = <&PIM3>; + local-mac-address = [ 02 00 00 00 00 00 ]; + reg = < 0x81c00000 0x40 >; + xlnx,bus2core-clk-ratio = <0x1>; + xlnx,phy-type = <0x1>; + xlnx,phyaddr = <0x1>; + xlnx,rxcsum = <0x0>; + xlnx,rxfifo = <0x1000>; + xlnx,temac-type = <0x0>; + xlnx,txcsum = <0x0>; + xlnx,txfifo = <0x1000>; + } ; + } ; + IIC_EEPROM: i2c@81600000 { + compatible = "xlnx,xps-iic-2.00.a"; + interrupt-parent = <&xps_intc_0>; + interrupts = < 6 2 >; + reg = < 0x81600000 0x10000 >; + xlnx,clk-freq = <0x7735940>; + xlnx,family = "virtex5"; + xlnx,gpo-width = <0x1>; + xlnx,iic-freq = <0x186a0>; + xlnx,scl-inertial-delay = <0x0>; + xlnx,sda-inertial-delay = <0x0>; + xlnx,ten-bit-adr = <0x0>; + } ; + LEDs_8Bit: gpio@81400000 { + compatible = "xlnx,xps-gpio-1.00.a"; + interrupt-parent = <&xps_intc_0>; + interrupts = < 7 2 >; + reg = < 0x81400000 0x10000 >; + xlnx,all-inputs = <0x0>; + xlnx,all-inputs-2 = <0x0>; + xlnx,dout-default = <0x0>; + xlnx,dout-default-2 = <0x0>; + xlnx,family = "virtex5"; + xlnx,gpio-width = <0x8>; + xlnx,interrupt-present = <0x1>; + xlnx,is-bidir = <0x1>; + xlnx,is-bidir-2 = <0x1>; + xlnx,is-dual = <0x0>; + xlnx,tri-default = <0xffffffff>; + xlnx,tri-default-2 = <0xffffffff>; + } ; + RS232_Uart_1: serial@84000000 { + clock-frequency = <125000000>; + compatible = "xlnx,xps-uartlite-1.00.a"; + current-speed = <115200>; + device_type = "serial"; + interrupt-parent = <&xps_intc_0>; + interrupts = < 8 0 >; + port-number = <0>; + reg = < 0x84000000 0x10000 >; + xlnx,baudrate = <0x1c200>; + xlnx,data-bits = <0x8>; + xlnx,family = "virtex5"; + xlnx,odd-parity = <0x0>; + xlnx,use-parity = <0x0>; + } ; + SysACE_CompactFlash: sysace@83600000 { + compatible = "xlnx,xps-sysace-1.00.a"; + interrupt-parent = <&xps_intc_0>; + interrupts = < 4 2 >; + reg = < 0x83600000 0x10000 >; + xlnx,family = "virtex5"; + xlnx,mem-width = <0x10>; + } ; + debug_module: debug@84400000 { + compatible = "xlnx,mdm-1.00.d"; + reg = < 0x84400000 0x10000 >; + xlnx,family = "virtex5"; + xlnx,interconnect = <0x1>; + xlnx,jtag-chain = <0x2>; + xlnx,mb-dbg-ports = <0x1>; + xlnx,uart-width = <0x8>; + xlnx,use-uart = <0x1>; + xlnx,write-fsl-ports = <0x0>; + } ; + mpmc@90000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "xlnx,mpmc-4.02.a"; + PIM3: sdma@84600180 { + compatible = "xlnx,ll-dma-1.00.a"; + interrupt-parent = <&xps_intc_0>; + interrupts = < 2 2 1 2 >; + reg = < 0x84600180 0x80 >; + } ; + } ; + xps_intc_0: interrupt-controller@81800000 { + #interrupt-cells = <0x2>; + compatible = "xlnx,xps-intc-1.00.a"; + interrupt-controller ; + reg = < 0x81800000 0x10000 >; + xlnx,kind-of-intr = <0x100>; + xlnx,num-intr-inputs = <0x9>; + } ; + xps_timer_1: timer@83c00000 { + compatible = "xlnx,xps-timer-1.00.a"; + interrupt-parent = <&xps_intc_0>; + interrupts = < 3 2 >; + reg = < 0x83c00000 0x10000 >; + xlnx,count-width = <0x20>; + xlnx,family = "virtex5"; + xlnx,gen0-assert = <0x1>; + xlnx,gen1-assert = <0x1>; + xlnx,one-timer-only = <0x0>; + xlnx,trig0-assert = <0x1>; + xlnx,trig1-assert = <0x1>; + } ; + } ; +} ; diff --git a/arch/microblaze/platform/platform.c b/arch/microblaze/platform/platform.c new file mode 100644 index 00000000000..56e0234fa34 --- /dev/null +++ b/arch/microblaze/platform/platform.c @@ -0,0 +1,31 @@ +/* + * Copyright 2008 Michal Simek <monstr@monstr.eu> + * + * based on virtex.c file + * + * Copyright 2007 Secret Lab Technologies Ltd. + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/init.h> +#include <linux/of_platform.h> +#include <asm/prom.h> + +static struct of_device_id xilinx_of_bus_ids[] __initdata = { + { .compatible = "simple-bus", }, + { .compatible = "xlnx,plb-v46-1.00.a", }, + { .compatible = "xlnx,opb-v20-1.10.c", }, + { .compatible = "xlnx,opb-v20-1.10.b", }, + { .compatible = "xlnx,compound", }, + {} +}; + +static int __init microblaze_device_probe(void) +{ + of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL); + return 0; +} +device_initcall(microblaze_device_probe); diff --git a/arch/mips/include/asm/mach-rc32434/gpio.h b/arch/mips/include/asm/mach-rc32434/gpio.h index 3cb50d17b62..12ee8d51016 100644 --- a/arch/mips/include/asm/mach-rc32434/gpio.h +++ b/arch/mips/include/asm/mach-rc32434/gpio.h @@ -80,6 +80,9 @@ struct rb532_gpio_reg { /* Compact Flash GPIO pin */ #define CF_GPIO_NUM 13 +/* S1 button GPIO (shared with UART0_SIN) */ +#define GPIO_BTN_S1 1 + extern void rb532_gpio_set_ilevel(int bit, unsigned gpio); extern void rb532_gpio_set_istat(int bit, unsigned gpio); extern void rb532_gpio_set_func(unsigned gpio); diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index 4a5f05b662a..9f40e1ff9b4 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -200,26 +200,9 @@ static struct platform_device rb532_led = { .id = -1, }; -static struct gpio_keys_button rb532_gpio_btn[] = { - { - .gpio = 1, - .code = BTN_0, - .desc = "S1", - .active_low = 1, - } -}; - -static struct gpio_keys_platform_data rb532_gpio_btn_data = { - .buttons = rb532_gpio_btn, - .nbuttons = ARRAY_SIZE(rb532_gpio_btn), -}; - static struct platform_device rb532_button = { - .name = "gpio-keys", + .name = "rb532-button", .id = -1, - .dev = { - .platform_data = &rb532_gpio_btn_data, - } }; static struct resource rb532_wdt_res[] = { diff --git a/arch/powerpc/include/asm/parport.h b/arch/powerpc/include/asm/parport.h index 414c50e2e88..94942d60ddf 100644 --- a/arch/powerpc/include/asm/parport.h +++ b/arch/powerpc/include/asm/parport.h @@ -29,7 +29,7 @@ static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma) prop = of_get_property(np, "interrupts", NULL); if (!prop) continue; - if (parport_pc_probe_port(io1, io2, prop[0], autodma, NULL) != NULL) + if (parport_pc_probe_port(io1, io2, prop[0], autodma, NULL, 0) != NULL) count++; } return count; diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index dcb667c4375..2eca5fe0e75 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -82,6 +82,7 @@ config S390 select USE_GENERIC_SMP_HELPERS if SMP select HAVE_SYSCALL_WRAPPERS select HAVE_FUNCTION_TRACER + select HAVE_DEFAULT_NO_SPIN_MUTEXES select HAVE_OPROFILE select HAVE_KPROBES select HAVE_KRETPROBES diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 5e4babecf93..e7390dd0283 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -14,6 +14,7 @@ config SUPERH select HAVE_GENERIC_DMA_COHERENT select HAVE_IOREMAP_PROT if MMU select HAVE_ARCH_TRACEHOOK + select HAVE_DMA_API_DEBUG help The SuperH is a RISC processor targeted for use in embedded systems and consumer electronics; it was also used in the Sega Dreamcast @@ -21,7 +22,7 @@ config SUPERH <http://www.linux-sh.org/>. config SUPERH32 - def_bool !SUPERH64 + def_bool ARCH = "sh" select HAVE_KPROBES select HAVE_KRETPROBES select HAVE_FUNCTION_TRACER @@ -31,7 +32,7 @@ config SUPERH32 select ARCH_HIBERNATION_POSSIBLE if MMU config SUPERH64 - def_bool y if CPU_SH5 + def_bool ARCH = "sh64" config ARCH_DEFCONFIG string @@ -187,6 +188,8 @@ config ARCH_SHMOBILE bool select ARCH_SUSPEND_POSSIBLE +if SUPERH32 + choice prompt "Processor sub-type selection" @@ -408,6 +411,15 @@ config CPU_SUBTYPE_SH7366 select SYS_SUPPORTS_NUMA select SYS_SUPPORTS_CMT +endchoice + +endif + +if SUPERH64 + +choice + prompt "Processor sub-type selection" + # SH-5 Processor Support config CPU_SUBTYPE_SH5_101 @@ -420,6 +432,8 @@ config CPU_SUBTYPE_SH5_103 endchoice +endif + source "arch/sh/mm/Kconfig" source "arch/sh/Kconfig.cpu" diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c index 912458f666e..39e46919df1 100644 --- a/arch/sh/boards/board-ap325rxa.c +++ b/arch/sh/boards/board-ap325rxa.c @@ -349,6 +349,7 @@ static int ov7725_power(struct device *dev, int mode) static struct ov772x_camera_info ov7725_info = { .buswidth = SOCAM_DATAWIDTH_8, .flags = OV772X_FLAG_VFLIP | OV772X_FLAG_HFLIP, + .edgectrl = OV772X_AUTO_EDGECTRL(0xf, 0), .link = { .power = ov7725_power, }, diff --git a/arch/sh/boards/board-urquell.c b/arch/sh/boards/board-urquell.c index 8367d1d789c..beb88c4da2c 100644 --- a/arch/sh/boards/board-urquell.c +++ b/arch/sh/boards/board-urquell.c @@ -2,6 +2,8 @@ * Renesas Technology Corp. SH7786 Urquell Support. * * Copyright (C) 2008 Kuninori Morimoto <morimoto.kuninori@renesas.com> + * + * Based on board-sh7785lcr.c * Copyright (C) 2008 Yoshihiro Shimoda * * This file is subject to the terms and conditions of the GNU General Public @@ -21,6 +23,32 @@ #include <asm/heartbeat.h> #include <asm/sizes.h> +/* + * bit 1234 5678 + *---------------------------- + * SW1 0101 0010 -> Pck 33MHz version + * (1101 0010) Pck 66MHz version + * SW2 0x1x xxxx -> little endian + * 29bit mode + * SW47 0001 1000 -> CS0 : on-board flash + * CS1 : SRAM, registers, LAN, PCMCIA + * 38400 bps for SCIF1 + * + * Address + * 0x00000000 - 0x04000000 (CS0) Nor Flash + * 0x04000000 - 0x04200000 (CS1) SRAM + * 0x05000000 - 0x05800000 (CS1) on board register + * 0x05800000 - 0x06000000 (CS1) LAN91C111 + * 0x06000000 - 0x06400000 (CS1) PCMCIA + * 0x08000000 - 0x10000000 (CS2-CS3) DDR3 + * 0x10000000 - 0x14000000 (CS4) PCIe + * 0x14000000 - 0x14800000 (CS5) Core0 LRAM/URAM + * 0x14800000 - 0x15000000 (CS5) Core1 LRAM/URAM + * 0x18000000 - 0x1C000000 (CS6) ATA/NAND-Flash + * 0x1C000000 - (CS7) SH7786 Control register + */ + +/* HeartBeat */ static struct resource heartbeat_resources[] = { [0] = { .start = BOARDREG(SLEDR), @@ -43,6 +71,7 @@ static struct platform_device heartbeat_device = { .resource = heartbeat_resources, }; +/* LAN91C111 */ static struct smc91x_platdata smc91x_info = { .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, }; @@ -69,6 +98,7 @@ static struct platform_device smc91x_eth_device = { }, }; +/* Nor Flash */ static struct mtd_partition nor_flash_partitions[] = { { .name = "loader", diff --git a/arch/sh/drivers/pci/ops-sh7785lcr.c b/arch/sh/drivers/pci/ops-sh7785lcr.c index e8b7446a7c2..fb0869f0bef 100644 --- a/arch/sh/drivers/pci/ops-sh7785lcr.c +++ b/arch/sh/drivers/pci/ops-sh7785lcr.c @@ -48,8 +48,13 @@ EXPORT_SYMBOL(board_pci_channels); static struct sh4_pci_address_map sh7785_pci_map = { .window0 = { +#if defined(CONFIG_32BIT) + .base = SH7780_32BIT_DDR_BASE_ADDR, + .size = 0x40000000, +#else .base = SH7780_CS0_BASE_ADDR, .size = 0x20000000, +#endif }, .flags = SH4_PCIC_NO_RESET, diff --git a/arch/sh/drivers/pci/pci-sh7780.h b/arch/sh/drivers/pci/pci-sh7780.h index 97b2c98f05c..93adc7119b7 100644 --- a/arch/sh/drivers/pci/pci-sh7780.h +++ b/arch/sh/drivers/pci/pci-sh7780.h @@ -104,6 +104,8 @@ #define SH7780_CS5_BASE_ADDR (SH7780_CS4_BASE_ADDR + SH7780_MEM_REGION_SIZE) #define SH7780_CS6_BASE_ADDR (SH7780_CS5_BASE_ADDR + SH7780_MEM_REGION_SIZE) +#define SH7780_32BIT_DDR_BASE_ADDR 0x40000000 + struct sh4_pci_address_map; /* arch/sh/drivers/pci/pci-sh7780.c */ diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index e36c7b87086..0d6ac7a1db4 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -19,6 +19,7 @@ #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> +#include <linux/dma-debug.h> #include <asm/io.h> static int __init pcibios_init(void) @@ -43,6 +44,8 @@ static int __init pcibios_init(void) pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq); + dma_debug_add_bus(&pci_bus_type); + return 0; } subsys_initcall(pcibios_init); diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h index 627315ecdb5..ea9d4f41c9d 100644 --- a/arch/sh/include/asm/dma-mapping.h +++ b/arch/sh/include/asm/dma-mapping.h @@ -3,6 +3,7 @@ #include <linux/mm.h> #include <linux/scatterlist.h> +#include <linux/dma-debug.h> #include <asm/cacheflush.h> #include <asm/io.h> #include <asm-generic/dma-coherent.h> @@ -38,16 +39,26 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction dir) { + dma_addr_t addr = virt_to_phys(ptr); + #if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) if (dev->bus == &pci_bus_type) - return virt_to_phys(ptr); + return addr; #endif dma_cache_sync(dev, ptr, size, dir); - return virt_to_phys(ptr); + debug_dma_map_page(dev, virt_to_page(ptr), + (unsigned long)ptr & ~PAGE_MASK, size, + dir, addr, true); + + return addr; } -#define dma_unmap_single(dev, addr, size, dir) do { } while (0) +static inline void dma_unmap_single(struct device *dev, dma_addr_t addr, + size_t size, enum dma_data_direction dir) +{ + debug_dma_unmap_page(dev, addr, size, dir, true); +} static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction dir) @@ -59,12 +70,19 @@ static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir); #endif sg[i].dma_address = sg_phys(&sg[i]); + sg[i].dma_length = sg[i].length; } + debug_dma_map_sg(dev, sg, nents, i, dir); + return nents; } -#define dma_unmap_sg(dev, sg, nents, dir) do { } while (0) +static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, enum dma_data_direction dir) +{ + debug_dma_unmap_sg(dev, sg, nents, dir); +} static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, size_t size, @@ -111,6 +129,7 @@ static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg, dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir); #endif sg[i].dma_address = sg_phys(&sg[i]); + sg[i].dma_length = sg[i].length; } } @@ -119,6 +138,7 @@ static inline void dma_sync_single_for_cpu(struct device *dev, enum dma_data_direction dir) { dma_sync_single(dev, dma_handle, size, dir); + debug_dma_sync_single_for_cpu(dev, dma_handle, size, dir); } static inline void dma_sync_single_for_device(struct device *dev, @@ -127,6 +147,7 @@ static inline void dma_sync_single_for_device(struct device *dev, enum dma_data_direction dir) { dma_sync_single(dev, dma_handle, size, dir); + debug_dma_sync_single_for_device(dev, dma_handle, size, dir); } static inline void dma_sync_single_range_for_cpu(struct device *dev, @@ -136,6 +157,8 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev, enum dma_data_direction direction) { dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction); + debug_dma_sync_single_range_for_cpu(dev, dma_handle, + offset, size, direction); } static inline void dma_sync_single_range_for_device(struct device *dev, @@ -145,6 +168,8 @@ static inline void dma_sync_single_range_for_device(struct device *dev, enum dma_data_direction direction) { dma_sync_single_for_device(dev, dma_handle+offset, size, direction); + debug_dma_sync_single_range_for_device(dev, dma_handle, + offset, size, direction); } @@ -153,6 +178,7 @@ static inline void dma_sync_sg_for_cpu(struct device *dev, enum dma_data_direction dir) { dma_sync_sg(dev, sg, nelems, dir); + debug_dma_sync_sg_for_cpu(dev, sg, nelems, dir); } static inline void dma_sync_sg_for_device(struct device *dev, @@ -160,9 +186,9 @@ static inline void dma_sync_sg_for_device(struct device *dev, enum dma_data_direction dir) { dma_sync_sg(dev, sg, nelems, dir); + debug_dma_sync_sg_for_device(dev, sg, nelems, dir); } - static inline int dma_get_cache_alignment(void) { /* diff --git a/arch/sh/include/asm/scatterlist.h b/arch/sh/include/asm/scatterlist.h index 2084d037369..c693d268a41 100644 --- a/arch/sh/include/asm/scatterlist.h +++ b/arch/sh/include/asm/scatterlist.h @@ -5,12 +5,13 @@ struct scatterlist { #ifdef CONFIG_DEBUG_SG - unsigned long sg_magic; + unsigned long sg_magic; #endif - unsigned long page_link; - unsigned int offset;/* for highmem, page offset */ - dma_addr_t dma_address; - unsigned int length; + unsigned long page_link; + unsigned int offset; /* for highmem, page offset */ + unsigned int length; + dma_addr_t dma_address; + unsigned int dma_length; }; #define ISA_DMA_THRESHOLD PHYS_ADDR_MASK diff --git a/arch/sh/include/asm/topology.h b/arch/sh/include/asm/topology.h index a3f23954589..8489a0905a8 100644 --- a/arch/sh/include/asm/topology.h +++ b/arch/sh/include/asm/topology.h @@ -37,8 +37,11 @@ #define pcibus_to_node(bus) ((void)(bus), -1) #define pcibus_to_cpumask(bus) (pcibus_to_node(bus) == -1 ? \ CPU_MASK_ALL : \ - node_to_cpumask(pcibus_to_node(bus)) \ - ) + node_to_cpumask(pcibus_to_node(bus))) +#define cpumask_of_pcibus(bus) (pcibus_to_node(bus) == -1 ? \ + CPU_MASK_ALL_PTR : \ + cpumask_of_node(pcibus_to_node(bus))) + #endif #include <asm-generic/topology.h> diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h index d52c000cf92..2efb819e2db 100644 --- a/arch/sh/include/asm/unistd_32.h +++ b/arch/sh/include/asm/unistd_32.h @@ -341,8 +341,10 @@ #define __NR_dup3 330 #define __NR_pipe2 331 #define __NR_inotify_init1 332 +#define __NR_preadv 333 +#define __NR_pwritev 334 -#define NR_syscalls 333 +#define NR_syscalls 335 #ifdef __KERNEL__ diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h index 7c54e91753c..6eb9d2934c0 100644 --- a/arch/sh/include/asm/unistd_64.h +++ b/arch/sh/include/asm/unistd_64.h @@ -381,10 +381,12 @@ #define __NR_dup3 358 #define __NR_pipe2 359 #define __NR_inotify_init1 360 +#define __NR_preadv 361 +#define __NR_pwritev 362 #ifdef __KERNEL__ -#define NR_syscalls 361 +#define NR_syscalls 363 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index 5a47e1cf442..90e8cfff55f 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -143,14 +143,14 @@ static void __init sh7786_usb_setup(void) * Set the PHY and PLL enable bit */ __raw_writel(PHY_ENB | PLL_ENB, USBPCTL1); - while (i-- && - ((__raw_readl(USBST) & ACT_PLL_STATUS) != ACT_PLL_STATUS)) + while (i--) { + if (ACT_PLL_STATUS == (__raw_readl(USBST) & ACT_PLL_STATUS)) { + /* Set the PHY RST bit */ + __raw_writel(PHY_ENB | PLL_ENB | PHY_RST, USBPCTL1); + printk(KERN_INFO "sh7786 usb setup done\n"); + break; + } cpu_relax(); - - if (i) { - /* Set the PHY RST bit */ - __raw_writel(PHY_ENB | PLL_ENB | PHY_RST, USBPCTL1); - printk(KERN_INFO "sh7786 usb setup done\n"); } } diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index e67c1733e1b..05202edd8e2 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S @@ -349,3 +349,5 @@ ENTRY(sys_call_table) .long sys_dup3 /* 330 */ .long sys_pipe2 .long sys_inotify_init1 + .long sys_preadv + .long sys_writev diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 557cb91f5ca..a083609f928 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S @@ -387,3 +387,5 @@ sys_call_table: .long sys_dup3 .long sys_pipe2 .long sys_inotify_init1 /* 360 */ + .long sys_preadv + .long sys_pwritev diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c index edcd5fbf965..e098ec158dd 100644 --- a/arch/sh/mm/consistent.c +++ b/arch/sh/mm/consistent.c @@ -10,11 +10,22 @@ * for more details. */ #include <linux/mm.h> +#include <linux/init.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/dma-debug.h> +#include <linux/io.h> #include <asm/cacheflush.h> #include <asm/addrspace.h> -#include <asm/io.h> + +#define PREALLOC_DMA_DEBUG_ENTRIES 4096 + +static int __init dma_init(void) +{ + dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); + return 0; +} +fs_initcall(dma_init); void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) @@ -45,6 +56,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size, split_page(pfn_to_page(virt_to_phys(ret) >> PAGE_SHIFT), order); *dma_handle = virt_to_phys(ret); + + debug_dma_alloc_coherent(dev, size, *dma_handle, ret_nocache); + return ret_nocache; } EXPORT_SYMBOL(dma_alloc_coherent); @@ -56,12 +70,15 @@ void dma_free_coherent(struct device *dev, size_t size, unsigned long pfn = dma_handle >> PAGE_SHIFT; int k; - if (!dma_release_from_coherent(dev, order, vaddr)) { - WARN_ON(irqs_disabled()); /* for portability */ - for (k = 0; k < (1 << order); k++) - __free_pages(pfn_to_page(pfn + k), 0); - iounmap(vaddr); - } + WARN_ON(irqs_disabled()); /* for portability */ + + if (dma_release_from_coherent(dev, order, vaddr)) + return; + + debug_dma_free_coherent(dev, size, vaddr, dma_handle); + for (k = 0; k < (1 << order); k++) + __free_pages(pfn_to_page(pfn + k), 0); + iounmap(vaddr); } EXPORT_SYMBOL(dma_free_coherent); diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h index dff3f0253aa..ff9ead640c4 100644 --- a/arch/sparc/include/asm/parport.h +++ b/arch/sparc/include/asm/parport.h @@ -117,7 +117,7 @@ static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id if (!strcmp(parent->name, "dma")) { p = parport_pc_probe_port(base, base + 0x400, op->irqs[0], PARPORT_DMA_NOFIFO, - op->dev.parent->parent); + op->dev.parent->parent, 0); if (!p) return -ENOMEM; dev_set_drvdata(&op->dev, p); @@ -168,7 +168,8 @@ static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id p = parport_pc_probe_port(base, base + 0x400, op->irqs[0], slot, - op->dev.parent); + op->dev.parent, + 0); err = -ENOMEM; if (!p) goto out_disable_irq; diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index e5383e3d2f8..73739322b6d 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -193,8 +193,10 @@ extern void __iomem *ioremap_wc(resource_size_t offset, unsigned long size); */ extern void early_ioremap_init(void); extern void early_ioremap_reset(void); -extern void __iomem *early_ioremap(unsigned long offset, unsigned long size); -extern void __iomem *early_memremap(unsigned long offset, unsigned long size); +extern void __iomem *early_ioremap(resource_size_t phys_addr, + unsigned long size); +extern void __iomem *early_memremap(resource_size_t phys_addr, + unsigned long size); extern void early_iounmap(void __iomem *addr, unsigned long size); #define IO_SPACE_LIMIT 0xffff diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 34c52370f2f..fcf4d92e7e0 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -352,6 +352,11 @@ struct i387_soft_struct { u32 entry_eip; }; +struct ymmh_struct { + /* 16 * 16 bytes for each YMMH-reg = 256 bytes */ + u32 ymmh_space[64]; +}; + struct xsave_hdr_struct { u64 xstate_bv; u64 reserved1[2]; @@ -361,6 +366,7 @@ struct xsave_hdr_struct { struct xsave_struct { struct i387_fxsave_struct i387; struct xsave_hdr_struct xsave_hdr; + struct ymmh_struct ymmh; /* new processor state extensions will go here */ } __attribute__ ((packed, aligned (64))); diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h index d5cd6c58688..a4737dddfd5 100644 --- a/arch/x86/include/asm/required-features.h +++ b/arch/x86/include/asm/required-features.h @@ -50,7 +50,7 @@ #ifdef CONFIG_X86_64 #define NEED_PSE 0 #define NEED_MSR (1<<(X86_FEATURE_MSR & 31)) -#define NEED_PGE (1<<(X86_FEATURE_PGE & 31)) +#define NEED_PGE 0 #define NEED_FXSR (1<<(X86_FEATURE_FXSR & 31)) #define NEED_XMM (1<<(X86_FEATURE_XMM & 31)) #define NEED_XMM2 (1<<(X86_FEATURE_XMM2 & 31)) diff --git a/arch/x86/include/asm/sigcontext.h b/arch/x86/include/asm/sigcontext.h index ec666491aaa..72e5a449166 100644 --- a/arch/x86/include/asm/sigcontext.h +++ b/arch/x86/include/asm/sigcontext.h @@ -269,6 +269,11 @@ struct _xsave_hdr { __u64 reserved2[5]; }; +struct _ymmh_state { + /* 16 * 16 bytes for each YMMH-reg */ + __u32 ymmh_space[64]; +}; + /* * Extended state pointed by the fpstate pointer in the sigcontext. * In addition to the fpstate, information encoded in the xstate_hdr @@ -278,6 +283,7 @@ struct _xsave_hdr { struct _xstate { struct _fpstate fpstate; struct _xsave_hdr xstate_hdr; + struct _ymmh_state ymmh; /* new processor state extensions go here */ }; diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index 1a918dde46b..018a0a40079 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h @@ -124,7 +124,8 @@ static inline unsigned long mfn_to_local_pfn(unsigned long mfn) /* VIRT <-> MACHINE conversion */ #define virt_to_machine(v) (phys_to_machine(XPADDR(__pa(v)))) -#define virt_to_mfn(v) (pfn_to_mfn(PFN_DOWN(__pa(v)))) +#define virt_to_pfn(v) (PFN_DOWN(__pa(v))) +#define virt_to_mfn(v) (pfn_to_mfn(virt_to_pfn(v))) #define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) static inline unsigned long pte_mfn(pte_t pte) diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h index 08e9a1ac07a..727acc15234 100644 --- a/arch/x86/include/asm/xsave.h +++ b/arch/x86/include/asm/xsave.h @@ -7,6 +7,7 @@ #define XSTATE_FP 0x1 #define XSTATE_SSE 0x2 +#define XSTATE_YMM 0x4 #define XSTATE_FPSSE (XSTATE_FP | XSTATE_SSE) @@ -15,7 +16,7 @@ /* * These are the features that the OS can handle currently. */ -#define XCNTXT_MASK (XSTATE_FP | XSTATE_SSE) +#define XCNTXT_MASK (XSTATE_FP | XSTATE_SSE | XSTATE_YMM) #ifdef CONFIG_X86_64 #define REX_PREFIX "0x48, " diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 767fe7e46d6..a2789e42e16 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2524,7 +2524,6 @@ static void irq_complete_move(struct irq_desc **descp) static inline void irq_complete_move(struct irq_desc **descp) {} #endif -#ifdef CONFIG_X86_X2APIC static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg) { int apic, pin; @@ -2558,6 +2557,7 @@ eoi_ioapic_irq(struct irq_desc *desc) spin_unlock_irqrestore(&ioapic_lock, flags); } +#ifdef CONFIG_X86_X2APIC static void ack_x2apic_level(unsigned int irq) { struct irq_desc *desc = irq_to_desc(irq); @@ -2634,6 +2634,9 @@ static void ack_apic_level(unsigned int irq) */ ack_APIC_irq(); + if (irq_remapped(irq)) + eoi_ioapic_irq(desc); + /* Now we can move and renable the irq */ if (unlikely(do_unmask_irq)) { /* Only migrate the irq if the ack has been received. diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 9d3af380c6b..837c2c4cc20 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -153,7 +153,8 @@ struct drv_cmd { u32 val; }; -static long do_drv_read(void *_cmd) +/* Called via smp_call_function_single(), on the target CPU */ +static void do_drv_read(void *_cmd) { struct drv_cmd *cmd = _cmd; u32 h; @@ -170,10 +171,10 @@ static long do_drv_read(void *_cmd) default: break; } - return 0; } -static long do_drv_write(void *_cmd) +/* Called via smp_call_function_many(), on the target CPUs */ +static void do_drv_write(void *_cmd) { struct drv_cmd *cmd = _cmd; u32 lo, hi; @@ -192,23 +193,18 @@ static long do_drv_write(void *_cmd) default: break; } - return 0; } static void drv_read(struct drv_cmd *cmd) { cmd->val = 0; - work_on_cpu(cpumask_any(cmd->mask), do_drv_read, cmd); + smp_call_function_single(cpumask_any(cmd->mask), do_drv_read, cmd, 1); } static void drv_write(struct drv_cmd *cmd) { - unsigned int i; - - for_each_cpu(i, cmd->mask) { - work_on_cpu(i, do_drv_write, cmd); - } + smp_call_function_many(cmd->mask, do_drv_write, cmd, 1); } static u32 get_cur_val(const struct cpumask *mask) @@ -252,15 +248,13 @@ struct perf_pair { } aperf, mperf; }; - -static long read_measured_perf_ctrs(void *_cur) +/* Called via smp_call_function_single(), on the target CPU */ +static void read_measured_perf_ctrs(void *_cur) { struct perf_pair *cur = _cur; rdmsr(MSR_IA32_APERF, cur->aperf.split.lo, cur->aperf.split.hi); rdmsr(MSR_IA32_MPERF, cur->mperf.split.lo, cur->mperf.split.hi); - - return 0; } /* @@ -283,7 +277,7 @@ static unsigned int get_measured_perf(struct cpufreq_policy *policy, unsigned int perf_percent; unsigned int retval; - if (!work_on_cpu(cpu, read_measured_perf_ctrs, &readin)) + if (smp_call_function_single(cpu, read_measured_perf_ctrs, &readin, 1)) return 0; cur.aperf.whole = readin.aperf.whole - diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index dce99dca6cf..70fd7e414c1 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -679,7 +679,7 @@ void __init get_smp_config(void) __get_smp_config(0); } -static void smp_reserve_bootmem(struct mpf_intel *mpf) +static void __init smp_reserve_bootmem(struct mpf_intel *mpf) { unsigned long size = get_mpc_size(mpf->physptr); #ifdef CONFIG_X86_32 @@ -838,7 +838,7 @@ static int __init get_MP_intsrc_index(struct mpc_intsrc *m) static struct mpc_intsrc __initdata *m_spare[SPARE_SLOT_NUM]; -static void check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) +static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) { int i; @@ -866,7 +866,8 @@ static void check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) } } #else /* CONFIG_X86_IO_APIC */ -static inline void check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {} +static +inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {} #endif /* CONFIG_X86_IO_APIC */ static int check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 2b54fe002e9..0a5b04aa98f 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -324,7 +324,7 @@ void __ref xsave_cntxt_init(void) } /* - * for now OS knows only about FP/SSE + * Support only the state known to OS. */ pcntxt_mask = pcntxt_mask & XCNTXT_MASK; xsave_init(); diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c index be54176e9eb..6340cef6798 100644 --- a/arch/x86/mm/gup.c +++ b/arch/x86/mm/gup.c @@ -219,6 +219,22 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, return 1; } +/** + * get_user_pages_fast() - pin user pages in memory + * @start: starting user address + * @nr_pages: number of pages from start to pin + * @write: whether pages will be written to + * @pages: array that receives pointers to the pages pinned. + * Should be at least nr_pages long. + * + * Attempt to pin user pages in memory without taking mm->mmap_sem. + * If not successful, it will fall back to taking the lock and + * calling get_user_pages(). + * + * Returns number of pages pinned. This may be fewer than the number + * requested. If nr_pages is 0 or negative, returns 0. If no pages + * were pinned, returns -errno. + */ int get_user_pages_fast(unsigned long start, int nr_pages, int write, struct page **pages) { diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 0dfa09d69e8..09daebfdb11 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -547,7 +547,7 @@ void __init early_ioremap_reset(void) } static void __init __early_set_fixmap(enum fixed_addresses idx, - unsigned long phys, pgprot_t flags) + phys_addr_t phys, pgprot_t flags) { unsigned long addr = __fix_to_virt(idx); pte_t *pte; @@ -566,7 +566,7 @@ static void __init __early_set_fixmap(enum fixed_addresses idx, } static inline void __init early_set_fixmap(enum fixed_addresses idx, - unsigned long phys, pgprot_t prot) + phys_addr_t phys, pgprot_t prot) { if (after_paging_init) __set_fixmap(idx, phys, prot); @@ -607,9 +607,10 @@ static int __init check_early_ioremap_leak(void) late_initcall(check_early_ioremap_leak); static void __init __iomem * -__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot) +__early_ioremap(resource_size_t phys_addr, unsigned long size, pgprot_t prot) { - unsigned long offset, last_addr; + unsigned long offset; + resource_size_t last_addr; unsigned int nrpages; enum fixed_addresses idx0, idx; int i, slot; @@ -625,15 +626,15 @@ __early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot) } if (slot < 0) { - printk(KERN_INFO "early_iomap(%08lx, %08lx) not found slot\n", - phys_addr, size); + printk(KERN_INFO "early_iomap(%08llx, %08lx) not found slot\n", + (u64)phys_addr, size); WARN_ON(1); return NULL; } if (early_ioremap_debug) { - printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ", - phys_addr, size, slot); + printk(KERN_INFO "early_ioremap(%08llx, %08lx) [%d] => ", + (u64)phys_addr, size, slot); dump_stack(); } @@ -680,13 +681,15 @@ __early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot) } /* Remap an IO device */ -void __init __iomem *early_ioremap(unsigned long phys_addr, unsigned long size) +void __init __iomem * +early_ioremap(resource_size_t phys_addr, unsigned long size) { return __early_ioremap(phys_addr, size, PAGE_KERNEL_IO); } /* Remap memory */ -void __init __iomem *early_memremap(unsigned long phys_addr, unsigned long size) +void __init __iomem * +early_memremap(resource_size_t phys_addr, unsigned long size) { return __early_ioremap(phys_addr, size, PAGE_KERNEL); } diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 640339ee4fb..c009a241d56 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -31,7 +31,7 @@ #ifdef CONFIG_X86_PAT int __read_mostly pat_enabled = 1; -void __cpuinit pat_disable(const char *reason) +static inline void pat_disable(const char *reason) { pat_enabled = 0; printk(KERN_INFO "%s\n", reason); diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 82cd39a6cbd..f09e8c36ee8 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -42,6 +42,7 @@ #include <asm/xen/hypervisor.h> #include <asm/fixmap.h> #include <asm/processor.h> +#include <asm/proto.h> #include <asm/msr-index.h> #include <asm/setup.h> #include <asm/desc.h> @@ -168,21 +169,23 @@ static void __init xen_banner(void) xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); } +static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0; +static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0; + static void xen_cpuid(unsigned int *ax, unsigned int *bx, unsigned int *cx, unsigned int *dx) { + unsigned maskecx = ~0; unsigned maskedx = ~0; /* * Mask out inconvenient features, to try and disable as many * unsupported kernel subsystems as possible. */ - if (*ax == 1) - maskedx = ~((1 << X86_FEATURE_APIC) | /* disable APIC */ - (1 << X86_FEATURE_ACPI) | /* disable ACPI */ - (1 << X86_FEATURE_MCE) | /* disable MCE */ - (1 << X86_FEATURE_MCA) | /* disable MCA */ - (1 << X86_FEATURE_ACC)); /* thermal monitoring */ + if (*ax == 1) { + maskecx = cpuid_leaf1_ecx_mask; + maskedx = cpuid_leaf1_edx_mask; + } asm(XEN_EMULATE_PREFIX "cpuid" : "=a" (*ax), @@ -190,9 +193,43 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, "=c" (*cx), "=d" (*dx) : "0" (*ax), "2" (*cx)); + + *cx &= maskecx; *dx &= maskedx; } +static __init void xen_init_cpuid_mask(void) +{ + unsigned int ax, bx, cx, dx; + + cpuid_leaf1_edx_mask = + ~((1 << X86_FEATURE_MCE) | /* disable MCE */ + (1 << X86_FEATURE_MCA) | /* disable MCA */ + (1 << X86_FEATURE_ACC)); /* thermal monitoring */ + + if (!xen_initial_domain()) + cpuid_leaf1_edx_mask &= + ~((1 << X86_FEATURE_APIC) | /* disable local APIC */ + (1 << X86_FEATURE_ACPI)); /* disable ACPI */ + + ax = 1; + xen_cpuid(&ax, &bx, &cx, &dx); + + /* cpuid claims we support xsave; try enabling it to see what happens */ + if (cx & (1 << (X86_FEATURE_XSAVE % 32))) { + unsigned long cr4; + + set_in_cr4(X86_CR4_OSXSAVE); + + cr4 = read_cr4(); + + if ((cr4 & X86_CR4_OSXSAVE) == 0) + cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_XSAVE % 32)); + + clear_in_cr4(X86_CR4_OSXSAVE); + } +} + static void xen_set_debugreg(int reg, unsigned long val) { HYPERVISOR_set_debugreg(reg, val); @@ -284,12 +321,11 @@ static void xen_set_ldt(const void *addr, unsigned entries) static void xen_load_gdt(const struct desc_ptr *dtr) { - unsigned long *frames; unsigned long va = dtr->address; unsigned int size = dtr->size + 1; unsigned pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; + unsigned long frames[pages]; int f; - struct multicall_space mcs; /* A GDT can be up to 64k in size, which corresponds to 8192 8-byte entries, or 16 4k pages.. */ @@ -297,19 +333,26 @@ static void xen_load_gdt(const struct desc_ptr *dtr) BUG_ON(size > 65536); BUG_ON(va & ~PAGE_MASK); - mcs = xen_mc_entry(sizeof(*frames) * pages); - frames = mcs.args; - for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) { - frames[f] = arbitrary_virt_to_mfn((void *)va); + int level; + pte_t *ptep = lookup_address(va, &level); + unsigned long pfn, mfn; + void *virt; + + BUG_ON(ptep == NULL); + + pfn = pte_pfn(*ptep); + mfn = pfn_to_mfn(pfn); + virt = __va(PFN_PHYS(pfn)); + + frames[f] = mfn; make_lowmem_page_readonly((void *)va); - make_lowmem_page_readonly(mfn_to_virt(frames[f])); + make_lowmem_page_readonly(virt); } - MULTI_set_gdt(mcs.mc, frames, size / sizeof(struct desc_struct)); - - xen_mc_issue(PARAVIRT_LAZY_CPU); + if (HYPERVISOR_set_gdt(frames, size / sizeof(struct desc_struct))) + BUG(); } static void load_TLS_descriptor(struct thread_struct *t, @@ -385,7 +428,7 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, static int cvt_gate_to_trap(int vector, const gate_desc *val, struct trap_info *info) { - if (val->type != 0xf && val->type != 0xe) + if (val->type != GATE_TRAP && val->type != GATE_INTERRUPT) return 0; info->vector = vector; @@ -393,8 +436,8 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val, info->cs = gate_segment(*val); info->flags = val->dpl; /* interrupt gates clear IF */ - if (val->type == 0xe) - info->flags |= 4; + if (val->type == GATE_INTERRUPT) + info->flags |= 1 << 2; return 1; } @@ -872,7 +915,6 @@ static const struct machine_ops __initdata xen_machine_ops = { .emergency_restart = xen_emergency_restart, }; - /* First C function to be called on Xen boot */ asmlinkage void __init xen_start_kernel(void) { @@ -897,6 +939,8 @@ asmlinkage void __init xen_start_kernel(void) xen_init_irq_ops(); + xen_init_cpuid_mask(); + #ifdef CONFIG_X86_LOCAL_APIC /* * set up the basic apic ops. @@ -938,6 +982,11 @@ asmlinkage void __init xen_start_kernel(void) if (!xen_initial_domain()) __supported_pte_mask &= ~(_PAGE_PWT | _PAGE_PCD); +#ifdef CONFIG_X86_64 + /* Work out if we support NX */ + check_efer(); +#endif + /* Don't do the full vcpu_info placement stuff until we have a possible map and a non-dummy shared_info. */ per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0]; diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 2a81838a9ab..9842b121240 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -184,7 +184,7 @@ static inline unsigned p2m_index(unsigned long pfn) } /* Build the parallel p2m_top_mfn structures */ -void xen_setup_mfn_list_list(void) +static void __init xen_build_mfn_list_list(void) { unsigned pfn, idx; @@ -198,7 +198,10 @@ void xen_setup_mfn_list_list(void) unsigned topidx = idx * P2M_ENTRIES_PER_PAGE; p2m_top_mfn_list[idx] = virt_to_mfn(&p2m_top_mfn[topidx]); } +} +void xen_setup_mfn_list_list(void) +{ BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info); HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = @@ -218,6 +221,8 @@ void __init xen_build_dynamic_phys_to_machine(void) p2m_top[topidx] = &mfn_list[pfn]; } + + xen_build_mfn_list_list(); } unsigned long get_phys_to_machine(unsigned long pfn) @@ -233,47 +238,74 @@ unsigned long get_phys_to_machine(unsigned long pfn) } EXPORT_SYMBOL_GPL(get_phys_to_machine); -static void alloc_p2m(unsigned long **pp, unsigned long *mfnp) +/* install a new p2m_top page */ +bool install_p2mtop_page(unsigned long pfn, unsigned long *p) { - unsigned long *p; + unsigned topidx = p2m_top_index(pfn); + unsigned long **pfnp, *mfnp; unsigned i; - p = (void *)__get_free_page(GFP_KERNEL | __GFP_NOFAIL); - BUG_ON(p == NULL); + pfnp = &p2m_top[topidx]; + mfnp = &p2m_top_mfn[topidx]; for (i = 0; i < P2M_ENTRIES_PER_PAGE; i++) p[i] = INVALID_P2M_ENTRY; - if (cmpxchg(pp, p2m_missing, p) != p2m_missing) - free_page((unsigned long)p); - else + if (cmpxchg(pfnp, p2m_missing, p) == p2m_missing) { *mfnp = virt_to_mfn(p); + return true; + } + + return false; } -void set_phys_to_machine(unsigned long pfn, unsigned long mfn) +static void alloc_p2m(unsigned long pfn) { - unsigned topidx, idx; + unsigned long *p; - if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { - BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); - return; - } + p = (void *)__get_free_page(GFP_KERNEL | __GFP_NOFAIL); + BUG_ON(p == NULL); + + if (!install_p2mtop_page(pfn, p)) + free_page((unsigned long)p); +} + +/* Try to install p2m mapping; fail if intermediate bits missing */ +bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) +{ + unsigned topidx, idx; if (unlikely(pfn >= MAX_DOMAIN_PAGES)) { BUG_ON(mfn != INVALID_P2M_ENTRY); - return; + return true; } topidx = p2m_top_index(pfn); if (p2m_top[topidx] == p2m_missing) { - /* no need to allocate a page to store an invalid entry */ if (mfn == INVALID_P2M_ENTRY) - return; - alloc_p2m(&p2m_top[topidx], &p2m_top_mfn[topidx]); + return true; + return false; } idx = p2m_index(pfn); p2m_top[topidx][idx] = mfn; + + return true; +} + +void set_phys_to_machine(unsigned long pfn, unsigned long mfn) +{ + if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { + BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); + return; + } + + if (unlikely(!__set_phys_to_machine(pfn, mfn))) { + alloc_p2m(pfn); + + if (!__set_phys_to_machine(pfn, mfn)) + BUG(); + } } unsigned long arbitrary_virt_to_mfn(void *vaddr) @@ -987,7 +1019,7 @@ static __init int xen_mark_pinned(struct mm_struct *mm, struct page *page, return 0; } -void __init xen_mark_init_mm_pinned(void) +static void __init xen_mark_init_mm_pinned(void) { xen_pgd_walk(&init_mm, xen_mark_pinned, FIXADDR_TOP); } @@ -1270,8 +1302,8 @@ static void xen_flush_tlb_others(const struct cpumask *cpus, } *args; struct multicall_space mcs; - BUG_ON(cpumask_empty(cpus)); - BUG_ON(!mm); + if (cpumask_empty(cpus)) + return; /* nothing to do */ mcs = xen_mc_entry(sizeof(*args)); args = mcs.args; @@ -1438,6 +1470,15 @@ static __init void xen_set_pte_init(pte_t *ptep, pte_t pte) } #endif +static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) +{ + struct mmuext_op op; + op.cmd = cmd; + op.arg1.mfn = pfn_to_mfn(pfn); + if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) + BUG(); +} + /* Early in boot, while setting up the initial pagetable, assume everything is pinned. */ static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn) @@ -1446,22 +1487,29 @@ static __init void xen_alloc_pte_init(struct mm_struct *mm, unsigned long pfn) BUG_ON(mem_map); /* should only be used early */ #endif make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); + pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); +} + +/* Used for pmd and pud */ +static __init void xen_alloc_pmd_init(struct mm_struct *mm, unsigned long pfn) +{ +#ifdef CONFIG_FLATMEM + BUG_ON(mem_map); /* should only be used early */ +#endif + make_lowmem_page_readonly(__va(PFN_PHYS(pfn))); } /* Early release_pte assumes that all pts are pinned, since there's only init_mm and anything attached to that is pinned. */ -static void xen_release_pte_init(unsigned long pfn) +static __init void xen_release_pte_init(unsigned long pfn) { + pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); } -static void pin_pagetable_pfn(unsigned cmd, unsigned long pfn) +static __init void xen_release_pmd_init(unsigned long pfn) { - struct mmuext_op op; - op.cmd = cmd; - op.arg1.mfn = pfn_to_mfn(pfn); - if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) - BUG(); + make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); } /* This needs to make sure the new pte page is pinned iff its being @@ -1773,6 +1821,9 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) #ifdef CONFIG_X86_LOCAL_APIC case FIX_APIC_BASE: /* maps dummy local APIC */ #endif + case FIX_TEXT_POKE0: + case FIX_TEXT_POKE1: + /* All local page mappings */ pte = pfn_pte(phys, prot); break; @@ -1819,7 +1870,6 @@ __init void xen_post_allocator_init(void) xen_mark_init_mm_pinned(); } - const struct pv_mmu_ops xen_mmu_ops __initdata = { .pagetable_setup_start = xen_pagetable_setup_start, .pagetable_setup_done = xen_pagetable_setup_done, @@ -1843,9 +1893,9 @@ const struct pv_mmu_ops xen_mmu_ops __initdata = { .alloc_pte = xen_alloc_pte_init, .release_pte = xen_release_pte_init, - .alloc_pmd = xen_alloc_pte_init, + .alloc_pmd = xen_alloc_pmd_init, .alloc_pmd_clone = paravirt_nop, - .release_pmd = xen_release_pte_init, + .release_pmd = xen_release_pmd_init, #ifdef CONFIG_HIGHPTE .kmap_atomic_pte = xen_kmap_atomic_pte, @@ -1883,8 +1933,8 @@ const struct pv_mmu_ops xen_mmu_ops __initdata = { .make_pud = PV_CALLEE_SAVE(xen_make_pud), .set_pgd = xen_set_pgd_hyper, - .alloc_pud = xen_alloc_pte_init, - .release_pud = xen_release_pte_init, + .alloc_pud = xen_alloc_pmd_init, + .release_pud = xen_release_pmd_init, #endif /* PAGETABLE_LEVELS == 4 */ .activate_mm = xen_activate_mm, diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h index 24d1b44a337..da730262489 100644 --- a/arch/x86/xen/mmu.h +++ b/arch/x86/xen/mmu.h @@ -11,6 +11,9 @@ enum pt_level { }; +bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn); +bool install_p2mtop_page(unsigned long pfn, unsigned long *p); + void set_pte_mfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 585a6e33083..429834ec168 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -317,7 +317,7 @@ static int __cpuinit xen_cpu_up(unsigned int cpu) BUG_ON(rc); while(per_cpu(cpu_state, cpu) != CPU_ONLINE) { - HYPERVISOR_sched_op(SCHEDOP_yield, 0); + HYPERVISOR_sched_op(SCHEDOP_yield, NULL); barrier(); } @@ -422,7 +422,7 @@ static void xen_smp_send_call_function_ipi(const struct cpumask *mask) /* Make sure other vcpus get a chance to run if they need to. */ for_each_cpu(cpu, mask) { if (xen_vcpu_stolen(cpu)) { - HYPERVISOR_sched_op(SCHEDOP_yield, 0); + HYPERVISOR_sched_op(SCHEDOP_yield, NULL); break; } } diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 2f5ef2632ea..20139464943 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -57,8 +57,6 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id); bool xen_vcpu_stolen(int vcpu); -void xen_mark_init_mm_pinned(void); - void xen_setup_vcpu_info_placement(void); #ifdef CONFIG_SMP diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 57be6bea48e..08186ecbaf8 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -114,6 +114,7 @@ enum { board_ahci_sb700 = 5, /* for SB700 and SB800 */ board_ahci_mcp65 = 6, board_ahci_nopmp = 7, + board_ahci_yesncq = 8, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -469,6 +470,14 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, + /* board_ahci_yesncq */ + { + AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ), + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, }; static const struct pci_device_id ahci_pci_tbl[] = { @@ -535,30 +544,30 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, 0x045d), board_ahci_mcp65 }, /* MCP65 */ { PCI_VDEVICE(NVIDIA, 0x045e), board_ahci_mcp65 }, /* MCP65 */ { PCI_VDEVICE(NVIDIA, 0x045f), board_ahci_mcp65 }, /* MCP65 */ - { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */ - { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci }, /* MCP73 */ - { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci }, /* MCP73 */ - { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci }, /* MCP73 */ - { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci }, /* MCP73 */ - { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci }, /* MCP73 */ - { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci }, /* MCP73 */ - { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci }, /* MCP73 */ - { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci }, /* MCP73 */ - { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci }, /* MCP73 */ - { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci }, /* MCP73 */ - { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci }, /* MCP73 */ - { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x0550), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0551), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0552), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0553), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_yesncq }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_yesncq }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci_yesncq }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci_yesncq }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci_yesncq }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci_yesncq }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci_yesncq }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci_yesncq }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci_yesncq }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci_yesncq }, /* MCP73 */ + { PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci_yesncq }, /* MCP73 */ { PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */ { PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */ { PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */ diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e7ea77cf606..065507c4664 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6110,13 +6110,11 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) ata_port_printk(ap, KERN_INFO, "DUMMY\n"); } - /* perform each probe synchronously */ - DPRINTK("probe begin\n"); + /* perform each probe asynchronously */ for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; async_schedule(async_port_probe, ap); } - DPRINTK("probe end\n"); return 0; } diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 98e8c50703b..bdd43c7f432 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -566,7 +566,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) static int printed_version; unsigned int i; int rc; - struct ata_host *host; + struct ata_host *host = NULL; int board_id = (int) ent->driver_data; const unsigned *bar_sizes; diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index be204308cc1..9359613addc 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -1059,7 +1059,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) goto out; } - err = pci_set_dma_mask(dev, DMA_32BIT_MASK); + err = pci_set_dma_mask(dev, DMA_BIT_MASK(32)); if (err) { dev_warn(&dev->dev, "Failed to set 32-bit DMA mask\n"); goto out; diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 0ef6f08aa6e..4d4d5e0d3fa 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3505,7 +3505,7 @@ static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, u /* The Inbound Post Queue only accepts 32-bit physical addresses for the CCISS commands, so they must be allocated from the lower 4GiB of memory. */ - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { iounmap(vaddr); return -ENOMEM; diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 9d9490e22e0..3686912427b 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -2131,6 +2131,8 @@ static const struct intel_driver_description { { PCI_DEVICE_ID_INTEL_82845G_HB, PCI_DEVICE_ID_INTEL_82845G_IG, 0, "830M", &intel_845_driver, &intel_830_driver }, { PCI_DEVICE_ID_INTEL_82850_HB, 0, 0, "i850", &intel_850_driver, NULL }, + { PCI_DEVICE_ID_INTEL_82854_HB, PCI_DEVICE_ID_INTEL_82854_IG, 0, "854", + &intel_845_driver, &intel_830_driver }, { PCI_DEVICE_ID_INTEL_82855PM_HB, 0, 0, "855PM", &intel_845_driver, NULL }, { PCI_DEVICE_ID_INTEL_82855GM_HB, PCI_DEVICE_ID_INTEL_82855GM_IG, 0, "855GM", &intel_845_driver, &intel_830_driver }, @@ -2355,6 +2357,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_82845_HB), ID(PCI_DEVICE_ID_INTEL_82845G_HB), ID(PCI_DEVICE_ID_INTEL_82850_HB), + ID(PCI_DEVICE_ID_INTEL_82854_HB), ID(PCI_DEVICE_ID_INTEL_82855PM_HB), ID(PCI_DEVICE_ID_INTEL_82855GM_HB), ID(PCI_DEVICE_ID_INTEL_82860_HB), diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 6de020d078e..b0a6a3e5192 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -35,7 +35,6 @@ #include <linux/vt_kern.h> #include <linux/workqueue.h> #include <linux/kexec.h> -#include <linux/interrupt.h> #include <linux/hrtimer.h> #include <linux/oom.h> diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 28f2c3f959b..6ad95c8d636 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -767,11 +767,19 @@ static inline void pci_write_bits16(struct pci_dev *pdev, int offset, pci_write_config_word(pdev, offset, value); } -/* write all or some bits in a dword-register*/ +/* + * pci_write_bits32 + * + * edac local routine to do pci_write_config_dword, but adds + * a mask parameter. If mask is all ones, ignore the mask. + * Otherwise utilize the mask to isolate specified bits + * + * write all or some bits in a dword-register + */ static inline void pci_write_bits32(struct pci_dev *pdev, int offset, u32 value, u32 mask) { - if (mask != 0xffff) { + if (mask != 0xffffffff) { u32 buf; pci_read_config_dword(pdev, offset, &buf); diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index ca9113e1c10..a7d2c717d03 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c @@ -389,7 +389,7 @@ static void del_edac_device_from_global_list(struct edac_device_ctl_info */ static void edac_device_workq_function(struct work_struct *work_req) { - struct delayed_work *d_work = (struct delayed_work *)work_req; + struct delayed_work *d_work = to_delayed_work(work_req); struct edac_device_ctl_info *edac_dev = to_edac_device_ctl_work(d_work); mutex_lock(&device_ctls_mutex); diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 25d66940b4f..335b7ebdb11 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -260,7 +260,7 @@ static int edac_mc_assert_error_check_and_clear(void) */ static void edac_mc_workq_function(struct work_struct *work_req) { - struct delayed_work *d_work = (struct delayed_work *)work_req; + struct delayed_work *d_work = to_delayed_work(work_req); struct mem_ctl_info *mci = to_edac_mem_ctl_work(d_work); mutex_lock(&mem_ctls_mutex); diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index 5b150aea703..30b585b1d60 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c @@ -233,7 +233,7 @@ EXPORT_SYMBOL_GPL(edac_pci_find); */ static void edac_pci_workq_function(struct work_struct *work_req) { - struct delayed_work *d_work = (struct delayed_work *)work_req; + struct delayed_work *d_work = to_delayed_work(work_req); struct edac_pci_ctl_info *pci = to_edac_pci_ctl_work(d_work); int msec; unsigned long delay; diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 0e8a9185f67..d73f5f473e3 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -692,6 +692,16 @@ config SENSORS_PCF8591 These devices are hard to detect and rarely found on mainstream hardware. If unsure, say N. +config SENSORS_SHT15 + tristate "Sensiron humidity and temperature sensors. SHT15 and compat." + depends on GENERIC_GPIO + help + If you say yes here you get support for the Sensiron SHT10, SHT11, + SHT15, SHT71, SHT75 humidity and temperature sensors. + + This driver can also be built as a module. If so, the module + will be called sht15. + config SENSORS_SIS5595 tristate "Silicon Integrated Systems Corp. SiS5595" depends on PCI diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 1d3757837b4..0ae26984ba4 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_SENSORS_MAX6650) += max6650.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PC87427) += pc87427.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o +obj-$(CONFIG_SENSORS_SHT15) += sht15.o obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index 55d3dc565be..abca7e9f953 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c @@ -34,7 +34,6 @@ #include <linux/wait.h> #include <linux/poll.h> #include <linux/freezer.h> -#include <linux/version.h> #include <linux/uaccess.h> #include <linux/leds.h> #include <acpi/acpi_drivers.h> diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c new file mode 100644 index 00000000000..6cbdc2fea73 --- /dev/null +++ b/drivers/hwmon/sht15.c @@ -0,0 +1,692 @@ +/* + * sht15.c - support for the SHT15 Temperature and Humidity Sensor + * + * Copyright (c) 2009 Jonathan Cameron + * + * Copyright (c) 2007 Wouter Horre + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Currently ignoring checksum on readings. + * Default resolution only (14bit temp, 12bit humidity) + * Ignoring battery status. + * Heater not enabled. + * Timings are all conservative. + * + * Data sheet available (1/2009) at + * http://www.sensirion.ch/en/pdf/product_information/Datasheet-humidity-sensor-SHT1x.pdf + * + * Regulator supply name = vcc + */ + +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/gpio.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/jiffies.h> +#include <linux/err.h> +#include <linux/sht15.h> +#include <linux/regulator/consumer.h> +#include <asm/atomic.h> + +#define SHT15_MEASURE_TEMP 3 +#define SHT15_MEASURE_RH 5 + +#define SHT15_READING_NOTHING 0 +#define SHT15_READING_TEMP 1 +#define SHT15_READING_HUMID 2 + +/* Min timings in nsecs */ +#define SHT15_TSCKL 100 /* clock low */ +#define SHT15_TSCKH 100 /* clock high */ +#define SHT15_TSU 150 /* data setup time */ + +/** + * struct sht15_temppair - elements of voltage dependant temp calc + * @vdd: supply voltage in microvolts + * @d1: see data sheet + */ +struct sht15_temppair { + int vdd; /* microvolts */ + int d1; +}; + +/* Table 9 from data sheet - relates temperature calculation + * to supply voltage. + */ +static const struct sht15_temppair temppoints[] = { + { 2500000, -39400 }, + { 3000000, -39600 }, + { 3500000, -39700 }, + { 4000000, -39800 }, + { 5000000, -40100 }, +}; + +/** + * struct sht15_data - device instance specific data + * @pdata: platform data (gpio's etc) + * @read_work: bh of interrupt handler + * @wait_queue: wait queue for getting values from device + * @val_temp: last temperature value read from device + * @val_humid: last humidity value read from device + * @flag: status flag used to identify what the last request was + * @valid: are the current stored values valid (start condition) + * @last_updat: time of last update + * @read_lock: mutex to ensure only one read in progress + * at a time. + * @dev: associate device structure + * @hwmon_dev: device associated with hwmon subsystem + * @reg: associated regulator (if specified) + * @nb: notifier block to handle notifications of voltage changes + * @supply_uV: local copy of supply voltage used to allow + * use of regulator consumer if available + * @supply_uV_valid: indicates that an updated value has not yet + * been obtained from the regulator and so any calculations + * based upon it will be invalid. + * @update_supply_work: work struct that is used to update the supply_uV + * @interrupt_handled: flag used to indicate a hander has been scheduled + */ +struct sht15_data { + struct sht15_platform_data *pdata; + struct work_struct read_work; + wait_queue_head_t wait_queue; + uint16_t val_temp; + uint16_t val_humid; + u8 flag; + u8 valid; + unsigned long last_updat; + struct mutex read_lock; + struct device *dev; + struct device *hwmon_dev; + struct regulator *reg; + struct notifier_block nb; + int supply_uV; + int supply_uV_valid; + struct work_struct update_supply_work; + atomic_t interrupt_handled; +}; + +/** + * sht15_connection_reset() - reset the comms interface + * @data: sht15 specific data + * + * This implements section 3.4 of the data sheet + */ +static void sht15_connection_reset(struct sht15_data *data) +{ + int i; + gpio_direction_output(data->pdata->gpio_data, 1); + ndelay(SHT15_TSCKL); + gpio_set_value(data->pdata->gpio_sck, 0); + ndelay(SHT15_TSCKL); + for (i = 0; i < 9; ++i) { + gpio_set_value(data->pdata->gpio_sck, 1); + ndelay(SHT15_TSCKH); + gpio_set_value(data->pdata->gpio_sck, 0); + ndelay(SHT15_TSCKL); + } +} +/** + * sht15_send_bit() - send an individual bit to the device + * @data: device state data + * @val: value of bit to be sent + **/ +static inline void sht15_send_bit(struct sht15_data *data, int val) +{ + + gpio_set_value(data->pdata->gpio_data, val); + ndelay(SHT15_TSU); + gpio_set_value(data->pdata->gpio_sck, 1); + ndelay(SHT15_TSCKH); + gpio_set_value(data->pdata->gpio_sck, 0); + ndelay(SHT15_TSCKL); /* clock low time */ +} + +/** + * sht15_transmission_start() - specific sequence for new transmission + * + * @data: device state data + * Timings for this are not documented on the data sheet, so very + * conservative ones used in implementation. This implements + * figure 12 on the data sheet. + **/ +static void sht15_transmission_start(struct sht15_data *data) +{ + /* ensure data is high and output */ + gpio_direction_output(data->pdata->gpio_data, 1); + ndelay(SHT15_TSU); + gpio_set_value(data->pdata->gpio_sck, 0); + ndelay(SHT15_TSCKL); + gpio_set_value(data->pdata->gpio_sck, 1); + ndelay(SHT15_TSCKH); + gpio_set_value(data->pdata->gpio_data, 0); + ndelay(SHT15_TSU); + gpio_set_value(data->pdata->gpio_sck, 0); + ndelay(SHT15_TSCKL); + gpio_set_value(data->pdata->gpio_sck, 1); + ndelay(SHT15_TSCKH); + gpio_set_value(data->pdata->gpio_data, 1); + ndelay(SHT15_TSU); + gpio_set_value(data->pdata->gpio_sck, 0); + ndelay(SHT15_TSCKL); +} +/** + * sht15_send_byte() - send a single byte to the device + * @data: device state + * @byte: value to be sent + **/ +static void sht15_send_byte(struct sht15_data *data, u8 byte) +{ + int i; + for (i = 0; i < 8; i++) { + sht15_send_bit(data, !!(byte & 0x80)); + byte <<= 1; + } +} +/** + * sht15_wait_for_response() - checks for ack from device + * @data: device state + **/ +static int sht15_wait_for_response(struct sht15_data *data) +{ + gpio_direction_input(data->pdata->gpio_data); + gpio_set_value(data->pdata->gpio_sck, 1); + ndelay(SHT15_TSCKH); + if (gpio_get_value(data->pdata->gpio_data)) { + gpio_set_value(data->pdata->gpio_sck, 0); + dev_err(data->dev, "Command not acknowledged\n"); + sht15_connection_reset(data); + return -EIO; + } + gpio_set_value(data->pdata->gpio_sck, 0); + ndelay(SHT15_TSCKL); + return 0; +} + +/** + * sht15_send_cmd() - Sends a command to the device. + * @data: device state + * @cmd: command byte to be sent + * + * On entry, sck is output low, data is output pull high + * and the interrupt disabled. + **/ +static int sht15_send_cmd(struct sht15_data *data, u8 cmd) +{ + int ret = 0; + sht15_transmission_start(data); + sht15_send_byte(data, cmd); + ret = sht15_wait_for_response(data); + return ret; +} +/** + * sht15_update_single_val() - get a new value from device + * @data: device instance specific data + * @command: command sent to request value + * @timeout_msecs: timeout after which comms are assumed + * to have failed are reset. + **/ +static inline int sht15_update_single_val(struct sht15_data *data, + int command, + int timeout_msecs) +{ + int ret; + ret = sht15_send_cmd(data, command); + if (ret) + return ret; + + gpio_direction_input(data->pdata->gpio_data); + atomic_set(&data->interrupt_handled, 0); + + enable_irq(gpio_to_irq(data->pdata->gpio_data)); + if (gpio_get_value(data->pdata->gpio_data) == 0) { + disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data)); + /* Only relevant if the interrupt hasn't occured. */ + if (!atomic_read(&data->interrupt_handled)) + schedule_work(&data->read_work); + } + ret = wait_event_timeout(data->wait_queue, + (data->flag == SHT15_READING_NOTHING), + msecs_to_jiffies(timeout_msecs)); + if (ret == 0) {/* timeout occurred */ + disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));; + sht15_connection_reset(data); + return -ETIME; + } + return 0; +} + +/** + * sht15_update_vals() - get updated readings from device if too old + * @data: device state + **/ +static int sht15_update_vals(struct sht15_data *data) +{ + int ret = 0; + int timeout = HZ; + + mutex_lock(&data->read_lock); + if (time_after(jiffies, data->last_updat + timeout) + || !data->valid) { + data->flag = SHT15_READING_HUMID; + ret = sht15_update_single_val(data, SHT15_MEASURE_RH, 160); + if (ret) + goto error_ret; + data->flag = SHT15_READING_TEMP; + ret = sht15_update_single_val(data, SHT15_MEASURE_TEMP, 400); + if (ret) + goto error_ret; + data->valid = 1; + data->last_updat = jiffies; + } +error_ret: + mutex_unlock(&data->read_lock); + + return ret; +} + +/** + * sht15_calc_temp() - convert the raw reading to a temperature + * @data: device state + * + * As per section 4.3 of the data sheet. + **/ +static inline int sht15_calc_temp(struct sht15_data *data) +{ + int d1 = 0; + int i; + + for (i = 1; i < ARRAY_SIZE(temppoints) - 1; i++) + /* Find pointer to interpolate */ + if (data->supply_uV > temppoints[i - 1].vdd) { + d1 = (data->supply_uV/1000 - temppoints[i - 1].vdd) + * (temppoints[i].d1 - temppoints[i - 1].d1) + / (temppoints[i].vdd - temppoints[i - 1].vdd) + + temppoints[i - 1].d1; + break; + } + + return data->val_temp*10 + d1; +} + +/** + * sht15_calc_humid() - using last temperature convert raw to humid + * @data: device state + * + * This is the temperature compensated version as per section 4.2 of + * the data sheet. + **/ +static inline int sht15_calc_humid(struct sht15_data *data) +{ + int RHlinear; /* milli percent */ + int temp = sht15_calc_temp(data); + + const int c1 = -4; + const int c2 = 40500; /* x 10 ^ -6 */ + const int c3 = 2800; /* x10 ^ -9 */ + + RHlinear = c1*1000 + + c2 * data->val_humid/1000 + + (data->val_humid * data->val_humid * c3)/1000000; + return (temp - 25000) * (10000 + 800 * data->val_humid) + / 1000000 + RHlinear; +} + +static ssize_t sht15_show_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + struct sht15_data *data = dev_get_drvdata(dev); + + /* Technically no need to read humidity as well */ + ret = sht15_update_vals(data); + + return ret ? ret : sprintf(buf, "%d\n", + sht15_calc_temp(data)); +} + +static ssize_t sht15_show_humidity(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + struct sht15_data *data = dev_get_drvdata(dev); + + ret = sht15_update_vals(data); + + return ret ? ret : sprintf(buf, "%d\n", sht15_calc_humid(data)); + +}; +static ssize_t show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + return sprintf(buf, "%s\n", pdev->name); +} + +static SENSOR_DEVICE_ATTR(temp1_input, + S_IRUGO, sht15_show_temp, + NULL, 0); +static SENSOR_DEVICE_ATTR(humidity1_input, + S_IRUGO, sht15_show_humidity, + NULL, 0); +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); +static struct attribute *sht15_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_humidity1_input.dev_attr.attr, + &dev_attr_name.attr, + NULL, +}; + +static const struct attribute_group sht15_attr_group = { + .attrs = sht15_attrs, +}; + +static irqreturn_t sht15_interrupt_fired(int irq, void *d) +{ + struct sht15_data *data = d; + /* First disable the interrupt */ + disable_irq_nosync(irq); + atomic_inc(&data->interrupt_handled); + /* Then schedule a reading work struct */ + if (data->flag != SHT15_READING_NOTHING) + schedule_work(&data->read_work); + return IRQ_HANDLED; +} + +/* Each byte of data is acknowledged by pulling the data line + * low for one clock pulse. + */ +static void sht15_ack(struct sht15_data *data) +{ + gpio_direction_output(data->pdata->gpio_data, 0); + ndelay(SHT15_TSU); + gpio_set_value(data->pdata->gpio_sck, 1); + ndelay(SHT15_TSU); + gpio_set_value(data->pdata->gpio_sck, 0); + ndelay(SHT15_TSU); + gpio_set_value(data->pdata->gpio_data, 1); + + gpio_direction_input(data->pdata->gpio_data); +} +/** + * sht15_end_transmission() - notify device of end of transmission + * @data: device state + * + * This is basically a NAK. (single clock pulse, data high) + **/ +static void sht15_end_transmission(struct sht15_data *data) +{ + gpio_direction_output(data->pdata->gpio_data, 1); + ndelay(SHT15_TSU); + gpio_set_value(data->pdata->gpio_sck, 1); + ndelay(SHT15_TSCKH); + gpio_set_value(data->pdata->gpio_sck, 0); + ndelay(SHT15_TSCKL); +} + +static void sht15_bh_read_data(struct work_struct *work_s) +{ + int i; + uint16_t val = 0; + struct sht15_data *data + = container_of(work_s, struct sht15_data, + read_work); + /* Firstly, verify the line is low */ + if (gpio_get_value(data->pdata->gpio_data)) { + /* If not, then start the interrupt again - care + here as could have gone low in meantime so verify + it hasn't! + */ + atomic_set(&data->interrupt_handled, 0); + enable_irq(gpio_to_irq(data->pdata->gpio_data)); + /* If still not occured or another handler has been scheduled */ + if (gpio_get_value(data->pdata->gpio_data) + || atomic_read(&data->interrupt_handled)) + return; + } + /* Read the data back from the device */ + for (i = 0; i < 16; ++i) { + val <<= 1; + gpio_set_value(data->pdata->gpio_sck, 1); + ndelay(SHT15_TSCKH); + val |= !!gpio_get_value(data->pdata->gpio_data); + gpio_set_value(data->pdata->gpio_sck, 0); + ndelay(SHT15_TSCKL); + if (i == 7) + sht15_ack(data); + } + /* Tell the device we are done */ + sht15_end_transmission(data); + + switch (data->flag) { + case SHT15_READING_TEMP: + data->val_temp = val; + break; + case SHT15_READING_HUMID: + data->val_humid = val; + break; + } + + data->flag = SHT15_READING_NOTHING; + wake_up(&data->wait_queue); +} + +static void sht15_update_voltage(struct work_struct *work_s) +{ + struct sht15_data *data + = container_of(work_s, struct sht15_data, + update_supply_work); + data->supply_uV = regulator_get_voltage(data->reg); +} + +/** + * sht15_invalidate_voltage() - mark supply voltage invalid when notified by reg + * @nb: associated notification structure + * @event: voltage regulator state change event code + * @ignored: function parameter - ignored here + * + * Note that as the notification code holds the regulator lock, we have + * to schedule an update of the supply voltage rather than getting it directly. + **/ +static int sht15_invalidate_voltage(struct notifier_block *nb, + unsigned long event, + void *ignored) +{ + struct sht15_data *data = container_of(nb, struct sht15_data, nb); + + if (event == REGULATOR_EVENT_VOLTAGE_CHANGE) + data->supply_uV_valid = false; + schedule_work(&data->update_supply_work); + + return NOTIFY_OK; +} + +static int __devinit sht15_probe(struct platform_device *pdev) +{ + int ret = 0; + struct sht15_data *data = kzalloc(sizeof(*data), GFP_KERNEL); + + if (!data) { + ret = -ENOMEM; + dev_err(&pdev->dev, "kzalloc failed"); + goto error_ret; + } + + INIT_WORK(&data->read_work, sht15_bh_read_data); + INIT_WORK(&data->update_supply_work, sht15_update_voltage); + platform_set_drvdata(pdev, data); + mutex_init(&data->read_lock); + data->dev = &pdev->dev; + init_waitqueue_head(&data->wait_queue); + + if (pdev->dev.platform_data == NULL) { + dev_err(&pdev->dev, "no platform data supplied"); + goto err_free_data; + } + data->pdata = pdev->dev.platform_data; + data->supply_uV = data->pdata->supply_mv*1000; + +/* If a regulator is available, query what the supply voltage actually is!*/ + data->reg = regulator_get(data->dev, "vcc"); + if (!IS_ERR(data->reg)) { + data->supply_uV = regulator_get_voltage(data->reg); + regulator_enable(data->reg); + /* setup a notifier block to update this if another device + * causes the voltage to change */ + data->nb.notifier_call = &sht15_invalidate_voltage; + ret = regulator_register_notifier(data->reg, &data->nb); + } +/* Try requesting the GPIOs */ + ret = gpio_request(data->pdata->gpio_sck, "SHT15 sck"); + if (ret) { + dev_err(&pdev->dev, "gpio request failed"); + goto err_free_data; + } + gpio_direction_output(data->pdata->gpio_sck, 0); + ret = gpio_request(data->pdata->gpio_data, "SHT15 data"); + if (ret) { + dev_err(&pdev->dev, "gpio request failed"); + goto err_release_gpio_sck; + } + ret = sysfs_create_group(&pdev->dev.kobj, &sht15_attr_group); + if (ret) { + dev_err(&pdev->dev, "sysfs create failed"); + goto err_free_data; + } + + ret = request_irq(gpio_to_irq(data->pdata->gpio_data), + sht15_interrupt_fired, + IRQF_TRIGGER_FALLING, + "sht15 data", + data); + if (ret) { + dev_err(&pdev->dev, "failed to get irq for data line"); + goto err_release_gpio_data; + } + disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data)); + sht15_connection_reset(data); + sht15_send_cmd(data, 0x1E); + + data->hwmon_dev = hwmon_device_register(data->dev); + if (IS_ERR(data->hwmon_dev)) { + ret = PTR_ERR(data->hwmon_dev); + goto err_release_gpio_data; + } + return 0; + +err_release_gpio_data: + gpio_free(data->pdata->gpio_data); +err_release_gpio_sck: + gpio_free(data->pdata->gpio_sck); +err_free_data: + kfree(data); +error_ret: + + return ret; +} + +static int __devexit sht15_remove(struct platform_device *pdev) +{ + struct sht15_data *data = platform_get_drvdata(pdev); + + /* Make sure any reads from the device are done and + * prevent new ones beginnning */ + mutex_lock(&data->read_lock); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group); + if (!IS_ERR(data->reg)) { + regulator_unregister_notifier(data->reg, &data->nb); + regulator_disable(data->reg); + regulator_put(data->reg); + } + + free_irq(gpio_to_irq(data->pdata->gpio_data), data); + gpio_free(data->pdata->gpio_data); + gpio_free(data->pdata->gpio_sck); + mutex_unlock(&data->read_lock); + kfree(data); + return 0; +} + + +static struct platform_driver sht_drivers[] = { + { + .driver = { + .name = "sht10", + .owner = THIS_MODULE, + }, + .probe = sht15_probe, + .remove = sht15_remove, + }, { + .driver = { + .name = "sht11", + .owner = THIS_MODULE, + }, + .probe = sht15_probe, + .remove = sht15_remove, + }, { + .driver = { + .name = "sht15", + .owner = THIS_MODULE, + }, + .probe = sht15_probe, + .remove = sht15_remove, + }, { + .driver = { + .name = "sht71", + .owner = THIS_MODULE, + }, + .probe = sht15_probe, + .remove = sht15_remove, + }, { + .driver = { + .name = "sht75", + .owner = THIS_MODULE, + }, + .probe = sht15_probe, + .remove = sht15_remove, + }, +}; + + +static int __init sht15_init(void) +{ + int ret; + int i; + + for (i = 0; i < ARRAY_SIZE(sht_drivers); i++) { + ret = platform_driver_register(&sht_drivers[i]); + if (ret) + goto error_unreg; + } + + return 0; + +error_unreg: + while (--i >= 0) + platform_driver_unregister(&sht_drivers[i]); + + return ret; +} +module_init(sht15_init); + +static void __exit sht15_exit(void) +{ + int i; + for (i = ARRAY_SIZE(sht_drivers) - 1; i >= 0; i--) + platform_driver_unregister(&sht_drivers[i]); +} +module_exit(sht15_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index f68e5f8e23e..6318f7ddc1d 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -190,7 +190,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, int completed = 1; unsigned long timeout = jiffies + i2c_adap->timeout; - while (pca_status(adap) != 0xf8) { + while ((state = pca_status(adap)) != 0xf8) { if (time_before(jiffies, timeout)) { msleep(10); } else { diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 94eae5c3cbc..a48c8aee021 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -604,12 +604,14 @@ comment "Graphics adapter I2C/DDC channel drivers" depends on PCI config I2C_VOODOO3 - tristate "Voodoo 3" + tristate "Voodoo 3 (DEPRECATED)" depends on PCI select I2C_ALGOBIT help If you say yes to this option, support will be included for the - Voodoo 3 I2C interface. + Voodoo 3 I2C interface. This driver is deprecated and you should + use the tdfxfb driver instead, which additionally provides + framebuffer support. This driver can also be built as a module. If so, the module will be called i2c-voodoo3. diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index b6f3a0de6ca..85e2e919d1c 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -716,8 +716,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) /* new style driver methods can't mix with legacy ones */ if (is_newstyle_driver(driver)) { - if (driver->attach_adapter || driver->detach_adapter - || driver->detach_client) { + if (driver->detach_adapter || driver->detach_client) { printk(KERN_WARNING "i2c-core: driver [%s] is confused\n", driver->driver.name); diff --git a/drivers/input/input.c b/drivers/input/input.c index ec3db3ade11..d44065d2e66 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -132,6 +132,11 @@ static void input_start_autorepeat(struct input_dev *dev, int code) } } +static void input_stop_autorepeat(struct input_dev *dev) +{ + del_timer(&dev->timer); +} + #define INPUT_IGNORE_EVENT 0 #define INPUT_PASS_TO_HANDLERS 1 #define INPUT_PASS_TO_DEVICE 2 @@ -167,6 +172,8 @@ static void input_handle_event(struct input_dev *dev, __change_bit(code, dev->key); if (value) input_start_autorepeat(dev, code); + else + input_stop_autorepeat(dev); } disposition = INPUT_PASS_TO_HANDLERS; @@ -737,11 +744,11 @@ static inline void input_wakeup_procfs_readers(void) static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait) { - int state = input_devices_state; - poll_wait(file, &input_devices_poll_wait, wait); - if (state != input_devices_state) + if (file->f_version != input_devices_state) { + file->f_version = input_devices_state; return POLLIN | POLLRDNORM; + } return 0; } diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 45470f18d7e..f999dc60c3b 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -229,7 +229,8 @@ struct atkbd { /* * System-specific ketymap fixup routine */ -static void (*atkbd_platform_fixup)(struct atkbd *); +static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); +static void *atkbd_platform_fixup_data; static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, ssize_t (*handler)(struct atkbd *, char *)); @@ -834,87 +835,64 @@ static void atkbd_disconnect(struct serio *serio) } /* - * Most special keys (Fn+F?) on Dell laptops do not generate release - * events so we have to do it ourselves. + * generate release events for the keycodes given in data */ -static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) +static void atkbd_apply_forced_release_keylist(struct atkbd* atkbd, + const void *data) { - static const unsigned int forced_release_keys[] = { - 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, - }; - int i; + const unsigned int *keys = data; + unsigned int i; if (atkbd->set == 2) - for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) - __set_bit(forced_release_keys[i], - atkbd->force_release_mask); + for (i = 0; keys[i] != -1U; i++) + __set_bit(keys[i], atkbd->force_release_mask); } /* + * Most special keys (Fn+F?) on Dell laptops do not generate release + * events so we have to do it ourselves. + */ +static unsigned int atkbd_dell_laptop_forced_release_keys[] = { + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, -1U +}; + +/* * Perform fixup for HP system that doesn't generate release * for its video switch */ -static void atkbd_hp_keymap_fixup(struct atkbd *atkbd) -{ - static const unsigned int forced_release_keys[] = { - 0x94, - }; - int i; - - if (atkbd->set == 2) - for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) - __set_bit(forced_release_keys[i], - atkbd->force_release_mask); -} +static unsigned int atkbd_hp_forced_release_keys[] = { + 0x94, -1U +}; /* * Inventec system with broken key release on volume keys */ -static void atkbd_inventec_keymap_fixup(struct atkbd *atkbd) -{ - const unsigned int forced_release_keys[] = { - 0xae, 0xb0, - }; - int i; - - if (atkbd->set == 2) - for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) - __set_bit(forced_release_keys[i], - atkbd->force_release_mask); -} +static unsigned int atkbd_inventec_forced_release_keys[] = { + 0xae, 0xb0, -1U +}; /* * Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release * for its volume buttons */ -static void atkbd_hp_zv6100_keymap_fixup(struct atkbd *atkbd) -{ - const unsigned int forced_release_keys[] = { - 0xae, 0xb0, - }; - int i; - - if (atkbd->set == 2) - for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) - __set_bit(forced_release_keys[i], - atkbd->force_release_mask); -} +static unsigned int atkbd_hp_zv6100_forced_release_keys[] = { + 0xae, 0xb0, -1U +}; /* * Samsung NC10 with Fn+F? key release not working */ -static void atkbd_samsung_keymap_fixup(struct atkbd *atkbd) -{ - const unsigned int forced_release_keys[] = { - 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, - }; - int i; +static unsigned int atkbd_samsung_forced_release_keys[] = { + 0x82, 0x83, 0x84, 0x86, 0x88, 0x89, 0xb3, 0xf7, 0xf9, -1U +}; - if (atkbd->set == 2) - for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++) - __set_bit(forced_release_keys[i], - atkbd->force_release_mask); -} +/* + * The volume up and volume down special keys on a Fujitsu Amilo PA 1510 laptop + * do not generate release events so we have to do it ourselves. + */ +static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = { + 0xb0, 0xae, -1U +}; /* * atkbd_set_keycode_table() initializes keyboard's keycode table @@ -967,7 +945,7 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd) * Perform additional fixups */ if (atkbd_platform_fixup) - atkbd_platform_fixup(atkbd); + atkbd_platform_fixup(atkbd, atkbd_platform_fixup_data); } /* @@ -1492,9 +1470,11 @@ static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf) return sprintf(buf, "%lu\n", atkbd->err_count); } -static int __init atkbd_setup_fixup(const struct dmi_system_id *id) +static int __init atkbd_setup_forced_release(const struct dmi_system_id *id) { - atkbd_platform_fixup = id->driver_data; + atkbd_platform_fixup = atkbd_apply_forced_release_keylist; + atkbd_platform_fixup_data = id->driver_data; + return 0; } @@ -1505,8 +1485,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ }, - .callback = atkbd_setup_fixup, - .driver_data = atkbd_dell_laptop_keymap_fixup, + .callback = atkbd_setup_forced_release, + .driver_data = atkbd_dell_laptop_forced_release_keys, }, { .ident = "Dell Laptop", @@ -1514,8 +1494,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ }, - .callback = atkbd_setup_fixup, - .driver_data = atkbd_dell_laptop_keymap_fixup, + .callback = atkbd_setup_forced_release, + .driver_data = atkbd_dell_laptop_forced_release_keys, }, { .ident = "HP 2133", @@ -1523,8 +1503,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"), }, - .callback = atkbd_setup_fixup, - .driver_data = atkbd_hp_keymap_fixup, + .callback = atkbd_setup_forced_release, + .driver_data = atkbd_hp_forced_release_keys, }, { .ident = "HP Pavilion ZV6100", @@ -1532,8 +1512,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"), }, - .callback = atkbd_setup_fixup, - .driver_data = atkbd_hp_zv6100_keymap_fixup, + .callback = atkbd_setup_forced_release, + .driver_data = atkbd_hp_zv6100_forced_release_keys, }, { .ident = "Inventec Symphony", @@ -1541,8 +1521,8 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"), DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"), }, - .callback = atkbd_setup_fixup, - .driver_data = atkbd_inventec_keymap_fixup, + .callback = atkbd_setup_forced_release, + .driver_data = atkbd_inventec_forced_release_keys, }, { .ident = "Samsung NC10", @@ -1550,8 +1530,17 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), DMI_MATCH(DMI_PRODUCT_NAME, "NC10"), }, - .callback = atkbd_setup_fixup, - .driver_data = atkbd_samsung_keymap_fixup, + .callback = atkbd_setup_forced_release, + .driver_data = atkbd_samsung_forced_release_keys, + }, + { + .ident = "Fujitsu Amilo PA 1510", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"), + }, + .callback = atkbd_setup_forced_release, + .driver_data = atkbd_amilo_pa1510_forced_release_keys, }, { } }; diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index ee855c5202e..e94b7d735ac 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -211,8 +211,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev) if (!pdata->debounce_time || pdata->debounce_time > MAX_MULT || !pdata->coldrive_time || pdata->coldrive_time > MAX_MULT) { - printk(KERN_ERR DRV_NAME - ": Invalid Debounce/Columdrive Time from pdata\n"); + printk(KERN_WARNING DRV_NAME + ": Invalid Debounce/Columndrive Time in platform data\n"); bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */ } else { bfin_write_KPAD_MSEL( diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index aacf71f3cd4..e9d639ec283 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c @@ -198,45 +198,28 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) } -/* initialise HIL */ -static int __init -hil_keyb_init(void) +/* initialize HIL */ +static int __devinit hil_keyb_init(void) { unsigned char c; unsigned int i, kbid; wait_queue_head_t hil_wait; int err; - if (hil_dev.dev) { + if (hil_dev.dev) return -ENODEV; /* already initialized */ - } + init_waitqueue_head(&hil_wait); spin_lock_init(&hil_dev.lock); + hil_dev.dev = input_allocate_device(); if (!hil_dev.dev) return -ENOMEM; -#if defined(CONFIG_HP300) - if (!MACH_IS_HP300) { - err = -ENODEV; - goto err1; - } - if (!hwreg_present((void *)(HILBASE + HIL_DATA))) { - printk(KERN_ERR "HIL: hardware register was not found\n"); - err = -ENODEV; - goto err1; - } - if (!request_region(HILBASE + HIL_DATA, 2, "hil")) { - printk(KERN_ERR "HIL: IOPORT region already used\n"); - err = -EIO; - goto err1; - } -#endif - err = request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id); if (err) { printk(KERN_ERR "HIL: Can't get IRQ\n"); - goto err2; + goto err1; } /* Turn on interrupts */ @@ -246,11 +229,9 @@ hil_keyb_init(void) hil_dev.valid = 0; /* clear any pending data */ hil_do(HIL_READKBDSADR, NULL, 0); - init_waitqueue_head(&hil_wait); - wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ); - if (!hil_dev.valid) { + wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3 * HZ); + if (!hil_dev.valid) printk(KERN_WARNING "HIL: timed out, assuming no keyboard present\n"); - } c = hil_dev.c; hil_dev.valid = 0; @@ -268,7 +249,7 @@ hil_keyb_init(void) for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++) if (hphilkeyb_keycode[i] != KEY_RESERVED) - set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); + __set_bit(hphilkeyb_keycode[i], hil_dev.dev->keybit); hil_dev.dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); hil_dev.dev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) | @@ -287,34 +268,45 @@ hil_keyb_init(void) err = input_register_device(hil_dev.dev); if (err) { printk(KERN_ERR "HIL: Can't register device\n"); - goto err3; + goto err2; } + printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n", hil_dev.dev->name, kbid, HILBASE, HIL_IRQ); return 0; -err3: +err2: hil_do(HIL_INTOFF, NULL, 0); - disable_irq(HIL_IRQ); free_irq(HIL_IRQ, hil_dev.dev_id); -err2: -#if defined(CONFIG_HP300) - release_region(HILBASE + HIL_DATA, 2); err1: -#endif input_free_device(hil_dev.dev); hil_dev.dev = NULL; return err; } +static void __devexit hil_keyb_exit(void) +{ + if (HIL_IRQ) + free_irq(HIL_IRQ, hil_dev.dev_id); + + /* Turn off interrupts */ + hil_do(HIL_INTOFF, NULL, 0); + + input_unregister_device(hil_dev.dev); + hil_dev.dev = NULL; +} #if defined(CONFIG_PARISC) -static int __init -hil_init_chip(struct parisc_device *dev) +static int __devinit hil_probe_chip(struct parisc_device *dev) { + /* Only allow one HIL keyboard */ + if (hil_dev.dev) + return -ENODEV; + if (!dev->irq) { - printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa.start); + printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%p\n", + (void *)dev->hpa.start); return -ENODEV; } @@ -327,51 +319,79 @@ hil_init_chip(struct parisc_device *dev) return hil_keyb_init(); } +static int __devexit hil_remove_chip(struct parisc_device *dev) +{ + hil_keyb_exit(); + + return 0; +} + static struct parisc_device_id hil_tbl[] = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 }, { 0, } }; +#if 0 +/* Disabled to avoid conflicts with the HP SDC HIL drivers */ MODULE_DEVICE_TABLE(parisc, hil_tbl); +#endif static struct parisc_driver hil_driver = { - .name = "hil", - .id_table = hil_tbl, - .probe = hil_init_chip, + .name = "hil", + .id_table = hil_tbl, + .probe = hil_probe_chip, + .remove = __devexit_p(hil_remove_chip), }; -#endif /* CONFIG_PARISC */ - static int __init hil_init(void) { -#if defined(CONFIG_PARISC) return register_parisc_driver(&hil_driver); -#else - return hil_keyb_init(); -#endif } - static void __exit hil_exit(void) { - if (HIL_IRQ) { - disable_irq(HIL_IRQ); - free_irq(HIL_IRQ, hil_dev.dev_id); + unregister_parisc_driver(&hil_driver); +} + +#else /* !CONFIG_PARISC */ + +static int __init hil_init(void) +{ + int error; + + /* Only allow one HIL keyboard */ + if (hil_dev.dev) + return -EBUSY; + + if (!MACH_IS_HP300) + return -ENODEV; + + if (!hwreg_present((void *)(HILBASE + HIL_DATA))) { + printk(KERN_ERR "HIL: hardware register was not found\n"); + return -ENODEV; } - /* Turn off interrupts */ - hil_do(HIL_INTOFF, NULL, 0); + if (!request_region(HILBASE + HIL_DATA, 2, "hil")) { + printk(KERN_ERR "HIL: IOPORT region already used\n"); + return -EIO; + } - input_unregister_device(hil_dev.dev); + error = hil_keyb_init(); + if (error) { + release_region(HILBASE + HIL_DATA, 2); + return error; + } - hil_dev.dev = NULL; + return 0; +} -#if defined(CONFIG_PARISC) - unregister_parisc_driver(&hil_driver); -#else - release_region(HILBASE+HIL_DATA, 2); -#endif +static void __exit hil_exit(void) +{ + hil_keyb_exit(); + release_region(HILBASE + HIL_DATA, 2); } +#endif /* CONFIG_PARISC */ + module_init(hil_init); module_exit(hil_exit); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 67e5553f699..203abac1e23 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -227,4 +227,27 @@ config INPUT_PCF50633_PMU Say Y to include support for delivering PMU events via input layer on NXP PCF50633. +config INPUT_GPIO_ROTARY_ENCODER + tristate "Rotary encoders connected to GPIO pins" + depends on GPIOLIB && GENERIC_GPIO + help + Say Y here to add support for rotary encoders connected to GPIO lines. + Check file:Documentation/incput/rotary_encoder.txt for more + information. + + To compile this driver as a module, choose M here: the + module will be called rotary_encoder. + +config INPUT_RB532_BUTTON + tristate "Mikrotik Routerboard 532 button interface" + depends on MIKROTIK_RB532 + depends on GPIOLIB && GENERIC_GPIO + select INPUT_POLLDEV + help + Say Y here if you want support for the S1 button built into + Mikrotik's Routerboard 532. + + To compile this driver as a module, choose M here: the + module will be called rb532_button. + endif diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index bb62e6efacf..eb3f407baed 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -4,21 +4,23 @@ # Each configuration option enables a list of files. -obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o -obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o -obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o -obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o -obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o -obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o -obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o +obj-$(CONFIG_INPUT_APANEL) += apanel.o obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o -obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o -obj-$(CONFIG_INPUT_POWERMATE) += powermate.o -obj-$(CONFIG_INPUT_YEALINK) += yealink.o +obj-$(CONFIG_INPUT_ATLAS_BTNS) += atlas_btns.o obj-$(CONFIG_INPUT_CM109) += cm109.o +obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o -obj-$(CONFIG_INPUT_UINPUT) += uinput.o -obj-$(CONFIG_INPUT_APANEL) += apanel.o -obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o +obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o +obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o +obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o +obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o +obj-$(CONFIG_INPUT_POWERMATE) += powermate.o +obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o +obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o +obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o +obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o +obj-$(CONFIG_INPUT_UINPUT) += uinput.o +obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o +obj-$(CONFIG_INPUT_YEALINK) += yealink.o diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 3c9988dc0e9..922c0514158 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -31,12 +31,73 @@ MODULE_LICENSE("GPL"); * newly configured "channel". */ -static unsigned int channel_mask = 0xFFFF; -module_param(channel_mask, uint, 0644); +enum { + ATI_REMOTE2_MAX_CHANNEL_MASK = 0xFFFF, + ATI_REMOTE2_MAX_MODE_MASK = 0x1F, +}; + +static int ati_remote2_set_mask(const char *val, + struct kernel_param *kp, unsigned int max) +{ + unsigned long mask; + int ret; + + if (!val) + return -EINVAL; + + ret = strict_strtoul(val, 0, &mask); + if (ret) + return ret; + + if (mask & ~max) + return -EINVAL; + + *(unsigned int *)kp->arg = mask; + + return 0; +} + +static int ati_remote2_set_channel_mask(const char *val, + struct kernel_param *kp) +{ + pr_debug("%s()\n", __func__); + + return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_CHANNEL_MASK); +} + +static int ati_remote2_get_channel_mask(char *buffer, struct kernel_param *kp) +{ + pr_debug("%s()\n", __func__); + + return sprintf(buffer, "0x%04x", *(unsigned int *)kp->arg); +} + +static int ati_remote2_set_mode_mask(const char *val, struct kernel_param *kp) +{ + pr_debug("%s()\n", __func__); + + return ati_remote2_set_mask(val, kp, ATI_REMOTE2_MAX_MODE_MASK); +} + +static int ati_remote2_get_mode_mask(char *buffer, struct kernel_param *kp) +{ + pr_debug("%s()\n", __func__); + + return sprintf(buffer, "0x%02x", *(unsigned int *)kp->arg); +} + +static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK; +#define param_check_channel_mask(name, p) __param_check(name, p, unsigned int) +#define param_set_channel_mask ati_remote2_set_channel_mask +#define param_get_channel_mask ati_remote2_get_channel_mask +module_param(channel_mask, channel_mask, 0644); MODULE_PARM_DESC(channel_mask, "Bitmask of channels to accept <15:Channel16>...<1:Channel2><0:Channel1>"); -static unsigned int mode_mask = 0x1F; -module_param(mode_mask, uint, 0644); +static unsigned int mode_mask = ATI_REMOTE2_MAX_MODE_MASK; +#define param_check_mode_mask(name, p) __param_check(name, p, unsigned int) +#define param_set_mode_mask ati_remote2_set_mode_mask +#define param_get_mode_mask ati_remote2_get_mode_mask +module_param(mode_mask, mode_mask, 0644); MODULE_PARM_DESC(mode_mask, "Bitmask of modes to accept <4:PC><3:AUX4><2:AUX3><1:AUX2><0:AUX1>"); static struct usb_device_id ati_remote2_id_table[] = { @@ -133,12 +194,18 @@ struct ati_remote2 { u16 keycode[ATI_REMOTE2_MODES][ARRAY_SIZE(ati_remote2_key_table)]; unsigned int flags; + + unsigned int channel_mask; + unsigned int mode_mask; }; static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); static void ati_remote2_disconnect(struct usb_interface *interface); static int ati_remote2_suspend(struct usb_interface *interface, pm_message_t message); static int ati_remote2_resume(struct usb_interface *interface); +static int ati_remote2_reset_resume(struct usb_interface *interface); +static int ati_remote2_pre_reset(struct usb_interface *interface); +static int ati_remote2_post_reset(struct usb_interface *interface); static struct usb_driver ati_remote2_driver = { .name = "ati_remote2", @@ -147,6 +214,9 @@ static struct usb_driver ati_remote2_driver = { .id_table = ati_remote2_id_table, .suspend = ati_remote2_suspend, .resume = ati_remote2_resume, + .reset_resume = ati_remote2_reset_resume, + .pre_reset = ati_remote2_pre_reset, + .post_reset = ati_remote2_post_reset, .supports_autosuspend = 1, }; @@ -238,7 +308,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2) channel = data[0] >> 4; - if (!((1 << channel) & channel_mask)) + if (!((1 << channel) & ar2->channel_mask)) return; mode = data[0] & 0x0F; @@ -250,7 +320,7 @@ static void ati_remote2_input_mouse(struct ati_remote2 *ar2) return; } - if (!((1 << mode) & mode_mask)) + if (!((1 << mode) & ar2->mode_mask)) return; input_event(idev, EV_REL, REL_X, (s8) data[1]); @@ -277,7 +347,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) channel = data[0] >> 4; - if (!((1 << channel) & channel_mask)) + if (!((1 << channel) & ar2->channel_mask)) return; mode = data[0] & 0x0F; @@ -305,7 +375,7 @@ static void ati_remote2_input_key(struct ati_remote2 *ar2) ar2->mode = mode; } - if (!((1 << mode) & mode_mask)) + if (!((1 << mode) & ar2->mode_mask)) return; index = ati_remote2_lookup(hw_code); @@ -410,7 +480,7 @@ static int ati_remote2_getkeycode(struct input_dev *idev, int index, mode; mode = scancode >> 8; - if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) + if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) return -EINVAL; index = ati_remote2_lookup(scancode & 0xFF); @@ -427,7 +497,7 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc int index, mode, old_keycode; mode = scancode >> 8; - if (mode > ATI_REMOTE2_PC || !((1 << mode) & mode_mask)) + if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) return -EINVAL; index = ati_remote2_lookup(scancode & 0xFF); @@ -550,7 +620,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) } } -static int ati_remote2_setup(struct ati_remote2 *ar2) +static int ati_remote2_setup(struct ati_remote2 *ar2, unsigned int ch_mask) { int r, i, channel; @@ -565,8 +635,8 @@ static int ati_remote2_setup(struct ati_remote2 *ar2) channel = 0; for (i = 0; i < 16; i++) { - if ((1 << i) & channel_mask) { - if (!(~(1 << i) & 0xFFFF & channel_mask)) + if ((1 << i) & ch_mask) { + if (!(~(1 << i) & ch_mask)) channel = i + 1; break; } @@ -585,6 +655,99 @@ static int ati_remote2_setup(struct ati_remote2 *ar2) return 0; } +static ssize_t ati_remote2_show_channel_mask(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct usb_device *udev = to_usb_device(dev); + struct usb_interface *intf = usb_ifnum_to_if(udev, 0); + struct ati_remote2 *ar2 = usb_get_intfdata(intf); + + return sprintf(buf, "0x%04x\n", ar2->channel_mask); +} + +static ssize_t ati_remote2_store_channel_mask(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_device *udev = to_usb_device(dev); + struct usb_interface *intf = usb_ifnum_to_if(udev, 0); + struct ati_remote2 *ar2 = usb_get_intfdata(intf); + unsigned long mask; + int r; + + if (strict_strtoul(buf, 0, &mask)) + return -EINVAL; + + if (mask & ~ATI_REMOTE2_MAX_CHANNEL_MASK) + return -EINVAL; + + r = usb_autopm_get_interface(ar2->intf[0]); + if (r) { + dev_err(&ar2->intf[0]->dev, + "%s(): usb_autopm_get_interface() = %d\n", __func__, r); + return r; + } + + mutex_lock(&ati_remote2_mutex); + + if (mask != ar2->channel_mask && !ati_remote2_setup(ar2, mask)) + ar2->channel_mask = mask; + + mutex_unlock(&ati_remote2_mutex); + + usb_autopm_put_interface(ar2->intf[0]); + + return count; +} + +static ssize_t ati_remote2_show_mode_mask(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct usb_device *udev = to_usb_device(dev); + struct usb_interface *intf = usb_ifnum_to_if(udev, 0); + struct ati_remote2 *ar2 = usb_get_intfdata(intf); + + return sprintf(buf, "0x%02x\n", ar2->mode_mask); +} + +static ssize_t ati_remote2_store_mode_mask(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_device *udev = to_usb_device(dev); + struct usb_interface *intf = usb_ifnum_to_if(udev, 0); + struct ati_remote2 *ar2 = usb_get_intfdata(intf); + unsigned long mask; + + if (strict_strtoul(buf, 0, &mask)) + return -EINVAL; + + if (mask & ~ATI_REMOTE2_MAX_MODE_MASK) + return -EINVAL; + + ar2->mode_mask = mask; + + return count; +} + +static DEVICE_ATTR(channel_mask, 0644, ati_remote2_show_channel_mask, + ati_remote2_store_channel_mask); + +static DEVICE_ATTR(mode_mask, 0644, ati_remote2_show_mode_mask, + ati_remote2_store_mode_mask); + +static struct attribute *ati_remote2_attrs[] = { + &dev_attr_channel_mask.attr, + &dev_attr_mode_mask.attr, + NULL, +}; + +static struct attribute_group ati_remote2_attr_group = { + .attrs = ati_remote2_attrs, +}; + static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(interface); @@ -615,7 +778,10 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d if (r) goto fail2; - r = ati_remote2_setup(ar2); + ar2->channel_mask = channel_mask; + ar2->mode_mask = mode_mask; + + r = ati_remote2_setup(ar2, ar2->channel_mask); if (r) goto fail2; @@ -624,19 +790,24 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); - r = ati_remote2_input_init(ar2); + r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group); if (r) goto fail2; + r = ati_remote2_input_init(ar2); + if (r) + goto fail3; + usb_set_intfdata(interface, ar2); interface->needs_remote_wakeup = 1; return 0; + fail3: + sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group); fail2: ati_remote2_urb_cleanup(ar2); - usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); fail1: kfree(ar2); @@ -657,6 +828,8 @@ static void ati_remote2_disconnect(struct usb_interface *interface) input_unregister_device(ar2->idev); + sysfs_remove_group(&ar2->udev->dev.kobj, &ati_remote2_attr_group); + ati_remote2_urb_cleanup(ar2); usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); @@ -715,6 +888,78 @@ static int ati_remote2_resume(struct usb_interface *interface) return r; } +static int ati_remote2_reset_resume(struct usb_interface *interface) +{ + struct ati_remote2 *ar2; + struct usb_host_interface *alt = interface->cur_altsetting; + int r = 0; + + if (alt->desc.bInterfaceNumber) + return 0; + + ar2 = usb_get_intfdata(interface); + + dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); + + mutex_lock(&ati_remote2_mutex); + + r = ati_remote2_setup(ar2, ar2->channel_mask); + if (r) + goto out; + + if (ar2->flags & ATI_REMOTE2_OPENED) + r = ati_remote2_submit_urbs(ar2); + + if (!r) + ar2->flags &= ~ATI_REMOTE2_SUSPENDED; + + out: + mutex_unlock(&ati_remote2_mutex); + + return r; +} + +static int ati_remote2_pre_reset(struct usb_interface *interface) +{ + struct ati_remote2 *ar2; + struct usb_host_interface *alt = interface->cur_altsetting; + + if (alt->desc.bInterfaceNumber) + return 0; + + ar2 = usb_get_intfdata(interface); + + dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); + + mutex_lock(&ati_remote2_mutex); + + if (ar2->flags == ATI_REMOTE2_OPENED) + ati_remote2_kill_urbs(ar2); + + return 0; +} + +static int ati_remote2_post_reset(struct usb_interface *interface) +{ + struct ati_remote2 *ar2; + struct usb_host_interface *alt = interface->cur_altsetting; + int r = 0; + + if (alt->desc.bInterfaceNumber) + return 0; + + ar2 = usb_get_intfdata(interface); + + dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); + + if (ar2->flags == ATI_REMOTE2_OPENED) + r = ati_remote2_submit_urbs(ar2); + + mutex_unlock(&ati_remote2_mutex); + + return r; +} + static int __init ati_remote2_init(void) { int r; diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c new file mode 100644 index 00000000000..e2c7f622a0b --- /dev/null +++ b/drivers/input/misc/rb532_button.c @@ -0,0 +1,120 @@ +/* + * Support for the S1 button on Routerboard 532 + * + * Copyright (C) 2009 Phil Sutter <n0-1@freewrt.org> + */ + +#include <linux/input-polldev.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <asm/mach-rc32434/gpio.h> +#include <asm/mach-rc32434/rb.h> + +#define DRV_NAME "rb532-button" + +#define RB532_BTN_RATE 100 /* msec */ +#define RB532_BTN_KSYM BTN_0 + +/* The S1 button state is provided by GPIO pin 1. But as this + * pin is also used for uart input as alternate function, the + * operational modes must be switched first: + * 1) disable uart using set_latch_u5() + * 2) turn off alternate function implicitly through + * gpio_direction_input() + * 3) read the GPIO's current value + * 4) undo step 2 by enabling alternate function (in this + * mode the GPIO direction is fixed, so no change needed) + * 5) turn on uart again + * The GPIO value occurs to be inverted, so pin high means + * button is not pressed. + */ +static bool rb532_button_pressed(void) +{ + int val; + + set_latch_u5(0, LO_FOFF); + gpio_direction_input(GPIO_BTN_S1); + + val = gpio_get_value(GPIO_BTN_S1); + + rb532_gpio_set_func(GPIO_BTN_S1); + set_latch_u5(LO_FOFF, 0); + + return !val; +} + +static void rb532_button_poll(struct input_polled_dev *poll_dev) +{ + input_report_key(poll_dev->input, RB532_BTN_KSYM, + rb532_button_pressed()); + input_sync(poll_dev->input); +} + +static int __devinit rb532_button_probe(struct platform_device *pdev) +{ + struct input_polled_dev *poll_dev; + int error; + + poll_dev = input_allocate_polled_device(); + if (!poll_dev) + return -ENOMEM; + + poll_dev->poll = rb532_button_poll; + poll_dev->poll_interval = RB532_BTN_RATE; + + poll_dev->input->name = "rb532 button"; + poll_dev->input->phys = "rb532/button0"; + poll_dev->input->id.bustype = BUS_HOST; + poll_dev->input->dev.parent = &pdev->dev; + + dev_set_drvdata(&pdev->dev, poll_dev); + + input_set_capability(poll_dev->input, EV_KEY, RB532_BTN_KSYM); + + error = input_register_polled_device(poll_dev); + if (error) { + input_free_polled_device(poll_dev); + return error; + } + + return 0; +} + +static int __devexit rb532_button_remove(struct platform_device *pdev) +{ + struct input_polled_dev *poll_dev = dev_get_drvdata(&pdev->dev); + + input_unregister_polled_device(poll_dev); + input_free_polled_device(poll_dev); + dev_set_drvdata(&pdev->dev, NULL); + + return 0; +} + +static struct platform_driver rb532_button_driver = { + .probe = rb532_button_probe, + .remove = __devexit_p(rb532_button_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init rb532_button_init(void) +{ + return platform_driver_register(&rb532_button_driver); +} + +static void __exit rb532_button_exit(void) +{ + platform_driver_unregister(&rb532_button_driver); +} + +module_init(rb532_button_init); +module_exit(rb532_button_exit); + +MODULE_AUTHOR("Phil Sutter <n0-1@freewrt.org>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Support for S1 button on Routerboard 532"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c new file mode 100644 index 00000000000..5bb3ab51b8c --- /dev/null +++ b/drivers/input/misc/rotary_encoder.c @@ -0,0 +1,221 @@ +/* + * rotary_encoder.c + * + * (c) 2009 Daniel Mack <daniel@caiaq.de> + * + * state machine code inspired by code from Tim Ruetz + * + * A generic driver for rotary encoders connected to GPIO lines. + * See file:Documentation/input/rotary_encoder.txt for more information + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/input.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/gpio.h> +#include <linux/rotary_encoder.h> + +#define DRV_NAME "rotary-encoder" + +struct rotary_encoder { + unsigned int irq_a; + unsigned int irq_b; + unsigned int pos; + unsigned int armed; + unsigned int dir; + struct input_dev *input; + struct rotary_encoder_platform_data *pdata; +}; + +static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) +{ + struct rotary_encoder *encoder = dev_id; + struct rotary_encoder_platform_data *pdata = encoder->pdata; + int a = !!gpio_get_value(pdata->gpio_a); + int b = !!gpio_get_value(pdata->gpio_b); + int state; + + a ^= pdata->inverted_a; + b ^= pdata->inverted_b; + state = (a << 1) | b; + + switch (state) { + + case 0x0: + if (!encoder->armed) + break; + + if (encoder->dir) { + /* turning counter-clockwise */ + encoder->pos += pdata->steps; + encoder->pos--; + encoder->pos %= pdata->steps; + } else { + /* turning clockwise */ + encoder->pos++; + encoder->pos %= pdata->steps; + } + + input_report_abs(encoder->input, pdata->axis, encoder->pos); + input_sync(encoder->input); + + encoder->armed = 0; + break; + + case 0x1: + case 0x2: + if (encoder->armed) + encoder->dir = state - 1; + break; + + case 0x3: + encoder->armed = 1; + break; + } + + return IRQ_HANDLED; +} + +static int __devinit rotary_encoder_probe(struct platform_device *pdev) +{ + struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data; + struct rotary_encoder *encoder; + struct input_dev *input; + int err; + + if (!pdata || !pdata->steps) { + dev_err(&pdev->dev, "invalid platform data\n"); + return -ENOENT; + } + + encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL); + input = input_allocate_device(); + if (!encoder || !input) { + dev_err(&pdev->dev, "failed to allocate memory for device\n"); + err = -ENOMEM; + goto exit_free_mem; + } + + encoder->input = input; + encoder->pdata = pdata; + encoder->irq_a = gpio_to_irq(pdata->gpio_a); + encoder->irq_b = gpio_to_irq(pdata->gpio_b); + + /* create and register the input driver */ + input->name = pdev->name; + input->id.bustype = BUS_HOST; + input->dev.parent = &pdev->dev; + input->evbit[0] = BIT_MASK(EV_ABS); + input_set_abs_params(encoder->input, + pdata->axis, 0, pdata->steps, 0, 1); + + err = input_register_device(input); + if (err) { + dev_err(&pdev->dev, "failed to register input device\n"); + goto exit_free_mem; + } + + /* request the GPIOs */ + err = gpio_request(pdata->gpio_a, DRV_NAME); + if (err) { + dev_err(&pdev->dev, "unable to request GPIO %d\n", + pdata->gpio_a); + goto exit_unregister_input; + } + + err = gpio_request(pdata->gpio_b, DRV_NAME); + if (err) { + dev_err(&pdev->dev, "unable to request GPIO %d\n", + pdata->gpio_b); + goto exit_free_gpio_a; + } + + /* request the IRQs */ + err = request_irq(encoder->irq_a, &rotary_encoder_irq, + IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, + DRV_NAME, encoder); + if (err) { + dev_err(&pdev->dev, "unable to request IRQ %d\n", + encoder->irq_a); + goto exit_free_gpio_b; + } + + err = request_irq(encoder->irq_b, &rotary_encoder_irq, + IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, + DRV_NAME, encoder); + if (err) { + dev_err(&pdev->dev, "unable to request IRQ %d\n", + encoder->irq_b); + goto exit_free_irq_a; + } + + platform_set_drvdata(pdev, encoder); + + return 0; + +exit_free_irq_a: + free_irq(encoder->irq_a, encoder); +exit_free_gpio_b: + gpio_free(pdata->gpio_b); +exit_free_gpio_a: + gpio_free(pdata->gpio_a); +exit_unregister_input: + input_unregister_device(input); + input = NULL; /* so we don't try to free it */ +exit_free_mem: + input_free_device(input); + kfree(encoder); + return err; +} + +static int __devexit rotary_encoder_remove(struct platform_device *pdev) +{ + struct rotary_encoder *encoder = platform_get_drvdata(pdev); + struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data; + + free_irq(encoder->irq_a, encoder); + free_irq(encoder->irq_b, encoder); + gpio_free(pdata->gpio_a); + gpio_free(pdata->gpio_b); + input_unregister_device(encoder->input); + platform_set_drvdata(pdev, NULL); + kfree(encoder); + + return 0; +} + +static struct platform_driver rotary_encoder_driver = { + .probe = rotary_encoder_probe, + .remove = __devexit_p(rotary_encoder_remove), + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + } +}; + +static int __init rotary_encoder_init(void) +{ + return platform_driver_register(&rotary_encoder_driver); +} + +static void __exit rotary_encoder_exit(void) +{ + platform_driver_unregister(&rotary_encoder_driver); +} + +module_init(rotary_encoder_init); +module_exit(rotary_encoder_exit); + +MODULE_ALIAS("platform:" DRV_NAME); +MODULE_DESCRIPTION("GPIO rotary encoder driver"); +MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); +MODULE_LICENSE("GPL v2"); + diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 4f38e6f7dfd..c66cc3d08c2 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -292,4 +292,15 @@ config MOUSE_PXA930_TRKBALL help Say Y here to support PXA930 Trackball mouse. +config MOUSE_MAPLE + tristate "Maple mouse (for the Dreamcast)" + depends on MAPLE + help + This driver supports the Maple mouse on the SEGA Dreamcast. + + Most Dreamcast users, who have a mouse, will say Y here. + + To compile this driver as a module choose M here: the module will be + called maplemouse. + endif diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 8c8a1f236e2..472189468d6 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -6,18 +6,19 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o -obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o -obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o +obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o +obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o +obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o obj-$(CONFIG_MOUSE_INPORT) += inport.o obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o +obj-$(CONFIG_MOUSE_MAPLE) += maplemouse.o obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o obj-$(CONFIG_MOUSE_PS2) += psmouse.o obj-$(CONFIG_MOUSE_PXA930_TRKBALL) += pxa930_trkball.o +obj-$(CONFIG_MOUSE_RISCPC) += rpcmouse.o obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o -obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o -obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o psmouse-objs := psmouse-base.o synaptics.o diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 55cd0fa6833..a1ad2f1a7bb 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -472,7 +472,7 @@ static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse) return -EIO; } - hgpk_dbg(psmouse, "ID: %02x %02x %02x", param[0], param[1], param[2]); + hgpk_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]); /* HGPK signature: 0x67, 0x00, 0x<model> */ if (param[0] != 0x67 || param[1] != 0x00) diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c new file mode 100644 index 00000000000..d196abfb68b --- /dev/null +++ b/drivers/input/mouse/maplemouse.c @@ -0,0 +1,147 @@ +/* + * SEGA Dreamcast mouse driver + * Based on drivers/usb/usbmouse.c + * + * Copyright Yaegashi Takeshi, 2001 + * Adrian McMenamin, 2008 + */ + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/timer.h> +#include <linux/maple.h> + +MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>"); +MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); +MODULE_LICENSE("GPL"); + +struct dc_mouse { + struct input_dev *dev; + struct maple_device *mdev; +}; + +static void dc_mouse_callback(struct mapleq *mq) +{ + int buttons, relx, rely, relz; + struct maple_device *mapledev = mq->dev; + struct dc_mouse *mse = maple_get_drvdata(mapledev); + struct input_dev *dev = mse->dev; + unsigned char *res = mq->recvbuf; + + buttons = ~res[8]; + relx = *(unsigned short *)(res + 12) - 512; + rely = *(unsigned short *)(res + 14) - 512; + relz = *(unsigned short *)(res + 16) - 512; + + input_report_key(dev, BTN_LEFT, buttons & 4); + input_report_key(dev, BTN_MIDDLE, buttons & 9); + input_report_key(dev, BTN_RIGHT, buttons & 2); + input_report_rel(dev, REL_X, relx); + input_report_rel(dev, REL_Y, rely); + input_report_rel(dev, REL_WHEEL, relz); + input_sync(dev); +} + +static int dc_mouse_open(struct input_dev *dev) +{ + struct dc_mouse *mse = dev->dev.platform_data; + + maple_getcond_callback(mse->mdev, dc_mouse_callback, HZ/50, + MAPLE_FUNC_MOUSE); + + return 0; +} + +static void dc_mouse_close(struct input_dev *dev) +{ + struct dc_mouse *mse = dev->dev.platform_data; + + maple_getcond_callback(mse->mdev, dc_mouse_callback, 0, + MAPLE_FUNC_MOUSE); +} + + +static int __devinit probe_maple_mouse(struct device *dev) +{ + struct maple_device *mdev = to_maple_dev(dev); + struct maple_driver *mdrv = to_maple_driver(dev->driver); + struct input_dev *input_dev; + struct dc_mouse *mse; + int error; + + mse = kzalloc(sizeof(struct dc_mouse), GFP_KERNEL); + input_dev = input_allocate_device(); + + if (!mse || !input_dev) { + error = -ENOMEM; + goto fail; + } + + mse->dev = input_dev; + mse->mdev = mdev; + + input_set_drvdata(input_dev, mse); + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); + input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | + BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); + input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | + BIT_MASK(REL_WHEEL); + input_dev->name = mdev->product_name; + input_dev->id.bustype = BUS_HOST; + input_dev->open = dc_mouse_open; + input_dev->close = dc_mouse_close; + + mdev->driver = mdrv; + maple_set_drvdata(mdev, mse); + + error = input_register_device(input_dev); + if (error) + goto fail; + + return 0; + +fail: + input_free_device(input_dev); + maple_set_drvdata(mdev, NULL); + kfree(mse); + mdev->driver = NULL; + return error; +} + +static int __devexit remove_maple_mouse(struct device *dev) +{ + struct maple_device *mdev = to_maple_dev(dev); + struct dc_mouse *mse = maple_get_drvdata(mdev); + + mdev->callback = NULL; + input_unregister_device(mse->dev); + maple_set_drvdata(mdev, NULL); + kfree(mse); + + return 0; +} + +static struct maple_driver dc_mouse_driver = { + .function = MAPLE_FUNC_MOUSE, + .drv = { + .name = "Dreamcast_mouse", + .probe = probe_maple_mouse, + .remove = __devexit_p(remove_maple_mouse), + }, +}; + +static int __init dc_mouse_init(void) +{ + return maple_driver_register(&dc_mouse_driver); +} + +static void __exit dc_mouse_exit(void) +{ + maple_driver_unregister(&dc_mouse_driver); +} + +module_init(dc_mouse_init); +module_exit(dc_mouse_exit); diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index fd09c8df81f..f63995f854f 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c @@ -111,11 +111,8 @@ static int __init pc110pad_init(void) struct pci_dev *dev; int err; - dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); - if (dev) { - pci_dev_put(dev); + if (!no_pci_devices()) return -ENODEV; - } if (!request_region(pc110pad_io, 4, "pc110pad")) { printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 6fa2deff744..83ed2d56b92 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -151,6 +151,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "01"), }, }, + { + .ident = "HP DV9700", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), + DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"), + }, + }, { } }; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index bb6486a8c07..b01fd61dadc 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -29,6 +29,51 @@ config TOUCHSCREEN_ADS7846 To compile this driver as a module, choose M here: the module will be called ads7846. +config TOUCHSCREEN_AD7877 + tristate "AD7877 based touchscreens" + depends on SPI_MASTER + help + Say Y here if you have a touchscreen interface using the + AD7877 controller, and your board-specific initialization + code includes that in its table of SPI devices. + + If unsure, say N (but it's safe to say "Y"). + + To compile this driver as a module, choose M here: the + module will be called ad7877. + +config TOUCHSCREEN_AD7879_I2C + tristate "AD7879 based touchscreens: AD7879-1 I2C Interface" + depends on I2C + select TOUCHSCREEN_AD7879 + help + Say Y here if you have a touchscreen interface using the + AD7879-1 controller, and your board-specific initialization + code includes that in its table of I2C devices. + + If unsure, say N (but it's safe to say "Y"). + + To compile this driver as a module, choose M here: the + module will be called ad7879. + +config TOUCHSCREEN_AD7879_SPI + tristate "AD7879 based touchscreens: AD7879 SPI Interface" + depends on SPI_MASTER && TOUCHSCREEN_AD7879_I2C = n + select TOUCHSCREEN_AD7879 + help + Say Y here if you have a touchscreen interface using the + AD7879 controller, and your board-specific initialization + code includes that in its table of SPI devices. + + If unsure, say N (but it's safe to say "Y"). + + To compile this driver as a module, choose M here: the + module will be called ad7879. + +config TOUCHSCREEN_AD7879 + tristate + default n + config TOUCHSCREEN_BITSY tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" depends on SA1100_BITSY @@ -308,6 +353,19 @@ config TOUCHSCREEN_WM97XX_MAINSTONE To compile this driver as a module, choose M here: the module will be called mainstone-wm97xx. +config TOUCHSCREEN_WM97XX_ZYLONITE + tristate "Zylonite accelerated touch" + depends on TOUCHSCREEN_WM97XX && MACH_ZYLONITE + select TOUCHSCREEN_WM9713 + help + Say Y here for support for streaming mode with the touchscreen + on Zylonite systems. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called zylonite-wm97xx. + config TOUCHSCREEN_USB_COMPOSITE tristate "USB Touchscreen Driver" depends on USB_ARCH_HAS_HCD diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index d3375aff46f..6700f7b9d16 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -6,6 +6,8 @@ wm97xx-ts-y := wm97xx-core.o +obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o +obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o @@ -34,3 +36,4 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o +obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c new file mode 100644 index 00000000000..e4728a28f49 --- /dev/null +++ b/drivers/input/touchscreen/ad7877.c @@ -0,0 +1,844 @@ +/* + * Copyright (C) 2006-2008 Michael Hennerich, Analog Devices Inc. + * + * Description: AD7877 based touchscreen, sensor (ADCs), DAC and GPIO driver + * Based on: ads7846.c + * + * 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 + * + * History: + * Copyright (c) 2005 David Brownell + * Copyright (c) 2006 Nokia Corporation + * Various changes: Imre Deak <imre.deak@nokia.com> + * + * Using code from: + * - corgi_ts.c + * Copyright (C) 2004-2005 Richard Purdie + * - omap_ts.[hc], ads7846.h, ts_osk.c + * Copyright (C) 2002 MontaVista Software + * Copyright (C) 2004 Texas Instruments + * Copyright (C) 2005 Dirk Behme + */ + + +#include <linux/device.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/spi/spi.h> +#include <linux/spi/ad7877.h> +#include <asm/irq.h> + +#define TS_PEN_UP_TIMEOUT msecs_to_jiffies(50) + +#define MAX_SPI_FREQ_HZ 20000000 +#define MAX_12BIT ((1<<12)-1) + +#define AD7877_REG_ZEROS 0 +#define AD7877_REG_CTRL1 1 +#define AD7877_REG_CTRL2 2 +#define AD7877_REG_ALERT 3 +#define AD7877_REG_AUX1HIGH 4 +#define AD7877_REG_AUX1LOW 5 +#define AD7877_REG_BAT1HIGH 6 +#define AD7877_REG_BAT1LOW 7 +#define AD7877_REG_BAT2HIGH 8 +#define AD7877_REG_BAT2LOW 9 +#define AD7877_REG_TEMP1HIGH 10 +#define AD7877_REG_TEMP1LOW 11 +#define AD7877_REG_SEQ0 12 +#define AD7877_REG_SEQ1 13 +#define AD7877_REG_DAC 14 +#define AD7877_REG_NONE1 15 +#define AD7877_REG_EXTWRITE 15 +#define AD7877_REG_XPLUS 16 +#define AD7877_REG_YPLUS 17 +#define AD7877_REG_Z2 18 +#define AD7877_REG_aux1 19 +#define AD7877_REG_aux2 20 +#define AD7877_REG_aux3 21 +#define AD7877_REG_bat1 22 +#define AD7877_REG_bat2 23 +#define AD7877_REG_temp1 24 +#define AD7877_REG_temp2 25 +#define AD7877_REG_Z1 26 +#define AD7877_REG_GPIOCTRL1 27 +#define AD7877_REG_GPIOCTRL2 28 +#define AD7877_REG_GPIODATA 29 +#define AD7877_REG_NONE2 30 +#define AD7877_REG_NONE3 31 + +#define AD7877_SEQ_YPLUS_BIT (1<<11) +#define AD7877_SEQ_XPLUS_BIT (1<<10) +#define AD7877_SEQ_Z2_BIT (1<<9) +#define AD7877_SEQ_AUX1_BIT (1<<8) +#define AD7877_SEQ_AUX2_BIT (1<<7) +#define AD7877_SEQ_AUX3_BIT (1<<6) +#define AD7877_SEQ_BAT1_BIT (1<<5) +#define AD7877_SEQ_BAT2_BIT (1<<4) +#define AD7877_SEQ_TEMP1_BIT (1<<3) +#define AD7877_SEQ_TEMP2_BIT (1<<2) +#define AD7877_SEQ_Z1_BIT (1<<1) + +enum { + AD7877_SEQ_YPOS = 0, + AD7877_SEQ_XPOS = 1, + AD7877_SEQ_Z2 = 2, + AD7877_SEQ_AUX1 = 3, + AD7877_SEQ_AUX2 = 4, + AD7877_SEQ_AUX3 = 5, + AD7877_SEQ_BAT1 = 6, + AD7877_SEQ_BAT2 = 7, + AD7877_SEQ_TEMP1 = 8, + AD7877_SEQ_TEMP2 = 9, + AD7877_SEQ_Z1 = 10, + AD7877_NR_SENSE = 11, +}; + +/* DAC Register Default RANGE 0 to Vcc, Volatge Mode, DAC On */ +#define AD7877_DAC_CONF 0x1 + +/* If gpio3 is set AUX3/GPIO3 acts as GPIO Output */ +#define AD7877_EXTW_GPIO_3_CONF 0x1C4 +#define AD7877_EXTW_GPIO_DATA 0x200 + +/* Control REG 2 */ +#define AD7877_TMR(x) ((x & 0x3) << 0) +#define AD7877_REF(x) ((x & 0x1) << 2) +#define AD7877_POL(x) ((x & 0x1) << 3) +#define AD7877_FCD(x) ((x & 0x3) << 4) +#define AD7877_PM(x) ((x & 0x3) << 6) +#define AD7877_ACQ(x) ((x & 0x3) << 8) +#define AD7877_AVG(x) ((x & 0x3) << 10) + +/* Control REG 1 */ +#define AD7877_SER (1 << 11) /* non-differential */ +#define AD7877_DFR (0 << 11) /* differential */ + +#define AD7877_MODE_NOC (0) /* Do not convert */ +#define AD7877_MODE_SCC (1) /* Single channel conversion */ +#define AD7877_MODE_SEQ0 (2) /* Sequence 0 in Slave Mode */ +#define AD7877_MODE_SEQ1 (3) /* Sequence 1 in Master Mode */ + +#define AD7877_CHANADD(x) ((x&0xF)<<7) +#define AD7877_READADD(x) ((x)<<2) +#define AD7877_WRITEADD(x) ((x)<<12) + +#define AD7877_READ_CHAN(x) (AD7877_WRITEADD(AD7877_REG_CTRL1) | AD7877_SER | \ + AD7877_MODE_SCC | AD7877_CHANADD(AD7877_REG_ ## x) | \ + AD7877_READADD(AD7877_REG_ ## x)) + +#define AD7877_MM_SEQUENCE (AD7877_SEQ_YPLUS_BIT | AD7877_SEQ_XPLUS_BIT | \ + AD7877_SEQ_Z2_BIT | AD7877_SEQ_Z1_BIT) + +/* + * Non-touchscreen sensors only use single-ended conversions. + */ + +struct ser_req { + u16 reset; + u16 ref_on; + u16 command; + u16 sample; + struct spi_message msg; + struct spi_transfer xfer[6]; +}; + +struct ad7877 { + struct input_dev *input; + char phys[32]; + + struct spi_device *spi; + u16 model; + u16 vref_delay_usecs; + u16 x_plate_ohms; + u16 pressure_max; + + u16 cmd_crtl1; + u16 cmd_crtl2; + u16 cmd_dummy; + u16 dac; + + u8 stopacq_polarity; + u8 first_conversion_delay; + u8 acquisition_time; + u8 averaging; + u8 pen_down_acc_interval; + + u16 conversion_data[AD7877_NR_SENSE]; + + struct spi_transfer xfer[AD7877_NR_SENSE + 2]; + struct spi_message msg; + + struct mutex mutex; + unsigned disabled:1; /* P: mutex */ + unsigned gpio3:1; /* P: mutex */ + unsigned gpio4:1; /* P: mutex */ + + spinlock_t lock; + struct timer_list timer; /* P: lock */ + unsigned pending:1; /* P: lock */ +}; + +static int gpio3; +module_param(gpio3, int, 0); +MODULE_PARM_DESC(gpio3, "If gpio3 is set to 1 AUX3 acts as GPIO3"); + +/* + * ad7877_read/write are only used for initial setup and for sysfs controls. + * The main traffic is done using spi_async() in the interrupt handler. + */ + +static int ad7877_read(struct spi_device *spi, u16 reg) +{ + struct ser_req *req; + int status, ret; + + req = kzalloc(sizeof *req, GFP_KERNEL); + if (!req) + return -ENOMEM; + + spi_message_init(&req->msg); + + req->command = (u16) (AD7877_WRITEADD(AD7877_REG_CTRL1) | + AD7877_READADD(reg)); + req->xfer[0].tx_buf = &req->command; + req->xfer[0].len = 2; + + req->xfer[1].rx_buf = &req->sample; + req->xfer[1].len = 2; + + spi_message_add_tail(&req->xfer[0], &req->msg); + spi_message_add_tail(&req->xfer[1], &req->msg); + + status = spi_sync(spi, &req->msg); + ret = status ? : req->sample; + + kfree(req); + + return ret; +} + +static int ad7877_write(struct spi_device *spi, u16 reg, u16 val) +{ + struct ser_req *req; + int status; + + req = kzalloc(sizeof *req, GFP_KERNEL); + if (!req) + return -ENOMEM; + + spi_message_init(&req->msg); + + req->command = (u16) (AD7877_WRITEADD(reg) | (val & MAX_12BIT)); + req->xfer[0].tx_buf = &req->command; + req->xfer[0].len = 2; + + spi_message_add_tail(&req->xfer[0], &req->msg); + + status = spi_sync(spi, &req->msg); + + kfree(req); + + return status; +} + +static int ad7877_read_adc(struct spi_device *spi, unsigned command) +{ + struct ad7877 *ts = dev_get_drvdata(&spi->dev); + struct ser_req *req; + int status; + int sample; + int i; + + req = kzalloc(sizeof *req, GFP_KERNEL); + if (!req) + return -ENOMEM; + + spi_message_init(&req->msg); + + /* activate reference, so it has time to settle; */ + req->ref_on = AD7877_WRITEADD(AD7877_REG_CTRL2) | + AD7877_POL(ts->stopacq_polarity) | + AD7877_AVG(0) | AD7877_PM(2) | AD7877_TMR(0) | + AD7877_ACQ(ts->acquisition_time) | AD7877_FCD(0); + + req->reset = AD7877_WRITEADD(AD7877_REG_CTRL1) | AD7877_MODE_NOC; + + req->command = (u16) command; + + req->xfer[0].tx_buf = &req->reset; + req->xfer[0].len = 2; + + req->xfer[1].tx_buf = &req->ref_on; + req->xfer[1].len = 2; + req->xfer[1].delay_usecs = ts->vref_delay_usecs; + + req->xfer[2].tx_buf = &req->command; + req->xfer[2].len = 2; + req->xfer[2].delay_usecs = ts->vref_delay_usecs; + + req->xfer[3].rx_buf = &req->sample; + req->xfer[3].len = 2; + + req->xfer[4].tx_buf = &ts->cmd_crtl2; /*REF OFF*/ + req->xfer[4].len = 2; + + req->xfer[5].tx_buf = &ts->cmd_crtl1; /*DEFAULT*/ + req->xfer[5].len = 2; + + /* group all the transfers together, so we can't interfere with + * reading touchscreen state; disable penirq while sampling + */ + for (i = 0; i < 6; i++) + spi_message_add_tail(&req->xfer[i], &req->msg); + + status = spi_sync(spi, &req->msg); + sample = req->sample; + + kfree(req); + + return status ? : sample; +} + +static void ad7877_rx(struct ad7877 *ts) +{ + struct input_dev *input_dev = ts->input; + unsigned Rt; + u16 x, y, z1, z2; + + x = ts->conversion_data[AD7877_SEQ_XPOS] & MAX_12BIT; + y = ts->conversion_data[AD7877_SEQ_YPOS] & MAX_12BIT; + z1 = ts->conversion_data[AD7877_SEQ_Z1] & MAX_12BIT; + z2 = ts->conversion_data[AD7877_SEQ_Z2] & MAX_12BIT; + + /* + * The samples processed here are already preprocessed by the AD7877. + * The preprocessing function consists of an averaging filter. + * The combination of 'first conversion delay' and averaging provides a robust solution, + * discarding the spurious noise in the signal and keeping only the data of interest. + * The size of the averaging filter is programmable. (dev.platform_data, see linux/spi/ad7877.h) + * Other user-programmable conversion controls include variable acquisition time, + * and first conversion delay. Up to 16 averages can be taken per conversion. + */ + + if (likely(x && z1)) { + /* compute touch pressure resistance using equation #1 */ + Rt = (z2 - z1) * x * ts->x_plate_ohms; + Rt /= z1; + Rt = (Rt + 2047) >> 12; + + input_report_abs(input_dev, ABS_X, x); + input_report_abs(input_dev, ABS_Y, y); + input_report_abs(input_dev, ABS_PRESSURE, Rt); + input_sync(input_dev); + } +} + +static inline void ad7877_ts_event_release(struct ad7877 *ts) +{ + struct input_dev *input_dev = ts->input; + + input_report_abs(input_dev, ABS_PRESSURE, 0); + input_sync(input_dev); +} + +static void ad7877_timer(unsigned long handle) +{ + struct ad7877 *ts = (void *)handle; + + ad7877_ts_event_release(ts); +} + +static irqreturn_t ad7877_irq(int irq, void *handle) +{ + struct ad7877 *ts = handle; + unsigned long flags; + int status; + + /* + * The repeated conversion sequencer controlled by TMR kicked off + * too fast. We ignore the last and process the sample sequence + * currently in the queue. It can't be older than 9.4ms, and we + * need to avoid that ts->msg doesn't get issued twice while in work. + */ + + spin_lock_irqsave(&ts->lock, flags); + if (!ts->pending) { + ts->pending = 1; + + status = spi_async(ts->spi, &ts->msg); + if (status) + dev_err(&ts->spi->dev, "spi_sync --> %d\n", status); + } + spin_unlock_irqrestore(&ts->lock, flags); + + return IRQ_HANDLED; +} + +static void ad7877_callback(void *_ts) +{ + struct ad7877 *ts = _ts; + + spin_lock_irq(&ts->lock); + + ad7877_rx(ts); + ts->pending = 0; + mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT); + + spin_unlock_irq(&ts->lock); +} + +static void ad7877_disable(struct ad7877 *ts) +{ + mutex_lock(&ts->mutex); + + if (!ts->disabled) { + ts->disabled = 1; + disable_irq(ts->spi->irq); + + /* Wait for spi_async callback */ + while (ts->pending) + msleep(1); + + if (del_timer_sync(&ts->timer)) + ad7877_ts_event_release(ts); + } + + /* we know the chip's in lowpower mode since we always + * leave it that way after every request + */ + + mutex_unlock(&ts->mutex); +} + +static void ad7877_enable(struct ad7877 *ts) +{ + mutex_lock(&ts->mutex); + + if (ts->disabled) { + ts->disabled = 0; + enable_irq(ts->spi->irq); + } + + mutex_unlock(&ts->mutex); +} + +#define SHOW(name) static ssize_t \ +name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ +{ \ + struct ad7877 *ts = dev_get_drvdata(dev); \ + ssize_t v = ad7877_read_adc(ts->spi, \ + AD7877_READ_CHAN(name)); \ + if (v < 0) \ + return v; \ + return sprintf(buf, "%u\n", (unsigned) v); \ +} \ +static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); + +SHOW(aux1) +SHOW(aux2) +SHOW(aux3) +SHOW(bat1) +SHOW(bat2) +SHOW(temp1) +SHOW(temp2) + +static ssize_t ad7877_disable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ad7877 *ts = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", ts->disabled); +} + +static ssize_t ad7877_disable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ad7877 *ts = dev_get_drvdata(dev); + unsigned long val; + int error; + + error = strict_strtoul(buf, 10, &val); + if (error) + return error; + + if (val) + ad7877_disable(ts); + else + ad7877_enable(ts); + + return count; +} + +static DEVICE_ATTR(disable, 0664, ad7877_disable_show, ad7877_disable_store); + +static ssize_t ad7877_dac_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ad7877 *ts = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", ts->dac); +} + +static ssize_t ad7877_dac_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ad7877 *ts = dev_get_drvdata(dev); + unsigned long val; + int error; + + error = strict_strtoul(buf, 10, &val); + if (error) + return error; + + mutex_lock(&ts->mutex); + ts->dac = val & 0xFF; + ad7877_write(ts->spi, AD7877_REG_DAC, (ts->dac << 4) | AD7877_DAC_CONF); + mutex_unlock(&ts->mutex); + + return count; +} + +static DEVICE_ATTR(dac, 0664, ad7877_dac_show, ad7877_dac_store); + +static ssize_t ad7877_gpio3_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ad7877 *ts = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", ts->gpio3); +} + +static ssize_t ad7877_gpio3_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ad7877 *ts = dev_get_drvdata(dev); + unsigned long val; + int error; + + error = strict_strtoul(buf, 10, &val); + if (error) + return error; + + mutex_lock(&ts->mutex); + ts->gpio3 = !!val; + ad7877_write(ts->spi, AD7877_REG_EXTWRITE, AD7877_EXTW_GPIO_DATA | + (ts->gpio4 << 4) | (ts->gpio3 << 5)); + mutex_unlock(&ts->mutex); + + return count; +} + +static DEVICE_ATTR(gpio3, 0664, ad7877_gpio3_show, ad7877_gpio3_store); + +static ssize_t ad7877_gpio4_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ad7877 *ts = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", ts->gpio4); +} + +static ssize_t ad7877_gpio4_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ad7877 *ts = dev_get_drvdata(dev); + unsigned long val; + int error; + + error = strict_strtoul(buf, 10, &val); + if (error) + return error; + + mutex_lock(&ts->mutex); + ts->gpio4 = !!val; + ad7877_write(ts->spi, AD7877_REG_EXTWRITE, AD7877_EXTW_GPIO_DATA | + (ts->gpio4 << 4) | (ts->gpio3 << 5)); + mutex_unlock(&ts->mutex); + + return count; +} + +static DEVICE_ATTR(gpio4, 0664, ad7877_gpio4_show, ad7877_gpio4_store); + +static struct attribute *ad7877_attributes[] = { + &dev_attr_temp1.attr, + &dev_attr_temp2.attr, + &dev_attr_aux1.attr, + &dev_attr_aux2.attr, + &dev_attr_bat1.attr, + &dev_attr_bat2.attr, + &dev_attr_disable.attr, + &dev_attr_dac.attr, + &dev_attr_gpio4.attr, + NULL +}; + +static const struct attribute_group ad7877_attr_group = { + .attrs = ad7877_attributes, +}; + +static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts) +{ + struct spi_message *m; + int i; + + ts->cmd_crtl2 = AD7877_WRITEADD(AD7877_REG_CTRL2) | + AD7877_POL(ts->stopacq_polarity) | + AD7877_AVG(ts->averaging) | AD7877_PM(1) | + AD7877_TMR(ts->pen_down_acc_interval) | + AD7877_ACQ(ts->acquisition_time) | + AD7877_FCD(ts->first_conversion_delay); + + ad7877_write(spi, AD7877_REG_CTRL2, ts->cmd_crtl2); + + ts->cmd_crtl1 = AD7877_WRITEADD(AD7877_REG_CTRL1) | + AD7877_READADD(AD7877_REG_XPLUS-1) | + AD7877_MODE_SEQ1 | AD7877_DFR; + + ad7877_write(spi, AD7877_REG_CTRL1, ts->cmd_crtl1); + + ts->cmd_dummy = 0; + + m = &ts->msg; + + spi_message_init(m); + + m->complete = ad7877_callback; + m->context = ts; + + ts->xfer[0].tx_buf = &ts->cmd_crtl1; + ts->xfer[0].len = 2; + + spi_message_add_tail(&ts->xfer[0], m); + + ts->xfer[1].tx_buf = &ts->cmd_dummy; /* Send ZERO */ + ts->xfer[1].len = 2; + + spi_message_add_tail(&ts->xfer[1], m); + + for (i = 0; i < 11; i++) { + ts->xfer[i + 2].rx_buf = &ts->conversion_data[AD7877_SEQ_YPOS + i]; + ts->xfer[i + 2].len = 2; + spi_message_add_tail(&ts->xfer[i + 2], m); + } +} + +static int __devinit ad7877_probe(struct spi_device *spi) +{ + struct ad7877 *ts; + struct input_dev *input_dev; + struct ad7877_platform_data *pdata = spi->dev.platform_data; + int err; + u16 verify; + + if (!spi->irq) { + dev_dbg(&spi->dev, "no IRQ?\n"); + return -ENODEV; + } + + if (!pdata) { + dev_dbg(&spi->dev, "no platform data?\n"); + return -ENODEV; + } + + /* don't exceed max specified SPI CLK frequency */ + if (spi->max_speed_hz > MAX_SPI_FREQ_HZ) { + dev_dbg(&spi->dev, "SPI CLK %d Hz?\n",spi->max_speed_hz); + return -EINVAL; + } + + ts = kzalloc(sizeof(struct ad7877), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!ts || !input_dev) { + err = -ENOMEM; + goto err_free_mem; + } + + dev_set_drvdata(&spi->dev, ts); + ts->spi = spi; + ts->input = input_dev; + + setup_timer(&ts->timer, ad7877_timer, (unsigned long) ts); + mutex_init(&ts->mutex); + spin_lock_init(&ts->lock); + + ts->model = pdata->model ? : 7877; + ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; + ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; + ts->pressure_max = pdata->pressure_max ? : ~0; + + ts->stopacq_polarity = pdata->stopacq_polarity; + ts->first_conversion_delay = pdata->first_conversion_delay; + ts->acquisition_time = pdata->acquisition_time; + ts->averaging = pdata->averaging; + ts->pen_down_acc_interval = pdata->pen_down_acc_interval; + + snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev)); + + input_dev->name = "AD7877 Touchscreen"; + input_dev->phys = ts->phys; + input_dev->dev.parent = &spi->dev; + + __set_bit(EV_ABS, input_dev->evbit); + __set_bit(ABS_X, input_dev->absbit); + __set_bit(ABS_Y, input_dev->absbit); + __set_bit(ABS_PRESSURE, input_dev->absbit); + + input_set_abs_params(input_dev, ABS_X, + pdata->x_min ? : 0, + pdata->x_max ? : MAX_12BIT, + 0, 0); + input_set_abs_params(input_dev, ABS_Y, + pdata->y_min ? : 0, + pdata->y_max ? : MAX_12BIT, + 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, + pdata->pressure_min, pdata->pressure_max, 0, 0); + + ad7877_write(spi, AD7877_REG_SEQ1, AD7877_MM_SEQUENCE); + + verify = ad7877_read(spi, AD7877_REG_SEQ1); + + if (verify != AD7877_MM_SEQUENCE){ + dev_err(&spi->dev, "%s: Failed to probe %s\n", + dev_name(&spi->dev), input_dev->name); + err = -ENODEV; + goto err_free_mem; + } + + if (gpio3) + ad7877_write(spi, AD7877_REG_EXTWRITE, AD7877_EXTW_GPIO_3_CONF); + + ad7877_setup_ts_def_msg(spi, ts); + + /* Request AD7877 /DAV GPIO interrupt */ + + err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING | + IRQF_SAMPLE_RANDOM, spi->dev.driver->name, ts); + if (err) { + dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); + goto err_free_mem; + } + + err = sysfs_create_group(&spi->dev.kobj, &ad7877_attr_group); + if (err) + goto err_free_irq; + + err = device_create_file(&spi->dev, + gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3); + if (err) + goto err_remove_attr_group; + + err = input_register_device(input_dev); + if (err) + goto err_remove_attr; + + return 0; + +err_remove_attr: + device_remove_file(&spi->dev, + gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3); +err_remove_attr_group: + sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group); +err_free_irq: + free_irq(spi->irq, ts); +err_free_mem: + input_free_device(input_dev); + kfree(ts); + dev_set_drvdata(&spi->dev, NULL); + return err; +} + +static int __devexit ad7877_remove(struct spi_device *spi) +{ + struct ad7877 *ts = dev_get_drvdata(&spi->dev); + + sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group); + device_remove_file(&spi->dev, + gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3); + + ad7877_disable(ts); + free_irq(ts->spi->irq, ts); + + input_unregister_device(ts->input); + kfree(ts); + + dev_dbg(&spi->dev, "unregistered touchscreen\n"); + dev_set_drvdata(&spi->dev, NULL); + + return 0; +} + +#ifdef CONFIG_PM +static int ad7877_suspend(struct spi_device *spi, pm_message_t message) +{ + struct ad7877 *ts = dev_get_drvdata(&spi->dev); + + ad7877_disable(ts); + + return 0; +} + +static int ad7877_resume(struct spi_device *spi) +{ + struct ad7877 *ts = dev_get_drvdata(&spi->dev); + + ad7877_enable(ts); + + return 0; +} +#else +#define ad7877_suspend NULL +#define ad7877_resume NULL +#endif + +static struct spi_driver ad7877_driver = { + .driver = { + .name = "ad7877", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = ad7877_probe, + .remove = __devexit_p(ad7877_remove), + .suspend = ad7877_suspend, + .resume = ad7877_resume, +}; + +static int __init ad7877_init(void) +{ + return spi_register_driver(&ad7877_driver); +} +module_init(ad7877_init); + +static void __exit ad7877_exit(void) +{ + spi_unregister_driver(&ad7877_driver); +} +module_exit(ad7877_exit); + +MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_DESCRIPTION("AD7877 touchscreen Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c new file mode 100644 index 00000000000..ea4c61d6868 --- /dev/null +++ b/drivers/input/touchscreen/ad7879.c @@ -0,0 +1,782 @@ +/* + * Copyright (C) 2008 Michael Hennerich, Analog Devices Inc. + * + * Description: AD7879 based touchscreen, and GPIO driver (I2C/SPI Interface) + * + * 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 + * + * History: + * Copyright (c) 2005 David Brownell + * Copyright (c) 2006 Nokia Corporation + * Various changes: Imre Deak <imre.deak@nokia.com> + * + * Using code from: + * - corgi_ts.c + * Copyright (C) 2004-2005 Richard Purdie + * - omap_ts.[hc], ads7846.h, ts_osk.c + * Copyright (C) 2002 MontaVista Software + * Copyright (C) 2004 Texas Instruments + * Copyright (C) 2005 Dirk Behme + * - ad7877.c + * Copyright (C) 2006-2008 Analog Devices Inc. + */ + +#include <linux/device.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/slab.h> +#include <linux/workqueue.h> +#include <linux/spi/spi.h> +#include <linux/i2c.h> + +#include <linux/spi/ad7879.h> + +#define AD7879_REG_ZEROS 0 +#define AD7879_REG_CTRL1 1 +#define AD7879_REG_CTRL2 2 +#define AD7879_REG_CTRL3 3 +#define AD7879_REG_AUX1HIGH 4 +#define AD7879_REG_AUX1LOW 5 +#define AD7879_REG_TEMP1HIGH 6 +#define AD7879_REG_TEMP1LOW 7 +#define AD7879_REG_XPLUS 8 +#define AD7879_REG_YPLUS 9 +#define AD7879_REG_Z1 10 +#define AD7879_REG_Z2 11 +#define AD7879_REG_AUXVBAT 12 +#define AD7879_REG_TEMP 13 +#define AD7879_REG_REVID 14 + +/* Control REG 1 */ +#define AD7879_TMR(x) ((x & 0xFF) << 0) +#define AD7879_ACQ(x) ((x & 0x3) << 8) +#define AD7879_MODE_NOC (0 << 10) /* Do not convert */ +#define AD7879_MODE_SCC (1 << 10) /* Single channel conversion */ +#define AD7879_MODE_SEQ0 (2 << 10) /* Sequence 0 in Slave Mode */ +#define AD7879_MODE_SEQ1 (3 << 10) /* Sequence 1 in Master Mode */ +#define AD7879_MODE_INT (1 << 15) /* PENIRQ disabled INT enabled */ + +/* Control REG 2 */ +#define AD7879_FCD(x) ((x & 0x3) << 0) +#define AD7879_RESET (1 << 4) +#define AD7879_MFS(x) ((x & 0x3) << 5) +#define AD7879_AVG(x) ((x & 0x3) << 7) +#define AD7879_SER (1 << 9) /* non-differential */ +#define AD7879_DFR (0 << 9) /* differential */ +#define AD7879_GPIOPOL (1 << 10) +#define AD7879_GPIODIR (1 << 11) +#define AD7879_GPIO_DATA (1 << 12) +#define AD7879_GPIO_EN (1 << 13) +#define AD7879_PM(x) ((x & 0x3) << 14) +#define AD7879_PM_SHUTDOWN (0) +#define AD7879_PM_DYN (1) +#define AD7879_PM_FULLON (2) + +/* Control REG 3 */ +#define AD7879_TEMPMASK_BIT (1<<15) +#define AD7879_AUXVBATMASK_BIT (1<<14) +#define AD7879_INTMODE_BIT (1<<13) +#define AD7879_GPIOALERTMASK_BIT (1<<12) +#define AD7879_AUXLOW_BIT (1<<11) +#define AD7879_AUXHIGH_BIT (1<<10) +#define AD7879_TEMPLOW_BIT (1<<9) +#define AD7879_TEMPHIGH_BIT (1<<8) +#define AD7879_YPLUS_BIT (1<<7) +#define AD7879_XPLUS_BIT (1<<6) +#define AD7879_Z1_BIT (1<<5) +#define AD7879_Z2_BIT (1<<4) +#define AD7879_AUX_BIT (1<<3) +#define AD7879_VBAT_BIT (1<<2) +#define AD7879_TEMP_BIT (1<<1) + +enum { + AD7879_SEQ_XPOS = 0, + AD7879_SEQ_YPOS = 1, + AD7879_SEQ_Z1 = 2, + AD7879_SEQ_Z2 = 3, + AD7879_NR_SENSE = 4, +}; + +#define MAX_12BIT ((1<<12)-1) +#define TS_PEN_UP_TIMEOUT msecs_to_jiffies(50) + +#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE) +#define AD7879_DEVID 0x7A +typedef struct spi_device bus_device; +#elif defined(CONFIG_TOUCHSCREEN_AD7879_I2C) || defined(CONFIG_TOUCHSCREEN_AD7879_I2C_MODULE) +#define AD7879_DEVID 0x79 +typedef struct i2c_client bus_device; +#endif + +struct ad7879 { + bus_device *bus; + struct input_dev *input; + struct work_struct work; + struct timer_list timer; + + struct mutex mutex; + unsigned disabled:1; /* P: mutex */ + +#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE) + struct spi_message msg; + struct spi_transfer xfer[AD7879_NR_SENSE + 1]; + u16 cmd; +#endif + u16 conversion_data[AD7879_NR_SENSE]; + char phys[32]; + u8 first_conversion_delay; + u8 acquisition_time; + u8 averaging; + u8 pen_down_acc_interval; + u8 median; + u16 x_plate_ohms; + u16 pressure_max; + u16 gpio_init; + u16 cmd_crtl1; + u16 cmd_crtl2; + u16 cmd_crtl3; + unsigned gpio:1; +}; + +static int ad7879_read(bus_device *, u8); +static int ad7879_write(bus_device *, u8, u16); +static void ad7879_collect(struct ad7879 *); + +static void ad7879_report(struct ad7879 *ts) +{ + struct input_dev *input_dev = ts->input; + unsigned Rt; + u16 x, y, z1, z2; + + x = ts->conversion_data[AD7879_SEQ_XPOS] & MAX_12BIT; + y = ts->conversion_data[AD7879_SEQ_YPOS] & MAX_12BIT; + z1 = ts->conversion_data[AD7879_SEQ_Z1] & MAX_12BIT; + z2 = ts->conversion_data[AD7879_SEQ_Z2] & MAX_12BIT; + + /* + * The samples processed here are already preprocessed by the AD7879. + * The preprocessing function consists of a median and an averaging filter. + * The combination of these two techniques provides a robust solution, + * discarding the spurious noise in the signal and keeping only the data of interest. + * The size of both filters is programmable. (dev.platform_data, see linux/spi/ad7879.h) + * Other user-programmable conversion controls include variable acquisition time, + * and first conversion delay. Up to 16 averages can be taken per conversion. + */ + + if (likely(x && z1)) { + /* compute touch pressure resistance using equation #1 */ + Rt = (z2 - z1) * x * ts->x_plate_ohms; + Rt /= z1; + Rt = (Rt + 2047) >> 12; + + input_report_abs(input_dev, ABS_X, x); + input_report_abs(input_dev, ABS_Y, y); + input_report_abs(input_dev, ABS_PRESSURE, Rt); + input_sync(input_dev); + } +} + +static void ad7879_work(struct work_struct *work) +{ + struct ad7879 *ts = container_of(work, struct ad7879, work); + + /* use keventd context to read the result registers */ + ad7879_collect(ts); + ad7879_report(ts); + mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT); +} + +static void ad7879_ts_event_release(struct ad7879 *ts) +{ + struct input_dev *input_dev = ts->input; + + input_report_abs(input_dev, ABS_PRESSURE, 0); + input_sync(input_dev); +} + +static void ad7879_timer(unsigned long handle) +{ + struct ad7879 *ts = (void *)handle; + + ad7879_ts_event_release(ts); +} + +static irqreturn_t ad7879_irq(int irq, void *handle) +{ + struct ad7879 *ts = handle; + + /* The repeated conversion sequencer controlled by TMR kicked off too fast. + * We ignore the last and process the sample sequence currently in the queue. + * It can't be older than 9.4ms + */ + + if (!work_pending(&ts->work)) + schedule_work(&ts->work); + + return IRQ_HANDLED; +} + +static void ad7879_setup(struct ad7879 *ts) +{ + ts->cmd_crtl3 = AD7879_YPLUS_BIT | + AD7879_XPLUS_BIT | + AD7879_Z2_BIT | + AD7879_Z1_BIT | + AD7879_TEMPMASK_BIT | + AD7879_AUXVBATMASK_BIT | + AD7879_GPIOALERTMASK_BIT; + + ts->cmd_crtl2 = AD7879_PM(AD7879_PM_DYN) | AD7879_DFR | + AD7879_AVG(ts->averaging) | + AD7879_MFS(ts->median) | + AD7879_FCD(ts->first_conversion_delay) | + ts->gpio_init; + + ts->cmd_crtl1 = AD7879_MODE_INT | AD7879_MODE_SEQ1 | + AD7879_ACQ(ts->acquisition_time) | + AD7879_TMR(ts->pen_down_acc_interval); + + ad7879_write(ts->bus, AD7879_REG_CTRL2, ts->cmd_crtl2); + ad7879_write(ts->bus, AD7879_REG_CTRL3, ts->cmd_crtl3); + ad7879_write(ts->bus, AD7879_REG_CTRL1, ts->cmd_crtl1); +} + +static void ad7879_disable(struct ad7879 *ts) +{ + mutex_lock(&ts->mutex); + + if (!ts->disabled) { + + ts->disabled = 1; + disable_irq(ts->bus->irq); + + cancel_work_sync(&ts->work); + + if (del_timer_sync(&ts->timer)) + ad7879_ts_event_release(ts); + + ad7879_write(ts->bus, AD7879_REG_CTRL2, + AD7879_PM(AD7879_PM_SHUTDOWN)); + } + + mutex_unlock(&ts->mutex); +} + +static void ad7879_enable(struct ad7879 *ts) +{ + mutex_lock(&ts->mutex); + + if (ts->disabled) { + ad7879_setup(ts); + ts->disabled = 0; + enable_irq(ts->bus->irq); + } + + mutex_unlock(&ts->mutex); +} + +static ssize_t ad7879_disable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ad7879 *ts = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", ts->disabled); +} + +static ssize_t ad7879_disable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ad7879 *ts = dev_get_drvdata(dev); + unsigned long val; + int error; + + error = strict_strtoul(buf, 10, &val); + if (error) + return error; + + if (val) + ad7879_disable(ts); + else + ad7879_enable(ts); + + return count; +} + +static DEVICE_ATTR(disable, 0664, ad7879_disable_show, ad7879_disable_store); + +static ssize_t ad7879_gpio_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ad7879 *ts = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", ts->gpio); +} + +static ssize_t ad7879_gpio_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ad7879 *ts = dev_get_drvdata(dev); + unsigned long val; + int error; + + error = strict_strtoul(buf, 10, &val); + if (error) + return error; + + mutex_lock(&ts->mutex); + ts->gpio = !!val; + error = ad7879_write(ts->bus, AD7879_REG_CTRL2, + ts->gpio ? + ts->cmd_crtl2 & ~AD7879_GPIO_DATA : + ts->cmd_crtl2 | AD7879_GPIO_DATA); + mutex_unlock(&ts->mutex); + + return error ? : count; +} + +static DEVICE_ATTR(gpio, 0664, ad7879_gpio_show, ad7879_gpio_store); + +static struct attribute *ad7879_attributes[] = { + &dev_attr_disable.attr, + &dev_attr_gpio.attr, + NULL +}; + +static const struct attribute_group ad7879_attr_group = { + .attrs = ad7879_attributes, +}; + +static int __devinit ad7879_construct(bus_device *bus, struct ad7879 *ts) +{ + struct input_dev *input_dev; + struct ad7879_platform_data *pdata = bus->dev.platform_data; + int err; + u16 revid; + + if (!bus->irq) { + dev_err(&bus->dev, "no IRQ?\n"); + return -ENODEV; + } + + if (!pdata) { + dev_err(&bus->dev, "no platform data?\n"); + return -ENODEV; + } + + input_dev = input_allocate_device(); + if (!input_dev) + return -ENOMEM; + + ts->input = input_dev; + + setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts); + INIT_WORK(&ts->work, ad7879_work); + mutex_init(&ts->mutex); + + ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; + ts->pressure_max = pdata->pressure_max ? : ~0; + + ts->first_conversion_delay = pdata->first_conversion_delay; + ts->acquisition_time = pdata->acquisition_time; + ts->averaging = pdata->averaging; + ts->pen_down_acc_interval = pdata->pen_down_acc_interval; + ts->median = pdata->median; + + if (pdata->gpio_output) + ts->gpio_init = AD7879_GPIO_EN | + (pdata->gpio_default ? 0 : AD7879_GPIO_DATA); + else + ts->gpio_init = AD7879_GPIO_EN | AD7879_GPIODIR; + + snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&bus->dev)); + + input_dev->name = "AD7879 Touchscreen"; + input_dev->phys = ts->phys; + input_dev->dev.parent = &bus->dev; + + __set_bit(EV_ABS, input_dev->evbit); + __set_bit(ABS_X, input_dev->absbit); + __set_bit(ABS_Y, input_dev->absbit); + __set_bit(ABS_PRESSURE, input_dev->absbit); + + input_set_abs_params(input_dev, ABS_X, + pdata->x_min ? : 0, + pdata->x_max ? : MAX_12BIT, + 0, 0); + input_set_abs_params(input_dev, ABS_Y, + pdata->y_min ? : 0, + pdata->y_max ? : MAX_12BIT, + 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, + pdata->pressure_min, pdata->pressure_max, 0, 0); + + err = ad7879_write(bus, AD7879_REG_CTRL2, AD7879_RESET); + + if (err < 0) { + dev_err(&bus->dev, "Failed to write %s\n", input_dev->name); + goto err_free_mem; + } + + revid = ad7879_read(bus, AD7879_REG_REVID); + + if ((revid & 0xFF) != AD7879_DEVID) { + dev_err(&bus->dev, "Failed to probe %s\n", input_dev->name); + err = -ENODEV; + goto err_free_mem; + } + + ad7879_setup(ts); + + err = request_irq(bus->irq, ad7879_irq, + IRQF_TRIGGER_FALLING | IRQF_SAMPLE_RANDOM, + bus->dev.driver->name, ts); + + if (err) { + dev_err(&bus->dev, "irq %d busy?\n", bus->irq); + goto err_free_mem; + } + + err = sysfs_create_group(&bus->dev.kobj, &ad7879_attr_group); + if (err) + goto err_free_irq; + + err = input_register_device(input_dev); + if (err) + goto err_remove_attr; + + dev_info(&bus->dev, "Rev.%d touchscreen, irq %d\n", + revid >> 8, bus->irq); + + return 0; + +err_remove_attr: + sysfs_remove_group(&bus->dev.kobj, &ad7879_attr_group); +err_free_irq: + free_irq(bus->irq, ts); +err_free_mem: + input_free_device(input_dev); + + return err; +} + +static int __devexit ad7879_destroy(bus_device *bus, struct ad7879 *ts) +{ + ad7879_disable(ts); + sysfs_remove_group(&ts->bus->dev.kobj, &ad7879_attr_group); + free_irq(ts->bus->irq, ts); + input_unregister_device(ts->input); + dev_dbg(&bus->dev, "unregistered touchscreen\n"); + + return 0; +} + +#ifdef CONFIG_PM +static int ad7879_suspend(bus_device *bus, pm_message_t message) +{ + struct ad7879 *ts = dev_get_drvdata(&bus->dev); + + ad7879_disable(ts); + + return 0; +} + +static int ad7879_resume(bus_device *bus) +{ + struct ad7879 *ts = dev_get_drvdata(&bus->dev); + + ad7879_enable(ts); + + return 0; +} +#else +#define ad7879_suspend NULL +#define ad7879_resume NULL +#endif + +#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE) +#define MAX_SPI_FREQ_HZ 5000000 +#define AD7879_CMD_MAGIC 0xE000 +#define AD7879_CMD_READ (1 << 10) +#define AD7879_WRITECMD(reg) (AD7879_CMD_MAGIC | (reg & 0xF)) +#define AD7879_READCMD(reg) (AD7879_CMD_MAGIC | AD7879_CMD_READ | (reg & 0xF)) + +struct ser_req { + u16 command; + u16 data; + struct spi_message msg; + struct spi_transfer xfer[2]; +}; + +/* + * ad7879_read/write are only used for initial setup and for sysfs controls. + * The main traffic is done in ad7879_collect(). + */ + +static int ad7879_read(struct spi_device *spi, u8 reg) +{ + struct ser_req *req; + int status, ret; + + req = kzalloc(sizeof *req, GFP_KERNEL); + if (!req) + return -ENOMEM; + + spi_message_init(&req->msg); + + req->command = (u16) AD7879_READCMD(reg); + req->xfer[0].tx_buf = &req->command; + req->xfer[0].len = 2; + + req->xfer[1].rx_buf = &req->data; + req->xfer[1].len = 2; + + spi_message_add_tail(&req->xfer[0], &req->msg); + spi_message_add_tail(&req->xfer[1], &req->msg); + + status = spi_sync(spi, &req->msg); + ret = status ? : req->data; + + kfree(req); + + return ret; +} + +static int ad7879_write(struct spi_device *spi, u8 reg, u16 val) +{ + struct ser_req *req; + int status; + + req = kzalloc(sizeof *req, GFP_KERNEL); + if (!req) + return -ENOMEM; + + spi_message_init(&req->msg); + + req->command = (u16) AD7879_WRITECMD(reg); + req->xfer[0].tx_buf = &req->command; + req->xfer[0].len = 2; + + req->data = val; + req->xfer[1].tx_buf = &req->data; + req->xfer[1].len = 2; + + spi_message_add_tail(&req->xfer[0], &req->msg); + spi_message_add_tail(&req->xfer[1], &req->msg); + + status = spi_sync(spi, &req->msg); + + kfree(req); + + return status; +} + +static void ad7879_collect(struct ad7879 *ts) +{ + int status = spi_sync(ts->bus, &ts->msg); + + if (status) + dev_err(&ts->bus->dev, "spi_sync --> %d\n", status); +} + +static void ad7879_setup_ts_def_msg(struct ad7879 *ts) +{ + struct spi_message *m; + int i; + + ts->cmd = (u16) AD7879_READCMD(AD7879_REG_XPLUS); + + m = &ts->msg; + spi_message_init(m); + ts->xfer[0].tx_buf = &ts->cmd; + ts->xfer[0].len = 2; + + spi_message_add_tail(&ts->xfer[0], m); + + for (i = 0; i < AD7879_NR_SENSE; i++) { + ts->xfer[i + 1].rx_buf = &ts->conversion_data[i]; + ts->xfer[i + 1].len = 2; + spi_message_add_tail(&ts->xfer[i + 1], m); + } +} + +static int __devinit ad7879_probe(struct spi_device *spi) +{ + struct ad7879 *ts; + int error; + + /* don't exceed max specified SPI CLK frequency */ + if (spi->max_speed_hz > MAX_SPI_FREQ_HZ) { + dev_err(&spi->dev, "SPI CLK %d Hz?\n", spi->max_speed_hz); + return -EINVAL; + } + + ts = kzalloc(sizeof(struct ad7879), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + dev_set_drvdata(&spi->dev, ts); + ts->bus = spi; + + ad7879_setup_ts_def_msg(ts); + + error = ad7879_construct(spi, ts); + if (error) { + dev_set_drvdata(&spi->dev, NULL); + kfree(ts); + } + + return 0; +} + +static int __devexit ad7879_remove(struct spi_device *spi) +{ + struct ad7879 *ts = dev_get_drvdata(&spi->dev); + + ad7879_destroy(spi, ts); + dev_set_drvdata(&spi->dev, NULL); + kfree(ts); + + return 0; +} + +static struct spi_driver ad7879_driver = { + .driver = { + .name = "ad7879", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = ad7879_probe, + .remove = __devexit_p(ad7879_remove), + .suspend = ad7879_suspend, + .resume = ad7879_resume, +}; + +static int __init ad7879_init(void) +{ + return spi_register_driver(&ad7879_driver); +} +module_init(ad7879_init); + +static void __exit ad7879_exit(void) +{ + spi_unregister_driver(&ad7879_driver); +} +module_exit(ad7879_exit); + +#elif defined(CONFIG_TOUCHSCREEN_AD7879_I2C) || defined(CONFIG_TOUCHSCREEN_AD7879_I2C_MODULE) + +/* All registers are word-sized. + * AD7879 uses a high-byte first convention. + */ +static int ad7879_read(struct i2c_client *client, u8 reg) +{ + return swab16(i2c_smbus_read_word_data(client, reg)); +} + +static int ad7879_write(struct i2c_client *client, u8 reg, u16 val) +{ + return i2c_smbus_write_word_data(client, reg, swab16(val)); +} + +static void ad7879_collect(struct ad7879 *ts) +{ + int i; + + for (i = 0; i < AD7879_NR_SENSE; i++) + ts->conversion_data[i] = ad7879_read(ts->bus, + AD7879_REG_XPLUS + i); +} + +static int __devinit ad7879_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ad7879 *ts; + int error; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_WORD_DATA)) { + dev_err(&client->dev, "SMBUS Word Data not Supported\n"); + return -EIO; + } + + ts = kzalloc(sizeof(struct ad7879), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + i2c_set_clientdata(client, ts); + ts->bus = client; + + error = ad7879_construct(client, ts); + if (error) { + i2c_set_clientdata(client, NULL); + kfree(ts); + } + + return 0; +} + +static int __devexit ad7879_remove(struct i2c_client *client) +{ + struct ad7879 *ts = dev_get_drvdata(&client->dev); + + ad7879_destroy(client, ts); + i2c_set_clientdata(client, NULL); + kfree(ts); + + return 0; +} + +static const struct i2c_device_id ad7879_id[] = { + { "ad7879", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ad7879_id); + +static struct i2c_driver ad7879_driver = { + .driver = { + .name = "ad7879", + .owner = THIS_MODULE, + }, + .probe = ad7879_probe, + .remove = __devexit_p(ad7879_remove), + .suspend = ad7879_suspend, + .resume = ad7879_resume, + .id_table = ad7879_id, +}; + +static int __init ad7879_init(void) +{ + return i2c_add_driver(&ad7879_driver); +} +module_init(ad7879_init); + +static void __exit ad7879_exit(void) +{ + i2c_del_driver(&ad7879_driver); +} +module_exit(ad7879_exit); +#endif + +MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); +MODULE_DESCRIPTION("AD7879(-1) touchscreen Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 1d11e2be9ef..dfa6a84ab50 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c @@ -162,6 +162,7 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) input_report_abs(wm->input_dev, ABS_X, x & 0xfff); input_report_abs(wm->input_dev, ABS_Y, y & 0xfff); input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff); + input_report_key(wm->input_dev, BTN_TOUCH, (p != 0)); input_sync(wm->input_dev); reads++; } while (reads < cinfo[sp_idx].reads); @@ -245,7 +246,7 @@ static void wm97xx_irq_enable(struct wm97xx *wm, int enable) if (enable) enable_irq(wm->pen_irq); else - disable_irq(wm->pen_irq); + disable_irq_nosync(wm->pen_irq); } static struct wm97xx_mach_ops mainstone_mach_ops = { diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 54986627def..e868264fe79 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -151,12 +151,14 @@ static void ucb1400_ts_evt_add(struct input_dev *idev, u16 pressure, u16 x, u16 input_report_abs(idev, ABS_X, x); input_report_abs(idev, ABS_Y, y); input_report_abs(idev, ABS_PRESSURE, pressure); + input_report_key(idev, BTN_TOUCH, 1); input_sync(idev); } static void ucb1400_ts_event_release(struct input_dev *idev) { input_report_abs(idev, ABS_PRESSURE, 0); + input_report_key(idev, BTN_TOUCH, 0); input_sync(idev); } @@ -377,7 +379,8 @@ static int ucb1400_ts_probe(struct platform_device *dev) ucb->ts_idev->id.product = ucb->id; ucb->ts_idev->open = ucb1400_ts_open; ucb->ts_idev->close = ucb1400_ts_close; - ucb->ts_idev->evbit[0] = BIT_MASK(EV_ABS); + ucb->ts_idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); + ucb->ts_idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); ucb1400_adc_enable(ucb->ac97); x_res = ucb1400_ts_read_xres(ucb); diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index d15aa11d705..cec480bffe3 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -409,6 +409,7 @@ static int wm97xx_read_samples(struct wm97xx *wm) wm->pen_is_down = 0; dev_dbg(wm->dev, "pen up\n"); input_report_abs(wm->input_dev, ABS_PRESSURE, 0); + input_report_key(wm->input_dev, BTN_TOUCH, 0); input_sync(wm->input_dev); } else if (!(rc & RC_AGAIN)) { /* We need high frequency updates only while @@ -433,6 +434,7 @@ static int wm97xx_read_samples(struct wm97xx *wm) input_report_abs(wm->input_dev, ABS_X, data.x & 0xfff); input_report_abs(wm->input_dev, ABS_Y, data.y & 0xfff); input_report_abs(wm->input_dev, ABS_PRESSURE, data.p & 0xfff); + input_report_key(wm->input_dev, BTN_TOUCH, 1); input_sync(wm->input_dev); wm->pen_is_down = 1; wm->ts_reader_interval = wm->ts_reader_min_interval; @@ -628,18 +630,21 @@ static int wm97xx_probe(struct device *dev) wm->input_dev->phys = "wm97xx"; wm->input_dev->open = wm97xx_ts_input_open; wm->input_dev->close = wm97xx_ts_input_close; - set_bit(EV_ABS, wm->input_dev->evbit); - set_bit(ABS_X, wm->input_dev->absbit); - set_bit(ABS_Y, wm->input_dev->absbit); - set_bit(ABS_PRESSURE, wm->input_dev->absbit); + + __set_bit(EV_ABS, wm->input_dev->evbit); + __set_bit(EV_KEY, wm->input_dev->evbit); + __set_bit(BTN_TOUCH, wm->input_dev->keybit); + input_set_abs_params(wm->input_dev, ABS_X, abs_x[0], abs_x[1], abs_x[2], 0); input_set_abs_params(wm->input_dev, ABS_Y, abs_y[0], abs_y[1], abs_y[2], 0); input_set_abs_params(wm->input_dev, ABS_PRESSURE, abs_p[0], abs_p[1], abs_p[2], 0); + input_set_drvdata(wm->input_dev, wm); wm->input_dev->dev.parent = dev; + ret = input_register_device(wm->input_dev); if (ret < 0) goto dev_alloc_err; diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c new file mode 100644 index 00000000000..41e4359c277 --- /dev/null +++ b/drivers/input/touchscreen/zylonite-wm97xx.c @@ -0,0 +1,240 @@ +/* + * zylonite-wm97xx.c -- Zylonite Continuous Touch screen driver + * + * Copyright 2004, 2007, 2008 Wolfson Microelectronics PLC. + * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> + * Parts Copyright : Ian Molton <spyro@f2s.com> + * Andrew Zabolotny <zap@homelink.ru> + * + * 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. + * + * Notes: + * This is a wm97xx extended touch driver supporting interrupt driven + * and continuous operation on Marvell Zylonite development systems + * (which have a WM9713 on board). + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/wm97xx.h> + +#include <mach/hardware.h> +#include <mach/mfp.h> +#include <mach/regs-ac97.h> + +struct continuous { + u16 id; /* codec id */ + u8 code; /* continuous code */ + u8 reads; /* number of coord reads per read cycle */ + u32 speed; /* number of coords per second */ +}; + +#define WM_READS(sp) ((sp / HZ) + 1) + +static const struct continuous cinfo[] = { + { WM9713_ID2, 0, WM_READS(94), 94 }, + { WM9713_ID2, 1, WM_READS(120), 120 }, + { WM9713_ID2, 2, WM_READS(154), 154 }, + { WM9713_ID2, 3, WM_READS(188), 188 }, +}; + +/* continuous speed index */ +static int sp_idx; + +/* + * Pen sampling frequency (Hz) in continuous mode. + */ +static int cont_rate = 200; +module_param(cont_rate, int, 0); +MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)"); + +/* + * Pressure readback. + * + * Set to 1 to read back pen down pressure + */ +static int pressure; +module_param(pressure, int, 0); +MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)"); + +/* + * AC97 touch data slot. + * + * Touch screen readback data ac97 slot + */ +static int ac97_touch_slot = 5; +module_param(ac97_touch_slot, int, 0); +MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number"); + + +/* flush AC97 slot 5 FIFO machines */ +static void wm97xx_acc_pen_up(struct wm97xx *wm) +{ + int i; + + msleep(1); + + for (i = 0; i < 16; i++) + MODR; +} + +static int wm97xx_acc_pen_down(struct wm97xx *wm) +{ + u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES; + int reads = 0; + static u16 last, tries; + + /* When the AC97 queue has been drained we need to allow time + * to buffer up samples otherwise we end up spinning polling + * for samples. The controller can't have a suitably low + * threashold set to use the notifications it gives. + */ + msleep(1); + + if (tries > 5) { + tries = 0; + return RC_PENUP; + } + + x = MODR; + if (x == last) { + tries++; + return RC_AGAIN; + } + last = x; + do { + if (reads) + x = MODR; + y = MODR; + if (pressure) + p = MODR; + + /* are samples valid */ + if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || + (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || + (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES) + goto up; + + /* coordinate is good */ + tries = 0; + input_report_abs(wm->input_dev, ABS_X, x & 0xfff); + input_report_abs(wm->input_dev, ABS_Y, y & 0xfff); + input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff); + input_report_key(wm->input_dev, BTN_TOUCH, (p != 0)); + input_sync(wm->input_dev); + reads++; + } while (reads < cinfo[sp_idx].reads); +up: + return RC_PENDOWN | RC_AGAIN; +} + +static int wm97xx_acc_startup(struct wm97xx *wm) +{ + int idx; + + /* check we have a codec */ + if (wm->ac97 == NULL) + return -ENODEV; + + /* Go you big red fire engine */ + for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) { + if (wm->id != cinfo[idx].id) + continue; + sp_idx = idx; + if (cont_rate <= cinfo[idx].speed) + break; + } + wm->acc_rate = cinfo[sp_idx].code; + wm->acc_slot = ac97_touch_slot; + dev_info(wm->dev, + "zylonite accelerated touchscreen driver, %d samples/sec\n", + cinfo[sp_idx].speed); + + return 0; +} + +static void wm97xx_irq_enable(struct wm97xx *wm, int enable) +{ + if (enable) + enable_irq(wm->pen_irq); + else + disable_irq_nosync(wm->pen_irq); +} + +static struct wm97xx_mach_ops zylonite_mach_ops = { + .acc_enabled = 1, + .acc_pen_up = wm97xx_acc_pen_up, + .acc_pen_down = wm97xx_acc_pen_down, + .acc_startup = wm97xx_acc_startup, + .irq_enable = wm97xx_irq_enable, + .irq_gpio = WM97XX_GPIO_2, +}; + +static int zylonite_wm97xx_probe(struct platform_device *pdev) +{ + struct wm97xx *wm = platform_get_drvdata(pdev); + int gpio_touch_irq; + + if (cpu_is_pxa320()) + gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO15); + else + gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26); + + wm->pen_irq = IRQ_GPIO(gpio_touch_irq); + set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH); + + wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN, + WM97XX_GPIO_POL_HIGH, + WM97XX_GPIO_STICKY, + WM97XX_GPIO_WAKE); + wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT, + WM97XX_GPIO_POL_HIGH, + WM97XX_GPIO_NOTSTICKY, + WM97XX_GPIO_NOWAKE); + + return wm97xx_register_mach_ops(wm, &zylonite_mach_ops); +} + +static int zylonite_wm97xx_remove(struct platform_device *pdev) +{ + struct wm97xx *wm = platform_get_drvdata(pdev); + + wm97xx_unregister_mach_ops(wm); + + return 0; +} + +static struct platform_driver zylonite_wm97xx_driver = { + .probe = zylonite_wm97xx_probe, + .remove = zylonite_wm97xx_remove, + .driver = { + .name = "wm97xx-touch", + }, +}; + +static int __init zylonite_wm97xx_init(void) +{ + return platform_driver_register(&zylonite_wm97xx_driver); +} + +static void __exit zylonite_wm97xx_exit(void) +{ + platform_driver_unregister(&zylonite_wm97xx_driver); +} + +module_init(zylonite_wm97xx_init); +module_exit(zylonite_wm97xx_exit); + +/* Module information */ +MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); +MODULE_DESCRIPTION("wm97xx continuous touch driver for Zylonite"); +MODULE_LICENSE("GPL"); diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 102ef4a14c5..d2109054de8 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -82,7 +82,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template, if (!gpio_is_valid(template->gpio)) { printk(KERN_INFO "Skipping unavilable LED gpio %d (%s)\n", template->gpio, template->name); - return; + return 0; } ret = gpio_request(template->gpio, template->name); diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index d184dfab963..db39f4a52f5 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -278,7 +278,7 @@ static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr, * We only use page mode writes; the alternative is sloooow. This routine * writes at most one page. */ -static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf, +static ssize_t at24_eeprom_write(struct at24_data *at24, const char *buf, unsigned offset, size_t count) { struct i2c_client *client; @@ -347,8 +347,8 @@ static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf, return -ETIMEDOUT; } -static ssize_t at24_write(struct at24_data *at24, - char *buf, loff_t off, size_t count) +static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off, + size_t count) { ssize_t retval = 0; @@ -406,7 +406,7 @@ static ssize_t at24_macc_read(struct memory_accessor *macc, char *buf, return at24_read(at24, buf, offset, count); } -static ssize_t at24_macc_write(struct memory_accessor *macc, char *buf, +static ssize_t at24_macc_write(struct memory_accessor *macc, const char *buf, off_t offset, size_t count) { struct at24_data *at24 = container_of(macc, struct at24_data, macc); diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index 6bc0dac5c1e..b34cb5f79ee 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -140,7 +140,8 @@ at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr, static ssize_t -at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count) +at25_ee_write(struct at25_data *at25, const char *buf, loff_t off, + size_t count) { ssize_t status = 0; unsigned written = 0; @@ -276,7 +277,7 @@ static ssize_t at25_mem_read(struct memory_accessor *mem, char *buf, return at25_ee_read(at25, buf, offset, count); } -static ssize_t at25_mem_write(struct memory_accessor *mem, char *buf, +static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf, off_t offset, size_t count) { struct at25_data *at25 = container_of(mem, struct at25_data, mem); diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h index 114444cfd49..b94d5f76770 100644 --- a/drivers/misc/sgi-xp/xpc.h +++ b/drivers/misc/sgi-xp/xpc.h @@ -90,18 +90,21 @@ struct xpc_rsvd_page { short max_npartitions; /* value of XPC_MAX_PARTITIONS */ u8 version; u8 pad1[3]; /* align to next u64 in 1st 64-byte cacheline */ + unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */ union { - unsigned long vars_pa; /* phys address of struct xpc_vars */ - unsigned long activate_gru_mq_desc_gpa; /* phys addr of */ - /* activate mq's */ - /* gru mq descriptor */ + struct { + unsigned long vars_pa; /* phys addr */ + } sn2; + struct { + unsigned long heartbeat_gpa; /* phys addr */ + unsigned long activate_gru_mq_desc_gpa; /* phys addr */ + } uv; } sn; - unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */ - u64 pad2[10]; /* align to last u64 in 2nd 64-byte cacheline */ + u64 pad2[9]; /* align to last u64 in 2nd 64-byte cacheline */ u64 SAL_nasids_size; /* SAL: size of each nasid mask in bytes */ }; -#define XPC_RP_VERSION _XPC_VERSION(2, 0) /* version 2.0 of the reserved page */ +#define XPC_RP_VERSION _XPC_VERSION(3, 0) /* version 3.0 of the reserved page */ /* * Define the structures by which XPC variables can be exported to other @@ -182,6 +185,17 @@ struct xpc_vars_part_sn2 { (XPC_RP_MACH_NASIDS(_rp) + \ xpc_nasid_mask_nlongs)) + +/* + * The following structure describes the partition's heartbeat info which + * will be periodically read by other partitions to determine whether this + * XPC is still 'alive'. + */ +struct xpc_heartbeat_uv { + unsigned long value; + unsigned long offline; /* if 0, heartbeat should be changing */ +}; + /* * Info pertinent to a GRU message queue using a watch list for irq generation. */ @@ -198,7 +212,7 @@ struct xpc_gru_mq_uv { /* * The activate_mq is used to send/receive GRU messages that affect XPC's - * heartbeat, partition active state, and channel state. This is UV only. + * partition active state and channel state. This is uv only. */ struct xpc_activate_mq_msghdr_uv { unsigned int gru_msg_hdr; /* FOR GRU INTERNAL USE ONLY */ @@ -210,33 +224,27 @@ struct xpc_activate_mq_msghdr_uv { /* activate_mq defined message types */ #define XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV 0 -#define XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV 1 -#define XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV 2 -#define XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV 3 -#define XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV 4 -#define XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV 5 +#define XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV 1 +#define XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV 2 -#define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV 6 -#define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV 7 -#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV 8 -#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV 9 +#define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV 3 +#define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV 4 +#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV 5 +#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV 6 +#define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV 7 -#define XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV 10 -#define XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV 11 +#define XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV 8 +#define XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV 9 struct xpc_activate_mq_msg_uv { struct xpc_activate_mq_msghdr_uv hdr; }; -struct xpc_activate_mq_msg_heartbeat_req_uv { - struct xpc_activate_mq_msghdr_uv hdr; - u64 heartbeat; -}; - struct xpc_activate_mq_msg_activate_req_uv { struct xpc_activate_mq_msghdr_uv hdr; unsigned long rp_gpa; + unsigned long heartbeat_gpa; unsigned long activate_gru_mq_desc_gpa; }; @@ -271,6 +279,11 @@ struct xpc_activate_mq_msg_chctl_openreply_uv { unsigned long notify_gru_mq_desc_gpa; }; +struct xpc_activate_mq_msg_chctl_opencomplete_uv { + struct xpc_activate_mq_msghdr_uv hdr; + short ch_number; +}; + /* * Functions registered by add_timer() or called by kernel_thread() only * allow for a single 64-bit argument. The following macros can be used to @@ -576,30 +589,32 @@ struct xpc_channel { #define XPC_C_WASCONNECTED 0x00000001 /* channel was connected */ -#define XPC_C_ROPENREPLY 0x00000002 /* remote open channel reply */ -#define XPC_C_OPENREPLY 0x00000004 /* local open channel reply */ -#define XPC_C_ROPENREQUEST 0x00000008 /* remote open channel request */ -#define XPC_C_OPENREQUEST 0x00000010 /* local open channel request */ +#define XPC_C_ROPENCOMPLETE 0x00000002 /* remote open channel complete */ +#define XPC_C_OPENCOMPLETE 0x00000004 /* local open channel complete */ +#define XPC_C_ROPENREPLY 0x00000008 /* remote open channel reply */ +#define XPC_C_OPENREPLY 0x00000010 /* local open channel reply */ +#define XPC_C_ROPENREQUEST 0x00000020 /* remote open channel request */ +#define XPC_C_OPENREQUEST 0x00000040 /* local open channel request */ -#define XPC_C_SETUP 0x00000020 /* channel's msgqueues are alloc'd */ -#define XPC_C_CONNECTEDCALLOUT 0x00000040 /* connected callout initiated */ +#define XPC_C_SETUP 0x00000080 /* channel's msgqueues are alloc'd */ +#define XPC_C_CONNECTEDCALLOUT 0x00000100 /* connected callout initiated */ #define XPC_C_CONNECTEDCALLOUT_MADE \ - 0x00000080 /* connected callout completed */ -#define XPC_C_CONNECTED 0x00000100 /* local channel is connected */ -#define XPC_C_CONNECTING 0x00000200 /* channel is being connected */ + 0x00000200 /* connected callout completed */ +#define XPC_C_CONNECTED 0x00000400 /* local channel is connected */ +#define XPC_C_CONNECTING 0x00000800 /* channel is being connected */ -#define XPC_C_RCLOSEREPLY 0x00000400 /* remote close channel reply */ -#define XPC_C_CLOSEREPLY 0x00000800 /* local close channel reply */ -#define XPC_C_RCLOSEREQUEST 0x00001000 /* remote close channel request */ -#define XPC_C_CLOSEREQUEST 0x00002000 /* local close channel request */ +#define XPC_C_RCLOSEREPLY 0x00001000 /* remote close channel reply */ +#define XPC_C_CLOSEREPLY 0x00002000 /* local close channel reply */ +#define XPC_C_RCLOSEREQUEST 0x00004000 /* remote close channel request */ +#define XPC_C_CLOSEREQUEST 0x00008000 /* local close channel request */ -#define XPC_C_DISCONNECTED 0x00004000 /* channel is disconnected */ -#define XPC_C_DISCONNECTING 0x00008000 /* channel is being disconnected */ +#define XPC_C_DISCONNECTED 0x00010000 /* channel is disconnected */ +#define XPC_C_DISCONNECTING 0x00020000 /* channel is being disconnected */ #define XPC_C_DISCONNECTINGCALLOUT \ - 0x00010000 /* disconnecting callout initiated */ + 0x00040000 /* disconnecting callout initiated */ #define XPC_C_DISCONNECTINGCALLOUT_MADE \ - 0x00020000 /* disconnecting callout completed */ -#define XPC_C_WDISCONNECT 0x00040000 /* waiting for channel disconnect */ + 0x00080000 /* disconnecting callout completed */ +#define XPC_C_WDISCONNECT 0x00100000 /* waiting for channel disconnect */ /* * The channel control flags (chctl) union consists of a 64-bit variable which @@ -618,11 +633,13 @@ union xpc_channel_ctl_flags { #define XPC_CHCTL_CLOSEREPLY 0x02 #define XPC_CHCTL_OPENREQUEST 0x04 #define XPC_CHCTL_OPENREPLY 0x08 -#define XPC_CHCTL_MSGREQUEST 0x10 +#define XPC_CHCTL_OPENCOMPLETE 0x10 +#define XPC_CHCTL_MSGREQUEST 0x20 #define XPC_OPENCLOSE_CHCTL_FLAGS \ (XPC_CHCTL_CLOSEREQUEST | XPC_CHCTL_CLOSEREPLY | \ - XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY) + XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY | \ + XPC_CHCTL_OPENCOMPLETE) #define XPC_MSG_CHCTL_FLAGS XPC_CHCTL_MSGREQUEST static inline int @@ -687,6 +704,9 @@ struct xpc_partition_sn2 { }; struct xpc_partition_uv { + unsigned long heartbeat_gpa; /* phys addr of partition's heartbeat */ + struct xpc_heartbeat_uv cached_heartbeat; /* cached copy of */ + /* partition's heartbeat */ unsigned long activate_gru_mq_desc_gpa; /* phys addr of parititon's */ /* activate mq's gru mq */ /* descriptor */ @@ -698,14 +718,12 @@ struct xpc_partition_uv { u8 remote_act_state; /* remote partition's act_state */ u8 act_state_req; /* act_state request from remote partition */ enum xp_retval reason; /* reason for deactivate act_state request */ - u64 heartbeat; /* incremented by remote partition */ }; /* struct xpc_partition_uv flags */ -#define XPC_P_HEARTBEAT_OFFLINE_UV 0x00000001 +#define XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV 0x00000001 #define XPC_P_ENGAGED_UV 0x00000002 -#define XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV 0x00000004 /* struct xpc_partition_uv act_state change requests */ @@ -762,6 +780,62 @@ struct xpc_partition { } ____cacheline_aligned; +struct xpc_arch_operations { + int (*setup_partitions) (void); + void (*teardown_partitions) (void); + void (*process_activate_IRQ_rcvd) (void); + enum xp_retval (*get_partition_rsvd_page_pa) + (void *, u64 *, unsigned long *, size_t *); + int (*setup_rsvd_page) (struct xpc_rsvd_page *); + + void (*allow_hb) (short); + void (*disallow_hb) (short); + void (*disallow_all_hbs) (void); + void (*increment_heartbeat) (void); + void (*offline_heartbeat) (void); + void (*online_heartbeat) (void); + void (*heartbeat_init) (void); + void (*heartbeat_exit) (void); + enum xp_retval (*get_remote_heartbeat) (struct xpc_partition *); + + void (*request_partition_activation) (struct xpc_rsvd_page *, + unsigned long, int); + void (*request_partition_reactivation) (struct xpc_partition *); + void (*request_partition_deactivation) (struct xpc_partition *); + void (*cancel_partition_deactivation_request) (struct xpc_partition *); + enum xp_retval (*setup_ch_structures) (struct xpc_partition *); + void (*teardown_ch_structures) (struct xpc_partition *); + + enum xp_retval (*make_first_contact) (struct xpc_partition *); + + u64 (*get_chctl_all_flags) (struct xpc_partition *); + void (*send_chctl_closerequest) (struct xpc_channel *, unsigned long *); + void (*send_chctl_closereply) (struct xpc_channel *, unsigned long *); + void (*send_chctl_openrequest) (struct xpc_channel *, unsigned long *); + void (*send_chctl_openreply) (struct xpc_channel *, unsigned long *); + void (*send_chctl_opencomplete) (struct xpc_channel *, unsigned long *); + void (*process_msg_chctl_flags) (struct xpc_partition *, int); + + enum xp_retval (*save_remote_msgqueue_pa) (struct xpc_channel *, + unsigned long); + + enum xp_retval (*setup_msg_structures) (struct xpc_channel *); + void (*teardown_msg_structures) (struct xpc_channel *); + + void (*indicate_partition_engaged) (struct xpc_partition *); + void (*indicate_partition_disengaged) (struct xpc_partition *); + void (*assume_partition_disengaged) (short); + int (*partition_engaged) (short); + int (*any_partition_engaged) (void); + + int (*n_of_deliverable_payloads) (struct xpc_channel *); + enum xp_retval (*send_payload) (struct xpc_channel *, u32, void *, + u16, u8, xpc_notify_func, void *); + void *(*get_deliverable_payload) (struct xpc_channel *); + void (*received_payload) (struct xpc_channel *, void *); + void (*notify_senders_of_disconnect) (struct xpc_channel *); +}; + /* struct xpc_partition act_state values (for XPC HB) */ #define XPC_P_AS_INACTIVE 0x00 /* partition is not active */ @@ -802,67 +876,17 @@ extern struct xpc_registration xpc_registrations[]; /* found in xpc_main.c */ extern struct device *xpc_part; extern struct device *xpc_chan; +extern struct xpc_arch_operations xpc_arch_ops; extern int xpc_disengage_timelimit; extern int xpc_disengage_timedout; extern int xpc_activate_IRQ_rcvd; extern spinlock_t xpc_activate_IRQ_rcvd_lock; extern wait_queue_head_t xpc_activate_IRQ_wq; -extern void *xpc_heartbeating_to_mask; extern void *xpc_kzalloc_cacheline_aligned(size_t, gfp_t, void **); extern void xpc_activate_partition(struct xpc_partition *); extern void xpc_activate_kthreads(struct xpc_channel *, int); extern void xpc_create_kthreads(struct xpc_channel *, int, int); extern void xpc_disconnect_wait(int); -extern int (*xpc_setup_partitions_sn) (void); -extern void (*xpc_teardown_partitions_sn) (void); -extern enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *, u64 *, - unsigned long *, - size_t *); -extern int (*xpc_setup_rsvd_page_sn) (struct xpc_rsvd_page *); -extern void (*xpc_heartbeat_init) (void); -extern void (*xpc_heartbeat_exit) (void); -extern void (*xpc_increment_heartbeat) (void); -extern void (*xpc_offline_heartbeat) (void); -extern void (*xpc_online_heartbeat) (void); -extern enum xp_retval (*xpc_get_remote_heartbeat) (struct xpc_partition *); -extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *); -extern u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *); -extern enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *); -extern void (*xpc_teardown_msg_structures) (struct xpc_channel *); -extern void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *); -extern void (*xpc_process_msg_chctl_flags) (struct xpc_partition *, int); -extern int (*xpc_n_of_deliverable_payloads) (struct xpc_channel *); -extern void *(*xpc_get_deliverable_payload) (struct xpc_channel *); -extern void (*xpc_request_partition_activation) (struct xpc_rsvd_page *, - unsigned long, int); -extern void (*xpc_request_partition_reactivation) (struct xpc_partition *); -extern void (*xpc_request_partition_deactivation) (struct xpc_partition *); -extern void (*xpc_cancel_partition_deactivation_request) ( - struct xpc_partition *); -extern void (*xpc_process_activate_IRQ_rcvd) (void); -extern enum xp_retval (*xpc_setup_ch_structures_sn) (struct xpc_partition *); -extern void (*xpc_teardown_ch_structures_sn) (struct xpc_partition *); - -extern void (*xpc_indicate_partition_engaged) (struct xpc_partition *); -extern int (*xpc_partition_engaged) (short); -extern int (*xpc_any_partition_engaged) (void); -extern void (*xpc_indicate_partition_disengaged) (struct xpc_partition *); -extern void (*xpc_assume_partition_disengaged) (short); - -extern void (*xpc_send_chctl_closerequest) (struct xpc_channel *, - unsigned long *); -extern void (*xpc_send_chctl_closereply) (struct xpc_channel *, - unsigned long *); -extern void (*xpc_send_chctl_openrequest) (struct xpc_channel *, - unsigned long *); -extern void (*xpc_send_chctl_openreply) (struct xpc_channel *, unsigned long *); - -extern enum xp_retval (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *, - unsigned long); - -extern enum xp_retval (*xpc_send_payload) (struct xpc_channel *, u32, void *, - u16, u8, xpc_notify_func, void *); -extern void (*xpc_received_payload) (struct xpc_channel *, void *); /* found in xpc_sn2.c */ extern int xpc_init_sn2(void); @@ -909,40 +933,6 @@ extern void xpc_disconnect_channel(const int, struct xpc_channel *, extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval); extern void xpc_partition_going_down(struct xpc_partition *, enum xp_retval); -static inline int -xpc_hb_allowed(short partid, void *heartbeating_to_mask) -{ - return test_bit(partid, heartbeating_to_mask); -} - -static inline int -xpc_any_hbs_allowed(void) -{ - DBUG_ON(xpc_heartbeating_to_mask == NULL); - return !bitmap_empty(xpc_heartbeating_to_mask, xp_max_npartitions); -} - -static inline void -xpc_allow_hb(short partid) -{ - DBUG_ON(xpc_heartbeating_to_mask == NULL); - set_bit(partid, xpc_heartbeating_to_mask); -} - -static inline void -xpc_disallow_hb(short partid) -{ - DBUG_ON(xpc_heartbeating_to_mask == NULL); - clear_bit(partid, xpc_heartbeating_to_mask); -} - -static inline void -xpc_disallow_all_hbs(void) -{ - DBUG_ON(xpc_heartbeating_to_mask == NULL); - bitmap_zero(xpc_heartbeating_to_mask, xp_max_npartitions); -} - static inline void xpc_wakeup_channel_mgr(struct xpc_partition *part) { diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c index 99a2534c38a..652593fc486 100644 --- a/drivers/misc/sgi-xp/xpc_channel.c +++ b/drivers/misc/sgi-xp/xpc_channel.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2009 Silicon Graphics, Inc. All Rights Reserved. */ /* @@ -39,34 +39,38 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags) if (!(ch->flags & XPC_C_SETUP)) { spin_unlock_irqrestore(&ch->lock, *irq_flags); - ret = xpc_setup_msg_structures(ch); + ret = xpc_arch_ops.setup_msg_structures(ch); spin_lock_irqsave(&ch->lock, *irq_flags); if (ret != xpSuccess) XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags); + else + ch->flags |= XPC_C_SETUP; - ch->flags |= XPC_C_SETUP; - - if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING)) + if (ch->flags & XPC_C_DISCONNECTING) return; } if (!(ch->flags & XPC_C_OPENREPLY)) { ch->flags |= XPC_C_OPENREPLY; - xpc_send_chctl_openreply(ch, irq_flags); + xpc_arch_ops.send_chctl_openreply(ch, irq_flags); } if (!(ch->flags & XPC_C_ROPENREPLY)) return; - ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP); /* clear all else */ + if (!(ch->flags & XPC_C_OPENCOMPLETE)) { + ch->flags |= (XPC_C_OPENCOMPLETE | XPC_C_CONNECTED); + xpc_arch_ops.send_chctl_opencomplete(ch, irq_flags); + } + + if (!(ch->flags & XPC_C_ROPENCOMPLETE)) + return; dev_info(xpc_chan, "channel %d to partition %d connected\n", ch->number, ch->partid); - spin_unlock_irqrestore(&ch->lock, *irq_flags); - xpc_create_kthreads(ch, 1, 0); - spin_lock_irqsave(&ch->lock, *irq_flags); + ch->flags = (XPC_C_CONNECTED | XPC_C_SETUP); /* clear all else */ } /* @@ -96,7 +100,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) if (part->act_state == XPC_P_AS_DEACTIVATING) { /* can't proceed until the other side disengages from us */ - if (xpc_partition_engaged(ch->partid)) + if (xpc_arch_ops.partition_engaged(ch->partid)) return; } else { @@ -108,7 +112,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) if (!(ch->flags & XPC_C_CLOSEREPLY)) { ch->flags |= XPC_C_CLOSEREPLY; - xpc_send_chctl_closereply(ch, irq_flags); + xpc_arch_ops.send_chctl_closereply(ch, irq_flags); } if (!(ch->flags & XPC_C_RCLOSEREPLY)) @@ -118,7 +122,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) /* wake those waiting for notify completion */ if (atomic_read(&ch->n_to_notify) > 0) { /* we do callout while holding ch->lock, callout can't block */ - xpc_notify_senders_of_disconnect(ch); + xpc_arch_ops.notify_senders_of_disconnect(ch); } /* both sides are disconnected now */ @@ -132,7 +136,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) DBUG_ON(atomic_read(&ch->n_to_notify) != 0); /* it's now safe to free the channel's message queues */ - xpc_teardown_msg_structures(ch); + xpc_arch_ops.teardown_msg_structures(ch); ch->func = NULL; ch->key = NULL; @@ -144,8 +148,9 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) /* * Mark the channel disconnected and clear all other flags, including - * XPC_C_SETUP (because of call to xpc_teardown_msg_structures()) but - * not including XPC_C_WDISCONNECT (if it was set). + * XPC_C_SETUP (because of call to + * xpc_arch_ops.teardown_msg_structures()) but not including + * XPC_C_WDISCONNECT (if it was set). */ ch->flags = (XPC_C_DISCONNECTED | (ch->flags & XPC_C_WDISCONNECT)); @@ -184,6 +189,7 @@ xpc_process_openclose_chctl_flags(struct xpc_partition *part, int ch_number, struct xpc_channel *ch = &part->channels[ch_number]; enum xp_retval reason; enum xp_retval ret; + int create_kthread = 0; spin_lock_irqsave(&ch->lock, irq_flags); @@ -196,8 +202,7 @@ again: * has had a chance to see that the channel is disconnected. */ ch->delayed_chctl_flags |= chctl_flags; - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; + goto out; } if (chctl_flags & XPC_CHCTL_CLOSEREQUEST) { @@ -239,8 +244,7 @@ again: XPC_CHCTL_CLOSEREQUEST; spin_unlock(&part->chctl_lock); } - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; + goto out; } XPC_SET_REASON(ch, 0, 0); @@ -250,7 +254,8 @@ again: ch->flags |= (XPC_C_CONNECTING | XPC_C_ROPENREQUEST); } - chctl_flags &= ~(XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY); + chctl_flags &= ~(XPC_CHCTL_OPENREQUEST | XPC_CHCTL_OPENREPLY | + XPC_CHCTL_OPENCOMPLETE); /* * The meaningful CLOSEREQUEST connection state fields are: @@ -269,8 +274,7 @@ again: XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags); DBUG_ON(chctl_flags & XPC_CHCTL_CLOSEREPLY); - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; + goto out; } xpc_process_disconnect(ch, &irq_flags); @@ -283,8 +287,7 @@ again: if (ch->flags & XPC_C_DISCONNECTED) { DBUG_ON(part->act_state != XPC_P_AS_DEACTIVATING); - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; + goto out; } DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST)); @@ -299,8 +302,7 @@ again: XPC_CHCTL_CLOSEREPLY; spin_unlock(&part->chctl_lock); } - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; + goto out; } ch->flags |= XPC_C_RCLOSEREPLY; @@ -320,14 +322,12 @@ again: if (part->act_state == XPC_P_AS_DEACTIVATING || (ch->flags & XPC_C_ROPENREQUEST)) { - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; + goto out; } if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) { ch->delayed_chctl_flags |= XPC_CHCTL_OPENREQUEST; - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; + goto out; } DBUG_ON(!(ch->flags & (XPC_C_DISCONNECTED | XPC_C_OPENREQUEST))); @@ -341,8 +341,7 @@ again: */ if (args->entry_size == 0 || args->local_nentries == 0) { /* assume OPENREQUEST was delayed by mistake */ - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; + goto out; } ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING); @@ -352,8 +351,7 @@ again: if (args->entry_size != ch->entry_size) { XPC_DISCONNECT_CHANNEL(ch, xpUnequalMsgSizes, &irq_flags); - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; + goto out; } } else { ch->entry_size = args->entry_size; @@ -375,15 +373,13 @@ again: args->local_msgqueue_pa, args->local_nentries, args->remote_nentries, ch->partid, ch->number); - if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) { - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; - } + if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) + goto out; + if (!(ch->flags & XPC_C_OPENREQUEST)) { XPC_DISCONNECT_CHANNEL(ch, xpOpenCloseError, &irq_flags); - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; + goto out; } DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST)); @@ -400,11 +396,11 @@ again: DBUG_ON(args->local_nentries == 0); DBUG_ON(args->remote_nentries == 0); - ret = xpc_save_remote_msgqueue_pa(ch, args->local_msgqueue_pa); + ret = xpc_arch_ops.save_remote_msgqueue_pa(ch, + args->local_msgqueue_pa); if (ret != xpSuccess) { XPC_DISCONNECT_CHANNEL(ch, ret, &irq_flags); - spin_unlock_irqrestore(&ch->lock, irq_flags); - return; + goto out; } ch->flags |= XPC_C_ROPENREPLY; @@ -430,7 +426,36 @@ again: xpc_process_connect(ch, &irq_flags); } + if (chctl_flags & XPC_CHCTL_OPENCOMPLETE) { + + dev_dbg(xpc_chan, "XPC_CHCTL_OPENCOMPLETE received from " + "partid=%d, channel=%d\n", ch->partid, ch->number); + + if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_DISCONNECTED)) + goto out; + + if (!(ch->flags & XPC_C_OPENREQUEST) || + !(ch->flags & XPC_C_OPENREPLY)) { + XPC_DISCONNECT_CHANNEL(ch, xpOpenCloseError, + &irq_flags); + goto out; + } + + DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST)); + DBUG_ON(!(ch->flags & XPC_C_ROPENREPLY)); + DBUG_ON(!(ch->flags & XPC_C_CONNECTED)); + + ch->flags |= XPC_C_ROPENCOMPLETE; + + xpc_process_connect(ch, &irq_flags); + create_kthread = 1; + } + +out: spin_unlock_irqrestore(&ch->lock, irq_flags); + + if (create_kthread) + xpc_create_kthreads(ch, 1, 0); } /* @@ -508,7 +533,7 @@ xpc_connect_channel(struct xpc_channel *ch) /* initiate the connection */ ch->flags |= (XPC_C_OPENREQUEST | XPC_C_CONNECTING); - xpc_send_chctl_openrequest(ch, &irq_flags); + xpc_arch_ops.send_chctl_openrequest(ch, &irq_flags); xpc_process_connect(ch, &irq_flags); @@ -526,7 +551,7 @@ xpc_process_sent_chctl_flags(struct xpc_partition *part) int ch_number; u32 ch_flags; - chctl.all_flags = xpc_get_chctl_all_flags(part); + chctl.all_flags = xpc_arch_ops.get_chctl_all_flags(part); /* * Initiate channel connections for registered channels. @@ -564,10 +589,6 @@ xpc_process_sent_chctl_flags(struct xpc_partition *part) if (!(ch_flags & XPC_C_OPENREQUEST)) { DBUG_ON(ch_flags & XPC_C_SETUP); (void)xpc_connect_channel(ch); - } else { - spin_lock_irqsave(&ch->lock, irq_flags); - xpc_process_connect(ch, &irq_flags); - spin_unlock_irqrestore(&ch->lock, irq_flags); } continue; } @@ -579,7 +600,7 @@ xpc_process_sent_chctl_flags(struct xpc_partition *part) */ if (chctl.flags[ch_number] & XPC_MSG_CHCTL_FLAGS) - xpc_process_msg_chctl_flags(part, ch_number); + xpc_arch_ops.process_msg_chctl_flags(part, ch_number); } } @@ -755,7 +776,7 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch, XPC_C_ROPENREQUEST | XPC_C_ROPENREPLY | XPC_C_CONNECTING | XPC_C_CONNECTED); - xpc_send_chctl_closerequest(ch, irq_flags); + xpc_arch_ops.send_chctl_closerequest(ch, irq_flags); if (channel_was_connected) ch->flags |= XPC_C_WASCONNECTED; @@ -862,8 +883,8 @@ xpc_initiate_send(short partid, int ch_number, u32 flags, void *payload, DBUG_ON(payload == NULL); if (xpc_part_ref(part)) { - ret = xpc_send_payload(&part->channels[ch_number], flags, - payload, payload_size, 0, NULL, NULL); + ret = xpc_arch_ops.send_payload(&part->channels[ch_number], + flags, payload, payload_size, 0, NULL, NULL); xpc_part_deref(part); } @@ -914,9 +935,8 @@ xpc_initiate_send_notify(short partid, int ch_number, u32 flags, void *payload, DBUG_ON(func == NULL); if (xpc_part_ref(part)) { - ret = xpc_send_payload(&part->channels[ch_number], flags, - payload, payload_size, XPC_N_CALL, func, - key); + ret = xpc_arch_ops.send_payload(&part->channels[ch_number], + flags, payload, payload_size, XPC_N_CALL, func, key); xpc_part_deref(part); } return ret; @@ -930,7 +950,7 @@ xpc_deliver_payload(struct xpc_channel *ch) { void *payload; - payload = xpc_get_deliverable_payload(ch); + payload = xpc_arch_ops.get_deliverable_payload(ch); if (payload != NULL) { /* @@ -984,7 +1004,7 @@ xpc_initiate_received(short partid, int ch_number, void *payload) DBUG_ON(ch_number < 0 || ch_number >= part->nchannels); ch = &part->channels[ch_number]; - xpc_received_payload(ch, payload); + xpc_arch_ops.received_payload(ch, payload); /* the call to xpc_msgqueue_ref() was done by xpc_deliver_payload() */ xpc_msgqueue_deref(ch); diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 1ab9fda87fa..fd3688a3e23 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2009 Silicon Graphics, Inc. All Rights Reserved. */ /* @@ -150,7 +150,6 @@ DECLARE_WAIT_QUEUE_HEAD(xpc_activate_IRQ_wq); static unsigned long xpc_hb_check_timeout; static struct timer_list xpc_hb_timer; -void *xpc_heartbeating_to_mask; /* notification that the xpc_hb_checker thread has exited */ static DECLARE_COMPLETION(xpc_hb_checker_exited); @@ -170,62 +169,7 @@ static struct notifier_block xpc_die_notifier = { .notifier_call = xpc_system_die, }; -int (*xpc_setup_partitions_sn) (void); -void (*xpc_teardown_partitions_sn) (void); -enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *buf, u64 *cookie, - unsigned long *rp_pa, - size_t *len); -int (*xpc_setup_rsvd_page_sn) (struct xpc_rsvd_page *rp); -void (*xpc_heartbeat_init) (void); -void (*xpc_heartbeat_exit) (void); -void (*xpc_increment_heartbeat) (void); -void (*xpc_offline_heartbeat) (void); -void (*xpc_online_heartbeat) (void); -enum xp_retval (*xpc_get_remote_heartbeat) (struct xpc_partition *part); - -enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *part); -void (*xpc_notify_senders_of_disconnect) (struct xpc_channel *ch); -u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *part); -enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *ch); -void (*xpc_teardown_msg_structures) (struct xpc_channel *ch); -void (*xpc_process_msg_chctl_flags) (struct xpc_partition *part, int ch_number); -int (*xpc_n_of_deliverable_payloads) (struct xpc_channel *ch); -void *(*xpc_get_deliverable_payload) (struct xpc_channel *ch); - -void (*xpc_request_partition_activation) (struct xpc_rsvd_page *remote_rp, - unsigned long remote_rp_pa, - int nasid); -void (*xpc_request_partition_reactivation) (struct xpc_partition *part); -void (*xpc_request_partition_deactivation) (struct xpc_partition *part); -void (*xpc_cancel_partition_deactivation_request) (struct xpc_partition *part); - -void (*xpc_process_activate_IRQ_rcvd) (void); -enum xp_retval (*xpc_setup_ch_structures_sn) (struct xpc_partition *part); -void (*xpc_teardown_ch_structures_sn) (struct xpc_partition *part); - -void (*xpc_indicate_partition_engaged) (struct xpc_partition *part); -int (*xpc_partition_engaged) (short partid); -int (*xpc_any_partition_engaged) (void); -void (*xpc_indicate_partition_disengaged) (struct xpc_partition *part); -void (*xpc_assume_partition_disengaged) (short partid); - -void (*xpc_send_chctl_closerequest) (struct xpc_channel *ch, - unsigned long *irq_flags); -void (*xpc_send_chctl_closereply) (struct xpc_channel *ch, - unsigned long *irq_flags); -void (*xpc_send_chctl_openrequest) (struct xpc_channel *ch, - unsigned long *irq_flags); -void (*xpc_send_chctl_openreply) (struct xpc_channel *ch, - unsigned long *irq_flags); - -enum xp_retval (*xpc_save_remote_msgqueue_pa) (struct xpc_channel *ch, - unsigned long msgqueue_pa); - -enum xp_retval (*xpc_send_payload) (struct xpc_channel *ch, u32 flags, - void *payload, u16 payload_size, - u8 notify_type, xpc_notify_func func, - void *key); -void (*xpc_received_payload) (struct xpc_channel *ch, void *payload); +struct xpc_arch_operations xpc_arch_ops; /* * Timer function to enforce the timelimit on the partition disengage. @@ -240,7 +184,7 @@ xpc_timeout_partition_disengage(unsigned long data) (void)xpc_partition_disengaged(part); DBUG_ON(part->disengage_timeout != 0); - DBUG_ON(xpc_partition_engaged(XPC_PARTID(part))); + DBUG_ON(xpc_arch_ops.partition_engaged(XPC_PARTID(part))); } /* @@ -251,7 +195,7 @@ xpc_timeout_partition_disengage(unsigned long data) static void xpc_hb_beater(unsigned long dummy) { - xpc_increment_heartbeat(); + xpc_arch_ops.increment_heartbeat(); if (time_is_before_eq_jiffies(xpc_hb_check_timeout)) wake_up_interruptible(&xpc_activate_IRQ_wq); @@ -263,7 +207,7 @@ xpc_hb_beater(unsigned long dummy) static void xpc_start_hb_beater(void) { - xpc_heartbeat_init(); + xpc_arch_ops.heartbeat_init(); init_timer(&xpc_hb_timer); xpc_hb_timer.function = xpc_hb_beater; xpc_hb_beater(0); @@ -273,7 +217,7 @@ static void xpc_stop_hb_beater(void) { del_timer_sync(&xpc_hb_timer); - xpc_heartbeat_exit(); + xpc_arch_ops.heartbeat_exit(); } /* @@ -302,7 +246,7 @@ xpc_check_remote_hb(void) continue; } - ret = xpc_get_remote_heartbeat(part); + ret = xpc_arch_ops.get_remote_heartbeat(part); if (ret != xpSuccess) XPC_DEACTIVATE_PARTITION(part, ret); } @@ -353,7 +297,7 @@ xpc_hb_checker(void *ignore) force_IRQ = 0; dev_dbg(xpc_part, "processing activate IRQs " "received\n"); - xpc_process_activate_IRQ_rcvd(); + xpc_arch_ops.process_activate_IRQ_rcvd(); } /* wait for IRQ or timeout */ @@ -528,7 +472,7 @@ xpc_setup_ch_structures(struct xpc_partition *part) init_waitqueue_head(&ch->idle_wq); } - ret = xpc_setup_ch_structures_sn(part); + ret = xpc_arch_ops.setup_ch_structures(part); if (ret != xpSuccess) goto out_2; @@ -572,7 +516,7 @@ xpc_teardown_ch_structures(struct xpc_partition *part) /* now we can begin tearing down the infrastructure */ - xpc_teardown_ch_structures_sn(part); + xpc_arch_ops.teardown_ch_structures(part); kfree(part->remote_openclose_args_base); part->remote_openclose_args = NULL; @@ -620,12 +564,12 @@ xpc_activating(void *__partid) dev_dbg(xpc_part, "activating partition %d\n", partid); - xpc_allow_hb(partid); + xpc_arch_ops.allow_hb(partid); if (xpc_setup_ch_structures(part) == xpSuccess) { (void)xpc_part_ref(part); /* this will always succeed */ - if (xpc_make_first_contact(part) == xpSuccess) { + if (xpc_arch_ops.make_first_contact(part) == xpSuccess) { xpc_mark_partition_active(part); xpc_channel_mgr(part); /* won't return until partition is deactivating */ @@ -635,12 +579,12 @@ xpc_activating(void *__partid) xpc_teardown_ch_structures(part); } - xpc_disallow_hb(partid); + xpc_arch_ops.disallow_hb(partid); xpc_mark_partition_inactive(part); if (part->reason == xpReactivating) { /* interrupting ourselves results in activating partition */ - xpc_request_partition_reactivation(part); + xpc_arch_ops.request_partition_reactivation(part); } return 0; @@ -713,10 +657,13 @@ xpc_activate_kthreads(struct xpc_channel *ch, int needed) static void xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch) { + int (*n_of_deliverable_payloads) (struct xpc_channel *) = + xpc_arch_ops.n_of_deliverable_payloads; + do { /* deliver messages to their intended recipients */ - while (xpc_n_of_deliverable_payloads(ch) > 0 && + while (n_of_deliverable_payloads(ch) > 0 && !(ch->flags & XPC_C_DISCONNECTING)) { xpc_deliver_payload(ch); } @@ -732,7 +679,7 @@ xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch) "wait_event_interruptible_exclusive()\n"); (void)wait_event_interruptible_exclusive(ch->idle_wq, - (xpc_n_of_deliverable_payloads(ch) > 0 || + (n_of_deliverable_payloads(ch) > 0 || (ch->flags & XPC_C_DISCONNECTING))); atomic_dec(&ch->kthreads_idle); @@ -749,6 +696,8 @@ xpc_kthread_start(void *args) struct xpc_channel *ch; int n_needed; unsigned long irq_flags; + int (*n_of_deliverable_payloads) (struct xpc_channel *) = + xpc_arch_ops.n_of_deliverable_payloads; dev_dbg(xpc_chan, "kthread starting, partid=%d, channel=%d\n", partid, ch_number); @@ -777,7 +726,7 @@ xpc_kthread_start(void *args) * additional kthreads to help deliver them. We only * need one less than total #of messages to deliver. */ - n_needed = xpc_n_of_deliverable_payloads(ch) - 1; + n_needed = n_of_deliverable_payloads(ch) - 1; if (n_needed > 0 && !(ch->flags & XPC_C_DISCONNECTING)) xpc_activate_kthreads(ch, n_needed); @@ -805,7 +754,7 @@ xpc_kthread_start(void *args) if (atomic_dec_return(&ch->kthreads_assigned) == 0 && atomic_dec_return(&part->nchannels_engaged) == 0) { - xpc_indicate_partition_disengaged(part); + xpc_arch_ops.indicate_partition_disengaged(part); } xpc_msgqueue_deref(ch); @@ -837,6 +786,8 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed, u64 args = XPC_PACK_ARGS(ch->partid, ch->number); struct xpc_partition *part = &xpc_partitions[ch->partid]; struct task_struct *kthread; + void (*indicate_partition_disengaged) (struct xpc_partition *) = + xpc_arch_ops.indicate_partition_disengaged; while (needed-- > 0) { @@ -858,7 +809,7 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed, } else if (atomic_inc_return(&ch->kthreads_assigned) == 1 && atomic_inc_return(&part->nchannels_engaged) == 1) { - xpc_indicate_partition_engaged(part); + xpc_arch_ops.indicate_partition_engaged(part); } (void)xpc_part_ref(part); xpc_msgqueue_ref(ch); @@ -880,7 +831,7 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed, if (atomic_dec_return(&ch->kthreads_assigned) == 0 && atomic_dec_return(&part->nchannels_engaged) == 0) { - xpc_indicate_partition_disengaged(part); + indicate_partition_disengaged(part); } xpc_msgqueue_deref(ch); xpc_part_deref(part); @@ -993,13 +944,13 @@ xpc_setup_partitions(void) atomic_set(&part->references, 0); } - return xpc_setup_partitions_sn(); + return xpc_arch_ops.setup_partitions(); } static void xpc_teardown_partitions(void) { - xpc_teardown_partitions_sn(); + xpc_arch_ops.teardown_partitions(); kfree(xpc_partitions); } @@ -1055,7 +1006,7 @@ xpc_do_exit(enum xp_retval reason) disengage_timeout = part->disengage_timeout; } - if (xpc_any_partition_engaged()) { + if (xpc_arch_ops.any_partition_engaged()) { if (time_is_before_jiffies(printmsg_time)) { dev_info(xpc_part, "waiting for remote " "partitions to deactivate, timeout in " @@ -1086,8 +1037,7 @@ xpc_do_exit(enum xp_retval reason) } while (1); - DBUG_ON(xpc_any_partition_engaged()); - DBUG_ON(xpc_any_hbs_allowed() != 0); + DBUG_ON(xpc_arch_ops.any_partition_engaged()); xpc_teardown_rsvd_page(); @@ -1152,15 +1102,15 @@ xpc_die_deactivate(void) /* keep xpc_hb_checker thread from doing anything (just in case) */ xpc_exiting = 1; - xpc_disallow_all_hbs(); /*indicate we're deactivated */ + xpc_arch_ops.disallow_all_hbs(); /*indicate we're deactivated */ for (partid = 0; partid < xp_max_npartitions; partid++) { part = &xpc_partitions[partid]; - if (xpc_partition_engaged(partid) || + if (xpc_arch_ops.partition_engaged(partid) || part->act_state != XPC_P_AS_INACTIVE) { - xpc_request_partition_deactivation(part); - xpc_indicate_partition_disengaged(part); + xpc_arch_ops.request_partition_deactivation(part); + xpc_arch_ops.indicate_partition_disengaged(part); } } @@ -1177,7 +1127,7 @@ xpc_die_deactivate(void) wait_to_print = XPC_DEACTIVATE_PRINTMSG_INTERVAL * 1000 * 5; while (1) { - any_engaged = xpc_any_partition_engaged(); + any_engaged = xpc_arch_ops.any_partition_engaged(); if (!any_engaged) { dev_info(xpc_part, "all partitions have deactivated\n"); break; @@ -1186,7 +1136,7 @@ xpc_die_deactivate(void) if (!keep_waiting--) { for (partid = 0; partid < xp_max_npartitions; partid++) { - if (xpc_partition_engaged(partid)) { + if (xpc_arch_ops.partition_engaged(partid)) { dev_info(xpc_part, "deactivate from " "remote partition %d timed " "out\n", partid); @@ -1233,7 +1183,7 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) /* fall through */ case DIE_MCA_MONARCH_ENTER: case DIE_INIT_MONARCH_ENTER: - xpc_offline_heartbeat(); + xpc_arch_ops.offline_heartbeat(); break; case DIE_KDEBUG_LEAVE: @@ -1244,7 +1194,7 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) /* fall through */ case DIE_MCA_MONARCH_LEAVE: case DIE_INIT_MONARCH_LEAVE: - xpc_online_heartbeat(); + xpc_arch_ops.online_heartbeat(); break; } #else diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c index 6722f6fe4dc..65877bc5eda 100644 --- a/drivers/misc/sgi-xp/xpc_partition.c +++ b/drivers/misc/sgi-xp/xpc_partition.c @@ -70,6 +70,9 @@ xpc_get_rsvd_page_pa(int nasid) size_t buf_len = 0; void *buf = buf; void *buf_base = NULL; + enum xp_retval (*get_partition_rsvd_page_pa) + (void *, u64 *, unsigned long *, size_t *) = + xpc_arch_ops.get_partition_rsvd_page_pa; while (1) { @@ -79,8 +82,7 @@ xpc_get_rsvd_page_pa(int nasid) * ??? function or have two versions? Rename rp_pa for UV to * ??? rp_gpa? */ - ret = xpc_get_partition_rsvd_page_pa(buf, &cookie, &rp_pa, - &len); + ret = get_partition_rsvd_page_pa(buf, &cookie, &rp_pa, &len); dev_dbg(xpc_part, "SAL returned with ret=%d, cookie=0x%016lx, " "address=0x%016lx, len=0x%016lx\n", ret, @@ -172,7 +174,7 @@ xpc_setup_rsvd_page(void) xpc_part_nasids = XPC_RP_PART_NASIDS(rp); xpc_mach_nasids = XPC_RP_MACH_NASIDS(rp); - ret = xpc_setup_rsvd_page_sn(rp); + ret = xpc_arch_ops.setup_rsvd_page(rp); if (ret != 0) return ret; @@ -264,7 +266,7 @@ xpc_partition_disengaged(struct xpc_partition *part) short partid = XPC_PARTID(part); int disengaged; - disengaged = !xpc_partition_engaged(partid); + disengaged = !xpc_arch_ops.partition_engaged(partid); if (part->disengage_timeout) { if (!disengaged) { if (time_is_after_jiffies(part->disengage_timeout)) { @@ -280,7 +282,7 @@ xpc_partition_disengaged(struct xpc_partition *part) dev_info(xpc_part, "deactivate request to remote " "partition %d timed out\n", partid); xpc_disengage_timedout = 1; - xpc_assume_partition_disengaged(partid); + xpc_arch_ops.assume_partition_disengaged(partid); disengaged = 1; } part->disengage_timeout = 0; @@ -294,7 +296,7 @@ xpc_partition_disengaged(struct xpc_partition *part) if (part->act_state != XPC_P_AS_INACTIVE) xpc_wakeup_channel_mgr(part); - xpc_cancel_partition_deactivation_request(part); + xpc_arch_ops.cancel_partition_deactivation_request(part); } return disengaged; } @@ -339,7 +341,7 @@ xpc_deactivate_partition(const int line, struct xpc_partition *part, spin_unlock_irqrestore(&part->act_lock, irq_flags); if (reason == xpReactivating) { /* we interrupt ourselves to reactivate partition */ - xpc_request_partition_reactivation(part); + xpc_arch_ops.request_partition_reactivation(part); } return; } @@ -358,7 +360,7 @@ xpc_deactivate_partition(const int line, struct xpc_partition *part, spin_unlock_irqrestore(&part->act_lock, irq_flags); /* ask remote partition to deactivate with regard to us */ - xpc_request_partition_deactivation(part); + xpc_arch_ops.request_partition_deactivation(part); /* set a timelimit on the disengage phase of the deactivation request */ part->disengage_timeout = jiffies + (xpc_disengage_timelimit * HZ); @@ -496,7 +498,7 @@ xpc_discovery(void) continue; } - xpc_request_partition_activation(remote_rp, + xpc_arch_ops.request_partition_activation(remote_rp, remote_rp_pa, nasid); } } diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c index eaaa964942d..915a3b495da 100644 --- a/drivers/misc/sgi-xp/xpc_sn2.c +++ b/drivers/misc/sgi-xp/xpc_sn2.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved. */ /* @@ -60,14 +60,14 @@ static struct xpc_vars_sn2 *xpc_vars_sn2; static struct xpc_vars_part_sn2 *xpc_vars_part_sn2; static int -xpc_setup_partitions_sn_sn2(void) +xpc_setup_partitions_sn2(void) { /* nothing needs to be done */ return 0; } static void -xpc_teardown_partitions_sn_sn2(void) +xpc_teardown_partitions_sn2(void) { /* nothing needs to be done */ } @@ -431,6 +431,13 @@ xpc_send_chctl_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags) } static void +xpc_send_chctl_opencomplete_sn2(struct xpc_channel *ch, + unsigned long *irq_flags) +{ + XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_OPENCOMPLETE, irq_flags); +} + +static void xpc_send_chctl_msgrequest_sn2(struct xpc_channel *ch) { XPC_SEND_NOTIFY_IRQ_SN2(ch, XPC_CHCTL_MSGREQUEST, NULL); @@ -621,7 +628,7 @@ xpc_get_partition_rsvd_page_pa_sn2(void *buf, u64 *cookie, unsigned long *rp_pa, static int -xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp) +xpc_setup_rsvd_page_sn2(struct xpc_rsvd_page *rp) { struct amo *amos_page; int i; @@ -629,7 +636,7 @@ xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp) xpc_vars_sn2 = XPC_RP_VARS(rp); - rp->sn.vars_pa = xp_pa(xpc_vars_sn2); + rp->sn.sn2.vars_pa = xp_pa(xpc_vars_sn2); /* vars_part array follows immediately after vars */ xpc_vars_part_sn2 = (struct xpc_vars_part_sn2 *)((u8 *)XPC_RP_VARS(rp) + @@ -693,6 +700,33 @@ xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp) return 0; } +static int +xpc_hb_allowed_sn2(short partid, void *heartbeating_to_mask) +{ + return test_bit(partid, heartbeating_to_mask); +} + +static void +xpc_allow_hb_sn2(short partid) +{ + DBUG_ON(xpc_vars_sn2 == NULL); + set_bit(partid, xpc_vars_sn2->heartbeating_to_mask); +} + +static void +xpc_disallow_hb_sn2(short partid) +{ + DBUG_ON(xpc_vars_sn2 == NULL); + clear_bit(partid, xpc_vars_sn2->heartbeating_to_mask); +} + +static void +xpc_disallow_all_hbs_sn2(void) +{ + DBUG_ON(xpc_vars_sn2 == NULL); + bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, xp_max_npartitions); +} + static void xpc_increment_heartbeat_sn2(void) { @@ -719,7 +753,6 @@ xpc_heartbeat_init_sn2(void) DBUG_ON(xpc_vars_sn2 == NULL); bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2); - xpc_heartbeating_to_mask = &xpc_vars_sn2->heartbeating_to_mask[0]; xpc_online_heartbeat_sn2(); } @@ -751,9 +784,9 @@ xpc_get_remote_heartbeat_sn2(struct xpc_partition *part) remote_vars->heartbeating_to_mask[0]); if ((remote_vars->heartbeat == part->last_heartbeat && - remote_vars->heartbeat_offline == 0) || - !xpc_hb_allowed(sn_partition_id, - &remote_vars->heartbeating_to_mask)) { + !remote_vars->heartbeat_offline) || + !xpc_hb_allowed_sn2(sn_partition_id, + remote_vars->heartbeating_to_mask)) { ret = xpNoHeartbeat; } else { part->last_heartbeat = remote_vars->heartbeat; @@ -972,7 +1005,7 @@ xpc_identify_activate_IRQ_req_sn2(int nasid) return; } - remote_vars_pa = remote_rp->sn.vars_pa; + remote_vars_pa = remote_rp->sn.sn2.vars_pa; remote_rp_version = remote_rp->version; remote_rp_ts_jiffies = remote_rp->ts_jiffies; @@ -1129,7 +1162,7 @@ xpc_process_activate_IRQ_rcvd_sn2(void) * Setup the channel structures that are sn2 specific. */ static enum xp_retval -xpc_setup_ch_structures_sn_sn2(struct xpc_partition *part) +xpc_setup_ch_structures_sn2(struct xpc_partition *part) { struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2; struct xpc_channel_sn2 *ch_sn2; @@ -1251,7 +1284,7 @@ out_1: * Teardown the channel structures that are sn2 specific. */ static void -xpc_teardown_ch_structures_sn_sn2(struct xpc_partition *part) +xpc_teardown_ch_structures_sn2(struct xpc_partition *part) { struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2; short partid = XPC_PARTID(part); @@ -2315,61 +2348,70 @@ xpc_received_payload_sn2(struct xpc_channel *ch, void *payload) xpc_acknowledge_msgs_sn2(ch, get, msg->flags); } +static struct xpc_arch_operations xpc_arch_ops_sn2 = { + .setup_partitions = xpc_setup_partitions_sn2, + .teardown_partitions = xpc_teardown_partitions_sn2, + .process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2, + .get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2, + .setup_rsvd_page = xpc_setup_rsvd_page_sn2, + + .allow_hb = xpc_allow_hb_sn2, + .disallow_hb = xpc_disallow_hb_sn2, + .disallow_all_hbs = xpc_disallow_all_hbs_sn2, + .increment_heartbeat = xpc_increment_heartbeat_sn2, + .offline_heartbeat = xpc_offline_heartbeat_sn2, + .online_heartbeat = xpc_online_heartbeat_sn2, + .heartbeat_init = xpc_heartbeat_init_sn2, + .heartbeat_exit = xpc_heartbeat_exit_sn2, + .get_remote_heartbeat = xpc_get_remote_heartbeat_sn2, + + .request_partition_activation = + xpc_request_partition_activation_sn2, + .request_partition_reactivation = + xpc_request_partition_reactivation_sn2, + .request_partition_deactivation = + xpc_request_partition_deactivation_sn2, + .cancel_partition_deactivation_request = + xpc_cancel_partition_deactivation_request_sn2, + + .setup_ch_structures = xpc_setup_ch_structures_sn2, + .teardown_ch_structures = xpc_teardown_ch_structures_sn2, + + .make_first_contact = xpc_make_first_contact_sn2, + + .get_chctl_all_flags = xpc_get_chctl_all_flags_sn2, + .send_chctl_closerequest = xpc_send_chctl_closerequest_sn2, + .send_chctl_closereply = xpc_send_chctl_closereply_sn2, + .send_chctl_openrequest = xpc_send_chctl_openrequest_sn2, + .send_chctl_openreply = xpc_send_chctl_openreply_sn2, + .send_chctl_opencomplete = xpc_send_chctl_opencomplete_sn2, + .process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2, + + .save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_sn2, + + .setup_msg_structures = xpc_setup_msg_structures_sn2, + .teardown_msg_structures = xpc_teardown_msg_structures_sn2, + + .indicate_partition_engaged = xpc_indicate_partition_engaged_sn2, + .indicate_partition_disengaged = xpc_indicate_partition_disengaged_sn2, + .partition_engaged = xpc_partition_engaged_sn2, + .any_partition_engaged = xpc_any_partition_engaged_sn2, + .assume_partition_disengaged = xpc_assume_partition_disengaged_sn2, + + .n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_sn2, + .send_payload = xpc_send_payload_sn2, + .get_deliverable_payload = xpc_get_deliverable_payload_sn2, + .received_payload = xpc_received_payload_sn2, + .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2, +}; + int xpc_init_sn2(void) { int ret; size_t buf_size; - xpc_setup_partitions_sn = xpc_setup_partitions_sn_sn2; - xpc_teardown_partitions_sn = xpc_teardown_partitions_sn_sn2; - xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2; - xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_sn2; - xpc_increment_heartbeat = xpc_increment_heartbeat_sn2; - xpc_offline_heartbeat = xpc_offline_heartbeat_sn2; - xpc_online_heartbeat = xpc_online_heartbeat_sn2; - xpc_heartbeat_init = xpc_heartbeat_init_sn2; - xpc_heartbeat_exit = xpc_heartbeat_exit_sn2; - xpc_get_remote_heartbeat = xpc_get_remote_heartbeat_sn2; - - xpc_request_partition_activation = xpc_request_partition_activation_sn2; - xpc_request_partition_reactivation = - xpc_request_partition_reactivation_sn2; - xpc_request_partition_deactivation = - xpc_request_partition_deactivation_sn2; - xpc_cancel_partition_deactivation_request = - xpc_cancel_partition_deactivation_request_sn2; - - xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2; - xpc_setup_ch_structures_sn = xpc_setup_ch_structures_sn_sn2; - xpc_teardown_ch_structures_sn = xpc_teardown_ch_structures_sn_sn2; - xpc_make_first_contact = xpc_make_first_contact_sn2; - - xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_sn2; - xpc_send_chctl_closerequest = xpc_send_chctl_closerequest_sn2; - xpc_send_chctl_closereply = xpc_send_chctl_closereply_sn2; - xpc_send_chctl_openrequest = xpc_send_chctl_openrequest_sn2; - xpc_send_chctl_openreply = xpc_send_chctl_openreply_sn2; - - xpc_save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_sn2; - - xpc_setup_msg_structures = xpc_setup_msg_structures_sn2; - xpc_teardown_msg_structures = xpc_teardown_msg_structures_sn2; - - xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2; - xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_sn2; - xpc_n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_sn2; - xpc_get_deliverable_payload = xpc_get_deliverable_payload_sn2; - - xpc_indicate_partition_engaged = xpc_indicate_partition_engaged_sn2; - xpc_indicate_partition_disengaged = - xpc_indicate_partition_disengaged_sn2; - xpc_partition_engaged = xpc_partition_engaged_sn2; - xpc_any_partition_engaged = xpc_any_partition_engaged_sn2; - xpc_assume_partition_disengaged = xpc_assume_partition_disengaged_sn2; - - xpc_send_payload = xpc_send_payload_sn2; - xpc_received_payload = xpc_received_payload_sn2; + xpc_arch_ops = xpc_arch_ops_sn2; if (offsetof(struct xpc_msg_sn2, payload) > XPC_MSG_HDR_MAX_SIZE) { dev_err(xpc_part, "header portion of struct xpc_msg_sn2 is " diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index f7fff4727ed..9172fcdee4e 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -46,8 +46,7 @@ struct uv_IO_APIC_route_entry { }; #endif -static atomic64_t xpc_heartbeat_uv; -static DECLARE_BITMAP(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV); +static struct xpc_heartbeat_uv *xpc_heartbeat_uv; #define XPC_ACTIVATE_MSG_SIZE_UV (1 * GRU_CACHE_LINE_BYTES) #define XPC_ACTIVATE_MQ_SIZE_UV (4 * XP_MAX_NPARTITIONS_UV * \ @@ -63,7 +62,7 @@ static struct xpc_gru_mq_uv *xpc_activate_mq_uv; static struct xpc_gru_mq_uv *xpc_notify_mq_uv; static int -xpc_setup_partitions_sn_uv(void) +xpc_setup_partitions_uv(void) { short partid; struct xpc_partition_uv *part_uv; @@ -79,7 +78,7 @@ xpc_setup_partitions_sn_uv(void) } static void -xpc_teardown_partitions_sn_uv(void) +xpc_teardown_partitions_uv(void) { short partid; struct xpc_partition_uv *part_uv; @@ -423,41 +422,6 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, /* syncing of remote_act_state was just done above */ break; - case XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV: { - struct xpc_activate_mq_msg_heartbeat_req_uv *msg; - - msg = container_of(msg_hdr, - struct xpc_activate_mq_msg_heartbeat_req_uv, - hdr); - part_uv->heartbeat = msg->heartbeat; - break; - } - case XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV: { - struct xpc_activate_mq_msg_heartbeat_req_uv *msg; - - msg = container_of(msg_hdr, - struct xpc_activate_mq_msg_heartbeat_req_uv, - hdr); - part_uv->heartbeat = msg->heartbeat; - - spin_lock_irqsave(&part_uv->flags_lock, irq_flags); - part_uv->flags |= XPC_P_HEARTBEAT_OFFLINE_UV; - spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); - break; - } - case XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV: { - struct xpc_activate_mq_msg_heartbeat_req_uv *msg; - - msg = container_of(msg_hdr, - struct xpc_activate_mq_msg_heartbeat_req_uv, - hdr); - part_uv->heartbeat = msg->heartbeat; - - spin_lock_irqsave(&part_uv->flags_lock, irq_flags); - part_uv->flags &= ~XPC_P_HEARTBEAT_OFFLINE_UV; - spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); - break; - } case XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV: { struct xpc_activate_mq_msg_activate_req_uv *msg; @@ -475,6 +439,7 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV; part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */ part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies; + part_uv->heartbeat_gpa = msg->heartbeat_gpa; if (msg->activate_gru_mq_desc_gpa != part_uv->activate_gru_mq_desc_gpa) { @@ -569,6 +534,17 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, xpc_wakeup_channel_mgr(part); break; } + case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: { + struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg; + + msg = container_of(msg_hdr, struct + xpc_activate_mq_msg_chctl_opencomplete_uv, hdr); + spin_lock_irqsave(&part->chctl_lock, irq_flags); + part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENCOMPLETE; + spin_unlock_irqrestore(&part->chctl_lock, irq_flags); + + xpc_wakeup_channel_mgr(part); + } case XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV: spin_lock_irqsave(&part_uv->flags_lock, irq_flags); part_uv->flags |= XPC_P_ENGAGED_UV; @@ -759,7 +735,7 @@ xpc_send_local_activate_IRQ_uv(struct xpc_partition *part, int act_state_req) /* * !!! Make our side think that the remote partition sent an activate - * !!! message our way by doing what the activate IRQ handler would + * !!! mq message our way by doing what the activate IRQ handler would * !!! do had one really been sent. */ @@ -806,90 +782,82 @@ xpc_get_partition_rsvd_page_pa_uv(void *buf, u64 *cookie, unsigned long *rp_pa, } static int -xpc_setup_rsvd_page_sn_uv(struct xpc_rsvd_page *rp) +xpc_setup_rsvd_page_uv(struct xpc_rsvd_page *rp) { - rp->sn.activate_gru_mq_desc_gpa = + xpc_heartbeat_uv = + &xpc_partitions[sn_partition_id].sn.uv.cached_heartbeat; + rp->sn.uv.heartbeat_gpa = uv_gpa(xpc_heartbeat_uv); + rp->sn.uv.activate_gru_mq_desc_gpa = uv_gpa(xpc_activate_mq_uv->gru_mq_desc); return 0; } static void -xpc_send_heartbeat_uv(int msg_type) +xpc_allow_hb_uv(short partid) { - short partid; - struct xpc_partition *part; - struct xpc_activate_mq_msg_heartbeat_req_uv msg; - - /* - * !!! On uv we're broadcasting a heartbeat message every 5 seconds. - * !!! Whereas on sn2 we're bte_copy'ng the heartbeat info every 20 - * !!! seconds. This is an increase in numalink traffic. - * ??? Is this good? - */ - - msg.heartbeat = atomic64_inc_return(&xpc_heartbeat_uv); - - partid = find_first_bit(xpc_heartbeating_to_mask_uv, - XP_MAX_NPARTITIONS_UV); - - while (partid < XP_MAX_NPARTITIONS_UV) { - part = &xpc_partitions[partid]; +} - xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg), - msg_type); +static void +xpc_disallow_hb_uv(short partid) +{ +} - partid = find_next_bit(xpc_heartbeating_to_mask_uv, - XP_MAX_NPARTITIONS_UV, partid + 1); - } +static void +xpc_disallow_all_hbs_uv(void) +{ } static void xpc_increment_heartbeat_uv(void) { - xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV); + xpc_heartbeat_uv->value++; } static void xpc_offline_heartbeat_uv(void) { - xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV); + xpc_increment_heartbeat_uv(); + xpc_heartbeat_uv->offline = 1; } static void xpc_online_heartbeat_uv(void) { - xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV); + xpc_increment_heartbeat_uv(); + xpc_heartbeat_uv->offline = 0; } static void xpc_heartbeat_init_uv(void) { - atomic64_set(&xpc_heartbeat_uv, 0); - bitmap_zero(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV); - xpc_heartbeating_to_mask = &xpc_heartbeating_to_mask_uv[0]; + xpc_heartbeat_uv->value = 1; + xpc_heartbeat_uv->offline = 0; } static void xpc_heartbeat_exit_uv(void) { - xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV); + xpc_offline_heartbeat_uv(); } static enum xp_retval xpc_get_remote_heartbeat_uv(struct xpc_partition *part) { struct xpc_partition_uv *part_uv = &part->sn.uv; - enum xp_retval ret = xpNoHeartbeat; + enum xp_retval ret; - if (part_uv->remote_act_state != XPC_P_AS_INACTIVE && - part_uv->remote_act_state != XPC_P_AS_DEACTIVATING) { + ret = xp_remote_memcpy(uv_gpa(&part_uv->cached_heartbeat), + part_uv->heartbeat_gpa, + sizeof(struct xpc_heartbeat_uv)); + if (ret != xpSuccess) + return ret; - if (part_uv->heartbeat != part->last_heartbeat || - (part_uv->flags & XPC_P_HEARTBEAT_OFFLINE_UV)) { + if (part_uv->cached_heartbeat.value == part->last_heartbeat && + !part_uv->cached_heartbeat.offline) { - part->last_heartbeat = part_uv->heartbeat; - ret = xpSuccess; - } + ret = xpNoHeartbeat; + } else { + part->last_heartbeat = part_uv->cached_heartbeat.value; } return ret; } @@ -904,8 +872,9 @@ xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp, part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */ part->remote_rp_ts_jiffies = remote_rp->ts_jiffies; + part->sn.uv.heartbeat_gpa = remote_rp->sn.uv.heartbeat_gpa; part->sn.uv.activate_gru_mq_desc_gpa = - remote_rp->sn.activate_gru_mq_desc_gpa; + remote_rp->sn.uv.activate_gru_mq_desc_gpa; /* * ??? Is it a good idea to make this conditional on what is @@ -913,8 +882,9 @@ xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp, */ if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) { msg.rp_gpa = uv_gpa(xpc_rsvd_page); + msg.heartbeat_gpa = xpc_rsvd_page->sn.uv.heartbeat_gpa; msg.activate_gru_mq_desc_gpa = - xpc_rsvd_page->sn.activate_gru_mq_desc_gpa; + xpc_rsvd_page->sn.uv.activate_gru_mq_desc_gpa; xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg), XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV); } @@ -1010,7 +980,7 @@ xpc_n_of_fifo_entries_uv(struct xpc_fifo_head_uv *head) * Setup the channel structures that are uv specific. */ static enum xp_retval -xpc_setup_ch_structures_sn_uv(struct xpc_partition *part) +xpc_setup_ch_structures_uv(struct xpc_partition *part) { struct xpc_channel_uv *ch_uv; int ch_number; @@ -1029,7 +999,7 @@ xpc_setup_ch_structures_sn_uv(struct xpc_partition *part) * Teardown the channel structures that are uv specific. */ static void -xpc_teardown_ch_structures_sn_uv(struct xpc_partition *part) +xpc_teardown_ch_structures_uv(struct xpc_partition *part) { /* nothing needs to be done */ return; @@ -1243,6 +1213,16 @@ xpc_send_chctl_openreply_uv(struct xpc_channel *ch, unsigned long *irq_flags) } static void +xpc_send_chctl_opencomplete_uv(struct xpc_channel *ch, unsigned long *irq_flags) +{ + struct xpc_activate_mq_msg_chctl_opencomplete_uv msg; + + msg.ch_number = ch->number; + xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg), + XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV); +} + +static void xpc_send_chctl_local_msgrequest_uv(struct xpc_partition *part, int ch_number) { unsigned long irq_flags; @@ -1669,58 +1649,67 @@ xpc_received_payload_uv(struct xpc_channel *ch, void *payload) msg->hdr.msg_slot_number += ch->remote_nentries; } +static struct xpc_arch_operations xpc_arch_ops_uv = { + .setup_partitions = xpc_setup_partitions_uv, + .teardown_partitions = xpc_teardown_partitions_uv, + .process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv, + .get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv, + .setup_rsvd_page = xpc_setup_rsvd_page_uv, + + .allow_hb = xpc_allow_hb_uv, + .disallow_hb = xpc_disallow_hb_uv, + .disallow_all_hbs = xpc_disallow_all_hbs_uv, + .increment_heartbeat = xpc_increment_heartbeat_uv, + .offline_heartbeat = xpc_offline_heartbeat_uv, + .online_heartbeat = xpc_online_heartbeat_uv, + .heartbeat_init = xpc_heartbeat_init_uv, + .heartbeat_exit = xpc_heartbeat_exit_uv, + .get_remote_heartbeat = xpc_get_remote_heartbeat_uv, + + .request_partition_activation = + xpc_request_partition_activation_uv, + .request_partition_reactivation = + xpc_request_partition_reactivation_uv, + .request_partition_deactivation = + xpc_request_partition_deactivation_uv, + .cancel_partition_deactivation_request = + xpc_cancel_partition_deactivation_request_uv, + + .setup_ch_structures = xpc_setup_ch_structures_uv, + .teardown_ch_structures = xpc_teardown_ch_structures_uv, + + .make_first_contact = xpc_make_first_contact_uv, + + .get_chctl_all_flags = xpc_get_chctl_all_flags_uv, + .send_chctl_closerequest = xpc_send_chctl_closerequest_uv, + .send_chctl_closereply = xpc_send_chctl_closereply_uv, + .send_chctl_openrequest = xpc_send_chctl_openrequest_uv, + .send_chctl_openreply = xpc_send_chctl_openreply_uv, + .send_chctl_opencomplete = xpc_send_chctl_opencomplete_uv, + .process_msg_chctl_flags = xpc_process_msg_chctl_flags_uv, + + .save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_uv, + + .setup_msg_structures = xpc_setup_msg_structures_uv, + .teardown_msg_structures = xpc_teardown_msg_structures_uv, + + .indicate_partition_engaged = xpc_indicate_partition_engaged_uv, + .indicate_partition_disengaged = xpc_indicate_partition_disengaged_uv, + .assume_partition_disengaged = xpc_assume_partition_disengaged_uv, + .partition_engaged = xpc_partition_engaged_uv, + .any_partition_engaged = xpc_any_partition_engaged_uv, + + .n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_uv, + .send_payload = xpc_send_payload_uv, + .get_deliverable_payload = xpc_get_deliverable_payload_uv, + .received_payload = xpc_received_payload_uv, + .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv, +}; + int xpc_init_uv(void) { - xpc_setup_partitions_sn = xpc_setup_partitions_sn_uv; - xpc_teardown_partitions_sn = xpc_teardown_partitions_sn_uv; - xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv; - xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv; - xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_uv; - xpc_increment_heartbeat = xpc_increment_heartbeat_uv; - xpc_offline_heartbeat = xpc_offline_heartbeat_uv; - xpc_online_heartbeat = xpc_online_heartbeat_uv; - xpc_heartbeat_init = xpc_heartbeat_init_uv; - xpc_heartbeat_exit = xpc_heartbeat_exit_uv; - xpc_get_remote_heartbeat = xpc_get_remote_heartbeat_uv; - - xpc_request_partition_activation = xpc_request_partition_activation_uv; - xpc_request_partition_reactivation = - xpc_request_partition_reactivation_uv; - xpc_request_partition_deactivation = - xpc_request_partition_deactivation_uv; - xpc_cancel_partition_deactivation_request = - xpc_cancel_partition_deactivation_request_uv; - - xpc_setup_ch_structures_sn = xpc_setup_ch_structures_sn_uv; - xpc_teardown_ch_structures_sn = xpc_teardown_ch_structures_sn_uv; - - xpc_make_first_contact = xpc_make_first_contact_uv; - - xpc_get_chctl_all_flags = xpc_get_chctl_all_flags_uv; - xpc_send_chctl_closerequest = xpc_send_chctl_closerequest_uv; - xpc_send_chctl_closereply = xpc_send_chctl_closereply_uv; - xpc_send_chctl_openrequest = xpc_send_chctl_openrequest_uv; - xpc_send_chctl_openreply = xpc_send_chctl_openreply_uv; - - xpc_save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_uv; - - xpc_setup_msg_structures = xpc_setup_msg_structures_uv; - xpc_teardown_msg_structures = xpc_teardown_msg_structures_uv; - - xpc_indicate_partition_engaged = xpc_indicate_partition_engaged_uv; - xpc_indicate_partition_disengaged = - xpc_indicate_partition_disengaged_uv; - xpc_assume_partition_disengaged = xpc_assume_partition_disengaged_uv; - xpc_partition_engaged = xpc_partition_engaged_uv; - xpc_any_partition_engaged = xpc_any_partition_engaged_uv; - - xpc_n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_uv; - xpc_process_msg_chctl_flags = xpc_process_msg_chctl_flags_uv; - xpc_send_payload = xpc_send_payload_uv; - xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv; - xpc_get_deliverable_payload = xpc_get_deliverable_payload_uv; - xpc_received_payload = xpc_received_payload_uv; + xpc_arch_ops = xpc_arch_ops_uv; if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) { dev_err(xpc_part, "xpc_notify_mq_msghdr_uv is larger than %d\n", diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c index deb7b53167e..83a12125b94 100644 --- a/drivers/net/atl1c/atl1c_main.c +++ b/drivers/net/atl1c/atl1c_main.c @@ -2532,8 +2532,8 @@ static int __devinit atl1c_probe(struct pci_dev *pdev, * various kernel subsystems to support the mechanics required by a * fixed-high-32-bit system. */ - if ((pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) || - (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) != 0)) { + if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) || + (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) { dev_err(&pdev->dev, "No usable DMA configuration,aborting\n"); goto err_dma; } diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 9b75aa63006..30d0c81c989 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1821,11 +1821,11 @@ static int __devinit be_probe(struct pci_dev *pdev, be_msix_enable(adapter); - status = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); if (!status) { netdev->features |= NETIF_F_HIGHDMA; } else { - status = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + status = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (status) { dev_err(&pdev->dev, "Could not set PCI DMA Mask\n"); goto free_netdev; diff --git a/drivers/net/jme.c b/drivers/net/jme.c index ece35040288..621a7c0c46b 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -2591,13 +2591,13 @@ static int jme_pci_dma64(struct pci_dev *pdev) { if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 && - !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) - if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) + !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) + if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) return 1; if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 && - !pci_set_dma_mask(pdev, DMA_40BIT_MASK)) - if (!pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK)) + !pci_set_dma_mask(pdev, DMA_BIT_MASK(40))) + if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40))) return 1; if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) diff --git a/drivers/net/wireless/ath9k/pci.c b/drivers/net/wireless/ath9k/pci.c index 6dbc58580ab..168411d322a 100644 --- a/drivers/net/wireless/ath9k/pci.c +++ b/drivers/net/wireless/ath9k/pci.c @@ -93,14 +93,14 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (pci_enable_device(pdev)) return -EIO; - ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (ret) { printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); goto bad; } - ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); if (ret) { printk(KERN_ERR "ath9k: 32-bit DMA consistent " diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index e3569a0a952..b1610ea4bb3 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c @@ -492,8 +492,8 @@ static int __devinit p54p_probe(struct pci_dev *pdev, goto err_disable_dev; } - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || - pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) || + pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { dev_err(&pdev->dev, "No suitable DMA available\n"); goto err_free_reg; } diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 4fa3bb2ddfe..33e5ade774c 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -434,7 +434,8 @@ static void __init superio_parport_init(void) 0 /*base_hi*/, PAR_IRQ, PARPORT_DMA_NONE /* dma */, - NULL /*struct pci_dev* */) ) + NULL /*struct pci_dev* */), + 0 /* shared irq flags */ ) printk(KERN_WARNING PFX "Probing parallel port failed.\n"); #endif /* CONFIG_PARPORT_PC */ diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 25a00ce4f24..fa3a11365ec 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -173,12 +173,21 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header) struct dmar_drhd_unit *dmaru; int ret = 0; + drhd = (struct acpi_dmar_hardware_unit *)header; + if (!drhd->address) { + /* Promote an attitude of violence to a BIOS engineer today */ + WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n" + "BIOS vendor: %s; Ver: %s; Product Version: %s\n", + dmi_get_system_info(DMI_BIOS_VENDOR), + dmi_get_system_info(DMI_BIOS_VERSION), + dmi_get_system_info(DMI_PRODUCT_VERSION)); + return -ENODEV; + } dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL); if (!dmaru) return -ENOMEM; dmaru->hdr = header; - drhd = (struct acpi_dmar_hardware_unit *)header; dmaru->reg_base_addr = drhd->address; dmaru->segment = drhd->segment; dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index fb3a3f3fca7..001b328adf8 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -733,8 +733,8 @@ static void dma_pte_clear_range(struct dmar_domain *domain, u64 start, u64 end) start &= (((u64)1) << addr_width) - 1; end &= (((u64)1) << addr_width) - 1; /* in case it's partial page */ - start = PAGE_ALIGN(start); - end &= PAGE_MASK; + start &= PAGE_MASK; + end = PAGE_ALIGN(end); npages = (end - start) / VTD_PAGE_SIZE; /* we don't need lock here, nobody else touches the iova range */ diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index fdb14ec4fd4..8b7983aba8f 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -2234,10 +2234,10 @@ static int twa_resume(struct pci_dev *pdev) pci_set_master(pdev); pci_try_set_mwi(pdev); - if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) - || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) - || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) + || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) + || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { TW_PRINTK(host, TW_DRIVER, 0x40, "Failed to set dma mask during resume"); retval = -ENODEV; goto out_disable_device; diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 280261c451d..2a889853a10 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -1378,7 +1378,7 @@ int aac_get_adapter_info(struct aac_dev* dev) if (dev->nondasd_support && !dev->in_reset) printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id); - if (dma_get_required_mask(&dev->pdev->dev) > DMA_32BIT_MASK) + if (dma_get_required_mask(&dev->pdev->dev) > DMA_BIT_MASK(32)) dev->needs_dac = 1; dev->dac_support = 0; if ((sizeof(dma_addr_t) > 4) && dev->needs_dac && diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index b1bd3fc7bae..36fd2e75da1 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1394,7 +1394,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, */ cmd->sense_buffer[8] = 0; /* Information */ cmd->sense_buffer[9] = 0xa; /* Add. length */ - do_div(bghm, cmd->device->sector_size); + bghm /= cmd->device->sector_size; failing_sector = scsi_get_lba(cmd); failing_sector += bghm; diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 52427a8324f..a91f5143cea 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -855,9 +855,9 @@ _base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev) if (sizeof(dma_addr_t) > 4) { const uint64_t required_mask = dma_get_required_mask(&pdev->dev); - if ((required_mask > DMA_32BIT_MASK) && !pci_set_dma_mask(pdev, - DMA_64BIT_MASK) && !pci_set_consistent_dma_mask(pdev, - DMA_64BIT_MASK)) { + if ((required_mask > DMA_BIT_MASK(32)) && !pci_set_dma_mask(pdev, + DMA_BIT_MASK(64)) && !pci_set_consistent_dma_mask(pdev, + DMA_BIT_MASK(64))) { ioc->base_add_sg_single = &_base_add_sg_single_64; ioc->sge_size = sizeof(Mpi2SGESimple64_t); desc = "64"; @@ -865,8 +865,8 @@ _base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev) } } - if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK) - && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) + && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { ioc->base_add_sg_single = &_base_add_sg_single_32; ioc->sge_size = sizeof(Mpi2SGESimple32_t); desc = "32"; diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index e1850904ff7..fbc83bebdd8 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -38,9 +38,6 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) { }; #endif -/* scsi_scan.c */ -int scsi_complete_async_scans(void); - /* scsi_devinfo.c */ extern int scsi_get_device_flags(struct scsi_device *sdev, const unsigned char *vendor, diff --git a/drivers/scsi/scsi_wait_scan.c b/drivers/scsi/scsi_wait_scan.c index 8a636103083..2f21af21269 100644 --- a/drivers/scsi/scsi_wait_scan.c +++ b/drivers/scsi/scsi_wait_scan.c @@ -11,7 +11,7 @@ */ #include <linux/module.h> -#include "scsi_priv.h" +#include <scsi/scsi_scan.h> static int __init wait_scan_init(void) { diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 0328fd4006e..343e3a35b6a 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -854,7 +854,7 @@ config SERIAL_IMX_CONSOLE config SERIAL_UARTLITE tristate "Xilinx uartlite serial port support" - depends on PPC32 + depends on PPC32 || MICROBLAZE select SERIAL_CORE help Say Y here if you want to use the Xilinx uartlite serial controller. @@ -1340,7 +1340,7 @@ config SERIAL_NETX_CONSOLE config SERIAL_OF_PLATFORM tristate "Serial port on Open Firmware platform bus" - depends on PPC_OF + depends on PPC_OF || MICROBLAZE depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL help If you have a PowerPC based system that has serial ports diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 7fb9b5c4669..12d13d99b6f 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -44,6 +44,7 @@ struct intc_handle_int { struct intc_desc_int { struct list_head list; struct sys_device sysdev; + pm_message_t state; unsigned long *reg; #ifdef CONFIG_SMP unsigned long *smp; @@ -786,18 +787,44 @@ static int intc_suspend(struct sys_device *dev, pm_message_t state) /* get intc controller associated with this sysdev */ d = container_of(dev, struct intc_desc_int, sysdev); - /* enable wakeup irqs belonging to this intc controller */ - for_each_irq_desc(irq, desc) { - if ((desc->status & IRQ_WAKEUP) && (desc->chip == &d->chip)) - intc_enable(irq); + switch (state.event) { + case PM_EVENT_ON: + if (d->state.event != PM_EVENT_FREEZE) + break; + for_each_irq_desc(irq, desc) { + if (desc->chip != &d->chip) + continue; + if (desc->status & IRQ_DISABLED) + intc_disable(irq); + else + intc_enable(irq); + } + break; + case PM_EVENT_FREEZE: + /* nothing has to be done */ + break; + case PM_EVENT_SUSPEND: + /* enable wakeup irqs belonging to this intc controller */ + for_each_irq_desc(irq, desc) { + if ((desc->status & IRQ_WAKEUP) && (desc->chip == &d->chip)) + intc_enable(irq); + } + break; } + d->state = state; return 0; } +static int intc_resume(struct sys_device *dev) +{ + return intc_suspend(dev, PMSG_ON); +} + static struct sysdev_class intc_sysdev_class = { .name = "intc", .suspend = intc_suspend, + .resume = intc_resume, }; /* register this intc as sysdev to allow suspend/resume */ diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 643908b74bc..8eba98c8ed1 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -658,7 +658,7 @@ int spi_write_then_read(struct spi_device *spi, int status; struct spi_message message; - struct spi_transfer x; + struct spi_transfer x[2]; u8 *local_buf; /* Use preallocated DMA-safe buffer. We can't avoid copying here, @@ -669,9 +669,15 @@ int spi_write_then_read(struct spi_device *spi, return -EINVAL; spi_message_init(&message); - memset(&x, 0, sizeof x); - x.len = n_tx + n_rx; - spi_message_add_tail(&x, &message); + memset(x, 0, sizeof x); + if (n_tx) { + x[0].len = n_tx; + spi_message_add_tail(&x[0], &message); + } + if (n_rx) { + x[1].len = n_rx; + spi_message_add_tail(&x[1], &message); + } /* ... unless someone else is using the pre-allocated buffer */ if (!mutex_trylock(&lock)) { @@ -682,15 +688,15 @@ int spi_write_then_read(struct spi_device *spi, local_buf = buf; memcpy(local_buf, txbuf, n_tx); - x.tx_buf = local_buf; - x.rx_buf = local_buf; + x[0].tx_buf = local_buf; + x[1].rx_buf = local_buf + n_tx; /* do the i/o */ status = spi_sync(spi, &message); if (status == 0) - memcpy(rxbuf, x.rx_buf + n_tx, n_rx); + memcpy(rxbuf, x[1].rx_buf, n_rx); - if (x.tx_buf == buf) + if (x[0].tx_buf == buf) mutex_unlock(&lock); else kfree(local_buf); diff --git a/drivers/staging/b3dfg/b3dfg.c b/drivers/staging/b3dfg/b3dfg.c index 0348072b3ab..75ebe338c6f 100644 --- a/drivers/staging/b3dfg/b3dfg.c +++ b/drivers/staging/b3dfg/b3dfg.c @@ -1000,7 +1000,7 @@ static int __devinit b3dfg_probe(struct pci_dev *pdev, pci_set_master(pdev); - r = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + r = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (r) { dev_err(&pdev->dev, "no usable DMA configuration\n"); goto err_free_res; diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 869d47cb6db..0a69c0977e3 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -546,10 +546,6 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) tty->driver_data = acm; acm->tty = tty; - /* force low_latency on so that our tty_push actually forces the data through, - otherwise it is scheduled, and with high data rates data can get lost. */ - tty->low_latency = 1; - if (usb_autopm_get_interface(acm->control) < 0) goto early_bail; else diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index 4b933f646f2..c567168f89a 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -36,14 +36,14 @@ struct nop_usb_xceiv { struct device *dev; }; -static u64 nop_xceiv_dmamask = DMA_32BIT_MASK; +static u64 nop_xceiv_dmamask = DMA_BIT_MASK(32); static struct platform_device nop_xceiv_device = { .name = "nop_usb_xceiv", .id = -1, .dev = { .dma_mask = &nop_xceiv_dmamask, - .coherent_dma_mask = DMA_32BIT_MASK, + .coherent_dma_mask = DMA_BIT_MASK(32), .platform_data = NULL, }, }; diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 2620bf6fe5e..9c4c700c7cc 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -1215,20 +1215,22 @@ static void ti_bulk_in_callback(struct urb *urb) } tty = tty_port_tty_get(&port->port); - if (tty && urb->actual_length) { - usb_serial_debug_data(debug, dev, __func__, - urb->actual_length, urb->transfer_buffer); - - if (!tport->tp_is_open) - dbg("%s - port closed, dropping data", __func__); - else - ti_recv(&urb->dev->dev, tty, + if (tty) { + if (urb->actual_length) { + usb_serial_debug_data(debug, dev, __func__, + urb->actual_length, urb->transfer_buffer); + + if (!tport->tp_is_open) + dbg("%s - port closed, dropping data", + __func__); + else + ti_recv(&urb->dev->dev, tty, urb->transfer_buffer, urb->actual_length); - - spin_lock(&tport->tp_lock); - tport->tp_icount.rx += urb->actual_length; - spin_unlock(&tport->tp_lock); + spin_lock(&tport->tp_lock); + tport->tp_icount.rx += urb->actual_length; + spin_unlock(&tport->tp_lock); + } tty_kref_put(tty); } diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 16bb7e3c031..6c37e8ee5ef 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -698,8 +698,8 @@ static void __devinit radeon_get_pllinfo(struct radeonfb_info *rinfo) found: /* * Some methods fail to retrieve SCLK and MCLK values, we apply default - * settings in this case (200Mhz). If that really happne often, we could - * fetch from registers instead... + * settings in this case (200Mhz). If that really happens often, we + * could fetch from registers instead... */ if (rinfo->pll.mclk == 0) rinfo->pll.mclk = 20000; diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index dd37cbcaf8c..157057c79ca 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -35,8 +35,6 @@ static int fb_notifier_callback(struct notifier_block *self, return 0; bd = container_of(self, struct backlight_device, fb_notif); - if (!lock_fb_info(evdata->info)) - return -ENODEV; mutex_lock(&bd->ops_lock); if (bd->ops) if (!bd->ops->check_fb || @@ -49,7 +47,6 @@ static int fb_notifier_callback(struct notifier_block *self, backlight_update_status(bd); } mutex_unlock(&bd->ops_lock); - unlock_fb_info(evdata->info); return 0; } diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 0bb13df0fa8..b6449470106 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -40,8 +40,6 @@ static int fb_notifier_callback(struct notifier_block *self, if (!ld->ops) return 0; - if (!lock_fb_info(evdata->info)) - return -ENODEV; mutex_lock(&ld->ops_lock); if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) { if (event == FB_EVENT_BLANK) { @@ -53,7 +51,6 @@ static int fb_notifier_callback(struct notifier_block *self, } } mutex_unlock(&ld->ops_lock); - unlock_fb_info(evdata->info); return 0; } diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index d42e385f091..4c2bf923418 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -567,9 +567,7 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, default: dev_dbg(info->device, "Unsupported bpp size: %d\n", var->bits_per_pixel); - assert(false); - /* should never occur */ - break; + return -EINVAL; } if (var->xres_virtual < var->xres) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 2cd500a304f..471a9a60376 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2263,9 +2263,12 @@ static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info, } + if (!lock_fb_info(info)) + return; event.info = info; event.data = ␣ fb_notifier_call_chain(FB_EVENT_CONBLANK, &event); + unlock_fb_info(info); } static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) @@ -2956,8 +2959,6 @@ static int fbcon_fb_unregistered(struct fb_info *info) { int i, idx; - if (!lock_fb_info(info)) - return -ENODEV; idx = info->node; for (i = first_fb_vc; i <= last_fb_vc; i++) { if (con2fb_map[i] == idx) @@ -2985,8 +2986,6 @@ static int fbcon_fb_unregistered(struct fb_info *info) if (primary_device == idx) primary_device = -1; - unlock_fb_info(info); - if (!num_registered_fb) unregister_con_driver(&fb_con); @@ -3027,11 +3026,8 @@ static int fbcon_fb_registered(struct fb_info *info) { int ret = 0, i, idx; - if (!lock_fb_info(info)) - return -ENODEV; idx = info->node; fbcon_select_primary(info); - unlock_fb_info(info); if (info_idx == -1) { for (i = first_fb_vc; i <= last_fb_vc; i++) { @@ -3152,53 +3148,23 @@ static int fbcon_event_notify(struct notifier_block *self, switch(action) { case FB_EVENT_SUSPEND: - if (!lock_fb_info(info)) { - ret = -ENODEV; - goto done; - } fbcon_suspended(info); - unlock_fb_info(info); break; case FB_EVENT_RESUME: - if (!lock_fb_info(info)) { - ret = -ENODEV; - goto done; - } fbcon_resumed(info); - unlock_fb_info(info); break; case FB_EVENT_MODE_CHANGE: - if (!lock_fb_info(info)) { - ret = -ENODEV; - goto done; - } fbcon_modechanged(info); - unlock_fb_info(info); break; case FB_EVENT_MODE_CHANGE_ALL: - if (!lock_fb_info(info)) { - ret = -ENODEV; - goto done; - } fbcon_set_all_vcs(info); - unlock_fb_info(info); break; case FB_EVENT_MODE_DELETE: mode = event->data; - if (!lock_fb_info(info)) { - ret = -ENODEV; - goto done; - } ret = fbcon_mode_deleted(info, mode); - unlock_fb_info(info); break; case FB_EVENT_FB_UNBIND: - if (!lock_fb_info(info)) { - ret = -ENODEV; - goto done; - } idx = info->node; - unlock_fb_info(info); ret = fbcon_fb_unbind(idx); break; case FB_EVENT_FB_REGISTERED: @@ -3217,29 +3183,14 @@ static int fbcon_event_notify(struct notifier_block *self, con2fb->framebuffer = con2fb_map[con2fb->console - 1]; break; case FB_EVENT_BLANK: - if (!lock_fb_info(info)) { - ret = -ENODEV; - goto done; - } fbcon_fb_blanked(info, *(int *)event->data); - unlock_fb_info(info); break; case FB_EVENT_NEW_MODELIST: - if (!lock_fb_info(info)) { - ret = -ENODEV; - goto done; - } fbcon_new_modelist(info); - unlock_fb_info(info); break; case FB_EVENT_GET_REQ: caps = event->data; - if (!lock_fb_info(info)) { - ret = -ENODEV; - goto done; - } fbcon_get_requirement(info, caps); - unlock_fb_info(info); break; } done: diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 0c5b9a9fd56..8dea2bc9270 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -210,12 +210,15 @@ static int __init efifb_probe(struct platform_device *dev) unsigned int size_total; int request_succeeded = 0; - printk(KERN_INFO "efifb: probing for efifb\n"); - if (!screen_info.lfb_depth) screen_info.lfb_depth = 32; if (!screen_info.pages) screen_info.pages = 1; + if (!screen_info.lfb_base) { + printk(KERN_DEBUG "efifb: invalid framebuffer address\n"); + return -ENODEV; + } + printk(KERN_INFO "efifb: probing for efifb\n"); /* just assume they're all unset if any are */ if (!screen_info.blue_size) { diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 2ac32e6b595..d412a1ddc12 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1097,8 +1097,11 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, return -EINVAL; con2fb.framebuffer = -1; event.data = &con2fb; + if (!lock_fb_info(info)) + return -ENODEV; event.info = info; fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); + unlock_fb_info(info); ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; break; case FBIOPUT_CON2FBMAP: @@ -1115,8 +1118,11 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, break; } event.data = &con2fb; + if (!lock_fb_info(info)) + return -ENODEV; event.info = info; ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); + unlock_fb_info(info); break; case FBIOBLANK: if (!lock_fb_info(info)) @@ -1521,7 +1527,10 @@ register_framebuffer(struct fb_info *fb_info) registered_fb[i] = fb_info; event.info = fb_info; + if (!lock_fb_info(fb_info)) + return -ENODEV; fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); + unlock_fb_info(fb_info); return 0; } @@ -1555,8 +1564,12 @@ unregister_framebuffer(struct fb_info *fb_info) goto done; } + + if (!lock_fb_info(fb_info)) + return -ENODEV; event.info = fb_info; ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); + unlock_fb_info(fb_info); if (ret) { ret = -EINVAL; @@ -1590,6 +1603,8 @@ void fb_set_suspend(struct fb_info *info, int state) { struct fb_event event; + if (!lock_fb_info(info)) + return; event.info = info; if (state) { fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); @@ -1598,6 +1613,7 @@ void fb_set_suspend(struct fb_info *info, int state) info->state = FBINFO_STATE_RUNNING; fb_notifier_call_chain(FB_EVENT_RESUME, &event); } + unlock_fb_info(info); } /** @@ -1667,8 +1683,11 @@ int fb_new_modelist(struct fb_info *info) err = 1; if (!list_empty(&info->modelist)) { + if (!lock_fb_info(info)) + return -ENODEV; event.info = info; err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); + unlock_fb_info(info); } return err; diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h index a50bea61480..40984551c92 100644 --- a/drivers/video/intelfb/intelfb.h +++ b/drivers/video/intelfb/intelfb.h @@ -53,6 +53,7 @@ #define PCI_DEVICE_ID_INTEL_830M 0x3577 #define PCI_DEVICE_ID_INTEL_845G 0x2562 #define PCI_DEVICE_ID_INTEL_85XGM 0x3582 +#define PCI_DEVICE_ID_INTEL_854 0x358E #define PCI_DEVICE_ID_INTEL_865G 0x2572 #define PCI_DEVICE_ID_INTEL_915G 0x2582 #define PCI_DEVICE_ID_INTEL_915GM 0x2592 @@ -154,6 +155,7 @@ enum intel_chips { INTEL_85XGM, INTEL_852GM, INTEL_852GME, + INTEL_854, INTEL_855GM, INTEL_855GME, INTEL_865G, diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/intelfb/intelfb_i2c.c index b3065492bb2..487f2be4746 100644 --- a/drivers/video/intelfb/intelfb_i2c.c +++ b/drivers/video/intelfb/intelfb_i2c.c @@ -156,6 +156,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo) switch(dinfo->chipset) { case INTEL_830M: case INTEL_845G: + case INTEL_854: case INTEL_855GM: case INTEL_865G: dinfo->output[i].type = INTELFB_OUTPUT_DVO; diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 6d8e5415c80..ace14fe02fc 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -182,6 +182,7 @@ static struct pci_device_id intelfb_pci_table[] __devinitdata = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_854, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_854 }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G }, diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 8b26b27c2db..0689f97c523 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c @@ -84,6 +84,11 @@ int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo) dinfo->mobile = 0; dinfo->pll_index = PLLS_I8xx; return 0; + case PCI_DEVICE_ID_INTEL_854: + dinfo->mobile = 1; + dinfo->name = "Intel(R) 854"; + dinfo->chipset = INTEL_854; + return 0; case PCI_DEVICE_ID_INTEL_85XGM: tmp = 0; dinfo->mobile = 1; diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 4dcec48a1d7..c3fad34309e 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c @@ -45,11 +45,11 @@ struct s3fb_info { static const struct svga_fb_format s3fb_formats[] = { { 0, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0, FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4, FB_VISUAL_PSEUDOCOLOR, 8, 16}, - { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0, + { 4, {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, 0, FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 8, 16}, - { 4, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 1, + { 4, {0, 4, 0}, {0, 4, 0}, {0, 4, 0}, {0, 0, 0}, 1, FB_TYPE_INTERLEAVED_PLANES, 1, FB_VISUAL_PSEUDOCOLOR, 8, 16}, - { 8, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0, + { 8, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_PSEUDOCOLOR, 4, 8}, {16, {10, 5, 0}, {5, 5, 0}, {0, 5, 0}, {0, 0, 0}, 0, FB_TYPE_PACKED_PIXELS, 0, FB_VISUAL_TRUECOLOR, 2, 4}, diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index fad58cf9ef7..10ddad8e17d 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -199,16 +199,20 @@ extern void (*sa1100fb_backlight_power)(int on); extern void (*sa1100fb_lcd_power)(int on); -/* - * IMHO this looks wrong. In 8BPP, length should be 8. - */ -static struct sa1100fb_rgb rgb_8 = { +static struct sa1100fb_rgb rgb_4 = { .red = { .offset = 0, .length = 4, }, .green = { .offset = 0, .length = 4, }, .blue = { .offset = 0, .length = 4, }, .transp = { .offset = 0, .length = 0, }, }; +static struct sa1100fb_rgb rgb_8 = { + .red = { .offset = 0, .length = 8, }, + .green = { .offset = 0, .length = 8, }, + .blue = { .offset = 0, .length = 8, }, + .transp = { .offset = 0, .length = 0, }, +}; + static struct sa1100fb_rgb def_rgb_16 = { .red = { .offset = 11, .length = 5, }, .green = { .offset = 5, .length = 6, }, @@ -613,7 +617,7 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel); switch (var->bits_per_pixel) { case 4: - rgbidx = RGB_8; + rgbidx = RGB_4; break; case 8: rgbidx = RGB_8; @@ -1382,6 +1386,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev) fbi->fb.monspecs = monspecs; fbi->fb.pseudo_palette = (fbi + 1); + fbi->rgb[RGB_4] = &rgb_4; fbi->rgb[RGB_8] = &rgb_8; fbi->rgb[RGB_16] = &def_rgb_16; diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h index 86831db9a04..1c3b459865d 100644 --- a/drivers/video/sa1100fb.h +++ b/drivers/video/sa1100fb.h @@ -57,9 +57,10 @@ struct sa1100fb_lcd_reg { unsigned long lccr3; }; -#define RGB_8 (0) -#define RGB_16 (1) -#define NR_RGB 2 +#define RGB_4 (0) +#define RGB_8 (1) +#define RGB_16 (2) +#define NR_RGB 3 struct sa1100fb_info { struct fb_info fb; diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 346d6458cf7..7e17ee95a97 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -1129,7 +1129,7 @@ sisfb_bpp_to_var(struct sis_video_info *ivideo, struct fb_var_screeninfo *var) switch(var->bits_per_pixel) { case 8: var->red.offset = var->green.offset = var->blue.offset = 0; - var->red.length = var->green.length = var->blue.length = 6; + var->red.length = var->green.length = var->blue.length = 8; break; case 16: var->red.offset = 11; diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index a439159204a..89158bc71da 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -308,9 +308,11 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green, * color depth = SUM(var->{color}.length) * * Pseudocolor: - * var->{color}.offset is 0 - * var->{color}.length contains width of DAC or the number of unique - * colors available (color depth) + * var->{color}.offset is 0 unless the palette index takes less than + * bits_per_pixel bits and is stored in the upper + * bits of the pixel value + * var->{color}.length is set so that 1 << length is the number of + * available palette entries * pseudo_palette is not used * RAMDAC[X] is programmed to (red, green, blue) * color depth = var->{color}.length diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 0b370aebdbf..421770b5e6a 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c @@ -55,6 +55,7 @@ static u16 maxvf __devinitdata; /* maximum vertical frequency */ static u16 maxhf __devinitdata; /* maximum horizontal frequency */ static u16 vbemode __devinitdata; /* force use of a specific VBE mode */ static char *mode_option __devinitdata; +static u8 dac_width = 6; static struct uvesafb_ktask *uvfb_tasks[UVESAFB_TASKS_MAX]; static DEFINE_MUTEX(uvfb_lock); @@ -303,22 +304,10 @@ static void uvesafb_setup_var(struct fb_var_screeninfo *var, var->blue.offset = 0; var->transp.offset = 0; - /* - * We're assuming that we can switch the DAC to 8 bits. If - * this proves to be incorrect, we'll update the fields - * later in set_par(). - */ - if (par->vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC) { - var->red.length = 8; - var->green.length = 8; - var->blue.length = 8; - var->transp.length = 0; - } else { - var->red.length = 6; - var->green.length = 6; - var->blue.length = 6; - var->transp.length = 0; - } + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.length = 0; } } @@ -1006,7 +995,7 @@ static int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green, struct fb_info *info) { struct uvesafb_pal_entry entry; - int shift = 16 - info->var.green.length; + int shift = 16 - dac_width; int err = 0; if (regno >= info->cmap.len) @@ -1055,7 +1044,7 @@ static int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green, static int uvesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info) { struct uvesafb_pal_entry *entries; - int shift = 16 - info->var.green.length; + int shift = 16 - dac_width; int i, err = 0; if (info->var.bits_per_pixel == 8) { @@ -1317,13 +1306,9 @@ setmode: err = uvesafb_exec(task); if (err || (task->t.regs.eax & 0xffff) != 0x004f || ((task->t.regs.ebx & 0xff00) >> 8) != 8) { - /* - * We've failed to set the DAC palette format - - * time to correct var. - */ - info->var.red.length = 6; - info->var.green.length = 6; - info->var.blue.length = 6; + dac_width = 6; + } else { + dac_width = 8; } } diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index cc919ae4657..050d432c7d9 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -318,13 +318,16 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, * {hardwarespecific} contains width of RAMDAC * cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset) * RAMDAC[X] is programmed to (red, green, blue) - * + * * Pseudocolor: - * uses offset = 0 && length = RAMDAC register width. - * var->{color}.offset is 0 - * var->{color}.length contains widht of DAC + * var->{color}.offset is 0 unless the palette index takes less than + * bits_per_pixel bits and is stored in the upper + * bits of the pixel value + * var->{color}.length is set so that 1 << length is the number of available + * palette entries * cmap is not used * RAMDAC[X] is programmed to (red, green, blue) + * * Truecolor: * does not use DAC. Usually 3 are present. * var->{color}.offset contains start of bitfield diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 63024145215..5eb8f21da82 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -240,8 +240,6 @@ config ORION5X_WATCHDOG To compile this driver as a module, choose M here: the module will be called orion5x_wdt. -# ARM26 Architecture - # AVR32 Architecture config AT32AP700X_WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 806b3eb0853..7f8c56b14f5 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -42,8 +42,6 @@ obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o obj-$(CONFIG_ORION5X_WATCHDOG) += orion5x_wdt.o -# ARM26 Architecture - # AVR32 Architecture obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index e35d5458923..29e52c237a3 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c @@ -197,7 +197,7 @@ static struct miscdevice at91wdt_miscdev = { .fops = &at91wdt_fops, }; -static int __init at91wdt_probe(struct platform_device *pdev) +static int __devinit at91wdt_probe(struct platform_device *pdev) { int res; @@ -214,7 +214,7 @@ static int __init at91wdt_probe(struct platform_device *pdev) return 0; } -static int __exit at91wdt_remove(struct platform_device *pdev) +static int __devexit at91wdt_remove(struct platform_device *pdev) { int res; @@ -252,7 +252,7 @@ static int at91wdt_resume(struct platform_device *pdev) static struct platform_driver at91wdt_driver = { .probe = at91wdt_probe, - .remove = __exit_p(at91wdt_remove), + .remove = __devexit_p(at91wdt_remove), .shutdown = at91wdt_shutdown, .suspend = at91wdt_suspend, .resume = at91wdt_resume, diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index 2dbe83570d6..7ba0b11ec52 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c @@ -52,10 +52,10 @@ #define ESB_LOCK_REG 0x68 /* WDT lock register */ /* Memory mapped registers */ -#define ESB_TIMER1_REG BASEADDR + 0x00 /* Timer1 value after each reset */ -#define ESB_TIMER2_REG BASEADDR + 0x04 /* Timer2 value after each reset */ -#define ESB_GINTSR_REG BASEADDR + 0x08 /* General Interrupt Status Register */ -#define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */ +#define ESB_TIMER1_REG (BASEADDR + 0x00)/* Timer1 value after each reset */ +#define ESB_TIMER2_REG (BASEADDR + 0x04)/* Timer2 value after each reset */ +#define ESB_GINTSR_REG (BASEADDR + 0x08)/* General Interrupt Status Register */ +#define ESB_RELOAD_REG (BASEADDR + 0x0c)/* Reload register */ /* Lock register bits */ #define ESB_WDT_FUNC (0x01 << 2) /* Watchdog functionality */ @@ -68,6 +68,7 @@ #define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */ /* Reload register bits */ +#define ESB_WDT_TIMEOUT (0x01 << 9) /* Watchdog timed out */ #define ESB_WDT_RELOAD (0x01 << 8) /* prevent timeout */ /* Magic constants */ @@ -87,7 +88,6 @@ static struct platform_device *esb_platform_device; /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ #define WATCHDOG_HEARTBEAT 30 static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ - module_param(heartbeat, int, 0); MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" @@ -123,7 +123,7 @@ static int esb_timer_start(void) esb_unlock_registers(); writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); /* Enable or Enable + Lock? */ - val = 0x02 | (nowayout ? 0x01 : 0x00); + val = ESB_WDT_ENABLE | (nowayout ? ESB_WDT_LOCK : 0x00); pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); spin_unlock(&esb_lock); return 0; @@ -143,7 +143,7 @@ static int esb_timer_stop(void) spin_unlock(&esb_lock); /* Returns 0 if the timer was disabled, non-zero otherwise */ - return (val & 0x01); + return val & ESB_WDT_ENABLE; } static void esb_timer_keepalive(void) @@ -190,18 +190,6 @@ static int esb_timer_set_heartbeat(int time) return 0; } -static int esb_timer_read(void) -{ - u32 count; - - /* This isn't documented, and doesn't take into - * acount which stage is running, but it looks - * like a 20 bit count down, so we might as well report it. - */ - pci_read_config_dword(esb_pci, 0x64, &count); - return (int)count; -} - /* * /dev/watchdog handling */ @@ -282,7 +270,7 @@ static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: - return put_user(esb_timer_read(), p); + return put_user(0, p); case WDIOC_GETBOOTSTATUS: return put_user(triggered, p); @@ -362,8 +350,6 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl); static unsigned char __devinit esb_getdevice(void) { - u8 val1; - unsigned short val2; /* * Find the PCI device */ @@ -371,66 +357,79 @@ static unsigned char __devinit esb_getdevice(void) esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9, NULL); - if (esb_pci) { - if (pci_enable_device(esb_pci)) { - printk(KERN_ERR PFX "failed to enable device\n"); - goto err_devput; - } + if (!esb_pci) + return 0; - if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { - printk(KERN_ERR PFX "failed to request region\n"); - goto err_disable; - } + if (pci_enable_device(esb_pci)) { + printk(KERN_ERR PFX "failed to enable device\n"); + goto err_devput; + } - BASEADDR = pci_ioremap_bar(esb_pci, 0); - if (BASEADDR == NULL) { - /* Something's wrong here, BASEADDR has to be set */ - printk(KERN_ERR PFX "failed to get BASEADDR\n"); - goto err_release; - } + if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { + printk(KERN_ERR PFX "failed to request region\n"); + goto err_disable; + } - /* - * The watchdog has two timers, it can be setup so that the - * expiry of timer1 results in an interrupt and the expiry of - * timer2 results in a reboot. We set it to not generate - * any interrupts as there is not much we can do with it - * right now. - * - * We also enable reboots and set the timer frequency to - * the PCI clock divided by 2^15 (approx 1KHz). - */ - pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003); - - /* Check that the WDT isn't already locked */ - pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1); - if (val1 & ESB_WDT_LOCK) - printk(KERN_WARNING PFX "nowayout already set\n"); - - /* Set the timer to watchdog mode and disable it for now */ - pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00); - - /* Check if the watchdog was previously triggered */ - esb_unlock_registers(); - val2 = readw(ESB_RELOAD_REG); - triggered = (val2 & (0x01 << 9) >> 9); - - /* Reset trigger flag and timers */ - esb_unlock_registers(); - writew((0x11 << 8), ESB_RELOAD_REG); - - /* Done */ - return 1; + BASEADDR = pci_ioremap_bar(esb_pci, 0); + if (BASEADDR == NULL) { + /* Something's wrong here, BASEADDR has to be set */ + printk(KERN_ERR PFX "failed to get BASEADDR\n"); + goto err_release; + } + + /* Done */ + return 1; err_release: - pci_release_region(esb_pci, 0); + pci_release_region(esb_pci, 0); err_disable: - pci_disable_device(esb_pci); + pci_disable_device(esb_pci); err_devput: - pci_dev_put(esb_pci); - } + pci_dev_put(esb_pci); return 0; } +static void __devinit esb_initdevice(void) +{ + u8 val1; + u16 val2; + + /* + * Config register: + * Bit 5 : 0 = Enable WDT_OUTPUT + * Bit 2 : 0 = set the timer frequency to the PCI clock + * divided by 2^15 (approx 1KHz). + * Bits 1:0 : 11 = WDT_INT_TYPE Disabled. + * The watchdog has two timers, it can be setup so that the + * expiry of timer1 results in an interrupt and the expiry of + * timer2 results in a reboot. We set it to not generate + * any interrupts as there is not much we can do with it + * right now. + */ + pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003); + + /* Check that the WDT isn't already locked */ + pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1); + if (val1 & ESB_WDT_LOCK) + printk(KERN_WARNING PFX "nowayout already set\n"); + + /* Set the timer to watchdog mode and disable it for now */ + pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00); + + /* Check if the watchdog was previously triggered */ + esb_unlock_registers(); + val2 = readw(ESB_RELOAD_REG); + if (val2 & ESB_WDT_TIMEOUT) + triggered = WDIOF_CARDRESET; + + /* Reset WDT_TIMEOUT flag and timers */ + esb_unlock_registers(); + writew((ESB_WDT_TIMEOUT | ESB_WDT_RELOAD), ESB_RELOAD_REG); + + /* And set the correct timeout value */ + esb_timer_set_heartbeat(heartbeat); +} + static int __devinit esb_probe(struct platform_device *dev) { int ret; @@ -441,13 +440,17 @@ static int __devinit esb_probe(struct platform_device *dev) /* Check that the heartbeat value is within it's range; if not reset to the default */ - if (esb_timer_set_heartbeat(heartbeat)) { - esb_timer_set_heartbeat(WATCHDOG_HEARTBEAT); + if (heartbeat < 0x1 || heartbeat > 2 * 0x03ff) { + heartbeat = WATCHDOG_HEARTBEAT; printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n", heartbeat); } + /* Initialize the watchdog and make sure it does not run */ + esb_initdevice(); + + /* Register the watchdog so that userspace has access to it */ ret = misc_register(&esb_miscdev); if (ret != 0) { printk(KERN_ERR PFX @@ -455,7 +458,6 @@ static int __devinit esb_probe(struct platform_device *dev) WATCHDOG_MINOR, ret); goto err_unmap; } - esb_timer_stop(); printk(KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", BASEADDR, heartbeat, nowayout); @@ -463,11 +465,8 @@ static int __devinit esb_probe(struct platform_device *dev) err_unmap: iounmap(BASEADDR); -/* err_release: */ pci_release_region(esb_pci, 0); -/* err_disable: */ pci_disable_device(esb_pci); -/* err_devput: */ pci_dev_put(esb_pci); return ret; } diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c index 74c92d38411..ae3832110ac 100644 --- a/drivers/watchdog/ks8695_wdt.c +++ b/drivers/watchdog/ks8695_wdt.c @@ -221,7 +221,7 @@ static struct miscdevice ks8695wdt_miscdev = { .fops = &ks8695wdt_fops, }; -static int __init ks8695wdt_probe(struct platform_device *pdev) +static int __devinit ks8695wdt_probe(struct platform_device *pdev) { int res; @@ -238,7 +238,7 @@ static int __init ks8695wdt_probe(struct platform_device *pdev) return 0; } -static int __exit ks8695wdt_remove(struct platform_device *pdev) +static int __devexit ks8695wdt_remove(struct platform_device *pdev) { int res; @@ -276,7 +276,7 @@ static int ks8695wdt_resume(struct platform_device *pdev) static struct platform_driver ks8695wdt_driver = { .probe = ks8695wdt_probe, - .remove = __exit_p(ks8695wdt_remove), + .remove = __devexit_p(ks8695wdt_remove), .shutdown = ks8695wdt_shutdown, .suspend = ks8695wdt_suspend, .resume = ks8695wdt_resume, diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index aa5ad6e33f0..f2713851aaa 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -258,7 +258,7 @@ static const struct file_operations omap_wdt_fops = { .release = omap_wdt_release, }; -static int __init omap_wdt_probe(struct platform_device *pdev) +static int __devinit omap_wdt_probe(struct platform_device *pdev) { struct resource *res, *mem; struct omap_wdt_dev *wdev; @@ -367,7 +367,7 @@ static void omap_wdt_shutdown(struct platform_device *pdev) omap_wdt_disable(wdev); } -static int omap_wdt_remove(struct platform_device *pdev) +static int __devexit omap_wdt_remove(struct platform_device *pdev) { struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -426,7 +426,7 @@ static int omap_wdt_resume(struct platform_device *pdev) static struct platform_driver omap_wdt_driver = { .probe = omap_wdt_probe, - .remove = omap_wdt_remove, + .remove = __devexit_p(omap_wdt_remove), .shutdown = omap_wdt_shutdown, .suspend = omap_wdt_suspend, .resume = omap_wdt_resume, diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c index e81441f103d..7529616739d 100644 --- a/drivers/watchdog/orion5x_wdt.c +++ b/drivers/watchdog/orion5x_wdt.c @@ -42,7 +42,17 @@ static unsigned int wdt_tclk; static unsigned long wdt_status; static spinlock_t wdt_lock; -static void wdt_enable(void) +static void orion5x_wdt_ping(void) +{ + spin_lock(&wdt_lock); + + /* Reload watchdog duration */ + writel(wdt_tclk * heartbeat, WDT_VAL); + + spin_unlock(&wdt_lock); +} + +static void orion5x_wdt_enable(void) { u32 reg; @@ -69,7 +79,7 @@ static void wdt_enable(void) spin_unlock(&wdt_lock); } -static void wdt_disable(void) +static void orion5x_wdt_disable(void) { u32 reg; @@ -101,7 +111,7 @@ static int orion5x_wdt_open(struct inode *inode, struct file *file) if (test_and_set_bit(WDT_IN_USE, &wdt_status)) return -EBUSY; clear_bit(WDT_OK_TO_CLOSE, &wdt_status); - wdt_enable(); + orion5x_wdt_enable(); return nonseekable_open(inode, file); } @@ -122,18 +132,28 @@ static ssize_t orion5x_wdt_write(struct file *file, const char *data, set_bit(WDT_OK_TO_CLOSE, &wdt_status); } } - wdt_enable(); + orion5x_wdt_ping(); } return len; } -static struct watchdog_info ident = { +static int orion5x_wdt_settimeout(int new_time) +{ + if ((new_time <= 0) || (new_time > wdt_max_duration)) + return -EINVAL; + + /* Set new watchdog time to be used when + * orion5x_wdt_enable() or orion5x_wdt_ping() is called. */ + heartbeat = new_time; + return 0; +} + +static const struct watchdog_info ident = { .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, .identity = "Orion5x Watchdog", }; - static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -152,7 +172,7 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, break; case WDIOC_KEEPALIVE: - wdt_enable(); + orion5x_wdt_ping(); ret = 0; break; @@ -161,12 +181,11 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, if (ret) break; - if (time <= 0 || time > wdt_max_duration) { + if (orion5x_wdt_settimeout(time)) { ret = -EINVAL; break; } - heartbeat = time; - wdt_enable(); + orion5x_wdt_ping(); /* Fall through */ case WDIOC_GETTIMEOUT: @@ -187,7 +206,7 @@ static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, static int orion5x_wdt_release(struct inode *inode, struct file *file) { if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) - wdt_disable(); + orion5x_wdt_disable(); else printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " "timer will not stop\n"); @@ -230,7 +249,7 @@ static int __devinit orion5x_wdt_probe(struct platform_device *pdev) orion5x_wdt_miscdev.parent = &pdev->dev; wdt_max_duration = WDT_MAX_CYCLE_COUNT / wdt_tclk; - if (heartbeat <= 0 || heartbeat > wdt_max_duration) + if (orion5x_wdt_settimeout(heartbeat)) heartbeat = wdt_max_duration; ret = misc_register(&orion5x_wdt_miscdev); @@ -247,7 +266,7 @@ static int __devexit orion5x_wdt_remove(struct platform_device *pdev) int ret; if (test_bit(WDT_IN_USE, &wdt_status)) { - wdt_disable(); + orion5x_wdt_disable(); clear_bit(WDT_IN_USE, &wdt_status); } @@ -258,9 +277,16 @@ static int __devexit orion5x_wdt_remove(struct platform_device *pdev) return ret; } +static void orion5x_wdt_shutdown(struct platform_device *pdev) +{ + if (test_bit(WDT_IN_USE, &wdt_status)) + orion5x_wdt_disable(); +} + static struct platform_driver orion5x_wdt_driver = { .probe = orion5x_wdt_probe, .remove = __devexit_p(orion5x_wdt_remove), + .shutdown = orion5x_wdt_shutdown, .driver = { .owner = THIS_MODULE, .name = "orion5x_wdt", @@ -285,10 +311,11 @@ MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>"); MODULE_DESCRIPTION("Orion5x Processor Watchdog"); module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds"); +MODULE_PARM_DESC(heartbeat, "Initial watchdog heartbeat in seconds"); module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c index 5f54c01c156..bdfd584ad85 100644 --- a/drivers/xen/cpu_hotplug.c +++ b/drivers/xen/cpu_hotplug.c @@ -21,29 +21,41 @@ static void disable_hotplug_cpu(int cpu) set_cpu_present(cpu, false); } -static void vcpu_hotplug(unsigned int cpu) +static int vcpu_online(unsigned int cpu) { int err; char dir[32], state[32]; - if (!cpu_possible(cpu)) - return; - sprintf(dir, "cpu/%u", cpu); err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state); if (err != 1) { printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); - return; + return err; } - if (strcmp(state, "online") == 0) { + if (strcmp(state, "online") == 0) + return 1; + else if (strcmp(state, "offline") == 0) + return 0; + + printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n", state, cpu); + return -EINVAL; +} +static void vcpu_hotplug(unsigned int cpu) +{ + if (!cpu_possible(cpu)) + return; + + switch (vcpu_online(cpu)) { + case 1: enable_hotplug_cpu(cpu); - } else if (strcmp(state, "offline") == 0) { + break; + case 0: (void)cpu_down(cpu); disable_hotplug_cpu(cpu); - } else { - printk(KERN_ERR "XENBUS: unknown state(%s) on CPU%d\n", - state, cpu); + break; + default: + break; } } @@ -64,12 +76,20 @@ static void handle_vcpu_hotplug_event(struct xenbus_watch *watch, static int setup_cpu_watcher(struct notifier_block *notifier, unsigned long event, void *data) { + int cpu; static struct xenbus_watch cpu_watch = { .node = "cpu", .callback = handle_vcpu_hotplug_event}; (void)register_xenbus_watch(&cpu_watch); + for_each_possible_cpu(cpu) { + if (vcpu_online(cpu) == 0) { + (void)cpu_down(cpu); + cpu_clear(cpu, cpu_present_map); + } + } + return NOTIFY_DONE; } diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 0d61db1e7b4..4b5b84837ee 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -62,14 +62,15 @@ static int xen_suspend(void *data) gnttab_resume(); xen_mm_unpin_all(); - sysdev_resume(); - if (!*cancelled) { xen_irq_resume(); xen_console_resume(); xen_timer_resume(); } + sysdev_resume(); + device_power_up(PMSG_RESUME); + return 0; } diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index b43b9556366..acf67883110 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -590,9 +590,8 @@ static int ext2_get_blocks(struct inode *inode, if (depth == 0) return (err); -reread: - partial = ext2_get_branch(inode, depth, offsets, chain, &err); + partial = ext2_get_branch(inode, depth, offsets, chain, &err); /* Simplest case - block found, no allocation needed */ if (!partial) { first_block = le32_to_cpu(chain[depth - 1].key); @@ -602,15 +601,16 @@ reread: while (count < maxblocks && count <= blocks_to_boundary) { ext2_fsblk_t blk; - if (!verify_chain(chain, partial)) { + if (!verify_chain(chain, chain + depth - 1)) { /* * Indirect block might be removed by * truncate while we were reading it. * Handling of that case: forget what we've * got now, go to reread. */ + err = -EAGAIN; count = 0; - goto changed; + break; } blk = le32_to_cpu(*(chain[depth-1].p + count)); if (blk == first_block + count) @@ -618,7 +618,8 @@ reread: else break; } - goto got_it; + if (err != -EAGAIN) + goto got_it; } /* Next simple case - plain lookup or failed read of indirect block */ @@ -626,6 +627,33 @@ reread: goto cleanup; mutex_lock(&ei->truncate_mutex); + /* + * If the indirect block is missing while we are reading + * the chain(ext3_get_branch() returns -EAGAIN err), or + * if the chain has been changed after we grab the semaphore, + * (either because another process truncated this branch, or + * another get_block allocated this branch) re-grab the chain to see if + * the request block has been allocated or not. + * + * Since we already block the truncate/other get_block + * at this point, we will have the current copy of the chain when we + * splice the branch into the tree. + */ + if (err == -EAGAIN || !verify_chain(chain, partial)) { + while (partial > chain) { + brelse(partial->bh); + partial--; + } + partial = ext2_get_branch(inode, depth, offsets, chain, &err); + if (!partial) { + count++; + mutex_unlock(&ei->truncate_mutex); + if (err) + goto cleanup; + clear_buffer_new(bh_result); + goto got_it; + } + } /* * Okay, we need to do block allocation. Lazily initialize the block @@ -683,12 +711,6 @@ cleanup: partial--; } return err; -changed: - while (partial > chain) { - brelse(partial->bh); - partial--; - } - goto reread; } int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 9435dda8f1e..a1cbff2b4d9 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -70,6 +70,10 @@ static int hfs_releasepage(struct page *page, gfp_t mask) BUG(); return 0; } + + if (!tree) + return 0; + if (tree->node_size >= PAGE_CACHE_SIZE) { nidx = page->index >> (tree->node_size_shift - PAGE_CACHE_SHIFT); spin_lock(&tree->hash_lock); diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c index 36ca2e1a4fa..7b6165f25fb 100644 --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c @@ -349,6 +349,7 @@ void hfs_mdb_put(struct super_block *sb) if (HFS_SB(sb)->nls_disk) unload_nls(HFS_SB(sb)->nls_disk); + free_pages((unsigned long)HFS_SB(sb)->bitmap, PAGE_SIZE < 8192 ? 1 : 0); kfree(HFS_SB(sb)); sb->s_fs_info = NULL; } diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c index c7bd649bbbd..3e9afc2a91d 100644 --- a/fs/jbd/revoke.c +++ b/fs/jbd/revoke.c @@ -55,6 +55,25 @@ * need do nothing. * RevokeValid set, Revoked set: * buffer has been revoked. + * + * Locking rules: + * We keep two hash tables of revoke records. One hashtable belongs to the + * running transaction (is pointed to by journal->j_revoke), the other one + * belongs to the committing transaction. Accesses to the second hash table + * happen only from the kjournald and no other thread touches this table. Also + * journal_switch_revoke_table() which switches which hashtable belongs to the + * running and which to the committing transaction is called only from + * kjournald. Therefore we need no locks when accessing the hashtable belonging + * to the committing transaction. + * + * All users operating on the hash table belonging to the running transaction + * have a handle to the transaction. Therefore they are safe from kjournald + * switching hash tables under them. For operations on the lists of entries in + * the hash table j_revoke_lock is used. + * + * Finally, also replay code uses the hash tables but at this moment noone else + * can touch them (filesystem isn't mounted yet) and hence no locking is + * needed. */ #ifndef __KERNEL__ @@ -402,8 +421,6 @@ int journal_revoke(handle_t *handle, unsigned long blocknr, * the second time we would still have a pending revoke to cancel. So, * do not trust the Revoked bit on buffers unless RevokeValid is also * set. - * - * The caller must have the journal locked. */ int journal_cancel_revoke(handle_t *handle, struct journal_head *jh) { @@ -481,10 +498,7 @@ void journal_switch_revoke_table(journal_t *journal) /* * Write revoke records to the journal for all entries in the current * revoke hash, deleting the entries as we go. - * - * Called with the journal lock held. */ - void journal_write_revoke_records(journal_t *journal, transaction_t *transaction) { diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index c13f67300fe..7ec89fc05b2 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -153,23 +153,6 @@ xfs_find_bdev_for_inode( } /* - * Schedule IO completion handling on a xfsdatad if this was - * the final hold on this ioend. If we are asked to wait, - * flush the workqueue. - */ -STATIC void -xfs_finish_ioend( - xfs_ioend_t *ioend, - int wait) -{ - if (atomic_dec_and_test(&ioend->io_remaining)) { - queue_work(xfsdatad_workqueue, &ioend->io_work); - if (wait) - flush_workqueue(xfsdatad_workqueue); - } -} - -/* * We're now finished for good with this ioend structure. * Update the page state via the associated buffer_heads, * release holds on the inode and bio, and finally free @@ -310,6 +293,27 @@ xfs_end_bio_read( } /* + * Schedule IO completion handling on a xfsdatad if this was + * the final hold on this ioend. If we are asked to wait, + * flush the workqueue. + */ +STATIC void +xfs_finish_ioend( + xfs_ioend_t *ioend, + int wait) +{ + if (atomic_dec_and_test(&ioend->io_remaining)) { + struct workqueue_struct *wq = xfsdatad_workqueue; + if (ioend->io_work.func == xfs_end_bio_unwritten) + wq = xfsconvertd_workqueue; + + queue_work(wq, &ioend->io_work); + if (wait) + flush_workqueue(wq); + } +} + +/* * Allocate and initialise an IO completion structure. * We need to track unwritten extent write completion here initially. * We'll need to extend this for updating the ondisk inode size later diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 1dd52884975..221b3e66cee 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h @@ -19,6 +19,7 @@ #define __XFS_AOPS_H__ extern struct workqueue_struct *xfsdatad_workqueue; +extern struct workqueue_struct *xfsconvertd_workqueue; extern mempool_t *xfs_ioend_pool; /* diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index aa1016bb913..e28800a9f2b 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -51,6 +51,7 @@ static struct shrinker xfs_buf_shake = { static struct workqueue_struct *xfslogd_workqueue; struct workqueue_struct *xfsdatad_workqueue; +struct workqueue_struct *xfsconvertd_workqueue; #ifdef XFS_BUF_TRACE void @@ -1775,6 +1776,7 @@ xfs_flush_buftarg( xfs_buf_t *bp, *n; int pincount = 0; + xfs_buf_runall_queues(xfsconvertd_workqueue); xfs_buf_runall_queues(xfsdatad_workqueue); xfs_buf_runall_queues(xfslogd_workqueue); @@ -1831,9 +1833,15 @@ xfs_buf_init(void) if (!xfsdatad_workqueue) goto out_destroy_xfslogd_workqueue; + xfsconvertd_workqueue = create_workqueue("xfsconvertd"); + if (!xfsconvertd_workqueue) + goto out_destroy_xfsdatad_workqueue; + register_shrinker(&xfs_buf_shake); return 0; + out_destroy_xfsdatad_workqueue: + destroy_workqueue(xfsdatad_workqueue); out_destroy_xfslogd_workqueue: destroy_workqueue(xfslogd_workqueue); out_free_buf_zone: @@ -1849,6 +1857,7 @@ void xfs_buf_terminate(void) { unregister_shrinker(&xfs_buf_shake); + destroy_workqueue(xfsconvertd_workqueue); destroy_workqueue(xfsdatad_workqueue); destroy_workqueue(xfslogd_workqueue); kmem_zone_destroy(xfs_buf_zone); diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c index 5aeb7777696..08be36d7326 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/linux-2.6/xfs_fs_subr.c @@ -74,14 +74,14 @@ xfs_flush_pages( if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) { xfs_iflags_clear(ip, XFS_ITRUNCATED); - ret = filemap_fdatawrite(mapping); - if (flags & XFS_B_ASYNC) - return -ret; - ret2 = filemap_fdatawait(mapping); - if (!ret) - ret = ret2; + ret = -filemap_fdatawrite(mapping); } - return -ret; + if (flags & XFS_B_ASYNC) + return ret; + ret2 = xfs_wait_on_pages(ip, first, last); + if (!ret) + ret = ret2; + return ret; } int diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 7e90daa0d1d..9142192ccbe 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -751,10 +751,26 @@ start: goto relock; } } else { + int enospc = 0; + ssize_t ret2 = 0; + +write_retry: xfs_rw_enter_trace(XFS_WRITE_ENTER, xip, (void *)iovp, segs, *offset, ioflags); - ret = generic_file_buffered_write(iocb, iovp, segs, + ret2 = generic_file_buffered_write(iocb, iovp, segs, pos, offset, count, ret); + /* + * if we just got an ENOSPC, flush the inode now we + * aren't holding any page locks and retry *once* + */ + if (ret2 == -ENOSPC && !enospc) { + error = xfs_flush_pages(xip, 0, -1, 0, FI_NONE); + if (error) + goto out_unlock_internal; + enospc = 1; + goto write_retry; + } + ret = ret2; } current->backing_dev_info = NULL; diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index a608e72fa40..f7ba76633c2 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -62,12 +62,6 @@ xfs_sync_inodes_ag( uint32_t first_index = 0; int error = 0; int last_error = 0; - int fflag = XFS_B_ASYNC; - - if (flags & SYNC_DELWRI) - fflag = XFS_B_DELWRI; - if (flags & SYNC_WAIT) - fflag = 0; /* synchronous overrides all */ do { struct inode *inode; @@ -128,11 +122,23 @@ xfs_sync_inodes_ag( * If we have to flush data or wait for I/O completion * we need to hold the iolock. */ - if ((flags & SYNC_DELWRI) && VN_DIRTY(inode)) { - xfs_ilock(ip, XFS_IOLOCK_SHARED); - lock_flags |= XFS_IOLOCK_SHARED; - error = xfs_flush_pages(ip, 0, -1, fflag, FI_NONE); - if (flags & SYNC_IOWAIT) + if (flags & SYNC_DELWRI) { + if (VN_DIRTY(inode)) { + if (flags & SYNC_TRYLOCK) { + if (xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) + lock_flags |= XFS_IOLOCK_SHARED; + } else { + xfs_ilock(ip, XFS_IOLOCK_SHARED); + lock_flags |= XFS_IOLOCK_SHARED; + } + if (lock_flags & XFS_IOLOCK_SHARED) { + error = xfs_flush_pages(ip, 0, -1, + (flags & SYNC_WAIT) ? 0 + : XFS_B_ASYNC, + FI_NONE); + } + } + if (VN_CACHED(inode) && (flags & SYNC_IOWAIT)) xfs_ioend_wait(ip); } xfs_ilock(ip, XFS_ILOCK_SHARED); @@ -398,15 +404,17 @@ STATIC void xfs_syncd_queue_work( struct xfs_mount *mp, void *data, - void (*syncer)(struct xfs_mount *, void *)) + void (*syncer)(struct xfs_mount *, void *), + struct completion *completion) { - struct bhv_vfs_sync_work *work; + struct xfs_sync_work *work; - work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP); + work = kmem_alloc(sizeof(struct xfs_sync_work), KM_SLEEP); INIT_LIST_HEAD(&work->w_list); work->w_syncer = syncer; work->w_data = data; work->w_mount = mp; + work->w_completion = completion; spin_lock(&mp->m_sync_lock); list_add_tail(&work->w_list, &mp->m_sync_list); spin_unlock(&mp->m_sync_lock); @@ -420,49 +428,26 @@ xfs_syncd_queue_work( * heads, looking about for more room... */ STATIC void -xfs_flush_inode_work( - struct xfs_mount *mp, - void *arg) -{ - struct inode *inode = arg; - filemap_flush(inode->i_mapping); - iput(inode); -} - -void -xfs_flush_inode( - xfs_inode_t *ip) -{ - struct inode *inode = VFS_I(ip); - - igrab(inode); - xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work); - delay(msecs_to_jiffies(500)); -} - -/* - * This is the "bigger hammer" version of xfs_flush_inode_work... - * (IOW, "If at first you don't succeed, use a Bigger Hammer"). - */ -STATIC void -xfs_flush_device_work( +xfs_flush_inodes_work( struct xfs_mount *mp, void *arg) { struct inode *inode = arg; - sync_blockdev(mp->m_super->s_bdev); + xfs_sync_inodes(mp, SYNC_DELWRI | SYNC_TRYLOCK); + xfs_sync_inodes(mp, SYNC_DELWRI | SYNC_TRYLOCK | SYNC_IOWAIT); iput(inode); } void -xfs_flush_device( +xfs_flush_inodes( xfs_inode_t *ip) { struct inode *inode = VFS_I(ip); + DECLARE_COMPLETION_ONSTACK(completion); igrab(inode); - xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work); - delay(msecs_to_jiffies(500)); + xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work, &completion); + wait_for_completion(&completion); xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); } @@ -497,7 +482,7 @@ xfssyncd( { struct xfs_mount *mp = arg; long timeleft; - bhv_vfs_sync_work_t *work, *n; + xfs_sync_work_t *work, *n; LIST_HEAD (tmp); set_freezable(); @@ -532,6 +517,8 @@ xfssyncd( list_del(&work->w_list); if (work == &mp->m_sync_work) continue; + if (work->w_completion) + complete(work->w_completion); kmem_free(work); } } @@ -545,6 +532,7 @@ xfs_syncd_init( { mp->m_sync_work.w_syncer = xfs_sync_worker; mp->m_sync_work.w_mount = mp; + mp->m_sync_work.w_completion = NULL; mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd"); if (IS_ERR(mp->m_sync_task)) return -PTR_ERR(mp->m_sync_task); diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index 04f058c848a..308d5bf6dfb 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h @@ -21,18 +21,20 @@ struct xfs_mount; struct xfs_perag; -typedef struct bhv_vfs_sync_work { +typedef struct xfs_sync_work { struct list_head w_list; struct xfs_mount *w_mount; void *w_data; /* syncer routine argument */ void (*w_syncer)(struct xfs_mount *, void *); -} bhv_vfs_sync_work_t; + struct completion *w_completion; +} xfs_sync_work_t; #define SYNC_ATTR 0x0001 /* sync attributes */ #define SYNC_DELWRI 0x0002 /* look at delayed writes */ #define SYNC_WAIT 0x0004 /* wait for i/o to complete */ #define SYNC_BDFLUSH 0x0008 /* BDFLUSH is calling -- don't block */ #define SYNC_IOWAIT 0x0010 /* wait for all I/O to complete */ +#define SYNC_TRYLOCK 0x0020 /* only try to lock inodes */ int xfs_syncd_init(struct xfs_mount *mp); void xfs_syncd_stop(struct xfs_mount *mp); @@ -43,8 +45,7 @@ int xfs_sync_fsdata(struct xfs_mount *mp, int flags); int xfs_quiesce_data(struct xfs_mount *mp); void xfs_quiesce_attr(struct xfs_mount *mp); -void xfs_flush_inode(struct xfs_inode *ip); -void xfs_flush_device(struct xfs_inode *ip); +void xfs_flush_inodes(struct xfs_inode *ip); int xfs_reclaim_inode(struct xfs_inode *ip, int locked, int sync_mode); int xfs_reclaim_inodes(struct xfs_mount *mp, int noblock, int mode); diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 478e587087f..89b81eedce6 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -69,15 +69,6 @@ xfs_inode_alloc( ASSERT(!spin_is_locked(&ip->i_flags_lock)); ASSERT(completion_done(&ip->i_flush)); - /* - * initialise the VFS inode here to get failures - * out of the way early. - */ - if (!inode_init_always(mp->m_super, VFS_I(ip))) { - kmem_zone_free(xfs_inode_zone, ip); - return NULL; - } - /* initialise the xfs inode */ ip->i_ino = ino; ip->i_mount = mp; @@ -113,6 +104,20 @@ xfs_inode_alloc( #ifdef XFS_DIR2_TRACE ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS); #endif + /* + * Now initialise the VFS inode. We do this after the xfs_inode + * initialisation as internal failures will result in ->destroy_inode + * being called and that will pass down through the reclaim path and + * free the XFS inode. This path requires the XFS inode to already be + * initialised. Hence if this call fails, the xfs_inode has already + * been freed and we should not reference it at all in the error + * handling. + */ + if (!inode_init_always(mp->m_super, VFS_I(ip))) + return NULL; + + /* prevent anyone from using this yet */ + VFS_I(ip)->i_state = I_NEW|I_LOCK; return ip; } diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 08ce72316bf..5aaa2d7ec15 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -338,38 +338,6 @@ xfs_iomap_eof_align_last_fsb( } STATIC int -xfs_flush_space( - xfs_inode_t *ip, - int *fsynced, - int *ioflags) -{ - switch (*fsynced) { - case 0: - if (ip->i_delayed_blks) { - xfs_iunlock(ip, XFS_ILOCK_EXCL); - xfs_flush_inode(ip); - xfs_ilock(ip, XFS_ILOCK_EXCL); - *fsynced = 1; - } else { - *ioflags |= BMAPI_SYNC; - *fsynced = 2; - } - return 0; - case 1: - *fsynced = 2; - *ioflags |= BMAPI_SYNC; - return 0; - case 2: - xfs_iunlock(ip, XFS_ILOCK_EXCL); - xfs_flush_device(ip); - xfs_ilock(ip, XFS_ILOCK_EXCL); - *fsynced = 3; - return 0; - } - return 1; -} - -STATIC int xfs_cmn_err_fsblock_zero( xfs_inode_t *ip, xfs_bmbt_irec_t *imap) @@ -538,15 +506,9 @@ error_out: } /* - * If the caller is doing a write at the end of the file, - * then extend the allocation out to the file system's write - * iosize. We clean up any extra space left over when the - * file is closed in xfs_inactive(). - * - * For sync writes, we are flushing delayed allocate space to - * try to make additional space available for allocation near - * the filesystem full boundary - preallocation hurts in that - * situation, of course. + * If the caller is doing a write at the end of the file, then extend the + * allocation out to the file system's write iosize. We clean up any extra + * space left over when the file is closed in xfs_inactive(). */ STATIC int xfs_iomap_eof_want_preallocate( @@ -565,7 +527,7 @@ xfs_iomap_eof_want_preallocate( int n, error, imaps; *prealloc = 0; - if ((ioflag & BMAPI_SYNC) || (offset + count) <= ip->i_size) + if ((offset + count) <= ip->i_size) return 0; /* @@ -611,7 +573,7 @@ xfs_iomap_write_delay( xfs_extlen_t extsz; int nimaps; xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS]; - int prealloc, fsynced = 0; + int prealloc, flushed = 0; int error; ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); @@ -627,12 +589,12 @@ xfs_iomap_write_delay( extsz = xfs_get_extsz_hint(ip); offset_fsb = XFS_B_TO_FSBT(mp, offset); -retry: error = xfs_iomap_eof_want_preallocate(mp, ip, offset, count, ioflag, imap, XFS_WRITE_IMAPS, &prealloc); if (error) return error; +retry: if (prealloc) { aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); ioalign = XFS_B_TO_FSBT(mp, aligned_offset); @@ -659,15 +621,22 @@ retry: /* * If bmapi returned us nothing, and if we didn't get back EDQUOT, - * then we must have run out of space - flush delalloc, and retry.. + * then we must have run out of space - flush all other inodes with + * delalloc blocks and retry without EOF preallocation. */ if (nimaps == 0) { xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE, ip, offset, count); - if (xfs_flush_space(ip, &fsynced, &ioflag)) + if (flushed) return XFS_ERROR(ENOSPC); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + xfs_flush_inodes(ip); + xfs_ilock(ip, XFS_ILOCK_EXCL); + + flushed = 1; error = 0; + prealloc = 0; goto retry; } diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index a1cc1322fc0..fdcf7b82747 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h @@ -40,8 +40,7 @@ typedef enum { BMAPI_IGNSTATE = (1 << 4), /* ignore unwritten state on read */ BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */ BMAPI_MMAP = (1 << 6), /* allocate for mmap write */ - BMAPI_SYNC = (1 << 7), /* sync write to flush delalloc space */ - BMAPI_TRYLOCK = (1 << 8), /* non-blocking request */ + BMAPI_TRYLOCK = (1 << 7), /* non-blocking request */ } bmapi_flags_t; diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index f76c6d7cea2..3750f04ede0 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -562,9 +562,8 @@ xfs_log_mount( } mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks); - if (!mp->m_log) { - cmn_err(CE_WARN, "XFS: Log allocation failed: No memory!"); - error = ENOMEM; + if (IS_ERR(mp->m_log)) { + error = -PTR_ERR(mp->m_log); goto out; } @@ -1180,10 +1179,13 @@ xlog_alloc_log(xfs_mount_t *mp, xfs_buf_t *bp; int i; int iclogsize; + int error = ENOMEM; log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); - if (!log) - return NULL; + if (!log) { + xlog_warn("XFS: Log allocation failed: No memory!"); + goto out; + } log->l_mp = mp; log->l_targ = log_target; @@ -1201,19 +1203,35 @@ xlog_alloc_log(xfs_mount_t *mp, log->l_grant_reserve_cycle = 1; log->l_grant_write_cycle = 1; + error = EFSCORRUPTED; if (xfs_sb_version_hassector(&mp->m_sb)) { log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; - ASSERT(log->l_sectbb_log <= mp->m_sectbb_log); + if (log->l_sectbb_log < 0 || + log->l_sectbb_log > mp->m_sectbb_log) { + xlog_warn("XFS: Log sector size (0x%x) out of range.", + log->l_sectbb_log); + goto out_free_log; + } + /* for larger sector sizes, must have v2 or external log */ - ASSERT(log->l_sectbb_log == 0 || - log->l_logBBstart == 0 || - xfs_sb_version_haslogv2(&mp->m_sb)); - ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT); + if (log->l_sectbb_log != 0 && + (log->l_logBBstart != 0 && + !xfs_sb_version_haslogv2(&mp->m_sb))) { + xlog_warn("XFS: log sector size (0x%x) invalid " + "for configuration.", log->l_sectbb_log); + goto out_free_log; + } + if (mp->m_sb.sb_logsectlog < BBSHIFT) { + xlog_warn("XFS: Log sector log (0x%x) too small.", + mp->m_sb.sb_logsectlog); + goto out_free_log; + } } log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1; xlog_get_iclog_buffer_size(mp, log); + error = ENOMEM; bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp); if (!bp) goto out_free_log; @@ -1313,7 +1331,8 @@ out_free_iclog: xfs_buf_free(log->l_xbuf); out_free_log: kmem_free(log); - return NULL; +out: + return ERR_PTR(-error); } /* xlog_alloc_log */ @@ -2541,18 +2560,19 @@ redo: xlog_ins_ticketq(&log->l_reserve_headq, tic); xlog_trace_loggrant(log, tic, "xlog_grant_log_space: sleep 2"); + spin_unlock(&log->l_grant_lock); + xlog_grant_push_ail(log->l_mp, need_bytes); + spin_lock(&log->l_grant_lock); + XFS_STATS_INC(xs_sleep_logspace); sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); - if (XLOG_FORCED_SHUTDOWN(log)) { - spin_lock(&log->l_grant_lock); + spin_lock(&log->l_grant_lock); + if (XLOG_FORCED_SHUTDOWN(log)) goto error_return; - } xlog_trace_loggrant(log, tic, "xlog_grant_log_space: wake 2"); - xlog_grant_push_ail(log->l_mp, need_bytes); - spin_lock(&log->l_grant_lock); goto redo; } else if (tic->t_flags & XLOG_TIC_IN_Q) xlog_del_ticketq(&log->l_reserve_headq, tic); @@ -2631,7 +2651,7 @@ xlog_regrant_write_log_space(xlog_t *log, * for more free space, otherwise try to get some space for * this transaction. */ - + need_bytes = tic->t_unit_res; if ((ntic = log->l_write_headq)) { free_bytes = xlog_space_left(log, log->l_grant_write_cycle, log->l_grant_write_bytes); @@ -2651,26 +2671,25 @@ xlog_regrant_write_log_space(xlog_t *log, xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: sleep 1"); + spin_unlock(&log->l_grant_lock); + xlog_grant_push_ail(log->l_mp, need_bytes); + spin_lock(&log->l_grant_lock); + XFS_STATS_INC(xs_sleep_logspace); sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); /* If we're shutting down, this tic is already * off the queue */ - if (XLOG_FORCED_SHUTDOWN(log)) { - spin_lock(&log->l_grant_lock); + spin_lock(&log->l_grant_lock); + if (XLOG_FORCED_SHUTDOWN(log)) goto error_return; - } xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: wake 1"); - xlog_grant_push_ail(log->l_mp, tic->t_unit_res); - spin_lock(&log->l_grant_lock); } } - need_bytes = tic->t_unit_res; - redo: if (XLOG_FORCED_SHUTDOWN(log)) goto error_return; @@ -2680,19 +2699,20 @@ redo: if (free_bytes < need_bytes) { if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) xlog_ins_ticketq(&log->l_write_headq, tic); + spin_unlock(&log->l_grant_lock); + xlog_grant_push_ail(log->l_mp, need_bytes); + spin_lock(&log->l_grant_lock); + XFS_STATS_INC(xs_sleep_logspace); sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); /* If we're shutting down, this tic is already off the queue */ - if (XLOG_FORCED_SHUTDOWN(log)) { - spin_lock(&log->l_grant_lock); + spin_lock(&log->l_grant_lock); + if (XLOG_FORCED_SHUTDOWN(log)) goto error_return; - } xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: wake 2"); - xlog_grant_push_ail(log->l_mp, need_bytes); - spin_lock(&log->l_grant_lock); goto redo; } else if (tic->t_flags & XLOG_TIC_IN_Q) xlog_del_ticketq(&log->l_write_headq, tic); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 7af44adffc8..d6a64392f98 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -313,7 +313,7 @@ typedef struct xfs_mount { #endif struct xfs_mru_cache *m_filestream; /* per-mount filestream data */ struct task_struct *m_sync_task; /* generalised sync thread */ - bhv_vfs_sync_work_t m_sync_work; /* work item for VFS_SYNC */ + xfs_sync_work_t m_sync_work; /* work item for VFS_SYNC */ struct list_head m_sync_list; /* sync thread work item list */ spinlock_t m_sync_lock; /* work item list lock */ int m_sync_seq; /* sync thread generation no. */ diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 7394c7af5de..19cf90a9c76 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -1457,6 +1457,13 @@ xfs_create( error = xfs_trans_reserve(tp, resblks, log_res, 0, XFS_TRANS_PERM_LOG_RES, log_count); if (error == ENOSPC) { + /* flush outstanding delalloc blocks and retry */ + xfs_flush_inodes(dp); + error = xfs_trans_reserve(tp, resblks, XFS_CREATE_LOG_RES(mp), 0, + XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT); + } + if (error == ENOSPC) { + /* No space at all so try a "no-allocation" reservation */ resblks = 0; error = xfs_trans_reserve(tp, 0, log_res, 0, XFS_TRANS_PERM_LOG_RES, log_count); diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h index 00f45ff081a..b0e63c672eb 100644 --- a/include/asm-generic/percpu.h +++ b/include/asm-generic/percpu.h @@ -80,56 +80,4 @@ extern void setup_per_cpu_areas(void); #define DECLARE_PER_CPU(type, name) extern PER_CPU_ATTRIBUTES \ __typeof__(type) per_cpu_var(name) -/* - * Optional methods for optimized non-lvalue per-cpu variable access. - * - * @var can be a percpu variable or a field of it and its size should - * equal char, int or long. percpu_read() evaluates to a lvalue and - * all others to void. - * - * These operations are guaranteed to be atomic w.r.t. preemption. - * The generic versions use plain get/put_cpu_var(). Archs are - * encouraged to implement single-instruction alternatives which don't - * require preemption protection. - */ -#ifndef percpu_read -# define percpu_read(var) \ - ({ \ - typeof(per_cpu_var(var)) __tmp_var__; \ - __tmp_var__ = get_cpu_var(var); \ - put_cpu_var(var); \ - __tmp_var__; \ - }) -#endif - -#define __percpu_generic_to_op(var, val, op) \ -do { \ - get_cpu_var(var) op val; \ - put_cpu_var(var); \ -} while (0) - -#ifndef percpu_write -# define percpu_write(var, val) __percpu_generic_to_op(var, (val), =) -#endif - -#ifndef percpu_add -# define percpu_add(var, val) __percpu_generic_to_op(var, (val), +=) -#endif - -#ifndef percpu_sub -# define percpu_sub(var, val) __percpu_generic_to_op(var, (val), -=) -#endif - -#ifndef percpu_and -# define percpu_and(var, val) __percpu_generic_to_op(var, (val), &=) -#endif - -#ifndef percpu_or -# define percpu_or(var, val) __percpu_generic_to_op(var, (val), |=) -#endif - -#ifndef percpu_xor -# define percpu_xor(var, val) __percpu_generic_to_op(var, (val), ^=) -#endif - #endif /* _ASM_GENERIC_PERCPU_H_ */ diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h index 35752dadd6d..c840719a8c5 100644 --- a/include/asm-generic/siginfo.h +++ b/include/asm-generic/siginfo.h @@ -201,7 +201,7 @@ typedef struct siginfo { #define TRAP_TRACE (__SI_FAULT|2) /* process trace trap */ #define TRAP_BRANCH (__SI_FAULT|3) /* process taken branch trap */ #define TRAP_HWBKPT (__SI_FAULT|4) /* hardware breakpoint/watchpoint */ -#define NSIGTRAP 2 +#define NSIGTRAP 4 /* * SIGCHLD si_codes diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 2df74eb0956..9477af01a63 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -472,6 +472,7 @@ {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x358e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0, 0, 0} #define gamma_PCI_IDS \ @@ -533,4 +534,5 @@ {0x8086, 0x2e22, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ {0x8086, 0xa001, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ {0x8086, 0xa011, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ + {0x8086, 0x35e8, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ {0, 0, 0} diff --git a/include/linux/capability.h b/include/linux/capability.h index 4864a43b2b4..c3021105edc 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -377,7 +377,21 @@ struct cpu_vfs_cap_data { #define CAP_FOR_EACH_U32(__capi) \ for (__capi = 0; __capi < _KERNEL_CAPABILITY_U32S; ++__capi) +/* + * CAP_FS_MASK and CAP_NFSD_MASKS: + * + * The fs mask is all the privileges that fsuid==0 historically meant. + * At one time in the past, that included CAP_MKNOD and CAP_LINUX_IMMUTABLE. + * + * It has never meant setting security.* and trusted.* xattrs. + * + * We could also define fsmask as follows: + * 1. CAP_FS_MASK is the privilege to bypass all fs-related DAC permissions + * 2. The security.* and trusted.* xattrs are fs-related MAC permissions + */ + # define CAP_FS_MASK_B0 (CAP_TO_MASK(CAP_CHOWN) \ + | CAP_TO_MASK(CAP_MKNOD) \ | CAP_TO_MASK(CAP_DAC_OVERRIDE) \ | CAP_TO_MASK(CAP_DAC_READ_SEARCH) \ | CAP_TO_MASK(CAP_FOWNER) \ @@ -392,11 +406,12 @@ struct cpu_vfs_cap_data { # define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }}) # define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }}) # define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }}) -# define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0, CAP_FS_MASK_B1 } }) +# define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ + | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \ + CAP_FS_MASK_B1 } }) # define CAP_NFSD_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ - | CAP_TO_MASK(CAP_SYS_RESOURCE) \ - | CAP_TO_MASK(CAP_MKNOD), \ - CAP_FS_MASK_B1 } }) + | CAP_TO_MASK(CAP_SYS_RESOURCE), \ + CAP_FS_MASK_B1 } }) #endif /* _KERNEL_CAPABILITY_U32S != 2 */ diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h index 096476f1fb3..493dedb7a67 100644 --- a/include/linux/debug_locks.h +++ b/include/linux/debug_locks.h @@ -2,12 +2,19 @@ #define __LINUX_DEBUG_LOCKING_H #include <linux/kernel.h> +#include <asm/atomic.h> struct task_struct; extern int debug_locks; extern int debug_locks_silent; + +static inline int __debug_locks_off(void) +{ + return xchg(&debug_locks, 0); +} + /* * Generic 'turn off all lock debugging' function: */ diff --git a/include/linux/fb.h b/include/linux/fb.h index f563c501393..330c4b1bfca 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -173,8 +173,12 @@ struct fb_fix_screeninfo { /* Interpretation of offset for color fields: All offsets are from the right, * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you * can use the offset as right argument to <<). A pixel afterwards is a bit - * stream and is written to video memory as that unmodified. This implies - * big-endian byte order if bits_per_pixel is greater than 8. + * stream and is written to video memory as that unmodified. + * + * For pseudocolor: offset and length should be the same for all color + * components. Offset specifies the position of the least significant bit + * of the pallette index in a pixel value. Length indicates the number + * of available palette entries (i.e. # of entries = 1 << length). */ struct fb_bitfield { __u32 offset; /* beginning of bitfield */ diff --git a/include/linux/fiemap.h b/include/linux/fiemap.h index 671decbd2ae..934e22d6580 100644 --- a/include/linux/fiemap.h +++ b/include/linux/fiemap.h @@ -11,6 +11,8 @@ #ifndef _LINUX_FIEMAP_H #define _LINUX_FIEMAP_H +#include <linux/types.h> + struct fiemap_extent { __u64 fe_logical; /* logical offset in bytes for the start of * the extent from the beginning of the file */ diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 00ee11eb909..ad258059603 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -274,7 +274,7 @@ struct i2c_board_info { * are provided using conventional syntax. */ #define I2C_BOARD_INFO(dev_type, dev_addr) \ - .type = (dev_type), .addr = (dev_addr) + .type = dev_type, .addr = (dev_addr) /* Add-on boards should register/unregister their devices; e.g. a board diff --git a/include/linux/init_task.h b/include/linux/init_task.h index dcfb93337e9..d87247d2641 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -15,19 +15,6 @@ extern struct files_struct init_files; extern struct fs_struct init_fs; -#define INIT_KIOCTX(name, which_mm) \ -{ \ - .users = ATOMIC_INIT(1), \ - .dead = 0, \ - .mm = &which_mm, \ - .user_id = 0, \ - .next = NULL, \ - .wait = __WAIT_QUEUE_HEAD_INITIALIZER(name.wait), \ - .ctx_lock = __SPIN_LOCK_UNLOCKED(name.ctx_lock), \ - .reqs_active = 0U, \ - .max_reqs = ~0U, \ -} - #define INIT_MM(name) \ { \ .mm_rb = RB_ROOT, \ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ee98cd57088..06ba90c211a 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2514,6 +2514,8 @@ #define PCI_DEVICE_ID_INTEL_IOAT_TBG3 0x3433 #define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 #define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 +#define PCI_DEVICE_ID_INTEL_82854_HB 0x358c +#define PCI_DEVICE_ID_INTEL_82854_IG 0x358e #define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580 #define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582 #define PCI_DEVICE_ID_INTEL_E7520_MCH 0x3590 diff --git a/include/linux/percpu.h b/include/linux/percpu.h index ee5615d6521..cfda2d5ad31 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -168,4 +168,56 @@ static inline void free_percpu(void *p) #define alloc_percpu(type) (type *)__alloc_percpu(sizeof(type), \ __alignof__(type)) +/* + * Optional methods for optimized non-lvalue per-cpu variable access. + * + * @var can be a percpu variable or a field of it and its size should + * equal char, int or long. percpu_read() evaluates to a lvalue and + * all others to void. + * + * These operations are guaranteed to be atomic w.r.t. preemption. + * The generic versions use plain get/put_cpu_var(). Archs are + * encouraged to implement single-instruction alternatives which don't + * require preemption protection. + */ +#ifndef percpu_read +# define percpu_read(var) \ + ({ \ + typeof(per_cpu_var(var)) __tmp_var__; \ + __tmp_var__ = get_cpu_var(var); \ + put_cpu_var(var); \ + __tmp_var__; \ + }) +#endif + +#define __percpu_generic_to_op(var, val, op) \ +do { \ + get_cpu_var(var) op val; \ + put_cpu_var(var); \ +} while (0) + +#ifndef percpu_write +# define percpu_write(var, val) __percpu_generic_to_op(var, (val), =) +#endif + +#ifndef percpu_add +# define percpu_add(var, val) __percpu_generic_to_op(var, (val), +=) +#endif + +#ifndef percpu_sub +# define percpu_sub(var, val) __percpu_generic_to_op(var, (val), -=) +#endif + +#ifndef percpu_and +# define percpu_and(var, val) __percpu_generic_to_op(var, (val), &=) +#endif + +#ifndef percpu_or +# define percpu_or(var, val) __percpu_generic_to_op(var, (val), |=) +#endif + +#ifndef percpu_xor +# define percpu_xor(var, val) __percpu_generic_to_op(var, (val), ^=) +#endif + #endif /* __LINUX_PERCPU_H */ diff --git a/include/linux/rotary_encoder.h b/include/linux/rotary_encoder.h new file mode 100644 index 00000000000..12d63a30c34 --- /dev/null +++ b/include/linux/rotary_encoder.h @@ -0,0 +1,13 @@ +#ifndef __ROTARY_ENCODER_H__ +#define __ROTARY_ENCODER_H__ + +struct rotary_encoder_platform_data { + unsigned int steps; + unsigned int axis; + unsigned int gpio_a; + unsigned int gpio_b; + unsigned int inverted_a; + unsigned int inverted_b; +}; + +#endif /* __ROTARY_ENCODER_H__ */ diff --git a/include/linux/sht15.h b/include/linux/sht15.h new file mode 100644 index 00000000000..046bce05eca --- /dev/null +++ b/include/linux/sht15.h @@ -0,0 +1,24 @@ +/* + * sht15.h - support for the SHT15 Temperature and Humidity Sensor + * + * Copyright (c) 2009 Jonathan Cameron + * + * Copyright (c) 2007 Wouter Horre + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/** + * struct sht15_platform_data - sht15 connectivity info + * @gpio_data: no. of gpio to which bidirectional data line is connected + * @gpio_sck: no. of gpio to which the data clock is connected. + * @supply_mv: supply voltage in mv. Overridden by regulator if available. + **/ +struct sht15_platform_data { + int gpio_data; + int gpio_sck; + int supply_mv; +}; + diff --git a/include/linux/spi/ad7879.h b/include/linux/spi/ad7879.h new file mode 100644 index 00000000000..4231104c9af --- /dev/null +++ b/include/linux/spi/ad7879.h @@ -0,0 +1,35 @@ +/* linux/spi/ad7879.h */ + +/* Touchscreen characteristics vary between boards and models. The + * platform_data for the device's "struct device" holds this information. + * + * It's OK if the min/max values are zero. + */ +struct ad7879_platform_data { + u16 model; /* 7879 */ + u16 x_plate_ohms; + u16 x_min, x_max; + u16 y_min, y_max; + u16 pressure_min, pressure_max; + + /* [0..255] 0=OFF Starts at 1=550us and goes + * all the way to 9.440ms in steps of 35us. + */ + u8 pen_down_acc_interval; + /* [0..15] Starts at 0=128us and goes all the + * way to 4.096ms in steps of 128us. + */ + u8 first_conversion_delay; + /* [0..3] 0 = 2us, 1 = 4us, 2 = 8us, 3 = 16us */ + u8 acquisition_time; + /* [0..3] Average X middle samples 0 = 2, 1 = 4, 2 = 8, 3 = 16 */ + u8 averaging; + /* [0..3] Perform X measurements 0 = OFF, + * 1 = 4, 2 = 8, 3 = 16 (median > averaging) + */ + u8 median; + /* 1 = AUX/VBAT/GPIO set to GPIO Output */ + u8 gpio_output; + /* Initial GPIO pin state (valid if gpio_output = 1) */ + u8 gpio_default; +}; diff --git a/include/linux/stringify.h b/include/linux/stringify.h index 0b4388356c8..841cec8ed52 100644 --- a/include/linux/stringify.h +++ b/include/linux/stringify.h @@ -6,7 +6,7 @@ * converts to "bar". */ -#define __stringify_1(x) #x -#define __stringify(x) __stringify_1(x) +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) #endif /* !__LINUX_STRINGIFY_H */ diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index b9584254259..625e9e4639c 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -29,7 +29,7 @@ /** * usb_serial_port: structure for the specific ports of a device. * @serial: pointer back to the struct usb_serial owner of this port. - * @tty: pointer to the corresponding tty for this port. + * @port: pointer to the corresponding tty_port for this port. * @lock: spinlock to grab when updating portions of this structure. * @mutex: mutex used to synchronize serial_open() and serial_close() * access for this port. @@ -44,19 +44,22 @@ * @interrupt_out_endpointAddress: endpoint address for the interrupt out pipe * for this port. * @bulk_in_buffer: pointer to the bulk in buffer for this port. + * @bulk_in_size: the size of the bulk_in_buffer, in bytes. * @read_urb: pointer to the bulk in struct urb for this port. * @bulk_in_endpointAddress: endpoint address for the bulk in pipe for this * port. * @bulk_out_buffer: pointer to the bulk out buffer for this port. * @bulk_out_size: the size of the bulk_out_buffer, in bytes. * @write_urb: pointer to the bulk out struct urb for this port. + * @write_urb_busy: port`s writing status * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this * port. * @write_wait: a wait_queue_head_t used by the port. * @work: work queue entry for the line discipline waking up. - * @open_count: number of times this port has been opened. * @throttled: nonzero if the read urb is inactive to throttle the device * @throttle_req: nonzero if the tty wants to throttle us + * @console: attached usb serial console + * @dev: pointer to the serial device * * This structure is used by the usb-serial core and drivers for the specific * ports of a device. diff --git a/include/scsi/scsi_scan.h b/include/scsi/scsi_scan.h new file mode 100644 index 00000000000..78898889243 --- /dev/null +++ b/include/scsi/scsi_scan.h @@ -0,0 +1,11 @@ +#ifndef _SCSI_SCSI_SCAN_H +#define _SCSI_SCSI_SCAN_H + +#ifdef CONFIG_SCSI +/* drivers/scsi/scsi_scan.c */ +extern int scsi_complete_async_scans(void); +#else +static inline int scsi_complete_async_scans(void) { return 0; } +#endif + +#endif /* _SCSI_SCSI_SCAN_H */ diff --git a/include/video/cyblafb.h b/include/video/cyblafb.h deleted file mode 100644 index d3c1d4e2c8e..00000000000 --- a/include/video/cyblafb.h +++ /dev/null @@ -1,175 +0,0 @@ - -#ifndef CYBLAFB_DEBUG -#define CYBLAFB_DEBUG 0 -#endif - -#if CYBLAFB_DEBUG -#define debug(f,a...) printk("%s:" f, __func__ , ## a); -#else -#define debug(f,a...) -#endif - -#define output(f, a...) printk("cyblafb: " f, ## a) - -#define Kb (1024) -#define Mb (Kb*Kb) - -/* PCI IDS of supported cards temporarily here */ - -#define CYBERBLADEi1 0x8500 - -/* these defines are for 'lcd' variable */ -#define LCD_STRETCH 0 -#define LCD_CENTER 1 -#define LCD_BIOS 2 - -/* display types */ -#define DISPLAY_CRT 0 -#define DISPLAY_FP 1 - -#define ROP_S 0xCC - -#define point(x,y) ((y)<<16|(x)) - -// -// Attribute Regs, ARxx, 3c0/3c1 -// -#define AR00 0x00 -#define AR01 0x01 -#define AR02 0x02 -#define AR03 0x03 -#define AR04 0x04 -#define AR05 0x05 -#define AR06 0x06 -#define AR07 0x07 -#define AR08 0x08 -#define AR09 0x09 -#define AR0A 0x0A -#define AR0B 0x0B -#define AR0C 0x0C -#define AR0D 0x0D -#define AR0E 0x0E -#define AR0F 0x0F -#define AR10 0x10 -#define AR12 0x12 -#define AR13 0x13 - -// -// Sequencer Regs, SRxx, 3c4/3c5 -// -#define SR00 0x00 -#define SR01 0x01 -#define SR02 0x02 -#define SR03 0x03 -#define SR04 0x04 -#define SR0D 0x0D -#define SR0E 0x0E -#define SR11 0x11 -#define SR18 0x18 -#define SR19 0x19 - -// -// -// -#define CR00 0x00 -#define CR01 0x01 -#define CR02 0x02 -#define CR03 0x03 -#define CR04 0x04 -#define CR05 0x05 -#define CR06 0x06 -#define CR07 0x07 -#define CR08 0x08 -#define CR09 0x09 -#define CR0A 0x0A -#define CR0B 0x0B -#define CR0C 0x0C -#define CR0D 0x0D -#define CR0E 0x0E -#define CR0F 0x0F -#define CR10 0x10 -#define CR11 0x11 -#define CR12 0x12 -#define CR13 0x13 -#define CR14 0x14 -#define CR15 0x15 -#define CR16 0x16 -#define CR17 0x17 -#define CR18 0x18 -#define CR19 0x19 -#define CR1A 0x1A -#define CR1B 0x1B -#define CR1C 0x1C -#define CR1D 0x1D -#define CR1E 0x1E -#define CR1F 0x1F -#define CR20 0x20 -#define CR21 0x21 -#define CR27 0x27 -#define CR29 0x29 -#define CR2A 0x2A -#define CR2B 0x2B -#define CR2D 0x2D -#define CR2F 0x2F -#define CR36 0x36 -#define CR38 0x38 -#define CR39 0x39 -#define CR3A 0x3A -#define CR55 0x55 -#define CR56 0x56 -#define CR57 0x57 -#define CR58 0x58 - -// -// -// - -#define GR00 0x01 -#define GR01 0x01 -#define GR02 0x02 -#define GR03 0x03 -#define GR04 0x04 -#define GR05 0x05 -#define GR06 0x06 -#define GR07 0x07 -#define GR08 0x08 -#define GR0F 0x0F -#define GR20 0x20 -#define GR23 0x23 -#define GR2F 0x2F -#define GR30 0x30 -#define GR31 0x31 -#define GR33 0x33 -#define GR52 0x52 -#define GR53 0x53 -#define GR5D 0x5d - - -// -// Graphics Engine -// -#define GEBase 0x2100 // could be mapped elsewhere if we like it -#define GE00 (GEBase+0x00) // source 1, p 111 -#define GE04 (GEBase+0x04) // source 2, p 111 -#define GE08 (GEBase+0x08) // destination 1, p 111 -#define GE0C (GEBase+0x0C) // destination 2, p 112 -#define GE10 (GEBase+0x10) // right view base & enable, p 112 -#define GE13 (GEBase+0x13) // left view base & enable, p 112 -#define GE18 (GEBase+0x18) // block write start address, p 112 -#define GE1C (GEBase+0x1C) // block write end address, p 112 -#define GE20 (GEBase+0x20) // engine status, p 113 -#define GE24 (GEBase+0x24) // reset all GE pointers -#define GE44 (GEBase+0x44) // command register, p 126 -#define GE48 (GEBase+0x48) // raster operation, p 127 -#define GE60 (GEBase+0x60) // foreground color, p 128 -#define GE64 (GEBase+0x64) // background color, p 128 -#define GE6C (GEBase+0x6C) // Pattern and Style, p 129, ok -#define GE9C (GEBase+0x9C) // pixel engine data port, p 125 -#define GEB8 (GEBase+0xB8) // Destination Stride / Buffer Base 0, p 133 -#define GEBC (GEBase+0xBC) // Destination Stride / Buffer Base 1, p 133 -#define GEC0 (GEBase+0xC0) // Destination Stride / Buffer Base 2, p 133 -#define GEC4 (GEBase+0xC4) // Destination Stride / Buffer Base 3, p 133 -#define GEC8 (GEBase+0xC8) // Source Stride / Buffer Base 0, p 133 -#define GECC (GEBase+0xCC) // Source Stride / Buffer Base 1, p 133 -#define GED0 (GEBase+0xD0) // Source Stride / Buffer Base 2, p 133 -#define GED4 (GEBase+0xD4) // Source Stride / Buffer Base 3, p 133 diff --git a/init/Kconfig b/init/Kconfig index f2f9b5362b4..7be4d383674 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -808,6 +808,14 @@ config KALLSYMS_EXTRA_PASS you wait for kallsyms to be fixed. +config STRIP_ASM_SYMS + bool "Strip assembler-generated symbols during link" + default n + help + Strip internal assembler-generated symbols during a link (symbols + that look like '.Lxxx') so they don't pollute the output of + get_wchan() and suchlike. + config HOTPLUG bool "Support for hot-pluggable devices" if EMBEDDED default y diff --git a/init/initramfs.c b/init/initramfs.c index 80cd713f6cc..9ee7b781041 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -310,7 +310,8 @@ static int __init do_name(void) if (wfd >= 0) { sys_fchown(wfd, uid, gid); sys_fchmod(wfd, mode); - sys_ftruncate(wfd, body_len); + if (body_len) + sys_ftruncate(wfd, body_len); vcollected = kstrdup(collected, GFP_KERNEL); state = CopyFile; } @@ -515,6 +516,7 @@ skip: initrd_end = 0; } +#ifdef CONFIG_BLK_DEV_RAM #define BUF_SIZE 1024 static void __init clean_rootfs(void) { @@ -561,6 +563,7 @@ static void __init clean_rootfs(void) sys_close(fd); kfree(buf); } +#endif static int __init populate_rootfs(void) { diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c index 89f60ec8ee5..24ae46dfe45 100644 --- a/ipc/mq_sysctl.c +++ b/ipc/mq_sysctl.c @@ -22,6 +22,7 @@ #define MIN_MSGSIZEMAX 128 /* min value for msgsize_max */ #define MAX_MSGSIZEMAX (8192*128) /* max value for msgsize_max */ +#ifdef CONFIG_PROC_SYSCTL static void *get_mq(ctl_table *table) { char *which = table->data; @@ -30,7 +31,6 @@ static void *get_mq(ctl_table *table) return which; } -#ifdef CONFIG_PROC_SYSCTL static int proc_mq_dointvec(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) { diff --git a/kernel/mutex.c b/kernel/mutex.c index 5d79781394a..507cf2b5e9f 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -148,7 +148,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, preempt_disable(); mutex_acquire(&lock->dep_map, subclass, 0, ip); -#if defined(CONFIG_SMP) && !defined(CONFIG_DEBUG_MUTEXES) +#if defined(CONFIG_SMP) && !defined(CONFIG_DEBUG_MUTEXES) && \ + !defined(CONFIG_HAVE_DEFAULT_NO_SPIN_MUTEXES) /* * Optimistic spinning. * diff --git a/kernel/panic.c b/kernel/panic.c index 3fd8c5bf8b3..934fb377f4b 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -213,8 +213,16 @@ unsigned long get_taint(void) void add_taint(unsigned flag) { - /* can't trust the integrity of the kernel anymore: */ - debug_locks = 0; + /* + * Can't trust the integrity of the kernel anymore. + * We don't call directly debug_locks_off() because the issue + * is not necessarily serious enough to set oops_in_progress to 1 + * Also we want to keep up lockdep for staging development and + * post-warning case. + */ + if (flag != TAINT_CRAP && flag != TAINT_WARN && __debug_locks_off()) + printk(KERN_WARNING "Disabling lockdep due to kernel taint\n"); + set_bit(flag, &tainted_mask); } EXPORT_SYMBOL(add_taint); diff --git a/kernel/power/disk.c b/kernel/power/disk.c index 5f21ab2bbcd..0854770b63b 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -22,6 +22,7 @@ #include <linux/console.h> #include <linux/cpu.h> #include <linux/freezer.h> +#include <scsi/scsi_scan.h> #include <asm/suspend.h> #include "power.h" @@ -645,6 +646,13 @@ static int software_resume(void) return 0; /* + * We can't depend on SCSI devices being available after loading one of + * their modules if scsi_complete_async_scans() is not called and the + * resume device usually is a SCSI one. + */ + scsi_complete_async_scans(); + + /* * name_to_dev_t() below takes a sysfs buffer mutex when sysfs * is configured into the kernel. Since the regular hibernate * trigger path is via sysfs which takes a buffer mutex before diff --git a/kernel/power/user.c b/kernel/power/user.c index 6c85359364f..ed97375daae 100644 --- a/kernel/power/user.c +++ b/kernel/power/user.c @@ -24,6 +24,7 @@ #include <linux/cpu.h> #include <linux/freezer.h> #include <linux/smp_lock.h> +#include <scsi/scsi_scan.h> #include <asm/uaccess.h> @@ -92,6 +93,7 @@ static int snapshot_open(struct inode *inode, struct file *filp) filp->private_data = data; memset(&data->handle, 0, sizeof(struct snapshot_handle)); if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { + /* Hibernating. The image device should be accessible. */ data->swap = swsusp_resume_device ? swap_type_of(swsusp_resume_device, 0, NULL) : -1; data->mode = O_RDONLY; @@ -99,6 +101,13 @@ static int snapshot_open(struct inode *inode, struct file *filp) if (error) pm_notifier_call_chain(PM_POST_HIBERNATION); } else { + /* + * Resuming. We may need to wait for the image device to + * appear. + */ + wait_for_device_probe(); + scsi_complete_async_scans(); + data->swap = -1; data->mode = O_WRONLY; error = pm_notifier_call_chain(PM_RESTORE_PREPARE); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 64191fa09b7..dfcd83ceee3 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -604,10 +604,11 @@ repeat: ret = security_ptrace_traceme(current->parent); /* - * Set the ptrace bit in the process ptrace flags. - * Then link us on our parent's ptraced list. + * Check PF_EXITING to ensure ->real_parent has not passed + * exit_ptrace(). Otherwise we don't report the error but + * pretend ->real_parent untraces us right after return. */ - if (!ret) { + if (!ret && !(current->real_parent->flags & PF_EXITING)) { current->ptrace |= PT_PTRACED; __ptrace_link(current, current->real_parent); } diff --git a/kernel/sys.c b/kernel/sys.c index 51dbb55604e..e7998cf3149 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -360,6 +360,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg) { char buffer[256]; + int ret = 0; /* We only trust the superuser with rebooting the system. */ if (!capable(CAP_SYS_BOOT)) @@ -397,7 +398,7 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, kernel_halt(); unlock_kernel(); do_exit(0); - break; + panic("cannot halt"); case LINUX_REBOOT_CMD_POWER_OFF: kernel_power_off(); @@ -417,29 +418,22 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, #ifdef CONFIG_KEXEC case LINUX_REBOOT_CMD_KEXEC: - { - int ret; - ret = kernel_kexec(); - unlock_kernel(); - return ret; - } + ret = kernel_kexec(); + break; #endif #ifdef CONFIG_HIBERNATION case LINUX_REBOOT_CMD_SW_SUSPEND: - { - int ret = hibernate(); - unlock_kernel(); - return ret; - } + ret = hibernate(); + break; #endif default: - unlock_kernel(); - return -EINVAL; + ret = -EINVAL; + break; } unlock_kernel(); - return 0; + return ret; } static void deferred_cad(struct work_struct *dummy) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4286b62b34a..e3d2c7dd59b 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -902,16 +902,6 @@ static struct ctl_table kern_table[] = { .proc_handler = &proc_dointvec, }, #endif -#ifdef CONFIG_UNEVICTABLE_LRU - { - .ctl_name = CTL_UNNUMBERED, - .procname = "scan_unevictable_pages", - .data = &scan_unevictable_pages, - .maxlen = sizeof(scan_unevictable_pages), - .mode = 0644, - .proc_handler = &scan_unevictable_handler, - }, -#endif #ifdef CONFIG_SLOW_WORK { .ctl_name = CTL_UNNUMBERED, @@ -1302,6 +1292,16 @@ static struct ctl_table vm_table[] = { .extra2 = &one, }, #endif +#ifdef CONFIG_UNEVICTABLE_LRU + { + .ctl_name = CTL_UNNUMBERED, + .procname = "scan_unevictable_pages", + .data = &scan_unevictable_pages, + .maxlen = sizeof(scan_unevictable_pages), + .mode = 0644, + .proc_handler = &scan_unevictable_handler, + }, +#endif /* * NOTE: do not add new entries to this table unless you have read * Documentation/sysctl/ctl_unnumbered.txt diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 2246141bda4..417d1985e29 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -312,7 +312,7 @@ config KMEMTRACE and profile kernel code. This requires an userspace application to use. See - Documentation/vm/kmemtrace.txt for more information. + Documentation/trace/kmemtrace.txt for more information. Saying Y will make the kernel somewhat larger and slower. However, if you disable kmemtrace at run-time or boot-time, the performance @@ -403,7 +403,7 @@ config MMIOTRACE implementation and works via page faults. Tracing is disabled by default and can be enabled at run-time. - See Documentation/tracers/mmiotrace.txt. + See Documentation/trace/mmiotrace.txt. If you are not helping to develop drivers, say N. config MMIOTRACE_TEST diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 9d28476a985..1ce5dc6372b 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3277,19 +3277,13 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp) info->tr = &global_trace; info->cpu = cpu; - info->spare = ring_buffer_alloc_read_page(info->tr->buffer); + info->spare = NULL; /* Force reading ring buffer for first read */ info->read = (unsigned int)-1; - if (!info->spare) - goto out; filp->private_data = info; - return 0; - - out: - kfree(info); - return -ENOMEM; + return nonseekable_open(inode, filp); } static ssize_t @@ -3304,6 +3298,11 @@ tracing_buffers_read(struct file *filp, char __user *ubuf, if (!count) return 0; + if (!info->spare) + info->spare = ring_buffer_alloc_read_page(info->tr->buffer); + if (!info->spare) + return -ENOMEM; + /* Do we have previous read data to read? */ if (info->read < PAGE_SIZE) goto read; @@ -3342,7 +3341,8 @@ static int tracing_buffers_release(struct inode *inode, struct file *file) { struct ftrace_buffer_info *info = file->private_data; - ring_buffer_free_read_page(info->tr->buffer, info->spare); + if (info->spare) + ring_buffer_free_read_page(info->tr->buffer, info->spare); kfree(info); return 0; @@ -3428,14 +3428,19 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, int size, i; size_t ret; - /* - * We can't seek on a buffer input - */ - if (unlikely(*ppos)) - return -ESPIPE; + if (*ppos & (PAGE_SIZE - 1)) { + WARN_ONCE(1, "Ftrace: previous read must page-align\n"); + return -EINVAL; + } + if (len & (PAGE_SIZE - 1)) { + WARN_ONCE(1, "Ftrace: splice_read should page-align\n"); + if (len < PAGE_SIZE) + return -EINVAL; + len &= PAGE_MASK; + } - for (i = 0; i < PIPE_BUFFERS && len; i++, len -= size) { + for (i = 0; i < PIPE_BUFFERS && len; i++, len -= PAGE_SIZE) { struct page *page; int r; @@ -3474,6 +3479,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, spd.partial[i].offset = 0; spd.partial[i].private = (unsigned long)ref; spd.nr_pages++; + *ppos += PAGE_SIZE; } spd.nr_pages = i; diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 64ec4d278ff..576f4fa2af0 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -503,6 +503,7 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, if (copy_from_user(&buf, ubuf, cnt)) return -EFAULT; + buf[cnt] = '\0'; pred = kzalloc(sizeof(*pred), GFP_KERNEL); if (!pred) @@ -520,9 +521,10 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, return cnt; } - if (filter_add_pred(call, pred)) { + err = filter_add_pred(call, pred); + if (err < 0) { filter_free_pred(pred); - return -EINVAL; + return err; } *ppos += cnt; @@ -569,6 +571,7 @@ subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, if (copy_from_user(&buf, ubuf, cnt)) return -EFAULT; + buf[cnt] = '\0'; pred = kzalloc(sizeof(*pred), GFP_KERNEL); if (!pred) @@ -586,10 +589,11 @@ subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, return cnt; } - if (filter_add_subsystem_pred(system, pred)) { + err = filter_add_subsystem_pred(system, pred); + if (err < 0) { filter_free_subsystem_preds(system); filter_free_pred(pred); - return -EINVAL; + return err; } *ppos += cnt; diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 026be412f35..e03cbf1e38f 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -215,7 +215,7 @@ static int __filter_add_pred(struct ftrace_event_call *call, } } - return -ENOMEM; + return -ENOSPC; } static int is_string_field(const char *type) @@ -319,7 +319,7 @@ int filter_add_subsystem_pred(struct event_subsystem *system, } if (i == MAX_FILTER_PRED) - return -EINVAL; + return -ENOSPC; events_for_each(call) { int err; @@ -410,16 +410,22 @@ int filter_parse(char **pbuf, struct filter_pred *pred) } } + if (!val_str) { + pred->field_name = NULL; + return -EINVAL; + } + pred->field_name = kstrdup(pred->field_name, GFP_KERNEL); if (!pred->field_name) return -ENOMEM; - pred->val = simple_strtoull(val_str, &tmp, 10); + pred->val = simple_strtoull(val_str, &tmp, 0); if (tmp == val_str) { pred->str_val = kstrdup(val_str, GFP_KERNEL); if (!pred->str_val) return -ENOMEM; - } + } else if (*tmp != '\0') + return -EINVAL; return 0; } diff --git a/kernel/trace/trace_events_stage_2.h b/kernel/trace/trace_events_stage_2.h index 30743f7d411..d363c6672c6 100644 --- a/kernel/trace/trace_events_stage_2.h +++ b/kernel/trace/trace_events_stage_2.h @@ -105,10 +105,10 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \ return 0; #undef __entry -#define __entry "REC" +#define __entry REC #undef TP_printk -#define TP_printk(fmt, args...) "%s, %s\n", #fmt, #args +#define TP_printk(fmt, args...) "%s, %s\n", #fmt, __stringify(args) #undef TP_fast_assign #define TP_fast_assign(args...) args diff --git a/lib/debug_locks.c b/lib/debug_locks.c index 0218b4693dd..bc3b11731b9 100644 --- a/lib/debug_locks.c +++ b/lib/debug_locks.c @@ -36,7 +36,7 @@ int debug_locks_silent; */ int debug_locks_off(void) { - if (xchg(&debug_locks, 0)) { + if (__debug_locks_off()) { if (!debug_locks_silent) { oops_in_progress = 1; console_verbose(); diff --git a/mm/Kconfig b/mm/Kconfig index b53427ad30a..57971d2ab84 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -213,6 +213,8 @@ config UNEVICTABLE_LRU will use one page flag and increase the code size a little, say Y unless you know what you are doing. + See Documentation/vm/unevictable-lru.txt for more information. + config HAVE_MLOCK bool default y if MMU=y diff --git a/mm/filemap.c b/mm/filemap.c index 2e2d38ebda4..8bd498040f3 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -567,8 +567,8 @@ EXPORT_SYMBOL(wait_on_page_bit); /** * add_page_wait_queue - Add an arbitrary waiter to a page's wait queue - * @page - Page defining the wait queue of interest - * @waiter - Waiter to add to the queue + * @page: Page defining the wait queue of interest + * @waiter: Waiter to add to the queue * * Add an arbitrary @waiter to the wait queue for the nominated @page. */ diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 2fc6d6c4823..e44fb0fbb80 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -932,7 +932,7 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm, if (unlikely(!mem)) return 0; - VM_BUG_ON(mem_cgroup_is_obsolete(mem)); + VM_BUG_ON(!mem || mem_cgroup_is_obsolete(mem)); while (1) { int ret; diff --git a/mm/shmem.c b/mm/shmem.c index d94d2e9146b..f9cb20ebb99 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -24,6 +24,7 @@ #include <linux/init.h> #include <linux/vfs.h> #include <linux/mount.h> +#include <linux/pagemap.h> #include <linux/file.h> #include <linux/mm.h> #include <linux/module.h> @@ -43,7 +44,6 @@ static struct vfsmount *shm_mnt; #include <linux/exportfs.h> #include <linux/generic_acl.h> #include <linux/mman.h> -#include <linux/pagemap.h> #include <linux/string.h> #include <linux/slab.h> #include <linux/backing-dev.h> @@ -65,13 +65,28 @@ static struct vfsmount *shm_mnt; #include <asm/div64.h> #include <asm/pgtable.h> +/* + * The maximum size of a shmem/tmpfs file is limited by the maximum size of + * its triple-indirect swap vector - see illustration at shmem_swp_entry(). + * + * With 4kB page size, maximum file size is just over 2TB on a 32-bit kernel, + * but one eighth of that on a 64-bit kernel. With 8kB page size, maximum + * file size is just over 4TB on a 64-bit kernel, but 16TB on a 32-bit kernel, + * MAX_LFS_FILESIZE being then more restrictive than swap vector layout. + * + * We use / and * instead of shifts in the definitions below, so that the swap + * vector can be tested with small even values (e.g. 20) for ENTRIES_PER_PAGE. + */ #define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long)) -#define ENTRIES_PER_PAGEPAGE (ENTRIES_PER_PAGE*ENTRIES_PER_PAGE) -#define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512) +#define ENTRIES_PER_PAGEPAGE ((unsigned long long)ENTRIES_PER_PAGE*ENTRIES_PER_PAGE) -#define SHMEM_MAX_INDEX (SHMEM_NR_DIRECT + (ENTRIES_PER_PAGEPAGE/2) * (ENTRIES_PER_PAGE+1)) -#define SHMEM_MAX_BYTES ((unsigned long long)SHMEM_MAX_INDEX << PAGE_CACHE_SHIFT) +#define SHMSWP_MAX_INDEX (SHMEM_NR_DIRECT + (ENTRIES_PER_PAGEPAGE/2) * (ENTRIES_PER_PAGE+1)) +#define SHMSWP_MAX_BYTES (SHMSWP_MAX_INDEX << PAGE_CACHE_SHIFT) +#define SHMEM_MAX_BYTES min_t(unsigned long long, SHMSWP_MAX_BYTES, MAX_LFS_FILESIZE) +#define SHMEM_MAX_INDEX ((unsigned long)((SHMEM_MAX_BYTES+1) >> PAGE_CACHE_SHIFT)) + +#define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512) #define VM_ACCT(size) (PAGE_CACHE_ALIGN(size) >> PAGE_SHIFT) /* info->flags needs VM_flags to handle pagein/truncate races efficiently */ @@ -2581,7 +2596,7 @@ int shmem_unuse(swp_entry_t entry, struct page *page) #define shmem_get_inode(sb, mode, dev, flags) ramfs_get_inode(sb, mode, dev) #define shmem_acct_size(flags, size) 0 #define shmem_unacct_size(flags, size) do {} while (0) -#define SHMEM_MAX_BYTES LLONG_MAX +#define SHMEM_MAX_BYTES MAX_LFS_FILESIZE #endif /* CONFIG_SHMEM */ diff --git a/mm/util.c b/mm/util.c index 2599e83eea1..55bef160b9f 100644 --- a/mm/util.c +++ b/mm/util.c @@ -223,6 +223,22 @@ void arch_pick_mmap_layout(struct mm_struct *mm) } #endif +/** + * get_user_pages_fast() - pin user pages in memory + * @start: starting user address + * @nr_pages: number of pages from start to pin + * @write: whether pages will be written to + * @pages: array that receives pointers to the pages pinned. + * Should be at least nr_pages long. + * + * Attempt to pin user pages in memory without taking mm->mmap_sem. + * If not successful, it will fall back to taking the lock and + * calling get_user_pages(). + * + * Returns number of pages pinned. This may be fewer than the number + * requested. If nr_pages is 0 or negative, returns 0. If no pages + * were pinned, returns -errno. + */ int __attribute__((weak)) get_user_pages_fast(unsigned long start, int nr_pages, int write, struct page **pages) { diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst index 612dc13ddd8..095cfc8b9db 100644 --- a/scripts/Makefile.headersinst +++ b/scripts/Makefile.headersinst @@ -14,6 +14,8 @@ _dst := $(if $(dst),$(dst),$(obj)) kbuild-file := $(srctree)/$(obj)/Kbuild include $(kbuild-file) +_dst := $(if $(destination-y),$(destination-y),$(_dst)) + include scripts/Kbuild.include install := $(INSTALL_HDR_PATH)/$(_dst) diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh index 3eea8f15131..76af5f9623e 100644 --- a/scripts/gen_initramfs_list.sh +++ b/scripts/gen_initramfs_list.sh @@ -97,7 +97,7 @@ print_mtime() { } list_parse() { - echo "$1 \\" + [ ! -L "$1" ] && echo "$1 \\" || : } # for each file print a line in following format diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl new file mode 100755 index 00000000000..60dc0c48c92 --- /dev/null +++ b/scripts/get_maintainer.pl @@ -0,0 +1,515 @@ +#!/usr/bin/perl -w +# (c) 2007, Joe Perches <joe@perches.com> +# created from checkpatch.pl +# +# Print selected MAINTAINERS information for +# the files modified in a patch or for a file +# +# usage: perl scripts/get_maintainers.pl [OPTIONS] <patch> +# perl scripts/get_maintainers.pl [OPTIONS] -f <file> +# +# Licensed under the terms of the GNU GPL License version 2 + +use strict; + +my $P = $0; +my $V = '0.15'; + +use Getopt::Long qw(:config no_auto_abbrev); + +my $lk_path = "./"; +my $email = 1; +my $email_usename = 1; +my $email_maintainer = 1; +my $email_list = 1; +my $email_subscriber_list = 0; +my $email_git = 1; +my $email_git_penguin_chiefs = 0; +my $email_git_min_signatures = 1; +my $email_git_max_maintainers = 5; +my $email_git_since = "1-year-ago"; +my $output_multiline = 1; +my $output_separator = ", "; +my $scm = 0; +my $web = 0; +my $subsystem = 0; +my $status = 0; +my $from_filename = 0; +my $version = 0; +my $help = 0; + +my $exit = 0; + +my @penguin_chief = (); +push(@penguin_chief,"Linus Torvalds:torvalds\@linux-foundation.org"); +#Andrew wants in on most everything - 2009/01/14 +#push(@penguin_chief,"Andrew Morton:akpm\@linux-foundation.org"); + +my @penguin_chief_names = (); +foreach my $chief (@penguin_chief) { + if ($chief =~ m/^(.*):(.*)/) { + my $chief_name = $1; + my $chief_addr = $2; + push(@penguin_chief_names, $chief_name); + } +} +my $penguin_chiefs = "\(" . join("|",@penguin_chief_names) . "\)"; + +if (!GetOptions( + 'email!' => \$email, + 'git!' => \$email_git, + 'git-chief-penguins!' => \$email_git_penguin_chiefs, + 'git-min-signatures=i' => \$email_git_min_signatures, + 'git-max-maintainers=i' => \$email_git_max_maintainers, + 'git-since=s' => \$email_git_since, + 'm!' => \$email_maintainer, + 'n!' => \$email_usename, + 'l!' => \$email_list, + 's!' => \$email_subscriber_list, + 'multiline!' => \$output_multiline, + 'separator=s' => \$output_separator, + 'subsystem!' => \$subsystem, + 'status!' => \$status, + 'scm!' => \$scm, + 'web!' => \$web, + 'f|file' => \$from_filename, + 'v|version' => \$version, + 'h|help' => \$help, + )) { + usage(); + die "$P: invalid argument\n"; +} + +if ($help != 0) { + usage(); + exit 0; +} + +if ($version != 0) { + print("${P} ${V}\n"); + exit 0; +} + +if ($#ARGV < 0) { + usage(); + die "$P: argument missing: patchfile or -f file please\n"; +} + +my $selections = $email + $scm + $status + $subsystem + $web; +if ($selections == 0) { + usage(); + die "$P: Missing required option: email, scm, status, subsystem or web\n"; +} + +if ($email && ($email_maintainer + $email_list + $email_subscriber_list + + $email_git + $email_git_penguin_chiefs) == 0) { + usage(); + die "$P: Please select at least 1 email option\n"; +} + +if (!top_of_kernel_tree($lk_path)) { + die "$P: The current directory does not appear to be " + . "a linux kernel source tree.\n"; +} + +## Read MAINTAINERS for type/value pairs + +my @typevalue = (); +open(MAINT, "<${lk_path}MAINTAINERS") || die "$P: Can't open MAINTAINERS\n"; +while (<MAINT>) { + my $line = $_; + + if ($line =~ m/^(\C):\s*(.*)/) { + my $type = $1; + my $value = $2; + + ##Filename pattern matching + if ($type eq "F" || $type eq "X") { + $value =~ s@\.@\\\.@g; ##Convert . to \. + $value =~ s/\*/\.\*/g; ##Convert * to .* + $value =~ s/\?/\./g; ##Convert ? to . + } + push(@typevalue, "$type:$value"); + } elsif (!/^(\s)*$/) { + $line =~ s/\n$//g; + push(@typevalue, $line); + } +} +close(MAINT); + +## use the filenames on the command line or find the filenames in the patchfiles + +my @files = (); + +foreach my $file (@ARGV) { + next if ((-d $file)); + if (!(-f $file)) { + die "$P: file '${file}' not found\n"; + } + if ($from_filename) { + push(@files, $file); + } else { + my $file_cnt = @files; + open(PATCH, "<$file") or die "$P: Can't open ${file}\n"; + while (<PATCH>) { + if (m/^\+\+\+\s+(\S+)/) { + my $filename = $1; + $filename =~ s@^[^/]*/@@; + $filename =~ s@\n@@; + push(@files, $filename); + } + } + close(PATCH); + if ($file_cnt == @files) { + die "$P: file '${file}' doesn't appear to be a patch. " + . "Add -f to options?\n"; + } + @files = sort_and_uniq(@files); + } +} + +my @email_to = (); +my @scm = (); +my @web = (); +my @subsystem = (); +my @status = (); + +# Find responsible parties + +foreach my $file (@files) { + +#Do not match excluded file patterns + + my $exclude = 0; + foreach my $line (@typevalue) { + if ($line =~ m/^(\C):(.*)/) { + my $type = $1; + my $value = $2; + if ($type eq 'X') { + if (file_match_pattern($file, $value)) { + $exclude = 1; + } + } + } + } + + if (!$exclude) { + my $tvi = 0; + foreach my $line (@typevalue) { + if ($line =~ m/^(\C):(.*)/) { + my $type = $1; + my $value = $2; + if ($type eq 'F') { + if (file_match_pattern($file, $value)) { + add_categories($tvi); + } + } + } + $tvi++; + } + } + + if ($email && $email_git) { + recent_git_signoffs($file); + } + +} + +if ($email_git_penguin_chiefs) { + foreach my $chief (@penguin_chief) { + if ($chief =~ m/^(.*):(.*)/) { + my $chief_name = $1; + my $chief_addr = $2; + if ($email_usename) { + push(@email_to, format_email($chief_name, $chief_addr)); + } else { + push(@email_to, $chief_addr); + } + } + } +} + +if ($email) { + my $address_cnt = @email_to; + if ($address_cnt == 0 && $email_list) { + push(@email_to, "linux-kernel\@vger.kernel.org"); + } + +#Don't sort email address list, but do remove duplicates + @email_to = uniq(@email_to); + output(@email_to); +} + +if ($scm) { + @scm = sort_and_uniq(@scm); + output(@scm); +} + +if ($status) { + @status = sort_and_uniq(@status); + output(@status); +} + +if ($subsystem) { + @subsystem = sort_and_uniq(@subsystem); + output(@subsystem); +} + +if ($web) { + @web = sort_and_uniq(@web); + output(@web); +} + +exit($exit); + +sub file_match_pattern { + my ($file, $pattern) = @_; + if (substr($pattern, -1) eq "/") { + if ($file =~ m@^$pattern@) { + return 1; + } + } else { + if ($file =~ m@^$pattern@) { + my $s1 = ($file =~ tr@/@@); + my $s2 = ($pattern =~ tr@/@@); + if ($s1 == $s2) { + return 1; + } + } + } + return 0; +} + +sub usage { + print <<EOT; +usage: $P [options] patchfile + $P [options] -f file +version: $V + +MAINTAINER field selection options: + --email => print email address(es) if any + --git => include recent git \*-by: signers + --git-chief-penguins => include ${penguin_chiefs} + --git-min-signatures => number of signatures required (default: 1) + --git-max-maintainers => maximum maintainers to add (default: 5) + --git-since => git history to use (default: 1-year-ago) + --m => include maintainer(s) if any + --n => include name 'Full Name <addr\@domain.tld>' + --l => include list(s) if any + --s => include subscriber only list(s) if any + --scm => print SCM tree(s) if any + --status => print status if any + --subsystem => print subsystem name if any + --web => print website(s) if any + +Output type options: + --separator [, ] => separator for multiple entries on 1 line + --multiline => print 1 entry per line + +Default options: + [--email --git --m --l --multiline] + +Other options: + --version -> show version + --help => show this help information + +EOT +} + +sub top_of_kernel_tree { + my ($lk_path) = @_; + + if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") { + $lk_path .= "/"; + } + if ( (-f "${lk_path}COPYING") + && (-f "${lk_path}CREDITS") + && (-f "${lk_path}Kbuild") + && (-f "${lk_path}MAINTAINERS") + && (-f "${lk_path}Makefile") + && (-f "${lk_path}README") + && (-d "${lk_path}Documentation") + && (-d "${lk_path}arch") + && (-d "${lk_path}include") + && (-d "${lk_path}drivers") + && (-d "${lk_path}fs") + && (-d "${lk_path}init") + && (-d "${lk_path}ipc") + && (-d "${lk_path}kernel") + && (-d "${lk_path}lib") + && (-d "${lk_path}scripts")) { + return 1; + } + return 0; +} + +sub format_email { + my ($name, $email) = @_; + + $name =~ s/^\s+|\s+$//g; + $email =~ s/^\s+|\s+$//g; + + my $formatted_email = ""; + + if ($name =~ /[^a-z0-9 \.\-]/i) { ##has "must quote" chars + $name =~ s/(?<!\\)"/\\"/g; ##escape quotes + $formatted_email = "\"${name}\"\ \<${email}\>"; + } else { + $formatted_email = "${name} \<${email}\>"; + } + return $formatted_email; +} + +sub add_categories { + my ($index) = @_; + + $index = $index - 1; + while ($index >= 0) { + my $tv = $typevalue[$index]; + if ($tv =~ m/^(\C):(.*)/) { + my $ptype = $1; + my $pvalue = $2; + if ($ptype eq "L") { + my $subscr = $pvalue; + if ($subscr =~ m/\s*\(subscribers-only\)/) { + if ($email_subscriber_list) { + $subscr =~ s/\s*\(subscribers-only\)//g; + push(@email_to, $subscr); + } + } else { + if ($email_list) { + push(@email_to, $pvalue); + } + } + } elsif ($ptype eq "M") { + if ($email_maintainer) { + if ($index >= 0) { + my $tv = $typevalue[$index - 1]; + if ($tv =~ m/^(\C):(.*)/) { + if ($1 eq "P" && $email_usename) { + push(@email_to, format_email($2, $pvalue)); + } else { + push(@email_to, $pvalue); + } + } + } else { + push(@email_to, $pvalue); + } + } + } elsif ($ptype eq "T") { + push(@scm, $pvalue); + } elsif ($ptype eq "W") { + push(@web, $pvalue); + } elsif ($ptype eq "S") { + push(@status, $pvalue); + } + + $index--; + } else { + push(@subsystem,$tv); + $index = -1; + } + } +} + +sub which { + my ($bin) = @_; + + foreach my $path (split /:/, $ENV{PATH}) { + if (-e "$path/$bin") { + return "$path/$bin"; + } + } + + return ""; +} + +sub recent_git_signoffs { + my ($file) = @_; + + my $sign_offs = ""; + my $cmd = ""; + my $output = ""; + my $count = 0; + my @lines = (); + + if (which("git") eq "") { + die("$P: git not found. Add --nogit to options?\n"); + } + + $cmd = "git log --since=${email_git_since} -- ${file}"; + $cmd .= " | grep -Pi \"^[-_ a-z]+by:.*\\\@\""; + if (!$email_git_penguin_chiefs) { + $cmd .= " | grep -Pv \"${penguin_chiefs}\""; + } + $cmd .= " | cut -f2- -d\":\""; + $cmd .= " | sed -e \"s/^\\s+//g\""; + $cmd .= " | sort | uniq -c | sort -rn"; + + $output = `${cmd}`; + $output =~ s/^\s*//gm; + + @lines = split("\n", $output); + foreach my $line (@lines) { + if ($line =~ m/([0-9]+)\s+(.*)/) { + my $sign_offs = $1; + $line = $2; + $count++; + if ($sign_offs < $email_git_min_signatures || + $count > $email_git_max_maintainers) { + last; + } + } else { + die("$P: Unexpected git output: ${line}\n"); + } + if ($line =~ m/(.+)<(.+)>/) { + my $git_name = $1; + my $git_addr = $2; + $git_name =~ tr/^\"//; + $git_name =~ tr/^\\s*//; + $git_name =~ tr/\"$//; + $git_name =~ tr/\\s*$//; + if ($email_usename) { + push(@email_to, format_email($git_name, $git_addr)); + } else { + push(@email_to, $git_addr); + } + } elsif ($line =~ m/<(.+)>/) { + my $git_addr = $1; + push(@email_to, $git_addr); + } else { + push(@email_to, $line); + } + } + return $output; +} + +sub uniq { + my @parms = @_; + + my %saw; + @parms = grep(!$saw{$_}++, @parms); + return @parms; +} + +sub sort_and_uniq { + my @parms = @_; + + my %saw; + @parms = sort @parms; + @parms = grep(!$saw{$_}++, @parms); + return @parms; +} + +sub output { + my @parms = @_; + + if ($output_multiline) { + foreach my $line (@parms) { + print("${line}\n"); + } + } else { + print(join($output_separator, @parms)); + print("\n"); + } +} diff --git a/scripts/headerdep.pl b/scripts/headerdep.pl index 97399da89ef..b7f6c560e24 100755 --- a/scripts/headerdep.pl +++ b/scripts/headerdep.pl @@ -19,7 +19,7 @@ my $opt_graph; version => \&version, all => \$opt_all, - I => \@opt_include, + "I=s" => \@opt_include, graph => \$opt_graph, ); diff --git a/scripts/kconfig/kxgettext.c b/scripts/kconfig/kxgettext.c index 6eb72a7f256..8d9ce22b0fc 100644 --- a/scripts/kconfig/kxgettext.c +++ b/scripts/kconfig/kxgettext.c @@ -43,6 +43,10 @@ static char *escape(const char* text, char *bf, int len) ++text; goto next; } + else if (*text == '\\') { + *bfp++ = '\\'; + len--; + } *bfp++ = *text++; next: --len; diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 8cc70612984..df6e6286a06 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1913,7 +1913,7 @@ static void read_dump(const char *fname, unsigned int kernel) if (!mod) { if (is_vmlinux(modname)) have_vmlinux = 1; - mod = new_module(NOFAIL(strdup(modname))); + mod = new_module(modname); mod->skip = 1; } s = sym_add_exported(symname, mod, export_no(export)); @@ -1997,7 +1997,7 @@ static void read_markers(const char *fname) mod = find_module(modname); if (!mod) { - mod = new_module(NOFAIL(strdup(modname))); + mod = new_module(modname); mod->skip = 1; } if (is_vmlinux(modname)) { diff --git a/scripts/setlocalversion b/scripts/setlocalversion index f1c4b35bc32..47e75b69a2e 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -21,7 +21,7 @@ if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then # Is this git on svn? if git config --get svn-remote.svn.url >/dev/null; then - printf -- '-svn%s' "`git-svn find-rev $head`" + printf -- '-svn%s' "`git svn find-rev $head`" fi # Are there uncommitted changes? diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index a0affd9cfca..d4d41b3efc7 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -5,7 +5,7 @@ * * Copyright (C) 2005-2009 NTT DATA CORPORATION * - * Version: 2.2.0-pre 2009/02/01 + * Version: 2.2.0 2009/04/01 * */ @@ -1773,7 +1773,7 @@ void tomoyo_load_policy(const char *filename) envp[2] = NULL; call_usermodehelper(argv[0], argv, envp, 1); - printk(KERN_INFO "TOMOYO: 2.2.0-pre 2009/02/01\n"); + printk(KERN_INFO "TOMOYO: 2.2.0 2009/04/01\n"); printk(KERN_INFO "Mandatory Access Control activated.\n"); tomoyo_policy_loaded = true; { /* Check all profiles currently assigned to domains are defined. */ @@ -1800,7 +1800,7 @@ void tomoyo_load_policy(const char *filename) static int tomoyo_read_version(struct tomoyo_io_buffer *head) { if (!head->read_eof) { - tomoyo_io_printf(head, "2.2.0-pre"); + tomoyo_io_printf(head, "2.2.0"); head->read_eof = true; } return 0; diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index e77e6a6de0f..678f4ff16aa 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -5,7 +5,7 @@ * * Copyright (C) 2005-2009 NTT DATA CORPORATION * - * Version: 2.2.0-pre 2009/02/01 + * Version: 2.2.0 2009/04/01 * */ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 2f2b449ffd2..2d6748741a2 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -5,7 +5,7 @@ * * Copyright (C) 2005-2009 NTT DATA CORPORATION * - * Version: 2.2.0-pre 2009/02/01 + * Version: 2.2.0 2009/04/01 * */ diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 65f50c1c5ee..2316da8ec5b 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -5,7 +5,7 @@ * * Copyright (C) 2005-2009 NTT DATA CORPORATION * - * Version: 2.2.0-pre 2009/02/01 + * Version: 2.2.0 2009/04/01 * */ diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 3bbe01a7a4b..bf8e2b45168 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -5,7 +5,7 @@ * * Copyright (C) 2005-2009 NTT DATA CORPORATION * - * Version: 2.2.0-pre 2009/02/01 + * Version: 2.2.0 2009/04/01 * */ diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h index 7ec9fc9cbc0..78217a37960 100644 --- a/security/tomoyo/realpath.h +++ b/security/tomoyo/realpath.h @@ -5,7 +5,7 @@ * * Copyright (C) 2005-2009 NTT DATA CORPORATION * - * Version: 2.2.0-pre 2009/02/01 + * Version: 2.2.0 2009/04/01 * */ diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 3eeeae12c4d..5b481912752 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -5,7 +5,7 @@ * * Copyright (C) 2005-2009 NTT DATA CORPORATION * - * Version: 2.2.0-pre 2009/02/01 + * Version: 2.2.0 2009/04/01 * */ diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h index a0c8f6e0bea..41c6ebafb9c 100644 --- a/security/tomoyo/tomoyo.h +++ b/security/tomoyo/tomoyo.h @@ -5,7 +5,7 @@ * * Copyright (C) 2005-2009 NTT DATA CORPORATION * - * Version: 2.2.0-pre 2009/02/01 + * Version: 2.2.0 2009/04/01 * */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 30829ee920c..7ba8db5d4c4 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2260,11 +2260,11 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, gcap &= ~0x01; /* allow 64bit DMA address if supported by H/W */ - if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK)) - pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK); + if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) + pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64)); else { - pci_set_dma_mask(pci, DMA_32BIT_MASK); - pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK); + pci_set_dma_mask(pci, DMA_BIT_MASK(32)); + pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32)); } /* read number of streams from GCAP register instead of using |