diff options
| author | Linus Torvalds <torvalds@home.osdl.org> | 2003-09-21 03:55:14 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-09-21 03:55:14 -0700 |
| commit | aad00662730e31461c6fffe493aef04a87d97d49 (patch) | |
| tree | e990baf40baf7e4635b07ac99f0142ff0fb45d9f | |
| parent | 9715e1df131ec4028e03d6f55fb22d935ee8b972 (diff) | |
| parent | 13cfaf50971b1e8f81d3b704e7ec62ce5ad42e1a (diff) | |
Merge bk://linux-pnp.bkbits.net/pnp-2.5
into home.osdl.org:/home/torvalds/v2.5/linux
236 files changed, 3586 insertions, 2246 deletions
diff --git a/Documentation/Changes b/Documentation/Changes index 6c3d414df1f5..458086bd7f04 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -52,7 +52,7 @@ o Gnu C 2.95.3 # gcc --version o Gnu make 3.78 # make --version o binutils 2.12 # ld -v o util-linux 2.10o # fdformat --version -o module-init-tools 0.9.9 # depmod -V +o module-init-tools 0.9.10 # depmod -V o e2fsprogs 1.29 # tune2fs o jfsutils 1.1.3 # fsck.jfs -V o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 4be777cf91a9..13691ba9967d 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -6,6 +6,8 @@ Notes Written on Jan 15, 2002: Suparna Bhattacharya <suparna@in.ibm.com> Last Updated May 2, 2002 +September 2003: Updated I/O Scheduler portions + Nick Piggin <piggin@cyberone.com.au> Introduction: @@ -220,42 +222,8 @@ i/o scheduling algorithm aspects and details outside of the generic loop. It also makes it possible to completely hide the implementation details of the i/o scheduler from block drivers. -New routines to be used instead of accessing the queue directly: - -elv_add_request: Should be called to queue a request -elv_next_request: Should be called to pull of the next request to be serviced - of the queue. It takes care of several things like skipping active requests, - invoking the command pre-builder etc. - -Some new plugins: -e->elevator_next_req_fn - Plugin called to extract the next request to service from the - queue -e->elevator_add_req_fn - Plugin called to add a new request to the queue -e->elevator_init_fn - Plugin called when initializing the queue -e->elevator_exit_fn - Plugin called when destrying the queue - -Elevator Linus and Elevator noop are the existing combinations that can be -directly used, but a driver can provide relevant callbacks, in case -it needs to do something different. - -Elevator noop only attempts to merge requests, but doesn't reorder (sort) -them. Even merging requires a linear scan today (except for the last merged -hint case discussed later) though, which takes take up some CPU cycles. - -[Note: Merging usually helps in general, because there's usually non-trivial -command overhead associated with setting up and starting a command. Sorting, -on the other hand, may not be relevant for intelligent devices that reorder -requests anyway] - -Elevator Linus attempts merging as well as sorting of requests on the queue. -The sorting happens via an insert scan whenever a request comes in. -Often some sorting still makes sense as the depth which most hardware can -handle may be less than the queue lengths during i/o loads. - +I/O scheduler wrappers are to be used instead of accessing the queue directly. +See section 4. The I/O scheduler for details. 1.2 Tuning Based on High level code capabilities @@ -317,32 +285,6 @@ Arjan's proposed request priority scheme allows higher levels some broad requests. Some bits in the bi_rw flags field in the bio structure are intended to be used for this priority information. - Jens has an implementation of a simple deadline i/o scheduler that - makes a best effort attempt to start requests within a given expiry - time limit, along with trying to optimize disk seeks as in the current - elevator. It does this by sorting a request on two lists, one by - the deadline and one by the sector order. It employs a policy that - follows sector ordering as long as a deadline is not violated, and - tries to keep up with deadlines in so far as it can batch up to at - least a certain minimum number of sector ordered requests to reduce - arbitrary disk seeks. This implementation is constructed in a way - that makes it possible to support advanced compound i/o schedulers - as a combination of several low level schedulers with an overall - class-independent scheduler layered above. - -The current elevator scheme provides a latency bound over how many future -requests can "pass" (get placed before) a given request, and this bound -is determined by the request type (read, write). However, it doesn't -prioritize a new request over existing requests in the queue based on its -latency requirement. A new request could of course get serviced before -earlier requests based on the position on disk which it accesses. This is -due to the sort/merge in the basic elevator scan logic, but irrespective -of the request's own priority/latency value. Interestingly the elevator -sequence or the latency bound setting of the new request is unaffected by the -number of existing requests it has passed, i.e. doesn't depend on where -it is positioned in the queue, but only on the number of requests that pass -it in the future. - 1.3 Direct Access to Low level Device/Driver Capabilities (Bypass mode) (e.g Diagnostics, Systems Management) @@ -964,7 +906,74 @@ Aside: 4. The I/O scheduler - +I/O schedulers are now per queue. They should be runtime switchable and modular +but aren't yet. Jens has most bits to do this, but the sysfs implementation is +missing. + +A block layer call to the i/o scheduler follows the convention elv_xxx(). This +calls elevator_xxx_fn in the elevator switch (drivers/block/elevator.c). Oh, +xxx and xxx might not match exactly, but use your imagination. If an elevator +doesn't implement a function, the switch does nothing or some minimal house +keeping work. + +4.1. I/O scheduler API + +The functions an elevator may implement are: (* are mandatory) +elevator_merge_fn called to query requests for merge with a bio + +elevator_merge_req_fn " " " with another request + +elevator_merged_fn called when a request in the scheduler has been + involved in a merge. It is used in the deadline + scheduler for example, to reposition the request + if its sorting order has changed. + +*elevator_next_req_fn returns the next scheduled request, or NULL + if there are none (or none are ready). + +*elevator_add_req_fn called to add a new request into the scheduler + +elevator_queue_empty_fn returns true if the merge queue is empty. + Drivers shouldn't use this, but rather check + if elv_next_request is NULL (without losing the + request if one exists!) + +elevator_remove_req_fn This is called when a driver claims ownership of + the target request - it now belongs to the + driver. It must not be modified or merged. + Drivers must not lose the request! A subsequent + call of elevator_next_req_fn must return the + _next_ request. + +elevator_requeue_req_fn called to add a request to the scheduler. This + is used when the request has alrnadebeen + returned by elv_next_request, but hasn't + completed. If this is not implemented then + elevator_add_req_fn is called instead. + +elevator_former_req_fn +elevator_latter_req_fn These return the request before or after the + one specified in disk sort order. Used by the + block layer to find merge possibilities. + +elevator_completed_req_fn called when a request is completed. This might + come about due to being merged with another or + when the device completes the request. + +elevator_may_queue_fn returns true if the scheduler wants to allow the + current context to queue a new request even if + it is over the queue limit. This must be used + very carefully!! + +elevator_set_req_fn +elevator_put_req_fn Must be used to allocate and free any elevator + specific storate for a request. + +elevator_init_fn +elevator_exit_fn Allocate and free any elevator specific storage + for a queue. + +4.2 I/O scheduler implementation The generic i/o scheduler algorithm attempts to sort/merge/batch requests for optimal disk scan and request servicing performance (based on generic principles and device capabilities), optimized for: @@ -974,49 +983,58 @@ iii. better utilization of h/w & CPU time Characteristics: -i. Linked list for O(n) insert/merge (linear scan) right now - -This is just the same as it was in 2.4. +i. Binary tree +AS and deadline i/o schedulers use red black binary trees for disk position +sorting and searching, and a fifo linked list for time-based searching. This +gives good scalability and good availablility of information. Requests are +almost always dispatched in disk sort order, so a cache is kept of the next +request in sort order to prevent binary tree lookups. -There is however an added level of abstraction in the operations for adding -and extracting a request to/from the queue, which makes it possible to -try out alternative queue structures without changes to the users of the queue. -Some things like head-active are thus now handled within elv_next_request -making it possible to mark more than one request to be left alone. +This arrangement is not a generic block layer characteristic however, so +elevators may implement queues as they please. -Aside: -1. The use of a merge hash was explored to reduce merge times and to make - elevator_noop close to noop by avoiding the scan for merge. However the - complexity and locking issues introduced wasn't desirable especially as - with multi-page bios the incidence of merges is expected to be lower. -2. The use of binomial/fibonacci heaps was explored to reduce the scan time; - however the idea was given up due to the complexity and added weight of - data structures, complications for handling barriers, as well as the - advantage of O(1) extraction and deletion (performance critical path) with - the existing list implementation vs heap based implementations. +ii. Last merge hint +The last merge hint is part of the generic queue layer. I/O schedulers must do +some management on it. For the most part, the most important thing is to make +sure q->last_merge is cleared (set to NULL) when the request on it is no longer +a candidate for merging (for example if it has been sent to the driver). -ii. Utilizes max_phys/hw_segments, and max_request_size parameters, to merge - within the limits that the device can handle (See 3.2.2) +The last merge performed is cached as a hint for the subsequent request. If +sequential data is being submitted, the hint is used to perform merges without +any scanning. This is not sufficient when there are multiple processes doing +I/O though, so a "merge hash" is used by some schedulers. -iii. Last merge hint +iii. Merge hash +AS and deadline use a hash table indexed by the last sector of a request. This +enables merging code to quickly look up "back merge" candidates, even when +multiple I/O streams are being performed at once on one disk. -In 2.5, information about the last merge is saved as a hint for the subsequent -request. This way, if sequential data is coming down the pipe, the hint can -be used to speed up merges without going through a scan. +"Front merges", a new request being merged at the front of an existing request, +are far less common than "back merges" due to the nature of most I/O patterns. +Front merges are handled by the binary trees in AS and deadline schedulers. iv. Handling barrier cases - -As mentioned earlier, barrier support is new to 2.5, and the i/o scheduler -has been modified accordingly. - -When a barrier comes in, then since insert happens in the form of a -linear scan, starting from the end, it just needs to be ensured that this -and future scans stops barrier point. This is achieved by skipping the -entire merge/scan logic for a barrier request, so it gets placed at the -end of the queue, and specifying a zero latency for the request containing -the bio so that no future requests can pass it. - -v. Plugging the queue to batch requests in anticipation of opportunities for +A request with flags REQ_HARDBARRIER or REQ_SOFTBARRIER must not be ordered +around. That is, they must be processed after all older requests, and before +any newer ones. This includes merges! + +In AS and deadline schedulers, barriers have the effect of flushing the reorder +queue. The performance cost of this will vary from nothing to a lot depending +on i/o patterns and device characteristics. Obviously they won't improve +performance, so their use should be kept to a minimum. + +v. Handling insertion position directives +A request may be inserted with a position directive. The directives are one of +ELEVATOR_INSERT_BACK, ELEVATOR_INSERT_FRONT, ELEVATOR_INSERT_SORT. + +ELEVATOR_INSERT_SORT is a general directive for non-barrier requests. +ELEVATOR_INSERT_BACK is used to insert a barrier to the back of the queue. +ELEVATOR_INSERT_FRONT is used to insert a barrier to the front of the queue, and +overrides the ordering requested by any previous barriers. In practice this is +harmless and required, because it is used for SCSI requeueing. This does not +require flushing the reorder queue, so does not impose a performance penalty. + +vi. Plugging the queue to batch requests in anticipation of opportunities for merge/sort optimizations This is just the same as in 2.4 so far, though per-device unplugging @@ -1051,6 +1069,12 @@ Aside: blk_kick_queue() to unplug a specific queue (right away ?) or optionally, all queues, is in the plan. +4.3 I/O contexts +I/O contexts provide a dynamically allocated per process data area. They may +be used in I/O schedulers, and in the block layer (could be used for IO statis, +priorities for example). See *io_context in drivers/block/ll_rw_blk.c, and +as-iosched.c for an example of usage in an i/o scheduler. + 5. Scalability related changes diff --git a/Documentation/smp.tex b/Documentation/smp.tex deleted file mode 100644 index 40e73fe6ea43..000000000000 --- a/Documentation/smp.tex +++ /dev/null @@ -1,346 +0,0 @@ -From: michael@Physik.Uni-Dortmund.DE (Michael Dirkmann) - -thanks for your information. Attached is the tex-code of your -SMP-documentation : --=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -\documentclass[]{article} -\parindent0.0cm -\parskip0.2cm - -\begin{document} - -\begin{center} -\LARGE \bf -An Implementation Of Multiprocessor Linux -\normalsize -\end{center} - -{ \it -This document describes the implementation of a simple SMP -Linux kernel extension and how to use this to develop SMP Linux kernels for -architectures other than the Intel MP v1.1 architecture for Pentium and 486 -processors.} - -\hfill Alan Cox, 1995 - - -The author wishes to thank Caldera Inc. ( http://www.caldera.com ) -whose donation of an ASUS dual Pentium board made this project possible, -and Thomas Radke, whose initial work on multiprocessor Linux formed -the backbone of this project. - -\section{Background: The Intel MP specification.} -Most IBM PC style multiprocessor motherboards combine Intel 486 or Pentium -processors and glue chipsets with a hardware/software specification. The -specification places much of the onus for hard work on the chipset and -hardware rather than the operating system. - -The Intel Pentium processors have a wide variety of inbuilt facilities for -supporting multiprocessing, including hardware cache coherency, built in -interprocessor interrupt handling and a set of atomic test and set, -exchange and similar operations. The cache coherency in particular makes the -operating system's job far easier. - -The specification defines a detailed configuration structure in ROM that -the boot up processor can read to find the full configuration of the -processors and buses. It also defines a procedure for starting up the -other processors. - - -\section{Mutual Exclusion Within A Single Processor Linux Kernel} -For any kernel to function in a sane manner it has to provide internal -locking and protection of its own tables to prevent two processes updating -them at once and for example allocating the same memory block. There are -two strategies for this within current Unix and Unixlike kernels. -Traditional Unix systems from the earliest of days use a scheme of 'Coarse -Grained Locking' where the entire kernel is protected by a small number of -locks only. Some modern systems use fine grained locking. Because fine -grained locking has more overhead it is normally used only on -multiprocessor kernels and real time kernels. In a real time kernel the -fine grained locking reduces the amount of time locks are held and reduces -the critical (to real time programming at least) latency times. - -Within the Linux kernel certain guarantees are made. No process running in -kernel mode will be pre-empted by another kernel mode process unless it -voluntarily sleeps. This ensures that blocks of kernel code are -effectively atomic with respect to other processes and greatly simplifies -many operations. Secondly interrupts may pre-empt a kernel running process, -but will always return to that process. A process in kernel mode may -disable interrupts on the processor and guarantee such an interruption will -not occur. The final guarantee is that an interrupt will not be pre-empted -by a kernel task. That is interrupts will run to completion or be -pre-empted by other interrupts only. - -The SMP kernel chooses to continue these basic guarantees in order to make -initial implementation and deployment easier. A single lock is maintained -across all processors. This lock is required to access the kernel space. -Any processor may hold it and once it is held may also re-enter the kernel -for interrupts and other services whenever it likes until the lock is -relinquished. This lock ensures that a kernel mode process will not be -pre-empted and ensures that blocking interrupts in kernel mode behaves -correctly. This is guaranteed because only the processor holding the lock -can be in kernel mode, only kernel mode processes can disable interrupts -and only the processor holding the lock may handle an interrupt. - -Such a choice is however poor for performance. In the longer term it is -necessary to move to finer grained parallelism in order to get the best -system performance. This can be done hierarchically by gradually refining -the locks to cover smaller areas. With the current kernel highly CPU bound -process sets perform well but I/O bound task sets can easily degenerate to -near single processor performance levels. This refinement will be needed to -get the best from Linux/SMP. - -\subsection{Changes To The Portable Kernel Components} -The kernel changes are split into generic SMP support changes and -architecture specific changes necessary to accommodate each different -processor type Linux is ported to. - - -\subsubsection{Initialisation} -The first problem with a multiprocessor kernel is starting the other -processors up. Linux/SMP defines that a single processor enters the normal -kernel entry point start\_kernel(). Other processors are assumed not to be -started or to have been captured elsewhere. The first processor begins the -normal Linux initialisation sequences and sets up paging, interrupts and -trap handlers. After it has obtained the processor information about the -boot CPU, the architecture specific function - - -{\tt \bf{void smp\_store\_cpu\_info(int processor\_id) }} - -is called to store any information about the processor into a per processor -array. This includes things like the bogomips speed ratings. - -Having completed the kernel initialisation the architecture specific -function - -{\tt \bf void smp\_boot\_cpus(void) } - -is called and is expected to start up each other processor and cause it to -enter start\_kernel() with its paging registers and other control -information correctly loaded. Each other processor skips the setup except -for calling the trap and irq initialisation functions that are needed on -some processors to set each CPU up correctly. These functions will -probably need to be modified in existing kernels to cope with this. - - -Each additional CPU then calls the architecture specific function - -{\tt \bf void smp\_callin(void)} - -which does any final setup and then spins the processor while the boot -up processor forks off enough idle threads for each processor. This is -necessary because the scheduler assumes there is always something to run. -Having generated these threads and forked init the architecture specific - -{\tt \bf void smp\_commence(void)} - -function is invoked. This does any final setup and indicates to the system -that multiprocessor mode is now active. All the processors spinning in the -smp\_callin() function are now released to run the idle processes, which -they will run when they have no real work to process. - - -\subsubsection{Scheduling} -The kernel scheduler implements a simple but very effective task -scheduler. The basic structure of this scheduler is unchanged in the -multiprocessor kernel. A processor field is added to each task, and this -maintains the number of the processor executing a given task, or a magic -constant (NO\_PROC\_ID) indicating the job is not allocated to a processor. - -Each processor executes the scheduler itself and will select the next task -to run from all runnable processes not allocated to a different processor. -The algorithm used by the selection is otherwise unchanged. This is -actually inadequate for the final system because there are advantages to -keeping a process on the same CPU, especially on processor boards with per -processor second level caches. - -Throughout the kernel the variable 'current' is used as a global for the -current process. In Linux/SMP this becomes a macro which expands to -current\_set[smp\_processor\_id()]. This enables almost the entire kernel to -be unaware of the array of running processors, but still allows the SMP -aware kernel modules to see all of the running processes. - -The fork system call is modified to generate multiple processes with a -process id of zero until the SMP kernel starts up properly. This is -necessary because process number 1 must be init, and it is desirable that -all the system threads are process 0. - -The final area within the scheduling of processes that does cause problems -is the fact the uniprocessor kernel hard codes tests for the idle threads -as task[0] and the init process as task[1]. Because there are multiple idle -threads it is necessary to replace these with tests that the process id is -0 and a search for process ID 1, respectively. - -\subsubsection{Memory Management} -The memory management core of the existing Linux system functions -adequately within the multiprocessor framework providing the locking is -used. Certain processor specific areas do need changing, in particular -invalidate() must invalidate the TLBs of all processors before it returns. - - -\subsubsection{Miscellaneous Functions} -The portable SMP code rests on a small set of functions and variables -that are provided by the processor specification functionality. These are - -{\tt \bf int smp\_processor\_id(void) } - -which returns the identity of the processor the call is executed upon. This -call is assumed to be valid at all times. This may mean additional tests -are needed during initialisation. - - -{\tt \bf int smp\_num\_cpus;} - -This is the number of processors in the system. \ - -{\tt \bf void smp\_message\_pass(int target, int msg, unsigned long data, - int wait)} - -This function passes messages between processors. At the moment it is not -sufficiently defined to sensibly document and needs cleaning up and further -work. Refer to the processor specific code documentation for more details. - - -\subsection{Architecture Specific Code For the Intel MP Port} -The architecture specific code for the Intel port splits fairly cleanly -into four sections. Firstly the initialisation code used to boot the -system, secondly the message handling and support code, thirdly the -interrupt and kernel syscall entry function handling and finally the -extensions to standard kernel facilities to cope with multiple processors. - -\subsubsection{Initialisation} -The Intel MP architecture captures all the processors except for a single -processor known as the 'boot processor' in the BIOS at boot time. Thus a -single processor enters the kernel bootup code. The first processor -executes the bootstrap code, loads and uncompresses the kernel. Having -unpacked the kernel it sets up the paging and control registers then enters -the C kernel startup. - -The assembler startup code for the kernel is modified so that it can be -used by the other processors to do the processor identification and various -other low level configurations but does not execute those parts of the -startup code that would damage the running system (such as clearing the BSS -segment). - -In the initialisation done by the first processor the arch/i386/mm/init -code is modified to scan the low page, top page and BIOS for intel MP -signature blocks. This is necessary because the MP signature blocks must -be read and processed before the kernel is allowed to allocate and destroy -the page at the top of low memory. Having established the number of -processors it reserves a set of pages to provide a stack come boot up area -for each processor in the system. These must be allocated at startup to -ensure they fall below the 1Mb boundary. - -Further processors are started up in smp\_boot\_cpus() by programming the -APIC controller registers and sending an inter-processor interrupt (IPI) to -the processor. This message causes the target processor to begin executing -code at the start of any page of memory within the lowest 1Mb, in 16bit -real mode. The kernel uses the single page it allocated for each processor -to use as stack. Before booting a given CPU the relocatable code from -trampoline.S and trampoline32.S is copied to the bottom of its stack page -and used as the target for the startup. - -The trampoline code calculates the desired stack base from the code -segment (since the code segment on startup is the bottom of the stack), - enters 32bit mode and jumps to the kernel entry assembler. This as -described above is modified to only execute the parts necessary for each -processor, and then to enter start\_kernel(). On entering the kernel the -processor initialises its trap and interrupt handlers before entering -smp\_callin(), where it reports its status and sets a flag that causes the -boot processor to continue and look for further processors. The processor -then spins until smp\_commence() is invoked. - -Having started each processor up the smp\_commence( ) function flips a -flag. Each processor spinning in smp\_callin() then loads the task register -with the task state segment (TSS) of its idle thread as is needed for task -switching. - -\subsubsection{Message Handling and Support Code} -The architecture specific code implements the smp\_processor\_id() function -by querying the APIC logical identity register. Because the APIC isn't -mapped into the kernel address space at boot, the initial value returned is -rigged by setting the APIC base pointer to point at a suitable constant. -Once the system starts doing the SMP setup (in smp\_boot\_cpus()), the APIC -is mapped with a vremap() call and the apic pointer is adjusted -appropriately. From then on the real APIC logical identity register is -read. - -Message passing is accomplished using a pair of IPIs on interrupt 13 -(unused by the 80486 FPUs in SMP mode) and interrupt 16. Two are used in -order to separate messages that cannot be processed until the receiver -obtains the kernel spinlock from messages that can be processed -immediately. In effect IRQ 13 is a fast IRQ handler that does not obtain -the locks, and cannot cause a reschedule, while IRQ 16 is a slow IRQ that -must acquire the kernel spinlocks and can cause a reschedule. This -interrupt is used for passing on slave timer messages from the processor -that receives the timer interrupt to the rest of the processors, so that -they can reschedule running tasks. - - -\subsubsection{Entry And Exit Code} -A single spinlock protects the entire kernel. The interrupt handlers, the -syscall entry code and the exception handlers all acquire the lock before -entering the kernel proper. When the processor is trying to acquire the -spinlock it spins continually on the lock with interrupts disabled. This -causes a specific deadlock problem. The lock owner may need to send an -invalidate request to the rest of the processors and wait for these to -complete before continuing. A processor spinning on the lock would not be -able to do this. Thus the loop of the spinlock tests and handles invalidate -requests. If the invalidate bit for the spinning CPU is set the processor -invalidates its TLB and atomically clears the bit. When the spinlock is -obtained that processor will take an IPI and in the IPI test the bit and -skip the invalidate as the bit is clear. - -One complexity of the spinlock is that a process running in kernel mode -can sleep voluntarily and be pre-empted. A switch from such a process to a -process executing in user space may reduce the lock count. To track this -the kernel uses a syscall\_count and a per process lock\_depth parameter to -track the kernel lock state. The switch\_to() function is modified in SMP -mode to adjust the lock appropriately. - -The final problem is the idle thread. In the single processor kernel the -idle thread executes 'hlt' instructions. This saves power and reduces the -running temperature of the processors when they are idle. However it means -the process spends all its time in kernel mode and would thus hold the -kernel spinlock. The SMP idle thread continually reschedules a new task and -returns to user mode. This is far from ideal and will be modified to use -'hlt' instructions and release the spinlock soon. Using 'hlt' is even more -beneficial on a multiprocessor system as it almost completely takes an idle -processor off the bus. - -Interrupts are distributed by an i82489 APIC. This chip is set up to work -as an emulation of the traditional PC interrupt controllers when the -machine boots (so that an Intel MP machine boots one CPU and PC -compatible). The kernel has all the relevant locks but does not yet -reprogram the 82489 to deliver interrupts to arbitrary processors as it -should. This requires further modification of the standard Linux interrupt -handling code, and is particularly messy as the interrupt handler behaviour -has to change as soon as the 82489 is switched into SMP mode. - - -\subsubsection{Extensions To Standard Facilities} -The kernel maintains a set of per processor control information such as -the speed of the processor for delay loops. These functions on the SMP -kernel look the values up in a per processor array that is set up from the -data generated at boot up by the smp\_store\_cpu\_info() function. This -includes other facts such as whether there is an FPU on the processor. The -current kernel does not handle floating point correctly, this requires some -changes to the techniques the single CPU kernel uses to minimise floating -point processor reloads. - -The highly useful atomic bit operations are prefixed with the 'lock' -prefix in the SMP kernel to maintain their atomic properties when used -outside of (and by) the spinlock and message code. Amongst other things -this is needed for the invalidate handler, as all CPU's will invalidate at -the same time without any locks. - -Interrupt 13 floating point error reporting is removed. This facility is -not usable on a multiprocessor board, nor relevant to the Intel MP -architecture which does not cover the 80386/80387 processor pair. \ - -The /proc filesystem support is changed so that the /proc/cpuinfo file -contains a column for each processor present. This information is extracted -from the data saved by smp\_store\_cpu\_info(). - -\end{document} diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran index 089143f5c4a1..d8c4d428d627 100644 --- a/Documentation/video4linux/Zoran +++ b/Documentation/video4linux/Zoran @@ -28,7 +28,7 @@ Iomega Buz: * Philips saa7111 TV decoder * Philips saa7185 TV encoder Drivers to use: videodev, i2c-core, i2c-algo-bit, - videocodec, saa7111, saa7185, zr36060, zoran + videocodec, saa7111, saa7185, zr36060, zr36067 Inputs/outputs: Composite and S-video Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) Card number: 7 @@ -39,7 +39,7 @@ Linux Media Labs LML33: * Brooktree bt819 TV decoder * Brooktree bt856 TV encoder Drivers to use: videodev, i2c-core, i2c-algo-bit, - videocodec, bt819, bt856, zr36060, zoran + videocodec, bt819, bt856, zr36060, zr36067 Inputs/outputs: Composite and S-video Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) Card number: 5 @@ -50,7 +50,7 @@ Linux Media Labs LML33R10: * Philips saa7114 TV decoder * Analog Devices adv7170 TV encoder Drivers to use: videodev, i2c-core, i2c-algo-bit, - videocodec, saa7114, adv7170, zr36060, zoran + videocodec, saa7114, adv7170, zr36060, zr36067 Inputs/outputs: Composite and S-video Norms: PAL (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps) Card number: 6 @@ -61,7 +61,7 @@ Pinnacle/Miro DC10(new): * Philips saa7110a TV decoder * Analog Devices adv7176 TV encoder Drivers to use: videodev, i2c-core, i2c-algo-bit, - videocodec, saa7110, adv7175, zr36060, zoran + videocodec, saa7110, adv7175, zr36060, zr36067 Inputs/outputs: Composite, S-video and Internal Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) Card number: 1 @@ -72,7 +72,7 @@ Pinnacle/Miro DC10+: * Philips saa7110a TV decoder * Analog Devices adv7176 TV encoder Drivers to use: videodev, i2c-core, i2c-algo-bit, - videocodec, sa7110, adv7175, zr36060, zoran + videocodec, sa7110, adv7175, zr36060, zr36067 Inputs/outputs: Composite, S-video and Internal Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) Card number: 2 @@ -84,7 +84,7 @@ Pinnacle/Miro DC10(old): * * Micronas vpx3220a TV decoder * mse3000 TV encoder or Analog Devices adv7176 TV encoder * Drivers to use: videodev, i2c-core, i2c-algo-bit, - videocodec, vpx3220, mse3000/adv7175, zr36050, zr36016, zoran + videocodec, vpx3220, mse3000/adv7175, zr36050, zr36016, zr36067 Inputs/outputs: Composite, S-video and Internal Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) Card number: 0 @@ -96,7 +96,7 @@ Pinnacle/Miro DC30: * * Micronas vpx3225d/vpx3220a/vpx3216b TV decoder * Analog Devices adv7176 TV encoder Drivers to use: videodev, i2c-core, i2c-algo-bit, - videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36016, zoran + videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36016, zr36067 Inputs/outputs: Composite, S-video and Internal Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) Card number: 3 @@ -108,7 +108,7 @@ Pinnacle/Miro DC30+: * * Micronas vpx3225d/vpx3220a/vpx3216b TV decoder * Analog Devices adv7176 TV encoder Drivers to use: videodev, i2c-core, i2c-algo-bit, - videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36015, zoran + videocodec, vpx3220/vpx3224, adv7175, zr36050, zr36015, zr36067 Inputs/outputs: Composite, S-video and Internal Norms: PAL, SECAM (768x576 @ 25 fps), NTSC (640x480 @ 29.97 fps) Card number: 4 @@ -229,16 +229,16 @@ to generate PAL N, maybe it would work if you use the PAL M settings. 2. How do I get this damn thing to work -Load zoran.o. If it can't autodetect your card, use the card=X insmod +Load zr36067.o. If it can't autodetect your card, use the card=X insmod option with X being the card number as given in the previous section. To have more than one card, use card=X1[,X2[,X3,[X4[..]]]] To automate this, add the following to your /etc/modules.conf: -options zoran card=X1[,X2[,X3[,X4[..]]]] -alias char-major-81-0 zoran +options zr36067 card=X1[,X2[,X3[,X4[..]]]] +alias char-major-81-0 zr36067 -One thing to keep in mind is that this doesn't load zoran.o itself yet. It +One thing to keep in mind is that this doesn't load zr36067.o itself yet. It just automates loading. If you start using xawtv, the device won't load on some systems, since you're trying to load modules as a user, which is not allowed ("permission denied"). A quick workaround is to add 'Load "v4l"' to @@ -500,7 +500,7 @@ proven by the Buz. 7. It hangs/crashes/fails/whatevers! Help! Make sure that the card has its own interrupts (see /proc/interrupts), check -the output of dmesg at high verbosity (load zoran.o/zr36067.o with debug=2, +the output of dmesg at high verbosity (load zr36067.o with debug=2, load all other modules with debug=1). Check that your mainboard is favorable (see question 2) and if not, test the card in another computer. Also see the notes given in question 3 and try lowering quality/buffersize/capturesize diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 7bc6ed87ba2b..d2dd8ae7834f 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -14,6 +14,7 @@ * All initialization functions provided here are intended to be called * from machine specific code with proper arguments when required. */ +#include <linux/config.h> #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index fdd6bcdd951d..49562ecdf365 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -10,8 +10,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ - -#include <linux/config.h> #include <linux/sched.h> #include <linux/mm.h> diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c index cadc229f8553..6241a43df292 100644 --- a/arch/arm/kernel/fiq.c +++ b/arch/arm/kernel/fiq.c @@ -35,7 +35,6 @@ * - enables FIQ. * 6. Goto 3 */ -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/mm.h> diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 8cded6988447..4a4532e91896 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -312,8 +312,8 @@ void release_thread(struct task_struct *dead_task) asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); int -copy_thread(int nr, unsigned long clone_flags, unsigned long esp, - unsigned long unused, struct task_struct *p, struct pt_regs *regs) +copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, + unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs) { struct thread_info *thread = p->thread_info; struct pt_regs *childregs; @@ -321,7 +321,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long esp, childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_SIZE - 8)) - 1; *childregs = *regs; childregs->ARM_r0 = 0; - childregs->ARM_sp = esp; + childregs->ARM_sp = stack_start; memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); thread->cpu_context.sp = (unsigned long)childregs; @@ -373,33 +373,35 @@ void dump_thread(struct pt_regs * regs, struct user * dump) } /* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be free'd until both the parent and the child have exited. + * Shuffle the argument into the correct register before calling the + * thread function. r1 is the thread argument, r2 is the pointer to + * the thread function, and r3 points to the exit function. + */ +extern void kernel_thread_helper(void); +asm( ".align\n" +" .type kernel_thread_helper, #function\n" +"kernel_thread_helper:\n" +" mov r0, r1\n" +" mov lr, r3\n" +" mov pc, r2\n" +" .size kernel_thread_helper, . - kernel_thread_helper"); + +/* + * Create a kernel thread. */ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) { - register unsigned int r0 asm("r0") = flags | CLONE_VM | CLONE_UNTRACED; - register unsigned int r1 asm("r1") = 0; - register pid_t __ret asm("r0"); - - __asm__ __volatile__( - __syscall(clone)" @ kernel_thread sys_clone \n\ - movs %0, r0 @ if we are the child \n\ - bne 1f \n\ - mov fp, #0 @ ensure that fp is zero \n\ - mov r0, %4 \n\ - mov lr, pc \n\ - mov pc, %3 \n\ - b sys_exit \n\ -1: " - : "=r" (__ret) - : "0" (r0), "r" (r1), "r" (fn), "r" (arg) - : "lr"); - return __ret; + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + + regs.ARM_r1 = (unsigned long)arg; + regs.ARM_r2 = (unsigned long)fn; + regs.ARM_r3 = (unsigned long)do_exit; + regs.ARM_pc = (unsigned long)kernel_thread_helper; + regs.ARM_cpsr = SVC_MODE; + + return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } /* diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index e146dab63778..3fafcf7e9e40 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -9,7 +9,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c index 5d83d3ba2e65..a50902e8bec7 100644 --- a/arch/arm/kernel/semaphore.c +++ b/arch/arm/kernel/semaphore.c @@ -11,7 +11,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include <linux/config.h> #include <linux/sched.h> #include <linux/errno.h> diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S index e6aab5ceec14..e87f06143311 100644 --- a/arch/arm/lib/lib1funcs.S +++ b/arch/arm/lib/lib1funcs.S @@ -41,7 +41,6 @@ Boston, MA 02111-1307, USA. */ #include <linux/linkage.h> #include <asm/assembler.h> #include <asm/hardware.h> -#include <linux/config.h> #define RET mov #define RETc(x) mov##x diff --git a/arch/arm/mach-anakin/arch.c b/arch/arm/mach-anakin/arch.c index 4adb9cf2e777..8041b7d99647 100644 --- a/arch/arm/mach-anakin/arch.c +++ b/arch/arm/mach-anakin/arch.c @@ -10,8 +10,6 @@ * Changelog: * 09-Apr-2001 W/TTC Created */ - -#include <linux/config.h> #include <linux/tty.h> #include <linux/init.h> diff --git a/arch/arm/mach-clps711x/mm.c b/arch/arm/mach-clps711x/mm.c index 8c7d11e0be78..120b7cac84b5 100644 --- a/arch/arm/mach-clps711x/mm.c +++ b/arch/arm/mach-clps711x/mm.c @@ -22,7 +22,6 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/init.h> -#include <linux/config.h> #include <linux/bootmem.h> #include <asm/hardware.h> diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 67d0fc309304..f4e83882eb24 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -17,7 +17,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index 50eab0a09c11..69456d0f095d 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -11,7 +11,6 @@ * * CPU support functions */ -#include <linux/config.h> #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> diff --git a/arch/arm/mach-iop3xx/mm-321.c b/arch/arm/mach-iop3xx/mm-321.c index 334811f12358..b24a1403d7c8 100644 --- a/arch/arm/mach-iop3xx/mm-321.c +++ b/arch/arm/mach-iop3xx/mm-321.c @@ -12,7 +12,7 @@ * option) any later version. * */ - +#include <linux/config.h> #include <linux/mm.h> #include <linux/init.h> diff --git a/arch/arm/mach-l7200/core.c b/arch/arm/mach-l7200/core.c index 2570c1f0943f..606ca95f8217 100644 --- a/arch/arm/mach-l7200/core.c +++ b/arch/arm/mach-l7200/core.c @@ -5,7 +5,6 @@ * * Extra MM routines for L7200 architecture */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/init.h> diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 4ec644f3defe..a7eff6ea1264 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -16,7 +16,6 @@ * initialization stuff for PXA machines which can be overridden later if * need be. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> diff --git a/arch/arm/mach-pxa/leds.c b/arch/arm/mach-pxa/leds.c index 8b27a2400437..b897be63889a 100644 --- a/arch/arm/mach-pxa/leds.c +++ b/arch/arm/mach-pxa/leds.c @@ -7,7 +7,6 @@ * * Copyright (c) 2001 Jeff Sutherland, Accelent Systems Inc. */ -#include <linux/config.h> #include <linux/init.h> #include <asm/leds.h> diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index c8183c873e1a..fe1a5b55c49a 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -10,7 +10,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License. */ - +#include <linux/config.h> #include <linux/errno.h> #include <linux/time.h> diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c index e705c3cc5b8f..f45e28116609 100644 --- a/arch/arm/mach-rpc/riscpc.c +++ b/arch/arm/mach-rpc/riscpc.c @@ -17,7 +17,6 @@ #include <asm/elf.h> #include <asm/io.h> -#include <asm/setup.h> #include <asm/mach-types.h> #include <asm/hardware.h> #include <asm/page.h> diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c index e4e8e9bf8cae..c3f5e79235f1 100644 --- a/arch/arm/mach-sa1100/h3600.c +++ b/arch/arm/mach-sa1100/h3600.c @@ -19,6 +19,7 @@ * and abstracted EGPIO interface. * */ +#include <linux/config.h> #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c index aa87418b1eac..e79bb441c8fe 100644 --- a/arch/arm/mach-sa1100/hackkit.c +++ b/arch/arm/mach-sa1100/hackkit.c @@ -11,8 +11,6 @@ * published by the Free Software Foundation. * */ - -#include <linux/config.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> diff --git a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c index a5f86cb723b4..65a29e7e2ddc 100644 --- a/arch/arm/mach-sa1100/pfs168.c +++ b/arch/arm/mach-sa1100/pfs168.c @@ -1,7 +1,6 @@ /* * linux/arch/arm/mach-sa1100/pfs168.c */ -#include <linux/config.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/tty.h> diff --git a/arch/arm/mach-sa1100/stork.c b/arch/arm/mach-sa1100/stork.c index 9ac3a0a10c7d..5aeb087c45d0 100644 --- a/arch/arm/mach-sa1100/stork.c +++ b/arch/arm/mach-sa1100/stork.c @@ -8,8 +8,6 @@ * published by the Free Software Foundation. * */ - -#include <linux/config.h> #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> diff --git a/arch/arm/mach-sa1100/trizeps.c b/arch/arm/mach-sa1100/trizeps.c index a41090012ffe..199d9cfc5024 100644 --- a/arch/arm/mach-sa1100/trizeps.c +++ b/arch/arm/mach-sa1100/trizeps.c @@ -12,7 +12,6 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#include <linux/config.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> diff --git a/arch/arm/mach-tbox/core.c b/arch/arm/mach-tbox/core.c index e9099444b2c2..db9ac783cfce 100644 --- a/arch/arm/mach-tbox/core.c +++ b/arch/arm/mach-tbox/core.c @@ -16,7 +16,6 @@ #include <asm/io.h> #include <asm/pgtable.h> #include <asm/page.h> -#include <asm/io.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S index 400ebf8654f5..b6422ef0d6db 100644 --- a/arch/arm/mm/cache-v4wb.S +++ b/arch/arm/mm/cache-v4wb.S @@ -7,6 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include <linux/config.h> #include <linux/linkage.h> #include <linux/init.h> #include <asm/hardware.h> diff --git a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c index 7c572275f4fd..2db4fb564f36 100644 --- a/arch/arm/mm/consistent.c +++ b/arch/arm/mm/consistent.c @@ -9,7 +9,6 @@ * * DMA uncached mapping support. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/mm.h> #include <linux/slab.h> diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index 273b1b42c2b5..a50e83d7092a 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -9,6 +9,7 @@ * * Page table sludge for ARM v3 and v4 processor architectures. */ +#include <linux/config.h> #include <linux/mm.h> #include <linux/init.h> #include <linux/bootmem.h> diff --git a/arch/arm/nwfpe/fpa11.c b/arch/arm/nwfpe/fpa11.c index 2fa0608152c5..bf61696865ec 100644 --- a/arch/arm/nwfpe/fpa11.c +++ b/arch/arm/nwfpe/fpa11.c @@ -26,6 +26,7 @@ #include "fpmodule.h" #include "fpmodule.inl" +#include <linux/config.h> #include <linux/compiler.h> #include <linux/string.h> #include <asm/system.h> diff --git a/arch/arm/nwfpe/fpa11.h b/arch/arm/nwfpe/fpa11.h index 1b58bfdde481..c3f14c7aa9c9 100644 --- a/arch/arm/nwfpe/fpa11.h +++ b/arch/arm/nwfpe/fpa11.h @@ -33,6 +33,7 @@ register unsigned int *user_registers asm("sl"); #define GET_USERREG() (user_registers) +#include <linux/config.h> #include <linux/thread_info.h> /* includes */ diff --git a/arch/arm/nwfpe/fpa11_cpdo.c b/arch/arm/nwfpe/fpa11_cpdo.c index 02601af35012..1bea67437b6f 100644 --- a/arch/arm/nwfpe/fpa11_cpdo.c +++ b/arch/arm/nwfpe/fpa11_cpdo.c @@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/config.h> #include "fpa11.h" #include "fpopcode.h" diff --git a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c index 384528b85cc8..59e3197d6d54 100644 --- a/arch/arm/nwfpe/fpa11_cpdt.c +++ b/arch/arm/nwfpe/fpa11_cpdt.c @@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/config.h> #include "fpa11.h" #include "softfloat.h" #include "fpopcode.h" diff --git a/arch/arm/nwfpe/fpa11_cprt.c b/arch/arm/nwfpe/fpa11_cprt.c index a656ed488fe5..db01fbc97216 100644 --- a/arch/arm/nwfpe/fpa11_cprt.c +++ b/arch/arm/nwfpe/fpa11_cprt.c @@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/config.h> #include "fpa11.h" #include "fpopcode.h" #include "fpa11.inl" diff --git a/arch/arm/nwfpe/fpopcode.c b/arch/arm/nwfpe/fpopcode.c index 1d4e89b63165..4c9f5703148c 100644 --- a/arch/arm/nwfpe/fpopcode.c +++ b/arch/arm/nwfpe/fpopcode.c @@ -19,6 +19,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/config.h> #include "fpa11.h" #include "softfloat.h" #include "fpopcode.h" diff --git a/arch/arm/nwfpe/fpopcode.h b/arch/arm/nwfpe/fpopcode.h index 6fa6d54be2ed..8035f4faafbf 100644 --- a/arch/arm/nwfpe/fpopcode.h +++ b/arch/arm/nwfpe/fpopcode.h @@ -23,6 +23,8 @@ #ifndef __FPOPCODE_H__ #define __FPOPCODE_H__ +#include <linux/config.h> + /* ARM Floating Point Instruction Classes | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | diff --git a/arch/arm/nwfpe/softfloat.h b/arch/arm/nwfpe/softfloat.h index 6678c382a4d7..1e1743173899 100644 --- a/arch/arm/nwfpe/softfloat.h +++ b/arch/arm/nwfpe/softfloat.h @@ -32,6 +32,8 @@ this code that are retained. #ifndef __SOFTFLOAT_H__ #define __SOFTFLOAT_H__ +#include <linux/config.h> + /* ------------------------------------------------------------------------------- The macro `FLOATX80' must be defined to enable the extended double-precision diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c index 8db25723b077..727b420fadca 100644 --- a/arch/h8300/kernel/signal.c +++ b/arch/h8300/kernel/signal.c @@ -593,7 +593,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: - if (is_orphaned_pgrp(current->pgrp)) + if (is_orphaned_pgrp(process_group(current))) continue; /* FALLTHRU */ diff --git a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c index 3f0ff9887da5..b5ae16027f55 100644 --- a/arch/i386/kernel/cpu/mtrr/if.c +++ b/arch/i386/kernel/cpu/mtrr/if.c @@ -13,7 +13,6 @@ /* RED-PEN: this is accessed without any locking */ extern unsigned int *usage_table; -static int mtrr_seq_show(struct seq_file *seq, void *offset); #define FILE_FCOUNT(f) (((struct seq_file *)((f)->private_data))->private) @@ -33,6 +32,8 @@ char *mtrr_attrib_to_str(int x) return (x <= 6) ? mtrr_strings[x] : "?"; } +#ifdef CONFIG_PROC_FS + static int mtrr_file_add(unsigned long base, unsigned long size, unsigned int type, char increment, struct file *file, int page) @@ -291,6 +292,8 @@ mtrr_close(struct inode *ino, struct file *file) return single_release(ino, file); } +static int mtrr_seq_show(struct seq_file *seq, void *offset); + static int mtrr_open(struct inode *inode, struct file *file) { if (!mtrr_if) @@ -310,11 +313,9 @@ static struct file_operations mtrr_fops = { .release = mtrr_close, }; -# ifdef CONFIG_PROC_FS static struct proc_dir_entry *proc_root_mtrr; -# endif /* CONFIG_PROC_FS */ static int mtrr_seq_show(struct seq_file *seq, void *offset) { @@ -351,15 +352,14 @@ static int mtrr_seq_show(struct seq_file *seq, void *offset) static int __init mtrr_if_init(void) { -#ifdef CONFIG_PROC_FS proc_root_mtrr = create_proc_entry("mtrr", S_IWUSR | S_IRUGO, &proc_root); if (proc_root_mtrr) { proc_root_mtrr->owner = THIS_MODULE; proc_root_mtrr->proc_fops = &mtrr_fops; } -#endif return 0; } arch_initcall(mtrr_if_init); +#endif /* CONFIG_PROC_FS */ diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 9426f8d59a2b..e33a9d439acf 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -1143,6 +1143,7 @@ int irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 }; static int __init assign_irq_vector(int irq) { static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; + BUG_ON(irq >= NR_IRQS); if (IO_APIC_VECTOR(irq) > 0) return IO_APIC_VECTOR(irq); next: @@ -1652,6 +1653,10 @@ static void __init setup_ioapic_ids_from_mpc(void) mp_ioapics[apic].mpc_apicid = reg_00.bits.ID; } + /* Don't check I/O APIC IDs for some xAPIC systems. They have + * no meaning without the serial APIC bus. */ + if (NO_IOAPIC_CHECK) + continue; /* * Sanity check, is the ID really free? Every APIC in a * system must have a unique ID or we get lots of nice diff --git a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c index 032e9a8d8768..a3e650b71f09 100644 --- a/arch/i386/kernel/numaq.c +++ b/arch/i386/kernel/numaq.c @@ -99,8 +99,14 @@ static void __init initialize_physnode_map(void) } } -void __init get_memcfg_numaq(void) +/* + * Unlike Summit, we don't really care to let the NUMA-Q + * fall back to flat mode. Don't compile for NUMA-Q + * unless you really need it! + */ +int __init get_memcfg_numaq(void) { smp_dump_qct(); initialize_physnode_map(); + return 1; } diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index a78d1cc88a1f..2d034f0374cc 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -915,13 +915,13 @@ static void smp_tune_scheduling (void) cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth; } - cache_decay_ticks = (long)cacheflush_time/cpu_khz * HZ / 1000; + cache_decay_ticks = (long)cacheflush_time/cpu_khz + 1; printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n", (long)cacheflush_time/(cpu_khz/1000), ((long)cacheflush_time*100/(cpu_khz/1000)) % 100); printk("task migration cache decay timeout: %ld msecs.\n", - (cache_decay_ticks + 1) * 1000 / HZ); + cache_decay_ticks); } /* diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c index 10906732862b..8c0bd561f4d6 100644 --- a/arch/i386/kernel/srat.c +++ b/arch/i386/kernel/srat.c @@ -239,6 +239,11 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp) } } + if (num_memory_chunks == 0) { + printk("could not finy any ACPI SRAT memory areas.\n"); + goto out_fail; + } + /* Calculate total number of nodes in system from PXM bitmap and create * a set of sequential node IDs starting at zero. (ACPI doesn't seem * to specify the range of _PXM values.) @@ -295,10 +300,12 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp) } } } + return 1; +out_fail: return 0; } -void __init get_memcfg_from_srat(void) +int __init get_memcfg_from_srat(void) { struct acpi_table_header *header = NULL; struct acpi_table_rsdp *rsdp = NULL; @@ -316,11 +323,11 @@ void __init get_memcfg_from_srat(void) (u32)rsdp_address->pointer.physical; } else { printk("%s: rsdp_address is not a physical pointer\n", __FUNCTION__); - return; + goto out_err; } if (!rsdp) { printk("%s: Didn't find ACPI root!\n", __FUNCTION__); - return; + goto out_err; } printk(KERN_INFO "%.8s v%d [%.6s]\n", rsdp->signature, rsdp->revision, @@ -328,7 +335,7 @@ void __init get_memcfg_from_srat(void) if (strncmp(rsdp->signature, RSDP_SIG,strlen(RSDP_SIG))) { printk(KERN_WARNING "%s: RSDP table signature incorrect\n", __FUNCTION__); - return; + goto out_err; } rsdt = (struct acpi_table_rsdt *) @@ -338,14 +345,14 @@ void __init get_memcfg_from_srat(void) printk(KERN_WARNING "%s: ACPI: Invalid root system description tables (RSDT)\n", __FUNCTION__); - return; + goto out_err; } header = & rsdt->header; if (strncmp(header->signature, RSDT_SIG, strlen(RSDT_SIG))) { printk(KERN_WARNING "ACPI: RSDT signature incorrect\n"); - return; + goto out_err; } /* @@ -356,15 +363,18 @@ void __init get_memcfg_from_srat(void) */ tables = (header->length - sizeof(struct acpi_table_header)) / 4; + if (!tables) + goto out_err; + memcpy(&saved_rsdt, rsdt, sizeof(saved_rsdt)); if (saved_rsdt.header.length > sizeof(saved_rsdt)) { printk(KERN_WARNING "ACPI: Too big length in RSDT: %d\n", saved_rsdt.header.length); - return; + goto out_err; } -printk("Begin table scan....\n"); + printk("Begin SRAT table scan....\n"); for (i = 0; i < tables; i++) { /* Map in header, then map in full table length. */ @@ -379,10 +389,13 @@ printk("Begin table scan....\n"); if (strncmp((char *) &header->signature, "SRAT", 4)) continue; - acpi20_parse_srat((struct acpi_table_srat *)header); + /* we've found the srat table. don't need to look at any more tables */ - break; + return acpi20_parse_srat((struct acpi_table_srat *)header); } +out_err: + printk("failed to get NUMA memory information from SRAT table\n"); + return 0; } /* For each node run the memory list to determine whether there are diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index af912f4d2cf1..f8b3c918a955 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -127,6 +127,30 @@ static unsigned long long monotonic_clock_tsc(void) return base + cycles_2_ns(this_offset - last_offset); } +/* + * Scheduler clock - returns current time in nanosec units. + */ +unsigned long long sched_clock(void) +{ + unsigned long long this_offset; + + /* + * In the NUMA case we dont use the TSC as they are not + * synchronized across all CPUs. + */ +#ifndef CONFIG_NUMA + if (unlikely(!cpu_has_tsc)) +#endif + return (unsigned long long)jiffies * (1000000000 / HZ); + + /* Read the Time Stamp Counter */ + rdtscll(this_offset); + + /* return the value in ns */ + return cycles_2_ns(this_offset); +} + + static void mark_offset_tsc(void) { unsigned long lost,delay; diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c index aadfcb53b6d0..e613ef8e7014 100644 --- a/arch/i386/mm/discontig.c +++ b/arch/i386/mm/discontig.c @@ -30,6 +30,7 @@ #include <linux/initrd.h> #include <asm/e820.h> #include <asm/setup.h> +#include <asm/mmzone.h> struct pglist_data *node_data[MAX_NUMNODES]; bootmem_data_t node0_bdata; @@ -84,7 +85,7 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); * a single node with all available processors in it with a flat * memory map. */ -void __init get_memcfg_numa_flat(void) +int __init get_memcfg_numa_flat(void) { int pfn; @@ -107,6 +108,7 @@ void __init get_memcfg_numa_flat(void) /* Indicate there is one node available. */ node_set_online(0); numnodes = 1; + return 1; } /* @@ -355,17 +357,20 @@ void __init zone_sizes_init(void) unsigned long low = max_low_pfn; unsigned long start = node_start_pfn[nid]; unsigned long high = node_end_pfn[nid]; - + max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; if (start > low) { #ifdef CONFIG_HIGHMEM - zones_size[ZONE_HIGHMEM] = high - start; + BUG_ON(start > high); + zones_size[ZONE_HIGHMEM] = high - start; #endif } else { if (low < max_dma) zones_size[ZONE_DMA] = low; else { + BUG_ON(max_dma > low); + BUG_ON(low > high); zones_size[ZONE_DMA] = max_dma; zones_size[ZONE_NORMAL] = low - max_dma; #ifdef CONFIG_HIGHMEM diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 54951a69f4cc..92c280c7016d 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -1082,7 +1082,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: - if (is_orphaned_pgrp(current->pgrp)) + if (is_orphaned_pgrp(process_group(current))) continue; /* FALLTHRU */ diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c index 4271a229b62c..d24df6f29517 100644 --- a/arch/m68knommu/kernel/signal.c +++ b/arch/m68knommu/kernel/signal.c @@ -841,7 +841,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: - if (is_orphaned_pgrp(current->pgrp)) + if (is_orphaned_pgrp(process_group(current))) continue; /* FALLTHRU */ diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index 31fbd57c7021..f925c6514aad 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c @@ -1130,7 +1130,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) prstatus.pr_sighold = current->blocked.sig[0]; psinfo.pr_pid = prstatus.pr_pid = current->pid; psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid; - psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp; + psinfo.pr_pgrp = prstatus.pr_pgrp = process_group(current); psinfo.pr_sid = prstatus.pr_sid = current->session; prstatus.pr_utime.tv_sec = CT_TO_SECS(current->utime); prstatus.pr_utime.tv_usec = CT_TO_USECS(current->utime); diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 85cc88d32b7d..9ed7b1e75a39 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -582,7 +582,7 @@ repeat: p = list_entry(_p,struct task_struct,sibling); if ((type == P_PID) && p->pid != pid) continue; - if ((type == P_PGID) && p->pgrp != pid) + if ((type == P_PGID) && process_group(p) != pid) continue; if ((p->exit_signal != SIGCHLD)) continue; diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 022aa036efef..cadafba927ac 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -803,11 +803,11 @@ asmlinkage int irix_setpgrp(int flags) printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags); #endif if(!flags) - error = current->pgrp; + error = process_group(current); else error = sys_setsid(); #ifdef DEBUG_PROCGRPS - printk("returning %d\n", current->pgrp); + printk("returning %d\n", process_group(current)); #endif return error; diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index b571bce80370..ee5072f60091 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -83,6 +83,7 @@ time_t last_rtc_update; unsigned tb_ticks_per_jiffy; unsigned tb_to_us; unsigned tb_last_stamp; +unsigned long tb_to_ns_scale; extern unsigned long wall_jiffies; @@ -309,6 +310,7 @@ void __init time_init(void) tb_to_us = 0x418937; } else { ppc_md.calibrate_decr(); + tb_to_ns_scale = mulhwu(tb_to_us, 1000 << 10); } /* Now that the decrementer is calibrated, it can be used in case the @@ -432,3 +434,26 @@ unsigned mulhwu_scale_factor(unsigned inscale, unsigned outscale) { return mlt; } +unsigned long long sched_clock(void) +{ + unsigned long lo, hi, hi2; + unsigned long long tb; + + if (!__USE_RTC()) { + do { + hi = get_tbu(); + lo = get_tbl(); + hi2 = get_tbu(); + } while (hi2 != hi); + tb = ((unsigned long long) hi << 32) | lo; + tb = (tb * tb_to_ns_scale) >> 10; + } else { + do { + hi = get_rtcu(); + lo = get_rtcl(); + hi2 = get_rtcu(); + } while (hi2 != hi); + tb = ((unsigned long long) hi) * 1000000000 + lo; + } + return tb; +} diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c index 6657873853b3..2f5366cb9848 100644 --- a/arch/ppc64/kernel/time.c +++ b/arch/ppc64/kernel/time.c @@ -307,6 +307,15 @@ int timer_interrupt(struct pt_regs * regs) return 1; } +/* + * Scheduler clock - returns current time in nanosec units. + * + * This is wrong, but my CPUs run at 1GHz, so nyer nyer. + */ +unsigned long long sched_clock(void) +{ + return get_tb(); +} /* * This version of gettimeofday has microsecond resolution. diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 2572fdcd9908..2039cf715782 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -416,6 +416,7 @@ unsigned long timer_tick_offset; unsigned long timer_tick_compare; static unsigned long timer_ticks_per_usec_quotient; +static unsigned long timer_ticks_per_nsec_quotient; #define TICK_SIZE (tick_nsec / 1000) @@ -1051,12 +1052,18 @@ static struct notifier_block sparc64_cpufreq_notifier_block = { #endif /* The quotient formula is taken from the IA64 port. */ +#define SPARC64_USEC_PER_CYC_SHIFT 30UL +#define SPARC64_NSEC_PER_CYC_SHIFT 30UL void __init time_init(void) { unsigned long clock = sparc64_init_timers(timer_interrupt); timer_ticks_per_usec_quotient = - (((1000000UL << 30) + + (((1000000UL << SPARC64_USEC_PER_CYC_SHIFT) + + (clock / 2)) / clock); + + timer_ticks_per_nsec_quotient = + (((NSEC_PER_SEC << SPARC64_NSEC_PER_CYC_SHIFT) + (clock / 2)) / clock); #ifdef CONFIG_CPU_FREQ @@ -1072,7 +1079,16 @@ static __inline__ unsigned long do_gettimeoffset(void) ticks += timer_tick_offset; ticks -= timer_tick_compare; - return (ticks * timer_ticks_per_usec_quotient) >> 30UL; + return (ticks * timer_ticks_per_usec_quotient) + >> SPARC64_USEC_PER_CYC_SHIFT; +} + +unsigned long long sched_clock(void) +{ + unsigned long ticks = tick_ops->get_tick(); + + return (ticks * timer_ticks_per_nsec_quotient) + >> SPARC64_NSEC_PER_CYC_SHIFT; } int do_settimeofday(struct timespec *tv) diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index 024b74c9d8b5..ea7b2c439653 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c @@ -392,7 +392,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid) switch (cmd) { case 0: /* getpgrp */ - return current->pgrp; + return process_group(current); case 1: /* setpgrp */ { int (*sys_setpgid)(pid_t,pid_t) = @@ -403,7 +403,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid) ret = sys_setpgid(0, 0); if (ret) return ret; current->tty = NULL; - return current->pgrp; + return process_group(current); } case 2: /* getsid */ { diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 92b8ffe633f6..315940661179 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c @@ -370,6 +370,19 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) return IRQ_HANDLED; } +/* RED-PEN: calculation is done in 32bits with multiply for performance + and could overflow, it may be better (but slower)to use an 64bit division. */ +unsigned long long sched_clock(void) +{ + unsigned long a; + + if (__vxtime.mode == VXTIME_HPET) + return (hpet_readl(HPET_COUNTER) * vxtime.quot) >> 32; + + rdtscll(a); + return (a * vxtime.tsc_quot) >> 32; +} + unsigned long get_cmos_time(void) { unsigned int timeout, year, mon, day, hour, min, sec; diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index a54f8e9a358e..6ef1db60da84 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c @@ -1303,7 +1303,7 @@ static struct request *as_next_request(request_queue_t *q) * Add arq to a list behind alias */ static inline void -as_add_aliased_request(struct as_rq *arq, struct as_rq *alias) +as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alias) { /* * Another request with the same start sector on the rbtree. @@ -1312,6 +1312,11 @@ as_add_aliased_request(struct as_rq *arq, struct as_rq *alias) */ list_add_tail(&arq->request->queuelist, &alias->request->queuelist); + /* + * Don't want to have to handle merges. + */ + as_remove_merge_hints(ad->q, arq); + } /* @@ -1353,7 +1358,7 @@ static void as_add_request(struct as_data *ad, struct as_rq *arq) as_update_arq(ad, arq); /* keep state machine up to date */ } else { - as_add_aliased_request(arq, alias); + as_add_aliased_request(ad, arq, alias); /* * have we been anticipating this request? * or does it come from the same process as the one we are @@ -1553,8 +1558,10 @@ static void as_merged_request(request_queue_t *q, struct request *req) * currently don't bother. Ditto the next function. */ as_del_arq_rb(ad, arq); - if ((alias = as_add_arq_rb(ad, arq)) ) - as_add_aliased_request(arq, alias); + if ((alias = as_add_arq_rb(ad, arq)) ) { + list_del_init(&arq->fifo); + as_add_aliased_request(ad, arq, alias); + } /* * Note! At this stage of this and the next function, our next * request may not be optimal - eg the request may have "grown" @@ -1586,8 +1593,10 @@ as_merged_requests(request_queue_t *q, struct request *req, if (rq_rb_key(req) != arq->rb_key) { struct as_rq *alias; as_del_arq_rb(ad, arq); - if ((alias = as_add_arq_rb(ad, arq)) ) - as_add_aliased_request(arq, alias); + if ((alias = as_add_arq_rb(ad, arq)) ) { + list_del_init(&arq->fifo); + as_add_aliased_request(ad, arq, alias); + } } /* @@ -1926,7 +1935,7 @@ elevator_t iosched_as = { .elevator_exit_fn = as_exit, .elevator_ktype = &as_ktype, - .elevator_name = "anticipatory scheduling", + .elevator_name = "anticipatory", }; EXPORT_SYMBOL(iosched_as); diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 657dc16d5438..3d7fc3bfa6c9 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -754,16 +754,24 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, status = -ENOMEM; goto cleanup1; } - if (copy_from_user(ioc, (void *) arg, sizeof(*ioc))) - return -EFAULT; + if (copy_from_user(ioc, (void *) arg, sizeof(*ioc))) { + status = -EFAULT; + goto cleanup1; + } if ((ioc->buf_size < 1) && - (ioc->Request.Type.Direction != XFER_NONE)) - return -EINVAL; + (ioc->Request.Type.Direction != XFER_NONE)) { + status = -EINVAL; + goto cleanup1; + } /* Check kmalloc limits using all SGs */ - if (ioc->malloc_size > MAX_KMALLOC_SIZE) - return -EINVAL; - if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) - return -EINVAL; + if (ioc->malloc_size > MAX_KMALLOC_SIZE) { + status = -EINVAL; + goto cleanup1; + } + if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) { + status = -EINVAL; + goto cleanup1; + } buff = (unsigned char **) kmalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL); if (!buff) { diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c index ecc2a9997007..1c8ca884396f 100644 --- a/drivers/block/deadline-iosched.c +++ b/drivers/block/deadline-iosched.c @@ -287,8 +287,11 @@ deadline_find_first_drq(struct deadline_data *dd, int data_dir) * add drq to rbtree and fifo */ static inline void -deadline_add_request(struct deadline_data *dd, struct deadline_rq *drq) +deadline_add_request(struct request_queue *q, struct request *rq) { + struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_rq *drq = RQ_DATA(rq); + const int data_dir = rq_data_dir(drq->request); deadline_add_drq_rb(dd, drq); @@ -297,6 +300,13 @@ deadline_add_request(struct deadline_data *dd, struct deadline_rq *drq) */ drq->expires = jiffies + dd->fifo_expire[data_dir]; list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]); + + if (rq_mergeable(rq)) { + deadline_add_drq_hash(dd, drq); + + if (!q->last_merge) + q->last_merge = rq; + } } /* @@ -616,7 +626,6 @@ static void deadline_insert_request(request_queue_t *q, struct request *rq, int where) { struct deadline_data *dd = q->elevator.elevator_data; - struct deadline_rq *drq = RQ_DATA(rq); /* barriers must flush the reorder queue */ if (unlikely(rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER) @@ -634,19 +643,12 @@ deadline_insert_request(request_queue_t *q, struct request *rq, int where) break; case ELEVATOR_INSERT_SORT: BUG_ON(!blk_fs_request(rq)); - deadline_add_request(dd, drq); + deadline_add_request(q, rq); break; default: printk("%s: bad insert point %d\n", __FUNCTION__,where); return; } - - if (rq_mergeable(rq)) { - deadline_add_drq_hash(dd, drq); - - if (!q->last_merge) - q->last_merge = rq; - } } static int deadline_queue_empty(request_queue_t *q) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index b25acb42542e..efc52196d36b 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -219,6 +219,7 @@ static int use_virtual_dma; */ static spinlock_t floppy_lock = SPIN_LOCK_UNLOCKED; +static struct completion device_release; static unsigned short virtual_dma_port=0x3f0; irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs); @@ -2152,18 +2153,20 @@ static int next_valid_format(void) static void bad_flp_intr(void) { + int err_count; + if (probing){ DRS->probed_format++; if (!next_valid_format()) return; } - (*errors)++; - INFBOUND(DRWE->badness, *errors); - if (*errors > DP->max_errors.abort) + err_count = ++(*errors); + INFBOUND(DRWE->badness, err_count); + if (err_count > DP->max_errors.abort) cont->done(0); - if (*errors > DP->max_errors.reset) + if (err_count > DP->max_errors.reset) FDCS->reset = 1; - else if (*errors > DP->max_errors.recal) + else if (err_count > DP->max_errors.recal) DRS->track = NEED_2_RECAL; } @@ -4203,9 +4206,17 @@ static int __init floppy_setup(char *str) static int have_no_fdc= -ENODEV; +static void floppy_device_release(struct device *dev) +{ + complete(&device_release); +} + static struct platform_device floppy_device = { .name = "floppy", .id = 0, + .dev = { + .release = floppy_device_release, + } }; static struct kobject *floppy_find(dev_t dev, int *part, void *data) @@ -4576,11 +4587,15 @@ int init_module(void) void cleanup_module(void) { int drive; - + + init_completion(&device_release); platform_device_unregister(&floppy_device); blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); unregister_blkdev(FLOPPY_MAJOR, "fd"); + for (drive = 0; drive < N_DRIVE; drive++) { + del_timer_sync(&motor_off_timer[drive]); + if ((allowed_drive_mask & (1 << drive)) && fdc_state[FDC(drive)].version != FDC_NONE) { del_gendisk(disks[drive]); @@ -4590,9 +4605,17 @@ void cleanup_module(void) } devfs_remove("floppy"); + del_timer_sync(&fd_timeout); + del_timer_sync(&fd_timer); blk_cleanup_queue(floppy_queue); + + if (usage_count) + floppy_release_irq_and_dma(); + /* eject disk, if any */ fd_eject(0); + + wait_for_completion(&device_release); } MODULE_PARM(floppy,"s"); diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 793712f993ef..fc416a29f75c 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -352,7 +352,7 @@ config STALLION config ISTALLION tristate "Stallion EC8/64, ONboard, Brumby support" - depends on STALDRV && BROKEN + depends on STALDRV && BROKEN_ON_SMP help If you have an EasyConnection 8/64, ONboard, Brumby or Stallion serial multiport card, say Y here. Make sure to read @@ -959,6 +959,7 @@ source "drivers/char/pcmcia/Kconfig" config MWAVE tristate "ACP Modem (Mwave) support" depends on X86 + select SERIAL_8250 ---help--- The ACP modem (Mwave) for Linux is a WinModem. It is composed of a kernel driver and a user level application. Together these components @@ -1001,6 +1002,7 @@ config RAW_DRIVER config HANGCHECK_TIMER tristate "Hangcheck timer" + depends on X86_64 || X86 help The hangcheck-timer module detects when the system has gone out to lunch past a certain margin. It can reboot the system diff --git a/drivers/char/Makefile b/drivers/char/Makefile index aeac2fb7d641..b53d91f5c10d 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -7,7 +7,7 @@ # FONTMAPFILE = cp437.uni -obj-y += mem.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o random.o +obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o consolemap_deftbl.o selection.o keyboard.o obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index f0f54e3b8450..cff44cad625c 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -318,6 +318,7 @@ void __exit agp_exit(void) { } +#ifdef MODULE static __init int agp_setup(char *s) { if (!strcmp(s,"off")) @@ -327,6 +328,7 @@ static __init int agp_setup(char *s) return 1; } __setup("agp=", agp_setup); +#endif MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>"); MODULE_DESCRIPTION("AGP GART driver"); diff --git a/drivers/char/ftape/lowlevel/ftape-init.c b/drivers/char/ftape/lowlevel/ftape-init.c index 9ffe3de655c0..8d5368a662dd 100644 --- a/drivers/char/ftape/lowlevel/ftape-init.c +++ b/drivers/char/ftape/lowlevel/ftape-init.c @@ -55,14 +55,24 @@ char ft_rev[] __initdata = "$Revision: 1.8 $"; char ft_dat[] __initdata = "$Date: 1997/11/06 00:38:08 $"; +#ifndef CONFIG_FT_NO_TRACE_AT_ALL +static int ft_tracing = -1; +#endif + + /* Called by modules package when installing the driver * or by kernel during the initialization phase */ -int __init ftape_init(void) +static int __init ftape_init(void) { TRACE_FUN(ft_t_flow); #ifdef MODULE +#ifndef CONFIG_FT_NO_TRACE_AT_ALL + if (ft_tracing != -1) { + ftape_tracing = ft_tracing; + } +#endif printk(KERN_INFO FTAPE_VERSION "\n"); if (TRACE_LEVEL >= ft_t_info) { printk( @@ -112,13 +122,6 @@ KERN_INFO "Compiled for Linux version %s\n", UTS_RELEASE); #endif TRACE_EXIT 0; } - -#ifdef MODULE - -#ifndef CONFIG_FT_NO_TRACE_AT_ALL -static int ft_tracing = -1; -#endif - #define FT_MOD_PARM(var,type,desc) \ MODULE_PARM(var,type); MODULE_PARM_DESC(var,desc) @@ -141,21 +144,7 @@ MODULE_DESCRIPTION( "QIC-117 driver for QIC-40/80/3010/3020 floppy tape drives."); MODULE_LICENSE("GPL"); -/* Called by modules package when installing the driver - */ -int init_module(void) -{ -#ifndef CONFIG_FT_NO_TRACE_AT_ALL - if (ft_tracing != -1) { - ftape_tracing = ft_tracing; - } -#endif - return ftape_init(); -} - -/* Called by modules package when removing the driver - */ -void cleanup_module(void) +static void __exit ftape_exit(void) { TRACE_FUN(ft_t_flow); @@ -166,4 +155,6 @@ void cleanup_module(void) printk(KERN_INFO "ftape: unloaded.\n"); TRACE_EXIT; } -#endif /* MODULE */ + +module_init(ftape_init); +module_exit(ftape_exit); diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index ff543516731d..f26a6e1dd76e 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -2303,7 +2303,7 @@ static void stli_dohangup(void *arg) /* * FIXME: There's a module removal race here: tty_hangup - * calls schedule_task which will call into this + * calls schedule_work which will call into this * driver later. */ portp = (stliport_t *) arg; @@ -2944,7 +2944,7 @@ static inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp) ((portp->sigs & TIOCM_CD) == 0)) { if (portp->flags & ASYNC_CHECK_CD) { if (tty) - schedule_task(&portp->tqhangup); + schedule_work(&portp->tqhangup); } } } diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 82b44f1c1a13..3e32d60c8b1e 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -680,18 +680,9 @@ static int __init chr_dev_init(void) S_IFCHR | devlist[i].mode, devlist[i].name); } - rand_initialize(); #if defined (CONFIG_FB) fbmem_init(); #endif - tty_init(); -#ifdef CONFIG_M68K_PRINTER - lp_m68k_init(); -#endif - misc_init(); -#ifdef CONFIG_FTAPE - ftape_init(); -#endif return 0; } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index e808cfa31236..8211052cecfe 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -277,7 +277,7 @@ int misc_deregister(struct miscdevice * misc) EXPORT_SYMBOL(misc_register); EXPORT_SYMBOL(misc_deregister); -int __init misc_init(void) +static int __init misc_init(void) { #ifdef CONFIG_PROC_FS struct proc_dir_entry *ent; @@ -320,3 +320,4 @@ int __init misc_init(void) } return 0; } +module_init(misc_init); diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 6cc938bbbf30..44d551ba1091 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -977,11 +977,11 @@ do_it_again: if (file->f_op->write != redirected_tty_write && current->tty == tty) { if (tty->pgrp <= 0) printk("read_chan: tty->pgrp <= 0!\n"); - else if (current->pgrp != tty->pgrp) { + else if (process_group(current) != tty->pgrp) { if (is_ignored(SIGTTIN) || - is_orphaned_pgrp(current->pgrp)) + is_orphaned_pgrp(process_group(current))) return -EIO; - kill_pg(current->pgrp, SIGTTIN, 1); + kill_pg(process_group(current), SIGTTIN, 1); return -ERESTARTSYS; } } diff --git a/drivers/char/random.c b/drivers/char/random.c index c36d2ea46b07..c782ff3622a8 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1493,16 +1493,16 @@ static void init_std_data(struct entropy_store *r) } } -void __init rand_initialize(void) +static int __init rand_initialize(void) { int i; if (create_entropy_store(DEFAULT_POOL_SIZE, &random_state)) - return; /* Error, return */ + goto err; if (batch_entropy_init(BATCH_ENTROPY_SIZE, random_state)) - return; /* Error, return */ + goto err; if (create_entropy_store(SECONDARY_POOL_SIZE, &sec_random_state)) - return; /* Error, return */ + goto err; clear_entropy_store(random_state); clear_entropy_store(sec_random_state); init_std_data(random_state); @@ -1515,7 +1515,11 @@ void __init rand_initialize(void) memset(&mouse_timer_state, 0, sizeof(struct timer_rand_state)); memset(&extract_timer_state, 0, sizeof(struct timer_rand_state)); extract_timer_state.dont_count_entropy = 1; + return 0; +err: + return -1; } +module_init(rand_initialize); void rand_initialize_irq(int irq) { diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 777f8ae5321e..9327ebe6b874 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -234,14 +234,12 @@ int rio_probe_addrs[]= {0xc0000, 0xd0000, 0xe0000}; support up to 64 bits on 64bit architectures. -- REW 20/06/99 */ long rio_irqmask = -1; -#ifndef TWO_ZERO MODULE_AUTHOR("Rogier Wolff <R.E.Wolff@bitwizard.nl>, Patrick van de Lageweg <patrick@bitwizard.nl>"); MODULE_DESCRIPTION("RIO driver"); MODULE_LICENSE("GPL"); MODULE_PARM(rio_poll, "i"); MODULE_PARM(rio_debug, "i"); MODULE_PARM(rio_irqmask, "i"); -#endif static struct real_driver rio_real_driver = { rio_disable_tx_interrupts, @@ -1034,13 +1032,6 @@ static void __exit rio_release_drivers(void) func_exit(); } -#ifdef TWO_ZERO -#define PDEV unsigned char pci_bus, unsigned pci_fun -#define pdev pci_bus, pci_fun -#else -#define PDEV struct pci_dev *pdev -#endif - #ifdef CONFIG_PCI /* This was written for SX, but applies to RIO too... @@ -1062,7 +1053,7 @@ static void __exit rio_release_drivers(void) EEprom. As the bit is read/write for the CPU, we can fix it here, if we detect that it isn't set correctly. -- REW */ -void fix_rio_pci (PDEV) +void fix_rio_pci (struct pci_dev *pdev) { unsigned int hwbase; unsigned long rebase; @@ -1095,12 +1086,7 @@ static int __init rio_init(void) int okboard; #ifdef CONFIG_PCI -#ifndef TWO_ZERO struct pci_dev *pdev = NULL; -#else - unsigned char pci_bus, pci_fun; - /* in 2.2.x pdev is a pointer defining a PCI device. In 2.0 its the bus/fn */ -#endif unsigned int tint; unsigned short tshort; #endif @@ -1128,17 +1114,11 @@ static int __init rio_init(void) #ifdef CONFIG_PCI /* First look for the JET devices: */ -#ifndef TWO_ZERO while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) { if (pci_enable_device(pdev)) continue; -#else - for (i=0;i< RIO_NBOARDS;i++) { - if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, - PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, i, - &pci_bus, &pci_fun)) break; -#endif + /* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say its because the standard requires it. Stupid standard. */ @@ -1196,16 +1176,9 @@ static int __init rio_init(void) } else { iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr)); } - -#ifdef TWO_ZERO - } /* We have two variants with the opening brace, so to prevent */ -#else - } /* Emacs from getting confused we have two closing braces too. */ -#endif + } /* Then look for the older PCI card.... : */ -#ifndef TWO_ZERO - /* These older PCI cards have problems (only byte-mode access is supported), which makes them a bit awkward to support. @@ -1219,12 +1192,6 @@ static int __init rio_init(void) PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) { if (pci_enable_device(pdev)) continue; -#else - for (i=0;i< RIO_NBOARDS;i++) { - if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, - PCI_DEVICE_ID_SPECIALIX_RIO, i, - &pci_bus, &pci_fun)) break; -#endif #ifdef CONFIG_RIO_OLDPCI pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &tint); @@ -1272,11 +1239,7 @@ static int __init rio_init(void) printk (KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n"); #endif -#ifdef TWO_ZERO - } /* We have two variants with the opening brace, so to prevent */ -#else - } /* Emacs from getting confused we have two closing braces too. */ -#endif + } #endif /* PCI */ /* Now probe for ISA cards... */ diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 8f969928c68b..50fab08d460f 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -956,7 +956,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) * Info->count is now 1; so it's safe to sleep now. */ info->session = current->session; - info->pgrp = current->pgrp; + info->pgrp = process_group(current); if ((info->flags & ROCKET_INITIALIZED) == 0) { cp = &info->channel; diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 277b9cd33657..a65506e8f6bd 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -92,40 +92,7 @@ #include <linux/delay.h> #include <linux/version.h> #include <linux/pci.h> - - -/* ************************************************************** */ -/* * This section can be removed when 2.0 becomes outdated.... * */ -/* ************************************************************** */ - -#if LINUX_VERSION_CODE < 131328 /* Less than 2.1.0 */ -#define TWO_ZERO -#else -#if LINUX_VERSION_CODE < 131371 /* less than 2.1.43 */ -/* This has not been extensively tested yet. Sorry. */ -#warning "You're on your own between 2.1.0 and 2.1.43.... " -#warning "Please use a recent kernel." -#endif -#endif - - -#ifdef TWO_ZERO -#define Get_user(a,b) a = get_user(b) -#define copy_from_user(a,b,c) memcpy_fromfs(a,b,c) -#define copy_to_user(a,b,c) memcpy_tofs(a,b,c) -#define queue_task queue_task_irq_off -#else -#define Get_user(a,b) get_user(a,b) -#endif - -/* ************************************************************** */ -/* * End of compatibility section.. * */ -/* ************************************************************** */ - - -#ifndef TWO_ZERO #include <asm/uaccess.h> -#endif #include "specialix_io8.h" #include "cd1865.h" @@ -1733,7 +1700,7 @@ static int sx_set_modem_info(struct specialix_port * port, unsigned int cmd, if (error) return error; - Get_user(arg, (unsigned long *) value); + get_user(arg, (unsigned long *) value); switch (cmd) { case TIOCMBIS: /* if (arg & TIOCM_RTS) @@ -1925,7 +1892,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, (unsigned long *) arg); return 0; case TIOCSSOFTCAR: - Get_user(arg, (unsigned long *) arg); + get_user(arg, (unsigned long *) arg); tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); diff --git a/drivers/char/sx.c b/drivers/char/sx.c index e809b8e1a9c8..27ca5381fc24 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -2356,14 +2356,6 @@ static void __exit sx_release_drivers(void) func_exit(); } -#ifdef TWO_ZERO -#define PDEV unsigned char pci_bus, unsigned pci_fun -#define pdev pci_bus, pci_fun -#else -#define PDEV struct pci_dev *pdev -#endif - - #ifdef CONFIG_PCI /******************************************************** * Setting bit 17 in the CNTRL register of the PLX 9050 * @@ -2376,7 +2368,7 @@ static void __exit sx_release_drivers(void) EEprom. As the bit is read/write for the CPU, we can fix it here, if we detect that it isn't set correctly. -- REW */ -static void fix_sx_pci (PDEV, struct sx_board *board) +static void fix_sx_pci (struct pci_dev *pdev, struct sx_board *board) { unsigned int hwbase; unsigned long rebase; @@ -2406,12 +2398,7 @@ static int __init sx_init(void) struct sx_board *board; #ifdef CONFIG_PCI -#ifndef TWO_ZERO struct pci_dev *pdev = NULL; -#else - unsigned char pci_bus, pci_fun; - /* in 2.2.x pdev is a pointer defining a PCI device. In 2.0 its the bus/fn */ -#endif unsigned int tint; unsigned short tshort; #endif @@ -2431,19 +2418,12 @@ static int __init sx_init(void) } #ifdef CONFIG_PCI -#ifndef TWO_ZERO while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) { if (pci_enable_device(pdev)) continue; -#else - for (i=0;i< SX_NBOARDS;i++) { - if (pcibios_find_device (PCI_VENDOR_ID_SPECIALIX, - PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, i, - &pci_bus, &pci_fun)) - break; -#endif + /* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say its because the standard requires it. Stupid standard. */ diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 8d1f8c6d3c23..41935ac3e375 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -325,13 +325,13 @@ int tty_check_change(struct tty_struct * tty) printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n"); return 0; } - if (current->pgrp == tty->pgrp) + if (process_group(current) == tty->pgrp) return 0; if (is_ignored(SIGTTOU)) return 0; - if (is_orphaned_pgrp(current->pgrp)) + if (is_orphaned_pgrp(process_group(current))) return -EIO; - (void) kill_pg(current->pgrp,SIGTTOU,1); + (void) kill_pg(process_group(current), SIGTTOU, 1); return -ERESTARTSYS; } @@ -1406,7 +1406,7 @@ got_driver: task_unlock(current); current->tty_old_pgrp = 0; tty->session = current->session; - tty->pgrp = current->pgrp; + tty->pgrp = process_group(current); } return 0; } @@ -1580,7 +1580,7 @@ static int tiocsctty(struct tty_struct *tty, int arg) task_unlock(current); current->tty_old_pgrp = 0; tty->session = current->session; - tty->pgrp = current->pgrp; + tty->pgrp = process_group(current); return 0; } @@ -2423,7 +2423,7 @@ static struct cdev vc0_cdev; * Ok, now we can initialize the rest of the tty devices and can count * on memory allocations, interrupts etc.. */ -void __init tty_init(void) +static int __init tty_init(void) { strcpy(tty_cdev.kobj.name, "dev.tty"); cdev_init(&tty_cdev, &tty_fops); @@ -2512,4 +2512,6 @@ void __init tty_init(void) #ifdef CONFIG_A2232 a2232board_init(); #endif + return 0; } +module_init(tty_init); diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 996e8c5a9612..390b0f484d26 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -1989,7 +1989,8 @@ modem_write_profile(atemu * m) memcpy(m->pmsn, m->msn, ISDN_MSNLEN); memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN); if ((get_isdn_dev())->profd) - kill_pg_info(SIGIO, SEND_SIG_PRIV, (get_isdn_dev())->profd->pgrp); + kill_pg_info(SIGIO, SEND_SIG_PRIV, + process_group((get_isdn_dev())->profd)); } static struct tty_operations modem_ops = { diff --git a/drivers/net/arm/ether00.c b/drivers/net/arm/ether00.c index 8124d193a426..8824494c4b51 100644 --- a/drivers/net/arm/ether00.c +++ b/drivers/net/arm/ether00.c @@ -19,7 +19,7 @@ */ /* includes */ - +#include <linux/config.h> #include <linux/pci.h> #include <linux/netdevice.h> #include <linux/sched.h> diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index df80c5c25e37..54003a7c6cea 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -342,6 +342,30 @@ config HDLC_X25 comment "X.25/LAPB support is disabled" depends on WAN && HDLC && (LAPB!=m || HDLC!=m) && LAPB!=y +config WANXL + tristate "SBE Inc. wanXL support" + depends on HDLC && PCI + help + This driver is for wanXL PCI cards made by SBE Inc. If you have + such a card, say Y here and see <http://hq.pm.waw.pl/pub/hdlc/>. + + If you want to compile the driver as a module ( = code which can be + inserted in and removed from the running kernel whenever you want), + say M here and read <file:Documentation/modules.txt>. The module + will be called wanxl. + + If unsure, say N here. + +config WANXL_BUILD_FIRMWARE + bool "rebuild wanXL firmware" + depends on WANXL + help + This option allows you to rebuild firmware run by the QUICC + processor. It requires as68k, ld68k and hexdump programs. + You should never need this option. + + If unsure, say N here. + config PC300 tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)" depends on HDLC && PCI diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile index 4d540014c93f..4383eeacb67e 100644 --- a/drivers/net/wan/Makefile +++ b/drivers/net/wan/Makefile @@ -66,3 +66,25 @@ ifeq ($(CONFIG_HDLC_PPP),y) endif obj-$(CONFIG_N2) += n2.o obj-$(CONFIG_C101) += c101.o +obj-$(CONFIG_WANXL) += wanxl.o + +ifeq ($(CONFIG_WANXL_BUILD_FIRMWARE),y) +ifeq ($(ARCH),m68k) + AS68K = $(AS) + LD68K = $(LD) +else + AS68K = as68k + LD68K = ld68k +endif + +quiet_cmd_build_wanxlfw = BLD FW $@ + cmd_build_wanxlfw = \ + $(CPP) -Wp,-MD,$(depfile) -Iinclude $(obj)/wanxlfw.S | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \ + $(LD68K) --oformat binary -Ttext 0x1000 $(obj)/wanxlfw.o -o $(obj)/wanxlfw.bin; \ + hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x ,//g;1s/^/static u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \ + rm -f $(obj)/wanxlfw.bin $(obj)/wanxlfw.o + +$(obj)/wanxlfw.inc: $(obj)/wanxlfw.S + $(call if_changed_dep,build_wanxlfw) +targets += wanxlfw.inc +endif diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c new file mode 100644 index 000000000000..17f12069a939 --- /dev/null +++ b/drivers/net/wan/wanxl.c @@ -0,0 +1,836 @@ +/* + * wanXL serial card driver for Linux + * host part + * + * Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * Status: + * - Only DTE (external clock) support with NRZ and NRZI encodings + * - wanXL100 will require minor driver modifications, no access to hw + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/fcntl.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/netdevice.h> +#include <linux/hdlc.h> +#include <linux/pci.h> +#include <asm/io.h> +#include <asm/delay.h> + +#include "wanxl.h" + +static const char* version = "wanXL serial card driver version: 0.46"; + +#define PLX_CTL_RESET 0x40000000 /* adapter reset */ + +#undef DEBUG_PKT +#define DEBUG_PCI + +/* MAILBOX #1 - PUTS COMMANDS */ +#define MBX1_CMD_ABORTJ 0x85000000 /* Abort and Jump */ +#ifdef __LITTLE_ENDIAN +#define MBX1_CMD_BSWAP 0x8C000001 /* little-endian Byte Swap Mode */ +#else +#define MBX1_CMD_BSWAP 0x8C000000 /* big-endian Byte Swap Mode */ +#endif + +/* MAILBOX #2 - DRAM SIZE */ +#define MBX2_MEMSZ_MASK 0xFFFF0000 /* PUTS Memory Size Register mask */ + + +typedef struct { + hdlc_device hdlc; /* HDLC device struct - must be first */ + struct card_t *card; + spinlock_t lock; /* for wanxl_xmit */ + int node; /* physical port #0 - 3 */ + unsigned int clock_type; + int tx_in, tx_out; + struct sk_buff *tx_skbs[TX_BUFFERS]; +}port_t; + + +typedef struct { + desc_t rx_descs[RX_QUEUE_LENGTH]; + port_status_t port_status[4]; +}card_status_t; + + +typedef struct card_t { + int n_ports; /* 1, 2 or 4 ports */ + u8 irq; + + u8 *plx; /* PLX PCI9060 virtual base address */ + struct pci_dev *pdev; /* for pdev->slot_name */ + port_t *ports[4]; + int rx_in; + struct sk_buff *rx_skbs[RX_QUEUE_LENGTH]; + card_status_t *status; /* shared between host and card */ + dma_addr_t status_address; +}card_t; + + + +static inline port_t* hdlc_to_port(hdlc_device *hdlc) +{ + return (port_t*)hdlc; +} + + +static inline port_t* dev_to_port(struct net_device *dev) +{ + return hdlc_to_port(dev_to_hdlc(dev)); +} + + +static inline struct net_device *port_to_dev(port_t* port) +{ + return hdlc_to_dev(&port->hdlc); +} + + +static inline const char* port_name(port_t *port) +{ + return hdlc_to_name((hdlc_device*)port); +} + + +static inline const char* card_name(struct pci_dev *pdev) +{ + return pdev->slot_name; +} + + +static inline port_status_t* get_status(port_t *port) +{ + return &port->card->status->port_status[port->node]; +} + + +#ifdef DEBUG_PCI +static inline dma_addr_t pci_map_single_debug(struct pci_dev *pdev, void *ptr, + size_t size, int direction) +{ + dma_addr_t addr = pci_map_single(pdev, ptr, size, direction); + if (addr + size > 0x100000000LL) + printk(KERN_CRIT "wanXL %s: pci_map_single() returned memory" + " at 0x%X!\n", card_name(pdev), addr); + return addr; +} + +#undef pci_map_single +#define pci_map_single pci_map_single_debug +#endif + + +/* Cable and/or personality module change interrupt service */ +static inline void wanxl_cable_intr(port_t *port) +{ + u32 value = get_status(port)->cable; + int valid = 1; + const char *cable, *pm, *dte = "", *dsr = "", *dcd = ""; + + switch(value & 0x7) { + case STATUS_CABLE_V35: cable = "V.35"; break; + case STATUS_CABLE_X21: cable = "X.21"; break; + case STATUS_CABLE_V24: cable = "V.24"; break; + case STATUS_CABLE_EIA530: cable = "EIA530"; break; + case STATUS_CABLE_NONE: cable = "no"; break; + default: cable = "invalid"; + } + + switch((value >> STATUS_CABLE_PM_SHIFT) & 0x7) { + case STATUS_CABLE_V35: pm = "V.35"; break; + case STATUS_CABLE_X21: pm = "X.21"; break; + case STATUS_CABLE_V24: pm = "V.24"; break; + case STATUS_CABLE_EIA530: pm = "EIA530"; break; + case STATUS_CABLE_NONE: pm = "no personality"; valid = 0; break; + default: pm = "invalid personality"; valid = 0; + } + + if (valid) { + if ((value & 7) == ((value >> STATUS_CABLE_PM_SHIFT) & 7)) { + dsr = (value & STATUS_CABLE_DSR) ? ", DSR ON" : + ", DSR off"; + dcd = (value & STATUS_CABLE_DCD) ? ", carrier ON" : + ", carrier off"; + } + dte = (value & STATUS_CABLE_DCE) ? " DCE" : " DTE"; + } + printk(KERN_INFO "%s: %s%s module, %s cable%s%s\n", + port_name(port), pm, dte, cable, dsr, dcd); + + hdlc_set_carrier(value & STATUS_CABLE_DCD, &port->hdlc); +} + + + +/* Transmit complete interrupt service */ +static inline void wanxl_tx_intr(port_t *port) +{ + while (1) { + desc_t *desc; + desc = &get_status(port)->tx_descs[port->tx_in]; + struct sk_buff *skb = port->tx_skbs[port->tx_in]; + + switch (desc->stat) { + case PACKET_FULL: + case PACKET_EMPTY: + netif_wake_queue(port_to_dev(port)); + return; + + case PACKET_UNDERRUN: + port->hdlc.stats.tx_errors++; + port->hdlc.stats.tx_fifo_errors++; + break; + + default: + port->hdlc.stats.tx_packets++; + port->hdlc.stats.tx_bytes += skb->len; + } + desc->stat = PACKET_EMPTY; /* Free descriptor */ + pci_unmap_single(port->card->pdev, desc->address, skb->len, + PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + port->tx_in = (port->tx_in + 1) % TX_BUFFERS; + } +} + + + +/* Receive complete interrupt service */ +static inline void wanxl_rx_intr(card_t *card) +{ + desc_t *desc; + while(desc = &card->status->rx_descs[card->rx_in], + desc->stat != PACKET_EMPTY) { + struct sk_buff *skb = card->rx_skbs[card->rx_in]; + port_t *port = card->ports[desc->stat & PACKET_PORT_MASK]; + struct net_device *dev = port_to_dev(port); + + if ((desc->stat & PACKET_PORT_MASK) > card->n_ports) + printk(KERN_CRIT "wanXL %s: received packet for" + " nonexistent port\n", card_name(card->pdev)); + + else if (!skb) + port->hdlc.stats.rx_dropped++; + + else { + pci_unmap_single(card->pdev, desc->address, + BUFFER_LENGTH, PCI_DMA_FROMDEVICE); + skb_put(skb, desc->length); + +#ifdef DEBUG_PKT + printk(KERN_DEBUG "%s RX(%i):", port_name(port), + skb->len); + debug_frame(skb); +#endif + port->hdlc.stats.rx_packets++; + port->hdlc.stats.rx_bytes += skb->len; + skb->mac.raw = skb->data; + skb->dev = dev; + dev->last_rx = jiffies; + skb->protocol = hdlc_type_trans(skb, dev); + netif_rx(skb); + skb = NULL; + } + + if (!skb) { + skb = dev_alloc_skb(BUFFER_LENGTH); + desc->address = skb ? + pci_map_single(card->pdev, skb->data, + BUFFER_LENGTH, + PCI_DMA_FROMDEVICE) : 0; + card->rx_skbs[card->rx_in] = skb; + } + desc->stat = PACKET_EMPTY; /* Free descriptor */ + card->rx_in = (card->rx_in + 1) % RX_QUEUE_LENGTH; + } +} + + + +static irqreturn_t wanxl_intr(int irq, void* dev_id, struct pt_regs *regs) +{ + card_t *card = dev_id; + int i; + u32 stat; + int handled = 0; + + + while((stat = readl(card->plx + PLX_DOORBELL_FROM_CARD)) != 0) { + handled = 1; + writel(stat, card->plx + PLX_DOORBELL_FROM_CARD); + + for (i = 0; i < card->n_ports; i++) { + if (stat & (1 << (DOORBELL_FROM_CARD_TX_0 + i))) + wanxl_tx_intr(card->ports[i]); + if (stat & (1 << (DOORBELL_FROM_CARD_CABLE_0 + i))) + wanxl_cable_intr(card->ports[i]); + } + if (stat & (1 << DOORBELL_FROM_CARD_RX)) + wanxl_rx_intr(card); + } + + return IRQ_RETVAL(handled); +} + + + +static int wanxl_xmit(struct sk_buff *skb, struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + port_t *port = hdlc_to_port(hdlc); + + spin_lock(&port->lock); + + desc_t *desc = &get_status(port)->tx_descs[port->tx_out]; + if (desc->stat != PACKET_EMPTY) { + /* should never happen - previous xmit should stop queue */ +#ifdef DEBUG_PKT + printk(KERN_DEBUG "%s: transmitter buffer full\n", + port_name(port)); +#endif + netif_stop_queue(dev); + spin_unlock_irq(&port->lock); + return 1; /* request packet to be queued */ + } + +#ifdef DEBUG_PKT + printk(KERN_DEBUG "%s TX(%i):", port_name(port), skb->len); + debug_frame(skb); +#endif + + port->tx_skbs[port->tx_out] = skb; + desc->address = pci_map_single(port->card->pdev, skb->data, skb->len, + PCI_DMA_TODEVICE); + desc->length = skb->len; + desc->stat = PACKET_FULL; + writel(1 << (DOORBELL_TO_CARD_TX_0 + port->node), + port->card->plx + PLX_DOORBELL_TO_CARD); + dev->trans_start = jiffies; + + port->tx_out = (port->tx_out + 1) % TX_BUFFERS; + + if (get_status(port)->tx_descs[port->tx_out].stat != PACKET_EMPTY) { + netif_stop_queue(dev); +#ifdef DEBUG_PKT + printk(KERN_DEBUG "%s: transmitter buffer full\n", + port_name(port)); +#endif + } + + spin_unlock(&port->lock); + return 0; +} + + + +static int wanxl_attach(hdlc_device *hdlc, unsigned short encoding, + unsigned short parity) +{ + port_t *port = hdlc_to_port(hdlc); + + if (encoding != ENCODING_NRZ && + encoding != ENCODING_NRZI) + return -EINVAL; + + if (parity != PARITY_NONE && + parity != PARITY_CRC32_PR1_CCITT && + parity != PARITY_CRC16_PR1_CCITT && + parity != PARITY_CRC32_PR0_CCITT && + parity != PARITY_CRC16_PR0_CCITT) + return -EINVAL; + + get_status(port)->encoding = encoding; + get_status(port)->parity = parity; + return 0; +} + + + +static int wanxl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + const size_t size = sizeof(sync_serial_settings); + sync_serial_settings line; + hdlc_device *hdlc = dev_to_hdlc(dev); + port_t *port = hdlc_to_port(hdlc); + + if (cmd != SIOCWANDEV) + return hdlc_ioctl(dev, ifr, cmd); + + switch (ifr->ifr_settings.type) { + case IF_GET_IFACE: + ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } + line.clock_type = get_status(port)->clocking; + line.clock_rate = 0; + line.loopback = 0; + + if (copy_to_user(ifr->ifr_settings.ifs_ifsu.sync, &line, size)) + return -EFAULT; + return 0; + + case IF_IFACE_SYNC_SERIAL: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (dev->flags & IFF_UP) + return -EBUSY; + + if (copy_from_user(&line, ifr->ifr_settings.ifs_ifsu.sync, + size)) + return -EFAULT; + + if (line.clock_type != CLOCK_EXT && + line.clock_type != CLOCK_TXFROMRX) + return -EINVAL; /* No such clock setting */ + + if (line.loopback != 0) + return -EINVAL; + + get_status(port)->clocking = line.clock_type; + return 0; + + default: + return hdlc_ioctl(dev, ifr, cmd); + } +} + + + +static int wanxl_open(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + port_t *port = hdlc_to_port(hdlc); + u8 *dbr = port->card->plx + PLX_DOORBELL_TO_CARD; + unsigned long timeout; + int i; + + if (get_status(port)->open) { + printk(KERN_ERR "%s: port already open\n", port_name(port)); + return -EIO; + } + if ((i = hdlc_open(hdlc)) != 0) + return i; + + port->tx_in = port->tx_out = 0; + for (i = 0; i < TX_BUFFERS; i++) + get_status(port)->tx_descs[i].stat = PACKET_EMPTY; + /* signal the card */ + writel(1 << (DOORBELL_TO_CARD_OPEN_0 + port->node), dbr); + + timeout = jiffies + HZ; + do + if (get_status(port)->open) + return 0; + while (time_after(timeout, jiffies)); + + printk(KERN_ERR "%s: unable to open port\n", port_name(port)); + /* ask the card to close the port, should it be still alive */ + writel(1 << (DOORBELL_TO_CARD_CLOSE_0 + port->node), dbr); + return -EFAULT; +} + + + +static int wanxl_close(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + port_t *port = hdlc_to_port(hdlc); + unsigned long timeout; + int i; + + hdlc_close(hdlc); + /* signal the card */ + writel(1 << (DOORBELL_TO_CARD_CLOSE_0 + port->node), + port->card->plx + PLX_DOORBELL_TO_CARD); + + timeout = jiffies + HZ; + do + if (!get_status(port)->open) + break; + while (time_after(timeout, jiffies)); + + if (get_status(port)->open) + printk(KERN_ERR "%s: unable to close port\n", port_name(port)); + + for (i = 0; i < TX_BUFFERS; i++) { + desc_t *desc = &get_status(port)->tx_descs[i]; + + if (desc->stat != PACKET_EMPTY) { + desc->stat = PACKET_EMPTY; + pci_unmap_single(port->card->pdev, desc->address, + port->tx_skbs[i]->len, + PCI_DMA_TODEVICE); + dev_kfree_skb(port->tx_skbs[i]); + } + } + return 0; +} + + + +static struct net_device_stats *wanxl_get_stats(struct net_device *dev) +{ + hdlc_device *hdlc = dev_to_hdlc(dev); + port_t *port = hdlc_to_port(hdlc); + + hdlc->stats.rx_over_errors = get_status(port)->rx_overruns; + hdlc->stats.rx_frame_errors = get_status(port)->rx_frame_errors; + hdlc->stats.rx_errors = hdlc->stats.rx_over_errors + + hdlc->stats.rx_frame_errors; + return &hdlc->stats; +} + + + +static int wanxl_puts_command(card_t *card, u32 cmd) +{ + unsigned long timeout = jiffies + 5 * HZ; + + writel(cmd, card->plx + PLX_MAILBOX_1); + do { + if (readl(card->plx + PLX_MAILBOX_1) == 0) + return 0; + + schedule(); + }while (time_after(timeout, jiffies)); + + return -1; +} + + + +static void wanxl_reset(card_t *card) +{ + u32 old_value = readl(card->plx + PLX_CONTROL) & ~PLX_CTL_RESET; + + writel(0x80, card->plx + PLX_MAILBOX_0); + writel(old_value | PLX_CTL_RESET, card->plx + PLX_CONTROL); + readl(card->plx + PLX_CONTROL); /* wait for posted write */ + udelay(1); + writel(old_value, card->plx + PLX_CONTROL); + readl(card->plx + PLX_CONTROL); /* wait for posted write */ +} + + + +static void wanxl_pci_remove_one(struct pci_dev *pdev) +{ + card_t *card = pci_get_drvdata(pdev); + int i; + + /* unregister and free all host resources */ + if (card->irq) + free_irq(card->irq, card); + + for (i = 0; i < 4; i++) + if (card->ports[i]) + unregister_hdlc_device(&card->ports[i]->hdlc); + + wanxl_reset(card); + + for (i = 0; i < RX_QUEUE_LENGTH; i++) + if (card->rx_skbs[i]) { + pci_unmap_single(card->pdev, + card->status->rx_descs[i].address, + BUFFER_LENGTH, PCI_DMA_FROMDEVICE); + dev_kfree_skb(card->rx_skbs[i]); + } + + if (card->plx) + iounmap(card->plx); + + if (card->status) + pci_free_consistent(pdev, sizeof(card_status_t), + card->status, card->status_address); + + pci_set_drvdata(pdev, NULL); + kfree(card); + pci_release_regions(pdev); +} + + +#include "wanxlfw.inc" + +static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + card_t *card; + u32 ramsize, stat; + unsigned long timeout; + u32 plx_phy; /* PLX PCI base address */ + u32 mem_phy; /* memory PCI base addr */ + u8 *mem; /* memory virtual base addr */ + int i, ports, alloc_size; + + i = pci_enable_device(pdev); + if (i) + return i; + + /* QUICC can only access first 256 MB of host RAM directly, + but PLX9060 DMA does 32-bits for actual packet data transfers */ + + /* FIXME when PCI/DMA subsystems are fixed. + We set both dma_mask and consistent_dma_mask to 28 bits + and pray pci_alloc_consistent() will use this info. It should + work on most platforms */ + if (pci_set_consistent_dma_mask(pdev, 0x0FFFFFFF) || + pci_set_dma_mask(pdev, 0x0FFFFFFF)) { + printk(KERN_ERR "No usable DMA configuration\n"); + return -EIO; + } + + i = pci_request_regions(pdev, "wanXL"); + if (i) + return i; + + switch (pdev->device) { + case PCI_DEVICE_ID_SBE_WANXL100: ports = 1; break; + case PCI_DEVICE_ID_SBE_WANXL200: ports = 2; break; + default: ports = 4; + } + + alloc_size = sizeof(card_t) + ports * sizeof(port_t); + card = kmalloc(alloc_size, GFP_KERNEL); + if (card == NULL) { + printk(KERN_ERR "wanXL %s: unable to allocate memory\n", + card_name(pdev)); + pci_release_regions(pdev); + return -ENOBUFS; + } + memset(card, 0, alloc_size); + + pci_set_drvdata(pdev, card); + card->pdev = pdev; + card->n_ports = ports; + + card->status = pci_alloc_consistent(pdev, sizeof(card_status_t), + &card->status_address); + if (card->status == NULL) { + wanxl_pci_remove_one(pdev); + return -ENOBUFS; + } + +#ifdef DEBUG_PCI + printk(KERN_DEBUG "wanXL %s: pci_alloc_consistent() returned memory" + " at 0x%X\n", card_name(pdev), card->status_address); +#endif + + /* FIXME when PCI/DMA subsystems are fixed. + We set both dma_mask and consistent_dma_mask back to 32 bits + to indicate the card can do 32-bit DMA addressing */ + if (pci_set_consistent_dma_mask(pdev, 0xFFFFFFFF) || + pci_set_dma_mask(pdev, 0xFFFFFFFF)) { + printk(KERN_ERR "No usable DMA configuration\n"); + wanxl_pci_remove_one(pdev); + return -EIO; + } + + /* set up PLX mapping */ + plx_phy = pci_resource_start(pdev, 0); + card->plx = ioremap_nocache(plx_phy, 0x70); + +#if RESET_WHILE_LOADING + wanxl_reset(card); +#endif + + timeout = jiffies + 20 * HZ; + while ((stat = readl(card->plx + PLX_MAILBOX_0)) != 0) { + if (time_before(timeout, jiffies)) { + printk(KERN_WARNING "wanXL %s: timeout waiting for" + " PUTS to complete\n", card_name(pdev)); + wanxl_pci_remove_one(pdev); + return -ENODEV; + } + + switch(stat & 0xC0) { + case 0x00: /* hmm - PUTS completed with non-zero code? */ + case 0x80: /* PUTS still testing the hardware */ + break; + + default: + printk(KERN_WARNING "wanXL %s: PUTS test 0x%X" + " failed\n", card_name(pdev), stat & 0x30); + wanxl_pci_remove_one(pdev); + return -ENODEV; + } + + schedule(); + } + + /* get on-board memory size (PUTS detects no more than 4 MB) */ + ramsize = readl(card->plx + PLX_MAILBOX_2) & MBX2_MEMSZ_MASK; + + /* set up on-board RAM mapping */ + mem_phy = pci_resource_start(pdev, 2); + + + /* sanity check the board's reported memory size */ + if (ramsize < BUFFERS_ADDR + + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports) { + printk(KERN_WARNING "wanXL %s: no enough on-board RAM" + " (%u bytes detected, %u bytes required)\n", + card_name(pdev), ramsize, BUFFERS_ADDR + + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports); + wanxl_pci_remove_one(pdev); + return -ENODEV; + } + + if (wanxl_puts_command(card, MBX1_CMD_BSWAP)) { + printk(KERN_WARNING "wanXL %s: unable to Set Byte Swap" + " Mode\n", card_name(pdev)); + wanxl_pci_remove_one(pdev); + return -ENODEV; + } + + for (i = 0; i < ports; i++) { + port_t *port = (void *)card + sizeof(card_t) + + i * sizeof(port_t); + struct net_device *dev = hdlc_to_dev(&port->hdlc); + spin_lock_init(&port->lock); + SET_MODULE_OWNER(dev); + dev->tx_queue_len = 50; + dev->do_ioctl = wanxl_ioctl; + dev->open = wanxl_open; + dev->stop = wanxl_close; + port->hdlc.attach = wanxl_attach; + port->hdlc.xmit = wanxl_xmit; + if(register_hdlc_device(&port->hdlc)) { + printk(KERN_ERR "wanXL %s: unable to register hdlc" + " device\n", card_name(pdev)); + wanxl_pci_remove_one(pdev); + return -ENOBUFS; + } + card->ports[i] = port; + dev->get_stats = wanxl_get_stats; + port->card = card; + port->node = i; + get_status(port)->clocking = CLOCK_EXT; + } + + for (i = 0; i < RX_QUEUE_LENGTH; i++) { + struct sk_buff *skb = dev_alloc_skb(BUFFER_LENGTH); + card->rx_skbs[i] = skb; + if (skb) + card->status->rx_descs[i].address = + pci_map_single(card->pdev, skb->data, + BUFFER_LENGTH, + PCI_DMA_FROMDEVICE); + } + + mem = ioremap_nocache(mem_phy, PDM_OFFSET + sizeof(firmware)); + for (i = 0; i < sizeof(firmware); i += 4) + writel(htonl(*(u32*)(firmware + i)), mem + PDM_OFFSET + i); + + for (i = 0; i < ports; i++) + writel(card->status_address + + (void *)&card->status->port_status[i] - + (void *)card->status, mem + PDM_OFFSET + 4 + i * 4); + writel(card->status_address, mem + PDM_OFFSET + 20); + writel(PDM_OFFSET, mem); + iounmap(mem); + + writel(0, card->plx + PLX_MAILBOX_5); + + if (wanxl_puts_command(card, MBX1_CMD_ABORTJ)) { + printk(KERN_WARNING "wanXL %s: unable to Abort and Jump\n", + card_name(pdev)); + wanxl_pci_remove_one(pdev); + return -ENODEV; + } + + stat = 0; + timeout = jiffies + 5 * HZ; + do { + if ((stat = readl(card->plx + PLX_MAILBOX_5)) != 0) + break; + schedule(); + }while (time_after(timeout, jiffies)); + + if (!stat) { + printk(KERN_WARNING "wanXL %s: timeout while initializing card" + "firmware\n", card_name(pdev)); + wanxl_pci_remove_one(pdev); + return -ENODEV; + } + +#if DETECT_RAM + ramsize = stat; +#endif + + printk(KERN_INFO "wanXL %s: at 0x%X, %u KB of RAM at 0x%X, irq" + " %u\n" KERN_INFO "wanXL %s: port", card_name(pdev), + plx_phy, ramsize / 1024, mem_phy, pdev->irq, card_name(pdev)); + + for (i = 0; i < ports; i++) + printk("%s #%i: %s", i ? "," : "", i, + port_name(card->ports[i])); + printk("\n"); + + /* Allocate IRQ */ + if(request_irq(pdev->irq, wanxl_intr, SA_SHIRQ, "wanXL", card)) { + printk(KERN_WARNING "wanXL %s: could not allocate IRQ%i.\n", + card_name(pdev), pdev->irq); + wanxl_pci_remove_one(pdev); + return -EBUSY; + } + card->irq = pdev->irq; + + return 0; +} + +static struct pci_device_id wanxl_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL100, PCI_ANY_ID, + PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL200, PCI_ANY_ID, + PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_SBE_WANXL400, PCI_ANY_ID, + PCI_ANY_ID, 0, 0, 0 }, + { 0, } +}; + + +static struct pci_driver wanxl_pci_driver = { + name: "wanXL", + id_table: wanxl_pci_tbl, + probe: wanxl_pci_init_one, + remove: wanxl_pci_remove_one, +}; + + +static int __init wanxl_init_module(void) +{ +#ifdef MODULE + printk(KERN_INFO "%s\n", version); +#endif + return pci_module_init(&wanxl_pci_driver); +} + +static void __exit wanxl_cleanup_module(void) +{ + pci_unregister_driver(&wanxl_pci_driver); +} + + +MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); +MODULE_DESCRIPTION("SBE Inc. wanXL serial port driver"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(pci, wanxl_pci_tbl); + +module_init(wanxl_init_module); +module_exit(wanxl_cleanup_module); diff --git a/drivers/net/wan/wanxl.h b/drivers/net/wan/wanxl.h new file mode 100644 index 000000000000..3f86558f8a6b --- /dev/null +++ b/drivers/net/wan/wanxl.h @@ -0,0 +1,152 @@ +/* + * wanXL serial card driver for Linux + * definitions common to host driver and card firmware + * + * Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#define RESET_WHILE_LOADING 0 + +/* you must rebuild the firmware if any of the following is changed */ +#define DETECT_RAM 0 /* needed for > 4MB RAM, 16 MB maximum */ +#define QUICC_MEMCPY_USES_PLX 1 /* must be used if the host has > 256 MB RAM */ + + +#define STATUS_CABLE_V35 2 +#define STATUS_CABLE_X21 3 +#define STATUS_CABLE_V24 4 +#define STATUS_CABLE_EIA530 5 +#define STATUS_CABLE_INVALID 6 +#define STATUS_CABLE_NONE 7 + +#define STATUS_CABLE_DCE 0x8000 +#define STATUS_CABLE_DSR 0x0010 +#define STATUS_CABLE_DCD 0x0008 +#define STATUS_CABLE_PM_SHIFT 5 + +#define PDM_OFFSET 0x1000 + +#define TX_BUFFERS 10 /* per port */ +#define RX_BUFFERS 30 +#define RX_QUEUE_LENGTH 40 /* card->host queue length - per card */ + +#define PACKET_EMPTY 0x00 +#define PACKET_FULL 0x10 +#define PACKET_SENT 0x20 /* TX only */ +#define PACKET_UNDERRUN 0x30 /* TX only */ +#define PACKET_PORT_MASK 0x03 /* RX only */ + +/* bit numbers in PLX9060 doorbell registers */ +#define DOORBELL_FROM_CARD_TX_0 0 /* packet sent by the card */ +#define DOORBELL_FROM_CARD_TX_1 1 +#define DOORBELL_FROM_CARD_TX_2 2 +#define DOORBELL_FROM_CARD_TX_3 3 +#define DOORBELL_FROM_CARD_RX 4 +#define DOORBELL_FROM_CARD_CABLE_0 5 /* cable/PM/etc. changed */ +#define DOORBELL_FROM_CARD_CABLE_1 6 +#define DOORBELL_FROM_CARD_CABLE_2 7 +#define DOORBELL_FROM_CARD_CABLE_3 8 + +#define DOORBELL_TO_CARD_OPEN_0 0 +#define DOORBELL_TO_CARD_OPEN_1 1 +#define DOORBELL_TO_CARD_OPEN_2 2 +#define DOORBELL_TO_CARD_OPEN_3 3 +#define DOORBELL_TO_CARD_CLOSE_0 4 +#define DOORBELL_TO_CARD_CLOSE_1 5 +#define DOORBELL_TO_CARD_CLOSE_2 6 +#define DOORBELL_TO_CARD_CLOSE_3 7 +#define DOORBELL_TO_CARD_TX_0 8 /* outbound packet queued */ +#define DOORBELL_TO_CARD_TX_1 9 +#define DOORBELL_TO_CARD_TX_2 10 +#define DOORBELL_TO_CARD_TX_3 11 + +/* firmware-only status bits, starting from last DOORBELL_TO_CARD + 1 */ +#define TASK_SCC_0 12 +#define TASK_SCC_1 13 +#define TASK_SCC_2 14 +#define TASK_SCC_3 15 + +#define ALIGN32(x) (((x) + 3) & 0xFFFFFFFC) +#define BUFFER_LENGTH ALIGN32(HDLC_MAX_MRU + 4) /* 4 bytes for 32-bit CRC */ + +/* Address of TX and RX buffers in 68360 address space */ +#define BUFFERS_ADDR 0x4000 /* 16 KB */ + +#ifndef __ASSEMBLER__ +#define PLX_OFFSET 0 +#else +#define PLX_OFFSET PLX + 0x80 +#endif + +#define PLX_MAILBOX_0 (PLX_OFFSET + 0x40) +#define PLX_MAILBOX_1 (PLX_OFFSET + 0x44) +#define PLX_MAILBOX_2 (PLX_OFFSET + 0x48) +#define PLX_MAILBOX_3 (PLX_OFFSET + 0x4C) +#define PLX_MAILBOX_4 (PLX_OFFSET + 0x50) +#define PLX_MAILBOX_5 (PLX_OFFSET + 0x54) +#define PLX_MAILBOX_6 (PLX_OFFSET + 0x58) +#define PLX_MAILBOX_7 (PLX_OFFSET + 0x5C) +#define PLX_DOORBELL_TO_CARD (PLX_OFFSET + 0x60) +#define PLX_DOORBELL_FROM_CARD (PLX_OFFSET + 0x64) +#define PLX_INTERRUPT_CS (PLX_OFFSET + 0x68) +#define PLX_CONTROL (PLX_OFFSET + 0x6C) + +#ifdef __ASSEMBLER__ +#define PLX_DMA_0_MODE (PLX + 0x100) +#define PLX_DMA_0_PCI (PLX + 0x104) +#define PLX_DMA_0_LOCAL (PLX + 0x108) +#define PLX_DMA_0_LENGTH (PLX + 0x10C) +#define PLX_DMA_0_DESC (PLX + 0x110) +#define PLX_DMA_1_MODE (PLX + 0x114) +#define PLX_DMA_1_PCI (PLX + 0x118) +#define PLX_DMA_1_LOCAL (PLX + 0x11C) +#define PLX_DMA_1_LENGTH (PLX + 0x120) +#define PLX_DMA_1_DESC (PLX + 0x124) +#define PLX_DMA_CMD_STS (PLX + 0x128) +#define PLX_DMA_ARBITR_0 (PLX + 0x12C) +#define PLX_DMA_ARBITR_1 (PLX + 0x130) +#endif + +#define DESC_LENGTH 12 + +/* offsets from start of status_t */ +/* card to host */ +#define STATUS_OPEN 0 +#define STATUS_CABLE (STATUS_OPEN + 4) +#define STATUS_RX_OVERRUNS (STATUS_CABLE + 4) +#define STATUS_RX_FRAME_ERRORS (STATUS_RX_OVERRUNS + 4) + +/* host to card */ +#define STATUS_PARITY (STATUS_RX_FRAME_ERRORS + 4) +#define STATUS_ENCODING (STATUS_PARITY + 4) +#define STATUS_CLOCKING (STATUS_ENCODING + 4) +#define STATUS_TX_DESCS (STATUS_CLOCKING + 4) + +#ifndef __ASSEMBLER__ + +typedef struct { + volatile u32 stat; + u32 address; /* PCI address */ + volatile u32 length; +}desc_t; + + +typedef struct { +// Card to host + volatile u32 open; + volatile u32 cable; + volatile u32 rx_overruns; + volatile u32 rx_frame_errors; + +// Host to card + u32 parity; + u32 encoding; + u32 clocking; + desc_t tx_descs[TX_BUFFERS]; +}port_status_t; + +#endif /* __ASSEMBLER__ */ diff --git a/drivers/net/wan/wanxlfw.S b/drivers/net/wan/wanxlfw.S new file mode 100644 index 000000000000..73aae2bf2f1c --- /dev/null +++ b/drivers/net/wan/wanxlfw.S @@ -0,0 +1,895 @@ +.psize 0 +/* + wanXL serial card driver for Linux + card firmware part + + Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl> + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + + + + DPRAM BDs: + 0x000 - 0x050 TX#0 0x050 - 0x140 RX#0 + 0x140 - 0x190 TX#1 0x190 - 0x280 RX#1 + 0x280 - 0x2D0 TX#2 0x2D0 - 0x3C0 RX#2 + 0x3C0 - 0x410 TX#3 0x410 - 0x500 RX#3 + + + 000 5FF 1536 Bytes Dual-Port RAM User Data / BDs + 600 6FF 256 Bytes Dual-Port RAM User Data / BDs + 700 7FF 256 Bytes Dual-Port RAM User Data / BDs + C00 CBF 192 Bytes Dual-Port RAM Parameter RAM Page 1 + D00 DBF 192 Bytes Dual-Port RAM Parameter RAM Page 2 + E00 EBF 192 Bytes Dual-Port RAM Parameter RAM Page 3 + F00 FBF 192 Bytes Dual-Port RAM Parameter RAM Page 4 + + local interrupts level + NMI 7 + PIT timer, CPM (RX/TX complete) 4 + PCI9060 DMA and PCI doorbells 3 + Cable - not used 1 +*/ + +#include <linux/hdlc.h> +#include "wanxl.h" + +/* memory addresses and offsets */ + +MAX_RAM_SIZE = 16 * 1024 * 1024 // max RAM supported by hardware + +PCI9060_VECTOR = 0x0000006C +CPM_IRQ_BASE = 0x40 +ERROR_VECTOR = CPM_IRQ_BASE * 4 +SCC1_VECTOR = (CPM_IRQ_BASE + 0x1E) * 4 +SCC2_VECTOR = (CPM_IRQ_BASE + 0x1D) * 4 +SCC3_VECTOR = (CPM_IRQ_BASE + 0x1C) * 4 +SCC4_VECTOR = (CPM_IRQ_BASE + 0x1B) * 4 +CPM_IRQ_LEVEL = 4 +TIMER_IRQ = 128 +TIMER_IRQ_LEVEL = 4 +PITR_CONST = 0x100 + 16 // 1 Hz timer + +MBAR = 0x0003FF00 + +VALUE_WINDOW = 0x40000000 +ORDER_WINDOW = 0xC0000000 + +PLX = 0xFFF90000 + +CSRA = 0xFFFB0000 +CSRB = 0xFFFB0002 +CSRC = 0xFFFB0004 +CSRD = 0xFFFB0006 +STATUS_CABLE_LL = 0x2000 +STATUS_CABLE_DTR = 0x1000 + +DPRBASE = 0xFFFC0000 + +SCC1_BASE = DPRBASE + 0xC00 +MISC_BASE = DPRBASE + 0xCB0 +SCC2_BASE = DPRBASE + 0xD00 +SCC3_BASE = DPRBASE + 0xE00 +SCC4_BASE = DPRBASE + 0xF00 + +// offset from SCCx_BASE +// SCC_xBASE contain offsets from DPRBASE and must be divisible by 8 +SCC_RBASE = 0 // 16-bit RxBD base address +SCC_TBASE = 2 // 16-bit TxBD base address +SCC_RFCR = 4 // 8-bit Rx function code +SCC_TFCR = 5 // 8-bit Tx function code +SCC_MRBLR = 6 // 16-bit maximum Rx buffer length +SCC_C_MASK = 0x34 // 32-bit CRC constant +SCC_C_PRES = 0x38 // 32-bit CRC preset +SCC_MFLR = 0x46 // 16-bit max Rx frame length (without flags) + +REGBASE = DPRBASE + 0x1000 +PICR = REGBASE + 0x026 // 16-bit periodic irq control +PITR = REGBASE + 0x02A // 16-bit periodic irq timing +OR1 = REGBASE + 0x064 // 32-bit RAM bank #1 options +CICR = REGBASE + 0x540 // 32(24)-bit CP interrupt config +CIMR = REGBASE + 0x548 // 32-bit CP interrupt mask +CISR = REGBASE + 0x54C // 32-bit CP interrupts in-service +PADIR = REGBASE + 0x550 // 16-bit PortA data direction bitmap +PAPAR = REGBASE + 0x552 // 16-bit PortA pin assignment bitmap +PAODR = REGBASE + 0x554 // 16-bit PortA open drain bitmap +PADAT = REGBASE + 0x556 // 16-bit PortA data register + +PCDIR = REGBASE + 0x560 // 16-bit PortC data direction bitmap +PCPAR = REGBASE + 0x562 // 16-bit PortC pin assignment bitmap +PCSO = REGBASE + 0x564 // 16-bit PortC special options +PCDAT = REGBASE + 0x566 // 16-bit PortC data register +PCINT = REGBASE + 0x568 // 16-bit PortC interrupt control +CR = REGBASE + 0x5C0 // 16-bit Command register + +SCC1_REGS = REGBASE + 0x600 +SCC2_REGS = REGBASE + 0x620 +SCC3_REGS = REGBASE + 0x640 +SCC4_REGS = REGBASE + 0x660 +SICR = REGBASE + 0x6EC // 32-bit SI clock route + +// offset from SCCx_REGS +SCC_GSMR_L = 0x00 // 32 bits +SCC_GSMR_H = 0x04 // 32 bits +SCC_PSMR = 0x08 // 16 bits +SCC_TODR = 0x0C // 16 bits +SCC_DSR = 0x0E // 16 bits +SCC_SCCE = 0x10 // 16 bits +SCC_SCCM = 0x14 // 16 bits +SCC_SCCS = 0x17 // 8 bits + +#if QUICC_MEMCPY_USES_PLX + .macro memcpy_from_pci src, dest, len // len must be < 8 MB + addl #3, \len + andl #0xFFFFFFFC, \len // always copy n * 4 bytes + movel \src, PLX_DMA_0_PCI + movel \dest, PLX_DMA_0_LOCAL + movel \len, PLX_DMA_0_LENGTH + movel #0x0103, PLX_DMA_CMD_STS // start channel 0 transfer + bsr memcpy_from_pci_run + .endm + + .macro memcpy_to_pci src, dest, len + addl #3, \len + andl #0xFFFFFFFC, \len // always copy n * 4 bytes + movel \src, PLX_DMA_1_LOCAL + movel \dest, PLX_DMA_1_PCI + movel \len, PLX_DMA_1_LENGTH + movel #0x0301, PLX_DMA_CMD_STS // start channel 1 transfer + bsr memcpy_to_pci_run + .endm + +#else + + .macro memcpy src, dest, len // len must be < 65536 bytes + movel %d7, -(%sp) // src and dest must be < 256 MB + movel \len, %d7 // bits 0 and 1 + lsrl #2, \len + andl \len, \len + beq 99f // only 0 - 3 bytes + subl #1, \len // for dbf +98: movel (\src)+, (\dest)+ + dbfw \len, 98b +99: movel %d7, \len + btstl #1, \len + beq 99f + movew (\src)+, (\dest)+ +99: btstl #0, \len + beq 99f + moveb (\src)+, (\dest)+ +99: + movel (%sp)+, %d7 + .endm + + .macro memcpy_from_pci src, dest, len + addl #VALUE_WINDOW, \src + memcpy \src, \dest, \len + .endm + + .macro memcpy_to_pci src, dest, len + addl #VALUE_WINDOW, \dest + memcpy \src, \dest, \len + .endm +#endif + + + .macro wait_for_command +99: btstl #0, CR + bne 99b + .endm + + + + +/****************************** card initialization *******************/ + .text + .global _start +_start: bra init + + .org _start + 4 +ch_status_addr: .long 0, 0, 0, 0 +rx_descs_addr: .long 0 + +init: +#if DETECT_RAM + movel OR1, %d0 + andl #0xF00007FF, %d0 // mask AMxx bits + orl #0xFFFF800 & ~(MAX_RAM_SIZE - 1), %d0 // update RAM bank size + movel %d0, OR1 +#endif + + addl #VALUE_WINDOW, rx_descs_addr // PCI addresses of shared data + clrl %d0 // D0 = 4 * port +init_1: tstl ch_status_addr(%d0) + beq init_2 + addl #VALUE_WINDOW, ch_status_addr(%d0) +init_2: addl #4, %d0 + cmpl #4 * 4, %d0 + bne init_1 + + movel #pci9060_interrupt, PCI9060_VECTOR + movel #error_interrupt, ERROR_VECTOR + movel #port_interrupt_1, SCC1_VECTOR + movel #port_interrupt_2, SCC2_VECTOR + movel #port_interrupt_3, SCC3_VECTOR + movel #port_interrupt_4, SCC4_VECTOR + movel #timer_interrupt, TIMER_IRQ * 4 + + movel #0x78000000, CIMR // only SCCx IRQs from CPM + movew #(TIMER_IRQ_LEVEL << 8) + TIMER_IRQ, PICR // interrupt from PIT + movew #PITR_CONST, PITR + + // SCC1=SCCa SCC2=SCCb SCC3=SCCc SCC4=SCCd prio=4 HP=-1 IRQ=64-79 + movel #0xD41F40 + (CPM_IRQ_LEVEL << 13), CICR + movel #0x543, PLX_DMA_0_MODE // 32-bit, Ready, Burst, IRQ + movel #0x543, PLX_DMA_1_MODE + movel #0x0, PLX_DMA_0_DESC // from PCI to local + movel #0x8, PLX_DMA_1_DESC // from local to PCI + movel #0x101, PLX_DMA_CMD_STS // enable both DMA channels + // enable local IRQ, DMA, doorbells and PCI IRQ + orl #0x000F0300, PLX_INTERRUPT_CS + +#if DETECT_RAM + bsr ram_test +#else + movel #1, PLX_MAILBOX_5 // non-zero value = init complete +#endif + bsr check_csr + + movew #0xFFFF, PAPAR // all pins are clocks/data + clrw PADIR // first function + clrw PCSO // CD and CTS always active + + +/****************************** main loop *****************************/ + +main: movel channel_stats, %d7 // D7 = doorbell + irq status + clrl channel_stats + + tstl %d7 + bne main_1 + // nothing to do - wait for next event + stop #0x2200 // supervisor + IRQ level 2 + movew #0x2700, %sr // disable IRQs again + bra main + +main_1: clrl %d0 // D0 = 4 * port + clrl %d6 // D6 = doorbell to host value + +main_l: btstl #DOORBELL_TO_CARD_CLOSE_0, %d7 + beq main_op + bclrl #DOORBELL_TO_CARD_OPEN_0, %d7 // in case both bits are set + bsr close_port +main_op: + btstl #DOORBELL_TO_CARD_OPEN_0, %d7 + beq main_cl + bsr open_port +main_cl: + btstl #DOORBELL_TO_CARD_TX_0, %d7 + beq main_txend + bsr tx +main_txend: + btstl #TASK_SCC_0, %d7 + beq main_next + bsr tx_end + bsr rx + +main_next: + lsrl #1, %d7 // port status for next port + addl #4, %d0 // D0 = 4 * next port + cmpl #4 * 4, %d0 + bne main_l + movel %d6, PLX_DOORBELL_FROM_CARD // signal the host + bra main + + +/****************************** open port *****************************/ + +open_port: // D0 = 4 * port, D6 = doorbell to host + movel ch_status_addr(%d0), %a0 // A0 = port status address + tstl STATUS_OPEN(%a0) + bne open_port_ret // port already open + movel #1, STATUS_OPEN(%a0) // confirm the port is open +// setup BDs + clrl tx_in(%d0) + clrl tx_out(%d0) + clrl tx_count(%d0) + clrl rx_in(%d0) + + movel SICR, %d1 // D1 = clock settings in SICR + andl clocking_mask(%d0), %d1 + cmpl #CLOCK_TXFROMRX, STATUS_CLOCKING(%a0) + bne open_port_clock_ext + orl clocking_txfromrx(%d0), %d1 + bra open_port_set_clock + +open_port_clock_ext: + orl clocking_ext(%d0), %d1 +open_port_set_clock: + movel %d1, SICR // update clock settings in SICR + + orw #STATUS_CABLE_DTR, csr_output(%d0) // DTR on + bsr check_csr // call with disabled timer interrupt + +// Setup TX descriptors + movel first_buffer(%d0), %d1 // D1 = starting buffer address + movel tx_first_bd(%d0), %a1 // A1 = starting TX BD address + movel #TX_BUFFERS - 2, %d2 // D2 = TX_BUFFERS - 1 counter + movel #0x18000000, %d3 // D3 = initial TX BD flags: Int + Last + cmpl #PARITY_NONE, STATUS_PARITY(%a0) + beq open_port_tx_loop + bsetl #26, %d3 // TX BD flag: Transmit CRC +open_port_tx_loop: + movel %d3, (%a1)+ // TX flags + length + movel %d1, (%a1)+ // buffer address + addl #BUFFER_LENGTH, %d1 + dbfw %d2, open_port_tx_loop + + bsetl #29, %d3 // TX BD flag: Wrap (last BD) + movel %d3, (%a1)+ // Final TX flags + length + movel %d1, (%a1)+ // buffer address + +// Setup RX descriptors // A1 = starting RX BD address + movel #RX_BUFFERS - 2, %d2 // D2 = RX_BUFFERS - 1 counter +open_port_rx_loop: + movel #0x90000000, (%a1)+ // RX flags + length + movel %d1, (%a1)+ // buffer address + addl #BUFFER_LENGTH, %d1 + dbfw %d2, open_port_rx_loop + + movel #0xB0000000, (%a1)+ // Final RX flags + length + movel %d1, (%a1)+ // buffer address + +// Setup port parameters + movel scc_base_addr(%d0), %a1 // A1 = SCC_BASE address + movel scc_reg_addr(%d0), %a2 // A2 = SCC_REGS address + + movel #0xFFFF, SCC_SCCE(%a2) // clear status bits + movel #0x0000, SCC_SCCM(%a2) // interrupt mask + + movel tx_first_bd(%d0), %d1 + movew %d1, SCC_TBASE(%a1) // D1 = offset of first TxBD + addl #TX_BUFFERS * 8, %d1 + movew %d1, SCC_RBASE(%a1) // D1 = offset of first RxBD + moveb #0x8, SCC_RFCR(%a1) // Intel mode, 1000 + moveb #0x8, SCC_TFCR(%a1) + +// Parity settings + cmpl #PARITY_CRC16_PR1_CCITT, STATUS_PARITY(%a0) + bne open_port_parity_1 + clrw SCC_PSMR(%a2) // CRC16-CCITT + movel #0xF0B8, SCC_C_MASK(%a1) + movel #0xFFFF, SCC_C_PRES(%a1) + movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC + movew #2, parity_bytes(%d0) + bra open_port_2 + +open_port_parity_1: + cmpl #PARITY_CRC32_PR1_CCITT, STATUS_PARITY(%a0) + bne open_port_parity_2 + movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT + movel #0xDEBB20E3, SCC_C_MASK(%a1) + movel #0xFFFFFFFF, SCC_C_PRES(%a1) + movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC + movew #4, parity_bytes(%d0) + bra open_port_2 + +open_port_parity_2: + cmpl #PARITY_CRC16_PR0_CCITT, STATUS_PARITY(%a0) + bne open_port_parity_3 + clrw SCC_PSMR(%a2) // CRC16-CCITT preset 0 + movel #0xF0B8, SCC_C_MASK(%a1) + clrl SCC_C_PRES(%a1) + movew #HDLC_MAX_MRU + 2, SCC_MFLR(%a1) // 2 bytes for CRC + movew #2, parity_bytes(%d0) + bra open_port_2 + +open_port_parity_3: + cmpl #PARITY_CRC32_PR0_CCITT, STATUS_PARITY(%a0) + bne open_port_parity_4 + movew #0x0800, SCC_PSMR(%a2) // CRC32-CCITT preset 0 + movel #0xDEBB20E3, SCC_C_MASK(%a1) + clrl SCC_C_PRES(%a1) + movew #HDLC_MAX_MRU + 4, SCC_MFLR(%a1) // 4 bytes for CRC + movew #4, parity_bytes(%d0) + bra open_port_2 + +open_port_parity_4: + clrw SCC_PSMR(%a2) // no parity + movel #0xF0B8, SCC_C_MASK(%a1) + movel #0xFFFF, SCC_C_PRES(%a1) + movew #HDLC_MAX_MRU, SCC_MFLR(%a1) // 0 bytes for CRC + clrw parity_bytes(%d0) + +open_port_2: + movel #0x00000003, SCC_GSMR_H(%a2) // RTSM + cmpl #ENCODING_NRZI, STATUS_ENCODING(%a0) + bne open_port_nrz + movel #0x10040900, SCC_GSMR_L(%a2) // NRZI: TCI Tend RECN+TENC=1 + bra open_port_3 + +open_port_nrz: + movel #0x10040000, SCC_GSMR_L(%a2) // NRZ: TCI Tend RECN+TENC=0 +open_port_3: + movew #BUFFER_LENGTH, SCC_MRBLR(%a1) + movel %d0, %d1 + lsll #4, %d1 // D1 bits 7 and 6 = port + orl #1, %d1 + movew %d1, CR // Init SCC RX and TX params + wait_for_command + + // TCI Tend ENR ENT + movew #0x001F, SCC_SCCM(%a2) // TXE RXF BSY TXB RXB interrupts + orl #0x00000030, SCC_GSMR_L(%a2) // enable SCC +open_port_ret: + rts + + +/****************************** close port ****************************/ + +close_port: // D0 = 4 * port, D6 = doorbell to host + movel scc_reg_addr(%d0), %a0 // A0 = SCC_REGS address + clrw SCC_SCCM(%a0) // no SCC interrupts + andl #0xFFFFFFCF, SCC_GSMR_L(%a0) // Disable ENT and ENR + + andw #~STATUS_CABLE_DTR, csr_output(%d0) // DTR off + bsr check_csr // call with disabled timer interrupt + + movel ch_status_addr(%d0), %d1 + clrl STATUS_OPEN(%d1) // confirm the port is closed + rts + + +/****************************** transmit packet ***********************/ +// queue packets for transmission +tx: // D0 = 4 * port, D6 = doorbell to host + cmpl #TX_BUFFERS, tx_count(%d0) + beq tx_ret // all DB's = descs in use + + movel tx_out(%d0), %d1 + movel %d1, %d2 // D1 = D2 = tx_out BD# = desc# + mulul #DESC_LENGTH, %d2 // D2 = TX desc offset + addl ch_status_addr(%d0), %d2 + addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address + cmpl #PACKET_FULL, (%d2) // desc status + bne tx_ret + +// queue it + movel 4(%d2), %a0 // PCI address + lsll #3, %d1 // BD is 8-bytes long + addl tx_first_bd(%d0), %d1 // D1 = current tx_out BD addr + + movel 4(%d1), %a1 // A1 = dest address + movel 8(%d2), %d2 // D2 = length + movew %d2, 2(%d1) // length into BD + memcpy_from_pci %a0, %a1, %d2 + bsetl #31, (%d1) // CP go ahead + +// update tx_out and tx_count + movel tx_out(%d0), %d1 + addl #1, %d1 + cmpl #TX_BUFFERS, %d1 + bne tx_1 + clrl %d1 +tx_1: movel %d1, tx_out(%d0) + + addl #1, tx_count(%d0) + bra tx + +tx_ret: rts + + +/****************************** packet received ***********************/ + +// Service receive buffers // D0 = 4 * port, D6 = doorbell to host +rx: movel rx_in(%d0), %d1 // D1 = rx_in BD# + lsll #3, %d1 // BD is 8-bytes long + addl rx_first_bd(%d0), %d1 // D1 = current rx_in BD address + movew (%d1), %d2 // D2 = RX BD flags + btstl #15, %d2 + bne rx_ret // BD still empty + + btstl #1, %d2 + bne rx_overrun + + tstw parity_bytes(%d0) + bne rx_parity + bclrl #2, %d2 // do not test for CRC errors +rx_parity: + andw #0x0CBC, %d2 // mask status bits + cmpw #0x0C00, %d2 // correct frame + bne rx_bad_frame + clrl %d3 + movew 2(%d1), %d3 + subw parity_bytes(%d0), %d3 // D3 = packet length + cmpw #HDLC_MAX_MRU, %d3 + bgt rx_bad_frame + +rx_good_frame: + movel rx_out, %d2 + mulul #DESC_LENGTH, %d2 + addl rx_descs_addr, %d2 // D2 = RX desc address + cmpl #PACKET_EMPTY, (%d2) // desc stat + bne rx_overrun + + movel %d3, 8(%d2) + movel 4(%d1), %a0 // A0 = source address + movel 4(%d2), %a1 + tstl %a1 + beq rx_ignore_data + memcpy_to_pci %a0, %a1, %d3 +rx_ignore_data: + movel packet_full(%d0), (%d2) // update desc stat + +// update D6 and rx_out + bsetl #DOORBELL_FROM_CARD_RX, %d6 // signal host that RX completed + movel rx_out, %d2 + addl #1, %d2 + cmpl #RX_QUEUE_LENGTH, %d2 + bne rx_1 + clrl %d2 +rx_1: movel %d2, rx_out + +rx_free_bd: + andw #0xF000, (%d1) // clear CM and error bits + bsetl #31, (%d1) // free BD +// update rx_in + movel rx_in(%d0), %d1 + addl #1, %d1 + cmpl #RX_BUFFERS, %d1 + bne rx_2 + clrl %d1 +rx_2: movel %d1, rx_in(%d0) + bra rx + +rx_overrun: + movel ch_status_addr(%d0), %d2 + addl #1, STATUS_RX_OVERRUNS(%d2) + bra rx_free_bd + +rx_bad_frame: + movel ch_status_addr(%d0), %d2 + addl #1, STATUS_RX_FRAME_ERRORS(%d2) + bra rx_free_bd + +rx_ret: rts + + +/****************************** packet transmitted ********************/ + +// Service transmit buffers // D0 = 4 * port, D6 = doorbell to host +tx_end: tstl tx_count(%d0) + beq tx_end_ret // TX buffers already empty + + movel tx_in(%d0), %d1 + movel %d1, %d2 // D1 = D2 = tx_in BD# = desc# + lsll #3, %d1 // BD is 8-bytes long + addl tx_first_bd(%d0), %d1 // D1 = current tx_in BD address + movew (%d1), %d3 // D3 = TX BD flags + btstl #15, %d3 + bne tx_end_ret // BD still being transmitted + +// update D6, tx_in and tx_count + orl bell_tx(%d0), %d6 // signal host that TX desc freed + subl #1, tx_count(%d0) + movel tx_in(%d0), %d1 + addl #1, %d1 + cmpl #TX_BUFFERS, %d1 + bne tx_end_1 + clrl %d1 +tx_end_1: + movel %d1, tx_in(%d0) + +// free host's descriptor + mulul #DESC_LENGTH, %d2 // D2 = TX desc offset + addl ch_status_addr(%d0), %d2 + addl #STATUS_TX_DESCS, %d2 // D2 = TX desc address + btstl #1, %d3 + bne tx_end_underrun + movel #PACKET_SENT, (%d2) + bra tx_end + +tx_end_underrun: + movel #PACKET_UNDERRUN, (%d2) + bra tx_end + +tx_end_ret: rts + + +/****************************** PLX PCI9060 DMA memcpy ****************/ + +#if QUICC_MEMCPY_USES_PLX +// called with interrupts disabled +memcpy_from_pci_run: + movel %d0, -(%sp) + movew %sr, -(%sp) +memcpy_1: + movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly + btstl #4, %d0 // transfer done? + bne memcpy_end + stop #0x2200 // enable PCI9060 interrupts + movew #0x2700, %sr // disable interrupts again + bra memcpy_1 + +memcpy_to_pci_run: + movel %d0, -(%sp) + movew %sr, -(%sp) +memcpy_2: + movel PLX_DMA_CMD_STS, %d0 // do not btst PLX register directly + btstl #12, %d0 // transfer done? + bne memcpy_end + stop #0x2200 // enable PCI9060 interrupts + movew #0x2700, %sr // disable interrupts again + bra memcpy_2 + +memcpy_end: + movew (%sp)+, %sr + movel (%sp)+, %d0 + rts +#endif + + + + + + +/****************************** PLX PCI9060 interrupt *****************/ + +pci9060_interrupt: + movel %d0, -(%sp) + + movel PLX_DOORBELL_TO_CARD, %d0 + movel %d0, PLX_DOORBELL_TO_CARD // confirm all requests + orl %d0, channel_stats + + movel #0x0909, PLX_DMA_CMD_STS // clear DMA ch #0 and #1 interrupts + + movel (%sp)+, %d0 + rte + +/****************************** SCC interrupts ************************/ + +port_interrupt_1: + orl #0, SCC1_REGS + SCC_SCCE; // confirm SCC events + orl #1 << TASK_SCC_0, channel_stats + movel #0x40000000, CISR + rte + +port_interrupt_2: + orl #0, SCC2_REGS + SCC_SCCE; // confirm SCC events + orl #1 << TASK_SCC_1, channel_stats + movel #0x20000000, CISR + rte + +port_interrupt_3: + orl #0, SCC3_REGS + SCC_SCCE; // confirm SCC events + orl #1 << TASK_SCC_2, channel_stats + movel #0x10000000, CISR + rte + +port_interrupt_4: + orl #0, SCC4_REGS + SCC_SCCE; // confirm SCC events + orl #1 << TASK_SCC_3, channel_stats + movel #0x08000000, CISR + rte + +error_interrupt: + rte + + +/****************************** cable and PM routine ******************/ +// modified registers: none +check_csr: + movel %d0, -(%sp) + movel %d1, -(%sp) + movel %d2, -(%sp) + movel %a0, -(%sp) + movel %a1, -(%sp) + + clrl %d0 // D0 = 4 * port + movel #CSRA, %a0 // A0 = CSR address + +check_csr_loop: + movew (%a0), %d1 // D1 = CSR input bits + andl #0xE7, %d1 // PM and cable sense bits (no DCE bit) + cmpw #STATUS_CABLE_V35 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 + bne check_csr_1 + movew #0x0E08, %d1 + bra check_csr_valid + +check_csr_1: + cmpw #STATUS_CABLE_X21 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 + bne check_csr_2 + movew #0x0408, %d1 + bra check_csr_valid + +check_csr_2: + cmpw #STATUS_CABLE_V24 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 + bne check_csr_3 + movew #0x0208, %d1 + bra check_csr_valid + +check_csr_3: + cmpw #STATUS_CABLE_EIA530 * (1 + 1 << STATUS_CABLE_PM_SHIFT), %d1 + bne check_csr_disable + movew #0x0D08, %d1 + bra check_csr_valid + +check_csr_disable: + movew #0x0008, %d1 // D1 = disable everything + movew #0x80E7, %d2 // D2 = input mask: ignore DSR + bra check_csr_write + +check_csr_valid: // D1 = mode and IRQ bits + movew csr_output(%d0), %d2 + andw #0x3000, %d2 // D2 = requested LL and DTR bits + orw %d2, %d1 // D1 = all requested output bits + movew #0x80FF, %d2 // D2 = input mask: include DSR + +check_csr_write: + cmpw old_csr_output(%d0), %d1 + beq check_csr_input + movew %d1, old_csr_output(%d0) + movew %d1, (%a0) // Write CSR output bits + +check_csr_input: + movew (PCDAT), %d1 + andw dcd_mask(%d0), %d1 + beq check_csr_dcd_on // DCD and CTS signals are negated + movew (%a0), %d1 // D1 = CSR input bits + andw #~STATUS_CABLE_DCD, %d1 // DCD off + bra check_csr_previous + +check_csr_dcd_on: + movew (%a0), %d1 // D1 = CSR input bits + orw #STATUS_CABLE_DCD, %d1 // DCD on +check_csr_previous: + andw %d2, %d1 // input mask + movel ch_status_addr(%d0), %a1 + cmpl STATUS_CABLE(%a1), %d1 // check for change + beq check_csr_next + movel %d1, STATUS_CABLE(%a1) // update status + movel bell_cable(%d0), PLX_DOORBELL_FROM_CARD // signal the host + +check_csr_next: + addl #2, %a0 // next CSR register + addl #4, %d0 // D0 = 4 * next port + cmpl #4 * 4, %d0 + bne check_csr_loop + + movel (%sp)+, %a1 + movel (%sp)+, %a0 + movel (%sp)+, %d2 + movel (%sp)+, %d1 + movel (%sp)+, %d0 + rts + + +/****************************** timer interrupt ***********************/ + +timer_interrupt: + bsr check_csr + rte + + +/****************************** RAM sizing and test *******************/ +#if DETECT_RAM +ram_test: + movel #0x12345678, %d1 // D1 = test value + movel %d1, (128 * 1024 - 4) + movel #128 * 1024, %d0 // D0 = RAM size tested +ram_test_size: + cmpl #MAX_RAM_SIZE, %d0 + beq ram_test_size_found + movel %d0, %a0 + addl #128 * 1024 - 4, %a0 + cmpl (%a0), %d1 + beq ram_test_size_check +ram_test_next_size: + lsll #1, %d0 + bra ram_test_size + +ram_test_size_check: + eorl #0xFFFFFFFF, %d1 + movel %d1, (128 * 1024 - 4) + cmpl (%a0), %d1 + bne ram_test_next_size + +ram_test_size_found: // D0 = RAM size + movel %d0, %a0 // A0 = fill ptr + subl #firmware_end + 4, %d0 + lsrl #2, %d0 + movel %d0, %d1 // D1 = DBf counter +ram_test_fill: + movel %a0, -(%a0) + dbfw %d1, ram_test_fill + subl #0x10000, %d1 + cmpl #0xFFFFFFFF, %d1 + bne ram_test_fill + +ram_test_loop: // D0 = DBf counter + cmpl (%a0)+, %a0 + dbnew %d0, ram_test_loop + bne ram_test_found_bad + subl #0x10000, %d0 + cmpl #0xFFFFFFFF, %d0 + bne ram_test_loop + bra ram_test_all_ok + +ram_test_found_bad: + subl #4, %a0 +ram_test_all_ok: + movel %a0, PLX_MAILBOX_5 + rts +#endif + + +/****************************** constants *****************************/ + +scc_reg_addr: + .long SCC1_REGS, SCC2_REGS, SCC3_REGS, SCC4_REGS +scc_base_addr: + .long SCC1_BASE, SCC2_BASE, SCC3_BASE, SCC4_BASE + +tx_first_bd: + .long DPRBASE + .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 + .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 2 + .long DPRBASE + (TX_BUFFERS + RX_BUFFERS) * 8 * 3 + +rx_first_bd: + .long DPRBASE + TX_BUFFERS * 8 + .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 + .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 2 + .long DPRBASE + TX_BUFFERS * 8 + (TX_BUFFERS + RX_BUFFERS) * 8 * 3 + +first_buffer: + .long BUFFERS_ADDR + .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH + .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 2 + .long BUFFERS_ADDR + (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * 3 + +bell_tx: + .long 1 << DOORBELL_FROM_CARD_TX_0, 1 << DOORBELL_FROM_CARD_TX_1 + .long 1 << DOORBELL_FROM_CARD_TX_2, 1 << DOORBELL_FROM_CARD_TX_3 + +bell_cable: + .long 1 << DOORBELL_FROM_CARD_CABLE_0, 1 << DOORBELL_FROM_CARD_CABLE_1 + .long 1 << DOORBELL_FROM_CARD_CABLE_2, 1 << DOORBELL_FROM_CARD_CABLE_3 + +packet_full: + .long PACKET_FULL, PACKET_FULL + 1, PACKET_FULL + 2, PACKET_FULL + 3 + +clocking_ext: + .long 0x0000002C, 0x00003E00, 0x002C0000, 0x3E000000 +clocking_txfromrx: + .long 0x0000002D, 0x00003F00, 0x002D0000, 0x3F000000 +clocking_mask: + .long 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 +dcd_mask: + .word 0x020, 0, 0x080, 0, 0x200, 0, 0x800 + + .ascii "wanXL firmware\n" + .asciz "Copyright (C) 2003 Krzysztof Halasa <khc@pm.waw.pl>\n" + + +/****************************** variables *****************************/ + + .align 4 +channel_stats: .long 0 + +tx_in: .long 0, 0, 0, 0 // transmitted +tx_out: .long 0, 0, 0, 0 // received from host for transmission +tx_count: .long 0, 0, 0, 0 // currently in transmit queue + +rx_in: .long 0, 0, 0, 0 // received from port +rx_out: .long 0 // transmitted to host +parity_bytes: .word 0, 0, 0, 0, 0, 0, 0 // only 4 words are used + +csr_output: .word 0 +old_csr_output: .word 0, 0, 0, 0, 0, 0, 0 + .align 4 +firmware_end: // must be dword-aligned diff --git a/drivers/net/wan/wanxlfw.inc b/drivers/net/wan/wanxlfw.inc new file mode 100644 index 000000000000..73da688f943b --- /dev/null +++ b/drivers/net/wan/wanxlfw.inc @@ -0,0 +1,158 @@ +static u8 firmware[]={ +0x60,0x00,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xB9,0x40,0x00,0x00,0x00,0x00,0x00, +0x10,0x14,0x42,0x80,0x4A,0xB0,0x09,0xB0,0x00,0x00,0x10,0x04,0x67,0x00,0x00,0x0E, +0x06,0xB0,0x40,0x00,0x00,0x00,0x09,0xB0,0x00,0x00,0x10,0x04,0x58,0x80,0x0C,0x80, +0x00,0x00,0x00,0x10,0x66,0x00,0xFF,0xDE,0x21,0xFC,0x00,0x00,0x16,0xBC,0x00,0x6C, +0x21,0xFC,0x00,0x00,0x17,0x5E,0x01,0x00,0x21,0xFC,0x00,0x00,0x16,0xDE,0x01,0x78, +0x21,0xFC,0x00,0x00,0x16,0xFE,0x01,0x74,0x21,0xFC,0x00,0x00,0x17,0x1E,0x01,0x70, +0x21,0xFC,0x00,0x00,0x17,0x3E,0x01,0x6C,0x21,0xFC,0x00,0x00,0x18,0x4C,0x02,0x00, +0x23,0xFC,0x78,0x00,0x00,0x00,0xFF,0xFC,0x15,0x48,0x33,0xFC,0x04,0x80,0xFF,0xFC, +0x10,0x26,0x33,0xFC,0x01,0x10,0xFF,0xFC,0x10,0x2A,0x23,0xFC,0x00,0xD4,0x9F,0x40, +0xFF,0xFC,0x15,0x40,0x23,0xFC,0x00,0x00,0x05,0x43,0xFF,0xF9,0x01,0x00,0x23,0xFC, +0x00,0x00,0x05,0x43,0xFF,0xF9,0x01,0x14,0x23,0xFC,0x00,0x00,0x00,0x00,0xFF,0xF9, +0x01,0x10,0x23,0xFC,0x00,0x00,0x00,0x08,0xFF,0xF9,0x01,0x24,0x23,0xFC,0x00,0x00, +0x01,0x01,0xFF,0xF9,0x01,0x28,0x00,0xB9,0x00,0x0F,0x03,0x00,0xFF,0xF9,0x00,0xE8, +0x23,0xFC,0x00,0x00,0x00,0x01,0xFF,0xF9,0x00,0xD4,0x61,0x00,0x06,0x74,0x33,0xFC, +0xFF,0xFF,0xFF,0xFC,0x15,0x52,0x42,0x79,0xFF,0xFC,0x15,0x50,0x42,0x79,0xFF,0xFC, +0x15,0x64,0x2E,0x3A,0x08,0x50,0x42,0xB9,0x00,0x00,0x19,0x54,0x4A,0x87,0x66,0x00, +0x00,0x0E,0x4E,0x72,0x22,0x00,0x46,0xFC,0x27,0x00,0x60,0x00,0xFF,0xE6,0x42,0x80, +0x42,0x86,0x08,0x07,0x00,0x04,0x67,0x00,0x00,0x0A,0x08,0x87,0x00,0x00,0x61,0x00, +0x02,0xA0,0x08,0x07,0x00,0x00,0x67,0x00,0x00,0x06,0x61,0x00,0x00,0x36,0x08,0x07, +0x00,0x08,0x67,0x00,0x00,0x06,0x61,0x00,0x02,0xB8,0x08,0x07,0x00,0x0C,0x67,0x00, +0x00,0x0A,0x61,0x00,0x04,0x94,0x61,0x00,0x03,0x60,0xE2,0x8F,0x58,0x80,0x0C,0x80, +0x00,0x00,0x00,0x10,0x66,0x00,0xFF,0xBC,0x23,0xC6,0xFF,0xF9,0x00,0xE4,0x60,0x00, +0xFF,0x92,0x20,0x70,0x09,0xB0,0x00,0x00,0x10,0x04,0x4A,0xA8,0x00,0x00,0x66,0x00, +0x02,0x4E,0x21,0x7C,0x00,0x00,0x00,0x01,0x00,0x00,0x42,0xB0,0x09,0xB0,0x00,0x00, +0x19,0x58,0x42,0xB0,0x09,0xB0,0x00,0x00,0x19,0x68,0x42,0xB0,0x09,0xB0,0x00,0x00, +0x19,0x78,0x42,0xB0,0x09,0xB0,0x00,0x00,0x19,0x88,0x22,0x39,0xFF,0xFC,0x16,0xEC, +0xC2,0xB0,0x09,0xB0,0x00,0x00,0x18,0xF2,0x0C,0xA8,0x00,0x00,0x00,0x04,0x00,0x18, +0x66,0x00,0x00,0x0E,0x82,0xB0,0x09,0xB0,0x00,0x00,0x18,0xE2,0x60,0x00,0x00,0x0A, +0x82,0xB0,0x09,0xB0,0x00,0x00,0x18,0xD2,0x23,0xC1,0xFF,0xFC,0x16,0xEC,0x00,0x70, +0x10,0x00,0x09,0xB0,0x00,0x00,0x19,0xAA,0x61,0x00,0x05,0x76,0x22,0x30,0x09,0xB0, +0x00,0x00,0x18,0x92,0x22,0x70,0x09,0xB0,0x00,0x00,0x18,0x72,0x74,0x08,0x26,0x3C, +0x18,0x00,0x00,0x00,0x0C,0xA8,0x00,0x00,0x00,0x01,0x00,0x10,0x67,0x00,0x00,0x06, +0x08,0xC3,0x00,0x1A,0x22,0xC3,0x22,0xC1,0x06,0x81,0x00,0x00,0x05,0xFC,0x51,0xCA, +0xFF,0xF4,0x08,0xC3,0x00,0x1D,0x22,0xC3,0x22,0xC1,0x74,0x1C,0x22,0xFC,0x90,0x00, +0x00,0x00,0x22,0xC1,0x06,0x81,0x00,0x00,0x05,0xFC,0x51,0xCA,0xFF,0xF0,0x22,0xFC, +0xB0,0x00,0x00,0x00,0x22,0xC1,0x22,0x70,0x09,0xB0,0x00,0x00,0x18,0x62,0x24,0x70, +0x09,0xB0,0x00,0x00,0x18,0x52,0x25,0x7C,0x00,0x00,0xFF,0xFF,0x00,0x10,0x25,0x7C, +0x00,0x00,0x00,0x00,0x00,0x14,0x22,0x30,0x09,0xB0,0x00,0x00,0x18,0x72,0x33,0x41, +0x00,0x02,0x06,0x81,0x00,0x00,0x00,0x50,0x33,0x41,0x00,0x00,0x13,0x7C,0x00,0x08, +0x00,0x04,0x13,0x7C,0x00,0x08,0x00,0x05,0x0C,0xA8,0x00,0x00,0x00,0x05,0x00,0x10, +0x66,0x00,0x00,0x2A,0x42,0x6A,0x00,0x08,0x23,0x7C,0x00,0x00,0xF0,0xB8,0x00,0x34, +0x23,0x7C,0x00,0x00,0xFF,0xFF,0x00,0x38,0x33,0x7C,0x05,0xFA,0x00,0x46,0x31,0xBC, +0x00,0x02,0x09,0xB0,0x00,0x00,0x19,0x9C,0x60,0x00,0x00,0xBC,0x0C,0xA8,0x00,0x00, +0x00,0x07,0x00,0x10,0x66,0x00,0x00,0x2C,0x35,0x7C,0x08,0x00,0x00,0x08,0x23,0x7C, +0xDE,0xBB,0x20,0xE3,0x00,0x34,0x23,0x7C,0xFF,0xFF,0xFF,0xFF,0x00,0x38,0x33,0x7C, +0x05,0xFC,0x00,0x46,0x31,0xBC,0x00,0x04,0x09,0xB0,0x00,0x00,0x19,0x9C,0x60,0x00, +0x00,0x86,0x0C,0xA8,0x00,0x00,0x00,0x04,0x00,0x10,0x66,0x00,0x00,0x26,0x42,0x6A, +0x00,0x08,0x23,0x7C,0x00,0x00,0xF0,0xB8,0x00,0x34,0x42,0xA9,0x00,0x38,0x33,0x7C, +0x05,0xFA,0x00,0x46,0x31,0xBC,0x00,0x02,0x09,0xB0,0x00,0x00,0x19,0x9C,0x60,0x00, +0x00,0x56,0x0C,0xA8,0x00,0x00,0x00,0x06,0x00,0x10,0x66,0x00,0x00,0x28,0x35,0x7C, +0x08,0x00,0x00,0x08,0x23,0x7C,0xDE,0xBB,0x20,0xE3,0x00,0x34,0x42,0xA9,0x00,0x38, +0x33,0x7C,0x05,0xFC,0x00,0x46,0x31,0xBC,0x00,0x04,0x09,0xB0,0x00,0x00,0x19,0x9C, +0x60,0x00,0x00,0x24,0x42,0x6A,0x00,0x08,0x23,0x7C,0x00,0x00,0xF0,0xB8,0x00,0x34, +0x23,0x7C,0x00,0x00,0xFF,0xFF,0x00,0x38,0x33,0x7C,0x05,0xF8,0x00,0x46,0x42,0x70, +0x09,0xB0,0x00,0x00,0x19,0x9C,0x25,0x7C,0x00,0x00,0x00,0x03,0x00,0x04,0x0C,0xA8, +0x00,0x00,0x00,0x02,0x00,0x14,0x66,0x00,0x00,0x0E,0x25,0x7C,0x10,0x04,0x09,0x00, +0x00,0x00,0x60,0x00,0x00,0x0A,0x25,0x7C,0x10,0x04,0x00,0x00,0x00,0x00,0x33,0x7C, +0x05,0xFC,0x00,0x06,0x22,0x00,0xE9,0x89,0x00,0x81,0x00,0x00,0x00,0x01,0x33,0xC1, +0xFF,0xFC,0x15,0xC0,0x08,0x39,0x00,0x00,0xFF,0xFC,0x15,0xC0,0x66,0x00,0xFF,0xF6, +0x35,0x7C,0x00,0x1F,0x00,0x14,0x00,0xAA,0x00,0x00,0x00,0x30,0x00,0x00,0x4E,0x75, +0x20,0x70,0x09,0xB0,0x00,0x00,0x18,0x52,0x42,0x68,0x00,0x14,0x02,0xA8,0xFF,0xFF, +0xFF,0xCF,0x00,0x00,0x02,0x70,0xEF,0xFF,0x09,0xB0,0x00,0x00,0x19,0xAA,0x61,0x00, +0x03,0x70,0x22,0x30,0x09,0xB0,0x00,0x00,0x10,0x04,0x42,0xB0,0x19,0x90,0x4E,0x75, +0x0C,0xB0,0x00,0x00,0x00,0x0A,0x09,0xB0,0x00,0x00,0x19,0x78,0x67,0x00,0x00,0xA8, +0x22,0x30,0x09,0xB0,0x00,0x00,0x19,0x68,0x24,0x01,0x4C,0x3C,0x20,0x00,0x00,0x00, +0x00,0x0C,0xD4,0xB0,0x09,0xB0,0x00,0x00,0x10,0x04,0x06,0x82,0x00,0x00,0x00,0x1C, +0x0C,0xB0,0x00,0x00,0x00,0x10,0x29,0x90,0x66,0x00,0x00,0x7C,0x20,0x70,0x29,0xA0, +0x00,0x04,0xE7,0x89,0xD2,0xB0,0x09,0xB0,0x00,0x00,0x18,0x72,0x22,0x70,0x19,0xA0, +0x00,0x04,0x24,0x30,0x29,0xA0,0x00,0x08,0x31,0x82,0x19,0xA0,0x00,0x02,0x56,0x82, +0x02,0x82,0xFF,0xFF,0xFF,0xFC,0x23,0xC8,0xFF,0xF9,0x01,0x04,0x23,0xC9,0xFF,0xF9, +0x01,0x08,0x23,0xC2,0xFF,0xF9,0x01,0x0C,0x23,0xFC,0x00,0x00,0x01,0x03,0xFF,0xF9, +0x01,0x28,0x61,0x00,0x01,0xF6,0x08,0xF0,0x00,0x1F,0x19,0x90,0x22,0x30,0x09,0xB0, +0x00,0x00,0x19,0x68,0x52,0x81,0x0C,0x81,0x00,0x00,0x00,0x0A,0x66,0x00,0x00,0x04, +0x42,0x81,0x21,0x81,0x09,0xB0,0x00,0x00,0x19,0x68,0x52,0xB0,0x09,0xB0,0x00,0x00, +0x19,0x78,0x60,0x00,0xFF,0x4C,0x4E,0x75,0x22,0x30,0x09,0xB0,0x00,0x00,0x19,0x88, +0xE7,0x89,0xD2,0xB0,0x09,0xB0,0x00,0x00,0x18,0x82,0x34,0x30,0x19,0x90,0x08,0x02, +0x00,0x0F,0x66,0x00,0x01,0x12,0x08,0x02,0x00,0x01,0x66,0x00,0x00,0xE6,0x4A,0x70, +0x09,0xB0,0x00,0x00,0x19,0x9C,0x66,0x00,0x00,0x06,0x08,0x82,0x00,0x02,0x02,0x42, +0x0C,0xBC,0x0C,0x42,0x0C,0x00,0x66,0x00,0x00,0xDC,0x42,0x83,0x36,0x30,0x19,0xA0, +0x00,0x02,0x96,0x70,0x09,0xB0,0x00,0x00,0x19,0x9C,0x0C,0x43,0x05,0xF8,0x6E,0x00, +0x00,0xC4,0x24,0x3A,0x04,0x84,0x4C,0x3C,0x20,0x00,0x00,0x00,0x00,0x0C,0xD4,0xBA, +0xFA,0xF4,0x0C,0xB0,0x00,0x00,0x00,0x00,0x29,0x90,0x66,0x00,0x00,0x96,0x21,0x83, +0x29,0xA0,0x00,0x08,0x20,0x70,0x19,0xA0,0x00,0x04,0x22,0x70,0x29,0xA0,0x00,0x04, +0x4A,0x89,0x67,0x00,0x00,0x2A,0x56,0x83,0x02,0x83,0xFF,0xFF,0xFF,0xFC,0x23,0xC8, +0xFF,0xF9,0x01,0x1C,0x23,0xC9,0xFF,0xF9,0x01,0x18,0x23,0xC3,0xFF,0xF9,0x01,0x20, +0x23,0xFC,0x00,0x00,0x03,0x01,0xFF,0xF9,0x01,0x28,0x61,0x00,0x01,0x2C,0x21,0xB0, +0x09,0xB0,0x00,0x00,0x18,0xC2,0x29,0x90,0x08,0xC6,0x00,0x04,0x24,0x3A,0x04,0x1A, +0x52,0x82,0x0C,0x82,0x00,0x00,0x00,0x28,0x66,0x00,0x00,0x04,0x42,0x82,0x23,0xC2, +0x00,0x00,0x19,0x98,0x02,0x70,0xF0,0x00,0x19,0x90,0x08,0xF0,0x00,0x1F,0x19,0x90, +0x22,0x30,0x09,0xB0,0x00,0x00,0x19,0x88,0x52,0x81,0x0C,0x81,0x00,0x00,0x00,0x1E, +0x66,0x00,0x00,0x04,0x42,0x81,0x21,0x81,0x09,0xB0,0x00,0x00,0x19,0x88,0x60,0x00, +0xFE,0xF8,0x24,0x30,0x09,0xB0,0x00,0x00,0x10,0x04,0x52,0xB0,0x29,0xA0,0x00,0x08, +0x60,0x00,0xFF,0xC2,0x24,0x30,0x09,0xB0,0x00,0x00,0x10,0x04,0x52,0xB0,0x29,0xA0, +0x00,0x0C,0x60,0x00,0xFF,0xB0,0x4E,0x75,0x4A,0xB0,0x09,0xB0,0x00,0x00,0x19,0x78, +0x67,0x00,0x00,0x86,0x22,0x30,0x09,0xB0,0x00,0x00,0x19,0x58,0x24,0x01,0xE7,0x89, +0xD2,0xB0,0x09,0xB0,0x00,0x00,0x18,0x72,0x36,0x30,0x19,0x90,0x08,0x03,0x00,0x0F, +0x66,0x00,0x00,0x66,0x8C,0xB0,0x09,0xB0,0x00,0x00,0x18,0xA2,0x53,0xB0,0x09,0xB0, +0x00,0x00,0x19,0x78,0x22,0x30,0x09,0xB0,0x00,0x00,0x19,0x58,0x52,0x81,0x0C,0x81, +0x00,0x00,0x00,0x0A,0x66,0x00,0x00,0x04,0x42,0x81,0x21,0x81,0x09,0xB0,0x00,0x00, +0x19,0x58,0x4C,0x3C,0x20,0x00,0x00,0x00,0x00,0x0C,0xD4,0xB0,0x09,0xB0,0x00,0x00, +0x10,0x04,0x06,0x82,0x00,0x00,0x00,0x1C,0x08,0x03,0x00,0x01,0x66,0x00,0x00,0x0E, +0x21,0xBC,0x00,0x00,0x00,0x20,0x29,0x90,0x60,0x00,0xFF,0x7E,0x21,0xBC,0x00,0x00, +0x00,0x30,0x29,0x90,0x60,0x00,0xFF,0x72,0x4E,0x75,0x2F,0x00,0x40,0xE7,0x20,0x39, +0xFF,0xF9,0x01,0x28,0x08,0x00,0x00,0x04,0x66,0x00,0x00,0x2C,0x4E,0x72,0x22,0x00, +0x46,0xFC,0x27,0x00,0x60,0x00,0xFF,0xE8,0x2F,0x00,0x40,0xE7,0x20,0x39,0xFF,0xF9, +0x01,0x28,0x08,0x00,0x00,0x0C,0x66,0x00,0x00,0x0E,0x4E,0x72,0x22,0x00,0x46,0xFC, +0x27,0x00,0x60,0x00,0xFF,0xE8,0x46,0xDF,0x20,0x1F,0x4E,0x75,0x2F,0x00,0x20,0x39, +0xFF,0xF9,0x00,0xE0,0x23,0xC0,0xFF,0xF9,0x00,0xE0,0x81,0xB9,0x00,0x00,0x19,0x54, +0x23,0xFC,0x00,0x00,0x09,0x09,0xFF,0xF9,0x01,0x28,0x20,0x1F,0x4E,0x73,0x00,0xB9, +0x00,0x00,0x00,0x00,0xFF,0xFC,0x16,0x10,0x00,0xB9,0x00,0x00,0x10,0x00,0x00,0x00, +0x19,0x54,0x23,0xFC,0x40,0x00,0x00,0x00,0xFF,0xFC,0x15,0x4C,0x4E,0x73,0x00,0xB9, +0x00,0x00,0x00,0x00,0xFF,0xFC,0x16,0x30,0x00,0xB9,0x00,0x00,0x20,0x00,0x00,0x00, +0x19,0x54,0x23,0xFC,0x20,0x00,0x00,0x00,0xFF,0xFC,0x15,0x4C,0x4E,0x73,0x00,0xB9, +0x00,0x00,0x00,0x00,0xFF,0xFC,0x16,0x50,0x00,0xB9,0x00,0x00,0x40,0x00,0x00,0x00, +0x19,0x54,0x23,0xFC,0x10,0x00,0x00,0x00,0xFF,0xFC,0x15,0x4C,0x4E,0x73,0x00,0xB9, +0x00,0x00,0x00,0x00,0xFF,0xFC,0x16,0x70,0x00,0xB9,0x00,0x00,0x80,0x00,0x00,0x00, +0x19,0x54,0x23,0xFC,0x08,0x00,0x00,0x00,0xFF,0xFC,0x15,0x4C,0x4E,0x73,0x4E,0x73, +0x2F,0x00,0x2F,0x01,0x2F,0x02,0x2F,0x08,0x2F,0x09,0x42,0x80,0x20,0x7C,0xFF,0xFB, +0x00,0x00,0x32,0x10,0x02,0x81,0x00,0x00,0x00,0xE7,0x0C,0x41,0x00,0x42,0x66,0x00, +0x00,0x0A,0x32,0x3C,0x0E,0x08,0x60,0x00,0x00,0x3E,0x0C,0x41,0x00,0x63,0x66,0x00, +0x00,0x0A,0x32,0x3C,0x04,0x08,0x60,0x00,0x00,0x2E,0x0C,0x41,0x00,0x84,0x66,0x00, +0x00,0x0A,0x32,0x3C,0x02,0x08,0x60,0x00,0x00,0x1E,0x0C,0x41,0x00,0xA5,0x66,0x00, +0x00,0x0A,0x32,0x3C,0x0D,0x08,0x60,0x00,0x00,0x0E,0x32,0x3C,0x00,0x08,0x34,0x3C, +0x80,0xE7,0x60,0x00,0x00,0x14,0x34,0x30,0x09,0xB0,0x00,0x00,0x19,0xAA,0x02,0x42, +0x30,0x00,0x82,0x42,0x34,0x3C,0x80,0xFF,0xB2,0x70,0x09,0xB0,0x00,0x00,0x19,0xAC, +0x67,0x00,0x00,0x0C,0x31,0x81,0x09,0xB0,0x00,0x00,0x19,0xAC,0x30,0x81,0x32,0x39, +0xFF,0xFC,0x15,0x66,0xC2,0x70,0x09,0xB0,0x00,0x00,0x19,0x02,0x67,0x00,0x00,0x0C, +0x32,0x10,0x02,0x41,0xFF,0xF7,0x60,0x00,0x00,0x08,0x32,0x10,0x00,0x41,0x00,0x08, +0xC2,0x42,0x22,0x70,0x09,0xB0,0x00,0x00,0x10,0x04,0xB2,0xA9,0x00,0x04,0x67,0x00, +0x00,0x12,0x23,0x41,0x00,0x04,0x23,0xF0,0x09,0xB0,0x00,0x00,0x18,0xB2,0xFF,0xF9, +0x00,0xE4,0x54,0x88,0x58,0x80,0x0C,0x80,0x00,0x00,0x00,0x10,0x66,0x00,0xFF,0x34, +0x22,0x5F,0x20,0x5F,0x24,0x1F,0x22,0x1F,0x20,0x1F,0x4E,0x75,0x61,0x00,0xFF,0x12, +0x4E,0x73,0xFF,0xFC,0x16,0x00,0xFF,0xFC,0x16,0x20,0xFF,0xFC,0x16,0x40,0xFF,0xFC, +0x16,0x60,0xFF,0xFC,0x0C,0x00,0xFF,0xFC,0x0D,0x00,0xFF,0xFC,0x0E,0x00,0xFF,0xFC, +0x0F,0x00,0xFF,0xFC,0x00,0x00,0xFF,0xFC,0x01,0x40,0xFF,0xFC,0x02,0x80,0xFF,0xFC, +0x03,0xC0,0xFF,0xFC,0x00,0x50,0xFF,0xFC,0x01,0x90,0xFF,0xFC,0x02,0xD0,0xFF,0xFC, +0x04,0x10,0x00,0x00,0x40,0x00,0x00,0x01,0x2F,0x60,0x00,0x02,0x1E,0xC0,0x00,0x03, +0x0E,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00, +0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x80,0x00,0x00, +0x01,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x12,0x00,0x00, +0x00,0x13,0x00,0x00,0x00,0x2C,0x00,0x00,0x3E,0x00,0x00,0x2C,0x00,0x00,0x3E,0x00, +0x00,0x00,0x00,0x00,0x00,0x2D,0x00,0x00,0x3F,0x00,0x00,0x2D,0x00,0x00,0x3F,0x00, +0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00, +0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x80,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00, +0x77,0x61,0x6E,0x58,0x4C,0x20,0x66,0x69,0x72,0x6D,0x77,0x61,0x72,0x65,0x0A,0x43, +0x6F,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29,0x20,0x32,0x30,0x30, +0x33,0x20,0x4B,0x72,0x7A,0x79,0x73,0x7A,0x74,0x6F,0x66,0x20,0x48,0x61,0x6C,0x61, +0x73,0x61,0x20,0x3C,0x6B,0x68,0x63,0x40,0x70,0x6D,0x2E,0x77,0x61,0x77,0x2E,0x70, +0x6C,0x3E,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index de635a575b8f..23fbc8589385 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -281,72 +281,29 @@ int pcmcia_socket_dev_resume(struct device *dev) EXPORT_SYMBOL(pcmcia_socket_dev_resume); -static int pccardd(void *__skt); -#define to_class_data(dev) dev->class_data - -static int pcmcia_add_socket(struct class_device *class_dev) -{ - struct pcmcia_socket *socket = class_get_devdata(class_dev); - int ret = 0; - - /* base address = 0, map = 0 */ - socket->cis_mem.flags = 0; - socket->cis_mem.speed = cis_speed; - socket->erase_busy.next = socket->erase_busy.prev = &socket->erase_busy; - INIT_LIST_HEAD(&socket->cis_cache); - spin_lock_init(&socket->lock); - - init_completion(&socket->thread_done); - init_waitqueue_head(&socket->thread_wait); - init_MUTEX(&socket->skt_sem); - spin_lock_init(&socket->thread_lock); - - socket->socket = dead_socket; - socket->ops->init(socket); - - ret = kernel_thread(pccardd, socket, CLONE_KERNEL); - if (ret < 0) - return ret; - - wait_for_completion(&socket->thread_done); - BUG_ON(!socket->thread); - pcmcia_parse_events(socket, SS_DETECT); - - return 0; -} - -static void pcmcia_remove_socket(struct class_device *class_dev) +static void pcmcia_release_socket(struct class_device *class_dev) { struct pcmcia_socket *socket = class_get_devdata(class_dev); client_t *client; - if (socket->thread) { - init_completion(&socket->thread_done); - socket->thread = NULL; - wake_up(&socket->thread_wait); - wait_for_completion(&socket->thread_done); - } - release_cis_mem(socket); while (socket->clients) { client = socket->clients; socket->clients = socket->clients->next; kfree(client); } - socket->ops = NULL; -} -static void pcmcia_release_socket(struct class_device *class_dev) -{ - struct pcmcia_socket *socket = class_get_devdata(class_dev); complete(&socket->socket_released); } +static int pccardd(void *__skt); /** * pcmcia_register_socket - add a new pcmcia socket device */ int pcmcia_register_socket(struct pcmcia_socket *socket) { + int ret; + if (!socket || !socket->ops || !socket->dev.dev) return -EINVAL; @@ -381,15 +338,34 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) socket->dev.class = &pcmcia_socket_class; snprintf(socket->dev.class_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock); - /* register with the device core */ - if (class_device_register(&socket->dev)) { - down_write(&pcmcia_socket_list_rwsem); - list_del(&socket->socket_list); - up_write(&pcmcia_socket_list_rwsem); - return -EINVAL; - } + /* base address = 0, map = 0 */ + socket->cis_mem.flags = 0; + socket->cis_mem.speed = cis_speed; + socket->erase_busy.next = socket->erase_busy.prev = &socket->erase_busy; + INIT_LIST_HEAD(&socket->cis_cache); + spin_lock_init(&socket->lock); + + init_completion(&socket->socket_released); + init_completion(&socket->thread_done); + init_waitqueue_head(&socket->thread_wait); + init_MUTEX(&socket->skt_sem); + spin_lock_init(&socket->thread_lock); + + ret = kernel_thread(pccardd, socket, CLONE_KERNEL); + if (ret < 0) + goto err; + + wait_for_completion(&socket->thread_done); + BUG_ON(!socket->thread); + pcmcia_parse_events(socket, SS_DETECT); return 0; + + err: + down_write(&pcmcia_socket_list_rwsem); + list_del(&socket->socket_list); + up_write(&pcmcia_socket_list_rwsem); + return ret; } /* pcmcia_register_socket */ EXPORT_SYMBOL(pcmcia_register_socket); @@ -404,10 +380,13 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket) DEBUG(0, "cs: pcmcia_unregister_socket(0x%p)\n", socket->ops); - init_completion(&socket->socket_released); - - /* remove from the device core */ - class_device_unregister(&socket->dev); + if (socket->thread) { + init_completion(&socket->thread_done); + socket->thread = NULL; + wake_up(&socket->thread_wait); + wait_for_completion(&socket->thread_done); + } + release_cis_mem(socket); /* remove from our own list */ down_write(&pcmcia_socket_list_rwsem); @@ -783,11 +762,22 @@ static int pccardd(void *__skt) { struct pcmcia_socket *skt = __skt; DECLARE_WAITQUEUE(wait, current); + int ret; daemonize("pccardd"); skt->thread = current; complete(&skt->thread_done); + skt->socket = dead_socket; + skt->ops->init(skt); + + /* register with the device core */ + ret = class_device_register(&skt->dev); + if (ret) { + printk(KERN_WARNING "PCMCIA: unable to register socket 0x%p\n", + skt); + } + add_wait_queue(&skt->thread_wait, &wait); for (;;) { unsigned long flags; @@ -823,6 +813,9 @@ static int pccardd(void *__skt) } remove_wait_queue(&skt->thread_wait, &wait); + /* remove from the device core */ + class_device_unregister(&skt->dev); + complete_and_exit(&skt->thread_done, 0); } @@ -2501,12 +2494,6 @@ struct class pcmcia_socket_class = { }; EXPORT_SYMBOL(pcmcia_socket_class); -static struct class_interface pcmcia_socket = { - .class = &pcmcia_socket_class, - .add = &pcmcia_add_socket, - .remove = &pcmcia_remove_socket, -}; - static int __init init_pcmcia_cs(void) { @@ -2514,7 +2501,6 @@ static int __init init_pcmcia_cs(void) printk(KERN_INFO " %s\n", options); DEBUG(0, "%s\n", version); class_register(&pcmcia_socket_class); - class_interface_register(&pcmcia_socket); return 0; } @@ -2523,7 +2509,6 @@ static void __exit exit_pcmcia_cs(void) { printk(KERN_INFO "unloading Kernel Card Services\n"); release_resource_db(); - class_interface_unregister(&pcmcia_socket); class_unregister(&pcmcia_socket_class); } diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index 6429b52d8649..b9cb632d8084 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -491,7 +491,7 @@ static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s) void validate_mem(struct pcmcia_socket *s) { - resource_map_t *m, *n; + resource_map_t *m, mm; static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 }; static int hi = 0, lo = 0; u_long b, i, ok = 0; @@ -510,18 +510,18 @@ void validate_mem(struct pcmcia_socket *s) } if (lo++) goto out; - for (m = mem_db.next; m != &mem_db; m = n) { - n = m->next; + for (m = mem_db.next; m != &mem_db; m = mm.next) { + mm = *m; /* Only probe < 1 MB */ - if (m->base >= 0x100000) continue; - if ((m->base | m->num) & 0xffff) { - ok += do_mem_probe(m->base, m->num, s); + if (mm.base >= 0x100000) continue; + if ((mm.base | mm.num) & 0xffff) { + ok += do_mem_probe(mm.base, mm.num, s); continue; } /* Special probe for 64K-aligned block */ for (i = 0; i < 4; i++) { b = order[i] << 12; - if ((b >= m->base) && (b+0x10000 <= m->base+m->num)) { + if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) { if (ok >= mem_limit) sub_interval(&mem_db, b, 0x10000); else @@ -537,14 +537,14 @@ void validate_mem(struct pcmcia_socket *s) void validate_mem(struct pcmcia_socket *s) { - resource_map_t *m, *n; + resource_map_t *m, mm; static int done = 0; if (probe_mem && done++ == 0) { down(&rsrc_sem); - for (m = mem_db.next; m != &mem_db; m = n) { - n = m->next; - if (do_mem_probe(m->base, m->num, s)) + for (m = mem_db.next; m != &mem_db; m = mm.next) { + mm = *m; + if (do_mem_probe(mm.base, mm.num, s)) break; } up(&rsrc_sem); diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c index e25e160d7e61..884a655efbfb 100644 --- a/drivers/pcmcia/sa1100_assabet.c +++ b/drivers/pcmcia/sa1100_assabet.c @@ -4,7 +4,6 @@ * PCMCIA implementation routines for Assabet * */ -#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index f72ebb3b1206..bc0788173daf 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -5,6 +5,7 @@ * basically means we handle everything except controlling the * power. Power is machine specific... */ +#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/ioport.h> diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 7262cca5529e..ff77a2887b8f 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -372,7 +372,7 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, int reg, int bit, i { r = NCR5380_read(reg); if((r & bit) == val) - return r; + return 0; cpu_relax(); } @@ -381,7 +381,7 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, int reg, int bit, i { r = NCR5380_read(reg); if((r & bit) == val) - return r; + return 0; if(!in_interrupt()) yield(); else diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 412e4dcb9e40..6171431272dc 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -123,7 +123,7 @@ static inline struct autofs_sb_info *autofs_sbi(struct super_block *sb) filesystem without "magic".) */ static inline int autofs_oz_mode(struct autofs_sb_info *sbi) { - return sbi->catatonic || current->pgrp == sbi->oz_pgrp; + return sbi->catatonic || process_group(current) == sbi->oz_pgrp; } /* Hash operations */ diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 76bb0d61dd91..398cade9442d 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -51,7 +51,7 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, pid *uid = current->uid; *gid = current->gid; - *pgrp = current->pgrp; + *pgrp = process_group(current); *minproto = *maxproto = AUTOFS_PROTO_VERSION; @@ -129,7 +129,7 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) sbi->magic = AUTOFS_SBI_MAGIC; sbi->catatonic = 0; sbi->exp_timeout = 0; - sbi->oz_pgrp = current->pgrp; + sbi->oz_pgrp = process_group(current); autofs_initialize_hash(&sbi->dirhash); sbi->queues = NULL; memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN); diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 546ac2f9af87..74ad37a84efc 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -213,7 +213,7 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr oz_mode = autofs_oz_mode(sbi); DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", - current->pid, current->pgrp, sbi->catatonic, oz_mode)); + current->pid, process_group(current), sbi->catatonic, oz_mode)); /* * Mark the dentry incomplete, but add it. This is needed so @@ -527,7 +527,7 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp, { struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb); - DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,current->pgrp)); + DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,process_group(current))); if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT ) diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 16a3ab2f6d05..0a4b95417122 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -113,7 +113,7 @@ static inline struct autofs_info *autofs4_dentry_ino(struct dentry *dentry) filesystem without "magic".) */ static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) { - return sbi->catatonic || current->pgrp == sbi->oz_pgrp; + return sbi->catatonic || process_group(current) == sbi->oz_pgrp; } /* Does a dentry have some pending activity? */ diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 35647d8eca94..f7cb9de42d95 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -101,7 +101,7 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, *uid = current->uid; *gid = current->gid; - *pgrp = current->pgrp; + *pgrp = process_group(current); *minproto = AUTOFS_MIN_PROTO_VERSION; *maxproto = AUTOFS_MAX_PROTO_VERSION; @@ -192,7 +192,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) sbi->magic = AUTOFS_SBI_MAGIC; sbi->catatonic = 0; sbi->exp_timeout = 0; - sbi->oz_pgrp = current->pgrp; + sbi->oz_pgrp = process_group(current); sbi->sb = s; sbi->version = 0; sbi->queues = NULL; diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 49f9f4d3b406..971dfa29b387 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -255,7 +255,7 @@ static struct dentry *autofs4_root_lookup(struct inode *dir, struct dentry *dent lock_kernel(); oz_mode = autofs4_oz_mode(sbi); DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", - current->pid, current->pgrp, sbi->catatonic, oz_mode)); + current->pid, process_group(current), sbi->catatonic, oz_mode)); /* * Mark the dentry incomplete, but add it. This is needed so @@ -518,7 +518,7 @@ static int autofs4_root_ioctl(struct inode *inode, struct file *filp, struct autofs_sb_info *sbi = autofs4_sbi(inode->i_sb); DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n", - cmd,arg,sbi,current->pgrp)); + cmd,arg,sbi,process_group(current))); if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) || _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT ) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index ffcef47900fd..dfdead4fcb63 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1077,7 +1077,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus, prstatus->pr_sighold = p->blocked.sig[0]; prstatus->pr_pid = p->pid; prstatus->pr_ppid = p->parent->pid; - prstatus->pr_pgrp = p->pgrp; + prstatus->pr_pgrp = process_group(p); prstatus->pr_sid = p->session; jiffies_to_timeval(p->utime, &prstatus->pr_utime); jiffies_to_timeval(p->stime, &prstatus->pr_stime); @@ -1105,7 +1105,7 @@ static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p, psinfo->pr_pid = p->pid; psinfo->pr_ppid = p->parent->pid; - psinfo->pr_pgrp = p->pgrp; + psinfo->pr_pgrp = process_group(p); psinfo->pr_sid = p->session; i = p->state ? ffz(~p->state) + 1 : 0; @@ -532,6 +532,12 @@ void bio_unmap_user(struct bio *bio, int write_to_vm) * check that the pages are still dirty. If so, fine. If not, redirty them * in process context. * + * We special-case compound pages here: normally this means reads into hugetlb + * pages. The logic in here doesn't really work right for compound pages + * because the VM does not uniformly chase down the head page in all cases. + * But dirtiness of compound pages is pretty meaningless anyway: the VM doesn't + * handle them at all. So we skip compound pages here at an early stage. + * * Note that this code is very hard to test under normal circumstances because * direct-io pins the pages with get_user_pages(). This makes * is_page_cache_freeable return false, and the VM will not clean the pages. @@ -553,8 +559,21 @@ void bio_set_pages_dirty(struct bio *bio) for (i = 0; i < bio->bi_vcnt; i++) { struct page *page = bvec[i].bv_page; + if (page && !PageCompound(page)) + set_page_dirty_lock(page); + } +} + +void bio_release_pages(struct bio *bio) +{ + struct bio_vec *bvec = bio->bi_io_vec; + int i; + + for (i = 0; i < bio->bi_vcnt; i++) { + struct page *page = bvec[i].bv_page; + if (page) - set_page_dirty_lock(bvec[i].bv_page); + put_page(page); } } @@ -592,6 +611,7 @@ static void bio_dirty_fn(void *data) struct bio *next = bio->bi_private; bio_set_pages_dirty(bio); + bio_release_pages(bio); bio_put(bio); bio = next; } @@ -606,7 +626,7 @@ void bio_check_pages_dirty(struct bio *bio) for (i = 0; i < bio->bi_vcnt; i++) { struct page *page = bvec[i].bv_page; - if (PageDirty(page)) { + if (PageDirty(page) || PageCompound(page)) { page_cache_release(page); bvec[i].bv_page = NULL; } else { diff --git a/fs/char_dev.c b/fs/char_dev.c index 44303f85e624..48f5a6791bec 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -445,3 +445,18 @@ void __init chrdev_init(void) kset_register(&kset_dynamic); cdev_map = kobj_map_init(base_probe, &cdev_subsys); } + + +/* Let modules do char dev stuff */ +EXPORT_SYMBOL(register_chrdev_region); +EXPORT_SYMBOL(unregister_chrdev_region); +EXPORT_SYMBOL(alloc_chrdev_region); +EXPORT_SYMBOL(cdev_init); +EXPORT_SYMBOL(cdev_alloc); +EXPORT_SYMBOL(cdev_get); +EXPORT_SYMBOL(cdev_put); +EXPORT_SYMBOL(cdev_del); +EXPORT_SYMBOL(cdev_add); +EXPORT_SYMBOL(cdev_unmap); +EXPORT_SYMBOL(register_chrdev); +EXPORT_SYMBOL(unregister_chrdev); diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index a513a4b823a9..5bce9b860d52 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -54,7 +54,7 @@ static void *alloc_upcall(int opcode, int size) inp->ih.opcode = opcode; inp->ih.pid = current->pid; - inp->ih.pgid = current->pgrp; + inp->ih.pgid = process_group(current); #ifdef CODA_FS_OLD_API memset(&inp->ih.cred, 0, sizeof(struct coda_cred)); inp->ih.cred.cr_fsuid = current->fsuid; diff --git a/fs/devfs/base.c b/fs/devfs/base.c index dd03e0397cc2..73894d9af19c 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c @@ -1334,7 +1334,7 @@ static int is_devfsd_or_child (struct fs_info *fs_info) struct task_struct *p = current; if (p == fs_info->devfsd_task) return (TRUE); - if (p->pgrp == fs_info->devfsd_pgrp) return (TRUE); + if (process_group(p) == fs_info->devfsd_pgrp) return (TRUE); read_lock(&tasklist_lock); for ( ; p != &init_task; p = p->real_parent) { @@ -2744,8 +2744,8 @@ static int devfsd_ioctl (struct inode *inode, struct file *file, } fs_info->devfsd_task = current; spin_unlock (&lock); - fs_info->devfsd_pgrp = (current->pgrp == current->pid) ? - current->pgrp : 0; + fs_info->devfsd_pgrp = (process_group(current) == current->pid) ? + process_group(current) : 0; fs_info->devfsd_file = file; fs_info->devfsd_info = kmalloc (sizeof *fs_info->devfsd_info, GFP_KERNEL); diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index cf9edd99e492..c19edbc42457 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1932,9 +1932,6 @@ void __journal_file_buffer(struct journal_head *jh, J_ASSERT_JH(jh, jbd_is_locked_bh_state(bh)); assert_spin_locked(&transaction->t_journal->j_list_lock); -#ifdef __SMP__ - J_ASSERT (current->lock_depth >= 0); -#endif J_ASSERT_JH(jh, jh->b_jlist < BJ_Types); J_ASSERT_JH(jh, jh->b_transaction == transaction || jh->b_transaction == 0); diff --git a/fs/locks.c b/fs/locks.c index 023a510e5676..d7a2688c8e5c 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -221,7 +221,7 @@ void locks_copy_lock(struct file_lock *new, struct file_lock *fl) static inline int flock_translate_cmd(int cmd) { if (cmd & LOCK_MAND) return cmd & (LOCK_MAND | LOCK_RW); - switch (cmd &~ LOCK_NB) { + switch (cmd) { case LOCK_SH: return F_RDLCK; case LOCK_EX: @@ -233,8 +233,8 @@ static inline int flock_translate_cmd(int cmd) { } /* Fill in a file_lock structure with an appropriate FLOCK lock. */ -static int flock_make_lock(struct file *filp, - struct file_lock **lock, unsigned int cmd) +static int flock_make_lock(struct file *filp, struct file_lock **lock, + unsigned int cmd) { struct file_lock *fl; int type = flock_translate_cmd(cmd); @@ -247,7 +247,7 @@ static int flock_make_lock(struct file *filp, fl->fl_file = filp; fl->fl_pid = current->tgid; - fl->fl_flags = (cmd & LOCK_NB) ? FL_FLOCK : FL_FLOCK | FL_SLEEP; + fl->fl_flags = FL_FLOCK; fl->fl_type = type; fl->fl_end = OFFSET_MAX; @@ -1265,9 +1265,8 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg) locks_free_lock(fl); goto out_unlock; } - fl->fl_next = *before; - *before = fl; - list_add(&fl->fl_link, &file_lock_list); + + locks_insert_lock(before, fl); error = f_setown(filp, current->tgid, 1); out_unlock: @@ -1298,6 +1297,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) { struct file *filp; struct file_lock *lock; + int can_sleep, unlock; int error; error = -EBADF; @@ -1305,12 +1305,18 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) if (!filp) goto out; - if ((cmd != LOCK_UN) && !(cmd & LOCK_MAND) && !(filp->f_mode & 3)) + can_sleep = !(cmd & LOCK_NB); + cmd &= ~LOCK_NB; + unlock = (cmd == LOCK_UN); + + if (!unlock && !(cmd & LOCK_MAND) && !(filp->f_mode & 3)) goto out_putf; error = flock_make_lock(filp, &lock, cmd); if (error) goto out_putf; + if (can_sleep) + lock->fl_flags |= FL_SLEEP; error = security_file_lock(filp, cmd); if (error) @@ -1318,7 +1324,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) for (;;) { error = flock_lock_file(filp, lock); - if ((error != -EAGAIN) || (cmd & LOCK_NB)) + if ((error != -EAGAIN) || !can_sleep) break; error = wait_event_interruptible(lock->fl_wait, !lock->fl_next); if (!error) @@ -1329,7 +1335,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd) } out_free: - if (error) { + if (list_empty(&lock->fl_link)) { locks_free_lock(lock); } diff --git a/fs/nls/Makefile b/fs/nls/Makefile index f56c8d4ce844..4548f2940327 100644 --- a/fs/nls/Makefile +++ b/fs/nls/Makefile @@ -19,14 +19,13 @@ obj-$(CONFIG_NLS_CODEPAGE_864) += nls_cp864.o obj-$(CONFIG_NLS_CODEPAGE_865) += nls_cp865.o obj-$(CONFIG_NLS_CODEPAGE_866) += nls_cp866.o obj-$(CONFIG_NLS_CODEPAGE_869) += nls_cp869.o -obj-$(CONFIG_NLS_CODEPAGE_874) += nls_cp874.o nls_tis-620.o -obj-$(CONFIG_NLS_CODEPAGE_932) += nls_cp932.o nls_sjis.o nls_euc-jp.o -obj-$(CONFIG_NLS_CODEPAGE_936) += nls_cp936.o nls_gb2312.o -obj-$(CONFIG_NLS_CODEPAGE_949) += nls_cp949.o nls_euc-kr.o -obj-$(CONFIG_NLS_CODEPAGE_950) += nls_cp950.o nls_big5.o +obj-$(CONFIG_NLS_CODEPAGE_874) += nls_cp874.o +obj-$(CONFIG_NLS_CODEPAGE_932) += nls_cp932.o nls_euc-jp.o +obj-$(CONFIG_NLS_CODEPAGE_936) += nls_cp936.o +obj-$(CONFIG_NLS_CODEPAGE_949) += nls_cp949.o +obj-$(CONFIG_NLS_CODEPAGE_950) += nls_cp950.o obj-$(CONFIG_NLS_CODEPAGE_1250) += nls_cp1250.o obj-$(CONFIG_NLS_CODEPAGE_1251) += nls_cp1251.o -obj-$(CONFIG_NLS_CODEPAGE_1255) += nls_cp1255.o obj-$(CONFIG_NLS_ISO8859_1) += nls_iso8859-1.o obj-$(CONFIG_NLS_ISO8859_2) += nls_iso8859-2.o obj-$(CONFIG_NLS_ISO8859_3) += nls_iso8859-3.o @@ -34,7 +33,7 @@ obj-$(CONFIG_NLS_ISO8859_4) += nls_iso8859-4.o obj-$(CONFIG_NLS_ISO8859_5) += nls_iso8859-5.o obj-$(CONFIG_NLS_ISO8859_6) += nls_iso8859-6.o obj-$(CONFIG_NLS_ISO8859_7) += nls_iso8859-7.o -obj-$(CONFIG_NLS_ISO8859_8) += nls_cp1255.o nls_iso8859-8.o +obj-$(CONFIG_NLS_ISO8859_8) += nls_cp1255.o obj-$(CONFIG_NLS_ISO8859_9) += nls_iso8859-9.o obj-$(CONFIG_NLS_ISO8859_10) += nls_iso8859-10.o obj-$(CONFIG_NLS_ISO8859_13) += nls_iso8859-13.o diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c index 972e46073072..d0904e1c94b2 100644 --- a/fs/nls/nls_base.c +++ b/fs/nls/nls_base.c @@ -203,9 +203,12 @@ static struct nls_table *find_nls(char *charset) { struct nls_table *nls; spin_lock(&nls_lock); - for (nls = tables; nls; nls = nls->next) + for (nls = tables; nls; nls = nls->next) { if (!strcmp(nls->charset, charset)) break; + if (nls->alias && !strcmp(nls->alias, charset)) + break; + } if (nls && !try_module_get(nls->owner)) nls = NULL; spin_unlock(&nls_lock); diff --git a/fs/nls/nls_big5.c b/fs/nls/nls_big5.c deleted file mode 100644 index ce8792b4bb3e..000000000000 --- a/fs/nls/nls_big5.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_big5.c - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/nls.h> -#include <linux/errno.h> - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "big5", - .owner = THIS_MODULE, -}; - -static int __init init_nls_big5(void) -{ - p_nls = load_nls("cp950"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_big5(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_big5) -module_exit(exit_nls_big5) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/fs/nls/nls_cp1250.c b/fs/nls/nls_cp1250.c index 982dc66a5227..32e78cf95180 100644 --- a/fs/nls/nls_cp1250.c +++ b/fs/nls/nls_cp1250.c @@ -345,21 +345,3 @@ module_init(init_nls_cp1250) module_exit(exit_nls_cp1250) MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ - diff --git a/fs/nls/nls_cp1251.c b/fs/nls/nls_cp1251.c index 3200c874a8a0..cb41c8ae4486 100644 --- a/fs/nls/nls_cp1251.c +++ b/fs/nls/nls_cp1251.c @@ -299,20 +299,4 @@ static void __exit exit_nls_cp1251(void) module_init(init_nls_cp1251) module_exit(exit_nls_cp1251) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp1255.c b/fs/nls/nls_cp1255.c index 479ef421f738..efdeefee5346 100644 --- a/fs/nls/nls_cp1255.c +++ b/fs/nls/nls_cp1255.c @@ -360,6 +360,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni) static struct nls_table table = { .charset = "cp1255", + .alias = "iso8859-8", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -380,20 +381,5 @@ static void __exit exit_nls_cp1255(void) module_init(init_nls_cp1255) module_exit(exit_nls_cp1255) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(iso8859-8); diff --git a/fs/nls/nls_cp437.c b/fs/nls/nls_cp437.c index e54aae3db06b..5c4a1cd685dd 100644 --- a/fs/nls/nls_cp437.c +++ b/fs/nls/nls_cp437.c @@ -385,20 +385,4 @@ static void __exit exit_nls_cp437(void) module_init(init_nls_cp437) module_exit(exit_nls_cp437) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp737.c b/fs/nls/nls_cp737.c index 043ffde515fa..e8b3ca8462e7 100644 --- a/fs/nls/nls_cp737.c +++ b/fs/nls/nls_cp737.c @@ -348,20 +348,4 @@ static void __exit exit_nls_cp737(void) module_init(init_nls_cp737) module_exit(exit_nls_cp737) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp775.c b/fs/nls/nls_cp775.c index 3af27ba5483e..bdb290ea523a 100644 --- a/fs/nls/nls_cp775.c +++ b/fs/nls/nls_cp775.c @@ -317,20 +317,4 @@ static void __exit exit_nls_cp775(void) module_init(init_nls_cp775) module_exit(exit_nls_cp775) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp850.c b/fs/nls/nls_cp850.c index 1799c1b04fb8..25deaa4c8648 100644 --- a/fs/nls/nls_cp850.c +++ b/fs/nls/nls_cp850.c @@ -313,20 +313,4 @@ static void __exit exit_nls_cp850(void) module_init(init_nls_cp850) module_exit(exit_nls_cp850) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp852.c b/fs/nls/nls_cp852.c index 8e06b85a8d3a..b822a7b6b970 100644 --- a/fs/nls/nls_cp852.c +++ b/fs/nls/nls_cp852.c @@ -335,20 +335,4 @@ static void __exit exit_nls_cp852(void) module_init(init_nls_cp852) module_exit(exit_nls_cp852) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp855.c b/fs/nls/nls_cp855.c index bf322f283300..e8641b7a8b27 100644 --- a/fs/nls/nls_cp855.c +++ b/fs/nls/nls_cp855.c @@ -297,20 +297,4 @@ static void __exit exit_nls_cp855(void) module_init(init_nls_cp855) module_exit(exit_nls_cp855) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp857.c b/fs/nls/nls_cp857.c index 5296a7d33582..7ba589ef8cc0 100644 --- a/fs/nls/nls_cp857.c +++ b/fs/nls/nls_cp857.c @@ -299,20 +299,4 @@ static void __exit exit_nls_cp857(void) module_init(init_nls_cp857) module_exit(exit_nls_cp857) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp860.c b/fs/nls/nls_cp860.c index 5b43e726778b..3b9e49ce8c80 100644 --- a/fs/nls/nls_cp860.c +++ b/fs/nls/nls_cp860.c @@ -362,20 +362,4 @@ static void __exit exit_nls_cp860(void) module_init(init_nls_cp860) module_exit(exit_nls_cp860) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp861.c b/fs/nls/nls_cp861.c index 1beafa8cf364..959ff64ee971 100644 --- a/fs/nls/nls_cp861.c +++ b/fs/nls/nls_cp861.c @@ -385,20 +385,4 @@ static void __exit exit_nls_cp861(void) module_init(init_nls_cp861) module_exit(exit_nls_cp861) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp862.c b/fs/nls/nls_cp862.c index e5e6254a85de..b96928f5a023 100644 --- a/fs/nls/nls_cp862.c +++ b/fs/nls/nls_cp862.c @@ -419,20 +419,4 @@ static void __exit exit_nls_cp862(void) module_init(init_nls_cp862) module_exit(exit_nls_cp862) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp863.c b/fs/nls/nls_cp863.c index 2878908fdce5..baa6e0eab1d6 100644 --- a/fs/nls/nls_cp863.c +++ b/fs/nls/nls_cp863.c @@ -379,20 +379,4 @@ static void __exit exit_nls_cp863(void) module_init(init_nls_cp863) module_exit(exit_nls_cp863) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp864.c b/fs/nls/nls_cp864.c index 84353d50a774..f4dabb037dfe 100644 --- a/fs/nls/nls_cp864.c +++ b/fs/nls/nls_cp864.c @@ -405,20 +405,4 @@ static void __exit exit_nls_cp864(void) module_init(init_nls_cp864) module_exit(exit_nls_cp864) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp865.c b/fs/nls/nls_cp865.c index be670ae14250..4caeafae32c2 100644 --- a/fs/nls/nls_cp865.c +++ b/fs/nls/nls_cp865.c @@ -385,20 +385,4 @@ static void __exit exit_nls_cp865(void) module_init(init_nls_cp865) module_exit(exit_nls_cp865) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp866.c b/fs/nls/nls_cp866.c index 66319e6cb8d7..f2b4a9a293fb 100644 --- a/fs/nls/nls_cp866.c +++ b/fs/nls/nls_cp866.c @@ -303,20 +303,4 @@ static void __exit exit_nls_cp866(void) module_init(init_nls_cp866) module_exit(exit_nls_cp866) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp869.c b/fs/nls/nls_cp869.c index 13718f32eba1..12b436f4eca1 100644 --- a/fs/nls/nls_cp869.c +++ b/fs/nls/nls_cp869.c @@ -313,20 +313,4 @@ static void __exit exit_nls_cp869(void) module_init(init_nls_cp869) module_exit(exit_nls_cp869) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_cp874.c b/fs/nls/nls_cp874.c index 34ae4cf7979c..b5766a01703a 100644 --- a/fs/nls/nls_cp874.c +++ b/fs/nls/nls_cp874.c @@ -251,6 +251,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni) static struct nls_table table = { .charset = "cp874", + .alias = "tis-620", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -271,20 +272,5 @@ static void __exit exit_nls_cp874(void) module_init(init_nls_cp874) module_exit(exit_nls_cp874) -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(tis-620); diff --git a/fs/nls/nls_cp932.c b/fs/nls/nls_cp932.c index a30961bccc34..af796a76315f 100644 --- a/fs/nls/nls_cp932.c +++ b/fs/nls/nls_cp932.c @@ -7885,6 +7885,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, static struct nls_table table = { .charset = "cp932", + .alias = "sjis", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -7904,22 +7905,6 @@ static void __exit exit_nls_cp932(void) module_init(init_nls_cp932) module_exit(exit_nls_cp932) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(sjis); diff --git a/fs/nls/nls_cp936.c b/fs/nls/nls_cp936.c index 06a4dee6372d..33e57a387a33 100644 --- a/fs/nls/nls_cp936.c +++ b/fs/nls/nls_cp936.c @@ -11005,6 +11005,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, static struct nls_table table = { .charset = "cp936", + .alias = "gb2312", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -11024,22 +11025,6 @@ static void __exit exit_nls_cp936(void) module_init(init_nls_cp936) module_exit(exit_nls_cp936) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(gb2312); diff --git a/fs/nls/nls_cp949.c b/fs/nls/nls_cp949.c index e1e4e9062b77..b21d56aba6b4 100644 --- a/fs/nls/nls_cp949.c +++ b/fs/nls/nls_cp949.c @@ -13922,6 +13922,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, static struct nls_table table = { .charset = "cp949", + .alias = "euc-kr", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -13941,22 +13942,6 @@ static void __exit exit_nls_cp949(void) module_init(init_nls_cp949) module_exit(exit_nls_cp949) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(euc-kr); diff --git a/fs/nls/nls_cp950.c b/fs/nls/nls_cp950.c index 604fd4874be6..3a478e547ef6 100644 --- a/fs/nls/nls_cp950.c +++ b/fs/nls/nls_cp950.c @@ -9461,6 +9461,7 @@ static int char2uni(const unsigned char *rawstring, int boundlen, static struct nls_table table = { .charset = "cp950", + .alias = "big5", .uni2char = uni2char, .char2uni = char2uni, .charset2lower = charset2lower, @@ -9480,22 +9481,6 @@ static void __exit exit_nls_cp950(void) module_init(init_nls_cp950) module_exit(exit_nls_cp950) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NLS(big5); diff --git a/fs/nls/nls_euc-jp.c b/fs/nls/nls_euc-jp.c index 258f91942db0..80f108ae6661 100644 --- a/fs/nls/nls_euc-jp.c +++ b/fs/nls/nls_euc-jp.c @@ -579,22 +579,5 @@ static void __exit exit_nls_euc_jp(void) module_init(init_nls_euc_jp) module_exit(exit_nls_euc_jp) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_euc-kr.c b/fs/nls/nls_euc-kr.c deleted file mode 100644 index adbf5ffa3496..000000000000 --- a/fs/nls/nls_euc-kr.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_euc-kr.c - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/nls.h> -#include <linux/errno.h> - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "euc-kr", - .owner = THIS_MODULE, -}; - -static int __init init_nls_euc_kr(void) -{ - p_nls = load_nls("cp949"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_euc_kr(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_euc_kr) -module_exit(exit_nls_euc_kr) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/fs/nls/nls_gb2312.c b/fs/nls/nls_gb2312.c deleted file mode 100644 index 7d92be88c05c..000000000000 --- a/fs/nls/nls_gb2312.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_gb2312.c - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/nls.h> -#include <linux/errno.h> - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "gb2312", - .owner = THIS_MODULE, -}; - -static int __init init_nls_gb2312(void) -{ - p_nls = load_nls("cp936"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_gb2312(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_gb2312) -module_exit(exit_nls_gb2312) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/fs/nls/nls_iso8859-1.c b/fs/nls/nls_iso8859-1.c index e10a982e2af4..70a2c1956723 100644 --- a/fs/nls/nls_iso8859-1.c +++ b/fs/nls/nls_iso8859-1.c @@ -254,21 +254,5 @@ static void __exit exit_nls_iso8859_1(void) module_init(init_nls_iso8859_1) module_exit(exit_nls_iso8859_1) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_iso8859-13.c b/fs/nls/nls_iso8859-13.c index 7cd4bd876c1c..4547035f21a3 100644 --- a/fs/nls/nls_iso8859-13.c +++ b/fs/nls/nls_iso8859-13.c @@ -282,21 +282,5 @@ static void __exit exit_nls_iso8859_13(void) module_init(init_nls_iso8859_13) module_exit(exit_nls_iso8859_13) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_iso8859-14.c b/fs/nls/nls_iso8859-14.c index 46dcc6b4cdc5..13628d0dd3a9 100644 --- a/fs/nls/nls_iso8859-14.c +++ b/fs/nls/nls_iso8859-14.c @@ -338,21 +338,5 @@ static void __exit exit_nls_iso8859_14(void) module_init(init_nls_iso8859_14) module_exit(exit_nls_iso8859_14) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_iso8859-15.c b/fs/nls/nls_iso8859-15.c index 285065950c3a..88b924bf7e18 100644 --- a/fs/nls/nls_iso8859-15.c +++ b/fs/nls/nls_iso8859-15.c @@ -304,21 +304,5 @@ static void __exit exit_nls_iso8859_15(void) module_init(init_nls_iso8859_15) module_exit(exit_nls_iso8859_15) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_iso8859-2.c b/fs/nls/nls_iso8859-2.c index fb2ff3d5d83e..372528a6c40c 100644 --- a/fs/nls/nls_iso8859-2.c +++ b/fs/nls/nls_iso8859-2.c @@ -305,21 +305,5 @@ static void __exit exit_nls_iso8859_2(void) module_init(init_nls_iso8859_2) module_exit(exit_nls_iso8859_2) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_iso8859-3.c b/fs/nls/nls_iso8859-3.c index 3ecde03594ee..81b45a234369 100644 --- a/fs/nls/nls_iso8859-3.c +++ b/fs/nls/nls_iso8859-3.c @@ -305,21 +305,5 @@ static void __exit exit_nls_iso8859_3(void) module_init(init_nls_iso8859_3) module_exit(exit_nls_iso8859_3) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_iso8859-4.c b/fs/nls/nls_iso8859-4.c index 901d3f2eb854..101b87f5a49b 100644 --- a/fs/nls/nls_iso8859-4.c +++ b/fs/nls/nls_iso8859-4.c @@ -305,21 +305,5 @@ static void __exit exit_nls_iso8859_4(void) module_init(init_nls_iso8859_4) module_exit(exit_nls_iso8859_4) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_iso8859-5.c b/fs/nls/nls_iso8859-5.c index bb654b74db5e..83b0084de5eb 100644 --- a/fs/nls/nls_iso8859-5.c +++ b/fs/nls/nls_iso8859-5.c @@ -269,21 +269,5 @@ static void __exit exit_nls_iso8859_5(void) module_init(init_nls_iso8859_5) module_exit(exit_nls_iso8859_5) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_iso8859-6.c b/fs/nls/nls_iso8859-6.c index 248c50a557ae..0c519d65f55b 100644 --- a/fs/nls/nls_iso8859-6.c +++ b/fs/nls/nls_iso8859-6.c @@ -260,21 +260,5 @@ static void __exit exit_nls_iso8859_6(void) module_init(init_nls_iso8859_6) module_exit(exit_nls_iso8859_6) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_iso8859-7.c b/fs/nls/nls_iso8859-7.c index 49a63e989f9a..bd0854625acf 100644 --- a/fs/nls/nls_iso8859-7.c +++ b/fs/nls/nls_iso8859-7.c @@ -314,21 +314,5 @@ static void __exit exit_nls_iso8859_7(void) module_init(init_nls_iso8859_7) module_exit(exit_nls_iso8859_7) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_iso8859-8.c b/fs/nls/nls_iso8859-8.c deleted file mode 100644 index 5f368b14066a..000000000000 --- a/fs/nls/nls_iso8859-8.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_iso8859-8.c - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/nls.h> -#include <linux/errno.h> - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "iso8859-8", - .owner = THIS_MODULE, -}; - -static int __init init_nls_iso8859_8(void) -{ - p_nls = load_nls("cp1255"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_iso8859_8(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_iso8859_8) -module_exit(exit_nls_iso8859_8) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/fs/nls/nls_iso8859-9.c b/fs/nls/nls_iso8859-9.c index d47908043afe..988eff791c06 100644 --- a/fs/nls/nls_iso8859-9.c +++ b/fs/nls/nls_iso8859-9.c @@ -269,21 +269,5 @@ static void __exit exit_nls_iso8859_9(void) module_init(init_nls_iso8859_9) module_exit(exit_nls_iso8859_9) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_koi8-r.c b/fs/nls/nls_koi8-r.c index 446a9a8015f2..0ad22c249796 100644 --- a/fs/nls/nls_koi8-r.c +++ b/fs/nls/nls_koi8-r.c @@ -320,21 +320,5 @@ static void __exit exit_nls_koi8_r(void) module_init(init_nls_koi8_r) module_exit(exit_nls_koi8_r) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_koi8-ru.c b/fs/nls/nls_koi8-ru.c index ff73403b3407..5db83efe27c6 100644 --- a/fs/nls/nls_koi8-ru.c +++ b/fs/nls/nls_koi8-ru.c @@ -79,21 +79,5 @@ static void __exit exit_nls_koi8_ru(void) module_init(init_nls_koi8_ru) module_exit(exit_nls_koi8_ru) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_koi8-u.c b/fs/nls/nls_koi8-u.c index e9b4d3742241..9d30fd61cf46 100644 --- a/fs/nls/nls_koi8-u.c +++ b/fs/nls/nls_koi8-u.c @@ -327,21 +327,5 @@ static void __exit exit_nls_koi8_u(void) module_init(init_nls_koi8_u) module_exit(exit_nls_koi8_u) -MODULE_LICENSE("Dual BSD/GPL"); -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/fs/nls/nls_sjis.c b/fs/nls/nls_sjis.c deleted file mode 100644 index d70a5305a87a..000000000000 --- a/fs/nls/nls_sjis.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_sjis.c - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/nls.h> -#include <linux/errno.h> - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "sjis", - .owner = THIS_MODULE, -}; - -static int __init init_nls_sjis(void) -{ - p_nls = load_nls("cp932"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_sjis(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_sjis) -module_exit(exit_nls_sjis) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/fs/nls/nls_tis-620.c b/fs/nls/nls_tis-620.c deleted file mode 100644 index 4fcea5e4dd36..000000000000 --- a/fs/nls/nls_tis-620.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * linux/fs/nls_tis-620.c - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/nls.h> -#include <linux/errno.h> - -static struct nls_table *p_nls; - -static struct nls_table table = { - .charset = "tis-620", - .owner = THIS_MODULE, -}; - -static int __init init_nls_tis_620(void) -{ - p_nls = load_nls("cp874"); - - if (p_nls) { - table.uni2char = p_nls->uni2char; - table.char2uni = p_nls->char2uni; - table.charset2upper = p_nls->charset2upper; - table.charset2lower = p_nls->charset2lower; - return register_nls(&table); - } - - return -EINVAL; -} - -static void __exit exit_nls_tis_620(void) -{ - unregister_nls(&table); - unload_nls(p_nls); -} - -module_init(init_nls_tis_620) -module_exit(exit_nls_tis_620) -MODULE_LICENSE("Dual BSD/GPL"); - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * ---------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 8 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -8 - * c-argdecl-indent: 8 - * c-label-offset: -8 - * c-continued-statement-offset: 8 - * c-continued-brace-offset: 0 - * End: - */ diff --git a/fs/proc/array.c b/fs/proc/array.c index a7a3bdaac4ec..bf39eb5013b0 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -154,13 +154,16 @@ static inline char * task_state(struct task_struct *p, char *buffer) read_lock(&tasklist_lock); buffer += sprintf(buffer, "State:\t%s\n" + "SleepAVG:\t%lu%%\n" "Tgid:\t%d\n" "Pid:\t%d\n" "PPid:\t%d\n" "TracerPid:\t%d\n" "Uid:\t%d\t%d\t%d\t%d\n" "Gid:\t%d\t%d\t%d\t%d\n", - get_task_state(p), p->tgid, + get_task_state(p), + (p->sleep_avg/1024)*100/(1000000000/1024), + p->tgid, p->pid, p->pid ? p->real_parent->pid : 0, p->pid && p->ptrace ? p->parent->pid : 0, p->uid, p->euid, p->suid, p->fsuid, @@ -341,7 +344,7 @@ int proc_pid_stat(struct task_struct *task, char * buffer) task->comm, state, ppid, - task->pgrp, + process_group(task), task->session, tty_nr, tty_pgrp, diff --git a/fs/proc/base.c b/fs/proc/base.c index 82dc461f0686..640cddefdb78 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1196,8 +1196,10 @@ static struct file_operations proc_pid_attr_operations = { .write = proc_pid_attr_write, }; -static struct file_operations proc_attr_operations; -static struct inode_operations proc_attr_inode_operations; +static struct file_operations proc_tid_attr_operations; +static struct inode_operations proc_tid_attr_inode_operations; +static struct file_operations proc_tgid_attr_operations; +static struct inode_operations proc_tgid_attr_inode_operations; #endif /* SMP-safe */ @@ -1304,10 +1306,14 @@ static struct dentry *proc_pident_lookup(struct inode *dir, break; #ifdef CONFIG_SECURITY case PROC_TID_ATTR: + inode->i_nlink = 2; + inode->i_op = &proc_tid_attr_inode_operations; + inode->i_fop = &proc_tid_attr_operations; + break; case PROC_TGID_ATTR: inode->i_nlink = 2; - inode->i_op = &proc_attr_inode_operations; - inode->i_fop = &proc_attr_operations; + inode->i_op = &proc_tgid_attr_inode_operations; + inode->i_fop = &proc_tgid_attr_operations; break; case PROC_TID_ATTR_CURRENT: case PROC_TGID_ATTR_CURRENT: @@ -1713,11 +1719,14 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi nr_tids = get_tid_list(pos, tid_array, inode); for (i = 0; i < nr_tids; i++) { + unsigned long j = PROC_NUMBUF; int tid = tid_array[i]; + ino = fake_ino(tid,PROC_TID_INO); - unsigned long j = PROC_NUMBUF; - do buf[--j] = '0' + (tid % 10); while (tid/=10); + do + buf[--j] = '0' + (tid % 10); + while (tid /= 10); if (filldir(dirent, buf+j, PROC_NUMBUF-j, pos, ino, DT_DIR) < 0) break; diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index ff2e4ff85540..02d21630d495 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -784,7 +784,7 @@ int reiserfs_prepare_file_region_for_write( /* Now if all the write area lies past the file end, no point in maping blocks, since there is none, so we just zero out remaining parts of first and last pages in write area (if needed) */ - if ( (pos & ~(PAGE_CACHE_SIZE - 1)) > inode->i_size ) { + if ( (pos & ~((loff_t)PAGE_CACHE_SIZE - 1)) > inode->i_size ) { if ( from != 0 ) {/* First page needs to be partially zeroed */ char *kaddr = kmap_atomic(prepared_pages[0], KM_USER0); memset(kaddr, 0, from); @@ -806,9 +806,9 @@ int reiserfs_prepare_file_region_for_write( we need to allocate (calculated above) */ /* Mask write position to start on blocksize, we do it out of the loop for performance reasons */ - pos &= ~(inode->i_sb->s_blocksize - 1); + pos &= ~((loff_t) inode->i_sb->s_blocksize - 1); /* Set cpu key to the starting position in a file (on left block boundary)*/ - make_cpu_key (&key, inode, 1 + ((pos) & ~(inode->i_sb->s_blocksize - 1)), TYPE_ANY, 3/*key length*/); + make_cpu_key (&key, inode, 1 + ((pos) & ~((loff_t) inode->i_sb->s_blocksize - 1)), TYPE_ANY, 3/*key length*/); reiserfs_write_lock(inode->i_sb); // We need that for at least search_by_key() for ( i = 0; i < num_pages ; i++ ) { diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 803d414747e3..8950c7fb0209 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -1406,6 +1406,10 @@ static int journal_transaction_is_valid(struct super_block *p_s_sb, struct buffe *newest_mount_id) ; return -1 ; } + if ( get_desc_trans_len(desc) > SB_JOURNAL_TRANS_MAX(p_s_sb) ) { + reiserfs_warning("journal-2018: Bad transaction length %d encountered, ignoring transaction\n", get_desc_trans_len(desc)); + return -1 ; + } offset = d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) ; /* ok, we have a journal description block, lets see if the transaction was valid */ @@ -1422,11 +1426,12 @@ static int journal_transaction_is_valid(struct super_block *p_s_sb, struct buffe get_commit_trans_id (commit), get_commit_trans_len(commit)); brelse(c_bh) ; - if (oldest_invalid_trans_id) - *oldest_invalid_trans_id = get_desc_trans_id(desc) ; + if (oldest_invalid_trans_id) { + *oldest_invalid_trans_id = get_desc_trans_id(desc) ; reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1004: " "transaction_is_valid setting oldest invalid trans_id " "to %d\n", get_desc_trans_id(desc)) ; + } return -1; } brelse(c_bh) ; @@ -1527,9 +1532,14 @@ static int journal_read_transaction(struct super_block *p_s_sb, unsigned long cu } else { real_blocks[i] = sb_getblk(p_s_sb, le32_to_cpu(commit->j_realblock[i - trans_half])) ; } + if ( real_blocks[i]->b_blocknr > SB_BLOCK_COUNT(p_s_sb) ) { + reiserfs_warning("journal-1207: REPLAY FAILURE fsck required! Block to replay is outside of filesystem\n"); + goto abort_replay; + } /* make sure we don't try to replay onto log or reserved area */ if (is_block_in_log_or_reserved_area(p_s_sb, real_blocks[i]->b_blocknr)) { reiserfs_warning("journal-1204: REPLAY FAILURE fsck required! Trying to replay onto a log block\n") ; +abort_replay: brelse_array(log_blocks, i) ; brelse_array(real_blocks, i) ; brelse(c_bh) ; diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 64892e35c677..fd4ca1a92836 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -1264,6 +1264,18 @@ static int reiserfs_fill_super (struct super_block * s, void * data, int silent) printk("sh-2021: reiserfs_fill_super: can not find reiserfs on %s\n", reiserfs_bdevname (s)); goto error; } + + rs = SB_DISK_SUPER_BLOCK (s); + /* Let's do basic sanity check to verify that underlying device is not + smaller than the filesystem. If the check fails then abort and scream, + because bad stuff will happen otherwise. */ + if ( s->s_bdev && s->s_bdev->bd_inode && i_size_read(s->s_bdev->bd_inode) < sb_block_count(rs)*sb_blocksize(rs) ) { + printk("Filesystem on %s cannot be mounted because it is bigger than the device\n", reiserfs_bdevname(s)); + printk("You may need to run fsck or increase size of your LVM partition\n"); + printk("Or may be you forgot to reboot after fdisk when it told you to\n"); + goto error; + } + sbi->s_mount_state = SB_REISERFS_STATE(s); sbi->s_mount_state = REISERFS_VALID_FS ; @@ -1324,7 +1336,6 @@ static int reiserfs_fill_super (struct super_block * s, void * data, int silent) goto error ; } - rs = SB_DISK_SUPER_BLOCK (s); if (is_reiserfs_3_5 (rs) || (is_reiserfs_jr (rs) && SB_VERSION (s) == REISERFS_VERSION_1)) set_bit(REISERFS_3_5, &(sbi->s_properties)); else diff --git a/include/asm-alpha/signal.h b/include/asm-alpha/signal.h index 27282f335de4..e24248f01340 100644 --- a/include/asm-alpha/signal.h +++ b/include/asm-alpha/signal.h @@ -71,7 +71,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-arm/arch-iop3xx/iop321-irqs.h b/include/asm-arm/arch-iop3xx/iop321-irqs.h index 6e757b819105..9d5518da56fc 100644 --- a/include/asm-arm/arch-iop3xx/iop321-irqs.h +++ b/include/asm-arm/arch-iop3xx/iop321-irqs.h @@ -10,6 +10,7 @@ * */ +#include <linux/config.h> /* * IOP80321 chipset interrupts diff --git a/include/asm-arm/arch-iop3xx/irqs.h b/include/asm-arm/arch-iop3xx/irqs.h index 7468fab71d94..1df33024c8ea 100644 --- a/include/asm-arm/arch-iop3xx/irqs.h +++ b/include/asm-arm/arch-iop3xx/irqs.h @@ -10,6 +10,8 @@ * */ +#include <linux/config.h> + /* * Whic iop3xx implementation is this? */ diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h index 9faf4e77b305..638bd35d7964 100644 --- a/include/asm-arm/arch-pxa/hardware.h +++ b/include/asm-arm/arch-pxa/hardware.h @@ -13,7 +13,6 @@ #ifndef __ASM_ARCH_HARDWARE_H #define __ASM_ARCH_HARDWARE_H -#include <linux/config.h> #include <asm/mach-types.h> diff --git a/include/asm-arm/arch-pxa/ide.h b/include/asm-arm/arch-pxa/ide.h index 926797e14a06..71a2e11b0206 100644 --- a/include/asm-arm/arch-pxa/ide.h +++ b/include/asm-arm/arch-pxa/ide.h @@ -14,7 +14,6 @@ * */ -#include <linux/config.h> #include <asm/irq.h> #include <asm/hardware.h> #include <asm/mach-types.h> diff --git a/include/asm-arm/arch-pxa/idp.h b/include/asm-arm/arch-pxa/idp.h index 63932060242e..e496ed7f496a 100644 --- a/include/asm-arm/arch-pxa/idp.h +++ b/include/asm-arm/arch-pxa/idp.h @@ -12,6 +12,7 @@ * */ +#include <linux/config.h> /* * Note: this file must be safe to include in assembly files diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h index 6d452434eabc..ba16af5ee41a 100644 --- a/include/asm-arm/arch-pxa/irqs.h +++ b/include/asm-arm/arch-pxa/irqs.h @@ -10,6 +10,8 @@ * published by the Free Software Foundation. */ +#include <linux/config.h> + #define PXA_IRQ_SKIP 7 /* The first 7 IRQs are not yet used */ #define PXA_IRQ(x) ((x) - PXA_IRQ_SKIP) diff --git a/include/asm-arm/arch-pxa/keyboard.h b/include/asm-arm/arch-pxa/keyboard.h index 8cd10f1aa231..7bec3179b189 100644 --- a/include/asm-arm/arch-pxa/keyboard.h +++ b/include/asm-arm/arch-pxa/keyboard.h @@ -7,7 +7,6 @@ #ifndef _PXA_KEYBOARD_H #define _PXA_KEYBOARD_H -#include <linux/config.h> #include <asm/mach-types.h> #include <asm/hardware.h> diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index 1823479b1057..15b8ddd50065 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ +#include <linux/config.h> // FIXME hack so that SA-1111.h will work [cb] diff --git a/include/asm-arm/arch-sa1100/serial.h b/include/asm-arm/arch-sa1100/serial.h index 74ebcd5c669c..a6a2267a2dfa 100644 --- a/include/asm-arm/arch-sa1100/serial.h +++ b/include/asm-arm/arch-sa1100/serial.h @@ -7,6 +7,8 @@ * This is included by serial.c -- serial_sa1100.c makes no use of it. */ +#include <linux/config.h> + /* Standard COM flags */ #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) diff --git a/include/asm-arm/arch-sa1100/trizeps.h b/include/asm-arm/arch-sa1100/trizeps.h index b9cc02bac5d9..1802947011be 100644 --- a/include/asm-arm/arch-sa1100/trizeps.h +++ b/include/asm-arm/arch-sa1100/trizeps.h @@ -13,6 +13,8 @@ #ifndef _ASM_ARCH_TRIZEPS_H_ #define _ASM_ARCH_TRIZEPS_H_ +#include <linux/config.h> + #ifdef CONFIG_TRIZEPS_MFTB2 #include "mftb2.h" #endif diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index 30a47cba4d4b..cff6d6f05913 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h @@ -10,6 +10,7 @@ #ifndef _ASMARM_CACHEFLUSH_H #define _ASMARM_CACHEFLUSH_H +#include <linux/config.h> #include <linux/sched.h> #include <linux/mm.h> diff --git a/include/asm-arm/mmu.h b/include/asm-arm/mmu.h index c33797d6cc7b..a457cb71984f 100644 --- a/include/asm-arm/mmu.h +++ b/include/asm-arm/mmu.h @@ -1,8 +1,6 @@ #ifndef __ARM_MMU_H #define __ARM_MMU_H -#include <linux/config.h> - typedef struct { #if __LINUX_ARM_ARCH__ >= 6 unsigned int id; diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h index 5b23a0a59778..9a09fb19258b 100644 --- a/include/asm-arm/pgtable.h +++ b/include/asm-arm/pgtable.h @@ -10,7 +10,6 @@ #ifndef _ASMARM_PGTABLE_H #define _ASMARM_PGTABLE_H -#include <linux/config.h> #include <asm/memory.h> #include <asm/proc-fns.h> #include <asm/arch/vmalloc.h> diff --git a/include/asm-arm/signal.h b/include/asm-arm/signal.h index eb59aa539b9c..6d623e24c0fb 100644 --- a/include/asm-arm/signal.h +++ b/include/asm-arm/signal.h @@ -68,7 +68,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG #define SIGSWI 32 diff --git a/include/asm-arm26/signal.h b/include/asm-arm26/signal.h index e166988dbd5c..6f62e51a2e5a 100644 --- a/include/asm-arm26/signal.h +++ b/include/asm-arm26/signal.h @@ -68,7 +68,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG #define SIGSWI 32 diff --git a/include/asm-cris/signal.h b/include/asm-cris/signal.h index 1335bf27d8e2..3f187ec4800a 100644 --- a/include/asm-cris/signal.h +++ b/include/asm-cris/signal.h @@ -68,7 +68,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-generic/cpumask_arith.h b/include/asm-generic/cpumask_arith.h index bd8712d38fee..c19a0a6e45f0 100644 --- a/include/asm-generic/cpumask_arith.h +++ b/include/asm-generic/cpumask_arith.h @@ -27,7 +27,12 @@ #define cpus_shift_right(dst, src, n) do { dst = (src) >> (n); } while (0) #define cpus_shift_left(dst, src, n) do { dst = (src) << (n); } while (0) -#define any_online_cpu(map) ({ (map) ? first_cpu(map) : NR_CPUS; }) +#define any_online_cpu(map) \ +({ \ + cpumask_t __tmp__; \ + cpus_and(__tmp__, map, cpu_online_map); \ + __tmp__ ? first_cpu(__tmp__) : NR_CPUS; \ +}) #define CPU_MASK_ALL (~((cpumask_t)0) >> (8*sizeof(cpumask_t) - NR_CPUS)) #define CPU_MASK_NONE ((cpumask_t)0) diff --git a/include/asm-generic/cpumask_array.h b/include/asm-generic/cpumask_array.h index 991a04bf7062..60c955d823b7 100644 --- a/include/asm-generic/cpumask_array.h +++ b/include/asm-generic/cpumask_array.h @@ -36,7 +36,13 @@ cpu_set(cpu, __cpu_mask); \ __cpu_mask; \ }) -#define any_online_cpu(map) find_first_bit((map).mask, NR_CPUS) +#define any_online_cpu(map) \ +({ \ + cpumask_t __tmp__; \ + cpus_and(__tmp__, map, cpu_online_map); \ + find_first_bit(__tmp__.mask, NR_CPUS); \ +}) + /* * um, these need to be usable as static initializers diff --git a/include/asm-h8300/signal.h b/include/asm-h8300/signal.h index 460d8a6f69f4..6612725c2297 100644 --- a/include/asm-h8300/signal.h +++ b/include/asm-h8300/signal.h @@ -68,7 +68,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-i386/genapic.h b/include/asm-i386/genapic.h index cd4b708133c3..76465ccbbdf8 100644 --- a/include/asm-i386/genapic.h +++ b/include/asm-i386/genapic.h @@ -30,6 +30,7 @@ struct genapic { unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid); unsigned long (*check_apicid_present)(int apicid); int no_balance_irq; + int no_ioapic_check; void (*init_apic_ldr)(void); physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map); @@ -77,6 +78,7 @@ struct genapic { .int_dest_mode = INT_DEST_MODE, \ .apic_broadcast_id = APIC_BROADCAST_ID, \ .no_balance_irq = NO_BALANCE_IRQ, \ + .no_ioapic_check = NO_IOAPIC_CHECK, \ APICFUNC(apic_id_registered), \ APICFUNC(target_cpus), \ APICFUNC(check_apicid_used), \ diff --git a/include/asm-i386/mach-bigsmp/mach_apic.h b/include/asm-i386/mach-bigsmp/mach_apic.h index dab6aa34c6fa..0e9855144660 100644 --- a/include/asm-i386/mach-bigsmp/mach_apic.h +++ b/include/asm-i386/mach-bigsmp/mach_apic.h @@ -14,6 +14,8 @@ #define NO_BALANCE_IRQ (1) #define esr_disable (1) +#define NO_IOAPIC_CHECK (0) + static inline int apic_id_registered(void) { return (1); diff --git a/include/asm-i386/mach-default/mach_apic.h b/include/asm-i386/mach-default/mach_apic.h index a96477cf10a0..8875f34285bd 100644 --- a/include/asm-i386/mach-default/mach_apic.h +++ b/include/asm-i386/mach-default/mach_apic.h @@ -18,6 +18,8 @@ static inline cpumask_t target_cpus(void) #define NO_BALANCE_IRQ (0) #define esr_disable (0) +#define NO_IOAPIC_CHECK (0) + #define INT_DELIVERY_MODE dest_LowestPrio #define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ diff --git a/include/asm-i386/mach-generic/mach_apic.h b/include/asm-i386/mach-generic/mach_apic.h index 71b4849614bc..21f0e75f1b25 100644 --- a/include/asm-i386/mach-generic/mach_apic.h +++ b/include/asm-i386/mach-generic/mach_apic.h @@ -5,6 +5,7 @@ #define esr_disable (genapic->esr_disable) #define NO_BALANCE_IRQ (genapic->no_balance_irq) +#define NO_IOAPIC_CHECK (genapic->no_ioapic_check) #define APIC_BROADCAST_ID (genapic->apic_broadcast_id) #define INT_DELIVERY_MODE (genapic->int_delivery_mode) #define INT_DEST_MODE (genapic->int_dest_mode) diff --git a/include/asm-i386/mach-numaq/mach_apic.h b/include/asm-i386/mach-numaq/mach_apic.h index 98b4e5921aa8..814ee9aa2521 100644 --- a/include/asm-i386/mach-numaq/mach_apic.h +++ b/include/asm-i386/mach-numaq/mach_apic.h @@ -17,6 +17,8 @@ static inline cpumask_t target_cpus(void) #define NO_BALANCE_IRQ (1) #define esr_disable (1) +#define NO_IOAPIC_CHECK (0) + #define INT_DELIVERY_MODE dest_LowestPrio #define INT_DEST_MODE 0 /* physical delivery on LOCAL quad */ diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h index 73a4a1077e85..a10b4591737e 100644 --- a/include/asm-i386/mach-summit/mach_apic.h +++ b/include/asm-i386/mach-summit/mach_apic.h @@ -7,14 +7,13 @@ #define esr_disable (1) #define NO_BALANCE_IRQ (0) -#define XAPIC_DEST_CPUS_MASK 0x0Fu -#define XAPIC_DEST_CLUSTER_MASK 0xF0u +#define NO_IOAPIC_CHECK (1) /* Don't check I/O APIC ID for xAPIC */ -static inline unsigned long xapic_phys_to_log_apicid(int phys_apic) -{ - return ( (1ul << ((phys_apic) & 0x3)) | - ((phys_apic) & XAPIC_DEST_CLUSTER_MASK) ); -} +/* In clustered mode, the high nibble of APIC ID is a cluster number. + * The low nibble is a 4-bit bitmap. */ +#define XAPIC_DEST_CPUS_SHIFT 4 +#define XAPIC_DEST_CPUS_MASK ((1u << XAPIC_DEST_CPUS_SHIFT) - 1) +#define XAPIC_DEST_CLUSTER_MASK (XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT) #define APIC_DFR_VALUE (APIC_DFR_CLUSTER) @@ -40,15 +39,29 @@ static inline unsigned long check_apicid_present(int bit) return 1; } -#define apicid_cluster(apicid) (apicid & 0xF0) +#define apicid_cluster(apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK) extern u8 bios_cpu_apicid[]; +extern u8 cpu_2_logical_apicid[]; static inline void init_apic_ldr(void) { unsigned long val, id; - - id = xapic_phys_to_log_apicid(hard_smp_processor_id()); + int i, count; + u8 lid; + u8 my_id = (u8)hard_smp_processor_id(); + u8 my_cluster = (u8)apicid_cluster(my_id); + + /* Create logical APIC IDs by counting CPUs already in cluster. */ + for (count = 0, i = NR_CPUS; --i >= 0; ) { + lid = cpu_2_logical_apicid[i]; + if (lid != BAD_APICID && apicid_cluster(lid) == my_cluster) + ++count; + } + /* We only have a 4 wide bitmap in cluster mode. If a deranged + * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */ + BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT); + id = my_cluster | (1UL << count); apic_write_around(APIC_DFR, APIC_DFR_VALUE); val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; val |= SET_APIC_LOGICAL_ID(id); @@ -77,7 +90,6 @@ static inline int apicid_to_node(int logical_apicid) } /* Mapping from cpu number to logical apicid */ -extern u8 cpu_2_logical_apicid[]; static inline int cpu_to_logical_apicid(int cpu) { if (cpu >= NR_CPUS) diff --git a/include/asm-i386/mach-visws/mach_apic.h b/include/asm-i386/mach-visws/mach_apic.h index ab40e5c0f3e5..9a0208496458 100644 --- a/include/asm-i386/mach-visws/mach_apic.h +++ b/include/asm-i386/mach-visws/mach_apic.h @@ -8,6 +8,8 @@ #define no_balance_irq (0) #define esr_disable (0) +#define NO_IOAPIC_CHECK (0) + #define INT_DELIVERY_MODE dest_LowestPrio #define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h index cdae0e44df92..8587d7e3a2ae 100644 --- a/include/asm-i386/mmzone.h +++ b/include/asm-i386/mmzone.h @@ -122,11 +122,29 @@ static inline struct pglist_data *pfn_to_pgdat(unsigned long pfn) #elif CONFIG_ACPI_SRAT #include <asm/srat.h> #elif CONFIG_X86_PC -#define get_memcfg_numa get_memcfg_numa_flat #define get_zholes_size(n) (0) #else #define pfn_to_nid(pfn) (0) #endif /* CONFIG_X86_NUMAQ */ +extern int get_memcfg_numa_flat(void ); +/* + * This allows any one NUMA architecture to be compiled + * for, and still fall back to the flat function if it + * fails. + */ +static inline void get_memcfg_numa(void) +{ +#ifdef CONFIG_X86_NUMAQ + if (get_memcfg_numaq()) + return; +#elif CONFIG_ACPI_SRAT + if (get_memcfg_from_srat()) + return; +#endif + + get_memcfg_numa_flat(); +} + #endif /* CONFIG_DISCONTIGMEM */ #endif /* _ASM_MMZONE_H_ */ diff --git a/include/asm-i386/numaq.h b/include/asm-i386/numaq.h index de52624c6e0b..13eb04501378 100644 --- a/include/asm-i386/numaq.h +++ b/include/asm-i386/numaq.h @@ -29,8 +29,7 @@ #ifdef CONFIG_X86_NUMAQ #define MAX_NUMNODES 16 -extern void get_memcfg_numaq(void); -#define get_memcfg_numa() get_memcfg_numaq() +extern int get_memcfg_numaq(void); /* * SYS_CFG_DATA_PRIV_ADDR, struct eachquadmem, and struct sys_cfg_data are the diff --git a/include/asm-i386/signal.h b/include/asm-i386/signal.h index 80b7d5fdef9b..e3397cd6f77b 100644 --- a/include/asm-i386/signal.h +++ b/include/asm-i386/signal.h @@ -70,7 +70,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-i386/srat.h b/include/asm-i386/srat.h index b71cca0553c3..13563f45870e 100644 --- a/include/asm-i386/srat.h +++ b/include/asm-i386/srat.h @@ -32,8 +32,7 @@ #endif #define MAX_NUMNODES 8 -extern void get_memcfg_from_srat(void); +extern int get_memcfg_from_srat(void); extern unsigned long *get_zholes_size(int); -#define get_memcfg_numa() get_memcfg_from_srat() #endif /* _ASM_SRAT_H_ */ diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h index d3eabf5b95c7..8042de63aa55 100644 --- a/include/asm-i386/uaccess.h +++ b/include/asm-i386/uaccess.h @@ -80,7 +80,7 @@ extern struct movsl_mask { * checks that the pointer is in the user space range - after calling * this function, memory access functions may still return -EFAULT. */ -#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) +#define access_ok(type,addr,size) (likely(__range_ok(addr,size) == 0)) /** * verify_area: - Obsolete, use access_ok() diff --git a/include/asm-ia64/signal.h b/include/asm-ia64/signal.h index f98d3bb65a92..5744b56571ba 100644 --- a/include/asm-ia64/signal.h +++ b/include/asm-ia64/signal.h @@ -50,7 +50,7 @@ /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-m68k/signal.h b/include/asm-m68k/signal.h index dfb43563e1cc..8d9c02cafc01 100644 --- a/include/asm-m68k/signal.h +++ b/include/asm-m68k/signal.h @@ -68,7 +68,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-m68knommu/signal.h b/include/asm-m68knommu/signal.h index 4b4f4b4058f1..486cbb0dc088 100644 --- a/include/asm-m68knommu/signal.h +++ b/include/asm-m68knommu/signal.h @@ -68,7 +68,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-mips/signal.h b/include/asm-mips/signal.h index 40d73cc2a1e0..994987db61be 100644 --- a/include/asm-mips/signal.h +++ b/include/asm-mips/signal.h @@ -59,7 +59,7 @@ typedef unsigned long old_sigset_t; /* at least 32 bits */ /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-parisc/signal.h b/include/asm-parisc/signal.h index 5ab02aef6dea..cd4beefef333 100644 --- a/include/asm-parisc/signal.h +++ b/include/asm-parisc/signal.h @@ -42,7 +42,7 @@ /* These should not be considered constants from userland. */ #define SIGRTMIN 37 -#define SIGRTMAX (_NSIG-1) /* it's 44 under HP/UX */ +#define SIGRTMAX _NSIG /* it's 44 under HP/UX */ /* * SA_FLAGS values: diff --git a/include/asm-ppc/signal.h b/include/asm-ppc/signal.h index f692baff3a44..b0528fcbe985 100644 --- a/include/asm-ppc/signal.h +++ b/include/asm-ppc/signal.h @@ -61,7 +61,7 @@ typedef struct { /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-ppc/time.h b/include/asm-ppc/time.h index ff2939bcbcf9..67188ec06a7a 100644 --- a/include/asm-ppc/time.h +++ b/include/asm-ppc/time.h @@ -97,6 +97,13 @@ extern __inline__ unsigned long get_rtcl(void) { return rtcl; } +extern __inline__ unsigned long get_rtcu(void) +{ + unsigned long rtcu; + asm volatile("mfrtcu %0" : "=r" (rtcu)); + return rtcu; +} + extern __inline__ unsigned get_native_tbl(void) { if (__USE_RTC()) return get_rtcl(); @@ -140,6 +147,7 @@ extern __inline__ unsigned binary_tbl(void) { #endif /* Use mulhwu to scale processor timebase to timeval */ +/* Specifically, this computes (x * y) / 2^32. -- paulus */ #define mulhwu(x,y) \ ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;}) diff --git a/include/asm-ppc64/signal.h b/include/asm-ppc64/signal.h index 97ed18c9bb60..d0baf44cc89a 100644 --- a/include/asm-ppc64/signal.h +++ b/include/asm-ppc64/signal.h @@ -57,7 +57,7 @@ typedef struct { /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-s390/signal.h b/include/asm-s390/signal.h index fe2263b3ee0d..f273cdcd1cf6 100644 --- a/include/asm-s390/signal.h +++ b/include/asm-s390/signal.h @@ -78,7 +78,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-sh/signal.h b/include/asm-sh/signal.h index 2f8118eb0cb5..51a5f0691ee5 100644 --- a/include/asm-sh/signal.h +++ b/include/asm-sh/signal.h @@ -57,7 +57,7 @@ typedef struct { /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-sparc/signal.h b/include/asm-sparc/signal.h index 4e455b7add4a..6813baae27c6 100644 --- a/include/asm-sparc/signal.h +++ b/include/asm-sparc/signal.h @@ -89,7 +89,7 @@ #define _NSIG_WORDS (__NEW_NSIG / _NSIG_BPW) #define SIGRTMIN 32 -#define SIGRTMAX (__NEW_NSIG - 1) +#define SIGRTMAX __NEW_NSIG #if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__) #define _NSIG __NEW_NSIG diff --git a/include/asm-sparc64/signal.h b/include/asm-sparc64/signal.h index 63ac2e389367..f2101925bb74 100644 --- a/include/asm-sparc64/signal.h +++ b/include/asm-sparc64/signal.h @@ -89,7 +89,7 @@ #define _NSIG_WORDS (__NEW_NSIG / _NSIG_BPW) #define SIGRTMIN 32 -#define SIGRTMAX (__NEW_NSIG - 1) +#define SIGRTMAX __NEW_NSIG #if defined(__KERNEL__) || defined(__WANT_POSIX1B_SIGNALS__) #define _NSIG __NEW_NSIG diff --git a/include/asm-v850/signal.h b/include/asm-v850/signal.h index c33b1db71749..407db875899c 100644 --- a/include/asm-v850/signal.h +++ b/include/asm-v850/signal.h @@ -71,7 +71,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/asm-x86_64/signal.h b/include/asm-x86_64/signal.h index bd1f350f1ba6..21c4bf716666 100644 --- a/include/asm-x86_64/signal.h +++ b/include/asm-x86_64/signal.h @@ -77,7 +77,7 @@ typedef unsigned long sigset_t; /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) +#define SIGRTMAX _NSIG /* * SA_FLAGS values: diff --git a/include/linux/bio.h b/include/linux/bio.h index 6ad6d20d3778..0ac6a27ea0db 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -20,7 +20,6 @@ #ifndef __LINUX_BIO_H #define __LINUX_BIO_H -#include <linux/kdev_t.h> #include <linux/highmem.h> #include <linux/mempool.h> diff --git a/include/linux/compiler-gcc+.h b/include/linux/compiler-gcc+.h new file mode 100644 index 000000000000..f6ae9e76b825 --- /dev/null +++ b/include/linux/compiler-gcc+.h @@ -0,0 +1,14 @@ +/* Never include this file directly. Include <linux/compiler.h> instead. */ + +/* + * These definitions are for Ueber-GCC: always newer than the latest + * version and hence sporting everything plus a kitchen-sink. + */ +#include <linux/compiler-gcc.h> + +#define inline __inline__ __attribute__((always_inline)) +#define __inline__ __inline__ __attribute__((always_inline)) +#define __inline __inline__ __attribute__((always_inline)) +#define __deprecated __attribute__((deprecated)) +#define __attribute_used__ __attribute__((__used__)) +#define __attribute_pure__ __attribute__((pure)) diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h new file mode 100644 index 000000000000..152734055403 --- /dev/null +++ b/include/linux/compiler-gcc.h @@ -0,0 +1,17 @@ +/* Never include this file directly. Include <linux/compiler.h> instead. */ + +/* + * Common definitions for all gcc versions go here. + */ + + +/* Optimization barrier */ +/* The "volatile" is due to gcc bugs */ +#define barrier() __asm__ __volatile__("": : :"memory") + +/* This macro obfuscates arithmetic on a variable address so that gcc + shouldn't recognize the original var, and make assumptions about it */ +#define RELOC_HIDE(ptr, off) \ + ({ unsigned long __ptr; \ + __asm__ ("" : "=g"(__ptr) : "0"(ptr)); \ + (typeof(ptr)) (__ptr + (off)); }) diff --git a/include/linux/compiler-gcc2.h b/include/linux/compiler-gcc2.h new file mode 100644 index 000000000000..6f4f9d526abe --- /dev/null +++ b/include/linux/compiler-gcc2.h @@ -0,0 +1,23 @@ +/* Never include this file directly. Include <linux/compiler.h> instead. */ + +/* These definitions are for GCC v2.x. */ + +/* Somewhere in the middle of the GCC 2.96 development cycle, we implemented + a mechanism by which the user can annotate likely branch directions and + expect the blocks to be reordered appropriately. Define __builtin_expect + to nothing for earlier compilers. */ +#include <linux/compiler-gcc.h> + +#if __GNUC_MINOR__ < 96 +# define __builtin_expect(x, expected_value) (x) +#endif + +#define __attribute_used__ __attribute__((__unused__)) + +/* + * The attribute `pure' is not implemented in GCC versions earlier + * than 2.96. + */ +#if __GNUC_MINOR__ >= 96 +# define __attribute_pure__ __attribute__((pure)) +#endif diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h new file mode 100644 index 000000000000..4eac3db89fda --- /dev/null +++ b/include/linux/compiler-gcc3.h @@ -0,0 +1,22 @@ +/* Never include this file directly. Include <linux/compiler.h> instead. */ + +/* These definitions are for GCC v3.x. */ +#include <linux/compiler-gcc.h> + +#if __GNUC_MINOR__ >= 1 +# define inline __inline__ __attribute__((always_inline)) +# define __inline__ __inline__ __attribute__((always_inline)) +# define __inline __inline__ __attribute__((always_inline)) +#endif + +#if __GNUC_MINOR__ > 0 +# define __deprecated __attribute__((deprecated)) +#endif + +#if __GNUC_MINOR__ >= 3 +# define __attribute_used__ __attribute__((__used__)) +#else +# define __attribute_used__ __attribute__((__unused__)) +#endif + +#define __attribute_pure__ __attribute__((pure)) diff --git a/include/linux/compiler-intel.h b/include/linux/compiler-intel.h new file mode 100644 index 000000000000..1d1c3ceaff4e --- /dev/null +++ b/include/linux/compiler-intel.h @@ -0,0 +1,24 @@ +/* Never include this file directly. Include <linux/compiler.h> instead. */ + +#ifdef __ECC + +/* Some compiler specific definitions are overwritten here + * for Intel ECC compiler + */ + +#include <asm/intrinsics.h> + +/* Intel ECC compiler doesn't support gcc specific asm stmts. + * It uses intrinsics to do the equivalent things. + */ +#undef barrier +#undef RELOC_HIDE + +#define barrier() __memory_barrier() + +#define RELOC_HIDE(ptr, off) \ + ({ unsigned long __ptr; \ + __ptr = (unsigned long) (ptr); \ + (typeof(ptr)) (__ptr + (off)); }) + +#endif diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 356428f649fc..528641f69043 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -2,28 +2,36 @@ #define __LINUX_COMPILER_H #ifdef __CHECKER__ - #define __user __attribute__((noderef, address_space(1))) - #define __kernel /* default address space */ +# define __user __attribute__((noderef, address_space(1))) +# define __kernel /* default address space */ #else - #define __user - #define __kernel +# define __user +# define __kernel #endif -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) -#define inline __inline__ __attribute__((always_inline)) -#define __inline__ __inline__ __attribute__((always_inline)) -#define __inline __inline__ __attribute__((always_inline)) +#if __GNUC__ > 3 +# include <linux/compiler-gcc+.h> /* catch-all for GCC 4, 5, etc. */ +#elif __GNUC__ == 3 +# include <linux/compiler-gcc3.h> +#elif __GNUC__ == 2 +# include <linux/compiler-gcc2.h> +#else +# error Sorry, your compiler is too old/not recognized. #endif -/* Somewhere in the middle of the GCC 2.96 development cycle, we implemented - a mechanism by which the user can annotate likely branch directions and - expect the blocks to be reordered appropriately. Define __builtin_expect - to nothing for earlier compilers. */ - -#if __GNUC__ == 2 && __GNUC_MINOR__ < 96 -#define __builtin_expect(x, expected_value) (x) +/* Intel compiler defines __GNUC__. So we will overwrite implementations + * coming from above header files here + */ +#ifdef __INTEL_COMPILER +# include <linux/compiler-intel.h> #endif +/* + * Generic compiler-dependent macros required for kernel + * build go below this comment. Actual compiler/compiler version + * specific implementations come from the above header files + */ + #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) @@ -33,10 +41,8 @@ * Usage is: * int __deprecated foo(void) */ -#if ( __GNUC__ == 3 && __GNUC_MINOR__ > 0 ) || __GNUC__ > 3 -#define __deprecated __attribute__((deprecated)) -#else -#define __deprecated +#ifndef __deprecated +# define __deprecated /* unimplemented */ #endif /* @@ -50,10 +56,8 @@ * In prior versions of gcc, such functions and data would be emitted, but * would be warned about except with attribute((unused)). */ -#if __GNUC__ == 3 && __GNUC_MINOR__ >= 3 || __GNUC__ > 3 -#define __attribute_used__ __attribute__((__used__)) -#else -#define __attribute_used__ __attribute__((__unused__)) +#ifndef __attribute_used__ +# define __attribute_used__ /* unimplemented */ #endif /* @@ -65,19 +69,21 @@ * elimination and loop optimization just as an arithmetic operator * would be. * [...] - * The attribute `pure' is not implemented in GCC versions earlier - * than 2.96. */ -#if (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || __GNUC__ > 2 -#define __attribute_pure__ __attribute__((pure)) -#else -#define __attribute_pure__ /* unimplemented */ +#ifndef __attribute_pure__ +# define __attribute_pure__ /* unimplemented */ +#endif + +/* Optimization barrier */ +#ifndef barrier +# define barrier() __memory_barrier() #endif -/* This macro obfuscates arithmetic on a variable address so that gcc - shouldn't recognize the original var, and make assumptions about it */ -#define RELOC_HIDE(ptr, off) \ +#ifndef RELOC_HIDE +# define RELOC_HIDE(ptr, off) \ ({ unsigned long __ptr; \ - __asm__ ("" : "=g"(__ptr) : "0"(ptr)); \ + __ptr = (unsigned long) (ptr); \ (typeof(ptr)) (__ptr + (off)); }) +#endif + #endif /* __LINUX_COMPILER_H */ diff --git a/include/linux/console.h b/include/linux/console.h index 414ebe159d67..cdff9de7ee71 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -15,7 +15,6 @@ #define _LINUX_CONSOLE_H_ 1 #include <linux/types.h> -#include <linux/kdev_t.h> #include <linux/spinlock.h> struct vc_data; diff --git a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h index f12addd1daeb..16c78f54f427 100644 --- a/include/linux/devfs_fs_kernel.h +++ b/include/linux/devfs_fs_kernel.h @@ -4,7 +4,6 @@ #include <linux/fs.h> #include <linux/config.h> #include <linux/spinlock.h> -#include <linux/kdev_t.h> #include <linux/types.h> #include <asm/semaphore.h> diff --git a/include/linux/elevator.h b/include/linux/elevator.h index e43d670c1371..cbd038b665e8 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -15,7 +15,6 @@ typedef int (elevator_queue_empty_fn) (request_queue_t *); typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *); typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *); typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *); -typedef struct list_head *(elevator_get_sort_head_fn) (request_queue_t *, struct request *); typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *); typedef int (elevator_may_queue_fn) (request_queue_t *, int); diff --git a/include/linux/ftape.h b/include/linux/ftape.h index 99b3535a4e20..e21d4b442843 100644 --- a/include/linux/ftape.h +++ b/include/linux/ftape.h @@ -199,8 +199,6 @@ typedef union { #define ABS(a) ((a) < 0 ? -(a) : (a)) #define NR_ITEMS(x) (int)(sizeof(x)/ sizeof(*x)) -extern int ftape_init(void); - #endif /* __KERNEL__ */ #endif diff --git a/include/linux/kernel.h b/include/linux/kernel.h index b2d17ea0dac0..6403c9ef2210 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -15,10 +15,6 @@ #include <asm/byteorder.h> #include <asm/bug.h> -/* Optimization barrier */ -/* The "volatile" is due to gcc bugs */ -#define barrier() __asm__ __volatile__("": : :"memory") - #define INT_MAX ((int)(~0U>>1)) #define INT_MIN (-INT_MAX - 1) #define UINT_MAX (~0U) diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index d3af91351521..6b7f9c1fa5cd 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -36,8 +36,6 @@ #define TUN_MINOR 200 -extern int misc_init(void); - struct miscdevice { int minor; diff --git a/include/linux/nls.h b/include/linux/nls.h index 2ab6466f8043..1c657d4f0cf3 100644 --- a/include/linux/nls.h +++ b/include/linux/nls.h @@ -8,6 +8,7 @@ typedef __u16 wchar_t; struct nls_table { char *charset; + char *alias; int (*uni2char) (wchar_t uni, unsigned char *out, int boundlen); int (*char2uni) (const unsigned char *rawstring, int boundlen, wchar_t *uni); @@ -32,5 +33,7 @@ extern int utf8_mbstowcs(wchar_t *, const __u8 *, int); extern int utf8_wctomb(__u8 *, wchar_t, int); extern int utf8_wcstombs(__u8 *, const wchar_t *, int); +#define MODULE_ALIAS_NLS(name) MODULE_ALIAS("nls_" __stringify(name)) + #endif /* _LINUX_NLS_H */ diff --git a/include/linux/random.h b/include/linux/random.h index ca0e460941a5..9ccb52fa0a01 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -42,7 +42,6 @@ struct rand_pool_info { #ifdef __KERNEL__ -extern void rand_initialize(void); extern void rand_initialize_irq(int irq); extern void batch_entropy_store(u32 a, u32 b, int num); diff --git a/include/linux/sched.h b/include/linux/sched.h index 3c6e3129144d..1618ae7f42d4 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -281,7 +281,9 @@ struct signal_struct { #define MAX_RT_PRIO MAX_USER_RT_PRIO #define MAX_PRIO (MAX_RT_PRIO + 40) - + +#define rt_task(p) ((p)->prio < MAX_RT_PRIO) + /* * Some day this will be a full-fledged user tracking system.. */ @@ -340,7 +342,9 @@ struct task_struct { prio_array_t *array; unsigned long sleep_avg; - unsigned long last_run; + long interactive_credit; + unsigned long long timestamp; + int activated; unsigned long policy; cpumask_t cpus_allowed; @@ -360,7 +364,7 @@ struct task_struct { unsigned long personality; int did_exec:1; pid_t pid; - pid_t pgrp; + pid_t __pgrp; /* Accessed via process_group() */ pid_t tty_old_pgrp; pid_t session; pid_t tgid; @@ -375,7 +379,7 @@ struct task_struct { struct task_struct *parent; /* parent process */ struct list_head children; /* list of my children */ struct list_head sibling; /* linkage in my parent's children list */ - struct task_struct *group_leader; + struct task_struct *group_leader; /* threadgroup leader */ /* PID/PID hash table linkage. */ struct pid_link pids[PIDTYPE_MAX]; @@ -461,6 +465,11 @@ struct task_struct { siginfo_t *last_siginfo; /* For ptrace use. */ }; +static inline pid_t process_group(struct task_struct *tsk) +{ + return tsk->group_leader->__pgrp; +} + extern void __put_task_struct(struct task_struct *tsk); #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0) #define put_task_struct(tsk) \ @@ -499,6 +508,8 @@ static inline int set_cpus_allowed(task_t *p, cpumask_t new_mask) } #endif +extern unsigned long long sched_clock(void); + #ifdef CONFIG_NUMA extern void sched_balance_exec(void); extern void node_nr_running_init(void); diff --git a/include/linux/swap.h b/include/linux/swap.h index 147e5bf40cbf..1f3517e965f3 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -3,7 +3,6 @@ #include <linux/config.h> #include <linux/spinlock.h> -#include <linux/kdev_t.h> #include <linux/linkage.h> #include <linux/mmzone.h> #include <linux/list.h> diff --git a/include/linux/tty.h b/include/linux/tty.h index 205e27af55a2..c575197f00b3 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -351,7 +351,6 @@ extern void console_init(void); extern int lp_init(void); extern int pty_init(void); -extern void tty_init(void); extern int mxser_init(void); extern int moxa_init(void); extern int ip2_init(void); diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 373e58fee2d4..1424811e1eab 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -84,7 +84,6 @@ int dirty_writeback_centisecs_handler(struct ctl_table *, int, struct file *, void __user *, size_t *); void page_writeback_init(void); -void balance_dirty_pages(struct address_space *mapping); void balance_dirty_pages_ratelimited(struct address_space *mapping); int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0); int do_writepages(struct address_space *mapping, struct writeback_control *wbc); diff --git a/init/main.c b/init/main.c index d857325e3dc8..13eff1cdd527 100644 --- a/init/main.c +++ b/init/main.c @@ -542,12 +542,16 @@ static void do_pre_smp_initcalls(void) spawn_ksoftirqd(); } +static void run_init_process(char *init_filename) +{ + argv_init[0] = init_filename; + execve(init_filename, argv_init, envp_init); +} + extern void prepare_namespace(void); static int init(void * unused) { - static char * argv_sh[] = { "sh", NULL, }; - lock_kernel(); /* * Tell the world that we're going to be the grim @@ -592,10 +596,12 @@ static int init(void * unused) */ if (execute_command) - execve(execute_command,argv_init,envp_init); - execve("/sbin/init",argv_init,envp_init); - execve("/etc/init",argv_init,envp_init); - execve("/bin/init",argv_init,envp_init); - execve("/bin/sh",argv_sh,envp_init); + run_init_process(execute_command); + + run_init_process("/sbin/init"); + run_init_process("/etc/init"); + run_init_process("/bin/init"); + run_init_process("/bin/sh"); + panic("No init found. Try passing init= option to kernel."); } diff --git a/ipc/sem.c b/ipc/sem.c index 81aa6977c993..828962a4ade6 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1038,8 +1038,10 @@ retry_undos: * allocated an undo structure, it was invalidated by an RMID * and now a new array with received the same id. Check and retry. */ - if (un && un->semid == -1) + if (un && un->semid == -1) { + sem_unlock(sma); goto retry_undos; + } error = -EFBIG; if (max >= sma->sem_nsems) goto out_unlock_free; diff --git a/kernel/configs.c b/kernel/configs.c index 6a5c0c9d9176..57f54451edbe 100644 --- a/kernel/configs.c +++ b/kernel/configs.c @@ -47,7 +47,7 @@ /**************************************************/ /* globals and useful constants */ -static const char IKCONFIG_VERSION[] = "0.6"; +static const char IKCONFIG_VERSION[] __initdata = "0.7"; static ssize_t ikconfig_read_current(struct file *file, char __user *buf, @@ -72,32 +72,6 @@ static struct file_operations ikconfig_file_ops = { .read = ikconfig_read_current, }; - -/***************************************************/ -/* build_info_show: let people read the info */ -/* we have on the tools used to build this kernel */ - -static int build_info_show(struct seq_file *seq, void *v) -{ - seq_printf(seq, - "Kernel: %s\nCompiler: %s\nVersion_in_Makefile: %s\n", - ikconfig_build_info, LINUX_COMPILER, UTS_RELEASE); - return 0; -} - -static int build_info_open(struct inode *inode, struct file *file) -{ - return single_open(file, build_info_show, PDE(inode)->data); -} - -static struct file_operations build_info_file_ops = { - .owner = THIS_MODULE, - .open = build_info_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - /***************************************************/ /* ikconfig_init: start up everything we need to */ @@ -112,26 +86,12 @@ static int __init ikconfig_init(void) entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO, &proc_root); if (!entry) - goto leave; + return -ENOMEM; entry->proc_fops = &ikconfig_file_ops; entry->size = kernel_config_data_size; - /* create the "build_info" file */ - entry = create_proc_entry("config_build_info", - S_IFREG | S_IRUGO, &proc_root); - if (!entry) - goto leave_gz; - entry->proc_fops = &build_info_file_ops; - return 0; - -leave_gz: - /* remove the file from proc */ - remove_proc_entry("config.gz", &proc_root); - -leave: - return -ENOMEM; } /***************************************************/ @@ -139,9 +99,7 @@ leave: static void __exit ikconfig_cleanup(void) { - /* remove the files */ remove_proc_entry("config.gz", &proc_root); - remove_proc_entry("config_build_info", &proc_root); } module_init(ikconfig_init); diff --git a/kernel/exit.c b/kernel/exit.c index b6174f82adf9..c565fd69d559 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -152,7 +152,7 @@ static int will_become_orphaned_pgrp(int pgrp, task_t *ignored_task) || p->state >= TASK_ZOMBIE || p->real_parent->pid == 1) continue; - if (p->real_parent->pgrp != pgrp + if (process_group(p->real_parent) != pgrp && p->real_parent->session == p->session) { ret = 0; break; @@ -247,9 +247,9 @@ void __set_special_pids(pid_t session, pid_t pgrp) curr->session = session; attach_pid(curr, PIDTYPE_SID, session); } - if (curr->pgrp != pgrp) { + if (process_group(curr) != pgrp) { detach_pid(curr, PIDTYPE_PGID); - curr->pgrp = pgrp; + curr->group_leader->__pgrp = pgrp; attach_pid(curr, PIDTYPE_PGID, pgrp); } } @@ -508,9 +508,9 @@ static inline void reparent_thread(task_t *p, task_t *father, int traced) * than we are, and it was the only connection * outside, so the child pgrp is now orphaned. */ - if ((p->pgrp != father->pgrp) && + if ((process_group(p) != process_group(father)) && (p->session == father->session)) { - int pgrp = p->pgrp; + int pgrp = process_group(p); if (will_become_orphaned_pgrp(pgrp, NULL) && has_stopped_jobs(pgrp)) { __kill_pg_info(SIGHUP, (void *)1, pgrp); @@ -618,12 +618,12 @@ static void exit_notify(struct task_struct *tsk) t = tsk->real_parent; - if ((t->pgrp != tsk->pgrp) && + if ((process_group(t) != process_group(tsk)) && (t->session == tsk->session) && - will_become_orphaned_pgrp(tsk->pgrp, tsk) && - has_stopped_jobs(tsk->pgrp)) { - __kill_pg_info(SIGHUP, (void *)1, tsk->pgrp); - __kill_pg_info(SIGCONT, (void *)1, tsk->pgrp); + will_become_orphaned_pgrp(process_group(tsk), tsk) && + has_stopped_jobs(process_group(tsk))) { + __kill_pg_info(SIGHUP, (void *)1, process_group(tsk)); + __kill_pg_info(SIGCONT, (void *)1, process_group(tsk)); } /* Let father know we died @@ -813,10 +813,10 @@ static int eligible_child(pid_t pid, int options, task_t *p) if (p->pid != pid) return 0; } else if (!pid) { - if (p->pgrp != current->pgrp) + if (process_group(p) != process_group(current)) return 0; } else if (pid != -1) { - if (p->pgrp != -pid) + if (process_group(p) != -pid) return 0; } diff --git a/kernel/fork.c b/kernel/fork.c index 37d79b4e16e6..f2d3115483da 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -305,7 +305,7 @@ out: return retval; fail_nomem: retval = -ENOMEM; - fail: +fail: vm_unacct_memory(charge); goto out; } @@ -499,7 +499,7 @@ static int copy_mm(unsigned long clone_flags, struct task_struct * tsk) goto fail_nomem; if (init_new_context(tsk,mm)) - goto free_pt; + goto fail_nocontext; retval = dup_mmap(mm, oldmm); if (retval) @@ -514,6 +514,15 @@ free_pt: mmput(mm); fail_nomem: return retval; + +fail_nocontext: + /* + * If init_new_context() failed, we cannot use mmput() to free the mm + * because it calls destroy_context() + */ + mm_free_pgd(mm); + free_mm(mm); + return retval; } static inline struct fs_struct *__copy_fs_struct(struct fs_struct *old) @@ -925,7 +934,7 @@ struct task_struct *copy_process(unsigned long clone_flags, */ p->first_time_slice = 1; current->time_slice >>= 1; - p->last_run = jiffies; + p->timestamp = sched_clock(); if (!current->time_slice) { /* * This case is rare, it happens when the parent has only @@ -1004,7 +1013,7 @@ struct task_struct *copy_process(unsigned long clone_flags, attach_pid(p, PIDTYPE_PID, p->pid); if (thread_group_leader(p)) { attach_pid(p, PIDTYPE_TGID, p->tgid); - attach_pid(p, PIDTYPE_PGID, p->pgrp); + attach_pid(p, PIDTYPE_PGID, process_group(p)); attach_pid(p, PIDTYPE_SID, p->session); if (p->pid) __get_cpu_var(process_counts)++; diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 9f61a0496c2a..9da2940ac0e6 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -348,8 +348,6 @@ EXPORT_SYMBOL(lock_page); EXPORT_SYMBOL(unlock_page); /* device registration */ -EXPORT_SYMBOL(register_chrdev); -EXPORT_SYMBOL(unregister_chrdev); EXPORT_SYMBOL(register_blkdev); EXPORT_SYMBOL(unregister_blkdev); EXPORT_SYMBOL(tty_register_driver); diff --git a/kernel/pid.c b/kernel/pid.c index 00413e3967b9..713f54eaeda9 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -250,13 +250,13 @@ void switch_exec_pids(task_t *leader, task_t *thread) attach_pid(thread, PIDTYPE_PID, thread->pid); attach_pid(thread, PIDTYPE_TGID, thread->tgid); - attach_pid(thread, PIDTYPE_PGID, thread->pgrp); + attach_pid(thread, PIDTYPE_PGID, leader->__pgrp); attach_pid(thread, PIDTYPE_SID, thread->session); list_add_tail(&thread->tasks, &init_task.tasks); attach_pid(leader, PIDTYPE_PID, leader->pid); attach_pid(leader, PIDTYPE_TGID, leader->tgid); - attach_pid(leader, PIDTYPE_PGID, leader->pgrp); + attach_pid(leader, PIDTYPE_PGID, leader->__pgrp); attach_pid(leader, PIDTYPE_SID, leader->session); } diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index d9be410a9e62..64940545cb84 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -344,6 +344,7 @@ static inline struct task_struct * good_sigevent(sigevent_t * event) return NULL; if ((event->sigev_notify & ~SIGEV_NONE & MIPS_SIGEV) && + event->sigev_signo && ((unsigned) (event->sigev_signo > SIGRTMAX))) return NULL; diff --git a/kernel/sched.c b/kernel/sched.c index 89f1bb28dacd..f4b866b8cb44 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -14,6 +14,7 @@ * an array-switch method of distributing timeslices * and per-CPU runqueues. Cleanups and useful suggestions * by Davide Libenzi, preemptible kernel bits by Robert Love. + * 2003-09-03 Interactivity tuning by Con Kolivas. */ #include <linux/mm.h> @@ -58,6 +59,14 @@ #define USER_PRIO(p) ((p)-MAX_RT_PRIO) #define TASK_USER_PRIO(p) USER_PRIO((p)->static_prio) #define MAX_USER_PRIO (USER_PRIO(MAX_PRIO)) +#define AVG_TIMESLICE (MIN_TIMESLICE + ((MAX_TIMESLICE - MIN_TIMESLICE) *\ + (MAX_PRIO-1-NICE_TO_PRIO(0))/(MAX_USER_PRIO - 1))) + +/* + * Some helpers for converting nanosecond timing to jiffy resolution + */ +#define NS_TO_JIFFIES(TIME) ((TIME) / (1000000000 / HZ)) +#define JIFFIES_TO_NS(TIME) ((TIME) * (1000000000 / HZ)) /* * These are the 'tuning knobs' of the scheduler: @@ -68,14 +77,18 @@ */ #define MIN_TIMESLICE ( 10 * HZ / 1000) #define MAX_TIMESLICE (200 * HZ / 1000) -#define CHILD_PENALTY 50 +#define ON_RUNQUEUE_WEIGHT 30 +#define CHILD_PENALTY 95 #define PARENT_PENALTY 100 #define EXIT_WEIGHT 3 #define PRIO_BONUS_RATIO 25 +#define MAX_BONUS (MAX_USER_PRIO * PRIO_BONUS_RATIO / 100) #define INTERACTIVE_DELTA 2 -#define MAX_SLEEP_AVG (10*HZ) -#define STARVATION_LIMIT (10*HZ) +#define MAX_SLEEP_AVG (AVG_TIMESLICE * MAX_BONUS) +#define STARVATION_LIMIT (MAX_SLEEP_AVG) +#define NS_MAX_SLEEP_AVG (JIFFIES_TO_NS(MAX_SLEEP_AVG)) #define NODE_THRESHOLD 125 +#define CREDIT_LIMIT 100 /* * If a task is 'interactive' then we reinsert it in the active @@ -105,6 +118,19 @@ * too hard. */ +#define CURRENT_BONUS(p) \ + (NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \ + MAX_SLEEP_AVG) + +#ifdef CONFIG_SMP +#define TIMESLICE_GRANULARITY(p) (MIN_TIMESLICE * \ + (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1)) * \ + num_online_cpus()) +#else +#define TIMESLICE_GRANULARITY(p) (MIN_TIMESLICE * \ + (1 << (((MAX_BONUS - CURRENT_BONUS(p)) ? : 1) - 1))) +#endif + #define SCALE(v1,v1_max,v2_max) \ (v1) * (v2_max) / (v1_max) @@ -115,6 +141,19 @@ #define TASK_INTERACTIVE(p) \ ((p)->prio <= (p)->static_prio - DELTA(p)) +#define JUST_INTERACTIVE_SLEEP(p) \ + (JIFFIES_TO_NS(MAX_SLEEP_AVG * \ + (MAX_BONUS / 2 + DELTA((p)) + 1) / MAX_BONUS - 1)) + +#define HIGH_CREDIT(p) \ + ((p)->interactive_credit > CREDIT_LIMIT) + +#define LOW_CREDIT(p) \ + ((p)->interactive_credit < -CREDIT_LIMIT) + +#define TASK_PREEMPTS_CURR(p, rq) \ + ((p)->prio < (rq)->curr->prio) + /* * BASE_TIMESLICE scales user-nice values [ -20 ... 19 ] * to time slice values. @@ -179,7 +218,6 @@ static DEFINE_PER_CPU(struct runqueue, runqueues); #define this_rq() (&__get_cpu_var(runqueues)) #define task_rq(p) cpu_rq(task_cpu(p)) #define cpu_curr(cpu) (cpu_rq(cpu)->curr) -#define rt_task(p) ((p)->prio < MAX_RT_PRIO) /* * Default context-switch locking: @@ -319,8 +357,7 @@ static int effective_prio(task_t *p) if (rt_task(p)) return p->prio; - bonus = MAX_USER_PRIO*PRIO_BONUS_RATIO*p->sleep_avg/MAX_SLEEP_AVG/100 - - MAX_USER_PRIO*PRIO_BONUS_RATIO/100/2; + bonus = CURRENT_BONUS(p) - MAX_BONUS / 2; prio = p->static_prio - bonus; if (prio < MAX_RT_PRIO) @@ -339,6 +376,82 @@ static inline void __activate_task(task_t *p, runqueue_t *rq) nr_running_inc(rq); } +static void recalc_task_prio(task_t *p, unsigned long long now) +{ + unsigned long long __sleep_time = now - p->timestamp; + unsigned long sleep_time; + + if (__sleep_time > NS_MAX_SLEEP_AVG) + sleep_time = NS_MAX_SLEEP_AVG; + else + sleep_time = (unsigned long)__sleep_time; + + if (likely(sleep_time > 0)) { + /* + * User tasks that sleep a long time are categorised as + * idle and will get just interactive status to stay active & + * prevent them suddenly becoming cpu hogs and starving + * other processes. + */ + if (p->mm && p->activated != -1 && + sleep_time > JUST_INTERACTIVE_SLEEP(p)){ + p->sleep_avg = JIFFIES_TO_NS(MAX_SLEEP_AVG - + AVG_TIMESLICE); + if (!HIGH_CREDIT(p)) + p->interactive_credit++; + } else { + /* + * The lower the sleep avg a task has the more + * rapidly it will rise with sleep time. + */ + sleep_time *= (MAX_BONUS - CURRENT_BONUS(p)) ? : 1; + + /* + * Tasks with low interactive_credit are limited to + * one timeslice worth of sleep avg bonus. + */ + if (LOW_CREDIT(p) && + sleep_time > JIFFIES_TO_NS(task_timeslice(p))) + sleep_time = + JIFFIES_TO_NS(task_timeslice(p)); + + /* + * Non high_credit tasks waking from uninterruptible + * sleep are limited in their sleep_avg rise as they + * are likely to be cpu hogs waiting on I/O + */ + if (p->activated == -1 && !HIGH_CREDIT(p) && p->mm){ + if (p->sleep_avg >= JUST_INTERACTIVE_SLEEP(p)) + sleep_time = 0; + else if (p->sleep_avg + sleep_time >= + JUST_INTERACTIVE_SLEEP(p)){ + p->sleep_avg = + JUST_INTERACTIVE_SLEEP(p); + sleep_time = 0; + } + } + + /* + * This code gives a bonus to interactive tasks. + * + * The boost works by updating the 'average sleep time' + * value here, based on ->timestamp. The more time a task + * spends sleeping, the higher the average gets - and the + * higher the priority boost gets as well. + */ + p->sleep_avg += sleep_time; + + if (p->sleep_avg > NS_MAX_SLEEP_AVG){ + p->sleep_avg = NS_MAX_SLEEP_AVG; + if (!HIGH_CREDIT(p)) + p->interactive_credit++; + } + } + } + + p->prio = effective_prio(p); +} + /* * activate_task - move a task to the runqueue and do priority recalculation * @@ -347,34 +460,33 @@ static inline void __activate_task(task_t *p, runqueue_t *rq) */ static inline void activate_task(task_t *p, runqueue_t *rq) { - long sleep_time = jiffies - p->last_run - 1; + unsigned long long now = sched_clock(); - if (sleep_time > 0) { - int sleep_avg; + recalc_task_prio(p, now); + /* + * This checks to make sure it's not an uninterruptible task + * that is now waking up. + */ + if (!p->activated){ /* - * This code gives a bonus to interactive tasks. - * - * The boost works by updating the 'average sleep time' - * value here, based on ->last_run. The more time a task - * spends sleeping, the higher the average gets - and the - * higher the priority boost gets as well. + * Tasks which were woken up by interrupts (ie. hw events) + * are most likely of interactive nature. So we give them + * the credit of extending their sleep time to the period + * of time they spend on the runqueue, waiting for execution + * on a CPU, first time around: */ - sleep_avg = p->sleep_avg + sleep_time; - + if (in_interrupt()) + p->activated = 2; + else /* - * 'Overflow' bonus ticks go to the waker as well, so the - * ticks are not lost. This has the effect of further - * boosting tasks that are related to maximum-interactive - * tasks. + * Normal first-time wakeups get a credit too for on-runqueue + * time, but it will be weighted down: */ - if (sleep_avg > MAX_SLEEP_AVG) - sleep_avg = MAX_SLEEP_AVG; - if (p->sleep_avg != sleep_avg) { - p->sleep_avg = sleep_avg; - p->prio = effective_prio(p); + p->activated = 1; } - } + p->timestamp = now; + __activate_task(p, rq); } @@ -495,13 +607,19 @@ repeat_lock_task: task_rq_unlock(rq, &flags); goto repeat_lock_task; } - if (old_state == TASK_UNINTERRUPTIBLE) + if (old_state == TASK_UNINTERRUPTIBLE){ rq->nr_uninterruptible--; + /* + * Tasks on involuntary sleep don't earn + * sleep_avg beyond just interactive state. + */ + p->activated = -1; + } if (sync) __activate_task(p, rq); else { activate_task(p, rq); - if (p->prio < rq->curr->prio) + if (TASK_PREEMPTS_CURR(p, rq)) resched_task(rq->curr); } success = 1; @@ -550,8 +668,14 @@ void wake_up_forked_process(task_t * p) * and children as well, to keep max-interactive tasks * from forking tasks that are max-interactive. */ - current->sleep_avg = current->sleep_avg * PARENT_PENALTY / 100; - p->sleep_avg = p->sleep_avg * CHILD_PENALTY / 100; + current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) * + PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); + + p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) * + CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); + + p->interactive_credit = 0; + p->prio = effective_prio(p); set_task_cpu(p, smp_processor_id()); @@ -592,8 +716,9 @@ void sched_exit(task_t * p) * the sleep_avg of the parent as well. */ if (p->sleep_avg < p->parent->sleep_avg) - p->parent->sleep_avg = (p->parent->sleep_avg * EXIT_WEIGHT + - p->sleep_avg) / (EXIT_WEIGHT + 1); + p->parent->sleep_avg = p->parent->sleep_avg / + (EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg / + (EXIT_WEIGHT + 1); } /** @@ -959,10 +1084,10 @@ static inline runqueue_t *find_busiest_queue(runqueue_t *this_rq, int this_cpu, if (likely(!busiest)) goto out; - *imbalance = (max_load - nr_running) / 2; + *imbalance = max_load - nr_running; /* It needs an at least ~25% imbalance to trigger balancing. */ - if (!idle && (*imbalance < (max_load + 3)/4)) { + if (!idle && ((*imbalance)*4 < max_load)) { busiest = NULL; goto out; } @@ -972,7 +1097,7 @@ static inline runqueue_t *find_busiest_queue(runqueue_t *this_rq, int this_cpu, * Make sure nothing changed since we checked the * runqueue length. */ - if (busiest->nr_running <= nr_running + 1) { + if (busiest->nr_running <= nr_running) { spin_unlock(&busiest->lock); busiest = NULL; } @@ -995,13 +1120,31 @@ static inline void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t * Note that idle threads have a prio of MAX_PRIO, for this test * to be always true for them. */ - if (p->prio < this_rq->curr->prio) + if (TASK_PREEMPTS_CURR(p, this_rq)) set_need_resched(); - else { - if (p->prio == this_rq->curr->prio && - p->time_slice > this_rq->curr->time_slice) - set_need_resched(); - } +} + +/* + * Previously: + * + * #define CAN_MIGRATE_TASK(p,rq,this_cpu) \ + * ((!idle || (NS_TO_JIFFIES(now - (p)->timestamp) > \ + * cache_decay_ticks)) && !task_running(rq, p) && \ + * cpu_isset(this_cpu, (p)->cpus_allowed)) + */ + +static inline int +can_migrate_task(task_t *tsk, runqueue_t *rq, int this_cpu, int idle) +{ + unsigned long delta = sched_clock() - tsk->timestamp; + + if (!idle && (delta <= JIFFIES_TO_NS(cache_decay_ticks))) + return 0; + if (task_running(rq, tsk)) + return 0; + if (!cpu_isset(this_cpu, tsk->cpus_allowed)) + return 0; + return 1; } /* @@ -1025,6 +1168,12 @@ static void load_balance(runqueue_t *this_rq, int idle, cpumask_t cpumask) goto out; /* + * We only want to steal a number of tasks equal to 1/2 the imbalance, + * otherwise we'll just shift the imbalance to the new queue: + */ + imbalance /= 2; + + /* * We first consider expired tasks. Those will likely not be * executed in the near future, and they are most likely to * be cache-cold, thus switching CPUs has the least effect @@ -1063,14 +1212,9 @@ skip_queue: * 3) are cache-hot on their current CPU. */ -#define CAN_MIGRATE_TASK(p,rq,this_cpu) \ - ((idle || (jiffies - (p)->last_run > cache_decay_ticks)) && \ - !task_running(rq, p) && \ - cpu_isset(this_cpu, (p)->cpus_allowed)) - curr = curr->prev; - if (!CAN_MIGRATE_TASK(tmp, busiest, this_cpu)) { + if (!can_migrate_task(tmp, busiest, this_cpu, idle)) { if (curr != head) goto skip_queue; idx++; @@ -1232,14 +1376,11 @@ void scheduler_tick(int user_ticks, int sys_ticks) spin_lock(&rq->lock); /* * The task was running during this tick - update the - * time slice counter and the sleep average. Note: we - * do not update a thread's priority until it either - * goes to sleep or uses up its timeslice. This makes - * it possible for interactive tasks to use up their - * timeslices at their highest priority levels. + * time slice counter. Note: we do not update a thread's + * priority until it either goes to sleep or uses up its + * timeslice. This makes it possible for interactive tasks + * to use up their timeslices at their highest priority levels. */ - if (p->sleep_avg) - p->sleep_avg--; if (unlikely(rt_task(p))) { /* * RR tasks need a special form of timeslice management. @@ -1263,12 +1404,39 @@ void scheduler_tick(int user_ticks, int sys_ticks) p->time_slice = task_timeslice(p); p->first_time_slice = 0; + if (!rq->expired_timestamp) + rq->expired_timestamp = jiffies; if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) { - if (!rq->expired_timestamp) - rq->expired_timestamp = jiffies; enqueue_task(p, rq->expired); } else enqueue_task(p, rq->active); + } else { + /* + * Prevent a too long timeslice allowing a task to monopolize + * the CPU. We do this by splitting up the timeslice into + * smaller pieces. + * + * Note: this does not mean the task's timeslices expire or + * get lost in any way, they just might be preempted by + * another task of equal priority. (one with higher + * priority would have preempted this task already.) We + * requeue this task to the end of the list on this priority + * level, which is in essence a round-robin of tasks with + * equal priority. + * + * This only applies to tasks in the interactive + * delta range with at least TIMESLICE_GRANULARITY to requeue. + */ + if (TASK_INTERACTIVE(p) && !((task_timeslice(p) - + p->time_slice) % TIMESLICE_GRANULARITY(p)) && + (p->time_slice >= TIMESLICE_GRANULARITY(p)) && + (p->array == rq->active)) { + + dequeue_task(p, rq->active); + set_tsk_need_resched(p); + p->prio = effective_prio(p); + enqueue_task(p, rq->active); + } } out_unlock: spin_unlock(&rq->lock); @@ -1287,6 +1455,8 @@ asmlinkage void schedule(void) runqueue_t *rq; prio_array_t *array; struct list_head *queue; + unsigned long long now; + unsigned long run_time; int idx; /* @@ -1307,7 +1477,20 @@ need_resched: rq = this_rq(); release_kernel_lock(prev); - prev->last_run = jiffies; + now = sched_clock(); + if (likely(now - prev->timestamp < NS_MAX_SLEEP_AVG)) + run_time = now - prev->timestamp; + else + run_time = NS_MAX_SLEEP_AVG; + + /* + * Tasks with interactive credits get charged less run_time + * at high sleep_avg to delay them losing their interactive + * status + */ + if (HIGH_CREDIT(prev)) + run_time /= (CURRENT_BONUS(prev) ? : 1); + spin_lock_irq(&rq->lock); /* @@ -1357,12 +1540,33 @@ pick_next_task: queue = array->queue + idx; next = list_entry(queue->next, task_t, run_list); + if (next->activated > 0) { + unsigned long long delta = now - next->timestamp; + + if (next->activated == 1) + delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128; + + array = next->array; + dequeue_task(next, array); + recalc_task_prio(next, next->timestamp + delta); + enqueue_task(next, array); + } + next->activated = 0; switch_tasks: prefetch(next); clear_tsk_need_resched(prev); RCU_qsctr(task_cpu(prev))++; + prev->sleep_avg -= run_time; + if ((long)prev->sleep_avg <= 0){ + prev->sleep_avg = 0; + if (!(HIGH_CREDIT(prev) || LOW_CREDIT(prev))) + prev->interactive_credit--; + } + prev->timestamp = now; + if (likely(prev != next)) { + next->timestamp = now; rq->nr_switches++; rq->curr = next; @@ -1602,6 +1806,7 @@ void set_user_nice(task_t *p, long nice) unsigned long flags; prio_array_t *array; runqueue_t *rq; + int old_prio, new_prio, delta; if (TASK_NICE(p) == nice || nice < -20 || nice > 19) return; @@ -1610,6 +1815,12 @@ void set_user_nice(task_t *p, long nice) * the task might be in the middle of scheduling on another CPU. */ rq = task_rq_lock(p, &flags); + /* + * The RT priorities are set via setscheduler(), but we still + * allow the 'normal' nice value to be set - but as expected + * it wont have any effect on scheduling until the task is + * not SCHED_NORMAL: + */ if (rt_task(p)) { p->static_prio = NICE_TO_PRIO(nice); goto out_unlock; @@ -1617,16 +1828,20 @@ void set_user_nice(task_t *p, long nice) array = p->array; if (array) dequeue_task(p, array); + + old_prio = p->prio; + new_prio = NICE_TO_PRIO(nice); + delta = new_prio - old_prio; p->static_prio = NICE_TO_PRIO(nice); - p->prio = NICE_TO_PRIO(nice); + p->prio += delta; + if (array) { enqueue_task(p, array); /* - * If the task is running and lowered its priority, - * or increased its priority then reschedule its CPU: + * If the task increased its priority or is running and + * lowered its priority, then reschedule its CPU: */ - if ((NICE_TO_PRIO(nice) < p->static_prio) || - task_running(rq, p)) + if (delta < 0 || (delta > 0 && task_running(rq, p))) resched_task(rq->curr); } out_unlock: @@ -2383,6 +2598,12 @@ static void move_task_away(struct task_struct *p, int dest_cpu) local_irq_restore(flags); } +typedef struct { + int cpu; + struct completion startup_done; + task_t *task; +} migration_startup_t; + /* * migration_thread - this is a highprio system thread that performs * thread migration by bumping thread off CPU then 'pushing' onto @@ -2392,20 +2613,21 @@ static int migration_thread(void * data) { /* Marking "param" __user is ok, since we do a set_fs(KERNEL_DS); */ struct sched_param __user param = { .sched_priority = MAX_RT_PRIO-1 }; - int cpu = (long) data; + migration_startup_t *startup = data; + int cpu = startup->cpu; runqueue_t *rq; int ret; + startup->task = current; + complete(&startup->startup_done); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + + BUG_ON(smp_processor_id() != cpu); + daemonize("migration/%d", cpu); set_fs(KERNEL_DS); - /* - * Either we are running on the right CPU, or there's a a - * migration thread on this CPU, guaranteed (we're started - * serially). - */ - set_cpus_allowed(current, cpumask_of_cpu(cpu)); - ret = setscheduler(0, SCHED_FIFO, ¶m); rq = this_rq(); @@ -2441,13 +2663,30 @@ static int migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) { + long cpu = (long) hcpu; + migration_startup_t startup; + switch (action) { case CPU_ONLINE: - printk("Starting migration thread for cpu %li\n", - (long)hcpu); - kernel_thread(migration_thread, hcpu, CLONE_KERNEL); - while (!cpu_rq((long)hcpu)->migration_thread) + + printk("Starting migration thread for cpu %li\n", cpu); + + startup.cpu = cpu; + startup.task = NULL; + init_completion(&startup.startup_done); + + kernel_thread(migration_thread, &startup, CLONE_KERNEL); + wait_for_completion(&startup.startup_done); + wait_task_inactive(startup.task); + + startup.task->thread_info->cpu = cpu; + startup.task->cpus_allowed = cpumask_of_cpu(cpu); + + wake_up_process(startup.task); + + while (!cpu_rq(cpu)->migration_thread) yield(); + break; } return NOTIFY_OK; @@ -2570,6 +2809,8 @@ void __might_sleep(char *file, int line) prev_jiffy = jiffies; printk(KERN_ERR "Debug: sleeping function called from invalid" " context at %s:%d\n", file, line); + printk("in_atomic():%d, irqs_disabled():%d\n", + in_atomic(), irqs_disabled()); dump_stack(); } #endif diff --git a/kernel/signal.c b/kernel/signal.c index 72333be1fd42..852da1a009da 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1139,7 +1139,7 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid) static int kill_something_info(int sig, struct siginfo *info, int pid) { if (!pid) { - return kill_pg_info(sig, info, current->pgrp); + return kill_pg_info(sig, info, process_group(current)); } else if (pid == -1) { int retval = 0, count = 0; struct task_struct * p; @@ -1798,7 +1798,7 @@ relock: /* signals can be posted during this window */ - if (is_orphaned_pgrp(current->pgrp)) + if (is_orphaned_pgrp(process_group(current))) goto relock; spin_lock_irq(¤t->sighand->siglock); diff --git a/kernel/sys.c b/kernel/sys.c index 02b5a12dfd59..9c6da1d16d9a 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -290,7 +290,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval) break; case PRIO_PGRP: if (!who) - who = current->pgrp; + who = process_group(current); for_each_task_pid(who, PIDTYPE_PGID, p, l, pid) error = set_one_prio(p, niceval, error); break; @@ -346,7 +346,7 @@ asmlinkage long sys_getpriority(int which, int who) break; case PRIO_PGRP: if (!who) - who = current->pgrp; + who = process_group(current); for_each_task_pid(who, PIDTYPE_PGID, p, l, pid) { niceval = 20 - task_nice(p); if (niceval > retval) @@ -979,11 +979,12 @@ ok_pgid: if (err) goto out; - if (p->pgrp != pgid) { + if (process_group(p) != pgid) { detach_pid(p, PIDTYPE_PGID); - p->pgrp = pgid; + p->group_leader->__pgrp = pgid; attach_pid(p, PIDTYPE_PGID, pgid); } + err = 0; out: /* All paths lead to here, thus we are safe. -DaveM */ @@ -994,7 +995,7 @@ out: asmlinkage long sys_getpgid(pid_t pid) { if (!pid) { - return current->pgrp; + return process_group(current); } else { int retval; struct task_struct *p; @@ -1006,7 +1007,7 @@ asmlinkage long sys_getpgid(pid_t pid) if (p) { retval = security_task_getpgid(p); if (!retval) - retval = p->pgrp; + retval = process_group(p); } read_unlock(&tasklist_lock); return retval; @@ -1016,7 +1017,7 @@ asmlinkage long sys_getpgid(pid_t pid) asmlinkage long sys_getpgrp(void) { /* SMP - assuming writes are word atomic this is fine */ - return current->pgrp; + return process_group(current); } asmlinkage long sys_getsid(pid_t pid) @@ -1059,7 +1060,7 @@ asmlinkage long sys_setsid(void) __set_special_pids(current->pid, current->pid); current->tty = NULL; current->tty_old_pgrp = 0; - err = current->pgrp; + err = process_group(current); out: write_unlock_irq(&tasklist_lock); return err; diff --git a/mm/memory.c b/mm/memory.c index 980953dbbfb4..be552e3cffbd 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1655,6 +1655,8 @@ int make_pages_present(unsigned long addr, unsigned long end) len = (end+PAGE_SIZE-1)/PAGE_SIZE-addr/PAGE_SIZE; ret = get_user_pages(current, current->mm, addr, len, write, 0, NULL, NULL); + if (ret < 0) + return ret; return ret == len ? 0 : -1; } diff --git a/mm/mlock.c b/mm/mlock.c index 21c8fbfa53a5..6f026bdd68e5 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -13,21 +13,24 @@ static int mlock_fixup(struct vm_area_struct * vma, unsigned long start, unsigned long end, unsigned int newflags) { struct mm_struct * mm = vma->vm_mm; - int pages, error; + int pages; + int ret = 0; if (newflags == vma->vm_flags) - return 0; + goto out; if (start != vma->vm_start) { - error = split_vma(mm, vma, start, 1); - if (error) - return -EAGAIN; + if (split_vma(mm, vma, start, 1)) { + ret = -EAGAIN; + goto out; + } } if (end != vma->vm_end) { - error = split_vma(mm, vma, end, 0); - if (error) - return -EAGAIN; + if (split_vma(mm, vma, end, 0)) { + ret = -EAGAIN; + goto out; + } } spin_lock(&mm->page_table_lock); @@ -40,11 +43,12 @@ static int mlock_fixup(struct vm_area_struct * vma, pages = (end - start) >> PAGE_SHIFT; if (newflags & VM_LOCKED) { pages = -pages; - make_pages_present(start, end); + ret = make_pages_present(start, end); } vma->vm_mm->locked_vm -= pages; - return 0; +out: + return ret; } static int do_mlock(unsigned long start, size_t len, int on) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 80047ad9a25e..327700df7e33 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -111,6 +111,7 @@ get_dirty_limits(struct page_state *ps, long *pbackground, long *pdirty) int unmapped_ratio; long background; long dirty; + struct task_struct *tsk; get_page_state(ps); @@ -129,7 +130,8 @@ get_dirty_limits(struct page_state *ps, long *pbackground, long *pdirty) background = (background_ratio * total_pages) / 100; dirty = (dirty_ratio * total_pages) / 100; - if (current->flags & PF_LESS_THROTTLE) { + tsk = current; + if (tsk->flags & PF_LESS_THROTTLE || rt_task(tsk)) { background += background / 4; dirty += dirty / 4; } @@ -144,7 +146,7 @@ get_dirty_limits(struct page_state *ps, long *pbackground, long *pdirty) * If we're over `background_thresh' then pdflush is woken to perform some * writeout. */ -void balance_dirty_pages(struct address_space *mapping) +static void balance_dirty_pages(struct address_space *mapping) { struct page_state ps; long nr_reclaimable; @@ -219,6 +221,10 @@ void balance_dirty_pages_ratelimited(struct address_space *mapping) if (dirty_exceeded) ratelimit = 8; + /* + * Check the rate limiting. Also, we do not want to throttle real-time + * tasks in balance_dirty_pages(). Period. + */ if (get_cpu_var(ratelimits)++ >= ratelimit) { __get_cpu_var(ratelimits) = 0; put_cpu_var(ratelimits); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 4051a19b0ab5..4ac2982747c9 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -520,7 +520,8 @@ static struct page *buffered_rmqueue(struct zone *zone, int order, int cold) * * Herein lies the mysterious "incremental min". That's the * - * min += z->pages_low; + * local_low = z->pages_low; + * min += local_low; * * thing. The intent here is to provide additional protection to low zones for * allocation requests which _could_ use higher zones. So a GFP_HIGHMEM @@ -538,10 +539,11 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, unsigned long min; struct zone **zones, *classzone; struct page *page; + struct reclaim_state reclaim_state; + struct task_struct *p = current; int i; int cold; int do_retry; - struct reclaim_state reclaim_state; might_sleep_if(wait); @@ -558,8 +560,17 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, min = 1UL << order; for (i = 0; zones[i] != NULL; i++) { struct zone *z = zones[i]; + unsigned long local_low; + + /* + * This is the fabled 'incremental min'. We let real-time tasks + * dip their real-time paws a little deeper into reserves. + */ + local_low = z->pages_low; + if (rt_task(p)) + local_low >>= 1; + min += local_low; - min += z->pages_low; if (z->free_pages >= min || (!wait && z->free_pages >= z->pages_high)) { page = buffered_rmqueue(z, order, cold); @@ -582,6 +593,8 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, local_min = z->pages_min; if (gfp_mask & __GFP_HIGH) local_min >>= 2; + if (rt_task(p)) + local_min >>= 1; min += local_min; if (z->free_pages >= min || (!wait && z->free_pages >= z->pages_high)) { @@ -595,7 +608,7 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order, /* here we're in the low on memory slow path */ rebalance: - if ((current->flags & (PF_MEMALLOC | PF_MEMDIE)) && !in_interrupt()) { + if ((p->flags & (PF_MEMALLOC | PF_MEMDIE)) && !in_interrupt()) { /* go through the zonelist yet again, ignoring mins */ for (i = 0; zones[i] != NULL; i++) { struct zone *z = zones[i]; @@ -611,14 +624,14 @@ rebalance: if (!wait) goto nopage; - current->flags |= PF_MEMALLOC; + p->flags |= PF_MEMALLOC; reclaim_state.reclaimed_slab = 0; - current->reclaim_state = &reclaim_state; + p->reclaim_state = &reclaim_state; try_to_free_pages(classzone, gfp_mask, order); - current->reclaim_state = NULL; - current->flags &= ~PF_MEMALLOC; + p->reclaim_state = NULL; + p->flags &= ~PF_MEMALLOC; /* go through the zonelist yet one more time */ min = 1UL << order; @@ -658,7 +671,7 @@ nopage: if (!(gfp_mask & __GFP_NOWARN)) { printk("%s: page allocation failure." " order:%d, mode:0x%x\n", - current->comm, order, gfp_mask); + p->comm, order, gfp_mask); } return NULL; got_pg: diff --git a/mm/slab.c b/mm/slab.c index 34b62ca48429..2f73bad2c440 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -293,6 +293,10 @@ struct kmem_cache_s { atomic_t freehit; atomic_t freemiss; #endif +#if DEBUG + int dbghead; + int reallen; +#endif }; #define CFLGS_OFF_SLAB (0x80000000UL) @@ -356,32 +360,68 @@ struct kmem_cache_s { #define POISON_AFTER 0x6b /* for use-after-free poisoning */ #define POISON_END 0xa5 /* end-byte of poisoning */ +/* memory layout of objects: + * 0 : objp + * 0 .. cachep->dbghead - BYTES_PER_WORD - 1: padding. This ensures that + * the end of an object is aligned with the end of the real + * allocation. Catches writes behind the end of the allocation. + * cachep->dbghead - BYTES_PER_WORD .. cachep->dbghead - 1: + * redzone word. + * cachep->dbghead: The real object. + * cachep->objsize - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long] + * cachep->objsize - 1* BYTES_PER_WORD: last caller address [BYTES_PER_WORD long] + */ static inline int obj_dbghead(kmem_cache_t *cachep) { - if (cachep->flags & SLAB_RED_ZONE) - return BYTES_PER_WORD; - return 0; + return cachep->dbghead; } -static inline int obj_dbglen(kmem_cache_t *cachep) +static inline int obj_reallen(kmem_cache_t *cachep) { - int len = 0; + return cachep->reallen; +} - if (cachep->flags & SLAB_RED_ZONE) { - len += 2*BYTES_PER_WORD; - } - if (cachep->flags & SLAB_STORE_USER) { - len += BYTES_PER_WORD; - } - return len; +static unsigned long *dbg_redzone1(kmem_cache_t *cachep, void *objp) +{ + BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); + return (unsigned long*) (objp+obj_dbghead(cachep)-BYTES_PER_WORD); +} + +static unsigned long *dbg_redzone2(kmem_cache_t *cachep, void *objp) +{ + BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); + if (cachep->flags & SLAB_STORE_USER) + return (unsigned long*) (objp+cachep->objsize-2*BYTES_PER_WORD); + return (unsigned long*) (objp+cachep->objsize-BYTES_PER_WORD); +} + +static void **dbg_userword(kmem_cache_t *cachep, void *objp) +{ + BUG_ON(!(cachep->flags & SLAB_STORE_USER)); + return (void**)(objp+cachep->objsize-BYTES_PER_WORD); } #else static inline int obj_dbghead(kmem_cache_t *cachep) { return 0; } -static inline int obj_dbglen(kmem_cache_t *cachep) +static inline int obj_reallen(kmem_cache_t *cachep) +{ + return cachep->objsize; +} +static inline unsigned long *dbg_redzone1(kmem_cache_t *cachep, void *objp) +{ + BUG(); + return 0; +} +static inline unsigned long *dbg_redzone2(kmem_cache_t *cachep, void *objp) +{ + BUG(); + return 0; +} +static inline void **dbg_userword(kmem_cache_t *cachep, void *objp) { + BUG(); return 0; } #endif @@ -804,7 +844,7 @@ static inline void kmem_freepages (kmem_cache_t *cachep, void *addr) #ifdef CONFIG_DEBUG_PAGEALLOC static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr, unsigned long caller) { - int size = cachep->objsize-obj_dbglen(cachep); + int size = obj_reallen(cachep); addr = (unsigned long *)&((char*)addr)[obj_dbghead(cachep)]; @@ -836,7 +876,7 @@ static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr, unsigned static void poison_obj(kmem_cache_t *cachep, void *addr, unsigned char val) { - int size = cachep->objsize-obj_dbglen(cachep); + int size = obj_reallen(cachep); addr = &((char*)addr)[obj_dbghead(cachep)]; memset(addr, val, size); @@ -858,47 +898,42 @@ static void *scan_poisoned_obj(unsigned char* addr, unsigned int size) return NULL; } -static void check_poison_obj(kmem_cache_t *cachep, void *addr) +static void check_poison_obj(kmem_cache_t *cachep, void *objp) { void *end; - int size = cachep->objsize-obj_dbglen(cachep); + void *realobj; + int size = obj_reallen(cachep); - addr = &((char*)addr)[obj_dbghead(cachep)]; + realobj = objp+obj_dbghead(cachep); - end = scan_poisoned_obj(addr, size); + end = scan_poisoned_obj(realobj, size); if (end) { int s; printk(KERN_ERR "Slab corruption: start=%p, expend=%p, " - "problemat=%p\n", addr, addr+size-1, end); + "problemat=%p\n", realobj, realobj+size-1, end); if (cachep->flags & SLAB_STORE_USER) { - void *pc; - - if (cachep->flags & SLAB_RED_ZONE) - pc = *(void**)(addr+size+BYTES_PER_WORD); - else - pc = *(void**)(addr+size); - printk(KERN_ERR "Last user: [<%p>]", pc); - print_symbol("(%s)", (unsigned long)pc); + printk(KERN_ERR "Last user: [<%p>]", *dbg_userword(cachep, objp)); + print_symbol("(%s)", (unsigned long)*dbg_userword(cachep, objp)); printk("\n"); } printk(KERN_ERR "Data: "); for (s = 0; s < size; s++) { - if (((char*)addr)[s] == POISON_BEFORE) + if (((char*)realobj)[s] == POISON_BEFORE) printk("."); - else if (((char*)addr)[s] == POISON_AFTER) + else if (((char*)realobj)[s] == POISON_AFTER) printk("*"); else - printk("%02X ", ((unsigned char*)addr)[s]); + printk("%02X ", ((unsigned char*)realobj)[s]); } printk("\n"); printk(KERN_ERR "Next: "); for (; s < size + 32; s++) { - if (((char*)addr)[s] == POISON_BEFORE) + if (((char*)realobj)[s] == POISON_BEFORE) printk("."); - else if (((char*)addr)[s] == POISON_AFTER) + else if (((char*)realobj)[s] == POISON_AFTER) printk("*"); else - printk("%02X ", ((unsigned char*)addr)[s]); + printk("%02X ", ((unsigned char*)realobj)[s]); } printk("\n"); slab_error(cachep, "object was modified after freeing"); @@ -916,7 +951,6 @@ static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp) int i; for (i = 0; i < cachep->num; i++) { void *objp = slabp->s_mem + cachep->objsize * i; - int objlen = cachep->objsize; if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC @@ -928,21 +962,16 @@ static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp) check_poison_obj(cachep, objp); #endif } - if (cachep->flags & SLAB_STORE_USER) - objlen -= BYTES_PER_WORD; - if (cachep->flags & SLAB_RED_ZONE) { - if (*((unsigned long*)(objp)) != RED_INACTIVE) + if (*dbg_redzone1(cachep, objp) != RED_INACTIVE) slab_error(cachep, "start of a freed object " "was overwritten"); - if (*((unsigned long*)(objp + objlen - BYTES_PER_WORD)) - != RED_INACTIVE) + if (*dbg_redzone2(cachep, objp) != RED_INACTIVE) slab_error(cachep, "end of a freed object " "was overwritten"); - objp += BYTES_PER_WORD; } if (cachep->dtor && !(cachep->flags & SLAB_POISON)) - (cachep->dtor)(objp, cachep, 0); + (cachep->dtor)(objp+obj_dbghead(cachep), cachep, 0); } #else if (cachep->dtor) { @@ -1020,10 +1049,6 @@ kmem_cache_create (const char *name, size_t size, size_t offset, } #if FORCED_DEBUG -#ifdef CONFIG_DEBUG_PAGEALLOC - if (size < PAGE_SIZE-3*BYTES_PER_WORD && size > 128) - size = PAGE_SIZE-3*BYTES_PER_WORD; -#endif /* * Enable redzoning and last user accounting, except * - for caches with forced alignment: redzoning would violate the @@ -1054,6 +1079,9 @@ kmem_cache_create (const char *name, size_t size, size_t offset, goto opps; memset(cachep, 0, sizeof(kmem_cache_t)); +#if DEBUG + cachep->reallen = size; +#endif /* Check that size is in terms of words. This is needed to avoid * unaligned accesses for some archs when redzoning is used, and makes * sure any on-slab bufctl's are also correctly aligned. @@ -1071,12 +1099,20 @@ kmem_cache_create (const char *name, size_t size, size_t offset, * when redzoning. */ flags &= ~SLAB_HWCACHE_ALIGN; - size += 2*BYTES_PER_WORD; /* words for redzone */ + /* add space for red zone words */ + cachep->dbghead += BYTES_PER_WORD; + size += 2*BYTES_PER_WORD; } if (flags & SLAB_STORE_USER) { flags &= ~SLAB_HWCACHE_ALIGN; - size += BYTES_PER_WORD; /* word for kfree caller address */ + size += BYTES_PER_WORD; /* add space */ } +#if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC) + if (size > 128 && cachep->reallen > L1_CACHE_BYTES && size < PAGE_SIZE) { + cachep->dbghead += PAGE_SIZE - size; + size = PAGE_SIZE; + } +#endif #endif align = BYTES_PER_WORD; if (flags & SLAB_HWCACHE_ALIGN) @@ -1444,20 +1480,15 @@ static void cache_init_objs (kmem_cache_t * cachep, for (i = 0; i < cachep->num; i++) { void* objp = slabp->s_mem+cachep->objsize*i; #if DEBUG - int objlen = cachep->objsize; /* need to poison the objs? */ if (cachep->flags & SLAB_POISON) poison_obj(cachep, objp, POISON_BEFORE); - if (cachep->flags & SLAB_STORE_USER) { - objlen -= BYTES_PER_WORD; - ((unsigned long*)(objp+objlen))[0] = 0; - } + if (cachep->flags & SLAB_STORE_USER) + *dbg_userword(cachep, objp) = NULL; if (cachep->flags & SLAB_RED_ZONE) { - *((unsigned long*)(objp)) = RED_INACTIVE; - objp += BYTES_PER_WORD; - objlen -= 2* BYTES_PER_WORD; - *((unsigned long*)(objp + objlen)) = RED_INACTIVE; + *dbg_redzone1(cachep, objp) = RED_INACTIVE; + *dbg_redzone2(cachep, objp) = RED_INACTIVE; } /* * Constructors are not allowed to allocate memory from @@ -1465,14 +1496,13 @@ static void cache_init_objs (kmem_cache_t * cachep, * Otherwise, deadlock. They must also be threaded. */ if (cachep->ctor && !(cachep->flags & SLAB_POISON)) - cachep->ctor(objp, cachep, ctor_flags); + cachep->ctor(objp+obj_dbghead(cachep), cachep, ctor_flags); if (cachep->flags & SLAB_RED_ZONE) { - if (*((unsigned long*)(objp + objlen)) != RED_INACTIVE) + if (*dbg_redzone2(cachep, objp) != RED_INACTIVE) slab_error(cachep, "constructor overwrote the" " end of an object"); - objp -= BYTES_PER_WORD; - if (*((unsigned long*)(objp)) != RED_INACTIVE) + if (*dbg_redzone1(cachep, objp) != RED_INACTIVE) slab_error(cachep, "constructor overwrote the" " start of an object"); } @@ -1623,9 +1653,9 @@ static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp, v #if DEBUG struct page *page; unsigned int objnr; - int objlen = cachep->objsize; struct slab *slabp; + objp -= obj_dbghead(cachep); kfree_debugcheck(objp); page = virt_to_page(objp); @@ -1638,21 +1668,18 @@ static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp, v } slabp = GET_PAGE_SLAB(page); - if (cachep->flags & SLAB_STORE_USER) { - objlen -= BYTES_PER_WORD; - } if (cachep->flags & SLAB_RED_ZONE) { - objp -= BYTES_PER_WORD; - if (xchg((unsigned long *)objp, RED_INACTIVE) != RED_ACTIVE) - slab_error(cachep, "double free, or memory before" - " object was overwritten"); - if (xchg((unsigned long *)(objp+objlen-BYTES_PER_WORD), RED_INACTIVE) != RED_ACTIVE) - slab_error(cachep, "double free, or memory after " + if (*dbg_redzone1(cachep, objp) != RED_ACTIVE || *dbg_redzone2(cachep, objp) != RED_ACTIVE) { + slab_error(cachep, "double free, or memory outside" " object was overwritten"); + printk(KERN_ERR "%p: redzone 1: 0x%lx, redzone 2: 0x%lx.\n", + objp, *dbg_redzone1(cachep, objp), *dbg_redzone2(cachep, objp)); + } + *dbg_redzone1(cachep, objp) = RED_INACTIVE; + *dbg_redzone2(cachep, objp) = RED_INACTIVE; } - if (cachep->flags & SLAB_STORE_USER) { - *((void**)(objp+objlen)) = caller; - } + if (cachep->flags & SLAB_STORE_USER) + *dbg_userword(cachep, objp) = caller; objnr = (objp-slabp->s_mem)/cachep->objsize; @@ -1825,8 +1852,6 @@ cache_alloc_debugcheck_after(kmem_cache_t *cachep, unsigned long flags, void *objp, void *caller) { #if DEBUG - int objlen = cachep->objsize; - if (!objp) return objp; if (cachep->flags & SLAB_POISON) { @@ -1840,24 +1865,20 @@ cache_alloc_debugcheck_after(kmem_cache_t *cachep, #endif poison_obj(cachep, objp, POISON_BEFORE); } - if (cachep->flags & SLAB_STORE_USER) { - objlen -= BYTES_PER_WORD; - *((void **)(objp+objlen)) = caller; - } + if (cachep->flags & SLAB_STORE_USER) + *dbg_userword(cachep, objp) = caller; if (cachep->flags & SLAB_RED_ZONE) { - /* Set alloc red-zone, and check old one. */ - if (xchg((unsigned long *)objp, RED_ACTIVE) != RED_INACTIVE) { - slab_error(cachep, "memory before object was " - "overwritten"); - } - if (xchg((unsigned long *)(objp+objlen - BYTES_PER_WORD), - RED_ACTIVE) != RED_INACTIVE) { - slab_error(cachep, "memory after object was " - "overwritten"); + if (*dbg_redzone1(cachep, objp) != RED_INACTIVE || *dbg_redzone2(cachep, objp) != RED_INACTIVE) { + slab_error(cachep, "double free, or memory outside" + " object was overwritten"); + printk(KERN_ERR "%p: redzone 1: 0x%lx, redzone 2: 0x%lx.\n", + objp, *dbg_redzone1(cachep, objp), *dbg_redzone2(cachep, objp)); } - objp += BYTES_PER_WORD; + *dbg_redzone1(cachep, objp) = RED_ACTIVE; + *dbg_redzone2(cachep, objp) = RED_ACTIVE; } + objp += obj_dbghead(cachep); if (cachep->ctor && cachep->flags & SLAB_POISON) { unsigned long ctor_flags = SLAB_CTOR_CONSTRUCTOR; @@ -2175,7 +2196,7 @@ free_percpu(const void *objp) unsigned int kmem_cache_size(kmem_cache_t *cachep) { - return cachep->objsize-obj_dbglen(cachep); + return obj_reallen(cachep); } kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags) @@ -2763,12 +2784,17 @@ void ptrinfo(unsigned long addr) if (objnr >= c->num) { printk("Bad obj number.\n"); } else { - kernel_map_pages(virt_to_page(objp), c->objsize/PAGE_SIZE, 1); + kernel_map_pages(virt_to_page(objp), + c->objsize/PAGE_SIZE, 1); + + if (c->flags & SLAB_RED_ZONE) + printk("redzone: 0x%lx/0x%lx.\n", + *dbg_redzone1(c, objp), + *dbg_redzone2(c, objp)); - printk("redzone: %lxh/%lxh/%lxh.\n", - ((unsigned long*)objp)[0], - ((unsigned long*)(objp+c->objsize))[-2], - ((unsigned long*)(objp+c->objsize))[-1]); + if (c->flags & SLAB_STORE_USER) + printk("Last user: %p.\n", + *dbg_userword(c, objp)); } spin_unlock_irqrestore(&c->spinlock, flags); diff --git a/scripts/mkconfigs b/scripts/mkconfigs index fc9c3dd978bc..a3166274ebc3 100755 --- a/scripts/mkconfigs +++ b/scripts/mkconfigs @@ -25,12 +25,6 @@ # - Retain lines that begin with "# CONFIG_" # - lines that use double-quotes must \\-escape-quote them - -kernel_version() -{ - KERNVER="`grep VERSION $1 | head -1 | cut -f3 -d' '`.`grep PATCHLEVEL $1 | head -1 | cut -f3 -d' '`.`grep SUBLEVEL $1 | head -1 | cut -f3 -d' '``grep EXTRAVERSION $1 | head -1 | cut -f3 -d' '`" -} - if [ $# -lt 2 ] then echo "Usage: `basename $0` <configuration_file> <Makefile>" @@ -66,12 +60,6 @@ echo \ * */" -echo "#ifdef CONFIG_IKCONFIG_PROC" -echo "static char const ikconfig_build_info[] =" -echo " \"`uname -s` `uname -r` `uname -v` `uname -m`\";" -echo "#endif" -echo -kernel_version $makefile echo "static char const ikconfig_config[] __attribute__((unused)) = " echo "\"CONFIG_BEGIN=n\\n\\" echo "`cat $config | sed 's/\"/\\\\\"/g' | grep "^#\? \?CONFIG_" | awk '{ print $0 "\\\\n\\\\" }' `" diff --git a/scripts/modpost.c b/scripts/modpost.c index 05369df84c02..5f8629d3425d 100644 --- a/scripts/modpost.c +++ b/scripts/modpost.c @@ -193,7 +193,7 @@ grab_file(const char *filename, unsigned long *size) *size = st.st_size; map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); - if (mmap == MAP_FAILED) { + if (map == MAP_FAILED) { perror(filename); abort(); } diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig index c051f9eece50..6f540f48c795 100644 --- a/sound/oss/Kconfig +++ b/sound/oss/Kconfig @@ -237,13 +237,6 @@ config SOUND_HARMONY tristate "PA Harmony audio driver" depends on GSC_LASI && SOUND -config SOUND_RME96XX - tristate "RME Hammerfall (RME96XX) support (EXPERIMENTAL)" - depends on SOUND_PRIME!=n && SOUND && PCI && EXPERIMENTAL - help - Say Y or M if you have a Hammerfall, Hammerfall light or Hammerfall - DSP card from RME. - config SOUND_SONICVIBES tristate "S3 SonicVibes" depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 2a779b11de52..1220a2d11d86 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c @@ -47,6 +47,13 @@ #define CHIP1370 #endif +#ifdef CHIP1370 +#define DRIVER_NAME "ENS1370" +#else +#define DRIVER_NAME "ENS1371" +#endif + + MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Thomas Sailer <sailer@ife.ee.ethz.ch>"); MODULE_LICENSE("GPL"); MODULE_CLASSES("{sound}"); @@ -2324,12 +2331,8 @@ static int __devinit snd_audiopci_probe(struct pci_dev *pci, snd_card_free(card); return err; } -#ifdef CHIP1370 - strcpy(card->driver, "ENS1370"); -#endif -#ifdef CHIP1371 - strcpy(card->driver, "ENS1371"); -#endif + strcpy(card->driver, DRIVER_NAME); + strcpy(card->shortname, "Ensoniq AudioPCI"); sprintf(card->longname, "%s %s at 0x%lx, irq %i", card->shortname, @@ -2354,7 +2357,7 @@ static void __devexit snd_audiopci_remove(struct pci_dev *pci) } static struct pci_driver driver = { - .name = "Ensoniq AudioPCI", + .name = DRIVER_NAME, .id_table = snd_audiopci_ids, .probe = snd_audiopci_probe, .remove = __devexit_p(snd_audiopci_remove), |
