diff --git a/[refs] b/[refs] index 7583748f5367..1af3aa578abc 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cbdb54d3ca986e30d0b8c1f755c3910b5573baae +refs/heads/master: 00280166993af8469dbfee24b779b61d3dd326c3 diff --git a/trunk/CREDITS b/trunk/CREDITS index 66b9e7a9abff..1d35f10ec3b2 100644 --- a/trunk/CREDITS +++ b/trunk/CREDITS @@ -24,11 +24,6 @@ S: C. Negri 6, bl. D3 S: Iasi 6600 S: Romania -N: Mark Adler -E: madler@alumni.caltech.edu -W: http://alumnus.caltech.edu/~madler/ -D: zlib decompression - N: Monalisa Agrawal E: magrawal@nortelnetworks.com D: Basic Interphase 5575 driver with UBR and ABR support. @@ -3401,10 +3396,10 @@ S: Czech Republic N: Thibaut Varene E: T-Bone@parisc-linux.org -W: http://www.parisc-linux.org/~varenet/ +W: http://www.parisc-linux.org/ P: 1024D/B7D2F063 E67C 0D43 A75E 12A5 BB1C FA2F 1E32 C3DA B7D2 F063 D: PA-RISC port minion, PDC and GSCPS2 drivers, debuglocks and other bits -D: Some ARM at91rm9200 bits, S1D13XXX FB driver, random patches here and there +D: Some bits in an ARM port, S1D13XXX FB driver, random patches here and there D: AD1889 sound driver S: Paris, France diff --git a/trunk/Documentation/Changes b/trunk/Documentation/Changes index 488272074c36..b02f476c2973 100644 --- a/trunk/Documentation/Changes +++ b/trunk/Documentation/Changes @@ -181,8 +181,8 @@ Intel IA32 microcode -------------------- A driver has been added to allow updating of Intel IA32 microcode, -accessible as a normal (misc) character device. If you are not using -udev you may need to: +accessible as both a devfs regular file and as a normal (misc) +character device. If you are not using devfs you may need to: mkdir /dev/cpu mknod /dev/cpu/microcode c 10 184 @@ -201,9 +201,7 @@ with programs using shared memory. udev ---- udev is a userspace application for populating /dev dynamically with -only entries for devices actually present. udev replaces the basic -functionality of devfs, while allowing persistant device naming for -devices. +only entries for devices actually present. udev replaces devfs. FUSE ---- @@ -233,13 +231,18 @@ The PPP driver has been restructured to support multilink and to enable it to operate over diverse media layers. If you use PPP, upgrade pppd to at least 2.4.0. -If you are not using udev, you must have the device file /dev/ppp +If you are not using devfs, you must have the device file /dev/ppp which can be made by: mknod /dev/ppp c 108 0 as root. +If you use devfsd and build ppp support as modules, you will need +the following in your /etc/devfsd.conf file: + +LOOKUP PPP MODLOAD + Isdn4k-utils ------------ diff --git a/trunk/Documentation/DocBook/Makefile b/trunk/Documentation/DocBook/Makefile index 66e1cf733571..5a2882d275ba 100644 --- a/trunk/Documentation/DocBook/Makefile +++ b/trunk/Documentation/DocBook/Makefile @@ -10,8 +10,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ procfs-guide.xml writing_usb_driver.xml \ kernel-api.xml journal-api.xml lsm.xml usb.xml \ - gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ - genericirq.xml + gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml ### # The build process is as follows (targets): diff --git a/trunk/Documentation/DocBook/genericirq.tmpl b/trunk/Documentation/DocBook/genericirq.tmpl deleted file mode 100644 index 0f4a4b6321e4..000000000000 --- a/trunk/Documentation/DocBook/genericirq.tmpl +++ /dev/null @@ -1,474 +0,0 @@ - - - - - - Linux generic IRQ handling - - - - Thomas - Gleixner - -
- tglx@linutronix.de -
-
-
- - Ingo - Molnar - -
- mingo@elte.hu -
-
-
-
- - - 2005-2006 - Thomas Gleixner - - - 2005-2006 - Ingo Molnar - - - - - This documentation is free software; you can redistribute - it and/or modify it under the terms of the GNU General Public - License version 2 as published by the Free Software Foundation. - - - - This program is distributed in the hope that it will be - useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, - MA 02111-1307 USA - - - - For more details see the file COPYING in the source - distribution of Linux. - - -
- - - - - Introduction - - The generic interrupt handling layer is designed to provide a - complete abstraction of interrupt handling for device drivers. - It is able to handle all the different types of interrupt controller - hardware. Device drivers use generic API functions to request, enable, - disable and free interrupts. The drivers do not have to know anything - about interrupt hardware details, so they can be used on different - platforms without code changes. - - - This documentation is provided to developers who want to implement - an interrupt subsystem based for their architecture, with the help - of the generic IRQ handling layer. - - - - - Rationale - - The original implementation of interrupt handling in Linux is using - the __do_IRQ() super-handler, which is able to deal with every - type of interrupt logic. - - - Originally, Russell King identified different types of handlers to - build a quite universal set for the ARM interrupt handler - implementation in Linux 2.5/2.6. He distinguished between: - - Level type - Edge type - Simple type - - In the SMP world of the __do_IRQ() super-handler another type - was identified: - - Per CPU type - - - - This split implementation of highlevel IRQ handlers allows us to - optimize the flow of the interrupt handling for each specific - interrupt type. This reduces complexity in that particular codepath - and allows the optimized handling of a given type. - - - The original general IRQ implementation used hw_interrupt_type - structures and their ->ack(), ->end() [etc.] callbacks to - differentiate the flow control in the super-handler. This leads to - a mix of flow logic and lowlevel hardware logic, and it also leads - to unnecessary code duplication: for example in i386, there is a - ioapic_level_irq and a ioapic_edge_irq irq-type which share many - of the lowlevel details but have different flow handling. - - - A more natural abstraction is the clean separation of the - 'irq flow' and the 'chip details'. - - - Analysing a couple of architecture's IRQ subsystem implementations - reveals that most of them can use a generic set of 'irq flow' - methods and only need to add the chip level specific code. - The separation is also valuable for (sub)architectures - which need specific quirks in the irq flow itself but not in the - chip-details - and thus provides a more transparent IRQ subsystem - design. - - - Each interrupt descriptor is assigned its own highlevel flow - handler, which is normally one of the generic - implementations. (This highlevel flow handler implementation also - makes it simple to provide demultiplexing handlers which can be - found in embedded platforms on various architectures.) - - - The separation makes the generic interrupt handling layer more - flexible and extensible. For example, an (sub)architecture can - use a generic irq-flow implementation for 'level type' interrupts - and add a (sub)architecture specific 'edge type' implementation. - - - To make the transition to the new model easier and prevent the - breakage of existing implementations, the __do_IRQ() super-handler - is still available. This leads to a kind of duality for the time - being. Over time the new model should be used in more and more - architectures, as it enables smaller and cleaner IRQ subsystems. - - - - Known Bugs And Assumptions - - None (knock on wood). - - - - - Abstraction layers - - There are three main levels of abstraction in the interrupt code: - - Highlevel driver API - Highlevel IRQ flow handlers - Chiplevel hardware encapsulation - - - - Interrupt control flow - - Each interrupt is described by an interrupt descriptor structure - irq_desc. The interrupt is referenced by an 'unsigned int' numeric - value which selects the corresponding interrupt decription structure - in the descriptor structures array. - The descriptor structure contains status information and pointers - to the interrupt flow method and the interrupt chip structure - which are assigned to this interrupt. - - - Whenever an interrupt triggers, the lowlevel arch code calls into - the generic interrupt code by calling desc->handle_irq(). - This highlevel IRQ handling function only uses desc->chip primitives - referenced by the assigned chip descriptor structure. - - - - Highlevel Driver API - - The highlevel Driver API consists of following functions: - - request_irq() - free_irq() - disable_irq() - enable_irq() - disable_irq_nosync() (SMP only) - synchronize_irq() (SMP only) - set_irq_type() - set_irq_wake() - set_irq_data() - set_irq_chip() - set_irq_chip_data() - - See the autogenerated function documentation for details. - - - - Highlevel IRQ flow handlers - - The generic layer provides a set of pre-defined irq-flow methods: - - handle_level_irq - handle_edge_irq - handle_simple_irq - handle_percpu_irq - - The interrupt flow handlers (either predefined or architecture - specific) are assigned to specific interrupts by the architecture - either during bootup or during device initialization. - - - Default flow implementations - - Helper functions - - The helper functions call the chip primitives and - are used by the default flow implementations. - The following helper functions are implemented (simplified excerpt): - -default_enable(irq) -{ - desc->chip->unmask(irq); -} - -default_disable(irq) -{ - if (!delay_disable(irq)) - desc->chip->mask(irq); -} - -default_ack(irq) -{ - chip->ack(irq); -} - -default_mask_ack(irq) -{ - if (chip->mask_ack) { - chip->mask_ack(irq); - } else { - chip->mask(irq); - chip->ack(irq); - } -} - -noop(irq) -{ -} - - - - - - - Default flow handler implementations - - Default Level IRQ flow handler - - handle_level_irq provides a generic implementation - for level-triggered interrupts. - - - The following control flow is implemented (simplified excerpt): - -desc->chip->start(); -handle_IRQ_event(desc->action); -desc->chip->end(); - - - - - Default Edge IRQ flow handler - - handle_edge_irq provides a generic implementation - for edge-triggered interrupts. - - - The following control flow is implemented (simplified excerpt): - -if (desc->status & running) { - desc->chip->hold(); - desc->status |= pending | masked; - return; -} -desc->chip->start(); -desc->status |= running; -do { - if (desc->status & masked) - desc->chip->enable(); - desc-status &= ~pending; - handle_IRQ_event(desc->action); -} while (status & pending); -desc-status &= ~running; -desc->chip->end(); - - - - - Default simple IRQ flow handler - - handle_simple_irq provides a generic implementation - for simple interrupts. - - - Note: The simple flow handler does not call any - handler/chip primitives. - - - The following control flow is implemented (simplified excerpt): - -handle_IRQ_event(desc->action); - - - - - Default per CPU flow handler - - handle_percpu_irq provides a generic implementation - for per CPU interrupts. - - - Per CPU interrupts are only available on SMP and - the handler provides a simplified version without - locking. - - - The following control flow is implemented (simplified excerpt): - -desc->chip->start(); -handle_IRQ_event(desc->action); -desc->chip->end(); - - - - - - Quirks and optimizations - - The generic functions are intended for 'clean' architectures and chips, - which have no platform-specific IRQ handling quirks. If an architecture - needs to implement quirks on the 'flow' level then it can do so by - overriding the highlevel irq-flow handler. - - - - Delayed interrupt disable - - This per interrupt selectable feature, which was introduced by Russell - King in the ARM interrupt implementation, does not mask an interrupt - at the hardware level when disable_irq() is called. The interrupt is - kept enabled and is masked in the flow handler when an interrupt event - happens. This prevents losing edge interrupts on hardware which does - not store an edge interrupt event while the interrupt is disabled at - the hardware level. When an interrupt arrives while the IRQ_DISABLED - flag is set, then the interrupt is masked at the hardware level and - the IRQ_PENDING bit is set. When the interrupt is re-enabled by - enable_irq() the pending bit is checked and if it is set, the - interrupt is resent either via hardware or by a software resend - mechanism. (It's necessary to enable CONFIG_HARDIRQS_SW_RESEND when - you want to use the delayed interrupt disable feature and your - hardware is not capable of retriggering an interrupt.) - The delayed interrupt disable can be runtime enabled, per interrupt, - by setting the IRQ_DELAYED_DISABLE flag in the irq_desc status field. - - - - - Chiplevel hardware encapsulation - - The chip level hardware descriptor structure irq_chip - contains all the direct chip relevant functions, which - can be utilized by the irq flow implementations. - - ack() - mask_ack() - Optional, recommended for performance - mask() - unmask() - retrigger() - Optional - set_type() - Optional - set_wake() - Optional - - These primitives are strictly intended to mean what they say: ack means - ACK, masking means masking of an IRQ line, etc. It is up to the flow - handler(s) to use these basic units of lowlevel functionality. - - - - - - __do_IRQ entry point - - The original implementation __do_IRQ() is an alternative entry - point for all types of interrupts. - - - This handler turned out to be not suitable for all - interrupt hardware and was therefore reimplemented with split - functionality for egde/level/simple/percpu interrupts. This is not - only a functional optimization. It also shortens code paths for - interrupts. - - - To make use of the split implementation, replace the call to - __do_IRQ by a call to desc->chip->handle_irq() and associate - the appropriate handler function to desc->chip->handle_irq(). - In most cases the generic handler implementations should - be sufficient. - - - - - Locking on SMP - - The locking of chip registers is up to the architecture that - defines the chip primitives. There is a chip->lock field that can be used - for serialization, but the generic layer does not touch it. The per-irq - structure is protected via desc->lock, by the generic layer. - - - - Structures - - This chapter contains the autogenerated documentation of the structures which are - used in the generic IRQ layer. - -!Iinclude/linux/irq.h - - - - Public Functions Provided - - This chapter contains the autogenerated documentation of the kernel API functions - which are exported. - -!Ekernel/irq/manage.c -!Ekernel/irq/chip.c - - - - Internal Functions Provided - - This chapter contains the autogenerated documentation of the internal functions. - -!Ikernel/irq/handle.c -!Ikernel/irq/chip.c - - - - Credits - - The following people have contributed to this document: - - Thomas Gleixnertglx@linutronix.de - Ingo Molnarmingo@elte.hu - - - -
diff --git a/trunk/Documentation/DocBook/kernel-api.tmpl b/trunk/Documentation/DocBook/kernel-api.tmpl index 1ae4dc0fd856..3630a0d7695f 100644 --- a/trunk/Documentation/DocBook/kernel-api.tmpl +++ b/trunk/Documentation/DocBook/kernel-api.tmpl @@ -348,6 +348,11 @@ X!Earch/i386/kernel/mca.c + + The Device File System +!Efs/devfs/base.c + + The Filesystem for Exporting Kernel Objects !Efs/sysfs/file.c diff --git a/trunk/Documentation/DocBook/kernel-locking.tmpl b/trunk/Documentation/DocBook/kernel-locking.tmpl index 644c3884fab9..158ffe9bfade 100644 --- a/trunk/Documentation/DocBook/kernel-locking.tmpl +++ b/trunk/Documentation/DocBook/kernel-locking.tmpl @@ -1590,7 +1590,7 @@ the amount of locking which needs to be done. Our final dilemma is this: when can we actually destroy the removed element? Remember, a reader might be stepping through - this element in the list right now: if we free this element and + this element in the list right now: it we free this element and the next pointer changes, the reader will jump off into garbage and crash. We need to wait until we know that all the readers who were traversing the list when we deleted the diff --git a/trunk/Documentation/DocBook/mtdnand.tmpl b/trunk/Documentation/DocBook/mtdnand.tmpl index 999afe1ca8cb..6e463d0db266 100644 --- a/trunk/Documentation/DocBook/mtdnand.tmpl +++ b/trunk/Documentation/DocBook/mtdnand.tmpl @@ -189,9 +189,9 @@ static unsigned long baseaddr; Partition defines - If you want to divide your device into partitions, then - enable the configuration switch CONFIG_MTD_PARTITIONS and define - a partitioning scheme suitable to your board. + If you want to divide your device into parititions, then + enable the configuration switch CONFIG_MTD_PARITIONS and define + a paritioning scheme suitable to your board. #define NUM_PARTITIONS 2 diff --git a/trunk/Documentation/DocBook/videobook.tmpl b/trunk/Documentation/DocBook/videobook.tmpl index b629da33951d..fdff984a5161 100644 --- a/trunk/Documentation/DocBook/videobook.tmpl +++ b/trunk/Documentation/DocBook/videobook.tmpl @@ -976,7 +976,7 @@ static int camera_close(struct video_device *dev) Interrupt Handling Our example handler is for an ISA bus device. If it was PCI you would be - able to share the interrupt and would have set IRQF_SHARED to indicate a + able to share the interrupt and would have set SA_SHIRQ to indicate a shared IRQ. We pass the device pointer as the interrupt routine argument. We don't need to since we only support one card but doing this will make it easier to upgrade the driver for multiple devices in the future. diff --git a/trunk/Documentation/IPMI.txt b/trunk/Documentation/IPMI.txt index 0256805b548f..bf1cf98d2a27 100644 --- a/trunk/Documentation/IPMI.txt +++ b/trunk/Documentation/IPMI.txt @@ -10,7 +10,7 @@ standard for controlling intelligent devices that monitor a system. It provides for dynamic discovery of sensors in the system and the ability to monitor the sensors and be informed when the sensor's values change or go outside certain boundaries. It also has a -standardized database for field-replaceable units (FRUs) and a watchdog +standardized database for field-replacable units (FRUs) and a watchdog timer. To use this, you need an interface to an IPMI controller in your @@ -64,7 +64,7 @@ situation, you need to read the section below named 'The SI Driver' or IPMI defines a standard watchdog timer. You can enable this with the 'IPMI Watchdog Timer' config option. If you compile the driver into the kernel, then via a kernel command-line option you can have the -watchdog timer start as soon as it initializes. It also have a lot +watchdog timer start as soon as it intitializes. It also have a lot of other options, see the 'Watchdog' section below for more details. Note that you can also have the watchdog continue to run if it is closed (by default it is disabled on close). Go into the 'Watchdog diff --git a/trunk/Documentation/IRQ.txt b/trunk/Documentation/IRQ.txt deleted file mode 100644 index 1011e7175021..000000000000 --- a/trunk/Documentation/IRQ.txt +++ /dev/null @@ -1,22 +0,0 @@ -What is an IRQ? - -An IRQ is an interrupt request from a device. -Currently they can come in over a pin, or over a packet. -Several devices may be connected to the same pin thus -sharing an IRQ. - -An IRQ number is a kernel identifier used to talk about a hardware -interrupt source. Typically this is an index into the global irq_desc -array, but except for what linux/interrupt.h implements the details -are architecture specific. - -An IRQ number is an enumeration of the possible interrupt sources on a -machine. Typically what is enumerated is the number of input pins on -all of the interrupt controller in the system. In the case of ISA -what is enumerated are the 16 input pins on the two i8259 interrupt -controllers. - -Architectures can assign additional meaning to the IRQ numbers, and -are encouraged to in the case where there is any manual configuration -of the hardware involved. The ISA IRQs are a classic example of -assigning this kind of additional meaning. diff --git a/trunk/Documentation/RCU/torture.txt b/trunk/Documentation/RCU/torture.txt index a4948591607d..e4c38152f7f7 100644 --- a/trunk/Documentation/RCU/torture.txt +++ b/trunk/Documentation/RCU/torture.txt @@ -7,7 +7,7 @@ The CONFIG_RCU_TORTURE_TEST config option is available for all RCU implementations. It creates an rcutorture kernel module that can be loaded to run a torture test. The test periodically outputs status messages via printk(), which can be examined via the dmesg -command (perhaps grepping for "torture"). The test is started +command (perhaps grepping for "rcutorture"). The test is started when the module is loaded, and stops when the module is unloaded. However, actually setting this config option to "y" results in the system @@ -35,19 +35,6 @@ stat_interval The number of seconds between output of torture be printed -only- when the module is unloaded, and this is the default. -shuffle_interval - The number of seconds to keep the test threads affinitied - to a particular subset of the CPUs. Used in conjunction - with test_no_idle_hz. - -test_no_idle_hz Whether or not to test the ability of RCU to operate in - a kernel that disables the scheduling-clock interrupt to - idle CPUs. Boolean parameter, "1" to test, "0" otherwise. - -torture_type The type of RCU to test: "rcu" for the rcu_read_lock() - API, "rcu_bh" for the rcu_read_lock_bh() API, and "srcu" - for the "srcu_read_lock()" API. - verbose Enable debug printk()s. Default is disabled. @@ -55,14 +42,14 @@ OUTPUT The statistics output is as follows: - rcu-torture: --- Start of test: nreaders=16 stat_interval=0 verbose=0 - rcu-torture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915 - rcu-torture: Reader Pipe: 1466408 9747 0 0 0 0 0 0 0 0 0 - rcu-torture: Reader Batch: 1464477 11678 0 0 0 0 0 0 0 0 - rcu-torture: Free-Block Circulation: 1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0 - rcu-torture: --- End of test + rcutorture: --- Start of test: nreaders=16 stat_interval=0 verbose=0 + rcutorture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915 + rcutorture: Reader Pipe: 1466408 9747 0 0 0 0 0 0 0 0 0 + rcutorture: Reader Batch: 1464477 11678 0 0 0 0 0 0 0 0 + rcutorture: Free-Block Circulation: 1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0 + rcutorture: --- End of test -The command "dmesg | grep torture:" will extract this information on +The command "dmesg | grep rcutorture:" will extract this information on most systems. On more esoteric configurations, it may be necessary to use other commands to access the output of the printk()s used by the RCU torture test. The printk()s use KERN_ALERT, so they should @@ -128,9 +115,8 @@ The following script may be used to torture RCU: modprobe rcutorture sleep 100 rmmod rcutorture - dmesg | grep torture: + dmesg | grep rcutorture: The output can be manually inspected for the error flag of "!!!". One could of course create a more elaborate script that automatically -checked for such errors. The "rmmod" command forces a "SUCCESS" or -"FAILURE" indication to be printk()ed. +checked for such errors. diff --git a/trunk/Documentation/README.DAC960 b/trunk/Documentation/README.DAC960 index 0e8f618ab534..98ea617a0dd6 100644 --- a/trunk/Documentation/README.DAC960 +++ b/trunk/Documentation/README.DAC960 @@ -78,9 +78,9 @@ also known as "System Drives", and Drive Groups are also called "Packs". Both terms are in use in the Mylex documentation; I have chosen to standardize on the more generic "Logical Drive" and "Drive Group". -DAC960 RAID disk devices are named in the style of the obsolete Device File -System (DEVFS). The device corresponding to Logical Drive D on Controller C -is referred to as /dev/rd/cCdD, and the partitions are called /dev/rd/cCdDp1 +DAC960 RAID disk devices are named in the style of the Device File System +(DEVFS). The device corresponding to Logical Drive D on Controller C is +referred to as /dev/rd/cCdD, and the partitions are called /dev/rd/cCdDp1 through /dev/rd/cCdDp7. For example, partition 3 of Logical Drive 5 on Controller 2 is referred to as /dev/rd/c2d5p3. Note that unlike with SCSI disks the device names will not change in the event of a disk drive failure. diff --git a/trunk/Documentation/arm/IXP4xx b/trunk/Documentation/arm/IXP4xx index 43edb4ecf27d..d4c6d3aa0c25 100644 --- a/trunk/Documentation/arm/IXP4xx +++ b/trunk/Documentation/arm/IXP4xx @@ -85,7 +85,7 @@ IXP4xx provides two methods of accessing PCI memory space: 2) If > 64MB of memory space is required, the IXP4xx can be configured to use indirect registers to access PCI This allows for up to 128MB (0x48000000 to 0x4fffffff) of memory on the bus. - The disadvantage of this is that every PCI access requires + The disadvantadge of this is that every PCI access requires three local register accesses plus a spinlock, but in some cases the performance hit is acceptable. In addition, you cannot mmap() PCI devices in this case due to the indirect nature diff --git a/trunk/Documentation/arm/Samsung-S3C24XX/Overview.txt b/trunk/Documentation/arm/Samsung-S3C24XX/Overview.txt index 3e46d2a31158..8c6ee684174c 100644 --- a/trunk/Documentation/arm/Samsung-S3C24XX/Overview.txt +++ b/trunk/Documentation/arm/Samsung-S3C24XX/Overview.txt @@ -7,13 +7,11 @@ Introduction ------------ The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported - by the 's3c2410' architecture of ARM Linux. Currently the S3C2410, - S3C2440 and S3C2442 devices are supported. + by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 and + the S3C2440 are supported CPUs. Support for the S3C2400 series is in progress. - Support for the S3C2412 and S3C2413 CPUs is being merged. - Configuration ------------- @@ -45,18 +43,9 @@ Machines Samsung's own development board, geared for PDA work. - Samsung/Aiji SMDK2412 - - The S3C2412 version of the SMDK2440. - - Samsung/Aiji SMDK2413 - - The S3C2412 version of the SMDK2440. - Samsung/Meritech SMDK2440 - The S3C2440 compatible version of the SMDK2440, which has the - option of an S3C2440 or S3C2442 CPU module. + The S3C2440 compatible version of the SMDK2440 Thorcom VR1000 @@ -222,6 +211,24 @@ Port Contributors Lucas Correia Villa Real (S3C2400 port) +Document Changes +---------------- + + 05 Sep 2004 - BJD - Added Document Changes section + 05 Sep 2004 - BJD - Added Klaus Fetscher to list of contributors + 25 Oct 2004 - BJD - Added Dimitry Andric to list of contributors + 25 Oct 2004 - BJD - Updated the MTD from the 2.6.9 merge + 21 Jan 2005 - BJD - Added rx3715, added Shannon to contributors + 10 Feb 2005 - BJD - Added Guillaume Gourat to contributors + 02 Mar 2005 - BJD - Added SMDK2440 to list of machines + 06 Mar 2005 - BJD - Added Christer Weinigel + 08 Mar 2005 - BJD - Added LCVR to list of people, updated introduction + 08 Mar 2005 - BJD - Added section on adding machines + 09 Sep 2005 - BJD - Added section on platform data + 11 Feb 2006 - BJD - Added I2C, RTC and Watchdog sections + 11 Feb 2006 - BJD - Added Osiris machine, and S3C2400 information + + Document Author --------------- diff --git a/trunk/Documentation/arm/Samsung-S3C24XX/S3C2412.txt b/trunk/Documentation/arm/Samsung-S3C24XX/S3C2412.txt deleted file mode 100644 index cb82a7fc7901..000000000000 --- a/trunk/Documentation/arm/Samsung-S3C24XX/S3C2412.txt +++ /dev/null @@ -1,120 +0,0 @@ - S3C2412 ARM Linux Overview - ========================== - -Introduction ------------- - - The S3C2412 is part of the S3C24XX range of ARM9 System-on-Chip CPUs - from Samsung. This part has an ARM926-EJS core, capable of running up - to 266MHz (see data-sheet for more information) - - -Clock ------ - - The core clock code provides a set of clocks to the drivers, and allows - for source selection and a number of other features. - - -Power ------ - - No support for suspend/resume to RAM in the current system. - - -DMA ---- - - No current support for DMA. - - -GPIO ----- - - There is support for setting the GPIO to input/output/special function - and reading or writing to them. - - -UART ----- - - The UART hardware is similar to the S3C2440, and is supported by the - s3c2410 driver in the drivers/serial directory. - - -NAND ----- - - The NAND hardware is similar to the S3C2440, and is supported by the - s3c2410 driver in the drivers/mtd/nand directory. - - -USB Host --------- - - The USB hardware is similar to the S3C2410, with extended clock source - control. The OHCI portion is supported by the ohci-s3c2410 driver, and - the clock control selection is supported by the core clock code. - - -USB Device ----------- - - No current support in the kernel - - -IRQs ----- - - All the standard, and external interrupt sources are supported. The - extra sub-sources are not yet supported. - - -RTC ---- - - The RTC hardware is similar to the S3C2410, and is supported by the - s3c2410-rtc driver. - - -Watchdog --------- - - The watchdog harware is the same as the S3C2410, and is supported by - the s3c2410_wdt driver. - - -MMC/SD/SDIO ------------ - - No current support for the MMC/SD/SDIO block. - -IIC ---- - - The IIC hardware is the same as the S3C2410, and is supported by the - i2c-s3c24xx driver. - - -IIS ---- - - No current support for the IIS interface. - - -SPI ---- - - No current support for the SPI interfaces. - - -ATA ---- - - No current support for the on-board ATA block. - - -Document Author ---------------- - -Ben Dooks, (c) 2006 Simtec Electronics diff --git a/trunk/Documentation/arm/Samsung-S3C24XX/S3C2413.txt b/trunk/Documentation/arm/Samsung-S3C24XX/S3C2413.txt deleted file mode 100644 index ab2a88858f12..000000000000 --- a/trunk/Documentation/arm/Samsung-S3C24XX/S3C2413.txt +++ /dev/null @@ -1,21 +0,0 @@ - S3C2413 ARM Linux Overview - ========================== - -Introduction ------------- - - The S3C2413 is an extended version of the S3C2412, with an camera - interface and mobile DDR memory support. See the S3C2412 support - documentation for more information. - - -Camera Interface ---------------- - - This block is currently not supported. - - -Document Author ---------------- - -Ben Dooks, (c) 2006 Simtec Electronics diff --git a/trunk/Documentation/atomic_ops.txt b/trunk/Documentation/atomic_ops.txt index 2a63d5662a93..23a1c2402bcc 100644 --- a/trunk/Documentation/atomic_ops.txt +++ b/trunk/Documentation/atomic_ops.txt @@ -157,13 +157,13 @@ For example, smp_mb__before_atomic_dec() can be used like so: smp_mb__before_atomic_dec(); atomic_dec(&obj->ref_count); -It makes sure that all memory operations preceding the atomic_dec() +It makes sure that all memory operations preceeding the atomic_dec() call are strongly ordered with respect to the atomic counter -operation. In the above example, it guarantees that the assignment of +operation. In the above example, it guarentees that the assignment of "1" to obj->dead will be globally visible to other cpus before the atomic counter decrement. -Without the explicit smp_mb__before_atomic_dec() call, the +Without the explicitl smp_mb__before_atomic_dec() call, the implementation could legally allow the atomic counter update visible to other cpus before the "obj->dead = 1;" assignment. @@ -173,11 +173,11 @@ ordering with respect to memory operations after an atomic_dec() call (smp_mb__{before,after}_atomic_inc()). A missing memory barrier in the cases where they are required by the -atomic_t implementation above can have disastrous results. Here is -an example, which follows a pattern occurring frequently in the Linux +atomic_t implementation above can have disasterous results. Here is +an example, which follows a pattern occuring frequently in the Linux kernel. It is the use of atomic counters to implement reference counting, and it works such that once the counter falls to zero it can -be guaranteed that no other entity can be accessing the object: +be guarenteed that no other entity can be accessing the object: static void obj_list_add(struct obj *obj) { @@ -291,9 +291,9 @@ to the size of an "unsigned long" C data type, and are least of that size. The endianness of the bits within each "unsigned long" are the native endianness of the cpu. - void set_bit(unsigned long nr, volatile unsigned long *addr); - void clear_bit(unsigned long nr, volatile unsigned long *addr); - void change_bit(unsigned long nr, volatile unsigned long *addr); + void set_bit(unsigned long nr, volatils unsigned long *addr); + void clear_bit(unsigned long nr, volatils unsigned long *addr); + void change_bit(unsigned long nr, volatils unsigned long *addr); These routines set, clear, and change, respectively, the bit number indicated by "nr" on the bit mask pointed to by "ADDR". @@ -301,9 +301,9 @@ indicated by "nr" on the bit mask pointed to by "ADDR". They must execute atomically, yet there are no implicit memory barrier semantics required of these interfaces. - int test_and_set_bit(unsigned long nr, volatile unsigned long *addr); - int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr); - int test_and_change_bit(unsigned long nr, volatile unsigned long *addr); + int test_and_set_bit(unsigned long nr, volatils unsigned long *addr); + int test_and_clear_bit(unsigned long nr, volatils unsigned long *addr); + int test_and_change_bit(unsigned long nr, volatils unsigned long *addr); Like the above, except that these routines return a boolean which indicates whether the changed bit was set _BEFORE_ the atomic bit @@ -335,7 +335,7 @@ subsequent memory operation is made visible. For example: /* ... */; obj->killed = 1; -The implementation of test_and_set_bit() must guarantee that +The implementation of test_and_set_bit() must guarentee that "obj->dead = 1;" is visible to cpus before the atomic memory operation done by test_and_set_bit() becomes visible. Likewise, the atomic memory operation done by test_and_set_bit() must become visible before @@ -474,7 +474,7 @@ Now, as far as memory barriers go, as long as spin_lock() strictly orders all subsequent memory operations (including the cas()) with respect to itself, things will be fine. -Said another way, _atomic_dec_and_lock() must guarantee that +Said another way, _atomic_dec_and_lock() must guarentee that a counter dropping to zero is never made visible before the spinlock being acquired. diff --git a/trunk/Documentation/console/console.txt b/trunk/Documentation/console/console.txt deleted file mode 100644 index d3e17447321c..000000000000 --- a/trunk/Documentation/console/console.txt +++ /dev/null @@ -1,144 +0,0 @@ -Console Drivers -=============== - -The linux kernel has 2 general types of console drivers. The first type is -assigned by the kernel to all the virtual consoles during the boot process. -This type will be called 'system driver', and only one system driver is allowed -to exist. The system driver is persistent and it can never be unloaded, though -it may become inactive. - -The second type has to be explicitly loaded and unloaded. This will be called -'modular driver' by this document. Multiple modular drivers can coexist at -any time with each driver sharing the console with other drivers including -the system driver. However, modular drivers cannot take over the console -that is currently occupied by another modular driver. (Exception: Drivers that -call take_over_console() will succeed in the takeover regardless of the type -of driver occupying the consoles.) They can only take over the console that is -occupied by the system driver. In the same token, if the modular driver is -released by the console, the system driver will take over. - -Modular drivers, from the programmer's point of view, has to call: - - take_over_console() - load and bind driver to console layer - give_up_console() - unbind and unload driver - -In newer kernels, the following are also available: - - register_con_driver() - unregister_con_driver() - -If sysfs is enabled, the contents of /sys/class/vtconsole can be -examined. This shows the console backends currently registered by the -system which are named vtcon where is an integer fro 0 to 15. Thus: - - ls /sys/class/vtconsole - . .. vtcon0 vtcon1 - -Each directory in /sys/class/vtconsole has 3 files: - - ls /sys/class/vtconsole/vtcon0 - . .. bind name uevent - -What do these files signify? - - 1. bind - this is a read/write file. It shows the status of the driver if - read, or acts to bind or unbind the driver to the virtual consoles - when written to. The possible values are: - - 0 - means the driver is not bound and if echo'ed, commands the driver - to unbind - - 1 - means the driver is bound and if echo'ed, commands the driver to - bind - - 2. name - read-only file. Shows the name of the driver in this format: - - cat /sys/class/vtconsole/vtcon0/name - (S) VGA+ - - '(S)' stands for a (S)ystem driver, ie, it cannot be directly - commanded to bind or unbind - - 'VGA+' is the name of the driver - - cat /sys/class/vtconsole/vtcon1/name - (M) frame buffer device - - In this case, '(M)' stands for a (M)odular driver, one that can be - directly commanded to bind or unbind. - - 3. uevent - ignore this file - -When unbinding, the modular driver is detached first, and then the system -driver takes over the consoles vacated by the driver. Binding, on the other -hand, will bind the driver to the consoles that are currently occupied by a -system driver. - -NOTE1: Binding and binding must be selected in Kconfig. It's under: - -Device Drivers -> Character devices -> Support for binding and unbinding -console drivers - -NOTE2: If any of the virtual consoles are in KD_GRAPHICS mode, then binding or -unbinding will not succeed. An example of an application that sets the console -to KD_GRAPHICS is X. - -How useful is this feature? This is very useful for console driver -developers. By unbinding the driver from the console layer, one can unload the -driver, make changes, recompile, reload and rebind the driver without any need -for rebooting the kernel. For regular users who may want to switch from -framebuffer console to VGA console and vice versa, this feature also makes -this possible. (NOTE NOTE NOTE: Please read fbcon.txt under Documentation/fb -for more details). - -Notes for developers: -===================== - -take_over_console() is now broken up into: - - register_con_driver() - bind_con_driver() - private function - -give_up_console() is a wrapper to unregister_con_driver(), and a driver must -be fully unbound for this call to succeed. con_is_bound() will check if the -driver is bound or not. - -Guidelines for console driver writers: -===================================== - -In order for binding to and unbinding from the console to properly work, -console drivers must follow these guidelines: - -1. All drivers, except system drivers, must call either register_con_driver() - or take_over_console(). register_con_driver() will just add the driver to - the console's internal list. It won't take over the - console. take_over_console(), as it name implies, will also take over (or - bind to) the console. - -2. All resources allocated during con->con_init() must be released in - con->con_deinit(). - -3. All resources allocated in con->con_startup() must be released when the - driver, which was previously bound, becomes unbound. The console layer - does not have a complementary call to con->con_startup() so it's up to the - driver to check when it's legal to release these resources. Calling - con_is_bound() in con->con_deinit() will help. If the call returned - false(), then it's safe to release the resources. This balance has to be - ensured because con->con_startup() can be called again when a request to - rebind the driver to the console arrives. - -4. Upon exit of the driver, ensure that the driver is totally unbound. If the - condition is satisfied, then the driver must call unregister_con_driver() - or give_up_console(). - -5. unregister_con_driver() can also be called on conditions which make it - impossible for the driver to service console requests. This can happen - with the framebuffer console that suddenly lost all of its drivers. - -The current crop of console drivers should still work correctly, but binding -and unbinding them may cause problems. With minimal fixes, these drivers can -be made to work correctly. - -========================== -Antonino Daplas - diff --git a/trunk/Documentation/digiepca.txt b/trunk/Documentation/digiepca.txt index f2560e22f2c9..88820fe38dad 100644 --- a/trunk/Documentation/digiepca.txt +++ b/trunk/Documentation/digiepca.txt @@ -2,7 +2,7 @@ NOTE: This driver is obsolete. Digi provides a 2.6 driver (dgdm) at http://www.digi.com for PCI cards. They no longer maintain this driver, and have no 2.6 driver for ISA cards. -This driver requires a number of user-space tools. They can be acquired from +This driver requires a number of user-space tools. They can be aquired from http://www.digi.com, but only works with 2.4 kernels. diff --git a/trunk/Documentation/driver-model/overview.txt b/trunk/Documentation/driver-model/overview.txt index 2050c9ffc629..ac4a7a737e43 100644 --- a/trunk/Documentation/driver-model/overview.txt +++ b/trunk/Documentation/driver-model/overview.txt @@ -18,7 +18,7 @@ Traditional driver models implemented some sort of tree-like structure (sometimes just a list) for the devices they control. There wasn't any uniformity across the different bus types. -The current driver model provides a common, uniform data model for describing +The current driver model provides a comon, uniform data model for describing a bus and the devices that can appear under the bus. The unified bus model includes a set of common attributes which all busses carry, and a set of common callbacks, such as device discovery during bus probing, bus diff --git a/trunk/Documentation/fb/fbcon.txt b/trunk/Documentation/fb/fbcon.txt index f373df12ed4c..08dce0f631bf 100644 --- a/trunk/Documentation/fb/fbcon.txt +++ b/trunk/Documentation/fb/fbcon.txt @@ -135,10 +135,10 @@ C. Boot options The angle can be changed anytime afterwards by 'echoing' the same numbers to any one of the 2 attributes found in - /sys/class/graphics/fbcon + /sys/class/graphics/fb{x} - rotate - rotate the display of the active console - rotate_all - rotate the display of all consoles + con_rotate - rotate the display of the active console + con_rotate_all - rotate the display of all consoles Console rotation will only become available if Console Rotation Support is compiled in your kernel. @@ -148,177 +148,5 @@ C. Boot options Actually, the underlying fb driver is totally ignorant of console rotation. -C. Attaching, Detaching and Unloading - -Before going on on how to attach, detach and unload the framebuffer console, an -illustration of the dependencies may help. - -The console layer, as with most subsystems, needs a driver that interfaces with -the hardware. Thus, in a VGA console: - -console ---> VGA driver ---> hardware. - -Assuming the VGA driver can be unloaded, one must first unbind the VGA driver -from the console layer before unloading the driver. The VGA driver cannot be -unloaded if it is still bound to the console layer. (See -Documentation/console/console.txt for more information). - -This is more complicated in the case of the the framebuffer console (fbcon), -because fbcon is an intermediate layer between the console and the drivers: - -console ---> fbcon ---> fbdev drivers ---> hardware - -The fbdev drivers cannot be unloaded if it's bound to fbcon, and fbcon cannot -be unloaded if it's bound to the console layer. - -So to unload the fbdev drivers, one must first unbind fbcon from the console, -then unbind the fbdev drivers from fbcon. Fortunately, unbinding fbcon from -the console layer will automatically unbind framebuffer drivers from -fbcon. Thus, there is no need to explicitly unbind the fbdev drivers from -fbcon. - -So, how do we unbind fbcon from the console? Part of the answer is in -Documentation/console/console.txt. To summarize: - -Echo a value to the bind file that represents the framebuffer console -driver. So assuming vtcon1 represents fbcon, then: - -echo 1 > sys/class/vtconsole/vtcon1/bind - attach framebuffer console to - console layer -echo 0 > sys/class/vtconsole/vtcon1/bind - detach framebuffer console from - console layer - -If fbcon is detached from the console layer, your boot console driver (which is -usually VGA text mode) will take over. A few drivers (rivafb and i810fb) will -restore VGA text mode for you. With the rest, before detaching fbcon, you -must take a few additional steps to make sure that your VGA text mode is -restored properly. The following is one of the several methods that you can do: - -1. Download or install vbetool. This utility is included with most - distributions nowadays, and is usually part of the suspend/resume tool. - -2. In your kernel configuration, ensure that CONFIG_FRAMEBUFFER_CONSOLE is set - to 'y' or 'm'. Enable one or more of your favorite framebuffer drivers. - -3. Boot into text mode and as root run: - - vbetool vbestate save > - - The above command saves the register contents of your graphics - hardware to . You need to do this step only once as - the state file can be reused. - -4. If fbcon is compiled as a module, load fbcon by doing: - - modprobe fbcon - -5. Now to detach fbcon: - - vbetool vbestate restore < && \ - echo 0 > /sys/class/vtconsole/vtcon1/bind - -6. That's it, you're back to VGA mode. And if you compiled fbcon as a module, - you can unload it by 'rmmod fbcon' - -7. To reattach fbcon: - - echo 1 > /sys/class/vtconsole/vtcon1/bind - -8. Once fbcon is unbound, all drivers registered to the system will also -become unbound. This means that fbcon and individual framebuffer drivers -can be unloaded or reloaded at will. Reloading the drivers or fbcon will -automatically bind the console, fbcon and the drivers together. Unloading -all the drivers without unloading fbcon will make it impossible for the -console to bind fbcon. - -Notes for vesafb users: -======================= - -Unfortunately, if your bootline includes a vga=xxx parameter that sets the -hardware in graphics mode, such as when loading vesafb, vgacon will not load. -Instead, vgacon will replace the default boot console with dummycon, and you -won't get any display after detaching fbcon. Your machine is still alive, so -you can reattach vesafb. However, to reattach vesafb, you need to do one of -the following: - -Variation 1: - - a. Before detaching fbcon, do - - vbetool vbemode save > # do once for each vesafb mode, - # the file can be reused - - b. Detach fbcon as in step 5. - - c. Attach fbcon - - vbetool vbestate restore < && \ - echo 1 > /sys/class/vtconsole/vtcon1/bind - -Variation 2: - - a. Before detaching fbcon, do: - echo > /sys/class/tty/console/bind - - - vbetool vbemode get - - b. Take note of the mode number - - b. Detach fbcon as in step 5. - - c. Attach fbcon: - - vbetool vbemode set && \ - echo 1 > /sys/class/vtconsole/vtcon1/bind - -Samples: -======== - -Here are 2 sample bash scripts that you can use to bind or unbind the -framebuffer console driver if you are in an X86 box: - ---------------------------------------------------------------------------- -#!/bin/bash -# Unbind fbcon - -# Change this to where your actual vgastate file is located -# Or Use VGASTATE=$1 to indicate the state file at runtime -VGASTATE=/tmp/vgastate - -# path to vbetool -VBETOOL=/usr/local/bin - - -for (( i = 0; i < 16; i++)) -do - if test -x /sys/class/vtconsole/vtcon$i; then - if [ `cat /sys/class/vtconsole/vtcon$i/name | grep -c "frame buffer"` \ - = 1 ]; then - if test -x $VBETOOL/vbetool; then - echo Unbinding vtcon$i - $VBETOOL/vbetool vbestate restore < $VGASTATE - echo 0 > /sys/class/vtconsole/vtcon$i/bind - fi - fi - fi -done - ---------------------------------------------------------------------------- -#!/bin/bash -# Bind fbcon - -for (( i = 0; i < 16; i++)) -do - if test -x /sys/class/vtconsole/vtcon$i; then - if [ `cat /sys/class/vtconsole/vtcon$i/name | grep -c "frame buffer"` \ - = 1 ]; then - echo Unbinding vtcon$i - echo 1 > /sys/class/vtconsole/vtcon$i/bind - fi - fi -done ---------------------------------------------------------------------------- - --- +--- Antonino Daplas diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 99f219a01e0e..027285d0c26c 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -6,6 +6,17 @@ be removed from this file. --------------------------- +What: devfs +When: July 2005 +Files: fs/devfs/*, include/linux/devfs_fs*.h and assorted devfs + function calls throughout the kernel tree +Why: It has been unmaintained for a number of years, has unfixable + races, contains a naming policy within the kernel that is + against the LSB, and can be replaced by using udev. +Who: Greg Kroah-Hartman + +--------------------------- + What: RAW driver (CONFIG_RAW_DRIVER) When: December 2005 Why: declared obsolete since kernel 2.6.3 @@ -121,6 +132,16 @@ Who: NeilBrown --------------------------- +What: au1x00_uart driver +When: January 2006 +Why: The 8250 serial driver now has the ability to deal with the differences + between the standard 8250 family of UARTs and their slightly strange + brother on Alchemy SOCs. The loss of features is not considered an + issue. +Who: Ralf Baechle + +--------------------------- + What: eepro100 network driver When: January 2007 Why: replaced by the e100 driver @@ -156,16 +177,6 @@ Who: Jean Delvare --------------------------- -What: Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports - (temporary transition config option provided until then) - The transition config option will also be removed at the same time. -When: before 2.6.19 -Why: Unused symbols are both increasing the size of the kernel binary - and are often a sign of "wrong API" -Who: Arjan van de Ven - ---------------------------- - What: remove EXPORT_SYMBOL(tasklist_lock) When: August 2006 Files: kernel/fork.c @@ -213,56 +224,3 @@ Why: The interface no longer has any callers left in the kernel. It Who: Nick Piggin --------------------------- - -What: Support for the MIPS EV96100 evaluation board -When: September 2006 -Why: Does no longer build since at least November 15, 2003, apparently - no userbase left. -Who: Ralf Baechle - ---------------------------- - -What: Support for the Momentum / PMC-Sierra Jaguar ATX evaluation board -When: September 2006 -Why: Does no longer build since quite some time, and was never popular, - due to the platform being replaced by successor models. Apparently - no user base left. It also is one of the last users of - WANT_PAGE_VIRTUAL. -Who: Ralf Baechle - ---------------------------- - -What: Support for the Momentum Ocelot, Ocelot 3, Ocelot C and Ocelot G -When: September 2006 -Why: Some do no longer build and apparently there is no user base left - for these platforms. -Who: Ralf Baechle - ---------------------------- - -What: Support for MIPS Technologies' Altas and SEAD evaluation board -When: September 2006 -Why: Some do no longer build and apparently there is no user base left - for these platforms. Hardware out of production since several years. -Who: Ralf Baechle - ---------------------------- - -What: Support for the IT8172-based platforms, ITE 8172G and Globespan IVR -When: September 2006 -Why: Code does no longer build since at least 2.6.0, apparently there is - no user base left for these platforms. Hardware out of production - since several years and hardly a trace of the manufacturer left on - the net. -Who: Ralf Baechle - ---------------------------- - -What: Interrupt only SA_* flags -When: Januar 2007 -Why: The interrupt related SA_* flags are replaced by IRQF_* to move them - out of the signal namespace. - -Who: Thomas Gleixner - ---------------------------- diff --git a/trunk/Documentation/filesystems/configfs/configfs_example.c b/trunk/Documentation/filesystems/configfs/configfs_example.c index 2d6a14a463e0..3d4713a6c207 100644 --- a/trunk/Documentation/filesystems/configfs/configfs_example.c +++ b/trunk/Documentation/filesystems/configfs/configfs_example.c @@ -264,15 +264,6 @@ static struct config_item_type simple_child_type = { }; -struct simple_children { - struct config_group group; -}; - -static inline struct simple_children *to_simple_children(struct config_item *item) -{ - return item ? container_of(to_config_group(item), struct simple_children, group) : NULL; -} - static struct config_item *simple_children_make_item(struct config_group *group, const char *name) { struct simple_child *simple_child; @@ -313,13 +304,7 @@ static ssize_t simple_children_attr_show(struct config_item *item, "items have only one attribute that is readable and writeable.\n"); } -static void simple_children_release(struct config_item *item) -{ - kfree(to_simple_children(item)); -} - static struct configfs_item_operations simple_children_item_ops = { - .release = simple_children_release, .show_attribute = simple_children_attr_show, }; @@ -360,6 +345,10 @@ static struct configfs_subsystem simple_children_subsys = { * children of its own. */ +struct simple_children { + struct config_group group; +}; + static struct config_group *group_children_make_group(struct config_group *group, const char *name) { struct simple_children *simple_children; diff --git a/trunk/Documentation/filesystems/devfs/ChangeLog b/trunk/Documentation/filesystems/devfs/ChangeLog new file mode 100644 index 000000000000..e5aba5246d7c --- /dev/null +++ b/trunk/Documentation/filesystems/devfs/ChangeLog @@ -0,0 +1,1977 @@ +/* -*- auto-fill -*- */ +=============================================================================== +Changes for patch v1 + +- creation of devfs + +- modified miscellaneous character devices to support devfs +=============================================================================== +Changes for patch v2 + +- bug fix with manual inode creation +=============================================================================== +Changes for patch v3 + +- bugfixes + +- documentation improvements + +- created a couple of scripts (one to save&restore a devfs and the + other to set up compatibility symlinks) + +- devfs support for SCSI discs. New name format is: sd_hHcCiIlL +=============================================================================== +Changes for patch v4 + +- bugfix for the directory reading code + +- bugfix for compilation with kerneld + +- devfs support for generic hard discs + +- rationalisation of the various watchdog drivers +=============================================================================== +Changes for patch v5 + +- support for mounting directly from entries in the devfs (it doesn't + need to be mounted to do this), including the root filesystem. + Mounting of swap partitions also works. Hence, now if you set + CONFIG_DEVFS_ONLY to 'Y' then you won't be able to access your discs + via ordinary device nodes. Naturally, the default is 'N' so that you + can still use your old device nodes. If you want to mount from devfs + entries, make sure you use: append = "root=/dev/sd_..." in your + lilo.conf. It seems LILO looks for the device number (major&minor) + and writes that into the kernel image :-( + +- support for character memory devices (/dev/null, /dev/zero, /dev/full + and so on). Thanks to C. Scott Ananian +=============================================================================== +Changes for patch v6 + +- support for subdirectories + +- support for symbolic links (created by devfs_mk_symlink(), no + support yet for creation via symlink(2)) + +- SCSI disc naming now cast in stone, with the format: + /dev/sd/c0b1t2u3 controller=0, bus=1, ID=2, LUN=3, whole disc + /dev/sd/c0b1t2u3p4 controller=0, bus=1, ID=2, LUN=3, 4th partition + +- loop devices now appear in devfs + +- tty devices, console, serial ports, etc. now appear in devfs + Thanks to C. Scott Ananian + +- bugs with mounting devfs-only devices now fixed +=============================================================================== +Changes for patch v7 + +- SCSI CD-ROMS, tapes and generic devices now appear in devfs +=============================================================================== +Changes for patch v8 + +- bugfix with no-rewind SCSI tapes + +- RAMDISCs now appear in devfs + +- better cleaning up of devfs entries created by various modules + +- interface change to +=============================================================================== +Changes for patch v9 + +- the v8 patch was corrupted somehow, which would affect the patch for + linux/fs/filesystems.c + I've also fixed the v8 patch file on the WWW + +- MetaDevices (/dev/md*) should now appear in devfs +=============================================================================== +Changes for patch v10 + +- bugfix in meta device support for devfs + +- created this ChangeLog file + +- added devfs support to the floppy driver + +- added support for creating sockets in a devfs +=============================================================================== +Changes for patch v11 + +- added DEVFS_FL_HIDE_UNREG flag + +- incorporated better patch for ttyname() in libc 5.4.43 from H.J. Lu. + +- interface change to + +- support for creating symlinks with symlink(2) + +- parallel port printer (/dev/lp*) now appears in devfs +=============================================================================== +Changes for patch v12 + +- added inode check to function + +- improved devfs support when mounting from devfs + +- added call to <> operation when removing swap areas on + devfs devices + +- increased NR_SUPER to 128 to support large numbers of devfs mounts + (for chroot(2) gaols) + +- fixed bug in SCSI disc support: was generating incorrect minors if + SCSI ID's did not start at 0 and increase by 1 + +- support symlink traversal when mounting root +=============================================================================== +Changes for patch v13 + +- added devfs support to soundcard driver + Thanks to Eric Dumas and + C. Scott Ananian + +- added devfs support to the joystick driver + +- loop driver now has it's own subdirectory "/dev/loop/" + +- created and functions + +- fix problem with SCSI disc compatibility names (sd{a,b,c,d,e,f}) + which assumes ID's start at 0 and increase by 1. Also only create + devfs entries for SCSI disc partitions which actually exist + Show new names in partition check + Thanks to Jakub Jelinek +=============================================================================== +Changes for patch v14 + +- bug fix in floppy driver: would not compile without + CONFIG_DEVFS_FS='Y' + Thanks to Jurgen Botz + +- bug fix in loop driver + Thanks to C. Scott Ananian + +- do not create devfs entries for printers not configured + Thanks to C. Scott Ananian + +- do not create devfs entries for serial ports not present + Thanks to C. Scott Ananian + +- ensure is exported from tty_io.c + Thanks to C. Scott Ananian + +- allow unregistering of devfs symlink entries + +- fixed bug in SCSI disc naming introduced in last patch version +=============================================================================== +Changes for patch v15 + +- ported to kernel 2.1.81 +=============================================================================== +Changes for patch v16 + +- created function + +- moved DEVFS_SUPER_MAGIC into header file + +- added DEVFS_FL_HIDE flag + +- created + +- created + +- fixed bugs in searching by major&minor + +- changed interface to , and + + +- fixed inode times when symlink created with symlink(2) + +- change tty driver to do auto-creation of devfs entries + Thanks to C. Scott Ananian + +- fixed bug in genhd.c: whole disc (non-SCSI) was not registered to + devfs + +- updated libc 5.4.43 patch for ttyname() +=============================================================================== +Changes for patch v17 + +- added CONFIG_DEVFS_TTY_COMPAT + Thanks to C. Scott Ananian + +- bugfix in devfs support for drivers/char/lp.c + Thanks to C. Scott Ananian + +- clean up serial driver so that PCMCIA devices unregister correctly + Thanks to C. Scott Ananian + +- fixed bug in genhd.c: whole disc (non-SCSI) was not registered to + devfs [was missing in patch v16] + +- updated libc 5.4.43 patch for ttyname() [was missing in patch v16] + +- all SCSI devices now registered in /dev/sg + +- support removal of devfs entries via unlink(2) +=============================================================================== +Changes for patch v18 + +- added floppy/?u720 floppy entry + +- fixed kerneld support for entries in devfs subdirectories + +- incorporated latest patch for ttyname() in libc 5.4.43 from H.J. Lu. +=============================================================================== +Changes for patch v19 + +- bug fix when looking up unregistered entries: kerneld was not called + +- fixes for kernel 2.1.86 (now requires 2.1.86) +=============================================================================== +Changes for patch v20 + +- only create available floppy entries + Thanks to Andrzej Krzysztofowicz + +- new IDE naming scheme following SCSI format (i.e. /dev/id/c0b0t0u0p1 + instead of /dev/hda1) + Thanks to Andrzej Krzysztofowicz + +- new XT disc naming scheme following SCSI format (i.e. /dev/xd/c0t0p1 + instead of /dev/xda1) + Thanks to Andrzej Krzysztofowicz + +- new non-standard CD-ROM names (i.e. /dev/sbp/c#t#) + Thanks to Andrzej Krzysztofowicz + +- allow symlink traversal when mounting the root filesystem + +- Create entries for MD devices at MD init + Thanks to Christophe Leroy +=============================================================================== +Changes for patch v21 + +- ported to kernel 2.1.91 +=============================================================================== +Changes for patch v22 + +- SCSI host number patch ("scsihosts=" kernel option) + Thanks to Andrzej Krzysztofowicz +=============================================================================== +Changes for patch v23 + +- Fixed persistence bug with device numbers for manually created + device files + +- Fixed problem with recreating symlinks with different content + +- Added CONFIG_DEVFS_MOUNT (mount devfs on /dev at boot time) +=============================================================================== +Changes for patch v24 + +- Switched from CONFIG_KERNELD to CONFIG_KMOD: module autoloading + should now work again + +- Hide entries which are manually unlinked + +- Always invalidate devfs dentry cache when registering entries + +- Support removal of devfs directories via rmdir(2) + +- Ensure directories created by are visible + +- Default no access for "other" for floppy device +=============================================================================== +Changes for patch v25 + +- Updates to CREDITS file and minor IDE numbering change + Thanks to Andrzej Krzysztofowicz + +- Invalidate devfs dentry cache when making directories + +- Invalidate devfs dentry cache when removing entries + +- More informative message if root FS mount fails when devfs + configured + +- Fixed persistence bug with fifos +=============================================================================== +Changes for patch v26 + +- ported to kernel 2.1.97 + +- Changed serial directory from "/dev/serial" to "/dev/tts" and + "/dev/consoles" to "/dev/vc" to be more friendly to new procps +=============================================================================== +Changes for patch v27 + +- Added support for IDE4 and IDE5 + Thanks to Andrzej Krzysztofowicz + +- Documented "scsihosts=" boot parameter + +- Print process command when debugging kerneld/kmod + +- Added debugging for register/unregister/change operations + +- Added "devfs=" boot options + +- Hide unregistered entries by default +=============================================================================== +Changes for patch v28 + +- No longer lock/unlock superblock in (cope with + recent VFS interface change) + +- Do not automatically change ownership/protection of /dev/tty + +- Drop negative dentries when they are released + +- Manage dcache more efficiently +=============================================================================== +Changes for patch v29 + +- Added DEVFS_FL_AUTO_DEVNUM flag +=============================================================================== +Changes for patch v30 + +- No longer set unnecessary methods + +- Ported to kernel 2.1.99-pre3 +=============================================================================== +Changes for patch v31 + +- Added PID display to debugging message + +- Added "diread" and "diwrite" options + +- Ported to kernel 2.1.102 + +- Fixed persistence problem with permissions +=============================================================================== +Changes for patch v32 + +- Fixed devfs support in drivers/block/md.c +=============================================================================== +Changes for patch v33 + +- Support legacy device nodes + +- Fixed bug where recreated inodes were hidden + +- New IDE naming scheme: everything is under /dev/ide +=============================================================================== +Changes for patch v34 + +- Improved debugging in + +- Prevent duplicate calls to in SCSI layer + +- No longer free old dentries in + +- Free all dentries for a given entry when deleting inodes +=============================================================================== +Changes for patch v35 + +- Ported to kernel 2.1.105 (sound driver changes) +=============================================================================== +Changes for patch v36 + +- Fixed sound driver port +=============================================================================== +Changes for patch v37 + +- Minor documentation tweaks +=============================================================================== +Changes for patch v38 + +- More documentation tweaks + +- Fix for sound driver port + +- Removed ttyname-patch (grab libc 5.4.44 instead) + +- Ported to kernel 2.1.107-pre2 (loop driver fix) +=============================================================================== +Changes for patch v39 + +- Ported to kernel 2.1.107 (hd.c hunk broke due to spelling "fixes"). Sigh + +- Removed many #ifdef's, replaced with trickery in include/devfs_fs.h +=============================================================================== +Changes for patch v40 + +- Fix for sound driver port + +- Limit auto-device numbering to majors 128 to 239 +=============================================================================== +Changes for patch v41 + +- Fixed inode times persistence problem +=============================================================================== +Changes for patch v42 + +- Ported to kernel 2.1.108 (drivers/scsi/hosts.c hunk broke) +=============================================================================== +Changes for patch v43 + +- Fixed spelling in debug + +- Fixed bug in parsing "dilookup" + +- More #ifdef's removed + +- Supported Sparc keyboard (/dev/kbd) + +- Supported DSP56001 digital signal processor (/dev/dsp56k) + +- Supported Apple Desktop Bus (/dev/adb) + +- Supported Coda network file system (/dev/cfs*) +=============================================================================== +Changes for patch v44 + +- Fixed devfs inode leak when manually recreating inodes + +- Fixed permission persistence problem when recreating inodes +=============================================================================== +Changes for patch v45 + +- Ported to kernel 2.1.110 +=============================================================================== +Changes for patch v46 + +- Ported to kernel 2.1.112-pre1 + +- Removed harmless "unused variable" compiler warning + +- Fixed modes for manually recreated device nodes +=============================================================================== +Changes for patch v47 + +- Added NULL devfs inode warning in + +- Force all inode nlink values to 1 +=============================================================================== +Changes for patch v48 + +- Added "dimknod" option + +- Set inode nlink to 0 when freeing dentries + +- Added support for virtual console capture devices (/dev/vcs*) + Thanks to Dennis Hou + +- Fixed modes for manually recreated symlinks +=============================================================================== +Changes for patch v49 + +- Ported to kernel 2.1.113 +=============================================================================== +Changes for patch v50 + +- Fixed bugs in recreated directories and symlinks +=============================================================================== +Changes for patch v51 + +- Improved robustness of rc.devfs script + Thanks to Roderich Schupp + +- Fixed bugs in recreated device nodes + +- Fixed bug in currently unused + +- Defined new type + +- Improved debugging when getting entries + +- Fixed bug where directories could be emptied + +- Ported to kernel 2.1.115 +=============================================================================== +Changes for patch v52 + +- Replaced dummy .epoch inode with .devfsd character device + +- Modified rc.devfs to take account of above change + +- Removed spurious driver warning messages when CONFIG_DEVFS_FS=n + +- Implemented devfsd protocol revision 0 +=============================================================================== +Changes for patch v53 + +- Ported to kernel 2.1.116 (kmod change broke hunk) + +- Updated Documentation/Configure.help + +- Test and tty pattern patch for rc.devfs script + Thanks to Roderich Schupp + +- Added soothing message to warning in +=============================================================================== +Changes for patch v54 + +- Ported to kernel 2.1.117 + +- Fixed default permissions in sound driver + +- Added support for frame buffer devices (/dev/fb*) +=============================================================================== +Changes for patch v55 + +- Ported to kernel 2.1.119 + +- Use GCC extensions for structure initialisations + +- Implemented async open notification + +- Incremented devfsd protocol revision to 1 +=============================================================================== +Changes for patch v56 + +- Ported to kernel 2.1.120-pre3 + +- Moved async open notification to end of +=============================================================================== +Changes for patch v57 + +- Ported to kernel 2.1.121 + +- Prepended "/dev/" to module load request + +- Renamed to + +- Created sample modules.conf file +=============================================================================== +Changes for patch v58 + +- Fixed typo "AYSNC" -> "ASYNC" +=============================================================================== +Changes for patch v59 + +- Added open flag for files +=============================================================================== +Changes for patch v60 + +- Ported to kernel 2.1.123-pre2 +=============================================================================== +Changes for patch v61 + +- Set i_blocks=0 and i_blksize=1024 in +=============================================================================== +Changes for patch v62 + +- Ported to kernel 2.1.123 +=============================================================================== +Changes for patch v63 + +- Ported to kernel 2.1.124-pre2 +=============================================================================== +Changes for patch v64 + +- Fixed Unix98 pty support + +- Increased buffer size in to avoid crash and + burn +=============================================================================== +Changes for patch v65 + +- More Unix98 pty support fixes + +- Added test for empty <> in + +- Renamed to and published + +- Created /dev/root symlink + Thanks to Roderich Schupp + with further modifications by me +=============================================================================== +Changes for patch v66 + +- Yet more Unix98 pty support fixes (now tested) + +- Created + +- Support media change checks when CONFIG_DEVFS_ONLY=y + +- Abolished Unix98-style PTY names for old PTY devices +=============================================================================== +Changes for patch v67 + +- Added inline declaration for dummy + +- Removed spurious "unable to register... in devfs" messages when + CONFIG_DEVFS_FS=n + +- Fixed misc. devices when CONFIG_DEVFS_FS=n + +- Limit auto-device numbering to majors 144 to 239 +=============================================================================== +Changes for patch v68 + +- Hide unopened virtual consoles from directory listings + +- Added support for video capture devices + +- Ported to kernel 2.1.125 +=============================================================================== +Changes for patch v69 + +- Fix for CONFIG_VT=n +=============================================================================== +Changes for patch v70 + +- Added support for non-OSS/Free sound cards +=============================================================================== +Changes for patch v71 + +- Ported to kernel 2.1.126-pre2 +=============================================================================== +Changes for patch v72 + +- #ifdef's for CONFIG_DEVFS_DISABLE_OLD_NAMES removed +=============================================================================== +Changes for patch v73 + +- CONFIG_DEVFS_DISABLE_OLD_NAMES replaced with "nocompat" boot option + +- CONFIG_DEVFS_BOOT_OPTIONS removed: boot options always available +=============================================================================== +Changes for patch v74 + +- Removed CONFIG_DEVFS_MOUNT and "mount" boot option and replaced with + "nomount" boot option + +- Documentation updates + +- Updated sample modules.conf +=============================================================================== +Changes for patch v75 + +- Updated sample modules.conf + +- Remount devfs after initrd finishes + +- Ported to kernel 2.1.127 + +- Added support for ISDN + Thanks to Christophe Leroy +=============================================================================== +Changes for patch v76 + +- Updated an email address in ChangeLog + +- CONFIG_DEVFS_ONLY replaced with "only" boot option +=============================================================================== +Changes for patch v77 + +- Added DEVFS_FL_REMOVABLE flag + +- Check for disc change when listing directories with removable media + devices + +- Use DEVFS_FL_REMOVABLE in sd.c + +- Ported to kernel 2.1.128 +=============================================================================== +Changes for patch v78 + +- Only call on first call to + +- Ported to kernel 2.1.129-pre5 + +- ISDN support improvements + Thanks to Christophe Leroy +=============================================================================== +Changes for patch v79 + +- Ported to kernel 2.1.130 + +- Renamed miscdevice "apm" to "apm_bios" to be consistent with + devices.txt +=============================================================================== +Changes for patch v80 + +- Ported to kernel 2.1.131 + +- Updated for VFS change in 2.1.131 +=============================================================================== +Changes for patch v81 + +- Fixed permissions on /dev/ptmx +=============================================================================== +Changes for patch v82 + +- Ported to kernel 2.1.132-pre4 + +- Changed initial permissions on /dev/pts/* + +- Created + +- Added "symlinks" boot option + +- Changed devfs_register_blkdev() back to register_blkdev() for IDE + +- Check for partitions on removable media in +=============================================================================== +Changes for patch v83 + +- Fixed support for ramdisc when using string-based root FS name + +- Ported to kernel 2.2.0-pre1 +=============================================================================== +Changes for patch v84 + +- Ported to kernel 2.2.0-pre7 +=============================================================================== +Changes for patch v85 + +- Compile fixes for driver/sound/sound_common.c (non-module) and + drivers/isdn/isdn_common.c + Thanks to Christophe Leroy + +- Added support for registering regular files + +- Created + +- Added /dev/cpu/mtrr as an alternative interface to /proc/mtrr + +- Update devfs inodes from entries if not changed through FS +=============================================================================== +Changes for patch v86 + +- Ported to kernel 2.2.0-pre9 +=============================================================================== +Changes for patch v87 + +- Fixed bug when mounting non-devfs devices in a devfs +=============================================================================== +Changes for patch v88 + +- Fixed to only initialise temporary inodes + +- Trap for NULL fops in + +- Return -ENODEV in for non-driver inodes + +- Fixed bug when unswapping non-devfs devices in a devfs +=============================================================================== +Changes for patch v89 + +- Switched to C data types in include/linux/devfs_fs.h + +- Switched from PATH_MAX to DEVFS_PATHLEN + +- Updated Documentation/filesystems/devfs/modules.conf to take account + of reverse scanning (!) by modprobe + +- Ported to kernel 2.2.0 +=============================================================================== +Changes for patch v90 + +- CONFIG_DEVFS_DISABLE_OLD_TTY_NAMES replaced with "nottycompat" boot + option + +- CONFIG_DEVFS_TTY_COMPAT removed: existing "symlinks" boot option now + controls this. This means you must have libc 5.4.44 or later, or a + recent version of libc 6 if you use the "symlinks" option +=============================================================================== +Changes for patch v91 + +- Switch from to in + drivers/char/vc_screen.c to fix problems with Midnight Commander +=============================================================================== +Changes for patch v92 + +- Ported to kernel 2.2.2-pre5 +=============================================================================== +Changes for patch v93 + +- Modified in drivers/scsi/sd.c to cope with devices that + don't exist (which happens with new RAID autostart code printk()s) +=============================================================================== +Changes for patch v94 + +- Fixed bug in joystick driver: only first joystick was registered +=============================================================================== +Changes for patch v95 + +- Fixed another bug in joystick driver + +- Fixed to not overrun event buffer +=============================================================================== +Changes for patch v96 + +- Ported to kernel 2.2.5-2 + +- Created + +- Fixed bugs: compatibility entries were not unregistered for: + loop driver + floppy driver + RAMDISC driver + IDE tape driver + SCSI CD-ROM driver + SCSI HDD driver +=============================================================================== +Changes for patch v97 + +- Fixed bugs: compatibility entries were not unregistered for: + ALSA sound driver + partitions in generic disc driver + +- Don't return unregistred entries in + +- Panic in if entry unregistered + +- Don't panic in for duplicates +=============================================================================== +Changes for patch v98 + +- Don't unregister already unregistered entries in + +- Register entry in + +- Unregister entry in + +- Changed to in drivers/char/tty_io.c + +- Ported to kernel 2.2.7 +=============================================================================== +Changes for patch v99 + +- Ported to kernel 2.2.8 + +- Fixed bug in drivers/scsi/sd.c when >16 SCSI discs + +- Disable warning messages when unable to read partition table for + removable media +=============================================================================== +Changes for patch v100 + +- Ported to kernel 2.3.1-pre5 + +- Added "oops-on-panic" boot option + +- Improved debugging in and + +- Register entry in + +- Unregister entry in + +- Register entry in + +- Unregister entry in + +- Added support for ALSA drivers +=============================================================================== +Changes for patch v101 + +- Ported to kernel 2.3.2 +=============================================================================== +Changes for patch v102 + +- Update serial driver to register PCMCIA entries + Thanks to Roch-Alexandre Nomine-Beguin + +- Updated an email address in ChangeLog + +- Hide virtual console capture entries from directory listings when + corresponding console device is not open +=============================================================================== +Changes for patch v103 + +- Ported to kernel 2.3.3 +=============================================================================== +Changes for patch v104 + +- Added documentation for some functions + +- Added "doc" target to fs/devfs/Makefile + +- Added "v4l" directory for video4linux devices + +- Replaced call to in with call to + + +- Moved registration for sr and sg drivers from detect() to attach() + methods + +- Register entries in and unregister in + +- Work around IDE driver treating CD-ROM as gendisk + +- Use instead of in rc.devfs + +- Updated ToDo list + +- Removed "oops-on-panic" boot option: now always Oops +=============================================================================== +Changes for patch v105 + +- Unregister SCSI host from in + Thanks to Zoltán Böszörményi + +- Don't save /dev/log in rc.devfs + +- Ported to kernel 2.3.4-pre1 +=============================================================================== +Changes for patch v106 + +- Fixed silly typo in drivers/scsi/st.c + +- Improved debugging in +=============================================================================== +Changes for patch v107 + +- Added "diunlink" and "nokmod" boot options + +- Removed superfluous warning message in +=============================================================================== +Changes for patch v108 + +- Remove entries when unloading sound module +=============================================================================== +Changes for patch v109 + +- Ported to kernel 2.3.6-pre2 +=============================================================================== +Changes for patch v110 + +- Took account of change to +=============================================================================== +Changes for patch v111 + +- Created separate event queue for each mounted devfs + +- Removed + +- Created new ioctl()s for devfsd + +- Incremented devfsd protocol revision to 3 + +- Fixed bug when re-creating directories: contents were lost + +- Block access to inodes until devfsd updates permissions +=============================================================================== +Changes for patch v112 + +- Modified patch so it applies against 2.3.5 and 2.3.6 + +- Updated an email address in ChangeLog + +- Do not automatically change ownership/protection of /dev/tty + +- Updated sample modules.conf + +- Switched to sending process uid/gid to devfsd + +- Renamed to + +- Added DEVFSD_NOTIFY_LOOKUP event + +- Added DEVFSD_NOTIFY_CHANGE event + +- Added DEVFSD_NOTIFY_CREATE event + +- Incremented devfsd protocol revision to 4 + +- Moved kernel-specific stuff to include/linux/devfs_fs_kernel.h +=============================================================================== +Changes for patch v113 + +- Ported to kernel 2.3.9 + +- Restricted permissions on some block devices +=============================================================================== +Changes for patch v114 + +- Added support for /dev/netlink + Thanks to Dennis Hou + +- Return EISDIR rather than EINVAL for read(2) on directories + +- Ported to kernel 2.3.10 +=============================================================================== +Changes for patch v115 + +- Added support for all remaining character devices + Thanks to Dennis Hou + +- Cleaned up netlink support +=============================================================================== +Changes for patch v116 + +- Added support for /dev/parport%d + Thanks to Tim Waugh + +- Fixed parallel port ATAPI tape driver + +- Fixed Atari SLM laser printer driver +=============================================================================== +Changes for patch v117 + +- Added support for COSA card + Thanks to Dennis Hou + +- Fixed drivers/char/ppdev.c: missing #include + +- Fixed drivers/char/ftape/zftape/zftape-init.c + Thanks to Vladimir Popov +=============================================================================== +Changes for patch v118 + +- Ported to kernel 2.3.15-pre3 + +- Fixed bug in loop driver + +- Unregister /dev/lp%d entries in drivers/char/lp.c + Thanks to Maciej W. Rozycki +=============================================================================== +Changes for patch v119 + +- Ported to kernel 2.3.16 +=============================================================================== +Changes for patch v120 + +- Fixed bug in drivers/scsi/scsi.c + +- Added /dev/ppp + Thanks to Dennis Hou + +- Ported to kernel 2.3.17 +=============================================================================== +Changes for patch v121 + +- Fixed bug in drivers/block/loop.c + +- Ported to kernel 2.3.18 +=============================================================================== +Changes for patch v122 + +- Ported to kernel 2.3.19 +=============================================================================== +Changes for patch v123 + +- Ported to kernel 2.3.20 +=============================================================================== +Changes for patch v124 + +- Ported to kernel 2.3.21 +=============================================================================== +Changes for patch v125 + +- Created , , + and + Added <> parameter to , , + and + Work sponsored by SGI + +- Fixed apparent bug in COSA driver + +- Re-instated "scsihosts=" boot option +=============================================================================== +Changes for patch v126 + +- Always create /dev/pts if CONFIG_UNIX98_PTYS=y + +- Fixed call to in drivers/block/ide-disk.c + Thanks to Dennis Hou + +- Allow multiple unregistrations + +- Created /dev/scsi hierarchy + Work sponsored by SGI +=============================================================================== +Changes for patch v127 + +Work sponsored by SGI + +- No longer disable devpts if devfs enabled (caveat emptor) + +- Added flags array to struct gendisk and removed code from + drivers/scsi/sd.c + +- Created /dev/discs hierarchy +=============================================================================== +Changes for patch v128 + +Work sponsored by SGI + +- Created /dev/cdroms hierarchy +=============================================================================== +Changes for patch v129 + +Work sponsored by SGI + +- Removed compatibility entries for sound devices + +- Removed compatibility entries for printer devices + +- Removed compatibility entries for video4linux devices + +- Removed compatibility entries for parallel port devices + +- Removed compatibility entries for frame buffer devices +=============================================================================== +Changes for patch v130 + +Work sponsored by SGI + +- Added major and minor number to devfsd protocol + +- Incremented devfsd protocol revision to 5 + +- Removed compatibility entries for SoundBlaster CD-ROMs + +- Removed compatibility entries for netlink devices + +- Removed compatibility entries for SCSI generic devices + +- Removed compatibility entries for SCSI tape devices +=============================================================================== +Changes for patch v131 + +Work sponsored by SGI + +- Support info pointer for all devfs entry types + +- Added <> parameter to and + +- Removed /dev/st hierarchy + +- Removed /dev/sg hierarchy + +- Removed compatibility entries for loop devices + +- Removed compatibility entries for IDE tape devices + +- Removed compatibility entries for SCSI CD-ROMs + +- Removed /dev/sr hierarchy +=============================================================================== +Changes for patch v132 + +Work sponsored by SGI + +- Removed compatibility entries for floppy devices + +- Removed compatibility entries for RAMDISCs + +- Removed compatibility entries for meta-devices + +- Removed compatibility entries for SCSI discs + +- Created + +- Removed /dev/sd hierarchy + +- Support "../" when searching devfs namespace + +- Created /dev/ide/host* hierarchy + +- Supported IDE hard discs in /dev/ide/host* hierarchy + +- Removed compatibility entries for IDE discs + +- Removed /dev/ide/hd hierarchy + +- Supported IDE CD-ROMs in /dev/ide/host* hierarchy + +- Removed compatibility entries for IDE CD-ROMs + +- Removed /dev/ide/cd hierarchy +=============================================================================== +Changes for patch v133 + +Work sponsored by SGI + +- Created + +- Fixed bug in fs/partitions/check.c when rescanning +=============================================================================== +Changes for patch v134 + +Work sponsored by SGI + +- Removed /dev/sd, /dev/sr, /dev/st and /dev/sg directories + +- Removed /dev/ide/hd directory + +- Exported + +- Created and /dev/tapes hierarchy + +- Removed /dev/ide/mt hierarchy + +- Removed /dev/ide/fd hierarchy + +- Ported to kernel 2.3.25 +=============================================================================== +Changes for patch v135 + +Work sponsored by SGI + +- Removed compatibility entries for virtual console capture devices + +- Removed unused + +- Removed compatibility entries for serial devices + +- Removed compatibility entries for console devices + +- Do not hide entries from devfsd or children + +- Removed DEVFS_FL_TTY_COMPAT flag + +- Removed "nottycompat" boot option + +- Removed +=============================================================================== +Changes for patch v136 + +Work sponsored by SGI + +- Moved BSD pty devices to /dev/pty + +- Added DEVFS_FL_WAIT flag +=============================================================================== +Changes for patch v137 + +Work sponsored by SGI + +- Really fixed bug in fs/partitions/check.c when rescanning + +- Support new "disc" naming scheme in + +- Allow NULL fops in + +- Removed redundant name functions in SCSI disc and IDE drivers +=============================================================================== +Changes for patch v138 + +Work sponsored by SGI + +- Fixed old bugs in drivers/block/paride/pt.c, drivers/char/tpqic02.c, + drivers/net/wan/cosa.c and drivers/scsi/scsi.c + Thanks to Sergey Kubushin + +- Fall back to major table if NULL fops given to +=============================================================================== +Changes for patch v139 + +Work sponsored by SGI + +- Corrected and moved and declarations + from arch/alpha/kernel/osf_sys.c to include/linux/fs.h + +- Removed name function from struct gendisk + +- Updated devfs FAQ +=============================================================================== +Changes for patch v140 + +Work sponsored by SGI + +- Ported to kernel 2.3.27 +=============================================================================== +Changes for patch v141 + +Work sponsored by SGI + +- Bug fix in arch/m68k/atari/joystick.c + +- Moved ISDN and capi devices to /dev/isdn +=============================================================================== +Changes for patch v142 + +Work sponsored by SGI + +- Bug fix in drivers/block/ide-probe.c (patch confusion) +=============================================================================== +Changes for patch v143 + +Work sponsored by SGI + +- Bug fix in drivers/block/blkpg.c:partition_name() +=============================================================================== +Changes for patch v144 + +Work sponsored by SGI + +- Ported to kernel 2.3.29 + +- Removed calls to from cdu31a, cm206, mcd and mcdx + CD-ROM drivers: generic driver handles this now + +- Moved joystick devices to /dev/joysticks +=============================================================================== +Changes for patch v145 + +Work sponsored by SGI + +- Ported to kernel 2.3.30-pre3 + +- Register whole-disc entry even for invalid partition tables + +- Fixed bug in mounting root FS when initrd enabled + +- Fixed device entry leak with IDE CD-ROMs + +- Fixed compile problem with drivers/isdn/isdn_common.c + +- Moved COSA devices to /dev/cosa + +- Support fifos when unregistering + +- Created and used in many drivers + +- Moved Coda devices to /dev/coda + +- Moved parallel port IDE tapes to /dev/pt + +- Moved parallel port IDE generic devices to /dev/pg +=============================================================================== +Changes for patch v146 + +Work sponsored by SGI + +- Removed obsolete DEVFS_FL_COMPAT and DEVFS_FL_TOLERANT flags + +- Fixed compile problem with fs/coda/psdev.c + +- Reinstate change to in + drivers/block/ide-probe.c now that fs/isofs/inode.c is fixed + +- Switched to in drivers/block/floppy.c, + drivers/scsi/sr.c and drivers/block/md.c + +- Moved DAC960 devices to /dev/dac960 +=============================================================================== +Changes for patch v147 + +Work sponsored by SGI + +- Ported to kernel 2.3.32-pre4 +=============================================================================== +Changes for patch v148 + +Work sponsored by SGI + +- Removed kmod support: use devfsd instead + +- Moved miscellaneous character devices to /dev/misc +=============================================================================== +Changes for patch v149 + +Work sponsored by SGI + +- Ensure include/linux/joystick.h is OK for user-space + +- Improved debugging in + +- Ensure dentries created by devfsd will be cleaned up +=============================================================================== +Changes for patch v150 + +Work sponsored by SGI + +- Ported to kernel 2.3.34 +=============================================================================== +Changes for patch v151 + +Work sponsored by SGI + +- Ported to kernel 2.3.35-pre1 + +- Created +=============================================================================== +Changes for patch v152 + +Work sponsored by SGI + +- Updated sample modules.conf + +- Ported to kernel 2.3.36-pre1 +=============================================================================== +Changes for patch v153 + +Work sponsored by SGI + +- Ported to kernel 2.3.42 + +- Removed +=============================================================================== +Changes for patch v154 + +Work sponsored by SGI + +- Took account of device number changes for /dev/fb* +=============================================================================== +Changes for patch v155 + +Work sponsored by SGI + +- Ported to kernel 2.3.43-pre8 + +- Moved /dev/tty0 to /dev/vc/0 + +- Moved sequence number formatting from <_tty_make_name> to drivers +=============================================================================== +Changes for patch v156 + +Work sponsored by SGI + +- Fixed breakage in drivers/scsi/sd.c due to recent SCSI changes +=============================================================================== +Changes for patch v157 + +Work sponsored by SGI + +- Ported to kernel 2.3.45 +=============================================================================== +Changes for patch v158 + +Work sponsored by SGI + +- Ported to kernel 2.3.46-pre2 +=============================================================================== +Changes for patch v159 + +Work sponsored by SGI + +- Fixed drivers/block/md.c + Thanks to Mike Galbraith + +- Documentation fixes + +- Moved device registration from to + Thanks to Tim Waugh +=============================================================================== +Changes for patch v160 + +Work sponsored by SGI + +- Fixed drivers/char/joystick/joystick.c + Thanks to Vojtech Pavlik + +- Documentation updates + +- Fixed arch/i386/kernel/mtrr.c if procfs and devfs not enabled + +- Fixed drivers/char/stallion.c +=============================================================================== +Changes for patch v161 + +Work sponsored by SGI + +- Remove /dev/ide when ide-mod is unloaded + +- Fixed bug in drivers/block/ide-probe.c when secondary but no primary + +- Added DEVFS_FL_NO_PERSISTENCE flag + +- Used new DEVFS_FL_NO_PERSISTENCE flag for Unix98 pty slaves + +- Removed unnecessary call to in + + +- Only set auto-ownership for /dev/pty/s* +=============================================================================== +Changes for patch v162 + +Work sponsored by SGI + +- Set inode->i_size to correct size for symlinks + Thanks to Jeremy Fitzhardinge + +- Only give lookup() method to directories to comply with new VFS + assumptions + +- Remove unnecessary tests in symlink methods + +- Don't kill existing block ops in + +- Restore auto-ownership for /dev/pty/m* +=============================================================================== +Changes for patch v163 + +Work sponsored by SGI + +- Don't create missing directories in + +- Removed Documentation/filesystems/devfs/mk-devlinks + +- Updated Documentation/filesystems/devfs/README +=============================================================================== +Changes for patch v164 + +Work sponsored by SGI + +- Fixed CONFIG_DEVFS breakage in drivers/char/serial.c introduced in + linux-2.3.99-pre6-7 +=============================================================================== +Changes for patch v165 + +Work sponsored by SGI + +- Ported to kernel 2.3.99-pre6 +=============================================================================== +Changes for patch v166 + +Work sponsored by SGI + +- Added CONFIG_DEVFS_MOUNT +=============================================================================== +Changes for patch v167 + +Work sponsored by SGI + +- Updated Documentation/filesystems/devfs/README + +- Updated sample modules.conf +=============================================================================== +Changes for patch v168 + +Work sponsored by SGI + +- Disabled multi-mount capability (use VFS bindings instead) + +- Updated README from master HTML file +=============================================================================== +Changes for patch v169 + +Work sponsored by SGI + +- Removed multi-mount code + +- Removed compatibility macros: VFS has changed too much +=============================================================================== +Changes for patch v170 + +Work sponsored by SGI + +- Updated README from master HTML file + +- Merged devfs inode into devfs entry +=============================================================================== +Changes for patch v171 + +Work sponsored by SGI + +- Updated sample modules.conf + +- Removed dead code in which used to call + + +- Ported to kernel 2.4.0-test2-pre3 +=============================================================================== +Changes for patch v172 + +Work sponsored by SGI + +- Changed interface to + +- Changed interface to +=============================================================================== +Changes for patch v173 + +Work sponsored by SGI + +- Simplified interface to + +- Simplified interface to + +- Simplified interface to +=============================================================================== +Changes for patch v174 + +Work sponsored by SGI + +- Updated README from master HTML file +=============================================================================== +Changes for patch v175 + +Work sponsored by SGI + +- DocBook update for fs/devfs/base.c + Thanks to Tim Waugh + +- Removed stale fs/tunnel.c (was never used or completed) +=============================================================================== +Changes for patch v176 + +Work sponsored by SGI + +- Updated ToDo list + +- Removed sample modules.conf: now distributed with devfsd + +- Updated README from master HTML file + +- Ported to kernel 2.4.0-test3-pre4 (which had devfs-patch-v174) +=============================================================================== +Changes for patch v177 + +- Updated README from master HTML file + +- Documentation cleanups + +- Ensure terminates string for root entry + Thanks to Tim Jansen + +- Exported to modules + +- Make send events to devfsd + +- Cleaned up option processing in + +- Fixed bugs in handling symlinks: could leak or cause Oops + +- Cleaned up directory handling by separating fops + Thanks to Alexander Viro +=============================================================================== +Changes for patch v178 + +- Fixed handling of inverted options in +=============================================================================== +Changes for patch v179 + +- Adjusted to account for fix +=============================================================================== +Changes for patch v180 + +- Fixed !CONFIG_DEVFS_FS stub declaration of +=============================================================================== +Changes for patch v181 + +- Answered question posed by Al Viro and removed his comments from + +- Moved setting of registered flag after other fields are changed + +- Fixed race between and + +- Global VFS changes added bogus BKL to devfsd_close(): removed + +- Widened locking in and + +- Replaced stack usage with kmalloc + +- Simplified locking in and fixed memory leak +=============================================================================== +Changes for patch v182 + +- Created and + +- Removed broken devnum allocation and use + +- Fixed old devnum leak by calling new + +- Created + +- Fixed number leak for /dev/cdroms/cdrom%d + +- Fixed number leak for /dev/discs/disc%d +=============================================================================== +Changes for patch v183 + +- Fixed bug in which could hang boot process +=============================================================================== +Changes for patch v184 + +- Documentation typo fix for fs/devfs/util.c + +- Fixed drivers/char/stallion.c for devfs + +- Added DEVFSD_NOTIFY_DELETE event + +- Updated README from master HTML file + +- Removed #include from fs/devfs/base.c +=============================================================================== +Changes for patch v185 + +- Made and in fs/devfs/util.c + private + +- Fixed inode table races by removing it and using inode->u.generic_ip + instead + +- Moved into + +- Moved into +=============================================================================== +Changes for patch v186 + +- Fixed race in for uni-processor + +- Updated README from master HTML file +=============================================================================== +Changes for patch v187 + +- Fixed drivers/char/stallion.c for devfs + +- Fixed drivers/char/rocket.c for devfs + +- Fixed bug in : limited to 128 numbers +=============================================================================== +Changes for patch v188 + +- Updated major masks in fs/devfs/util.c up to Linus' "no new majors" + proclamation. Block: were 126 now 122 free, char: were 26 now 19 free + +- Updated README from master HTML file + +- Removed remnant of multi-mount support in + +- Removed unused DEVFS_FL_SHOW_UNREG flag +=============================================================================== +Changes for patch v189 + +- Removed nlink field from struct devfs_inode + +- Removed auto-ownership for /dev/pty/* (BSD ptys) and used + DEVFS_FL_CURRENT_OWNER|DEVFS_FL_NO_PERSISTENCE for /dev/pty/s* (just + like Unix98 pty slaves) and made /dev/pty/m* rw-rw-rw- access +=============================================================================== +Changes for patch v190 + +- Updated README from master HTML file + +- Replaced BKL with global rwsem to protect symlink data (quick and + dirty hack) +=============================================================================== +Changes for patch v191 + +- Replaced global rwsem for symlink with per-link refcount +=============================================================================== +Changes for patch v192 + +- Removed unnecessary #ifdef CONFIG_DEVFS_FS from arch/i386/kernel/mtrr.c + +- Ported to kernel 2.4.10-pre11 + +- Set inode->i_mapping->a_ops for block nodes in +=============================================================================== +Changes for patch v193 + +- Went back to global rwsem for symlinks (refcount scheme no good) +=============================================================================== +Changes for patch v194 + +- Fixed overrun in by removing function (not needed) + +- Updated README from master HTML file +=============================================================================== +Changes for patch v195 + +- Fixed buffer underrun in + +- Moved down_read() from to +=============================================================================== +Changes for patch v196 + +- Fixed race in when setting event mask + Thanks to Kari Hurtta + +- Avoid deadlock in by using temporary buffer +=============================================================================== +Changes for patch v197 + +- First release of new locking code for devfs core (v1.0) + +- Fixed bug in drivers/cdrom/cdrom.c +=============================================================================== +Changes for patch v198 + +- Discard temporary buffer, now use "%s" for dentry names + +- Don't generate path in : use fake entry instead + +- Use "existing" directory in <_devfs_make_parent_for_leaf> + +- Use slab cache rather than fixed buffer for devfsd events +=============================================================================== +Changes for patch v199 + +- Removed obsolete usage of DEVFS_FL_NO_PERSISTENCE + +- Send DEVFSD_NOTIFY_REGISTERED events in + +- Fixed locking bug in due to typo + +- Do not send CREATE, CHANGE, ASYNC_OPEN or DELETE events from devfsd + or children +=============================================================================== +Changes for patch v200 + +- Ported to kernel 2.5.1-pre2 +=============================================================================== +Changes for patch v201 + +- Fixed bug in : was dereferencing freed pointer +=============================================================================== +Changes for patch v202 + +- Fixed bug in : was dereferencing freed pointer + +- Added process group check for devfsd privileges +=============================================================================== +Changes for patch v203 + +- Use SLAB_ATOMIC in from +=============================================================================== +Changes for patch v204 + +- Removed long obsolete rc.devfs + +- Return old entry in for 2.4.x kernels + +- Updated README from master HTML file + +- Increment refcount on module in + +- Created and exported + +- Increment refcount on module in + +- Created and used where needed to fix races + +- Added clarifying comments in response to preliminary EMC code review + +- Added poisoning to + +- Improved debugging messages + +- Fixed unregister bugs in drivers/md/lvm-fs.c +=============================================================================== +Changes for patch v205 + +- Corrected (made useful) debugging message in + +- Moved in to + +- Fixed drivers/md/lvm-fs.c to create "lvm" entry + +- Added magic number to guard against scribbling drivers + +- Only return old entry in if a directory + +- Defined macros for error and debug messages + +- Updated README from master HTML file +=============================================================================== +Changes for patch v206 + +- Added support for multiple Compaq cpqarray controllers + +- Fixed (rare, old) race in +=============================================================================== +Changes for patch v207 + +- Fixed deadlock bug in + +- Tag VFS deletable in if handle ignored + +- Updated README from master HTML file +=============================================================================== +Changes for patch v208 + +- Added KERN_* to remaining messages + +- Cleaned up declaration of + +- Updated README from master HTML file +=============================================================================== +Changes for patch v209 + +- Updated README from master HTML file + +- Removed silently introduced calls to lock_kernel() and + unlock_kernel() due to recent VFS locking changes. BKL isn't + required in devfs + +- Changed to allow later additions if not yet empty + +- Added calls to in drivers/block/blkpc.c + and + +- Fixed bug in : was clearing beyond + bitfield + +- Fixed bitfield data type for + +- Made major bitfield type and initialiser 64 bit safe +=============================================================================== +Changes for patch v210 + +- Updated fs/devfs/util.c to fix shift warning on 64 bit machines + Thanks to Anton Blanchard + +- Updated README from master HTML file +=============================================================================== +Changes for patch v211 + +- Do not put miscellaneous character devices in /dev/misc if they + specify their own directory (i.e. contain a '/' character) + +- Copied macro for error messages from fs/devfs/base.c to + fs/devfs/util.c and made use of this macro + +- Removed 2.4.x compatibility code from fs/devfs/base.c +=============================================================================== +Changes for patch v212 + +- Added BKL to because drivers still need it +=============================================================================== +Changes for patch v213 + +- Protected and + from changing directory contents +=============================================================================== +Changes for patch v214 + +- Switched to ISO C structure field initialisers + +- Switch to set_current_state() and move before add_wait_queue() + +- Updated README from master HTML file + +- Fixed devfs entry leak in when *readdir fails +=============================================================================== +Changes for patch v215 + +- Created + +- Switched many functions from to + + +- Switched many functions from to +=============================================================================== +Changes for patch v216 + +- Switched arch/ia64/sn/io/hcl.c from to + + +- Removed deprecated +=============================================================================== +Changes for patch v217 + +- Exported and to modules + +- Updated README from master HTML file + +- Fixed module unload race in +=============================================================================== +Changes for patch v218 + +- Removed DEVFS_FL_AUTO_OWNER flag + +- Switched lingering structure field initialiser to ISO C + +- Added locking when setting/clearing flags + +- Documentation fix in fs/devfs/util.c diff --git a/trunk/Documentation/filesystems/devfs/README b/trunk/Documentation/filesystems/devfs/README new file mode 100644 index 000000000000..aabfba24bc2e --- /dev/null +++ b/trunk/Documentation/filesystems/devfs/README @@ -0,0 +1,1959 @@ +Devfs (Device File System) FAQ + + +Linux Devfs (Device File System) FAQ +Richard Gooch +20-AUG-2002 + + +Document languages: + + + + + + + +----------------------------------------------------------------------------- + +NOTE: the master copy of this document is available online at: + +http://www.atnf.csiro.au/~rgooch/linux/docs/devfs.html +and looks much better than the text version distributed with the +kernel sources. A mirror site is available at: + +http://www.ras.ucalgary.ca/~rgooch/linux/docs/devfs.html + +There is also an optional daemon that may be used with devfs. You can +find out more about it at: + +http://www.atnf.csiro.au/~rgooch/linux/ + +A mailing list is available which you may subscribe to. Send +email +to majordomo@oss.sgi.com with the following line in the +body of the message: +subscribe devfs +To unsubscribe, send the message body: +unsubscribe devfs +instead. The list is archived at + +http://oss.sgi.com/projects/devfs/archive/. + +----------------------------------------------------------------------------- + +Contents + + +What is it? + +Why do it? + +Who else does it? + +How it works + +Operational issues (essential reading) + +Instructions for the impatient +Permissions persistence across reboots +Dealing with drivers without devfs support +All the way with Devfs +Other Issues +Kernel Naming Scheme +Devfsd Naming Scheme +Old Compatibility Names +SCSI Host Probing Issues + + + +Device drivers currently ported + +Allocation of Device Numbers + +Questions and Answers + +Making things work +Alternatives to devfs +What I don't like about devfs +How to report bugs +Strange kernel messages +Compilation problems with devfsd + + +Other resources + +Translations of this document + + +----------------------------------------------------------------------------- + + +What is it? + +Devfs is an alternative to "real" character and block special devices +on your root filesystem. Kernel device drivers can register devices by +name rather than major and minor numbers. These devices will appear in +devfs automatically, with whatever default ownership and +protection the driver specified. A daemon (devfsd) can be used to +override these defaults. Devfs has been in the kernel since 2.3.46. + +NOTE that devfs is entirely optional. If you prefer the old +disc-based device nodes, then simply leave CONFIG_DEVFS_FS=n (the +default). In this case, nothing will change. ALSO NOTE that if you do +enable devfs, the defaults are such that full compatibility is +maintained with the old devices names. + +There are two aspects to devfs: one is the underlying device +namespace, which is a namespace just like any mounted filesystem. The +other aspect is the filesystem code which provides a view of the +device namespace. The reason I make a distinction is because devfs +can be mounted many times, with each mount showing the same device +namespace. Changes made are global to all mounted devfs filesystems. +Also, because the devfs namespace exists without any devfs mounts, you +can easily mount the root filesystem by referring to an entry in the +devfs namespace. + + +The cost of devfs is a small increase in kernel code size and memory +usage. About 7 pages of code (some of that in __init sections) and 72 +bytes for each entry in the namespace. A modest system has only a +couple of hundred device entries, so this costs a few more +pages. Compare this with the suggestion to put /dev on a ramdisc. + +On a typical machine, the cost is under 0.2 percent. On a modest +system with 64 MBytes of RAM, the cost is under 0.1 percent. The +accusations of "bloatware" levelled at devfs are not justified. + +----------------------------------------------------------------------------- + + +Why do it? + +There are several problems that devfs addresses. Some of these +problems are more serious than others (depending on your point of +view), and some can be solved without devfs. However, the totality of +these problems really calls out for devfs. + +The choice is a patchwork of inefficient user space solutions, which +are complex and likely to be fragile, or to use a simple and efficient +devfs which is robust. + +There have been many counter-proposals to devfs, all seeking to +provide some of the benefits without actually implementing devfs. So +far there has been an absence of code and no proposed alternative has +been able to provide all the features that devfs does. Further, +alternative proposals require far more complexity in user-space (and +still deliver less functionality than devfs). Some people have the +mantra of reducing "kernel bloat", but don't consider the effects on +user-space. + +A good solution limits the total complexity of kernel-space and +user-space. + + +Major&minor allocation + +The existing scheme requires the allocation of major and minor device +numbers for each and every device. This means that a central +co-ordinating authority is required to issue these device numbers +(unless you're developing a "private" device driver), in order to +preserve uniqueness. Devfs shifts the burden to a namespace. This may +not seem like a huge benefit, but actually it is. Since driver authors +will naturally choose a device name which reflects the functionality +of the device, there is far less potential for namespace conflict. +Solving this requires a kernel change. + +/dev management + +Because you currently access devices through device nodes, these must +be created by the system administrator. For standard devices you can +usually find a MAKEDEV programme which creates all these (hundreds!) +of nodes. This means that changes in the kernel must be reflected by +changes in the MAKEDEV programme, or else the system administrator +creates device nodes by hand. + +The basic problem is that there are two separate databases of +major and minor numbers. One is in the kernel and one is in /dev (or +in a MAKEDEV programme, if you want to look at it that way). This is +duplication of information, which is not good practice. +Solving this requires a kernel change. + +/dev growth + +A typical /dev has over 1200 nodes! Most of these devices simply don't +exist because the hardware is not available. A huge /dev increases the +time to access devices (I'm just referring to the dentry lookup times +and the time taken to read inodes off disc: the next subsection shows +some more horrors). + +An example of how big /dev can grow is if we consider SCSI devices: + +host 6 bits (say up to 64 hosts on a really big machine) +channel 4 bits (say up to 16 SCSI buses per host) +id 4 bits +lun 3 bits +partition 6 bits +TOTAL 23 bits + + +This requires 8 Mega (1024*1024) inodes if we want to store all +possible device nodes. Even if we scrap everything but id,partition +and assume a single host adapter with a single SCSI bus and only one +logical unit per SCSI target (id), that's still 10 bits or 1024 +inodes. Each VFS inode takes around 256 bytes (kernel 2.1.78), so +that's 256 kBytes of inode storage on disc (assuming real inodes take +a similar amount of space as VFS inodes). This is actually not so bad, +because disc is cheap these days. Embedded systems would care about +256 kBytes of /dev inodes, but you could argue that embedded systems +would have hand-tuned /dev directories. I've had to do just that on my +embedded systems, but I would rather just leave it to devfs. + +Another issue is the time taken to lookup an inode when first +referenced. Not only does this take time in scanning through a list in +memory, but also the seek times to read the inodes off disc. +This could be solved in user-space using a clever programme which +scanned the kernel logs and deleted /dev entries which are not +available and created them when they were available. This programme +would need to be run every time a new module was loaded, which would +slow things down a lot. + +There is an existing programme called scsidev which will automatically +create device nodes for SCSI devices. It can do this by scanning files +in /proc/scsi. Unfortunately, to extend this idea to other device +nodes would require significant modifications to existing drivers (so +they too would provide information in /proc). This is a non-trivial +change (I should know: devfs has had to do something similar). Once +you go to this much effort, you may as well use devfs itself (which +also provides this information). Furthermore, such a system would +likely be implemented in an ad-hoc fashion, as different drivers will +provide their information in different ways. + +Devfs is much cleaner, because it (naturally) has a uniform mechanism +to provide this information: the device nodes themselves! + + +Node to driver file_operations translation + +There is an important difference between the way disc-based character +and block nodes and devfs entries make the connection between an entry +in /dev and the actual device driver. + +With the current 8 bit major and minor numbers the connection between +disc-based c&b nodes and per-major drivers is done through a +fixed-length table of 128 entries. The various filesystem types set +the inode operations for c&b nodes to {chr,blk}dev_inode_operations, +so when a device is opened a few quick levels of indirection bring us +to the driver file_operations. + +For miscellaneous character devices a second step is required: there +is a scan for the driver entry with the same minor number as the file +that was opened, and the appropriate minor open method is called. This +scanning is done *every time* you open a device node. Potentially, you +may be searching through dozens of misc. entries before you find your +open method. While not an enormous performance overhead, this does +seem pointless. + +Linux *must* move beyond the 8 bit major and minor barrier, +somehow. If we simply increase each to 16 bits, then the indexing +scheme used for major driver lookup becomes untenable, because the +major tables (one each for character and block devices) would need to +be 64 k entries long (512 kBytes on x86, 1 MByte for 64 bit +systems). So we would have to use a scheme like that used for +miscellaneous character devices, which means the search time goes up +linearly with the average number of major device drivers on your +system. Not all "devices" are hardware, some are higher-level drivers +like KGI, so you can get more "devices" without adding hardware +You can improve this by creating an ordered (balanced:-) +binary tree, in which case your search time becomes log(N). +Alternatively, you can use hashing to speed up the search. +But why do that search at all if you don't have to? Once again, it +seems pointless. + +Note that devfs doesn't use the major&minor system. For devfs +entries, the connection is done when you lookup the /dev entry. When +devfs_register() is called, an internal table is appended which has +the entry name and the file_operations. If the dentry cache doesn't +have the /dev entry already, this internal table is scanned to get the +file_operations, and an inode is created. If the dentry cache already +has the entry, there is *no lookup time* (other than the dentry scan +itself, but we can't avoid that anyway, and besides Linux dentries +cream other OS's which don't have them:-). Furthermore, the number of +node entries in a devfs is only the number of available device +entries, not the number of *conceivable* entries. Even if you remove +unnecessary entries in a disc-based /dev, the number of conceivable +entries remains the same: you just limit yourself in order to save +space. + +Devfs provides a fast connection between a VFS node and the device +driver, in a scalable way. + +/dev as a system administration tool + +Right now /dev contains a list of conceivable devices, most of which I +don't have. Devfs only shows those devices available on my +system. This means that listing /dev is a handy way of checking what +devices are available. + +Major&minor size + +Existing major and minor numbers are limited to 8 bits each. This is +now a limiting factor for some drivers, particularly the SCSI disc +driver, which consumes a single major number. Only 16 discs are +supported, and each disc may have only 15 partitions. Maybe this isn't +a problem for you, but some of us are building huge Linux systems with +disc arrays. With devfs an arbitrary pointer can be associated with +each device entry, which can be used to give an effective 32 bit +device identifier (i.e. that's like having a 32 bit minor +number). Since this is private to the kernel, there are no C library +compatibility issues which you would have with increasing major and +minor number sizes. See the section on "Allocation of Device Numbers" +for details on maintaining compatibility with userspace. + +Solving this requires a kernel change. + +Since writing this, the kernel has been modified so that the SCSI disc +driver has more major numbers allocated to it and now supports up to +128 discs. Since these major numbers are non-contiguous (a result of +unplanned expansion), the implementation is a little more cumbersome +than originally. + +Just like the changes to IPv4 to fix impending limitations in the +address space, people find ways around the limitations. In the long +run, however, solutions like IPv6 or devfs can't be put off forever. + +Read-only root filesystem + +Having your device nodes on the root filesystem means that you can't +operate properly with a read-only root filesystem. This is because you +want to change ownerships and protections of tty devices. Existing +practice prevents you using a CD-ROM as your root filesystem for a +*real* system. Sure, you can boot off a CD-ROM, but you can't change +tty ownerships, so it's only good for installing. + +Also, you can't use a shared NFS root filesystem for a cluster of +discless Linux machines (having tty ownerships changed on a common +/dev is not good). Nor can you embed your root filesystem in a +ROM-FS. + +You can get around this by creating a RAMDISC at boot time, making +an ext2 filesystem in it, mounting it somewhere and copying the +contents of /dev into it, then unmounting it and mounting it over +/dev. + +A devfs is a cleaner way of solving this. + +Non-Unix root filesystem + +Non-Unix filesystems (such as NTFS) can't be used for a root +filesystem because they variously don't support character and block +special files or symbolic links. You can't have a separate disc-based +or RAMDISC-based filesystem mounted on /dev because you need device +nodes before you can mount these. Devfs can be mounted without any +device nodes. Devlinks won't work because symlinks aren't supported. +An alternative solution is to use initrd to mount a RAMDISC initial +root filesystem (which is populated with a minimal set of device +nodes), and then construct a new /dev in another RAMDISC, and finally +switch to your non-Unix root filesystem. This requires clever boot +scripts and a fragile and conceptually complex boot procedure. + +Devfs solves this in a robust and conceptually simple way. + +PTY security + +Current pseudo-tty (pty) devices are owned by root and read-writable +by everyone. The user of a pty-pair cannot change +ownership/protections without being suid-root. + +This could be solved with a secure user-space daemon which runs as +root and does the actual creation of pty-pairs. Such a daemon would +require modification to *every* programme that wants to use this new +mechanism. It also slows down creation of pty-pairs. + +An alternative is to create a new open_pty() syscall which does much +the same thing as the user-space daemon. Once again, this requires +modifications to pty-handling programmes. + +The devfs solution allows a device driver to "tag" certain device +files so that when an unopened device is opened, the ownerships are +changed to the current euid and egid of the opening process, and the +protections are changed to the default registered by the driver. When +the device is closed ownership is set back to root and protections are +set back to read-write for everybody. No programme need be changed. +The devpts filesystem provides this auto-ownership feature for Unix98 +ptys. It doesn't support old-style pty devices, nor does it have all +the other features of devfs. + +Intelligent device management + +Devfs implements a simple yet powerful protocol for communication with +a device management daemon (devfsd) which runs in user space. It is +possible to send a message (either synchronously or asynchronously) to +devfsd on any event, such as registration/unregistration of device +entries, opening and closing devices, looking up inodes, scanning +directories and more. This has many possibilities. Some of these are +already implemented. See: + + +http://www.atnf.csiro.au/~rgooch/linux/ + +Device entry registration events can be used by devfsd to change +permissions of newly-created device nodes. This is one mechanism to +control device permissions. + +Device entry registration/unregistration events can be used to run +programmes or scripts. This can be used to provide automatic mounting +of filesystems when a new block device media is inserted into the +drive. + +Asynchronous device open and close events can be used to implement +clever permissions management. For example, the default permissions on +/dev/dsp do not allow everybody to read from the device. This is +sensible, as you don't want some remote user recording what you say at +your console. However, the console user is also prevented from +recording. This behaviour is not desirable. With asynchronous device +open and close events, you can have devfsd run a programme or script +when console devices are opened to change the ownerships for *other* +device nodes (such as /dev/dsp). On closure, you can run a different +script to restore permissions. An advantage of this scheme over +modifying the C library tty handling is that this works even if your +programme crashes (how many times have you seen the utmp database with +lingering entries for non-existent logins?). + +Synchronous device open events can be used to perform intelligent +device access protections. Before the device driver open() method is +called, the daemon must first validate the open attempt, by running an +external programme or script. This is far more flexible than access +control lists, as access can be determined on the basis of other +system conditions instead of just the UID and GID. + +Inode lookup events can be used to authenticate module autoload +requests. Instead of using kmod directly, the event is sent to +devfsd which can implement an arbitrary authentication before loading +the module itself. + +Inode lookup events can also be used to construct arbitrary +namespaces, without having to resort to populating devfs with symlinks +to devices that don't exist. + +Speculative Device Scanning + +Consider an application (like cdparanoia) that wants to find all +CD-ROM devices on the system (SCSI, IDE and other types), whether or +not their respective modules are loaded. The application must +speculatively open certain device nodes (such as /dev/sr0 for the SCSI +CD-ROMs) in order to make sure the module is loaded. This requires +that all Linux distributions follow the standard device naming scheme +(last time I looked RedHat did things differently). Devfs solves the +naming problem. + +The same application also wants to see which devices are actually +available on the system. With the existing system it needs to read the +/dev directory and speculatively open each /dev/sr* device to +determine if the device exists or not. With a large /dev this is an +inefficient operation, especially if there are many /dev/sr* nodes. A +solution like scsidev could reduce the number of /dev/sr* entries (but +of course that also requires all that inefficient directory scanning). + +With devfs, the application can open the /dev/sr directory +(which triggers the module autoloading if required), and proceed to +read /dev/sr. Since only the available devices will have +entries, there are no inefficencies in directory scanning or device +openings. + +----------------------------------------------------------------------------- + +Who else does it? + +FreeBSD has a devfs implementation. Solaris and AIX each have a +pseudo-devfs (something akin to scsidev but for all devices, with some +unspecified kernel support). BeOS, Plan9 and QNX also have it. SGI's +IRIX 6.4 and above also have a device filesystem. + +While we shouldn't just automatically do something because others do +it, we should not ignore the work of others either. FreeBSD has a lot +of competent people working on it, so their opinion should not be +blithely ignored. + +----------------------------------------------------------------------------- + + +How it works + +Registering device entries + +For every entry (device node) in a devfs-based /dev a driver must call +devfs_register(). This adds the name of the device entry, the +file_operations structure pointer and a few other things to an +internal table. Device entries may be added and removed at any +time. When a device entry is registered, it automagically appears in +any mounted devfs'. + +Inode lookup + +When a lookup operation on an entry is performed and if there is no +driver information for that entry devfs will attempt to call +devfsd. If still no driver information can be found then a negative +dentry is yielded and the next stage operation will be called by the +VFS (such as create() or mknod() inode methods). If driver information +can be found, an inode is created (if one does not exist already) and +all is well. + +Manually creating device nodes + +The mknod() method allows you to create an ordinary named pipe in the +devfs, or you can create a character or block special inode if one +does not already exist. You may wish to create a character or block +special inode so that you can set permissions and ownership. Later, if +a device driver registers an entry with the same name, the +permissions, ownership and times are retained. This is how you can set +the protections on a device even before the driver is loaded. Once you +create an inode it appears in the directory listing. + +Unregistering device entries + +A device driver calls devfs_unregister() to unregister an entry. + +Chroot() gaols + +2.2.x kernels + +The semantics of inode creation are different when devfs is mounted +with the "explicit" option. Now, when a device entry is registered, it +will not appear until you use mknod() to create the device. It doesn't +matter if you mknod() before or after the device is registered with +devfs_register(). The purpose of this behaviour is to support +chroot(2) gaols, where you want to mount a minimal devfs inside the +gaol. Only the devices you specifically want to be available (through +your mknod() setup) will be accessible. + +2.4.x kernels + +As of kernel 2.3.99, the VFS has had the ability to rebind parts of +the global filesystem namespace into another part of the namespace. +This now works even at the leaf-node level, which means that +individual files and device nodes may be bound into other parts of the +namespace. This is like making links, but better, because it works +across filesystems (unlike hard links) and works through chroot() +gaols (unlike symbolic links). + +Because of these improvements to the VFS, the multi-mount capability +in devfs is no longer needed. The administrator may create a minimal +device tree inside a chroot(2) gaol by using VFS bindings. As this +provides most of the features of the devfs multi-mount capability, I +removed the multi-mount support code (after issuing an RFC). This +yielded code size reductions and simplifications. + +If you want to construct a minimal chroot() gaol, the following +command should suffice: + +mount --bind /dev/null /gaol/dev/null + + +Repeat for other device nodes you want to expose. Simple! + +----------------------------------------------------------------------------- + + +Operational issues + + +Instructions for the impatient + +Nobody likes reading documentation. People just want to get in there +and play. So this section tells you quickly the steps you need to take +to run with devfs mounted over /dev. Skip these steps and you will end +up with a nearly unbootable system. Subsequent sections describe the +issues in more detail, and discuss non-essential configuration +options. + +Devfsd +OK, if you're reading this, I assume you want to play with +devfs. First you should ensure that /usr/src/linux contains a +recent kernel source tree. Then you need to compile devfsd, the device +management daemon, available at + +http://www.atnf.csiro.au/~rgooch/linux/. +Because the kernel has a naming scheme +which is quite different from the old naming scheme, you need to +install devfsd so that software and configuration files that use the +old naming scheme will not break. + +Compile and install devfsd. You will be provided with a default +configuration file /etc/devfsd.conf which will provide +compatibility symlinks for the old naming scheme. Don't change this +config file unless you know what you're doing. Even if you think you +do know what you're doing, don't change it until you've followed all +the steps below and booted a devfs-enabled system and verified that it +works. + +Now edit your main system boot script so that devfsd is started at the +very beginning (before any filesystem +checks). /etc/rc.d/rc.sysinit is often the main boot script +on systems with SysV-style boot scripts. On systems with BSD-style +boot scripts it is often /etc/rc. Also check +/sbin/rc. + +NOTE that the line you put into the boot +script should be exactly: + +/sbin/devfsd /dev + +DO NOT use some special daemon-launching +programme, otherwise the boot script may not wait for devfsd to finish +initialising. + +System Libraries +There may still be some problems because of broken software making +assumptions about device names. In particular, some software does not +handle devices which are symbolic links. If you are running a libc 5 +based system, install libc 5.4.44 (if you have libc 5.4.46, go back to +libc 5.4.44, which is actually correct). If you are running a glibc +based system, make sure you have glibc 2.1.3 or later. + +/etc/securetty +PAM (Pluggable Authentication Modules) is supposed to be a flexible +mechanism for providing better user authentication and access to +services. Unfortunately, it's also fragile, complex and undocumented +(check out RedHat 6.1, and probably other distributions as well). PAM +has problems with symbolic links. Append the following lines to your +/etc/securetty file: + +vc/1 +vc/2 +vc/3 +vc/4 +vc/5 +vc/6 +vc/7 +vc/8 + +This will not weaken security. If you have a version of util-linux +earlier than 2.10.h, please upgrade to 2.10.h or later. If you +absolutely cannot upgrade, then also append the following lines to +your /etc/securetty file: + +1 +2 +3 +4 +5 +6 +7 +8 + +This may potentially weaken security by allowing root logins over the +network (a password is still required, though). However, since there +are problems with dealing with symlinks, I'm suspicious of the level +of security offered in any case. + +XFree86 +While not essential, it's probably a good idea to upgrade to XFree86 +4.0, as patches went in to make it more devfs-friendly. If you don't, +you'll probably need to apply the following patch to +/etc/security/console.perms so that ordinary users can run +startx. Note that not all distributions have this file (e.g. Debian), +so if it's not present, don't worry about it. + +--- /etc/security/console.perms.orig Sat Apr 17 16:26:47 1999 ++++ /etc/security/console.perms Fri Feb 25 23:53:55 2000 +@@ -14,7 +14,7 @@ + # man 5 console.perms + + # file classes -- these are regular expressions +-=tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9] ++=tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9] + + # device classes -- these are shell-style globs + =/dev/fd[0-1]* + +If the patch does not apply, then change the line: + +=tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9] + +with: + +=tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9] + + +Disable devpts +I've had a report of devpts mounted on /dev/pts not working +correctly. Since devfs will also manage /dev/pts, there is no +need to mount devpts as well. You should either edit your +/etc/fstab so devpts is not mounted, or disable devpts from +your kernel configuration. + +Unsupported drivers +Not all drivers have devfs support. If you depend on one of these +drivers, you will need to create a script or tarfile that you can use +at boot time to create device nodes as appropriate. There is a +section which describes this. Another +section lists the drivers which have +devfs support. + +/dev/mouse + +Many disributions configure /dev/mouse to be the mouse device +for XFree86 and GPM. I actually think this is a bad idea, because it +adds another level of indirection. When looking at a config file, if +you see /dev/mouse you're left wondering which mouse +is being referred to. Hence I recommend putting the actual mouse +device (for example /dev/psaux) into your +/etc/X11/XF86Config file (and similarly for the GPM +configuration file). + +Alternatively, use the same technique used for unsupported drivers +described above. + +The Kernel +Finally, you need to make sure devfs is compiled into your kernel. Set +CONFIG_EXPERIMENTAL=y, CONFIG_DEVFS_FS=y and CONFIG_DEVFS_MOUNT=y by +using favourite configuration tool (i.e. make config or +make xconfig) and then make clean and then recompile your kernel and +modules. At boot, devfs will be mounted onto /dev. + +If you encounter problems booting (for example if you forgot a +configuration step), you can pass devfs=nomount at the kernel +boot command line. This will prevent the kernel from mounting devfs at +boot time onto /dev. + +In general, a kernel built with CONFIG_DEVFS_FS=y but without mounting +devfs onto /dev is completely safe, and requires no +configuration changes. One exception to take note of is when +LABEL= directives are used in /etc/fstab. In this +case you will be unable to boot properly. This is because the +mount(8) programme uses /proc/partitions as part of +the volume label search process, and the device names it finds are not +available, because setting CONFIG_DEVFS_FS=y changes the names in +/proc/partitions, irrespective of whether devfs is mounted. + +Now you've finished all the steps required. You're now ready to boot +your shiny new kernel. Enjoy. + +Changing the configuration + +OK, you've now booted a devfs-enabled system, and everything works. +Now you may feel like changing the configuration (common targets are +/etc/fstab and /etc/devfsd.conf). Since you have a +system that works, if you make any changes and it doesn't work, you +now know that you only have to restore your configuration files to the +default and it will work again. + + +Permissions persistence across reboots + +If you don't use mknod(2) to create a device file, nor use chmod(2) or +chown(2) to change the ownerships/permissions, the inode ctime will +remain at 0 (the epoch, 12 am, 1-JAN-1970, GMT). Anything with a ctime +later than this has had it's ownership/permissions changed. Hence, a +simple script or programme may be used to tar up all changed inodes, +prior to shutdown. Although effective, many consider this approach a +kludge. + +A much better approach is to use devfsd to save and restore +permissions. It may be configured to record changes in permissions and +will save them in a database (in fact a directory tree), and restore +these upon boot. This is an efficient method and results in immediate +saving of current permissions (unlike the tar approach, which saves +permissions at some unspecified future time). + +The default configuration file supplied with devfsd has config entries +which you may uncomment to enable persistence management. + +If you decide to use the tar approach anyway, be aware that tar will +first unlink(2) an inode before creating a new device node. The +unlink(2) has the effect of breaking the connection between a devfs +entry and the device driver. If you use the "devfs=only" boot option, +you lose access to the device driver, requiring you to reload the +module. I consider this a bug in tar (there is no real need to +unlink(2) the inode first). + +Alternatively, you can use devfsd to provide more sophisticated +management of device permissions. You can use devfsd to store +permissions for whole groups of devices with a single configuration +entry, rather than the conventional single entry per device entry. + +Permissions database stored in mounted-over /dev + +If you wish to save and restore your device permissions into the +disc-based /dev while still mounting devfs onto /dev +you may do so. This requires a 2.4.x kernel (in fact, 2.3.99 or +later), which has the VFS binding facility. You need to do the +following to set this up: + + + +make sure the kernel does not mount devfs at boot time + + +make sure you have a correct /dev/console entry in your +root file-system (where your disc-based /dev lives) + +create the /dev-state directory + + +add the following lines near the very beginning of your boot +scripts: + +mount --bind /dev /dev-state +mount -t devfs none /dev +devfsd /dev + + + + +add the following lines to your /etc/devfsd.conf file: + +REGISTER ^pt[sy] IGNORE +CREATE ^pt[sy] IGNORE +CHANGE ^pt[sy] IGNORE +DELETE ^pt[sy] IGNORE +REGISTER .* COPY /dev-state/$devname $devpath +CREATE .* COPY $devpath /dev-state/$devname +CHANGE .* COPY $devpath /dev-state/$devname +DELETE .* CFUNCTION GLOBAL unlink /dev-state/$devname +RESTORE /dev-state + +Note that the sample devfsd.conf file contains these lines, +as well as other sample configurations you may find useful. See the +devfsd distribution + + +reboot. + + + + +Permissions database stored in normal directory + +If you are using an older kernel which doesn't support VFS binding, +then you won't be able to have the permissions database in a +mounted-over /dev. However, you can still use a regular +directory to store the database. The sample /etc/devfsd.conf +file above may still be used. You will need to create the +/dev-state directory prior to installing devfsd. If you have +old permissions in /dev, then just copy (or move) the device +nodes over to the new directory. + +Which method is better? + +The best method is to have the permissions database stored in the +mounted-over /dev. This is because you will not need to copy +device nodes over to /dev-state, and because it allows you to +switch between devfs and non-devfs kernels, without requiring you to +copy permissions between /dev-state (for devfs) and +/dev (for non-devfs). + + +Dealing with drivers without devfs support + +Currently, not all device drivers in the kernel have been modified to +use devfs. Device drivers which do not yet have devfs support will not +automagically appear in devfs. The simplest way to create device nodes +for these drivers is to unpack a tarfile containing the required +device nodes. You can do this in your boot scripts. All your drivers +will now work as before. + +Hopefully for most people devfs will have enough support so that they +can mount devfs directly over /dev without losing most functionality +(i.e. losing access to various devices). As of 22-JAN-1998 (devfs +patch version 10) I am now running this way. All the devices I have +are available in devfs, so I don't lose anything. + +WARNING: if your configuration requires the old-style device names +(i.e. /dev/hda1 or /dev/sda1), you must install devfsd and configure +it to maintain compatibility entries. It is almost certain that you +will require this. Note that the kernel creates a compatibility entry +for the root device, so you don't need initrd. + +Note that you no longer need to mount devpts if you use Unix98 PTYs, +as devfs can manage /dev/pts itself. This saves you some RAM, as you +don't need to compile and install devpts. Note that some versions of +glibc have a bug with Unix98 pty handling on devfs systems. Contact +the glibc maintainers for a fix. Glibc 2.1.3 has the fix. + +Note also that apart from editing /etc/fstab, other things will need +to be changed if you *don't* install devfsd. Some software (like the X +server) hard-wire device names in their source. It really is much +easier to install devfsd so that compatibility entries are created. +You can then slowly migrate your system to using the new device names +(for example, by starting with /etc/fstab), and then limiting the +compatibility entries that devfsd creates. + +IF YOU CONFIGURE TO MOUNT DEVFS AT BOOT, MAKE SURE YOU INSTALL DEVFSD +BEFORE YOU BOOT A DEVFS-ENABLED KERNEL! + +Now that devfs has gone into the 2.3.46 kernel, I'm getting a lot of +reports back. Many of these are because people are trying to run +without devfsd, and hence some things break. Please just run devfsd if +things break. I want to concentrate on real bugs rather than +misconfiguration problems at the moment. If people are willing to fix +bugs/false assumptions in other code (i.e. glibc, X server) and submit +that to the respective maintainers, that would be great. + + +All the way with Devfs + +The devfs kernel patch creates a rationalised device tree. As stated +above, if you want to keep using the old /dev naming scheme, +you just need to configure devfsd appopriately (see the man +page). People who prefer the old names can ignore this section. For +those of us who like the rationalised names and an uncluttered +/dev, read on. + +If you don't run devfsd, or don't enable compatibility entry +management, then you will have to configure your system to use the new +names. For example, you will then need to edit your +/etc/fstab to use the new disc naming scheme. If you want to +be able to boot non-devfs kernels, you will need compatibility +symlinks in the underlying disc-based /dev pointing back to +the old-style names for when you boot a kernel without devfs. + +You can selectively decide which devices you want compatibility +entries for. For example, you may only want compatibility entries for +BSD pseudo-terminal devices (otherwise you'll have to patch you C +library or use Unix98 ptys instead). It's just a matter of putting in +the correct regular expression into /dev/devfsd.conf. + +There are other choices of naming schemes that you may prefer. For +example, I don't use the kernel-supplied +names, because they are too verbose. A common misconception is +that the kernel-supplied names are meant to be used directly in +configuration files. This is not the case. They are designed to +reflect the layout of the devices attached and to provide easy +classification. + +If you like the kernel-supplied names, that's fine. If you don't then +you should be using devfsd to construct a namespace more to your +liking. Devfsd has built-in code to construct a +namespace that is both logical and easy to +manage. In essence, it creates a convenient abbreviation of the +kernel-supplied namespace. + +You are of course free to build your own namespace. Devfsd has all the +infrastructure required to make this easy for you. All you need do is +write a script. You can even write some C code and devfsd can load the +shared object as a callable extension. + + +Other Issues + +The init programme +Another thing to take note of is whether your init programme +creates a Unix socket /dev/telinit. Some versions of init +create /dev/telinit so that the telinit programme can +communicate with the init process. If you have such a system you need +to make sure that devfs is mounted over /dev *before* init +starts. In other words, you can't leave the mounting of devfs to +/etc/rc, since this is executed after init. Other +versions of init require a named pipe /dev/initctl +which must exist *before* init starts. Once again, you need to +mount devfs and then create the named pipe *before* init +starts. + +The default behaviour now is not to mount devfs onto /dev at +boot time for 2.3.x and later kernels. You can correct this with the +"devfs=mount" boot option. This solves any problems with init, +and also prevents the dreaded: + +Cannot open initial console + +message. For 2.2.x kernels where you need to apply the devfs patch, +the default is to mount. + +If you have automatic mounting of devfs onto /dev then you +may need to create /dev/initctl in your boot scripts. The +following lines should suffice: + +mknod /dev/initctl p +kill -SIGUSR1 1 # tell init that /dev/initctl now exists + +Alternatively, if you don't want the kernel to mount devfs onto +/dev then you could use the following procedure is a +guideline for how to get around /dev/initctl problems: + +# cd /sbin +# mv init init.real +# cat > init +#! /bin/sh +mount -n -t devfs none /dev +mknod /dev/initctl p +exec /sbin/init.real $* +[control-D] +# chmod a+x init + +Note that newer versions of init create /dev/initctl +automatically, so you don't have to worry about this. + +Module autoloading +You will need to configure devfsd to enable module +autoloading. The following lines should be placed in your +/etc/devfsd.conf file: + +LOOKUP .* MODLOAD + + +As of devfsd-v1.3.10, a generic /etc/modules.devfs +configuration file is installed, which is used by the MODLOAD +action. This should be sufficient for most configurations. If you +require further configuration, edit your /etc/modules.conf +file. The way module autoloading work with devfs is: + + +a process attempts to lookup a device node (e.g. /dev/fred) + + +if that device node does not exist, the full pathname is passed to +devfsd as a string + + +devfsd will pass the string to the modprobe programme (provided the +configuration line shown above is present), and specifies that +/etc/modules.devfs is the configuration file + + +/etc/modules.devfs includes /etc/modules.conf to +access local configurations + +modprobe will search it's configuration files, looking for an alias +that translates the pathname into a module name + + +the translated pathname is then used to load the module. + + +If you wanted a lookup of /dev/fred to load the +mymod module, you would require the following configuration +line in /etc/modules.conf: + +alias /dev/fred mymod + +The /etc/modules.devfs configuration file provides many such +aliases for standard device names. If you look closely at this file, +you will note that some modules require multiple alias configuration +lines. This is required to support module autoloading for old and new +device names. + +Mounting root off a devfs device +If you wish to mount root off a devfs device when you pass the +"devfs=only" boot option, then you need to pass in the +"root=" option to the kernel when booting. If you use +LILO, then you must have this in lilo.conf: + +append = "root=" + +Surprised? Yep, so was I. It turns out if you have (as most people +do): + +root = + + +then LILO will determine the device number of and will +write that device number into a special place in the kernel image +before starting the kernel, and the kernel will use that device number +to mount the root filesystem. So, using the "append" variety ensures +that LILO passes the root filesystem device as a string, which devfs +can then use. + +Note that this isn't an issue if you don't pass "devfs=only". + +TTY issues +The ttyname(3) function in some versions of the C library makes +false assumptions about device entries which are symbolic links. The +tty(1) programme is one that depends on this function. I've +written a patch to libc 5.4.43 which fixes this. This has been +included in libc 5.4.44 and a similar fix is in glibc 2.1.3. + + +Kernel Naming Scheme + +The kernel provides a default naming scheme. This scheme is designed +to make it easy to search for specific devices or device types, and to +view the available devices. Some device types (such as hard discs), +have a directory of entries, making it easy to see what devices of +that class are available. Often, the entries are symbolic links into a +directory tree that reflects the topology of available devices. The +topological tree is useful for finding how your devices are arranged. + +Below is a list of the naming schemes for the most common drivers. A +list of reserved device names is +available for reference. Please send email to +rgooch@atnf.csiro.au to obtain an allocation. Please be +patient (the maintainer is busy). An alternative name may be allocated +instead of the requested name, at the discretion of the maintainer. + +Disc Devices + +All discs, whether SCSI, IDE or whatever, are placed under the +/dev/discs hierarchy: + + /dev/discs/disc0 first disc + /dev/discs/disc1 second disc + + +Each of these entries is a symbolic link to the directory for that +device. The device directory contains: + + disc for the whole disc + part* for individual partitions + + +CD-ROM Devices + +All CD-ROMs, whether SCSI, IDE or whatever, are placed under the +/dev/cdroms hierarchy: + + /dev/cdroms/cdrom0 first CD-ROM + /dev/cdroms/cdrom1 second CD-ROM + + +Each of these entries is a symbolic link to the real device entry for +that device. + +Tape Devices + +All tapes, whether SCSI, IDE or whatever, are placed under the +/dev/tapes hierarchy: + + /dev/tapes/tape0 first tape + /dev/tapes/tape1 second tape + + +Each of these entries is a symbolic link to the directory for that +device. The device directory contains: + + mt for mode 0 + mtl for mode 1 + mtm for mode 2 + mta for mode 3 + mtn for mode 0, no rewind + mtln for mode 1, no rewind + mtmn for mode 2, no rewind + mtan for mode 3, no rewind + + +SCSI Devices + +To uniquely identify any SCSI device requires the following +information: + + controller (host adapter) + bus (SCSI channel) + target (SCSI ID) + unit (Logical Unit Number) + + +All SCSI devices are placed under /dev/scsi (assuming devfs +is mounted on /dev). Hence, a SCSI device with the following +parameters: c=1,b=2,t=3,u=4 would appear as: + + /dev/scsi/host1/bus2/target3/lun4 device directory + + +Inside this directory, a number of device entries may be created, +depending on which SCSI device-type drivers were installed. + +See the section on the disc naming scheme to see what entries the SCSI +disc driver creates. + +See the section on the tape naming scheme to see what entries the SCSI +tape driver creates. + +The SCSI CD-ROM driver creates: + + cd + + +The SCSI generic driver creates: + + generic + + +IDE Devices + +To uniquely identify any IDE device requires the following +information: + + controller + bus (aka. primary/secondary) + target (aka. master/slave) + unit + + +All IDE devices are placed under /dev/ide, and uses a similar +naming scheme to the SCSI subsystem. + +XT Hard Discs + +All XT discs are placed under /dev/xd. The first XT disc has +the directory /dev/xd/disc0. + +TTY devices + +The tty devices now appear as: + + New name Old-name Device Type + -------- -------- ----------- + /dev/tts/{0,1,...} /dev/ttyS{0,1,...} Serial ports + /dev/cua/{0,1,...} /dev/cua{0,1,...} Call out devices + /dev/vc/0 /dev/tty Current virtual console + /dev/vc/{1,2,...} /dev/tty{1...63} Virtual consoles + /dev/vcc/{0,1,...} /dev/vcs{1...63} Virtual consoles + /dev/pty/m{0,1,...} /dev/ptyp?? PTY masters + /dev/pty/s{0,1,...} /dev/ttyp?? PTY slaves + + +RAMDISCS + +The RAMDISCS are placed in their own directory, and are named thus: + + /dev/rd/{0,1,2,...} + + +Meta Devices + +The meta devices are placed in their own directory, and are named +thus: + + /dev/md/{0,1,2,...} + + +Floppy discs + +Floppy discs are placed in the /dev/floppy directory. + +Loop devices + +Loop devices are placed in the /dev/loop directory. + +Sound devices + +Sound devices are placed in the /dev/sound directory +(audio, sequencer, ...). + + +Devfsd Naming Scheme + +Devfsd provides a naming scheme which is a convenient abbreviation of +the kernel-supplied namespace. In some +cases, the kernel-supplied naming scheme is quite convenient, so +devfsd does not provide another naming scheme. The convenience names +that devfsd creates are in fact the same names as the original devfs +kernel patch created (before Linus mandated the Big Name +Change). These are referred to as "new compatibility entries". + +In order to configure devfsd to create these convenience names, the +following lines should be placed in your /etc/devfsd.conf: + +REGISTER .* MKNEWCOMPAT +UNREGISTER .* RMNEWCOMPAT + +This will cause devfsd to create (and destroy) symbolic links which +point to the kernel-supplied names. + +SCSI Hard Discs + +All SCSI discs are placed under /dev/sd (assuming devfs is +mounted on /dev). Hence, a SCSI disc with the following +parameters: c=1,b=2,t=3,u=4 would appear as: + + /dev/sd/c1b2t3u4 for the whole disc + /dev/sd/c1b2t3u4p5 for the 5th partition + /dev/sd/c1b2t3u4p5s6 for the 6th slice in the 5th partition + + +SCSI Tapes + +All SCSI tapes are placed under /dev/st. A similar naming +scheme is used as for SCSI discs. A SCSI tape with the +parameters:c=1,b=2,t=3,u=4 would appear as: + + /dev/st/c1b2t3u4m0 for mode 0 + /dev/st/c1b2t3u4m1 for mode 1 + /dev/st/c1b2t3u4m2 for mode 2 + /dev/st/c1b2t3u4m3 for mode 3 + /dev/st/c1b2t3u4m0n for mode 0, no rewind + /dev/st/c1b2t3u4m1n for mode 1, no rewind + /dev/st/c1b2t3u4m2n for mode 2, no rewind + /dev/st/c1b2t3u4m3n for mode 3, no rewind + + +SCSI CD-ROMs + +All SCSI CD-ROMs are placed under /dev/sr. A similar naming +scheme is used as for SCSI discs. A SCSI CD-ROM with the +parameters:c=1,b=2,t=3,u=4 would appear as: + + /dev/sr/c1b2t3u4 + + +SCSI Generic Devices + +The generic (aka. raw) interface for all SCSI devices are placed under +/dev/sg. A similar naming scheme is used as for SCSI discs. A +SCSI generic device with the parameters:c=1,b=2,t=3,u=4 would appear +as: + + /dev/sg/c1b2t3u4 + + +IDE Hard Discs + +All IDE discs are placed under /dev/ide/hd, using a similar +convention to SCSI discs. The following mappings exist between the new +and the old names: + + /dev/hda /dev/ide/hd/c0b0t0u0 + /dev/hdb /dev/ide/hd/c0b0t1u0 + /dev/hdc /dev/ide/hd/c0b1t0u0 + /dev/hdd /dev/ide/hd/c0b1t1u0 + + +IDE Tapes + +A similar naming scheme is used as for IDE discs. The entries will +appear in the /dev/ide/mt directory. + +IDE CD-ROM + +A similar naming scheme is used as for IDE discs. The entries will +appear in the /dev/ide/cd directory. + +IDE Floppies + +A similar naming scheme is used as for IDE discs. The entries will +appear in the /dev/ide/fd directory. + +XT Hard Discs + +All XT discs are placed under /dev/xd. The first XT disc +would appear as /dev/xd/c0t0. + + +Old Compatibility Names + +The old compatibility names are the legacy device names, such as +/dev/hda, /dev/sda, /dev/rtc and so on. +Devfsd can be configured to create compatibility symlinks so that you +may continue to use the old names in your configuration files and so +that old applications will continue to function correctly. + +In order to configure devfsd to create these legacy names, the +following lines should be placed in your /etc/devfsd.conf: + +REGISTER .* MKOLDCOMPAT +UNREGISTER .* RMOLDCOMPAT + +This will cause devfsd to create (and destroy) symbolic links which +point to the kernel-supplied names. + + +----------------------------------------------------------------------------- + + +Device drivers currently ported + +- All miscellaneous character devices support devfs (this is done + transparently through misc_register()) + +- SCSI discs and generic hard discs + +- Character memory devices (null, zero, full and so on) + Thanks to C. Scott Ananian + +- Loop devices (/dev/loop?) + +- TTY devices (console, serial ports, terminals and pseudo-terminals) + Thanks to C. Scott Ananian + +- SCSI tapes (/dev/scsi and /dev/tapes) + +- SCSI CD-ROMs (/dev/scsi and /dev/cdroms) + +- SCSI generic devices (/dev/scsi) + +- RAMDISCS (/dev/ram?) + +- Meta Devices (/dev/md*) + +- Floppy discs (/dev/floppy) + +- Parallel port printers (/dev/printers) + +- Sound devices (/dev/sound) + Thanks to Eric Dumas and + C. Scott Ananian + +- Joysticks (/dev/joysticks) + +- Sparc keyboard (/dev/kbd) + +- DSP56001 digital signal processor (/dev/dsp56k) + +- Apple Desktop Bus (/dev/adb) + +- Coda network file system (/dev/cfs*) + +- Virtual console capture devices (/dev/vcc) + Thanks to Dennis Hou + +- Frame buffer devices (/dev/fb) + +- Video capture devices (/dev/v4l) + + +----------------------------------------------------------------------------- + + +Allocation of Device Numbers + +Devfs allows you to write a driver which doesn't need to allocate a +device number (major&minor numbers) for the internal operation of the +kernel. However, there are a number of userspace programmes that use +the device number as a unique handle for a device. An example is the +find programme, which uses device numbers to determine whether +an inode is on a different filesystem than another inode. The device +number used is the one for the block device which a filesystem is +using. To preserve compatibility with userspace programmes, block +devices using devfs need to have unique device numbers allocated to +them. Furthermore, POSIX specifies device numbers, so some kind of +device number needs to be presented to userspace. + +The simplest option (especially when porting drivers to devfs) is to +keep using the old major and minor numbers. Devfs will take whatever +values are given for major&minor and pass them onto userspace. + +This device number is a 16 bit number, so this leaves plenty of space +for large numbers of discs and partitions. This scheme can also be +used for character devices, in particular the tty devices, which are +currently limited to 256 pseudo-ttys (this limits the total number of +simultaneous xterms and remote logins). Note that the device number +is limited to the range 36864-61439 (majors 144-239), in order to +avoid any possible conflicts with existing official allocations. + +Please note that using dynamically allocated block device numbers may +break the NFS daemons (both user and kernel mode), which expect dev_t +for a given device to be constant over the lifetime of remote mounts. + +A final note on this scheme: since it doesn't increase the size of +device numbers, there are no compatibility issues with userspace. + +----------------------------------------------------------------------------- + + +Questions and Answers + + +Making things work +Alternatives to devfs +What I don't like about devfs +How to report bugs +Strange kernel messages +Compilation problems with devfsd + + + +Making things work + +Here are some common questions and answers. + + + +Devfsd doesn't start + +Make sure you have compiled and installed devfsd +Make sure devfsd is being started from your boot +scripts +Make sure you have configured your kernel to enable devfs (see +below) +Make sure devfs is mounted (see below) + + +Devfsd is not managing all my permissions + +Make sure you are capturing the appropriate events. For example, +device entries created by the kernel generate REGISTER events, +but those created by devfsd generate CREATE events. + + +Devfsd is not capturing all REGISTER events + +See the previous entry: you may need to capture CREATE events. + + +X will not start + +Make sure you followed the steps +outlined above. + + +Why don't my network devices appear in devfs? + +This is not a bug. Network devices have their own, completely separate +namespace. They are accessed via socket(2) and +setsockopt(2) calls, and thus require no device nodes. I have +raised the possibilty of moving network devices into the device +namespace, but have had no response. + + +How can I test if I have devfs compiled into my kernel? + +All filesystems built-in or currently loaded are listed in +/proc/filesystems. If you see a devfs entry, then +you know that devfs was compiled into your kernel. If you have +correctly configured and rebuilt your kernel, then devfs will be +built-in. If you think you've configured it in, but +/proc/filesystems doesn't show it, you've made a mistake. +Common mistakes include: + +Using a 2.2.x kernel without applying the devfs patch (if you +don't know how to patch your kernel, use 2.4.x instead, don't bother +asking me how to patch) +Forgetting to set CONFIG_EXPERIMENTAL=y +Forgetting to set CONFIG_DEVFS_FS=y +Forgetting to set CONFIG_DEVFS_MOUNT=y (if you want devfs +to be automatically mounted at boot) +Editing your .config manually, instead of using make +config or make xconfig +Forgetting to run make dep; make clean after changing the +configuration and before compiling +Forgetting to compile your kernel and modules +Forgetting to install your kernel +Forgetting to install your modules + +Please check twice that you've done all these steps before sending in +a bug report. + + + +How can I test if devfs is mounted on /dev? + +The device filesystem will always create an entry called +".devfsd", which is used to communicate with the daemon. Even +if the daemon is not running, this entry will exist. Testing for the +existence of this entry is the approved method of determining if devfs +is mounted or not. Note that the type of entry (i.e. regular file, +character device, named pipe, etc.) may change without notice. Only +the existence of the entry should be relied upon. + + +When I start devfsd, I see the error: +Error opening file: ".devfsd" No such file or directory? + +This means that devfs is not mounted. Make sure you have devfs mounted. + + +How do I mount devfs? + +First make sure you have devfs compiled into your kernel (see +above). Then you will either need to: + +set CONFIG_DEVFS_MOUNT=y in your kernel config +pass devfs=mount to your boot loader +mount devfs manually in your boot scripts with: +mount -t none devfs /dev + + + +Mount by volume LABEL=> parameter to , , + and . + Work sponsored by SGI. + v0.76 + 19991017 Richard Gooch + Allow multiple unregistrations. + Work sponsored by SGI. + v0.77 + 19991026 Richard Gooch + Added major and minor number to devfsd protocol. + Incremented devfsd protocol revision to 5. + Work sponsored by SGI. + v0.78 + 19991030 Richard Gooch + Support info pointer for all devfs entry types. + Added <> parameter to and + . + Work sponsored by SGI. + v0.79 + 19991031 Richard Gooch + Support "../" when searching devfs namespace. + Work sponsored by SGI. + v0.80 + 19991101 Richard Gooch + Created . + Work sponsored by SGI. + v0.81 + 19991103 Richard Gooch + Exported . + Work sponsored by SGI. + v0.82 + 19991104 Richard Gooch + Removed unused . + 19991105 Richard Gooch + Do not hide entries from devfsd or children. + Removed DEVFS_ FL_TTY_COMPAT flag. + Removed "nottycompat" boot option. + Removed . + Work sponsored by SGI. + v0.83 + 19991107 Richard Gooch + Added DEVFS_FL_WAIT flag. + Work sponsored by SGI. + v0.84 + 19991107 Richard Gooch + Support new "disc" naming scheme in . + Allow NULL fops in . + Work sponsored by SGI. + v0.85 + 19991110 Richard Gooch + Fall back to major table if NULL fops given to . + Work sponsored by SGI. + v0.86 + 19991204 Richard Gooch + Support fifos when unregistering. + Work sponsored by SGI. + v0.87 + 19991209 Richard Gooch + Removed obsolete DEVFS_ FL_COMPAT and DEVFS_ FL_TOLERANT flags. + Work sponsored by SGI. + v0.88 + 19991214 Richard Gooch + Removed kmod support. + Work sponsored by SGI. + v0.89 + 19991216 Richard Gooch + Improved debugging in . + Ensure dentries created by devfsd will be cleaned up. + Work sponsored by SGI. + v0.90 + 19991223 Richard Gooch + Created . + Work sponsored by SGI. + v0.91 + 20000203 Richard Gooch + Ported to kernel 2.3.42. + Removed . + Work sponsored by SGI. + v0.92 + 20000306 Richard Gooch + Added DEVFS_ FL_NO_PERSISTENCE flag. + Removed unnecessary call to in + . + Work sponsored by SGI. + v0.93 + 20000413 Richard Gooch + Set inode->i_size to correct size for symlinks. + 20000414 Richard Gooch + Only give lookup() method to directories to comply with new VFS + assumptions. + Work sponsored by SGI. + 20000415 Richard Gooch + Remove unnecessary tests in symlink methods. + Don't kill existing block ops in . + Work sponsored by SGI. + v0.94 + 20000424 Richard Gooch + Don't create missing directories in . + Work sponsored by SGI. + v0.95 + 20000430 Richard Gooch + Added CONFIG_DEVFS_MOUNT. + Work sponsored by SGI. + v0.96 + 20000608 Richard Gooch + Disabled multi-mount capability (use VFS bindings instead). + Work sponsored by SGI. + v0.97 + 20000610 Richard Gooch + Switched to FS_SINGLE to disable multi-mounts. + 20000612 Richard Gooch + Removed module support. + Removed multi-mount code. + Removed compatibility macros: VFS has changed too much. + Work sponsored by SGI. + v0.98 + 20000614 Richard Gooch + Merged devfs inode into devfs entry. + Work sponsored by SGI. + v0.99 + 20000619 Richard Gooch + Removed dead code in which used to call + . + Work sponsored by SGI. + v0.100 + 20000621 Richard Gooch + Changed interface to . + Work sponsored by SGI. + v0.101 + 20000622 Richard Gooch + Simplified interface to and . + Simplified interface to . + Work sponsored by SGI. + v0.102 + 20010519 Richard Gooch + Ensure terminates string for root entry. + Exported to modules. + 20010520 Richard Gooch + Make send events to devfsd. + Cleaned up option processing in . + 20010521 Richard Gooch + Fixed bugs in handling symlinks: could leak or cause Oops. + 20010522 Richard Gooch + Cleaned up directory handling by separating fops. + v0.103 + 20010601 Richard Gooch + Fixed handling of inverted options in . + v0.104 + 20010604 Richard Gooch + Adjusted to account for fix. + v0.105 + 20010617 Richard Gooch + Answered question posed by Al Viro and removed his comments. + Moved setting of registered flag after other fields are changed. + Fixed race between and . + Global VFS changes added bogus BKL to : removed. + Widened locking in and . + Replaced stack usage with kmalloc. + Simplified locking in and fixed memory leak. + v0.106 + 20010709 Richard Gooch + Removed broken devnum allocation and use . + Fixed old devnum leak by calling new . + v0.107 + 20010712 Richard Gooch + Fixed bug in which could hang boot process. + v0.108 + 20010730 Richard Gooch + Added DEVFSD_NOTIFY_DELETE event. + 20010801 Richard Gooch + Removed #include . + v0.109 + 20010807 Richard Gooch + Fixed inode table races by removing it and using + inode->u.generic_ip instead. + Moved into . + Moved into . + v0.110 + 20010808 Richard Gooch + Fixed race in for uni-processor. + v0.111 + 20010818 Richard Gooch + Removed remnant of multi-mount support in . + Removed unused DEVFS_FL_SHOW_UNREG flag. + v0.112 + 20010820 Richard Gooch + Removed nlink field from struct devfs_inode. + v0.113 + 20010823 Richard Gooch + Replaced BKL with global rwsem to protect symlink data (quick + and dirty hack). + v0.114 + 20010827 Richard Gooch + Replaced global rwsem for symlink with per-link refcount. + v0.115 + 20010919 Richard Gooch + Set inode->i_mapping->a_ops for block nodes in . + v0.116 + 20011008 Richard Gooch + Fixed overrun in by removing function (not needed). + 20011009 Richard Gooch + Fixed buffer underrun in . + 20011029 Richard Gooch + Fixed race in when setting event mask. + 20011114 Richard Gooch + First release of new locking code. + v1.0 + 20011117 Richard Gooch + Discard temporary buffer, now use "%s" for dentry names. + 20011118 Richard Gooch + Don't generate path in : use fake entry instead. + Use "existing" directory in <_devfs_make_parent_for_leaf>. + 20011122 Richard Gooch + Use slab cache rather than fixed buffer for devfsd events. + v1.1 + 20011125 Richard Gooch + Send DEVFSD_NOTIFY_REGISTERED events in . + 20011127 Richard Gooch + Fixed locking bug in due to typo. + Do not send CREATE, CHANGE, ASYNC_OPEN or DELETE events from + devfsd or children. + v1.2 + 20011202 Richard Gooch + Fixed bug in : was dereferencing freed pointer. + v1.3 + 20011203 Richard Gooch + Fixed bug in : was dereferencing freed pointer. + Added process group check for devfsd privileges. + v1.4 + 20011204 Richard Gooch + Use SLAB_ATOMIC in from . + v1.5 + 20011211 Richard Gooch + Return old entry in for 2.4.x kernels. + 20011212 Richard Gooch + Increment refcount on module in . + 20011215 Richard Gooch + Created and exported . + Increment refcount on module in . + Created . + v1.6 + 20011216 Richard Gooch + Added poisoning to . + Improved debugging messages. + v1.7 + 20011221 Richard Gooch + Corrected (made useful) debugging message in . + Moved in to + 20011224 Richard Gooch + Added magic number to guard against scribbling drivers. + 20011226 Richard Gooch + Only return old entry in if a directory. + Defined macros for error and debug messages. + v1.8 + 20020113 Richard Gooch + Fixed (rare, old) race in . + v1.9 + 20020120 Richard Gooch + Fixed deadlock bug in . + Tag VFS deletable in if handle ignored. + v1.10 + 20020129 Richard Gooch + Added KERN_* to remaining messages. + Cleaned up declaration of . + v1.11 + 20020219 Richard Gooch + Changed to allow later additions if not yet empty. + v1.12 + 20020406 Richard Gooch + Removed silently introduced calls to lock_kernel() and + unlock_kernel() due to recent VFS locking changes. BKL isn't + required in devfs. + v1.13 + 20020428 Richard Gooch + Removed 2.4.x compatibility code. + v1.14 + 20020510 Richard Gooch + Added BKL to because drivers still need it. + v1.15 + 20020512 Richard Gooch + Protected and + from changing directory contents. + v1.16 + 20020514 Richard Gooch + Minor cleanup of . + v1.17 + 20020721 Richard Gooch + Switched to ISO C structure field initialisers. + Switch to set_current_state() and move before add_wait_queue(). + 20020722 Richard Gooch + Fixed devfs entry leak in when *readdir fails. + v1.18 + 20020725 Richard Gooch + Created . + v1.19 + 20020728 Richard Gooch + Removed deprecated . + v1.20 + 20020820 Richard Gooch + Fixed module unload race in . + v1.21 + 20021013 Richard Gooch + Removed DEVFS_ FL_AUTO_OWNER. + Switched lingering structure field initialiser to ISO C. + Added locking when updating FCB flags. + v1.22 +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define DEVFS_VERSION "2004-01-31" + +#define DEVFS_NAME "devfs" + +#define FIRST_INODE 1 + +#define STRING_LENGTH 256 +#define FAKE_BLOCK_SIZE 1024 +#define POISON_PTR ( *(void **) poison_array ) +#define MAGIC_VALUE 0x327db823 + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +#define MODE_DIR (S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO) + +#define DEBUG_NONE 0x0000000 +#define DEBUG_MODULE_LOAD 0x0000001 +#define DEBUG_REGISTER 0x0000002 +#define DEBUG_UNREGISTER 0x0000004 +#define DEBUG_FREE 0x0000008 +#define DEBUG_SET_FLAGS 0x0000010 +#define DEBUG_S_READ 0x0000100 /* Break */ +#define DEBUG_I_LOOKUP 0x0001000 /* Break */ +#define DEBUG_I_CREATE 0x0002000 +#define DEBUG_I_GET 0x0004000 +#define DEBUG_I_CHANGE 0x0008000 +#define DEBUG_I_UNLINK 0x0010000 +#define DEBUG_I_RLINK 0x0020000 +#define DEBUG_I_FLINK 0x0040000 +#define DEBUG_I_MKNOD 0x0080000 +#define DEBUG_F_READDIR 0x0100000 /* Break */ +#define DEBUG_D_DELETE 0x1000000 /* Break */ +#define DEBUG_D_RELEASE 0x2000000 +#define DEBUG_D_IPUT 0x4000000 +#define DEBUG_ALL 0xfffffff +#define DEBUG_DISABLED DEBUG_NONE + +#define OPTION_NONE 0x00 +#define OPTION_MOUNT 0x01 + +#define PRINTK(format, args...) \ + {printk (KERN_ERR "%s" format, __FUNCTION__ , ## args);} + +#define OOPS(format, args...) \ + {printk (KERN_CRIT "%s" format, __FUNCTION__ , ## args); \ + printk ("Forcing Oops\n"); \ + BUG();} + +#ifdef CONFIG_DEVFS_DEBUG +# define VERIFY_ENTRY(de) \ + {if ((de) && (de)->magic_number != MAGIC_VALUE) \ + OOPS ("(%p): bad magic value: %x\n", (de), (de)->magic_number);} +# define WRITE_ENTRY_MAGIC(de,magic) (de)->magic_number = (magic) +# define DPRINTK(flag, format, args...) \ + {if (devfs_debug & flag) \ + printk (KERN_INFO "%s" format, __FUNCTION__ , ## args);} +#else +# define VERIFY_ENTRY(de) +# define WRITE_ENTRY_MAGIC(de,magic) +# define DPRINTK(flag, format, args...) +#endif + +typedef struct devfs_entry *devfs_handle_t; + +struct directory_type { + rwlock_t lock; /* Lock for searching(R)/updating(W) */ + struct devfs_entry *first; + struct devfs_entry *last; + unsigned char no_more_additions:1; +}; + +struct symlink_type { + unsigned int length; /* Not including the NULL-termimator */ + char *linkname; /* This is NULL-terminated */ +}; + +struct devfs_inode { /* This structure is for "persistent" inode storage */ + struct dentry *dentry; + struct timespec atime; + struct timespec mtime; + struct timespec ctime; + unsigned int ino; /* Inode number as seen in the VFS */ + uid_t uid; + gid_t gid; +}; + +struct devfs_entry { +#ifdef CONFIG_DEVFS_DEBUG + unsigned int magic_number; +#endif + void *info; + atomic_t refcount; /* When this drops to zero, it's unused */ + union { + struct directory_type dir; + dev_t dev; + struct symlink_type symlink; + const char *name; /* Only used for (mode == 0) */ + } u; + struct devfs_entry *prev; /* Previous entry in the parent directory */ + struct devfs_entry *next; /* Next entry in the parent directory */ + struct devfs_entry *parent; /* The parent directory */ + struct devfs_inode inode; + umode_t mode; + unsigned short namelen; /* I think 64k+ filenames are a way off... */ + unsigned char vfs:1; /* Whether the VFS may delete the entry */ + char name[1]; /* This is just a dummy: the allocated array + is bigger. This is NULL-terminated */ +}; + +/* The root of the device tree */ +static struct devfs_entry *root_entry; + +struct devfsd_buf_entry { + struct devfs_entry *de; /* The name is generated with this */ + unsigned short type; /* The type of event */ + umode_t mode; + uid_t uid; + gid_t gid; + struct devfsd_buf_entry *next; +}; + +struct fs_info { /* This structure is for the mounted devfs */ + struct super_block *sb; + spinlock_t devfsd_buffer_lock; /* Lock when inserting/deleting events */ + struct devfsd_buf_entry *devfsd_first_event; + struct devfsd_buf_entry *devfsd_last_event; + volatile int devfsd_sleeping; + volatile struct task_struct *devfsd_task; + volatile pid_t devfsd_pgrp; + volatile struct file *devfsd_file; + struct devfsd_notify_struct *devfsd_info; + volatile unsigned long devfsd_event_mask; + atomic_t devfsd_overrun_count; + wait_queue_head_t devfsd_wait_queue; /* Wake devfsd on input */ + wait_queue_head_t revalidate_wait_queue; /* Wake when devfsd sleeps */ +}; + +static struct fs_info fs_info = {.devfsd_buffer_lock = SPIN_LOCK_UNLOCKED }; +static kmem_cache_t *devfsd_buf_cache; +#ifdef CONFIG_DEVFS_DEBUG +static unsigned int devfs_debug_init __initdata = DEBUG_NONE; +static unsigned int devfs_debug = DEBUG_NONE; +static DEFINE_SPINLOCK(stat_lock); +static unsigned int stat_num_entries; +static unsigned int stat_num_bytes; +#endif +static unsigned char poison_array[8] = + { 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a }; + +#ifdef CONFIG_DEVFS_MOUNT +static unsigned int boot_options = OPTION_MOUNT; +#else +static unsigned int boot_options = OPTION_NONE; +#endif + +/* Forward function declarations */ +static devfs_handle_t _devfs_walk_path(struct devfs_entry *dir, + const char *name, int namelen, + int traverse_symlink); +static ssize_t devfsd_read(struct file *file, char __user *buf, size_t len, + loff_t * ppos); +static int devfsd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +static int devfsd_close(struct inode *inode, struct file *file); +#ifdef CONFIG_DEVFS_DEBUG +static ssize_t stat_read(struct file *file, char __user *buf, size_t len, + loff_t * ppos); +static const struct file_operations stat_fops = { + .open = nonseekable_open, + .read = stat_read, +}; +#endif + +/* Devfs daemon file operations */ +static const struct file_operations devfsd_fops = { + .open = nonseekable_open, + .read = devfsd_read, + .ioctl = devfsd_ioctl, + .release = devfsd_close, +}; + +/* Support functions follow */ + +/** + * devfs_get - Get a reference to a devfs entry. + * @de: The devfs entry. + */ + +static struct devfs_entry *devfs_get(struct devfs_entry *de) +{ + VERIFY_ENTRY(de); + if (de) + atomic_inc(&de->refcount); + return de; +} /* End Function devfs_get */ + +/** + * devfs_put - Put (release) a reference to a devfs entry. + * @de: The handle to the devfs entry. + */ + +static void devfs_put(devfs_handle_t de) +{ + if (!de) + return; + VERIFY_ENTRY(de); + if (de->info == POISON_PTR) + OOPS("(%p): poisoned pointer\n", de); + if (!atomic_dec_and_test(&de->refcount)) + return; + if (de == root_entry) + OOPS("(%p): root entry being freed\n", de); + DPRINTK(DEBUG_FREE, "(%s): de: %p, parent: %p \"%s\"\n", + de->name, de, de->parent, + de->parent ? de->parent->name : "no parent"); + if (S_ISLNK(de->mode)) + kfree(de->u.symlink.linkname); + WRITE_ENTRY_MAGIC(de, 0); +#ifdef CONFIG_DEVFS_DEBUG + spin_lock(&stat_lock); + --stat_num_entries; + stat_num_bytes -= sizeof *de + de->namelen; + if (S_ISLNK(de->mode)) + stat_num_bytes -= de->u.symlink.length + 1; + spin_unlock(&stat_lock); +#endif + de->info = POISON_PTR; + kfree(de); +} /* End Function devfs_put */ + +/** + * _devfs_search_dir - Search for a devfs entry in a directory. + * @dir: The directory to search. + * @name: The name of the entry to search for. + * @namelen: The number of characters in @name. + * + * Search for a devfs entry in a directory and returns a pointer to the entry + * on success, else %NULL. The directory must be locked already. + * An implicit devfs_get() is performed on the returned entry. + */ + +static struct devfs_entry *_devfs_search_dir(struct devfs_entry *dir, + const char *name, + unsigned int namelen) +{ + struct devfs_entry *curr; + + if (!S_ISDIR(dir->mode)) { + PRINTK("(%s): not a directory\n", dir->name); + return NULL; + } + for (curr = dir->u.dir.first; curr != NULL; curr = curr->next) { + if (curr->namelen != namelen) + continue; + if (memcmp(curr->name, name, namelen) == 0) + break; + /* Not found: try the next one */ + } + return devfs_get(curr); +} /* End Function _devfs_search_dir */ + +/** + * _devfs_alloc_entry - Allocate a devfs entry. + * @name: the name of the entry + * @namelen: the number of characters in @name + * @mode: the mode for the entry + * + * Allocate a devfs entry and returns a pointer to the entry on success, else + * %NULL. + */ + +static struct devfs_entry *_devfs_alloc_entry(const char *name, + unsigned int namelen, + umode_t mode) +{ + struct devfs_entry *new; + static unsigned long inode_counter = FIRST_INODE; + static DEFINE_SPINLOCK(counter_lock); + + if (name && (namelen < 1)) + namelen = strlen(name); + if ((new = kmalloc(sizeof *new + namelen, GFP_KERNEL)) == NULL) + return NULL; + memset(new, 0, sizeof *new + namelen); /* Will set '\0' on name */ + new->mode = mode; + if (S_ISDIR(mode)) + rwlock_init(&new->u.dir.lock); + atomic_set(&new->refcount, 1); + spin_lock(&counter_lock); + new->inode.ino = inode_counter++; + spin_unlock(&counter_lock); + if (name) + memcpy(new->name, name, namelen); + new->namelen = namelen; + WRITE_ENTRY_MAGIC(new, MAGIC_VALUE); +#ifdef CONFIG_DEVFS_DEBUG + spin_lock(&stat_lock); + ++stat_num_entries; + stat_num_bytes += sizeof *new + namelen; + spin_unlock(&stat_lock); +#endif + return new; +} /* End Function _devfs_alloc_entry */ + +/** + * _devfs_append_entry - Append a devfs entry to a directory's child list. + * @dir: The directory to add to. + * @de: The devfs entry to append. + * @old_de: If an existing entry exists, it will be written here. This may + * be %NULL. An implicit devfs_get() is performed on this entry. + * + * Append a devfs entry to a directory's list of children, checking first to + * see if an entry of the same name exists. The directory will be locked. + * The value 0 is returned on success, else a negative error code. + * On failure, an implicit devfs_put() is performed on %de. + */ + +static int _devfs_append_entry(devfs_handle_t dir, devfs_handle_t de, + devfs_handle_t * old_de) +{ + int retval; + + if (old_de) + *old_de = NULL; + if (!S_ISDIR(dir->mode)) { + PRINTK("(%s): dir: \"%s\" is not a directory\n", de->name, + dir->name); + devfs_put(de); + return -ENOTDIR; + } + write_lock(&dir->u.dir.lock); + if (dir->u.dir.no_more_additions) + retval = -ENOENT; + else { + struct devfs_entry *old; + + old = _devfs_search_dir(dir, de->name, de->namelen); + if (old_de) + *old_de = old; + else + devfs_put(old); + if (old == NULL) { + de->parent = dir; + de->prev = dir->u.dir.last; + /* Append to the directory's list of children */ + if (dir->u.dir.first == NULL) + dir->u.dir.first = de; + else + dir->u.dir.last->next = de; + dir->u.dir.last = de; + retval = 0; + } else + retval = -EEXIST; + } + write_unlock(&dir->u.dir.lock); + if (retval) + devfs_put(de); + return retval; +} /* End Function _devfs_append_entry */ + +/** + * _devfs_get_root_entry - Get the root devfs entry. + * + * Returns the root devfs entry on success, else %NULL. + * + * TODO it must be called asynchronously due to the fact + * that devfs is initialized relatively late. Proper way + * is to remove module_init from init_devfs_fs and manually + * call it early enough during system init + */ + +static struct devfs_entry *_devfs_get_root_entry(void) +{ + struct devfs_entry *new; + static DEFINE_SPINLOCK(root_lock); + + if (root_entry) + return root_entry; + + new = _devfs_alloc_entry(NULL, 0, MODE_DIR); + if (new == NULL) + return NULL; + + spin_lock(&root_lock); + if (root_entry) { + spin_unlock(&root_lock); + devfs_put(new); + return root_entry; + } + root_entry = new; + spin_unlock(&root_lock); + + return root_entry; +} /* End Function _devfs_get_root_entry */ + +/** + * _devfs_descend - Descend down a tree using the next component name. + * @dir: The directory to search. + * @name: The component name to search for. + * @namelen: The length of %name. + * @next_pos: The position of the next '/' or '\0' is written here. + * + * Descend into a directory, searching for a component. This function forms + * the core of a tree-walking algorithm. The directory will be locked. + * The devfs entry corresponding to the component is returned. If there is + * no matching entry, %NULL is returned. + * An implicit devfs_get() is performed on the returned entry. + */ + +static struct devfs_entry *_devfs_descend(struct devfs_entry *dir, + const char *name, int namelen, + int *next_pos) +{ + const char *stop, *ptr; + struct devfs_entry *entry; + + if ((namelen >= 3) && (strncmp(name, "../", 3) == 0)) { /* Special-case going to parent directory */ + *next_pos = 3; + return devfs_get(dir->parent); + } + stop = name + namelen; + /* Search for a possible '/' */ + for (ptr = name; (ptr < stop) && (*ptr != '/'); ++ptr) ; + *next_pos = ptr - name; + read_lock(&dir->u.dir.lock); + entry = _devfs_search_dir(dir, name, *next_pos); + read_unlock(&dir->u.dir.lock); + return entry; +} /* End Function _devfs_descend */ + +static devfs_handle_t _devfs_make_parent_for_leaf(struct devfs_entry *dir, + const char *name, + int namelen, int *leaf_pos) +{ + int next_pos = 0; + + if (dir == NULL) + dir = _devfs_get_root_entry(); + if (dir == NULL) + return NULL; + devfs_get(dir); + /* Search for possible trailing component and ignore it */ + for (--namelen; (namelen > 0) && (name[namelen] != '/'); --namelen) ; + *leaf_pos = (name[namelen] == '/') ? (namelen + 1) : 0; + for (; namelen > 0; name += next_pos, namelen -= next_pos) { + struct devfs_entry *de, *old = NULL; + + if ((de = + _devfs_descend(dir, name, namelen, &next_pos)) == NULL) { + de = _devfs_alloc_entry(name, next_pos, MODE_DIR); + devfs_get(de); + if (!de || _devfs_append_entry(dir, de, &old)) { + devfs_put(de); + if (!old || !S_ISDIR(old->mode)) { + devfs_put(old); + devfs_put(dir); + return NULL; + } + de = old; /* Use the existing directory */ + } + } + if (de == dir->parent) { + devfs_put(dir); + devfs_put(de); + return NULL; + } + devfs_put(dir); + dir = de; + if (name[next_pos] == '/') + ++next_pos; + } + return dir; +} /* End Function _devfs_make_parent_for_leaf */ + +static devfs_handle_t _devfs_prepare_leaf(devfs_handle_t * dir, + const char *name, umode_t mode) +{ + int namelen, leaf_pos; + struct devfs_entry *de; + + namelen = strlen(name); + if ((*dir = _devfs_make_parent_for_leaf(*dir, name, namelen, + &leaf_pos)) == NULL) { + PRINTK("(%s): could not create parent path\n", name); + return NULL; + } + if ((de = _devfs_alloc_entry(name + leaf_pos, namelen - leaf_pos, mode)) + == NULL) { + PRINTK("(%s): could not allocate entry\n", name); + devfs_put(*dir); + return NULL; + } + return de; +} /* End Function _devfs_prepare_leaf */ + +static devfs_handle_t _devfs_walk_path(struct devfs_entry *dir, + const char *name, int namelen, + int traverse_symlink) +{ + int next_pos = 0; + + if (dir == NULL) + dir = _devfs_get_root_entry(); + if (dir == NULL) + return NULL; + devfs_get(dir); + for (; namelen > 0; name += next_pos, namelen -= next_pos) { + struct devfs_entry *de, *link; + + if (!S_ISDIR(dir->mode)) { + devfs_put(dir); + return NULL; + } + + if ((de = + _devfs_descend(dir, name, namelen, &next_pos)) == NULL) { + devfs_put(dir); + return NULL; + } + if (S_ISLNK(de->mode) && traverse_symlink) { /* Need to follow the link: this is a stack chomper */ + /* FIXME what if it puts outside of mounted tree? */ + link = _devfs_walk_path(dir, de->u.symlink.linkname, + de->u.symlink.length, TRUE); + devfs_put(de); + if (!link) { + devfs_put(dir); + return NULL; + } + de = link; + } + devfs_put(dir); + dir = de; + if (name[next_pos] == '/') + ++next_pos; + } + return dir; +} /* End Function _devfs_walk_path */ + +/** + * _devfs_find_entry - Find a devfs entry. + * @dir: The handle to the parent devfs directory entry. If this is %NULL the + * name is relative to the root of the devfs. + * @name: The name of the entry. This may be %NULL. + * @traverse_symlink: If %TRUE then symbolic links are traversed. + * + * Returns the devfs_entry pointer on success, else %NULL. An implicit + * devfs_get() is performed. + */ + +static struct devfs_entry *_devfs_find_entry(devfs_handle_t dir, + const char *name, + int traverse_symlink) +{ + unsigned int namelen = strlen(name); + + if (name[0] == '/') { + /* Skip leading pathname component */ + if (namelen < 2) { + PRINTK("(%s): too short\n", name); + return NULL; + } + for (++name, --namelen; (*name != '/') && (namelen > 0); + ++name, --namelen) ; + if (namelen < 2) { + PRINTK("(%s): too short\n", name); + return NULL; + } + ++name; + --namelen; + } + return _devfs_walk_path(dir, name, namelen, traverse_symlink); +} /* End Function _devfs_find_entry */ + +static struct devfs_entry *get_devfs_entry_from_vfs_inode(struct inode *inode) +{ + if (inode == NULL) + return NULL; + VERIFY_ENTRY((struct devfs_entry *)inode->u.generic_ip); + return inode->u.generic_ip; +} /* End Function get_devfs_entry_from_vfs_inode */ + +/** + * free_dentry - Free the dentry for a device entry and invalidate inode. + * @de: The entry. + * + * This must only be called after the entry has been unhooked from its + * parent directory. + */ + +static void free_dentry(struct devfs_entry *de) +{ + struct dentry *dentry = de->inode.dentry; + + if (!dentry) + return; + spin_lock(&dcache_lock); + dget_locked(dentry); + spin_unlock(&dcache_lock); + /* Forcefully remove the inode */ + if (dentry->d_inode != NULL) + dentry->d_inode->i_nlink = 0; + d_drop(dentry); + dput(dentry); +} /* End Function free_dentry */ + +/** + * is_devfsd_or_child - Test if the current process is devfsd or one of its children. + * @fs_info: The filesystem information. + * + * Returns %TRUE if devfsd or child, else %FALSE. + */ + +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 (process_group(p) == fs_info->devfsd_pgrp) + return (TRUE); + read_lock(&tasklist_lock); + for (; p != &init_task; p = p->real_parent) { + if (p == fs_info->devfsd_task) { + read_unlock(&tasklist_lock); + return (TRUE); + } + } + read_unlock(&tasklist_lock); + return (FALSE); +} /* End Function is_devfsd_or_child */ + +/** + * devfsd_queue_empty - Test if devfsd has work pending in its event queue. + * @fs_info: The filesystem information. + * + * Returns %TRUE if the queue is empty, else %FALSE. + */ + +static inline int devfsd_queue_empty(struct fs_info *fs_info) +{ + return (fs_info->devfsd_last_event) ? FALSE : TRUE; +} /* End Function devfsd_queue_empty */ + +/** + * wait_for_devfsd_finished - Wait for devfsd to finish processing its event queue. + * @fs_info: The filesystem information. + * + * Returns %TRUE if no more waiting will be required, else %FALSE. + */ + +static int wait_for_devfsd_finished(struct fs_info *fs_info) +{ + DECLARE_WAITQUEUE(wait, current); + + if (fs_info->devfsd_task == NULL) + return (TRUE); + if (devfsd_queue_empty(fs_info) && fs_info->devfsd_sleeping) + return TRUE; + if (is_devfsd_or_child(fs_info)) + return (FALSE); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&fs_info->revalidate_wait_queue, &wait); + if (!devfsd_queue_empty(fs_info) || !fs_info->devfsd_sleeping) + if (fs_info->devfsd_task) + schedule(); + remove_wait_queue(&fs_info->revalidate_wait_queue, &wait); + __set_current_state(TASK_RUNNING); + return (TRUE); +} /* End Function wait_for_devfsd_finished */ + +/** + * devfsd_notify_de - Notify the devfsd daemon of a change. + * @de: The devfs entry that has changed. This and all parent entries will + * have their reference counts incremented if the event was queued. + * @type: The type of change. + * @mode: The mode of the entry. + * @uid: The user ID. + * @gid: The group ID. + * @fs_info: The filesystem info. + * + * Returns %TRUE if an event was queued and devfsd woken up, else %FALSE. + */ + +static int devfsd_notify_de(struct devfs_entry *de, + unsigned short type, umode_t mode, + uid_t uid, gid_t gid, struct fs_info *fs_info) +{ + struct devfsd_buf_entry *entry; + struct devfs_entry *curr; + + if (!(fs_info->devfsd_event_mask & (1 << type))) + return (FALSE); + if ((entry = kmem_cache_alloc(devfsd_buf_cache, SLAB_KERNEL)) == NULL) { + atomic_inc(&fs_info->devfsd_overrun_count); + return (FALSE); + } + for (curr = de; curr != NULL; curr = curr->parent) + devfs_get(curr); + entry->de = de; + entry->type = type; + entry->mode = mode; + entry->uid = uid; + entry->gid = gid; + entry->next = NULL; + spin_lock(&fs_info->devfsd_buffer_lock); + if (!fs_info->devfsd_first_event) + fs_info->devfsd_first_event = entry; + if (fs_info->devfsd_last_event) + fs_info->devfsd_last_event->next = entry; + fs_info->devfsd_last_event = entry; + spin_unlock(&fs_info->devfsd_buffer_lock); + wake_up_interruptible(&fs_info->devfsd_wait_queue); + return (TRUE); +} /* End Function devfsd_notify_de */ + +/** + * devfsd_notify - Notify the devfsd daemon of a change. + * @de: The devfs entry that has changed. + * @type: The type of change event. + * @wait: If TRUE, the function waits for the daemon to finish processing + * the event. + */ + +static void devfsd_notify(struct devfs_entry *de, unsigned short type) +{ + devfsd_notify_de(de, type, de->mode, current->euid, + current->egid, &fs_info); +} + +static int devfs_mk_dev(dev_t dev, umode_t mode, const char *fmt, va_list args) +{ + struct devfs_entry *dir = NULL, *de; + char buf[64]; + int error, n; + + n = vsnprintf(buf, sizeof(buf), fmt, args); + if (n >= sizeof(buf) || !buf[0]) { + printk(KERN_WARNING "%s: invalid format string %s\n", + __FUNCTION__, fmt); + return -EINVAL; + } + + de = _devfs_prepare_leaf(&dir, buf, mode); + if (!de) { + printk(KERN_WARNING "%s: could not prepare leaf for %s\n", + __FUNCTION__, buf); + return -ENOMEM; /* could be more accurate... */ + } + + de->u.dev = dev; + + error = _devfs_append_entry(dir, de, NULL); + if (error) { + printk(KERN_WARNING "%s: could not append to parent for %s\n", + __FUNCTION__, buf); + goto out; + } + + devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED); + out: + devfs_put(dir); + return error; +} + +int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) +{ + va_list args; + + if (!S_ISBLK(mode)) { + printk(KERN_WARNING "%s: invalide mode (%u) for %s\n", + __FUNCTION__, mode, fmt); + return -EINVAL; + } + + va_start(args, fmt); + return devfs_mk_dev(dev, mode, fmt, args); +} + +EXPORT_SYMBOL(devfs_mk_bdev); + +int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) +{ + va_list args; + + if (!S_ISCHR(mode)) { + printk(KERN_WARNING "%s: invalide mode (%u) for %s\n", + __FUNCTION__, mode, fmt); + return -EINVAL; + } + + va_start(args, fmt); + return devfs_mk_dev(dev, mode, fmt, args); +} + +EXPORT_SYMBOL(devfs_mk_cdev); + +/** + * _devfs_unhook - Unhook a device entry from its parents list + * @de: The entry to unhook. + * + * Returns %TRUE if the entry was unhooked, else %FALSE if it was + * previously unhooked. + * The caller must have a write lock on the parent directory. + */ + +static int _devfs_unhook(struct devfs_entry *de) +{ + struct devfs_entry *parent; + + if (!de || (de->prev == de)) + return FALSE; + parent = de->parent; + if (de->prev == NULL) + parent->u.dir.first = de->next; + else + de->prev->next = de->next; + if (de->next == NULL) + parent->u.dir.last = de->prev; + else + de->next->prev = de->prev; + de->prev = de; /* Indicate we're unhooked */ + de->next = NULL; /* Force early termination for */ + return TRUE; +} /* End Function _devfs_unhook */ + +/** + * _devfs_unregister - Unregister a device entry from its parent. + * @dir: The parent directory. + * @de: The entry to unregister. + * + * The caller must have a write lock on the parent directory, which is + * unlocked by this function. + */ + +static void _devfs_unregister(struct devfs_entry *dir, struct devfs_entry *de) +{ + int unhooked = _devfs_unhook(de); + + write_unlock(&dir->u.dir.lock); + if (!unhooked) + return; + devfs_get(dir); + devfsd_notify(de, DEVFSD_NOTIFY_UNREGISTERED); + free_dentry(de); + devfs_put(dir); + if (!S_ISDIR(de->mode)) + return; + while (TRUE) { /* Recursively unregister: this is a stack chomper */ + struct devfs_entry *child; + + write_lock(&de->u.dir.lock); + de->u.dir.no_more_additions = TRUE; + child = de->u.dir.first; + VERIFY_ENTRY(child); + _devfs_unregister(de, child); + if (!child) + break; + DPRINTK(DEBUG_UNREGISTER, "(%s): child: %p refcount: %d\n", + child->name, child, atomic_read(&child->refcount)); + devfs_put(child); + } +} /* End Function _devfs_unregister */ + +static int devfs_do_symlink(devfs_handle_t dir, const char *name, + const char *link, devfs_handle_t * handle) +{ + int err; + unsigned int linklength; + char *newlink; + struct devfs_entry *de; + + if (handle != NULL) + *handle = NULL; + if (name == NULL) { + PRINTK("(): NULL name pointer\n"); + return -EINVAL; + } + if (link == NULL) { + PRINTK("(%s): NULL link pointer\n", name); + return -EINVAL; + } + linklength = strlen(link); + if ((newlink = kmalloc(linklength + 1, GFP_KERNEL)) == NULL) + return -ENOMEM; + memcpy(newlink, link, linklength); + newlink[linklength] = '\0'; + if ((de = _devfs_prepare_leaf(&dir, name, S_IFLNK | S_IRUGO | S_IXUGO)) + == NULL) { + PRINTK("(%s): could not prepare leaf\n", name); + kfree(newlink); + return -ENOTDIR; + } + de->info = NULL; + de->u.symlink.linkname = newlink; + de->u.symlink.length = linklength; + if ((err = _devfs_append_entry(dir, de, NULL)) != 0) { + PRINTK("(%s): could not append to parent, err: %d\n", name, + err); + devfs_put(dir); + return err; + } + devfs_put(dir); +#ifdef CONFIG_DEVFS_DEBUG + spin_lock(&stat_lock); + stat_num_bytes += linklength + 1; + spin_unlock(&stat_lock); +#endif + if (handle != NULL) + *handle = de; + return 0; +} /* End Function devfs_do_symlink */ + +/** + * devfs_mk_symlink Create a symbolic link in the devfs namespace. + * @from: The name of the entry. + * @to: Name of the destination + * + * Returns 0 on success, else a negative error code is returned. + */ + +int devfs_mk_symlink(const char *from, const char *to) +{ + devfs_handle_t de; + int err; + + err = devfs_do_symlink(NULL, from, to, &de); + if (!err) { + de->vfs = TRUE; + devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED); + } + + return err; +} + +/** + * devfs_mk_dir - Create a directory in the devfs namespace. + * new name is relative to the root of the devfs. + * @fmt: The name of the entry. + * + * Use of this function is optional. The devfs_register() function + * will automatically create intermediate directories as needed. This function + * is provided for efficiency reasons, as it provides a handle to a directory. + * On failure %NULL is returned. + */ + +int devfs_mk_dir(const char *fmt, ...) +{ + struct devfs_entry *dir = NULL, *de = NULL, *old; + char buf[64]; + va_list args; + int error, n; + + va_start(args, fmt); + n = vsnprintf(buf, 64, fmt, args); + if (n >= 64 || !buf[0]) { + printk(KERN_WARNING "%s: invalid argument.", __FUNCTION__); + return -EINVAL; + } + + de = _devfs_prepare_leaf(&dir, buf, MODE_DIR); + if (!de) { + PRINTK("(%s): could not prepare leaf\n", buf); + return -EINVAL; + } + + error = _devfs_append_entry(dir, de, &old); + if (error == -EEXIST && S_ISDIR(old->mode)) { + /* + * devfs_mk_dir() of an already-existing directory will + * return success. + */ + error = 0; + goto out_put; + } else if (error) { + PRINTK("(%s): could not append to dir: %p \"%s\"\n", + buf, dir, dir->name); + devfs_put(old); + goto out_put; + } + + devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED); + + out_put: + devfs_put(dir); + return error; +} + +void devfs_remove(const char *fmt, ...) +{ + char buf[64]; + va_list args; + int n; + + va_start(args, fmt); + n = vsnprintf(buf, sizeof(buf), fmt, args); + if (n < sizeof(buf) && buf[0]) { + devfs_handle_t de = _devfs_find_entry(NULL, buf, 0); + + if (!de) { + printk(KERN_ERR "%s: %s not found, cannot remove\n", + __FUNCTION__, buf); + dump_stack(); + return; + } + + write_lock(&de->parent->u.dir.lock); + _devfs_unregister(de->parent, de); + devfs_put(de); + devfs_put(de); + } +} + +/** + * devfs_generate_path - Generate a pathname for an entry, relative to the devfs root. + * @de: The devfs entry. + * @path: The buffer to write the pathname to. The pathname and '\0' + * terminator will be written at the end of the buffer. + * @buflen: The length of the buffer. + * + * Returns the offset in the buffer where the pathname starts on success, + * else a negative error code. + */ + +static int devfs_generate_path(devfs_handle_t de, char *path, int buflen) +{ + int pos; +#define NAMEOF(de) ( (de)->mode ? (de)->name : (de)->u.name ) + + if (de == NULL) + return -EINVAL; + VERIFY_ENTRY(de); + if (de->namelen >= buflen) + return -ENAMETOOLONG; /* Must be first */ + path[buflen - 1] = '\0'; + if (de->parent == NULL) + return buflen - 1; /* Don't prepend root */ + pos = buflen - de->namelen - 1; + memcpy(path + pos, NAMEOF(de), de->namelen); + for (de = de->parent; de->parent != NULL; de = de->parent) { + if (pos - de->namelen - 1 < 0) + return -ENAMETOOLONG; + path[--pos] = '/'; + pos -= de->namelen; + memcpy(path + pos, NAMEOF(de), de->namelen); + } + return pos; +} /* End Function devfs_generate_path */ + +/** + * devfs_setup - Process kernel boot options. + * @str: The boot options after the "devfs=". + */ + +static int __init devfs_setup(char *str) +{ + static struct { + char *name; + unsigned int mask; + unsigned int *opt; + } devfs_options_tab[] __initdata = { +#ifdef CONFIG_DEVFS_DEBUG + { + "dall", DEBUG_ALL, &devfs_debug_init}, { + "dmod", DEBUG_MODULE_LOAD, &devfs_debug_init}, { + "dreg", DEBUG_REGISTER, &devfs_debug_init}, { + "dunreg", DEBUG_UNREGISTER, &devfs_debug_init}, { + "dfree", DEBUG_FREE, &devfs_debug_init}, { + "diget", DEBUG_I_GET, &devfs_debug_init}, { + "dchange", DEBUG_SET_FLAGS, &devfs_debug_init}, { + "dsread", DEBUG_S_READ, &devfs_debug_init}, { + "dichange", DEBUG_I_CHANGE, &devfs_debug_init}, { + "dimknod", DEBUG_I_MKNOD, &devfs_debug_init}, { + "dilookup", DEBUG_I_LOOKUP, &devfs_debug_init}, { + "diunlink", DEBUG_I_UNLINK, &devfs_debug_init}, +#endif /* CONFIG_DEVFS_DEBUG */ + { + "mount", OPTION_MOUNT, &boot_options}, { + NULL, 0, NULL} + }; + + while ((*str != '\0') && !isspace(*str)) { + int i, found = 0, invert = 0; + + if (strncmp(str, "no", 2) == 0) { + invert = 1; + str += 2; + } + for (i = 0; devfs_options_tab[i].name != NULL; i++) { + int len = strlen(devfs_options_tab[i].name); + + if (strncmp(str, devfs_options_tab[i].name, len) == 0) { + if (invert) + *devfs_options_tab[i].opt &= + ~devfs_options_tab[i].mask; + else + *devfs_options_tab[i].opt |= + devfs_options_tab[i].mask; + str += len; + found = 1; + break; + } + } + if (!found) + return 0; /* No match */ + if (*str != ',') + return 0; /* No more options */ + ++str; + } + return 1; +} /* End Function devfs_setup */ + +__setup("devfs=", devfs_setup); + +EXPORT_SYMBOL(devfs_mk_dir); +EXPORT_SYMBOL(devfs_remove); + +/** + * try_modload - Notify devfsd of an inode lookup by a non-devfsd process. + * @parent: The parent devfs entry. + * @fs_info: The filesystem info. + * @name: The device name. + * @namelen: The number of characters in @name. + * @buf: A working area that will be used. This must not go out of scope + * until devfsd is idle again. + * + * Returns 0 on success (event was queued), else a negative error code. + */ + +static int try_modload(struct devfs_entry *parent, struct fs_info *fs_info, + const char *name, unsigned namelen, + struct devfs_entry *buf) +{ + if (!(fs_info->devfsd_event_mask & (1 << DEVFSD_NOTIFY_LOOKUP))) + return -ENOENT; + if (is_devfsd_or_child(fs_info)) + return -ENOENT; + memset(buf, 0, sizeof *buf); + atomic_set(&buf->refcount, 1); + buf->parent = parent; + buf->namelen = namelen; + buf->u.name = name; + WRITE_ENTRY_MAGIC(buf, MAGIC_VALUE); + if (!devfsd_notify_de(buf, DEVFSD_NOTIFY_LOOKUP, 0, + current->euid, current->egid, fs_info)) + return -ENOENT; + /* Possible success: event has been queued */ + return 0; +} /* End Function try_modload */ + +/* Superblock operations follow */ + +static struct inode_operations devfs_iops; +static struct inode_operations devfs_dir_iops; +static const struct file_operations devfs_fops; +static const struct file_operations devfs_dir_fops; +static struct inode_operations devfs_symlink_iops; + +static int devfs_notify_change(struct dentry *dentry, struct iattr *iattr) +{ + int retval; + struct devfs_entry *de; + struct inode *inode = dentry->d_inode; + struct fs_info *fs_info = inode->i_sb->s_fs_info; + + de = get_devfs_entry_from_vfs_inode(inode); + if (de == NULL) + return -ENODEV; + retval = inode_change_ok(inode, iattr); + if (retval != 0) + return retval; + retval = inode_setattr(inode, iattr); + if (retval != 0) + return retval; + DPRINTK(DEBUG_I_CHANGE, "(%d): VFS inode: %p devfs_entry: %p\n", + (int)inode->i_ino, inode, de); + DPRINTK(DEBUG_I_CHANGE, "(): mode: 0%o uid: %d gid: %d\n", + (int)inode->i_mode, (int)inode->i_uid, (int)inode->i_gid); + /* Inode is not on hash chains, thus must save permissions here rather + than in a write_inode() method */ + de->mode = inode->i_mode; + de->inode.uid = inode->i_uid; + de->inode.gid = inode->i_gid; + de->inode.atime = inode->i_atime; + de->inode.mtime = inode->i_mtime; + de->inode.ctime = inode->i_ctime; + if ((iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) && + !is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_CHANGE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + return 0; +} /* End Function devfs_notify_change */ + +static struct super_operations devfs_sops = { + .drop_inode = generic_delete_inode, + .statfs = simple_statfs, +}; + +/** + * _devfs_get_vfs_inode - Get a VFS inode. + * @sb: The super block. + * @de: The devfs inode. + * @dentry: The dentry to register with the devfs inode. + * + * Returns the inode on success, else %NULL. An implicit devfs_get() is + * performed if the inode is created. + */ + +static struct inode *_devfs_get_vfs_inode(struct super_block *sb, + struct devfs_entry *de, + struct dentry *dentry) +{ + struct inode *inode; + + if (de->prev == de) + return NULL; /* Quick check to see if unhooked */ + if ((inode = new_inode(sb)) == NULL) { + PRINTK("(%s): new_inode() failed, de: %p\n", de->name, de); + return NULL; + } + if (de->parent) { + read_lock(&de->parent->u.dir.lock); + if (de->prev != de) + de->inode.dentry = dentry; /* Not unhooked */ + read_unlock(&de->parent->u.dir.lock); + } else + de->inode.dentry = dentry; /* Root: no locking needed */ + if (de->inode.dentry != dentry) { /* Must have been unhooked */ + iput(inode); + return NULL; + } + /* FIXME where is devfs_put? */ + inode->u.generic_ip = devfs_get(de); + inode->i_ino = de->inode.ino; + DPRINTK(DEBUG_I_GET, "(%d): VFS inode: %p devfs_entry: %p\n", + (int)inode->i_ino, inode, de); + inode->i_blocks = 0; + inode->i_blksize = FAKE_BLOCK_SIZE; + inode->i_op = &devfs_iops; + inode->i_mode = de->mode; + if (S_ISDIR(de->mode)) { + inode->i_op = &devfs_dir_iops; + inode->i_fop = &devfs_dir_fops; + } else if (S_ISLNK(de->mode)) { + inode->i_op = &devfs_symlink_iops; + inode->i_size = de->u.symlink.length; + } else if (S_ISCHR(de->mode) || S_ISBLK(de->mode)) { + init_special_inode(inode, de->mode, de->u.dev); + } else if (S_ISFIFO(de->mode) || S_ISSOCK(de->mode)) { + init_special_inode(inode, de->mode, 0); + } else { + PRINTK("(%s): unknown mode %o de: %p\n", + de->name, de->mode, de); + iput(inode); + devfs_put(de); + return NULL; + } + + inode->i_uid = de->inode.uid; + inode->i_gid = de->inode.gid; + inode->i_atime = de->inode.atime; + inode->i_mtime = de->inode.mtime; + inode->i_ctime = de->inode.ctime; + DPRINTK(DEBUG_I_GET, "(): mode: 0%o uid: %d gid: %d\n", + (int)inode->i_mode, (int)inode->i_uid, (int)inode->i_gid); + return inode; +} /* End Function _devfs_get_vfs_inode */ + +/* File operations for device entries follow */ + +static int devfs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + int err, count; + int stored = 0; + struct fs_info *fs_info; + struct devfs_entry *parent, *de, *next = NULL; + struct inode *inode = file->f_dentry->d_inode; + + fs_info = inode->i_sb->s_fs_info; + parent = get_devfs_entry_from_vfs_inode(file->f_dentry->d_inode); + if ((long)file->f_pos < 0) + return -EINVAL; + DPRINTK(DEBUG_F_READDIR, "(%s): fs_info: %p pos: %ld\n", + parent->name, fs_info, (long)file->f_pos); + switch ((long)file->f_pos) { + case 0: + err = (*filldir) (dirent, "..", 2, file->f_pos, + parent_ino(file->f_dentry), DT_DIR); + if (err == -EINVAL) + break; + if (err < 0) + return err; + file->f_pos++; + ++stored; + /* Fall through */ + case 1: + err = + (*filldir) (dirent, ".", 1, file->f_pos, inode->i_ino, + DT_DIR); + if (err == -EINVAL) + break; + if (err < 0) + return err; + file->f_pos++; + ++stored; + /* Fall through */ + default: + /* Skip entries */ + count = file->f_pos - 2; + read_lock(&parent->u.dir.lock); + for (de = parent->u.dir.first; de && (count > 0); de = de->next) + --count; + devfs_get(de); + read_unlock(&parent->u.dir.lock); + /* Now add all remaining entries */ + while (de) { + err = (*filldir) (dirent, de->name, de->namelen, + file->f_pos, de->inode.ino, + de->mode >> 12); + if (err < 0) + devfs_put(de); + else { + file->f_pos++; + ++stored; + } + if (err == -EINVAL) + break; + if (err < 0) + return err; + read_lock(&parent->u.dir.lock); + next = devfs_get(de->next); + read_unlock(&parent->u.dir.lock); + devfs_put(de); + de = next; + } + break; + } + return stored; +} /* End Function devfs_readdir */ + +/* Open devfs specific special files */ +static int devfs_open(struct inode *inode, struct file *file) +{ + int err; + int minor = MINOR(inode->i_rdev); + struct file_operations *old_fops, *new_fops; + + switch (minor) { + case 0: /* /dev/.devfsd */ + new_fops = fops_get(&devfsd_fops); + break; +#ifdef CONFIG_DEVFS_DEBUG + case 1: /* /dev/.stat */ + new_fops = fops_get(&stat_fops); + break; +#endif + default: + return -ENODEV; + } + + if (new_fops == NULL) + return -ENODEV; + old_fops = file->f_op; + file->f_op = new_fops; + err = new_fops->open ? new_fops->open(inode, file) : 0; + if (err) { + file->f_op = old_fops; + fops_put(new_fops); + } else + fops_put(old_fops); + return err; +} /* End Function devfs_open */ + +static const struct file_operations devfs_fops = { + .open = devfs_open, +}; + +static const struct file_operations devfs_dir_fops = { + .read = generic_read_dir, + .readdir = devfs_readdir, +}; + +/* Dentry operations for device entries follow */ + +/** + * devfs_d_release - Callback for when a dentry is freed. + * @dentry: The dentry. + */ + +static void devfs_d_release(struct dentry *dentry) +{ + DPRINTK(DEBUG_D_RELEASE, "(%p): inode: %p\n", dentry, dentry->d_inode); +} /* End Function devfs_d_release */ + +/** + * devfs_d_iput - Callback for when a dentry loses its inode. + * @dentry: The dentry. + * @inode: The inode. + */ + +static void devfs_d_iput(struct dentry *dentry, struct inode *inode) +{ + struct devfs_entry *de; + + de = get_devfs_entry_from_vfs_inode(inode); + DPRINTK(DEBUG_D_IPUT, + "(%s): dentry: %p inode: %p de: %p de->dentry: %p\n", de->name, + dentry, inode, de, de->inode.dentry); + if (de->inode.dentry && (de->inode.dentry != dentry)) + OOPS("(%s): de: %p dentry: %p de->dentry: %p\n", + de->name, de, dentry, de->inode.dentry); + de->inode.dentry = NULL; + iput(inode); + devfs_put(de); +} /* End Function devfs_d_iput */ + +static int devfs_d_delete(struct dentry *dentry); + +static struct dentry_operations devfs_dops = { + .d_delete = devfs_d_delete, + .d_release = devfs_d_release, + .d_iput = devfs_d_iput, +}; + +static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *); + +static struct dentry_operations devfs_wait_dops = { + .d_delete = devfs_d_delete, + .d_release = devfs_d_release, + .d_iput = devfs_d_iput, + .d_revalidate = devfs_d_revalidate_wait, +}; + +/** + * devfs_d_delete - Callback for when all files for a dentry are closed. + * @dentry: The dentry. + */ + +static int devfs_d_delete(struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + + if (dentry->d_op == &devfs_wait_dops) + dentry->d_op = &devfs_dops; + /* Unhash dentry if negative (has no inode) */ + if (inode == NULL) { + DPRINTK(DEBUG_D_DELETE, "(%p): dropping negative dentry\n", + dentry); + return 1; + } + return 0; +} /* End Function devfs_d_delete */ + +struct devfs_lookup_struct { + devfs_handle_t de; + wait_queue_head_t wait_queue; +}; + +/* XXX: this doesn't handle the case where we got a negative dentry + but a devfs entry has been registered in the meanwhile */ +static int devfs_d_revalidate_wait(struct dentry *dentry, struct nameidata *nd) +{ + struct inode *dir = dentry->d_parent->d_inode; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + devfs_handle_t parent = get_devfs_entry_from_vfs_inode(dir); + struct devfs_lookup_struct *lookup_info = dentry->d_fsdata; + DECLARE_WAITQUEUE(wait, current); + int need_lock; + + /* + * FIXME HACK + * + * make sure that + * d_instantiate always runs under lock + * we release i_mutex lock before going to sleep + * + * unfortunately sometimes d_revalidate is called with + * and sometimes without i_mutex lock held. The following checks + * attempt to deduce when we need to add (and drop resp.) lock + * here. This relies on current (2.6.2) calling coventions: + * + * lookup_hash is always run under i_mutex and is passing NULL + * as nd + * + * open(...,O_CREATE,...) calls _lookup_hash under i_mutex + * and sets flags to LOOKUP_OPEN|LOOKUP_CREATE + * + * all other invocations of ->d_revalidate seem to happen + * outside of i_mutex + */ + need_lock = nd && + (!(nd->flags & LOOKUP_CREATE) || (nd->flags & LOOKUP_PARENT)); + + if (need_lock) + mutex_lock(&dir->i_mutex); + + if (is_devfsd_or_child(fs_info)) { + devfs_handle_t de = lookup_info->de; + struct inode *inode; + + DPRINTK(DEBUG_I_LOOKUP, + "(%s): dentry: %p inode: %p de: %p by: \"%s\"\n", + dentry->d_name.name, dentry, dentry->d_inode, de, + current->comm); + if (dentry->d_inode) + goto out; + if (de == NULL) { + read_lock(&parent->u.dir.lock); + de = _devfs_search_dir(parent, dentry->d_name.name, + dentry->d_name.len); + read_unlock(&parent->u.dir.lock); + if (de == NULL) + goto out; + lookup_info->de = de; + } + /* Create an inode, now that the driver information is available */ + inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry); + if (!inode) + goto out; + DPRINTK(DEBUG_I_LOOKUP, + "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n", + de->name, de->inode.ino, inode, de, current->comm); + d_instantiate(dentry, inode); + goto out; + } + if (lookup_info == NULL) + goto out; /* Early termination */ + read_lock(&parent->u.dir.lock); + if (dentry->d_fsdata) { + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&lookup_info->wait_queue, &wait); + read_unlock(&parent->u.dir.lock); + /* at this point it is always (hopefully) locked */ + mutex_unlock(&dir->i_mutex); + schedule(); + mutex_lock(&dir->i_mutex); + /* + * This does not need nor should remove wait from wait_queue. + * Wait queue head is never reused - nothing is ever added to it + * after all waiters have been waked up and head itself disappears + * very soon after it. Moreover it is local variable on stack that + * is likely to have already disappeared so any reference to it + * at this point is buggy. + */ + + } else + read_unlock(&parent->u.dir.lock); + + out: + if (need_lock) + mutex_unlock(&dir->i_mutex); + return 1; +} /* End Function devfs_d_revalidate_wait */ + +/* Inode operations for device entries follow */ + +static struct dentry *devfs_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) +{ + struct devfs_entry tmp; /* Must stay in scope until devfsd idle again */ + struct devfs_lookup_struct lookup_info; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + struct devfs_entry *parent, *de; + struct inode *inode; + struct dentry *retval = NULL; + + /* Set up the dentry operations before anything else, to ensure cleaning + up on any error */ + dentry->d_op = &devfs_dops; + /* First try to get the devfs entry for this directory */ + parent = get_devfs_entry_from_vfs_inode(dir); + DPRINTK(DEBUG_I_LOOKUP, "(%s): dentry: %p parent: %p by: \"%s\"\n", + dentry->d_name.name, dentry, parent, current->comm); + if (parent == NULL) + return ERR_PTR(-ENOENT); + read_lock(&parent->u.dir.lock); + de = _devfs_search_dir(parent, dentry->d_name.name, dentry->d_name.len); + read_unlock(&parent->u.dir.lock); + lookup_info.de = de; + init_waitqueue_head(&lookup_info.wait_queue); + dentry->d_fsdata = &lookup_info; + if (de == NULL) { /* Try with devfsd. For any kind of failure, leave a negative dentry + so someone else can deal with it (in the case where the sysadmin + does a mknod()). It's important to do this before hashing the + dentry, so that the devfsd queue is filled before revalidates + can start */ + if (try_modload(parent, fs_info, dentry->d_name.name, dentry->d_name.len, &tmp) < 0) { /* Lookup event was not queued to devfsd */ + d_add(dentry, NULL); + return NULL; + } + } + dentry->d_op = &devfs_wait_dops; + d_add(dentry, NULL); /* Open the floodgates */ + /* Unlock directory semaphore, which will release any waiters. They + will get the hashed dentry, and may be forced to wait for + revalidation */ + mutex_unlock(&dir->i_mutex); + wait_for_devfsd_finished(fs_info); /* If I'm not devfsd, must wait */ + mutex_lock(&dir->i_mutex); /* Grab it again because them's the rules */ + de = lookup_info.de; + /* If someone else has been so kind as to make the inode, we go home + early */ + if (dentry->d_inode) + goto out; + if (de == NULL) { + read_lock(&parent->u.dir.lock); + de = _devfs_search_dir(parent, dentry->d_name.name, + dentry->d_name.len); + read_unlock(&parent->u.dir.lock); + if (de == NULL) + goto out; + /* OK, there's an entry now, but no VFS inode yet */ + } + /* Create an inode, now that the driver information is available */ + inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry); + if (!inode) { + retval = ERR_PTR(-ENOMEM); + goto out; + } + DPRINTK(DEBUG_I_LOOKUP, + "(%s): new VFS inode(%u): %p de: %p by: \"%s\"\n", de->name, + de->inode.ino, inode, de, current->comm); + d_instantiate(dentry, inode); + out: + write_lock(&parent->u.dir.lock); + dentry->d_op = &devfs_dops; + dentry->d_fsdata = NULL; + wake_up(&lookup_info.wait_queue); + write_unlock(&parent->u.dir.lock); + devfs_put(de); + return retval; +} /* End Function devfs_lookup */ + +static int devfs_unlink(struct inode *dir, struct dentry *dentry) +{ + int unhooked; + struct devfs_entry *de; + struct inode *inode = dentry->d_inode; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + + de = get_devfs_entry_from_vfs_inode(inode); + DPRINTK(DEBUG_I_UNLINK, "(%s): de: %p\n", dentry->d_name.name, de); + if (de == NULL) + return -ENOENT; + if (!de->vfs) + return -EPERM; + write_lock(&de->parent->u.dir.lock); + unhooked = _devfs_unhook(de); + write_unlock(&de->parent->u.dir.lock); + if (!unhooked) + return -ENOENT; + if (!is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_DELETE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + free_dentry(de); + devfs_put(de); + return 0; +} /* End Function devfs_unlink */ + +static int devfs_symlink(struct inode *dir, struct dentry *dentry, + const char *symname) +{ + int err; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + struct devfs_entry *parent, *de; + struct inode *inode; + + /* First try to get the devfs entry for this directory */ + parent = get_devfs_entry_from_vfs_inode(dir); + if (parent == NULL) + return -ENOENT; + err = devfs_do_symlink(parent, dentry->d_name.name, symname, &de); + DPRINTK(DEBUG_DISABLED, "(%s): errcode from : %d\n", + dentry->d_name.name, err); + if (err < 0) + return err; + de->vfs = TRUE; + de->inode.uid = current->euid; + de->inode.gid = current->egid; + de->inode.atime = CURRENT_TIME; + de->inode.mtime = CURRENT_TIME; + de->inode.ctime = CURRENT_TIME; + if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL) + return -ENOMEM; + DPRINTK(DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n", + dentry->d_name.name, de->inode.ino, inode, dentry); + d_instantiate(dentry, inode); + if (!is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + return 0; +} /* End Function devfs_symlink */ + +static int devfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +{ + int err; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + struct devfs_entry *parent, *de; + struct inode *inode; + + mode = (mode & ~S_IFMT) | S_IFDIR; /* VFS doesn't pass S_IFMT part */ + parent = get_devfs_entry_from_vfs_inode(dir); + if (parent == NULL) + return -ENOENT; + de = _devfs_alloc_entry(dentry->d_name.name, dentry->d_name.len, mode); + if (!de) + return -ENOMEM; + de->vfs = TRUE; + if ((err = _devfs_append_entry(parent, de, NULL)) != 0) + return err; + de->inode.uid = current->euid; + de->inode.gid = current->egid; + de->inode.atime = CURRENT_TIME; + de->inode.mtime = CURRENT_TIME; + de->inode.ctime = CURRENT_TIME; + if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL) + return -ENOMEM; + DPRINTK(DEBUG_DISABLED, "(%s): new VFS inode(%u): %p dentry: %p\n", + dentry->d_name.name, de->inode.ino, inode, dentry); + d_instantiate(dentry, inode); + if (!is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + return 0; +} /* End Function devfs_mkdir */ + +static int devfs_rmdir(struct inode *dir, struct dentry *dentry) +{ + int err = 0; + struct devfs_entry *de; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + struct inode *inode = dentry->d_inode; + + if (dir->i_sb->s_fs_info != inode->i_sb->s_fs_info) + return -EINVAL; + de = get_devfs_entry_from_vfs_inode(inode); + if (de == NULL) + return -ENOENT; + if (!S_ISDIR(de->mode)) + return -ENOTDIR; + if (!de->vfs) + return -EPERM; + /* First ensure the directory is empty and will stay that way */ + write_lock(&de->u.dir.lock); + if (de->u.dir.first) + err = -ENOTEMPTY; + else + de->u.dir.no_more_additions = TRUE; + write_unlock(&de->u.dir.lock); + if (err) + return err; + /* Now unhook the directory from its parent */ + write_lock(&de->parent->u.dir.lock); + if (!_devfs_unhook(de)) + err = -ENOENT; + write_unlock(&de->parent->u.dir.lock); + if (err) + return err; + if (!is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_DELETE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + free_dentry(de); + devfs_put(de); + return 0; +} /* End Function devfs_rmdir */ + +static int devfs_mknod(struct inode *dir, struct dentry *dentry, int mode, + dev_t rdev) +{ + int err; + struct fs_info *fs_info = dir->i_sb->s_fs_info; + struct devfs_entry *parent, *de; + struct inode *inode; + + DPRINTK(DEBUG_I_MKNOD, "(%s): mode: 0%o dev: %u:%u\n", + dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); + parent = get_devfs_entry_from_vfs_inode(dir); + if (parent == NULL) + return -ENOENT; + de = _devfs_alloc_entry(dentry->d_name.name, dentry->d_name.len, mode); + if (!de) + return -ENOMEM; + de->vfs = TRUE; + if (S_ISCHR(mode) || S_ISBLK(mode)) + de->u.dev = rdev; + if ((err = _devfs_append_entry(parent, de, NULL)) != 0) + return err; + de->inode.uid = current->euid; + de->inode.gid = current->egid; + de->inode.atime = CURRENT_TIME; + de->inode.mtime = CURRENT_TIME; + de->inode.ctime = CURRENT_TIME; + if ((inode = _devfs_get_vfs_inode(dir->i_sb, de, dentry)) == NULL) + return -ENOMEM; + DPRINTK(DEBUG_I_MKNOD, ": new VFS inode(%u): %p dentry: %p\n", + de->inode.ino, inode, dentry); + d_instantiate(dentry, inode); + if (!is_devfsd_or_child(fs_info)) + devfsd_notify_de(de, DEVFSD_NOTIFY_CREATE, inode->i_mode, + inode->i_uid, inode->i_gid, fs_info); + return 0; +} /* End Function devfs_mknod */ + +static void *devfs_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + struct devfs_entry *p = get_devfs_entry_from_vfs_inode(dentry->d_inode); + nd_set_link(nd, p ? p->u.symlink.linkname : ERR_PTR(-ENODEV)); + return NULL; +} /* End Function devfs_follow_link */ + +static struct inode_operations devfs_iops = { + .setattr = devfs_notify_change, +}; + +static struct inode_operations devfs_dir_iops = { + .lookup = devfs_lookup, + .unlink = devfs_unlink, + .symlink = devfs_symlink, + .mkdir = devfs_mkdir, + .rmdir = devfs_rmdir, + .mknod = devfs_mknod, + .setattr = devfs_notify_change, +}; + +static struct inode_operations devfs_symlink_iops = { + .readlink = generic_readlink, + .follow_link = devfs_follow_link, + .setattr = devfs_notify_change, +}; + +static int devfs_fill_super(struct super_block *sb, void *data, int silent) +{ + struct inode *root_inode = NULL; + + if (_devfs_get_root_entry() == NULL) + goto out_no_root; + atomic_set(&fs_info.devfsd_overrun_count, 0); + init_waitqueue_head(&fs_info.devfsd_wait_queue); + init_waitqueue_head(&fs_info.revalidate_wait_queue); + fs_info.sb = sb; + sb->s_fs_info = &fs_info; + sb->s_blocksize = 1024; + sb->s_blocksize_bits = 10; + sb->s_magic = DEVFS_SUPER_MAGIC; + sb->s_op = &devfs_sops; + sb->s_time_gran = 1; + if ((root_inode = _devfs_get_vfs_inode(sb, root_entry, NULL)) == NULL) + goto out_no_root; + sb->s_root = d_alloc_root(root_inode); + if (!sb->s_root) + goto out_no_root; + DPRINTK(DEBUG_S_READ, "(): made devfs ptr: %p\n", sb->s_fs_info); + return 0; + + out_no_root: + PRINTK("(): get root inode failed\n"); + if (root_inode) + iput(root_inode); + return -EINVAL; +} /* End Function devfs_fill_super */ + +static int devfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) +{ + return get_sb_single(fs_type, flags, data, devfs_fill_super, mnt); +} + +static struct file_system_type devfs_fs_type = { + .name = DEVFS_NAME, + .get_sb = devfs_get_sb, + .kill_sb = kill_anon_super, +}; + +/* File operations for devfsd follow */ + +static ssize_t devfsd_read(struct file *file, char __user *buf, size_t len, + loff_t * ppos) +{ + int done = FALSE; + int ival; + loff_t pos, devname_offset, tlen, rpos; + devfs_handle_t de; + struct devfsd_buf_entry *entry; + struct fs_info *fs_info = file->f_dentry->d_inode->i_sb->s_fs_info; + struct devfsd_notify_struct *info = fs_info->devfsd_info; + DECLARE_WAITQUEUE(wait, current); + + /* Verify the task has grabbed the queue */ + if (fs_info->devfsd_task != current) + return -EPERM; + info->major = 0; + info->minor = 0; + /* Block for a new entry */ + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&fs_info->devfsd_wait_queue, &wait); + while (devfsd_queue_empty(fs_info)) { + fs_info->devfsd_sleeping = TRUE; + wake_up(&fs_info->revalidate_wait_queue); + schedule(); + fs_info->devfsd_sleeping = FALSE; + if (signal_pending(current)) { + remove_wait_queue(&fs_info->devfsd_wait_queue, &wait); + __set_current_state(TASK_RUNNING); + return -EINTR; + } + set_current_state(TASK_INTERRUPTIBLE); + } + remove_wait_queue(&fs_info->devfsd_wait_queue, &wait); + __set_current_state(TASK_RUNNING); + /* Now play with the data */ + ival = atomic_read(&fs_info->devfsd_overrun_count); + info->overrun_count = ival; + entry = fs_info->devfsd_first_event; + info->type = entry->type; + info->mode = entry->mode; + info->uid = entry->uid; + info->gid = entry->gid; + de = entry->de; + if (S_ISCHR(de->mode) || S_ISBLK(de->mode)) { + info->major = MAJOR(de->u.dev); + info->minor = MINOR(de->u.dev); + } + pos = devfs_generate_path(de, info->devname, DEVFS_PATHLEN); + if (pos < 0) + return pos; + info->namelen = DEVFS_PATHLEN - pos - 1; + if (info->mode == 0) + info->mode = de->mode; + devname_offset = info->devname - (char *)info; + rpos = *ppos; + if (rpos < devname_offset) { + /* Copy parts of the header */ + tlen = devname_offset - rpos; + if (tlen > len) + tlen = len; + if (copy_to_user(buf, (char *)info + rpos, tlen)) { + return -EFAULT; + } + rpos += tlen; + buf += tlen; + len -= tlen; + } + if ((rpos >= devname_offset) && (len > 0)) { + /* Copy the name */ + tlen = info->namelen + 1; + if (tlen > len) + tlen = len; + else + done = TRUE; + if (copy_to_user + (buf, info->devname + pos + rpos - devname_offset, tlen)) { + return -EFAULT; + } + rpos += tlen; + } + tlen = rpos - *ppos; + if (done) { + devfs_handle_t parent; + + spin_lock(&fs_info->devfsd_buffer_lock); + fs_info->devfsd_first_event = entry->next; + if (entry->next == NULL) + fs_info->devfsd_last_event = NULL; + spin_unlock(&fs_info->devfsd_buffer_lock); + for (; de != NULL; de = parent) { + parent = de->parent; + devfs_put(de); + } + kmem_cache_free(devfsd_buf_cache, entry); + if (ival > 0) + atomic_sub(ival, &fs_info->devfsd_overrun_count); + *ppos = 0; + } else + *ppos = rpos; + return tlen; +} /* End Function devfsd_read */ + +static int devfsd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ival; + struct fs_info *fs_info = inode->i_sb->s_fs_info; + + switch (cmd) { + case DEVFSDIOC_GET_PROTO_REV: + ival = DEVFSD_PROTOCOL_REVISION_KERNEL; + if (copy_to_user((void __user *)arg, &ival, sizeof ival)) + return -EFAULT; + break; + case DEVFSDIOC_SET_EVENT_MASK: + /* Ensure only one reader has access to the queue. This scheme will + work even if the global kernel lock were to be removed, because it + doesn't matter who gets in first, as long as only one gets it */ + if (fs_info->devfsd_task == NULL) { + static DEFINE_SPINLOCK(lock); + + if (!spin_trylock(&lock)) + return -EBUSY; + if (fs_info->devfsd_task != NULL) { /* We lost the race... */ + spin_unlock(&lock); + return -EBUSY; + } + fs_info->devfsd_task = current; + spin_unlock(&lock); + 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); + if (!fs_info->devfsd_info) { + devfsd_close(inode, file); + return -ENOMEM; + } + } else if (fs_info->devfsd_task != current) + return -EBUSY; + fs_info->devfsd_event_mask = arg; /* Let the masses come forth */ + break; + case DEVFSDIOC_RELEASE_EVENT_QUEUE: + if (fs_info->devfsd_file != file) + return -EPERM; + return devfsd_close(inode, file); + /*break; */ +#ifdef CONFIG_DEVFS_DEBUG + case DEVFSDIOC_SET_DEBUG_MASK: + if (copy_from_user(&ival, (void __user *)arg, sizeof ival)) + return -EFAULT; + devfs_debug = ival; + break; +#endif + default: + return -ENOIOCTLCMD; + } + return 0; +} /* End Function devfsd_ioctl */ + +static int devfsd_close(struct inode *inode, struct file *file) +{ + struct devfsd_buf_entry *entry, *next; + struct fs_info *fs_info = inode->i_sb->s_fs_info; + + if (fs_info->devfsd_file != file) + return 0; + fs_info->devfsd_event_mask = 0; + fs_info->devfsd_file = NULL; + spin_lock(&fs_info->devfsd_buffer_lock); + entry = fs_info->devfsd_first_event; + fs_info->devfsd_first_event = NULL; + fs_info->devfsd_last_event = NULL; + kfree(fs_info->devfsd_info); + fs_info->devfsd_info = NULL; + spin_unlock(&fs_info->devfsd_buffer_lock); + fs_info->devfsd_pgrp = 0; + fs_info->devfsd_task = NULL; + wake_up(&fs_info->revalidate_wait_queue); + for (; entry; entry = next) { + next = entry->next; + kmem_cache_free(devfsd_buf_cache, entry); + } + return 0; +} /* End Function devfsd_close */ + +#ifdef CONFIG_DEVFS_DEBUG +static ssize_t stat_read(struct file *file, char __user *buf, size_t len, + loff_t * ppos) +{ + ssize_t num; + char txt[80]; + + num = sprintf(txt, "Number of entries: %u number of bytes: %u\n", + stat_num_entries, stat_num_bytes) + 1; + if (*ppos >= num) + return 0; + if (*ppos + len > num) + len = num - *ppos; + if (copy_to_user(buf, txt + *ppos, len)) + return -EFAULT; + *ppos += len; + return len; +} /* End Function stat_read */ +#endif + +static int __init init_devfs_fs(void) +{ + int err; + int major; + struct devfs_entry *devfsd; +#ifdef CONFIG_DEVFS_DEBUG + struct devfs_entry *stat; +#endif + + if (_devfs_get_root_entry() == NULL) + return -ENOMEM; + + printk(KERN_INFO "%s: %s Richard Gooch (rgooch@atnf.csiro.au)\n", + DEVFS_NAME, DEVFS_VERSION); + devfsd_buf_cache = kmem_cache_create("devfsd_event", + sizeof(struct devfsd_buf_entry), + 0, 0, NULL, NULL); + if (!devfsd_buf_cache) + OOPS("(): unable to allocate event slab\n"); +#ifdef CONFIG_DEVFS_DEBUG + devfs_debug = devfs_debug_init; + printk(KERN_INFO "%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug); +#endif + printk(KERN_INFO "%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options); + + /* register special device for devfsd communication */ + major = register_chrdev(0, "devfs", &devfs_fops); + if (major < 0) + return major; + + /* And create the entry for ".devfsd" */ + devfsd = _devfs_alloc_entry(".devfsd", 0, S_IFCHR | S_IRUSR | S_IWUSR); + if (devfsd == NULL) + return -ENOMEM; + devfsd->u.dev = MKDEV(major, 0); + _devfs_append_entry(root_entry, devfsd, NULL); + +#ifdef CONFIG_DEVFS_DEBUG + stat = _devfs_alloc_entry(".stat", 0, S_IFCHR | S_IRUGO); + if (stat == NULL) + return -ENOMEM; + stat->u.dev = MKDEV(major, 1); + _devfs_append_entry(root_entry, stat, NULL); +#endif + + err = register_filesystem(&devfs_fs_type); + return err; +} /* End Function init_devfs_fs */ + +void __init mount_devfs_fs(void) +{ + int err; + + if (!(boot_options & OPTION_MOUNT)) + return; + err = do_mount("none", "/dev", "devfs", 0, NULL); + if (err == 0) + printk(KERN_INFO "Mounted devfs on /dev\n"); + else + PRINTK("(): unable to mount devfs, err: %d\n", err); +} /* End Function mount_devfs_fs */ + +module_init(init_devfs_fs) diff --git a/trunk/fs/devfs/util.c b/trunk/fs/devfs/util.c new file mode 100644 index 000000000000..db06d388c9ac --- /dev/null +++ b/trunk/fs/devfs/util.c @@ -0,0 +1,97 @@ +/* devfs (Device FileSystem) utilities. + + Copyright (C) 1999-2002 Richard Gooch + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Richard Gooch may be reached by email at rgooch@atnf.csiro.au + The postal address is: + Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. + + ChangeLog + + 19991031 Richard Gooch + Created. + 19991103 Richard Gooch + Created <_devfs_convert_name> and supported SCSI and IDE CD-ROMs + 20000203 Richard Gooch + Changed operations pointer type to void *. + 20000621 Richard Gooch + Changed interface to . + 20000622 Richard Gooch + Took account of interface change to . + Took account of interface change to . + 20010519 Richard Gooch + Documentation cleanup. + 20010709 Richard Gooch + Created and . + 20010710 Richard Gooch + Created . + 20010730 Richard Gooch + Documentation typo fix. + 20010806 Richard Gooch + Made and private. + 20010813 Richard Gooch + Fixed bug in : limited to 128 numbers + 20010818 Richard Gooch + Updated major masks up to Linus' "no new majors" proclamation. + Block: were 126 now 122 free, char: were 26 now 19 free. + 20020324 Richard Gooch + Fixed bug in : was clearing beyond + bitfield. + 20020326 Richard Gooch + Fixed bitfield data type for . + Made major bitfield type and initialiser 64 bit safe. + 20020413 Richard Gooch + Fixed shift warning on 64 bit machines. + 20020428 Richard Gooch + Copied and used macro for error messages from fs/devfs/base.c + 20021013 Richard Gooch + Documentation fix. + 20030101 Adam J. Richter + Eliminate DEVFS_SPECIAL_{CHR,BLK}. Use mode_t instead. + 20030106 Christoph Hellwig + Rewrite devfs_{,de}alloc_devnum to look like C code. +*/ +#include +#include +#include +#include +#include +#include +#include + +int devfs_register_tape(const char *name) +{ + char tname[32], dest[64]; + static unsigned int tape_counter; + unsigned int n = tape_counter++; + + sprintf(dest, "../%s", name); + sprintf(tname, "tapes/tape%u", n); + devfs_mk_symlink(tname, dest); + + return n; +} + +EXPORT_SYMBOL(devfs_register_tape); + +void devfs_unregister_tape(int num) +{ + if (num >= 0) + devfs_remove("tapes/tape%u", num); +} + +EXPORT_SYMBOL(devfs_unregister_tape); diff --git a/trunk/fs/dquot.c b/trunk/fs/dquot.c index 0122a279106a..81d87a413c68 100644 --- a/trunk/fs/dquot.c +++ b/trunk/fs/dquot.c @@ -250,7 +250,7 @@ static inline struct dquot *find_dquot(unsigned int hashent, struct super_block /* Add a dquot to the tail of the free list */ static inline void put_dquot_last(struct dquot *dquot) { - list_add_tail(&dquot->dq_free, &free_dquots); + list_add(&dquot->dq_free, free_dquots.prev); dqstats.free_dquots++; } @@ -266,7 +266,7 @@ static inline void put_inuse(struct dquot *dquot) { /* We add to the back of inuse list so we don't have to restart * when traversing this list and we block */ - list_add_tail(&dquot->dq_inuse, &inuse_list); + list_add(&dquot->dq_inuse, inuse_list.prev); dqstats.allocated_dquots++; } diff --git a/trunk/fs/efs/inode.c b/trunk/fs/efs/inode.c index 174696f9bf14..180607f9314d 100644 --- a/trunk/fs/efs/inode.c +++ b/trunk/fs/efs/inode.c @@ -21,7 +21,7 @@ static sector_t _efs_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping,block,efs_get_block); } -static const struct address_space_operations efs_aops = { +static struct address_space_operations efs_aops = { .readpage = efs_readpage, .sync_page = block_sync_page, .bmap = _efs_bmap diff --git a/trunk/fs/efs/symlink.c b/trunk/fs/efs/symlink.c index e249cf733a6b..3d9a350e3e7f 100644 --- a/trunk/fs/efs/symlink.c +++ b/trunk/fs/efs/symlink.c @@ -53,6 +53,6 @@ static int efs_symlink_readpage(struct file *file, struct page *page) return err; } -const struct address_space_operations efs_symlink_aops = { +struct address_space_operations efs_symlink_aops = { .readpage = efs_symlink_readpage }; diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index 8344ba73a2a6..0b88bf646143 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -22,6 +22,7 @@ * formats. */ +#include #include #include #include @@ -665,6 +666,8 @@ static int de_thread(struct task_struct *tsk) * and to assume its PID: */ if (!thread_group_leader(current)) { + struct dentry *proc_dentry1, *proc_dentry2; + /* * Wait for the thread group leader to be a zombie. * It should already be zombie at this point, most @@ -686,6 +689,10 @@ static int de_thread(struct task_struct *tsk) */ current->start_time = leader->start_time; + spin_lock(&leader->proc_lock); + spin_lock(¤t->proc_lock); + proc_dentry1 = proc_pid_unhash(current); + proc_dentry2 = proc_pid_unhash(leader); write_lock_irq(&tasklist_lock); BUG_ON(leader->tgid != current->tgid); @@ -706,7 +713,7 @@ static int de_thread(struct task_struct *tsk) attach_pid(current, PIDTYPE_PID, current->pid); attach_pid(current, PIDTYPE_PGID, current->signal->pgrp); attach_pid(current, PIDTYPE_SID, current->signal->session); - list_replace_rcu(&leader->tasks, ¤t->tasks); + list_add_tail_rcu(¤t->tasks, &init_task.tasks); current->group_leader = current; leader->group_leader = current; @@ -714,6 +721,7 @@ static int de_thread(struct task_struct *tsk) /* Reduce leader to a thread */ detach_pid(leader, PIDTYPE_PGID); detach_pid(leader, PIDTYPE_SID); + list_del_init(&leader->tasks); current->exit_signal = SIGCHLD; @@ -721,6 +729,10 @@ static int de_thread(struct task_struct *tsk) leader->exit_state = EXIT_DEAD; write_unlock_irq(&tasklist_lock); + spin_unlock(&leader->proc_lock); + spin_unlock(¤t->proc_lock); + proc_pid_flush(proc_dentry1); + proc_pid_flush(proc_dentry2); } /* @@ -1367,102 +1379,67 @@ static void format_corename(char *corename, const char *pattern, long signr) *out_ptr = 0; } -static void zap_process(struct task_struct *start) -{ - struct task_struct *t; - - start->signal->flags = SIGNAL_GROUP_EXIT; - start->signal->group_stop_count = 0; - - t = start; - do { - if (t != current && t->mm) { - t->mm->core_waiters++; - sigaddset(&t->pending.signal, SIGKILL); - signal_wake_up(t, 1); - } - } while ((t = next_thread(t)) != start); -} - -static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, - int exit_code) +static void zap_threads (struct mm_struct *mm) { struct task_struct *g, *p; - unsigned long flags; - int err = -EAGAIN; - - spin_lock_irq(&tsk->sighand->siglock); - if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) { - tsk->signal->group_exit_code = exit_code; - zap_process(tsk); - err = 0; + struct task_struct *tsk = current; + struct completion *vfork_done = tsk->vfork_done; + int traced = 0; + + /* + * Make sure nobody is waiting for us to release the VM, + * otherwise we can deadlock when we wait on each other + */ + if (vfork_done) { + tsk->vfork_done = NULL; + complete(vfork_done); } - spin_unlock_irq(&tsk->sighand->siglock); - if (err) - return err; - if (atomic_read(&mm->mm_users) == mm->core_waiters + 1) - goto done; + read_lock(&tasklist_lock); + do_each_thread(g,p) + if (mm == p->mm && p != tsk) { + force_sig_specific(SIGKILL, p); + mm->core_waiters++; + if (unlikely(p->ptrace) && + unlikely(p->parent->mm == mm)) + traced = 1; + } + while_each_thread(g,p); - rcu_read_lock(); - for_each_process(g) { - if (g == tsk->group_leader) - continue; + read_unlock(&tasklist_lock); - p = g; - do { - if (p->mm) { - if (p->mm == mm) { - /* - * p->sighand can't disappear, but - * may be changed by de_thread() - */ - lock_task_sighand(p, &flags); - zap_process(p); - unlock_task_sighand(p, &flags); - } - break; + if (unlikely(traced)) { + /* + * We are zapping a thread and the thread it ptraces. + * If the tracee went into a ptrace stop for exit tracing, + * we could deadlock since the tracer is waiting for this + * coredump to finish. Detach them so they can both die. + */ + write_lock_irq(&tasklist_lock); + do_each_thread(g,p) { + if (mm == p->mm && p != tsk && + p->ptrace && p->parent->mm == mm) { + __ptrace_detach(p, 0); } - } while ((p = next_thread(p)) != g); + } while_each_thread(g,p); + write_unlock_irq(&tasklist_lock); } - rcu_read_unlock(); -done: - return mm->core_waiters; } -static int coredump_wait(int exit_code) +static void coredump_wait(struct mm_struct *mm) { - struct task_struct *tsk = current; - struct mm_struct *mm = tsk->mm; - struct completion startup_done; - struct completion *vfork_done; + DECLARE_COMPLETION(startup_done); int core_waiters; - init_completion(&mm->core_done); - init_completion(&startup_done); mm->core_startup_done = &startup_done; - core_waiters = zap_threads(tsk, mm, exit_code); + zap_threads(mm); + core_waiters = mm->core_waiters; up_write(&mm->mmap_sem); - if (unlikely(core_waiters < 0)) - goto fail; - - /* - * Make sure nobody is waiting for us to release the VM, - * otherwise we can deadlock when we wait on each other - */ - vfork_done = tsk->vfork_done; - if (vfork_done) { - tsk->vfork_done = NULL; - complete(vfork_done); - } - if (core_waiters) wait_for_completion(&startup_done); -fail: BUG_ON(mm->core_waiters); - return core_waiters; } int do_coredump(long signr, int exit_code, struct pt_regs * regs) @@ -1496,9 +1473,22 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) } mm->dumpable = 0; - retval = coredump_wait(exit_code); - if (retval < 0) + retval = -EAGAIN; + spin_lock_irq(¤t->sighand->siglock); + if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) { + current->signal->flags = SIGNAL_GROUP_EXIT; + current->signal->group_exit_code = exit_code; + current->signal->group_stop_count = 0; + retval = 0; + } + spin_unlock_irq(¤t->sighand->siglock); + if (retval) { + up_write(&mm->mmap_sem); goto fail; + } + + init_completion(&mm->core_done); + coredump_wait(mm); /* * Clear any false indication of pending signals that might diff --git a/trunk/fs/ext2/balloc.c b/trunk/fs/ext2/balloc.c index d4870432ecfc..433a213a8bd9 100644 --- a/trunk/fs/ext2/balloc.c +++ b/trunk/fs/ext2/balloc.c @@ -11,6 +11,7 @@ * David S. Miller (davem@caip.rutgers.edu), 1995 */ +#include #include "ext2.h" #include #include diff --git a/trunk/fs/ext2/ext2.h b/trunk/fs/ext2/ext2.h index e65a019fc7a5..9f74a62be555 100644 --- a/trunk/fs/ext2/ext2.h +++ b/trunk/fs/ext2/ext2.h @@ -162,9 +162,9 @@ extern const struct file_operations ext2_file_operations; extern const struct file_operations ext2_xip_file_operations; /* inode.c */ -extern const struct address_space_operations ext2_aops; -extern const struct address_space_operations ext2_aops_xip; -extern const struct address_space_operations ext2_nobh_aops; +extern struct address_space_operations ext2_aops; +extern struct address_space_operations ext2_aops_xip; +extern struct address_space_operations ext2_nobh_aops; /* namei.c */ extern struct inode_operations ext2_dir_inode_operations; diff --git a/trunk/fs/ext2/ialloc.c b/trunk/fs/ext2/ialloc.c index de85c61c58c5..308c252568c6 100644 --- a/trunk/fs/ext2/ialloc.c +++ b/trunk/fs/ext2/ialloc.c @@ -12,6 +12,7 @@ * David S. Miller (davem@caip.rutgers.edu), 1995 */ +#include #include #include #include diff --git a/trunk/fs/ext2/inode.c b/trunk/fs/ext2/inode.c index fb4d3220eb8d..04af9c45dce2 100644 --- a/trunk/fs/ext2/inode.c +++ b/trunk/fs/ext2/inode.c @@ -684,7 +684,7 @@ ext2_writepages(struct address_space *mapping, struct writeback_control *wbc) return mpage_writepages(mapping, wbc, ext2_get_block); } -const struct address_space_operations ext2_aops = { +struct address_space_operations ext2_aops = { .readpage = ext2_readpage, .readpages = ext2_readpages, .writepage = ext2_writepage, @@ -697,12 +697,12 @@ const struct address_space_operations ext2_aops = { .migratepage = buffer_migrate_page, }; -const struct address_space_operations ext2_aops_xip = { +struct address_space_operations ext2_aops_xip = { .bmap = ext2_bmap, .get_xip_page = ext2_get_xip_page, }; -const struct address_space_operations ext2_nobh_aops = { +struct address_space_operations ext2_nobh_aops = { .readpage = ext2_readpage, .readpages = ext2_readpages, .writepage = ext2_nobh_writepage, diff --git a/trunk/fs/ext2/super.c b/trunk/fs/ext2/super.c index 9f43879d6d68..d4233b2e6436 100644 --- a/trunk/fs/ext2/super.c +++ b/trunk/fs/ext2/super.c @@ -16,6 +16,7 @@ * David S. Miller (davem@caip.rutgers.edu), 1995 */ +#include #include #include #include diff --git a/trunk/fs/ext2/xattr.h b/trunk/fs/ext2/xattr.h index bf8175b2ced9..67cfeb66e897 100644 --- a/trunk/fs/ext2/xattr.h +++ b/trunk/fs/ext2/xattr.h @@ -6,6 +6,7 @@ (C) 2001 Andreas Gruenbacher, */ +#include #include #include diff --git a/trunk/fs/ext3/balloc.c b/trunk/fs/ext3/balloc.c index a504a40d6d29..96172e89ddc3 100644 --- a/trunk/fs/ext3/balloc.c +++ b/trunk/fs/ext3/balloc.c @@ -11,6 +11,7 @@ * David S. Miller (davem@caip.rutgers.edu), 1995 */ +#include #include #include #include diff --git a/trunk/fs/ext3/inode.c b/trunk/fs/ext3/inode.c index f804d5e9d60c..0321e1b9034a 100644 --- a/trunk/fs/ext3/inode.c +++ b/trunk/fs/ext3/inode.c @@ -1698,7 +1698,7 @@ static int ext3_journalled_set_page_dirty(struct page *page) return __set_page_dirty_nobuffers(page); } -static const struct address_space_operations ext3_ordered_aops = { +static struct address_space_operations ext3_ordered_aops = { .readpage = ext3_readpage, .readpages = ext3_readpages, .writepage = ext3_ordered_writepage, @@ -1712,7 +1712,7 @@ static const struct address_space_operations ext3_ordered_aops = { .migratepage = buffer_migrate_page, }; -static const struct address_space_operations ext3_writeback_aops = { +static struct address_space_operations ext3_writeback_aops = { .readpage = ext3_readpage, .readpages = ext3_readpages, .writepage = ext3_writeback_writepage, @@ -1726,7 +1726,7 @@ static const struct address_space_operations ext3_writeback_aops = { .migratepage = buffer_migrate_page, }; -static const struct address_space_operations ext3_journalled_aops = { +static struct address_space_operations ext3_journalled_aops = { .readpage = ext3_readpage, .readpages = ext3_readpages, .writepage = ext3_journalled_writepage, diff --git a/trunk/fs/ext3/resize.c b/trunk/fs/ext3/resize.c index 5e1337fd878a..dfd811895d8f 100644 --- a/trunk/fs/ext3/resize.c +++ b/trunk/fs/ext3/resize.c @@ -8,6 +8,7 @@ * This could probably be made into a module, because it is not often in use. */ +#include #define EXT3FS_DEBUG diff --git a/trunk/fs/ext3/super.c b/trunk/fs/ext3/super.c index f2dd71336612..b2891cc29db1 100644 --- a/trunk/fs/ext3/super.c +++ b/trunk/fs/ext3/super.c @@ -16,6 +16,7 @@ * David S. Miller (davem@caip.rutgers.edu), 1995 */ +#include #include #include #include @@ -629,7 +630,7 @@ enum { Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro, Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, - Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh, + Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, @@ -665,7 +666,6 @@ static match_table_t tokens = { {Opt_noreservation, "noreservation"}, {Opt_noload, "noload"}, {Opt_nobh, "nobh"}, - {Opt_bh, "bh"}, {Opt_commit, "commit=%u"}, {Opt_journal_update, "journal=update"}, {Opt_journal_inum, "journal=%u"}, @@ -1014,9 +1014,6 @@ static int parse_options (char *options, struct super_block *sb, case Opt_nobh: set_opt(sbi->s_mount_opt, NOBH); break; - case Opt_bh: - clear_opt(sbi->s_mount_opt, NOBH); - break; default: printk (KERN_ERR "EXT3-fs: Unrecognized mount option \"%s\" " diff --git a/trunk/fs/ext3/xattr.h b/trunk/fs/ext3/xattr.h index 6b1ae1c6182c..2ceae38f3d49 100644 --- a/trunk/fs/ext3/xattr.h +++ b/trunk/fs/ext3/xattr.h @@ -6,6 +6,7 @@ (C) 2001 Andreas Gruenbacher, */ +#include #include /* Magic value in attribute blocks */ diff --git a/trunk/fs/fat/inode.c b/trunk/fs/fat/inode.c index 31b7174176ba..7c35d582ec10 100644 --- a/trunk/fs/fat/inode.c +++ b/trunk/fs/fat/inode.c @@ -196,7 +196,7 @@ static sector_t _fat_bmap(struct address_space *mapping, sector_t block) return generic_block_bmap(mapping, block, fat_get_block); } -static const struct address_space_operations fat_aops = { +static struct address_space_operations fat_aops = { .readpage = fat_readpage, .readpages = fat_readpages, .writepage = fat_writepage, diff --git a/trunk/fs/file_table.c b/trunk/fs/file_table.c index 0131ba06e1ee..506d5307108d 100644 --- a/trunk/fs/file_table.c +++ b/trunk/fs/file_table.c @@ -5,6 +5,7 @@ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) */ +#include #include #include #include diff --git a/trunk/fs/freevxfs/vxfs_immed.c b/trunk/fs/freevxfs/vxfs_immed.c index 4e25f3fbed86..6f5df1700e95 100644 --- a/trunk/fs/freevxfs/vxfs_immed.c +++ b/trunk/fs/freevxfs/vxfs_immed.c @@ -56,7 +56,7 @@ struct inode_operations vxfs_immed_symlink_iops = { /* * Adress space operations for immed files and directories. */ -const struct address_space_operations vxfs_immed_aops = { +struct address_space_operations vxfs_immed_aops = { .readpage = vxfs_immed_readpage, }; diff --git a/trunk/fs/freevxfs/vxfs_inode.c b/trunk/fs/freevxfs/vxfs_inode.c index ca6a39714771..f544aae9169f 100644 --- a/trunk/fs/freevxfs/vxfs_inode.c +++ b/trunk/fs/freevxfs/vxfs_inode.c @@ -41,8 +41,8 @@ #include "vxfs_extern.h" -extern const struct address_space_operations vxfs_aops; -extern const struct address_space_operations vxfs_immed_aops; +extern struct address_space_operations vxfs_aops; +extern struct address_space_operations vxfs_immed_aops; extern struct inode_operations vxfs_immed_symlink_iops; @@ -295,7 +295,7 @@ vxfs_read_inode(struct inode *ip) { struct super_block *sbp = ip->i_sb; struct vxfs_inode_info *vip; - const struct address_space_operations *aops; + struct address_space_operations *aops; ino_t ino = ip->i_ino; if (!(vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist))) diff --git a/trunk/fs/freevxfs/vxfs_subr.c b/trunk/fs/freevxfs/vxfs_subr.c index decac62efe57..c1be118fc067 100644 --- a/trunk/fs/freevxfs/vxfs_subr.c +++ b/trunk/fs/freevxfs/vxfs_subr.c @@ -42,7 +42,7 @@ static int vxfs_readpage(struct file *, struct page *); static sector_t vxfs_bmap(struct address_space *, sector_t); -const struct address_space_operations vxfs_aops = { +struct address_space_operations vxfs_aops = { .readpage = vxfs_readpage, .bmap = vxfs_bmap, .sync_page = block_sync_page, diff --git a/trunk/fs/fs-writeback.c b/trunk/fs/fs-writeback.c index 892643dc9af1..031b27a4bc9a 100644 --- a/trunk/fs/fs-writeback.c +++ b/trunk/fs/fs-writeback.c @@ -464,8 +464,8 @@ void sync_inodes_sb(struct super_block *sb, int wait) .range_start = 0, .range_end = LLONG_MAX, }; - unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY); - unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS); + unsigned long nr_dirty = read_page_state(nr_dirty); + unsigned long nr_unstable = read_page_state(nr_unstable); wbc.nr_to_write = nr_dirty + nr_unstable + (inodes_stat.nr_inodes - inodes_stat.nr_unused) + diff --git a/trunk/fs/fuse/file.c b/trunk/fs/fuse/file.c index 63614ed16336..28aa81eae2cc 100644 --- a/trunk/fs/fuse/file.c +++ b/trunk/fs/fuse/file.c @@ -770,7 +770,7 @@ static const struct file_operations fuse_direct_io_file_operations = { /* no mmap and sendfile */ }; -static const struct address_space_operations fuse_file_aops = { +static struct address_space_operations fuse_file_aops = { .readpage = fuse_readpage, .prepare_write = fuse_prepare_write, .commit_write = fuse_commit_write, diff --git a/trunk/fs/hfs/hfs_fs.h b/trunk/fs/hfs/hfs_fs.h index 735332dfd1b8..3ed8663a8db1 100644 --- a/trunk/fs/hfs/hfs_fs.h +++ b/trunk/fs/hfs/hfs_fs.h @@ -182,8 +182,8 @@ extern void hfs_file_truncate(struct inode *); extern int hfs_get_block(struct inode *, sector_t, struct buffer_head *, int); /* inode.c */ -extern const struct address_space_operations hfs_aops; -extern const struct address_space_operations hfs_btree_aops; +extern struct address_space_operations hfs_aops; +extern struct address_space_operations hfs_btree_aops; extern struct inode *hfs_new_inode(struct inode *, struct qstr *, int); extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *); diff --git a/trunk/fs/hfs/inode.c b/trunk/fs/hfs/inode.c index 315cf44a90b2..2d4ced22201b 100644 --- a/trunk/fs/hfs/inode.c +++ b/trunk/fs/hfs/inode.c @@ -114,7 +114,7 @@ static int hfs_writepages(struct address_space *mapping, return mpage_writepages(mapping, wbc, hfs_get_block); } -const struct address_space_operations hfs_btree_aops = { +struct address_space_operations hfs_btree_aops = { .readpage = hfs_readpage, .writepage = hfs_writepage, .sync_page = block_sync_page, @@ -124,7 +124,7 @@ const struct address_space_operations hfs_btree_aops = { .releasepage = hfs_releasepage, }; -const struct address_space_operations hfs_aops = { +struct address_space_operations hfs_aops = { .readpage = hfs_readpage, .writepage = hfs_writepage, .sync_page = block_sync_page, diff --git a/trunk/fs/hfs/super.c b/trunk/fs/hfs/super.c index 34937ee83ab1..d9227bf14e86 100644 --- a/trunk/fs/hfs/super.c +++ b/trunk/fs/hfs/super.c @@ -12,6 +12,7 @@ * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds */ +#include #include #include #include diff --git a/trunk/fs/hfsplus/hfsplus_fs.h b/trunk/fs/hfsplus/hfsplus_fs.h index 8a1ca5ef7ada..7ae393637a0c 100644 --- a/trunk/fs/hfsplus/hfsplus_fs.h +++ b/trunk/fs/hfsplus/hfsplus_fs.h @@ -323,8 +323,8 @@ int hfsplus_file_extend(struct inode *); void hfsplus_file_truncate(struct inode *); /* inode.c */ -extern const struct address_space_operations hfsplus_aops; -extern const struct address_space_operations hfsplus_btree_aops; +extern struct address_space_operations hfsplus_aops; +extern struct address_space_operations hfsplus_btree_aops; void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *); void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *); diff --git a/trunk/fs/hfsplus/inode.c b/trunk/fs/hfsplus/inode.c index 924ecdef8091..acf66dba3e01 100644 --- a/trunk/fs/hfsplus/inode.c +++ b/trunk/fs/hfsplus/inode.c @@ -109,7 +109,7 @@ static int hfsplus_writepages(struct address_space *mapping, return mpage_writepages(mapping, wbc, hfsplus_get_block); } -const struct address_space_operations hfsplus_btree_aops = { +struct address_space_operations hfsplus_btree_aops = { .readpage = hfsplus_readpage, .writepage = hfsplus_writepage, .sync_page = block_sync_page, @@ -119,7 +119,7 @@ const struct address_space_operations hfsplus_btree_aops = { .releasepage = hfsplus_releasepage, }; -const struct address_space_operations hfsplus_aops = { +struct address_space_operations hfsplus_aops = { .readpage = hfsplus_readpage, .writepage = hfsplus_writepage, .sync_page = block_sync_page, diff --git a/trunk/fs/hfsplus/super.c b/trunk/fs/hfsplus/super.c index d279d5924f28..0a92fa2336a2 100644 --- a/trunk/fs/hfsplus/super.c +++ b/trunk/fs/hfsplus/super.c @@ -7,6 +7,7 @@ * */ +#include #include #include #include diff --git a/trunk/fs/hostfs/hostfs_kern.c b/trunk/fs/hostfs/hostfs_kern.c index b82e3d9c8790..8e0d37743e7c 100644 --- a/trunk/fs/hostfs/hostfs_kern.c +++ b/trunk/fs/hostfs/hostfs_kern.c @@ -54,7 +54,7 @@ static int append = 0; static struct inode_operations hostfs_iops; static struct inode_operations hostfs_dir_iops; -static const struct address_space_operations hostfs_link_aops; +static struct address_space_operations hostfs_link_aops; #ifndef MODULE static int __init hostfs_args(char *options, int *add) @@ -518,7 +518,7 @@ int hostfs_commit_write(struct file *file, struct page *page, unsigned from, return(err); } -static const struct address_space_operations hostfs_aops = { +static struct address_space_operations hostfs_aops = { .writepage = hostfs_writepage, .readpage = hostfs_readpage, .set_page_dirty = __set_page_dirty_nobuffers, @@ -935,7 +935,7 @@ int hostfs_link_readpage(struct file *file, struct page *page) return(err); } -static const struct address_space_operations hostfs_link_aops = { +static struct address_space_operations hostfs_link_aops = { .readpage = hostfs_link_readpage, }; diff --git a/trunk/fs/hpfs/file.c b/trunk/fs/hpfs/file.c index d9eb19b7b8ae..d3b9fffe45a1 100644 --- a/trunk/fs/hpfs/file.c +++ b/trunk/fs/hpfs/file.c @@ -99,7 +99,7 @@ static sector_t _hpfs_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping,block,hpfs_get_block); } -const struct address_space_operations hpfs_aops = { +struct address_space_operations hpfs_aops = { .readpage = hpfs_readpage, .writepage = hpfs_writepage, .sync_page = block_sync_page, diff --git a/trunk/fs/hpfs/hpfs_fn.h b/trunk/fs/hpfs/hpfs_fn.h index f687d54ed442..29b7a3e55173 100644 --- a/trunk/fs/hpfs/hpfs_fn.h +++ b/trunk/fs/hpfs/hpfs_fn.h @@ -268,7 +268,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int); int hpfs_file_fsync(struct file *, struct dentry *, int); extern const struct file_operations hpfs_file_ops; extern struct inode_operations hpfs_file_iops; -extern const struct address_space_operations hpfs_aops; +extern struct address_space_operations hpfs_aops; /* inode.c */ @@ -304,7 +304,7 @@ void hpfs_decide_conv(struct inode *, unsigned char *, unsigned); /* namei.c */ extern struct inode_operations hpfs_dir_iops; -extern const struct address_space_operations hpfs_symlink_aops; +extern struct address_space_operations hpfs_symlink_aops; static inline struct hpfs_inode_info *hpfs_i(struct inode *inode) { diff --git a/trunk/fs/hpfs/namei.c b/trunk/fs/hpfs/namei.c index 59e7dc182a0c..a03abb12c610 100644 --- a/trunk/fs/hpfs/namei.c +++ b/trunk/fs/hpfs/namei.c @@ -538,7 +538,7 @@ static int hpfs_symlink_readpage(struct file *file, struct page *page) return err; } -const struct address_space_operations hpfs_symlink_aops = { +struct address_space_operations hpfs_symlink_aops = { .readpage = hpfs_symlink_readpage }; diff --git a/trunk/fs/hugetlbfs/inode.c b/trunk/fs/hugetlbfs/inode.c index 6449cb697967..e6410d8edd0e 100644 --- a/trunk/fs/hugetlbfs/inode.c +++ b/trunk/fs/hugetlbfs/inode.c @@ -34,7 +34,7 @@ #define HUGETLBFS_MAGIC 0x958458f6 static struct super_operations hugetlbfs_ops; -static const struct address_space_operations hugetlbfs_aops; +static struct address_space_operations hugetlbfs_aops; const struct file_operations hugetlbfs_file_operations; static struct inode_operations hugetlbfs_dir_inode_operations; static struct inode_operations hugetlbfs_inode_operations; @@ -547,7 +547,7 @@ static void hugetlbfs_destroy_inode(struct inode *inode) kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode)); } -static const struct address_space_operations hugetlbfs_aops = { +static struct address_space_operations hugetlbfs_aops = { .readpage = hugetlbfs_readpage, .prepare_write = hugetlbfs_prepare_write, .commit_write = hugetlbfs_commit_write, diff --git a/trunk/fs/inode.c b/trunk/fs/inode.c index 0bf9f0444a96..3a2446a27d2c 100644 --- a/trunk/fs/inode.c +++ b/trunk/fs/inode.c @@ -4,6 +4,7 @@ * (C) 1997 Linus Torvalds */ +#include #include #include #include @@ -101,7 +102,7 @@ static kmem_cache_t * inode_cachep __read_mostly; static struct inode *alloc_inode(struct super_block *sb) { - static const struct address_space_operations empty_aops; + static struct address_space_operations empty_aops; static struct inode_operations empty_iops; static const struct file_operations empty_fops; struct inode *inode; @@ -451,14 +452,15 @@ static void prune_icache(int nr_to_scan) nr_pruned++; } inodes_stat.nr_unused -= nr_pruned; - if (current_is_kswapd()) - __count_vm_events(KSWAPD_INODESTEAL, reap); - else - __count_vm_events(PGINODESTEAL, reap); spin_unlock(&inode_lock); dispose_list(&freeable); mutex_unlock(&iprune_mutex); + + if (current_is_kswapd()) + mod_page_state(kswapd_inodesteal, reap); + else + mod_page_state(pginodesteal, reap); } /* diff --git a/trunk/fs/ioctl.c b/trunk/fs/ioctl.c index 4b7660b09ac0..f8aeec3ca10c 100644 --- a/trunk/fs/ioctl.c +++ b/trunk/fs/ioctl.c @@ -4,6 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ +#include #include #include #include diff --git a/trunk/fs/ioprio.c b/trunk/fs/ioprio.c index 93aa5715f224..7fa76ed53c10 100644 --- a/trunk/fs/ioprio.c +++ b/trunk/fs/ioprio.c @@ -125,24 +125,11 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) return ret; } -static int get_task_ioprio(struct task_struct *p) -{ - int ret; - - ret = security_task_getioprio(p); - if (ret) - goto out; - ret = p->ioprio; -out: - return ret; -} - asmlinkage long sys_ioprio_get(int which, int who) { struct task_struct *g, *p; struct user_struct *user; int ret = -ESRCH; - int tmpio; read_lock_irq(&tasklist_lock); switch (which) { @@ -152,19 +139,16 @@ asmlinkage long sys_ioprio_get(int which, int who) else p = find_task_by_pid(who); if (p) - ret = get_task_ioprio(p); + ret = p->ioprio; break; case IOPRIO_WHO_PGRP: if (!who) who = process_group(current); do_each_task_pid(who, PIDTYPE_PGID, p) { - tmpio = get_task_ioprio(p); - if (tmpio < 0) - continue; if (ret == -ESRCH) - ret = tmpio; + ret = p->ioprio; else - ret = ioprio_best(ret, tmpio); + ret = ioprio_best(ret, p->ioprio); } while_each_task_pid(who, PIDTYPE_PGID, p); break; case IOPRIO_WHO_USER: @@ -179,13 +163,10 @@ asmlinkage long sys_ioprio_get(int which, int who) do_each_thread(g, p) { if (p->uid != user->uid) continue; - tmpio = get_task_ioprio(p); - if (tmpio < 0) - continue; if (ret == -ESRCH) - ret = tmpio; + ret = p->ioprio; else - ret = ioprio_best(ret, tmpio); + ret = ioprio_best(ret, p->ioprio); } while_each_thread(g, p); if (who) diff --git a/trunk/fs/isofs/compress.c b/trunk/fs/isofs/compress.c index 731816332b12..4917315db732 100644 --- a/trunk/fs/isofs/compress.c +++ b/trunk/fs/isofs/compress.c @@ -16,6 +16,7 @@ * Transparent decompression of files on an iso9660 filesystem */ +#include #include #include @@ -311,7 +312,7 @@ static int zisofs_readpage(struct file *file, struct page *page) return err; } -const struct address_space_operations zisofs_aops = { +struct address_space_operations zisofs_aops = { .readpage = zisofs_readpage, /* No sync_page operation supported? */ /* No bmap operation supported */ diff --git a/trunk/fs/isofs/dir.c b/trunk/fs/isofs/dir.c index 27e276987fd2..5440ea292c69 100644 --- a/trunk/fs/isofs/dir.c +++ b/trunk/fs/isofs/dir.c @@ -10,6 +10,7 @@ * * isofs directory handling functions */ +#include #include #include "isofs.h" diff --git a/trunk/fs/isofs/inode.c b/trunk/fs/isofs/inode.c index 14391361c886..3f9c8ba1fa1f 100644 --- a/trunk/fs/isofs/inode.c +++ b/trunk/fs/isofs/inode.c @@ -11,6 +11,7 @@ * 2004 Paul Serice - NFS Export Operations */ +#include #include #include @@ -1053,7 +1054,7 @@ static sector_t _isofs_bmap(struct address_space *mapping, sector_t block) return generic_block_bmap(mapping,block,isofs_get_block); } -static const struct address_space_operations isofs_aops = { +static struct address_space_operations isofs_aops = { .readpage = isofs_readpage, .sync_page = block_sync_page, .bmap = _isofs_bmap diff --git a/trunk/fs/isofs/isofs.h b/trunk/fs/isofs/isofs.h index e6308c8b5735..b87ba066f5e7 100644 --- a/trunk/fs/isofs/isofs.h +++ b/trunk/fs/isofs/isofs.h @@ -176,5 +176,5 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de, extern struct inode_operations isofs_dir_inode_operations; extern const struct file_operations isofs_dir_operations; -extern const struct address_space_operations isofs_symlink_aops; +extern struct address_space_operations isofs_symlink_aops; extern struct export_operations isofs_export_ops; diff --git a/trunk/fs/isofs/rock.c b/trunk/fs/isofs/rock.c index f3a1db3098de..4326cb47f8fa 100644 --- a/trunk/fs/isofs/rock.c +++ b/trunk/fs/isofs/rock.c @@ -754,6 +754,6 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page) return -EIO; } -const struct address_space_operations isofs_symlink_aops = { +struct address_space_operations isofs_symlink_aops = { .readpage = rock_ridge_symlink_readpage }; diff --git a/trunk/fs/isofs/zisofs.h b/trunk/fs/isofs/zisofs.h index 273795709155..d78485d101c2 100644 --- a/trunk/fs/isofs/zisofs.h +++ b/trunk/fs/isofs/zisofs.h @@ -15,7 +15,7 @@ */ #ifdef CONFIG_ZISOFS -extern const struct address_space_operations zisofs_aops; +extern struct address_space_operations zisofs_aops; extern int __init zisofs_init(void); extern void zisofs_cleanup(void); #endif diff --git a/trunk/fs/jbd/journal.c b/trunk/fs/jbd/journal.c index 8c9b28dff119..7f96b5cb6781 100644 --- a/trunk/fs/jbd/journal.c +++ b/trunk/fs/jbd/journal.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -1676,7 +1675,7 @@ static void journal_free_journal_head(struct journal_head *jh) { #ifdef CONFIG_JBD_DEBUG atomic_dec(&nr_journal_heads); - memset(jh, JBD_POISON_FREE, sizeof(*jh)); + memset(jh, 0x5b, sizeof(*jh)); #endif kmem_cache_free(journal_head_cache, jh); } diff --git a/trunk/fs/jffs/inode-v23.c b/trunk/fs/jffs/inode-v23.c index 93068697a9bf..9e46ea6da752 100644 --- a/trunk/fs/jffs/inode-v23.c +++ b/trunk/fs/jffs/inode-v23.c @@ -59,7 +59,7 @@ static const struct file_operations jffs_file_operations; static struct inode_operations jffs_file_inode_operations; static const struct file_operations jffs_dir_operations; static struct inode_operations jffs_dir_inode_operations; -static const struct address_space_operations jffs_address_operations; +static struct address_space_operations jffs_address_operations; kmem_cache_t *node_cache = NULL; kmem_cache_t *fm_cache = NULL; @@ -1614,7 +1614,7 @@ jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, } /* jffs_ioctl() */ -static const struct address_space_operations jffs_address_operations = { +static struct address_space_operations jffs_address_operations = { .readpage = jffs_readpage, .prepare_write = jffs_prepare_write, .commit_write = jffs_commit_write, diff --git a/trunk/fs/jffs/intrep.c b/trunk/fs/jffs/intrep.c index 9000f1effedf..5371a403130a 100644 --- a/trunk/fs/jffs/intrep.c +++ b/trunk/fs/jffs/intrep.c @@ -55,6 +55,7 @@ * */ +#include #include #include #include diff --git a/trunk/fs/jffs/jffs_fm.h b/trunk/fs/jffs/jffs_fm.h index 9ee6ad29eff5..c794d923df2a 100644 --- a/trunk/fs/jffs/jffs_fm.h +++ b/trunk/fs/jffs/jffs_fm.h @@ -20,6 +20,7 @@ #ifndef __LINUX_JFFS_FM_H__ #define __LINUX_JFFS_FM_H__ +#include #include #include #include diff --git a/trunk/fs/jffs2/acl.c b/trunk/fs/jffs2/acl.c index 9c2077e7e081..320dd48b834e 100644 --- a/trunk/fs/jffs2/acl.c +++ b/trunk/fs/jffs2/acl.c @@ -267,8 +267,6 @@ static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) } rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0); - if (!value && rc == -ENODATA) - rc = 0; if (value) kfree(value); if (!rc) { diff --git a/trunk/fs/jffs2/compr_zlib.c b/trunk/fs/jffs2/compr_zlib.c index 3681d0728ac7..5c63e0cdcf4c 100644 --- a/trunk/fs/jffs2/compr_zlib.c +++ b/trunk/fs/jffs2/compr_zlib.c @@ -15,6 +15,7 @@ #error "The userspace support got too messy and was removed. Update your mkfs.jffs2" #endif +#include #include #include #include diff --git a/trunk/fs/jffs2/debug.h b/trunk/fs/jffs2/debug.h index 3daf3bca0376..5fa494a792b2 100644 --- a/trunk/fs/jffs2/debug.h +++ b/trunk/fs/jffs2/debug.h @@ -13,6 +13,7 @@ #ifndef _JFFS2_DEBUG_H_ #define _JFFS2_DEBUG_H_ +#include #ifndef CONFIG_JFFS2_FS_DEBUG #define CONFIG_JFFS2_FS_DEBUG 0 diff --git a/trunk/fs/jffs2/erase.c b/trunk/fs/jffs2/erase.c index ad0121088dde..1862e8bc101d 100644 --- a/trunk/fs/jffs2/erase.c +++ b/trunk/fs/jffs2/erase.c @@ -53,7 +53,8 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, if (!instr) { printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n"); spin_lock(&c->erase_completion_lock); - list_move(&jeb->list, &c->erase_pending_list); + list_del(&jeb->list); + list_add(&jeb->list, &c->erase_pending_list); c->erasing_size -= c->sector_size; c->dirty_size += c->sector_size; jeb->dirty_size = c->sector_size; @@ -85,7 +86,8 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, /* Erase failed immediately. Refile it on the list */ D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret)); spin_lock(&c->erase_completion_lock); - list_move(&jeb->list, &c->erase_pending_list); + list_del(&jeb->list); + list_add(&jeb->list, &c->erase_pending_list); c->erasing_size -= c->sector_size; c->dirty_size += c->sector_size; jeb->dirty_size = c->sector_size; @@ -159,7 +161,8 @@ static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblo { D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset)); spin_lock(&c->erase_completion_lock); - list_move_tail(&jeb->list, &c->erase_complete_list); + list_del(&jeb->list); + list_add_tail(&jeb->list, &c->erase_complete_list); spin_unlock(&c->erase_completion_lock); /* Ensure that kupdated calls us again to mark them clean */ jffs2_erase_pending_trigger(c); @@ -175,7 +178,8 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) { /* We'd like to give this block another try. */ spin_lock(&c->erase_completion_lock); - list_move(&jeb->list, &c->erase_pending_list); + list_del(&jeb->list); + list_add(&jeb->list, &c->erase_pending_list); c->erasing_size -= c->sector_size; c->dirty_size += c->sector_size; jeb->dirty_size = c->sector_size; @@ -187,7 +191,8 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock spin_lock(&c->erase_completion_lock); c->erasing_size -= c->sector_size; c->bad_size += c->sector_size; - list_move(&jeb->list, &c->bad_list); + list_del(&jeb->list); + list_add(&jeb->list, &c->bad_list); c->nr_erasing_blocks--; spin_unlock(&c->erase_completion_lock); wake_up(&c->erase_wait); @@ -225,6 +230,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, at the end of the linked list. Stash it and continue from the beginning of the list */ ic = (struct jffs2_inode_cache *)(*prev); + BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE); prev = &ic->nodes; continue; } @@ -248,8 +254,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, /* PARANOIA */ if (!ic) { - JFFS2_WARNING("inode_cache/xattr_datum/xattr_ref" - " not found in remove_node_refs()!!\n"); + printk(KERN_WARNING "inode_cache not found in remove_node_refs()!!\n"); return; } @@ -274,19 +279,8 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, printk("\n"); }); - switch (ic->class) { -#ifdef CONFIG_JFFS2_FS_XATTR - case RAWNODE_CLASS_XATTR_DATUM: - jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic); - break; - case RAWNODE_CLASS_XATTR_REF: - jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic); - break; -#endif - default: - if (ic->nodes == (void *)ic && ic->nlink == 0) - jffs2_del_ino_cache(c, ic); - } + if (ic->nodes == (void *)ic && ic->nlink == 0) + jffs2_del_ino_cache(c, ic); } void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) diff --git a/trunk/fs/jffs2/file.c b/trunk/fs/jffs2/file.c index 3ed6e3e120b6..bb8844f40e48 100644 --- a/trunk/fs/jffs2/file.c +++ b/trunk/fs/jffs2/file.c @@ -62,7 +62,7 @@ struct inode_operations jffs2_file_inode_operations = .removexattr = jffs2_removexattr }; -const struct address_space_operations jffs2_file_address_operations = +struct address_space_operations jffs2_file_address_operations = { .readpage = jffs2_readpage, .prepare_write =jffs2_prepare_write, diff --git a/trunk/fs/jffs2/fs.c b/trunk/fs/jffs2/fs.c index 4780f82825d6..2900ec3ec3af 100644 --- a/trunk/fs/jffs2/fs.c +++ b/trunk/fs/jffs2/fs.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include @@ -226,6 +227,8 @@ void jffs2_clear_inode (struct inode *inode) struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); + + jffs2_xattr_delete_inode(c, f->inocache); jffs2_do_clear_inode(c, f); } diff --git a/trunk/fs/jffs2/gc.c b/trunk/fs/jffs2/gc.c index daff3341ff92..477c526d638b 100644 --- a/trunk/fs/jffs2/gc.c +++ b/trunk/fs/jffs2/gc.c @@ -165,7 +165,6 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n", ic->ino)); spin_unlock(&c->inocache_lock); - jffs2_xattr_delete_inode(c, ic); continue; } switch(ic->state) { @@ -276,12 +275,13 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) * We can decide whether this node is inode or xattr by ic->class. */ if (ic->class == RAWNODE_CLASS_XATTR_DATUM || ic->class == RAWNODE_CLASS_XATTR_REF) { + BUG_ON(raw->next_in_ino != (void *)ic); spin_unlock(&c->erase_completion_lock); if (ic->class == RAWNODE_CLASS_XATTR_DATUM) { - ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic, raw); + ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic); } else { - ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw); + ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic); } goto release_sem; } diff --git a/trunk/fs/jffs2/jffs2_fs_sb.h b/trunk/fs/jffs2/jffs2_fs_sb.h index b98594992eed..935fec1b1201 100644 --- a/trunk/fs/jffs2/jffs2_fs_sb.h +++ b/trunk/fs/jffs2/jffs2_fs_sb.h @@ -119,11 +119,8 @@ struct jffs2_sb_info { #ifdef CONFIG_JFFS2_FS_XATTR #define XATTRINDEX_HASHSIZE (57) uint32_t highest_xid; - uint32_t highest_xseqno; struct list_head xattrindex[XATTRINDEX_HASHSIZE]; struct list_head xattr_unchecked; - struct list_head xattr_dead_list; - struct jffs2_xattr_ref *xref_dead_list; struct jffs2_xattr_ref *xref_temp; struct rw_semaphore xattr_sem; uint32_t xdatum_mem_usage; diff --git a/trunk/fs/jffs2/malloc.c b/trunk/fs/jffs2/malloc.c index 8310c95478e9..4889d0700c0e 100644 --- a/trunk/fs/jffs2/malloc.c +++ b/trunk/fs/jffs2/malloc.c @@ -291,7 +291,6 @@ struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void) memset(xd, 0, sizeof(struct jffs2_xattr_datum)); xd->class = RAWNODE_CLASS_XATTR_DATUM; - xd->node = (void *)xd; INIT_LIST_HEAD(&xd->xindex); return xd; } @@ -310,7 +309,6 @@ struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void) memset(ref, 0, sizeof(struct jffs2_xattr_ref)); ref->class = RAWNODE_CLASS_XATTR_REF; - ref->node = (void *)ref; return ref; } diff --git a/trunk/fs/jffs2/nodelist.c b/trunk/fs/jffs2/nodelist.c index 7675b33396c7..927dfe42ba76 100644 --- a/trunk/fs/jffs2/nodelist.c +++ b/trunk/fs/jffs2/nodelist.c @@ -906,9 +906,6 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) { struct jffs2_inode_cache **prev; -#ifdef CONFIG_JFFS2_FS_XATTR - BUG_ON(old->xref); -#endif dbg_inocache("del %p (ino #%u)\n", old, old->ino); spin_lock(&c->inocache_lock); diff --git a/trunk/fs/jffs2/nodelist.h b/trunk/fs/jffs2/nodelist.h index f752baa8d399..b16c60bbcf6e 100644 --- a/trunk/fs/jffs2/nodelist.h +++ b/trunk/fs/jffs2/nodelist.h @@ -14,6 +14,7 @@ #ifndef __JFFS2_NODELIST_H__ #define __JFFS2_NODELIST_H__ +#include #include #include #include diff --git a/trunk/fs/jffs2/nodemgmt.c b/trunk/fs/jffs2/nodemgmt.c index d88376992ed9..8bedfd2ff689 100644 --- a/trunk/fs/jffs2/nodemgmt.c +++ b/trunk/fs/jffs2/nodemgmt.c @@ -211,7 +211,8 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) struct jffs2_eraseblock *ejeb; ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); - list_move_tail(&ejeb->list, &c->erase_pending_list); + list_del(&ejeb->list); + list_add_tail(&ejeb->list, &c->erase_pending_list); c->nr_erasing_blocks++; jffs2_erase_pending_trigger(c); D1(printk(KERN_DEBUG "jffs2_find_nextblock: Triggering erase of erasable block at 0x%08x\n", @@ -683,26 +684,19 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref spin_lock(&c->erase_completion_lock); ic = jffs2_raw_ref_to_ic(ref); + /* It seems we should never call jffs2_mark_node_obsolete() for + XATTR nodes.... yet. Make sure we notice if/when we change + that :) */ + BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE); for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino)) ; *p = ref->next_in_ino; ref->next_in_ino = NULL; - switch (ic->class) { -#ifdef CONFIG_JFFS2_FS_XATTR - case RAWNODE_CLASS_XATTR_DATUM: - jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic); - break; - case RAWNODE_CLASS_XATTR_REF: - jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic); - break; -#endif - default: - if (ic->nodes == (void *)ic && ic->nlink == 0) - jffs2_del_ino_cache(c, ic); - break; - } + if (ic->nodes == (void *)ic && ic->nlink == 0) + jffs2_del_ino_cache(c, ic); + spin_unlock(&c->erase_completion_lock); } diff --git a/trunk/fs/jffs2/os-linux.h b/trunk/fs/jffs2/os-linux.h index 9f41fc01a371..6b5223565405 100644 --- a/trunk/fs/jffs2/os-linux.h +++ b/trunk/fs/jffs2/os-linux.h @@ -158,7 +158,7 @@ extern struct inode_operations jffs2_dir_inode_operations; /* file.c */ extern const struct file_operations jffs2_file_operations; extern struct inode_operations jffs2_file_inode_operations; -extern const struct address_space_operations jffs2_file_address_operations; +extern struct address_space_operations jffs2_file_address_operations; int jffs2_fsync(struct file *, struct dentry *, int); int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg); diff --git a/trunk/fs/jffs2/readinode.c b/trunk/fs/jffs2/readinode.c index cc1899268c43..5fec012b02ed 100644 --- a/trunk/fs/jffs2/readinode.c +++ b/trunk/fs/jffs2/readinode.c @@ -968,7 +968,6 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) struct jffs2_full_dirent *fd, *fds; int deleted; - jffs2_xattr_delete_inode(c, f->inocache); down(&f->sem); deleted = f->inocache && !f->inocache->nlink; diff --git a/trunk/fs/jffs2/scan.c b/trunk/fs/jffs2/scan.c index 2bfdc33752d3..61618080b86f 100644 --- a/trunk/fs/jffs2/scan.c +++ b/trunk/fs/jffs2/scan.c @@ -317,23 +317,20 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc struct jffs2_summary *s) { struct jffs2_xattr_datum *xd; - uint32_t xid, version, totlen, crc; + uint32_t totlen, crc; int err; crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4); if (crc != je32_to_cpu(rx->node_crc)) { - JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", - ofs, je32_to_cpu(rx->node_crc), crc); + if (je32_to_cpu(rx->node_crc) != 0xffffffff) + JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", + ofs, je32_to_cpu(rx->node_crc), crc); if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen)))) return err; return 0; } - xid = je32_to_cpu(rx->xid); - version = je32_to_cpu(rx->version); - - totlen = PAD(sizeof(struct jffs2_raw_xattr) - + rx->name_len + 1 + je16_to_cpu(rx->value_len)); + totlen = PAD(sizeof(*rx) + rx->name_len + 1 + je16_to_cpu(rx->value_len)); if (totlen != je32_to_cpu(rx->totlen)) { JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n", ofs, je32_to_cpu(rx->totlen), totlen); @@ -342,24 +339,22 @@ static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_erasebloc return 0; } - xd = jffs2_setup_xattr_datum(c, xid, version); - if (IS_ERR(xd)) + xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version)); + if (IS_ERR(xd)) { + if (PTR_ERR(xd) == -EEXIST) { + if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen))))) + return err; + return 0; + } return PTR_ERR(xd); - - if (xd->version > version) { - struct jffs2_raw_node_ref *raw - = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL); - raw->next_in_ino = xd->node->next_in_ino; - xd->node->next_in_ino = raw; - } else { - xd->version = version; - xd->xprefix = rx->xprefix; - xd->name_len = rx->name_len; - xd->value_len = je16_to_cpu(rx->value_len); - xd->data_crc = je32_to_cpu(rx->data_crc); - - jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, (void *)xd); } + xd->xprefix = rx->xprefix; + xd->name_len = rx->name_len; + xd->value_len = je16_to_cpu(rx->value_len); + xd->data_crc = je32_to_cpu(rx->data_crc); + + xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL); + /* FIXME */ xd->node->next_in_ino = (void *)xd; if (jffs2_sum_active()) jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); @@ -378,8 +373,9 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock crc = crc32(0, rr, sizeof(*rr) - 4); if (crc != je32_to_cpu(rr->node_crc)) { - JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", - ofs, je32_to_cpu(rr->node_crc), crc); + if (je32_to_cpu(rr->node_crc) != 0xffffffff) + JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", + ofs, je32_to_cpu(rr->node_crc), crc); if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen))))) return err; return 0; @@ -399,7 +395,6 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock return -ENOMEM; /* BEFORE jffs2_build_xattr_subsystem() called, - * and AFTER xattr_ref is marked as a dead xref, * ref->xid is used to store 32bit xid, xd is not used * ref->ino is used to store 32bit inode-number, ic is not used * Thoes variables are declared as union, thus using those @@ -409,13 +404,11 @@ static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock */ ref->ino = je32_to_cpu(rr->ino); ref->xid = je32_to_cpu(rr->xid); - ref->xseqno = je32_to_cpu(rr->xseqno); - if (ref->xseqno > c->highest_xseqno) - c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER); ref->next = c->xref_temp; c->xref_temp = ref; - jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), (void *)ref); + ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL); + /* FIXME */ ref->node->next_in_ino = (void *)ref; if (jffs2_sum_active()) jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); diff --git a/trunk/fs/jffs2/summary.c b/trunk/fs/jffs2/summary.c index c19bd476e8ec..0b02fc79e4d1 100644 --- a/trunk/fs/jffs2/summary.c +++ b/trunk/fs/jffs2/summary.c @@ -5,7 +5,7 @@ * Zoltan Sogor , * Patrik Kluba , * University of Szeged, Hungary - * 2006 KaiGai Kohei + * 2005 KaiGai Kohei * * For licensing information, see the file 'LICENCE' in this directory. * @@ -43,7 +43,7 @@ int jffs2_sum_init(struct jffs2_sb_info *c) return -ENOMEM; } - dbg_summary("returned successfully\n"); + dbg_summary("returned succesfully\n"); return 0; } @@ -310,6 +310,8 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, #ifdef CONFIG_JFFS2_FS_XATTR case JFFS2_NODETYPE_XATTR: { struct jffs2_sum_xattr_mem *temp; + if (je32_to_cpu(node->x.version) == 0xffffffff) + return 0; temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL); if (!temp) goto no_mem; @@ -325,6 +327,10 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, } case JFFS2_NODETYPE_XREF: { struct jffs2_sum_xref_mem *temp; + + if (je32_to_cpu(node->r.ino) == 0xffffffff + && je32_to_cpu(node->r.xid) == 0xffffffff) + return 0; temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL); if (!temp) goto no_mem; @@ -477,20 +483,22 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid), je32_to_cpu(spx->version)); - if (IS_ERR(xd)) + if (IS_ERR(xd)) { + if (PTR_ERR(xd) == -EEXIST) { + /* a newer version of xd exists */ + if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen)))) + return err; + sp += JFFS2_SUMMARY_XATTR_SIZE; + break; + } + JFFS2_NOTICE("allocation of xattr_datum failed\n"); return PTR_ERR(xd); - if (xd->version > je32_to_cpu(spx->version)) { - /* node is not the newest one */ - struct jffs2_raw_node_ref *raw - = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED, - PAD(je32_to_cpu(spx->totlen)), NULL); - raw->next_in_ino = xd->node->next_in_ino; - xd->node->next_in_ino = raw; - } else { - xd->version = je32_to_cpu(spx->version); - sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED, - PAD(je32_to_cpu(spx->totlen)), (void *)xd); } + + xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED, + PAD(je32_to_cpu(spx->totlen)), NULL); + /* FIXME */ xd->node->next_in_ino = (void *)xd; + *pseudo_random += je32_to_cpu(spx->xid); sp += JFFS2_SUMMARY_XATTR_SIZE; @@ -511,11 +519,14 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras JFFS2_NOTICE("allocation of xattr_datum failed\n"); return -ENOMEM; } + ref->ino = 0xfffffffe; + ref->xid = 0xfffffffd; ref->next = c->xref_temp; c->xref_temp = ref; - sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED, - PAD(sizeof(struct jffs2_raw_xref)), (void *)ref); + ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED, + PAD(sizeof(struct jffs2_raw_xref)), NULL); + /* FIXME */ ref->node->next_in_ino = (void *)ref; *pseudo_random += ref->node->flash_offset; sp += JFFS2_SUMMARY_XREF_SIZE; diff --git a/trunk/fs/jffs2/super.c b/trunk/fs/jffs2/super.c index 68e3953419b4..2378a662c256 100644 --- a/trunk/fs/jffs2/super.c +++ b/trunk/fs/jffs2/super.c @@ -11,6 +11,7 @@ * */ +#include #include #include #include diff --git a/trunk/fs/jffs2/wbuf.c b/trunk/fs/jffs2/wbuf.c index b9b700730dfe..a7f153f79ecb 100644 --- a/trunk/fs/jffs2/wbuf.c +++ b/trunk/fs/jffs2/wbuf.c @@ -495,7 +495,8 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) /* Fix up the original jeb now it's on the bad_list */ if (first_raw == jeb->first_node) { D1(printk(KERN_DEBUG "Failing block at %08x is now empty. Moving to erase_pending_list\n", jeb->offset)); - list_move(&jeb->list, &c->erase_pending_list); + list_del(&jeb->list); + list_add(&jeb->list, &c->erase_pending_list); c->nr_erasing_blocks++; jffs2_erase_pending_trigger(c); } diff --git a/trunk/fs/jffs2/xattr.c b/trunk/fs/jffs2/xattr.c index 18e66dbf23b4..2d82e250be34 100644 --- a/trunk/fs/jffs2/xattr.c +++ b/trunk/fs/jffs2/xattr.c @@ -23,15 +23,18 @@ * xattr_datum_hashkey(xprefix, xname, xvalue, xsize) * is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is * the index of the xattr name/value pair cache (c->xattrindex). - * is_xattr_datum_unchecked(c, xd) - * returns 1, if xdatum contains any unchecked raw nodes. if all raw nodes are not - * unchecked, it returns 0. * unload_xattr_datum(c, xd) * is used to release xattr name/value pair and detach from c->xattrindex. * reclaim_xattr_datum(c) * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when * memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold * is hard coded as 32KiB. + * delete_xattr_datum_node(c, xd) + * is used to delete a jffs2 node is dominated by xdatum. When EBS(Erase Block Summary) is + * enabled, it overwrites the obsolete node by myself. + * delete_xattr_datum(c, xd) + * is used to delete jffs2_xattr_datum object. It must be called with 0-value of reference + * counter. (It means how many jffs2_xattr_ref object refers this xdatum.) * do_verify_xattr_datum(c, xd) * is used to load the xdatum informations without name/value pair from the medium. * It's necessary once, because those informations are not collected during mounting @@ -50,10 +53,8 @@ * is used to write xdatum to medium. xd->version will be incremented. * create_xattr_datum(c, xprefix, xname, xvalue, xsize) * is used to create new xdatum and write to medium. - * delete_xattr_datum(c, xd) - * is used to delete a xdatum. It marks xd JFFS2_XFLAGS_DEAD, and allows - * GC to reclaim those physical nodes. * -------------------------------------------------- */ + static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize) { int name_len = strlen(xname); @@ -61,22 +62,6 @@ static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char * return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize); } -static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) -{ - struct jffs2_raw_node_ref *raw; - int rc = 0; - - spin_lock(&c->erase_completion_lock); - for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) { - if (ref_flags(raw) == REF_UNCHECKED) { - rc = 1; - break; - } - } - spin_unlock(&c->erase_completion_lock); - return rc; -} - static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) { /* must be called under down_write(xattr_sem) */ @@ -122,33 +107,77 @@ static void reclaim_xattr_datum(struct jffs2_sb_info *c) before, c->xdatum_mem_usage, before - c->xdatum_mem_usage); } +static void delete_xattr_datum_node(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_raw_xattr rx; + size_t length; + int rc; + + if (!xd->node) { + JFFS2_WARNING("xdatum (xid=%u) is removed twice.\n", xd->xid); + return; + } + if (jffs2_sum_active()) { + memset(&rx, 0xff, sizeof(struct jffs2_raw_xattr)); + rc = jffs2_flash_read(c, ref_offset(xd->node), + sizeof(struct jffs2_unknown_node), + &length, (char *)&rx); + if (rc || length != sizeof(struct jffs2_unknown_node)) { + JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", + rc, sizeof(struct jffs2_unknown_node), + length, ref_offset(xd->node)); + } + rc = jffs2_flash_write(c, ref_offset(xd->node), sizeof(rx), + &length, (char *)&rx); + if (rc || length != sizeof(struct jffs2_raw_xattr)) { + JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu ar %#08x\n", + rc, sizeof(rx), length, ref_offset(xd->node)); + } + } + spin_lock(&c->erase_completion_lock); + xd->node->next_in_ino = NULL; + spin_unlock(&c->erase_completion_lock); + jffs2_mark_node_obsolete(c, xd->node); + xd->node = NULL; +} + +static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + BUG_ON(xd->refcnt); + + unload_xattr_datum(c, xd); + if (xd->node) { + delete_xattr_datum_node(c, xd); + xd->node = NULL; + } + jffs2_free_xattr_datum(xd); +} + static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) { /* must be called under down_write(xattr_sem) */ struct jffs2_eraseblock *jeb; - struct jffs2_raw_node_ref *raw; struct jffs2_raw_xattr rx; size_t readlen; - uint32_t crc, offset, totlen; + uint32_t crc, totlen; int rc; - spin_lock(&c->erase_completion_lock); - offset = ref_offset(xd->node); - if (ref_flags(xd->node) == REF_PRISTINE) - goto complete; - spin_unlock(&c->erase_completion_lock); + BUG_ON(!xd->node); + BUG_ON(ref_flags(xd->node) != REF_UNCHECKED); - rc = jffs2_flash_read(c, offset, sizeof(rx), &readlen, (char *)&rx); + rc = jffs2_flash_read(c, ref_offset(xd->node), sizeof(rx), &readlen, (char *)&rx); if (rc || readlen != sizeof(rx)) { JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", - rc, sizeof(rx), readlen, offset); + rc, sizeof(rx), readlen, ref_offset(xd->node)); return rc ? rc : -EIO; } crc = crc32(0, &rx, sizeof(rx) - 4); if (crc != je32_to_cpu(rx.node_crc)) { - JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", - offset, je32_to_cpu(rx.hdr_crc), crc); - xd->flags |= JFFS2_XFLAGS_INVALID; + if (je32_to_cpu(rx.node_crc) != 0xffffffff) + JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", + ref_offset(xd->node), je32_to_cpu(rx.hdr_crc), crc); return EIO; } totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len)); @@ -159,12 +188,11 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat || je32_to_cpu(rx.version) != xd->version) { JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, " "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n", - offset, je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK, + ref_offset(xd->node), je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK, je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR, je32_to_cpu(rx.totlen), totlen, je32_to_cpu(rx.xid), xd->xid, je32_to_cpu(rx.version), xd->version); - xd->flags |= JFFS2_XFLAGS_INVALID; return EIO; } xd->xprefix = rx.xprefix; @@ -172,17 +200,14 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat xd->value_len = je16_to_cpu(rx.value_len); xd->data_crc = je32_to_cpu(rx.data_crc); + /* This JFFS2_NODETYPE_XATTR node is checked */ + jeb = &c->blocks[ref_offset(xd->node) / c->sector_size]; + totlen = PAD(je32_to_cpu(rx.totlen)); + spin_lock(&c->erase_completion_lock); - complete: - for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) { - jeb = &c->blocks[ref_offset(raw) / c->sector_size]; - totlen = PAD(ref_totlen(c, jeb, raw)); - if (ref_flags(raw) == REF_UNCHECKED) { - c->unchecked_size -= totlen; c->used_size += totlen; - jeb->unchecked_size -= totlen; jeb->used_size += totlen; - } - raw->flash_offset = ref_offset(raw) | ((xd->node==raw) ? REF_PRISTINE : REF_NORMAL); - } + c->unchecked_size -= totlen; c->used_size += totlen; + jeb->unchecked_size -= totlen; jeb->used_size += totlen; + xd->node->flash_offset = ref_offset(xd->node) | REF_PRISTINE; spin_unlock(&c->erase_completion_lock); /* unchecked xdatum is chained with c->xattr_unchecked */ @@ -202,6 +227,7 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum uint32_t crc, length; int i, ret, retry = 0; + BUG_ON(!xd->node); BUG_ON(ref_flags(xd->node) != REF_PRISTINE); BUG_ON(!list_empty(&xd->xindex)); retry: @@ -227,7 +253,6 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum " at %#08x, read: 0x%08x calculated: 0x%08x\n", ref_offset(xd->node), xd->data_crc, crc); kfree(data); - xd->flags |= JFFS2_XFLAGS_INVALID; return EIO; } @@ -261,14 +286,16 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x * rc > 0 : Unrecoverable error, this node should be deleted. */ int rc = 0; - - BUG_ON(xd->flags & JFFS2_XFLAGS_DEAD); - if (xd->xname) - return 0; - if (xd->flags & JFFS2_XFLAGS_INVALID) + BUG_ON(xd->xname); + if (!xd->node) return EIO; - if (unlikely(is_xattr_datum_unchecked(c, xd))) + if (unlikely(ref_flags(xd->node) != REF_PRISTINE)) { rc = do_verify_xattr_datum(c, xd); + if (rc > 0) { + list_del_init(&xd->xindex); + delete_xattr_datum_node(c, xd); + } + } if (!rc) rc = do_load_xattr_datum(c, xd); return rc; @@ -277,6 +304,7 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) { /* must be called under down_write(xattr_sem) */ + struct jffs2_raw_node_ref *raw; struct jffs2_raw_xattr rx; struct kvec vecs[2]; size_t length; @@ -284,16 +312,14 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x uint32_t phys_ofs = write_ofs(c); BUG_ON(!xd->xname); - BUG_ON(xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID)); vecs[0].iov_base = ℞ - vecs[0].iov_len = sizeof(rx); + vecs[0].iov_len = PAD(sizeof(rx)); vecs[1].iov_base = xd->xname; vecs[1].iov_len = xd->name_len + 1 + xd->value_len; totlen = vecs[0].iov_len + vecs[1].iov_len; /* Setup raw-xattr */ - memset(&rx, 0, sizeof(rx)); rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); rx.totlen = cpu_to_je32(PAD(totlen)); @@ -317,8 +343,14 @@ static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x return rc; } + /* success */ - jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), (void *)xd); + raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL); + /* FIXME */ raw->next_in_ino = (void *)xd; + + if (xd->node) + delete_xattr_datum_node(c, xd); + xd->node = raw; dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n", xd->xid, xd->version, xd->xprefix, xd->xname); @@ -345,7 +377,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, && xd->value_len==xsize && !strcmp(xd->xname, xname) && !memcmp(xd->xvalue, xvalue, xsize)) { - atomic_inc(&xd->refcnt); + xd->refcnt++; return xd; } } @@ -365,7 +397,7 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, strcpy(data, xname); memcpy(data + name_len + 1, xvalue, xsize); - atomic_set(&xd->refcnt, 1); + xd->refcnt = 1; xd->xid = ++c->highest_xid; xd->flags |= JFFS2_XFLAGS_HOT; xd->xprefix = xprefix; @@ -394,36 +426,20 @@ static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, return xd; } -static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) -{ - /* must be called under down_write(xattr_sem) */ - BUG_ON(atomic_read(&xd->refcnt)); - - unload_xattr_datum(c, xd); - xd->flags |= JFFS2_XFLAGS_DEAD; - spin_lock(&c->erase_completion_lock); - if (xd->node == (void *)xd) { - BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID)); - jffs2_free_xattr_datum(xd); - } else { - list_add(&xd->xindex, &c->xattr_dead_list); - } - spin_unlock(&c->erase_completion_lock); - dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xd->xid, xd->version); -} - /* -------- xref related functions ------------------ * verify_xattr_ref(c, ref) * is used to load xref information from medium. Because summary data does not * contain xid/ino, it's necessary to verify once while mounting process. + * delete_xattr_ref_node(c, ref) + * is used to delete a jffs2 node is dominated by xref. When EBS is enabled, + * it overwrites the obsolete node by myself. + * delete_xattr_ref(c, ref) + * is used to delete jffs2_xattr_ref object. If the reference counter of xdatum + * is refered by this xref become 0, delete_xattr_datum() is called later. * save_xattr_ref(c, ref) - * is used to write xref to medium. If delete marker is marked, it write - * a delete marker of xref into medium. + * is used to write xref to medium. * create_xattr_ref(c, ic, xd) * is used to create a new xref and write to medium. - * delete_xattr_ref(c, ref) - * is used to delete jffs2_xattr_ref. It marks xref XREF_DELETE_MARKER, - * and allows GC to reclaim those physical nodes. * jffs2_xattr_delete_inode(c, ic) * is called to remove xrefs related to obsolete inode when inode is unlinked. * jffs2_xattr_free_inode(c, ic) @@ -434,29 +450,25 @@ static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) { struct jffs2_eraseblock *jeb; - struct jffs2_raw_node_ref *raw; struct jffs2_raw_xref rr; size_t readlen; - uint32_t crc, offset, totlen; + uint32_t crc, totlen; int rc; - spin_lock(&c->erase_completion_lock); - if (ref_flags(ref->node) != REF_UNCHECKED) - goto complete; - offset = ref_offset(ref->node); - spin_unlock(&c->erase_completion_lock); + BUG_ON(ref_flags(ref->node) != REF_UNCHECKED); - rc = jffs2_flash_read(c, offset, sizeof(rr), &readlen, (char *)&rr); + rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr); if (rc || sizeof(rr) != readlen) { JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n", - rc, sizeof(rr), readlen, offset); + rc, sizeof(rr), readlen, ref_offset(ref->node)); return rc ? rc : -EIO; } /* obsolete node */ crc = crc32(0, &rr, sizeof(rr) - 4); if (crc != je32_to_cpu(rr.node_crc)) { - JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", - offset, je32_to_cpu(rr.node_crc), crc); + if (je32_to_cpu(rr.node_crc) != 0xffffffff) + JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", + ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc); return EIO; } if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK @@ -464,28 +476,22 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) { JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, " "nodetype=%#04x/%#04x, totlen=%u/%zu\n", - offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, + ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, je32_to_cpu(rr.totlen), PAD(sizeof(rr))); return EIO; } ref->ino = je32_to_cpu(rr.ino); ref->xid = je32_to_cpu(rr.xid); - ref->xseqno = je32_to_cpu(rr.xseqno); - if (ref->xseqno > c->highest_xseqno) - c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER); + + /* fixup superblock/eraseblock info */ + jeb = &c->blocks[ref_offset(ref->node) / c->sector_size]; + totlen = PAD(sizeof(rr)); spin_lock(&c->erase_completion_lock); - complete: - for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) { - jeb = &c->blocks[ref_offset(raw) / c->sector_size]; - totlen = PAD(ref_totlen(c, jeb, raw)); - if (ref_flags(raw) == REF_UNCHECKED) { - c->unchecked_size -= totlen; c->used_size += totlen; - jeb->unchecked_size -= totlen; jeb->used_size += totlen; - } - raw->flash_offset = ref_offset(raw) | ((ref->node==raw) ? REF_PRISTINE : REF_NORMAL); - } + c->unchecked_size -= totlen; c->used_size += totlen; + jeb->unchecked_size -= totlen; jeb->used_size += totlen; + ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE; spin_unlock(&c->erase_completion_lock); dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n", @@ -493,12 +499,58 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref return 0; } +static void delete_xattr_ref_node(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) +{ + struct jffs2_raw_xref rr; + size_t length; + int rc; + + if (jffs2_sum_active()) { + memset(&rr, 0xff, sizeof(rr)); + rc = jffs2_flash_read(c, ref_offset(ref->node), + sizeof(struct jffs2_unknown_node), + &length, (char *)&rr); + if (rc || length != sizeof(struct jffs2_unknown_node)) { + JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", + rc, sizeof(struct jffs2_unknown_node), + length, ref_offset(ref->node)); + } + rc = jffs2_flash_write(c, ref_offset(ref->node), sizeof(rr), + &length, (char *)&rr); + if (rc || length != sizeof(struct jffs2_raw_xref)) { + JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu at %#08x\n", + rc, sizeof(rr), length, ref_offset(ref->node)); + } + } + spin_lock(&c->erase_completion_lock); + ref->node->next_in_ino = NULL; + spin_unlock(&c->erase_completion_lock); + jffs2_mark_node_obsolete(c, ref->node); + ref->node = NULL; +} + +static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_xattr_datum *xd; + + BUG_ON(!ref->node); + delete_xattr_ref_node(c, ref); + + xd = ref->xd; + xd->refcnt--; + if (!xd->refcnt) + delete_xattr_datum(c, xd); + jffs2_free_xattr_ref(ref); +} + static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) { /* must be called under down_write(xattr_sem) */ + struct jffs2_raw_node_ref *raw; struct jffs2_raw_xref rr; size_t length; - uint32_t xseqno, phys_ofs = write_ofs(c); + uint32_t phys_ofs = write_ofs(c); int ret; rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -506,16 +558,8 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) rr.totlen = cpu_to_je32(PAD(sizeof(rr))); rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4)); - xseqno = (c->highest_xseqno += 2); - if (is_xattr_ref_dead(ref)) { - xseqno |= XREF_DELETE_MARKER; - rr.ino = cpu_to_je32(ref->ino); - rr.xid = cpu_to_je32(ref->xid); - } else { - rr.ino = cpu_to_je32(ref->ic->ino); - rr.xid = cpu_to_je32(ref->xd->xid); - } - rr.xseqno = cpu_to_je32(xseqno); + rr.ino = cpu_to_je32(ref->ic->ino); + rr.xid = cpu_to_je32(ref->xd->xid); rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4)); ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr); @@ -528,9 +572,12 @@ static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) return ret; } - /* success */ - ref->xseqno = xseqno; - jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), (void *)ref); + + raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL); + /* FIXME */ raw->next_in_ino = (void *)ref; + if (ref->node) + delete_xattr_ref_node(c, ref); + ref->node = raw; dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid); @@ -563,27 +610,6 @@ static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct return ref; /* success */ } -static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) -{ - /* must be called under down_write(xattr_sem) */ - struct jffs2_xattr_datum *xd; - - xd = ref->xd; - ref->xseqno |= XREF_DELETE_MARKER; - ref->ino = ref->ic->ino; - ref->xid = ref->xd->xid; - spin_lock(&c->erase_completion_lock); - ref->next = c->xref_dead_list; - c->xref_dead_list = ref; - spin_unlock(&c->erase_completion_lock); - - dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n", - ref->ino, ref->xid, ref->xseqno); - - if (atomic_dec_and_test(&xd->refcnt)) - delete_xattr_datum(c, xd); -} - void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) { /* It's called from jffs2_clear_inode() on inode removing. @@ -612,7 +638,8 @@ void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i for (ref = ic->xref; ref; ref = _ref) { _ref = ref->next; xd = ref->xd; - if (atomic_dec_and_test(&xd->refcnt)) { + xd->refcnt--; + if (!xd->refcnt) { unload_xattr_datum(c, xd); jffs2_free_xattr_datum(xd); } @@ -628,7 +655,7 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac * duplicate name/value pairs. If duplicate name/value pair would be found, * one will be removed. */ - struct jffs2_xattr_ref *ref, *cmp, **pref, **pcmp; + struct jffs2_xattr_ref *ref, *cmp, **pref; int rc = 0; if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED)) @@ -646,13 +673,13 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac } else if (unlikely(rc < 0)) goto out; } - for (cmp=ref->next, pcmp=&ref->next; cmp; pcmp=&cmp->next, cmp=cmp->next) { + for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) { if (!cmp->xd->xname) { ref->xd->flags |= JFFS2_XFLAGS_BIND; rc = load_xattr_datum(c, cmp->xd); ref->xd->flags &= ~JFFS2_XFLAGS_BIND; if (unlikely(rc > 0)) { - *pcmp = cmp->next; + *pref = cmp->next; delete_xattr_ref(c, cmp); goto retry; } else if (unlikely(rc < 0)) @@ -660,13 +687,8 @@ static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cac } if (ref->xd->xprefix == cmp->xd->xprefix && !strcmp(ref->xd->xname, cmp->xd->xname)) { - if (ref->xseqno > cmp->xseqno) { - *pcmp = cmp->next; - delete_xattr_ref(c, cmp); - } else { - *pref = ref->next; - delete_xattr_ref(c, ref); - } + *pref = cmp->next; + delete_xattr_ref(c, cmp); goto retry; } } @@ -697,13 +719,9 @@ void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c) for (i=0; i < XATTRINDEX_HASHSIZE; i++) INIT_LIST_HEAD(&c->xattrindex[i]); INIT_LIST_HEAD(&c->xattr_unchecked); - INIT_LIST_HEAD(&c->xattr_dead_list); - c->xref_dead_list = NULL; c->xref_temp = NULL; init_rwsem(&c->xattr_sem); - c->highest_xid = 0; - c->highest_xseqno = 0; c->xdatum_mem_usage = 0; c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */ } @@ -733,11 +751,7 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c) _ref = ref->next; jffs2_free_xattr_ref(ref); } - - for (ref=c->xref_dead_list; ref; ref = _ref) { - _ref = ref->next; - jffs2_free_xattr_ref(ref); - } + c->xref_temp = NULL; for (i=0; i < XATTRINDEX_HASHSIZE; i++) { list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { @@ -747,143 +761,100 @@ void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c) jffs2_free_xattr_datum(xd); } } - - list_for_each_entry_safe(xd, _xd, &c->xattr_dead_list, xindex) { - list_del(&xd->xindex); - jffs2_free_xattr_datum(xd); - } } -#define XREF_TMPHASH_SIZE (128) void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) { struct jffs2_xattr_ref *ref, *_ref; - struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE]; struct jffs2_xattr_datum *xd, *_xd; struct jffs2_inode_cache *ic; - struct jffs2_raw_node_ref *raw; - int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0; - int xdatum_orphan_count = 0, xref_orphan_count = 0, xref_dead_count = 0; + int i, xdatum_count =0, xdatum_unchecked_count = 0, xref_count = 0; BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); - /* Phase.1 : Merge same xref */ - for (i=0; i < XREF_TMPHASH_SIZE; i++) - xref_tmphash[i] = NULL; + /* Phase.1 */ for (ref=c->xref_temp; ref; ref=_ref) { - struct jffs2_xattr_ref *tmp; - _ref = ref->next; + /* checking REF_UNCHECKED nodes */ if (ref_flags(ref->node) != REF_PRISTINE) { if (verify_xattr_ref(c, ref)) { - BUG_ON(ref->node->next_in_ino != (void *)ref); - ref->node->next_in_ino = NULL; - jffs2_mark_node_obsolete(c, ref->node); + delete_xattr_ref_node(c, ref); jffs2_free_xattr_ref(ref); continue; } } - - i = (ref->ino ^ ref->xid) % XREF_TMPHASH_SIZE; - for (tmp=xref_tmphash[i]; tmp; tmp=tmp->next) { - if (tmp->ino == ref->ino && tmp->xid == ref->xid) - break; - } - if (tmp) { - raw = ref->node; - if (ref->xseqno > tmp->xseqno) { - tmp->xseqno = ref->xseqno; - raw->next_in_ino = tmp->node; - tmp->node = raw; - } else { - raw->next_in_ino = tmp->node->next_in_ino; - tmp->node->next_in_ino = raw; - } + /* At this point, ref->xid and ref->ino contain XID and inode number. + ref->xd and ref->ic are not valid yet. */ + xd = jffs2_find_xattr_datum(c, ref->xid); + ic = jffs2_get_ino_cache(c, ref->ino); + if (!xd || !ic) { + if (ref_flags(ref->node) != REF_UNCHECKED) + JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n", + ref->ino, ref->xid); + delete_xattr_ref_node(c, ref); jffs2_free_xattr_ref(ref); continue; - } else { - ref->next = xref_tmphash[i]; - xref_tmphash[i] = ref; } + ref->xd = xd; + ref->ic = ic; + xd->refcnt++; + ref->next = ic->xref; + ic->xref = ref; + xref_count++; } c->xref_temp = NULL; + /* After this, ref->xid/ino are NEVER used. */ - /* Phase.2 : Bind xref with inode_cache and xattr_datum */ - for (i=0; i < XREF_TMPHASH_SIZE; i++) { - for (ref=xref_tmphash[i]; ref; ref=_ref) { - xref_count++; - _ref = ref->next; - if (is_xattr_ref_dead(ref)) { - ref->next = c->xref_dead_list; - c->xref_dead_list = ref; - xref_dead_count++; - continue; - } - /* At this point, ref->xid and ref->ino contain XID and inode number. - ref->xd and ref->ic are not valid yet. */ - xd = jffs2_find_xattr_datum(c, ref->xid); - ic = jffs2_get_ino_cache(c, ref->ino); - if (!xd || !ic) { - dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n", - ref->ino, ref->xid, ref->xseqno); - ref->xseqno |= XREF_DELETE_MARKER; - ref->next = c->xref_dead_list; - c->xref_dead_list = ref; - xref_orphan_count++; - continue; - } - ref->xd = xd; - ref->ic = ic; - atomic_inc(&xd->refcnt); - ref->next = ic->xref; - ic->xref = ref; - } - } - - /* Phase.3 : Link unchecked xdatum to xattr_unchecked list */ + /* Phase.2 */ for (i=0; i < XATTRINDEX_HASHSIZE; i++) { list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { - xdatum_count++; list_del_init(&xd->xindex); - if (!atomic_read(&xd->refcnt)) { - dbg_xattr("xdatum(xid=%u, version=%u) is orphan.\n", - xd->xid, xd->version); - xd->flags |= JFFS2_XFLAGS_DEAD; - list_add(&xd->xindex, &c->xattr_unchecked); - xdatum_orphan_count++; + if (!xd->refcnt) { + if (ref_flags(xd->node) != REF_UNCHECKED) + JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n", + xd->xid, xd->version, ref_offset(xd->node)); + delete_xattr_datum(c, xd); continue; } - if (is_xattr_datum_unchecked(c, xd)) { - dbg_xattr("unchecked xdatum(xid=%u, version=%u)\n", - xd->xid, xd->version); + if (ref_flags(xd->node) != REF_PRISTINE) { + dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n", + xd->xid, ref_offset(xd->node)); list_add(&xd->xindex, &c->xattr_unchecked); xdatum_unchecked_count++; } + xdatum_count++; } } /* build complete */ - JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum" - " (%u unchecked, %u orphan) and " - "%u of xref (%u dead, %u orphan) found.\n", - xdatum_count, xdatum_unchecked_count, xdatum_orphan_count, - xref_count, xref_dead_count, xref_orphan_count); + JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and " + "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count); } struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, uint32_t xid, uint32_t version) { - struct jffs2_xattr_datum *xd; + struct jffs2_xattr_datum *xd, *_xd; - xd = jffs2_find_xattr_datum(c, xid); - if (!xd) { - xd = jffs2_alloc_xattr_datum(); - if (!xd) - return ERR_PTR(-ENOMEM); - xd->xid = xid; - xd->version = version; - if (xd->xid > c->highest_xid) - c->highest_xid = xd->xid; - list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]); + _xd = jffs2_find_xattr_datum(c, xid); + if (_xd) { + dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n", + xid, version, _xd->version, ref_offset(_xd->node)); + if (version < _xd->version) + return ERR_PTR(-EEXIST); + } + xd = jffs2_alloc_xattr_datum(); + if (!xd) + return ERR_PTR(-ENOMEM); + xd->xid = xid; + xd->version = version; + if (xd->xid > c->highest_xid) + c->highest_xid = xd->xid; + list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]); + + if (_xd) { + list_del_init(&_xd->xindex); + delete_xattr_datum_node(c, _xd); + jffs2_free_xattr_datum(_xd); } return xd; } @@ -1109,23 +1080,9 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, goto out; } if (!buffer) { - ref->ino = ic->ino; - ref->xid = xd->xid; - ref->xseqno |= XREF_DELETE_MARKER; - rc = save_xattr_ref(c, ref); - if (!rc) { - *pref = ref->next; - spin_lock(&c->erase_completion_lock); - ref->next = c->xref_dead_list; - c->xref_dead_list = ref; - spin_unlock(&c->erase_completion_lock); - if (atomic_dec_and_test(&xd->refcnt)) - delete_xattr_datum(c, xd); - } else { - ref->ic = ic; - ref->xd = xd; - ref->xseqno &= ~XREF_DELETE_MARKER; - } + *pref = ref->next; + delete_xattr_ref(c, ref); + rc = 0; goto out; } goto found; @@ -1137,7 +1094,7 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, goto out; } if (!buffer) { - rc = -ENODATA; + rc = -EINVAL; goto out; } found: @@ -1153,14 +1110,16 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, request = PAD(sizeof(struct jffs2_raw_xref)); rc = jffs2_reserve_space(c, request, &length, ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE); - down_write(&c->xattr_sem); if (rc) { JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); - if (atomic_dec_and_test(&xd->refcnt)) + down_write(&c->xattr_sem); + xd->refcnt--; + if (!xd->refcnt) delete_xattr_datum(c, xd); up_write(&c->xattr_sem); return rc; } + down_write(&c->xattr_sem); if (ref) *pref = ref->next; newref = create_xattr_ref(c, ic, xd); @@ -1170,7 +1129,8 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, ic->xref = ref; } rc = PTR_ERR(newref); - if (atomic_dec_and_test(&xd->refcnt)) + xd->refcnt--; + if (!xd->refcnt) delete_xattr_datum(c, xd); } else if (ref) { delete_xattr_ref(c, ref); @@ -1182,40 +1142,38 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, } /* -------- garbage collector functions ------------- - * jffs2_garbage_collect_xattr_datum(c, xd, raw) + * jffs2_garbage_collect_xattr_datum(c, xd) * is used to move xdatum into new node. - * jffs2_garbage_collect_xattr_ref(c, ref, raw) + * jffs2_garbage_collect_xattr_ref(c, ref) * is used to move xref into new node. * jffs2_verify_xattr(c) * is used to call do_verify_xattr_datum() before garbage collecting. - * jffs2_release_xattr_datum(c, xd) - * is used to release an in-memory object of xdatum. - * jffs2_release_xattr_ref(c, ref) - * is used to release an in-memory object of xref. * -------------------------------------------------- */ -int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd, - struct jffs2_raw_node_ref *raw) +int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) { uint32_t totlen, length, old_ofs; - int rc = 0; + int rc = -EINVAL; down_write(&c->xattr_sem); - if (xd->node != raw) - goto out; - if (xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID)) - goto out; + BUG_ON(!xd->node); - rc = load_xattr_datum(c, xd); - if (unlikely(rc)) { - rc = (rc > 0) ? 0 : rc; + old_ofs = ref_offset(xd->node); + totlen = ref_totlen(c, c->gcblock, xd->node); + if (totlen < sizeof(struct jffs2_raw_xattr)) goto out; + + if (!xd->xname) { + rc = load_xattr_datum(c, xd); + if (unlikely(rc > 0)) { + delete_xattr_datum_node(c, xd); + rc = 0; + goto out; + } else if (unlikely(rc < 0)) + goto out; } - old_ofs = ref_offset(xd->node); - totlen = PAD(sizeof(struct jffs2_raw_xattr) - + xd->name_len + 1 + xd->value_len); rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); - if (rc) { - JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen); + if (rc || length < totlen) { + JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen); rc = rc ? rc : -EBADFD; goto out; } @@ -1224,32 +1182,27 @@ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xatt dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n", xd->xid, xd->version, old_ofs, ref_offset(xd->node)); out: - if (!rc) - jffs2_mark_node_obsolete(c, raw); up_write(&c->xattr_sem); return rc; } -int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, - struct jffs2_raw_node_ref *raw) + +int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) { uint32_t totlen, length, old_ofs; - int rc = 0; + int rc = -EINVAL; down_write(&c->xattr_sem); BUG_ON(!ref->node); - if (ref->node != raw) - goto out; - if (is_xattr_ref_dead(ref) && (raw->next_in_ino == (void *)ref)) - goto out; - old_ofs = ref_offset(ref->node); totlen = ref_totlen(c, c->gcblock, ref->node); + if (totlen != sizeof(struct jffs2_raw_xref)) + goto out; rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE); - if (rc) { - JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n", + if (rc || length < totlen) { + JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n", __FUNCTION__, rc, totlen); rc = rc ? rc : -EBADFD; goto out; @@ -1259,8 +1212,6 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n", ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node)); out: - if (!rc) - jffs2_mark_node_obsolete(c, raw); up_write(&c->xattr_sem); return rc; } @@ -1268,59 +1219,20 @@ int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ int jffs2_verify_xattr(struct jffs2_sb_info *c) { struct jffs2_xattr_datum *xd, *_xd; - struct jffs2_eraseblock *jeb; - struct jffs2_raw_node_ref *raw; - uint32_t totlen; int rc; down_write(&c->xattr_sem); list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) { rc = do_verify_xattr_datum(c, xd); - if (rc < 0) - continue; - list_del_init(&xd->xindex); - spin_lock(&c->erase_completion_lock); - for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) { - if (ref_flags(raw) != REF_UNCHECKED) - continue; - jeb = &c->blocks[ref_offset(raw) / c->sector_size]; - totlen = PAD(ref_totlen(c, jeb, raw)); - c->unchecked_size -= totlen; c->used_size += totlen; - jeb->unchecked_size -= totlen; jeb->used_size += totlen; - raw->flash_offset = ref_offset(raw) - | ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL); + if (rc == 0) { + list_del_init(&xd->xindex); + break; + } else if (rc > 0) { + list_del_init(&xd->xindex); + delete_xattr_datum_node(c, xd); } - if (xd->flags & JFFS2_XFLAGS_DEAD) - list_add(&xd->xindex, &c->xattr_dead_list); - spin_unlock(&c->erase_completion_lock); } up_write(&c->xattr_sem); - return list_empty(&c->xattr_unchecked) ? 1 : 0; -} - -void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) -{ - /* must be called under spin_lock(&c->erase_completion_lock) */ - if (atomic_read(&xd->refcnt) || xd->node != (void *)xd) - return; - list_del(&xd->xindex); - jffs2_free_xattr_datum(xd); -} - -void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) -{ - /* must be called under spin_lock(&c->erase_completion_lock) */ - struct jffs2_xattr_ref *tmp, **ptmp; - - if (ref->node != (void *)ref) - return; - - for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) { - if (ref == tmp) { - *ptmp = tmp->next; - break; - } - } - jffs2_free_xattr_ref(ref); + return list_empty(&c->xattr_unchecked) ? 1 : 0; } diff --git a/trunk/fs/jffs2/xattr.h b/trunk/fs/jffs2/xattr.h index 06a5c69dcf8b..2c199856c582 100644 --- a/trunk/fs/jffs2/xattr.h +++ b/trunk/fs/jffs2/xattr.h @@ -16,8 +16,6 @@ #define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */ #define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */ -#define JFFS2_XFLAGS_DEAD (0x40) /* This datum is already dead */ -#define JFFS2_XFLAGS_INVALID (0x80) /* This datum contains crc error */ struct jffs2_xattr_datum { @@ -25,10 +23,10 @@ struct jffs2_xattr_datum struct jffs2_raw_node_ref *node; uint8_t class; uint8_t flags; - uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */ + uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */ struct list_head xindex; /* chained from c->xattrindex[n] */ - atomic_t refcnt; /* # of xattr_ref refers this */ + uint32_t refcnt; /* # of xattr_ref refers this */ uint32_t xid; uint32_t version; @@ -49,7 +47,6 @@ struct jffs2_xattr_ref uint8_t flags; /* Currently unused */ u16 unused; - uint32_t xseqno; union { struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */ uint32_t ino; /* only used in scanning/building */ @@ -61,12 +58,6 @@ struct jffs2_xattr_ref struct jffs2_xattr_ref *next; /* chained from ic->xref_list */ }; -#define XREF_DELETE_MARKER (0x00000001) -static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref) -{ - return ((ref->xseqno & XREF_DELETE_MARKER) != 0); -} - #ifdef CONFIG_JFFS2_FS_XATTR extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c); @@ -79,13 +70,9 @@ extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); -extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd, - struct jffs2_raw_node_ref *raw); -extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, - struct jffs2_raw_node_ref *raw); +extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd); +extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref); extern int jffs2_verify_xattr(struct jffs2_sb_info *c); -extern void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd); -extern void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref); extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, char *buffer, size_t size); diff --git a/trunk/fs/jfs/inode.c b/trunk/fs/jfs/inode.c index 43e3f566aad6..04eb78f1252e 100644 --- a/trunk/fs/jfs/inode.c +++ b/trunk/fs/jfs/inode.c @@ -305,7 +305,7 @@ static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb, offset, nr_segs, jfs_get_block, NULL); } -const struct address_space_operations jfs_aops = { +struct address_space_operations jfs_aops = { .readpage = jfs_readpage, .readpages = jfs_readpages, .writepage = jfs_writepage, diff --git a/trunk/fs/jfs/jfs_extent.c b/trunk/fs/jfs/jfs_extent.c index 4d52593a5fc6..5549378358bf 100644 --- a/trunk/fs/jfs/jfs_extent.c +++ b/trunk/fs/jfs/jfs_extent.c @@ -126,7 +126,7 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, boolean_t abnr) /* allocate the disk blocks for the extent. initially, extBalloc() * will try to allocate disk blocks for the requested size (xlen). - * if this fails (xlen contiguous free blocks not avaliable), it'll + * if this fails (xlen contigious free blocks not avaliable), it'll * try to allocate a smaller number of blocks (producing a smaller * extent), with this smaller number of blocks consisting of the * requested number of blocks rounded down to the next smaller @@ -493,7 +493,7 @@ int extFill(struct inode *ip, xad_t * xp) * * initially, we will try to allocate disk blocks for the * requested size (nblocks). if this fails (nblocks - * contiguous free blocks not avaliable), we'll try to allocate + * contigious free blocks not avaliable), we'll try to allocate * a smaller number of blocks (producing a smaller extent), with * this smaller number of blocks consisting of the requested * number of blocks rounded down to the next smaller power of 2 @@ -529,7 +529,7 @@ extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno) /* get the number of blocks to initially attempt to allocate. * we'll first try the number of blocks requested unless this - * number is greater than the maximum number of contiguous free + * number is greater than the maximum number of contigious free * blocks in the map. in that case, we'll start off with the * maximum free. */ @@ -586,7 +586,7 @@ extBalloc(struct inode *ip, s64 hint, s64 * nblocks, s64 * blkno) * in place. if this fails, we'll try to move the extent * to a new set of blocks. if moving the extent, we initially * will try to allocate disk blocks for the requested size - * (nnew). if this fails (new contiguous free blocks not + * (nnew). if this fails (nnew contigious free blocks not * avaliable), we'll try to allocate a smaller number of * blocks (producing a smaller extent), with this smaller * number of blocks consisting of the requested number of diff --git a/trunk/fs/jfs/jfs_inode.h b/trunk/fs/jfs/jfs_inode.h index b5c7da6190dc..c30072674464 100644 --- a/trunk/fs/jfs/jfs_inode.h +++ b/trunk/fs/jfs/jfs_inode.h @@ -33,7 +33,7 @@ extern void jfs_free_zero_link(struct inode *); extern struct dentry *jfs_get_parent(struct dentry *dentry); extern void jfs_set_inode_flags(struct inode *); -extern const struct address_space_operations jfs_aops; +extern struct address_space_operations jfs_aops; extern struct inode_operations jfs_dir_inode_operations; extern const struct file_operations jfs_dir_operations; extern struct inode_operations jfs_file_inode_operations; diff --git a/trunk/fs/jfs/jfs_metapage.c b/trunk/fs/jfs/jfs_metapage.c index e1e0a6e6ebdf..7f6e88039700 100644 --- a/trunk/fs/jfs/jfs_metapage.c +++ b/trunk/fs/jfs/jfs_metapage.c @@ -577,7 +577,7 @@ static void metapage_invalidatepage(struct page *page, unsigned long offset) metapage_releasepage(page, 0); } -const struct address_space_operations jfs_metapage_aops = { +struct address_space_operations jfs_metapage_aops = { .readpage = metapage_readpage, .writepage = metapage_writepage, .sync_page = block_sync_page, diff --git a/trunk/fs/jfs/jfs_metapage.h b/trunk/fs/jfs/jfs_metapage.h index d17a3290f5aa..f0b7d3282b07 100644 --- a/trunk/fs/jfs/jfs_metapage.h +++ b/trunk/fs/jfs/jfs_metapage.h @@ -139,7 +139,7 @@ static inline void metapage_homeok(struct metapage *mp) put_metapage(mp); } -extern const struct address_space_operations jfs_metapage_aops; +extern struct address_space_operations jfs_metapage_aops; /* * This routines invalidate all pages for an extent. diff --git a/trunk/fs/jfs/jfs_txnmgr.c b/trunk/fs/jfs/jfs_txnmgr.c index 10c46231ce15..ac3d66948e8c 100644 --- a/trunk/fs/jfs/jfs_txnmgr.c +++ b/trunk/fs/jfs/jfs_txnmgr.c @@ -842,7 +842,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, TXN_UNLOCK(); release_metapage(mp); TXN_LOCK(); - xtid = tlck->tid; /* reacquire after dropping TXN_LOCK */ + xtid = tlck->tid; /* reaquire after dropping TXN_LOCK */ jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d", tid, xtid, lid); diff --git a/trunk/fs/jfs/super.c b/trunk/fs/jfs/super.c index 4f6cfebc82db..73d2aba084c6 100644 --- a/trunk/fs/jfs/super.c +++ b/trunk/fs/jfs/super.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include diff --git a/trunk/fs/libfs.c b/trunk/fs/libfs.c index ac02ea602c3d..fc785d8befb9 100644 --- a/trunk/fs/libfs.c +++ b/trunk/fs/libfs.c @@ -149,9 +149,10 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) /* fallthrough */ default: spin_lock(&dcache_lock); - if (filp->f_pos == 2) - list_move(q, &dentry->d_subdirs); - + if (filp->f_pos == 2) { + list_del(q); + list_add(q, &dentry->d_subdirs); + } for (p=q->next; p != &dentry->d_subdirs; p=p->next) { struct dentry *next; next = list_entry(p, struct dentry, d_u.d_child); @@ -163,7 +164,8 @@ int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) return 0; spin_lock(&dcache_lock); /* next is still alive */ - list_move(q, p); + list_del(q); + list_add(q, p); p = q; filp->f_pos++; } diff --git a/trunk/fs/lockd/clntproc.c b/trunk/fs/lockd/clntproc.c index 5980c45998cc..4db62098d3f4 100644 --- a/trunk/fs/lockd/clntproc.c +++ b/trunk/fs/lockd/clntproc.c @@ -6,6 +6,7 @@ * Copyright (C) 1996, Olaf Kirch */ +#include #include #include #include diff --git a/trunk/fs/lockd/svc.c b/trunk/fs/lockd/svc.c index 9a991b52c647..fd56c8872f34 100644 --- a/trunk/fs/lockd/svc.c +++ b/trunk/fs/lockd/svc.c @@ -12,6 +12,7 @@ * Copyright (C) 1995, 1996 Olaf Kirch */ +#include #include #include #include diff --git a/trunk/fs/lockd/svclock.c b/trunk/fs/lockd/svclock.c index baf5ae513481..3ef739120dff 100644 --- a/trunk/fs/lockd/svclock.c +++ b/trunk/fs/lockd/svclock.c @@ -20,6 +20,7 @@ * Copyright (C) 1996, Olaf Kirch */ +#include #include #include #include diff --git a/trunk/fs/lockd/svcproc.c b/trunk/fs/lockd/svcproc.c index dbb66a3b5cd9..d210cf304e92 100644 --- a/trunk/fs/lockd/svcproc.c +++ b/trunk/fs/lockd/svcproc.c @@ -7,6 +7,7 @@ * Copyright (C) 1996, Olaf Kirch */ +#include #include #include #include diff --git a/trunk/fs/lockd/svcsubs.c b/trunk/fs/lockd/svcsubs.c index 2a4df9b3779a..a570e5c8a930 100644 --- a/trunk/fs/lockd/svcsubs.c +++ b/trunk/fs/lockd/svcsubs.c @@ -6,6 +6,7 @@ * Copyright (C) 1996, Olaf Kirch */ +#include #include #include #include diff --git a/trunk/fs/lockd/xdr.c b/trunk/fs/lockd/xdr.c index 033ea4ac2c30..f22a3764461a 100644 --- a/trunk/fs/lockd/xdr.c +++ b/trunk/fs/lockd/xdr.c @@ -6,6 +6,7 @@ * Copyright (C) 1995, 1996 Olaf Kirch */ +#include #include #include #include diff --git a/trunk/fs/minix/inode.c b/trunk/fs/minix/inode.c index 9ea91c5eeb7b..a6fb509b7341 100644 --- a/trunk/fs/minix/inode.c +++ b/trunk/fs/minix/inode.c @@ -335,7 +335,7 @@ static sector_t minix_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping,block,minix_get_block); } -static const struct address_space_operations minix_aops = { +static struct address_space_operations minix_aops = { .readpage = minix_readpage, .writepage = minix_writepage, .sync_page = block_sync_page, diff --git a/trunk/fs/namespace.c b/trunk/fs/namespace.c index fa7ed6a9fc2d..866430bb024d 100644 --- a/trunk/fs/namespace.c +++ b/trunk/fs/namespace.c @@ -8,6 +8,7 @@ * Heavily rewritten. */ +#include #include #include #include @@ -525,8 +526,10 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) { struct vfsmount *p; - for (p = mnt; p; p = next_mnt(p, mnt)) - list_move(&p->mnt_hash, kill); + for (p = mnt; p; p = next_mnt(p, mnt)) { + list_del(&p->mnt_hash); + list_add(&p->mnt_hash, kill); + } if (propagate) propagate_umount(kill); diff --git a/trunk/fs/ncpfs/dir.c b/trunk/fs/ncpfs/dir.c index b4ee89250e95..f0860c602d8b 100644 --- a/trunk/fs/ncpfs/dir.c +++ b/trunk/fs/ncpfs/dir.c @@ -10,6 +10,7 @@ * */ +#include #include #include diff --git a/trunk/fs/ncpfs/inode.c b/trunk/fs/ncpfs/inode.c index 1ddf77b0b825..90d2ea28f333 100644 --- a/trunk/fs/ncpfs/inode.c +++ b/trunk/fs/ncpfs/inode.c @@ -9,6 +9,7 @@ * */ +#include #include #include @@ -104,7 +105,7 @@ static struct super_operations ncp_sops = extern struct dentry_operations ncp_root_dentry_operations; #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) -extern const struct address_space_operations ncp_symlink_aops; +extern struct address_space_operations ncp_symlink_aops; extern int ncp_symlink(struct inode*, struct dentry*, const char*); #endif diff --git a/trunk/fs/ncpfs/ioctl.c b/trunk/fs/ncpfs/ioctl.c index 42039fe0653c..eb3813ad136f 100644 --- a/trunk/fs/ncpfs/ioctl.c +++ b/trunk/fs/ncpfs/ioctl.c @@ -7,6 +7,7 @@ * */ +#include #include #include diff --git a/trunk/fs/ncpfs/mmap.c b/trunk/fs/ncpfs/mmap.c index e7d5a3097fe6..52d60c3d8996 100644 --- a/trunk/fs/ncpfs/mmap.c +++ b/trunk/fs/ncpfs/mmap.c @@ -93,7 +93,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area, */ if (type) *type = VM_FAULT_MAJOR; - count_vm_event(PGMAJFAULT); + inc_page_state(pgmajfault); return page; } diff --git a/trunk/fs/ncpfs/ncplib_kernel.c b/trunk/fs/ncpfs/ncplib_kernel.c index 551e0bac7aac..d9ebf6439f59 100644 --- a/trunk/fs/ncpfs/ncplib_kernel.c +++ b/trunk/fs/ncpfs/ncplib_kernel.c @@ -10,6 +10,7 @@ */ +#include #include "ncplib_kernel.h" diff --git a/trunk/fs/ncpfs/ncplib_kernel.h b/trunk/fs/ncpfs/ncplib_kernel.h index 2441d1ab57dc..799e5c2bec55 100644 --- a/trunk/fs/ncpfs/ncplib_kernel.h +++ b/trunk/fs/ncpfs/ncplib_kernel.h @@ -12,6 +12,7 @@ #ifndef _NCPLIB_H #define _NCPLIB_H +#include #include #include diff --git a/trunk/fs/ncpfs/ncpsign_kernel.c b/trunk/fs/ncpfs/ncpsign_kernel.c index 749a18d33599..a6ec90cd8894 100644 --- a/trunk/fs/ncpfs/ncpsign_kernel.c +++ b/trunk/fs/ncpfs/ncpsign_kernel.c @@ -5,6 +5,7 @@ * */ +#include #ifdef CONFIG_NCPFS_PACKET_SIGNING diff --git a/trunk/fs/ncpfs/sock.c b/trunk/fs/ncpfs/sock.c index 11c2b252ebed..8783eb7ec641 100644 --- a/trunk/fs/ncpfs/sock.c +++ b/trunk/fs/ncpfs/sock.c @@ -8,6 +8,7 @@ * */ +#include #include #include diff --git a/trunk/fs/ncpfs/symlink.c b/trunk/fs/ncpfs/symlink.c index ca92c2406635..e935f1b34bc2 100644 --- a/trunk/fs/ncpfs/symlink.c +++ b/trunk/fs/ncpfs/symlink.c @@ -20,6 +20,7 @@ * */ +#include #include @@ -98,7 +99,7 @@ static int ncp_symlink_readpage(struct file *file, struct page *page) /* * symlinks can't do much... */ -const struct address_space_operations ncp_symlink_aops = { +struct address_space_operations ncp_symlink_aops = { .readpage = ncp_symlink_readpage, }; diff --git a/trunk/fs/nfs/callback.c b/trunk/fs/nfs/callback.c index fe0a6b8ac149..d53f8c6a9ecb 100644 --- a/trunk/fs/nfs/callback.c +++ b/trunk/fs/nfs/callback.c @@ -6,6 +6,7 @@ * NFSv4 callback handling */ +#include #include #include #include diff --git a/trunk/fs/nfs/callback_proc.c b/trunk/fs/nfs/callback_proc.c index 7719483ecdfc..462cfceb50c5 100644 --- a/trunk/fs/nfs/callback_proc.c +++ b/trunk/fs/nfs/callback_proc.c @@ -5,6 +5,7 @@ * * NFSv4 callback procedures */ +#include #include #include #include "nfs4_fs.h" diff --git a/trunk/fs/nfs/callback_xdr.c b/trunk/fs/nfs/callback_xdr.c index 29f932192054..c92991328d9a 100644 --- a/trunk/fs/nfs/callback_xdr.c +++ b/trunk/fs/nfs/callback_xdr.c @@ -5,6 +5,7 @@ * * NFSv4 callback encode/decode procedures */ +#include #include #include #include diff --git a/trunk/fs/nfs/delegation.c b/trunk/fs/nfs/delegation.c index 9540a316c05e..d3be923d4e43 100644 --- a/trunk/fs/nfs/delegation.c +++ b/trunk/fs/nfs/delegation.c @@ -6,6 +6,7 @@ * NFS file delegation management * */ +#include #include #include #include diff --git a/trunk/fs/nfs/direct.c b/trunk/fs/nfs/direct.c index 4cdd1b499e35..402005c35ab3 100644 --- a/trunk/fs/nfs/direct.c +++ b/trunk/fs/nfs/direct.c @@ -38,6 +38,7 @@ * */ +#include #include #include #include @@ -908,7 +909,7 @@ int __init nfs_init_directcache(void) * nfs_destroy_directcache - destroy the slab cache for nfs_direct_req structures * */ -void nfs_destroy_directcache(void) +void __exit nfs_destroy_directcache(void) { if (kmem_cache_destroy(nfs_direct_cachep)) printk(KERN_INFO "nfs_direct_cache: not all structures were freed\n"); diff --git a/trunk/fs/nfs/file.c b/trunk/fs/nfs/file.c index cc2b874ad5a4..add289138836 100644 --- a/trunk/fs/nfs/file.c +++ b/trunk/fs/nfs/file.c @@ -315,7 +315,7 @@ static int nfs_release_page(struct page *page, gfp_t gfp) return !nfs_wb_page(page->mapping->host, page); } -const struct address_space_operations nfs_file_aops = { +struct address_space_operations nfs_file_aops = { .readpage = nfs_readpage, .readpages = nfs_readpages, .set_page_dirty = __set_page_dirty_nobuffers, diff --git a/trunk/fs/nfs/inode.c b/trunk/fs/nfs/inode.c index d349fb2245da..51bc88b662fe 100644 --- a/trunk/fs/nfs/inode.c +++ b/trunk/fs/nfs/inode.c @@ -13,6 +13,7 @@ * */ +#include #include #include @@ -1131,7 +1132,7 @@ static int __init nfs_init_inodecache(void) return 0; } -static void nfs_destroy_inodecache(void) +static void __exit nfs_destroy_inodecache(void) { if (kmem_cache_destroy(nfs_inode_cachep)) printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n"); diff --git a/trunk/fs/nfs/internal.h b/trunk/fs/nfs/internal.h index e4f4e5def0fc..bd2815e2dec1 100644 --- a/trunk/fs/nfs/internal.h +++ b/trunk/fs/nfs/internal.h @@ -31,15 +31,15 @@ extern struct svc_version nfs4_callback_version1; /* pagelist.c */ extern int __init nfs_init_nfspagecache(void); -extern void nfs_destroy_nfspagecache(void); +extern void __exit nfs_destroy_nfspagecache(void); extern int __init nfs_init_readpagecache(void); -extern void nfs_destroy_readpagecache(void); +extern void __exit nfs_destroy_readpagecache(void); extern int __init nfs_init_writepagecache(void); -extern void nfs_destroy_writepagecache(void); +extern void __exit nfs_destroy_writepagecache(void); #ifdef CONFIG_NFS_DIRECTIO extern int __init nfs_init_directcache(void); -extern void nfs_destroy_directcache(void); +extern void __exit nfs_destroy_directcache(void); #else #define nfs_init_directcache() (0) #define nfs_destroy_directcache() do {} while(0) @@ -81,9 +81,9 @@ extern struct file_system_type clone_nfs_fs_type; #ifdef CONFIG_NFS_V4 extern struct file_system_type clone_nfs4_fs_type; #endif - +#ifdef CONFIG_PROC_FS extern struct rpc_stat nfs_rpcstat; - +#endif extern int __init register_nfs_fs(void); extern void __exit unregister_nfs_fs(void); diff --git a/trunk/fs/nfs/nfs4state.c b/trunk/fs/nfs/nfs4state.c index 090a36b07a22..96e5b82c153b 100644 --- a/trunk/fs/nfs/nfs4state.c +++ b/trunk/fs/nfs/nfs4state.c @@ -38,6 +38,7 @@ * subsequent patch. */ +#include #include #include #include diff --git a/trunk/fs/nfs/pagelist.c b/trunk/fs/nfs/pagelist.c index 36e902a88ca1..ef9429643ebc 100644 --- a/trunk/fs/nfs/pagelist.c +++ b/trunk/fs/nfs/pagelist.c @@ -9,6 +9,7 @@ * */ +#include #include #include #include @@ -314,7 +315,6 @@ nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst, req->wb_index, NFS_PAGE_TAG_DIRTY); nfs_list_remove_request(req); nfs_list_add_request(req, dst); - dec_zone_page_state(req->wb_page, NR_FILE_DIRTY); res++; } } @@ -390,7 +390,7 @@ int __init nfs_init_nfspagecache(void) return 0; } -void nfs_destroy_nfspagecache(void) +void __exit nfs_destroy_nfspagecache(void) { if (kmem_cache_destroy(nfs_page_cachep)) printk(KERN_INFO "nfs_page: not all structures were freed\n"); diff --git a/trunk/fs/nfs/read.c b/trunk/fs/nfs/read.c index 52bf634260a1..41c2ffee24f5 100644 --- a/trunk/fs/nfs/read.c +++ b/trunk/fs/nfs/read.c @@ -15,6 +15,7 @@ * within the RPC code when root squashing is suspected. */ +#include #include #include #include @@ -710,7 +711,7 @@ int __init nfs_init_readpagecache(void) return 0; } -void nfs_destroy_readpagecache(void) +void __exit nfs_destroy_readpagecache(void) { mempool_destroy(nfs_rdata_mempool); if (kmem_cache_destroy(nfs_rdata_cachep)) diff --git a/trunk/fs/nfs/sysctl.c b/trunk/fs/nfs/sysctl.c index 2fe3403c2409..db61e51bb154 100644 --- a/trunk/fs/nfs/sysctl.c +++ b/trunk/fs/nfs/sysctl.c @@ -3,6 +3,7 @@ * * Sysctl interface to NFS parameters */ +#include #include #include #include diff --git a/trunk/fs/nfs/write.c b/trunk/fs/nfs/write.c index bca5734ca9fb..b383fdd3a15c 100644 --- a/trunk/fs/nfs/write.c +++ b/trunk/fs/nfs/write.c @@ -46,6 +46,7 @@ * Copyright (C) 1996, 1997, Olaf Kirch */ +#include #include #include #include @@ -496,7 +497,7 @@ nfs_mark_request_dirty(struct nfs_page *req) nfs_list_add_request(req, &nfsi->dirty); nfsi->ndirty++; spin_unlock(&nfsi->req_lock); - inc_zone_page_state(req->wb_page, NR_FILE_DIRTY); + inc_page_state(nr_dirty); mark_inode_dirty(inode); } @@ -524,7 +525,7 @@ nfs_mark_request_commit(struct nfs_page *req) nfs_list_add_request(req, &nfsi->commit); nfsi->ncommit++; spin_unlock(&nfsi->req_lock); - inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); + inc_page_state(nr_unstable); mark_inode_dirty(inode); } #endif @@ -608,6 +609,7 @@ nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_sta if (nfsi->ndirty != 0) { res = nfs_scan_lock_dirty(nfsi, dst, idx_start, npages); nfsi->ndirty -= res; + sub_page_state(nr_dirty,res); if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty)) printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n"); } @@ -1392,6 +1394,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) { struct nfs_write_data *data = calldata; struct nfs_page *req; + int res = 0; dprintk("NFS: %4d nfs_commit_done (status %d)\n", task->tk_pid, task->tk_status); @@ -1403,7 +1406,6 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) while (!list_empty(&data->pages)) { req = nfs_list_entry(data->pages.next); nfs_list_remove_request(req); - dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); dprintk("NFS: commit (%s/%Ld %d@%Ld)", req->wb_context->dentry->d_inode->i_sb->s_id, @@ -1430,7 +1432,9 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) nfs_mark_request_dirty(req); next: nfs_clear_page_writeback(req); + res++; } + sub_page_state(nr_unstable,res); } static const struct rpc_call_ops nfs_commit_ops = { @@ -1547,7 +1551,7 @@ int __init nfs_init_writepagecache(void) return 0; } -void nfs_destroy_writepagecache(void) +void __exit nfs_destroy_writepagecache(void) { mempool_destroy(nfs_commit_mempool); mempool_destroy(nfs_wdata_mempool); diff --git a/trunk/fs/nfsctl.c b/trunk/fs/nfsctl.c index c043136a82ca..a5a18d4aca40 100644 --- a/trunk/fs/nfsctl.c +++ b/trunk/fs/nfsctl.c @@ -4,6 +4,7 @@ * This should eventually move to userland. * */ +#include #include #include #include diff --git a/trunk/fs/nfsd/export.c b/trunk/fs/nfsd/export.c index 01bc68c628ad..3eec30000f3f 100644 --- a/trunk/fs/nfsd/export.c +++ b/trunk/fs/nfsd/export.c @@ -126,7 +126,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) if (*ep) goto out; dprintk("found fsidtype %d\n", fsidtype); - if (key_len(fsidtype)==0) /* invalid type */ + if (fsidtype > 2) goto out; if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) goto out; diff --git a/trunk/fs/nfsd/nfs4callback.c b/trunk/fs/nfsd/nfs4callback.c index 54b37b1d2e3a..dbaf3f93f328 100644 --- a/trunk/fs/nfsd/nfs4callback.c +++ b/trunk/fs/nfsd/nfs4callback.c @@ -33,6 +33,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include diff --git a/trunk/fs/nfsd/nfs4idmap.c b/trunk/fs/nfsd/nfs4idmap.c index bea6b9478114..4b6aa60dfceb 100644 --- a/trunk/fs/nfsd/nfs4idmap.c +++ b/trunk/fs/nfsd/nfs4idmap.c @@ -34,6 +34,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include diff --git a/trunk/fs/nfsd/nfs4state.c b/trunk/fs/nfsd/nfs4state.c index 9daa0b9feb8d..96c7578cbe1e 100644 --- a/trunk/fs/nfsd/nfs4state.c +++ b/trunk/fs/nfsd/nfs4state.c @@ -123,7 +123,7 @@ static void release_stateid(struct nfs4_stateid *stp, int flags); */ /* recall_lock protects the del_recall_lru */ -static DEFINE_SPINLOCK(recall_lock); +static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED; static struct list_head del_recall_lru; static void @@ -529,7 +529,8 @@ move_to_confirmed(struct nfs4_client *clp) dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp); list_del_init(&clp->cl_strhash); - list_move(&clp->cl_idhash, &conf_id_hashtbl[idhashval]); + list_del_init(&clp->cl_idhash); + list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]); strhashval = clientstr_hashval(clp->cl_recdir); list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]); renew_client(clp); @@ -1237,15 +1238,8 @@ find_file(struct inode *ino) return NULL; } -static int access_valid(u32 x) -{ - return (x > 0 && x < 4); -} - -static int deny_valid(u32 x) -{ - return (x >= 0 && x < 5); -} +#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0) +#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0) static void set_access(unsigned int *access, unsigned long bmap) { @@ -1752,8 +1746,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf int status; status = nfserr_inval; - if (!access_valid(open->op_share_access) - || !deny_valid(open->op_share_deny)) + if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) goto out; /* * Lookup file; if found, lookup stateid and check open request, @@ -1790,10 +1783,10 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf } else { /* Stateid was not found, this is a new OPEN */ int flags = 0; - if (open->op_share_access & NFS4_SHARE_ACCESS_READ) - flags |= MAY_READ; if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) - flags |= MAY_WRITE; + flags = MAY_WRITE; + else + flags = MAY_READ; status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags); if (status) goto out; @@ -2078,12 +2071,16 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl if (!stateid->si_fileid) { /* delegation stateid */ if(!(dp = find_delegation_stateid(ino, stateid))) { dprintk("NFSD: delegation stateid not found\n"); + if (nfs4_in_grace()) + status = nfserr_grace; goto out; } stidp = &dp->dl_stateid; } else { /* open or lock stateid */ if (!(stp = find_stateid(stateid, flags))) { dprintk("NFSD: open or lock stateid not found\n"); + if (nfs4_in_grace()) + status = nfserr_grace; goto out; } if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) @@ -2256,9 +2253,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs (int)current_fh->fh_dentry->d_name.len, current_fh->fh_dentry->d_name.name); - status = fh_verify(rqstp, current_fh, S_IFREG, 0); - if (status) - return status; + if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) + goto out; nfs4_lock_state(); @@ -2325,8 +2321,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n (int)current_fh->fh_dentry->d_name.len, current_fh->fh_dentry->d_name.name); - if (!access_valid(od->od_share_access) - || !deny_valid(od->od_share_deny)) + if (!TEST_ACCESS(od->od_share_access) || !TEST_DENY(od->od_share_deny)) return nfserr_inval; nfs4_lock_state(); diff --git a/trunk/fs/nfsd/nfscache.c b/trunk/fs/nfsd/nfscache.c index fdf7cf3dfadc..d852ebb538e3 100644 --- a/trunk/fs/nfsd/nfscache.c +++ b/trunk/fs/nfsd/nfscache.c @@ -103,7 +103,8 @@ nfsd_cache_shutdown(void) static void lru_put_end(struct svc_cacherep *rp) { - list_move_tail(&rp->c_lru, &lru_head); + list_del(&rp->c_lru); + list_add_tail(&rp->c_lru, &lru_head); } /* diff --git a/trunk/fs/nfsd/nfsctl.c b/trunk/fs/nfsd/nfsctl.c index 7046ac9cf97f..a1810e6a93e5 100644 --- a/trunk/fs/nfsd/nfsctl.c +++ b/trunk/fs/nfsd/nfsctl.c @@ -6,6 +6,7 @@ * Copyright (C) 1995, 1996 Olaf Kirch */ +#include #include #include diff --git a/trunk/fs/nfsd/nfsfh.c b/trunk/fs/nfsd/nfsfh.c index ecc439d2565f..3f2ec2e6d06c 100644 --- a/trunk/fs/nfsd/nfsfh.c +++ b/trunk/fs/nfsd/nfsfh.c @@ -187,6 +187,13 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) goto out; } + /* Set user creds for this exportpoint */ + error = nfsd_setuser(rqstp, exp); + if (error) { + error = nfserrno(error); + goto out; + } + /* * Look up the dentry using the NFS file handle. */ @@ -244,14 +251,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) } cache_get(&exp->h); - /* Set user creds for this exportpoint; necessary even in the "just - * checking" case because this may be a filehandle that was created by - * fh_compose, and that is about to be used in another nfsv4 compound - * operation */ - error = nfserrno(nfsd_setuser(rqstp, exp)); - if (error) - goto out; - error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type); if (error) goto out; @@ -313,8 +312,8 @@ int fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, struct svc_fh *ref_fh) { /* ref_fh is a reference file handle. - * if it is non-null and for the same filesystem, then we should compose - * a filehandle which is of the same version, where possible. + * if it is non-null, then we should compose a filehandle which is + * of the same version, where possible. * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca * Then create a 32byte filehandle using nfs_fhbase_old * @@ -333,7 +332,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, st parent->d_name.name, dentry->d_name.name, (inode ? inode->i_ino : 0)); - if (ref_fh && ref_fh->fh_export == exp) { + if (ref_fh) { ref_fh_version = ref_fh->fh_handle.fh_version; if (ref_fh_version == 0xca) ref_fh_fsid_type = 0; @@ -462,7 +461,7 @@ fh_update(struct svc_fh *fhp) } else { int size; if (fhp->fh_handle.fh_fileid_type != 0) - goto out; + goto out_uptodate; datap = fhp->fh_handle.fh_auth+ fhp->fh_handle.fh_size/4 -1; size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4; @@ -482,6 +481,10 @@ fh_update(struct svc_fh *fhp) printk(KERN_ERR "fh_update: %s/%s still negative!\n", dentry->d_parent->d_name.name, dentry->d_name.name); goto out; +out_uptodate: + printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n", + dentry->d_parent->d_name.name, dentry->d_name.name); + goto out; } /* diff --git a/trunk/fs/nfsd/nfssvc.c b/trunk/fs/nfsd/nfssvc.c index ec1decf29bab..3790727e5dfd 100644 --- a/trunk/fs/nfsd/nfssvc.c +++ b/trunk/fs/nfsd/nfssvc.c @@ -8,6 +8,7 @@ * Copyright (C) 1995, 1996, 1997 Olaf Kirch */ +#include #include #include diff --git a/trunk/fs/nfsd/vfs.c b/trunk/fs/nfsd/vfs.c index c9e3b5a8fe07..245eaa1fb59b 100644 --- a/trunk/fs/nfsd/vfs.c +++ b/trunk/fs/nfsd/vfs.c @@ -16,6 +16,7 @@ * Zerocpy NFS support (C) 2002 Hirokazu Takahashi */ +#include #include #include #include @@ -672,10 +673,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, goto out_nfserr; if (access & MAY_WRITE) { - if (access & MAY_READ) - flags = O_RDWR|O_LARGEFILE; - else - flags = O_WRONLY|O_LARGEFILE; + flags = O_WRONLY|O_LARGEFILE; DQUOT_INIT(inode); } @@ -836,7 +834,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, if (ra && ra->p_set) file->f_ra = ra->p_ra; - if (file->f_op->sendfile && rqstp->rq_sendfile_ok) { + if (file->f_op->sendfile) { svc_pushback_unused_pages(rqstp); err = file->f_op->sendfile(file, &offset, *count, nfsd_read_actor, rqstp); @@ -1519,15 +1517,14 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, err = nfserrno(err); } - dput(dnew); -out_unlock: fh_unlock(ffhp); + dput(dnew); out: return err; out_nfserr: err = nfserrno(err); - goto out_unlock; + goto out; } /* @@ -1556,7 +1553,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, tdir = tdentry->d_inode; err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev; - if (ffhp->fh_export != tfhp->fh_export) + if (fdir->i_sb != tdir->i_sb) goto out; err = nfserr_perm; diff --git a/trunk/fs/nls/nls_base.c b/trunk/fs/nls/nls_base.c index 9de6b495f112..a912debcd20b 100644 --- a/trunk/fs/nls/nls_base.c +++ b/trunk/fs/nls/nls_base.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include diff --git a/trunk/fs/ntfs/aops.c b/trunk/fs/ntfs/aops.c index bc579bfdfbd8..580412d330cb 100644 --- a/trunk/fs/ntfs/aops.c +++ b/trunk/fs/ntfs/aops.c @@ -1544,7 +1544,7 @@ static int ntfs_writepage(struct page *page, struct writeback_control *wbc) /** * ntfs_aops - general address space operations for inodes and attributes */ -const struct address_space_operations ntfs_aops = { +struct address_space_operations ntfs_aops = { .readpage = ntfs_readpage, /* Fill page with data. */ .sync_page = block_sync_page, /* Currently, just unplugs the disk request queue. */ @@ -1560,7 +1560,7 @@ const struct address_space_operations ntfs_aops = { * ntfs_mst_aops - general address space operations for mst protecteed inodes * and attributes */ -const struct address_space_operations ntfs_mst_aops = { +struct address_space_operations ntfs_mst_aops = { .readpage = ntfs_readpage, /* Fill page with data. */ .sync_page = block_sync_page, /* Currently, just unplugs the disk request queue. */ diff --git a/trunk/fs/ntfs/ntfs.h b/trunk/fs/ntfs/ntfs.h index ddd3d503097c..bf7b3d7c0930 100644 --- a/trunk/fs/ntfs/ntfs.h +++ b/trunk/fs/ntfs/ntfs.h @@ -57,8 +57,8 @@ extern struct kmem_cache *ntfs_attr_ctx_cache; extern struct kmem_cache *ntfs_index_ctx_cache; /* The various operations structs defined throughout the driver files. */ -extern const struct address_space_operations ntfs_aops; -extern const struct address_space_operations ntfs_mst_aops; +extern struct address_space_operations ntfs_aops; +extern struct address_space_operations ntfs_mst_aops; extern const struct file_operations ntfs_file_ops; extern struct inode_operations ntfs_file_inode_ops; diff --git a/trunk/fs/ntfs/sysctl.h b/trunk/fs/ntfs/sysctl.h index beda5bf96405..c8064cae8f17 100644 --- a/trunk/fs/ntfs/sysctl.h +++ b/trunk/fs/ntfs/sysctl.h @@ -24,6 +24,7 @@ #ifndef _LINUX_NTFS_SYSCTL_H #define _LINUX_NTFS_SYSCTL_H +#include #if defined(DEBUG) && defined(CONFIG_SYSCTL) diff --git a/trunk/fs/ocfs2/aops.c b/trunk/fs/ocfs2/aops.c index f1d1c342ce01..47152bf9a7f2 100644 --- a/trunk/fs/ocfs2/aops.c +++ b/trunk/fs/ocfs2/aops.c @@ -558,9 +558,16 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, u64 vbo_max; /* file offset, max_blocks from iblock */ u64 p_blkno; int contig_blocks; - unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; + unsigned char blocksize_bits; unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; + if (!inode || !bh_result) { + mlog(ML_ERROR, "inode or bh_result is null\n"); + return -EIO; + } + + blocksize_bits = inode->i_sb->s_blocksize_bits; + /* This function won't even be called if the request isn't all * nicely aligned and of the right size, so there's no need * for us to check any of that. */ @@ -659,7 +666,7 @@ static ssize_t ocfs2_direct_IO(int rw, return ret; } -const struct address_space_operations ocfs2_aops = { +struct address_space_operations ocfs2_aops = { .readpage = ocfs2_readpage, .writepage = ocfs2_writepage, .prepare_write = ocfs2_prepare_write, diff --git a/trunk/fs/ocfs2/cluster/heartbeat.c b/trunk/fs/ocfs2/cluster/heartbeat.c index 504595d6cf65..21f38accd039 100644 --- a/trunk/fs/ocfs2/cluster/heartbeat.c +++ b/trunk/fs/ocfs2/cluster/heartbeat.c @@ -54,7 +54,7 @@ static DECLARE_RWSEM(o2hb_callback_sem); * multiple hb threads are watching multiple regions. A node is live * whenever any of the threads sees activity from the node in its region. */ -static DEFINE_SPINLOCK(o2hb_live_lock); +static spinlock_t o2hb_live_lock = SPIN_LOCK_UNLOCKED; static struct list_head o2hb_live_slots[O2NM_MAX_NODES]; static unsigned long o2hb_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; static LIST_HEAD(o2hb_node_events); @@ -517,7 +517,6 @@ static inline void o2hb_prepare_block(struct o2hb_region *reg, hb_block->hb_seq = cpu_to_le64(cputime); hb_block->hb_node = node_num; hb_block->hb_generation = cpu_to_le64(generation); - hb_block->hb_dead_ms = cpu_to_le32(o2hb_dead_threshold * O2HB_REGION_TIMEOUT_MS); /* This step must always happen last! */ hb_block->hb_cksum = cpu_to_le32(o2hb_compute_block_crc_le(reg, @@ -646,8 +645,6 @@ static int o2hb_check_slot(struct o2hb_region *reg, struct o2nm_node *node; struct o2hb_disk_heartbeat_block *hb_block = reg->hr_tmp_block; u64 cputime; - unsigned int dead_ms = o2hb_dead_threshold * O2HB_REGION_TIMEOUT_MS; - unsigned int slot_dead_ms; memcpy(hb_block, slot->ds_raw_block, reg->hr_block_bytes); @@ -736,23 +733,6 @@ static int o2hb_check_slot(struct o2hb_region *reg, &o2hb_live_slots[slot->ds_node_num]); slot->ds_equal_samples = 0; - - /* We want to be sure that all nodes agree on the - * number of milliseconds before a node will be - * considered dead. The self-fencing timeout is - * computed from this value, and a discrepancy might - * result in heartbeat calling a node dead when it - * hasn't self-fenced yet. */ - slot_dead_ms = le32_to_cpu(hb_block->hb_dead_ms); - if (slot_dead_ms && slot_dead_ms != dead_ms) { - /* TODO: Perhaps we can fail the region here. */ - mlog(ML_ERROR, "Node %d on device %s has a dead count " - "of %u ms, but our count is %u ms.\n" - "Please double check your configuration values " - "for 'O2CB_HEARTBEAT_THRESHOLD'\n", - slot->ds_node_num, reg->hr_dev_name, slot_dead_ms, - dead_ms); - } goto out; } diff --git a/trunk/fs/ocfs2/cluster/masklog.h b/trunk/fs/ocfs2/cluster/masklog.h index a42628ba9ddf..73edad782537 100644 --- a/trunk/fs/ocfs2/cluster/masklog.h +++ b/trunk/fs/ocfs2/cluster/masklog.h @@ -123,17 +123,6 @@ #define MLOG_MASK_PREFIX 0 #endif -/* - * When logging is disabled, force the bit test to 0 for anything other - * than errors and notices, allowing gcc to remove the code completely. - * When enabled, allow all masks. - */ -#if defined(CONFIG_OCFS2_DEBUG_MASKLOG) -#define ML_ALLOWED_BITS ~0 -#else -#define ML_ALLOWED_BITS (ML_ERROR|ML_NOTICE) -#endif - #define MLOG_MAX_BITS 64 struct mlog_bits { @@ -198,8 +187,7 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; #define mlog(mask, fmt, args...) do { \ u64 __m = MLOG_MASK_PREFIX | (mask); \ - if ((__m & ML_ALLOWED_BITS) && \ - __mlog_test_u64(__m, mlog_and_bits) && \ + if (__mlog_test_u64(__m, mlog_and_bits) && \ !__mlog_test_u64(__m, mlog_not_bits)) { \ if (__m & ML_ERROR) \ __mlog_printk(KERN_ERR, "ERROR: "fmt , ##args); \ @@ -216,7 +204,6 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; mlog(ML_ERROR, "status = %lld\n", (long long)_st); \ } while (0) -#if defined(CONFIG_OCFS2_DEBUG_MASKLOG) #define mlog_entry(fmt, args...) do { \ mlog(ML_ENTRY, "ENTRY:" fmt , ##args); \ } while (0) @@ -260,13 +247,6 @@ extern struct mlog_bits mlog_and_bits, mlog_not_bits; #define mlog_exit_void() do { \ mlog(ML_EXIT, "EXIT\n"); \ } while (0) -#else -#define mlog_entry(...) do { } while (0) -#define mlog_entry_void(...) do { } while (0) -#define mlog_exit(...) do { } while (0) -#define mlog_exit_ptr(...) do { } while (0) -#define mlog_exit_void(...) do { } while (0) -#endif /* defined(CONFIG_OCFS2_DEBUG_MASKLOG) */ #define mlog_bug_on_msg(cond, fmt, args...) do { \ if (cond) { \ diff --git a/trunk/fs/ocfs2/cluster/ocfs2_heartbeat.h b/trunk/fs/ocfs2/cluster/ocfs2_heartbeat.h index 3f4151da9709..94096069cb43 100644 --- a/trunk/fs/ocfs2/cluster/ocfs2_heartbeat.h +++ b/trunk/fs/ocfs2/cluster/ocfs2_heartbeat.h @@ -32,7 +32,6 @@ struct o2hb_disk_heartbeat_block { __u8 hb_pad1[3]; __le32 hb_cksum; __le64 hb_generation; - __le32 hb_dead_ms; }; #endif /* _OCFS2_HEARTBEAT_H */ diff --git a/trunk/fs/ocfs2/cluster/tcp.c b/trunk/fs/ocfs2/cluster/tcp.c index b650efa8c8be..0f60cc0d3985 100644 --- a/trunk/fs/ocfs2/cluster/tcp.c +++ b/trunk/fs/ocfs2/cluster/tcp.c @@ -108,7 +108,7 @@ ##args); \ } while (0) -static DEFINE_RWLOCK(o2net_handler_lock); +static rwlock_t o2net_handler_lock = RW_LOCK_UNLOCKED; static struct rb_root o2net_handler_tree = RB_ROOT; static struct o2net_node o2net_nodes[O2NM_MAX_NODES]; @@ -396,8 +396,8 @@ static void o2net_set_nn_state(struct o2net_node *nn, } if (was_valid && !valid) { - printk(KERN_INFO "o2net: no longer connected to " - SC_NODEF_FMT "\n", SC_NODEF_ARGS(old_sc)); + mlog(ML_NOTICE, "no longer connected to " SC_NODEF_FMT "\n", + SC_NODEF_ARGS(old_sc)); o2net_complete_nodes_nsw(nn); } @@ -409,10 +409,10 @@ static void o2net_set_nn_state(struct o2net_node *nn, * the only way to start connecting again is to down * heartbeat and bring it back up. */ cancel_delayed_work(&nn->nn_connect_expired); - printk(KERN_INFO "o2net: %s " SC_NODEF_FMT "\n", - o2nm_this_node() > sc->sc_node->nd_num ? - "connected to" : "accepted connection from", - SC_NODEF_ARGS(sc)); + mlog(ML_NOTICE, "%s " SC_NODEF_FMT "\n", + o2nm_this_node() > sc->sc_node->nd_num ? + "connected to" : "accepted connection from", + SC_NODEF_ARGS(sc)); } /* trigger the connecting worker func as long as we're not valid, @@ -1280,7 +1280,7 @@ static void o2net_idle_timer(unsigned long data) do_gettimeofday(&now); - printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT " has been idle for 10 " + mlog(ML_NOTICE, "connection to " SC_NODEF_FMT " has been idle for 10 " "seconds, shutting it down.\n", SC_NODEF_ARGS(sc)); mlog(ML_NOTICE, "here are some times that might help debug the " "situation: (tmr %ld.%ld now %ld.%ld dr %ld.%ld adv " diff --git a/trunk/fs/ocfs2/dir.c b/trunk/fs/ocfs2/dir.c index 3d494d1a5f36..ae47f450792f 100644 --- a/trunk/fs/ocfs2/dir.c +++ b/trunk/fs/ocfs2/dir.c @@ -213,9 +213,11 @@ int ocfs2_find_files_on_disk(const char *name, struct ocfs2_dir_entry **dirent) { int status = -ENOENT; + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - mlog_entry("(name=%.*s, blkno=%p, inode=%p, dirent_bh=%p, dirent=%p)\n", - namelen, name, blkno, inode, dirent_bh, dirent); + mlog_entry("(osb=%p, parent=%llu, name='%.*s', blkno=%p, inode=%p)\n", + osb, (unsigned long long)OCFS2_I(inode)->ip_blkno, + namelen, name, blkno, inode); *dirent_bh = ocfs2_find_entry(name, namelen, inode, dirent); if (!*dirent_bh || !*dirent) { diff --git a/trunk/fs/ocfs2/dlm/dlmast.c b/trunk/fs/ocfs2/dlm/dlmast.c index 42775e2bbe2c..355593dd8ef8 100644 --- a/trunk/fs/ocfs2/dlm/dlmast.c +++ b/trunk/fs/ocfs2/dlm/dlmast.c @@ -197,14 +197,12 @@ static void dlm_update_lvb(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, lock->ml.node == dlm->node_num ? "master" : "remote"); memcpy(lksb->lvb, res->lvb, DLM_LVB_LEN); + } else if (lksb->flags & DLM_LKSB_PUT_LVB) { + mlog(0, "setting lvb from lockres for %s node\n", + lock->ml.node == dlm->node_num ? "master" : + "remote"); + memcpy(res->lvb, lksb->lvb, DLM_LVB_LEN); } - /* Do nothing for lvb put requests - they should be done in - * place when the lock is downconverted - otherwise we risk - * racing gets and puts which could result in old lvb data - * being propagated. We leave the put flag set and clear it - * here. In the future we might want to clear it at the time - * the put is actually done. - */ spin_unlock(&res->spinlock); } @@ -383,7 +381,8 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data) ret = DLM_NORMAL; if (past->type == DLM_AST) { /* do not alter lock refcount. switching lists. */ - list_move_tail(&lock->list, &res->granted); + list_del_init(&lock->list); + list_add_tail(&lock->list, &res->granted); mlog(0, "ast: adding to granted list... type=%d, " "convert_type=%d\n", lock->ml.type, lock->ml.convert_type); if (lock->ml.convert_type != LKM_IVMODE) { diff --git a/trunk/fs/ocfs2/dlm/dlmcommon.h b/trunk/fs/ocfs2/dlm/dlmcommon.h index 14530ee7e11d..88cc43df18f1 100644 --- a/trunk/fs/ocfs2/dlm/dlmcommon.h +++ b/trunk/fs/ocfs2/dlm/dlmcommon.h @@ -37,17 +37,7 @@ #define DLM_THREAD_SHUFFLE_INTERVAL 5 // flush everything every 5 passes #define DLM_THREAD_MS 200 // flush at least every 200 ms -#define DLM_HASH_SIZE_DEFAULT (1 << 14) -#if DLM_HASH_SIZE_DEFAULT < PAGE_SIZE -# define DLM_HASH_PAGES 1 -#else -# define DLM_HASH_PAGES (DLM_HASH_SIZE_DEFAULT / PAGE_SIZE) -#endif -#define DLM_BUCKETS_PER_PAGE (PAGE_SIZE / sizeof(struct hlist_head)) -#define DLM_HASH_BUCKETS (DLM_HASH_PAGES * DLM_BUCKETS_PER_PAGE) - -/* Intended to make it easier for us to switch out hash functions */ -#define dlm_lockid_hash(_n, _l) full_name_hash(_n, _l) +#define DLM_HASH_BUCKETS (PAGE_SIZE / sizeof(struct hlist_head)) enum dlm_ast_type { DLM_AST = 0, @@ -71,8 +61,7 @@ static inline int dlm_is_recovery_lock(const char *lock_name, int name_len) return 0; } -#define DLM_RECO_STATE_ACTIVE 0x0001 -#define DLM_RECO_STATE_FINALIZE 0x0002 +#define DLM_RECO_STATE_ACTIVE 0x0001 struct dlm_recovery_ctxt { @@ -96,7 +85,7 @@ enum dlm_ctxt_state { struct dlm_ctxt { struct list_head list; - struct hlist_head **lockres_hash; + struct hlist_head *lockres_hash; struct list_head dirty_list; struct list_head purge_list; struct list_head pending_asts; @@ -131,7 +120,6 @@ struct dlm_ctxt struct o2hb_callback_func dlm_hb_down; struct task_struct *dlm_thread_task; struct task_struct *dlm_reco_thread_task; - struct workqueue_struct *dlm_worker; wait_queue_head_t dlm_thread_wq; wait_queue_head_t dlm_reco_thread_wq; wait_queue_head_t ast_wq; @@ -144,11 +132,6 @@ struct dlm_ctxt struct list_head dlm_eviction_callbacks; }; -static inline struct hlist_head *dlm_lockres_hash(struct dlm_ctxt *dlm, unsigned i) -{ - return dlm->lockres_hash[(i / DLM_BUCKETS_PER_PAGE) % DLM_HASH_PAGES] + (i % DLM_BUCKETS_PER_PAGE); -} - /* these keventd work queue items are for less-frequently * called functions that cannot be directly called from the * net message handlers for some reason, usually because @@ -233,29 +216,20 @@ struct dlm_lock_resource /* WARNING: Please see the comment in dlm_init_lockres before * adding fields here. */ struct hlist_node hash_node; - struct qstr lockname; struct kref refs; - /* - * Please keep granted, converting, and blocked in this order, - * as some funcs want to iterate over all lists. - * - * All four lists are protected by the hash's reference. - */ + /* please keep these next 3 in this order + * some funcs want to iterate over all lists */ struct list_head granted; struct list_head converting; struct list_head blocked; - struct list_head purge; - /* - * These two lists require you to hold an additional reference - * while they are on the list. - */ struct list_head dirty; struct list_head recovering; // dlm_recovery_ctxt.resources list /* unused lock resources have their last_used stamped and are * put on a list for the dlm thread to run. */ + struct list_head purge; unsigned long last_used; unsigned migration_pending:1; @@ -264,6 +238,7 @@ struct dlm_lock_resource wait_queue_head_t wq; u8 owner; //node which owns the lock resource, or unknown u16 state; + struct qstr lockname; char lvb[DLM_LVB_LEN]; }; @@ -325,15 +300,6 @@ enum dlm_lockres_list { DLM_BLOCKED_LIST }; -static inline int dlm_lvb_is_empty(char *lvb) -{ - int i; - for (i=0; irefs); -} +void dlm_lockres_get(struct dlm_lock_resource *res); void dlm_lockres_put(struct dlm_lock_resource *res); void __dlm_unhash_lockres(struct dlm_lock_resource *res); void __dlm_insert_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res); struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm, const char *name, - unsigned int len, - unsigned int hash); + unsigned int len); struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm, const char *name, unsigned int len); @@ -822,6 +780,8 @@ int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data); int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data); int dlm_do_master_requery(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, u8 nodenum, u8 *real_master); +int dlm_lockres_master_requery(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res, u8 *real_master); int dlm_dispatch_assert_master(struct dlm_ctxt *dlm, @@ -859,7 +819,6 @@ void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node); int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock); -int __dlm_lockres_unused(struct dlm_lock_resource *res); static inline const char * dlm_lock_mode_name(int mode) { diff --git a/trunk/fs/ocfs2/dlm/dlmconvert.c b/trunk/fs/ocfs2/dlm/dlmconvert.c index c764dc8e40a2..8285228d9e37 100644 --- a/trunk/fs/ocfs2/dlm/dlmconvert.c +++ b/trunk/fs/ocfs2/dlm/dlmconvert.c @@ -214,9 +214,6 @@ static enum dlm_status __dlmconvert_master(struct dlm_ctxt *dlm, if (lock->ml.node == dlm->node_num) mlog(0, "doing in-place convert for nonlocal lock\n"); lock->ml.type = type; - if (lock->lksb->flags & DLM_LKSB_PUT_LVB) - memcpy(res->lvb, lock->lksb->lvb, DLM_LVB_LEN); - status = DLM_NORMAL; *call_ast = 1; goto unlock_exit; @@ -234,7 +231,8 @@ static enum dlm_status __dlmconvert_master(struct dlm_ctxt *dlm, lock->ml.convert_type = type; /* do not alter lock refcount. switching lists. */ - list_move_tail(&lock->list, &res->converting); + list_del_init(&lock->list); + list_add_tail(&lock->list, &res->converting); unlock_exit: spin_unlock(&lock->spinlock); @@ -250,7 +248,8 @@ void dlm_revert_pending_convert(struct dlm_lock_resource *res, struct dlm_lock *lock) { /* do not alter lock refcount. switching lists. */ - list_move_tail(&lock->list, &res->granted); + list_del_init(&lock->list); + list_add_tail(&lock->list, &res->granted); lock->ml.convert_type = LKM_IVMODE; lock->lksb->flags &= ~(DLM_LKSB_GET_LVB|DLM_LKSB_PUT_LVB); } @@ -295,7 +294,8 @@ enum dlm_status dlmconvert_remote(struct dlm_ctxt *dlm, res->state |= DLM_LOCK_RES_IN_PROGRESS; /* move lock to local convert queue */ /* do not alter lock refcount. switching lists. */ - list_move_tail(&lock->list, &res->converting); + list_del_init(&lock->list); + list_add_tail(&lock->list, &res->converting); lock->convert_pending = 1; lock->ml.convert_type = type; @@ -464,12 +464,6 @@ int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data) } spin_lock(&res->spinlock); - status = __dlm_lockres_state_to_status(res); - if (status != DLM_NORMAL) { - spin_unlock(&res->spinlock); - dlm_error(status); - goto leave; - } list_for_each(iter, &res->granted) { lock = list_entry(iter, struct dlm_lock, list); if (lock->ml.cookie == cnv->cookie && @@ -479,21 +473,6 @@ int dlm_convert_lock_handler(struct o2net_msg *msg, u32 len, void *data) } lock = NULL; } - if (!lock) { - __dlm_print_one_lock_resource(res); - list_for_each(iter, &res->granted) { - lock = list_entry(iter, struct dlm_lock, list); - if (lock->ml.node == cnv->node_idx) { - mlog(ML_ERROR, "There is something here " - "for node %u, lock->ml.cookie=%llu, " - "cnv->cookie=%llu\n", cnv->node_idx, - (unsigned long long)lock->ml.cookie, - (unsigned long long)cnv->cookie); - break; - } - } - lock = NULL; - } spin_unlock(&res->spinlock); if (!lock) { status = DLM_IVLOCKID; diff --git a/trunk/fs/ocfs2/dlm/dlmdebug.c b/trunk/fs/ocfs2/dlm/dlmdebug.c index 3f6c8d88f7af..c7eae5d3324e 100644 --- a/trunk/fs/ocfs2/dlm/dlmdebug.c +++ b/trunk/fs/ocfs2/dlm/dlmdebug.c @@ -37,8 +37,10 @@ #include "dlmapi.h" #include "dlmcommon.h" +#include "dlmdebug.h" #include "dlmdomain.h" +#include "dlmdebug.h" #define MLOG_MASK_PREFIX ML_DLM #include "cluster/masklog.h" @@ -118,7 +120,6 @@ void dlm_print_one_lock(struct dlm_lock *lockid) } EXPORT_SYMBOL_GPL(dlm_print_one_lock); -#if 0 void dlm_dump_lock_resources(struct dlm_ctxt *dlm) { struct dlm_lock_resource *res; @@ -135,13 +136,12 @@ void dlm_dump_lock_resources(struct dlm_ctxt *dlm) spin_lock(&dlm->spinlock); for (i=0; ilockres_hash[i]); hlist_for_each_entry(res, iter, bucket, hash_node) dlm_print_one_lock_resource(res); } spin_unlock(&dlm->spinlock); } -#endif /* 0 */ static const char *dlm_errnames[] = { [DLM_NORMAL] = "DLM_NORMAL", diff --git a/trunk/fs/ocfs2/dlm/dlmdebug.h b/trunk/fs/ocfs2/dlm/dlmdebug.h new file mode 100644 index 000000000000..6858510c3ccd --- /dev/null +++ b/trunk/fs/ocfs2/dlm/dlmdebug.h @@ -0,0 +1,30 @@ +/* -*- mode: c; c-basic-offset: 8; -*- + * vim: noexpandtab sw=8 ts=8 sts=0: + * + * dlmdebug.h + * + * Copyright (C) 2004 Oracle. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + * + */ + +#ifndef DLMDEBUG_H +#define DLMDEBUG_H + +void dlm_dump_lock_resources(struct dlm_ctxt *dlm); + +#endif diff --git a/trunk/fs/ocfs2/dlm/dlmdomain.c b/trunk/fs/ocfs2/dlm/dlmdomain.c index 8d1065f8b3bd..8f3a9e3106fd 100644 --- a/trunk/fs/ocfs2/dlm/dlmdomain.c +++ b/trunk/fs/ocfs2/dlm/dlmdomain.c @@ -41,6 +41,7 @@ #include "dlmapi.h" #include "dlmcommon.h" +#include "dlmdebug.h" #include "dlmdomain.h" #include "dlmver.h" @@ -48,33 +49,6 @@ #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_DOMAIN) #include "cluster/masklog.h" -static void dlm_free_pagevec(void **vec, int pages) -{ - while (pages--) - free_page((unsigned long)vec[pages]); - kfree(vec); -} - -static void **dlm_alloc_pagevec(int pages) -{ - void **vec = kmalloc(pages * sizeof(void *), GFP_KERNEL); - int i; - - if (!vec) - return NULL; - - for (i = 0; i < pages; i++) - if (!(vec[i] = (void *)__get_free_page(GFP_KERNEL))) - goto out_free; - - mlog(0, "Allocated DLM hash pagevec; %d pages (%lu expected), %lu buckets per page\n", - pages, DLM_HASH_PAGES, (unsigned long)DLM_BUCKETS_PER_PAGE); - return vec; -out_free: - dlm_free_pagevec(vec, i); - return NULL; -} - /* * * spinlock lock ordering: if multiple locks are needed, obey this ordering: @@ -88,7 +62,7 @@ static void **dlm_alloc_pagevec(int pages) * */ -DEFINE_SPINLOCK(dlm_domain_lock); +spinlock_t dlm_domain_lock = SPIN_LOCK_UNLOCKED; LIST_HEAD(dlm_domains); static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events); @@ -116,7 +90,8 @@ void __dlm_insert_lockres(struct dlm_ctxt *dlm, assert_spin_locked(&dlm->spinlock); q = &res->lockname; - bucket = dlm_lockres_hash(dlm, q->hash); + q->hash = full_name_hash(q->name, q->len); + bucket = &(dlm->lockres_hash[q->hash % DLM_HASH_BUCKETS]); /* get a reference for our hashtable */ dlm_lockres_get(res); @@ -125,32 +100,34 @@ void __dlm_insert_lockres(struct dlm_ctxt *dlm, } struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm, - const char *name, - unsigned int len, - unsigned int hash) + const char *name, + unsigned int len) { + unsigned int hash; + struct hlist_node *iter; + struct dlm_lock_resource *tmpres=NULL; struct hlist_head *bucket; - struct hlist_node *list; mlog_entry("%.*s\n", len, name); assert_spin_locked(&dlm->spinlock); - bucket = dlm_lockres_hash(dlm, hash); + hash = full_name_hash(name, len); - hlist_for_each(list, bucket) { - struct dlm_lock_resource *res = hlist_entry(list, - struct dlm_lock_resource, hash_node); - if (res->lockname.name[0] != name[0]) - continue; - if (unlikely(res->lockname.len != len)) - continue; - if (memcmp(res->lockname.name + 1, name + 1, len - 1)) - continue; - dlm_lockres_get(res); - return res; + bucket = &(dlm->lockres_hash[hash % DLM_HASH_BUCKETS]); + + /* check for pre-existing lock */ + hlist_for_each(iter, bucket) { + tmpres = hlist_entry(iter, struct dlm_lock_resource, hash_node); + if (tmpres->lockname.len == len && + memcmp(tmpres->lockname.name, name, len) == 0) { + dlm_lockres_get(tmpres); + break; + } + + tmpres = NULL; } - return NULL; + return tmpres; } struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm, @@ -158,10 +135,9 @@ struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm, unsigned int len) { struct dlm_lock_resource *res; - unsigned int hash = dlm_lockid_hash(name, len); spin_lock(&dlm->spinlock); - res = __dlm_lookup_lockres(dlm, name, len, hash); + res = __dlm_lookup_lockres(dlm, name, len); spin_unlock(&dlm->spinlock); return res; } @@ -218,7 +194,7 @@ static int dlm_wait_on_domain_helper(const char *domain) static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm) { if (dlm->lockres_hash) - dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES); + free_page((unsigned long) dlm->lockres_hash); if (dlm->name) kfree(dlm->name); @@ -302,21 +278,11 @@ int dlm_domain_fully_joined(struct dlm_ctxt *dlm) return ret; } -static void dlm_destroy_dlm_worker(struct dlm_ctxt *dlm) -{ - if (dlm->dlm_worker) { - flush_workqueue(dlm->dlm_worker); - destroy_workqueue(dlm->dlm_worker); - dlm->dlm_worker = NULL; - } -} - static void dlm_complete_dlm_shutdown(struct dlm_ctxt *dlm) { dlm_unregister_domain_handlers(dlm); dlm_complete_thread(dlm); dlm_complete_recovery_thread(dlm); - dlm_destroy_dlm_worker(dlm); /* We've left the domain. Now we can take ourselves out of the * list and allow the kref stuff to help us free the @@ -338,8 +304,8 @@ static void dlm_migrate_all_locks(struct dlm_ctxt *dlm) restart: spin_lock(&dlm->spinlock); for (i = 0; i < DLM_HASH_BUCKETS; i++) { - while (!hlist_empty(dlm_lockres_hash(dlm, i))) { - res = hlist_entry(dlm_lockres_hash(dlm, i)->first, + while (!hlist_empty(&dlm->lockres_hash[i])) { + res = hlist_entry(dlm->lockres_hash[i].first, struct dlm_lock_resource, hash_node); /* need reference when manually grabbing lockres */ dlm_lockres_get(res); @@ -408,13 +374,12 @@ static void __dlm_print_nodes(struct dlm_ctxt *dlm) assert_spin_locked(&dlm->spinlock); - printk(KERN_INFO "ocfs2_dlm: Nodes in domain (\"%s\"): ", dlm->name); + mlog(ML_NOTICE, "Nodes in my domain (\"%s\"):\n", dlm->name); while ((node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES, node + 1)) < O2NM_MAX_NODES) { - printk("%d ", node); + mlog(ML_NOTICE, " node %d\n", node); } - printk("\n"); } static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data) @@ -430,7 +395,7 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data) node = exit_msg->node_idx; - printk(KERN_INFO "ocfs2_dlm: Node %u leaves domain %s\n", node, dlm->name); + mlog(0, "Node %u leaves domain %s\n", node, dlm->name); spin_lock(&dlm->spinlock); clear_bit(node, dlm->domain_map); @@ -679,8 +644,6 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data) set_bit(assert->node_idx, dlm->domain_map); __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN); - printk(KERN_INFO "ocfs2_dlm: Node %u joins domain %s\n", - assert->node_idx, dlm->name); __dlm_print_nodes(dlm); /* notify anything attached to the heartbeat events */ @@ -1163,13 +1126,6 @@ static int dlm_join_domain(struct dlm_ctxt *dlm) goto bail; } - dlm->dlm_worker = create_singlethread_workqueue("dlm_wq"); - if (!dlm->dlm_worker) { - status = -ENOMEM; - mlog_errno(status); - goto bail; - } - do { unsigned int backoff; status = dlm_try_to_join_domain(dlm); @@ -1210,7 +1166,6 @@ static int dlm_join_domain(struct dlm_ctxt *dlm) dlm_unregister_domain_handlers(dlm); dlm_complete_thread(dlm); dlm_complete_recovery_thread(dlm); - dlm_destroy_dlm_worker(dlm); } return status; @@ -1236,7 +1191,7 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, goto leave; } - dlm->lockres_hash = (struct hlist_head **)dlm_alloc_pagevec(DLM_HASH_PAGES); + dlm->lockres_hash = (struct hlist_head *) __get_free_page(GFP_KERNEL); if (!dlm->lockres_hash) { mlog_errno(-ENOMEM); kfree(dlm->name); @@ -1245,8 +1200,8 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, goto leave; } - for (i = 0; i < DLM_HASH_BUCKETS; i++) - INIT_HLIST_HEAD(dlm_lockres_hash(dlm, i)); + for (i=0; ilockres_hash[i]); strcpy(dlm->name, domain); dlm->key = key; @@ -1276,7 +1231,6 @@ static struct dlm_ctxt *dlm_alloc_ctxt(const char *domain, dlm->dlm_thread_task = NULL; dlm->dlm_reco_thread_task = NULL; - dlm->dlm_worker = NULL; init_waitqueue_head(&dlm->dlm_thread_wq); init_waitqueue_head(&dlm->dlm_reco_thread_wq); init_waitqueue_head(&dlm->reco.event); diff --git a/trunk/fs/ocfs2/dlm/dlmfs.c b/trunk/fs/ocfs2/dlm/dlmfs.c index 033ad1701232..7273d9fa6bab 100644 --- a/trunk/fs/ocfs2/dlm/dlmfs.c +++ b/trunk/fs/ocfs2/dlm/dlmfs.c @@ -116,7 +116,7 @@ static int dlmfs_file_open(struct inode *inode, * doesn't make sense for LVB writes. */ file->f_flags &= ~O_APPEND; - fp = kmalloc(sizeof(*fp), GFP_NOFS); + fp = kmalloc(sizeof(*fp), GFP_KERNEL); if (!fp) { status = -ENOMEM; goto bail; @@ -196,7 +196,7 @@ static ssize_t dlmfs_file_read(struct file *filp, else readlen = count - *ppos; - lvb_buf = kmalloc(readlen, GFP_NOFS); + lvb_buf = kmalloc(readlen, GFP_KERNEL); if (!lvb_buf) return -ENOMEM; @@ -240,7 +240,7 @@ static ssize_t dlmfs_file_write(struct file *filp, else writelen = count - *ppos; - lvb_buf = kmalloc(writelen, GFP_NOFS); + lvb_buf = kmalloc(writelen, GFP_KERNEL); if (!lvb_buf) return -ENOMEM; diff --git a/trunk/fs/ocfs2/dlm/dlmlock.c b/trunk/fs/ocfs2/dlm/dlmlock.c index 5ca57ec650c7..6fea28318d6d 100644 --- a/trunk/fs/ocfs2/dlm/dlmlock.c +++ b/trunk/fs/ocfs2/dlm/dlmlock.c @@ -53,7 +53,7 @@ #define MLOG_MASK_PREFIX ML_DLM #include "cluster/masklog.h" -static DEFINE_SPINLOCK(dlm_cookie_lock); +static spinlock_t dlm_cookie_lock = SPIN_LOCK_UNLOCKED; static u64 dlm_next_cookie = 1; static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm, @@ -201,7 +201,6 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm, struct dlm_lock *lock, int flags) { enum dlm_status status = DLM_DENIED; - int lockres_changed = 1; mlog_entry("type=%d\n", lock->ml.type); mlog(0, "lockres %.*s, flags = 0x%x\n", res->lockname.len, @@ -227,25 +226,8 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm, res->state &= ~DLM_LOCK_RES_IN_PROGRESS; lock->lock_pending = 0; if (status != DLM_NORMAL) { - if (status == DLM_RECOVERING && - dlm_is_recovery_lock(res->lockname.name, - res->lockname.len)) { - /* recovery lock was mastered by dead node. - * we need to have calc_usage shoot down this - * lockres and completely remaster it. */ - mlog(0, "%s: recovery lock was owned by " - "dead node %u, remaster it now.\n", - dlm->name, res->owner); - } else if (status != DLM_NOTQUEUED) { - /* - * DO NOT call calc_usage, as this would unhash - * the remote lockres before we ever get to use - * it. treat as if we never made any change to - * the lockres. - */ - lockres_changed = 0; + if (status != DLM_NOTQUEUED) dlm_error(status); - } dlm_revert_pending_lock(res, lock); dlm_lock_put(lock); } else if (dlm_is_recovery_lock(res->lockname.name, @@ -257,12 +239,12 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm, mlog(0, "%s: $RECOVERY lock for this node (%u) is " "mastered by %u; got lock, manually granting (no ast)\n", dlm->name, dlm->node_num, res->owner); - list_move_tail(&lock->list, &res->granted); + list_del_init(&lock->list); + list_add_tail(&lock->list, &res->granted); } spin_unlock(&res->spinlock); - if (lockres_changed) - dlm_lockres_calc_usage(dlm, res); + dlm_lockres_calc_usage(dlm, res); wake_up(&res->wq); return status; @@ -299,14 +281,6 @@ static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm, if (tmpret >= 0) { // successfully sent and received ret = status; // this is already a dlm_status - if (ret == DLM_REJECTED) { - mlog(ML_ERROR, "%s:%.*s: BUG. this is a stale lockres " - "no longer owned by %u. that node is coming back " - "up currently.\n", dlm->name, create.namelen, - create.name, res->owner); - dlm_print_one_lock_resource(res); - BUG(); - } } else { mlog_errno(tmpret); if (dlm_is_host_down(tmpret)) { @@ -408,13 +382,13 @@ struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie, struct dlm_lock *lock; int kernel_allocated = 0; - lock = kcalloc(1, sizeof(*lock), GFP_NOFS); + lock = kcalloc(1, sizeof(*lock), GFP_KERNEL); if (!lock) return NULL; if (!lksb) { /* zero memory only if kernel-allocated */ - lksb = kcalloc(1, sizeof(*lksb), GFP_NOFS); + lksb = kcalloc(1, sizeof(*lksb), GFP_KERNEL); if (!lksb) { kfree(lock); return NULL; @@ -455,16 +429,11 @@ int dlm_create_lock_handler(struct o2net_msg *msg, u32 len, void *data) if (!dlm_grab(dlm)) return DLM_REJECTED; + mlog_bug_on_msg(!dlm_domain_fully_joined(dlm), + "Domain %s not fully joined!\n", dlm->name); + name = create->name; namelen = create->namelen; - status = DLM_REJECTED; - if (!dlm_domain_fully_joined(dlm)) { - mlog(ML_ERROR, "Domain %s not fully joined, but node %u is " - "sending a create_lock message for lock %.*s!\n", - dlm->name, create->node_idx, namelen, name); - dlm_error(status); - goto leave; - } status = DLM_IVBUFLEN; if (namelen > DLM_LOCKID_NAME_MAX) { @@ -700,22 +669,18 @@ enum dlm_status dlmlock(struct dlm_ctxt *dlm, int mode, msleep(100); /* no waiting for dlm_reco_thread */ if (recovery) { - if (status != DLM_RECOVERING) - goto retry_lock; - - mlog(0, "%s: got RECOVERING " - "for $RECOVERY lock, master " - "was %u\n", dlm->name, - res->owner); - /* wait to see the node go down, then - * drop down and allow the lockres to - * get cleaned up. need to remaster. */ - dlm_wait_for_node_death(dlm, res->owner, - DLM_NODE_DEATH_WAIT_MAX); + if (status == DLM_RECOVERING) { + mlog(0, "%s: got RECOVERING " + "for $REOCVERY lock, master " + "was %u\n", dlm->name, + res->owner); + dlm_wait_for_node_death(dlm, res->owner, + DLM_NODE_DEATH_WAIT_MAX); + } } else { dlm_wait_for_recovery(dlm); - goto retry_lock; } + goto retry_lock; } if (status != DLM_NORMAL) { diff --git a/trunk/fs/ocfs2/dlm/dlmmaster.c b/trunk/fs/ocfs2/dlm/dlmmaster.c index 1b8346dd0572..940be4c13b1f 100644 --- a/trunk/fs/ocfs2/dlm/dlmmaster.c +++ b/trunk/fs/ocfs2/dlm/dlmmaster.c @@ -47,6 +47,7 @@ #include "dlmapi.h" #include "dlmcommon.h" +#include "dlmdebug.h" #include "dlmdomain.h" #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_MASTER) @@ -73,7 +74,6 @@ struct dlm_master_list_entry wait_queue_head_t wq; atomic_t woken; struct kref mle_refs; - int inuse; unsigned long maybe_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; unsigned long vote_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; unsigned long response_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; @@ -127,30 +127,18 @@ static inline int dlm_mle_equal(struct dlm_ctxt *dlm, return 1; } -#define dlm_print_nodemap(m) _dlm_print_nodemap(m,#m) -static void _dlm_print_nodemap(unsigned long *map, const char *mapname) -{ - int i; - printk("%s=[ ", mapname); - for (i=0; imaybe_map, - *vote = mle->vote_map, - *resp = mle->response_map, - *node = mle->node_map; k = &mle->mle_refs; if (mle->type == DLM_MLE_BLOCK) @@ -171,29 +159,18 @@ static void dlm_print_one_mle(struct dlm_master_list_entry *mle) name = mle->u.res->lockname.name; } - mlog(ML_NOTICE, "%.*s: %3s refs=%3d mas=%3u new=%3u evt=%c inuse=%d ", - namelen, name, type, refs, master, mle->new_master, attached, - mle->inuse); - dlm_print_nodemap(maybe); - printk(", "); - dlm_print_nodemap(vote); - printk(", "); - dlm_print_nodemap(resp); - printk(", "); - dlm_print_nodemap(node); - printk(", "); - printk("\n"); + mlog(ML_NOTICE, " #%3d: %3s %3d %3u %3u %c (%d)%.*s\n", + i, type, refs, master, mle->new_master, attached, + namelen, namelen, name); } -#if 0 -/* Code here is included but defined out as it aids debugging */ - static void dlm_dump_mles(struct dlm_ctxt *dlm) { struct dlm_master_list_entry *mle; struct list_head *iter; mlog(ML_NOTICE, "dumping all mles for domain %s:\n", dlm->name); + mlog(ML_NOTICE, " ####: type refs owner new events? lockname nodemap votemap respmap maybemap\n"); spin_lock(&dlm->master_lock); list_for_each(iter, &dlm->master_list) { mle = list_entry(iter, struct dlm_master_list_entry, list); @@ -337,31 +314,6 @@ static inline void dlm_mle_detach_hb_events(struct dlm_ctxt *dlm, spin_unlock(&dlm->spinlock); } -static void dlm_get_mle_inuse(struct dlm_master_list_entry *mle) -{ - struct dlm_ctxt *dlm; - dlm = mle->dlm; - - assert_spin_locked(&dlm->spinlock); - assert_spin_locked(&dlm->master_lock); - mle->inuse++; - kref_get(&mle->mle_refs); -} - -static void dlm_put_mle_inuse(struct dlm_master_list_entry *mle) -{ - struct dlm_ctxt *dlm; - dlm = mle->dlm; - - spin_lock(&dlm->spinlock); - spin_lock(&dlm->master_lock); - mle->inuse--; - __dlm_put_mle(mle); - spin_unlock(&dlm->master_lock); - spin_unlock(&dlm->spinlock); - -} - /* remove from list and free */ static void __dlm_put_mle(struct dlm_master_list_entry *mle) { @@ -370,14 +322,9 @@ static void __dlm_put_mle(struct dlm_master_list_entry *mle) assert_spin_locked(&dlm->spinlock); assert_spin_locked(&dlm->master_lock); - if (!atomic_read(&mle->mle_refs.refcount)) { - /* this may or may not crash, but who cares. - * it's a BUG. */ - mlog(ML_ERROR, "bad mle: %p\n", mle); - dlm_print_one_mle(mle); - BUG(); - } else - kref_put(&mle->mle_refs, dlm_mle_release); + BUG_ON(!atomic_read(&mle->mle_refs.refcount)); + + kref_put(&mle->mle_refs, dlm_mle_release); } @@ -420,7 +367,6 @@ static void dlm_init_mle(struct dlm_master_list_entry *mle, memset(mle->response_map, 0, sizeof(mle->response_map)); mle->master = O2NM_MAX_NODES; mle->new_master = O2NM_MAX_NODES; - mle->inuse = 0; if (mle->type == DLM_MLE_MASTER) { BUG_ON(!res); @@ -618,28 +564,6 @@ static void dlm_lockres_release(struct kref *kref) mlog(0, "destroying lockres %.*s\n", res->lockname.len, res->lockname.name); - if (!hlist_unhashed(&res->hash_node) || - !list_empty(&res->granted) || - !list_empty(&res->converting) || - !list_empty(&res->blocked) || - !list_empty(&res->dirty) || - !list_empty(&res->recovering) || - !list_empty(&res->purge)) { - mlog(ML_ERROR, - "Going to BUG for resource %.*s." - " We're on a list! [%c%c%c%c%c%c%c]\n", - res->lockname.len, res->lockname.name, - !hlist_unhashed(&res->hash_node) ? 'H' : ' ', - !list_empty(&res->granted) ? 'G' : ' ', - !list_empty(&res->converting) ? 'C' : ' ', - !list_empty(&res->blocked) ? 'B' : ' ', - !list_empty(&res->dirty) ? 'D' : ' ', - !list_empty(&res->recovering) ? 'R' : ' ', - !list_empty(&res->purge) ? 'P' : ' '); - - dlm_print_one_lock_resource(res); - } - /* By the time we're ready to blow this guy away, we shouldn't * be on any lists. */ BUG_ON(!hlist_unhashed(&res->hash_node)); @@ -655,6 +579,11 @@ static void dlm_lockres_release(struct kref *kref) kfree(res); } +void dlm_lockres_get(struct dlm_lock_resource *res) +{ + kref_get(&res->refs); +} + void dlm_lockres_put(struct dlm_lock_resource *res) { kref_put(&res->refs, dlm_lockres_release); @@ -674,7 +603,7 @@ static void dlm_init_lockres(struct dlm_ctxt *dlm, memcpy(qname, name, namelen); res->lockname.len = namelen; - res->lockname.hash = dlm_lockid_hash(name, namelen); + res->lockname.hash = full_name_hash(name, namelen); init_waitqueue_head(&res->wq); spin_lock_init(&res->spinlock); @@ -708,11 +637,11 @@ struct dlm_lock_resource *dlm_new_lockres(struct dlm_ctxt *dlm, { struct dlm_lock_resource *res; - res = kmalloc(sizeof(struct dlm_lock_resource), GFP_NOFS); + res = kmalloc(sizeof(struct dlm_lock_resource), GFP_KERNEL); if (!res) return NULL; - res->lockname.name = kmalloc(namelen, GFP_NOFS); + res->lockname.name = kmalloc(namelen, GFP_KERNEL); if (!res->lockname.name) { kfree(res); return NULL; @@ -748,20 +677,19 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, int blocked = 0; int ret, nodenum; struct dlm_node_iter iter; - unsigned int namelen, hash; + unsigned int namelen; int tries = 0; int bit, wait_on_recovery = 0; BUG_ON(!lockid); namelen = strlen(lockid); - hash = dlm_lockid_hash(lockid, namelen); mlog(0, "get lockres %s (len %d)\n", lockid, namelen); lookup: spin_lock(&dlm->spinlock); - tmpres = __dlm_lookup_lockres(dlm, lockid, namelen, hash); + tmpres = __dlm_lookup_lockres(dlm, lockid, namelen); if (tmpres) { spin_unlock(&dlm->spinlock); mlog(0, "found in hash!\n"); @@ -776,7 +704,7 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, mlog(0, "allocating a new resource\n"); /* nothing found and we need to allocate one. */ alloc_mle = (struct dlm_master_list_entry *) - kmem_cache_alloc(dlm_mle_cache, GFP_NOFS); + kmem_cache_alloc(dlm_mle_cache, GFP_KERNEL); if (!alloc_mle) goto leave; res = dlm_new_lockres(dlm, lockid, namelen); @@ -862,11 +790,10 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, * if so, the creator of the BLOCK may try to put the last * ref at this time in the assert master handler, so we * need an extra one to keep from a bad ptr deref. */ - dlm_get_mle_inuse(mle); + dlm_get_mle(mle); spin_unlock(&dlm->master_lock); spin_unlock(&dlm->spinlock); -redo_request: while (wait_on_recovery) { /* any cluster changes that occurred after dropping the * dlm spinlock would be detectable be a change on the mle, @@ -885,7 +812,7 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, } dlm_kick_recovery_thread(dlm); - msleep(1000); + msleep(100); dlm_wait_for_recovery(dlm); spin_lock(&dlm->spinlock); @@ -898,15 +825,13 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, } else wait_on_recovery = 0; spin_unlock(&dlm->spinlock); - - if (wait_on_recovery) - dlm_wait_for_node_recovery(dlm, bit, 10000); } /* must wait for lock to be mastered elsewhere */ if (blocked) goto wait; +redo_request: ret = -EINVAL; dlm_node_iter_init(mle->vote_map, &iter); while ((nodenum = dlm_node_iter_next(&iter)) >= 0) { @@ -931,7 +856,6 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, /* keep going until the response map includes all nodes */ ret = dlm_wait_for_lock_mastery(dlm, res, mle, &blocked); if (ret < 0) { - wait_on_recovery = 1; mlog(0, "%s:%.*s: node map changed, redo the " "master request now, blocked=%d\n", dlm->name, res->lockname.len, @@ -942,7 +866,7 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, dlm->name, res->lockname.len, res->lockname.name, blocked); dlm_print_one_lock_resource(res); - dlm_print_one_mle(mle); + /* dlm_print_one_mle(mle); */ tries = 0; } goto redo_request; @@ -956,7 +880,7 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm, dlm_mle_detach_hb_events(dlm, mle); dlm_put_mle(mle); /* put the extra ref */ - dlm_put_mle_inuse(mle); + dlm_put_mle(mle); wake_waiters: spin_lock(&res->spinlock); @@ -997,14 +921,12 @@ static int dlm_wait_for_lock_mastery(struct dlm_ctxt *dlm, spin_unlock(&res->spinlock); /* this will cause the master to re-assert across * the whole cluster, freeing up mles */ - if (res->owner != dlm->node_num) { - ret = dlm_do_master_request(mle, res->owner); - if (ret < 0) { - /* give recovery a chance to run */ - mlog(ML_ERROR, "link to %u went down?: %d\n", res->owner, ret); - msleep(500); - goto recheck; - } + ret = dlm_do_master_request(mle, res->owner); + if (ret < 0) { + /* give recovery a chance to run */ + mlog(ML_ERROR, "link to %u went down?: %d\n", res->owner, ret); + msleep(500); + goto recheck; } ret = 0; goto leave; @@ -1040,12 +962,6 @@ static int dlm_wait_for_lock_mastery(struct dlm_ctxt *dlm, "rechecking now\n", dlm->name, res->lockname.len, res->lockname.name); goto recheck; - } else { - if (!voting_done) { - mlog(0, "map not changed and voting not done " - "for %s:%.*s\n", dlm->name, res->lockname.len, - res->lockname.name); - } } if (m != O2NM_MAX_NODES) { @@ -1213,6 +1129,18 @@ static int dlm_restart_lock_mastery(struct dlm_ctxt *dlm, set_bit(node, mle->vote_map); } else { mlog(ML_ERROR, "node down! %d\n", node); + + /* if the node wasn't involved in mastery skip it, + * but clear it out from the maps so that it will + * not affect mastery of this lockres */ + clear_bit(node, mle->response_map); + clear_bit(node, mle->vote_map); + if (!test_bit(node, mle->maybe_map)) + goto next; + + /* if we're already blocked on lock mastery, and the + * dead node wasn't the expected master, or there is + * another node in the maybe_map, keep waiting */ if (blocked) { int lowest = find_next_bit(mle->maybe_map, O2NM_MAX_NODES, 0); @@ -1220,53 +1148,54 @@ static int dlm_restart_lock_mastery(struct dlm_ctxt *dlm, /* act like it was never there */ clear_bit(node, mle->maybe_map); - if (node == lowest) { - mlog(0, "expected master %u died" - " while this node was blocked " - "waiting on it!\n", node); - lowest = find_next_bit(mle->maybe_map, - O2NM_MAX_NODES, - lowest+1); - if (lowest < O2NM_MAX_NODES) { - mlog(0, "%s:%.*s:still " - "blocked. waiting on %u " - "now\n", dlm->name, - res->lockname.len, - res->lockname.name, - lowest); - } else { - /* mle is an MLE_BLOCK, but - * there is now nothing left to - * block on. we need to return - * all the way back out and try - * again with an MLE_MASTER. - * dlm_do_local_recovery_cleanup - * has already run, so the mle - * refcount is ok */ - mlog(0, "%s:%.*s: no " - "longer blocking. try to " - "master this here\n", - dlm->name, - res->lockname.len, - res->lockname.name); - mle->type = DLM_MLE_MASTER; - mle->u.res = res; - } + if (node != lowest) + goto next; + + mlog(ML_ERROR, "expected master %u died while " + "this node was blocked waiting on it!\n", + node); + lowest = find_next_bit(mle->maybe_map, + O2NM_MAX_NODES, + lowest+1); + if (lowest < O2NM_MAX_NODES) { + mlog(0, "still blocked. waiting " + "on %u now\n", lowest); + goto next; } - } - /* now blank out everything, as if we had never - * contacted anyone */ - memset(mle->maybe_map, 0, sizeof(mle->maybe_map)); - memset(mle->response_map, 0, sizeof(mle->response_map)); - /* reset the vote_map to the current node_map */ - memcpy(mle->vote_map, mle->node_map, - sizeof(mle->node_map)); - /* put myself into the maybe map */ - if (mle->type != DLM_MLE_BLOCK) + /* mle is an MLE_BLOCK, but there is now + * nothing left to block on. we need to return + * all the way back out and try again with + * an MLE_MASTER. dlm_do_local_recovery_cleanup + * has already run, so the mle refcount is ok */ + mlog(0, "no longer blocking. we can " + "try to master this here\n"); + mle->type = DLM_MLE_MASTER; + memset(mle->maybe_map, 0, + sizeof(mle->maybe_map)); + memset(mle->response_map, 0, + sizeof(mle->maybe_map)); + memcpy(mle->vote_map, mle->node_map, + sizeof(mle->node_map)); + mle->u.res = res; set_bit(dlm->node_num, mle->maybe_map); + + ret = -EAGAIN; + goto next; + } + + clear_bit(node, mle->maybe_map); + if (node > dlm->node_num) + goto next; + + mlog(0, "dead node in map!\n"); + /* yuck. go back and re-contact all nodes + * in the vote_map, removing this node. */ + memset(mle->response_map, 0, + sizeof(mle->response_map)); } ret = -EAGAIN; +next: node = dlm_bitmap_diff_iter_next(&bdi, &sc); } return ret; @@ -1387,7 +1316,7 @@ int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data) struct dlm_master_request *request = (struct dlm_master_request *) msg->buf; struct dlm_master_list_entry *mle = NULL, *tmpmle = NULL; char *name; - unsigned int namelen, hash; + unsigned int namelen; int found, ret; int set_maybe; int dispatch_assert = 0; @@ -1402,7 +1331,6 @@ int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data) name = request->name; namelen = request->namelen; - hash = dlm_lockid_hash(name, namelen); if (namelen > DLM_LOCKID_NAME_MAX) { response = DLM_IVBUFLEN; @@ -1411,7 +1339,7 @@ int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data) way_up_top: spin_lock(&dlm->spinlock); - res = __dlm_lookup_lockres(dlm, name, namelen, hash); + res = __dlm_lookup_lockres(dlm, name, namelen); if (res) { spin_unlock(&dlm->spinlock); @@ -1531,18 +1459,21 @@ int dlm_master_request_handler(struct o2net_msg *msg, u32 len, void *data) spin_unlock(&dlm->spinlock); mle = (struct dlm_master_list_entry *) - kmem_cache_alloc(dlm_mle_cache, GFP_NOFS); + kmem_cache_alloc(dlm_mle_cache, GFP_KERNEL); if (!mle) { response = DLM_MASTER_RESP_ERROR; mlog_errno(-ENOMEM); goto send_response; } + spin_lock(&dlm->spinlock); + dlm_init_mle(mle, DLM_MLE_BLOCK, dlm, NULL, + name, namelen); + spin_unlock(&dlm->spinlock); goto way_up_top; } // mlog(0, "this is second time thru, already allocated, " // "add the block.\n"); - dlm_init_mle(mle, DLM_MLE_BLOCK, dlm, NULL, name, namelen); set_bit(request->node_idx, mle->maybe_map); list_add(&mle->list, &dlm->master_list); response = DLM_MASTER_RESP_NO; @@ -1625,8 +1556,6 @@ static int dlm_do_assert_master(struct dlm_ctxt *dlm, const char *lockname, dlm_node_iter_init(nodemap, &iter); while ((to = dlm_node_iter_next(&iter)) >= 0) { int r = 0; - struct dlm_master_list_entry *mle = NULL; - mlog(0, "sending assert master to %d (%.*s)\n", to, namelen, lockname); memset(&assert, 0, sizeof(assert)); @@ -1638,28 +1567,20 @@ static int dlm_do_assert_master(struct dlm_ctxt *dlm, const char *lockname, tmpret = o2net_send_message(DLM_ASSERT_MASTER_MSG, dlm->key, &assert, sizeof(assert), to, &r); if (tmpret < 0) { - mlog(0, "assert_master returned %d!\n", tmpret); + mlog(ML_ERROR, "assert_master returned %d!\n", tmpret); if (!dlm_is_host_down(tmpret)) { - mlog(ML_ERROR, "unhandled error=%d!\n", tmpret); + mlog(ML_ERROR, "unhandled error!\n"); BUG(); } /* a node died. finish out the rest of the nodes. */ - mlog(0, "link to %d went down!\n", to); + mlog(ML_ERROR, "link to %d went down!\n", to); /* any nonzero status return will do */ ret = tmpret; } else if (r < 0) { /* ok, something horribly messed. kill thyself. */ mlog(ML_ERROR,"during assert master of %.*s to %u, " "got %d.\n", namelen, lockname, to, r); - spin_lock(&dlm->spinlock); - spin_lock(&dlm->master_lock); - if (dlm_find_mle(dlm, &mle, (char *)lockname, - namelen)) { - dlm_print_one_mle(mle); - __dlm_put_mle(mle); - } - spin_unlock(&dlm->master_lock); - spin_unlock(&dlm->spinlock); + dlm_dump_lock_resources(dlm); BUG(); } else if (r == EAGAIN) { mlog(0, "%.*s: node %u create mles on other " @@ -1691,7 +1612,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data) struct dlm_assert_master *assert = (struct dlm_assert_master *)msg->buf; struct dlm_lock_resource *res = NULL; char *name; - unsigned int namelen, hash; + unsigned int namelen; u32 flags; int master_request = 0; int ret = 0; @@ -1701,7 +1622,6 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data) name = assert->name; namelen = assert->namelen; - hash = dlm_lockid_hash(name, namelen); flags = be32_to_cpu(assert->flags); if (namelen > DLM_LOCKID_NAME_MAX) { @@ -1726,7 +1646,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data) if (bit >= O2NM_MAX_NODES) { /* not necessarily an error, though less likely. * could be master just re-asserting. */ - mlog(0, "no bits set in the maybe_map, but %u " + mlog(ML_ERROR, "no bits set in the maybe_map, but %u " "is asserting! (%.*s)\n", assert->node_idx, namelen, name); } else if (bit != assert->node_idx) { @@ -1738,36 +1658,19 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data) * number winning the mastery will respond * YES to mastery requests, but this node * had no way of knowing. let it pass. */ - mlog(0, "%u is the lowest node, " + mlog(ML_ERROR, "%u is the lowest node, " "%u is asserting. (%.*s) %u must " "have begun after %u won.\n", bit, assert->node_idx, namelen, name, bit, assert->node_idx); } } - if (mle->type == DLM_MLE_MIGRATION) { - if (flags & DLM_ASSERT_MASTER_MLE_CLEANUP) { - mlog(0, "%s:%.*s: got cleanup assert" - " from %u for migration\n", - dlm->name, namelen, name, - assert->node_idx); - } else if (!(flags & DLM_ASSERT_MASTER_FINISH_MIGRATION)) { - mlog(0, "%s:%.*s: got unrelated assert" - " from %u for migration, ignoring\n", - dlm->name, namelen, name, - assert->node_idx); - __dlm_put_mle(mle); - spin_unlock(&dlm->master_lock); - spin_unlock(&dlm->spinlock); - goto done; - } - } } spin_unlock(&dlm->master_lock); /* ok everything checks out with the MLE * now check to see if there is a lockres */ - res = __dlm_lookup_lockres(dlm, name, namelen, hash); + res = __dlm_lookup_lockres(dlm, name, namelen); if (res) { spin_lock(&res->spinlock); if (res->state & DLM_LOCK_RES_RECOVERING) { @@ -1776,8 +1679,7 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data) goto kill; } if (!mle) { - if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN && - res->owner != assert->node_idx) { + if (res->owner != assert->node_idx) { mlog(ML_ERROR, "assert_master from " "%u, but current owner is " "%u! (%.*s)\n", @@ -1830,7 +1732,6 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data) if (mle) { int extra_ref = 0; int nn = -1; - int rr, err = 0; spin_lock(&mle->spinlock); if (mle->type == DLM_MLE_BLOCK || mle->type == DLM_MLE_MIGRATION) @@ -1850,64 +1751,27 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data) wake_up(&mle->wq); spin_unlock(&mle->spinlock); - if (res) { + if (mle->type == DLM_MLE_MIGRATION && res) { + mlog(0, "finishing off migration of lockres %.*s, " + "from %u to %u\n", + res->lockname.len, res->lockname.name, + dlm->node_num, mle->new_master); spin_lock(&res->spinlock); - if (mle->type == DLM_MLE_MIGRATION) { - mlog(0, "finishing off migration of lockres %.*s, " - "from %u to %u\n", - res->lockname.len, res->lockname.name, - dlm->node_num, mle->new_master); - res->state &= ~DLM_LOCK_RES_MIGRATING; - dlm_change_lockres_owner(dlm, res, mle->new_master); - BUG_ON(res->state & DLM_LOCK_RES_DIRTY); - } else { - dlm_change_lockres_owner(dlm, res, mle->master); - } + res->state &= ~DLM_LOCK_RES_MIGRATING; + dlm_change_lockres_owner(dlm, res, mle->new_master); + BUG_ON(res->state & DLM_LOCK_RES_DIRTY); spin_unlock(&res->spinlock); } - - /* master is known, detach if not already detached. - * ensures that only one assert_master call will happen - * on this mle. */ - spin_lock(&dlm->spinlock); - spin_lock(&dlm->master_lock); - - rr = atomic_read(&mle->mle_refs.refcount); - if (mle->inuse > 0) { - if (extra_ref && rr < 3) - err = 1; - else if (!extra_ref && rr < 2) - err = 1; - } else { - if (extra_ref && rr < 2) - err = 1; - else if (!extra_ref && rr < 1) - err = 1; - } - if (err) { - mlog(ML_ERROR, "%s:%.*s: got assert master from %u " - "that will mess up this node, refs=%d, extra=%d, " - "inuse=%d\n", dlm->name, namelen, name, - assert->node_idx, rr, extra_ref, mle->inuse); - dlm_print_one_mle(mle); - } - list_del_init(&mle->list); - __dlm_mle_detach_hb_events(dlm, mle); - __dlm_put_mle(mle); + /* master is known, detach if not already detached */ + dlm_mle_detach_hb_events(dlm, mle); + dlm_put_mle(mle); + if (extra_ref) { /* the assert master message now balances the extra * ref given by the master / migration request message. * if this is the last put, it will be removed * from the list. */ - __dlm_put_mle(mle); - } - spin_unlock(&dlm->master_lock); - spin_unlock(&dlm->spinlock); - } else if (res) { - if (res->owner != assert->node_idx) { - mlog(0, "assert_master from %u, but current " - "owner is %u (%.*s), no mle\n", assert->node_idx, - res->owner, namelen, name); + dlm_put_mle(mle); } } @@ -1924,12 +1788,12 @@ int dlm_assert_master_handler(struct o2net_msg *msg, u32 len, void *data) kill: /* kill the caller! */ - mlog(ML_ERROR, "Bad message received from another node. Dumping state " - "and killing the other node now! This node is OK and can continue.\n"); - __dlm_print_one_lock_resource(res); spin_unlock(&res->spinlock); spin_unlock(&dlm->spinlock); dlm_lockres_put(res); + mlog(ML_ERROR, "Bad message received from another node. Dumping state " + "and killing the other node now! This node is OK and can continue.\n"); + dlm_dump_lock_resources(dlm); dlm_put(dlm); return -EINVAL; } @@ -1939,7 +1803,7 @@ int dlm_dispatch_assert_master(struct dlm_ctxt *dlm, int ignore_higher, u8 request_from, u32 flags) { struct dlm_work_item *item; - item = kcalloc(1, sizeof(*item), GFP_NOFS); + item = kcalloc(1, sizeof(*item), GFP_KERNEL); if (!item) return -ENOMEM; @@ -1961,7 +1825,7 @@ int dlm_dispatch_assert_master(struct dlm_ctxt *dlm, list_add_tail(&item->list, &dlm->work_list); spin_unlock(&dlm->work_lock); - queue_work(dlm->dlm_worker, &dlm->dispatched_work); + schedule_work(&dlm->dispatched_work); return 0; } @@ -2002,23 +1866,6 @@ static void dlm_assert_master_worker(struct dlm_work_item *item, void *data) } } - /* - * If we're migrating this lock to someone else, we are no - * longer allowed to assert out own mastery. OTOH, we need to - * prevent migration from starting while we're still asserting - * our dominance. The reserved ast delays migration. - */ - spin_lock(&res->spinlock); - if (res->state & DLM_LOCK_RES_MIGRATING) { - mlog(0, "Someone asked us to assert mastery, but we're " - "in the middle of migration. Skipping assert, " - "the new master will handle that.\n"); - spin_unlock(&res->spinlock); - goto put; - } else - __dlm_lockres_reserve_ast(res); - spin_unlock(&res->spinlock); - /* this call now finishes out the nodemap * even if one or more nodes die */ mlog(0, "worker about to master %.*s here, this=%u\n", @@ -2028,14 +1875,9 @@ static void dlm_assert_master_worker(struct dlm_work_item *item, void *data) nodemap, flags); if (ret < 0) { /* no need to restart, we are done */ - if (!dlm_is_host_down(ret)) - mlog_errno(ret); + mlog_errno(ret); } - /* Ok, we've asserted ourselves. Let's let migration start. */ - dlm_lockres_release_ast(dlm, res); - -put: dlm_lockres_put(res); mlog(0, "finished with dlm_assert_master_worker\n"); @@ -2074,7 +1916,6 @@ static int dlm_pre_master_reco_lockres(struct dlm_ctxt *dlm, BUG(); /* host is down, so answer for that node would be * DLM_LOCK_RES_OWNER_UNKNOWN. continue. */ - ret = 0; } if (master != DLM_LOCK_RES_OWNER_UNKNOWN) { @@ -2175,14 +2016,14 @@ int dlm_migrate_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, */ ret = -ENOMEM; - mres = (struct dlm_migratable_lockres *) __get_free_page(GFP_NOFS); + mres = (struct dlm_migratable_lockres *) __get_free_page(GFP_KERNEL); if (!mres) { mlog_errno(ret); goto leave; } mle = (struct dlm_master_list_entry *) kmem_cache_alloc(dlm_mle_cache, - GFP_NOFS); + GFP_KERNEL); if (!mle) { mlog_errno(ret); goto leave; @@ -2276,7 +2117,7 @@ int dlm_migrate_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, * take both dlm->spinlock and dlm->master_lock */ spin_lock(&dlm->spinlock); spin_lock(&dlm->master_lock); - dlm_get_mle_inuse(mle); + dlm_get_mle(mle); spin_unlock(&dlm->master_lock); spin_unlock(&dlm->spinlock); @@ -2293,10 +2134,7 @@ int dlm_migrate_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, /* migration failed, detach and clean up mle */ dlm_mle_detach_hb_events(dlm, mle); dlm_put_mle(mle); - dlm_put_mle_inuse(mle); - spin_lock(&res->spinlock); - res->state &= ~DLM_LOCK_RES_MIGRATING; - spin_unlock(&res->spinlock); + dlm_put_mle(mle); goto leave; } @@ -2326,8 +2164,8 @@ int dlm_migrate_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, /* avoid hang during shutdown when migrating lockres * to a node which also goes down */ if (dlm_is_node_dead(dlm, target)) { - mlog(0, "%s:%.*s: expected migration " - "target %u is no longer up, restarting\n", + mlog(0, "%s:%.*s: expected migration target %u " + "is no longer up. restarting.\n", dlm->name, res->lockname.len, res->lockname.name, target); ret = -ERESTARTSYS; @@ -2337,10 +2175,7 @@ int dlm_migrate_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, /* migration failed, detach and clean up mle */ dlm_mle_detach_hb_events(dlm, mle); dlm_put_mle(mle); - dlm_put_mle_inuse(mle); - spin_lock(&res->spinlock); - res->state &= ~DLM_LOCK_RES_MIGRATING; - spin_unlock(&res->spinlock); + dlm_put_mle(mle); goto leave; } /* TODO: if node died: stop, clean up, return error */ @@ -2356,7 +2191,7 @@ int dlm_migrate_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, /* master is known, detach if not already detached */ dlm_mle_detach_hb_events(dlm, mle); - dlm_put_mle_inuse(mle); + dlm_put_mle(mle); ret = 0; dlm_lockres_calc_usage(dlm, res); @@ -2627,7 +2462,7 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data) struct dlm_migrate_request *migrate = (struct dlm_migrate_request *) msg->buf; struct dlm_master_list_entry *mle = NULL, *oldmle = NULL; const char *name; - unsigned int namelen, hash; + unsigned int namelen; int ret = 0; if (!dlm_grab(dlm)) @@ -2635,11 +2470,10 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data) name = migrate->name; namelen = migrate->namelen; - hash = dlm_lockid_hash(name, namelen); /* preallocate.. if this fails, abort */ mle = (struct dlm_master_list_entry *) kmem_cache_alloc(dlm_mle_cache, - GFP_NOFS); + GFP_KERNEL); if (!mle) { ret = -ENOMEM; @@ -2648,7 +2482,7 @@ int dlm_migrate_request_handler(struct o2net_msg *msg, u32 len, void *data) /* check for pre-existing lock */ spin_lock(&dlm->spinlock); - res = __dlm_lookup_lockres(dlm, name, namelen, hash); + res = __dlm_lookup_lockres(dlm, name, namelen); spin_lock(&dlm->master_lock); if (res) { @@ -2746,7 +2580,6 @@ static int dlm_add_migration_mle(struct dlm_ctxt *dlm, /* remove it from the list so that only one * mle will be found */ list_del_init(&tmp->list); - __dlm_mle_detach_hb_events(dlm, mle); } spin_unlock(&tmp->spinlock); } @@ -2768,7 +2601,6 @@ void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node) struct list_head *iter, *iter2; struct dlm_master_list_entry *mle; struct dlm_lock_resource *res; - unsigned int hash; mlog_entry("dlm=%s, dead node=%u\n", dlm->name, dead_node); top: @@ -2808,7 +2640,7 @@ void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node) * may result in the mle being unlinked and * freed, but there may still be a process * waiting in the dlmlock path which is fine. */ - mlog(0, "node %u was expected master\n", + mlog(ML_ERROR, "node %u was expected master\n", dead_node); atomic_set(&mle->woken, 1); spin_unlock(&mle->spinlock); @@ -2841,21 +2673,19 @@ void dlm_clean_master_list(struct dlm_ctxt *dlm, u8 dead_node) /* remove from the list early. NOTE: unlinking * list_head while in list_for_each_safe */ - __dlm_mle_detach_hb_events(dlm, mle); spin_lock(&mle->spinlock); list_del_init(&mle->list); atomic_set(&mle->woken, 1); spin_unlock(&mle->spinlock); wake_up(&mle->wq); - mlog(0, "%s: node %u died during migration from " - "%u to %u!\n", dlm->name, dead_node, + mlog(0, "node %u died during migration from " + "%u to %u!\n", dead_node, mle->master, mle->new_master); /* if there is a lockres associated with this * mle, find it and set its owner to UNKNOWN */ - hash = dlm_lockid_hash(mle->u.name.name, mle->u.name.len); res = __dlm_lookup_lockres(dlm, mle->u.name.name, - mle->u.name.len, hash); + mle->u.name.len); if (res) { /* unfortunately if we hit this rare case, our * lock ordering is messed. we need to drop diff --git a/trunk/fs/ocfs2/dlm/dlmrecovery.c b/trunk/fs/ocfs2/dlm/dlmrecovery.c index 594745fab0b5..805cbabac051 100644 --- a/trunk/fs/ocfs2/dlm/dlmrecovery.c +++ b/trunk/fs/ocfs2/dlm/dlmrecovery.c @@ -95,14 +95,11 @@ static void dlm_reco_unlock_ast(void *astdata, enum dlm_status st); static void dlm_request_all_locks_worker(struct dlm_work_item *item, void *data); static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data); -static int dlm_lockres_master_requery(struct dlm_ctxt *dlm, - struct dlm_lock_resource *res, - u8 *real_master); static u64 dlm_get_next_mig_cookie(void); -static DEFINE_SPINLOCK(dlm_reco_state_lock); -static DEFINE_SPINLOCK(dlm_mig_cookie_lock); +static spinlock_t dlm_reco_state_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t dlm_mig_cookie_lock = SPIN_LOCK_UNLOCKED; static u64 dlm_mig_cookie = 1; static u64 dlm_get_next_mig_cookie(void) @@ -118,37 +115,12 @@ static u64 dlm_get_next_mig_cookie(void) return c; } -static inline void dlm_set_reco_dead_node(struct dlm_ctxt *dlm, - u8 dead_node) -{ - assert_spin_locked(&dlm->spinlock); - if (dlm->reco.dead_node != dead_node) - mlog(0, "%s: changing dead_node from %u to %u\n", - dlm->name, dlm->reco.dead_node, dead_node); - dlm->reco.dead_node = dead_node; -} - -static inline void dlm_set_reco_master(struct dlm_ctxt *dlm, - u8 master) -{ - assert_spin_locked(&dlm->spinlock); - mlog(0, "%s: changing new_master from %u to %u\n", - dlm->name, dlm->reco.new_master, master); - dlm->reco.new_master = master; -} - -static inline void __dlm_reset_recovery(struct dlm_ctxt *dlm) -{ - assert_spin_locked(&dlm->spinlock); - clear_bit(dlm->reco.dead_node, dlm->recovery_map); - dlm_set_reco_dead_node(dlm, O2NM_INVALID_NODE_NUM); - dlm_set_reco_master(dlm, O2NM_INVALID_NODE_NUM); -} - static inline void dlm_reset_recovery(struct dlm_ctxt *dlm) { spin_lock(&dlm->spinlock); - __dlm_reset_recovery(dlm); + clear_bit(dlm->reco.dead_node, dlm->recovery_map); + dlm->reco.dead_node = O2NM_INVALID_NODE_NUM; + dlm->reco.new_master = O2NM_INVALID_NODE_NUM; spin_unlock(&dlm->spinlock); } @@ -160,20 +132,11 @@ void dlm_dispatch_work(void *data) struct list_head *iter, *iter2; struct dlm_work_item *item; dlm_workfunc_t *workfunc; - int tot=0; - - if (!dlm_joined(dlm)) - return; spin_lock(&dlm->work_lock); list_splice_init(&dlm->work_list, &tmp_list); spin_unlock(&dlm->work_lock); - list_for_each_safe(iter, iter2, &tmp_list) { - tot++; - } - mlog(0, "%s: work thread has %d work items\n", dlm->name, tot); - list_for_each_safe(iter, iter2, &tmp_list) { item = list_entry(iter, struct dlm_work_item, list); workfunc = item->func; @@ -257,52 +220,6 @@ void dlm_complete_recovery_thread(struct dlm_ctxt *dlm) * */ -static void dlm_print_reco_node_status(struct dlm_ctxt *dlm) -{ - struct dlm_reco_node_data *ndata; - struct dlm_lock_resource *res; - - mlog(ML_NOTICE, "%s(%d): recovery info, state=%s, dead=%u, master=%u\n", - dlm->name, dlm->dlm_reco_thread_task->pid, - dlm->reco.state & DLM_RECO_STATE_ACTIVE ? "ACTIVE" : "inactive", - dlm->reco.dead_node, dlm->reco.new_master); - - list_for_each_entry(ndata, &dlm->reco.node_data, list) { - char *st = "unknown"; - switch (ndata->state) { - case DLM_RECO_NODE_DATA_INIT: - st = "init"; - break; - case DLM_RECO_NODE_DATA_REQUESTING: - st = "requesting"; - break; - case DLM_RECO_NODE_DATA_DEAD: - st = "dead"; - break; - case DLM_RECO_NODE_DATA_RECEIVING: - st = "receiving"; - break; - case DLM_RECO_NODE_DATA_REQUESTED: - st = "requested"; - break; - case DLM_RECO_NODE_DATA_DONE: - st = "done"; - break; - case DLM_RECO_NODE_DATA_FINALIZE_SENT: - st = "finalize-sent"; - break; - default: - st = "bad"; - break; - } - mlog(ML_NOTICE, "%s: reco state, node %u, state=%s\n", - dlm->name, ndata->node_num, st); - } - list_for_each_entry(res, &dlm->reco.resources, recovering) { - mlog(ML_NOTICE, "%s: lockres %.*s on recovering list\n", - dlm->name, res->lockname.len, res->lockname.name); - } -} #define DLM_RECO_THREAD_TIMEOUT_MS (5 * 1000) @@ -350,23 +267,11 @@ int dlm_is_node_dead(struct dlm_ctxt *dlm, u8 node) { int dead; spin_lock(&dlm->spinlock); - dead = !test_bit(node, dlm->domain_map); + dead = test_bit(node, dlm->domain_map); spin_unlock(&dlm->spinlock); return dead; } -/* returns true if node is no longer in the domain - * could be dead or just not joined */ -static int dlm_is_node_recovered(struct dlm_ctxt *dlm, u8 node) -{ - int recovered; - spin_lock(&dlm->spinlock); - recovered = !test_bit(node, dlm->recovery_map); - spin_unlock(&dlm->spinlock); - return recovered; -} - - int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout) { if (timeout) { @@ -385,24 +290,6 @@ int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout) return 0; } -int dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout) -{ - if (timeout) { - mlog(0, "%s: waiting %dms for notification of " - "recovery of node %u\n", dlm->name, timeout, node); - wait_event_timeout(dlm->dlm_reco_thread_wq, - dlm_is_node_recovered(dlm, node), - msecs_to_jiffies(timeout)); - } else { - mlog(0, "%s: waiting indefinitely for notification " - "of recovery of node %u\n", dlm->name, node); - wait_event(dlm->dlm_reco_thread_wq, - dlm_is_node_recovered(dlm, node)); - } - /* for now, return 0 */ - return 0; -} - /* callers of the top-level api calls (dlmlock/dlmunlock) should * block on the dlm->reco.event when recovery is in progress. * the dlm recovery thread will set this state when it begins @@ -421,13 +308,6 @@ static int dlm_in_recovery(struct dlm_ctxt *dlm) void dlm_wait_for_recovery(struct dlm_ctxt *dlm) { - if (dlm_in_recovery(dlm)) { - mlog(0, "%s: reco thread %d in recovery: " - "state=%d, master=%u, dead=%u\n", - dlm->name, dlm->dlm_reco_thread_task->pid, - dlm->reco.state, dlm->reco.new_master, - dlm->reco.dead_node); - } wait_event(dlm->reco.event, !dlm_in_recovery(dlm)); } @@ -461,7 +341,7 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) mlog(0, "new master %u died while recovering %u!\n", dlm->reco.new_master, dlm->reco.dead_node); /* unset the new_master, leave dead_node */ - dlm_set_reco_master(dlm, O2NM_INVALID_NODE_NUM); + dlm->reco.new_master = O2NM_INVALID_NODE_NUM; } /* select a target to recover */ @@ -470,14 +350,14 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) bit = find_next_bit (dlm->recovery_map, O2NM_MAX_NODES+1, 0); if (bit >= O2NM_MAX_NODES || bit < 0) - dlm_set_reco_dead_node(dlm, O2NM_INVALID_NODE_NUM); + dlm->reco.dead_node = O2NM_INVALID_NODE_NUM; else - dlm_set_reco_dead_node(dlm, bit); + dlm->reco.dead_node = bit; } else if (!test_bit(dlm->reco.dead_node, dlm->recovery_map)) { /* BUG? */ mlog(ML_ERROR, "dead_node %u no longer in recovery map!\n", dlm->reco.dead_node); - dlm_set_reco_dead_node(dlm, O2NM_INVALID_NODE_NUM); + dlm->reco.dead_node = O2NM_INVALID_NODE_NUM; } if (dlm->reco.dead_node == O2NM_INVALID_NODE_NUM) { @@ -486,8 +366,7 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) /* return to main thread loop and sleep. */ return 0; } - mlog(0, "%s(%d):recovery thread found node %u in the recovery map!\n", - dlm->name, dlm->dlm_reco_thread_task->pid, + mlog(0, "recovery thread found node %u in the recovery map!\n", dlm->reco.dead_node); spin_unlock(&dlm->spinlock); @@ -510,8 +389,8 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) } mlog(0, "another node will master this recovery session.\n"); } - mlog(0, "dlm=%s (%d), new_master=%u, this node=%u, dead_node=%u\n", - dlm->name, dlm->dlm_reco_thread_task->pid, dlm->reco.new_master, + mlog(0, "dlm=%s, new_master=%u, this node=%u, dead_node=%u\n", + dlm->name, dlm->reco.new_master, dlm->node_num, dlm->reco.dead_node); /* it is safe to start everything back up here @@ -523,13 +402,11 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) return 0; master_here: - mlog(0, "(%d) mastering recovery of %s:%u here(this=%u)!\n", - dlm->dlm_reco_thread_task->pid, + mlog(0, "mastering recovery of %s:%u here(this=%u)!\n", dlm->name, dlm->reco.dead_node, dlm->node_num); status = dlm_remaster_locks(dlm, dlm->reco.dead_node); if (status < 0) { - /* we should never hit this anymore */ mlog(ML_ERROR, "error %d remastering locks for node %u, " "retrying.\n", status, dlm->reco.dead_node); /* yield a bit to allow any final network messages @@ -556,16 +433,9 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) int destroy = 0; int pass = 0; - do { - /* we have become recovery master. there is no escaping - * this, so just keep trying until we get it. */ - status = dlm_init_recovery_area(dlm, dead_node); - if (status < 0) { - mlog(ML_ERROR, "%s: failed to alloc recovery area, " - "retrying\n", dlm->name); - msleep(1000); - } - } while (status != 0); + status = dlm_init_recovery_area(dlm, dead_node); + if (status < 0) + goto leave; /* safe to access the node data list without a lock, since this * process is the only one to change the list */ @@ -582,36 +452,16 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) continue; } - do { - status = dlm_request_all_locks(dlm, ndata->node_num, - dead_node); - if (status < 0) { - mlog_errno(status); - if (dlm_is_host_down(status)) { - /* node died, ignore it for recovery */ - status = 0; - ndata->state = DLM_RECO_NODE_DATA_DEAD; - /* wait for the domain map to catch up - * with the network state. */ - wait_event_timeout(dlm->dlm_reco_thread_wq, - dlm_is_node_dead(dlm, - ndata->node_num), - msecs_to_jiffies(1000)); - mlog(0, "waited 1 sec for %u, " - "dead? %s\n", ndata->node_num, - dlm_is_node_dead(dlm, ndata->node_num) ? - "yes" : "no"); - } else { - /* -ENOMEM on the other node */ - mlog(0, "%s: node %u returned " - "%d during recovery, retrying " - "after a short wait\n", - dlm->name, ndata->node_num, - status); - msleep(100); - } + status = dlm_request_all_locks(dlm, ndata->node_num, dead_node); + if (status < 0) { + mlog_errno(status); + if (dlm_is_host_down(status)) + ndata->state = DLM_RECO_NODE_DATA_DEAD; + else { + destroy = 1; + goto leave; } - } while (status != 0); + } switch (ndata->state) { case DLM_RECO_NODE_DATA_INIT: @@ -623,9 +473,10 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) mlog(0, "node %u died after requesting " "recovery info for node %u\n", ndata->node_num, dead_node); - /* fine. don't need this node's info. - * continue without it. */ - break; + // start all over + destroy = 1; + status = -EAGAIN; + goto leave; case DLM_RECO_NODE_DATA_REQUESTING: ndata->state = DLM_RECO_NODE_DATA_REQUESTED; mlog(0, "now receiving recovery data from " @@ -669,26 +520,35 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) BUG(); break; case DLM_RECO_NODE_DATA_DEAD: - mlog(0, "node %u died after " + mlog(ML_NOTICE, "node %u died after " "requesting recovery info for " "node %u\n", ndata->node_num, dead_node); - break; + spin_unlock(&dlm_reco_state_lock); + // start all over + destroy = 1; + status = -EAGAIN; + /* instead of spinning like crazy here, + * wait for the domain map to catch up + * with the network state. otherwise this + * can be hit hundreds of times before + * the node is really seen as dead. */ + wait_event_timeout(dlm->dlm_reco_thread_wq, + dlm_is_node_dead(dlm, + ndata->node_num), + msecs_to_jiffies(1000)); + mlog(0, "waited 1 sec for %u, " + "dead? %s\n", ndata->node_num, + dlm_is_node_dead(dlm, ndata->node_num) ? + "yes" : "no"); + goto leave; case DLM_RECO_NODE_DATA_RECEIVING: case DLM_RECO_NODE_DATA_REQUESTED: - mlog(0, "%s: node %u still in state %s\n", - dlm->name, ndata->node_num, - ndata->state==DLM_RECO_NODE_DATA_RECEIVING ? - "receiving" : "requested"); all_nodes_done = 0; break; case DLM_RECO_NODE_DATA_DONE: - mlog(0, "%s: node %u state is done\n", - dlm->name, ndata->node_num); break; case DLM_RECO_NODE_DATA_FINALIZE_SENT: - mlog(0, "%s: node %u state is finalize\n", - dlm->name, ndata->node_num); break; } } @@ -718,7 +578,7 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) jiffies, dlm->reco.dead_node, dlm->node_num, dlm->reco.new_master); destroy = 1; - status = 0; + status = ret; /* rescan everything marked dirty along the way */ dlm_kick_thread(dlm, NULL); break; @@ -731,6 +591,7 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node) } +leave: if (destroy) dlm_destroy_recovery_area(dlm, dead_node); @@ -756,7 +617,7 @@ static int dlm_init_recovery_area(struct dlm_ctxt *dlm, u8 dead_node) } BUG_ON(num == dead_node); - ndata = kcalloc(1, sizeof(*ndata), GFP_NOFS); + ndata = kcalloc(1, sizeof(*ndata), GFP_KERNEL); if (!ndata) { dlm_destroy_recovery_area(dlm, dead_node); return -ENOMEM; @@ -830,25 +691,16 @@ int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data) if (!dlm_grab(dlm)) return -EINVAL; - if (lr->dead_node != dlm->reco.dead_node) { - mlog(ML_ERROR, "%s: node %u sent dead_node=%u, but local " - "dead_node is %u\n", dlm->name, lr->node_idx, - lr->dead_node, dlm->reco.dead_node); - dlm_print_reco_node_status(dlm); - /* this is a hack */ - dlm_put(dlm); - return -ENOMEM; - } BUG_ON(lr->dead_node != dlm->reco.dead_node); - item = kcalloc(1, sizeof(*item), GFP_NOFS); + item = kcalloc(1, sizeof(*item), GFP_KERNEL); if (!item) { dlm_put(dlm); return -ENOMEM; } /* this will get freed by dlm_request_all_locks_worker */ - buf = (char *) __get_free_page(GFP_NOFS); + buf = (char *) __get_free_page(GFP_KERNEL); if (!buf) { kfree(item); dlm_put(dlm); @@ -863,7 +715,7 @@ int dlm_request_all_locks_handler(struct o2net_msg *msg, u32 len, void *data) spin_lock(&dlm->work_lock); list_add_tail(&item->list, &dlm->work_list); spin_unlock(&dlm->work_lock); - queue_work(dlm->dlm_worker, &dlm->dispatched_work); + schedule_work(&dlm->dispatched_work); dlm_put(dlm); return 0; @@ -878,34 +730,32 @@ static void dlm_request_all_locks_worker(struct dlm_work_item *item, void *data) struct list_head *iter; int ret; u8 dead_node, reco_master; - int skip_all_done = 0; dlm = item->dlm; dead_node = item->u.ral.dead_node; reco_master = item->u.ral.reco_master; mres = (struct dlm_migratable_lockres *)data; - mlog(0, "%s: recovery worker started, dead=%u, master=%u\n", - dlm->name, dead_node, reco_master); - if (dead_node != dlm->reco.dead_node || reco_master != dlm->reco.new_master) { - /* worker could have been created before the recovery master - * died. if so, do not continue, but do not error. */ - if (dlm->reco.new_master == O2NM_INVALID_NODE_NUM) { - mlog(ML_NOTICE, "%s: will not send recovery state, " - "recovery master %u died, thread=(dead=%u,mas=%u)" - " current=(dead=%u,mas=%u)\n", dlm->name, - reco_master, dead_node, reco_master, - dlm->reco.dead_node, dlm->reco.new_master); - } else { - mlog(ML_NOTICE, "%s: reco state invalid: reco(dead=%u, " - "master=%u), request(dead=%u, master=%u)\n", - dlm->name, dlm->reco.dead_node, - dlm->reco.new_master, dead_node, reco_master); - } - goto leave; + /* show extra debug info if the recovery state is messed */ + mlog(ML_ERROR, "%s: bad reco state: reco(dead=%u, master=%u), " + "request(dead=%u, master=%u)\n", + dlm->name, dlm->reco.dead_node, dlm->reco.new_master, + dead_node, reco_master); + mlog(ML_ERROR, "%s: name=%.*s master=%u locks=%u/%u flags=%u " + "entry[0]={c=%u:%llu,l=%u,f=%u,t=%d,ct=%d,hb=%d,n=%u}\n", + dlm->name, mres->lockname_len, mres->lockname, mres->master, + mres->num_locks, mres->total_locks, mres->flags, + dlm_get_lock_cookie_node(mres->ml[0].cookie), + dlm_get_lock_cookie_seq(mres->ml[0].cookie), + mres->ml[0].list, mres->ml[0].flags, + mres->ml[0].type, mres->ml[0].convert_type, + mres->ml[0].highest_blocked, mres->ml[0].node); + BUG(); } + BUG_ON(dead_node != dlm->reco.dead_node); + BUG_ON(reco_master != dlm->reco.new_master); /* lock resources should have already been moved to the * dlm->reco.resources list. now move items from that list @@ -916,20 +766,12 @@ static void dlm_request_all_locks_worker(struct dlm_work_item *item, void *data) dlm_move_reco_locks_to_list(dlm, &resources, dead_node); /* now we can begin blasting lockreses without the dlm lock */ - - /* any errors returned will be due to the new_master dying, - * the dlm_reco_thread should detect this */ list_for_each(iter, &resources) { res = list_entry (iter, struct dlm_lock_resource, recovering); ret = dlm_send_one_lockres(dlm, res, mres, reco_master, DLM_MRES_RECOVERY); - if (ret < 0) { - mlog(ML_ERROR, "%s: node %u went down while sending " - "recovery state for dead node %u, ret=%d\n", dlm->name, - reco_master, dead_node, ret); - skip_all_done = 1; - break; - } + if (ret < 0) + mlog_errno(ret); } /* move the resources back to the list */ @@ -937,15 +779,10 @@ static void dlm_request_all_locks_worker(struct dlm_work_item *item, void *data) list_splice_init(&resources, &dlm->reco.resources); spin_unlock(&dlm->spinlock); - if (!skip_all_done) { - ret = dlm_send_all_done_msg(dlm, dead_node, reco_master); - if (ret < 0) { - mlog(ML_ERROR, "%s: node %u went down while sending " - "recovery all-done for dead node %u, ret=%d\n", - dlm->name, reco_master, dead_node, ret); - } - } -leave: + ret = dlm_send_all_done_msg(dlm, dead_node, reco_master); + if (ret < 0) + mlog_errno(ret); + free_page((unsigned long)data); } @@ -964,14 +801,8 @@ static int dlm_send_all_done_msg(struct dlm_ctxt *dlm, u8 dead_node, u8 send_to) ret = o2net_send_message(DLM_RECO_DATA_DONE_MSG, dlm->key, &done_msg, sizeof(done_msg), send_to, &tmpret); - if (ret < 0) { - if (!dlm_is_host_down(ret)) { - mlog_errno(ret); - mlog(ML_ERROR, "%s: unknown error sending data-done " - "to %u\n", dlm->name, send_to); - BUG(); - } - } else + /* negative status is ignored by the caller */ + if (ret >= 0) ret = tmpret; return ret; } @@ -991,11 +822,7 @@ int dlm_reco_data_done_handler(struct o2net_msg *msg, u32 len, void *data) mlog(0, "got DATA DONE: dead_node=%u, reco.dead_node=%u, " "node_idx=%u, this node=%u\n", done->dead_node, dlm->reco.dead_node, done->node_idx, dlm->node_num); - - mlog_bug_on_msg((done->dead_node != dlm->reco.dead_node), - "Got DATA DONE: dead_node=%u, reco.dead_node=%u, " - "node_idx=%u, this node=%u\n", done->dead_node, - dlm->reco.dead_node, done->node_idx, dlm->node_num); + BUG_ON(done->dead_node != dlm->reco.dead_node); spin_lock(&dlm_reco_state_lock); list_for_each(iter, &dlm->reco.node_data) { @@ -1078,11 +905,13 @@ static void dlm_move_reco_locks_to_list(struct dlm_ctxt *dlm, mlog(0, "found lockres owned by dead node while " "doing recovery for node %u. sending it.\n", dead_node); - list_move_tail(&res->recovering, list); + list_del_init(&res->recovering); + list_add_tail(&res->recovering, list); } else if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) { mlog(0, "found UNKNOWN owner while doing recovery " "for node %u. sending it.\n", dead_node); - list_move_tail(&res->recovering, list); + list_del_init(&res->recovering); + list_add_tail(&res->recovering, list); } } spin_unlock(&dlm->spinlock); @@ -1194,9 +1023,8 @@ static int dlm_add_lock_to_array(struct dlm_lock *lock, ml->type == LKM_PRMODE) { /* if it is already set, this had better be a PR * and it has to match */ - if (!dlm_lvb_is_empty(mres->lvb) && - (ml->type == LKM_EXMODE || - memcmp(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN))) { + if (mres->lvb[0] && (ml->type == LKM_EXMODE || + memcmp(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN))) { mlog(ML_ERROR, "mismatched lvbs!\n"); __dlm_print_one_lock_resource(lock->lockres); BUG(); @@ -1255,25 +1083,22 @@ int dlm_send_one_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, * we must send it immediately. */ ret = dlm_send_mig_lockres_msg(dlm, mres, send_to, res, total_locks); - if (ret < 0) - goto error; + if (ret < 0) { + // TODO + mlog(ML_ERROR, "dlm_send_mig_lockres_msg " + "returned %d, TODO\n", ret); + BUG(); + } } } /* flush any remaining locks */ ret = dlm_send_mig_lockres_msg(dlm, mres, send_to, res, total_locks); - if (ret < 0) - goto error; - return ret; - -error: - mlog(ML_ERROR, "%s: dlm_send_mig_lockres_msg returned %d\n", - dlm->name, ret); - if (!dlm_is_host_down(ret)) + if (ret < 0) { + // TODO + mlog(ML_ERROR, "dlm_send_mig_lockres_msg returned %d, " + "TODO\n", ret); BUG(); - mlog(0, "%s: node %u went down while sending %s " - "lockres %.*s\n", dlm->name, send_to, - flags & DLM_MRES_RECOVERY ? "recovery" : "migration", - res->lockname.len, res->lockname.name); + } return ret; } @@ -1321,8 +1146,8 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data) mlog(0, "all done flag. all lockres data received!\n"); ret = -ENOMEM; - buf = kmalloc(be16_to_cpu(msg->data_len), GFP_NOFS); - item = kcalloc(1, sizeof(*item), GFP_NOFS); + buf = kmalloc(be16_to_cpu(msg->data_len), GFP_KERNEL); + item = kcalloc(1, sizeof(*item), GFP_KERNEL); if (!buf || !item) goto leave; @@ -1413,7 +1238,7 @@ int dlm_mig_lockres_handler(struct o2net_msg *msg, u32 len, void *data) spin_lock(&dlm->work_lock); list_add_tail(&item->list, &dlm->work_list); spin_unlock(&dlm->work_lock); - queue_work(dlm->dlm_worker, &dlm->dispatched_work); + schedule_work(&dlm->dispatched_work); leave: dlm_put(dlm); @@ -1487,9 +1312,8 @@ static void dlm_mig_lockres_worker(struct dlm_work_item *item, void *data) -static int dlm_lockres_master_requery(struct dlm_ctxt *dlm, - struct dlm_lock_resource *res, - u8 *real_master) +int dlm_lockres_master_requery(struct dlm_ctxt *dlm, + struct dlm_lock_resource *res, u8 *real_master) { struct dlm_node_iter iter; int nodenum; @@ -1582,7 +1406,6 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data) struct dlm_ctxt *dlm = data; struct dlm_master_requery *req = (struct dlm_master_requery *)msg->buf; struct dlm_lock_resource *res = NULL; - unsigned int hash; int master = DLM_LOCK_RES_OWNER_UNKNOWN; u32 flags = DLM_ASSERT_MASTER_REQUERY; @@ -1592,10 +1415,8 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data) return master; } - hash = dlm_lockid_hash(req->name, req->namelen); - spin_lock(&dlm->spinlock); - res = __dlm_lookup_lockres(dlm, req->name, req->namelen, hash); + res = __dlm_lookup_lockres(dlm, req->name, req->namelen); if (res) { spin_lock(&res->spinlock); master = res->owner; @@ -1662,7 +1483,7 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm, struct dlm_lock *newlock = NULL; struct dlm_lockstatus *lksb = NULL; int ret = 0; - int i, bad; + int i; struct list_head *iter; struct dlm_lock *lock = NULL; @@ -1708,7 +1529,8 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm, /* move the lock to its proper place */ /* do not alter lock refcount. switching lists. */ - list_move_tail(&lock->list, queue); + list_del_init(&lock->list); + list_add_tail(&lock->list, queue); spin_unlock(&res->spinlock); mlog(0, "just reordered a local lock!\n"); @@ -1731,48 +1553,28 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm, } lksb->flags |= (ml->flags & (DLM_LKSB_PUT_LVB|DLM_LKSB_GET_LVB)); - - if (ml->type == LKM_NLMODE) - goto skip_lvb; - - if (!dlm_lvb_is_empty(mres->lvb)) { + + if (mres->lvb[0]) { if (lksb->flags & DLM_LKSB_PUT_LVB) { /* other node was trying to update * lvb when node died. recreate the * lksb with the updated lvb. */ memcpy(lksb->lvb, mres->lvb, DLM_LVB_LEN); - /* the lock resource lvb update must happen - * NOW, before the spinlock is dropped. - * we no longer wait for the AST to update - * the lvb. */ - memcpy(res->lvb, mres->lvb, DLM_LVB_LEN); } else { /* otherwise, the node is sending its * most recent valid lvb info */ BUG_ON(ml->type != LKM_EXMODE && ml->type != LKM_PRMODE); - if (!dlm_lvb_is_empty(res->lvb) && - (ml->type == LKM_EXMODE || - memcmp(res->lvb, mres->lvb, DLM_LVB_LEN))) { - int i; - mlog(ML_ERROR, "%s:%.*s: received bad " - "lvb! type=%d\n", dlm->name, - res->lockname.len, - res->lockname.name, ml->type); - printk("lockres lvb=["); - for (i=0; ilvb[i]); - printk("]\nmigrated lvb=["); - for (i=0; ilvb[i]); - printk("]\n"); - dlm_print_one_lock_resource(res); - BUG(); + if (res->lvb[0] && (ml->type == LKM_EXMODE || + memcmp(res->lvb, mres->lvb, DLM_LVB_LEN))) { + mlog(ML_ERROR, "received bad lvb!\n"); + __dlm_print_one_lock_resource(res); + BUG(); } memcpy(res->lvb, mres->lvb, DLM_LVB_LEN); } } -skip_lvb: + /* NOTE: * wrt lock queue ordering and recovery: @@ -1790,33 +1592,9 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm, * relative to each other, but clearly *not* * preserved relative to locks from other nodes. */ - bad = 0; spin_lock(&res->spinlock); - list_for_each_entry(lock, queue, list) { - if (lock->ml.cookie == ml->cookie) { - u64 c = lock->ml.cookie; - mlog(ML_ERROR, "%s:%.*s: %u:%llu: lock already " - "exists on this lockres!\n", dlm->name, - res->lockname.len, res->lockname.name, - dlm_get_lock_cookie_node(c), - dlm_get_lock_cookie_seq(c)); - - mlog(ML_NOTICE, "sent lock: type=%d, conv=%d, " - "node=%u, cookie=%u:%llu, queue=%d\n", - ml->type, ml->convert_type, ml->node, - dlm_get_lock_cookie_node(ml->cookie), - dlm_get_lock_cookie_seq(ml->cookie), - ml->list); - - __dlm_print_one_lock_resource(res); - bad = 1; - break; - } - } - if (!bad) { - dlm_lock_get(newlock); - list_add_tail(&newlock->list, queue); - } + dlm_lock_get(newlock); + list_add_tail(&newlock->list, queue); spin_unlock(&res->spinlock); } mlog(0, "done running all the locks\n"); @@ -1840,14 +1618,8 @@ void dlm_move_lockres_to_recovery_list(struct dlm_ctxt *dlm, struct dlm_lock *lock; res->state |= DLM_LOCK_RES_RECOVERING; - if (!list_empty(&res->recovering)) { - mlog(0, - "Recovering res %s:%.*s, is already on recovery list!\n", - dlm->name, res->lockname.len, res->lockname.name); + if (!list_empty(&res->recovering)) list_del_init(&res->recovering); - } - /* We need to hold a reference while on the recovery list */ - dlm_lockres_get(res); list_add_tail(&res->recovering, &dlm->reco.resources); /* find any pending locks and put them back on proper list */ @@ -1936,11 +1708,9 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm, spin_lock(&res->spinlock); dlm_change_lockres_owner(dlm, res, new_master); res->state &= ~DLM_LOCK_RES_RECOVERING; - if (!__dlm_lockres_unused(res)) - __dlm_dirty_lockres(dlm, res); + __dlm_dirty_lockres(dlm, res); spin_unlock(&res->spinlock); wake_up(&res->wq); - dlm_lockres_put(res); } } @@ -1949,7 +1719,7 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm, * the RECOVERING state and set the owner * if necessary */ for (i = 0; i < DLM_HASH_BUCKETS; i++) { - bucket = dlm_lockres_hash(dlm, i); + bucket = &(dlm->lockres_hash[i]); hlist_for_each_entry(res, hash_iter, bucket, hash_node) { if (res->state & DLM_LOCK_RES_RECOVERING) { if (res->owner == dead_node) { @@ -1973,13 +1743,11 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm, dlm->name, res->lockname.len, res->lockname.name, res->owner); list_del_init(&res->recovering); - dlm_lockres_put(res); } spin_lock(&res->spinlock); dlm_change_lockres_owner(dlm, res, new_master); res->state &= ~DLM_LOCK_RES_RECOVERING; - if (!__dlm_lockres_unused(res)) - __dlm_dirty_lockres(dlm, res); + __dlm_dirty_lockres(dlm, res); spin_unlock(&res->spinlock); wake_up(&res->wq); } @@ -2116,7 +1884,7 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node) * need to be fired as a result. */ for (i = 0; i < DLM_HASH_BUCKETS; i++) { - bucket = dlm_lockres_hash(dlm, i); + bucket = &(dlm->lockres_hash[i]); hlist_for_each_entry(res, iter, bucket, hash_node) { /* always prune any $RECOVERY entries for dead nodes, * otherwise hangs can occur during later recovery */ @@ -2156,20 +1924,6 @@ static void __dlm_hb_node_down(struct dlm_ctxt *dlm, int idx) { assert_spin_locked(&dlm->spinlock); - if (dlm->reco.new_master == idx) { - mlog(0, "%s: recovery master %d just died\n", - dlm->name, idx); - if (dlm->reco.state & DLM_RECO_STATE_FINALIZE) { - /* finalize1 was reached, so it is safe to clear - * the new_master and dead_node. that recovery - * is complete. */ - mlog(0, "%s: dead master %d had reached " - "finalize1 state, clearing\n", dlm->name, idx); - dlm->reco.state &= ~DLM_RECO_STATE_FINALIZE; - __dlm_reset_recovery(dlm); - } - } - /* check to see if the node is already considered dead */ if (!test_bit(idx, dlm->live_nodes_map)) { mlog(0, "for domain %s, node %d is already dead. " @@ -2333,7 +2087,7 @@ static int dlm_pick_recovery_master(struct dlm_ctxt *dlm) /* set the new_master to this node */ spin_lock(&dlm->spinlock); - dlm_set_reco_master(dlm, dlm->node_num); + dlm->reco.new_master = dlm->node_num; spin_unlock(&dlm->spinlock); } @@ -2371,10 +2125,6 @@ static int dlm_pick_recovery_master(struct dlm_ctxt *dlm) mlog(0, "%s: reco master %u is ready to recover %u\n", dlm->name, dlm->reco.new_master, dlm->reco.dead_node); status = -EEXIST; - } else if (ret == DLM_RECOVERING) { - mlog(0, "dlm=%s dlmlock says master node died (this=%u)\n", - dlm->name, dlm->node_num); - goto again; } else { struct dlm_lock_resource *res; @@ -2406,7 +2156,7 @@ static int dlm_send_begin_reco_message(struct dlm_ctxt *dlm, u8 dead_node) mlog_entry("%u\n", dead_node); - mlog(0, "%s: dead node is %u\n", dlm->name, dead_node); + mlog(0, "dead node is %u\n", dead_node); spin_lock(&dlm->spinlock); dlm_node_iter_init(dlm->domain_map, &iter); @@ -2464,14 +2214,6 @@ static int dlm_send_begin_reco_message(struct dlm_ctxt *dlm, u8 dead_node) * another ENOMEM */ msleep(100); goto retry; - } else if (ret == EAGAIN) { - mlog(0, "%s: trying to start recovery of node " - "%u, but node %u is waiting for last recovery " - "to complete, backoff for a bit\n", dlm->name, - dead_node, nodenum); - /* TODO Look into replacing msleep with cond_resched() */ - msleep(100); - goto retry; } } @@ -2487,20 +2229,8 @@ int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data) if (!dlm_grab(dlm)) return 0; - spin_lock(&dlm->spinlock); - if (dlm->reco.state & DLM_RECO_STATE_FINALIZE) { - mlog(0, "%s: node %u wants to recover node %u (%u:%u) " - "but this node is in finalize state, waiting on finalize2\n", - dlm->name, br->node_idx, br->dead_node, - dlm->reco.dead_node, dlm->reco.new_master); - spin_unlock(&dlm->spinlock); - return EAGAIN; - } - spin_unlock(&dlm->spinlock); - - mlog(0, "%s: node %u wants to recover node %u (%u:%u)\n", - dlm->name, br->node_idx, br->dead_node, - dlm->reco.dead_node, dlm->reco.new_master); + mlog(0, "node %u wants to recover node %u\n", + br->node_idx, br->dead_node); dlm_fire_domain_eviction_callbacks(dlm, br->dead_node); @@ -2522,8 +2252,8 @@ int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data) "node %u changing it to %u\n", dlm->name, dlm->reco.dead_node, br->node_idx, br->dead_node); } - dlm_set_reco_master(dlm, br->node_idx); - dlm_set_reco_dead_node(dlm, br->dead_node); + dlm->reco.new_master = br->node_idx; + dlm->reco.dead_node = br->dead_node; if (!test_bit(br->dead_node, dlm->recovery_map)) { mlog(0, "recovery master %u sees %u as dead, but this " "node has not yet. marking %u as dead\n", @@ -2542,16 +2272,10 @@ int dlm_begin_reco_handler(struct o2net_msg *msg, u32 len, void *data) spin_unlock(&dlm->spinlock); dlm_kick_recovery_thread(dlm); - - mlog(0, "%s: recovery started by node %u, for %u (%u:%u)\n", - dlm->name, br->node_idx, br->dead_node, - dlm->reco.dead_node, dlm->reco.new_master); - dlm_put(dlm); return 0; } -#define DLM_FINALIZE_STAGE2 0x01 static int dlm_send_finalize_reco_message(struct dlm_ctxt *dlm) { int ret = 0; @@ -2559,31 +2283,25 @@ static int dlm_send_finalize_reco_message(struct dlm_ctxt *dlm) struct dlm_node_iter iter; int nodenum; int status; - int stage = 1; - mlog(0, "finishing recovery for node %s:%u, " - "stage %d\n", dlm->name, dlm->reco.dead_node, stage); + mlog(0, "finishing recovery for node %s:%u\n", + dlm->name, dlm->reco.dead_node); spin_lock(&dlm->spinlock); dlm_node_iter_init(dlm->domain_map, &iter); spin_unlock(&dlm->spinlock); -stage2: memset(&fr, 0, sizeof(fr)); fr.node_idx = dlm->node_num; fr.dead_node = dlm->reco.dead_node; - if (stage == 2) - fr.flags |= DLM_FINALIZE_STAGE2; while ((nodenum = dlm_node_iter_next(&iter)) >= 0) { if (nodenum == dlm->node_num) continue; ret = o2net_send_message(DLM_FINALIZE_RECO_MSG, dlm->key, &fr, sizeof(fr), nodenum, &status); - if (ret >= 0) + if (ret >= 0) { ret = status; - if (ret < 0) { - mlog_errno(ret); if (dlm_is_host_down(ret)) { /* this has no effect on this recovery * session, so set the status to zero to @@ -2591,17 +2309,13 @@ static int dlm_send_finalize_reco_message(struct dlm_ctxt *dlm) mlog(ML_ERROR, "node %u went down after this " "node finished recovery.\n", nodenum); ret = 0; - continue; } + } + if (ret < 0) { + mlog_errno(ret); break; } } - if (stage == 1) { - /* reset the node_iter back to the top and send finalize2 */ - iter.curnode = -1; - stage = 2; - goto stage2; - } return ret; } @@ -2610,19 +2324,14 @@ int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data) { struct dlm_ctxt *dlm = data; struct dlm_finalize_reco *fr = (struct dlm_finalize_reco *)msg->buf; - int stage = 1; /* ok to return 0, domain has gone away */ if (!dlm_grab(dlm)) return 0; - if (fr->flags & DLM_FINALIZE_STAGE2) - stage = 2; + mlog(0, "node %u finalizing recovery of node %u\n", + fr->node_idx, fr->dead_node); - mlog(0, "%s: node %u finalizing recovery stage%d of " - "node %u (%u:%u)\n", dlm->name, fr->node_idx, stage, - fr->dead_node, dlm->reco.dead_node, dlm->reco.new_master); - spin_lock(&dlm->spinlock); if (dlm->reco.new_master != fr->node_idx) { @@ -2638,41 +2347,13 @@ int dlm_finalize_reco_handler(struct o2net_msg *msg, u32 len, void *data) BUG(); } - switch (stage) { - case 1: - dlm_finish_local_lockres_recovery(dlm, fr->dead_node, fr->node_idx); - if (dlm->reco.state & DLM_RECO_STATE_FINALIZE) { - mlog(ML_ERROR, "%s: received finalize1 from " - "new master %u for dead node %u, but " - "this node has already received it!\n", - dlm->name, fr->node_idx, fr->dead_node); - dlm_print_reco_node_status(dlm); - BUG(); - } - dlm->reco.state |= DLM_RECO_STATE_FINALIZE; - spin_unlock(&dlm->spinlock); - break; - case 2: - if (!(dlm->reco.state & DLM_RECO_STATE_FINALIZE)) { - mlog(ML_ERROR, "%s: received finalize2 from " - "new master %u for dead node %u, but " - "this node did not have finalize1!\n", - dlm->name, fr->node_idx, fr->dead_node); - dlm_print_reco_node_status(dlm); - BUG(); - } - dlm->reco.state &= ~DLM_RECO_STATE_FINALIZE; - spin_unlock(&dlm->spinlock); - dlm_reset_recovery(dlm); - dlm_kick_recovery_thread(dlm); - break; - default: - BUG(); - } + dlm_finish_local_lockres_recovery(dlm, fr->dead_node, fr->node_idx); - mlog(0, "%s: recovery done, reco master was %u, dead now %u, master now %u\n", - dlm->name, fr->node_idx, dlm->reco.dead_node, dlm->reco.new_master); + spin_unlock(&dlm->spinlock); + dlm_reset_recovery(dlm); + + dlm_kick_recovery_thread(dlm); dlm_put(dlm); return 0; } diff --git a/trunk/fs/ocfs2/dlm/dlmthread.c b/trunk/fs/ocfs2/dlm/dlmthread.c index 0c822f3ffb05..5be9d14f12cb 100644 --- a/trunk/fs/ocfs2/dlm/dlmthread.c +++ b/trunk/fs/ocfs2/dlm/dlmthread.c @@ -39,7 +39,6 @@ #include #include #include -#include #include "cluster/heartbeat.h" @@ -54,8 +53,6 @@ #include "cluster/masklog.h" static int dlm_thread(void *data); -static void dlm_purge_lockres_now(struct dlm_ctxt *dlm, - struct dlm_lock_resource *lockres); static void dlm_flush_asts(struct dlm_ctxt *dlm); @@ -83,7 +80,7 @@ void __dlm_wait_on_lockres_flags(struct dlm_lock_resource *res, int flags) } -int __dlm_lockres_unused(struct dlm_lock_resource *res) +static int __dlm_lockres_unused(struct dlm_lock_resource *res) { if (list_empty(&res->granted) && list_empty(&res->converting) && @@ -106,20 +103,6 @@ void __dlm_lockres_calc_usage(struct dlm_ctxt *dlm, assert_spin_locked(&res->spinlock); if (__dlm_lockres_unused(res)){ - /* For now, just keep any resource we master */ - if (res->owner == dlm->node_num) - { - if (!list_empty(&res->purge)) { - mlog(0, "we master %s:%.*s, but it is on " - "the purge list. Removing\n", - dlm->name, res->lockname.len, - res->lockname.name); - list_del_init(&res->purge); - dlm->purge_count--; - } - return; - } - if (list_empty(&res->purge)) { mlog(0, "putting lockres %.*s from purge list\n", res->lockname.len, res->lockname.name); @@ -127,23 +110,10 @@ void __dlm_lockres_calc_usage(struct dlm_ctxt *dlm, res->last_used = jiffies; list_add_tail(&res->purge, &dlm->purge_list); dlm->purge_count++; - - /* if this node is not the owner, there is - * no way to keep track of who the owner could be. - * unhash it to avoid serious problems. */ - if (res->owner != dlm->node_num) { - mlog(0, "%s:%.*s: doing immediate " - "purge of lockres owned by %u\n", - dlm->name, res->lockname.len, - res->lockname.name, res->owner); - - dlm_purge_lockres_now(dlm, res); - } } } else if (!list_empty(&res->purge)) { - mlog(0, "removing lockres %.*s from purge list, " - "owner=%u\n", res->lockname.len, res->lockname.name, - res->owner); + mlog(0, "removing lockres %.*s from purge list\n", + res->lockname.len, res->lockname.name); list_del_init(&res->purge); dlm->purge_count--; @@ -195,7 +165,6 @@ void dlm_purge_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *lockres) } else if (ret < 0) { mlog(ML_NOTICE, "lockres %.*s: migrate failed, retrying\n", lockres->lockname.len, lockres->lockname.name); - msleep(100); goto again; } @@ -209,24 +178,6 @@ void dlm_purge_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *lockres) __dlm_unhash_lockres(lockres); } -/* make an unused lockres go away immediately. - * as soon as the dlm spinlock is dropped, this lockres - * will not be found. kfree still happens on last put. */ -static void dlm_purge_lockres_now(struct dlm_ctxt *dlm, - struct dlm_lock_resource *lockres) -{ - assert_spin_locked(&dlm->spinlock); - assert_spin_locked(&lockres->spinlock); - - BUG_ON(!__dlm_lockres_unused(lockres)); - - if (!list_empty(&lockres->purge)) { - list_del_init(&lockres->purge); - dlm->purge_count--; - } - __dlm_unhash_lockres(lockres); -} - static void dlm_run_purge_list(struct dlm_ctxt *dlm, int purge_now) { @@ -367,7 +318,8 @@ static void dlm_shuffle_lists(struct dlm_ctxt *dlm, target->ml.type = target->ml.convert_type; target->ml.convert_type = LKM_IVMODE; - list_move_tail(&target->list, &res->granted); + list_del_init(&target->list); + list_add_tail(&target->list, &res->granted); BUG_ON(!target->lksb); target->lksb->status = DLM_NORMAL; @@ -428,7 +380,8 @@ static void dlm_shuffle_lists(struct dlm_ctxt *dlm, target->ml.type, target->ml.node); // target->ml.type is already correct - list_move_tail(&target->list, &res->granted); + list_del_init(&target->list); + list_add_tail(&target->list, &res->granted); BUG_ON(!target->lksb); target->lksb->status = DLM_NORMAL; @@ -469,8 +422,6 @@ void __dlm_dirty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res) /* don't shuffle secondary queues */ if ((res->owner == dlm->node_num) && !(res->state & DLM_LOCK_RES_DIRTY)) { - /* ref for dirty_list */ - dlm_lockres_get(res); list_add_tail(&res->dirty, &dlm->dirty_list); res->state |= DLM_LOCK_RES_DIRTY; } @@ -655,8 +606,6 @@ static int dlm_thread(void *data) list_del_init(&res->dirty); spin_unlock(&res->spinlock); spin_unlock(&dlm->spinlock); - /* Drop dirty_list ref */ - dlm_lockres_put(res); /* lockres can be re-dirtied/re-added to the * dirty_list in this gap, but that is ok */ @@ -693,9 +642,8 @@ static int dlm_thread(void *data) * spinlock and do NOT have the dlm lock. * safe to reserve/queue asts and run the lists. */ - mlog(0, "calling dlm_shuffle_lists with dlm=%s, " - "res=%.*s\n", dlm->name, - res->lockname.len, res->lockname.name); + mlog(0, "calling dlm_shuffle_lists with dlm=%p, " + "res=%p\n", dlm, res); /* called while holding lockres lock */ dlm_shuffle_lists(dlm, res); @@ -709,8 +657,6 @@ static int dlm_thread(void *data) /* if the lock was in-progress, stick * it on the back of the list */ if (delay) { - /* ref for dirty_list */ - dlm_lockres_get(res); spin_lock(&res->spinlock); list_add_tail(&res->dirty, &dlm->dirty_list); res->state |= DLM_LOCK_RES_DIRTY; @@ -731,7 +677,7 @@ static int dlm_thread(void *data) /* yield and continue right away if there is more work to do */ if (!n) { - cond_resched(); + yield(); continue; } diff --git a/trunk/fs/ocfs2/dlm/dlmunlock.c b/trunk/fs/ocfs2/dlm/dlmunlock.c index b0c3134f4f70..7b1a27542674 100644 --- a/trunk/fs/ocfs2/dlm/dlmunlock.c +++ b/trunk/fs/ocfs2/dlm/dlmunlock.c @@ -271,7 +271,8 @@ void dlm_commit_pending_unlock(struct dlm_lock_resource *res, void dlm_commit_pending_cancel(struct dlm_lock_resource *res, struct dlm_lock *lock) { - list_move_tail(&lock->list, &res->granted); + list_del_init(&lock->list); + list_add_tail(&lock->list, &res->granted); lock->ml.convert_type = LKM_IVMODE; } @@ -318,16 +319,6 @@ static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm, mlog_entry("%.*s\n", res->lockname.len, res->lockname.name); - if (owner == dlm->node_num) { - /* ended up trying to contact ourself. this means - * that the lockres had been remote but became local - * via a migration. just retry it, now as local */ - mlog(0, "%s:%.*s: this node became the master due to a " - "migration, re-evaluate now\n", dlm->name, - res->lockname.len, res->lockname.name); - return DLM_FORWARD; - } - memset(&unlock, 0, sizeof(unlock)); unlock.node_idx = dlm->node_num; unlock.flags = cpu_to_be32(flags); diff --git a/trunk/fs/ocfs2/dlm/userdlm.c b/trunk/fs/ocfs2/dlm/userdlm.c index e641b084b343..74ca4e5f9765 100644 --- a/trunk/fs/ocfs2/dlm/userdlm.c +++ b/trunk/fs/ocfs2/dlm/userdlm.c @@ -672,7 +672,7 @@ struct dlm_ctxt *user_dlm_register_context(struct qstr *name) u32 dlm_key; char *domain; - domain = kmalloc(name->len + 1, GFP_NOFS); + domain = kmalloc(name->len + 1, GFP_KERNEL); if (!domain) { mlog_errno(-ENOMEM); return ERR_PTR(-ENOMEM); diff --git a/trunk/fs/ocfs2/dlmglue.c b/trunk/fs/ocfs2/dlmglue.c index 762eb1fbb34d..64cd52860c87 100644 --- a/trunk/fs/ocfs2/dlmglue.c +++ b/trunk/fs/ocfs2/dlmglue.c @@ -242,7 +242,7 @@ static void ocfs2_build_lock_name(enum ocfs2_lock_type type, mlog_exit_void(); } -static DEFINE_SPINLOCK(ocfs2_dlm_tracking_lock); +static spinlock_t ocfs2_dlm_tracking_lock = SPIN_LOCK_UNLOCKED; static void ocfs2_add_lockres_tracking(struct ocfs2_lock_res *res, struct ocfs2_dlm_debug *dlm_debug) @@ -2071,7 +2071,8 @@ int ocfs2_dlm_init(struct ocfs2_super *osb) } /* launch vote thread */ - osb->vote_task = kthread_run(ocfs2_vote_thread, osb, "ocfs2vote"); + osb->vote_task = kthread_run(ocfs2_vote_thread, osb, "ocfs2vote-%d", + osb->osb_id); if (IS_ERR(osb->vote_task)) { status = PTR_ERR(osb->vote_task); osb->vote_task = NULL; diff --git a/trunk/fs/ocfs2/extent_map.c b/trunk/fs/ocfs2/extent_map.c index fcd4475d1f89..1a5c69071df6 100644 --- a/trunk/fs/ocfs2/extent_map.c +++ b/trunk/fs/ocfs2/extent_map.c @@ -298,7 +298,7 @@ static int ocfs2_extent_map_find_leaf(struct inode *inode, ret = ocfs2_extent_map_insert(inode, rec, le16_to_cpu(el->l_tree_depth)); - if (ret && (ret != -EEXIST)) { + if (ret) { mlog_errno(ret); goto out_free; } @@ -427,11 +427,6 @@ static int ocfs2_extent_map_insert_entry(struct ocfs2_extent_map *em, /* * Simple rule: on any return code other than -EAGAIN, anything left * in the insert_context will be freed. - * - * Simple rule #2: A return code of -EEXIST from this function or - * its calls to ocfs2_extent_map_insert_entry() signifies that another - * thread beat us to the insert. It is not an actual error, but it - * tells the caller we have no more work to do. */ static int ocfs2_extent_map_try_insert(struct inode *inode, struct ocfs2_extent_rec *rec, @@ -453,32 +448,22 @@ static int ocfs2_extent_map_try_insert(struct inode *inode, goto out_unlock; } - /* Since insert_entry failed, the map MUST have old_ent */ old_ent = ocfs2_extent_map_lookup(em, le32_to_cpu(rec->e_cpos), - le32_to_cpu(rec->e_clusters), - NULL, NULL); + le32_to_cpu(rec->e_clusters), NULL, + NULL); BUG_ON(!old_ent); - if (old_ent->e_tree_depth < tree_depth) { - /* Another thread beat us to the lower tree_depth */ - ret = -EEXIST; + ret = -EEXIST; + if (old_ent->e_tree_depth < tree_depth) goto out_unlock; - } if (old_ent->e_tree_depth == tree_depth) { - /* - * Another thread beat us to this tree_depth. - * Let's make sure we agree with that thread (the - * extent_rec should be identical). - */ if (!memcmp(rec, &old_ent->e_rec, sizeof(struct ocfs2_extent_rec))) ret = 0; - else - /* FIXME: Should this be ESRCH/EBADR??? */ - ret = -EEXIST; + /* FIXME: Should this be ESRCH/EBADR??? */ goto out_unlock; } @@ -614,7 +599,7 @@ static int ocfs2_extent_map_insert(struct inode *inode, tree_depth, &ctxt); } while (ret == -EAGAIN); - if ((ret < 0) && (ret != -EEXIST)) + if (ret < 0) mlog_errno(ret); if (ctxt.left_ent) diff --git a/trunk/fs/ocfs2/inode.h b/trunk/fs/ocfs2/inode.h index 35140f6cf840..84c507961287 100644 --- a/trunk/fs/ocfs2/inode.h +++ b/trunk/fs/ocfs2/inode.h @@ -114,7 +114,7 @@ static inline struct ocfs2_inode_info *OCFS2_I(struct inode *inode) extern kmem_cache_t *ocfs2_inode_cache; -extern const struct address_space_operations ocfs2_aops; +extern struct address_space_operations ocfs2_aops; struct buffer_head *ocfs2_bread(struct inode *inode, int block, int *err, int reada); diff --git a/trunk/fs/ocfs2/journal.c b/trunk/fs/ocfs2/journal.c index f92bf1dd379a..eebc3cfa6be8 100644 --- a/trunk/fs/ocfs2/journal.c +++ b/trunk/fs/ocfs2/journal.c @@ -49,7 +49,7 @@ #include "buffer_head_io.h" -DEFINE_SPINLOCK(trans_inc_lock); +spinlock_t trans_inc_lock = SPIN_LOCK_UNLOCKED; static int ocfs2_force_read_journal(struct inode *inode); static int ocfs2_recover_node(struct ocfs2_super *osb, @@ -222,7 +222,8 @@ void ocfs2_handle_add_inode(struct ocfs2_journal_handle *handle, BUG_ON(!list_empty(&OCFS2_I(inode)->ip_handle_list)); OCFS2_I(inode)->ip_handle = handle; - list_move_tail(&(OCFS2_I(inode)->ip_handle_list), &(handle->inode_list)); + list_del(&(OCFS2_I(inode)->ip_handle_list)); + list_add_tail(&(OCFS2_I(inode)->ip_handle_list), &(handle->inode_list)); } static void ocfs2_handle_unlock_inodes(struct ocfs2_journal_handle *handle) @@ -784,7 +785,8 @@ int ocfs2_journal_load(struct ocfs2_journal *journal) } /* Launch the commit thread */ - osb->commit_task = kthread_run(ocfs2_commit_thread, osb, "ocfs2cmt"); + osb->commit_task = kthread_run(ocfs2_commit_thread, osb, "ocfs2cmt-%d", + osb->osb_id); if (IS_ERR(osb->commit_task)) { status = PTR_ERR(osb->commit_task); osb->commit_task = NULL; @@ -1117,7 +1119,7 @@ void ocfs2_recovery_thread(struct ocfs2_super *osb, int node_num) goto out; osb->recovery_thread_task = kthread_run(__ocfs2_recovery_thread, osb, - "ocfs2rec"); + "ocfs2rec-%d", osb->osb_id); if (IS_ERR(osb->recovery_thread_task)) { mlog_errno((int)PTR_ERR(osb->recovery_thread_task)); osb->recovery_thread_task = NULL; diff --git a/trunk/fs/ocfs2/mmap.c b/trunk/fs/ocfs2/mmap.c index 83934e33e5b0..843cf9ddefe8 100644 --- a/trunk/fs/ocfs2/mmap.c +++ b/trunk/fs/ocfs2/mmap.c @@ -46,12 +46,12 @@ static struct page *ocfs2_nopage(struct vm_area_struct * area, unsigned long address, int *type) { + struct inode *inode = area->vm_file->f_dentry->d_inode; struct page *page = NOPAGE_SIGBUS; sigset_t blocked, oldset; int ret; - mlog_entry("(area=%p, address=%lu, type=%p)\n", area, address, - type); + mlog_entry("(inode %lu, address %lu)\n", inode->i_ino, address); /* The best way to deal with signals in this path is * to block them upfront, rather than allowing the diff --git a/trunk/fs/ocfs2/ocfs2.h b/trunk/fs/ocfs2/ocfs2.h index cd4a6f253d13..da1093039c01 100644 --- a/trunk/fs/ocfs2/ocfs2.h +++ b/trunk/fs/ocfs2/ocfs2.h @@ -184,6 +184,7 @@ struct ocfs2_journal; struct ocfs2_journal_handle; struct ocfs2_super { + u32 osb_id; /* id used by the proc interface */ struct task_struct *commit_task; struct super_block *sb; struct inode *root_inode; @@ -221,11 +222,13 @@ struct ocfs2_super unsigned long s_mount_opt; u16 max_slots; + u16 num_nodes; s16 node_num; s16 slot_num; int s_sectsize_bits; int s_clustersize; int s_clustersize_bits; + struct proc_dir_entry *proc_sub_dir; /* points to /proc/fs/ocfs2/ */ atomic_t vol_state; struct mutex recovery_lock; @@ -291,6 +294,7 @@ struct ocfs2_super }; #define OCFS2_SB(sb) ((struct ocfs2_super *)(sb)->s_fs_info) +#define OCFS2_MAX_OSB_ID 65536 static inline int ocfs2_should_order_data(struct inode *inode) { diff --git a/trunk/fs/ocfs2/slot_map.c b/trunk/fs/ocfs2/slot_map.c index aa6f5aadedc4..871627961d6d 100644 --- a/trunk/fs/ocfs2/slot_map.c +++ b/trunk/fs/ocfs2/slot_map.c @@ -264,7 +264,7 @@ int ocfs2_find_slot(struct ocfs2_super *osb) osb->slot_num = slot; spin_unlock(&si->si_lock); - mlog(0, "taking node slot %d\n", osb->slot_num); + mlog(ML_NOTICE, "taking node slot %d\n", osb->slot_num); status = ocfs2_update_disk_slots(osb, si); if (status < 0) diff --git a/trunk/fs/ocfs2/super.c b/trunk/fs/ocfs2/super.c index 382706a67ffd..cdf73393f094 100644 --- a/trunk/fs/ocfs2/super.c +++ b/trunk/fs/ocfs2/super.c @@ -68,6 +68,13 @@ #include "buffer_head_io.h" +/* + * Globals + */ +static spinlock_t ocfs2_globals_lock = SPIN_LOCK_UNLOCKED; + +static u32 osb_id; /* Keeps track of next available OSB Id */ + static kmem_cache_t *ocfs2_inode_cachep = NULL; kmem_cache_t *ocfs2_lock_cache = NULL; @@ -635,9 +642,10 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent) ocfs2_complete_mount_recovery(osb); - printk(KERN_INFO "ocfs2: Mounting device (%s) on (node %d, slot %d) " - "with %s data mode.\n", - osb->dev_str, osb->node_num, osb->slot_num, + printk("ocfs2: Mounting device (%u,%u) on (node %d, slot %d) with %s " + "data mode.\n", + MAJOR(sb->s_dev), MINOR(sb->s_dev), osb->node_num, + osb->slot_num, osb->s_mount_opt & OCFS2_MOUNT_DATA_WRITEBACK ? "writeback" : "ordered"); @@ -792,6 +800,10 @@ static int __init ocfs2_init(void) goto leave; } + spin_lock(&ocfs2_globals_lock); + osb_id = 0; + spin_unlock(&ocfs2_globals_lock); + ocfs2_debugfs_root = debugfs_create_dir("ocfs2", NULL); if (!ocfs2_debugfs_root) { status = -EFAULT; @@ -1008,7 +1020,7 @@ static int ocfs2_fill_local_node_info(struct ocfs2_super *osb) goto bail; } - mlog(0, "I am node %d\n", osb->node_num); + mlog(ML_NOTICE, "I am node %d\n", osb->node_num); status = 0; bail: @@ -1179,8 +1191,8 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) atomic_set(&osb->vol_state, VOLUME_DISMOUNTED); - printk(KERN_INFO "ocfs2: Unmounting device (%s) on (node %d)\n", - osb->dev_str, osb->node_num); + printk("ocfs2: Unmounting device (%u,%u) on (node %d)\n", + MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev), osb->node_num); ocfs2_delete_osb(osb); kfree(osb); @@ -1200,6 +1212,8 @@ static int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uu if (osb->uuid_str == NULL) return -ENOMEM; + memcpy(osb->uuid, uuid, OCFS2_VOL_UUID_LEN); + for (i = 0, ptr = osb->uuid_str; i < OCFS2_VOL_UUID_LEN; i++) { /* print with null */ ret = snprintf(ptr, 3, "%02X", uuid[i]); @@ -1297,6 +1311,13 @@ static int ocfs2_initialize_super(struct super_block *sb, goto bail; } + osb->uuid = kmalloc(OCFS2_VOL_UUID_LEN, GFP_KERNEL); + if (!osb->uuid) { + mlog(ML_ERROR, "unable to alloc uuid\n"); + status = -ENOMEM; + goto bail; + } + di = (struct ocfs2_dinode *)bh->b_data; osb->max_slots = le16_to_cpu(di->id2.i_super.s_max_slots); @@ -1306,7 +1327,7 @@ static int ocfs2_initialize_super(struct super_block *sb, status = -EINVAL; goto bail; } - mlog(0, "max_slots for this device: %u\n", osb->max_slots); + mlog(ML_NOTICE, "max_slots for this device: %u\n", osb->max_slots); init_waitqueue_head(&osb->osb_wipe_event); osb->osb_orphan_wipes = kcalloc(osb->max_slots, @@ -1397,7 +1418,7 @@ static int ocfs2_initialize_super(struct super_block *sb, goto bail; } - memcpy(&uuid_net_key, di->id2.i_super.s_uuid, sizeof(uuid_net_key)); + memcpy(&uuid_net_key, &osb->uuid[i], sizeof(osb->net_key)); osb->net_key = le32_to_cpu(uuid_net_key); strncpy(osb->vol_label, di->id2.i_super.s_label, 63); @@ -1463,6 +1484,18 @@ static int ocfs2_initialize_super(struct super_block *sb, goto bail; } + /* Link this osb onto the global linked list of all osb structures. */ + /* The Global Link List is mainted for the whole driver . */ + spin_lock(&ocfs2_globals_lock); + osb->osb_id = osb_id; + if (osb_id < OCFS2_MAX_OSB_ID) + osb_id++; + else { + mlog(ML_ERROR, "Too many volumes mounted\n"); + status = -ENOMEM; + } + spin_unlock(&ocfs2_globals_lock); + bail: mlog_exit(status); return status; diff --git a/trunk/fs/ocfs2/symlink.c b/trunk/fs/ocfs2/symlink.c index c0f68aa6c175..0c8a1294ec96 100644 --- a/trunk/fs/ocfs2/symlink.c +++ b/trunk/fs/ocfs2/symlink.c @@ -154,7 +154,7 @@ static void *ocfs2_follow_link(struct dentry *dentry, } status = vfs_follow_link(nd, link); - if (status && status != -ENOENT) + if (status) mlog_errno(status); bail: if (page) { diff --git a/trunk/fs/ocfs2/vote.c b/trunk/fs/ocfs2/vote.c index cf70fe2075b8..ee42765a8553 100644 --- a/trunk/fs/ocfs2/vote.c +++ b/trunk/fs/ocfs2/vote.c @@ -988,7 +988,9 @@ int ocfs2_request_mount_vote(struct ocfs2_super *osb) } bail: - kfree(request); + if (request) + kfree(request); + return status; } @@ -1019,7 +1021,9 @@ int ocfs2_request_umount_vote(struct ocfs2_super *osb) } bail: - kfree(request); + if (request) + kfree(request); + return status; } diff --git a/trunk/fs/openpromfs/inode.c b/trunk/fs/openpromfs/inode.c index 93a56bd4a2b7..efc7c91128af 100644 --- a/trunk/fs/openpromfs/inode.c +++ b/trunk/fs/openpromfs/inode.c @@ -1,4 +1,5 @@ -/* inode.c: /proc/openprom handling routines +/* $Id: inode.c,v 1.15 2001/11/12 09:43:39 davem Exp $ + * openpromfs.c: /proc/openprom handling routines * * Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) @@ -11,245 +12,762 @@ #include #include #include -#include +#include #include #include -#include #include -static DEFINE_MUTEX(op_mutex); - -#define OPENPROM_ROOT_INO 0 - -enum op_inode_type { - op_inode_node, - op_inode_prop, -}; - -union op_inode_data { - struct device_node *node; - struct property *prop; -}; - -struct op_inode_info { - struct inode vfs_inode; - enum op_inode_type type; - union op_inode_data u; -}; +#define ALIASES_NNODES 64 + +typedef struct { + u16 parent; + u16 next; + u16 child; + u16 first_prop; + u32 node; +} openpromfs_node; + +typedef struct { +#define OPP_STRING 0x10 +#define OPP_STRINGLIST 0x20 +#define OPP_BINARY 0x40 +#define OPP_HEXSTRING 0x80 +#define OPP_DIRTY 0x01 +#define OPP_QUOTED 0x02 +#define OPP_NOTQUOTED 0x04 +#define OPP_ASCIIZ 0x08 + u32 flag; + u32 alloclen; + u32 len; + char *value; + char name[8]; +} openprom_property; + +static openpromfs_node *nodes; +static int alloced; +static u16 last_node; +static u16 first_prop; +static u16 options = 0xffff; +static u16 aliases = 0xffff; +static int aliases_nodes; +static char *alias_names [ALIASES_NNODES]; + +#define OPENPROM_ROOT_INO 16 +#define OPENPROM_FIRST_INO OPENPROM_ROOT_INO +#define NODE(ino) nodes[ino - OPENPROM_FIRST_INO] +#define NODE2INO(node) (node + OPENPROM_FIRST_INO) +#define NODEP2INO(no) (no + OPENPROM_FIRST_INO + last_node) + +static int openpromfs_create (struct inode *, struct dentry *, int, struct nameidata *); +static int openpromfs_readdir(struct file *, void *, filldir_t); +static struct dentry *openpromfs_lookup(struct inode *, struct dentry *dentry, struct nameidata *nd); +static int openpromfs_unlink (struct inode *, struct dentry *dentry); -static inline struct op_inode_info *OP_I(struct inode *inode) +static inline u16 ptr_nod(void *p) { - return container_of(inode, struct op_inode_info, vfs_inode); + return (long)p & 0xFFFF; } -static int is_string(unsigned char *p, int len) +static ssize_t nodenum_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) { - int i; - - for (i = 0; i < len; i++) { - unsigned char val = p[i]; - - if ((i && !val) || - (val >= ' ' && val <= '~')) - continue; - + struct inode *inode = file->f_dentry->d_inode; + char buffer[10]; + + if (count < 0 || !inode->u.generic_ip) + return -EINVAL; + sprintf (buffer, "%8.8lx\n", (long)inode->u.generic_ip); + if (file->f_pos >= 9) return 0; - } - - return 1; + if (count > 9 - file->f_pos) + count = 9 - file->f_pos; + if (copy_to_user(buf, buffer + file->f_pos, count)) + return -EFAULT; + *ppos += count; + return count; } -static int property_show(struct seq_file *f, void *v) +static ssize_t property_read(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) { - struct property *prop = f->private; - void *pval; - int len; + struct inode *inode = filp->f_dentry->d_inode; + int i, j, k; + u32 node; + char *p, *s; + u32 *q; + openprom_property *op; + char buffer[64]; + + if (!filp->private_data) { + node = nodes[ptr_nod(inode->u.generic_ip)].node; + i = ((u32)(long)inode->u.generic_ip) >> 16; + if (ptr_nod(inode->u.generic_ip) == aliases) { + if (i >= aliases_nodes) + p = NULL; + else + p = alias_names [i]; + } else + for (p = prom_firstprop (node, buffer); + i && p && *p; + p = prom_nextprop (node, p, buffer), i--) + /* nothing */ ; + if (!p || !*p) + return -EIO; + i = prom_getproplen (node, p); + if (i < 0) { + if (ptr_nod(inode->u.generic_ip) == aliases) + i = 0; + else + return -EIO; + } + k = i; + if (i < 64) i = 64; + filp->private_data = kmalloc (sizeof (openprom_property) + + (j = strlen (p)) + 2 * i, + GFP_KERNEL); + if (!filp->private_data) + return -ENOMEM; + op = filp->private_data; + op->flag = 0; + op->alloclen = 2 * i; + strcpy (op->name, p); + op->value = (char *)(((unsigned long)(op->name + j + 4)) & ~3); + op->len = k; + if (k && prom_getproperty (node, p, op->value, i) < 0) + return -EIO; + op->value [k] = 0; + if (k) { + for (s = NULL, p = op->value; p < op->value + k; p++) { + if ((*p >= ' ' && *p <= '~') || *p == '\n') { + op->flag |= OPP_STRING; + s = p; + continue; + } + if (p > op->value && !*p && s == p - 1) { + if (p < op->value + k - 1) + op->flag |= OPP_STRINGLIST; + else + op->flag |= OPP_ASCIIZ; + continue; + } + if (k == 1 && !*p) { + op->flag |= (OPP_STRING|OPP_ASCIIZ); + break; + } + op->flag &= ~(OPP_STRING|OPP_STRINGLIST); + if (k & 3) + op->flag |= OPP_HEXSTRING; + else + op->flag |= OPP_BINARY; + break; + } + if (op->flag & OPP_STRINGLIST) + op->flag &= ~(OPP_STRING); + if (op->flag & OPP_ASCIIZ) + op->len--; + } + } else + op = filp->private_data; + if (!count || !(op->len || (op->flag & OPP_ASCIIZ))) + return 0; + if (*ppos >= 0xffffff || count >= 0xffffff) + return -EINVAL; + if (op->flag & OPP_STRINGLIST) { + for (k = 0, p = op->value; p < op->value + op->len; p++) + if (!*p) + k++; + i = op->len + 4 * k + 3; + } else if (op->flag & OPP_STRING) { + i = op->len + 3; + } else if (op->flag & OPP_BINARY) { + i = (op->len * 9) >> 2; + } else { + i = (op->len << 1) + 1; + } + k = *ppos; + if (k >= i) return 0; + if (count > i - k) count = i - k; + if (op->flag & OPP_STRING) { + if (!k) { + if (put_user('\'', buf)) + return -EFAULT; + k++; + count--; + } - len = prop->length; - pval = prop->value; + if (k + count >= i - 2) + j = i - 2 - k; + else + j = count; + + if (j >= 0) { + if (copy_to_user(buf + k - *ppos, + op->value + k - 1, j)) + return -EFAULT; + count -= j; + k += j; + } - if (is_string(pval, len)) { - while (len > 0) { - int n = strlen(pval); + if (count) { + if (put_user('\'', &buf [k++ - *ppos])) + return -EFAULT; + } + if (count > 1) { + if (put_user('\n', &buf [k++ - *ppos])) + return -EFAULT; + } + } else if (op->flag & OPP_STRINGLIST) { + char *tmp; + + tmp = kmalloc (i, GFP_KERNEL); + if (!tmp) + return -ENOMEM; + + s = tmp; + *s++ = '\''; + for (p = op->value; p < op->value + op->len; p++) { + if (!*p) { + strcpy(s, "' + '"); + s += 5; + continue; + } + *s++ = *p; + } + strcpy(s, "'\n"); + + if (copy_to_user(buf, tmp + k, count)) + return -EFAULT; + + kfree(tmp); + k += count; + + } else if (op->flag & OPP_BINARY) { + char buffer[10]; + u32 *first, *last; + int first_off, last_cnt; + + first = ((u32 *)op->value) + k / 9; + first_off = k % 9; + last = ((u32 *)op->value) + (k + count - 1) / 9; + last_cnt = (k + count) % 9; + if (!last_cnt) last_cnt = 9; + + if (first == last) { + sprintf (buffer, "%08x.", *first); + if (copy_to_user(buf, buffer + first_off, + last_cnt - first_off)) + return -EFAULT; + buf += last_cnt - first_off; + } else { + for (q = first; q <= last; q++) { + sprintf (buffer, "%08x.", *q); + if (q == first) { + if (copy_to_user(buf, buffer + first_off, + 9 - first_off)) + return -EFAULT; + buf += 9 - first_off; + } else if (q == last) { + if (copy_to_user(buf, buffer, last_cnt)) + return -EFAULT; + buf += last_cnt; + } else { + if (copy_to_user(buf, buffer, 9)) + return -EFAULT; + buf += 9; + } + } + } - seq_printf(f, "%s", (char *) pval); + if (last == (u32 *)(op->value + op->len - 4) && last_cnt == 9) { + if (put_user('\n', (buf - 1))) + return -EFAULT; + } - /* Skip over the NULL byte too. */ - pval += n + 1; - len -= n + 1; + k += count; - if (len > 0) - seq_printf(f, " + "); - } - } else { - if (len & 3) { - while (len) { - len--; - if (len) - seq_printf(f, "%02x.", - *(unsigned char *) pval); - else - seq_printf(f, "%02x", - *(unsigned char *) pval); - pval++; - } - } else { - while (len >= 4) { - len -= 4; + } else if (op->flag & OPP_HEXSTRING) { + char buffer[3]; - if (len) - seq_printf(f, "%08x.", - *(unsigned int *) pval); - else - seq_printf(f, "%08x", - *(unsigned int *) pval); - pval += 4; - } + if ((k < i - 1) && (k & 1)) { + sprintf (buffer, "%02x", + (unsigned char) *(op->value + (k >> 1)) & 0xff); + if (put_user(buffer[1], &buf[k++ - *ppos])) + return -EFAULT; + count--; } - } - seq_printf(f, "\n"); - return 0; -} + for (; (count > 1) && (k < i - 1); k += 2) { + sprintf (buffer, "%02x", + (unsigned char) *(op->value + (k >> 1)) & 0xff); + if (copy_to_user(buf + k - *ppos, buffer, 2)) + return -EFAULT; + count -= 2; + } -static void *property_start(struct seq_file *f, loff_t *pos) -{ - if (*pos == 0) - return pos; - return NULL; -} + if (count && (k < i - 1)) { + sprintf (buffer, "%02x", + (unsigned char) *(op->value + (k >> 1)) & 0xff); + if (put_user(buffer[0], &buf[k++ - *ppos])) + return -EFAULT; + count--; + } -static void *property_next(struct seq_file *f, void *v, loff_t *pos) -{ - (*pos)++; - return NULL; + if (count) { + if (put_user('\n', &buf [k++ - *ppos])) + return -EFAULT; + } + } + count = k - *ppos; + *ppos = k; + return count; } -static void property_stop(struct seq_file *f, void *v) +static ssize_t property_write(struct file *filp, const char __user *buf, + size_t count, loff_t *ppos) { - /* Nothing to do */ + int i, j, k; + char *p; + u32 *q; + void *b; + openprom_property *op; + + if (*ppos >= 0xffffff || count >= 0xffffff) + return -EINVAL; + if (!filp->private_data) { + i = property_read (filp, NULL, 0, NULL); + if (i) + return i; + } + k = *ppos; + op = filp->private_data; + if (!(op->flag & OPP_STRING)) { + u32 *first, *last; + int first_off, last_cnt; + u32 mask, mask2; + char tmp [9]; + int forcelen = 0; + + j = k % 9; + for (i = 0; i < count; i++, j++) { + if (j == 9) j = 0; + if (!j) { + char ctmp; + if (get_user(ctmp, &buf[i])) + return -EFAULT; + if (ctmp != '.') { + if (ctmp != '\n') { + if (op->flag & OPP_BINARY) + return -EINVAL; + else + goto write_try_string; + } else { + count = i + 1; + forcelen = 1; + break; + } + } + } else { + char ctmp; + if (get_user(ctmp, &buf[i])) + return -EFAULT; + if (ctmp < '0' || + (ctmp > '9' && ctmp < 'A') || + (ctmp > 'F' && ctmp < 'a') || + ctmp > 'f') { + if (op->flag & OPP_BINARY) + return -EINVAL; + else + goto write_try_string; + } + } + } + op->flag |= OPP_BINARY; + tmp [8] = 0; + i = ((count + k + 8) / 9) << 2; + if (op->alloclen <= i) { + b = kmalloc (sizeof (openprom_property) + 2 * i, + GFP_KERNEL); + if (!b) + return -ENOMEM; + memcpy (b, filp->private_data, + sizeof (openprom_property) + + strlen (op->name) + op->alloclen); + memset (b + sizeof (openprom_property) + + strlen (op->name) + op->alloclen, + 0, 2 * i - op->alloclen); + op = b; + op->alloclen = 2*i; + b = filp->private_data; + filp->private_data = op; + kfree (b); + } + first = ((u32 *)op->value) + (k / 9); + first_off = k % 9; + last = (u32 *)(op->value + i); + last_cnt = (k + count) % 9; + if (first + 1 == last) { + memset (tmp, '0', 8); + if (copy_from_user(tmp + first_off, buf, + (count + first_off > 8) ? + 8 - first_off : count)) + return -EFAULT; + mask = 0xffffffff; + mask2 = 0xffffffff; + for (j = 0; j < first_off; j++) + mask >>= 1; + for (j = 8 - count - first_off; j > 0; j--) + mask2 <<= 1; + mask &= mask2; + if (mask) { + *first &= ~mask; + *first |= simple_strtoul (tmp, NULL, 16); + op->flag |= OPP_DIRTY; + } + } else { + op->flag |= OPP_DIRTY; + for (q = first; q < last; q++) { + if (q == first) { + if (first_off < 8) { + memset (tmp, '0', 8); + if (copy_from_user(tmp + first_off, + buf, + 8 - first_off)) + return -EFAULT; + mask = 0xffffffff; + for (j = 0; j < first_off; j++) + mask >>= 1; + *q &= ~mask; + *q |= simple_strtoul (tmp,NULL,16); + } + buf += 9; + } else if ((q == last - 1) && last_cnt + && (last_cnt < 8)) { + memset (tmp, '0', 8); + if (copy_from_user(tmp, buf, last_cnt)) + return -EFAULT; + mask = 0xffffffff; + for (j = 0; j < 8 - last_cnt; j++) + mask <<= 1; + *q &= ~mask; + *q |= simple_strtoul (tmp, NULL, 16); + buf += last_cnt; + } else { + char tchars[2 * sizeof(long) + 1]; + + if (copy_from_user(tchars, buf, sizeof(tchars) - 1)) + return -EFAULT; + tchars[sizeof(tchars) - 1] = '\0'; + *q = simple_strtoul (tchars, NULL, 16); + buf += 9; + } + } + } + if (!forcelen) { + if (op->len < i) + op->len = i; + } else + op->len = i; + *ppos += count; + } +write_try_string: + if (!(op->flag & OPP_BINARY)) { + if (!(op->flag & (OPP_QUOTED | OPP_NOTQUOTED))) { + char ctmp; + + /* No way, if somebody starts writing from the middle, + * we don't know whether he uses quotes around or not + */ + if (k > 0) + return -EINVAL; + if (get_user(ctmp, buf)) + return -EFAULT; + if (ctmp == '\'') { + op->flag |= OPP_QUOTED; + buf++; + count--; + (*ppos)++; + if (!count) { + op->flag |= OPP_STRING; + return 1; + } + } else + op->flag |= OPP_NOTQUOTED; + } + op->flag |= OPP_STRING; + if (op->alloclen <= count + *ppos) { + b = kmalloc (sizeof (openprom_property) + + 2 * (count + *ppos), GFP_KERNEL); + if (!b) + return -ENOMEM; + memcpy (b, filp->private_data, + sizeof (openprom_property) + + strlen (op->name) + op->alloclen); + memset (b + sizeof (openprom_property) + + strlen (op->name) + op->alloclen, + 0, 2*(count - *ppos) - op->alloclen); + op = b; + op->alloclen = 2*(count + *ppos); + b = filp->private_data; + filp->private_data = op; + kfree (b); + } + p = op->value + *ppos - ((op->flag & OPP_QUOTED) ? 1 : 0); + if (copy_from_user(p, buf, count)) + return -EFAULT; + op->flag |= OPP_DIRTY; + for (i = 0; i < count; i++, p++) + if (*p == '\n') { + *p = 0; + break; + } + if (i < count) { + op->len = p - op->value; + *ppos += i + 1; + if ((p > op->value) && (op->flag & OPP_QUOTED) + && (*(p - 1) == '\'')) + op->len--; + } else { + if (p - op->value > op->len) + op->len = p - op->value; + *ppos += count; + } + } + return *ppos - k; } -static struct seq_operations property_op = { - .start = property_start, - .next = property_next, - .stop = property_stop, - .show = property_show -}; - -static int property_open(struct inode *inode, struct file *file) +int property_release (struct inode *inode, struct file *filp) { - struct op_inode_info *oi = OP_I(inode); - int ret; - - BUG_ON(oi->type != op_inode_prop); - - ret = seq_open(file, &property_op); - if (!ret) { - struct seq_file *m = file->private_data; - m->private = oi->u.prop; + openprom_property *op = filp->private_data; + int error; + u32 node; + + if (!op) + return 0; + lock_kernel(); + node = nodes[ptr_nod(inode->u.generic_ip)].node; + if (ptr_nod(inode->u.generic_ip) == aliases) { + if ((op->flag & OPP_DIRTY) && (op->flag & OPP_STRING)) { + char *p = op->name; + int i = (op->value - op->name) - strlen (op->name) - 1; + op->value [op->len] = 0; + *(op->value - 1) = ' '; + if (i) { + for (p = op->value - i - 2; p >= op->name; p--) + p[i] = *p; + p = op->name + i; + } + memcpy (p - 8, "nvalias ", 8); + prom_feval (p - 8); + } + } else if (op->flag & OPP_DIRTY) { + if (op->flag & OPP_STRING) { + op->value [op->len] = 0; + error = prom_setprop (node, op->name, + op->value, op->len + 1); + if (error <= 0) + printk (KERN_WARNING "openpromfs: " + "Couldn't write property %s\n", + op->name); + } else if ((op->flag & OPP_BINARY) || !op->len) { + error = prom_setprop (node, op->name, + op->value, op->len); + if (error <= 0) + printk (KERN_WARNING "openpromfs: " + "Couldn't write property %s\n", + op->name); + } else { + printk (KERN_WARNING "openpromfs: " + "Unknown property type of %s\n", + op->name); + } } - return ret; + unlock_kernel(); + kfree (filp->private_data); + return 0; } static const struct file_operations openpromfs_prop_ops = { - .open = property_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, + .read = property_read, + .write = property_write, + .release = property_release, }; -static int openpromfs_readdir(struct file *, void *, filldir_t); +static const struct file_operations openpromfs_nodenum_ops = { + .read = nodenum_read, +}; static const struct file_operations openprom_operations = { .read = generic_read_dir, .readdir = openpromfs_readdir, }; -static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *); +static struct inode_operations openprom_alias_inode_operations = { + .create = openpromfs_create, + .lookup = openpromfs_lookup, + .unlink = openpromfs_unlink, +}; static struct inode_operations openprom_inode_operations = { .lookup = openpromfs_lookup, }; -static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) +static int lookup_children(u16 n, const char * name, int len) { - struct op_inode_info *ent_oi, *oi = OP_I(dir); - struct device_node *dp, *child; - struct property *prop; - enum op_inode_type ent_type; - union op_inode_data ent_data; + int ret; + u16 node; + for (; n != 0xffff; n = nodes[n].next) { + node = nodes[n].child; + if (node != 0xffff) { + char buffer[128]; + int i; + char *p; + + while (node != 0xffff) { + if (prom_getname (nodes[node].node, + buffer, 128) >= 0) { + i = strlen (buffer); + if ((len == i) + && !strncmp (buffer, name, len)) + return NODE2INO(node); + p = strchr (buffer, '@'); + if (p && (len == p - buffer) + && !strncmp (buffer, name, len)) + return NODE2INO(node); + } + node = nodes[node].next; + } + } else + continue; + ret = lookup_children (nodes[n].child, name, len); + if (ret) return ret; + } + return 0; +} + +static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd) +{ + int ino = 0; +#define OPFSL_DIR 0 +#define OPFSL_PROPERTY 1 +#define OPFSL_NODENUM 2 + int type = 0; + char buffer[128]; + char *p; const char *name; + u32 n; + u16 dirnode; + unsigned int len; + int i; struct inode *inode; - unsigned int ino; - int len; + char buffer2[64]; - BUG_ON(oi->type != op_inode_node); - - dp = oi->u.node; - + inode = NULL; name = dentry->d_name.name; len = dentry->d_name.len; - - mutex_lock(&op_mutex); - - child = dp->child; - while (child) { - int n = strlen(child->path_component_name); - - if (len == n && - !strncmp(child->path_component_name, name, len)) { - ent_type = op_inode_node; - ent_data.node = child; - ino = child->unique_id; - goto found; + lock_kernel(); + if (name [0] == '.' && len == 5 && !strncmp (name + 1, "node", 4)) { + ino = NODEP2INO(NODE(dir->i_ino).first_prop); + type = OPFSL_NODENUM; + } + if (!ino) { + u16 node = NODE(dir->i_ino).child; + while (node != 0xffff) { + if (prom_getname (nodes[node].node, buffer, 128) >= 0) { + i = strlen (buffer); + if (len == i && !strncmp (buffer, name, len)) { + ino = NODE2INO(node); + type = OPFSL_DIR; + break; + } + p = strchr (buffer, '@'); + if (p && (len == p - buffer) + && !strncmp (buffer, name, len)) { + ino = NODE2INO(node); + type = OPFSL_DIR; + break; + } + } + node = nodes[node].next; } - child = child->sibling; } - - prop = dp->properties; - while (prop) { - int n = strlen(prop->name); - - if (len == n && !strncmp(prop->name, name, len)) { - ent_type = op_inode_prop; - ent_data.prop = prop; - ino = prop->unique_id; - goto found; + n = NODE(dir->i_ino).node; + dirnode = dir->i_ino - OPENPROM_FIRST_INO; + if (!ino) { + int j = NODEP2INO(NODE(dir->i_ino).first_prop); + if (dirnode != aliases) { + for (p = prom_firstprop (n, buffer2); + p && *p; + p = prom_nextprop (n, p, buffer2)) { + j++; + if ((len == strlen (p)) + && !strncmp (p, name, len)) { + ino = j; + type = OPFSL_PROPERTY; + break; + } + } + } else { + int k; + for (k = 0; k < aliases_nodes; k++) { + j++; + if (alias_names [k] + && (len == strlen (alias_names [k])) + && !strncmp (alias_names [k], name, len)) { + ino = j; + type = OPFSL_PROPERTY; + break; + } + } } - - prop = prop->next; } - - mutex_unlock(&op_mutex); - return ERR_PTR(-ENOENT); - -found: - inode = iget(dir->i_sb, ino); - mutex_unlock(&op_mutex); + if (!ino) { + ino = lookup_children (NODE(dir->i_ino).child, name, len); + if (ino) + type = OPFSL_DIR; + else { + unlock_kernel(); + return ERR_PTR(-ENOENT); + } + } + inode = iget (dir->i_sb, ino); + unlock_kernel(); if (!inode) return ERR_PTR(-EINVAL); - ent_oi = OP_I(inode); - ent_oi->type = ent_type; - ent_oi->u = ent_data; - - switch (ent_type) { - case op_inode_node: + switch (type) { + case OPFSL_DIR: inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; - inode->i_op = &openprom_inode_operations; + if (ino == OPENPROM_FIRST_INO + aliases) { + inode->i_mode |= S_IWUSR; + inode->i_op = &openprom_alias_inode_operations; + } else + inode->i_op = &openprom_inode_operations; inode->i_fop = &openprom_operations; inode->i_nlink = 2; break; - case op_inode_prop: - if (!strcmp(dp->name, "options") && (len == 17) && - !strncmp (name, "security-password", 17)) + case OPFSL_NODENUM: + inode->i_mode = S_IFREG | S_IRUGO; + inode->i_fop = &openpromfs_nodenum_ops; + inode->i_nlink = 1; + inode->u.generic_ip = (void *)(long)(n); + break; + case OPFSL_PROPERTY: + if ((dirnode == options) && (len == 17) + && !strncmp (name, "security-password", 17)) inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR; - else + else { inode->i_mode = S_IFREG | S_IRUGO; + if (dirnode == options || dirnode == aliases) { + if (len != 4 || strncmp (name, "name", 4)) + inode->i_mode |= S_IWUSR; + } + } inode->i_fop = &openpromfs_prop_ops; inode->i_nlink = 1; - inode->i_size = ent_oi->u.prop->length; + if (inode->i_size < 0) + inode->i_size = 0; + inode->u.generic_ip = (void *)(long)(((u16)dirnode) | + (((u16)(ino - NODEP2INO(NODE(dir->i_ino).first_prop) - 1)) << 16)); break; } @@ -263,89 +781,237 @@ static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir) { struct inode *inode = filp->f_dentry->d_inode; - struct op_inode_info *oi = OP_I(inode); - struct device_node *dp = oi->u.node; - struct device_node *child; - struct property *prop; unsigned int ino; - int i; - - mutex_lock(&op_mutex); + u32 n; + int i, j; + char buffer[128]; + u16 node; + char *p; + char buffer2[64]; + + lock_kernel(); ino = inode->i_ino; i = filp->f_pos; switch (i) { case 0: - if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) - goto out; + if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) goto out; i++; filp->f_pos++; /* fall thru */ case 1: - if (filldir(dirent, "..", 2, i, - (dp->parent == NULL ? - OPENPROM_ROOT_INO : - dp->parent->unique_id), DT_DIR) < 0) + if (filldir(dirent, "..", 2, i, + (NODE(ino).parent == 0xffff) ? + OPENPROM_ROOT_INO : NODE2INO(NODE(ino).parent), DT_DIR) < 0) goto out; i++; filp->f_pos++; /* fall thru */ default: i -= 2; - - /* First, the children nodes as directories. */ - child = dp->child; - while (i && child) { - child = child->sibling; + node = NODE(ino).child; + while (i && node != 0xffff) { + node = nodes[node].next; i--; } - while (child) { - if (filldir(dirent, - child->path_component_name, - strlen(child->path_component_name), - filp->f_pos, child->unique_id, DT_DIR) < 0) + while (node != 0xffff) { + if (prom_getname (nodes[node].node, buffer, 128) < 0) + goto out; + if (filldir(dirent, buffer, strlen(buffer), + filp->f_pos, NODE2INO(node), DT_DIR) < 0) goto out; - filp->f_pos++; - child = child->sibling; + node = nodes[node].next; } - - /* Next, the properties as files. */ - prop = dp->properties; - while (i && prop) { - prop = prop->next; - i--; - } - while (prop) { - if (filldir(dirent, prop->name, strlen(prop->name), - filp->f_pos, prop->unique_id, DT_REG) < 0) + j = NODEP2INO(NODE(ino).first_prop); + if (!i) { + if (filldir(dirent, ".node", 5, filp->f_pos, j, DT_REG) < 0) goto out; - filp->f_pos++; - prop = prop->next; + } else + i--; + n = NODE(ino).node; + if (ino == OPENPROM_FIRST_INO + aliases) { + for (j++; i < aliases_nodes; i++, j++) { + if (alias_names [i]) { + if (filldir (dirent, alias_names [i], + strlen (alias_names [i]), + filp->f_pos, j, DT_REG) < 0) goto out; + filp->f_pos++; + } + } + } else { + for (p = prom_firstprop (n, buffer2); + p && *p; + p = prom_nextprop (n, p, buffer2)) { + j++; + if (i) i--; + else { + if (filldir(dirent, p, strlen(p), + filp->f_pos, j, DT_REG) < 0) + goto out; + filp->f_pos++; + } + } } } out: - mutex_unlock(&op_mutex); + unlock_kernel(); + return 0; +} + +static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +{ + char *p; + struct inode *inode; + + if (!dir) + return -ENOENT; + if (dentry->d_name.len > 256) + return -EINVAL; + p = kmalloc (dentry->d_name.len + 1, GFP_KERNEL); + if (!p) + return -ENOMEM; + strncpy (p, dentry->d_name.name, dentry->d_name.len); + p [dentry->d_name.len] = 0; + lock_kernel(); + if (aliases_nodes == ALIASES_NNODES) { + kfree(p); + unlock_kernel(); + return -EIO; + } + alias_names [aliases_nodes++] = p; + inode = iget (dir->i_sb, + NODEP2INO(NODE(dir->i_ino).first_prop) + aliases_nodes); + if (!inode) { + unlock_kernel(); + return -EINVAL; + } + inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR; + inode->i_fop = &openpromfs_prop_ops; + inode->i_nlink = 1; + if (inode->i_size < 0) inode->i_size = 0; + inode->u.generic_ip = (void *)(long)(((u16)aliases) | + (((u16)(aliases_nodes - 1)) << 16)); + unlock_kernel(); + d_instantiate(dentry, inode); return 0; } -static kmem_cache_t *op_inode_cachep; +static int openpromfs_unlink (struct inode *dir, struct dentry *dentry) +{ + unsigned int len; + char *p; + const char *name; + int i; + + name = dentry->d_name.name; + len = dentry->d_name.len; + lock_kernel(); + for (i = 0; i < aliases_nodes; i++) + if ((strlen (alias_names [i]) == len) + && !strncmp (name, alias_names[i], len)) { + char buffer[512]; + + p = alias_names [i]; + alias_names [i] = NULL; + kfree (p); + strcpy (buffer, "nvunalias "); + memcpy (buffer + 10, name, len); + buffer [10 + len] = 0; + prom_feval (buffer); + } + unlock_kernel(); + return 0; +} -static struct inode *openprom_alloc_inode(struct super_block *sb) +/* {{{ init section */ +static int __init check_space (u16 n) { - struct op_inode_info *oi; + unsigned long pages; - oi = kmem_cache_alloc(op_inode_cachep, SLAB_KERNEL); - if (!oi) - return NULL; + if ((1 << alloced) * PAGE_SIZE < (n + 2) * sizeof(openpromfs_node)) { + pages = __get_free_pages (GFP_KERNEL, alloced + 1); + if (!pages) + return -1; - return &oi->vfs_inode; + if (nodes) { + memcpy ((char *)pages, nodes, + (1 << alloced) * PAGE_SIZE); + free_pages ((unsigned long)nodes, alloced); + } + alloced++; + nodes = (openpromfs_node *)pages; + } + return 0; } -static void openprom_destroy_inode(struct inode *inode) +static u16 __init get_nodes (u16 parent, u32 node) { - kmem_cache_free(op_inode_cachep, OP_I(inode)); + char *p; + u16 n = last_node++, i; + char buffer[64]; + + if (check_space (n) < 0) + return 0xffff; + nodes[n].parent = parent; + nodes[n].node = node; + nodes[n].next = 0xffff; + nodes[n].child = 0xffff; + nodes[n].first_prop = first_prop++; + if (!parent) { + char buffer[8]; + int j; + + if ((j = prom_getproperty (node, "name", buffer, 8)) >= 0) { + buffer[j] = 0; + if (!strcmp (buffer, "options")) + options = n; + else if (!strcmp (buffer, "aliases")) + aliases = n; + } + } + if (n != aliases) + for (p = prom_firstprop (node, buffer); + p && p != (char *)-1 && *p; + p = prom_nextprop (node, p, buffer)) + first_prop++; + else { + char *q; + for (p = prom_firstprop (node, buffer); + p && p != (char *)-1 && *p; + p = prom_nextprop (node, p, buffer)) { + if (aliases_nodes == ALIASES_NNODES) + break; + for (i = 0; i < aliases_nodes; i++) + if (!strcmp (p, alias_names [i])) + break; + if (i < aliases_nodes) + continue; + q = kmalloc (strlen (p) + 1, GFP_KERNEL); + if (!q) + return 0xffff; + strcpy (q, p); + alias_names [aliases_nodes++] = q; + } + first_prop += ALIASES_NNODES; + } + node = prom_getchild (node); + if (node) { + parent = get_nodes (n, node); + if (parent == 0xffff) + return 0xffff; + nodes[n].child = parent; + while ((node = prom_getsibling (node)) != 0) { + i = get_nodes (n, node); + if (i == 0xffff) + return 0xffff; + nodes[parent].next = i; + parent = i; + } + } + return n; } static void openprom_read_inode(struct inode * inode) @@ -365,8 +1031,6 @@ static int openprom_remount(struct super_block *sb, int *flags, char *data) } static struct super_operations openprom_sops = { - .alloc_inode = openprom_alloc_inode, - .destroy_inode = openprom_destroy_inode, .read_inode = openprom_read_inode, .statfs = simple_statfs, .remount_fs = openprom_remount, @@ -374,8 +1038,7 @@ static struct super_operations openprom_sops = { static int openprom_fill_super(struct super_block *s, void *data, int silent) { - struct inode *root_inode; - struct op_inode_info *oi; + struct inode * root_inode; s->s_flags |= MS_NOATIME; s->s_blocksize = 1024; @@ -386,11 +1049,6 @@ static int openprom_fill_super(struct super_block *s, void *data, int silent) root_inode = iget(s, OPENPROM_ROOT_INO); if (!root_inode) goto out_no_root; - - oi = OP_I(root_inode); - oi->type = op_inode_node; - oi->u.node = of_find_node_by_path("/"); - s->s_root = d_alloc_root(root_inode); if (!s->s_root) goto out_no_root; @@ -415,39 +1073,29 @@ static struct file_system_type openprom_fs_type = { .kill_sb = kill_anon_super, }; -static void op_inode_init_once(void *data, kmem_cache_t * cachep, unsigned long flags) -{ - struct op_inode_info *oi = (struct op_inode_info *) data; - - if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == - SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&oi->vfs_inode); -} - static int __init init_openprom_fs(void) { - int err; - - op_inode_cachep = kmem_cache_create("op_inode_cache", - sizeof(struct op_inode_info), - 0, - (SLAB_RECLAIM_ACCOUNT | - SLAB_MEM_SPREAD), - op_inode_init_once, NULL); - if (!op_inode_cachep) - return -ENOMEM; - - err = register_filesystem(&openprom_fs_type); - if (err) - kmem_cache_destroy(op_inode_cachep); - - return err; + nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0); + if (!nodes) { + printk (KERN_WARNING "openpromfs: can't get free page\n"); + return -EIO; + } + if (get_nodes (0xffff, prom_root_node) == 0xffff) { + printk (KERN_WARNING "openpromfs: couldn't setup tree\n"); + return -EIO; + } + nodes[last_node].first_prop = first_prop; + return register_filesystem(&openprom_fs_type); } static void __exit exit_openprom_fs(void) { + int i; unregister_filesystem(&openprom_fs_type); - kmem_cache_destroy(op_inode_cachep); + free_pages ((unsigned long)nodes, alloced); + for (i = 0; i < aliases_nodes; i++) + kfree (alias_names [i]); + nodes = NULL; } module_init(init_openprom_fs) diff --git a/trunk/fs/partitions/Makefile b/trunk/fs/partitions/Makefile index d713ce6b3e12..42c7d3878ed0 100644 --- a/trunk/fs/partitions/Makefile +++ b/trunk/fs/partitions/Makefile @@ -4,6 +4,7 @@ obj-y := check.o +obj-$(CONFIG_DEVFS_FS) += devfs.o obj-$(CONFIG_ACORN_PARTITION) += acorn.o obj-$(CONFIG_AMIGA_PARTITION) += amiga.o obj-$(CONFIG_ATARI_PARTITION) += atari.o diff --git a/trunk/fs/partitions/acorn.c b/trunk/fs/partitions/acorn.c index 1bc9f372c7d4..c05085710fce 100644 --- a/trunk/fs/partitions/acorn.c +++ b/trunk/fs/partitions/acorn.c @@ -12,6 +12,7 @@ * every single manufacturer of SCSI and IDE cards created their own * method. */ +#include #include #include diff --git a/trunk/fs/partitions/check.c b/trunk/fs/partitions/check.c index 839634026eb5..2ef313a96b66 100644 --- a/trunk/fs/partitions/check.c +++ b/trunk/fs/partitions/check.c @@ -18,8 +18,10 @@ #include #include #include +#include #include "check.h" +#include "devfs.h" #include "acorn.h" #include "amiga.h" @@ -159,11 +161,18 @@ check_partition(struct gendisk *hd, struct block_device *bdev) if (!state) return NULL; - disk_name(hd, 0, state->name); - printk(KERN_INFO " %s:", state->name); - if (isdigit(state->name[strlen(state->name)-1])) +#ifdef CONFIG_DEVFS_FS + if (hd->devfs_name[0] != '\0') { + printk(KERN_INFO " /dev/%s:", hd->devfs_name); sprintf(state->name, "p"); - + } +#endif + else { + disk_name(hd, 0, state->name); + printk(KERN_INFO " %s:", state->name); + if (isdigit(state->name[strlen(state->name)-1])) + sprintf(state->name, "p"); + } state->limit = hd->minors; i = res = 0; while (!res && check_part[i]) { @@ -319,6 +328,7 @@ void delete_partition(struct gendisk *disk, int part) p->nr_sects = 0; p->ios[0] = p->ios[1] = 0; p->sectors[0] = p->sectors[1] = 0; + devfs_remove("%s/part%d", disk->devfs_name, part); sysfs_remove_link(&p->kobj, "subsystem"); if (p->holder_dir) kobject_unregister(p->holder_dir); @@ -340,6 +350,10 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) p->nr_sects = len; p->partno = part; + devfs_mk_bdev(MKDEV(disk->major, disk->first_minor + part), + S_IFBLK|S_IRUSR|S_IWUSR, + "%s/part%d", disk->devfs_name, part); + if (isdigit(disk->kobj.name[strlen(disk->kobj.name)-1])) snprintf(p->kobj.name,KOBJ_NAME_LEN,"%sp%d",disk->kobj.name,part); else @@ -409,8 +423,14 @@ void register_disk(struct gendisk *disk) disk_sysfs_add_subdirs(disk); /* No minors to use for partitions */ - if (disk->minors == 1) + if (disk->minors == 1) { + if (disk->devfs_name[0] != '\0') + devfs_add_disk(disk); goto exit; + } + + /* always add handle for the whole disk */ + devfs_add_partitioned(disk); /* No such device (e.g., media were just removed) */ if (!get_capacity(disk)) @@ -518,6 +538,8 @@ void del_gendisk(struct gendisk *disk) disk_stat_set_all(disk, 0); disk->stamp = 0; + devfs_remove_disk(disk); + kobject_uevent(&disk->kobj, KOBJ_REMOVE); if (disk->holder_dir) kobject_unregister(disk->holder_dir); diff --git a/trunk/fs/partitions/devfs.c b/trunk/fs/partitions/devfs.c new file mode 100644 index 000000000000..3f0a780c9cec --- /dev/null +++ b/trunk/fs/partitions/devfs.c @@ -0,0 +1,130 @@ +/* + * This tries to keep block devices away from devfs as much as possible. + */ +#include +#include +#include +#include +#include +#include + + +struct unique_numspace { + u32 num_free; /* Num free in bits */ + u32 length; /* Array length in bytes */ + unsigned long *bits; + struct semaphore mutex; +}; + +static DEFINE_MUTEX(numspace_mutex); + +static int expand_numspace(struct unique_numspace *s) +{ + u32 length; + void *bits; + + if (s->length < 16) + length = 16; + else + length = s->length << 1; + + bits = vmalloc(length); + if (!bits) + return -ENOMEM; + if (s->bits) { + memcpy(bits, s->bits, s->length); + vfree(s->bits); + } + + s->num_free = (length - s->length) << 3; + s->bits = bits; + memset(bits + s->length, 0, length - s->length); + s->length = length; + + return 0; +} + +static int alloc_unique_number(struct unique_numspace *s) +{ + int rval = 0; + + mutex_lock(&numspace_mutex); + if (s->num_free < 1) + rval = expand_numspace(s); + if (!rval) { + rval = find_first_zero_bit(s->bits, s->length << 3); + --s->num_free; + __set_bit(rval, s->bits); + } + mutex_unlock(&numspace_mutex); + + return rval; +} + +static void dealloc_unique_number(struct unique_numspace *s, int number) +{ + int old_val; + + if (number >= 0) { + mutex_lock(&numspace_mutex); + old_val = __test_and_clear_bit(number, s->bits); + if (old_val) + ++s->num_free; + mutex_unlock(&numspace_mutex); + } +} + +static struct unique_numspace disc_numspace; +static struct unique_numspace cdrom_numspace; + +void devfs_add_partitioned(struct gendisk *disk) +{ + char dirname[64], symlink[16]; + + devfs_mk_dir(disk->devfs_name); + devfs_mk_bdev(MKDEV(disk->major, disk->first_minor), + S_IFBLK|S_IRUSR|S_IWUSR, + "%s/disc", disk->devfs_name); + + disk->number = alloc_unique_number(&disc_numspace); + + sprintf(symlink, "discs/disc%d", disk->number); + sprintf(dirname, "../%s", disk->devfs_name); + devfs_mk_symlink(symlink, dirname); + +} + +void devfs_add_disk(struct gendisk *disk) +{ + devfs_mk_bdev(MKDEV(disk->major, disk->first_minor), + (disk->flags & GENHD_FL_CD) ? + S_IFBLK|S_IRUGO|S_IWUGO : + S_IFBLK|S_IRUSR|S_IWUSR, + "%s", disk->devfs_name); + + if (disk->flags & GENHD_FL_CD) { + char dirname[64], symlink[16]; + + disk->number = alloc_unique_number(&cdrom_numspace); + + sprintf(symlink, "cdroms/cdrom%d", disk->number); + sprintf(dirname, "../%s", disk->devfs_name); + devfs_mk_symlink(symlink, dirname); + } +} + +void devfs_remove_disk(struct gendisk *disk) +{ + if (disk->minors != 1) { + devfs_remove("discs/disc%d", disk->number); + dealloc_unique_number(&disc_numspace, disk->number); + devfs_remove("%s/disc", disk->devfs_name); + } + if (disk->flags & GENHD_FL_CD) { + devfs_remove("cdroms/cdrom%d", disk->number); + dealloc_unique_number(&cdrom_numspace, disk->number); + } + devfs_remove(disk->devfs_name); +} + + diff --git a/trunk/fs/partitions/devfs.h b/trunk/fs/partitions/devfs.h new file mode 100644 index 000000000000..176118b4e492 --- /dev/null +++ b/trunk/fs/partitions/devfs.h @@ -0,0 +1,10 @@ + +#ifdef CONFIG_DEVFS_FS +void devfs_add_disk(struct gendisk *dev); +void devfs_add_partitioned(struct gendisk *dev); +void devfs_remove_disk(struct gendisk *dev); +#else +# define devfs_add_disk(disk) do { } while (0) +# define devfs_add_partitioned(disk) do { } while (0) +# define devfs_remove_disk(disk) do { } while (0) +#endif diff --git a/trunk/fs/partitions/efi.c b/trunk/fs/partitions/efi.c index 63730282ad81..0f5b017aebad 100644 --- a/trunk/fs/partitions/efi.c +++ b/trunk/fs/partitions/efi.c @@ -91,6 +91,7 @@ * - Code works, detects all the partitions. * ************************************************************/ +#include #include #include "check.h" #include "efi.h" diff --git a/trunk/fs/partitions/efi.h b/trunk/fs/partitions/efi.h index 2cc89d0475bf..c44fb0561448 100644 --- a/trunk/fs/partitions/efi.h +++ b/trunk/fs/partitions/efi.h @@ -26,6 +26,7 @@ #define FS_PART_EFI_H_INCLUDED #include +#include #include #include #include diff --git a/trunk/fs/partitions/ibm.c b/trunk/fs/partitions/ibm.c index d352a7381fed..830c55d86ab1 100644 --- a/trunk/fs/partitions/ibm.c +++ b/trunk/fs/partitions/ibm.c @@ -6,6 +6,7 @@ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 */ +#include #include #include #include diff --git a/trunk/fs/partitions/mac.c b/trunk/fs/partitions/mac.c index c0871002d00d..813292f21210 100644 --- a/trunk/fs/partitions/mac.c +++ b/trunk/fs/partitions/mac.c @@ -6,6 +6,7 @@ * Re-organised Feb 1998 Russell King */ +#include #include #include "check.h" #include "mac.h" diff --git a/trunk/fs/partitions/msdos.c b/trunk/fs/partitions/msdos.c index 8f12587c3129..9935d254186e 100644 --- a/trunk/fs/partitions/msdos.c +++ b/trunk/fs/partitions/msdos.c @@ -19,6 +19,7 @@ * Re-organised Feb 1998 Russell King */ +#include #include "check.h" #include "msdos.h" diff --git a/trunk/fs/pnode.c b/trunk/fs/pnode.c index da42ee61c1df..37b568ed0e05 100644 --- a/trunk/fs/pnode.c +++ b/trunk/fs/pnode.c @@ -53,7 +53,8 @@ static int do_make_slave(struct vfsmount *mnt) if (master) { list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave) slave_mnt->mnt_master = master; - list_move(&mnt->mnt_slave, &master->mnt_slave_list); + list_del(&mnt->mnt_slave); + list_add(&mnt->mnt_slave, &master->mnt_slave_list); list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev); INIT_LIST_HEAD(&mnt->mnt_slave_list); } else { @@ -282,8 +283,10 @@ static void __propagate_umount(struct vfsmount *mnt) * umount the child only if the child has no * other children */ - if (child && list_empty(&child->mnt_mounts)) - list_move_tail(&child->mnt_hash, &mnt->mnt_hash); + if (child && list_empty(&child->mnt_mounts)) { + list_del(&child->mnt_hash); + list_add_tail(&child->mnt_hash, &mnt->mnt_hash); + } } } diff --git a/trunk/fs/proc/array.c b/trunk/fs/proc/array.c index 7495d3e20775..7a76ad570230 100644 --- a/trunk/fs/proc/array.c +++ b/trunk/fs/proc/array.c @@ -52,6 +52,7 @@ * : base.c too. */ +#include #include #include #include diff --git a/trunk/fs/proc/base.c b/trunk/fs/proc/base.c index 243a94af0427..6afff725a8c9 100644 --- a/trunk/fs/proc/base.c +++ b/trunk/fs/proc/base.c @@ -49,6 +49,7 @@ #include +#include #include #include #include @@ -73,16 +74,6 @@ #include #include "internal.h" -/* NOTE: - * Implementing inode permission operations in /proc is almost - * certainly an error. Permission checks need to happen during - * each system call not at open time. The reason is that most of - * what we wish to check for permissions in /proc varies at runtime. - * - * The classic example of a problem is opening file descriptors - * in /proc for a task before it execs a suid executable. - */ - /* * For hysterical raisins we keep the same inumbers as in the old procfs. * Feel free to change the macro below - just keep the range distinct from @@ -130,8 +121,6 @@ enum pid_directory_inos { PROC_TGID_ATTR_PREV, PROC_TGID_ATTR_EXEC, PROC_TGID_ATTR_FSCREATE, - PROC_TGID_ATTR_KEYCREATE, - PROC_TGID_ATTR_SOCKCREATE, #endif #ifdef CONFIG_AUDITSYSCALL PROC_TGID_LOGINUID, @@ -173,8 +162,6 @@ enum pid_directory_inos { PROC_TID_ATTR_PREV, PROC_TID_ATTR_EXEC, PROC_TID_ATTR_FSCREATE, - PROC_TID_ATTR_KEYCREATE, - PROC_TID_ATTR_SOCKCREATE, #endif #ifdef CONFIG_AUDITSYSCALL PROC_TID_LOGINUID, @@ -186,9 +173,6 @@ enum pid_directory_inos { PROC_TID_FD_DIR = 0x8000, /* 0x8000-0xffff */ }; -/* Worst case buffer size needed for holding an integer. */ -#define PROC_NUMBUF 10 - struct pid_entry { int type; int len; @@ -291,8 +275,6 @@ static struct pid_entry tgid_attr_stuff[] = { E(PROC_TGID_ATTR_PREV, "prev", S_IFREG|S_IRUGO), E(PROC_TGID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO), E(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO), - E(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO), - E(PROC_TGID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO), {0,0,NULL,0} }; static struct pid_entry tid_attr_stuff[] = { @@ -300,8 +282,6 @@ static struct pid_entry tid_attr_stuff[] = { E(PROC_TID_ATTR_PREV, "prev", S_IFREG|S_IRUGO), E(PROC_TID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO), E(PROC_TID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO), - E(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO), - E(PROC_TID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO), {0,0,NULL,0} }; #endif @@ -310,15 +290,12 @@ static struct pid_entry tid_attr_stuff[] = { static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) { - struct task_struct *task = get_proc_task(inode); - struct files_struct *files = NULL; + struct task_struct *task = proc_task(inode); + struct files_struct *files; struct file *file; - int fd = proc_fd(inode); + int fd = proc_type(inode) - PROC_TID_FD_DIR; - if (task) { - files = get_files_struct(task); - put_task_struct(task); - } + files = get_files_struct(task); if (files) { /* * We are not taking a ref to the file structure, so we must @@ -350,29 +327,10 @@ static struct fs_struct *get_fs_struct(struct task_struct *task) return fs; } -static int get_nr_threads(struct task_struct *tsk) -{ - /* Must be called with the rcu_read_lock held */ - unsigned long flags; - int count = 0; - - if (lock_task_sighand(tsk, &flags)) { - count = atomic_read(&tsk->signal->count); - unlock_task_sighand(tsk, &flags); - } - return count; -} - static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) { - struct task_struct *task = get_proc_task(inode); - struct fs_struct *fs = NULL; + struct fs_struct *fs = get_fs_struct(proc_task(inode)); int result = -ENOENT; - - if (task) { - fs = get_fs_struct(task); - put_task_struct(task); - } if (fs) { read_lock(&fs->lock); *mnt = mntget(fs->pwdmnt); @@ -386,14 +344,55 @@ static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfs static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) { - struct task_struct *task = get_proc_task(inode); - struct fs_struct *fs = NULL; + struct fs_struct *fs = get_fs_struct(proc_task(inode)); int result = -ENOENT; + if (fs) { + read_lock(&fs->lock); + *mnt = mntget(fs->rootmnt); + *dentry = dget(fs->root); + read_unlock(&fs->lock); + result = 0; + put_fs_struct(fs); + } + return result; +} - if (task) { - fs = get_fs_struct(task); - put_task_struct(task); + +/* Same as proc_root_link, but this addionally tries to get fs from other + * threads in the group */ +static int proc_task_root_link(struct inode *inode, struct dentry **dentry, + struct vfsmount **mnt) +{ + struct fs_struct *fs; + int result = -ENOENT; + struct task_struct *leader = proc_task(inode); + + task_lock(leader); + fs = leader->fs; + if (fs) { + atomic_inc(&fs->count); + task_unlock(leader); + } else { + /* Try to get fs from other threads */ + task_unlock(leader); + read_lock(&tasklist_lock); + if (pid_alive(leader)) { + struct task_struct *task = leader; + + while ((task = next_thread(task)) != leader) { + task_lock(task); + fs = task->fs; + if (fs) { + atomic_inc(&fs->count); + task_unlock(task); + break; + } + task_unlock(task); + } + } + read_unlock(&tasklist_lock); } + if (fs) { read_lock(&fs->lock); *mnt = mntget(fs->rootmnt); @@ -405,6 +404,7 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf return result; } + #define MAY_PTRACE(task) \ (task == current || \ (task->parent == current && \ @@ -535,22 +535,142 @@ static int proc_oom_score(struct task_struct *task, char *buffer) /************************************************************************/ /* permission checks */ -static int proc_fd_access_allowed(struct inode *inode) + +/* If the process being read is separated by chroot from the reading process, + * don't let the reader access the threads. + * + * note: this does dput(root) and mntput(vfsmnt) on exit. + */ +static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt) { - struct task_struct *task; - int allowed = 0; - /* Allow access to a task's file descriptors if it is us or we - * may use ptrace attach to the process and find out that - * information. - */ - task = get_proc_task(inode); - if (task) { - allowed = ptrace_may_attach(task); - put_task_struct(task); + struct dentry *de, *base; + struct vfsmount *our_vfsmnt, *mnt; + int res = 0; + + read_lock(¤t->fs->lock); + our_vfsmnt = mntget(current->fs->rootmnt); + base = dget(current->fs->root); + read_unlock(¤t->fs->lock); + + spin_lock(&vfsmount_lock); + de = root; + mnt = vfsmnt; + + while (mnt != our_vfsmnt) { + if (mnt == mnt->mnt_parent) + goto out; + de = mnt->mnt_mountpoint; + mnt = mnt->mnt_parent; + } + + if (!is_subdir(de, base)) + goto out; + spin_unlock(&vfsmount_lock); + +exit: + dput(base); + mntput(our_vfsmnt); + dput(root); + mntput(vfsmnt); + return res; +out: + spin_unlock(&vfsmount_lock); + res = -EACCES; + goto exit; +} + +static int proc_check_root(struct inode *inode) +{ + struct dentry *root; + struct vfsmount *vfsmnt; + + if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */ + return -ENOENT; + return proc_check_chroot(root, vfsmnt); +} + +static int proc_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + if (generic_permission(inode, mask, NULL) != 0) + return -EACCES; + return proc_check_root(inode); +} + +static int proc_task_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + struct dentry *root; + struct vfsmount *vfsmnt; + + if (generic_permission(inode, mask, NULL) != 0) + return -EACCES; + + if (proc_task_root_link(inode, &root, &vfsmnt)) + return -ENOENT; + + return proc_check_chroot(root, vfsmnt); +} + +extern struct seq_operations proc_pid_maps_op; +static int maps_open(struct inode *inode, struct file *file) +{ + struct task_struct *task = proc_task(inode); + int ret = seq_open(file, &proc_pid_maps_op); + if (!ret) { + struct seq_file *m = file->private_data; + m->private = task; + } + return ret; +} + +static struct file_operations proc_maps_operations = { + .open = maps_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +#ifdef CONFIG_NUMA +extern struct seq_operations proc_pid_numa_maps_op; +static int numa_maps_open(struct inode *inode, struct file *file) +{ + struct task_struct *task = proc_task(inode); + int ret = seq_open(file, &proc_pid_numa_maps_op); + if (!ret) { + struct seq_file *m = file->private_data; + m->private = task; } - return allowed; + return ret; } +static struct file_operations proc_numa_maps_operations = { + .open = numa_maps_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; +#endif + +#ifdef CONFIG_MMU +extern struct seq_operations proc_pid_smaps_op; +static int smaps_open(struct inode *inode, struct file *file) +{ + struct task_struct *task = proc_task(inode); + int ret = seq_open(file, &proc_pid_smaps_op); + if (!ret) { + struct seq_file *m = file->private_data; + m->private = task; + } + return ret; +} + +static struct file_operations proc_smaps_operations = { + .open = smaps_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; +#endif + extern struct seq_operations mounts_op; struct proc_mounts { struct seq_file m; @@ -559,19 +679,16 @@ struct proc_mounts { static int mounts_open(struct inode *inode, struct file *file) { - struct task_struct *task = get_proc_task(inode); - struct namespace *namespace = NULL; + struct task_struct *task = proc_task(inode); + struct namespace *namespace; struct proc_mounts *p; int ret = -EINVAL; - if (task) { - task_lock(task); - namespace = task->namespace; - if (namespace) - get_namespace(namespace); - task_unlock(task); - put_task_struct(task); - } + task_lock(task); + namespace = task->namespace; + if (namespace) + get_namespace(namespace); + task_unlock(task); if (namespace) { ret = -ENOMEM; @@ -628,21 +745,17 @@ static struct file_operations proc_mounts_operations = { extern struct seq_operations mountstats_op; static int mountstats_open(struct inode *inode, struct file *file) { + struct task_struct *task = proc_task(inode); int ret = seq_open(file, &mountstats_op); if (!ret) { struct seq_file *m = file->private_data; - struct namespace *namespace = NULL; - struct task_struct *task = get_proc_task(inode); - - if (task) { - task_lock(task); - namespace = task->namespace; - if (namespace) - get_namespace(namespace); - task_unlock(task); - put_task_struct(task); - } + struct namespace *namespace; + task_lock(task); + namespace = task->namespace; + if (namespace) + get_namespace(namespace); + task_unlock(task); if (namespace) m->private = namespace; @@ -669,27 +782,18 @@ static ssize_t proc_info_read(struct file * file, char __user * buf, struct inode * inode = file->f_dentry->d_inode; unsigned long page; ssize_t length; - struct task_struct *task = get_proc_task(inode); - - length = -ESRCH; - if (!task) - goto out_no_task; + struct task_struct *task = proc_task(inode); if (count > PROC_BLOCK_SIZE) count = PROC_BLOCK_SIZE; - - length = -ENOMEM; if (!(page = __get_free_page(GFP_KERNEL))) - goto out; + return -ENOMEM; length = PROC_I(inode)->op.proc_read(task, (char*)page); if (length >= 0) length = simple_read_from_buffer(buf, count, ppos, (char *)page, length); free_page(page); -out: - put_task_struct(task); -out_no_task: return length; } @@ -706,15 +810,12 @@ static int mem_open(struct inode* inode, struct file* file) static ssize_t mem_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - struct task_struct *task = get_proc_task(file->f_dentry->d_inode); + struct task_struct *task = proc_task(file->f_dentry->d_inode); char *page; unsigned long src = *ppos; int ret = -ESRCH; struct mm_struct *mm; - if (!task) - goto out_no_task; - if (!MAY_PTRACE(task) || !ptrace_may_attach(task)) goto out; @@ -764,8 +865,6 @@ static ssize_t mem_read(struct file * file, char __user * buf, out_free: free_page((unsigned long) page); out: - put_task_struct(task); -out_no_task: return ret; } @@ -778,20 +877,15 @@ static ssize_t mem_write(struct file * file, const char * buf, { int copied = 0; char *page; - struct task_struct *task = get_proc_task(file->f_dentry->d_inode); + struct task_struct *task = proc_task(file->f_dentry->d_inode); unsigned long dst = *ppos; - copied = -ESRCH; - if (!task) - goto out_no_task; - if (!MAY_PTRACE(task) || !ptrace_may_attach(task)) - goto out; + return -ESRCH; - copied = -ENOMEM; page = (char *)__get_free_page(GFP_USER); if (!page) - goto out; + return -ENOMEM; while (count > 0) { int this_len, retval; @@ -814,9 +908,6 @@ static ssize_t mem_write(struct file * file, const char * buf, } *ppos = dst; free_page((unsigned long) page); -out: - put_task_struct(task); -out_no_task: return copied; } #endif @@ -847,18 +938,13 @@ static struct file_operations proc_mem_operations = { static ssize_t oom_adjust_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct task_struct *task = get_proc_task(file->f_dentry->d_inode); - char buffer[PROC_NUMBUF]; + struct task_struct *task = proc_task(file->f_dentry->d_inode); + char buffer[8]; size_t len; - int oom_adjust; + int oom_adjust = task->oomkilladj; loff_t __ppos = *ppos; - if (!task) - return -ESRCH; - oom_adjust = task->oomkilladj; - put_task_struct(task); - - len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust); + len = sprintf(buffer, "%i\n", oom_adjust); if (__ppos >= len) return 0; if (count > len-__ppos) @@ -872,15 +958,15 @@ static ssize_t oom_adjust_read(struct file *file, char __user *buf, static ssize_t oom_adjust_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct task_struct *task; - char buffer[PROC_NUMBUF], *end; + struct task_struct *task = proc_task(file->f_dentry->d_inode); + char buffer[8], *end; int oom_adjust; if (!capable(CAP_SYS_RESOURCE)) return -EPERM; - memset(buffer, 0, sizeof(buffer)); - if (count > sizeof(buffer) - 1) - count = sizeof(buffer) - 1; + memset(buffer, 0, 8); + if (count > 6) + count = 6; if (copy_from_user(buffer, buf, count)) return -EFAULT; oom_adjust = simple_strtol(buffer, &end, 0); @@ -888,11 +974,7 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf, return -EINVAL; if (*end == '\n') end++; - task = get_proc_task(file->f_dentry->d_inode); - if (!task) - return -ESRCH; task->oomkilladj = oom_adjust; - put_task_struct(task); if (end - buffer == 0) return -EIO; return end - buffer; @@ -903,21 +985,22 @@ static struct file_operations proc_oom_adjust_operations = { .write = oom_adjust_write, }; +static struct inode_operations proc_mem_inode_operations = { + .permission = proc_permission, +}; + #ifdef CONFIG_AUDITSYSCALL #define TMPBUFLEN 21 static ssize_t proc_loginuid_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { struct inode * inode = file->f_dentry->d_inode; - struct task_struct *task = get_proc_task(inode); + struct task_struct *task = proc_task(inode); ssize_t length; char tmpbuf[TMPBUFLEN]; - if (!task) - return -ESRCH; length = scnprintf(tmpbuf, TMPBUFLEN, "%u", audit_get_loginuid(task->audit_context)); - put_task_struct(task); return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); } @@ -927,12 +1010,13 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf, struct inode * inode = file->f_dentry->d_inode; char *page, *tmp; ssize_t length; + struct task_struct *task = proc_task(inode); uid_t loginuid; if (!capable(CAP_AUDIT_CONTROL)) return -EPERM; - if (current != pid_task(proc_pid(inode), PIDTYPE_PID)) + if (current != task) return -EPERM; if (count >= PAGE_SIZE) @@ -956,7 +1040,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf, goto out_free_page; } - length = audit_set_loginuid(current, loginuid); + length = audit_set_loginuid(task, loginuid); if (likely(length == 0)) length = count; @@ -975,16 +1059,13 @@ static struct file_operations proc_loginuid_operations = { static ssize_t seccomp_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode); + struct task_struct *tsk = proc_task(file->f_dentry->d_inode); char __buf[20]; loff_t __ppos = *ppos; size_t len; - if (!tsk) - return -ESRCH; /* no need to print the trailing zero, so use only len */ len = sprintf(__buf, "%u\n", tsk->seccomp.mode); - put_task_struct(tsk); if (__ppos >= len) return 0; if (count > len - __ppos) @@ -998,43 +1079,29 @@ static ssize_t seccomp_read(struct file *file, char __user *buf, static ssize_t seccomp_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode); + struct task_struct *tsk = proc_task(file->f_dentry->d_inode); char __buf[20], *end; unsigned int seccomp_mode; - ssize_t result; - - result = -ESRCH; - if (!tsk) - goto out_no_task; /* can set it only once to be even more secure */ - result = -EPERM; if (unlikely(tsk->seccomp.mode)) - goto out; + return -EPERM; - result = -EFAULT; memset(__buf, 0, sizeof(__buf)); count = min(count, sizeof(__buf) - 1); if (copy_from_user(__buf, buf, count)) - goto out; - + return -EFAULT; seccomp_mode = simple_strtoul(__buf, &end, 0); if (*end == '\n') end++; - result = -EINVAL; if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) { tsk->seccomp.mode = seccomp_mode; set_tsk_thread_flag(tsk, TIF_SECCOMP); } else - goto out; - result = -EIO; + return -EINVAL; if (unlikely(!(end - __buf))) - goto out; - result = end - __buf; -out: - put_task_struct(tsk); -out_no_task: - return result; + return -EIO; + return end - __buf; } static struct file_operations proc_seccomp_operations = { @@ -1051,8 +1118,10 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) /* We don't need a base pointer in the /proc filesystem */ path_release(nd); - /* Are we allowed to snoop on the tasks file descriptors? */ - if (!proc_fd_access_allowed(inode)) + if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE)) + goto out; + error = proc_check_root(inode); + if (error) goto out; error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt); @@ -1094,8 +1163,12 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b struct dentry *de; struct vfsmount *mnt = NULL; - /* Are we allowed to snoop on the tasks file descriptors? */ - if (!proc_fd_access_allowed(inode)) + lock_kernel(); + + if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE)) + goto out; + error = proc_check_root(inode); + if (error) goto out; error = PROC_I(inode)->op.proc_get_link(inode, &de, &mnt); @@ -1106,6 +1179,7 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b dput(de); mntput(mnt); out: + unlock_kernel(); return error; } @@ -1114,20 +1188,21 @@ static struct inode_operations proc_pid_link_inode_operations = { .follow_link = proc_pid_follow_link }; +#define NUMBUF 10 + static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) { - struct dentry *dentry = filp->f_dentry; - struct inode *inode = dentry->d_inode; - struct task_struct *p = get_proc_task(inode); + struct inode *inode = filp->f_dentry->d_inode; + struct task_struct *p = proc_task(inode); unsigned int fd, tid, ino; int retval; - char buf[PROC_NUMBUF]; + char buf[NUMBUF]; struct files_struct * files; struct fdtable *fdt; retval = -ENOENT; - if (!p) - goto out_no_task; + if (!pid_alive(p)) + goto out; retval = 0; tid = p->pid; @@ -1138,7 +1213,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) goto out; filp->f_pos++; case 1: - ino = parent_ino(dentry); + ino = fake_ino(tid, PROC_TID_INO); if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) goto out; filp->f_pos++; @@ -1157,7 +1232,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) continue; rcu_read_unlock(); - j = PROC_NUMBUF; + j = NUMBUF; i = fd; do { j--; @@ -1166,7 +1241,7 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) } while (i); ino = fake_ino(tid, PROC_TID_FD_DIR + fd); - if (filldir(dirent, buf+j, PROC_NUMBUF-j, fd+2, ino, DT_LNK) < 0) { + if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) { rcu_read_lock(); break; } @@ -1176,8 +1251,6 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir) put_files_struct(files); } out: - put_task_struct(p); -out_no_task: return retval; } @@ -1189,18 +1262,16 @@ static int proc_pident_readdir(struct file *filp, int pid; struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; - struct task_struct *task = get_proc_task(inode); struct pid_entry *p; ino_t ino; int ret; ret = -ENOENT; - if (!task) + if (!pid_alive(proc_task(inode))) goto out; ret = 0; - pid = task->pid; - put_task_struct(task); + pid = proc_task(inode)->pid; i = filp->f_pos; switch (i) { case 0: @@ -1283,19 +1354,22 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st /* Common stuff */ ei = PROC_I(inode); + ei->task = NULL; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_ino = fake_ino(task->pid, ino); + if (!pid_alive(task)) + goto out_unlock; + /* * grab the reference to task. */ - ei->pid = get_pid(task->pids[PIDTYPE_PID].pid); - if (!ei->pid) - goto out_unlock; - + get_task_struct(task); + ei->task = task; + ei->type = ino; inode->i_uid = 0; inode->i_gid = 0; - if (task_dumpable(task)) { + if (ino == PROC_TGID_INO || ino == PROC_TID_INO || task_dumpable(task)) { inode->i_uid = task->euid; inode->i_gid = task->egid; } @@ -1305,6 +1379,7 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st return inode; out_unlock: + ei->pde = NULL; iput(inode); return NULL; } @@ -1318,21 +1393,13 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st * * Rewrite the inode's ownerships here because the owning task may have * performed a setuid(), etc. - * - * Before the /proc/pid/status file was created the only way to read - * the effective uid of a /process was to stat /proc/pid. Reading - * /proc/pid/status is slow enough that procps and other packages - * kept stating /proc/pid. To keep the rules in /proc simple I have - * made this apply to all per process world readable and executable - * directories. */ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; - struct task_struct *task = get_proc_task(inode); - if (task) { - if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || - task_dumpable(task)) { + struct task_struct *task = proc_task(inode); + if (pid_alive(task)) { + if (proc_type(inode) == PROC_TGID_INO || proc_type(inode) == PROC_TID_INO || task_dumpable(task)) { inode->i_uid = task->euid; inode->i_gid = task->egid; } else { @@ -1340,75 +1407,59 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd) inode->i_gid = 0; } security_task_to_inode(task, inode); - put_task_struct(task); return 1; } d_drop(dentry); return 0; } -static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) -{ - struct inode *inode = dentry->d_inode; - struct task_struct *task; - generic_fillattr(inode, stat); - - rcu_read_lock(); - stat->uid = 0; - stat->gid = 0; - task = pid_task(proc_pid(inode), PIDTYPE_PID); - if (task) { - if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || - task_dumpable(task)) { - stat->uid = task->euid; - stat->gid = task->egid; - } - } - rcu_read_unlock(); - return 0; -} - static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) { struct inode *inode = dentry->d_inode; - struct task_struct *task = get_proc_task(inode); - int fd = proc_fd(inode); + struct task_struct *task = proc_task(inode); + int fd = proc_type(inode) - PROC_TID_FD_DIR; struct files_struct *files; - if (task) { - files = get_files_struct(task); - if (files) { - rcu_read_lock(); - if (fcheck_files(files, fd)) { - rcu_read_unlock(); - put_files_struct(files); - if (task_dumpable(task)) { - inode->i_uid = task->euid; - inode->i_gid = task->egid; - } else { - inode->i_uid = 0; - inode->i_gid = 0; - } - security_task_to_inode(task, inode); - put_task_struct(task); - return 1; - } + files = get_files_struct(task); + if (files) { + rcu_read_lock(); + if (fcheck_files(files, fd)) { rcu_read_unlock(); put_files_struct(files); + if (task_dumpable(task)) { + inode->i_uid = task->euid; + inode->i_gid = task->egid; + } else { + inode->i_uid = 0; + inode->i_gid = 0; + } + security_task_to_inode(task, inode); + return 1; } - put_task_struct(task); + rcu_read_unlock(); + put_files_struct(files); } d_drop(dentry); return 0; } +static void pid_base_iput(struct dentry *dentry, struct inode *inode) +{ + struct task_struct *task = proc_task(inode); + spin_lock(&task->proc_lock); + if (task->proc_dentry == dentry) + task->proc_dentry = NULL; + spin_unlock(&task->proc_lock); + iput(inode); +} + static int pid_delete_dentry(struct dentry * dentry) { /* Is the task we represent dead? * If so, then don't put the dentry on the lru list, * kill it immediately. */ - return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first; + return !pid_alive(proc_task(dentry->d_inode)); } static struct dentry_operations tid_fd_dentry_operations = @@ -1423,6 +1474,13 @@ static struct dentry_operations pid_dentry_operations = .d_delete = pid_delete_dentry, }; +static struct dentry_operations pid_base_dentry_operations = +{ + .d_revalidate = pid_revalidate, + .d_iput = pid_base_iput, + .d_delete = pid_delete_dentry, +}; + /* Lookups */ static unsigned name_to_int(struct dentry *dentry) @@ -1450,24 +1508,22 @@ static unsigned name_to_int(struct dentry *dentry) /* SMP-safe */ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd) { - struct task_struct *task = get_proc_task(dir); + struct task_struct *task = proc_task(dir); unsigned fd = name_to_int(dentry); - struct dentry *result = ERR_PTR(-ENOENT); struct file * file; struct files_struct * files; struct inode *inode; struct proc_inode *ei; - if (!task) - goto out_no_task; if (fd == ~0U) goto out; + if (!pid_alive(task)) + goto out; inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_FD_DIR+fd); if (!inode) goto out; ei = PROC_I(inode); - ei->fd = fd; files = get_files_struct(task); if (!files) goto out_unlock; @@ -1492,25 +1548,19 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, ei->op.proc_get_link = proc_fd_link; dentry->d_op = &tid_fd_dentry_operations; d_add(dentry, inode); - /* Close the race of the process dying before we return the dentry */ - if (tid_fd_revalidate(dentry, NULL)) - result = NULL; -out: - put_task_struct(task); -out_no_task: - return result; + return NULL; out_unlock2: spin_unlock(&files->file_lock); put_files_struct(files); out_unlock: iput(inode); - goto out; +out: + return ERR_PTR(-ENOENT); } static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir); static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd); -static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); static struct file_operations proc_fd_operations = { .read = generic_read_dir, @@ -1527,11 +1577,12 @@ static struct file_operations proc_task_operations = { */ static struct inode_operations proc_fd_inode_operations = { .lookup = proc_lookupfd, + .permission = proc_permission, }; static struct inode_operations proc_task_inode_operations = { .lookup = proc_task_lookup, - .getattr = proc_task_getattr, + .permission = proc_task_permission, }; #ifdef CONFIG_SECURITY @@ -1541,17 +1592,12 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, struct inode * inode = file->f_dentry->d_inode; unsigned long page; ssize_t length; - struct task_struct *task = get_proc_task(inode); - - length = -ESRCH; - if (!task) - goto out_no_task; + struct task_struct *task = proc_task(inode); if (count > PAGE_SIZE) count = PAGE_SIZE; - length = -ENOMEM; if (!(page = __get_free_page(GFP_KERNEL))) - goto out; + return -ENOMEM; length = security_getprocattr(task, (char*)file->f_dentry->d_name.name, @@ -1559,9 +1605,6 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf, if (length >= 0) length = simple_read_from_buffer(buf, count, ppos, (char *)page, length); free_page(page); -out: - put_task_struct(task); -out_no_task: return length; } @@ -1571,36 +1614,26 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, struct inode * inode = file->f_dentry->d_inode; char *page; ssize_t length; - struct task_struct *task = get_proc_task(inode); + struct task_struct *task = proc_task(inode); - length = -ESRCH; - if (!task) - goto out_no_task; if (count > PAGE_SIZE) count = PAGE_SIZE; - - /* No partial writes. */ - length = -EINVAL; - if (*ppos != 0) - goto out; - - length = -ENOMEM; + if (*ppos != 0) { + /* No partial writes. */ + return -EINVAL; + } page = (char*)__get_free_page(GFP_USER); if (!page) - goto out; - + return -ENOMEM; length = -EFAULT; if (copy_from_user(page, buf, count)) - goto out_free; + goto out; length = security_setprocattr(task, (char*)file->f_dentry->d_name.name, (void*)page, count); -out_free: - free_page((unsigned long) page); out: - put_task_struct(task); -out_no_task: + free_page((unsigned long) page); return length; } @@ -1615,22 +1648,24 @@ static struct file_operations proc_tgid_attr_operations; static struct inode_operations proc_tgid_attr_inode_operations; #endif +static int get_tid_list(int index, unsigned int *tids, struct inode *dir); + /* SMP-safe */ static struct dentry *proc_pident_lookup(struct inode *dir, struct dentry *dentry, struct pid_entry *ents) { struct inode *inode; - struct dentry *error; - struct task_struct *task = get_proc_task(dir); + int error; + struct task_struct *task = proc_task(dir); struct pid_entry *p; struct proc_inode *ei; - error = ERR_PTR(-ENOENT); + error = -ENOENT; inode = NULL; - if (!task) - goto out_no_task; + if (!pid_alive(task)) + goto out; for (p = ents; p->name; p++) { if (p->len != dentry->d_name.len) @@ -1641,7 +1676,7 @@ static struct dentry *proc_pident_lookup(struct inode *dir, if (!p->name) goto out; - error = ERR_PTR(-EINVAL); + error = -EINVAL; inode = proc_pid_make_inode(dir->i_sb, task, p->type); if (!inode) goto out; @@ -1654,7 +1689,7 @@ static struct dentry *proc_pident_lookup(struct inode *dir, */ switch(p->type) { case PROC_TGID_TASK: - inode->i_nlink = 2; + inode->i_nlink = 2 + get_tid_list(2, NULL, dir); inode->i_op = &proc_task_inode_operations; inode->i_fop = &proc_task_operations; break; @@ -1724,6 +1759,7 @@ static struct dentry *proc_pident_lookup(struct inode *dir, #endif case PROC_TID_MEM: case PROC_TGID_MEM: + inode->i_op = &proc_mem_inode_operations; inode->i_fop = &proc_mem_operations; break; #ifdef CONFIG_SECCOMP @@ -1765,10 +1801,6 @@ static struct dentry *proc_pident_lookup(struct inode *dir, case PROC_TGID_ATTR_EXEC: case PROC_TID_ATTR_FSCREATE: case PROC_TGID_ATTR_FSCREATE: - case PROC_TID_ATTR_KEYCREATE: - case PROC_TGID_ATTR_KEYCREATE: - case PROC_TID_ATTR_SOCKCREATE: - case PROC_TGID_ATTR_SOCKCREATE: inode->i_fop = &proc_pid_attr_operations; break; #endif @@ -1810,18 +1842,14 @@ static struct dentry *proc_pident_lookup(struct inode *dir, default: printk("procfs: impossible type (%d)",p->type); iput(inode); - error = ERR_PTR(-EINVAL); - goto out; + return ERR_PTR(-EINVAL); } dentry->d_op = &pid_dentry_operations; d_add(dentry, inode); - /* Close the race of the process dying before we return the dentry */ - if (pid_revalidate(dentry, NULL)) - error = NULL; + return NULL; + out: - put_task_struct(task); -out_no_task: - return error; + return ERR_PTR(error); } static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ @@ -1844,12 +1872,10 @@ static struct file_operations proc_tid_base_operations = { static struct inode_operations proc_tgid_base_inode_operations = { .lookup = proc_tgid_base_lookup, - .getattr = pid_getattr, }; static struct inode_operations proc_tid_base_inode_operations = { .lookup = proc_tid_base_lookup, - .getattr = pid_getattr, }; #ifdef CONFIG_SECURITY @@ -1891,12 +1917,10 @@ static struct dentry *proc_tid_attr_lookup(struct inode *dir, static struct inode_operations proc_tgid_attr_inode_operations = { .lookup = proc_tgid_attr_lookup, - .getattr = pid_getattr, }; static struct inode_operations proc_tid_attr_inode_operations = { .lookup = proc_tid_attr_lookup, - .getattr = pid_getattr, }; #endif @@ -1906,14 +1930,14 @@ static struct inode_operations proc_tid_attr_inode_operations = { static int proc_self_readlink(struct dentry *dentry, char __user *buffer, int buflen) { - char tmp[PROC_NUMBUF]; + char tmp[30]; sprintf(tmp, "%d", current->tgid); return vfs_readlink(dentry,buffer,buflen,tmp); } static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) { - char tmp[PROC_NUMBUF]; + char tmp[30]; sprintf(tmp, "%d", current->tgid); return ERR_PTR(vfs_follow_link(nd,tmp)); } @@ -1924,80 +1948,67 @@ static struct inode_operations proc_self_inode_operations = { }; /** - * proc_flush_task - Remove dcache entries for @task from the /proc dcache. - * - * @task: task that should be flushed. - * - * Looks in the dcache for - * /proc/@pid - * /proc/@tgid/task/@pid - * if either directory is present flushes it and all of it'ts children - * from the dcache. + * proc_pid_unhash - Unhash /proc/@pid entry from the dcache. + * @p: task that should be flushed. * - * It is safe and reasonable to cache /proc entries for a task until - * that task exits. After that they just clog up the dcache with - * useless entries, possibly causing useful dcache entries to be - * flushed instead. This routine is proved to flush those useless - * dcache entries at process exit time. + * Drops the /proc/@pid dcache entry from the hash chains. * - * NOTE: This routine is just an optimization so it does not guarantee - * that no dcache entries will exist at process exit time it - * just makes it very unlikely that any will persist. + * Dropping /proc/@pid entries and detach_pid must be synchroneous, + * otherwise e.g. /proc/@pid/exe might point to the wrong executable, + * if the pid value is immediately reused. This is enforced by + * - caller must acquire spin_lock(p->proc_lock) + * - must be called before detach_pid() + * - proc_pid_lookup acquires proc_lock, and checks that + * the target is not dead by looking at the attach count + * of PIDTYPE_PID. */ -void proc_flush_task(struct task_struct *task) -{ - struct dentry *dentry, *leader, *dir; - char buf[PROC_NUMBUF]; - struct qstr name; - - name.name = buf; - name.len = snprintf(buf, sizeof(buf), "%d", task->pid); - dentry = d_hash_and_lookup(proc_mnt->mnt_root, &name); - if (dentry) { - shrink_dcache_parent(dentry); - d_drop(dentry); - dput(dentry); - } - if (thread_group_leader(task)) - goto out; +struct dentry *proc_pid_unhash(struct task_struct *p) +{ + struct dentry *proc_dentry; - name.name = buf; - name.len = snprintf(buf, sizeof(buf), "%d", task->tgid); - leader = d_hash_and_lookup(proc_mnt->mnt_root, &name); - if (!leader) - goto out; + proc_dentry = p->proc_dentry; + if (proc_dentry != NULL) { - name.name = "task"; - name.len = strlen(name.name); - dir = d_hash_and_lookup(leader, &name); - if (!dir) - goto out_put_leader; - - name.name = buf; - name.len = snprintf(buf, sizeof(buf), "%d", task->pid); - dentry = d_hash_and_lookup(dir, &name); - if (dentry) { - shrink_dcache_parent(dentry); - d_drop(dentry); - dput(dentry); + spin_lock(&dcache_lock); + spin_lock(&proc_dentry->d_lock); + if (!d_unhashed(proc_dentry)) { + dget_locked(proc_dentry); + __d_drop(proc_dentry); + spin_unlock(&proc_dentry->d_lock); + } else { + spin_unlock(&proc_dentry->d_lock); + proc_dentry = NULL; + } + spin_unlock(&dcache_lock); } + return proc_dentry; +} - dput(dir); -out_put_leader: - dput(leader); -out: - return; +/** + * proc_pid_flush - recover memory used by stale /proc/@pid/x entries + * @proc_dentry: directoy to prune. + * + * Shrink the /proc directory that was used by the just killed thread. + */ + +void proc_pid_flush(struct dentry *proc_dentry) +{ + might_sleep(); + if(proc_dentry != NULL) { + shrink_dcache_parent(proc_dentry); + dput(proc_dentry); + } } /* SMP-safe */ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) { - struct dentry *result = ERR_PTR(-ENOENT); struct task_struct *task; struct inode *inode; struct proc_inode *ei; unsigned tgid; + int died; if (dentry->d_name.len == 4 && !memcmp(dentry->d_name.name,"self",4)) { inode = new_inode(dir->i_sb); @@ -2018,18 +2029,21 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct if (tgid == ~0U) goto out; - rcu_read_lock(); + read_lock(&tasklist_lock); task = find_task_by_pid(tgid); if (task) get_task_struct(task); - rcu_read_unlock(); + read_unlock(&tasklist_lock); if (!task) goto out; inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO); - if (!inode) - goto out_put_task; + + if (!inode) { + put_task_struct(task); + goto out; + } inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; inode->i_op = &proc_tgid_base_inode_operations; inode->i_fop = &proc_tgid_base_operations; @@ -2040,40 +2054,45 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct inode->i_nlink = 4; #endif - dentry->d_op = &pid_dentry_operations; + dentry->d_op = &pid_base_dentry_operations; + died = 0; d_add(dentry, inode); - /* Close the race of the process dying before we return the dentry */ - if (pid_revalidate(dentry, NULL)) - result = NULL; + spin_lock(&task->proc_lock); + task->proc_dentry = dentry; + if (!pid_alive(task)) { + dentry = proc_pid_unhash(task); + died = 1; + } + spin_unlock(&task->proc_lock); -out_put_task: put_task_struct(task); + if (died) { + proc_pid_flush(dentry); + goto out; + } + return NULL; out: - return result; + return ERR_PTR(-ENOENT); } /* SMP-safe */ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd) { - struct dentry *result = ERR_PTR(-ENOENT); struct task_struct *task; - struct task_struct *leader = get_proc_task(dir); + struct task_struct *leader = proc_task(dir); struct inode *inode; unsigned tid; - if (!leader) - goto out_no_task; - tid = name_to_int(dentry); if (tid == ~0U) goto out; - rcu_read_lock(); + read_lock(&tasklist_lock); task = find_task_by_pid(tid); if (task) get_task_struct(task); - rcu_read_unlock(); + read_unlock(&tasklist_lock); if (!task) goto out; if (leader->tgid != task->tgid) @@ -2094,95 +2113,101 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry inode->i_nlink = 3; #endif - dentry->d_op = &pid_dentry_operations; + dentry->d_op = &pid_base_dentry_operations; d_add(dentry, inode); - /* Close the race of the process dying before we return the dentry */ - if (pid_revalidate(dentry, NULL)) - result = NULL; + put_task_struct(task); + return NULL; out_drop_task: put_task_struct(task); out: - put_task_struct(leader); -out_no_task: - return result; + return ERR_PTR(-ENOENT); } +#define PROC_NUMBUF 10 +#define PROC_MAXPIDS 20 + /* - * Find the first tgid to return to user space. - * - * Usually this is just whatever follows &init_task, but if the users - * buffer was too small to hold the full list or there was a seek into - * the middle of the directory we have more work to do. - * - * In the case of a short read we start with find_task_by_pid. - * - * In the case of a seek we start with &init_task and walk nr - * threads past it. + * Get a few tgid's to return for filldir - we need to hold the + * tasklist lock while doing this, and we must release it before + * we actually do the filldir itself, so we use a temp buffer.. */ -static struct task_struct *first_tgid(int tgid, unsigned int nr) -{ - struct task_struct *pos; - rcu_read_lock(); - if (tgid && nr) { - pos = find_task_by_pid(tgid); - if (pos && thread_group_leader(pos)) - goto found; +static int get_tgid_list(int index, unsigned long version, unsigned int *tgids) +{ + struct task_struct *p; + int nr_tgids = 0; + + index--; + read_lock(&tasklist_lock); + p = NULL; + if (version) { + p = find_task_by_pid(version); + if (p && !thread_group_leader(p)) + p = NULL; } - /* If nr exceeds the number of processes get out quickly */ - pos = NULL; - if (nr && nr >= nr_processes()) - goto done; - /* If we haven't found our starting place yet start with - * the init_task and walk nr tasks forward. - */ - for (pos = next_task(&init_task); nr > 0; --nr) { - pos = next_task(pos); - if (pos == &init_task) { - pos = NULL; - goto done; - } + if (p) + index = 0; + else + p = next_task(&init_task); + + for ( ; p != &init_task; p = next_task(p)) { + int tgid = p->pid; + if (!pid_alive(p)) + continue; + if (--index >= 0) + continue; + tgids[nr_tgids] = tgid; + nr_tgids++; + if (nr_tgids >= PROC_MAXPIDS) + break; } -found: - get_task_struct(pos); -done: - rcu_read_unlock(); - return pos; + read_unlock(&tasklist_lock); + return nr_tgids; } /* - * Find the next task in the task list. - * Return NULL if we loop or there is any error. - * - * The reference to the input task_struct is released. + * Get a few tid's to return for filldir - we need to hold the + * tasklist lock while doing this, and we must release it before + * we actually do the filldir itself, so we use a temp buffer.. */ -static struct task_struct *next_tgid(struct task_struct *start) -{ - struct task_struct *pos; - rcu_read_lock(); - pos = start; - if (pid_alive(start)) - pos = next_task(start); - if (pid_alive(pos) && (pos != &init_task)) { - get_task_struct(pos); - goto done; - } - pos = NULL; -done: - rcu_read_unlock(); - put_task_struct(start); - return pos; +static int get_tid_list(int index, unsigned int *tids, struct inode *dir) +{ + struct task_struct *leader_task = proc_task(dir); + struct task_struct *task = leader_task; + int nr_tids = 0; + + index -= 2; + read_lock(&tasklist_lock); + /* + * The starting point task (leader_task) might be an already + * unlinked task, which cannot be used to access the task-list + * via next_thread(). + */ + if (pid_alive(task)) do { + int tid = task->pid; + + if (--index >= 0) + continue; + if (tids != NULL) + tids[nr_tids] = tid; + nr_tids++; + if (nr_tids >= PROC_MAXPIDS) + break; + } while ((task = next_thread(task)) != leader_task); + read_unlock(&tasklist_lock); + return nr_tids; } /* for the /proc/ directory itself, after non-process stuff has been done */ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) { + unsigned int tgid_array[PROC_MAXPIDS]; char buf[PROC_NUMBUF]; unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; - struct task_struct *task; - int tgid; + unsigned int nr_tgids, i; + int next_tgid; if (!nr) { ino_t ino = fake_ino(0,PROC_TGID_INO); @@ -2191,116 +2216,63 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir) filp->f_pos++; nr++; } - nr -= 1; /* f_version caches the tgid value that the last readdir call couldn't * return. lseek aka telldir automagically resets f_version to 0. */ - tgid = filp->f_version; + next_tgid = filp->f_version; filp->f_version = 0; - for (task = first_tgid(tgid, nr); - task; - task = next_tgid(task), filp->f_pos++) { - int len; - ino_t ino; - tgid = task->pid; - len = snprintf(buf, sizeof(buf), "%d", tgid); - ino = fake_ino(tgid, PROC_TGID_INO); - if (filldir(dirent, buf, len, filp->f_pos, ino, DT_DIR) < 0) { - /* returning this tgid failed, save it as the first - * pid for the next readir call */ - filp->f_version = tgid; - put_task_struct(task); + for (;;) { + nr_tgids = get_tgid_list(nr, next_tgid, tgid_array); + if (!nr_tgids) { + /* no more entries ! */ break; } - } - return 0; -} + next_tgid = 0; -/* - * Find the first tid of a thread group to return to user space. - * - * Usually this is just the thread group leader, but if the users - * buffer was too small or there was a seek into the middle of the - * directory we have more work todo. - * - * In the case of a short read we start with find_task_by_pid. - * - * In the case of a seek we start with the leader and walk nr - * threads past it. - */ -static struct task_struct *first_tid(struct task_struct *leader, - int tid, int nr) -{ - struct task_struct *pos; + /* do not use the last found pid, reserve it for next_tgid */ + if (nr_tgids == PROC_MAXPIDS) { + nr_tgids--; + next_tgid = tgid_array[nr_tgids]; + } - rcu_read_lock(); - /* Attempt to start with the pid of a thread */ - if (tid && (nr > 0)) { - pos = find_task_by_pid(tid); - if (pos && (pos->group_leader == leader)) - goto found; - } + for (i=0;i= get_nr_threads(leader)) - goto out; + do + buf[--j] = '0' + (tgid % 10); + while ((tgid /= 10) != 0); - /* If we haven't found our starting place yet start - * with the leader and walk nr threads forward. - */ - for (pos = leader; nr > 0; --nr) { - pos = next_thread(pos); - if (pos == leader) { - pos = NULL; - goto out; + if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) { + /* returning this tgid failed, save it as the first + * pid for the next readir call */ + filp->f_version = tgid_array[i]; + goto out; + } + filp->f_pos++; + nr++; } } -found: - get_task_struct(pos); out: - rcu_read_unlock(); - return pos; -} - -/* - * Find the next thread in the thread list. - * Return NULL if there is an error or no next thread. - * - * The reference to the input task_struct is released. - */ -static struct task_struct *next_tid(struct task_struct *start) -{ - struct task_struct *pos = NULL; - rcu_read_lock(); - if (pid_alive(start)) { - pos = next_thread(start); - if (thread_group_leader(pos)) - pos = NULL; - else - get_task_struct(pos); - } - rcu_read_unlock(); - put_task_struct(start); - return pos; + return 0; } /* for the /proc/TGID/task/ directories */ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir) { + unsigned int tid_array[PROC_MAXPIDS]; char buf[PROC_NUMBUF]; + unsigned int nr_tids, i; struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; - struct task_struct *leader = get_proc_task(inode); - struct task_struct *task; int retval = -ENOENT; ino_t ino; - int tid; unsigned long pos = filp->f_pos; /* avoiding "long long" filp->f_pos */ - if (!leader) - goto out_no_task; + if (!pid_alive(proc_task(inode))) + goto out; retval = 0; switch (pos) { @@ -2318,45 +2290,24 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi /* fall through */ } - /* f_version caches the tgid value that the last readdir call couldn't - * return. lseek aka telldir automagically resets f_version to 0. - */ - tid = filp->f_version; - filp->f_version = 0; - for (task = first_tid(leader, tid, pos - 2); - task; - task = next_tid(task), pos++) { - int len; - tid = task->pid; - len = snprintf(buf, sizeof(buf), "%d", tid); - ino = fake_ino(tid, PROC_TID_INO); - if (filldir(dirent, buf, len, pos, ino, DT_DIR < 0)) { - /* returning this tgid failed, save it as the first - * pid for the next readir call */ - filp->f_version = tid; - put_task_struct(task); + nr_tids = get_tid_list(pos, tid_array, inode); + inode->i_nlink = pos + nr_tids; + + for (i = 0; i < nr_tids; i++) { + unsigned long j = PROC_NUMBUF; + int tid = tid_array[i]; + + ino = fake_ino(tid,PROC_TID_INO); + + do + buf[--j] = '0' + (tid % 10); + while ((tid /= 10) != 0); + + if (filldir(dirent, buf+j, PROC_NUMBUF-j, pos, ino, DT_DIR) < 0) break; - } + pos++; } out: filp->f_pos = pos; - put_task_struct(leader); -out_no_task: return retval; } - -static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) -{ - struct inode *inode = dentry->d_inode; - struct task_struct *p = get_proc_task(inode); - generic_fillattr(inode, stat); - - if (p) { - rcu_read_lock(); - stat->nlink += get_nr_threads(p); - rcu_read_unlock(); - put_task_struct(p); - } - - return 0; -} diff --git a/trunk/fs/proc/inode.c b/trunk/fs/proc/inode.c index 6dcef089e18e..722b9c463111 100644 --- a/trunk/fs/proc/inode.c +++ b/trunk/fs/proc/inode.c @@ -58,11 +58,14 @@ static void de_put(struct proc_dir_entry *de) static void proc_delete_inode(struct inode *inode) { struct proc_dir_entry *de; + struct task_struct *tsk; truncate_inode_pages(&inode->i_data, 0); - /* Stop tracking associated processes */ - put_pid(PROC_I(inode)->pid); + /* Let go of any associated process */ + tsk = PROC_I(inode)->task; + if (tsk) + put_task_struct(tsk); /* Let go of any associated proc directory entry */ de = PROC_I(inode)->pde; @@ -91,8 +94,8 @@ static struct inode *proc_alloc_inode(struct super_block *sb) ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, SLAB_KERNEL); if (!ei) return NULL; - ei->pid = NULL; - ei->fd = 0; + ei->task = NULL; + ei->type = 0; ei->op.proc_get_link = NULL; ei->pde = NULL; inode = &ei->vfs_inode; diff --git a/trunk/fs/proc/internal.h b/trunk/fs/proc/internal.h index 146a434ba944..0502f17b860d 100644 --- a/trunk/fs/proc/internal.h +++ b/trunk/fs/proc/internal.h @@ -37,30 +37,16 @@ extern int proc_tgid_stat(struct task_struct *, char *); extern int proc_pid_status(struct task_struct *, char *); extern int proc_pid_statm(struct task_struct *, char *); -extern struct file_operations proc_maps_operations; -extern struct file_operations proc_numa_maps_operations; -extern struct file_operations proc_smaps_operations; - -extern struct file_operations proc_maps_operations; -extern struct file_operations proc_numa_maps_operations; -extern struct file_operations proc_smaps_operations; - - void free_proc_entry(struct proc_dir_entry *de); int proc_init_inodecache(void); -static inline struct pid *proc_pid(struct inode *inode) -{ - return PROC_I(inode)->pid; -} - -static inline struct task_struct *get_proc_task(struct inode *inode) +static inline struct task_struct *proc_task(struct inode *inode) { - return get_pid_task(proc_pid(inode), PIDTYPE_PID); + return PROC_I(inode)->task; } -static inline int proc_fd(struct inode *inode) +static inline int proc_type(struct inode *inode) { - return PROC_I(inode)->fd; + return PROC_I(inode)->type; } diff --git a/trunk/fs/proc/kcore.c b/trunk/fs/proc/kcore.c index 036d14d83627..17f6e8fa1397 100644 --- a/trunk/fs/proc/kcore.c +++ b/trunk/fs/proc/kcore.c @@ -9,6 +9,7 @@ * Safe accesses to vmalloc/direct-mapped discontiguous areas, Kanoj Sarcar */ +#include #include #include #include diff --git a/trunk/fs/proc/proc_misc.c b/trunk/fs/proc/proc_misc.c index 9f2cfc30f9cf..5c10ea157425 100644 --- a/trunk/fs/proc/proc_misc.c +++ b/trunk/fs/proc/proc_misc.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -119,6 +120,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off, { struct sysinfo i; int len; + struct page_state ps; unsigned long inactive; unsigned long active; unsigned long free; @@ -127,6 +129,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off, struct vmalloc_info vmi; long cached; + get_page_state(&ps); get_zone_counts(&active, &inactive, &free); /* @@ -139,8 +142,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off, allowed = ((totalram_pages - hugetlb_total_pages()) * sysctl_overcommit_ratio / 100) + total_swap_pages; - cached = global_page_state(NR_FILE_PAGES) - - total_swapcache_pages - i.bufferram; + cached = get_page_cache_size() - total_swapcache_pages - i.bufferram; if (cached < 0) cached = 0; @@ -165,14 +167,11 @@ static int meminfo_read_proc(char *page, char **start, off_t off, "SwapFree: %8lu kB\n" "Dirty: %8lu kB\n" "Writeback: %8lu kB\n" - "AnonPages: %8lu kB\n" "Mapped: %8lu kB\n" "Slab: %8lu kB\n" - "PageTables: %8lu kB\n" - "NFS Unstable: %8lu kB\n" - "Bounce: %8lu kB\n" "CommitLimit: %8lu kB\n" "Committed_AS: %8lu kB\n" + "PageTables: %8lu kB\n" "VmallocTotal: %8lu kB\n" "VmallocUsed: %8lu kB\n" "VmallocChunk: %8lu kB\n", @@ -189,16 +188,13 @@ static int meminfo_read_proc(char *page, char **start, off_t off, K(i.freeram-i.freehigh), K(i.totalswap), K(i.freeswap), - K(global_page_state(NR_FILE_DIRTY)), - K(global_page_state(NR_WRITEBACK)), - K(global_page_state(NR_ANON_PAGES)), - K(global_page_state(NR_FILE_MAPPED)), - K(global_page_state(NR_SLAB)), - K(global_page_state(NR_PAGETABLE)), - K(global_page_state(NR_UNSTABLE_NFS)), - K(global_page_state(NR_BOUNCE)), + K(ps.nr_dirty), + K(ps.nr_writeback), + K(ps.nr_mapped), + K(ps.nr_slab), K(allowed), K(committed), + K(ps.nr_page_table_pages), (unsigned long)VMALLOC_TOTAL >> 10, vmi.used >> 10, vmi.largest_chunk >> 10 diff --git a/trunk/fs/proc/root.c b/trunk/fs/proc/root.c index 8901c65caca8..9995356ce73e 100644 --- a/trunk/fs/proc/root.c +++ b/trunk/fs/proc/root.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/fs/proc/task_mmu.c b/trunk/fs/proc/task_mmu.c index 0a163a4f7764..91b7c15ab373 100644 --- a/trunk/fs/proc/task_mmu.c +++ b/trunk/fs/proc/task_mmu.c @@ -75,13 +75,9 @@ int proc_exe_link(struct inode *inode, struct dentry **dentry, struct vfsmount * { struct vm_area_struct * vma; int result = -ENOENT; - struct task_struct *task = get_proc_task(inode); - struct mm_struct * mm = NULL; + struct task_struct *task = proc_task(inode); + struct mm_struct * mm = get_task_mm(task); - if (task) { - mm = get_task_mm(task); - put_task_struct(task); - } if (!mm) goto out; down_read(&mm->mmap_sem); @@ -122,15 +118,9 @@ struct mem_size_stats unsigned long private_dirty; }; -__attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma) -{ - return NULL; -} - static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss) { - struct proc_maps_private *priv = m->private; - struct task_struct *task = priv->task; + struct task_struct *task = m->private; struct vm_area_struct *vma = v; struct mm_struct *mm = vma->vm_mm; struct file *file = vma->vm_file; @@ -163,23 +153,22 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats pad_len_spaces(m, len); seq_path(m, file->f_vfsmnt, file->f_dentry, "\n"); } else { - const char *name = arch_vma_name(vma); - if (!name) { - if (mm) { - if (vma->vm_start <= mm->start_brk && + if (mm) { + if (vma->vm_start <= mm->start_brk && vma->vm_end >= mm->brk) { - name = "[heap]"; - } else if (vma->vm_start <= mm->start_stack && - vma->vm_end >= mm->start_stack) { - name = "[stack]"; - } + pad_len_spaces(m, len); + seq_puts(m, "[heap]"); } else { - name = "[vdso]"; + if (vma->vm_start <= mm->start_stack && + vma->vm_end >= mm->start_stack) { + + pad_len_spaces(m, len); + seq_puts(m, "[stack]"); + } } - } - if (name) { + } else { pad_len_spaces(m, len); - seq_puts(m, name); + seq_puts(m, "[vdso]"); } } seq_putc(m, '\n'); @@ -306,16 +295,12 @@ static int show_smap(struct seq_file *m, void *v) static void *m_start(struct seq_file *m, loff_t *pos) { - struct proc_maps_private *priv = m->private; + struct task_struct *task = m->private; unsigned long last_addr = m->version; struct mm_struct *mm; - struct vm_area_struct *vma, *tail_vma = NULL; + struct vm_area_struct *vma, *tail_vma; loff_t l = *pos; - /* Clear the per syscall fields in priv */ - priv->task = NULL; - priv->tail_vma = NULL; - /* * We remember last_addr rather than next_addr to hit with * mmap_cache most of the time. We have zero last_addr at @@ -326,15 +311,11 @@ static void *m_start(struct seq_file *m, loff_t *pos) if (last_addr == -1UL) return NULL; - priv->task = get_pid_task(priv->pid, PIDTYPE_PID); - if (!priv->task) - return NULL; - - mm = get_task_mm(priv->task); + mm = get_task_mm(task); if (!mm) return NULL; - priv->tail_vma = tail_vma = get_gate_vma(priv->task); + tail_vma = get_gate_vma(task); down_read(&mm->mmap_sem); /* Start with last addr hint */ @@ -369,9 +350,11 @@ static void *m_start(struct seq_file *m, loff_t *pos) return tail_vma; } -static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma) +static void m_stop(struct seq_file *m, void *v) { - if (vma && vma != priv->tail_vma) { + struct task_struct *task = m->private; + struct vm_area_struct *vma = v; + if (vma && vma != get_gate_vma(task)) { struct mm_struct *mm = vma->vm_mm; up_read(&mm->mmap_sem); mmput(mm); @@ -380,103 +363,38 @@ static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma) static void *m_next(struct seq_file *m, void *v, loff_t *pos) { - struct proc_maps_private *priv = m->private; + struct task_struct *task = m->private; struct vm_area_struct *vma = v; - struct vm_area_struct *tail_vma = priv->tail_vma; + struct vm_area_struct *tail_vma = get_gate_vma(task); (*pos)++; if (vma && (vma != tail_vma) && vma->vm_next) return vma->vm_next; - vma_stop(priv, vma); + m_stop(m, v); return (vma != tail_vma)? tail_vma: NULL; } -static void m_stop(struct seq_file *m, void *v) -{ - struct proc_maps_private *priv = m->private; - struct vm_area_struct *vma = v; - - vma_stop(priv, vma); - if (priv->task) - put_task_struct(priv->task); -} - -static struct seq_operations proc_pid_maps_op = { +struct seq_operations proc_pid_maps_op = { .start = m_start, .next = m_next, .stop = m_stop, .show = show_map }; -static struct seq_operations proc_pid_smaps_op = { +struct seq_operations proc_pid_smaps_op = { .start = m_start, .next = m_next, .stop = m_stop, .show = show_smap }; -static int do_maps_open(struct inode *inode, struct file *file, - struct seq_operations *ops) -{ - struct proc_maps_private *priv; - int ret = -ENOMEM; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (priv) { - priv->pid = proc_pid(inode); - ret = seq_open(file, ops); - if (!ret) { - struct seq_file *m = file->private_data; - m->private = priv; - } else { - kfree(priv); - } - } - return ret; -} - -static int maps_open(struct inode *inode, struct file *file) -{ - return do_maps_open(inode, file, &proc_pid_maps_op); -} - -struct file_operations proc_maps_operations = { - .open = maps_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_private, -}; - #ifdef CONFIG_NUMA extern int show_numa_map(struct seq_file *m, void *v); -static struct seq_operations proc_pid_numa_maps_op = { +struct seq_operations proc_pid_numa_maps_op = { .start = m_start, .next = m_next, .stop = m_stop, .show = show_numa_map }; - -static int numa_maps_open(struct inode *inode, struct file *file) -{ - return do_maps_open(inode, file, &proc_pid_numa_maps_op); -} - -struct file_operations proc_numa_maps_operations = { - .open = numa_maps_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_private, -}; #endif - -static int smaps_open(struct inode *inode, struct file *file) -{ - return do_maps_open(inode, file, &proc_pid_smaps_op); -} - -struct file_operations proc_smaps_operations = { - .open = smaps_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_private, -}; diff --git a/trunk/fs/proc/task_nommu.c b/trunk/fs/proc/task_nommu.c index af69f28277b6..8f68827ed10e 100644 --- a/trunk/fs/proc/task_nommu.c +++ b/trunk/fs/proc/task_nommu.c @@ -156,28 +156,9 @@ static void *m_next(struct seq_file *m, void *v, loff_t *pos) { return NULL; } -static struct seq_operations proc_pid_maps_op = { +struct seq_operations proc_pid_maps_op = { .start = m_start, .next = m_next, .stop = m_stop, .show = show_map }; - -static int maps_open(struct inode *inode, struct file *file) -{ - int ret; - ret = seq_open(file, &proc_pid_maps_op); - if (!ret) { - struct seq_file *m = file->private_data; - m->private = NULL; - } - return ret; -} - -struct file_operations proc_maps_operations = { - .open = maps_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - diff --git a/trunk/fs/proc/vmcore.c b/trunk/fs/proc/vmcore.c index d96050728c43..20d4b2237fce 100644 --- a/trunk/fs/proc/vmcore.c +++ b/trunk/fs/proc/vmcore.c @@ -7,6 +7,7 @@ * */ +#include #include #include #include diff --git a/trunk/fs/qnx4/bitmap.c b/trunk/fs/qnx4/bitmap.c index 8425cf6e9624..46efbf52cbec 100644 --- a/trunk/fs/qnx4/bitmap.c +++ b/trunk/fs/qnx4/bitmap.c @@ -13,6 +13,7 @@ * 28-06-1998 by Frank Denis : qnx4_free_inode (to be fixed) . */ +#include #include #include #include diff --git a/trunk/fs/qnx4/dir.c b/trunk/fs/qnx4/dir.c index 0d7103fa0df5..9031948fefd0 100644 --- a/trunk/fs/qnx4/dir.c +++ b/trunk/fs/qnx4/dir.c @@ -11,6 +11,7 @@ * 20-06-1998 by Frank Denis : Linux 2.1.99+ & dcache support. */ +#include #include #include #include diff --git a/trunk/fs/qnx4/fsync.c b/trunk/fs/qnx4/fsync.c index aa3b19544bee..df5bc75d5414 100644 --- a/trunk/fs/qnx4/fsync.c +++ b/trunk/fs/qnx4/fsync.c @@ -10,6 +10,7 @@ * 24-03-1998 by Richard Frowijn : first release. */ +#include #include #include #include diff --git a/trunk/fs/qnx4/inode.c b/trunk/fs/qnx4/inode.c index 5a903491e697..2f24c46f72a1 100644 --- a/trunk/fs/qnx4/inode.c +++ b/trunk/fs/qnx4/inode.c @@ -12,6 +12,7 @@ * 30-06-1998 by Frank Denis : first step to write inodes. */ +#include #include #include #include @@ -449,7 +450,7 @@ static sector_t qnx4_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping,block,qnx4_get_block); } -static const struct address_space_operations qnx4_aops = { +static struct address_space_operations qnx4_aops = { .readpage = qnx4_readpage, .writepage = qnx4_writepage, .sync_page = block_sync_page, diff --git a/trunk/fs/qnx4/namei.c b/trunk/fs/qnx4/namei.c index c3d83f67154a..4af4951d7f54 100644 --- a/trunk/fs/qnx4/namei.c +++ b/trunk/fs/qnx4/namei.c @@ -12,6 +12,7 @@ * 04-07-1998 by Frank Denis : first step for rmdir/unlink. */ +#include #include #include #include diff --git a/trunk/fs/qnx4/truncate.c b/trunk/fs/qnx4/truncate.c index 6437c1c3d1dd..86563ec01b39 100644 --- a/trunk/fs/qnx4/truncate.c +++ b/trunk/fs/qnx4/truncate.c @@ -10,6 +10,7 @@ * 30-06-1998 by Frank DENIS : ugly filler. */ +#include #include #include #include diff --git a/trunk/fs/ramfs/file-mmu.c b/trunk/fs/ramfs/file-mmu.c index 86f14cacf641..00a933eb820c 100644 --- a/trunk/fs/ramfs/file-mmu.c +++ b/trunk/fs/ramfs/file-mmu.c @@ -26,7 +26,7 @@ #include -const struct address_space_operations ramfs_aops = { +struct address_space_operations ramfs_aops = { .readpage = simple_readpage, .prepare_write = simple_prepare_write, .commit_write = simple_commit_write diff --git a/trunk/fs/ramfs/file-nommu.c b/trunk/fs/ramfs/file-nommu.c index 99fffc9e1bfd..f443a84b98a5 100644 --- a/trunk/fs/ramfs/file-nommu.c +++ b/trunk/fs/ramfs/file-nommu.c @@ -27,7 +27,7 @@ static int ramfs_nommu_setattr(struct dentry *, struct iattr *); -const struct address_space_operations ramfs_aops = { +struct address_space_operations ramfs_aops = { .readpage = simple_readpage, .prepare_write = simple_prepare_write, .commit_write = simple_commit_write diff --git a/trunk/fs/ramfs/internal.h b/trunk/fs/ramfs/internal.h index c2bb58e74653..313237631b49 100644 --- a/trunk/fs/ramfs/internal.h +++ b/trunk/fs/ramfs/internal.h @@ -10,6 +10,6 @@ */ -extern const struct address_space_operations ramfs_aops; +extern struct address_space_operations ramfs_aops; extern const struct file_operations ramfs_file_operations; extern struct inode_operations ramfs_file_inode_operations; diff --git a/trunk/fs/reiserfs/bitmap.c b/trunk/fs/reiserfs/bitmap.c index 4a7dbdee1b6d..909f71e9a30f 100644 --- a/trunk/fs/reiserfs/bitmap.c +++ b/trunk/fs/reiserfs/bitmap.c @@ -3,6 +3,7 @@ */ /* Reiserfs block (de)allocator, bitmap-based. */ +#include #include #include #include diff --git a/trunk/fs/reiserfs/dir.c b/trunk/fs/reiserfs/dir.c index 9aabcc0ccd2d..973c819f8033 100644 --- a/trunk/fs/reiserfs/dir.c +++ b/trunk/fs/reiserfs/dir.c @@ -2,6 +2,7 @@ * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README */ +#include #include #include #include diff --git a/trunk/fs/reiserfs/do_balan.c b/trunk/fs/reiserfs/do_balan.c index fba304e64de8..b2264ba3cc56 100644 --- a/trunk/fs/reiserfs/do_balan.c +++ b/trunk/fs/reiserfs/do_balan.c @@ -15,6 +15,7 @@ ** **/ +#include #include #include #include diff --git a/trunk/fs/reiserfs/file.c b/trunk/fs/reiserfs/file.c index 752cea12e30f..cf6e1cf40351 100644 --- a/trunk/fs/reiserfs/file.c +++ b/trunk/fs/reiserfs/file.c @@ -1560,6 +1560,12 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t return res; } +static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user * buf, + size_t count, loff_t pos) +{ + return generic_file_aio_write(iocb, buf, count, pos); +} + const struct file_operations reiserfs_file_operations = { .read = generic_file_read, .write = reiserfs_file_write, @@ -1569,7 +1575,7 @@ const struct file_operations reiserfs_file_operations = { .fsync = reiserfs_sync_file, .sendfile = generic_file_sendfile, .aio_read = generic_file_aio_read, - .aio_write = generic_file_aio_write, + .aio_write = reiserfs_aio_write, .splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, }; diff --git a/trunk/fs/reiserfs/fix_node.c b/trunk/fs/reiserfs/fix_node.c index 6d0e554daa9d..5600d3d60cf7 100644 --- a/trunk/fs/reiserfs/fix_node.c +++ b/trunk/fs/reiserfs/fix_node.c @@ -34,6 +34,7 @@ ** **/ +#include #include #include #include diff --git a/trunk/fs/reiserfs/ibalance.c b/trunk/fs/reiserfs/ibalance.c index de391a82b999..6c5a726fd34b 100644 --- a/trunk/fs/reiserfs/ibalance.c +++ b/trunk/fs/reiserfs/ibalance.c @@ -2,6 +2,7 @@ * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README */ +#include #include #include #include diff --git a/trunk/fs/reiserfs/inode.c b/trunk/fs/reiserfs/inode.c index 12dfdcfbee3d..9857e50f85e7 100644 --- a/trunk/fs/reiserfs/inode.c +++ b/trunk/fs/reiserfs/inode.c @@ -2,6 +2,7 @@ * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README */ +#include #include #include #include @@ -2932,11 +2933,6 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) } if (error) goto out; - /* - * file size is changed, ctime and mtime are - * to be updated - */ - attr->ia_valid |= (ATTR_MTIME | ATTR_CTIME); } } @@ -3000,7 +2996,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) return error; } -const struct address_space_operations reiserfs_address_space_operations = { +struct address_space_operations reiserfs_address_space_operations = { .writepage = reiserfs_writepage, .readpage = reiserfs_readpage, .readpages = reiserfs_readpages, diff --git a/trunk/fs/reiserfs/journal.c b/trunk/fs/reiserfs/journal.c index 9b3672d69367..1b73529b8099 100644 --- a/trunk/fs/reiserfs/journal.c +++ b/trunk/fs/reiserfs/journal.c @@ -34,6 +34,7 @@ ** from within kupdate, it will ignore the immediate flag */ +#include #include #include @@ -833,7 +834,8 @@ static int write_ordered_buffers(spinlock_t * lock, get_bh(bh); if (test_set_buffer_locked(bh)) { if (!buffer_dirty(bh)) { - list_move(&jh->list, &tmp); + list_del_init(&jh->list); + list_add(&jh->list, &tmp); goto loop_next; } spin_unlock(lock); @@ -853,7 +855,8 @@ static int write_ordered_buffers(spinlock_t * lock, ret = -EIO; } if (buffer_dirty(bh)) { - list_move(&jh->list, &tmp); + list_del_init(&jh->list); + list_add(&jh->list, &tmp); add_to_chunk(&chunk, bh, lock, write_ordered_chunk); } else { reiserfs_free_jh(bh); diff --git a/trunk/fs/reiserfs/lbalance.c b/trunk/fs/reiserfs/lbalance.c index 281f8061ac58..2533c1f64aba 100644 --- a/trunk/fs/reiserfs/lbalance.c +++ b/trunk/fs/reiserfs/lbalance.c @@ -2,6 +2,7 @@ * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README */ +#include #include #include #include diff --git a/trunk/fs/reiserfs/namei.c b/trunk/fs/reiserfs/namei.c index c61710e49c62..284f7852de8b 100644 --- a/trunk/fs/reiserfs/namei.c +++ b/trunk/fs/reiserfs/namei.c @@ -11,6 +11,7 @@ * NO WARRANTY */ +#include #include #include #include diff --git a/trunk/fs/reiserfs/objectid.c b/trunk/fs/reiserfs/objectid.c index 65feba4deb69..f62590aa9c95 100644 --- a/trunk/fs/reiserfs/objectid.c +++ b/trunk/fs/reiserfs/objectid.c @@ -2,6 +2,7 @@ * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README */ +#include #include #include #include diff --git a/trunk/fs/reiserfs/prints.c b/trunk/fs/reiserfs/prints.c index bc808a91eeaa..27bd3a1df2ad 100644 --- a/trunk/fs/reiserfs/prints.c +++ b/trunk/fs/reiserfs/prints.c @@ -2,6 +2,7 @@ * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README */ +#include #include #include #include diff --git a/trunk/fs/reiserfs/procfs.c b/trunk/fs/reiserfs/procfs.c index 5d8a8cfebc70..731688e1cfe3 100644 --- a/trunk/fs/reiserfs/procfs.c +++ b/trunk/fs/reiserfs/procfs.c @@ -10,6 +10,7 @@ /* $Id: procfs.c,v 1.1.8.2 2001/07/15 17:08:42 god Exp $ */ +#include #include #include #include diff --git a/trunk/fs/reiserfs/stree.c b/trunk/fs/reiserfs/stree.c index 8b9b13127136..d2b25e1ba6e9 100644 --- a/trunk/fs/reiserfs/stree.c +++ b/trunk/fs/reiserfs/stree.c @@ -49,6 +49,7 @@ * reiserfs_insert_item */ +#include #include #include #include diff --git a/trunk/fs/reiserfs/super.c b/trunk/fs/reiserfs/super.c index 28eb3c886034..00f1321e9209 100644 --- a/trunk/fs/reiserfs/super.c +++ b/trunk/fs/reiserfs/super.c @@ -11,6 +11,7 @@ * NO WARRANTY */ +#include #include #include #include diff --git a/trunk/fs/reiserfs/tail_conversion.c b/trunk/fs/reiserfs/tail_conversion.c index 36f108fc1cf5..196e971c03c9 100644 --- a/trunk/fs/reiserfs/tail_conversion.c +++ b/trunk/fs/reiserfs/tail_conversion.c @@ -2,6 +2,7 @@ * Copyright 1999 Hans Reiser, see reiserfs/README for licensing and copyright details */ +#include #include #include #include diff --git a/trunk/fs/romfs/inode.c b/trunk/fs/romfs/inode.c index 22eed61ebf69..283fbc6b8eea 100644 --- a/trunk/fs/romfs/inode.c +++ b/trunk/fs/romfs/inode.c @@ -459,7 +459,7 @@ romfs_readpage(struct file *file, struct page * page) /* Mapping from our types to the kernel */ -static const struct address_space_operations romfs_aops = { +static struct address_space_operations romfs_aops = { .readpage = romfs_readpage }; diff --git a/trunk/fs/smbfs/file.c b/trunk/fs/smbfs/file.c index dae67048baba..ed9a24d19d7d 100644 --- a/trunk/fs/smbfs/file.c +++ b/trunk/fs/smbfs/file.c @@ -306,7 +306,7 @@ static int smb_commit_write(struct file *file, struct page *page, return status; } -const struct address_space_operations smb_file_aops = { +struct address_space_operations smb_file_aops = { .readpage = smb_readpage, .writepage = smb_writepage, .prepare_write = smb_prepare_write, diff --git a/trunk/fs/smbfs/inode.c b/trunk/fs/smbfs/inode.c index a1ed657c3c84..506ff87c1d4b 100644 --- a/trunk/fs/smbfs/inode.c +++ b/trunk/fs/smbfs/inode.c @@ -7,6 +7,7 @@ * Please add a note about your changes to smbfs in the ChangeLog file. */ +#include #include #include #include diff --git a/trunk/fs/smbfs/proto.h b/trunk/fs/smbfs/proto.h index 34fb462b2379..972ed7dad388 100644 --- a/trunk/fs/smbfs/proto.h +++ b/trunk/fs/smbfs/proto.h @@ -63,7 +63,7 @@ extern int smb_revalidate_inode(struct dentry *dentry); extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat); extern int smb_notify_change(struct dentry *dentry, struct iattr *attr); /* file.c */ -extern const struct address_space_operations smb_file_aops; +extern struct address_space_operations smb_file_aops; extern const struct file_operations smb_file_operations; extern struct inode_operations smb_file_inode_operations; /* ioctl.c */ diff --git a/trunk/fs/smbfs/request.c b/trunk/fs/smbfs/request.c index c8e96195b96e..c71dd2760d32 100644 --- a/trunk/fs/smbfs/request.c +++ b/trunk/fs/smbfs/request.c @@ -400,7 +400,8 @@ static int smb_request_send_req(struct smb_request *req) if (!(req->rq_flags & SMB_REQ_TRANSMITTED)) goto out; - list_move_tail(&req->rq_queue, &server->recvq); + list_del_init(&req->rq_queue); + list_add_tail(&req->rq_queue, &server->recvq); result = 1; out: return result; @@ -434,7 +435,8 @@ int smb_request_send_server(struct smb_sb_info *server) result = smb_request_send_req(req); if (result < 0) { server->conn_error = result; - list_move(&req->rq_queue, &server->xmitq); + list_del_init(&req->rq_queue); + list_add(&req->rq_queue, &server->xmitq); result = -EIO; goto out; } diff --git a/trunk/fs/smbfs/smbiod.c b/trunk/fs/smbfs/smbiod.c index e67540441288..3f71384020cb 100644 --- a/trunk/fs/smbfs/smbiod.c +++ b/trunk/fs/smbfs/smbiod.c @@ -5,6 +5,7 @@ * Copyright (C) 2001, Urban Widmark */ +#include #include #include @@ -192,7 +193,8 @@ int smbiod_retry(struct smb_sb_info *server) if (req->rq_flags & SMB_REQ_RETRY) { /* must move the request to the xmitq */ VERBOSE("retrying request %p on recvq\n", req); - list_move(&req->rq_queue, &server->xmitq); + list_del(&req->rq_queue); + list_add(&req->rq_queue, &server->xmitq); continue; } #endif diff --git a/trunk/fs/stat.c b/trunk/fs/stat.c index 3a44dcf97da2..0f282face322 100644 --- a/trunk/fs/stat.c +++ b/trunk/fs/stat.c @@ -4,6 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ +#include #include #include #include diff --git a/trunk/fs/super.c b/trunk/fs/super.c index 9b780c42d845..8a669f6f3f52 100644 --- a/trunk/fs/super.c +++ b/trunk/fs/super.c @@ -20,6 +20,7 @@ * Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000 */ +#include #include #include #include diff --git a/trunk/fs/sysfs/dir.c b/trunk/fs/sysfs/dir.c index 61c42430cba3..610b5bdbe75b 100644 --- a/trunk/fs/sysfs/dir.c +++ b/trunk/fs/sysfs/dir.c @@ -430,9 +430,10 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) i++; /* fallthrough */ default: - if (filp->f_pos == 2) - list_move(q, &parent_sd->s_children); - + if (filp->f_pos == 2) { + list_del(q); + list_add(q, &parent_sd->s_children); + } for (p=q->next; p!= &parent_sd->s_children; p=p->next) { struct sysfs_dirent *next; const char * name; @@ -454,7 +455,8 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) dt_type(next)) < 0) return 0; - list_move(q, p); + list_del(q); + list_add(q, p); p = q; filp->f_pos++; } diff --git a/trunk/fs/sysfs/inode.c b/trunk/fs/sysfs/inode.c index 5e0e31cc46f5..f0b347bd12ca 100644 --- a/trunk/fs/sysfs/inode.c +++ b/trunk/fs/sysfs/inode.c @@ -16,7 +16,7 @@ extern struct super_block * sysfs_sb; -static const struct address_space_operations sysfs_aops = { +static struct address_space_operations sysfs_aops = { .readpage = simple_readpage, .prepare_write = simple_prepare_write, .commit_write = simple_commit_write diff --git a/trunk/fs/sysv/itree.c b/trunk/fs/sysv/itree.c index f2bcccd1d6fc..86f5f8d43d0f 100644 --- a/trunk/fs/sysv/itree.c +++ b/trunk/fs/sysv/itree.c @@ -465,7 +465,7 @@ static sector_t sysv_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping,block,get_block); } -const struct address_space_operations sysv_aops = { +struct address_space_operations sysv_aops = { .readpage = sysv_readpage, .writepage = sysv_writepage, .sync_page = block_sync_page, diff --git a/trunk/fs/sysv/sysv.h b/trunk/fs/sysv/sysv.h index 9dcc82120935..393a480e4deb 100644 --- a/trunk/fs/sysv/sysv.h +++ b/trunk/fs/sysv/sysv.h @@ -161,7 +161,7 @@ extern struct inode_operations sysv_dir_inode_operations; extern struct inode_operations sysv_fast_symlink_inode_operations; extern const struct file_operations sysv_file_operations; extern const struct file_operations sysv_dir_operations; -extern const struct address_space_operations sysv_aops; +extern struct address_space_operations sysv_aops; extern struct super_operations sysv_sops; extern struct dentry_operations sysv_dentry_operations; diff --git a/trunk/fs/udf/file.c b/trunk/fs/udf/file.c index a59e5f33daf6..e34b00e303f1 100644 --- a/trunk/fs/udf/file.c +++ b/trunk/fs/udf/file.c @@ -95,7 +95,7 @@ static int udf_adinicb_commit_write(struct file *file, struct page *page, unsign return 0; } -const struct address_space_operations udf_adinicb_aops = { +struct address_space_operations udf_adinicb_aops = { .readpage = udf_adinicb_readpage, .writepage = udf_adinicb_writepage, .sync_page = block_sync_page, diff --git a/trunk/fs/udf/inode.c b/trunk/fs/udf/inode.c index 605f5111b6d8..2983afd5e7fd 100644 --- a/trunk/fs/udf/inode.c +++ b/trunk/fs/udf/inode.c @@ -132,7 +132,7 @@ static sector_t udf_bmap(struct address_space *mapping, sector_t block) return generic_block_bmap(mapping,block,udf_get_block); } -const struct address_space_operations udf_aops = { +struct address_space_operations udf_aops = { .readpage = udf_readpage, .writepage = udf_writepage, .sync_page = block_sync_page, diff --git a/trunk/fs/udf/super.c b/trunk/fs/udf/super.c index 4df822c881b6..44fe2cb0bbb2 100644 --- a/trunk/fs/udf/super.c +++ b/trunk/fs/udf/super.c @@ -40,6 +40,7 @@ #include "udfdecl.h" +#include #include #include #include diff --git a/trunk/fs/udf/symlink.c b/trunk/fs/udf/symlink.c index ba068a786563..674bb40edc83 100644 --- a/trunk/fs/udf/symlink.c +++ b/trunk/fs/udf/symlink.c @@ -113,6 +113,6 @@ static int udf_symlink_filler(struct file *file, struct page *page) /* * symlinks can't do much... */ -const struct address_space_operations udf_symlink_aops = { +struct address_space_operations udf_symlink_aops = { .readpage = udf_symlink_filler, }; diff --git a/trunk/fs/udf/udfdecl.h b/trunk/fs/udf/udfdecl.h index 1033b7cf2939..023e19ba5a2e 100644 --- a/trunk/fs/udf/udfdecl.h +++ b/trunk/fs/udf/udfdecl.h @@ -6,6 +6,7 @@ #include "osta_udf.h" #include +#include #include #include #include @@ -46,9 +47,9 @@ extern struct inode_operations udf_dir_inode_operations; extern const struct file_operations udf_dir_operations; extern struct inode_operations udf_file_inode_operations; extern const struct file_operations udf_file_operations; -extern const struct address_space_operations udf_aops; -extern const struct address_space_operations udf_adinicb_aops; -extern const struct address_space_operations udf_symlink_aops; +extern struct address_space_operations udf_aops; +extern struct address_space_operations udf_adinicb_aops; +extern struct address_space_operations udf_symlink_aops; struct udf_fileident_bh { diff --git a/trunk/fs/ufs/balloc.c b/trunk/fs/ufs/balloc.c index b01804baa120..95b878e5c7a0 100644 --- a/trunk/fs/ufs/balloc.c +++ b/trunk/fs/ufs/balloc.c @@ -217,6 +217,48 @@ void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count) return; } +static struct page *ufs_get_locked_page(struct address_space *mapping, + unsigned long index) +{ + struct page *page; + +try_again: + page = find_lock_page(mapping, index); + if (!page) { + page = read_cache_page(mapping, index, + (filler_t*)mapping->a_ops->readpage, + NULL); + if (IS_ERR(page)) { + printk(KERN_ERR "ufs_change_blocknr: " + "read_cache_page error: ino %lu, index: %lu\n", + mapping->host->i_ino, index); + goto out; + } + + lock_page(page); + + if (!PageUptodate(page) || PageError(page)) { + unlock_page(page); + page_cache_release(page); + + printk(KERN_ERR "ufs_change_blocknr: " + "can not read page: ino %lu, index: %lu\n", + mapping->host->i_ino, index); + + page = ERR_PTR(-EIO); + goto out; + } + } + + if (unlikely(!page->mapping || !page_has_buffers(page))) { + unlock_page(page); + page_cache_release(page); + goto try_again;/*we really need these buffers*/ + } +out: + return page; +} + /* * Modify inode page cache in such way: * have - blocks with b_blocknr equal to oldb...oldb+count-1 @@ -269,8 +311,10 @@ static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk, set_page_dirty(page); - if (likely(cur_index != index)) - ufs_put_locked_page(page); + if (likely(cur_index != index)) { + unlock_page(page); + page_cache_release(page); + } } UFSD("EXIT\n"); } diff --git a/trunk/fs/ufs/file.c b/trunk/fs/ufs/file.c index a9c6e5f04fae..0e5001512a9d 100644 --- a/trunk/fs/ufs/file.c +++ b/trunk/fs/ufs/file.c @@ -60,3 +60,7 @@ const struct file_operations ufs_file_operations = { .fsync = ufs_sync_file, .sendfile = generic_file_sendfile, }; + +struct inode_operations ufs_file_inode_operations = { + .truncate = ufs_truncate, +}; diff --git a/trunk/fs/ufs/inode.c b/trunk/fs/ufs/inode.c index e7c8615beb65..f2dbdf5a8769 100644 --- a/trunk/fs/ufs/inode.c +++ b/trunk/fs/ufs/inode.c @@ -98,9 +98,7 @@ static u64 ufs_frag_map(struct inode *inode, sector_t frag) u64 temp = 0L; UFSD(": frag = %llu depth = %d\n", (unsigned long long)frag, depth); - UFSD(": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n", - uspi->s_fpbshift, uspi->s_apbmask, - (unsigned long long)mask); + UFSD(": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask); if (depth == 0) return 0; @@ -431,7 +429,7 @@ int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head if (!create) { phys64 = ufs_frag_map(inode, fragment); - UFSD("phys64 = %llu\n", (unsigned long long)phys64); + UFSD("phys64 = %llu \n",phys64); if (phys64) map_bh(bh_result, sb, phys64); return 0; @@ -576,7 +574,7 @@ static sector_t ufs_bmap(struct address_space *mapping, sector_t block) { return generic_block_bmap(mapping,block,ufs_getfrag_block); } -const struct address_space_operations ufs_aops = { +struct address_space_operations ufs_aops = { .readpage = ufs_readpage, .writepage = ufs_writepage, .sync_page = block_sync_page, @@ -607,12 +605,39 @@ static void ufs_set_inode_ops(struct inode *inode) ufs_get_inode_dev(inode->i_sb, UFS_I(inode))); } -static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) +void ufs_read_inode (struct inode * inode) { struct ufs_inode_info *ufsi = UFS_I(inode); - struct super_block *sb = inode->i_sb; + struct super_block * sb; + struct ufs_sb_private_info * uspi; + struct ufs_inode * ufs_inode; + struct ufs2_inode *ufs2_inode; + struct buffer_head * bh; mode_t mode; unsigned i; + unsigned flags; + + UFSD("ENTER, ino %lu\n", inode->i_ino); + + sb = inode->i_sb; + uspi = UFS_SB(sb)->s_uspi; + flags = UFS_SB(sb)->s_flags; + + if (inode->i_ino < UFS_ROOTINO || + inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { + ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino); + goto bad_inode; + } + + bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); + if (!bh) { + ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino); + goto bad_inode; + } + if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) + goto ufs2_inode; + + ufs_inode = (struct ufs_inode *) (bh->b_data + sizeof(struct ufs_inode) * ufs_inotofsbo(inode->i_ino)); /* * Copy data to the in-core inode. @@ -636,11 +661,14 @@ static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) inode->i_atime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0; inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks); + inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat) */ + inode->i_version++; ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags); ufsi->i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen); ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); - + ufsi->i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; + ufsi->i_dir_start_lookup = 0; if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) @@ -649,16 +677,24 @@ static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode) for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i]; } -} + ufsi->i_osync = 0; -static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) -{ - struct ufs_inode_info *ufsi = UFS_I(inode); - struct super_block *sb = inode->i_sb; - mode_t mode; - unsigned i; + ufs_set_inode_ops(inode); + + brelse (bh); + + UFSD("EXIT\n"); + return; + +bad_inode: + make_bad_inode(inode); + return; +ufs2_inode : UFSD("Reading ufs2 inode, ino %lu\n", inode->i_ino); + + ufs2_inode = (struct ufs2_inode *)(bh->b_data + sizeof(struct ufs2_inode) * ufs_inotofsbo(inode->i_ino)); + /* * Copy data to the in-core inode. */ @@ -681,64 +717,26 @@ static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode) inode->i_atime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0; inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks); + inode->i_blksize = PAGE_SIZE; /*This is the optimal IO size(for stat)*/ + + inode->i_version++; ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags); ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen); /* ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow); ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag); */ + ufsi->i_lastfrag= (inode->i_size + uspi->s_fsize- 1) >> uspi->s_fshift; if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) { for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++) ufsi->i_u1.u2_i_data[i] = ufs2_inode->ui_u2.ui_addr.ui_db[i]; - } else { + } + else { for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++) ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i]; } -} - -void ufs_read_inode(struct inode * inode) -{ - struct ufs_inode_info *ufsi = UFS_I(inode); - struct super_block * sb; - struct ufs_sb_private_info * uspi; - struct buffer_head * bh; - - UFSD("ENTER, ino %lu\n", inode->i_ino); - - sb = inode->i_sb; - uspi = UFS_SB(sb)->s_uspi; - - if (inode->i_ino < UFS_ROOTINO || - inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) { - ufs_warning(sb, "ufs_read_inode", "bad inode number (%lu)\n", - inode->i_ino); - goto bad_inode; - } - - bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino)); - if (!bh) { - ufs_warning(sb, "ufs_read_inode", "unable to read inode %lu\n", - inode->i_ino); - goto bad_inode; - } - if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) { - struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data; - - ufs2_read_inode(inode, - ufs2_inode + ufs_inotofsbo(inode->i_ino)); - } else { - struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data; - - ufs1_read_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino)); - } - - inode->i_blksize = PAGE_SIZE;/*This is the optimal IO size (for stat)*/ - inode->i_version++; - ufsi->i_lastfrag = - (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift; - ufsi->i_dir_start_lookup = 0; ufsi->i_osync = 0; ufs_set_inode_ops(inode); @@ -747,9 +745,6 @@ void ufs_read_inode(struct inode * inode) UFSD("EXIT\n"); return; - -bad_inode: - make_bad_inode(inode); } static int ufs_update_inode(struct inode * inode, int do_sync) @@ -843,17 +838,14 @@ int ufs_sync_inode (struct inode *inode) void ufs_delete_inode (struct inode * inode) { - loff_t old_i_size; - truncate_inode_pages(&inode->i_data, 0); /*UFS_I(inode)->i_dtime = CURRENT_TIME;*/ lock_kernel(); mark_inode_dirty(inode); ufs_update_inode(inode, IS_SYNC(inode)); - old_i_size = inode->i_size; inode->i_size = 0; - if (inode->i_blocks && ufs_truncate(inode, old_i_size)) - ufs_warning(inode->i_sb, __FUNCTION__, "ufs_truncate failed\n"); + if (inode->i_blocks) + ufs_truncate (inode); ufs_free_inode (inode); unlock_kernel(); } diff --git a/trunk/fs/ufs/super.c b/trunk/fs/ufs/super.c index 19a99726e58d..74ef5e9bedff 100644 --- a/trunk/fs/ufs/super.c +++ b/trunk/fs/ufs/super.c @@ -64,6 +64,7 @@ */ +#include #include #include diff --git a/trunk/fs/ufs/truncate.c b/trunk/fs/ufs/truncate.c index c9b55872079b..3c3b301f8701 100644 --- a/trunk/fs/ufs/truncate.c +++ b/trunk/fs/ufs/truncate.c @@ -369,97 +369,24 @@ static int ufs_trunc_tindirect (struct inode * inode) UFSD("EXIT\n"); return retry; } - -static int ufs_alloc_lastblock(struct inode *inode) -{ - int err = 0; - struct address_space *mapping = inode->i_mapping; - struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; - struct ufs_inode_info *ufsi = UFS_I(inode); - unsigned lastfrag, i, end; - struct page *lastpage; - struct buffer_head *bh; - - lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; - - if (!lastfrag) { - ufsi->i_lastfrag = 0; - goto out; - } - lastfrag--; - - lastpage = ufs_get_locked_page(mapping, lastfrag >> - (PAGE_CACHE_SHIFT - inode->i_blkbits)); - if (IS_ERR(lastpage)) { - err = -EIO; - goto out; - } - - end = lastfrag & ((1 << (PAGE_CACHE_SHIFT - inode->i_blkbits)) - 1); - bh = page_buffers(lastpage); - for (i = 0; i < end; ++i) - bh = bh->b_this_page; - - if (!buffer_mapped(bh)) { - err = ufs_getfrag_block(inode, lastfrag, bh, 1); - - if (unlikely(err)) - goto out_unlock; - - if (buffer_new(bh)) { - clear_buffer_new(bh); - unmap_underlying_metadata(bh->b_bdev, - bh->b_blocknr); - /* - * we do not zeroize fragment, because of - * if it maped to hole, it already contains zeroes - */ - set_buffer_uptodate(bh); - mark_buffer_dirty(bh); - set_page_dirty(lastpage); - } - } -out_unlock: - ufs_put_locked_page(lastpage); -out: - return err; -} - -int ufs_truncate(struct inode *inode, loff_t old_i_size) + +void ufs_truncate (struct inode * inode) { struct ufs_inode_info *ufsi = UFS_I(inode); - struct super_block *sb = inode->i_sb; - struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; - int retry, err = 0; + struct super_block * sb; + struct ufs_sb_private_info * uspi; + int retry; UFSD("ENTER\n"); + sb = inode->i_sb; + uspi = UFS_SB(sb)->s_uspi; - if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || - S_ISLNK(inode->i_mode))) - return -EINVAL; + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))) + return; if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) - return -EPERM; - - if (inode->i_size > old_i_size) { - /* - * if we expand file we should care about - * allocation of block for last byte first of all - */ - err = ufs_alloc_lastblock(inode); - - if (err) { - i_size_write(inode, old_i_size); - goto out; - } - /* - * go away, because of we expand file, and we do not - * need free blocks, and zeroizes page - */ - lock_kernel(); - goto almost_end; - } + return; - block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); + block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); lock_kernel(); while (1) { @@ -477,58 +404,9 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) yield(); } - if (inode->i_size < old_i_size) { - /* - * now we should have enough space - * to allocate block for last byte - */ - err = ufs_alloc_lastblock(inode); - if (err) - /* - * looks like all the same - we have no space, - * but we truncate file already - */ - inode->i_size = (ufsi->i_lastfrag - 1) * uspi->s_fsize; - } -almost_end: inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; + ufsi->i_lastfrag = DIRECT_FRAGMENT; unlock_kernel(); mark_inode_dirty(inode); -out: - UFSD("EXIT: err %d\n", err); - return err; -} - - -/* - * We don't define our `inode->i_op->truncate', and call it here, - * because of: - * - there is no way to know old size - * - there is no way inform user about error, if it happens in `truncate' - */ -static int ufs_setattr(struct dentry *dentry, struct iattr *attr) -{ - struct inode *inode = dentry->d_inode; - unsigned int ia_valid = attr->ia_valid; - int error; - - error = inode_change_ok(inode, attr); - if (error) - return error; - - if (ia_valid & ATTR_SIZE && - attr->ia_size != i_size_read(inode)) { - loff_t old_i_size = inode->i_size; - error = vmtruncate(inode, attr->ia_size); - if (error) - return error; - error = ufs_truncate(inode, old_i_size); - if (error) - return error; - } - return inode_setattr(inode, attr); + UFSD("EXIT\n"); } - -struct inode_operations ufs_file_inode_operations = { - .setattr = ufs_setattr, -}; diff --git a/trunk/fs/ufs/util.c b/trunk/fs/ufs/util.c index 337cf2c46d10..a2f13f45708b 100644 --- a/trunk/fs/ufs/util.c +++ b/trunk/fs/ufs/util.c @@ -233,57 +233,3 @@ ufs_set_inode_dev(struct super_block *sb, struct ufs_inode_info *ufsi, dev_t dev else ufsi->i_u1.i_data[0] = fs32; } - -/** - * ufs_get_locked_page() - locate, pin and lock a pagecache page, if not exist - * read it from disk. - * @mapping: the address_space to search - * @index: the page index - * - * Locates the desired pagecache page, if not exist we'll read it, - * locks it, increments its reference - * count and returns its address. - * - */ - -struct page *ufs_get_locked_page(struct address_space *mapping, - pgoff_t index) -{ - struct page *page; - -try_again: - page = find_lock_page(mapping, index); - if (!page) { - page = read_cache_page(mapping, index, - (filler_t*)mapping->a_ops->readpage, - NULL); - if (IS_ERR(page)) { - printk(KERN_ERR "ufs_change_blocknr: " - "read_cache_page error: ino %lu, index: %lu\n", - mapping->host->i_ino, index); - goto out; - } - - lock_page(page); - - if (!PageUptodate(page) || PageError(page)) { - unlock_page(page); - page_cache_release(page); - - printk(KERN_ERR "ufs_change_blocknr: " - "can not read page: ino %lu, index: %lu\n", - mapping->host->i_ino, index); - - page = ERR_PTR(-EIO); - goto out; - } - } - - if (unlikely(!page->mapping || !page_has_buffers(page))) { - unlock_page(page); - page_cache_release(page); - goto try_again;/*we really need these buffers*/ - } -out: - return page; -} diff --git a/trunk/fs/ufs/util.h b/trunk/fs/ufs/util.h index 28fce6c239b5..406981fff5e7 100644 --- a/trunk/fs/ufs/util.h +++ b/trunk/fs/ufs/util.h @@ -251,14 +251,6 @@ extern void _ubh_ubhcpymem_(struct ufs_sb_private_info *, unsigned char *, struc #define ubh_memcpyubh(ubh,mem,size) _ubh_memcpyubh_(uspi,ubh,mem,size) extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head *, unsigned char *, unsigned); -/* This functions works with cache pages*/ -extern struct page *ufs_get_locked_page(struct address_space *mapping, - pgoff_t index); -static inline void ufs_put_locked_page(struct page *page) -{ - unlock_page(page); - page_cache_release(page); -} /* diff --git a/trunk/fs/xfs/linux-2.6/xfs_aops.c b/trunk/fs/xfs/linux-2.6/xfs_aops.c index c40f81ba9b13..3e807b828e22 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_aops.c +++ b/trunk/fs/xfs/linux-2.6/xfs_aops.c @@ -1454,7 +1454,7 @@ xfs_vm_invalidatepage( block_invalidatepage(page, offset); } -const struct address_space_operations xfs_address_space_operations = { +struct address_space_operations xfs_address_space_operations = { .readpage = xfs_vm_readpage, .readpages = xfs_vm_readpages, .writepage = xfs_vm_writepage, diff --git a/trunk/fs/xfs/linux-2.6/xfs_aops.h b/trunk/fs/xfs/linux-2.6/xfs_aops.h index 2244e516b66a..706d8c781b8a 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_aops.h +++ b/trunk/fs/xfs/linux-2.6/xfs_aops.h @@ -40,7 +40,7 @@ typedef struct xfs_ioend { struct work_struct io_work; /* xfsdatad work queue */ } xfs_ioend_t; -extern const struct address_space_operations xfs_address_space_operations; +extern struct address_space_operations xfs_address_space_operations; extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); #endif /* __XFS_AOPS_H__ */ diff --git a/trunk/fs/xfs/linux-2.6/xfs_buf.c b/trunk/fs/xfs/linux-2.6/xfs_buf.c index 2af528dcfb04..26fed0756f01 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_buf.c +++ b/trunk/fs/xfs/linux-2.6/xfs_buf.c @@ -1520,7 +1520,7 @@ xfs_mapping_buftarg( struct backing_dev_info *bdi; struct inode *inode; struct address_space *mapping; - static const struct address_space_operations mapping_aops = { + static struct address_space_operations mapping_aops = { .sync_page = block_sync_page, .migratepage = fail_migrate_page, }; diff --git a/trunk/fs/xfs/linux-2.6/xfs_buf.h b/trunk/fs/xfs/linux-2.6/xfs_buf.h index ceda3a2859d2..4dd6592d5a4c 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_buf.h +++ b/trunk/fs/xfs/linux-2.6/xfs_buf.h @@ -18,6 +18,7 @@ #ifndef __XFS_BUF_H__ #define __XFS_BUF_H__ +#include #include #include #include diff --git a/trunk/fs/xfs/linux-2.6/xfs_ioctl32.c b/trunk/fs/xfs/linux-2.6/xfs_ioctl32.c index 270db0f3861d..601f01c92f7f 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/trunk/fs/xfs/linux-2.6/xfs_ioctl32.c @@ -15,6 +15,7 @@ * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include diff --git a/trunk/fs/xfs/linux-2.6/xfs_iops.c b/trunk/fs/xfs/linux-2.6/xfs_iops.c index d9180020de63..12810baeb5d4 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_iops.c +++ b/trunk/fs/xfs/linux-2.6/xfs_iops.c @@ -419,15 +419,16 @@ xfs_vn_link( int error; ip = old_dentry->d_inode; /* inode being linked to */ + if (S_ISDIR(ip->i_mode)) + return -EPERM; + tdvp = vn_from_inode(dir); vp = vn_from_inode(ip); - VN_HOLD(vp); error = bhv_vop_link(tdvp, vp, dentry, NULL); - if (unlikely(error)) { - VN_RELE(vp); - } else { + if (likely(!error)) { VMODIFY(tdvp); + VN_HOLD(vp); xfs_validate_fields(ip, &vattr); d_instantiate(dentry, ip); } diff --git a/trunk/fs/xfs/linux-2.6/xfs_linux.h b/trunk/fs/xfs/linux-2.6/xfs_linux.h index 8c021dc57d1f..aa26ab906c88 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_linux.h +++ b/trunk/fs/xfs/linux-2.6/xfs_linux.h @@ -19,6 +19,7 @@ #define __XFS_LINUX__ #include +#include /* * Some types are conditional depending on the target system. @@ -139,7 +140,9 @@ BUFFER_FNS(PrivateStart, unwritten); #define current_pid() (current->pid) #define current_fsuid(cred) (current->fsuid) #define current_fsgid(cred) (current->fsgid) +#define current_set_flags(f) (current->flags |= (f)) #define current_test_flags(f) (current->flags & (f)) +#define current_clear_flags(f) (current->flags & ~(f)) #define current_set_flags_nested(sp, f) \ (*(sp) = current->flags, current->flags |= (f)) #define current_clear_flags_nested(sp, f) \ diff --git a/trunk/fs/xfs/linux-2.6/xfs_vnode.h b/trunk/fs/xfs/linux-2.6/xfs_vnode.h index c42b3221b20c..35c6a01963a7 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_vnode.h +++ b/trunk/fs/xfs/linux-2.6/xfs_vnode.h @@ -93,7 +93,7 @@ typedef enum { */ static inline struct bhv_vnode *vn_from_inode(struct inode *inode) { - return container_of(inode, bhv_vnode_t, v_inode); + return (bhv_vnode_t *)list_entry(inode, bhv_vnode_t, v_inode); } static inline struct inode *vn_to_inode(struct bhv_vnode *vnode) { diff --git a/trunk/fs/xfs/xfs_behavior.h b/trunk/fs/xfs/xfs_behavior.h index 6e6e56fb352d..1d8ff103201c 100644 --- a/trunk/fs/xfs/xfs_behavior.h +++ b/trunk/fs/xfs/xfs_behavior.h @@ -78,12 +78,15 @@ * */ +struct bhv_head_lock; + /* * Behavior head. Head of the chain of behaviors. * Contained within each virtualized object data structure. */ typedef struct bhv_head { struct bhv_desc *bh_first; /* first behavior in chain */ + struct bhv_head_lock *bh_lockp; /* pointer to lock info struct */ } bhv_head_t; /* diff --git a/trunk/fs/xfs/xfs_inode.c b/trunk/fs/xfs/xfs_inode.c index 86c1bf0bba9e..5fa0adb7e173 100644 --- a/trunk/fs/xfs/xfs_inode.c +++ b/trunk/fs/xfs/xfs_inode.c @@ -1961,9 +1961,9 @@ xfs_iunlink_remove( xfs_agino_t agino; xfs_agino_t next_agino; xfs_buf_t *last_ibp; - xfs_dinode_t *last_dip = NULL; + xfs_dinode_t *last_dip; short bucket_index; - int offset, last_offset = 0; + int offset, last_offset; int error; int agi_ok; diff --git a/trunk/fs/xfs/xfs_log.c b/trunk/fs/xfs/xfs_log.c index e730328636c3..d8f5d4cbe8b7 100644 --- a/trunk/fs/xfs/xfs_log.c +++ b/trunk/fs/xfs/xfs_log.c @@ -1740,10 +1740,10 @@ xlog_write(xfs_mount_t * mp, xlog_in_core_t **commit_iclog, uint flags) { - xlog_t *log = mp->m_log; + xlog_t *log = mp->m_log; xlog_ticket_t *ticket = (xlog_ticket_t *)tic; - xlog_in_core_t *iclog = NULL; /* ptr to current in-core log */ xlog_op_header_t *logop_head; /* ptr to log operation header */ + xlog_in_core_t *iclog; /* ptr to current in-core log */ __psint_t ptr; /* copy address into data region */ int len; /* # xlog_write() bytes 2 still copy */ int index; /* region index currently copying */ diff --git a/trunk/fs/xfs/xfs_log_recover.c b/trunk/fs/xfs/xfs_log_recover.c index 3cb678e3a132..55b4237c2153 100644 --- a/trunk/fs/xfs/xfs_log_recover.c +++ b/trunk/fs/xfs/xfs_log_recover.c @@ -990,8 +990,6 @@ xlog_find_zeroed( xfs_daddr_t num_scan_bblks; int error, log_bbnum = log->l_logBBsize; - *blk_no = 0; - /* check totally zeroed log */ bp = xlog_get_bp(log, 1); if (!bp) diff --git a/trunk/fs/xfs/xfs_mount.c b/trunk/fs/xfs/xfs_mount.c index 4be5c0b2d296..10dbf203c62f 100644 --- a/trunk/fs/xfs/xfs_mount.c +++ b/trunk/fs/xfs/xfs_mount.c @@ -1721,14 +1721,15 @@ xfs_mount_log_sbunit( * is present to prevent thrashing). */ -#ifdef CONFIG_HOTPLUG_CPU /* * hot-plug CPU notifier support. * - * We need a notifier per filesystem as we need to be able to identify - * the filesystem to balance the counters out. This is achieved by - * having a notifier block embedded in the xfs_mount_t and doing pointer - * magic to get the mount pointer from the notifier block address. + * We cannot use the hotcpu_register() function because it does + * not allow notifier instances. We need a notifier per filesystem + * as we need to be able to identify the filesystem to balance + * the counters out. This is achieved by having a notifier block + * embedded in the xfs_mount_t and doing pointer magic to get the + * mount pointer from the notifier block address. */ STATIC int xfs_icsb_cpu_notify( @@ -1778,7 +1779,6 @@ xfs_icsb_cpu_notify( return NOTIFY_OK; } -#endif /* CONFIG_HOTPLUG_CPU */ int xfs_icsb_init_counters( @@ -1791,11 +1791,9 @@ xfs_icsb_init_counters( if (mp->m_sb_cnts == NULL) return -ENOMEM; -#ifdef CONFIG_HOTPLUG_CPU mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify; mp->m_icsb_notifier.priority = 0; - register_hotcpu_notifier(&mp->m_icsb_notifier); -#endif /* CONFIG_HOTPLUG_CPU */ + register_cpu_notifier(&mp->m_icsb_notifier); for_each_online_cpu(i) { cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); @@ -1814,7 +1812,7 @@ xfs_icsb_destroy_counters( xfs_mount_t *mp) { if (mp->m_sb_cnts) { - unregister_hotcpu_notifier(&mp->m_icsb_notifier); + unregister_cpu_notifier(&mp->m_icsb_notifier); free_percpu(mp->m_sb_cnts); } } @@ -2028,7 +2026,7 @@ xfs_icsb_balance_counter( xfs_sb_field_t field, int flags) { - uint64_t count, resid; + uint64_t count, resid = 0; int weight = num_online_cpus(); int s; @@ -2060,7 +2058,6 @@ xfs_icsb_balance_counter( break; default: BUG(); - count = resid = 0; /* quiet, gcc */ break; } diff --git a/trunk/fs/xfs/xfs_rtalloc.c b/trunk/fs/xfs/xfs_rtalloc.c index 5a0b678956e0..0c1e42b037ef 100644 --- a/trunk/fs/xfs/xfs_rtalloc.c +++ b/trunk/fs/xfs/xfs_rtalloc.c @@ -1929,7 +1929,7 @@ xfs_growfs_rt( /* * Initial error checking. */ - if (mp->m_rtdev_targp == NULL || mp->m_rbmip == NULL || + if (mp->m_rtdev_targp || mp->m_rbmip == NULL || (nrblocks = in->newblocks) <= sbp->sb_rblocks || (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize))) return XFS_ERROR(EINVAL); diff --git a/trunk/fs/xfs/xfs_trans.h b/trunk/fs/xfs/xfs_trans.h index 9dc88b380608..cb65c3a603f5 100644 --- a/trunk/fs/xfs/xfs_trans.h +++ b/trunk/fs/xfs/xfs_trans.h @@ -338,6 +338,8 @@ typedef void (*xfs_trans_callback_t)(struct xfs_trans *, void *); typedef struct xfs_trans { unsigned int t_magic; /* magic number */ xfs_log_callback_t t_logcb; /* log callback struct */ + struct xfs_trans *t_forw; /* async list pointers */ + struct xfs_trans *t_back; /* async list pointers */ unsigned int t_type; /* transaction type */ unsigned int t_log_res; /* amt of log space resvd */ unsigned int t_log_count; /* count for perm log res */ @@ -362,11 +364,9 @@ typedef struct xfs_trans { long t_res_fdblocks_delta; /* on-disk only chg */ long t_frextents_delta;/* superblock freextents chg*/ long t_res_frextents_delta; /* on-disk only chg */ -#ifdef DEBUG long t_ag_freeblks_delta; /* debugging counter */ long t_ag_flist_delta; /* debugging counter */ long t_ag_btree_delta; /* debugging counter */ -#endif long t_dblocks_delta;/* superblock dblocks change */ long t_agcount_delta;/* superblock agcount change */ long t_imaxpct_delta;/* superblock imaxpct change */ diff --git a/trunk/fs/xfs/xfs_vnodeops.c b/trunk/fs/xfs/xfs_vnodeops.c index 23cfa5837728..00a6b7dc24a0 100644 --- a/trunk/fs/xfs/xfs_vnodeops.c +++ b/trunk/fs/xfs/xfs_vnodeops.c @@ -2603,7 +2603,8 @@ xfs_link( vn_trace_entry(src_vp, __FUNCTION__, (inst_t *)__return_address); target_namelen = VNAMELEN(dentry); - ASSERT(!VN_ISDIR(src_vp)); + if (VN_ISDIR(src_vp)) + return XFS_ERROR(EPERM); sip = xfs_vtoi(src_vp); tdp = XFS_BHVTOI(target_dir_bdp); @@ -2698,8 +2699,9 @@ xfs_link( xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE); error = xfs_bumplink(tp, sip); - if (error) + if (error) { goto abort_return; + } /* * If this is a synchronous mount, make sure that the @@ -2717,8 +2719,9 @@ xfs_link( } error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); - if (error) + if (error) { goto std_return; + } /* Fall through to std_return with error = 0. */ std_return: @@ -2739,8 +2742,6 @@ xfs_link( xfs_trans_cancel(tp, cancel_flags); goto std_return; } - - /* * xfs_mkdir * diff --git a/trunk/include/acpi/acconfig.h b/trunk/include/acpi/acconfig.h index b492857fe721..b9beceb33141 100644 --- a/trunk/include/acpi/acconfig.h +++ b/trunk/include/acpi/acconfig.h @@ -63,7 +63,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20060623 +#define ACPI_CA_VERSION 0x20060608 /* * OS name, used for the _OS object. The _OS object is essentially obsolete, diff --git a/trunk/include/acpi/acdispat.h b/trunk/include/acpi/acdispat.h index a22fe9cf8493..288f84903af7 100644 --- a/trunk/include/acpi/acdispat.h +++ b/trunk/include/acpi/acdispat.h @@ -201,7 +201,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, acpi_status acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, union acpi_operand_object *obj_desc, - struct acpi_walk_state *walk_state); + struct acpi_namespace_node *calling_method_node); acpi_status acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state); diff --git a/trunk/include/acpi/acglobal.h b/trunk/include/acpi/acglobal.h index 06972e6637de..14531d48f6b6 100644 --- a/trunk/include/acpi/acglobal.h +++ b/trunk/include/acpi/acglobal.h @@ -181,12 +181,6 @@ ACPI_EXTERN u8 acpi_gbl_integer_nybble_width; extern struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1]; extern struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1]; -/***************************************************************************** - * - * Mutual exlusion within ACPICA subsystem - * - ****************************************************************************/ - /* * Predefined mutex objects. This array contains the * actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs. @@ -194,20 +188,6 @@ extern struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1]; */ ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX]; -/* - * Global lock semaphore works in conjunction with the actual HW global lock - */ -ACPI_EXTERN acpi_semaphore acpi_gbl_global_lock_semaphore; - -/* - * Spinlocks are used for interfaces that can be possibly called at - * interrupt level - */ -ACPI_EXTERN spinlock_t _acpi_gbl_gpe_lock; /* For GPE data structs and registers */ -ACPI_EXTERN spinlock_t _acpi_gbl_hardware_lock; /* For ACPI H/W except GPE registers */ -#define acpi_gbl_gpe_lock &_acpi_gbl_gpe_lock -#define acpi_gbl_hardware_lock &_acpi_gbl_hardware_lock - /***************************************************************************** * * Miscellaneous globals @@ -237,6 +217,7 @@ ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify; ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk; +ACPI_EXTERN acpi_handle acpi_gbl_global_lock_semaphore; /* Misc */ @@ -334,6 +315,11 @@ ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; ACPI_EXTERN struct acpi_gpe_block_info *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; +/* Spinlocks */ + +ACPI_EXTERN acpi_handle acpi_gbl_gpe_lock; +ACPI_EXTERN acpi_handle acpi_gbl_hardware_lock; + /***************************************************************************** * * Debugger globals diff --git a/trunk/include/acpi/acinterp.h b/trunk/include/acpi/acinterp.h index 216339a8f1f6..9f22cfcb624b 100644 --- a/trunk/include/acpi/acinterp.h +++ b/trunk/include/acpi/acinterp.h @@ -287,10 +287,7 @@ acpi_ex_system_wait_event(union acpi_operand_object *time, acpi_status acpi_ex_system_reset_event(union acpi_operand_object *obj_desc); -acpi_status -acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout); - -acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout); +acpi_status acpi_ex_system_wait_semaphore(acpi_handle semaphore, u16 timeout); /* * exoparg1 - ACPI AML execution, 1 operand diff --git a/trunk/include/acpi/aclocal.h b/trunk/include/acpi/aclocal.h index 56b802486161..1eeca7adca95 100644 --- a/trunk/include/acpi/aclocal.h +++ b/trunk/include/acpi/aclocal.h @@ -47,11 +47,10 @@ /* acpisrc:struct_defs -- for acpisrc conversion */ #define ACPI_WAIT_FOREVER 0xFFFF /* u16, as per ACPI spec */ -#define ACPI_DO_NOT_WAIT 0 -#define ACPI_SERIALIZED 0xFF +#define ACPI_INFINITE_CONCURRENCY 0xFF +typedef void *acpi_mutex; typedef u32 acpi_mutex_handle; -#define ACPI_GLOBAL_LOCK (acpi_semaphore) (-1) /* Total number of aml opcodes defined */ @@ -80,15 +79,16 @@ union acpi_parse_object; * table below also! */ #define ACPI_MTX_INTERPRETER 0 /* AML Interpreter, main lock */ -#define ACPI_MTX_TABLES 1 /* Data for ACPI tables */ -#define ACPI_MTX_NAMESPACE 2 /* ACPI Namespace */ -#define ACPI_MTX_EVENTS 3 /* Data for ACPI events */ -#define ACPI_MTX_CACHES 4 /* Internal caches, general purposes */ -#define ACPI_MTX_MEMORY 5 /* Debug memory tracking lists */ -#define ACPI_MTX_DEBUG_CMD_COMPLETE 6 /* AML debugger */ -#define ACPI_MTX_DEBUG_CMD_READY 7 /* AML debugger */ - -#define ACPI_MAX_MUTEX 7 +#define ACPI_MTX_CONTROL_METHOD 1 /* Control method termination [TBD: may no longer be necessary] */ +#define ACPI_MTX_TABLES 2 /* Data for ACPI tables */ +#define ACPI_MTX_NAMESPACE 3 /* ACPI Namespace */ +#define ACPI_MTX_EVENTS 4 /* Data for ACPI events */ +#define ACPI_MTX_CACHES 5 /* Internal caches, general purposes */ +#define ACPI_MTX_MEMORY 6 /* Debug memory tracking lists */ +#define ACPI_MTX_DEBUG_CMD_COMPLETE 7 /* AML debugger */ +#define ACPI_MTX_DEBUG_CMD_READY 8 /* AML debugger */ + +#define ACPI_MAX_MUTEX 8 #define ACPI_NUM_MUTEX ACPI_MAX_MUTEX+1 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) @@ -98,13 +98,14 @@ union acpi_parse_object; static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { "ACPI_MTX_Interpreter", + "ACPI_MTX_Method", "ACPI_MTX_Tables", "ACPI_MTX_Namespace", "ACPI_MTX_Events", "ACPI_MTX_Caches", "ACPI_MTX_Memory", - "ACPI_MTX_CommandComplete", - "ACPI_MTX_CommandReady" + "ACPI_MTX_DebugCmdComplete", + "ACPI_MTX_DebugCmdReady" }; #endif @@ -703,13 +704,6 @@ struct acpi_bit_register_info { u16 access_bit_mask; }; -/* - * Some ACPI registers have bits that must be ignored -- meaning that they - * must be preserved. - */ -#define ACPI_PM1_STATUS_PRESERVED_BITS 0x0800 /* Bit 11 */ -#define ACPI_PM1_CONTROL_PRESERVED_BITS 0x0201 /* Bit 9, Bit 0 (SCI_EN) */ - /* * Register IDs * These are the full ACPI registers diff --git a/trunk/include/acpi/acmacros.h b/trunk/include/acpi/acmacros.h index 4bb38068f40d..38f9aa4bef00 100644 --- a/trunk/include/acpi/acmacros.h +++ b/trunk/include/acpi/acmacros.h @@ -394,8 +394,6 @@ #define ACPI_REGISTER_PREPARE_BITS(val, pos, mask) ((val << pos) & mask) #define ACPI_REGISTER_INSERT_VALUE(reg, pos, mask, val) reg = (reg & (~(mask))) | ACPI_REGISTER_PREPARE_BITS(val, pos, mask) -#define ACPI_INSERT_BITS(target, mask, source) target = ((target & (~(mask))) | (source & mask)) - /* Generate a UUID */ #define ACPI_INIT_UUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ diff --git a/trunk/include/acpi/acobject.h b/trunk/include/acpi/acobject.h index 8fdee31119f3..1747d94084d8 100644 --- a/trunk/include/acpi/acobject.h +++ b/trunk/include/acpi/acobject.h @@ -140,14 +140,14 @@ struct acpi_object_package { *****************************************************************************/ struct acpi_object_event { - ACPI_OBJECT_COMMON_HEADER acpi_semaphore os_semaphore; /* Actual OS synchronization object */ + ACPI_OBJECT_COMMON_HEADER void *semaphore; }; struct acpi_object_mutex { ACPI_OBJECT_COMMON_HEADER u8 sync_level; /* 0-15, specified in Mutex() call */ u16 acquisition_depth; /* Allow multiple Acquires, same thread */ struct acpi_thread_state *owner_thread; /* Current owner of the mutex */ - acpi_mutex os_mutex; /* Actual OS synchronization object */ + void *semaphore; /* Actual OS synchronization object */ union acpi_operand_object *prev; /* Link for list of acquired mutexes */ union acpi_operand_object *next; /* Link for list of acquired mutexes */ struct acpi_namespace_node *node; /* Containing namespace node */ @@ -166,8 +166,8 @@ struct acpi_object_region { struct acpi_object_method { ACPI_OBJECT_COMMON_HEADER u8 method_flags; u8 param_count; - u8 sync_level; - union acpi_operand_object *mutex; + u8 concurrency; + void *semaphore; u8 *aml_start; ACPI_INTERNAL_METHOD implementation; u32 aml_length; diff --git a/trunk/include/acpi/acpi_bus.h b/trunk/include/acpi/acpi_bus.h index f338e40bd544..a2b3e390a503 100644 --- a/trunk/include/acpi/acpi_bus.h +++ b/trunk/include/acpi/acpi_bus.h @@ -334,7 +334,7 @@ int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type); int acpi_bus_trim(struct acpi_device *start, int rmdevice); int acpi_bus_start(struct acpi_device *device); -acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd); + int acpi_match_ids(struct acpi_device *device, char *ids); int acpi_create_dir(struct acpi_device *); void acpi_remove_dir(struct acpi_device *); diff --git a/trunk/include/acpi/acpi_drivers.h b/trunk/include/acpi/acpi_drivers.h index 6a5bdcefec64..b425f9bb6d43 100644 --- a/trunk/include/acpi/acpi_drivers.h +++ b/trunk/include/acpi/acpi_drivers.h @@ -110,21 +110,4 @@ int acpi_processor_set_thermal_limit(acpi_handle handle, int type); extern int acpi_specific_hotkey_enabled; -/*-------------------------------------------------------------------------- - Dock Station - -------------------------------------------------------------------------- */ -#if defined(CONFIG_ACPI_DOCK) || defined(CONFIG_ACPI_DOCK_MODULE) -extern int is_dock_device(acpi_handle handle); -extern int register_dock_notifier(struct notifier_block *nb); -extern void unregister_dock_notifier(struct notifier_block *nb); -extern int register_hotplug_dock_device(acpi_handle handle, - acpi_notify_handler handler, void *context); -extern void unregister_hotplug_dock_device(acpi_handle handle); -#else -#define is_dock_device(h) (0) -#define register_dock_notifier(nb) (-ENODEV) -#define unregister_dock_notifier(nb) do { } while(0) -#define register_hotplug_dock_device(h1, h2, c) (-ENODEV) -#define unregister_hotplug_dock_device(h) do { } while(0) -#endif #endif /*__ACPI_DRIVERS_H__*/ diff --git a/trunk/include/acpi/acpiosxf.h b/trunk/include/acpi/acpiosxf.h index 89bc4a16c2e8..8f473c83b7c4 100644 --- a/trunk/include/acpi/acpiosxf.h +++ b/trunk/include/acpi/acpiosxf.h @@ -96,47 +96,25 @@ acpi_os_table_override(struct acpi_table_header *existing_table, struct acpi_table_header **new_table); /* - * Spinlock primitives - */ -acpi_status acpi_os_create_lock(acpi_spinlock * out_handle); - -void acpi_os_delete_lock(acpi_spinlock handle); - -acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock handle); - -void acpi_os_release_lock(acpi_spinlock handle, acpi_cpu_flags flags); - -/* - * Semaphore primitives + * Synchronization primitives */ acpi_status acpi_os_create_semaphore(u32 max_units, - u32 initial_units, acpi_semaphore * out_handle); + u32 initial_units, acpi_handle * out_handle); -acpi_status acpi_os_delete_semaphore(acpi_semaphore handle); +acpi_status acpi_os_delete_semaphore(acpi_handle handle); -acpi_status -acpi_os_wait_semaphore(acpi_semaphore handle, u32 units, u16 timeout); - -acpi_status acpi_os_signal_semaphore(acpi_semaphore handle, u32 units); - -/* - * Mutex primitives - */ -acpi_status acpi_os_create_mutex(acpi_mutex * out_handle); +acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout); -void acpi_os_delete_mutex(acpi_mutex handle); +acpi_status acpi_os_signal_semaphore(acpi_handle handle, u32 units); -acpi_status acpi_os_acquire_mutex(acpi_mutex handle, u16 timeout); +acpi_status acpi_os_create_lock(acpi_handle * out_handle); -void acpi_os_release_mutex(acpi_mutex handle); +void acpi_os_delete_lock(acpi_handle handle); -/* Temporary macros for Mutex* interfaces, map to existing semaphore xfaces */ +acpi_cpu_flags acpi_os_acquire_lock(acpi_handle handle); -#define acpi_os_create_mutex(out_handle) acpi_os_create_semaphore (1, 1, out_handle) -#define acpi_os_delete_mutex(handle) (void) acpi_os_delete_semaphore (handle) -#define acpi_os_acquire_mutex(handle,time) acpi_os_wait_semaphore (handle, 1, time) -#define acpi_os_release_mutex(handle) (void) acpi_os_signal_semaphore (handle, 1) +void acpi_os_release_lock(acpi_handle handle, acpi_cpu_flags flags); /* * Memory allocation and mapping diff --git a/trunk/include/acpi/actypes.h b/trunk/include/acpi/actypes.h index 64b603cfe92e..77cf1236b05a 100644 --- a/trunk/include/acpi/actypes.h +++ b/trunk/include/acpi/actypes.h @@ -241,7 +241,7 @@ typedef acpi_native_uint acpi_size; /******************************************************************************* * - * OS-dependent and compiler-dependent types + * OS- or compiler-dependent types * * If the defaults below are not appropriate for the host system, they can * be defined in the compiler-specific or OS-specific header, and this will @@ -249,34 +249,27 @@ typedef acpi_native_uint acpi_size; * ******************************************************************************/ -/* Value returned by acpi_os_get_thread_id */ - -#ifndef acpi_thread_id -#define acpi_thread_id acpi_native_uint -#endif - -/* Object returned from acpi_os_create_lock */ - -#ifndef acpi_spinlock -#define acpi_spinlock void * -#endif - -/* Flags for acpi_os_acquire_lock/acpi_os_release_lock */ +/* Use C99 uintptr_t for pointer casting if available, "void *" otherwise */ -#ifndef acpi_cpu_flags -#define acpi_cpu_flags acpi_native_uint +#ifndef acpi_uintptr_t +#define acpi_uintptr_t void * #endif -/* Object returned from acpi_os_create_cache */ - +/* + * If acpi_cache_t was not defined in the OS-dependent header, + * define it now. This is typically the case where the local cache + * manager implementation is to be used (ACPI_USE_LOCAL_CACHE) + */ #ifndef acpi_cache_t #define acpi_cache_t struct acpi_memory_list #endif -/* Use C99 uintptr_t for pointer casting if available, "void *" otherwise */ - -#ifndef acpi_uintptr_t -#define acpi_uintptr_t void * +/* + * Allow the CPU flags word to be defined per-OS to simplify the use of the + * lock and unlock OSL interfaces. + */ +#ifndef acpi_cpu_flags +#define acpi_cpu_flags acpi_native_uint #endif /* @@ -305,6 +298,13 @@ typedef acpi_native_uint acpi_size; #define ACPI_EXPORT_SYMBOL(symbol) #endif +/* + * thread_id is returned by acpi_os_get_thread_id. + */ +#ifndef acpi_thread_id +#define acpi_thread_id acpi_native_uint +#endif + /******************************************************************************* * * Independent types @@ -380,11 +380,6 @@ struct uint32_struct { u32 hi; }; -/* Synchronization objects */ - -#define acpi_mutex void * -#define acpi_semaphore void * - /* * Acpi integer width. In ACPI version 1, integers are * 32 bits. In ACPI version 2, integers are 64 bits. diff --git a/trunk/include/acpi/platform/aclinux.h b/trunk/include/acpi/platform/aclinux.h index 3f853cabbd41..277d35bced03 100644 --- a/trunk/include/acpi/platform/aclinux.h +++ b/trunk/include/acpi/platform/aclinux.h @@ -58,13 +58,11 @@ #include #include #include -#include /* Host-dependent types and defines */ #define ACPI_MACHINE_WIDTH BITS_PER_LONG #define acpi_cache_t kmem_cache_t -#define acpi_spinlock spinlock_t * #define ACPI_EXPORT_SYMBOL(symbol) EXPORT_SYMBOL(symbol); #define strtoul simple_strtoul diff --git a/trunk/include/acpi/processor.h b/trunk/include/acpi/processor.h index 9dd5b75961f8..77371b3cdc44 100644 --- a/trunk/include/acpi/processor.h +++ b/trunk/include/acpi/processor.h @@ -62,7 +62,6 @@ struct acpi_processor_cx { u32 latency_ticks; u32 power; u32 usage; - u64 time; struct acpi_processor_cx_policy promotion; struct acpi_processor_cx_policy demotion; }; diff --git a/trunk/include/asm-alpha/core_t2.h b/trunk/include/asm-alpha/core_t2.h index 457c34b6eb09..dba70c62a16c 100644 --- a/trunk/include/asm-alpha/core_t2.h +++ b/trunk/include/asm-alpha/core_t2.h @@ -435,7 +435,7 @@ static inline void t2_outl(u32 b, unsigned long addr) set_hae(msb); \ } -static DEFINE_SPINLOCK(t2_hae_lock); +static spinlock_t t2_hae_lock = SPIN_LOCK_UNLOCKED; __EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr) { diff --git a/trunk/include/asm-alpha/floppy.h b/trunk/include/asm-alpha/floppy.h index 6a9f02af9529..21816d35ef89 100644 --- a/trunk/include/asm-alpha/floppy.h +++ b/trunk/include/asm-alpha/floppy.h @@ -26,7 +26,7 @@ #define fd_disable_irq() disable_irq(FLOPPY_IRQ) #define fd_cacheflush(addr,size) /* nothing */ #define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt,\ - IRQF_DISABLED, "floppy", NULL) + SA_INTERRUPT, "floppy", NULL) #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL); #ifdef CONFIG_PCI diff --git a/trunk/include/asm-alpha/hw_irq.h b/trunk/include/asm-alpha/hw_irq.h index a37db0f95092..ca9d43b63502 100644 --- a/trunk/include/asm-alpha/hw_irq.h +++ b/trunk/include/asm-alpha/hw_irq.h @@ -2,6 +2,8 @@ #define _ALPHA_HW_IRQ_H +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} + extern volatile unsigned long irq_err_count; #ifdef CONFIG_ALPHA_GENERIC diff --git a/trunk/include/asm-alpha/signal.h b/trunk/include/asm-alpha/signal.h index 13c2305d35ef..1a2c52a056fb 100644 --- a/trunk/include/asm-alpha/signal.h +++ b/trunk/include/asm-alpha/signal.h @@ -77,6 +77,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -97,6 +98,7 @@ typedef unsigned long sigset_t; #define SA_ONESHOT SA_RESETHAND #define SA_NOMASK SA_NODEFER +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ /* * sigaltstack controls diff --git a/trunk/include/asm-alpha/socket.h b/trunk/include/asm-alpha/socket.h index d22ab97ea72e..b5193229132a 100644 --- a/trunk/include/asm-alpha/socket.h +++ b/trunk/include/asm-alpha/socket.h @@ -51,7 +51,6 @@ #define SCM_TIMESTAMP SO_TIMESTAMP #define SO_PEERSEC 30 -#define SO_PASSSEC 34 /* Security levels - as per NRL IPv6 - don't actually do anything */ #define SO_SECURITY_AUTHENTICATION 19 diff --git a/trunk/include/asm-arm/arch-at91rm9200/board.h b/trunk/include/asm-arm/arch-at91rm9200/board.h index c1ca9a4658ec..1fdd70b23809 100644 --- a/trunk/include/asm-arm/arch-at91rm9200/board.h +++ b/trunk/include/asm-arm/arch-at91rm9200/board.h @@ -20,7 +20,7 @@ /* * These are data structures found in platform_device.dev.platform_data, - * and describing board-specific data needed by drivers. For example, + * and describing board-specfic data needed by drivers. For example, * which pin is used for a given GPIO role. * * In 2.6, drivers should strongly avoid board-specific knowledge so diff --git a/trunk/include/asm-arm/arch-at91rm9200/memory.h b/trunk/include/asm-arm/arch-at91rm9200/memory.h index f985069e6d01..3c327c404373 100644 --- a/trunk/include/asm-arm/arch-at91rm9200/memory.h +++ b/trunk/include/asm-arm/arch-at91rm9200/memory.h @@ -33,7 +33,9 @@ * bus_to_virt: Used to convert an address for DMA operations * to an address that the kernel can use. */ +#define __virt_to_bus__is_a_macro #define __virt_to_bus(x) __virt_to_phys(x) +#define __bus_to_virt__is_a_macro #define __bus_to_virt(x) __phys_to_virt(x) #endif diff --git a/trunk/include/asm-arm/arch-h720x/memory.h b/trunk/include/asm-arm/arch-h720x/memory.h index 53e923dba76e..4a1bfd78a0fe 100644 --- a/trunk/include/asm-arm/arch-h720x/memory.h +++ b/trunk/include/asm-arm/arch-h720x/memory.h @@ -23,7 +23,9 @@ * There is something to do here later !, Mar 2000, Jungjun Kim */ +#define __virt_to_bus__is_a_macro #define __virt_to_bus(x) __virt_to_phys(x) +#define __bus_to_virt__is_a_macro #define __bus_to_virt(x) __phys_to_virt(x) #endif diff --git a/trunk/include/asm-arm/arch-imx/memory.h b/trunk/include/asm-arm/arch-imx/memory.h index 5ad90127915f..d09ae32cd2f4 100644 --- a/trunk/include/asm-arm/arch-imx/memory.h +++ b/trunk/include/asm-arm/arch-imx/memory.h @@ -30,7 +30,9 @@ * bus_to_virt: Used to convert an address for DMA operations * to an address that the kernel can use. */ -#define __virt_to_bus(x) (x - PAGE_OFFSET + PHYS_OFFSET) -#define __bus_to_virt(x) (x - PHYS_OFFSET + PAGE_OFFSET) +#define __virt_to_bus__is_a_macro +#define __virt_to_bus(x) (x - PAGE_OFFSET + PHYS_OFFSET) +#define __bus_to_virt__is_a_macro +#define __bus_to_virt(x) (x - PHYS_OFFSET + PAGE_OFFSET) #endif diff --git a/trunk/include/asm-arm/arch-ixp23xx/ixp23xx.h b/trunk/include/asm-arm/arch-ixp23xx/ixp23xx.h index 3927b1d61b17..d0a72201ee96 100644 --- a/trunk/include/asm-arm/arch-ixp23xx/ixp23xx.h +++ b/trunk/include/asm-arm/arch-ixp23xx/ixp23xx.h @@ -295,4 +295,15 @@ #define IXP23XX_PCI_CPP_ADDR_BITS IXP23XX_PCI_CSR(0x0160) +#ifndef __ASSEMBLY__ +/* + * Is system memory on the XSI or CPP bus? + */ +static inline unsigned ixp23xx_cpp_boot(void) +{ + return (*IXP23XX_EXP_CFG0 & IXP23XX_EXP_CFG0_XSI_NOT_PRES); +} +#endif + + #endif diff --git a/trunk/include/asm-arm/arch-ixp23xx/platform.h b/trunk/include/asm-arm/arch-ixp23xx/platform.h index 56e16d66645a..19a73b39c864 100644 --- a/trunk/include/asm-arm/arch-ixp23xx/platform.h +++ b/trunk/include/asm-arm/arch-ixp23xx/platform.h @@ -43,15 +43,5 @@ extern struct sys_timer ixp23xx_timer; #define IXP23XX_UART_XTAL 14745600 -#ifndef __ASSEMBLY__ -/* - * Is system memory on the XSI or CPP bus? - */ -static inline unsigned ixp23xx_cpp_boot(void) -{ - return (*IXP23XX_EXP_CFG0 & IXP23XX_EXP_CFG0_XSI_NOT_PRES); -} -#endif - #endif diff --git a/trunk/include/asm-arm/arch-ixp23xx/uncompress.h b/trunk/include/asm-arm/arch-ixp23xx/uncompress.h index 16c1110f2304..013575e6a9a1 100644 --- a/trunk/include/asm-arm/arch-ixp23xx/uncompress.h +++ b/trunk/include/asm-arm/arch-ixp23xx/uncompress.h @@ -11,7 +11,7 @@ #ifndef __ASM_ARCH_UNCOMPRESS_H #define __ASM_ARCH_UNCOMPRESS_H -#include +#include #include #define UART_BASE ((volatile u32 *)IXP23XX_UART1_PHYS) diff --git a/trunk/include/asm-arm/arch-ixp4xx/io.h b/trunk/include/asm-arm/arch-ixp4xx/io.h index 0d517267fb63..b59520e56fc7 100644 --- a/trunk/include/asm-arm/arch-ixp4xx/io.h +++ b/trunk/include/asm-arm/arch-ixp4xx/io.h @@ -38,7 +38,7 @@ extern int ixp4xx_pci_write(u32 addr, u32 cmd, u32 data); * 2) If > 64MB of memory space is required, the IXP4xx can be configured * to use indirect registers to access PCI (as we do below for I/O * transactions). This allows for up to 128MB (0x48000000 to 0x4fffffff) - * of memory on the bus. The disadvantage of this is that every + * of memory on the bus. The disadvantadge of this is that every * PCI access requires three local register accesses plus a spinlock, * but in some cases the performance hit is acceptable. In addition, * you cannot mmap() PCI devices in this case. diff --git a/trunk/include/asm-arm/arch-omap/board-fsample.h b/trunk/include/asm-arm/arch-omap/board-fsample.h deleted file mode 100644 index 89a1e529fb6f..000000000000 --- a/trunk/include/asm-arm/arch-omap/board-fsample.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * linux/include/asm-arm/arch-omap/board-fsample.h - * - * Board-specific goodies for TI F-Sample. - * - * Copyright (C) 2006 Google, Inc. - * Author: Brian Swetland - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ASM_ARCH_OMAP_FSAMPLE_H -#define __ASM_ARCH_OMAP_FSAMPLE_H - -/* fsample is pretty close to p2-sample */ -#include - -#define fsample_cpld_read(reg) __raw_readb(reg) -#define fsample_cpld_write(val, reg) __raw_writeb(val, reg) - -#define FSAMPLE_CPLD_BASE 0xE8100000 -#define FSAMPLE_CPLD_SIZE SZ_4K -#define FSAMPLE_CPLD_START 0x05080000 - -#define FSAMPLE_CPLD_REG_A (FSAMPLE_CPLD_BASE + 0x00) -#define FSAMPLE_CPLD_SWITCH (FSAMPLE_CPLD_BASE + 0x02) -#define FSAMPLE_CPLD_UART (FSAMPLE_CPLD_BASE + 0x02) -#define FSAMPLE_CPLD_REG_B (FSAMPLE_CPLD_BASE + 0x04) -#define FSAMPLE_CPLD_VERSION (FSAMPLE_CPLD_BASE + 0x06) -#define FSAMPLE_CPLD_SET_CLR (FSAMPLE_CPLD_BASE + 0x06) - -#define FSAMPLE_CPLD_BIT_BT_RESET 0 -#define FSAMPLE_CPLD_BIT_LCD_RESET 1 -#define FSAMPLE_CPLD_BIT_CAM_PWDN 2 -#define FSAMPLE_CPLD_BIT_CHARGER_ENABLE 3 -#define FSAMPLE_CPLD_BIT_SD_MMC_EN 4 -#define FSAMPLE_CPLD_BIT_aGPS_PWREN 5 -#define FSAMPLE_CPLD_BIT_BACKLIGHT 6 -#define FSAMPLE_CPLD_BIT_aGPS_EN_RESET 7 -#define FSAMPLE_CPLD_BIT_aGPS_SLEEPx_N 8 -#define FSAMPLE_CPLD_BIT_OTG_RESET 9 - -#define fsample_cpld_set(bit) \ - fsample_cpld_write((((bit) & 15) << 4) | 0x0f, FSAMPLE_CPLD_SET_CLR) - -#define fsample_cpld_clear(bit) \ - fsample_cpld_write(0xf0 | ((bit) & 15), FSAMPLE_CPLD_SET_CLR) - -#endif diff --git a/trunk/include/asm-arm/arch-omap/board.h b/trunk/include/asm-arm/arch-omap/board.h index edf1dc6ad919..dfdbf06fd646 100644 --- a/trunk/include/asm-arm/arch-omap/board.h +++ b/trunk/include/asm-arm/arch-omap/board.h @@ -22,7 +22,6 @@ #define OMAP_TAG_UART 0x4f07 #define OMAP_TAG_FBMEM 0x4f08 #define OMAP_TAG_STI_CONSOLE 0x4f09 -#define OMAP_TAG_CAMERA_SENSOR 0x4f0a #define OMAP_TAG_BOOT_REASON 0x4f80 #define OMAP_TAG_FLASH_PART 0x4f81 @@ -62,12 +61,6 @@ struct omap_sti_console_config { u8 channel; }; -struct omap_camera_sensor_config { - u16 reset_gpio; - int (*power_on)(void * data); - int (*power_off)(void * data); -}; - struct omap_usb_config { /* Configure drivers according to the connectors on your board: * - "A" connector (rectagular) diff --git a/trunk/include/asm-arm/arch-omap/dma.h b/trunk/include/asm-arm/arch-omap/dma.h index 1b1b02307e77..ca1202312a45 100644 --- a/trunk/include/asm-arm/arch-omap/dma.h +++ b/trunk/include/asm-arm/arch-omap/dma.h @@ -185,8 +185,8 @@ /* DMA channels for 24xx */ #define OMAP24XX_DMA_NO_DEVICE 0 #define OMAP24XX_DMA_XTI_DMA 1 /* S_DMA_0 */ -#define OMAP24XX_DMA_EXT_DMAREQ0 2 /* S_DMA_1 */ -#define OMAP24XX_DMA_EXT_DMAREQ1 3 /* S_DMA_2 */ +#define OMAP24XX_DMA_EXT_NDMA_REQ0 2 /* S_DMA_1 */ +#define OMAP24XX_DMA_EXT_NDMA_REQ1 3 /* S_DMA_2 */ #define OMAP24XX_DMA_GPMC 4 /* S_DMA_3 */ #define OMAP24XX_DMA_GFX 5 /* S_DMA_4 */ #define OMAP24XX_DMA_DSS 6 /* S_DMA_5 */ @@ -197,9 +197,7 @@ #define OMAP24XX_DMA_DES_TX 11 /* S_DMA_10 */ #define OMAP24XX_DMA_DES_RX 12 /* S_DMA_11 */ #define OMAP24XX_DMA_SHA1MD5_RX 13 /* S_DMA_12 */ -#define OMAP24XX_DMA_EXT_DMAREQ2 14 /* S_DMA_13 */ -#define OMAP24XX_DMA_EXT_DMAREQ3 15 /* S_DMA_14 */ -#define OMAP24XX_DMA_EXT_DMAREQ4 16 /* S_DMA_15 */ + #define OMAP24XX_DMA_EAC_AC_RD 17 /* S_DMA_16 */ #define OMAP24XX_DMA_EAC_AC_WR 18 /* S_DMA_17 */ #define OMAP24XX_DMA_EAC_MD_UL_RD 19 /* S_DMA_18 */ @@ -246,7 +244,6 @@ #define OMAP24XX_DMA_MMC1_TX 61 /* SDMA_60 */ #define OMAP24XX_DMA_MMC1_RX 62 /* SDMA_61 */ #define OMAP24XX_DMA_MS 63 /* SDMA_62 */ -#define OMAP24XX_DMA_EXT_DMAREQ5 64 /* S_DMA_63 */ /*----------------------------------------------------------------------------*/ @@ -277,7 +274,7 @@ #define OMAP1610_DMA_LCD_LCH_CTRL (OMAP1610_DMA_LCD_BASE + 0xea) #define OMAP1610_DMA_LCD_SRC_FI_B1_U (OMAP1610_DMA_LCD_BASE + 0xf4) -#define OMAP1_DMA_TOUT_IRQ (1 << 0) +#define OMAP_DMA_TOUT_IRQ (1 << 0) /* Only on omap1 */ #define OMAP_DMA_DROP_IRQ (1 << 1) #define OMAP_DMA_HALF_IRQ (1 << 2) #define OMAP_DMA_FRAME_IRQ (1 << 3) @@ -318,11 +315,11 @@ enum { OMAP_LCD_DMA_B2_BOTTOM }; +/* REVISIT: Check if BURST_4 is really 1 (or 2) */ enum omap_dma_burst_mode { OMAP_DMA_DATA_BURST_DIS = 0, OMAP_DMA_DATA_BURST_4, - OMAP_DMA_DATA_BURST_8, - OMAP_DMA_DATA_BURST_16, + OMAP_DMA_DATA_BURST_8 }; enum omap_dma_color_mode { diff --git a/trunk/include/asm-arm/arch-omap/dmtimer.h b/trunk/include/asm-arm/arch-omap/dmtimer.h index 7a289ff07404..e6522e6a3834 100644 --- a/trunk/include/asm-arm/arch-omap/dmtimer.h +++ b/trunk/include/asm-arm/arch-omap/dmtimer.h @@ -5,7 +5,6 @@ * * Copyright (C) 2005 Nokia Corporation * Author: Lauri Leukkunen - * PWM and clock framwork support by Timo Teras. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -26,56 +25,69 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef __ASM_ARCH_DMTIMER_H -#define __ASM_ARCH_DMTIMER_H - -/* clock sources */ -#define OMAP_TIMER_SRC_SYS_CLK 0x00 -#define OMAP_TIMER_SRC_32_KHZ 0x01 -#define OMAP_TIMER_SRC_EXT_CLK 0x02 +#ifndef __ASM_ARCH_TIMER_H +#define __ASM_ARCH_TIMER_H + +#include + +#define OMAP_TIMER_SRC_ARMXOR 0x00 +#define OMAP_TIMER_SRC_32_KHZ 0x01 +#define OMAP_TIMER_SRC_EXT_CLK 0x02 + +/* timer control reg bits */ +#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13) +#define OMAP_TIMER_CTRL_PT (1 << 12) +#define OMAP_TIMER_CTRL_TRG_OVERFLOW (0x1 << 10) +#define OMAP_TIMER_CTRL_TRG_OFANDMATCH (0x2 << 10) +#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8) +#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8) +#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8) +#define OMAP_TIMER_CTRL_SCPWM (1 << 7) +#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */ +#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */ +#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* how much to shift the prescaler value */ +#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */ +#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */ /* timer interrupt enable bits */ -#define OMAP_TIMER_INT_CAPTURE (1 << 2) -#define OMAP_TIMER_INT_OVERFLOW (1 << 1) -#define OMAP_TIMER_INT_MATCH (1 << 0) +#define OMAP_TIMER_INT_CAPTURE (1 << 2) +#define OMAP_TIMER_INT_OVERFLOW (1 << 1) +#define OMAP_TIMER_INT_MATCH (1 << 0) -/* trigger types */ -#define OMAP_TIMER_TRIGGER_NONE 0x00 -#define OMAP_TIMER_TRIGGER_OVERFLOW 0x01 -#define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE 0x02 -struct omap_dm_timer; -struct clk; +struct omap_dm_timer { + struct list_head timer_list; -int omap_dm_timer_init(void); + u32 base; + unsigned int irq; +}; -struct omap_dm_timer *omap_dm_timer_request(void); -struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id); -void omap_dm_timer_free(struct omap_dm_timer *timer); +u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, int reg); +void omap_dm_timer_write_reg(struct omap_dm_timer *timer, int reg, u32 value); -int omap_dm_timer_get_irq(struct omap_dm_timer *timer); +struct omap_dm_timer * omap_dm_timer_request(void); +void omap_dm_timer_free(struct omap_dm_timer *timer); +void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source); -u32 omap_dm_timer_modify_idlect_mask(u32 inputmask); -struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer); +void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value); +void omap_dm_timer_set_trigger(struct omap_dm_timer *timer, unsigned int value); +void omap_dm_timer_enable_compare(struct omap_dm_timer *timer); +void omap_dm_timer_enable_autoreload(struct omap_dm_timer *timer); void omap_dm_timer_trigger(struct omap_dm_timer *timer); void omap_dm_timer_start(struct omap_dm_timer *timer); void omap_dm_timer_stop(struct omap_dm_timer *timer); -void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source); -void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value); -void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match); -void omap_dm_timer_set_pwm(struct omap_dm_timer *timer, int def_on, int toggle, int trigger); -void omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler); - -void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer, unsigned int value); +void omap_dm_timer_set_load(struct omap_dm_timer *timer, unsigned int load); +void omap_dm_timer_set_match(struct omap_dm_timer *timer, unsigned int match); unsigned int omap_dm_timer_read_status(struct omap_dm_timer *timer); void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value); + unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer); -void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value); +void omap_dm_timer_reset_counter(struct omap_dm_timer *timer); int omap_dm_timers_active(void); +u32 omap_dm_timer_modify_idlect_mask(u32 inputmask); - -#endif /* __ASM_ARCH_DMTIMER_H */ +#endif /* __ASM_ARCH_TIMER_H */ diff --git a/trunk/include/asm-arm/arch-omap/gpmc.h b/trunk/include/asm-arm/arch-omap/gpmc.h deleted file mode 100644 index 1a0a5207822d..000000000000 --- a/trunk/include/asm-arm/arch-omap/gpmc.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * General-Purpose Memory Controller for OMAP2 - * - * Copyright (C) 2005-2006 Nokia Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __OMAP2_GPMC_H -#define __OMAP2_GPMC_H - -#define GPMC_CS_CONFIG1 0x00 -#define GPMC_CS_CONFIG2 0x04 -#define GPMC_CS_CONFIG3 0x08 -#define GPMC_CS_CONFIG4 0x0c -#define GPMC_CS_CONFIG5 0x10 -#define GPMC_CS_CONFIG6 0x14 -#define GPMC_CS_CONFIG7 0x18 -#define GPMC_CS_NAND_COMMAND 0x1c -#define GPMC_CS_NAND_ADDRESS 0x20 -#define GPMC_CS_NAND_DATA 0x24 - -#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) -#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 20) -#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29) -#define GPMC_CONFIG1_READTYPE_SYNC (1 << 29) -#define GPMC_CONFIG1_WRITETYPE_ASYNC (0 << 27) -#define GPMC_CONFIG1_WRITETYPE_SYNC (1 << 27) -#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25) -#define GPMC_CONFIG1_PAGE_LEN(val) ((val & 3) << 23) -#define GPMC_CONFIG1_WAIT_READ_MON (1 << 22) -#define GPMC_CONFIG1_WAIT_WRITE_MON (1 << 21) -#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18) -#define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16) -#define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12) -#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) -#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) -#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) -#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(1) -#define GPMC_CONFIG1_MUXADDDATA (1 << 9) -#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) -#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) -#define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1)) -#define GPMC_CONFIG1_FCLK_DIV3 (GPMC_CONFIG1_FCLK_DIV(2)) -#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) - -/* - * Note that all values in this struct are in nanoseconds, while - * the register values are in gpmc_fck cycles. - */ -struct gpmc_timings { - /* Minimum clock period for synchronous mode */ - u16 sync_clk; - - /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ - u16 cs_on; /* Assertion time */ - u16 cs_rd_off; /* Read deassertion time */ - u16 cs_wr_off; /* Write deassertion time */ - - /* ADV signal timings corresponding to GPMC_CONFIG3 */ - u16 adv_on; /* Assertion time */ - u16 adv_rd_off; /* Read deassertion time */ - u16 adv_wr_off; /* Write deassertion time */ - - /* WE signals timings corresponding to GPMC_CONFIG4 */ - u16 we_on; /* WE assertion time */ - u16 we_off; /* WE deassertion time */ - - /* OE signals timings corresponding to GPMC_CONFIG4 */ - u16 oe_on; /* OE assertion time */ - u16 oe_off; /* OE deassertion time */ - - /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ - u16 page_burst_access; /* Multiple access word delay */ - u16 access; /* Start-cycle to first data valid delay */ - u16 rd_cycle; /* Total read cycle time */ - u16 wr_cycle; /* Total write cycle time */ -}; - -extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns); - -extern void gpmc_cs_write_reg(int cs, int idx, u32 val); -extern u32 gpmc_cs_read_reg(int cs, int idx); -extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk); -extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t); -extern unsigned long gpmc_cs_get_base_addr(int cs); - - -#endif diff --git a/trunk/include/asm-arm/arch-omap/hardware.h b/trunk/include/asm-arm/arch-omap/hardware.h index 481048d65214..c7d9e857795d 100644 --- a/trunk/include/asm-arm/arch-omap/hardware.h +++ b/trunk/include/asm-arm/arch-omap/hardware.h @@ -297,10 +297,6 @@ #include "board-perseus2.h" #endif -#ifdef CONFIG_MACH_OMAP_FSAMPLE -#include "board-fsample.h" -#endif - #ifdef CONFIG_MACH_OMAP_H3 #include "board-h3.h" #endif diff --git a/trunk/include/asm-arm/arch-omap/irqs.h b/trunk/include/asm-arm/arch-omap/irqs.h index 2542495d8a43..42098d99f302 100644 --- a/trunk/include/asm-arm/arch-omap/irqs.h +++ b/trunk/include/asm-arm/arch-omap/irqs.h @@ -242,24 +242,10 @@ #define INT_24XX_GPIO_BANK2 30 #define INT_24XX_GPIO_BANK3 31 #define INT_24XX_GPIO_BANK4 32 -#define INT_24XX_GPTIMER1 37 -#define INT_24XX_GPTIMER2 38 -#define INT_24XX_GPTIMER3 39 -#define INT_24XX_GPTIMER4 40 -#define INT_24XX_GPTIMER5 41 -#define INT_24XX_GPTIMER6 42 -#define INT_24XX_GPTIMER7 43 -#define INT_24XX_GPTIMER8 44 -#define INT_24XX_GPTIMER9 45 -#define INT_24XX_GPTIMER10 46 -#define INT_24XX_GPTIMER11 47 -#define INT_24XX_GPTIMER12 48 #define INT_24XX_MCBSP1_IRQ_TX 59 #define INT_24XX_MCBSP1_IRQ_RX 60 #define INT_24XX_MCBSP2_IRQ_TX 62 #define INT_24XX_MCBSP2_IRQ_RX 63 -#define INT_24XX_UART1_IRQ 72 -#define INT_24XX_UART2_IRQ 73 #define INT_24XX_UART3_IRQ 74 /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730) and diff --git a/trunk/include/asm-arm/arch-omap/mux.h b/trunk/include/asm-arm/arch-omap/mux.h index 679869c5e68f..0dc24d4ba59c 100644 --- a/trunk/include/asm-arm/arch-omap/mux.h +++ b/trunk/include/asm-arm/arch-omap/mux.h @@ -410,12 +410,6 @@ enum omap24xx_index { /* 24xx clock */ W14_24XX_SYS_CLKOUT, - /* 24xx GPMC wait pin monitoring */ - L3_GPMC_WAIT0, - N7_GPMC_WAIT1, - M1_GPMC_WAIT2, - P1_GPMC_WAIT3, - /* 242X McBSP */ Y15_24XX_MCBSP2_CLKX, R14_24XX_MCBSP2_FSX, @@ -435,26 +429,6 @@ enum omap24xx_index { M15_24XX_GPIO92, V14_24XX_GPIO117, - /* 242x DBG GPIO */ - V4_242X_GPIO49, - W2_242X_GPIO50, - U4_242X_GPIO51, - V3_242X_GPIO52, - V2_242X_GPIO53, - V6_242X_GPIO53, - T4_242X_GPIO54, - Y4_242X_GPIO54, - T3_242X_GPIO55, - U2_242X_GPIO56, - - /* 24xx external DMA requests */ - AA10_242X_DMAREQ0, - AA6_242X_DMAREQ1, - E4_242X_DMAREQ2, - G4_242X_DMAREQ3, - D3_242X_DMAREQ4, - E3_242X_DMAREQ5, - P20_24XX_TSC_IRQ, /* UART3 */ diff --git a/trunk/include/asm-arm/arch-omap/pm.h b/trunk/include/asm-arm/arch-omap/pm.h index e46623c61a72..05b003f3a94c 100644 --- a/trunk/include/asm-arm/arch-omap/pm.h +++ b/trunk/include/asm-arm/arch-omap/pm.h @@ -299,43 +299,10 @@ enum omap24xx_save_state { OMAP24XX_SLEEP_SAVE_INTC_MIR0, OMAP24XX_SLEEP_SAVE_INTC_MIR1, OMAP24XX_SLEEP_SAVE_INTC_MIR2, - - OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_MPU, - OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_CORE, - OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_GFX, - OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_DSP, - OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_MDM, - - OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MPU, - OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_CORE, - OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_GFX, - OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_DSP, - OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MDM, - - OMAP24XX_SLEEP_SAVE_CM_IDLEST1_CORE, - OMAP24XX_SLEEP_SAVE_CM_IDLEST2_CORE, - OMAP24XX_SLEEP_SAVE_CM_IDLEST3_CORE, - OMAP24XX_SLEEP_SAVE_CM_IDLEST4_CORE, - OMAP24XX_SLEEP_SAVE_CM_IDLEST_GFX, - OMAP24XX_SLEEP_SAVE_CM_IDLEST_WKUP, - OMAP24XX_SLEEP_SAVE_CM_IDLEST_CKGEN, - OMAP24XX_SLEEP_SAVE_CM_IDLEST_DSP, - OMAP24XX_SLEEP_SAVE_CM_IDLEST_MDM, - - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE1_CORE, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE2_CORE, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE3_CORE, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE4_CORE, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_WKUP, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_PLL, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_DSP, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_MDM, - OMAP24XX_SLEEP_SAVE_CM_FCLKEN1_CORE, OMAP24XX_SLEEP_SAVE_CM_FCLKEN2_CORE, OMAP24XX_SLEEP_SAVE_CM_ICLKEN1_CORE, OMAP24XX_SLEEP_SAVE_CM_ICLKEN2_CORE, - OMAP24XX_SLEEP_SAVE_CM_ICLKEN3_CORE, OMAP24XX_SLEEP_SAVE_CM_ICLKEN4_CORE, OMAP24XX_SLEEP_SAVE_GPIO1_IRQENABLE1, OMAP24XX_SLEEP_SAVE_GPIO2_IRQENABLE1, diff --git a/trunk/include/asm-arm/arch-pxa/pxa-regs.h b/trunk/include/asm-arm/arch-pxa/pxa-regs.h index f5cc65dd7d0d..9f83f4adfbf3 100644 --- a/trunk/include/asm-arm/arch-pxa/pxa-regs.h +++ b/trunk/include/asm-arm/arch-pxa/pxa-regs.h @@ -1329,7 +1329,6 @@ #define GPIO84_NSRXD 84 /* NSSP receive */ #define GPIO85_nPCE_1 85 /* Card Enable for Card Space (PXA27x) */ #define GPIO92_MMCDAT0 92 /* MMC DAT0 (PXA27x) */ -#define GPIO102_nPCE_1 102 /* PCMCIA (PXA27x) */ #define GPIO109_MMCDAT1 109 /* MMC DAT1 (PXA27x) */ #define GPIO110_MMCDAT2 110 /* MMC DAT2 (PXA27x) */ #define GPIO110_MMCCS0 110 /* MMC Chip Select 0 (PXA27x) */ @@ -1472,7 +1471,6 @@ #define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN) #define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT) #define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT) -#define GPIO102_nPCE_1_MD (102 | GPIO_ALT_FN_1_OUT) #define GPIO104_pSKTSEL_MD (104 | GPIO_ALT_FN_1_OUT) #define GPIO109_MMCDAT1_MD (109 | GPIO_ALT_FN_1_OUT) #define GPIO110_MMCDAT2_MD (110 | GPIO_ALT_FN_1_OUT) diff --git a/trunk/include/asm-arm/arch-pxa/trizeps4.h b/trunk/include/asm-arm/arch-pxa/trizeps4.h deleted file mode 100644 index 641d0ec110bb..000000000000 --- a/trunk/include/asm-arm/arch-pxa/trizeps4.h +++ /dev/null @@ -1,106 +0,0 @@ -/************************************************************************ - * Include file for TRIZEPS4 SoM and ConXS eval-board - * Copyright (c) Jürgen Schindele - * 2006 - ************************************************************************/ - -/* - * Includes/Defines - */ -#ifndef _TRIPEPS4_H_ -#define _TRIPEPS4_H_ - -/* physical memory regions */ -#define TRIZEPS4_FLASH_PHYS (PXA_CS0_PHYS) /* Flash region */ -#define TRIZEPS4_DISK_PHYS (PXA_CS1_PHYS) /* Disk On Chip region */ -#define TRIZEPS4_ETH_PHYS (PXA_CS2_PHYS) /* Ethernet DM9000 region */ -#define TRIZEPS4_PIC_PHYS (PXA_CS3_PHYS) /* Logic chip on ConXS-Board */ -#define TRIZEPS4_SDRAM_BASE 0xa0000000 /* SDRAM region */ - -#define TRIZEPS4_CFSR_PHYS (PXA_CS3_PHYS) /* Logic chip on ConXS-Board CSFR register */ -#define TRIZEPS4_BOCR_PHYS (PXA_CS3_PHYS+0x02000000) /* Logic chip on ConXS-Board BOCR register */ -#define TRIZEPS4_IRCR_PHYS (PXA_CS3_PHYS+0x02400000) /* Logic chip on ConXS-Board IRCR register*/ -#define TRIZEPS4_UPSR_PHYS (PXA_CS3_PHYS+0x02800000) /* Logic chip on ConXS-Board UPSR register*/ -#define TRIZEPS4_DICR_PHYS (PXA_CS3_PHYS+0x03800000) /* Logic chip on ConXS-Board DICR register*/ - -/* virtual memory regions */ -#define TRIZEPS4_DISK_VIRT 0xF0000000 /* Disk On Chip region */ - -#define TRIZEPS4_PIC_VIRT 0xF0100000 /* not used */ -#define TRIZEPS4_CFSR_VIRT 0xF0100000 -#define TRIZEPS4_BOCR_VIRT 0xF0200000 -#define TRIZEPS4_DICR_VIRT 0xF0300000 -#define TRIZEPS4_IRCR_VIRT 0xF0400000 -#define TRIZEPS4_UPSR_VIRT 0xF0500000 - -/* size of flash */ -#define TRIZEPS4_FLASH_SIZE 0x02000000 /* Flash size 32 MB */ - -/* Ethernet Controller Davicom DM9000 */ -#define GPIO_DM9000 101 -#define TRIZEPS4_ETH_IRQ IRQ_GPIO(GPIO_DM9000) - -/* UCB1400 audio / TS-controller */ -#define GPIO_UCB1400 1 -#define TRIZEPS4_UCB1400_IRQ IRQ_GPIO(GPIO_UCB1400) - -/* PCMCIA socket Compact Flash */ -#define GPIO_PCD 11 /* PCMCIA Card Detect */ -#define TRIZEPS4_CD_IRQ IRQ_GPIO(GPIO_PCD) -#define GPIO_PRDY 13 /* READY / nINT */ -#define TRIZEPS4_READY_NINT IRQ_GPIO(GPIO_PRDY) - -/* MMC socket */ -#define GPIO_MMC_DET 12 -#define TRIZEPS4_MMC_IRQ IRQ_GPIO(GPIO_MMC_DET) - -/* LEDS using tx2 / rx2 */ -#define GPIO_SYS_BUSY_LED 46 -#define GPIO_HEARTBEAT_LED 47 - -/* Off-module PIC on ConXS board */ -#define GPIO_PIC 0 -#define TRIZEPS4_PIC_IRQ IRQ_GPIO(GPIO_PIC) - -#define CFSR_P2V(x) ((x) - TRIZEPS4_CFSR_PHYS + TRIZEPS4_CFSR_VIRT) -#define CFSR_V2P(x) ((x) - TRIZEPS4_CFSR_VIRT + TRIZEPS4_CFSR_PHYS) - -#define BCR_P2V(x) ((x) - TRIZEPS4_BOCR_PHYS + TRIZEPS4_BOCR_VIRT) -#define BCR_V2P(x) ((x) - TRIZEPS4_BOCR_VIRT + TRIZEPS4_BOCR_PHYS) - -#define DCR_P2V(x) ((x) - TRIZEPS4_DICR_PHYS + TRIZEPS4_DICR_VIRT) -#define DCR_V2P(x) ((x) - TRIZEPS4_DICR_VIRT + TRIZEPS4_DICR_PHYS) - -#ifndef __ASSEMBLY__ -#define ConXS_CFSR (*((volatile unsigned short *)CFSR_P2V(0x0C000000))) -#define ConXS_BCR (*((volatile unsigned short *)BCR_P2V(0x0E000000))) -#define ConXS_DCR (*((volatile unsigned short *)DCR_P2V(0x0F800000))) -#else -#define ConXS_CFSR CFSR_P2V(0x0C000000) -#define ConXS_BCR BCR_P2V(0x0E000000) -#define ConXS_DCR DCR_P2V(0x0F800000) -#endif - -#define ConXS_CFSR_BVD_MASK 0x0003 -#define ConXS_CFSR_BVD1 (1 << 0) -#define ConXS_CFSR_BVD2 (1 << 1) -#define ConXS_CFSR_VS_MASK 0x000C -#define ConXS_CFSR_VS1 (1 << 2) -#define ConXS_CFSR_VS2 (1 << 3) -#define ConXS_CFSR_VS_5V (0x3 << 2) -#define ConXS_CFSR_VS_3V3 0x0 - -#define ConXS_BCR_S0_POW_EN0 (1 << 0) -#define ConXS_BCR_S0_POW_EN1 (1 << 1) -#define ConXS_BCR_L_DISP (1 << 4) -#define ConXS_BCR_CF_BUF_EN (1 << 5) -#define ConXS_BCR_CF_RESET (1 << 7) -#define ConXS_BCR_S0_VCC_3V3 0x1 -#define ConXS_BCR_S0_VCC_5V0 0x2 -#define ConXS_BCR_S0_VPP_12V 0x4 -#define ConXS_BCR_S0_VPP_3V3 0x8 - -#define ConXS_IRCR_MODE (1 << 0) -#define ConXS_IRCR_SD (1 << 1) - -#endif /* _TRIPEPS4_H_ */ diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-dsc.h b/trunk/include/asm-arm/arch-s3c2410/regs-dsc.h index a0a124875164..84aca61cbaa3 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-dsc.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-dsc.h @@ -7,23 +7,25 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * S3C2440/S3C2412 Signal Drive Strength Control + * S3C2440 Signal Drive Strength Control + * + * Changelog: + * 11-Aug-2004 BJD Created file + * 25-Aug-2004 BJD Added the _SELECT_* defs for using with functions */ #ifndef __ASM_ARCH_REGS_DSC_H #define __ASM_ARCH_REGS_DSC_H "2440-dsc" -#if defined(CONFIG_CPU_S3C2412) -#define S3C2412_DSC0 S3C2410_GPIOREG(0xdc) -#define S3C2412_DSC1 S3C2410_GPIOREG(0xe0) -#endif - -#if defined(CONFIG_CPU_S3C2440) +#ifdef CONFIG_CPU_S3C2440 #define S3C2440_DSC0 S3C2410_GPIOREG(0xc4) #define S3C2440_DSC1 S3C2410_GPIOREG(0xc8) +#define S3C2412_DSC0 S3C2410_GPIOREG(0xdc) +#define S3C2412_DSC1 S3C2410_GPIOREG(0xe0) + #define S3C2440_SELECT_DSC0 (0) #define S3C2440_SELECT_DSC1 (1<<31) diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-nand.h b/trunk/include/asm-arm/arch-s3c2410/regs-nand.h index c1470c695c33..7cff235e667a 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-nand.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-nand.h @@ -39,19 +39,10 @@ #define S3C2440_NFESTAT1 S3C2410_NFREG(0x28) #define S3C2440_NFMECC0 S3C2410_NFREG(0x2C) #define S3C2440_NFMECC1 S3C2410_NFREG(0x30) -#define S3C2440_NFSECC S3C24E10_NFREG(0x34) +#define S3C2440_NFSECC S3C2410_NFREG(0x34) #define S3C2440_NFSBLK S3C2410_NFREG(0x38) #define S3C2440_NFEBLK S3C2410_NFREG(0x3C) -#define S3C2412_NFSBLK S3C2410_NFREG(0x20) -#define S3C2412_NFEBLK S3C2410_NFREG(0x24) -#define S3C2412_NFSTAT S3C2410_NFREG(0x28) -#define S3C2412_NFMECC_ERR0 S3C2410_NFREG(0x2C) -#define S3C2412_NFMECC_ERR1 S3C2410_NFREG(0x30) -#define S3C2412_NFMECC0 S3C2410_NFREG(0x34) -#define S3C2412_NFMECC1 S3C2410_NFREG(0x38) -#define S3C2412_NFSECC S3C2410_NFREG(0x3C) - #define S3C2410_NFCONF_EN (1<<15) #define S3C2410_NFCONF_512BYTE (1<<14) #define S3C2410_NFCONF_4STEP (1<<13) @@ -86,42 +77,5 @@ #define S3C2440_NFSTAT_RnB_CHANGE (1<<2) #define S3C2440_NFSTAT_ILLEGAL_ACCESS (1<<3) -#define S3C2412_NFCONF_NANDBOOT (1<<31) -#define S3C2412_NFCONF_ECCCLKCON (1<<30) -#define S3C2412_NFCONF_ECC_MLC (1<<24) -#define S3C2412_NFCONF_TACLS_MASK (7<<12) /* 1 extra bit of Tacls */ - -#define S3C2412_NFCONT_ECC4_DIRWR (1<<18) -#define S3C2412_NFCONT_LOCKTIGHT (1<<17) -#define S3C2412_NFCONT_SOFTLOCK (1<<16) -#define S3C2412_NFCONT_ECC4_ENCINT (1<<13) -#define S3C2412_NFCONT_ECC4_DECINT (1<<12) -#define S3C2412_NFCONT_MAIN_ECC_LOCK (1<<7) -#define S3C2412_NFCONT_INIT_MAIN_ECC (1<<5) -#define S3C2412_NFCONT_nFCE1 (1<<2) -#define S3C2412_NFCONT_nFCE0 (1<<1) - -#define S3C2412_NFSTAT_ECC_ENCDONE (1<<7) -#define S3C2412_NFSTAT_ECC_DECDONE (1<<6) -#define S3C2412_NFSTAT_ILLEGAL_ACCESS (1<<5) -#define S3C2412_NFSTAT_RnB_CHANGE (1<<4) -#define S3C2412_NFSTAT_nFCE1 (1<<3) -#define S3C2412_NFSTAT_nFCE0 (1<<2) -#define S3C2412_NFSTAT_Res1 (1<<1) -#define S3C2412_NFSTAT_READY (1<<0) - -#define S3C2412_NFECCERR_SERRDATA(x) (((x) >> 21) & 0xf) -#define S3C2412_NFECCERR_SERRBIT(x) (((x) >> 18) & 0x7) -#define S3C2412_NFECCERR_MERRDATA(x) (((x) >> 7) & 0x3ff) -#define S3C2412_NFECCERR_MERRBIT(x) (((x) >> 4) & 0x7) -#define S3C2412_NFECCERR_SPARE_ERR(x) (((x) >> 2) & 0x3) -#define S3C2412_NFECCERR_MAIN_ERR(x) (((x) >> 2) & 0x3) -#define S3C2412_NFECCERR_NONE (0) -#define S3C2412_NFECCERR_1BIT (1) -#define S3C2412_NFECCERR_MULTIBIT (2) -#define S3C2412_NFECCERR_ECCAREA (3) - - - #endif /* __ASM_ARM_REGS_NAND */ diff --git a/trunk/include/asm-arm/assembler.h b/trunk/include/asm-arm/assembler.h index fce832820825..d53bafa9bf1c 100644 --- a/trunk/include/asm-arm/assembler.h +++ b/trunk/include/asm-arm/assembler.h @@ -55,6 +55,30 @@ #define PLD(code...) #endif +#define MODE_USR USR_MODE +#define MODE_FIQ FIQ_MODE +#define MODE_IRQ IRQ_MODE +#define MODE_SVC SVC_MODE + +#define DEFAULT_FIQ MODE_FIQ + +/* + * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc}) + */ +#ifdef __STDC__ +#define LOADREGS(cond, base, reglist...)\ + ldm##cond base,reglist +#else +#define LOADREGS(cond, base, reglist...)\ + ldm/**/cond base,reglist +#endif + +/* + * Build a return instruction for this processor type. + */ +#define RETINSTR(instr, regs...)\ + instr regs + /* * Enable and disable interrupts */ @@ -93,6 +117,18 @@ msr cpsr_c, \oldcpsr .endm +/* + * These two are used to save LR/restore PC over a user-based access. + * The old 26-bit architecture requires that we do. On 32-bit + * architecture, we can safely ignore this requirement. + */ + .macro save_lr + .endm + + .macro restore_pc + mov pc, lr + .endm + #define USER(x...) \ 9999: x; \ .section __ex_table,"a"; \ diff --git a/trunk/include/asm-arm/bug.h b/trunk/include/asm-arm/bug.h index 0e36fd5d87df..7fb02138f585 100644 --- a/trunk/include/asm-arm/bug.h +++ b/trunk/include/asm-arm/bug.h @@ -1,6 +1,7 @@ #ifndef _ASMARM_BUG_H #define _ASMARM_BUG_H +#include #ifdef CONFIG_BUG #ifdef CONFIG_DEBUG_BUGVERBOSE diff --git a/trunk/include/asm-arm/bugs.h b/trunk/include/asm-arm/bugs.h index ca54eb0f12d7..4c80ec519d45 100644 --- a/trunk/include/asm-arm/bugs.h +++ b/trunk/include/asm-arm/bugs.h @@ -10,12 +10,8 @@ #ifndef __ASM_BUGS_H #define __ASM_BUGS_H -#ifdef CONFIG_MMU extern void check_writebuffer_bugs(void); #define check_bugs() check_writebuffer_bugs() -#else -#define check_bugs() do { } while (0) -#endif #endif diff --git a/trunk/include/asm-arm/domain.h b/trunk/include/asm-arm/domain.h index 4c2885abbe6c..f8ea2de4848e 100644 --- a/trunk/include/asm-arm/domain.h +++ b/trunk/include/asm-arm/domain.h @@ -50,8 +50,6 @@ #define domain_val(dom,type) ((type) << (2*(dom))) #ifndef __ASSEMBLY__ - -#ifdef CONFIG_MMU #define set_domain(x) \ do { \ __asm__ __volatile__( \ @@ -68,10 +66,5 @@ set_domain(thread->cpu_domain); \ } while (0) -#else -#define set_domain(x) do { } while (0) -#define modify_domain(dom,type) do { } while (0) -#endif - #endif #endif /* !__ASSEMBLY__ */ diff --git a/trunk/include/asm-arm/dyntick.h b/trunk/include/asm-arm/dyntick.h deleted file mode 100644 index 19fab2d2b760..000000000000 --- a/trunk/include/asm-arm/dyntick.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASMARM_DYNTICK_H -#define _ASMARM_DYNTICK_H - -#include - -#endif /* _ASMARM_DYNTICK_H */ diff --git a/trunk/include/asm-arm/fpstate.h b/trunk/include/asm-arm/fpstate.h index 6af4e6bd1290..132c3c5628b2 100644 --- a/trunk/include/asm-arm/fpstate.h +++ b/trunk/include/asm-arm/fpstate.h @@ -72,14 +72,6 @@ union fp_state { #define FP_SIZE (sizeof(union fp_state) / sizeof(int)) -struct crunch_state { - unsigned int mvdx[16][2]; - unsigned int mvax[4][3]; - unsigned int dspsc[2]; -}; - -#define CRUNCH_SIZE sizeof(struct crunch_state) - #endif #endif diff --git a/trunk/include/asm-arm/hardware/locomo.h b/trunk/include/asm-arm/hardware/locomo.h index 22dfb1737768..5f10048ec54e 100644 --- a/trunk/include/asm-arm/hardware/locomo.h +++ b/trunk/include/asm-arm/hardware/locomo.h @@ -111,8 +111,6 @@ #define LOCOMO_ALS 0x00 /* Adjust light cycle */ #define LOCOMO_ALD 0x04 /* Adjust light duty */ -#define LOCOMO_ALC_EN 0x8000 - /* Backlight controller: TFT signal */ #define LOCOMO_BACKLIGHT 0x38 #define LOCOMO_TC 0x00 /* TFT control signal */ @@ -205,7 +203,4 @@ void locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int /* M62332 control function */ void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel); -/* Frontlight control */ -void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf); - #endif diff --git a/trunk/include/asm-arm/hw_irq.h b/trunk/include/asm-arm/hw_irq.h deleted file mode 100644 index f1a08a500604..000000000000 --- a/trunk/include/asm-arm/hw_irq.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Nothing to see here yet - */ -#ifndef _ARCH_ARM_HW_IRQ_H -#define _ARCH_ARM_HW_IRQ_H - -#include - -#endif diff --git a/trunk/include/asm-arm/irq.h b/trunk/include/asm-arm/irq.h index 283af50a16cb..66e67e60bc56 100644 --- a/trunk/include/asm-arm/irq.h +++ b/trunk/include/asm-arm/irq.h @@ -21,13 +21,18 @@ struct irqaction; +extern void disable_irq_nosync(unsigned int); +extern void disable_irq(unsigned int); +extern void enable_irq(unsigned int); + /* - * Migration helpers + * These correspond with the SA_TRIGGER_* defines, and therefore the + * IORESOURCE_IRQ_* defines. */ -#define __IRQT_FALEDGE IRQ_TYPE_EDGE_FALLING -#define __IRQT_RISEDGE IRQ_TYPE_EDGE_RISING -#define __IRQT_LOWLVL IRQ_TYPE_LEVEL_LOW -#define __IRQT_HIGHLVL IRQ_TYPE_LEVEL_HIGH +#define __IRQT_RISEDGE (1 << 0) +#define __IRQT_FALEDGE (1 << 1) +#define __IRQT_HIGHLVL (1 << 2) +#define __IRQT_LOWLVL (1 << 3) #define IRQT_NOEDGE (0) #define IRQT_RISING (__IRQT_RISEDGE) @@ -35,7 +40,12 @@ struct irqaction; #define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE) #define IRQT_LOW (__IRQT_LOWLVL) #define IRQT_HIGH (__IRQT_HIGHLVL) -#define IRQT_PROBE IRQ_TYPE_PROBE +#define IRQT_PROBE (1 << 4) + +int set_irq_type(unsigned int irq, unsigned int type); +void disable_irq_wake(unsigned int irq); +void enable_irq_wake(unsigned int irq); +int setup_irq(unsigned int, struct irqaction *); extern void migrate_irqs(void); #endif diff --git a/trunk/include/asm-arm/mach/irq.h b/trunk/include/asm-arm/mach/irq.h index 131f33733d25..d4d420ecf3a8 100644 --- a/trunk/include/asm-arm/mach/irq.h +++ b/trunk/include/asm-arm/mach/irq.h @@ -10,32 +10,114 @@ #ifndef __ASM_ARM_MACH_IRQ_H #define __ASM_ARM_MACH_IRQ_H -#include - +struct irqdesc; +struct pt_regs; struct seq_file; +typedef void (*irq_handler_t)(unsigned int, struct irqdesc *, struct pt_regs *); +typedef void (*irq_control_t)(unsigned int); + +struct irqchip { + /* + * Acknowledge the IRQ. + * If this is a level-based IRQ, then it is expected to mask the IRQ + * as well. + */ + void (*ack)(unsigned int); + /* + * Mask the IRQ in hardware. + */ + void (*mask)(unsigned int); + /* + * Unmask the IRQ in hardware. + */ + void (*unmask)(unsigned int); + /* + * Ask the hardware to re-trigger the IRQ. + * Note: This method _must_ _not_ call the interrupt handler. + * If you are unable to retrigger the interrupt, do not + * provide a function, or if you do, return non-zero. + */ + int (*retrigger)(unsigned int); + /* + * Set the type of the IRQ. + */ + int (*set_type)(unsigned int, unsigned int); + /* + * Set wakeup-enable on the selected IRQ + */ + int (*set_wake)(unsigned int, unsigned int); + +#ifdef CONFIG_SMP + /* + * Route an interrupt to a CPU + */ + void (*set_cpu)(struct irqdesc *desc, unsigned int irq, unsigned int cpu); +#endif +}; + +struct irqdesc { + irq_handler_t handle; + struct irqchip *chip; + struct irqaction *action; + struct list_head pend; + void __iomem *base; + void *data; + unsigned int disable_depth; + + unsigned int triggered: 1; /* IRQ has occurred */ + unsigned int running : 1; /* IRQ is running */ + unsigned int pending : 1; /* IRQ is pending */ + unsigned int probing : 1; /* IRQ in use for a probe */ + unsigned int probe_ok : 1; /* IRQ can be used for probe */ + unsigned int valid : 1; /* IRQ claimable */ + unsigned int noautoenable : 1; /* don't automatically enable IRQ */ + unsigned int unused :25; + + unsigned int irqs_unhandled; + struct proc_dir_entry *procdir; + +#ifdef CONFIG_SMP + cpumask_t affinity; + unsigned int cpu; +#endif + + /* + * IRQ lock detection + */ + unsigned int lck_cnt; + unsigned int lck_pc; + unsigned int lck_jif; +}; + +extern struct irqdesc irq_desc[]; + +/* + * Helpful inline function for calling irq descriptor handlers. + */ +static inline void desc_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) +{ + desc->handle(irq, desc, regs); +} + /* * This is internal. Do not use it. */ extern void (*init_arch_irq)(void); extern void init_FIQ(void); extern int show_fiq_list(struct seq_file *, void *); +void __set_irq_handler(unsigned int irq, irq_handler_t, int); /* - * Function wrappers - */ -#define set_irq_chipdata(irq, d) set_irq_chip_data(irq, d) -#define get_irq_chipdata(irq) get_irq_chip_data(irq) - -/* - * Obsolete inline function for calling irq descriptor handlers. + * External stuff. */ -static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc, - struct pt_regs *regs) -{ - desc->handle_irq(irq, desc, regs); -} +#define set_irq_handler(irq,handler) __set_irq_handler(irq,handler,0) +#define set_irq_chained_handler(irq,handler) __set_irq_handler(irq,handler,1) +#define set_irq_data(irq,d) do { irq_desc[irq].data = d; } while (0) +#define set_irq_chipdata(irq,d) do { irq_desc[irq].base = d; } while (0) +#define get_irq_chipdata(irq) (irq_desc[irq].base) +void set_irq_chip(unsigned int irq, struct irqchip *); void set_irq_flags(unsigned int irq, unsigned int flags); #define IRQF_VALID (1 << 0) @@ -43,25 +125,12 @@ void set_irq_flags(unsigned int irq, unsigned int flags); #define IRQF_NOAUTOEN (1 << 2) /* - * This is for easy migration, but should be changed in the source + * Built-in IRQ handlers. */ -#define do_level_IRQ handle_level_irq -#define do_edge_IRQ handle_edge_irq -#define do_simple_IRQ handle_simple_irq -#define irqdesc irq_desc -#define irqchip irq_chip - -#define do_bad_IRQ(irq,desc,regs) \ -do { \ - spin_lock(&desc->lock); \ - handle_bad_irq(irq, desc, regs); \ - spin_unlock(&desc->lock); \ -} while(0) - -extern unsigned long irq_err_count; -static inline void ack_bad_irq(int irq) -{ - irq_err_count++; -} +void do_level_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs); +void do_edge_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs); +void do_simple_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs); +void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs); +void dummy_mask_unmask_irq(unsigned int irq); #endif diff --git a/trunk/include/asm-arm/mach/map.h b/trunk/include/asm-arm/mach/map.h index cef5364ed5fe..e8ea67c97c73 100644 --- a/trunk/include/asm-arm/mach/map.h +++ b/trunk/include/asm-arm/mach/map.h @@ -16,6 +16,8 @@ struct map_desc { unsigned int type; }; +struct meminfo; + #define MT_DEVICE 0 #define MT_CACHECLEAN 1 #define MT_MINICLEAN 2 @@ -26,8 +28,7 @@ struct map_desc { #define MT_IXP2000_DEVICE 7 #define MT_NONSHARED_DEVICE 8 -#ifdef CONFIG_MMU +extern void create_memmap_holes(struct meminfo *); +extern void memtable_init(struct meminfo *); extern void iotable_init(struct map_desc *, int); -#else -#define iotable_init(map,num) do { } while (0) -#endif +extern void setup_io_desc(void); diff --git a/trunk/include/asm-arm/mach/pci.h b/trunk/include/asm-arm/mach/pci.h index 923e0ca66200..25d540ed0079 100644 --- a/trunk/include/asm-arm/mach/pci.h +++ b/trunk/include/asm-arm/mach/pci.h @@ -28,7 +28,7 @@ struct hw_pci { struct pci_sys_data { struct list_head node; int busnr; /* primary bus number */ - u64 mem_offset; /* bus->cpu memory mapping offset */ + unsigned long mem_offset; /* bus->cpu memory mapping offset */ unsigned long io_offset; /* bus->cpu IO mapping offset */ struct pci_bus *bus; /* PCI bus */ struct resource *resource[3]; /* Primary PCI bus resources */ diff --git a/trunk/include/asm-arm/memory.h b/trunk/include/asm-arm/memory.h index 91d536c215d7..731e321a57d1 100644 --- a/trunk/include/asm-arm/memory.h +++ b/trunk/include/asm-arm/memory.h @@ -2,7 +2,6 @@ * linux/include/asm-arm/memory.h * * Copyright (C) 2000-2002 Russell King - * modification for nommu, Hyok S. Choi, 2004 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -27,8 +26,6 @@ #include #include -#ifdef CONFIG_MMU - #ifndef TASK_SIZE /* * TASK_SIZE - the maximum size of a user space task. @@ -50,65 +47,6 @@ #define PAGE_OFFSET UL(0xc0000000) #endif -/* - * The module space lives between the addresses given by TASK_SIZE - * and PAGE_OFFSET - it must be within 32MB of the kernel text. - */ -#define MODULE_END (PAGE_OFFSET) -#define MODULE_START (MODULE_END - 16*1048576) - -#if TASK_SIZE > MODULE_START -#error Top of user space clashes with start of module space -#endif - -/* - * The XIP kernel gets mapped at the bottom of the module vm area. - * Since we use sections to map it, this macro replaces the physical address - * with its virtual address while keeping offset from the base section. - */ -#define XIP_VIRT_ADDR(physaddr) (MODULE_START + ((physaddr) & 0x000fffff)) - -/* - * Allow 16MB-aligned ioremap pages - */ -#define IOREMAP_MAX_ORDER 24 - -#else /* CONFIG_MMU */ - -/* - * The limitation of user task size can grow up to the end of free ram region. - * It is difficult to define and perhaps will never meet the original meaning - * of this define that was meant to. - * Fortunately, there is no reference for this in noMMU mode, for now. - */ -#ifndef TASK_SIZE -#define TASK_SIZE (CONFIG_DRAM_SIZE) -#endif - -#ifndef TASK_UNMAPPED_BASE -#define TASK_UNMAPPED_BASE UL(0x00000000) -#endif - -#ifndef PHYS_OFFSET -#define PHYS_OFFSET (CONFIG_DRAM_BASE) -#endif - -#ifndef END_MEM -#define END_MEM (CONFIG_DRAM_BASE + CONFIG_DRAM_SIZE) -#endif - -#ifndef PAGE_OFFSET -#define PAGE_OFFSET (PHYS_OFFSET) -#endif - -/* - * The module can be at any place in ram in nommu mode. - */ -#define MODULE_END (END_MEM) -#define MODULE_START (PHYS_OFFSET) - -#endif /* !CONFIG_MMU */ - /* * Size of DMA-consistent memory region. Must be multiple of 2M, * between 2MB and 14MB inclusive. @@ -133,6 +71,24 @@ #define __phys_to_pfn(paddr) ((paddr) >> PAGE_SHIFT) #define __pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) +/* + * The module space lives between the addresses given by TASK_SIZE + * and PAGE_OFFSET - it must be within 32MB of the kernel text. + */ +#define MODULE_END (PAGE_OFFSET) +#define MODULE_START (MODULE_END - 16*1048576) + +#if TASK_SIZE > MODULE_START +#error Top of user space clashes with start of module space +#endif + +/* + * The XIP kernel gets mapped at the bottom of the module vm area. + * Since we use sections to map it, this macro replaces the physical address + * with its virtual address while keeping offset from the base section. + */ +#define XIP_VIRT_ADDR(physaddr) (MODULE_START + ((physaddr) & 0x000fffff)) + #ifndef __ASSEMBLY__ /* diff --git a/trunk/include/asm-arm/mmu.h b/trunk/include/asm-arm/mmu.h index fe2a23b5627b..a457cb71984f 100644 --- a/trunk/include/asm-arm/mmu.h +++ b/trunk/include/asm-arm/mmu.h @@ -1,13 +1,10 @@ #ifndef __ARM_MMU_H #define __ARM_MMU_H -#ifdef CONFIG_MMU - typedef struct { #if __LINUX_ARM_ARCH__ >= 6 unsigned int id; #endif - unsigned int kvm_seq; } mm_context_t; #if __LINUX_ARM_ARCH__ >= 6 @@ -16,18 +13,4 @@ typedef struct { #define ASID(mm) (0) #endif -#else - -/* - * From nommu.h: - * Copyright (C) 2002, David McCullough - * modified for 2.6 by Hyok S. Choi - */ -typedef struct { - struct vm_list_struct *vmlist; - unsigned long end_brk; -} mm_context_t; - -#endif - #endif diff --git a/trunk/include/asm-arm/mmu_context.h b/trunk/include/asm-arm/mmu_context.h index d1a65b1edcaa..81c59facea3b 100644 --- a/trunk/include/asm-arm/mmu_context.h +++ b/trunk/include/asm-arm/mmu_context.h @@ -17,8 +17,6 @@ #include #include -void __check_kvm_seq(struct mm_struct *mm); - #if __LINUX_ARM_ARCH__ >= 6 /* @@ -47,21 +45,13 @@ static inline void check_context(struct mm_struct *mm) { if (unlikely((mm->context.id ^ cpu_last_asid) >> ASID_BITS)) __new_context(mm); - - if (unlikely(mm->context.kvm_seq != init_mm.context.kvm_seq)) - __check_kvm_seq(mm); } #define init_new_context(tsk,mm) (__init_new_context(tsk,mm),0) #else -static inline void check_context(struct mm_struct *mm) -{ - if (unlikely(mm->context.kvm_seq != init_mm.context.kvm_seq)) - __check_kvm_seq(mm); -} - +#define check_context(mm) do { } while (0) #define init_new_context(tsk,mm) 0 #endif @@ -92,7 +82,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) { -#ifdef CONFIG_MMU unsigned int cpu = smp_processor_id(); if (prev != next) { @@ -102,7 +91,6 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, if (cache_is_vivt()) cpu_clear(cpu, prev->cpu_vm_mask); } -#endif } #define deactivate_mm(tsk,mm) do { } while (0) diff --git a/trunk/include/asm-arm/page-nommu.h b/trunk/include/asm-arm/page-nommu.h deleted file mode 100644 index a1bcad060480..000000000000 --- a/trunk/include/asm-arm/page-nommu.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * linux/include/asm-arm/page-nommu.h - * - * Copyright (C) 2004 Hyok S. Choi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef _ASMARM_PAGE_NOMMU_H -#define _ASMARM_PAGE_NOMMU_H - -#if !defined(CONFIG_SMALL_TASKS) && PAGE_SHIFT < 13 -#define KTHREAD_SIZE (8192) -#else -#define KTHREAD_SIZE PAGE_SIZE -#endif - -#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) -#define free_user_page(page, addr) free_page(addr) - -#define clear_page(page) memset((page), 0, PAGE_SIZE) -#define copy_page(to,from) memcpy((to), (from), PAGE_SIZE) - -#define clear_user_page(page, vaddr, pg) clear_page(page) -#define copy_user_page(to, from, vaddr, pg) copy_page(to, from) - -/* - * These are used to make use of C type-checking.. - */ -typedef unsigned long pte_t; -typedef unsigned long pmd_t; -typedef unsigned long pgd_t[2]; -typedef unsigned long pgprot_t; - -#define pte_val(x) (x) -#define pmd_val(x) (x) -#define pgd_val(x) ((x)[0]) -#define pgprot_val(x) (x) - -#define __pte(x) (x) -#define __pmd(x) (x) -#define __pgprot(x) (x) - -/* to align the pointer to the (next) page boundary */ -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) - -extern unsigned long memory_start; -extern unsigned long memory_end; - -#endif diff --git a/trunk/include/asm-arm/page.h b/trunk/include/asm-arm/page.h index 63d12f0244c5..66cfeb5290ea 100644 --- a/trunk/include/asm-arm/page.h +++ b/trunk/include/asm-arm/page.h @@ -23,12 +23,6 @@ #ifndef __ASSEMBLY__ -#ifndef CONFIG_MMU - -#include "page-nommu.h" - -#else - #include /* @@ -177,8 +171,6 @@ typedef unsigned long pgprot_t; /* the upper-most page table pointer */ extern pmd_t *top_pmd; -#endif /* CONFIG_MMU */ - #include #endif /* !__ASSEMBLY__ */ diff --git a/trunk/include/asm-arm/pgalloc.h b/trunk/include/asm-arm/pgalloc.h index 4d4394552911..c4ac2e67768d 100644 --- a/trunk/include/asm-arm/pgalloc.h +++ b/trunk/include/asm-arm/pgalloc.h @@ -16,10 +16,6 @@ #include #include -#define check_pgt_cache() do { } while (0) - -#ifdef CONFIG_MMU - #define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_USER)) #define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_BIT4 | PMD_DOMAIN(DOMAIN_KERNEL)) @@ -36,6 +32,8 @@ extern void free_pgd_slow(pgd_t *pgd); #define pgd_alloc(mm) get_pgd_slow(mm) #define pgd_free(pgd) free_pgd_slow(pgd) +#define check_pgt_cache() do { } while (0) + /* * Allocate one PTE table. * @@ -128,6 +126,4 @@ pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep) __pmd_populate(pmdp, page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE); } -#endif /* CONFIG_MMU */ - #endif diff --git a/trunk/include/asm-arm/pgtable-hwdef.h b/trunk/include/asm-arm/pgtable-hwdef.h index f3b5120c99fe..1bc1f997bda2 100644 --- a/trunk/include/asm-arm/pgtable-hwdef.h +++ b/trunk/include/asm-arm/pgtable-hwdef.h @@ -28,7 +28,6 @@ */ #define PMD_SECT_BUFFERABLE (1 << 2) #define PMD_SECT_CACHEABLE (1 << 3) -#define PMD_SECT_XN (1 << 4) /* v6 */ #define PMD_SECT_AP_WRITE (1 << 10) #define PMD_SECT_AP_READ (1 << 11) #define PMD_SECT_TEX(x) ((x) << 12) /* v5 */ diff --git a/trunk/include/asm-arm/pgtable-nommu.h b/trunk/include/asm-arm/pgtable-nommu.h deleted file mode 100644 index b13322dccf41..000000000000 --- a/trunk/include/asm-arm/pgtable-nommu.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * linux/include/asm-arm/pgtable-nommu.h - * - * Copyright (C) 1995-2002 Russell King - * Copyright (C) 2004 Hyok S. Choi - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef _ASMARM_PGTABLE_NOMMU_H -#define _ASMARM_PGTABLE_NOMMU_H - -#ifndef __ASSEMBLY__ - -#include -#include -#include -#include -#include - -/* - * Trivial page table functions. - */ -#define pgd_present(pgd) (1) -#define pgd_none(pgd) (0) -#define pgd_bad(pgd) (0) -#define pgd_clear(pgdp) -#define kern_addr_valid(addr) (1) -#define pmd_offset(a, b) ((void *)0) -/* FIXME */ -/* - * PMD_SHIFT determines the size of the area a second-level page table can map - * PGDIR_SHIFT determines what a third-level page table entry can map - */ -#define PGDIR_SHIFT 21 - -#define PGDIR_SIZE (1UL << PGDIR_SHIFT) -#define PGDIR_MASK (~(PGDIR_SIZE-1)) -/* FIXME */ - -#define PAGE_NONE __pgprot(0) -#define PAGE_SHARED __pgprot(0) -#define PAGE_COPY __pgprot(0) -#define PAGE_READONLY __pgprot(0) -#define PAGE_KERNEL __pgprot(0) - -//extern void paging_init(struct meminfo *, struct machine_desc *); -#define swapper_pg_dir ((pgd_t *) 0) - -#define __swp_type(x) (0) -#define __swp_offset(x) (0) -#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) }) -#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - - -typedef pte_t *pte_addr_t; - -static inline int pte_file(pte_t pte) { return 0; } - -/* - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ -#define ZERO_PAGE(vaddr) (virt_to_page(0)) - -/* - * Mark the prot value as uncacheable and unbufferable. - */ -#define pgprot_noncached(prot) __pgprot(0) -#define pgprot_writecombine(prot) __pgprot(0) - - -/* - * These would be in other places but having them here reduces the diffs. - */ -extern unsigned int kobjsize(const void *objp); -extern int is_in_rom(unsigned long); - -/* - * No page table caches to initialise. - */ -#define pgtable_cache_init() do { } while (0) -#define io_remap_page_range remap_page_range -#define io_remap_pfn_range remap_pfn_range - -#define MK_IOSPACE_PFN(space, pfn) (pfn) -#define GET_IOSPACE(pfn) 0 -#define GET_PFN(pfn) (pfn) - - -/* - * All 32bit addresses are effectively valid for vmalloc... - * Sort of meaningless for non-VM targets. - */ -#define VMALLOC_START 0 -#define VMALLOC_END 0xffffffff - -#define FIRST_USER_ADDRESS (0) - -#else - -/* - * dummy tlb and user structures. - */ -#define v3_tlb_fns (0) -#define v4_tlb_fns (0) -#define v4wb_tlb_fns (0) -#define v4wbi_tlb_fns (0) -#define v6_tlb_fns (0) - -#define v3_user_fns (0) -#define v4_user_fns (0) -#define v4_mc_user_fns (0) -#define v4wb_user_fns (0) -#define v4wt_user_fns (0) -#define v6_user_fns (0) -#define xscale_mc_user_fns (0) - -#endif /*__ASSEMBLY__*/ - -#endif /* _ASMARM_PGTABLE_H */ diff --git a/trunk/include/asm-arm/pgtable.h b/trunk/include/asm-arm/pgtable.h index 8d3919c6458c..e85c08d78dda 100644 --- a/trunk/include/asm-arm/pgtable.h +++ b/trunk/include/asm-arm/pgtable.h @@ -11,15 +11,9 @@ #define _ASMARM_PGTABLE_H #include -#include - -#ifndef CONFIG_MMU - -#include "pgtable-nommu.h" - -#else #include +#include #include /* @@ -384,6 +378,4 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; #endif /* !__ASSEMBLY__ */ -#endif /* CONFIG_MMU */ - #endif /* _ASMARM_PGTABLE_H */ diff --git a/trunk/include/asm-arm/proc-fns.h b/trunk/include/asm-arm/proc-fns.h index 1bde92cdaebd..e9310895e79d 100644 --- a/trunk/include/asm-arm/proc-fns.h +++ b/trunk/include/asm-arm/proc-fns.h @@ -165,8 +165,6 @@ #include -#ifdef CONFIG_MMU - #define cpu_switch_mm(pgd,mm) cpu_do_switch_mm(virt_to_phys(pgd),mm) #define cpu_get_pgd() \ @@ -178,8 +176,6 @@ (pgd_t *)phys_to_virt(pg); \ }) -#endif - #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* __ASM_PROCFNS_H */ diff --git a/trunk/include/asm-arm/procinfo.h b/trunk/include/asm-arm/procinfo.h index edb7b6502fcf..842526055225 100644 --- a/trunk/include/asm-arm/procinfo.h +++ b/trunk/include/asm-arm/procinfo.h @@ -29,8 +29,7 @@ struct processor; struct proc_info_list { unsigned int cpu_val; unsigned int cpu_mask; - unsigned long __cpu_mm_mmu_flags; /* used by head.S */ - unsigned long __cpu_io_mmu_flags; /* used by head.S */ + unsigned long __cpu_mmu_flags; /* used by head.S */ unsigned long __cpu_flush; /* used by head.S */ const char *arch_name; const char *elf_name; diff --git a/trunk/include/asm-arm/ptrace.h b/trunk/include/asm-arm/ptrace.h index 5a8ef787dbf8..2bebe3dc0a30 100644 --- a/trunk/include/asm-arm/ptrace.h +++ b/trunk/include/asm-arm/ptrace.h @@ -25,11 +25,6 @@ #define PTRACE_SET_SYSCALL 23 -/* PTRACE_SYSCALL is 24 */ - -#define PTRACE_GETCRUNCHREGS 25 -#define PTRACE_SETCRUNCHREGS 26 - /* * PSR bits */ diff --git a/trunk/include/asm-arm/socket.h b/trunk/include/asm-arm/socket.h index 19f7df702b06..3c51da6438c9 100644 --- a/trunk/include/asm-arm/socket.h +++ b/trunk/include/asm-arm/socket.h @@ -48,6 +48,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_SOCKET_H */ diff --git a/trunk/include/asm-arm/thread_info.h b/trunk/include/asm-arm/thread_info.h index f28b236139ed..cfbccb63c67b 100644 --- a/trunk/include/asm-arm/thread_info.h +++ b/trunk/include/asm-arm/thread_info.h @@ -59,7 +59,6 @@ struct thread_info { struct cpu_context_save cpu_context; /* cpu context */ __u8 used_cp[16]; /* thread used copro */ unsigned long tp_value; - struct crunch_state crunchstate; union fp_state fpstate __attribute__((aligned(8))); union vfp_state vfpstate; struct restart_block restart_block; @@ -102,22 +101,16 @@ extern void free_thread_info(struct thread_info *); #define thread_saved_fp(tsk) \ ((unsigned long)(task_thread_info(tsk)->cpu_context.fp)) -extern void crunch_task_disable(struct thread_info *); -extern void crunch_task_copy(struct thread_info *, void *); -extern void crunch_task_restore(struct thread_info *, void *); -extern void crunch_task_release(struct thread_info *); - extern void iwmmxt_task_disable(struct thread_info *); extern void iwmmxt_task_copy(struct thread_info *, void *); extern void iwmmxt_task_restore(struct thread_info *, void *); extern void iwmmxt_task_release(struct thread_info *); -extern void iwmmxt_task_switch(struct thread_info *); #endif /* * We use bit 30 of the preempt_count to indicate that kernel - * preemption is occurring. See include/asm-arm/hardirq.h. + * preemption is occuring. See include/asm-arm/hardirq.h. */ #define PREEMPT_ACTIVE 0x40000000 diff --git a/trunk/include/asm-arm/uaccess.h b/trunk/include/asm-arm/uaccess.h index 87aba57a66c4..064f0f5e8e2b 100644 --- a/trunk/include/asm-arm/uaccess.h +++ b/trunk/include/asm-arm/uaccess.h @@ -40,25 +40,16 @@ struct exception_table_entry extern int fixup_exception(struct pt_regs *regs); -/* - * These two are intentionally not defined anywhere - if the kernel - * code generates any references to them, that's a bug. - */ -extern int __get_user_bad(void); -extern int __put_user_bad(void); - /* * Note that this is actually 0x1,0000,0000 */ #define KERNEL_DS 0x00000000 -#define get_ds() (KERNEL_DS) - -#ifdef CONFIG_MMU - #define USER_DS TASK_SIZE + +#define get_ds() (KERNEL_DS) #define get_fs() (current_thread_info()->addr_limit) -static inline void set_fs(mm_segment_t fs) +static inline void set_fs (mm_segment_t fs) { current_thread_info()->addr_limit = fs; modify_domain(DOMAIN_KERNEL, fs ? DOMAIN_CLIENT : DOMAIN_MANAGER); @@ -84,6 +75,8 @@ static inline void set_fs(mm_segment_t fs) : "cc"); \ flag; }) +#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) + /* * Single-value transfer routines. They automatically use the right * size if we just have the right pointer type. Note that the functions @@ -94,10 +87,20 @@ static inline void set_fs(mm_segment_t fs) * fixup code, but there are a few places where it intrudes on the * main code path. When we only write to user space, there is no * problem. + * + * The "__xxx" versions of the user access functions do not verify the + * address space - it must have been done previously with a separate + * "access_ok()" call. + * + * The "xxx_error" versions set the third argument to EFAULT if an + * error occurs, and leave it unchanged on success. Note that these + * versions are void (ie, don't return a value as such). */ + extern int __get_user_1(void *); extern int __get_user_2(void *); extern int __get_user_4(void *); +extern int __get_user_bad(void); #define __get_user_x(__r2,__p,__e,__s,__i...) \ __asm__ __volatile__ ( \ @@ -128,74 +131,6 @@ extern int __get_user_4(void *); __e; \ }) -extern int __put_user_1(void *, unsigned int); -extern int __put_user_2(void *, unsigned int); -extern int __put_user_4(void *, unsigned int); -extern int __put_user_8(void *, unsigned long long); - -#define __put_user_x(__r2,__p,__e,__s) \ - __asm__ __volatile__ ( \ - __asmeq("%0", "r0") __asmeq("%2", "r2") \ - "bl __put_user_" #__s \ - : "=&r" (__e) \ - : "0" (__p), "r" (__r2) \ - : "ip", "lr", "cc") - -#define put_user(x,p) \ - ({ \ - const register typeof(*(p)) __r2 asm("r2") = (x); \ - const register typeof(*(p)) __user *__p asm("r0") = (p);\ - register int __e asm("r0"); \ - switch (sizeof(*(__p))) { \ - case 1: \ - __put_user_x(__r2, __p, __e, 1); \ - break; \ - case 2: \ - __put_user_x(__r2, __p, __e, 2); \ - break; \ - case 4: \ - __put_user_x(__r2, __p, __e, 4); \ - break; \ - case 8: \ - __put_user_x(__r2, __p, __e, 8); \ - break; \ - default: __e = __put_user_bad(); break; \ - } \ - __e; \ - }) - -#else /* CONFIG_MMU */ - -/* - * uClinux has only one addr space, so has simplified address limits. - */ -#define USER_DS KERNEL_DS - -#define segment_eq(a,b) (1) -#define __addr_ok(addr) (1) -#define __range_ok(addr,size) (0) -#define get_fs() (KERNEL_DS) - -static inline void set_fs(mm_segment_t fs) -{ -} - -#define get_user(x,p) __get_user(x,p) -#define put_user(x,p) __put_user(x,p) - -#endif /* CONFIG_MMU */ - -#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) - -/* - * The "__xxx" versions of the user access functions do not verify the - * address space - it must have been done previously with a separate - * "access_ok()" call. - * - * The "xxx_error" versions set the third argument to EFAULT if an - * error occurs, and leave it unchanged on success. Note that these - * versions are void (ie, don't return a value as such). - */ #define __get_user(x,ptr) \ ({ \ long __gu_err = 0; \ @@ -277,6 +212,43 @@ do { \ : "r" (addr), "i" (-EFAULT) \ : "cc") +extern int __put_user_1(void *, unsigned int); +extern int __put_user_2(void *, unsigned int); +extern int __put_user_4(void *, unsigned int); +extern int __put_user_8(void *, unsigned long long); +extern int __put_user_bad(void); + +#define __put_user_x(__r2,__p,__e,__s) \ + __asm__ __volatile__ ( \ + __asmeq("%0", "r0") __asmeq("%2", "r2") \ + "bl __put_user_" #__s \ + : "=&r" (__e) \ + : "0" (__p), "r" (__r2) \ + : "ip", "lr", "cc") + +#define put_user(x,p) \ + ({ \ + const register typeof(*(p)) __r2 asm("r2") = (x); \ + const register typeof(*(p)) __user *__p asm("r0") = (p);\ + register int __e asm("r0"); \ + switch (sizeof(*(__p))) { \ + case 1: \ + __put_user_x(__r2, __p, __e, 1); \ + break; \ + case 2: \ + __put_user_x(__r2, __p, __e, 2); \ + break; \ + case 4: \ + __put_user_x(__r2, __p, __e, 4); \ + break; \ + case 8: \ + __put_user_x(__r2, __p, __e, 8); \ + break; \ + default: __e = __put_user_bad(); break; \ + } \ + __e; \ + }) + #define __put_user(x,ptr) \ ({ \ long __pu_err = 0; \ @@ -381,54 +353,66 @@ do { \ : "r" (x), "i" (-EFAULT) \ : "cc") - -#ifdef CONFIG_MMU -extern unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n); -extern unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n); -extern unsigned long __clear_user(void __user *addr, unsigned long n); -#else -#define __copy_from_user(to,from,n) (memcpy(to, (void __force *)from, n), 0) -#define __copy_to_user(to,from,n) (memcpy((void __force *)to, from, n), 0) -#define __clear_user(addr,n) (memset((void __force *)addr, 0, n), 0) -#endif - -extern unsigned long __strncpy_from_user(char *to, const char __user *from, unsigned long count); -extern unsigned long __strnlen_user(const char __user *s, long n); +extern unsigned long __arch_copy_from_user(void *to, const void __user *from, unsigned long n); +extern unsigned long __arch_copy_to_user(void __user *to, const void *from, unsigned long n); +extern unsigned long __arch_clear_user(void __user *addr, unsigned long n); +extern unsigned long __arch_strncpy_from_user(char *to, const char __user *from, unsigned long count); +extern unsigned long __arch_strnlen_user(const char __user *s, long n); static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) - n = __copy_from_user(to, from, n); + n = __arch_copy_from_user(to, from, n); else /* security hole - plug it */ memzero(to, n); return n; } +static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) +{ + return __arch_copy_from_user(to, from, n); +} + static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) - n = __copy_to_user(to, from, n); + n = __arch_copy_to_user(to, from, n); return n; } +static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n) +{ + return __arch_copy_to_user(to, from, n); +} + #define __copy_to_user_inatomic __copy_to_user #define __copy_from_user_inatomic __copy_from_user -static inline unsigned long clear_user(void __user *to, unsigned long n) +static inline unsigned long clear_user (void __user *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) - n = __clear_user(to, n); + n = __arch_clear_user(to, n); return n; } -static inline long strncpy_from_user(char *dst, const char __user *src, long count) +static inline unsigned long __clear_user (void __user *to, unsigned long n) +{ + return __arch_clear_user(to, n); +} + +static inline long strncpy_from_user (char *dst, const char __user *src, long count) { long res = -EFAULT; if (access_ok(VERIFY_READ, src, 1)) - res = __strncpy_from_user(dst, src, count); + res = __arch_strncpy_from_user(dst, src, count); return res; } +static inline long __strncpy_from_user (char *dst, const char __user *src, long count) +{ + return __arch_strncpy_from_user(dst, src, count); +} + #define strlen_user(s) strnlen_user(s, ~0UL >> 1) static inline long strnlen_user(const char __user *s, long n) @@ -436,7 +420,7 @@ static inline long strnlen_user(const char __user *s, long n) unsigned long res = 0; if (__addr_ok(s)) - res = __strnlen_user(s, n); + res = __arch_strnlen_user(s, n); return res; } diff --git a/trunk/include/asm-arm/ucontext.h b/trunk/include/asm-arm/ucontext.h index bf65e9f4525d..9e6f7ca9f5ae 100644 --- a/trunk/include/asm-arm/ucontext.h +++ b/trunk/include/asm-arm/ucontext.h @@ -35,17 +35,6 @@ struct ucontext { * bytes, to prevent unpredictable padding in the signal frame. */ -#ifdef CONFIG_CRUNCH -#define CRUNCH_MAGIC 0x5065cf03 -#define CRUNCH_STORAGE_SIZE (CRUNCH_SIZE + 8) - -struct crunch_sigframe { - unsigned long magic; - unsigned long size; - struct crunch_state storage; -} __attribute__((__aligned__(8))); -#endif - #ifdef CONFIG_IWMMXT /* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */ #define IWMMXT_MAGIC 0x12ef842a @@ -85,9 +74,6 @@ struct vfp_sigframe * one of these. */ struct aux_sigframe { -#ifdef CONFIG_CRUNCH - struct crunch_sigframe crunch; -#endif #ifdef CONFIG_IWMMXT struct iwmmxt_sigframe iwmmxt; #endif diff --git a/trunk/include/asm-arm26/floppy.h b/trunk/include/asm-arm26/floppy.h index efb732165a4f..a18af069ca28 100644 --- a/trunk/include/asm-arm26/floppy.h +++ b/trunk/include/asm-arm26/floppy.h @@ -22,7 +22,7 @@ #define fd_inb(port) inb((port)) #define fd_request_irq() request_irq(IRQ_FLOPPYDISK,floppy_interrupt,\ - IRQF_DISABLED,"floppy",NULL) + SA_INTERRUPT,"floppy",NULL) #define fd_free_irq() free_irq(IRQ_FLOPPYDISK,NULL) #define fd_disable_irq() disable_irq(IRQ_FLOPPYDISK) #define fd_enable_irq() enable_irq(IRQ_FLOPPYDISK) diff --git a/trunk/include/asm-arm26/signal.h b/trunk/include/asm-arm26/signal.h index 967ba4947e40..37ad25355591 100644 --- a/trunk/include/asm-arm26/signal.h +++ b/trunk/include/asm-arm26/signal.h @@ -82,6 +82,7 @@ typedef unsigned long sigset_t; * is running in 26-bit. * SA_ONSTACK allows alternate signal stacks (see sigaltstack(2)). * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_NODEFER prevents the current signal from being masked in the handler. * SA_RESETHAND clears the handler when the signal is delivered. * @@ -100,6 +101,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ /* diff --git a/trunk/include/asm-arm26/socket.h b/trunk/include/asm-arm26/socket.h index 19f7df702b06..3c51da6438c9 100644 --- a/trunk/include/asm-arm26/socket.h +++ b/trunk/include/asm-arm26/socket.h @@ -48,6 +48,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_SOCKET_H */ diff --git a/trunk/include/asm-cris/arch-v10/irq.h b/trunk/include/asm-cris/arch-v10/irq.h index b1128a9984ae..4fa8945b0263 100644 --- a/trunk/include/asm-cris/arch-v10/irq.h +++ b/trunk/include/asm-cris/arch-v10/irq.h @@ -141,7 +141,7 @@ __asm__ ( \ * it here, we would not get the multiple_irq at all. * * The non-blocking here is based on the knowledge that the timer interrupt is - * registred as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not + * registred as a fast interrupt (SA_INTERRUPT) so that we _know_ there will not * be an sti() before the timer irq handler is run to acknowledge the interrupt. */ diff --git a/trunk/include/asm-cris/arch-v32/arbiter.h b/trunk/include/asm-cris/arch-v32/arbiter.h index 081a911d7af1..dba3c285cacd 100644 --- a/trunk/include/asm-cris/arch-v32/arbiter.h +++ b/trunk/include/asm-cris/arch-v32/arbiter.h @@ -20,8 +20,8 @@ enum arbiter_all_accesses = 0xff }; -int crisv32_arbiter_allocate_bandwidth(int client, int region, - unsigned long bandwidth); +int crisv32_arbiter_allocate_bandwith(int client, int region, + unsigned long bandwidth); int crisv32_arbiter_watch(unsigned long start, unsigned long size, unsigned long clients, unsigned long accesses, watch_callback* cb); diff --git a/trunk/include/asm-cris/arch-v32/irq.h b/trunk/include/asm-cris/arch-v32/irq.h index bac94ee6bc90..eeb0a80262c8 100644 --- a/trunk/include/asm-cris/arch-v32/irq.h +++ b/trunk/include/asm-cris/arch-v32/irq.h @@ -98,7 +98,7 @@ __asm__ ( \ * if we had BLOCK'edit here, we would not get the multiple_irq at all. * * The non-blocking here is based on the knowledge that the timer interrupt is - * registred as a fast interrupt (IRQF_DISABLED) so that we _know_ there will not + * registred as a fast interrupt (SA_INTERRUPT) so that we _know_ there will not * be an sti() before the timer irq handler is run to acknowledge the interrupt. */ #define BUILD_TIMER_IRQ(nr, mask) \ diff --git a/trunk/include/asm-cris/hw_irq.h b/trunk/include/asm-cris/hw_irq.h index 298066020af2..341536a234e9 100644 --- a/trunk/include/asm-cris/hw_irq.h +++ b/trunk/include/asm-cris/hw_irq.h @@ -1,5 +1,7 @@ #ifndef _ASM_HW_IRQ_H #define _ASM_HW_IRQ_H +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} + #endif diff --git a/trunk/include/asm-cris/irq.h b/trunk/include/asm-cris/irq.h index 998cce9f3200..4b338792218b 100644 --- a/trunk/include/asm-cris/irq.h +++ b/trunk/include/asm-cris/irq.h @@ -1,6 +1,11 @@ #ifndef _ASM_IRQ_H #define _ASM_IRQ_H +/* + * IRQ line status macro IRQ_PER_CPU is used + */ +#define ARCH_HAS_IRQ_PER_CPU + #include static inline int irq_canonicalize(int irq) diff --git a/trunk/include/asm-cris/signal.h b/trunk/include/asm-cris/signal.h index 349ae682b568..dfe039593a78 100644 --- a/trunk/include/asm-cris/signal.h +++ b/trunk/include/asm-cris/signal.h @@ -74,6 +74,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -94,6 +95,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 diff --git a/trunk/include/asm-cris/socket.h b/trunk/include/asm-cris/socket.h index 01cfdf1d6d33..8b1da3e58c55 100644 --- a/trunk/include/asm-cris/socket.h +++ b/trunk/include/asm-cris/socket.h @@ -50,7 +50,6 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_SOCKET_H */ diff --git a/trunk/include/asm-frv/irq-routing.h b/trunk/include/asm-frv/irq-routing.h index ac3ab900a1dc..686fb2b39d6a 100644 --- a/trunk/include/asm-frv/irq-routing.h +++ b/trunk/include/asm-frv/irq-routing.h @@ -51,7 +51,7 @@ struct irq_source { struct irq_level { int usage; int disable_count; - unsigned long flags; /* current IRQF_DISABLED and IRQF_SHARED settings */ + unsigned long flags; /* current SA_INTERRUPT and SA_SHIRQ settings */ spinlock_t lock; struct irq_source *sources; }; diff --git a/trunk/include/asm-frv/signal.h b/trunk/include/asm-frv/signal.h index 2079197d483d..dcc1b3592918 100644 --- a/trunk/include/asm-frv/signal.h +++ b/trunk/include/asm-frv/signal.h @@ -74,6 +74,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -93,6 +94,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 diff --git a/trunk/include/asm-frv/socket.h b/trunk/include/asm-frv/socket.h index 31db18fc871f..7177f8b9817c 100644 --- a/trunk/include/asm-frv/socket.h +++ b/trunk/include/asm-frv/socket.h @@ -48,7 +48,6 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_SOCKET_H */ diff --git a/trunk/include/asm-generic/audit_change_attr.h b/trunk/include/asm-generic/audit_change_attr.h deleted file mode 100644 index cb05bf69745a..000000000000 --- a/trunk/include/asm-generic/audit_change_attr.h +++ /dev/null @@ -1,18 +0,0 @@ -__NR_chmod, -__NR_fchmod, -__NR_chown, -__NR_fchown, -__NR_lchown, -__NR_setxattr, -__NR_lsetxattr, -__NR_fsetxattr, -__NR_removexattr, -__NR_lremovexattr, -__NR_fremovexattr, -__NR_fchownat, -__NR_fchmodat, -#ifdef __NR_chown32 -__NR_chown32, -__NR_fchown32, -__NR_lchown32, -#endif diff --git a/trunk/include/asm-generic/audit_dir_write.h b/trunk/include/asm-generic/audit_dir_write.h deleted file mode 100644 index 161a7a58fbab..000000000000 --- a/trunk/include/asm-generic/audit_dir_write.h +++ /dev/null @@ -1,14 +0,0 @@ -__NR_rename, -__NR_mkdir, -__NR_rmdir, -__NR_creat, -__NR_link, -__NR_unlink, -__NR_symlink, -__NR_mknod, -__NR_mkdirat, -__NR_mknodat, -__NR_unlinkat, -__NR_renameat, -__NR_linkat, -__NR_symlinkat, diff --git a/trunk/include/asm-generic/bug.h b/trunk/include/asm-generic/bug.h index 8ceab7bcd8b4..845cb67ad8ea 100644 --- a/trunk/include/asm-generic/bug.h +++ b/trunk/include/asm-generic/bug.h @@ -51,10 +51,4 @@ __ret; \ }) -#ifdef CONFIG_SMP -# define WARN_ON_SMP(x) WARN_ON(x) -#else -# define WARN_ON_SMP(x) do { } while (0) -#endif - #endif diff --git a/trunk/include/asm-generic/sections.h b/trunk/include/asm-generic/sections.h index 962cad7cfbbd..0b49f9e070f1 100644 --- a/trunk/include/asm-generic/sections.h +++ b/trunk/include/asm-generic/sections.h @@ -14,6 +14,5 @@ extern char _end[]; extern char __per_cpu_start[], __per_cpu_end[]; extern char __kprobes_text_start[], __kprobes_text_end[]; extern char __initdata_begin[], __initdata_end[]; -extern char __start_rodata[], __end_rodata[]; #endif /* _ASM_GENERIC_SECTIONS_H_ */ diff --git a/trunk/include/asm-generic/vmlinux.lds.h b/trunk/include/asm-generic/vmlinux.lds.h index db5a3732f106..9d11550b4818 100644 --- a/trunk/include/asm-generic/vmlinux.lds.h +++ b/trunk/include/asm-generic/vmlinux.lds.h @@ -58,20 +58,6 @@ VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \ } \ \ - /* Kernel symbol table: Normal unused symbols */ \ - __ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \ - *(__ksymtab_unused) \ - VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \ - } \ - \ - /* Kernel symbol table: GPL-only unused symbols */ \ - __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \ - *(__ksymtab_unused_gpl) \ - VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \ - } \ - \ /* Kernel symbol table: GPL-future-only symbols */ \ __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \ @@ -93,20 +79,6 @@ VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \ } \ \ - /* Kernel symbol table: Normal unused symbols */ \ - __kcrctab_unused : AT(ADDR(__kcrctab_unused) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___kcrctab_unused) = .; \ - *(__kcrctab_unused) \ - VMLINUX_SYMBOL(__stop___kcrctab_unused) = .; \ - } \ - \ - /* Kernel symbol table: GPL-only unused symbols */ \ - __kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \ - VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .; \ - *(__kcrctab_unused_gpl) \ - VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .; \ - } \ - \ /* Kernel symbol table: GPL-future-only symbols */ \ __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \ diff --git a/trunk/include/asm-h8300/signal.h b/trunk/include/asm-h8300/signal.h index 7bc15048a64f..8eccdc176163 100644 --- a/trunk/include/asm-h8300/signal.h +++ b/trunk/include/asm-h8300/signal.h @@ -74,6 +74,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -93,6 +94,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 diff --git a/trunk/include/asm-h8300/socket.h b/trunk/include/asm-h8300/socket.h index ebc830fee0d0..d98cf85bafc1 100644 --- a/trunk/include/asm-h8300/socket.h +++ b/trunk/include/asm-h8300/socket.h @@ -48,6 +48,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_SOCKET_H */ diff --git a/trunk/include/asm-i386/alternative.h b/trunk/include/asm-i386/alternative.h index 96adbabec740..d79e9ee10fd7 100644 --- a/trunk/include/asm-i386/alternative.h +++ b/trunk/include/asm-i386/alternative.h @@ -5,8 +5,6 @@ #include -#include - struct alt_instr { u8 *instr; /* original instruction */ u8 *replacement; @@ -19,19 +17,11 @@ struct alt_instr { extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); struct module; -#ifdef CONFIG_SMP extern void alternatives_smp_module_add(struct module *mod, char *name, void *locks, void *locks_end, void *text, void *text_end); extern void alternatives_smp_module_del(struct module *mod); extern void alternatives_smp_switch(int smp); -#else -static inline void alternatives_smp_module_add(struct module *mod, char *name, - void *locks, void *locks_end, - void *text, void *text_end) {} -static inline void alternatives_smp_module_del(struct module *mod) {} -static inline void alternatives_smp_switch(int smp) {} -#endif #endif diff --git a/trunk/include/asm-i386/apic.h b/trunk/include/asm-i386/apic.h index 2c1e371cebb6..1d8362cb2c5d 100644 --- a/trunk/include/asm-i386/apic.h +++ b/trunk/include/asm-i386/apic.h @@ -111,12 +111,24 @@ extern void init_apic_mappings (void); extern void smp_local_timer_interrupt (struct pt_regs * regs); extern void setup_boot_APIC_clock (void); extern void setup_secondary_APIC_clock (void); +extern void setup_apic_nmi_watchdog (void); +extern int reserve_lapic_nmi(void); +extern void release_lapic_nmi(void); +extern void disable_timer_nmi_watchdog(void); +extern void enable_timer_nmi_watchdog(void); +extern void nmi_watchdog_tick (struct pt_regs * regs); extern int APIC_init_uniprocessor (void); extern void disable_APIC_timer(void); extern void enable_APIC_timer(void); extern void enable_NMI_through_LVT0 (void * dummy); +extern unsigned int nmi_watchdog; +#define NMI_NONE 0 +#define NMI_IO_APIC 1 +#define NMI_LOCAL_APIC 2 +#define NMI_INVALID 3 + extern int disable_timer_pin_1; void smp_send_timer_broadcast_ipi(struct pt_regs *regs); diff --git a/trunk/include/asm-i386/cpu.h b/trunk/include/asm-i386/cpu.h index b1bc7b1b64b0..e7252c216ca8 100644 --- a/trunk/include/asm-i386/cpu.h +++ b/trunk/include/asm-i386/cpu.h @@ -7,6 +7,8 @@ #include #include +#include + struct i386_cpu { struct cpu cpu; }; diff --git a/trunk/include/asm-i386/cpufeature.h b/trunk/include/asm-i386/cpufeature.h index d314ebb3d59e..3ecedbafa8ce 100644 --- a/trunk/include/asm-i386/cpufeature.h +++ b/trunk/include/asm-i386/cpufeature.h @@ -72,7 +72,6 @@ #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */ #define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */ #define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */ -#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ diff --git a/trunk/include/asm-i386/delay.h b/trunk/include/asm-i386/delay.h index b1c7650dc7b9..456db8501c09 100644 --- a/trunk/include/asm-i386/delay.h +++ b/trunk/include/asm-i386/delay.h @@ -23,6 +23,4 @@ extern void __delay(unsigned long loops); ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \ __ndelay(n)) -void use_tsc_delay(void); - #endif /* defined(_I386_DELAY_H) */ diff --git a/trunk/include/asm-i386/dwarf2.h b/trunk/include/asm-i386/dwarf2.h deleted file mode 100644 index 2280f6272f80..000000000000 --- a/trunk/include/asm-i386/dwarf2.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef _DWARF2_H -#define _DWARF2_H - -#include - -#ifndef __ASSEMBLY__ -#warning "asm/dwarf2.h should be only included in pure assembly files" -#endif - -/* - Macros for dwarf2 CFI unwind table entries. - See "as.info" for details on these pseudo ops. Unfortunately - they are only supported in very new binutils, so define them - away for older version. - */ - -#ifdef CONFIG_UNWIND_INFO - -#define CFI_STARTPROC .cfi_startproc -#define CFI_ENDPROC .cfi_endproc -#define CFI_DEF_CFA .cfi_def_cfa -#define CFI_DEF_CFA_REGISTER .cfi_def_cfa_register -#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset -#define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset -#define CFI_OFFSET .cfi_offset -#define CFI_REL_OFFSET .cfi_rel_offset -#define CFI_REGISTER .cfi_register -#define CFI_RESTORE .cfi_restore -#define CFI_REMEMBER_STATE .cfi_remember_state -#define CFI_RESTORE_STATE .cfi_restore_state - -#else - -/* Due to the structure of pre-exisiting code, don't use assembler line - comment character # to ignore the arguments. Instead, use a dummy macro. */ -.macro ignore a=0, b=0, c=0, d=0 -.endm - -#define CFI_STARTPROC ignore -#define CFI_ENDPROC ignore -#define CFI_DEF_CFA ignore -#define CFI_DEF_CFA_REGISTER ignore -#define CFI_DEF_CFA_OFFSET ignore -#define CFI_ADJUST_CFA_OFFSET ignore -#define CFI_OFFSET ignore -#define CFI_REL_OFFSET ignore -#define CFI_REGISTER ignore -#define CFI_RESTORE ignore -#define CFI_REMEMBER_STATE ignore -#define CFI_RESTORE_STATE ignore - -#endif - -#endif diff --git a/trunk/include/asm-i386/elf.h b/trunk/include/asm-i386/elf.h index 1eac92cb5b16..4153d80e4d2b 100644 --- a/trunk/include/asm-i386/elf.h +++ b/trunk/include/asm-i386/elf.h @@ -10,7 +10,6 @@ #include #include /* for savesegment */ #include -#include #include @@ -130,41 +129,15 @@ extern int dump_task_extended_fpu (struct task_struct *, struct user_fxsr_struct #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs) #define ELF_CORE_COPY_XFPREGS(tsk, elf_xfpregs) dump_task_extended_fpu(tsk, elf_xfpregs) -#define VDSO_HIGH_BASE (__fix_to_virt(FIX_VDSO)) -#define VDSO_BASE ((unsigned long)current->mm->context.vdso) - -#ifdef CONFIG_COMPAT_VDSO -# define VDSO_COMPAT_BASE VDSO_HIGH_BASE -# define VDSO_PRELINK VDSO_HIGH_BASE -#else -# define VDSO_COMPAT_BASE VDSO_BASE -# define VDSO_PRELINK 0 -#endif - -#define VDSO_COMPAT_SYM(x) \ - (VDSO_COMPAT_BASE + (unsigned long)(x) - VDSO_PRELINK) - -#define VDSO_SYM(x) \ - (VDSO_BASE + (unsigned long)(x) - VDSO_PRELINK) - -#define VDSO_HIGH_EHDR ((const struct elfhdr *) VDSO_HIGH_BASE) -#define VDSO_EHDR ((const struct elfhdr *) VDSO_COMPAT_BASE) - +#define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL)) +#define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE) +#define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall) extern void __kernel_vsyscall; -#define VDSO_ENTRY VDSO_SYM(&__kernel_vsyscall) - -#define ARCH_HAS_SETUP_ADDITIONAL_PAGES -struct linux_binprm; -extern int arch_setup_additional_pages(struct linux_binprm *bprm, - int executable_stack); - -extern unsigned int vdso_enabled; - #define ARCH_DLINFO \ -do if (vdso_enabled) { \ - NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \ - NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_COMPAT_BASE); \ +do { \ + NEW_AUX_ENT(AT_SYSINFO, VSYSCALL_ENTRY); \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE); \ } while (0) /* @@ -175,15 +148,15 @@ do if (vdso_enabled) { \ * Dumping its extra ELF program headers includes all the other information * a debugger needs to easily find how the vsyscall DSO was being used. */ -#define ELF_CORE_EXTRA_PHDRS (VDSO_HIGH_EHDR->e_phnum) +#define ELF_CORE_EXTRA_PHDRS (VSYSCALL_EHDR->e_phnum) #define ELF_CORE_WRITE_EXTRA_PHDRS \ do { \ const struct elf_phdr *const vsyscall_phdrs = \ - (const struct elf_phdr *) (VDSO_HIGH_BASE \ - + VDSO_HIGH_EHDR->e_phoff); \ + (const struct elf_phdr *) (VSYSCALL_BASE \ + + VSYSCALL_EHDR->e_phoff); \ int i; \ Elf32_Off ofs = 0; \ - for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) { \ + for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \ struct elf_phdr phdr = vsyscall_phdrs[i]; \ if (phdr.p_type == PT_LOAD) { \ BUG_ON(ofs != 0); \ @@ -201,10 +174,10 @@ do { \ #define ELF_CORE_WRITE_EXTRA_DATA \ do { \ const struct elf_phdr *const vsyscall_phdrs = \ - (const struct elf_phdr *) (VDSO_HIGH_BASE \ - + VDSO_HIGH_EHDR->e_phoff); \ + (const struct elf_phdr *) (VSYSCALL_BASE \ + + VSYSCALL_EHDR->e_phoff); \ int i; \ - for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) { \ + for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \ if (vsyscall_phdrs[i].p_type == PT_LOAD) \ DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr, \ PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \ diff --git a/trunk/include/asm-i386/fixmap.h b/trunk/include/asm-i386/fixmap.h index a48cc3f7ccc6..f7e068f4d2f9 100644 --- a/trunk/include/asm-i386/fixmap.h +++ b/trunk/include/asm-i386/fixmap.h @@ -51,7 +51,7 @@ */ enum fixed_addresses { FIX_HOLE, - FIX_VDSO, + FIX_VSYSCALL, #ifdef CONFIG_X86_LOCAL_APIC FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ #endif @@ -115,6 +115,14 @@ extern void __set_fixmap (enum fixed_addresses idx, #define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) #define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT) +/* + * This is the range that is readable by user mode, and things + * acting like user mode such as get_user_pages. + */ +#define FIXADDR_USER_START (__fix_to_virt(FIX_VSYSCALL)) +#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE) + + extern void __this_fixmap_does_not_exist(void); /* diff --git a/trunk/include/asm-i386/floppy.h b/trunk/include/asm-i386/floppy.h index 359ead60b718..9cb2793eb211 100644 --- a/trunk/include/asm-i386/floppy.h +++ b/trunk/include/asm-i386/floppy.h @@ -144,11 +144,11 @@ static int vdma_get_dma_residue(unsigned int dummy) static int fd_request_irq(void) { if(can_use_virtual_dma) - return request_irq(FLOPPY_IRQ, floppy_hardint, - IRQF_DISABLED, "floppy", NULL); + return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT, + "floppy", NULL); else - return request_irq(FLOPPY_IRQ, floppy_interrupt, - IRQF_DISABLED, "floppy", NULL); + return request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT, + "floppy", NULL); } diff --git a/trunk/include/asm-i386/hw_irq.h b/trunk/include/asm-i386/hw_irq.h index 87e5a351d881..95d3fd090298 100644 --- a/trunk/include/asm-i386/hw_irq.h +++ b/trunk/include/asm-i386/hw_irq.h @@ -19,8 +19,6 @@ struct hw_interrupt_type; -#define NMI_VECTOR 0x02 - /* * Various low-level irq details needed by irq.c, process.c, * time.c, io_apic.c and smp.c @@ -69,4 +67,14 @@ extern atomic_t irq_mis_count; #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs)) +#if defined(CONFIG_X86_IO_APIC) +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) +{ + if (IO_APIC_IRQ(i)) + send_IPI_self(IO_APIC_VECTOR(i)); +} +#else +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} +#endif + #endif /* _ASM_HW_IRQ_H */ diff --git a/trunk/include/asm-i386/intel_arch_perfmon.h b/trunk/include/asm-i386/intel_arch_perfmon.h deleted file mode 100644 index 134ea9cc5283..000000000000 --- a/trunk/include/asm-i386/intel_arch_perfmon.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef X86_INTEL_ARCH_PERFMON_H -#define X86_INTEL_ARCH_PERFMON_H 1 - -#define MSR_ARCH_PERFMON_PERFCTR0 0xc1 -#define MSR_ARCH_PERFMON_PERFCTR1 0xc2 - -#define MSR_ARCH_PERFMON_EVENTSEL0 0x186 -#define MSR_ARCH_PERFMON_EVENTSEL1 0x187 - -#define ARCH_PERFMON_EVENTSEL0_ENABLE (1 << 22) -#define ARCH_PERFMON_EVENTSEL_INT (1 << 20) -#define ARCH_PERFMON_EVENTSEL_OS (1 << 17) -#define ARCH_PERFMON_EVENTSEL_USR (1 << 16) - -#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL (0x3c) -#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8) -#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT (1 << 0) - -#endif /* X86_INTEL_ARCH_PERFMON_H */ diff --git a/trunk/include/asm-i386/k8.h b/trunk/include/asm-i386/k8.h deleted file mode 100644 index dfd88a6e6040..000000000000 --- a/trunk/include/asm-i386/k8.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/trunk/include/asm-i386/kdebug.h b/trunk/include/asm-i386/kdebug.h index d18cdb9fc9a6..96d0828ce096 100644 --- a/trunk/include/asm-i386/kdebug.h +++ b/trunk/include/asm-i386/kdebug.h @@ -19,8 +19,6 @@ struct die_args { extern int register_die_notifier(struct notifier_block *); extern int unregister_die_notifier(struct notifier_block *); -extern int register_page_fault_notifier(struct notifier_block *); -extern int unregister_page_fault_notifier(struct notifier_block *); extern struct atomic_notifier_head i386die_chain; diff --git a/trunk/include/asm-i386/kprobes.h b/trunk/include/asm-i386/kprobes.h index 0730a20f6db8..57d157c5cf89 100644 --- a/trunk/include/asm-i386/kprobes.h +++ b/trunk/include/asm-i386/kprobes.h @@ -44,7 +44,6 @@ typedef u8 kprobe_opcode_t; #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry #define ARCH_SUPPORTS_KRETPROBES -#define ARCH_INACTIVE_KPROBE_COUNT 0 void arch_remove_kprobe(struct kprobe *p); void kretprobe_trampoline(void); diff --git a/trunk/include/asm-i386/local.h b/trunk/include/asm-i386/local.h index 3b4998c51d08..e67fa08260fe 100644 --- a/trunk/include/asm-i386/local.h +++ b/trunk/include/asm-i386/local.h @@ -55,26 +55,12 @@ static __inline__ void local_sub(long i, local_t *v) * much more efficient than these naive implementations. Note they take * a variable, not an address. */ - -/* Need to disable preemption for the cpu local counters otherwise we could - still access a variable of a previous CPU in a non atomic way. */ -#define cpu_local_wrap_v(v) \ - ({ local_t res__; \ - preempt_disable(); \ - res__ = (v); \ - preempt_enable(); \ - res__; }) -#define cpu_local_wrap(v) \ - ({ preempt_disable(); \ - v; \ - preempt_enable(); }) \ - -#define cpu_local_read(v) cpu_local_wrap_v(local_read(&__get_cpu_var(v))) -#define cpu_local_set(v, i) cpu_local_wrap(local_set(&__get_cpu_var(v), (i))) -#define cpu_local_inc(v) cpu_local_wrap(local_inc(&__get_cpu_var(v))) -#define cpu_local_dec(v) cpu_local_wrap(local_dec(&__get_cpu_var(v))) -#define cpu_local_add(i, v) cpu_local_wrap(local_add((i), &__get_cpu_var(v))) -#define cpu_local_sub(i, v) cpu_local_wrap(local_sub((i), &__get_cpu_var(v))) +#define cpu_local_read(v) local_read(&__get_cpu_var(v)) +#define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i)) +#define cpu_local_inc(v) local_inc(&__get_cpu_var(v)) +#define cpu_local_dec(v) local_dec(&__get_cpu_var(v)) +#define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v)) +#define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v)) #define __cpu_local_inc(v) cpu_local_inc(v) #define __cpu_local_dec(v) cpu_local_dec(v) diff --git a/trunk/include/asm-i386/mach-default/mach_ipi.h b/trunk/include/asm-i386/mach-default/mach_ipi.h index 0dba244c86db..a1d0072e36bc 100644 --- a/trunk/include/asm-i386/mach-default/mach_ipi.h +++ b/trunk/include/asm-i386/mach-default/mach_ipi.h @@ -1,9 +1,6 @@ #ifndef __ASM_MACH_IPI_H #define __ASM_MACH_IPI_H -/* Avoid include hell */ -#define NMI_VECTOR 0x02 - void send_IPI_mask_bitmask(cpumask_t mask, int vector); void __send_IPI_shortcut(unsigned int shortcut, int vector); @@ -16,7 +13,7 @@ static inline void send_IPI_mask(cpumask_t mask, int vector) static inline void __local_send_IPI_allbutself(int vector) { - if (no_broadcast || vector == NMI_VECTOR) { + if (no_broadcast) { cpumask_t mask = cpu_online_map; cpu_clear(smp_processor_id(), mask); @@ -27,7 +24,7 @@ static inline void __local_send_IPI_allbutself(int vector) static inline void __local_send_IPI_all(int vector) { - if (no_broadcast || vector == NMI_VECTOR) + if (no_broadcast) send_IPI_mask(cpu_online_map, vector); else __send_IPI_shortcut(APIC_DEST_ALLINC, vector); diff --git a/trunk/include/asm-i386/mach-default/mach_timer.h b/trunk/include/asm-i386/mach-default/mach_timer.h index 807992fd4171..4b9703bb0288 100644 --- a/trunk/include/asm-i386/mach-default/mach_timer.h +++ b/trunk/include/asm-i386/mach-default/mach_timer.h @@ -15,9 +15,7 @@ #ifndef _MACH_TIMER_H #define _MACH_TIMER_H -#define CALIBRATE_TIME_MSEC 30 /* 30 msecs */ -#define CALIBRATE_LATCH \ - ((CLOCK_TICK_RATE * CALIBRATE_TIME_MSEC + 1000/2)/1000) +#define CALIBRATE_LATCH (5 * LATCH) static inline void mach_prepare_counter(void) { diff --git a/trunk/include/asm-i386/mach-summit/mach_mpparse.h b/trunk/include/asm-i386/mach-summit/mach_mpparse.h index 94268399170d..1cce2b924a80 100644 --- a/trunk/include/asm-i386/mach-summit/mach_mpparse.h +++ b/trunk/include/asm-i386/mach-summit/mach_mpparse.h @@ -2,7 +2,6 @@ #define __ASM_MACH_MPPARSE_H #include -#include extern int use_cyclone; @@ -30,7 +29,6 @@ static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, (!strncmp(productid, "VIGIL SMP", 9) || !strncmp(productid, "EXA", 3) || !strncmp(productid, "RUTHLESS SMP", 12))){ - mark_tsc_unstable(); use_cyclone = 1; /*enable cyclone-timer*/ setup_summit(); return 1; @@ -44,7 +42,6 @@ static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) if (!strncmp(oem_id, "IBM", 3) && (!strncmp(oem_table_id, "SERVIGIL", 8) || !strncmp(oem_table_id, "EXA", 3))){ - mark_tsc_unstable(); use_cyclone = 1; /*enable cyclone-timer*/ setup_summit(); return 1; diff --git a/trunk/include/asm-i386/mach-visws/setup_arch.h b/trunk/include/asm-i386/mach-visws/setup_arch.h index 33f700ef6831..b92d6d9a4d3c 100644 --- a/trunk/include/asm-i386/mach-visws/setup_arch.h +++ b/trunk/include/asm-i386/mach-visws/setup_arch.h @@ -1,8 +1,5 @@ /* Hook to call BIOS initialisation function */ -extern unsigned long sgivwfb_mem_phys; -extern unsigned long sgivwfb_mem_size; - /* no action for visws */ #define ARCH_SETUP diff --git a/trunk/include/asm-i386/mmu.h b/trunk/include/asm-i386/mmu.h index 8358dd3df7aa..f431a0b86d4c 100644 --- a/trunk/include/asm-i386/mmu.h +++ b/trunk/include/asm-i386/mmu.h @@ -12,7 +12,6 @@ typedef struct { int size; struct semaphore sem; void *ldt; - void *vdso; } mm_context_t; #endif diff --git a/trunk/include/asm-i386/nmi.h b/trunk/include/asm-i386/nmi.h index 67d994799999..21f16638fc61 100644 --- a/trunk/include/asm-i386/nmi.h +++ b/trunk/include/asm-i386/nmi.h @@ -5,38 +5,24 @@ #define ASM_NMI_H #include - + struct pt_regs; - + typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu); - -/** + +/** * set_nmi_callback * * Set a handler for an NMI. Only one handler may be * set. Return 1 if the NMI was handled. */ void set_nmi_callback(nmi_callback_t callback); - -/** + +/** * unset_nmi_callback * * Remove the handler previously set. */ void unset_nmi_callback(void); - -extern void setup_apic_nmi_watchdog (void); -extern int reserve_lapic_nmi(void); -extern void release_lapic_nmi(void); -extern void disable_timer_nmi_watchdog(void); -extern void enable_timer_nmi_watchdog(void); -extern void nmi_watchdog_tick (struct pt_regs * regs); - -extern unsigned int nmi_watchdog; -#define NMI_DEFAULT -1 -#define NMI_NONE 0 -#define NMI_IO_APIC 1 -#define NMI_LOCAL_APIC 2 -#define NMI_INVALID 3 - + #endif /* ASM_NMI_H */ diff --git a/trunk/include/asm-i386/node.h b/trunk/include/asm-i386/node.h new file mode 100644 index 000000000000..e13c6ffa72ae --- /dev/null +++ b/trunk/include/asm-i386/node.h @@ -0,0 +1,29 @@ +#ifndef _ASM_I386_NODE_H_ +#define _ASM_I386_NODE_H_ + +#include +#include +#include +#include +#include + +struct i386_node { + struct node node; +}; +extern struct i386_node node_devices[MAX_NUMNODES]; + +static inline int arch_register_node(int num){ + int p_node; + struct node *parent = NULL; + + if (!node_online(num)) + return 0; + p_node = parent_node(num); + + if (p_node != num) + parent = &node_devices[p_node].node; + + return register_node(&node_devices[num].node, num, parent); +} + +#endif /* _ASM_I386_NODE_H_ */ diff --git a/trunk/include/asm-i386/page.h b/trunk/include/asm-i386/page.h index f5bf544c729a..e3a552fa5538 100644 --- a/trunk/include/asm-i386/page.h +++ b/trunk/include/asm-i386/page.h @@ -96,8 +96,6 @@ typedef struct { unsigned long pgprot; } pgprot_t; #ifndef __ASSEMBLY__ -struct vm_area_struct; - /* * This much address space is reserved for vmalloc() and iomap() * as well as fixmap mappings. @@ -141,7 +139,6 @@ extern int page_is_ram(unsigned long pagenr); #include #include -#define __HAVE_ARCH_GATE_AREA 1 #endif /* __KERNEL__ */ #endif /* _I386_PAGE_H */ diff --git a/trunk/include/asm-i386/processor.h b/trunk/include/asm-i386/processor.h index b32346d62e10..0c83cf12eec9 100644 --- a/trunk/include/asm-i386/processor.h +++ b/trunk/include/asm-i386/processor.h @@ -71,12 +71,8 @@ struct cpuinfo_x86 { cpumask_t llc_shared_map; /* cpus sharing the last level cache */ #endif unsigned char x86_max_cores; /* cpuid returned max cores value */ - unsigned char apicid; -#ifdef CONFIG_SMP unsigned char booted_cores; /* number of cores as seen by OS */ - __u8 phys_proc_id; /* Physical processor id. */ - __u8 cpu_core_id; /* Core id */ -#endif + unsigned char apicid; } __attribute__((__aligned__(SMP_CACHE_BYTES))); #define X86_VENDOR_INTEL 0 @@ -108,13 +104,14 @@ extern struct cpuinfo_x86 cpu_data[]; #define current_cpu_data boot_cpu_data #endif +extern int phys_proc_id[NR_CPUS]; +extern int cpu_core_id[NR_CPUS]; extern int cpu_llc_id[NR_CPUS]; extern char ignore_fpu_irq; extern void identify_cpu(struct cpuinfo_x86 *); extern void print_cpu_info(struct cpuinfo_x86 *); extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); -extern unsigned short num_cache_leaves; #ifdef CONFIG_X86_HT extern void detect_ht(struct cpuinfo_x86 *c); @@ -557,7 +554,7 @@ extern void prepare_to_copy(struct task_struct *tsk); extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); extern unsigned long thread_saved_pc(struct task_struct *tsk); -void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *stack); +void show_trace(struct task_struct *task, unsigned long *stack); unsigned long get_wchan(struct task_struct *p); diff --git a/trunk/include/asm-i386/signal.h b/trunk/include/asm-i386/signal.h index 3824a502351f..026fd231488d 100644 --- a/trunk/include/asm-i386/signal.h +++ b/trunk/include/asm-i386/signal.h @@ -77,6 +77,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -96,6 +97,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 diff --git a/trunk/include/asm-i386/socket.h b/trunk/include/asm-i386/socket.h index 5755d57c4e95..802ae76195b7 100644 --- a/trunk/include/asm-i386/socket.h +++ b/trunk/include/asm-i386/socket.h @@ -48,6 +48,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_SOCKET_H */ diff --git a/trunk/include/asm-i386/system.h b/trunk/include/asm-i386/system.h index cab0180567f9..0249f912a29c 100644 --- a/trunk/include/asm-i386/system.h +++ b/trunk/include/asm-i386/system.h @@ -427,7 +427,7 @@ static inline unsigned long long __cmpxchg64(volatile void *ptr, unsigned long l * does not enforce ordering, since there is no data dependency between * the read of "a" and the read of "b". Therefore, on some CPUs, such * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb() - * in cases like this where there are no data dependencies. + * in cases like thiswhere there are no data dependencies. **/ #define read_barrier_depends() do { } while(0) diff --git a/trunk/include/asm-i386/thread_info.h b/trunk/include/asm-i386/thread_info.h index 2833fa2c0dd0..8420ed12491e 100644 --- a/trunk/include/asm-i386/thread_info.h +++ b/trunk/include/asm-i386/thread_info.h @@ -37,7 +37,6 @@ struct thread_info { 0-0xBFFFFFFF for user-thead 0-0xFFFFFFFF for kernel-thread */ - void *sysenter_return; struct restart_block restart_block; unsigned long previous_esp; /* ESP of the previous stack in case @@ -84,15 +83,17 @@ struct thread_info { #define init_stack (init_thread_union.stack) -/* how to get the current stack pointer from C */ -register unsigned long current_stack_pointer asm("esp") __attribute_used__; - /* how to get the thread information struct from C */ static inline struct thread_info *current_thread_info(void) { - return (struct thread_info *)(current_stack_pointer & ~(THREAD_SIZE - 1)); + struct thread_info *ti; + __asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1))); + return ti; } +/* how to get the current stack pointer from C */ +register unsigned long current_stack_pointer asm("esp") __attribute_used__; + /* thread information allocation */ #ifdef CONFIG_DEBUG_STACK_USAGE #define alloc_thread_info(tsk) \ @@ -139,7 +140,8 @@ static inline struct thread_info *current_thread_info(void) #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ #define TIF_SECCOMP 8 /* secure computing */ #define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ -#define TIF_MEMDIE 16 +#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ +#define TIF_MEMDIE 17 #define _TIF_SYSCALL_TRACE (1<thread_info->status & TS_POLLING) #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-i386/timer.h b/trunk/include/asm-i386/timer.h index d0ebd05f8516..aed16437479d 100644 --- a/trunk/include/asm-i386/timer.h +++ b/trunk/include/asm-i386/timer.h @@ -3,11 +3,68 @@ #include #include +/** + * struct timer_ops - used to define a timer source + * + * @name: name of the timer. + * @init: Probes and initializes the timer. Takes clock= override + * string as an argument. Returns 0 on success, anything else + * on failure. + * @mark_offset: called by the timer interrupt. + * @get_offset: called by gettimeofday(). Returns the number of microseconds + * since the last timer interupt. + * @monotonic_clock: returns the number of nanoseconds since the init of the + * timer. + * @delay: delays this many clock cycles. + */ +struct timer_opts { + char* name; + void (*mark_offset)(void); + unsigned long (*get_offset)(void); + unsigned long long (*monotonic_clock)(void); + void (*delay)(unsigned long); + unsigned long (*read_timer)(void); + int (*suspend)(pm_message_t state); + int (*resume)(void); +}; + +struct init_timer_opts { + int (*init)(char *override); + struct timer_opts *opts; +}; + #define TICK_SIZE (tick_nsec / 1000) + +extern struct timer_opts* __init select_timer(void); +extern void clock_fallback(void); void setup_pit_timer(void); + /* Modifiers for buggy PIT handling */ + extern int pit_latch_buggy; + +extern struct timer_opts *cur_timer; extern int timer_ack; + +/* list of externed timers */ +extern struct timer_opts timer_none; +extern struct timer_opts timer_pit; +extern struct init_timer_opts timer_pit_init; +extern struct init_timer_opts timer_tsc_init; +#ifdef CONFIG_X86_CYCLONE_TIMER +extern struct init_timer_opts timer_cyclone_init; +#endif + +extern unsigned long calibrate_tsc(void); +extern unsigned long read_timer_tsc(void); +extern void init_cpu_khz(void); extern int recalibrate_cpu_khz(void); +#ifdef CONFIG_HPET_TIMER +extern struct init_timer_opts timer_hpet_init; +extern unsigned long calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr); +#endif +#ifdef CONFIG_X86_PM_TIMER +extern struct init_timer_opts timer_pmtmr_init; +#endif #endif diff --git a/trunk/include/asm-i386/timex.h b/trunk/include/asm-i386/timex.h index 3666044409f0..d434984303ca 100644 --- a/trunk/include/asm-i386/timex.h +++ b/trunk/include/asm-i386/timex.h @@ -7,7 +7,6 @@ #define _ASMi386_TIMEX_H #include -#include #ifdef CONFIG_X86_ELAN # define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */ @@ -16,6 +15,39 @@ #endif +/* + * Standard way to access the cycle counter on i586+ CPUs. + * Currently only used on SMP. + * + * If you really have a SMP machine with i486 chips or older, + * compile for that, and this will just always return zero. + * That's ok, it just means that the nicer scheduling heuristics + * won't work for you. + * + * We only use the low 32 bits, and we'd simply better make sure + * that we reschedule before that wraps. Scheduling at least every + * four billion cycles just basically sounds like a good idea, + * regardless of how fast the machine is. + */ +typedef unsigned long long cycles_t; + +static inline cycles_t get_cycles (void) +{ + unsigned long long ret=0; + +#ifndef CONFIG_X86_TSC + if (!cpu_has_tsc) + return 0; +#endif + +#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC) + rdtscll(ret); +#endif + return ret; +} + +extern unsigned int cpu_khz; + extern int read_current_timer(unsigned long *timer_value); #define ARCH_HAS_READ_CURRENT_TIMER 1 diff --git a/trunk/include/asm-i386/topology.h b/trunk/include/asm-i386/topology.h index 6adbd9b1ae88..b94e5eeef917 100644 --- a/trunk/include/asm-i386/topology.h +++ b/trunk/include/asm-i386/topology.h @@ -28,8 +28,10 @@ #define _ASM_I386_TOPOLOGY_H #ifdef CONFIG_X86_HT -#define topology_physical_package_id(cpu) (cpu_data[cpu].phys_proc_id) -#define topology_core_id(cpu) (cpu_data[cpu].cpu_core_id) +#define topology_physical_package_id(cpu) \ + (phys_proc_id[cpu] == BAD_APICID ? -1 : phys_proc_id[cpu]) +#define topology_core_id(cpu) \ + (cpu_core_id[cpu] == BAD_APICID ? 0 : cpu_core_id[cpu]) #define topology_core_siblings(cpu) (cpu_core_map[cpu]) #define topology_thread_siblings(cpu) (cpu_sibling_map[cpu]) #endif @@ -112,9 +114,4 @@ extern unsigned long node_remap_size[]; extern cpumask_t cpu_coregroup_map(int cpu); -#ifdef CONFIG_SMP -#define mc_capable() (boot_cpu_data.x86_max_cores > 1) -#define smt_capable() (smp_num_siblings > 1) -#endif - #endif /* _ASM_I386_TOPOLOGY_H */ diff --git a/trunk/include/asm-i386/tsc.h b/trunk/include/asm-i386/tsc.h deleted file mode 100644 index 97b828ce31e0..000000000000 --- a/trunk/include/asm-i386/tsc.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * linux/include/asm-i386/tsc.h - * - * i386 TSC related functions - */ -#ifndef _ASM_i386_TSC_H -#define _ASM_i386_TSC_H - -#include -#include - -/* - * Standard way to access the cycle counter on i586+ CPUs. - * Currently only used on SMP. - * - * If you really have a SMP machine with i486 chips or older, - * compile for that, and this will just always return zero. - * That's ok, it just means that the nicer scheduling heuristics - * won't work for you. - * - * We only use the low 32 bits, and we'd simply better make sure - * that we reschedule before that wraps. Scheduling at least every - * four billion cycles just basically sounds like a good idea, - * regardless of how fast the machine is. - */ -typedef unsigned long long cycles_t; - -extern unsigned int cpu_khz; -extern unsigned int tsc_khz; - -static inline cycles_t get_cycles(void) -{ - unsigned long long ret = 0; - -#ifndef CONFIG_X86_TSC - if (!cpu_has_tsc) - return 0; -#endif - -#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC) - rdtscll(ret); -#endif - return ret; -} - -extern void tsc_init(void); -extern void mark_tsc_unstable(void); - -#endif diff --git a/trunk/include/asm-i386/unwind.h b/trunk/include/asm-i386/unwind.h deleted file mode 100644 index 69f0f1df6722..000000000000 --- a/trunk/include/asm-i386/unwind.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef _ASM_I386_UNWIND_H -#define _ASM_I386_UNWIND_H - -/* - * Copyright (C) 2002-2006 Novell, Inc. - * Jan Beulich - * This code is released under version 2 of the GNU GPL. - */ - -#ifdef CONFIG_STACK_UNWIND - -#include -#include -#include -#include - -struct unwind_frame_info -{ - struct pt_regs regs; - struct task_struct *task; -}; - -#define UNW_PC(frame) (frame)->regs.eip -#define UNW_SP(frame) (frame)->regs.esp -#ifdef CONFIG_FRAME_POINTER -#define UNW_FP(frame) (frame)->regs.ebp -#define FRAME_RETADDR_OFFSET 4 -#define FRAME_LINK_OFFSET 0 -#define STACK_BOTTOM(tsk) STACK_LIMIT((tsk)->thread.esp0) -#define STACK_TOP(tsk) ((tsk)->thread.esp0) -#endif -#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1)) - -#define UNW_REGISTER_INFO \ - PTREGS_INFO(eax), \ - PTREGS_INFO(ecx), \ - PTREGS_INFO(edx), \ - PTREGS_INFO(ebx), \ - PTREGS_INFO(esp), \ - PTREGS_INFO(ebp), \ - PTREGS_INFO(esi), \ - PTREGS_INFO(edi), \ - PTREGS_INFO(eip) - -static inline void arch_unw_init_frame_info(struct unwind_frame_info *info, - /*const*/ struct pt_regs *regs) -{ - if (user_mode_vm(regs)) - info->regs = *regs; - else { - memcpy(&info->regs, regs, offsetof(struct pt_regs, esp)); - info->regs.esp = (unsigned long)®s->esp; - info->regs.xss = __KERNEL_DS; - } -} - -static inline void arch_unw_init_blocked(struct unwind_frame_info *info) -{ - memset(&info->regs, 0, sizeof(info->regs)); - info->regs.eip = info->task->thread.eip; - info->regs.xcs = __KERNEL_CS; - __get_user(info->regs.ebp, (long *)info->task->thread.esp); - info->regs.esp = info->task->thread.esp; - info->regs.xss = __KERNEL_DS; - info->regs.xds = __USER_DS; - info->regs.xes = __USER_DS; -} - -extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *, - asmlinkage int (*callback)(struct unwind_frame_info *, - void *arg), - void *arg); - -static inline int arch_unw_user_mode(const struct unwind_frame_info *info) -{ -#if 0 /* This can only work when selector register and EFLAGS saves/restores - are properly annotated (and tracked in UNW_REGISTER_INFO). */ - return user_mode_vm(&info->regs); -#else - return info->regs.eip < PAGE_OFFSET - || (info->regs.eip >= __fix_to_virt(FIX_VDSO) - && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE) - || info->regs.esp < PAGE_OFFSET; -#endif -} - -#else - -#define UNW_PC(frame) ((void)(frame), 0) - -static inline int arch_unw_user_mode(const void *info) -{ - return 0; -} - -#endif - -#endif /* _ASM_I386_UNWIND_H */ diff --git a/trunk/include/asm-ia64/hw_irq.h b/trunk/include/asm-ia64/hw_irq.h index 27f9df6b9145..ea8b8c407ab4 100644 --- a/trunk/include/asm-ia64/hw_irq.h +++ b/trunk/include/asm-ia64/hw_irq.h @@ -97,7 +97,8 @@ extern int reserve_irq_vector (int vector); extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect); extern void register_percpu_irq (ia64_vector vec, struct irqaction *action); -static inline void ia64_resend_irq(unsigned int vector) +static inline void +hw_resend_irq (struct hw_interrupt_type *h, unsigned int vector) { platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0); } diff --git a/trunk/include/asm-ia64/irq.h b/trunk/include/asm-ia64/irq.h index 8acb00190d5a..dbe86c0bbce5 100644 --- a/trunk/include/asm-ia64/irq.h +++ b/trunk/include/asm-ia64/irq.h @@ -14,7 +14,10 @@ #define NR_IRQS 256 #define NR_IRQ_VECTORS NR_IRQS -#define IRQF_PERCPU 0x02000000 +/* + * IRQ line status macro IRQ_PER_CPU is used + */ +#define ARCH_HAS_IRQ_PER_CPU static __inline__ int irq_canonicalize (int irq) diff --git a/trunk/include/asm-ia64/kdebug.h b/trunk/include/asm-ia64/kdebug.h index aed7142f9e4a..c195a9ad1255 100644 --- a/trunk/include/asm-ia64/kdebug.h +++ b/trunk/include/asm-ia64/kdebug.h @@ -40,8 +40,6 @@ struct die_args { extern int register_die_notifier(struct notifier_block *); extern int unregister_die_notifier(struct notifier_block *); -extern int register_page_fault_notifier(struct notifier_block *); -extern int unregister_page_fault_notifier(struct notifier_block *); extern struct atomic_notifier_head ia64die_chain; enum die_val { diff --git a/trunk/include/asm-ia64/kprobes.h b/trunk/include/asm-ia64/kprobes.h index 2418a787c405..8c0fc227f0fb 100644 --- a/trunk/include/asm-ia64/kprobes.h +++ b/trunk/include/asm-ia64/kprobes.h @@ -82,7 +82,6 @@ struct kprobe_ctlblk { #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry #define ARCH_SUPPORTS_KRETPROBES -#define ARCH_INACTIVE_KPROBE_COUNT 1 #define SLOT0_OPCODE_SHIFT (37) #define SLOT1_p1_OPCODE_SHIFT (37 - (64-46)) diff --git a/trunk/include/asm-ia64/nodedata.h b/trunk/include/asm-ia64/nodedata.h index 2fb337b0e9b7..a140310bf84d 100644 --- a/trunk/include/asm-ia64/nodedata.h +++ b/trunk/include/asm-ia64/nodedata.h @@ -46,18 +46,6 @@ struct ia64_node_data { */ #define NODE_DATA(nid) (local_node_data->pg_data_ptrs[nid]) -/* - * LOCAL_DATA_ADDR - This is to calculate the address of other node's - * "local_node_data" at hot-plug phase. The local_node_data - * is pointed by per_cpu_page. Kernel usually use it for - * just executing cpu. However, when new node is hot-added, - * the addresses of local data for other nodes are necessary - * to update all of them. - */ -#define LOCAL_DATA_ADDR(pgdat) \ - ((struct ia64_node_data *)((u64)(pgdat) + \ - L1_CACHE_ALIGN(sizeof(struct pglist_data)))) - #endif /* CONFIG_NUMA */ #endif /* _ASM_IA64_NODEDATA_H */ diff --git a/trunk/include/asm-ia64/signal.h b/trunk/include/asm-ia64/signal.h index 4f5ca5643cb1..5e328ed5d01d 100644 --- a/trunk/include/asm-ia64/signal.h +++ b/trunk/include/asm-ia64/signal.h @@ -56,6 +56,7 @@ * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -75,6 +76,7 @@ #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 @@ -112,6 +114,8 @@ #define _NSIG_BPW 64 #define _NSIG_WORDS (_NSIG / _NSIG_BPW) +#define SA_PERCPU_IRQ 0x02000000 + #endif /* __KERNEL__ */ #include diff --git a/trunk/include/asm-ia64/sn/sn_sal.h b/trunk/include/asm-ia64/sn/sn_sal.h index bd4452bda357..cd490b20d592 100644 --- a/trunk/include/asm-ia64/sn/sn_sal.h +++ b/trunk/include/asm-ia64/sn/sn_sal.h @@ -85,7 +85,6 @@ #define SN_SAL_GET_PROM_FEATURE_SET 0x02000065 #define SN_SAL_SET_OS_FEATURE_SET 0x02000066 #define SN_SAL_INJECT_ERROR 0x02000067 -#define SN_SAL_SET_CPU_NUMBER 0x02000068 /* * Service-specific constants @@ -1151,13 +1150,4 @@ sn_inject_error(u64 paddr, u64 *data, u64 *ecc) local_irq_restore(irq_flags); return ret_stuff.status; } - -static inline int -ia64_sn_set_cpu_number(int cpu) -{ - struct ia64_sal_retval rv; - - SAL_CALL_NOLOCK(rv, SN_SAL_SET_CPU_NUMBER, cpu, 0, 0, 0, 0, 0, 0); - return rv.status; -} #endif /* _ASM_IA64_SN_SN_SAL_H */ diff --git a/trunk/include/asm-ia64/sn/tioca_provider.h b/trunk/include/asm-ia64/sn/tioca_provider.h index 65cdd73c2a57..ab7fe2463468 100644 --- a/trunk/include/asm-ia64/sn/tioca_provider.h +++ b/trunk/include/asm-ia64/sn/tioca_provider.h @@ -27,7 +27,7 @@ #define PV908234 (1 << 1) /* CA:AGPDMA write request data mismatch with ABC1CL merge */ #define PV895469 (1 << 1) - /* TIO:CA TLB invalidate of written GART entries possibly not occurring in CA*/ + /* TIO:CA TLB invalidate of written GART entries possibly not occuring in CA*/ #define PV910244 (1 << 1) struct tioca_dmamap{ diff --git a/trunk/include/asm-ia64/socket.h b/trunk/include/asm-ia64/socket.h index d638ef3d50c3..a255006fb7b5 100644 --- a/trunk/include/asm-ia64/socket.h +++ b/trunk/include/asm-ia64/socket.h @@ -57,6 +57,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_IA64_SOCKET_H */ diff --git a/trunk/include/asm-ia64/thread_info.h b/trunk/include/asm-ia64/thread_info.h index 8bc9869e5765..e5392c4d30c6 100644 --- a/trunk/include/asm-ia64/thread_info.h +++ b/trunk/include/asm-ia64/thread_info.h @@ -27,7 +27,6 @@ struct thread_info { __u32 flags; /* thread_info flags (see TIF_*) */ __u32 cpu; /* current CPU */ __u32 last_cpu; /* Last CPU thread ran on */ - __u32 status; /* Thread synchronous flags */ mm_segment_t addr_limit; /* user-level address space limit */ int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */ struct restart_block restart_block; @@ -104,8 +103,4 @@ struct thread_info { /* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT */ #define TIF_WORK_MASK (TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)) -#define TS_POLLING 1 /* true if in idle loop and not sleeping */ - -#define tsk_is_polling(t) ((t)->thread_info->status & TS_POLLING) - #endif /* _ASM_IA64_THREAD_INFO_H */ diff --git a/trunk/include/asm-ia64/topology.h b/trunk/include/asm-ia64/topology.h index 937c21257523..616b5ed2aa72 100644 --- a/trunk/include/asm-ia64/topology.h +++ b/trunk/include/asm-ia64/topology.h @@ -112,7 +112,6 @@ void build_cpu_to_node_map(void); #define topology_core_id(cpu) (cpu_data(cpu)->core_id) #define topology_core_siblings(cpu) (cpu_core_map[cpu]) #define topology_thread_siblings(cpu) (cpu_sibling_map[cpu]) -#define smt_capable() (smp_num_siblings > 1) #endif #include diff --git a/trunk/include/asm-m32r/hw_irq.h b/trunk/include/asm-m32r/hw_irq.h index 7138537cda03..8d7e9d0e09e8 100644 --- a/trunk/include/asm-m32r/hw_irq.h +++ b/trunk/include/asm-m32r/hw_irq.h @@ -1,4 +1,9 @@ #ifndef _ASM_M32R_HW_IRQ_H #define _ASM_M32R_HW_IRQ_H +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) +{ + /* Nothing to do */ +} + #endif /* _ASM_M32R_HW_IRQ_H */ diff --git a/trunk/include/asm-m32r/signal.h b/trunk/include/asm-m32r/signal.h index e750045164d4..95f69b191953 100644 --- a/trunk/include/asm-m32r/signal.h +++ b/trunk/include/asm-m32r/signal.h @@ -81,6 +81,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -100,6 +101,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 diff --git a/trunk/include/asm-m32r/socket.h b/trunk/include/asm-m32r/socket.h index acdf748fcdc8..8b6680f223c0 100644 --- a/trunk/include/asm-m32r/socket.h +++ b/trunk/include/asm-m32r/socket.h @@ -48,6 +48,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_M32R_SOCKET_H */ diff --git a/trunk/include/asm-m32r/system.h b/trunk/include/asm-m32r/system.h index 66c4742f09e7..33567e8bfe6b 100644 --- a/trunk/include/asm-m32r/system.h +++ b/trunk/include/asm-m32r/system.h @@ -318,7 +318,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) * does not enforce ordering, since there is no data dependency between * the read of "a" and the read of "b". Therefore, on some CPUs, such * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb() - * in cases like this where there are no data dependencies. + * in cases like thiswhere there are no data dependencies. **/ #define read_barrier_depends() do { } while (0) diff --git a/trunk/include/asm-m68k/floppy.h b/trunk/include/asm-m68k/floppy.h index 57f4fdda65ab..63a05ed95c17 100644 --- a/trunk/include/asm-m68k/floppy.h +++ b/trunk/include/asm-m68k/floppy.h @@ -88,8 +88,8 @@ static __inline__ void fd_outb(unsigned char value, int port) static int fd_request_irq(void) { if(MACH_IS_Q40) - return request_irq(FLOPPY_IRQ, floppy_hardint, - IRQF_DISABLED, "floppy", floppy_hardint); + return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT, + "floppy", floppy_hardint); else if(MACH_IS_SUN3X) return sun3xflop_request_irq(); return -ENXIO; diff --git a/trunk/include/asm-m68k/irq.h b/trunk/include/asm-m68k/irq.h index 3257f9881002..f4ae7d8feac6 100644 --- a/trunk/include/asm-m68k/irq.h +++ b/trunk/include/asm-m68k/irq.h @@ -67,8 +67,8 @@ struct pt_regs; /* * various flags for request_irq() - the Amiga now uses the standard - * mechanism like all other architectures - IRQF_DISABLED and - * IRQF_SHARED are your friends. + * mechanism like all other architectures - SA_INTERRUPT and SA_SHIRQ + * are your friends. */ #ifndef MACH_AMIGA_ONLY #define IRQ_FLG_LOCK (0x0001) /* handler is not replaceable */ diff --git a/trunk/include/asm-m68k/signal.h b/trunk/include/asm-m68k/signal.h index de1ba6ead3b4..85037a3d3e8e 100644 --- a/trunk/include/asm-m68k/signal.h +++ b/trunk/include/asm-m68k/signal.h @@ -74,6 +74,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -93,6 +94,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ /* * sigaltstack controls diff --git a/trunk/include/asm-m68k/socket.h b/trunk/include/asm-m68k/socket.h index a5966ec005ae..f578ca4b776a 100644 --- a/trunk/include/asm-m68k/socket.h +++ b/trunk/include/asm-m68k/socket.h @@ -48,6 +48,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_SOCKET_H */ diff --git a/trunk/include/asm-m68k/sun3xflop.h b/trunk/include/asm-m68k/sun3xflop.h index ca8cc4113843..98a9f79dab29 100644 --- a/trunk/include/asm-m68k/sun3xflop.h +++ b/trunk/include/asm-m68k/sun3xflop.h @@ -208,8 +208,7 @@ static int sun3xflop_request_irq(void) if(!once) { once = 1; - error = request_irq(FLOPPY_IRQ, sun3xflop_hardint, - IRQF_DISABLED, "floppy", NULL); + error = request_irq(FLOPPY_IRQ, sun3xflop_hardint, SA_INTERRUPT, "floppy", NULL); return ((error == 0) ? 0 : -1); } else return 0; } diff --git a/trunk/include/asm-m68knommu/bootstd.h b/trunk/include/asm-m68knommu/bootstd.h index bdc1a4ac4fe9..3fdc79f06d50 100644 --- a/trunk/include/asm-m68knommu/bootstd.h +++ b/trunk/include/asm-m68knommu/bootstd.h @@ -52,7 +52,7 @@ type name(void) \ __asm__ __volatile__ ("trap #2" \ : "=g" (__res) \ : "0" (__res) \ - ); \ + : "%d0"); \ __bsc_return(type,__res); \ } @@ -64,7 +64,7 @@ type name(atype a) \ __asm__ __volatile__ ("trap #2" \ : "=g" (__res) \ : "0" (__res), "d" (__a) \ - ); \ + : "%d0"); \ __bsc_return(type,__res); \ } @@ -77,7 +77,7 @@ type name(atype a, btype b) \ __asm__ __volatile__ ("trap #2" \ : "=g" (__res) \ : "0" (__res), "d" (__a), "d" (__b) \ - ); \ + : "%d0"); \ __bsc_return(type,__res); \ } @@ -92,7 +92,7 @@ type name(atype a, btype b, ctype c) \ : "=g" (__res) \ : "0" (__res), "d" (__a), "d" (__b), \ "d" (__c) \ - ); \ + : "%d0"); \ __bsc_return(type,__res); \ } @@ -108,7 +108,7 @@ type name(atype a, btype b, ctype c, dtype d) \ : "=g" (__res) \ : "0" (__res), "d" (__a), "d" (__b), \ "d" (__c), "d" (__d) \ - ); \ + : "%d0"); \ __bsc_return(type,__res); \ } @@ -125,7 +125,7 @@ type name(atype a, btype b, ctype c, dtype d, etype e) \ : "=g" (__res) \ : "0" (__res), "d" (__a), "d" (__b), \ "d" (__c), "d" (__d), "d" (__e) \ - ); \ + : "%d0"); \ __bsc_return(type,__res); \ } diff --git a/trunk/include/asm-m68knommu/irq.h b/trunk/include/asm-m68knommu/irq.h index 45e7a2fd1689..53557274eef8 100644 --- a/trunk/include/asm-m68knommu/irq.h +++ b/trunk/include/asm-m68knommu/irq.h @@ -62,8 +62,8 @@ extern void (*mach_disable_irq)(unsigned int); /* * various flags for request_irq() - the Amiga now uses the standard - * mechanism like all other architectures - IRQF_DISABLED and - * IRQF_SHARED are your friends. + * mechanism like all other architectures - SA_INTERRUPT and SA_SHIRQ + * are your friends. */ #define IRQ_FLG_LOCK (0x0001) /* handler is not replaceable */ #define IRQ_FLG_REPLACE (0x0002) /* replace existing handler */ diff --git a/trunk/include/asm-m68knommu/page_offset.h b/trunk/include/asm-m68knommu/page_offset.h index d4e73e0ba646..8ed6d7b7d9d1 100644 --- a/trunk/include/asm-m68knommu/page_offset.h +++ b/trunk/include/asm-m68knommu/page_offset.h @@ -1,5 +1,46 @@ /* This handles the memory map.. */ -#define PAGE_OFFSET_RAW CONFIG_RAMBASE + +#ifdef CONFIG_COLDFIRE +#if defined(CONFIG_SMALL) +#define PAGE_OFFSET_RAW 0x30020000 +#elif defined(CONFIG_CFV240) +#define PAGE_OFFSET_RAW 0x02000000 +#else +#define PAGE_OFFSET_RAW 0x00000000 +#endif +#endif + +#ifdef CONFIG_M68360 +#define PAGE_OFFSET_RAW 0x00000000 +#endif + +#ifdef CONFIG_PILOT +#ifdef CONFIG_M68328 +#define PAGE_OFFSET_RAW 0x10000000 +#endif +#ifdef CONFIG_M68EZ328 +#define PAGE_OFFSET_RAW 0x00000000 +#endif +#endif +#ifdef CONFIG_UCSIMM +#define PAGE_OFFSET_RAW 0x00000000 +#endif + +#if defined(CONFIG_UCDIMM) || defined(CONFIG_DRAGEN2) +#ifdef CONFIG_M68VZ328 +#define PAGE_OFFSET_RAW 0x00000000 +#endif /* CONFIG_M68VZ328 */ +#endif /* CONFIG_UCDIMM */ + +#ifdef CONFIG_M68EZ328ADS +#define PAGE_OFFSET_RAW 0x00000000 +#endif +#ifdef CONFIG_ALMA_ANS +#define PAGE_OFFSET_RAW 0x00000000 +#endif +#ifdef CONFIG_M68EN302 +#define PAGE_OFFSET_RAW 0x00000000 +#endif diff --git a/trunk/include/asm-m68knommu/ptrace.h b/trunk/include/asm-m68knommu/ptrace.h index 47258e86e8c4..1e19c457de7d 100644 --- a/trunk/include/asm-m68knommu/ptrace.h +++ b/trunk/include/asm-m68knommu/ptrace.h @@ -46,9 +46,11 @@ struct pt_regs { #else unsigned short sr; unsigned long pc; +#ifndef NO_FORMAT_VEC unsigned format : 4; /* frame format specifier */ unsigned vector : 12; /* vector offset */ #endif +#endif }; /* diff --git a/trunk/include/asm-m68knommu/signal.h b/trunk/include/asm-m68knommu/signal.h index 216c08be54a0..1d13187f6062 100644 --- a/trunk/include/asm-m68knommu/signal.h +++ b/trunk/include/asm-m68knommu/signal.h @@ -74,6 +74,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -93,6 +94,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ /* * sigaltstack controls diff --git a/trunk/include/asm-mips/asmmacro.h b/trunk/include/asm-mips/asmmacro.h index 92e62ef711ed..2c42f6b00a49 100644 --- a/trunk/include/asm-mips/asmmacro.h +++ b/trunk/include/asm-mips/asmmacro.h @@ -26,14 +26,14 @@ ori \reg, \reg, TCSTATUS_IXMT xori \reg, \reg, TCSTATUS_IXMT mtc0 \reg, CP0_TCSTATUS - _ehb + ehb .endm .macro local_irq_disable reg=t0 mfc0 \reg, CP0_TCSTATUS ori \reg, \reg, TCSTATUS_IXMT mtc0 \reg, CP0_TCSTATUS - _ehb + ehb .endm #else .macro local_irq_enable reg=t0 diff --git a/trunk/include/asm-mips/cpu-features.h b/trunk/include/asm-mips/cpu-features.h index 44285a9d5520..881ce1f9803d 100644 --- a/trunk/include/asm-mips/cpu-features.h +++ b/trunk/include/asm-mips/cpu-features.h @@ -187,15 +187,19 @@ # endif #endif -#if defined(CONFIG_CPU_MIPSR2_IRQ_VI) && !defined(cpu_has_vint) -# define cpu_has_vint (cpu_data[0].options & MIPS_CPU_VINT) -#elif !defined(cpu_has_vint) +#ifdef CONFIG_CPU_MIPSR2 +# if defined(CONFIG_CPU_MIPSR2_IRQ_VI) && !defined(cpu_has_vint) +# define cpu_has_vint (cpu_data[0].options & MIPS_CPU_VINT) +# else +# define cpu_has_vint 0 +# endif +# if defined(CONFIG_CPU_MIPSR2_IRQ_EI) && !defined(cpu_has_veic) +# define cpu_has_veic (cpu_data[0].options & MIPS_CPU_VEIC) +# else +# define cpu_has_veic 0 +# endif +#else # define cpu_has_vint 0 -#endif - -#if defined(CONFIG_CPU_MIPSR2_IRQ_EI) && !defined(cpu_has_veic) -# define cpu_has_veic (cpu_data[0].options & MIPS_CPU_VEIC) -#elif !defined(cpu_has_veic) # define cpu_has_veic 0 #endif diff --git a/trunk/include/asm-mips/fixmap.h b/trunk/include/asm-mips/fixmap.h index 6959bdb59310..1cadefbbc037 100644 --- a/trunk/include/asm-mips/fixmap.h +++ b/trunk/include/asm-mips/fixmap.h @@ -69,11 +69,7 @@ extern void __set_fixmap (enum fixed_addresses idx, * the start of the fixmap, and leave one page empty * at the top of mem.. */ -#if defined(CONFIG_CPU_TX39XX) || defined(CONFIG_CPU_TX49XX) -#define FIXADDR_TOP (0xff000000UL - 0x2000) -#else #define FIXADDR_TOP (0xffffe000UL) -#endif #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) diff --git a/trunk/include/asm-mips/hazards.h b/trunk/include/asm-mips/hazards.h index 25f5e8a4177d..66943c451c1d 100644 --- a/trunk/include/asm-mips/hazards.h +++ b/trunk/include/asm-mips/hazards.h @@ -69,10 +69,10 @@ * Use a macro for ehb unless explicit support for MIPSR2 is enabled */ -#define irq_enable_hazard \ +#define irq_enable_hazard _ehb -#define irq_disable_hazard \ +#define irq_disable_hazard _ehb #elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) diff --git a/trunk/include/asm-mips/hw_irq.h b/trunk/include/asm-mips/hw_irq.h index 458d9fdc76bf..c854d017c0e5 100644 --- a/trunk/include/asm-mips/hw_irq.h +++ b/trunk/include/asm-mips/hw_irq.h @@ -19,9 +19,9 @@ extern void init_8259A(int aeoi); extern atomic_t irq_err_count; -/* - * interrupt-retrigger: NOP for now. This may not be apropriate for all - * machines, we'll see ... - */ +/* This may not be apropriate for all machines, we'll see ... */ +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) +{ +} #endif /* __ASM_HW_IRQ_H */ diff --git a/trunk/include/asm-mips/irq.h b/trunk/include/asm-mips/irq.h index 896550bad322..d35c61776a02 100644 --- a/trunk/include/asm-mips/irq.h +++ b/trunk/include/asm-mips/irq.h @@ -76,8 +76,4 @@ extern int setup_irq_smtc(unsigned int irq, struct irqaction * new, unsigned long hwmask); #endif /* CONFIG_MIPS_MT_SMTC */ -#ifdef CONFIG_SMP -#define ARCH_HAS_IRQ_PER_CPU -#endif - #endif /* _ASM_IRQ_H */ diff --git a/trunk/include/asm-mips/mach-au1x00/au1xxx_psc.h b/trunk/include/asm-mips/mach-au1x00/au1xxx_psc.h index 1bd4e27caf6b..d7cbacdd21fe 100644 --- a/trunk/include/asm-mips/mach-au1x00/au1xxx_psc.h +++ b/trunk/include/asm-mips/mach-au1x00/au1xxx_psc.h @@ -512,7 +512,7 @@ typedef struct psc_smb { /* Transmit register control. */ -#define PSC_SMBTXRX_RSR (1 << 28) +#define PSC_SMBTXRX_RSR (1 << 30) #define PSC_SMBTXRX_STP (1 << 29) #define PSC_SMBTXRX_DATAMASK (0xff) diff --git a/trunk/include/asm-mips/mach-generic/floppy.h b/trunk/include/asm-mips/mach-generic/floppy.h index 001a8ce17c17..83cd69e30ec3 100644 --- a/trunk/include/asm-mips/mach-generic/floppy.h +++ b/trunk/include/asm-mips/mach-generic/floppy.h @@ -98,7 +98,7 @@ static inline void fd_disable_irq(void) static inline int fd_request_irq(void) { return request_irq(FLOPPY_IRQ, floppy_interrupt, - IRQF_DISABLED, "floppy", NULL); + SA_INTERRUPT, "floppy", NULL); } static inline void fd_free_irq(void) diff --git a/trunk/include/asm-mips/mach-jazz/floppy.h b/trunk/include/asm-mips/mach-jazz/floppy.h index 56e9ca6ae426..9413117915f4 100644 --- a/trunk/include/asm-mips/mach-jazz/floppy.h +++ b/trunk/include/asm-mips/mach-jazz/floppy.h @@ -90,7 +90,7 @@ static inline void fd_disable_irq(void) static inline int fd_request_irq(void) { return request_irq(FLOPPY_IRQ, floppy_interrupt, - IRQF_DISABLED, "floppy", NULL); + SA_INTERRUPT, "floppy", NULL); } static inline void fd_free_irq(void) diff --git a/trunk/include/asm-mips/mach-mips/irq.h b/trunk/include/asm-mips/mach-mips/irq.h index e994b0c01227..083d9c512a04 100644 --- a/trunk/include/asm-mips/mach-mips/irq.h +++ b/trunk/include/asm-mips/mach-mips/irq.h @@ -4,4 +4,10 @@ #define NR_IRQS 256 +#ifdef CONFIG_SMP + +#define ARCH_HAS_IRQ_PER_CPU + +#endif + #endif /* __ASM_MACH_MIPS_IRQ_H */ diff --git a/trunk/include/asm-mips/mipsregs.h b/trunk/include/asm-mips/mipsregs.h index 9192d76c133d..673977901ed3 100644 --- a/trunk/include/asm-mips/mipsregs.h +++ b/trunk/include/asm-mips/mipsregs.h @@ -1459,8 +1459,7 @@ static inline void __emt(unsigned int previous) static inline void __ehb(void) { __asm__ __volatile__( - " .set mips32r2 \n" - " ehb \n" " .set mips0 \n"); + " ehb \n"); } /* diff --git a/trunk/include/asm-mips/signal.h b/trunk/include/asm-mips/signal.h index 87a1dff95199..a1f3a3fa9bd6 100644 --- a/trunk/include/asm-mips/signal.h +++ b/trunk/include/asm-mips/signal.h @@ -64,6 +64,7 @@ typedef unsigned long old_sigset_t; /* at least 32 bits */ * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -83,6 +84,7 @@ typedef unsigned long old_sigset_t; /* at least 32 bits */ #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 /* Only for o32 */ @@ -97,6 +99,15 @@ typedef unsigned long old_sigset_t; /* at least 32 bits */ #ifdef __KERNEL__ +/* + * These values of sa_flags are used only by the kernel as part of the + * irq handling routines. + * + * SA_INTERRUPT is also used by the irq handling routines. + * SA_SHIRQ flag is for shared interrupt support on PCI and EISA. + */ +#define SA_SAMPLE_RANDOM SA_RESTART + #ifdef CONFIG_TRAD_SIGNALS #define sig_uses_siginfo(ka) ((ka)->sa.sa_flags & SA_SIGINFO) #else diff --git a/trunk/include/asm-mips/sn/ioc3.h b/trunk/include/asm-mips/sn/ioc3.h index 099677774d71..f7d530f306f2 100644 --- a/trunk/include/asm-mips/sn/ioc3.h +++ b/trunk/include/asm-mips/sn/ioc3.h @@ -5,8 +5,6 @@ #ifndef _IOC3_H #define _IOC3_H -#include - /* SUPERIO uart register map */ typedef volatile struct ioc3_uartregs { union { diff --git a/trunk/include/asm-mips/sn/klconfig.h b/trunk/include/asm-mips/sn/klconfig.h index b63cd0655b3d..52238e65af8e 100644 --- a/trunk/include/asm-mips/sn/klconfig.h +++ b/trunk/include/asm-mips/sn/klconfig.h @@ -602,7 +602,7 @@ typedef struct klcpu_s { /* CPU */ typedef struct klhub_s { /* HUB */ klinfo_t hub_info; - unsigned int hub_flags; /* PCFG_HUB_xxx flags */ + uint hub_flags; /* PCFG_HUB_xxx flags */ klport_t hub_port; /* hub is connected to this */ nic_t hub_box_nic; /* nic of containing box */ klconf_off_t hub_mfg_nic; /* MFG NIC string */ @@ -611,7 +611,7 @@ typedef struct klhub_s { /* HUB */ typedef struct klhub_uart_s { /* HUB */ klinfo_t hubuart_info; - unsigned int hubuart_flags; /* PCFG_HUB_xxx flags */ + uint hubuart_flags; /* PCFG_HUB_xxx flags */ nic_t hubuart_box_nic; /* nic of containing box */ } klhub_uart_t ; @@ -710,7 +710,7 @@ typedef struct klvmed_s { /* VME DEVICE - VME BOARD */ /* XXX - Don't we need the number of ports here?!? */ typedef struct klrou_s { /* ROUTER */ klinfo_t rou_info ; - unsigned int rou_flags ; /* PCFG_ROUTER_xxx flags */ + uint rou_flags ; /* PCFG_ROUTER_xxx flags */ nic_t rou_box_nic ; /* nic of the containing module */ klport_t rou_port[MAX_ROUTER_PORTS + 1] ; /* array index 1 to 6 */ klconf_off_t rou_mfg_nic ; /* MFG NIC string */ @@ -733,8 +733,8 @@ typedef struct klgfx_s { /* GRAPHICS Device */ klinfo_t gfx_info; klconf_off_t old_gndevs; /* for compatibility with older proms */ klconf_off_t old_gdoff0; /* for compatibility with older proms */ - unsigned int cookie; /* for compatibility with older proms */ - unsigned int moduleslot; + uint cookie; /* for compatibility with older proms */ + uint moduleslot; struct klgfx_s *gfx_next_pipe; graphics_t gfx_specific; klconf_off_t pad0; /* for compatibility with older proms */ diff --git a/trunk/include/asm-mips/socket.h b/trunk/include/asm-mips/socket.h index 36ebe4e186a7..0bb31e5aaca6 100644 --- a/trunk/include/asm-mips/socket.h +++ b/trunk/include/asm-mips/socket.h @@ -69,7 +69,6 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ #define SO_PEERSEC 30 #define SO_SNDBUFFORCE 31 #define SO_RCVBUFFORCE 33 -#define SO_PASSSEC 34 #ifdef __KERNEL__ diff --git a/trunk/include/asm-mips/stackframe.h b/trunk/include/asm-mips/stackframe.h index 158a4cd12e46..513aa5133830 100644 --- a/trunk/include/asm-mips/stackframe.h +++ b/trunk/include/asm-mips/stackframe.h @@ -304,7 +304,7 @@ mfc0 v0, CP0_TCSTATUS ori v0, TCSTATUS_IXMT mtc0 v0, CP0_TCSTATUS - _ehb + ehb DMT 5 # dmt a1 jal mips_ihb #endif /* CONFIG_MIPS_MT_SMTC */ @@ -325,14 +325,14 @@ * restore TCStatus.IXMT. */ LONG_L v1, PT_TCSTATUS(sp) - _ehb + ehb mfc0 v0, CP0_TCSTATUS andi v1, TCSTATUS_IXMT /* We know that TCStatua.IXMT should be set from above */ xori v0, v0, TCSTATUS_IXMT or v0, v0, v1 mtc0 v0, CP0_TCSTATUS - _ehb + ehb andi a1, a1, VPECONTROL_TE beqz a1, 1f emt @@ -411,7 +411,7 @@ /* Clear TKSU, leave IXMT */ xori t0, 0x00001800 mtc0 t0, CP0_TCSTATUS - _ehb + ehb /* We need to leave the global IE bit set, but clear EXL...*/ mfc0 t0, CP0_STATUS ori t0, ST0_EXL | ST0_ERL @@ -438,7 +438,7 @@ * and enable interrupts only for the * current TC, using the TCStatus register. */ - _ehb + ehb mfc0 t0,CP0_TCSTATUS /* Fortunately CU 0 is in the same place in both registers */ /* Set TCU0, TKSU (for later inversion) and IXMT */ @@ -447,7 +447,7 @@ /* Clear TKSU *and* IXMT */ xori t0, 0x00001c00 mtc0 t0, CP0_TCSTATUS - _ehb + ehb /* We need to leave the global IE bit set, but clear EXL...*/ mfc0 t0, CP0_STATUS ori t0, ST0_EXL @@ -479,7 +479,7 @@ andi v1, v0, TCSTATUS_IXMT ori v0, TCSTATUS_IXMT mtc0 v0, CP0_TCSTATUS - _ehb + ehb DMT 2 # dmt v0 /* * We don't know a priori if ra is "live" @@ -495,7 +495,7 @@ xori t0, 0x1e mtc0 t0, CP0_STATUS #ifdef CONFIG_MIPS_MT_SMTC - _ehb + ehb andi v0, v0, VPECONTROL_TE beqz v0, 2f nop /* delay slot */ diff --git a/trunk/include/asm-mips/unistd.h b/trunk/include/asm-mips/unistd.h index 809f9f55bacb..8bb0bb9b2e68 100644 --- a/trunk/include/asm-mips/unistd.h +++ b/trunk/include/asm-mips/unistd.h @@ -326,17 +326,16 @@ #define __NR_unshare (__NR_Linux + 303) #define __NR_splice (__NR_Linux + 304) #define __NR_sync_file_range (__NR_Linux + 305) -#define __NR_tee (__NR_Linux + 306) /* * Offset of the last Linux o32 flavoured syscall */ -#define __NR_Linux_syscalls 306 +#define __NR_Linux_syscalls 305 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #define __NR_O32_Linux 4000 -#define __NR_O32_Linux_syscalls 306 +#define __NR_O32_Linux_syscalls 305 #if _MIPS_SIM == _MIPS_SIM_ABI64 @@ -609,17 +608,16 @@ #define __NR_unshare (__NR_Linux + 262) #define __NR_splice (__NR_Linux + 263) #define __NR_sync_file_range (__NR_Linux + 264) -#define __NR_tee (__NR_Linux + 265) /* * Offset of the last Linux 64-bit flavoured syscall */ -#define __NR_Linux_syscalls 265 +#define __NR_Linux_syscalls 264 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #define __NR_64_Linux 5000 -#define __NR_64_Linux_syscalls 265 +#define __NR_64_Linux_syscalls 264 #if _MIPS_SIM == _MIPS_SIM_NABI32 @@ -896,17 +894,16 @@ #define __NR_unshare (__NR_Linux + 266) #define __NR_splice (__NR_Linux + 267) #define __NR_sync_file_range (__NR_Linux + 268) -#define __NR_tee (__NR_Linux + 269) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 269 +#define __NR_Linux_syscalls 268 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 269 +#define __NR_N32_Linux_syscalls 268 #ifdef __KERNEL__ diff --git a/trunk/include/asm-parisc/assembly.h b/trunk/include/asm-parisc/assembly.h index 1a7bfe699e0c..3ce3440d1b0c 100644 --- a/trunk/include/asm-parisc/assembly.h +++ b/trunk/include/asm-parisc/assembly.h @@ -48,7 +48,6 @@ #define CALLEE_SAVE_FRAME_SIZE (CALLEE_REG_FRAME_SIZE + CALLEE_FLOAT_FRAME_SIZE) #ifdef CONFIG_PA20 -#define LDCW ldcw,co #define BL b,l # ifdef CONFIG_64BIT # define LEVEL 2.0w @@ -56,7 +55,6 @@ # define LEVEL 2.0 # endif #else -#define LDCW ldcw #define BL bl #define LEVEL 1.1 #endif diff --git a/trunk/include/asm-parisc/compat.h b/trunk/include/asm-parisc/compat.h index 71b4eeea205a..289624d8b2d4 100644 --- a/trunk/include/asm-parisc/compat.h +++ b/trunk/include/asm-parisc/compat.h @@ -5,7 +5,6 @@ */ #include #include -#include #define COMPAT_USER_HZ 100 @@ -150,14 +149,4 @@ static __inline__ void __user *compat_alloc_user_space(long len) return (void __user *)regs->gr[30]; } -static inline int __is_compat_task(struct task_struct *t) -{ - return personality(t->personality) == PER_LINUX32; -} - -static inline int is_compat_task(void) -{ - return __is_compat_task(current); -} - #endif /* _ASM_PARISC_COMPAT_H */ diff --git a/trunk/include/asm-parisc/floppy.h b/trunk/include/asm-parisc/floppy.h index da2f9c157143..458cdb2a7530 100644 --- a/trunk/include/asm-parisc/floppy.h +++ b/trunk/include/asm-parisc/floppy.h @@ -156,11 +156,11 @@ static int vdma_get_dma_residue(unsigned int dummy) static int fd_request_irq(void) { if(can_use_virtual_dma) - return request_irq(FLOPPY_IRQ, floppy_hardint, - IRQF_DISABLED, "floppy", NULL); + return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT, + "floppy", NULL); else - return request_irq(FLOPPY_IRQ, floppy_interrupt, - IRQF_DISABLED, "floppy", NULL); + return request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT, + "floppy", NULL); } static unsigned long dma_mem_alloc(unsigned long size) diff --git a/trunk/include/asm-parisc/hw_irq.h b/trunk/include/asm-parisc/hw_irq.h index 6707f7df3921..151426e27521 100644 --- a/trunk/include/asm-parisc/hw_irq.h +++ b/trunk/include/asm-parisc/hw_irq.h @@ -3,6 +3,15 @@ /* * linux/include/asm/hw_irq.h + * + * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar + * + * moved some of the old arch/i386/kernel/irq.h to here. VY + * + * IRQ/IPI changes taken from work by Thomas Radke + * */ +extern void hw_resend_irq(struct hw_interrupt_type *, unsigned int); + #endif diff --git a/trunk/include/asm-parisc/irq.h b/trunk/include/asm-parisc/irq.h index 5cae260615a2..377ba90c7d02 100644 --- a/trunk/include/asm-parisc/irq.h +++ b/trunk/include/asm-parisc/irq.h @@ -26,6 +26,11 @@ #define NR_IRQS (CPU_IRQ_MAX + 1) +/* + * IRQ line status macro IRQ_PER_CPU is used + */ +#define ARCH_HAS_IRQ_PER_CPU + static __inline__ int irq_canonicalize(int irq) { return (irq == 2) ? 9 : irq; diff --git a/trunk/include/asm-parisc/pdc.h b/trunk/include/asm-parisc/pdc.h index c9b2e35326ee..08364f957e7a 100644 --- a/trunk/include/asm-parisc/pdc.h +++ b/trunk/include/asm-parisc/pdc.h @@ -278,11 +278,12 @@ typedef struct { /* constants for OS (NVM...) */ #define OS_ID_NONE 0 /* Undefined OS ID */ #define OS_ID_HPUX 1 /* HP-UX OS */ +#define OS_ID_LINUX OS_ID_HPUX /* just use the same value as hpux */ #define OS_ID_MPEXL 2 /* MPE XL OS */ #define OS_ID_OSF 3 /* OSF OS */ #define OS_ID_HPRT 4 /* HP-RT OS */ #define OS_ID_NOVEL 5 /* NOVELL OS */ -#define OS_ID_LINUX 6 /* Linux */ +#define OS_ID_NT 6 /* NT OS */ /* constants for PDC_CHASSIS */ @@ -351,8 +352,8 @@ struct pdc_cache_cf { /* for PDC_CACHE (I/D-caches) */ cc_wt : 1, /* 0 = WT-Dcache, 1 = WB-Dcache */ cc_sh : 2, /* 0 = separate I/D-cache, else shared I/D-cache */ cc_cst : 3, /* 0 = incoherent D-cache, 1=coherent D-cache */ - cc_pad1 : 10, /* reserved */ - cc_hv : 3; /* hversion dependent */ + cc_pad1 : 5, /* reserved */ + cc_assoc: 8; /* associativity of I/D-cache */ }; struct pdc_tlb_cf { /* for PDC_CACHE (I/D-TLB's) */ @@ -718,7 +719,6 @@ void setup_pdc(void); /* in inventory.c */ int pdc_add_valid(unsigned long address); int pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len); int pdc_chassis_disp(unsigned long disp); -int pdc_chassis_warn(unsigned long *warn); int pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info); int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index, void *iodc_data, unsigned int iodc_data_size); @@ -732,7 +732,6 @@ int pdc_model_cpuid(unsigned long *cpu_id); int pdc_model_versions(unsigned long *versions, int id); int pdc_model_capabilities(unsigned long *capabilities); int pdc_cache_info(struct pdc_cache_info *cache); -int pdc_spaceid_bits(unsigned long *space_bits); #ifndef CONFIG_PA20 int pdc_btlb_info(struct pdc_btlb_info *btlb); int pdc_mem_map_hpa(struct pdc_memory_map *r_addr, struct pdc_module_path *mod_path); @@ -776,18 +775,6 @@ int pdc_sti_call(unsigned long func, unsigned long flags, extern void pdc_init(void); -static inline char * os_id_to_string(u16 os_id) { - switch(os_id) { - case OS_ID_NONE: return "No OS"; - case OS_ID_HPUX: return "HP-UX"; - case OS_ID_MPEXL: return "MPE-iX"; - case OS_ID_OSF: return "OSF"; - case OS_ID_HPRT: return "HP-RT"; - case OS_ID_NOVEL: return "Novell Netware"; - case OS_ID_LINUX: return "Linux"; - default: return "Unknown"; - } -} #endif /* __ASSEMBLY__ */ #endif /* _PARISC_PDC_H */ diff --git a/trunk/include/asm-parisc/pgtable.h b/trunk/include/asm-parisc/pgtable.h index 5066c54dae0a..b6bcc672ba80 100644 --- a/trunk/include/asm-parisc/pgtable.h +++ b/trunk/include/asm-parisc/pgtable.h @@ -506,13 +506,13 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, /* TLB page size encoding - see table 3-1 in parisc20.pdf */ #define _PAGE_SIZE_ENCODING_4K 0 -#define _PAGE_SIZE_ENCODING_16K 1 -#define _PAGE_SIZE_ENCODING_64K 2 +#define _PAGE_SIZE_ENCODING_16K 1 +#define _PAGE_SIZE_ENCODING_64K 2 #define _PAGE_SIZE_ENCODING_256K 3 #define _PAGE_SIZE_ENCODING_1M 4 #define _PAGE_SIZE_ENCODING_4M 5 -#define _PAGE_SIZE_ENCODING_16M 6 -#define _PAGE_SIZE_ENCODING_64M 7 +#define _PAGE_SIZE_ENCODING_16M 6 +#define _PAGE_SIZE_ENCODING_64M 7 #if defined(CONFIG_PARISC_PAGE_SIZE_4KB) # define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_4K diff --git a/trunk/include/asm-parisc/processor.h b/trunk/include/asm-parisc/processor.h index b73626f040da..ca49dc91f4fc 100644 --- a/trunk/include/asm-parisc/processor.h +++ b/trunk/include/asm-parisc/processor.h @@ -26,12 +26,14 @@ * Default implementation of macro that returns current * instruction pointer ("program counter"). */ -#ifdef CONFIG_PA20 -#define current_ia(x) __asm__("mfia %0" : "=r"(x)) -#else /* mfia added in pa2.0 */ -#define current_ia(x) __asm__("blr 0,%0\n\tnop" : "=r"(x)) -#endif -#define current_text_addr() ({ void *pc; current_ia(pc); pc; }) + +/* We cannot use MFIA as it was added for PA2.0 - prumpf + + At one point there were no "0f/0b" type local symbols in gas for + PA-RISC. This is no longer true, but this still seems like the + nicest way to implement this. */ + +#define current_text_addr() ({ void *pc; __asm__("\n\tblr 0,%0\n\tnop":"=r" (pc)); pc; }) #define TASK_SIZE (current->thread.task_size) #define TASK_UNMAPPED_BASE (current->thread.map_base) diff --git a/trunk/include/asm-parisc/signal.h b/trunk/include/asm-parisc/signal.h index 98a82fa0cfdb..25cb23ef7dd1 100644 --- a/trunk/include/asm-parisc/signal.h +++ b/trunk/include/asm-parisc/signal.h @@ -48,6 +48,7 @@ * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -68,6 +69,7 @@ #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 /* obsolete -- ignored */ diff --git a/trunk/include/asm-parisc/socket.h b/trunk/include/asm-parisc/socket.h index ce2eae1708b5..1bf54dc53c10 100644 --- a/trunk/include/asm-parisc/socket.h +++ b/trunk/include/asm-parisc/socket.h @@ -48,6 +48,5 @@ #define SO_ACCEPTCONN 0x401c #define SO_PEERSEC 0x401d -#define SO_PASSSEC 0x401e #endif /* _ASM_SOCKET_H */ diff --git a/trunk/include/asm-parisc/system.h b/trunk/include/asm-parisc/system.h index 5fe2d2329ab5..863876134b2c 100644 --- a/trunk/include/asm-parisc/system.h +++ b/trunk/include/asm-parisc/system.h @@ -155,14 +155,13 @@ static inline void set_eiem(unsigned long val) type and dynamically select the 16-byte aligned int from the array for the semaphore. */ -#define __PA_LDCW_ALIGNMENT 16 -#define __ldcw_align(a) ({ \ - unsigned long __ret = (unsigned long) &(a)->lock[0]; \ - __ret = (__ret + __PA_LDCW_ALIGNMENT - 1) \ - & ~(__PA_LDCW_ALIGNMENT - 1); \ - (volatile unsigned int *) __ret; \ +#define __PA_LDCW_ALIGNMENT 16 +#define __ldcw_align(a) ({ \ + unsigned long __ret = (unsigned long) &(a)->lock[0]; \ + __ret = (__ret + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1); \ + (volatile unsigned int *) __ret; \ }) -#define __LDCW "ldcw" +#define LDCW "ldcw" #else /*CONFIG_PA20*/ /* From: "Jim Hull" @@ -172,18 +171,17 @@ static inline void set_eiem(unsigned long val) they only require "natural" alignment (4-byte for ldcw, 8-byte for ldcd). */ -#define __PA_LDCW_ALIGNMENT 4 +#define __PA_LDCW_ALIGNMENT 4 #define __ldcw_align(a) ((volatile unsigned int *)a) -#define __LDCW "ldcw,co" +#define LDCW "ldcw,co" #endif /*!CONFIG_PA20*/ /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. */ -#define __ldcw(a) ({ \ - unsigned __ret; \ - __asm__ __volatile__(__LDCW " 0(%1),%0" \ - : "=r" (__ret) : "r" (a)); \ - __ret; \ +#define __ldcw(a) ({ \ + unsigned __ret; \ + __asm__ __volatile__(LDCW " 0(%1),%0" : "=r" (__ret) : "r" (a)); \ + __ret; \ }) #ifdef CONFIG_SMP diff --git a/trunk/include/asm-parisc/uaccess.h b/trunk/include/asm-parisc/uaccess.h index d973e8b3466c..f6c417c8c484 100644 --- a/trunk/include/asm-parisc/uaccess.h +++ b/trunk/include/asm-parisc/uaccess.h @@ -172,11 +172,7 @@ struct exception_data { /* * The "__put_user/kernel_asm()" macros tell gcc they read from memory * instead of writing. This is because they do not write to any memory - * gcc knows about, so there are no aliasing issues. These macros must - * also be aware that "fixup_put_user_skip_[12]" are executed in the - * context of the fault, and any registers used there must be listed - * as clobbers. In this case only "r1" is used by the current routines. - * r8/r9 are already listed as err/val. + * gcc knows about, so there are no aliasing issues. */ #ifdef __LP64__ @@ -187,8 +183,7 @@ struct exception_data { "\t.dword\t1b,fixup_put_user_skip_1\n" \ "\t.previous" \ : "=r"(__pu_err) \ - : "r"(ptr), "r"(x), "0"(__pu_err) \ - : "r1") + : "r"(ptr), "r"(x), "0"(__pu_err)) #define __put_user_asm(stx,x,ptr) \ __asm__ __volatile__ ( \ diff --git a/trunk/include/asm-parisc/unistd.h b/trunk/include/asm-parisc/unistd.h index 27bcfad1c3e3..12b867238a47 100644 --- a/trunk/include/asm-parisc/unistd.h +++ b/trunk/include/asm-parisc/unistd.h @@ -797,6 +797,11 @@ #define SYS_ify(syscall_name) __NR_##syscall_name +/* Assume all syscalls are done from PIC code just to be + * safe. The worst case scenario is that you lose a register + * and save/restore r19 across the syscall. */ +#define PIC + #ifndef ASM_LINE_SEP # define ASM_LINE_SEP ; #endif diff --git a/trunk/include/asm-powerpc/cputable.h b/trunk/include/asm-powerpc/cputable.h index 1ba3c9983614..fab41c280aa1 100644 --- a/trunk/include/asm-powerpc/cputable.h +++ b/trunk/include/asm-powerpc/cputable.h @@ -117,30 +117,38 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_PPC_LE ASM_CONST(0x0000000000200000) #define CPU_FTR_REAL_LE ASM_CONST(0x0000000000400000) -/* - * Add the 64-bit processor unique features in the top half of the word; - * on 32-bit, make the names available but defined to be 0. - */ #ifdef __powerpc64__ -#define LONG_ASM_CONST(x) ASM_CONST(x) +/* Add the 64b processor unique features in the top half of the word */ +#define CPU_FTR_SLB ASM_CONST(0x0000000100000000) +#define CPU_FTR_16M_PAGE ASM_CONST(0x0000000200000000) +#define CPU_FTR_TLBIEL ASM_CONST(0x0000000400000000) +#define CPU_FTR_NOEXECUTE ASM_CONST(0x0000000800000000) +#define CPU_FTR_IABR ASM_CONST(0x0000002000000000) +#define CPU_FTR_MMCRA ASM_CONST(0x0000004000000000) +#define CPU_FTR_CTRL ASM_CONST(0x0000008000000000) +#define CPU_FTR_SMT ASM_CONST(0x0000010000000000) +#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0000020000000000) +#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0000040000000000) +#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0000100000000000) +#define CPU_FTR_PAUSE_ZERO ASM_CONST(0x0000200000000000) +#define CPU_FTR_PURR ASM_CONST(0x0000400000000000) #else -#define LONG_ASM_CONST(x) 0 +/* ensure on 32b processors the flags are available for compiling but + * don't do anything */ +#define CPU_FTR_SLB ASM_CONST(0x0) +#define CPU_FTR_16M_PAGE ASM_CONST(0x0) +#define CPU_FTR_TLBIEL ASM_CONST(0x0) +#define CPU_FTR_NOEXECUTE ASM_CONST(0x0) +#define CPU_FTR_IABR ASM_CONST(0x0) +#define CPU_FTR_MMCRA ASM_CONST(0x0) +#define CPU_FTR_CTRL ASM_CONST(0x0) +#define CPU_FTR_SMT ASM_CONST(0x0) +#define CPU_FTR_COHERENT_ICACHE ASM_CONST(0x0) +#define CPU_FTR_LOCKLESS_TLBIE ASM_CONST(0x0) +#define CPU_FTR_CI_LARGE_PAGE ASM_CONST(0x0) +#define CPU_FTR_PURR ASM_CONST(0x0) #endif -#define CPU_FTR_SLB LONG_ASM_CONST(0x0000000100000000) -#define CPU_FTR_16M_PAGE LONG_ASM_CONST(0x0000000200000000) -#define CPU_FTR_TLBIEL LONG_ASM_CONST(0x0000000400000000) -#define CPU_FTR_NOEXECUTE LONG_ASM_CONST(0x0000000800000000) -#define CPU_FTR_IABR LONG_ASM_CONST(0x0000002000000000) -#define CPU_FTR_MMCRA LONG_ASM_CONST(0x0000004000000000) -#define CPU_FTR_CTRL LONG_ASM_CONST(0x0000008000000000) -#define CPU_FTR_SMT LONG_ASM_CONST(0x0000010000000000) -#define CPU_FTR_COHERENT_ICACHE LONG_ASM_CONST(0x0000020000000000) -#define CPU_FTR_LOCKLESS_TLBIE LONG_ASM_CONST(0x0000040000000000) -#define CPU_FTR_CI_LARGE_PAGE LONG_ASM_CONST(0x0000100000000000) -#define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) -#define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000) - #ifndef __ASSEMBLY__ #define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ diff --git a/trunk/include/asm-powerpc/floppy.h b/trunk/include/asm-powerpc/floppy.h index fd242a22331c..9c8d91bf5a0d 100644 --- a/trunk/include/asm-powerpc/floppy.h +++ b/trunk/include/asm-powerpc/floppy.h @@ -27,7 +27,7 @@ #define fd_disable_irq() disable_irq(FLOPPY_IRQ) #define fd_cacheflush(addr,size) /* nothing */ #define fd_request_irq() request_irq(FLOPPY_IRQ, floppy_interrupt, \ - IRQF_DISABLED, "floppy", NULL) + SA_INTERRUPT, "floppy", NULL) #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL); #ifdef CONFIG_PCI diff --git a/trunk/include/asm-powerpc/hw_irq.h b/trunk/include/asm-powerpc/hw_irq.h index d40359204aba..ce0f7db63c16 100644 --- a/trunk/include/asm-powerpc/hw_irq.h +++ b/trunk/include/asm-powerpc/hw_irq.h @@ -86,27 +86,27 @@ static inline void local_irq_save_ptr(unsigned long *flags) #define mask_irq(irq) \ ({ \ irq_desc_t *desc = get_irq_desc(irq); \ - if (desc->chip && desc->chip->disable) \ - desc->chip->disable(irq); \ + if (desc->handler && desc->handler->disable) \ + desc->handler->disable(irq); \ }) #define unmask_irq(irq) \ ({ \ irq_desc_t *desc = get_irq_desc(irq); \ - if (desc->chip && desc->chip->enable) \ - desc->chip->enable(irq); \ + if (desc->handler && desc->handler->enable) \ + desc->handler->enable(irq); \ }) #define ack_irq(irq) \ ({ \ irq_desc_t *desc = get_irq_desc(irq); \ - if (desc->chip && desc->chip->ack) \ - desc->chip->ack(irq); \ + if (desc->handler && desc->handler->ack) \ + desc->handler->ack(irq); \ }) -/* - * interrupt-retrigger: should we handle this via lost interrupts and IPIs - * or should we not care like we do now ? --BenH. +/* Should we handle this via lost interrupts and IPIs or should we don't care like + * we do now ? --BenH. */ struct hw_interrupt_type; +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_HW_IRQ_H */ diff --git a/trunk/include/asm-powerpc/i8259.h b/trunk/include/asm-powerpc/i8259.h index c80e113052cd..0392159e16e4 100644 --- a/trunk/include/asm-powerpc/i8259.h +++ b/trunk/include/asm-powerpc/i8259.h @@ -4,13 +4,11 @@ #include -#ifdef CONFIG_PPC_MERGE -extern void i8259_init(struct device_node *node, unsigned long intack_addr); -extern unsigned int i8259_irq(struct pt_regs *regs); -#else +extern struct hw_interrupt_type i8259_pic; + extern void i8259_init(unsigned long intack_addr, int offset); extern int i8259_irq(struct pt_regs *regs); -#endif +extern int i8259_irq_cascade(struct pt_regs *regs, void *unused); #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_I8259_H */ diff --git a/trunk/include/asm-powerpc/irq.h b/trunk/include/asm-powerpc/irq.h index e05754752028..a10feec29d4d 100644 --- a/trunk/include/asm-powerpc/irq.h +++ b/trunk/include/asm-powerpc/irq.h @@ -9,340 +9,82 @@ * 2 of the License, or (at your option) any later version. */ -#include #include -#include -#include #include #include +/* this number is used when no interrupt has been assigned */ +#define NO_IRQ (-1) -#define get_irq_desc(irq) (&irq_desc[(irq)]) - -/* Define a way to iterate across irqs. */ -#define for_each_irq(i) \ - for ((i) = 0; (i) < NR_IRQS; ++(i)) - -extern atomic_t ppc_n_lost_interrupts; - -#ifdef CONFIG_PPC_MERGE - -/* This number is used when no interrupt has been assigned */ -#define NO_IRQ (0) - -/* This is a special irq number to return from get_irq() to tell that - * no interrupt happened _and_ ignore it (don't count it as bad). Some - * platforms like iSeries rely on that. - */ -#define NO_IRQ_IGNORE ((unsigned int)-1) - -/* Total number of virq in the platform (make it a CONFIG_* option ? */ -#define NR_IRQS 512 - -/* Number of irqs reserved for the legacy controller */ -#define NUM_ISA_INTERRUPTS 16 - -/* This type is the placeholder for a hardware interrupt number. It has to - * be big enough to enclose whatever representation is used by a given - * platform. - */ -typedef unsigned long irq_hw_number_t; - -/* Interrupt controller "host" data structure. This could be defined as a - * irq domain controller. That is, it handles the mapping between hardware - * and virtual interrupt numbers for a given interrupt domain. The host - * structure is generally created by the PIC code for a given PIC instance - * (though a host can cover more than one PIC if they have a flat number - * model). It's the host callbacks that are responsible for setting the - * irq_chip on a given irq_desc after it's been mapped. - * - * The host code and data structures are fairly agnostic to the fact that - * we use an open firmware device-tree. We do have references to struct - * device_node in two places: in irq_find_host() to find the host matching - * a given interrupt controller node, and of course as an argument to its - * counterpart host->ops->match() callback. However, those are treated as - * generic pointers by the core and the fact that it's actually a device-node - * pointer is purely a convention between callers and implementation. This - * code could thus be used on other architectures by replacing those two - * by some sort of arch-specific void * "token" used to identify interrupt - * controllers. - */ -struct irq_host; -struct radix_tree_root; - -/* Functions below are provided by the host and called whenever a new mapping - * is created or an old mapping is disposed. The host can then proceed to - * whatever internal data structures management is required. It also needs - * to setup the irq_desc when returning from map(). - */ -struct irq_host_ops { - /* Match an interrupt controller device node to a host, returns - * 1 on a match - */ - int (*match)(struct irq_host *h, struct device_node *node); - - /* Create or update a mapping between a virtual irq number and a hw - * irq number. This can be called several times for the same mapping - * but with different flags, though unmap shall always be called - * before the virq->hw mapping is changed. - */ - int (*map)(struct irq_host *h, unsigned int virq, - irq_hw_number_t hw, unsigned int flags); - - /* Dispose of such a mapping */ - void (*unmap)(struct irq_host *h, unsigned int virq); - - /* Translate device-tree interrupt specifier from raw format coming - * from the firmware to a irq_hw_number_t (interrupt line number) and - * trigger flags that can be passed to irq_create_mapping(). - * If no translation is provided, raw format is assumed to be one cell - * for interrupt line and default sense. - */ - int (*xlate)(struct irq_host *h, struct device_node *ctrler, - u32 *intspec, unsigned int intsize, - irq_hw_number_t *out_hwirq, unsigned int *out_flags); -}; - -struct irq_host { - struct list_head link; - - /* type of reverse mapping technique */ - unsigned int revmap_type; -#define IRQ_HOST_MAP_LEGACY 0 /* legacy 8259, gets irqs 1..15 */ -#define IRQ_HOST_MAP_NOMAP 1 /* no fast reverse mapping */ -#define IRQ_HOST_MAP_LINEAR 2 /* linear map of interrupts */ -#define IRQ_HOST_MAP_TREE 3 /* radix tree */ - union { - struct { - unsigned int size; - unsigned int *revmap; - } linear; - struct radix_tree_root tree; - } revmap_data; - struct irq_host_ops *ops; - void *host_data; - irq_hw_number_t inval_irq; -}; - -/* The main irq map itself is an array of NR_IRQ entries containing the - * associate host and irq number. An entry with a host of NULL is free. - * An entry can be allocated if it's free, the allocator always then sets - * hwirq first to the host's invalid irq number and then fills ops. - */ -struct irq_map_entry { - irq_hw_number_t hwirq; - struct irq_host *host; -}; - -extern struct irq_map_entry irq_map[NR_IRQS]; - - -/*** - * irq_alloc_host - Allocate a new irq_host data structure - * @node: device-tree node of the interrupt controller - * @revmap_type: type of reverse mapping to use - * @revmap_arg: for IRQ_HOST_MAP_LINEAR linear only: size of the map - * @ops: map/unmap host callbacks - * @inval_irq: provide a hw number in that host space that is always invalid - * - * Allocates and initialize and irq_host structure. Note that in the case of - * IRQ_HOST_MAP_LEGACY, the map() callback will be called before this returns - * for all legacy interrupts except 0 (which is always the invalid irq for - * a legacy controller). For a IRQ_HOST_MAP_LINEAR, the map is allocated by - * this call as well. For a IRQ_HOST_MAP_TREE, the radix tree will be allocated - * later during boot automatically (the reverse mapping will use the slow path - * until that happens). - */ -extern struct irq_host *irq_alloc_host(unsigned int revmap_type, - unsigned int revmap_arg, - struct irq_host_ops *ops, - irq_hw_number_t inval_irq); - - -/*** - * irq_find_host - Locates a host for a given device node - * @node: device-tree node of the interrupt controller - */ -extern struct irq_host *irq_find_host(struct device_node *node); - - -/*** - * irq_set_default_host - Set a "default" host - * @host: default host pointer - * - * For convenience, it's possible to set a "default" host that will be used - * whenever NULL is passed to irq_create_mapping(). It makes life easier for - * platforms that want to manipulate a few hard coded interrupt numbers that - * aren't properly represented in the device-tree. - */ -extern void irq_set_default_host(struct irq_host *host); - - -/*** - * irq_set_virq_count - Set the maximum number of virt irqs - * @count: number of linux virtual irqs, capped with NR_IRQS - * - * This is mainly for use by platforms like iSeries who want to program - * the virtual irq number in the controller to avoid the reverse mapping - */ -extern void irq_set_virq_count(unsigned int count); - - -/*** - * irq_create_mapping - Map a hardware interrupt into linux virq space - * @host: host owning this hardware interrupt or NULL for default host - * @hwirq: hardware irq number in that host space - * @flags: flags passed to the controller. contains the trigger type among - * others. Use IRQ_TYPE_* defined in include/linux/irq.h - * - * Only one mapping per hardware interrupt is permitted. Returns a linux - * virq number. The flags can be used to provide sense information to the - * controller (typically extracted from the device-tree). If no information - * is passed, the controller defaults will apply (for example, xics can only - * do edge so flags are irrelevant for some pseries specific irqs). - * - * The device-tree generally contains the trigger info in an encoding that is - * specific to a given type of controller. In that case, you can directly use - * host->ops->trigger_xlate() to translate that. - * - * It is recommended that new PICs that don't have existing OF bindings chose - * to use a representation of triggers identical to linux. - */ -extern unsigned int irq_create_mapping(struct irq_host *host, - irq_hw_number_t hwirq, - unsigned int flags); - - -/*** - * irq_dispose_mapping - Unmap an interrupt - * @virq: linux virq number of the interrupt to unmap - */ -extern void irq_dispose_mapping(unsigned int virq); - -/*** - * irq_find_mapping - Find a linux virq from an hw irq number. - * @host: host owning this hardware interrupt - * @hwirq: hardware irq number in that host space - * - * This is a slow path, for use by generic code. It's expected that an - * irq controller implementation directly calls the appropriate low level - * mapping function. +/* + * These constants are used for passing information about interrupt + * signal polarity and level/edge sensing to the low-level PIC chip + * drivers. */ -extern unsigned int irq_find_mapping(struct irq_host *host, - irq_hw_number_t hwirq); - +#define IRQ_SENSE_MASK 0x1 +#define IRQ_SENSE_LEVEL 0x1 /* interrupt on active level */ +#define IRQ_SENSE_EDGE 0x0 /* interrupt triggered by edge */ -/*** - * irq_radix_revmap - Find a linux virq from a hw irq number. - * @host: host owning this hardware interrupt - * @hwirq: hardware irq number in that host space - * - * This is a fast path, for use by irq controller code that uses radix tree - * revmaps - */ -extern unsigned int irq_radix_revmap(struct irq_host *host, - irq_hw_number_t hwirq); +#define IRQ_POLARITY_MASK 0x2 +#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */ +#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */ -/*** - * irq_linear_revmap - Find a linux virq from a hw irq number. - * @host: host owning this hardware interrupt - * @hwirq: hardware irq number in that host space - * - * This is a fast path, for use by irq controller code that uses linear - * revmaps. It does fallback to the slow path if the revmap doesn't exist - * yet and will create the revmap entry with appropriate locking +/* + * IRQ line status macro IRQ_PER_CPU is used */ +#define ARCH_HAS_IRQ_PER_CPU -extern unsigned int irq_linear_revmap(struct irq_host *host, - irq_hw_number_t hwirq); +#define get_irq_desc(irq) (&irq_desc[(irq)]) +/* Define a way to iterate across irqs. */ +#define for_each_irq(i) \ + for ((i) = 0; (i) < NR_IRQS; ++(i)) +#ifdef CONFIG_PPC64 -/*** - * irq_alloc_virt - Allocate virtual irq numbers - * @host: host owning these new virtual irqs - * @count: number of consecutive numbers to allocate - * @hint: pass a hint number, the allocator will try to use a 1:1 mapping - * - * This is a low level function that is used internally by irq_create_mapping() - * and that can be used by some irq controllers implementations for things - * like allocating ranges of numbers for MSIs. The revmaps are left untouched. - */ -extern unsigned int irq_alloc_virt(struct irq_host *host, - unsigned int count, - unsigned int hint); - -/*** - * irq_free_virt - Free virtual irq numbers - * @virq: virtual irq number of the first interrupt to free - * @count: number of interrupts to free - * - * This function is the opposite of irq_alloc_virt. It will not clear reverse - * maps, this should be done previously by unmap'ing the interrupt. In fact, - * all interrupts covered by the range being freed should have been unmapped - * prior to calling this. +/* + * Maximum number of interrupt sources that we can handle. */ -extern void irq_free_virt(unsigned int virq, unsigned int count); - - -/* -- OF helpers -- */ +#define NR_IRQS 512 -/* irq_create_of_mapping - Map a hardware interrupt into linux virq space - * @controller: Device node of the interrupt controller - * @inspec: Interrupt specifier from the device-tree - * @intsize: Size of the interrupt specifier from the device-tree - * - * This function is identical to irq_create_mapping except that it takes - * as input informations straight from the device-tree (typically the results - * of the of_irq_map_*() functions +/* Interrupt numbers are virtual in case they are sparsely + * distributed by the hardware. */ -extern unsigned int irq_create_of_mapping(struct device_node *controller, - u32 *intspec, unsigned int intsize); - +extern unsigned int virt_irq_to_real_map[NR_IRQS]; -/* irq_of_parse_and_map - Parse nad Map an interrupt into linux virq space - * @device: Device node of the device whose interrupt is to be mapped - * @index: Index of the interrupt to map - * - * This function is a wrapper that chains of_irq_map_one() and - * irq_create_of_mapping() to make things easier to callers +/* The maximum virtual IRQ number that we support. This + * can be set by the platform and will be reduced by the + * value of __irq_offset_value. It defaults to and is + * capped by (NR_IRQS - 1). */ -extern unsigned int irq_of_parse_and_map(struct device_node *dev, int index); - -/* -- End OF helpers -- */ +extern unsigned int virt_irq_max; -/*** - * irq_early_init - Init irq remapping subsystem +/* Create a mapping for a real_irq if it doesn't already exist. + * Return the virtual irq as a convenience. */ -extern void irq_early_init(void); +int virt_irq_create_mapping(unsigned int real_irq); +void virt_irq_init(void); -static __inline__ int irq_canonicalize(int irq) +static inline unsigned int virt_irq_to_real(unsigned int virt_irq) { - return irq; + return virt_irq_to_real_map[virt_irq]; } - -#else /* CONFIG_PPC_MERGE */ - -/* This number is used when no interrupt has been assigned */ -#define NO_IRQ (-1) -#define NO_IRQ_IGNORE (-2) - +extern unsigned int real_irq_to_virt_slowpath(unsigned int real_irq); /* - * These constants are used for passing information about interrupt - * signal polarity and level/edge sensing to the low-level PIC chip - * drivers. + * List of interrupt controllers. */ -#define IRQ_SENSE_MASK 0x1 -#define IRQ_SENSE_LEVEL 0x1 /* interrupt on active level */ -#define IRQ_SENSE_EDGE 0x0 /* interrupt triggered by edge */ +#define IC_INVALID 0 +#define IC_OPEN_PIC 1 +#define IC_PPC_XIC 2 +#define IC_CELL_PIC 3 +#define IC_ISERIES 4 -#define IRQ_POLARITY_MASK 0x2 -#define IRQ_POLARITY_POSITIVE 0x2 /* high level or low->high edge */ -#define IRQ_POLARITY_NEGATIVE 0x0 /* low level or high->low edge */ +extern u64 ppc64_interrupt_controller; +#else /* 32-bit */ #if defined(CONFIG_40x) #include @@ -775,11 +517,16 @@ static __inline__ int irq_canonicalize(int irq) #endif /* CONFIG_8260 */ -#endif /* Whatever way too big #ifdef */ +#endif #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) /* pedantic: these are long because they are used with set_bit --RR */ extern unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; +extern atomic_t ppc_n_lost_interrupts; + +#define virt_irq_create_mapping(x) (x) + +#endif /* * Because many systems have two overlapping names spaces for @@ -818,7 +565,6 @@ static __inline__ int irq_canonicalize(int irq) irq = 9; return irq; } -#endif /* CONFIG_PPC_MERGE */ extern int distribute_irqs; @@ -838,8 +584,9 @@ extern struct thread_info *softirq_ctx[NR_CPUS]; extern void irq_ctx_init(void); extern void call_do_softirq(struct thread_info *tp); -extern int call_handle_irq(int irq, void *p1, void *p2, - struct thread_info *tp, void *func); +extern int call___do_IRQ(int irq, struct pt_regs *regs, + struct thread_info *tp); + #else #define irq_ctx_init() diff --git a/trunk/include/asm-powerpc/iseries/it_lp_queue.h b/trunk/include/asm-powerpc/iseries/it_lp_queue.h index 284c5a7db3ac..b7c6fc12cce2 100644 --- a/trunk/include/asm-powerpc/iseries/it_lp_queue.h +++ b/trunk/include/asm-powerpc/iseries/it_lp_queue.h @@ -29,20 +29,20 @@ struct HvLpEvent; -#define IT_LP_MAX_QUEUES 8 +#define ITMaxLpQueues 8 -#define IT_LP_NOT_USED 0 /* Queue will not be used by PLIC */ -#define IT_LP_DEDICATED_IO 1 /* Queue dedicated to IO processor specified */ -#define IT_LP_DEDICATED_LP 2 /* Queue dedicated to LP specified */ -#define IT_LP_SHARED 3 /* Queue shared for both IO and LP */ +#define NotUsed 0 // Queue will not be used by PLIC +#define DedicatedIo 1 // Queue dedicated to IO processor specified +#define DedicatedLp 2 // Queue dedicated to LP specified +#define Shared 3 // Queue shared for both IO and LP -#define IT_LP_EVENT_STACK_SIZE 4096 -#define IT_LP_EVENT_MAX_SIZE 256 -#define IT_LP_EVENT_ALIGN 64 +#define LpEventStackSize 4096 +#define LpEventMaxSize 256 +#define LpEventAlign 64 struct hvlpevent_queue { /* - * The hq_current_event is the pointer to the next event stack entry + * The xSlicCurEventPtr is the pointer to the next event stack entry * that will become valid. The OS must peek at this entry to determine * if it is valid. PLIC will set the valid indicator as the very last * store into that entry. @@ -52,23 +52,23 @@ struct hvlpevent_queue { * location again. * * If the event stack fills and there are overflow events, then PLIC - * will set the hq_overflow_pending flag in which case the OS will + * will set the xPlicOverflowIntPending flag in which case the OS will * have to fetch the additional LP events once they have drained the * event stack. * * The first 16-bytes are known by both the OS and PLIC. The remainder * of the cache line is for use by the OS. */ - u8 hq_overflow_pending; /* 0x00 Overflow events are pending */ - u8 hq_status; /* 0x01 DedicatedIo or DedicatedLp or NotUsed */ - u16 hq_proc_index; /* 0x02 Logical Proc Index for correlation */ - u8 hq_reserved1[12]; /* 0x04 */ - char *hq_current_event; /* 0x10 */ - char *hq_last_event; /* 0x18 */ - char *hq_event_stack; /* 0x20 */ - u8 hq_index; /* 0x28 unique sequential index. */ - u8 hq_reserved2[3]; /* 0x29-2b */ - spinlock_t hq_lock; + u8 xPlicOverflowIntPending;// 0x00 Overflow events are pending + u8 xPlicStatus; // 0x01 DedicatedIo or DedicatedLp or NotUsed + u16 xSlicLogicalProcIndex; // 0x02 Logical Proc Index for correlation + u8 xPlicRsvd[12]; // 0x04 + char *xSlicCurEventPtr; // 0x10 + char *xSlicLastValidEventPtr; // 0x18 + char *xSlicEventStackPtr; // 0x20 + u8 xIndex; // 0x28 unique sequential index. + u8 xSlicRsvd[3]; // 0x29-2b + spinlock_t lock; }; extern struct hvlpevent_queue hvlpevent_queue; diff --git a/trunk/include/asm-powerpc/kdebug.h b/trunk/include/asm-powerpc/kdebug.h index 532bfee934f4..c01786ab5fa6 100644 --- a/trunk/include/asm-powerpc/kdebug.h +++ b/trunk/include/asm-powerpc/kdebug.h @@ -18,8 +18,6 @@ struct die_args { extern int register_die_notifier(struct notifier_block *); extern int unregister_die_notifier(struct notifier_block *); -extern int register_page_fault_notifier(struct notifier_block *); -extern int unregister_page_fault_notifier(struct notifier_block *); extern struct atomic_notifier_head powerpc_die_chain; /* Grossly misnamed. */ diff --git a/trunk/include/asm-powerpc/kdump.h b/trunk/include/asm-powerpc/kdump.h index dc1574c945f8..5a5c3b5ab1e0 100644 --- a/trunk/include/asm-powerpc/kdump.h +++ b/trunk/include/asm-powerpc/kdump.h @@ -15,8 +15,6 @@ #define KDUMP_TRAMPOLINE_START 0x0100 #define KDUMP_TRAMPOLINE_END 0x3000 -#define KDUMP_MIN_TCE_ENTRIES 2048 - #else /* !CONFIG_CRASH_DUMP */ #define PHYSICAL_START 0x0 diff --git a/trunk/include/asm-powerpc/kexec.h b/trunk/include/asm-powerpc/kexec.h index 8f7fd5cfec34..efe8872ec583 100644 --- a/trunk/include/asm-powerpc/kexec.h +++ b/trunk/include/asm-powerpc/kexec.h @@ -112,13 +112,9 @@ static inline void crash_setup_regs(struct pt_regs *newregs, #ifdef __powerpc64__ extern void kexec_smp_wait(void); /* get and clear naca physid, wait for master to copy new code to 0 */ +extern void __init kexec_setup(void); extern int crashing_cpu; extern void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *)); -extern cpumask_t cpus_in_sr; -static inline int kexec_sr_activated(int cpu) -{ - return cpu_isset(cpu,cpus_in_sr); -} #endif /* __powerpc64 __ */ struct kimage; @@ -128,13 +124,10 @@ extern int default_machine_kexec_prepare(struct kimage *image); extern void default_machine_crash_shutdown(struct pt_regs *regs); extern void machine_kexec_simple(struct kimage *image); -extern void crash_kexec_secondary(struct pt_regs *regs); extern int overlaps_crashkernel(unsigned long start, unsigned long size); extern void reserve_crashkernel(void); #else /* !CONFIG_KEXEC */ -static inline int kexec_sr_activated(int cpu) { return 0; } -static inline void crash_kexec_secondary(struct pt_regs *regs) { } static inline int overlaps_crashkernel(unsigned long start, unsigned long size) { diff --git a/trunk/include/asm-powerpc/kprobes.h b/trunk/include/asm-powerpc/kprobes.h index 2d0af52c823d..f466bc804f41 100644 --- a/trunk/include/asm-powerpc/kprobes.h +++ b/trunk/include/asm-powerpc/kprobes.h @@ -50,8 +50,6 @@ typedef unsigned int kprobe_opcode_t; IS_TWI(instr) || IS_TDI(instr)) #define ARCH_SUPPORTS_KRETPROBES -#define ARCH_INACTIVE_KPROBE_COUNT 1 - void kretprobe_trampoline(void); extern void arch_remove_kprobe(struct kprobe *p); diff --git a/trunk/include/asm-powerpc/machdep.h b/trunk/include/asm-powerpc/machdep.h index c17c13742401..73db1f71329d 100644 --- a/trunk/include/asm-powerpc/machdep.h +++ b/trunk/include/asm-powerpc/machdep.h @@ -81,8 +81,6 @@ struct machdep_calls { void (*tce_free)(struct iommu_table *tbl, long index, long npages); - unsigned long (*tce_get)(struct iommu_table *tbl, - long index); void (*tce_flush)(struct iommu_table *tbl); void (*iommu_dev_setup)(struct pci_dev *dev); void (*iommu_bus_setup)(struct pci_bus *bus); @@ -97,7 +95,7 @@ struct machdep_calls { void (*show_percpuinfo)(struct seq_file *m, int i); void (*init_IRQ)(void); - unsigned int (*get_irq)(struct pt_regs *); + int (*get_irq)(struct pt_regs *); #ifdef CONFIG_KEXEC void (*kexec_cpu_down)(int crash_shutdown, int secondary); #endif diff --git a/trunk/include/asm-powerpc/mmu.h b/trunk/include/asm-powerpc/mmu.h index c3fc7a28e3cd..3a5ebe229af5 100644 --- a/trunk/include/asm-powerpc/mmu.h +++ b/trunk/include/asm-powerpc/mmu.h @@ -238,6 +238,7 @@ extern int hash_huge_page(struct mm_struct *mm, unsigned long access, unsigned long ea, unsigned long vsid, int local, unsigned long trap); +extern void htab_finish_init(void); extern int htab_bolt_mapping(unsigned long vstart, unsigned long vend, unsigned long pstart, unsigned long mode, int psize); diff --git a/trunk/include/asm-powerpc/mmu_context.h b/trunk/include/asm-powerpc/mmu_context.h index 083ac917bd29..8c6b1a6d944f 100644 --- a/trunk/include/asm-powerpc/mmu_context.h +++ b/trunk/include/asm-powerpc/mmu_context.h @@ -25,13 +25,8 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, { } -/* - * The proto-VSID space has 2^35 - 1 segments available for user mappings. - * Each segment contains 2^28 bytes. Each context maps 2^44 bytes, - * so we can support 2^19-1 contexts (19 == 35 + 28 - 44). - */ #define NO_CONTEXT 0 -#define MAX_CONTEXT ((1UL << 19) - 1) +#define MAX_CONTEXT (0x100000-1) extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm); extern void destroy_context(struct mm_struct *mm); diff --git a/trunk/include/asm-powerpc/mpc86xx.h b/trunk/include/asm-powerpc/mpc86xx.h index f260382739fa..d0a6718d188b 100644 --- a/trunk/include/asm-powerpc/mpc86xx.h +++ b/trunk/include/asm-powerpc/mpc86xx.h @@ -15,10 +15,15 @@ #ifndef __ASM_POWERPC_MPC86xx_H__ #define __ASM_POWERPC_MPC86xx_H__ +#include #include #ifdef CONFIG_PPC_86xx +#ifdef CONFIG_MPC8641_HPCN +#include +#endif + #define _IO_BASE isa_io_base #define _ISA_MEM_BASE isa_mem_base #ifdef CONFIG_PCI diff --git a/trunk/include/asm-powerpc/mpic.h b/trunk/include/asm-powerpc/mpic.h index eb241c99c457..f0d22ac34b96 100644 --- a/trunk/include/asm-powerpc/mpic.h +++ b/trunk/include/asm-powerpc/mpic.h @@ -114,6 +114,9 @@ #define MPIC_VEC_TIMER_1 248 #define MPIC_VEC_TIMER_0 247 +/* Type definition of the cascade handler */ +typedef int (*mpic_cascade_t)(struct pt_regs *regs, void *data); + #ifdef CONFIG_MPIC_BROKEN_U3 /* Fixup table entry */ struct mpic_irq_fixup @@ -129,19 +132,10 @@ struct mpic_irq_fixup /* The instance data of a given MPIC */ struct mpic { - /* The device node of the interrupt controller */ - struct device_node *of_node; - - /* The remapper for this MPIC */ - struct irq_host *irqhost; - /* The "linux" controller struct */ - struct irq_chip hc_irq; -#ifdef CONFIG_MPIC_BROKEN_U3 - struct irq_chip hc_ht_irq; -#endif + hw_irq_controller hc_irq; #ifdef CONFIG_SMP - struct irq_chip hc_ipi; + hw_irq_controller hc_ipi; #endif const char *name; /* Flags */ @@ -150,12 +144,20 @@ struct mpic unsigned int isu_size; unsigned int isu_shift; unsigned int isu_mask; + /* Offset of irq vector numbers */ + unsigned int irq_offset; unsigned int irq_count; + /* Offset of ipi vector numbers */ + unsigned int ipi_offset; /* Number of sources */ unsigned int num_sources; /* Number of CPUs */ unsigned int num_cpus; - /* default senses array */ + /* cascade handler */ + mpic_cascade_t cascade; + void *cascade_data; + unsigned int cascade_vec; + /* senses array */ unsigned char *senses; unsigned int senses_count; @@ -211,11 +213,14 @@ struct mpic * The values in the array start at the first source of the MPIC, * that is senses[0] correspond to linux irq "irq_offset". */ -extern struct mpic *mpic_alloc(struct device_node *node, - unsigned long phys_addr, +extern struct mpic *mpic_alloc(unsigned long phys_addr, unsigned int flags, unsigned int isu_size, + unsigned int irq_offset, unsigned int irq_count, + unsigned int ipi_offset, + unsigned char *senses, + unsigned int senses_num, const char *name); /* Assign ISUs, to call before mpic_init() @@ -227,27 +232,22 @@ extern struct mpic *mpic_alloc(struct device_node *node, extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, unsigned long phys_addr); -/* Set default sense codes - * - * @mpic: controller - * @senses: array of sense codes - * @count: size of above array - * - * Optionally provide an array (indexed on hardware interrupt numbers - * for this MPIC) of default sense codes for the chip. Those are linux - * sense codes IRQ_TYPE_* - * - * The driver gets ownership of the pointer, don't dispose of it or - * anything like that. __init only. - */ -extern void mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count); - - /* Initialize the controller. After this has been called, none of the above * should be called again for this mpic */ extern void mpic_init(struct mpic *mpic); +/* Setup a cascade. Currently, only one cascade is supported this + * way, though you can always do a normal request_irq() and add + * other cascades this way. You should call this _after_ having + * added all the ISUs + * + * @irq_no: "linux" irq number of the cascade (that is offset'ed vector) + * @handler: cascade handler function + */ +extern void mpic_setup_cascade(unsigned int irq_no, mpic_cascade_t hanlder, + void *data); + /* * All of the following functions must only be used after the * ISUs have been assigned and the controller fully initialized @@ -284,9 +284,9 @@ extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask); void smp_mpic_message_pass(int target, int msg); /* Fetch interrupt from a given mpic */ -extern unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs); +extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs); /* This one gets to the primary mpic */ -extern unsigned int mpic_get_irq(struct pt_regs *regs); +extern int mpic_get_irq(struct pt_regs *regs); /* Set the EPIC clock ratio */ void mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio); @@ -294,5 +294,8 @@ void mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio); /* Enable/Disable EPIC serial interrupt mode */ void mpic_set_serial_int(struct mpic *mpic, int enable); +/* global mpic for pSeries */ +extern struct mpic *pSeries_mpic; + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_MPIC_H */ diff --git a/trunk/include/asm-powerpc/of_device.h b/trunk/include/asm-powerpc/of_device.h index c5c0b0b3cd52..6249a7c39639 100644 --- a/trunk/include/asm-powerpc/of_device.h +++ b/trunk/include/asm-powerpc/of_device.h @@ -9,7 +9,7 @@ /* * The of_platform_bus_type is a bus type used by drivers that do not * attach to a macio or similar bus but still use OF probing - * mechanism + * mecanism */ extern struct bus_type of_platform_bus_type; diff --git a/trunk/include/asm-powerpc/pci.h b/trunk/include/asm-powerpc/pci.h index 46afd29b904e..5d2c9e6c4be2 100644 --- a/trunk/include/asm-powerpc/pci.h +++ b/trunk/include/asm-powerpc/pci.h @@ -242,7 +242,7 @@ extern pgprot_t pci_phys_mem_access_prot(struct file *file, #define HAVE_ARCH_PCI_RESOURCE_TO_USER extern void pci_resource_to_user(const struct pci_dev *dev, int bar, const struct resource *rsrc, - resource_size_t *start, resource_size_t *end); + u64 *start, u64 *end); #endif /* CONFIG_PPC_MULTIPLATFORM || CONFIG_PPC32 */ #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-powerpc/pmac_pfunc.h b/trunk/include/asm-powerpc/pmac_pfunc.h index 1330d6a58c57..cef61304ffc2 100644 --- a/trunk/include/asm-powerpc/pmac_pfunc.h +++ b/trunk/include/asm-powerpc/pmac_pfunc.h @@ -205,7 +205,7 @@ extern void pmf_do_irq(struct pmf_function *func); * * The args array contains as many arguments as is required by the function, * this is dependent on the function you are calling, unfortunately Apple - * mechanism provides no way to encode that so you have to get it right at + * mecanism provides no way to encode that so you have to get it right at * the call site. Some functions require no args, in which case, you can * pass NULL. * diff --git a/trunk/include/asm-powerpc/prom.h b/trunk/include/asm-powerpc/prom.h index b095a285c84b..010d186d095b 100644 --- a/trunk/include/asm-powerpc/prom.h +++ b/trunk/include/asm-powerpc/prom.h @@ -64,6 +64,11 @@ struct boot_param_header typedef u32 phandle; typedef u32 ihandle; +struct interrupt_info { + int line; + int sense; /* +ve/-ve logic, edge or level, etc. */ +}; + struct property { char *name; int length; @@ -76,6 +81,8 @@ struct device_node { char *type; phandle node; phandle linux_phandle; + int n_intrs; + struct interrupt_info *intrs; char *full_name; struct property *properties; @@ -160,8 +167,8 @@ extern void unflatten_device_tree(void); extern void early_init_devtree(void *); extern int device_is_compatible(struct device_node *device, const char *); extern int machine_is_compatible(const char *compat); -extern void *get_property(struct device_node *node, const char *name, - int *lenp); +extern unsigned char *get_property(struct device_node *node, const char *name, + int *lenp); extern void print_properties(struct device_node *node); extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); @@ -197,15 +204,6 @@ extern int release_OF_resource(struct device_node* node, int index); */ -/* Helper to read a big number */ -static inline u64 of_read_number(u32 *cell, int size) -{ - u64 r = 0; - while (size--) - r = (r << 32) | *(cell++); - return r; -} - /* Translate an OF address block into a CPU physical address */ #define OF_BAD_ADDR ((u64)-1) @@ -242,83 +240,5 @@ extern void kdump_move_device_tree(void); /* CPU OF node matching */ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); - -/* - * OF interrupt mapping - */ - -/* This structure is returned when an interrupt is mapped. The controller - * field needs to be put() after use - */ - -#define OF_MAX_IRQ_SPEC 4 /* We handle specifiers of at most 4 cells */ - -struct of_irq { - struct device_node *controller; /* Interrupt controller node */ - u32 size; /* Specifier size */ - u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */ -}; - -/*** - * of_irq_map_init - Initialize the irq remapper - * @flags: flags defining workarounds to enable - * - * Some machines have bugs in the device-tree which require certain workarounds - * to be applied. Call this before any interrupt mapping attempts to enable - * those workarounds. - */ -#define OF_IMAP_OLDWORLD_MAC 0x00000001 -#define OF_IMAP_NO_PHANDLE 0x00000002 - -extern void of_irq_map_init(unsigned int flags); - -/*** - * of_irq_map_raw - Low level interrupt tree parsing - * @parent: the device interrupt parent - * @intspec: interrupt specifier ("interrupts" property of the device) - * @addr: address specifier (start of "reg" property of the device) - * @out_irq: structure of_irq filled by this function - * - * Returns 0 on success and a negative number on error - * - * This function is a low-level interrupt tree walking function. It - * can be used to do a partial walk with synthetized reg and interrupts - * properties, for example when resolving PCI interrupts when no device - * node exist for the parent. - * - */ - -extern int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr, - struct of_irq *out_irq); - - -/*** - * of_irq_map_one - Resolve an interrupt for a device - * @device: the device whose interrupt is to be resolved - * @index: index of the interrupt to resolve - * @out_irq: structure of_irq filled by this function - * - * This function resolves an interrupt, walking the tree, for a given - * device-tree node. It's the high level pendant to of_irq_map_raw(). - * It also implements the workarounds for OldWolrd Macs. - */ -extern int of_irq_map_one(struct device_node *device, int index, - struct of_irq *out_irq); - -/*** - * of_irq_map_pci - Resolve the interrupt for a PCI device - * @pdev: the device whose interrupt is to be resolved - * @out_irq: structure of_irq filled by this function - * - * This function resolves the PCI interrupt for a given PCI device. If a - * device-node exists for a given pci_dev, it will use normal OF tree - * walking. If not, it will implement standard swizzling and walk up the - * PCI tree until an device-node is found, at which point it will finish - * resolving using the OF tree walking. - */ -struct pci_dev; -extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq); - - #endif /* __KERNEL__ */ #endif /* _POWERPC_PROM_H */ diff --git a/trunk/include/asm-powerpc/rtas.h b/trunk/include/asm-powerpc/rtas.h index a33c6acffa61..02e213e3d69f 100644 --- a/trunk/include/asm-powerpc/rtas.h +++ b/trunk/include/asm-powerpc/rtas.h @@ -181,9 +181,6 @@ extern int rtas_set_rtc_time(struct rtc_time *rtc_time); extern unsigned int rtas_busy_delay_time(int status); extern unsigned int rtas_busy_delay(int status); -extern int early_init_dt_scan_rtas(unsigned long node, - const char *uname, int depth, void *data); - extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal); /* Error types logged. */ diff --git a/trunk/include/asm-powerpc/signal.h b/trunk/include/asm-powerpc/signal.h index a8c7babf4950..a4d8f8648541 100644 --- a/trunk/include/asm-powerpc/signal.h +++ b/trunk/include/asm-powerpc/signal.h @@ -63,6 +63,7 @@ typedef struct { * SA_FLAGS values: * * SA_ONSTACK is not currently supported, but will allow sigaltstack(2). + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -82,6 +83,7 @@ typedef struct { #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000u /* dummy -- ignored */ #define SA_RESTORER 0x04000000U diff --git a/trunk/include/asm-powerpc/socket.h b/trunk/include/asm-powerpc/socket.h index c8b1da50e72d..e4b8177d4acc 100644 --- a/trunk/include/asm-powerpc/socket.h +++ b/trunk/include/asm-powerpc/socket.h @@ -55,6 +55,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_POWERPC_SOCKET_H */ diff --git a/trunk/include/asm-powerpc/spu.h b/trunk/include/asm-powerpc/spu.h index c02d105d8294..9609d3ee8798 100644 --- a/trunk/include/asm-powerpc/spu.h +++ b/trunk/include/asm-powerpc/spu.h @@ -117,7 +117,6 @@ struct spu { struct list_head sched_list; int number; int nid; - unsigned int irqs[3]; u32 isrc; u32 node; u64 flags; diff --git a/trunk/include/asm-powerpc/time.h b/trunk/include/asm-powerpc/time.h index dcde4410348d..4463148c659f 100644 --- a/trunk/include/asm-powerpc/time.h +++ b/trunk/include/asm-powerpc/time.h @@ -18,9 +18,8 @@ #include #include -#ifdef CONFIG_PPC_ISERIES +#ifdef CONFIG_PPC64 #include -#include #include #endif @@ -178,8 +177,7 @@ static inline void set_dec(int val) #ifdef CONFIG_PPC_ISERIES int cur_dec; - if (firmware_has_feature(FW_FEATURE_ISERIES) && - get_lppaca()->shared_proc) { + if (get_lppaca()->shared_proc) { get_lppaca()->virtual_decr = val; cur_dec = get_dec(); if (cur_dec > val) diff --git a/trunk/include/asm-powerpc/todc.h b/trunk/include/asm-powerpc/todc.h deleted file mode 100644 index 60a8c39b8c11..000000000000 --- a/trunk/include/asm-powerpc/todc.h +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Definitions for the M48Txx and mc146818 series of Time of day/Real Time - * Clock chips. - * - * Author: Mark A. Greer - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -/* - * Support for the M48T37/M48T59/.../mc146818 Real Time Clock chips. - * Purpose is to make one generic file that handles all of these chips instead - * of every platform implementing the same code over & over again. - */ - -#ifndef __PPC_KERNEL_TODC_H -#define __PPC_KERNEL_TODC_H - -typedef struct { - uint rtc_type; /* your particular chip */ - - /* - * Following are the addresses of the AS0, AS1, and DATA registers - * of these chips. Note that these are board-specific. - */ - unsigned int nvram_as0; - unsigned int nvram_as1; - unsigned int nvram_data; - - /* - * Define bits to stop external set of regs from changing so - * the chip can be read/written reliably. - */ - unsigned char enable_read; - unsigned char enable_write; - - /* - * Following is the number of AS0 address bits. This is normally - * 8 but some bad hardware routes address lines incorrectly. - */ - int as0_bits; - - int nvram_size; /* Size of NVRAM on chip */ - int sw_flags; /* Software control flags */ - - /* Following are the register offsets for the particular chip */ - int year; - int month; - int day_of_month; - int day_of_week; - int hours; - int minutes; - int seconds; - int control_b; - int control_a; - int watchdog; - int interrupts; - int alarm_date; - int alarm_hour; - int alarm_minutes; - int alarm_seconds; - int century; - int flags; - - /* - * Some RTC chips have their NVRAM buried behind a addr/data pair of - * regs on the first level/clock registers. The following fields - * are the addresses for those addr/data regs. - */ - int nvram_addr_reg; - int nvram_data_reg; -} todc_info_t; - -/* - * Define the types of TODC/RTC variants that are supported in - * arch/ppc/kernel/todc_time.c - * Make a new one of these for any chip somehow differs from what's already - * defined. That way, if you ever need to put in code to touch those - * bits/registers in todc_time.c, you can put it inside an - * 'if (todc_info->rtc_type == TODC_TYPE_XXX)' so you won't break - * anyone else. - */ -#define TODC_TYPE_MK48T35 1 -#define TODC_TYPE_MK48T37 2 -#define TODC_TYPE_MK48T59 3 -#define TODC_TYPE_DS1693 4 /* Dallas DS1693 RTC */ -#define TODC_TYPE_DS1743 5 /* Dallas DS1743 RTC */ -#define TODC_TYPE_DS1746 6 /* Dallas DS1746 RTC */ -#define TODC_TYPE_DS1747 7 /* Dallas DS1747 RTC */ -#define TODC_TYPE_DS1501 8 /* Dallas DS1501 RTC */ -#define TODC_TYPE_DS1643 9 /* Dallas DS1643 RTC */ -#define TODC_TYPE_PC97307 10 /* PC97307 internal RTC */ -#define TODC_TYPE_DS1557 11 /* Dallas DS1557 RTC */ -#define TODC_TYPE_DS17285 12 /* Dallas DS17285 RTC */ -#define TODC_TYPE_DS1553 13 /* Dallas DS1553 RTC */ -#define TODC_TYPE_MC146818 100 /* Leave room for m48txx's */ - -/* - * Bit to clear/set to enable reads/writes to the chip - */ -#define TODC_MK48TXX_CNTL_A_R 0x40 -#define TODC_MK48TXX_CNTL_A_W 0x80 -#define TODC_MK48TXX_DAY_CB 0x80 - -#define TODC_DS1501_CNTL_B_TE 0x80 - -/* - * Define flag bits used by todc routines. - */ -#define TODC_FLAG_2_LEVEL_NVRAM 0x00000001 - -/* - * Define the values for the various RTC's that should to into the todc_info - * table. - * Note: The XXX_NVRAM_SIZE, XXX_NVRAM_ADDR_REG, and XXX_NVRAM_DATA_REG only - * matter if XXX_SW_FLAGS has TODC_FLAG_2_LEVEL_NVRAM set. - */ -#define TODC_TYPE_MK48T35_NVRAM_SIZE 0x7ff8 -#define TODC_TYPE_MK48T35_SW_FLAGS 0 -#define TODC_TYPE_MK48T35_YEAR 0x7fff -#define TODC_TYPE_MK48T35_MONTH 0x7ffe -#define TODC_TYPE_MK48T35_DOM 0x7ffd /* Day of Month */ -#define TODC_TYPE_MK48T35_DOW 0x7ffc /* Day of Week */ -#define TODC_TYPE_MK48T35_HOURS 0x7ffb -#define TODC_TYPE_MK48T35_MINUTES 0x7ffa -#define TODC_TYPE_MK48T35_SECONDS 0x7ff9 -#define TODC_TYPE_MK48T35_CNTL_B 0x7ff9 -#define TODC_TYPE_MK48T35_CNTL_A 0x7ff8 -#define TODC_TYPE_MK48T35_WATCHDOG 0x0000 -#define TODC_TYPE_MK48T35_INTERRUPTS 0x0000 -#define TODC_TYPE_MK48T35_ALARM_DATE 0x0000 -#define TODC_TYPE_MK48T35_ALARM_HOUR 0x0000 -#define TODC_TYPE_MK48T35_ALARM_MINUTES 0x0000 -#define TODC_TYPE_MK48T35_ALARM_SECONDS 0x0000 -#define TODC_TYPE_MK48T35_CENTURY 0x0000 -#define TODC_TYPE_MK48T35_FLAGS 0x0000 -#define TODC_TYPE_MK48T35_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MK48T35_NVRAM_DATA_REG 0 - -#define TODC_TYPE_MK48T37_NVRAM_SIZE 0x7ff0 -#define TODC_TYPE_MK48T37_SW_FLAGS 0 -#define TODC_TYPE_MK48T37_YEAR 0x7fff -#define TODC_TYPE_MK48T37_MONTH 0x7ffe -#define TODC_TYPE_MK48T37_DOM 0x7ffd /* Day of Month */ -#define TODC_TYPE_MK48T37_DOW 0x7ffc /* Day of Week */ -#define TODC_TYPE_MK48T37_HOURS 0x7ffb -#define TODC_TYPE_MK48T37_MINUTES 0x7ffa -#define TODC_TYPE_MK48T37_SECONDS 0x7ff9 -#define TODC_TYPE_MK48T37_CNTL_B 0x7ff9 -#define TODC_TYPE_MK48T37_CNTL_A 0x7ff8 -#define TODC_TYPE_MK48T37_WATCHDOG 0x7ff7 -#define TODC_TYPE_MK48T37_INTERRUPTS 0x7ff6 -#define TODC_TYPE_MK48T37_ALARM_DATE 0x7ff5 -#define TODC_TYPE_MK48T37_ALARM_HOUR 0x7ff4 -#define TODC_TYPE_MK48T37_ALARM_MINUTES 0x7ff3 -#define TODC_TYPE_MK48T37_ALARM_SECONDS 0x7ff2 -#define TODC_TYPE_MK48T37_CENTURY 0x7ff1 -#define TODC_TYPE_MK48T37_FLAGS 0x7ff0 -#define TODC_TYPE_MK48T37_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MK48T37_NVRAM_DATA_REG 0 - -#define TODC_TYPE_MK48T59_NVRAM_SIZE 0x1ff0 -#define TODC_TYPE_MK48T59_SW_FLAGS 0 -#define TODC_TYPE_MK48T59_YEAR 0x1fff -#define TODC_TYPE_MK48T59_MONTH 0x1ffe -#define TODC_TYPE_MK48T59_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_MK48T59_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_MK48T59_HOURS 0x1ffb -#define TODC_TYPE_MK48T59_MINUTES 0x1ffa -#define TODC_TYPE_MK48T59_SECONDS 0x1ff9 -#define TODC_TYPE_MK48T59_CNTL_B 0x1ff9 -#define TODC_TYPE_MK48T59_CNTL_A 0x1ff8 -#define TODC_TYPE_MK48T59_WATCHDOG 0x1fff -#define TODC_TYPE_MK48T59_INTERRUPTS 0x1fff -#define TODC_TYPE_MK48T59_ALARM_DATE 0x1fff -#define TODC_TYPE_MK48T59_ALARM_HOUR 0x1fff -#define TODC_TYPE_MK48T59_ALARM_MINUTES 0x1fff -#define TODC_TYPE_MK48T59_ALARM_SECONDS 0x1fff -#define TODC_TYPE_MK48T59_CENTURY 0x1fff -#define TODC_TYPE_MK48T59_FLAGS 0x1fff -#define TODC_TYPE_MK48T59_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MK48T59_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1501_NVRAM_SIZE 0x100 -#define TODC_TYPE_DS1501_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM -#define TODC_TYPE_DS1501_YEAR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x06) -#define TODC_TYPE_DS1501_MONTH (TODC_TYPE_DS1501_NVRAM_SIZE + 0x05) -#define TODC_TYPE_DS1501_DOM (TODC_TYPE_DS1501_NVRAM_SIZE + 0x04) -#define TODC_TYPE_DS1501_DOW (TODC_TYPE_DS1501_NVRAM_SIZE + 0x03) -#define TODC_TYPE_DS1501_HOURS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x02) -#define TODC_TYPE_DS1501_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x01) -#define TODC_TYPE_DS1501_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x00) -#define TODC_TYPE_DS1501_CNTL_B (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f) -#define TODC_TYPE_DS1501_CNTL_A (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f) -#define TODC_TYPE_DS1501_WATCHDOG (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) -#define TODC_TYPE_DS1501_INTERRUPTS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) -#define TODC_TYPE_DS1501_ALARM_DATE (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0b) -#define TODC_TYPE_DS1501_ALARM_HOUR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0a) -#define TODC_TYPE_DS1501_ALARM_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x09) -#define TODC_TYPE_DS1501_ALARM_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x08) -#define TODC_TYPE_DS1501_CENTURY (TODC_TYPE_DS1501_NVRAM_SIZE + 0x07) -#define TODC_TYPE_DS1501_FLAGS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) -#define TODC_TYPE_DS1501_NVRAM_ADDR_REG 0x10 -#define TODC_TYPE_DS1501_NVRAM_DATA_REG 0x13 - -#define TODC_TYPE_DS1553_NVRAM_SIZE 0x1ff0 -#define TODC_TYPE_DS1553_SW_FLAGS 0 -#define TODC_TYPE_DS1553_YEAR 0x1fff -#define TODC_TYPE_DS1553_MONTH 0x1ffe -#define TODC_TYPE_DS1553_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_DS1553_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_DS1553_HOURS 0x1ffb -#define TODC_TYPE_DS1553_MINUTES 0x1ffa -#define TODC_TYPE_DS1553_SECONDS 0x1ff9 -#define TODC_TYPE_DS1553_CNTL_B 0x1ff9 -#define TODC_TYPE_DS1553_CNTL_A 0x1ff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1553_WATCHDOG 0x1ff7 -#define TODC_TYPE_DS1553_INTERRUPTS 0x1ff6 -#define TODC_TYPE_DS1553_ALARM_DATE 0x1ff5 -#define TODC_TYPE_DS1553_ALARM_HOUR 0x1ff4 -#define TODC_TYPE_DS1553_ALARM_MINUTES 0x1ff3 -#define TODC_TYPE_DS1553_ALARM_SECONDS 0x1ff2 -#define TODC_TYPE_DS1553_CENTURY 0x1ff8 -#define TODC_TYPE_DS1553_FLAGS 0x1ff0 -#define TODC_TYPE_DS1553_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1553_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1557_NVRAM_SIZE 0x7fff0 -#define TODC_TYPE_DS1557_SW_FLAGS 0 -#define TODC_TYPE_DS1557_YEAR 0x7ffff -#define TODC_TYPE_DS1557_MONTH 0x7fffe -#define TODC_TYPE_DS1557_DOM 0x7fffd /* Day of Month */ -#define TODC_TYPE_DS1557_DOW 0x7fffc /* Day of Week */ -#define TODC_TYPE_DS1557_HOURS 0x7fffb -#define TODC_TYPE_DS1557_MINUTES 0x7fffa -#define TODC_TYPE_DS1557_SECONDS 0x7fff9 -#define TODC_TYPE_DS1557_CNTL_B 0x7fff9 -#define TODC_TYPE_DS1557_CNTL_A 0x7fff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1557_WATCHDOG 0x7fff7 -#define TODC_TYPE_DS1557_INTERRUPTS 0x7fff6 -#define TODC_TYPE_DS1557_ALARM_DATE 0x7fff5 -#define TODC_TYPE_DS1557_ALARM_HOUR 0x7fff4 -#define TODC_TYPE_DS1557_ALARM_MINUTES 0x7fff3 -#define TODC_TYPE_DS1557_ALARM_SECONDS 0x7fff2 -#define TODC_TYPE_DS1557_CENTURY 0x7fff8 -#define TODC_TYPE_DS1557_FLAGS 0x7fff0 -#define TODC_TYPE_DS1557_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1557_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1643_NVRAM_SIZE 0x1ff8 -#define TODC_TYPE_DS1643_SW_FLAGS 0 -#define TODC_TYPE_DS1643_YEAR 0x1fff -#define TODC_TYPE_DS1643_MONTH 0x1ffe -#define TODC_TYPE_DS1643_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_DS1643_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_DS1643_HOURS 0x1ffb -#define TODC_TYPE_DS1643_MINUTES 0x1ffa -#define TODC_TYPE_DS1643_SECONDS 0x1ff9 -#define TODC_TYPE_DS1643_CNTL_B 0x1ff9 -#define TODC_TYPE_DS1643_CNTL_A 0x1ff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1643_WATCHDOG 0x1fff -#define TODC_TYPE_DS1643_INTERRUPTS 0x1fff -#define TODC_TYPE_DS1643_ALARM_DATE 0x1fff -#define TODC_TYPE_DS1643_ALARM_HOUR 0x1fff -#define TODC_TYPE_DS1643_ALARM_MINUTES 0x1fff -#define TODC_TYPE_DS1643_ALARM_SECONDS 0x1fff -#define TODC_TYPE_DS1643_CENTURY 0x1ff8 -#define TODC_TYPE_DS1643_FLAGS 0x1fff -#define TODC_TYPE_DS1643_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1643_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1693_NVRAM_SIZE 0 /* Not handled yet */ -#define TODC_TYPE_DS1693_SW_FLAGS 0 -#define TODC_TYPE_DS1693_YEAR 0x09 -#define TODC_TYPE_DS1693_MONTH 0x08 -#define TODC_TYPE_DS1693_DOM 0x07 /* Day of Month */ -#define TODC_TYPE_DS1693_DOW 0x06 /* Day of Week */ -#define TODC_TYPE_DS1693_HOURS 0x04 -#define TODC_TYPE_DS1693_MINUTES 0x02 -#define TODC_TYPE_DS1693_SECONDS 0x00 -#define TODC_TYPE_DS1693_CNTL_B 0x0b -#define TODC_TYPE_DS1693_CNTL_A 0x0a -#define TODC_TYPE_DS1693_WATCHDOG 0xff -#define TODC_TYPE_DS1693_INTERRUPTS 0xff -#define TODC_TYPE_DS1693_ALARM_DATE 0x49 -#define TODC_TYPE_DS1693_ALARM_HOUR 0x05 -#define TODC_TYPE_DS1693_ALARM_MINUTES 0x03 -#define TODC_TYPE_DS1693_ALARM_SECONDS 0x01 -#define TODC_TYPE_DS1693_CENTURY 0x48 -#define TODC_TYPE_DS1693_FLAGS 0xff -#define TODC_TYPE_DS1693_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1693_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1743_NVRAM_SIZE 0x1ff8 -#define TODC_TYPE_DS1743_SW_FLAGS 0 -#define TODC_TYPE_DS1743_YEAR 0x1fff -#define TODC_TYPE_DS1743_MONTH 0x1ffe -#define TODC_TYPE_DS1743_DOM 0x1ffd /* Day of Month */ -#define TODC_TYPE_DS1743_DOW 0x1ffc /* Day of Week */ -#define TODC_TYPE_DS1743_HOURS 0x1ffb -#define TODC_TYPE_DS1743_MINUTES 0x1ffa -#define TODC_TYPE_DS1743_SECONDS 0x1ff9 -#define TODC_TYPE_DS1743_CNTL_B 0x1ff9 -#define TODC_TYPE_DS1743_CNTL_A 0x1ff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1743_WATCHDOG 0x1fff -#define TODC_TYPE_DS1743_INTERRUPTS 0x1fff -#define TODC_TYPE_DS1743_ALARM_DATE 0x1fff -#define TODC_TYPE_DS1743_ALARM_HOUR 0x1fff -#define TODC_TYPE_DS1743_ALARM_MINUTES 0x1fff -#define TODC_TYPE_DS1743_ALARM_SECONDS 0x1fff -#define TODC_TYPE_DS1743_CENTURY 0x1ff8 -#define TODC_TYPE_DS1743_FLAGS 0x1fff -#define TODC_TYPE_DS1743_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1743_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1746_NVRAM_SIZE 0x1fff8 -#define TODC_TYPE_DS1746_SW_FLAGS 0 -#define TODC_TYPE_DS1746_YEAR 0x1ffff -#define TODC_TYPE_DS1746_MONTH 0x1fffe -#define TODC_TYPE_DS1746_DOM 0x1fffd /* Day of Month */ -#define TODC_TYPE_DS1746_DOW 0x1fffc /* Day of Week */ -#define TODC_TYPE_DS1746_HOURS 0x1fffb -#define TODC_TYPE_DS1746_MINUTES 0x1fffa -#define TODC_TYPE_DS1746_SECONDS 0x1fff9 -#define TODC_TYPE_DS1746_CNTL_B 0x1fff9 -#define TODC_TYPE_DS1746_CNTL_A 0x1fff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1746_WATCHDOG 0x00000 -#define TODC_TYPE_DS1746_INTERRUPTS 0x00000 -#define TODC_TYPE_DS1746_ALARM_DATE 0x00000 -#define TODC_TYPE_DS1746_ALARM_HOUR 0x00000 -#define TODC_TYPE_DS1746_ALARM_MINUTES 0x00000 -#define TODC_TYPE_DS1746_ALARM_SECONDS 0x00000 -#define TODC_TYPE_DS1746_CENTURY 0x00000 -#define TODC_TYPE_DS1746_FLAGS 0x00000 -#define TODC_TYPE_DS1746_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1746_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS1747_NVRAM_SIZE 0x7fff8 -#define TODC_TYPE_DS1747_SW_FLAGS 0 -#define TODC_TYPE_DS1747_YEAR 0x7ffff -#define TODC_TYPE_DS1747_MONTH 0x7fffe -#define TODC_TYPE_DS1747_DOM 0x7fffd /* Day of Month */ -#define TODC_TYPE_DS1747_DOW 0x7fffc /* Day of Week */ -#define TODC_TYPE_DS1747_HOURS 0x7fffb -#define TODC_TYPE_DS1747_MINUTES 0x7fffa -#define TODC_TYPE_DS1747_SECONDS 0x7fff9 -#define TODC_TYPE_DS1747_CNTL_B 0x7fff9 -#define TODC_TYPE_DS1747_CNTL_A 0x7fff8 /* control_a R/W regs */ -#define TODC_TYPE_DS1747_WATCHDOG 0x00000 -#define TODC_TYPE_DS1747_INTERRUPTS 0x00000 -#define TODC_TYPE_DS1747_ALARM_DATE 0x00000 -#define TODC_TYPE_DS1747_ALARM_HOUR 0x00000 -#define TODC_TYPE_DS1747_ALARM_MINUTES 0x00000 -#define TODC_TYPE_DS1747_ALARM_SECONDS 0x00000 -#define TODC_TYPE_DS1747_CENTURY 0x00000 -#define TODC_TYPE_DS1747_FLAGS 0x00000 -#define TODC_TYPE_DS1747_NVRAM_ADDR_REG 0 -#define TODC_TYPE_DS1747_NVRAM_DATA_REG 0 - -#define TODC_TYPE_DS17285_NVRAM_SIZE (0x1000-0x80) /* 4Kx8 NVRAM (minus RTC regs) */ -#define TODC_TYPE_DS17285_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM -#define TODC_TYPE_DS17285_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x00) -#define TODC_TYPE_DS17285_ALARM_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x01) -#define TODC_TYPE_DS17285_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x02) -#define TODC_TYPE_DS17285_ALARM_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x03) -#define TODC_TYPE_DS17285_HOURS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x04) -#define TODC_TYPE_DS17285_ALARM_HOUR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x05) -#define TODC_TYPE_DS17285_DOW (TODC_TYPE_DS17285_NVRAM_SIZE + 0x06) -#define TODC_TYPE_DS17285_DOM (TODC_TYPE_DS17285_NVRAM_SIZE + 0x07) -#define TODC_TYPE_DS17285_MONTH (TODC_TYPE_DS17285_NVRAM_SIZE + 0x08) -#define TODC_TYPE_DS17285_YEAR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x09) -#define TODC_TYPE_DS17285_CNTL_A (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0A) -#define TODC_TYPE_DS17285_CNTL_B (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0B) -#define TODC_TYPE_DS17285_CNTL_C (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0C) -#define TODC_TYPE_DS17285_CNTL_D (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0D) -#define TODC_TYPE_DS17285_WATCHDOG 0 -#define TODC_TYPE_DS17285_INTERRUPTS 0 -#define TODC_TYPE_DS17285_ALARM_DATE 0 -#define TODC_TYPE_DS17285_CENTURY 0 -#define TODC_TYPE_DS17285_FLAGS 0 -#define TODC_TYPE_DS17285_NVRAM_ADDR_REG 0x50 -#define TODC_TYPE_DS17285_NVRAM_DATA_REG 0x53 - -#define TODC_TYPE_MC146818_NVRAM_SIZE 0 /* XXXX */ -#define TODC_TYPE_MC146818_SW_FLAGS 0 -#define TODC_TYPE_MC146818_YEAR 0x09 -#define TODC_TYPE_MC146818_MONTH 0x08 -#define TODC_TYPE_MC146818_DOM 0x07 /* Day of Month */ -#define TODC_TYPE_MC146818_DOW 0x06 /* Day of Week */ -#define TODC_TYPE_MC146818_HOURS 0x04 -#define TODC_TYPE_MC146818_MINUTES 0x02 -#define TODC_TYPE_MC146818_SECONDS 0x00 -#define TODC_TYPE_MC146818_CNTL_B 0x0a -#define TODC_TYPE_MC146818_CNTL_A 0x0b /* control_a R/W regs */ -#define TODC_TYPE_MC146818_WATCHDOG 0 -#define TODC_TYPE_MC146818_INTERRUPTS 0x0c -#define TODC_TYPE_MC146818_ALARM_DATE 0xff -#define TODC_TYPE_MC146818_ALARM_HOUR 0x05 -#define TODC_TYPE_MC146818_ALARM_MINUTES 0x03 -#define TODC_TYPE_MC146818_ALARM_SECONDS 0x01 -#define TODC_TYPE_MC146818_CENTURY 0xff -#define TODC_TYPE_MC146818_FLAGS 0xff -#define TODC_TYPE_MC146818_NVRAM_ADDR_REG 0 -#define TODC_TYPE_MC146818_NVRAM_DATA_REG 0 - -#define TODC_TYPE_PC97307_NVRAM_SIZE 0 /* No NVRAM? */ -#define TODC_TYPE_PC97307_SW_FLAGS 0 -#define TODC_TYPE_PC97307_YEAR 0x09 -#define TODC_TYPE_PC97307_MONTH 0x08 -#define TODC_TYPE_PC97307_DOM 0x07 /* Day of Month */ -#define TODC_TYPE_PC97307_DOW 0x06 /* Day of Week */ -#define TODC_TYPE_PC97307_HOURS 0x04 -#define TODC_TYPE_PC97307_MINUTES 0x02 -#define TODC_TYPE_PC97307_SECONDS 0x00 -#define TODC_TYPE_PC97307_CNTL_B 0x0a -#define TODC_TYPE_PC97307_CNTL_A 0x0b /* control_a R/W regs */ -#define TODC_TYPE_PC97307_WATCHDOG 0x0c -#define TODC_TYPE_PC97307_INTERRUPTS 0x0d -#define TODC_TYPE_PC97307_ALARM_DATE 0xff -#define TODC_TYPE_PC97307_ALARM_HOUR 0x05 -#define TODC_TYPE_PC97307_ALARM_MINUTES 0x03 -#define TODC_TYPE_PC97307_ALARM_SECONDS 0x01 -#define TODC_TYPE_PC97307_CENTURY 0xff -#define TODC_TYPE_PC97307_FLAGS 0xff -#define TODC_TYPE_PC97307_NVRAM_ADDR_REG 0 -#define TODC_TYPE_PC97307_NVRAM_DATA_REG 0 - -/* - * Define macros to allocate and init the todc_info_t table that will - * be used by the todc_time.c routines. - */ -#define TODC_ALLOC() \ - static todc_info_t todc_info_alloc; \ - todc_info_t *todc_info = &todc_info_alloc; - -#define TODC_INIT(clock_type, as0, as1, data, bits) { \ - todc_info->rtc_type = clock_type; \ - \ - todc_info->nvram_as0 = (unsigned int)(as0); \ - todc_info->nvram_as1 = (unsigned int)(as1); \ - todc_info->nvram_data = (unsigned int)(data); \ - \ - todc_info->as0_bits = (bits); \ - \ - todc_info->nvram_size = clock_type ##_NVRAM_SIZE; \ - todc_info->sw_flags = clock_type ##_SW_FLAGS; \ - \ - todc_info->year = clock_type ##_YEAR; \ - todc_info->month = clock_type ##_MONTH; \ - todc_info->day_of_month = clock_type ##_DOM; \ - todc_info->day_of_week = clock_type ##_DOW; \ - todc_info->hours = clock_type ##_HOURS; \ - todc_info->minutes = clock_type ##_MINUTES; \ - todc_info->seconds = clock_type ##_SECONDS; \ - todc_info->control_b = clock_type ##_CNTL_B; \ - todc_info->control_a = clock_type ##_CNTL_A; \ - todc_info->watchdog = clock_type ##_WATCHDOG; \ - todc_info->interrupts = clock_type ##_INTERRUPTS; \ - todc_info->alarm_date = clock_type ##_ALARM_DATE; \ - todc_info->alarm_hour = clock_type ##_ALARM_HOUR; \ - todc_info->alarm_minutes = clock_type ##_ALARM_MINUTES; \ - todc_info->alarm_seconds = clock_type ##_ALARM_SECONDS; \ - todc_info->century = clock_type ##_CENTURY; \ - todc_info->flags = clock_type ##_FLAGS; \ - \ - todc_info->nvram_addr_reg = clock_type ##_NVRAM_ADDR_REG; \ - todc_info->nvram_data_reg = clock_type ##_NVRAM_DATA_REG; \ -} - -extern todc_info_t *todc_info; - -unsigned char todc_direct_read_val(int addr); -void todc_direct_write_val(int addr, unsigned char val); -unsigned char todc_m48txx_read_val(int addr); -void todc_m48txx_write_val(int addr, unsigned char val); -unsigned char todc_mc146818_read_val(int addr); -void todc_mc146818_write_val(int addr, unsigned char val); - -long todc_time_init(void); -void todc_get_rtc_time(struct rtc_time *); -int todc_set_rtc_time(struct rtc_time *); -void todc_calibrate_decr(void); - -#endif /* __PPC_KERNEL_TODC_H */ diff --git a/trunk/include/asm-powerpc/topology.h b/trunk/include/asm-powerpc/topology.h index bbc3844b086f..92f3e5507d22 100644 --- a/trunk/include/asm-powerpc/topology.h +++ b/trunk/include/asm-powerpc/topology.h @@ -93,10 +93,5 @@ static inline void sysfs_remove_device_from_node(struct sys_device *dev, #endif /* CONFIG_NUMA */ -#ifdef CONFIG_SMP -#include -#define smt_capable() (cpu_has_feature(CPU_FTR_SMT)) -#endif - #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_TOPOLOGY_H */ diff --git a/trunk/include/asm-powerpc/tsi108.h b/trunk/include/asm-powerpc/tsi108.h deleted file mode 100644 index c4c278d72f71..000000000000 --- a/trunk/include/asm-powerpc/tsi108.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * include/asm-ppc/tsi108.h - * - * common routine and memory layout for Tundra TSI108(Grendel) host bridge - * memory controller. - * - * Author: Jacob Pan (jacob.pan@freescale.com) - * Alex Bounine (alexandreb@tundra.com) - * 2004 (c) Freescale Semiconductor Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -#ifndef __PPC_KERNEL_TSI108_H -#define __PPC_KERNEL_TSI108_H - -#include - -/* Size of entire register space */ -#define TSI108_REG_SIZE (0x10000) - -/* Sizes of register spaces for individual blocks */ -#define TSI108_HLP_SIZE 0x1000 -#define TSI108_PCI_SIZE 0x1000 -#define TSI108_CLK_SIZE 0x1000 -#define TSI108_PB_SIZE 0x1000 -#define TSI108_SD_SIZE 0x1000 -#define TSI108_DMA_SIZE 0x1000 -#define TSI108_ETH_SIZE 0x1000 -#define TSI108_I2C_SIZE 0x400 -#define TSI108_MPIC_SIZE 0x400 -#define TSI108_UART0_SIZE 0x200 -#define TSI108_GPIO_SIZE 0x200 -#define TSI108_UART1_SIZE 0x200 - -/* Offsets within Tsi108(A) CSR space for individual blocks */ -#define TSI108_HLP_OFFSET 0x0000 -#define TSI108_PCI_OFFSET 0x1000 -#define TSI108_CLK_OFFSET 0x2000 -#define TSI108_PB_OFFSET 0x3000 -#define TSI108_SD_OFFSET 0x4000 -#define TSI108_DMA_OFFSET 0x5000 -#define TSI108_ETH_OFFSET 0x6000 -#define TSI108_I2C_OFFSET 0x7000 -#define TSI108_MPIC_OFFSET 0x7400 -#define TSI108_UART0_OFFSET 0x7800 -#define TSI108_GPIO_OFFSET 0x7A00 -#define TSI108_UART1_OFFSET 0x7C00 - -/* Tsi108 registers used by common code components */ -#define TSI108_PCI_CSR (0x004) -#define TSI108_PCI_IRP_CFG_CTL (0x180) -#define TSI108_PCI_IRP_STAT (0x184) -#define TSI108_PCI_IRP_ENABLE (0x188) -#define TSI108_PCI_IRP_INTAD (0x18C) - -#define TSI108_PCI_IRP_STAT_P_INT (0x00400000) -#define TSI108_PCI_IRP_ENABLE_P_INT (0x00400000) - -#define TSI108_CG_PWRUP_STATUS (0x234) - -#define TSI108_PB_ISR (0x00C) -#define TSI108_PB_ERRCS (0x404) -#define TSI108_PB_AERR (0x408) - -#define TSI108_PB_ERRCS_ES (1 << 1) -#define TSI108_PB_ISR_PBS_RD_ERR (1 << 8) - -#define TSI108_PCI_CFG_BASE_PHYS (0xfb000000) -#define TSI108_PCI_CFG_SIZE (0x01000000) -/* Global variables */ - -extern u32 tsi108_pci_cfg_base; -/* Exported functions */ - -extern int tsi108_bridge_init(struct pci_controller *hose, uint phys_csr_base); -extern unsigned long tsi108_get_mem_size(void); -extern unsigned long tsi108_get_cpu_clk(void); -extern unsigned long tsi108_get_sdc_clk(void); -extern int tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfn, - int offset, int len, u32 val); -extern int tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, - int offset, int len, u32 * val); -extern void tsi108_clear_pci_error(u32 pci_cfg_base); - -extern phys_addr_t get_csrbase(void); - -typedef struct { - u32 regs; /* hw registers base address */ - u32 phyregs; /* phy registers base address */ - u16 phy; /* phy address */ - u16 irq_num; /* irq number */ - u8 mac_addr[6]; /* phy mac address */ -} hw_info; - -extern u32 get_vir_csrbase(void); -extern u32 tsi108_csr_vir_base; - -extern inline u32 tsi108_read_reg(u32 reg_offset) -{ - return in_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset)); -} - -extern inline void tsi108_write_reg(u32 reg_offset, u32 val) -{ - out_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset), val); -} - -#endif /* __PPC_KERNEL_TSI108_H */ diff --git a/trunk/include/asm-powerpc/udbg.h b/trunk/include/asm-powerpc/udbg.h index 55e57844fa78..19a1517ac43b 100644 --- a/trunk/include/asm-powerpc/udbg.h +++ b/trunk/include/asm-powerpc/udbg.h @@ -42,8 +42,7 @@ extern void __init udbg_init_debug_lpar(void); extern void __init udbg_init_pmac_realmode(void); extern void __init udbg_init_maple_realmode(void); extern void __init udbg_init_iseries(void); -extern void __init udbg_init_rtas_panel(void); -extern void __init udbg_init_rtas_console(void); +extern void __init udbg_init_rtas(void); #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_UDBG_H */ diff --git a/trunk/include/asm-ppc/floppy.h b/trunk/include/asm-ppc/floppy.h index d3963ca79ad8..2ba191eba448 100644 --- a/trunk/include/asm-ppc/floppy.h +++ b/trunk/include/asm-ppc/floppy.h @@ -96,11 +96,11 @@ static int vdma_get_dma_residue(unsigned int dummy) static int fd_request_irq(void) { if (can_use_virtual_dma) - return request_irq(FLOPPY_IRQ, floppy_hardint, - IRQF_DISABLED, "floppy", NULL); + return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT, + "floppy", NULL); else - return request_irq(FLOPPY_IRQ, floppy_interrupt, - IRQF_DISABLED, "floppy", NULL); + return request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT, + "floppy", NULL); } static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io) diff --git a/trunk/include/asm-ppc/ocp.h b/trunk/include/asm-ppc/ocp.h index 16dbc7d17450..3be5d760ffcd 100644 --- a/trunk/include/asm-ppc/ocp.h +++ b/trunk/include/asm-ppc/ocp.h @@ -26,6 +26,7 @@ #include #include +#include #include #include diff --git a/trunk/include/asm-ppc/page.h b/trunk/include/asm-ppc/page.h index fe95c8258cf9..0b19af82507f 100644 --- a/trunk/include/asm-ppc/page.h +++ b/trunk/include/asm-ppc/page.h @@ -170,7 +170,7 @@ extern __inline__ int get_order(unsigned long size) #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) -/* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */ +/* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */ #define __HAVE_ARCH_GATE_AREA 1 #include diff --git a/trunk/include/asm-ppc/pci.h b/trunk/include/asm-ppc/pci.h index 11ffaaa5da16..61434edbad7b 100644 --- a/trunk/include/asm-ppc/pci.h +++ b/trunk/include/asm-ppc/pci.h @@ -133,7 +133,7 @@ extern pgprot_t pci_phys_mem_access_prot(struct file *file, #define HAVE_ARCH_PCI_RESOURCE_TO_USER extern void pci_resource_to_user(const struct pci_dev *dev, int bar, const struct resource *rsrc, - resource_size_t *start, resource_size_t *end); + u64 *start, u64 *end); #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-s390/bitops.h b/trunk/include/asm-s390/bitops.h index 0ddcdba79e4a..4d2b126ba159 100644 --- a/trunk/include/asm-s390/bitops.h +++ b/trunk/include/asm-s390/bitops.h @@ -12,9 +12,6 @@ * Copyright (C) 1992, Linus Torvalds * */ - -#ifdef __KERNEL__ - #include /* @@ -53,6 +50,19 @@ * with operation of the form "set_bit(bitnr, flags)". */ +/* set ALIGN_CS to 1 if the SMP safe bit operations should + * align the address to 4 byte boundary. It seems to work + * without the alignment. + */ +#ifdef __KERNEL__ +#define ALIGN_CS 0 +#else +#define ALIGN_CS 1 +#ifndef CONFIG_SMP +#error "bitops won't work without CONFIG_SMP" +#endif +#endif + /* bitmap tables from arch/S390/kernel/bitmap.S */ extern const char _oi_bitmap[]; extern const char _ni_bitmap[]; @@ -111,6 +121,10 @@ static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; +#if ALIGN_CS == 1 + nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ + addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ +#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make OR mask */ @@ -127,6 +141,10 @@ static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; +#if ALIGN_CS == 1 + nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ + addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ +#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make AND mask */ @@ -143,6 +161,10 @@ static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; +#if ALIGN_CS == 1 + nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ + addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ +#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make XOR mask */ @@ -160,6 +182,10 @@ test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; +#if ALIGN_CS == 1 + nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ + addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ +#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make OR/test mask */ @@ -179,6 +205,10 @@ test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; +#if ALIGN_CS == 1 + nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ + addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ +#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make AND/test mask */ @@ -198,6 +228,10 @@ test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr) unsigned long addr, old, new, mask; addr = (unsigned long) ptr; +#if ALIGN_CS == 1 + nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ + addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ +#endif /* calculate address for CS */ addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; /* make XOR/test mask */ @@ -800,6 +834,8 @@ static inline int sched_find_first_bit(unsigned long *b) #include +#ifdef __KERNEL__ + /* * ATTENTION: intel byte ordering convention for ext2 and minix !! * bit 0 is the LSB of addr; bit 31 is the MSB of addr; diff --git a/trunk/include/asm-s390/cio.h b/trunk/include/asm-s390/cio.h index 2b1619306351..089cf567c317 100644 --- a/trunk/include/asm-s390/cio.h +++ b/trunk/include/asm-s390/cio.h @@ -276,8 +276,6 @@ extern void wait_cons_dev(void); extern void clear_all_subchannels(void); -extern void css_schedule_reprobe(void); - #endif #endif diff --git a/trunk/include/asm-s390/cmb.h b/trunk/include/asm-s390/cmb.h index 241756f80df3..2d09950a9c11 100644 --- a/trunk/include/asm-s390/cmb.h +++ b/trunk/include/asm-s390/cmb.h @@ -44,6 +44,10 @@ struct cmbdata { #define BIODASDCMFENABLE _IO(DASD_IOCTL_LETTER,32) /* enable channel measurement */ #define BIODASDCMFDISABLE _IO(DASD_IOCTL_LETTER,33) +/* reset channel measurement block */ +#define BIODASDRESETCMB _IO(DASD_IOCTL_LETTER,34) +/* read channel measurement data */ +#define BIODASDREADCMB _IOWR(DASD_IOCTL_LETTER,32,__u64) /* read channel measurement data */ #define BIODASDREADALLCMB _IOWR(DASD_IOCTL_LETTER,33,struct cmbdata) diff --git a/trunk/include/asm-s390/dasd.h b/trunk/include/asm-s390/dasd.h index c042f9578081..1630c26e8f45 100644 --- a/trunk/include/asm-s390/dasd.h +++ b/trunk/include/asm-s390/dasd.h @@ -68,12 +68,10 @@ typedef struct dasd_information2_t { * 0x00: default features * 0x01: readonly (ro) * 0x02: use diag discipline (diag) - * 0x04: set the device initially online (internal use only) */ -#define DASD_FEATURE_DEFAULT 0x00 -#define DASD_FEATURE_READONLY 0x01 -#define DASD_FEATURE_USEDIAG 0x02 -#define DASD_FEATURE_INITIAL_ONLINE 0x04 +#define DASD_FEATURE_DEFAULT 0 +#define DASD_FEATURE_READONLY 1 +#define DASD_FEATURE_USEDIAG 2 #define DASD_PARTN_BITS 2 diff --git a/trunk/include/asm-s390/pgtable.h b/trunk/include/asm-s390/pgtable.h index 24312387fa24..859b5e969826 100644 --- a/trunk/include/asm-s390/pgtable.h +++ b/trunk/include/asm-s390/pgtable.h @@ -657,6 +657,13 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) __pte; \ }) +#define SetPageUptodate(_page) \ + do { \ + struct page *__page = (_page); \ + if (!test_and_set_bit(PG_uptodate, &__page->flags)) \ + page_test_and_clear_dirty(_page); \ + } while (0) + #ifdef __s390x__ #define pfn_pmd(pfn, pgprot) \ diff --git a/trunk/include/asm-s390/signal.h b/trunk/include/asm-s390/signal.h index f6cfddb278cb..7084626de215 100644 --- a/trunk/include/asm-s390/signal.h +++ b/trunk/include/asm-s390/signal.h @@ -84,6 +84,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -103,6 +104,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 diff --git a/trunk/include/asm-s390/socket.h b/trunk/include/asm-s390/socket.h index 1778a49a74c5..15a5298c8744 100644 --- a/trunk/include/asm-s390/socket.h +++ b/trunk/include/asm-s390/socket.h @@ -56,6 +56,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_SOCKET_H */ diff --git a/trunk/include/asm-s390/thread_info.h b/trunk/include/asm-s390/thread_info.h index 0a518915bf90..8e0c7ed73d03 100644 --- a/trunk/include/asm-s390/thread_info.h +++ b/trunk/include/asm-s390/thread_info.h @@ -63,7 +63,6 @@ struct thread_info { .exec_domain = &default_exec_domain, \ .flags = 0, \ .cpu = 0, \ - .preempt_count = 1, \ .restart_block = { \ .fn = do_no_restart_syscall, \ }, \ diff --git a/trunk/include/asm-s390/unistd.h b/trunk/include/asm-s390/unistd.h index aa7a243862e1..e21443d3ea1d 100644 --- a/trunk/include/asm-s390/unistd.h +++ b/trunk/include/asm-s390/unistd.h @@ -394,9 +394,11 @@ #ifdef __KERNEL__ +/* user-visible error numbers are in the range -1 - -122: see */ + #define __syscall_return(type, res) \ do { \ - if ((unsigned long)(res) >= (unsigned long)(-4095)) {\ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ errno = -(res); \ res = -1; \ } \ diff --git a/trunk/include/asm-sh/floppy.h b/trunk/include/asm-sh/floppy.h index dc1ad464fa32..307d9ce9f9ed 100644 --- a/trunk/include/asm-sh/floppy.h +++ b/trunk/include/asm-sh/floppy.h @@ -146,11 +146,12 @@ static int vdma_get_dma_residue(unsigned int dummy) static int fd_request_irq(void) { if(can_use_virtual_dma) - return request_irq(FLOPPY_IRQ, floppy_hardint, - IRQF_DISABLED, "floppy", NULL); + return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT, + "floppy", NULL); else - return request_irq(FLOPPY_IRQ, floppy_interrupt, - IRQF_DISABLED, "floppy", NULL); + return request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT, + "floppy", NULL); + } static unsigned long dma_mem_alloc(unsigned long size) diff --git a/trunk/include/asm-sh/hw_irq.h b/trunk/include/asm-sh/hw_irq.h index fed26616967a..1d934fb2c581 100644 --- a/trunk/include/asm-sh/hw_irq.h +++ b/trunk/include/asm-sh/hw_irq.h @@ -1,4 +1,9 @@ #ifndef __ASM_SH_HW_IRQ_H #define __ASM_SH_HW_IRQ_H +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) +{ + /* Nothing to do */ +} + #endif /* __ASM_SH_HW_IRQ_H */ diff --git a/trunk/include/asm-sh/mpc1211/keyboard.h b/trunk/include/asm-sh/mpc1211/keyboard.h index 71ef4cf4242d..5f0b9088c796 100644 --- a/trunk/include/asm-sh/mpc1211/keyboard.h +++ b/trunk/include/asm-sh/mpc1211/keyboard.h @@ -57,7 +57,7 @@ extern unsigned char pckbd_sysrq_xlate[128]; #define AUX_IRQ 12 #define aux_request_irq(hand, dev_id) \ - request_irq(AUX_IRQ, hand, IRQF_SHARED, "PS2 Mouse", dev_id) + request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS2 Mouse", dev_id) #define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id) diff --git a/trunk/include/asm-sh/signal.h b/trunk/include/asm-sh/signal.h index 5c5c1e852089..d6e8eb0e65c7 100644 --- a/trunk/include/asm-sh/signal.h +++ b/trunk/include/asm-sh/signal.h @@ -75,6 +75,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -94,6 +95,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 diff --git a/trunk/include/asm-sh/socket.h b/trunk/include/asm-sh/socket.h index ca70362eb563..553904ff9336 100644 --- a/trunk/include/asm-sh/socket.h +++ b/trunk/include/asm-sh/socket.h @@ -48,6 +48,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* __ASM_SH_SOCKET_H */ diff --git a/trunk/include/asm-sh64/hw_irq.h b/trunk/include/asm-sh64/hw_irq.h index ebb39089b0ac..ae718d1f2d6c 100644 --- a/trunk/include/asm-sh64/hw_irq.h +++ b/trunk/include/asm-sh64/hw_irq.h @@ -11,5 +11,6 @@ * Copyright (C) 2000, 2001 Paolo Alberelli * */ +static __inline__ void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { /* Nothing to do */ } #endif /* __ASM_SH64_HW_IRQ_H */ diff --git a/trunk/include/asm-sh64/keyboard.h b/trunk/include/asm-sh64/keyboard.h index 1fab96d792bf..733e2bbe7b8c 100644 --- a/trunk/include/asm-sh64/keyboard.h +++ b/trunk/include/asm-sh64/keyboard.h @@ -65,7 +65,7 @@ extern unsigned char pckbd_sysrq_xlate[128]; #endif #define aux_request_irq(hand, dev_id) \ - request_irq(AUX_IRQ, hand, IRQF_SHARED, "PS2 Mouse", dev_id) + request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS2 Mouse", dev_id) #define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id) diff --git a/trunk/include/asm-sh64/signal.h b/trunk/include/asm-sh64/signal.h index a5a28203cb3b..2400dc688a65 100644 --- a/trunk/include/asm-sh64/signal.h +++ b/trunk/include/asm-sh64/signal.h @@ -74,6 +74,7 @@ typedef struct { * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -93,6 +94,7 @@ typedef struct { #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 diff --git a/trunk/include/asm-sparc/floppy.h b/trunk/include/asm-sparc/floppy.h index c53b332c850a..7a941b800b6b 100644 --- a/trunk/include/asm-sparc/floppy.h +++ b/trunk/include/asm-sparc/floppy.h @@ -271,8 +271,7 @@ static int sun_fd_request_irq(void) if(!once) { once = 1; - error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, - IRQF_DISABLED, "floppy"); + error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, SA_INTERRUPT, "floppy"); return ((error == 0) ? 0 : -1); } else return 0; } diff --git a/trunk/include/asm-sparc/io.h b/trunk/include/asm-sparc/io.h index cab0b851b8b1..a42df208d590 100644 --- a/trunk/include/asm-sparc/io.h +++ b/trunk/include/asm-sparc/io.h @@ -249,22 +249,6 @@ extern void __iomem *ioremap(unsigned long offset, unsigned long size); #define ioremap_nocache(X,Y) ioremap((X),(Y)) extern void iounmap(volatile void __iomem *addr); -#define ioread8(X) readb(X) -#define ioread16(X) readw(X) -#define ioread32(X) readl(X) -#define iowrite8(val,X) writeb(val,X) -#define iowrite16(val,X) writew(val,X) -#define iowrite32(val,X) writel(val,X) - -/* Create a virtual mapping cookie for an IO port range */ -extern void __iomem *ioport_map(unsigned long port, unsigned int nr); -extern void ioport_unmap(void __iomem *); - -/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ -struct pci_dev; -extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); -extern void pci_iounmap(struct pci_dev *dev, void __iomem *); - /* * Bus number may be in res->flags... somewhere. */ diff --git a/trunk/include/asm-sparc/of_device.h b/trunk/include/asm-sparc/of_device.h index 80ea31f6e17f..4816d102f918 100644 --- a/trunk/include/asm-sparc/of_device.h +++ b/trunk/include/asm-sparc/of_device.h @@ -4,12 +4,10 @@ #include #include -#include #include extern struct bus_type ebus_bus_type; extern struct bus_type sbus_bus_type; -extern struct bus_type of_bus_type; /* * The of_device is a kind of "base class" that is a superset of @@ -18,25 +16,11 @@ extern struct bus_type of_bus_type; */ struct of_device { - struct device_node *node; - struct device dev; - struct resource resource[PROMREG_MAX]; - unsigned int irqs[PROMINTR_MAX]; - int num_irqs; - - void *sysdata; - - int slot; - int portid; - int clock_freq; + struct device_node *node; /* OF device node */ + struct device dev; /* Generic device interface */ }; #define to_of_device(d) container_of(d, struct of_device, dev) -extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); -extern void of_iounmap(void __iomem *base, unsigned long size); - -extern struct of_device *of_find_device_by_node(struct device_node *); - extern const struct of_device_id *of_match_device( const struct of_device_id *matches, const struct of_device *dev); diff --git a/trunk/include/asm-sparc/prom.h b/trunk/include/asm-sparc/prom.h index 86c13dccea3d..c5e3d26eabd3 100644 --- a/trunk/include/asm-sparc/prom.h +++ b/trunk/include/asm-sparc/prom.h @@ -25,19 +25,25 @@ typedef u32 phandle; typedef u32 ihandle; +struct interrupt_info { + int line; + int sense; /* +ve/-ve logic, edge or level, etc. */ +}; + struct property { char *name; int length; void *value; struct property *next; - unsigned long _flags; - unsigned int unique_id; }; struct device_node { char *name; char *type; phandle node; + phandle linux_phandle; + int n_intrs; + struct interrupt_info *intrs; char *path_component_name; char *full_name; @@ -52,17 +58,8 @@ struct device_node { struct kref kref; unsigned long _flags; void *data; - unsigned int unique_id; }; -/* flag descriptions */ -#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ - -#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) -#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) - -#define OF_BAD_ADDR ((u64)-1) - static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) { dn->pde = de; @@ -91,12 +88,9 @@ extern struct property *of_find_property(struct device_node *np, extern int of_device_is_compatible(struct device_node *device, const char *); extern void *of_get_property(struct device_node *node, const char *name, int *lenp); -extern int of_set_property(struct device_node *node, const char *name, void *val, int len); extern int of_getintprop_default(struct device_node *np, const char *name, int def); -extern int of_n_addr_cells(struct device_node *np); -extern int of_n_size_cells(struct device_node *np); extern void prom_build_devicetree(void); diff --git a/trunk/include/asm-sparc/signal.h b/trunk/include/asm-sparc/signal.h index 0ae5084c427b..aa9960ad0ca9 100644 --- a/trunk/include/asm-sparc/signal.h +++ b/trunk/include/asm-sparc/signal.h @@ -132,13 +132,16 @@ struct sigstack { * usage of signal stacks by using the (now obsolete) sa_restorer field in * the sigaction structure as a stack pointer. This is now possible due to * the changes in signal handling. LBT 010493. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_SHIRQ flag is for shared interrupt support on PCI and EISA. */ #define SA_NOCLDSTOP _SV_IGNCHILD #define SA_STACK _SV_SSTACK #define SA_ONSTACK _SV_SSTACK #define SA_RESTART _SV_INTR #define SA_ONESHOT _SV_RESET +#define SA_INTERRUPT 0x10u #define SA_NOMASK 0x20u #define SA_NOCLDWAIT 0x100u #define SA_SIGINFO 0x200u diff --git a/trunk/include/asm-sparc/socket.h b/trunk/include/asm-sparc/socket.h index f6c4e5baf3f7..4e0ce3a35ea9 100644 --- a/trunk/include/asm-sparc/socket.h +++ b/trunk/include/asm-sparc/socket.h @@ -48,7 +48,6 @@ #define SCM_TIMESTAMP SO_TIMESTAMP #define SO_PEERSEC 0x001e -#define SO_PASSSEC 0x001f /* Security levels - as per NRL IPv6 - don't actually do anything */ #define SO_SECURITY_AUTHENTICATION 0x5001 diff --git a/trunk/include/asm-sparc64/dma-mapping.h b/trunk/include/asm-sparc64/dma-mapping.h index 0f5b89c9323b..3c2b5bc8650b 100644 --- a/trunk/include/asm-sparc64/dma-mapping.h +++ b/trunk/include/asm-sparc64/dma-mapping.h @@ -162,47 +162,4 @@ static inline void dma_free_coherent(struct device *dev, size_t size, #endif /* PCI */ - -/* Now for the API extensions over the pci_ one */ - -#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) -#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) -#define dma_is_consistent(d) (1) - -static inline int -dma_get_cache_alignment(void) -{ - /* no easy way to get cache size on all processors, so return - * the maximum possible, to be safe */ - return (1 << INTERNODE_CACHE_SHIFT); -} - -static inline void -dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - /* just sync everything, that's all the pci API can do */ - dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction); -} - -static inline void -dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction direction) -{ - /* just sync everything, that's all the pci API can do */ - dma_sync_single_for_device(dev, dma_handle, offset+size, direction); -} - -static inline void -dma_cache_sync(void *vaddr, size_t size, - enum dma_data_direction direction) -{ - /* could define this in terms of the dma_cache ... operations, - * but if you get this on a platform, you should convert the platform - * to using the generic device DMA API */ - BUG(); -} - #endif /* _ASM_SPARC64_DMA_MAPPING_H */ diff --git a/trunk/include/asm-sparc64/floppy.h b/trunk/include/asm-sparc64/floppy.h index abf150038019..f8d57bb5570c 100644 --- a/trunk/include/asm-sparc64/floppy.h +++ b/trunk/include/asm-sparc64/floppy.h @@ -208,55 +208,7 @@ static void sun_fd_enable_dma(void) pdma_areasize = pdma_size; } -irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs) -{ - if (likely(doing_pdma)) { - void __iomem *stat = (void __iomem *) fdc_status; - unsigned char *vaddr = pdma_vaddr; - unsigned long size = pdma_size; - u8 val; - - while (size) { - val = readb(stat); - if (unlikely(!(val & 0x80))) { - pdma_vaddr = vaddr; - pdma_size = size; - return IRQ_HANDLED; - } - if (unlikely(!(val & 0x20))) { - pdma_vaddr = vaddr; - pdma_size = size; - doing_pdma = 0; - goto main_interrupt; - } - if (val & 0x40) { - /* read */ - *vaddr++ = readb(stat + 1); - } else { - unsigned char data = *vaddr++; - - /* write */ - writeb(data, stat + 1); - } - size--; - } - - pdma_vaddr = vaddr; - pdma_size = size; - - /* Send Terminal Count pulse to floppy controller. */ - val = readb(auxio_register); - val |= AUXIO_AUX1_FTCNT; - writeb(val, auxio_register); - val &= ~AUXIO_AUX1_FTCNT; - writeb(val, auxio_register); - - doing_pdma = 0; - } - -main_interrupt: - return floppy_interrupt(irq, dev_cookie, regs); -} +extern irqreturn_t sparc_floppy_irq(int, void *, struct pt_regs *); static int sun_fd_request_irq(void) { @@ -267,7 +219,7 @@ static int sun_fd_request_irq(void) once = 1; error = request_irq(FLOPPY_IRQ, sparc_floppy_irq, - IRQF_DISABLED, "floppy", NULL); + SA_INTERRUPT, "floppy", NULL); return ((error == 0) ? 0 : -1); } diff --git a/trunk/include/asm-sparc64/kdebug.h b/trunk/include/asm-sparc64/kdebug.h index 11251bdd00cb..4040d127ac3e 100644 --- a/trunk/include/asm-sparc64/kdebug.h +++ b/trunk/include/asm-sparc64/kdebug.h @@ -17,8 +17,6 @@ struct die_args { extern int register_die_notifier(struct notifier_block *); extern int unregister_die_notifier(struct notifier_block *); -extern int register_page_fault_notifier(struct notifier_block *); -extern int unregister_page_fault_notifier(struct notifier_block *); extern struct atomic_notifier_head sparc64die_chain; extern void bad_trap(struct pt_regs *, long); diff --git a/trunk/include/asm-sparc64/kprobes.h b/trunk/include/asm-sparc64/kprobes.h index 15065af566c2..e9bb26f770ed 100644 --- a/trunk/include/asm-sparc64/kprobes.h +++ b/trunk/include/asm-sparc64/kprobes.h @@ -12,7 +12,6 @@ typedef u32 kprobe_opcode_t; #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry #define arch_remove_kprobe(p) do {} while (0) -#define ARCH_INACTIVE_KPROBE_COUNT 0 /* Architecture specific copy of original instruction*/ struct arch_specific_insn { diff --git a/trunk/include/asm-sparc64/of_device.h b/trunk/include/asm-sparc64/of_device.h index a62c7b997d66..024088ef9d27 100644 --- a/trunk/include/asm-sparc64/of_device.h +++ b/trunk/include/asm-sparc64/of_device.h @@ -4,13 +4,11 @@ #include #include -#include #include extern struct bus_type isa_bus_type; extern struct bus_type ebus_bus_type; extern struct bus_type sbus_bus_type; -extern struct bus_type of_bus_type; /* * The of_device is a kind of "base class" that is a superset of @@ -19,25 +17,11 @@ extern struct bus_type of_bus_type; */ struct of_device { - struct device_node *node; - struct device dev; - struct resource resource[PROMREG_MAX]; - unsigned int irqs[PROMINTR_MAX]; - int num_irqs; - - void *sysdata; - - int slot; - int portid; - int clock_freq; + struct device_node *node; /* OF device node */ + struct device dev; /* Generic device interface */ }; #define to_of_device(d) container_of(d, struct of_device, dev) -extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); -extern void of_iounmap(void __iomem *base, unsigned long size); - -extern struct of_device *of_find_device_by_node(struct device_node *); - extern const struct of_device_id *of_match_device( const struct of_device_id *matches, const struct of_device *dev); diff --git a/trunk/include/asm-sparc64/pbm.h b/trunk/include/asm-sparc64/pbm.h index dcfa7629358c..cebe80b1da6c 100644 --- a/trunk/include/asm-sparc64/pbm.h +++ b/trunk/include/asm-sparc64/pbm.h @@ -16,7 +16,6 @@ #include #include #include -#include #include /* The abstraction used here is that there are PCI controllers, @@ -210,6 +209,7 @@ struct pci_controller_info { /* Operations which are controller specific. */ void (*scan_bus)(struct pci_controller_info *); + unsigned int (*irq_build)(struct pci_pbm_info *, struct pci_dev *, unsigned int); void (*base_address_update)(struct pci_dev *, int); void (*resource_adjust)(struct pci_dev *, struct resource *, struct resource *); @@ -217,6 +217,8 @@ struct pci_controller_info { struct pci_ops *pci_ops; unsigned int pci_first_busno; unsigned int pci_last_busno; + + void *starfire_cookie; }; /* PCI devices which are not bridges have this placed in their pci_dev @@ -226,7 +228,6 @@ struct pci_controller_info { struct pcidev_cookie { struct pci_pbm_info *pbm; struct device_node *prom_node; - struct of_device *op; struct linux_prom_pci_registers prom_regs[PROMREG_MAX]; int num_prom_regs; struct linux_prom_pci_registers prom_assignments[PROMREG_MAX]; diff --git a/trunk/include/asm-sparc64/prom.h b/trunk/include/asm-sparc64/prom.h index 99671ed6625d..6d1556c0c263 100644 --- a/trunk/include/asm-sparc64/prom.h +++ b/trunk/include/asm-sparc64/prom.h @@ -25,20 +25,25 @@ typedef u32 phandle; typedef u32 ihandle; +struct interrupt_info { + int line; + int sense; /* +ve/-ve logic, edge or level, etc. */ +}; + struct property { char *name; int length; void *value; struct property *next; - unsigned long _flags; - unsigned int unique_id; }; -struct of_irq_controller; struct device_node { char *name; char *type; phandle node; + phandle linux_phandle; + int n_intrs; + struct interrupt_info *intrs; char *path_component_name; char *full_name; @@ -53,24 +58,8 @@ struct device_node { struct kref kref; unsigned long _flags; void *data; - unsigned int unique_id; - - struct of_irq_controller *irq_trans; }; -struct of_irq_controller { - unsigned int (*irq_build)(struct device_node *, unsigned int, void *); - void *data; -}; - -/* flag descriptions */ -#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ - -#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) -#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) - -#define OF_BAD_ADDR ((u64)-1) - static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) { dn->pde = de; @@ -99,12 +88,9 @@ extern struct property *of_find_property(struct device_node *np, extern int of_device_is_compatible(struct device_node *device, const char *); extern void *of_get_property(struct device_node *node, const char *name, int *lenp); -extern int of_set_property(struct device_node *node, const char *name, void *val, int len); extern int of_getintprop_default(struct device_node *np, const char *name, int def); -extern int of_n_addr_cells(struct device_node *np); -extern int of_n_size_cells(struct device_node *np); extern void prom_build_devicetree(void); diff --git a/trunk/include/asm-sparc64/sbus.h b/trunk/include/asm-sparc64/sbus.h index 7efd49d31bb8..56ee985e4605 100644 --- a/trunk/include/asm-sparc64/sbus.h +++ b/trunk/include/asm-sparc64/sbus.h @@ -80,6 +80,7 @@ struct sbus_bus { int num_sbus_ranges; int portid; + void *starfire_cookie; }; #define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) diff --git a/trunk/include/asm-sparc64/signal.h b/trunk/include/asm-sparc64/signal.h index 9968871103bc..fdc42a14d4e6 100644 --- a/trunk/include/asm-sparc64/signal.h +++ b/trunk/include/asm-sparc64/signal.h @@ -133,13 +133,16 @@ struct sigstack { * usage of signal stacks by using the (now obsolete) sa_restorer field in * the sigaction structure as a stack pointer. This is now possible due to * the changes in signal handling. LBT 010493. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_SHIRQ flag is for shared interrupt support on PCI and EISA. */ #define SA_NOCLDSTOP _SV_IGNCHILD #define SA_STACK _SV_SSTACK #define SA_ONSTACK _SV_SSTACK #define SA_RESTART _SV_INTR #define SA_ONESHOT _SV_RESET +#define SA_INTERRUPT 0x10u #define SA_NOMASK 0x20u #define SA_NOCLDWAIT 0x100u #define SA_SIGINFO 0x200u diff --git a/trunk/include/asm-sparc64/socket.h b/trunk/include/asm-sparc64/socket.h index 754d46a50af3..59987dad3359 100644 --- a/trunk/include/asm-sparc64/socket.h +++ b/trunk/include/asm-sparc64/socket.h @@ -48,7 +48,6 @@ #define SCM_TIMESTAMP SO_TIMESTAMP #define SO_PEERSEC 0x001e -#define SO_PASSSEC 0x001f /* Security levels - as per NRL IPv6 - don't actually do anything */ #define SO_SECURITY_AUTHENTICATION 0x5001 diff --git a/trunk/include/asm-sparc64/starfire.h b/trunk/include/asm-sparc64/starfire.h index 48b50b5e35b0..b606cb2b32a8 100644 --- a/trunk/include/asm-sparc64/starfire.h +++ b/trunk/include/asm-sparc64/starfire.h @@ -14,7 +14,7 @@ extern int this_is_starfire; extern void check_if_starfire(void); extern void starfire_cpu_setup(void); extern int starfire_hard_smp_processor_id(void); -extern void starfire_hookup(int); +extern void *starfire_hookup(int); extern unsigned int starfire_translate(unsigned long imap, unsigned int upaid); #endif diff --git a/trunk/include/asm-sparc64/topology.h b/trunk/include/asm-sparc64/topology.h index 98a6c613589d..0e234e201bd6 100644 --- a/trunk/include/asm-sparc64/topology.h +++ b/trunk/include/asm-sparc64/topology.h @@ -1,9 +1,6 @@ #ifndef _ASM_SPARC64_TOPOLOGY_H #define _ASM_SPARC64_TOPOLOGY_H -#include -#define smt_capable() (tlb_type == hypervisor) - #include #endif /* _ASM_SPARC64_TOPOLOGY_H */ diff --git a/trunk/include/asm-sparc64/vdev.h b/trunk/include/asm-sparc64/vdev.h new file mode 100644 index 000000000000..25637c57675d --- /dev/null +++ b/trunk/include/asm-sparc64/vdev.h @@ -0,0 +1,17 @@ +/* vdev.h: SUN4V virtual device interfaces and defines. + * + * Copyright (C) 2006 David S. Miller + */ + +#ifndef _SPARC64_VDEV_H +#define _SPARC64_VDEV_H + +#include +#include + +extern u32 sun4v_vdev_devhandle; +extern struct device_node *sun4v_vdev_root; + +extern unsigned int sun4v_vdev_device_interrupt(struct device_node *dev_node); + +#endif /* !(_SPARC64_VDEV_H) */ diff --git a/trunk/include/asm-um/hw_irq.h b/trunk/include/asm-um/hw_irq.h index 1cf84cf5f21a..4ee38c0b6a64 100644 --- a/trunk/include/asm-um/hw_irq.h +++ b/trunk/include/asm-um/hw_irq.h @@ -4,4 +4,7 @@ #include "asm/irq.h" #include "asm/archparam.h" +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) +{} + #endif diff --git a/trunk/include/asm-um/io.h b/trunk/include/asm-um/io.h index 44e8b8c772ae..1934d9340e2c 100644 --- a/trunk/include/asm-um/io.h +++ b/trunk/include/asm-um/io.h @@ -45,13 +45,8 @@ static inline void writel(unsigned int b, volatile void __iomem *addr) { *(volatile unsigned int __force *) addr = b; } -static inline void writeq(unsigned int b, volatile void __iomem *addr) -{ - *(volatile unsigned long long __force *) addr = b; -} #define __raw_writeb writeb #define __raw_writew writew #define __raw_writel writel -#define __raw_writeq writeq #endif diff --git a/trunk/include/asm-um/kmap_types.h b/trunk/include/asm-um/kmap_types.h index 6c03acdb4405..0b22ad776e76 100644 --- a/trunk/include/asm-um/kmap_types.h +++ b/trunk/include/asm-um/kmap_types.h @@ -6,24 +6,6 @@ #ifndef __UM_KMAP_TYPES_H #define __UM_KMAP_TYPES_H -/* No more #include "asm/arch/kmap_types.h" ! */ - -enum km_type { - KM_BOUNCE_READ, - KM_SKB_SUNRPC_DATA, - KM_SKB_DATA_SOFTIRQ, - KM_USER0, - KM_USER1, - KM_UML_USERCOPY, /* UML specific, for copy_*_user - used in do_op_one_page */ - KM_BIO_SRC_IRQ, - KM_BIO_DST_IRQ, - KM_PTE0, - KM_PTE1, - KM_IRQ0, - KM_IRQ1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, - KM_TYPE_NR -}; +#include "asm/arch/kmap_types.h" #endif diff --git a/trunk/include/asm-v850/hw_irq.h b/trunk/include/asm-v850/hw_irq.h index 043e94bb6bd8..a8aab4342712 100644 --- a/trunk/include/asm-v850/hw_irq.h +++ b/trunk/include/asm-v850/hw_irq.h @@ -1,4 +1,8 @@ #ifndef __V850_HW_IRQ_H__ #define __V850_HW_IRQ_H__ +static inline void hw_resend_irq (struct hw_interrupt_type *h, unsigned int i) +{ +} + #endif /* __V850_HW_IRQ_H__ */ diff --git a/trunk/include/asm-v850/signal.h b/trunk/include/asm-v850/signal.h index a38df0834bbf..cb52caa69925 100644 --- a/trunk/include/asm-v850/signal.h +++ b/trunk/include/asm-v850/signal.h @@ -77,6 +77,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -96,6 +97,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 diff --git a/trunk/include/asm-v850/socket.h b/trunk/include/asm-v850/socket.h index 0dfe55ac2ef2..0240d366a0a4 100644 --- a/trunk/include/asm-v850/socket.h +++ b/trunk/include/asm-v850/socket.h @@ -48,6 +48,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* __V850_SOCKET_H__ */ diff --git a/trunk/include/asm-x86_64/alternative.h b/trunk/include/asm-x86_64/alternative.h deleted file mode 100644 index aa67bfd1b3ce..000000000000 --- a/trunk/include/asm-x86_64/alternative.h +++ /dev/null @@ -1,155 +0,0 @@ -#ifndef _X86_64_ALTERNATIVE_H -#define _X86_64_ALTERNATIVE_H - -#ifdef __KERNEL__ - -#include - -struct alt_instr { - u8 *instr; /* original instruction */ - u8 *replacement; - u8 cpuid; /* cpuid bit set for replacement */ - u8 instrlen; /* length of original instruction */ - u8 replacementlen; /* length of new instruction, <= instrlen */ - u8 pad[5]; -}; - -extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); - -struct module; - -#ifdef CONFIG_SMP -extern void alternatives_smp_module_add(struct module *mod, char *name, - void *locks, void *locks_end, - void *text, void *text_end); -extern void alternatives_smp_module_del(struct module *mod); -extern void alternatives_smp_switch(int smp); -#else -static inline void alternatives_smp_module_add(struct module *mod, char *name, - void *locks, void *locks_end, - void *text, void *text_end) {} -static inline void alternatives_smp_module_del(struct module *mod) {} -static inline void alternatives_smp_switch(int smp) {} -#endif - -#endif - -/* - * Alternative instructions for different CPU types or capabilities. - * - * This allows to use optimized instructions even on generic binary - * kernels. - * - * length of oldinstr must be longer or equal the length of newinstr - * It can be padded with nops as needed. - * - * For non barrier like inlines please define new variants - * without volatile and memory clobber. - */ -#define alternative(oldinstr, newinstr, feature) \ - asm volatile ("661:\n\t" oldinstr "\n662:\n" \ - ".section .altinstructions,\"a\"\n" \ - " .align 8\n" \ - " .quad 661b\n" /* label */ \ - " .quad 663f\n" /* new instruction */ \ - " .byte %c0\n" /* feature bit */ \ - " .byte 662b-661b\n" /* sourcelen */ \ - " .byte 664f-663f\n" /* replacementlen */ \ - ".previous\n" \ - ".section .altinstr_replacement,\"ax\"\n" \ - "663:\n\t" newinstr "\n664:\n" /* replacement */ \ - ".previous" :: "i" (feature) : "memory") - -/* - * Alternative inline assembly with input. - * - * Pecularities: - * No memory clobber here. - * Argument numbers start with 1. - * Best is to use constraints that are fixed size (like (%1) ... "r") - * If you use variable sized constraints like "m" or "g" in the - * replacement make sure to pad to the worst case length. - */ -#define alternative_input(oldinstr, newinstr, feature, input...) \ - asm volatile ("661:\n\t" oldinstr "\n662:\n" \ - ".section .altinstructions,\"a\"\n" \ - " .align 8\n" \ - " .quad 661b\n" /* label */ \ - " .quad 663f\n" /* new instruction */ \ - " .byte %c0\n" /* feature bit */ \ - " .byte 662b-661b\n" /* sourcelen */ \ - " .byte 664f-663f\n" /* replacementlen */ \ - ".previous\n" \ - ".section .altinstr_replacement,\"ax\"\n" \ - "663:\n\t" newinstr "\n664:\n" /* replacement */ \ - ".previous" :: "i" (feature), ##input) - -/* Like alternative_input, but with a single output argument */ -#define alternative_io(oldinstr, newinstr, feature, output, input...) \ - asm volatile ("661:\n\t" oldinstr "\n662:\n" \ - ".section .altinstructions,\"a\"\n" \ - " .align 8\n" \ - " .quad 661b\n" /* label */ \ - " .quad 663f\n" /* new instruction */ \ - " .byte %c[feat]\n" /* feature bit */ \ - " .byte 662b-661b\n" /* sourcelen */ \ - " .byte 664f-663f\n" /* replacementlen */ \ - ".previous\n" \ - ".section .altinstr_replacement,\"ax\"\n" \ - "663:\n\t" newinstr "\n664:\n" /* replacement */ \ - ".previous" : output : [feat] "i" (feature), ##input) - -/* - * Alternative inline assembly for SMP. - * - * alternative_smp() takes two versions (SMP first, UP second) and is - * for more complex stuff such as spinlocks. - * - * The LOCK_PREFIX macro defined here replaces the LOCK and - * LOCK_PREFIX macros used everywhere in the source tree. - * - * SMP alternatives use the same data structures as the other - * alternatives and the X86_FEATURE_UP flag to indicate the case of a - * UP system running a SMP kernel. The existing apply_alternatives() - * works fine for patching a SMP kernel for UP. - * - * The SMP alternative tables can be kept after boot and contain both - * UP and SMP versions of the instructions to allow switching back to - * SMP at runtime, when hotplugging in a new CPU, which is especially - * useful in virtualized environments. - * - * The very common lock prefix is handled as special case in a - * separate table which is a pure address list without replacement ptr - * and size information. That keeps the table sizes small. - */ - -#ifdef CONFIG_SMP -#define alternative_smp(smpinstr, upinstr, args...) \ - asm volatile ("661:\n\t" smpinstr "\n662:\n" \ - ".section .smp_altinstructions,\"a\"\n" \ - " .align 8\n" \ - " .quad 661b\n" /* label */ \ - " .quad 663f\n" /* new instruction */ \ - " .byte 0x66\n" /* X86_FEATURE_UP */ \ - " .byte 662b-661b\n" /* sourcelen */ \ - " .byte 664f-663f\n" /* replacementlen */ \ - ".previous\n" \ - ".section .smp_altinstr_replacement,\"awx\"\n" \ - "663:\n\t" upinstr "\n" /* replacement */ \ - "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \ - ".previous" : args) - -#define LOCK_PREFIX \ - ".section .smp_locks,\"a\"\n" \ - " .align 8\n" \ - " .quad 661f\n" /* address */ \ - ".previous\n" \ - "661:\n\tlock; " - -#else /* ! CONFIG_SMP */ -#define alternative_smp(smpinstr, upinstr, args...) \ - asm volatile (upinstr : args) -#define LOCK_PREFIX "" -#endif - -#endif /* _X86_64_ALTERNATIVE_H */ diff --git a/trunk/include/asm-x86_64/apic.h b/trunk/include/asm-x86_64/apic.h index 9c96a0a8d1bd..a731be2204d2 100644 --- a/trunk/include/asm-x86_64/apic.h +++ b/trunk/include/asm-x86_64/apic.h @@ -49,8 +49,7 @@ static __inline unsigned int apic_read(unsigned long reg) static __inline__ void apic_wait_icr_idle(void) { - while (apic_read( APIC_ICR ) & APIC_ICR_BUSY) - cpu_relax(); + while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY ); } static inline void ack_APIC_irq(void) @@ -80,23 +79,30 @@ extern void init_apic_mappings (void); extern void smp_local_timer_interrupt (struct pt_regs * regs); extern void setup_boot_APIC_clock (void); extern void setup_secondary_APIC_clock (void); +extern void setup_apic_nmi_watchdog (void); +extern int reserve_lapic_nmi(void); +extern void release_lapic_nmi(void); +extern void disable_timer_nmi_watchdog(void); +extern void enable_timer_nmi_watchdog(void); +extern void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason); extern int APIC_init_uniprocessor (void); extern void disable_APIC_timer(void); extern void enable_APIC_timer(void); extern void clustered_apic_check(void); -extern void setup_APIC_extened_lvt(unsigned char lvt_off, unsigned char vector, - unsigned char msg_type, unsigned char mask); +extern void nmi_watchdog_default(void); +extern int setup_nmi_watchdog(char *); -#define K8_APIC_EXT_LVT_BASE 0x500 -#define K8_APIC_EXT_INT_MSG_FIX 0x0 -#define K8_APIC_EXT_INT_MSG_SMI 0x2 -#define K8_APIC_EXT_INT_MSG_NMI 0x4 -#define K8_APIC_EXT_INT_MSG_EXT 0x7 -#define K8_APIC_EXT_LVT_ENTRY_THRESHOLD 0 +extern unsigned int nmi_watchdog; +#define NMI_DEFAULT -1 +#define NMI_NONE 0 +#define NMI_IO_APIC 1 +#define NMI_LOCAL_APIC 2 +#define NMI_INVALID 3 extern int disable_timer_pin_1; +extern void setup_threshold_lvt(unsigned long lvt_off); void smp_send_timer_broadcast_ipi(void); void switch_APIC_timer_to_ipi(void *cpumask); diff --git a/trunk/include/asm-x86_64/atomic.h b/trunk/include/asm-x86_64/atomic.h index 007e88d6d43f..bd3fa67ed835 100644 --- a/trunk/include/asm-x86_64/atomic.h +++ b/trunk/include/asm-x86_64/atomic.h @@ -1,7 +1,7 @@ #ifndef __ARCH_X86_64_ATOMIC__ #define __ARCH_X86_64_ATOMIC__ -#include +#include /* atomic_t should be 32 bit signed type */ @@ -52,7 +52,7 @@ typedef struct { volatile int counter; } atomic_t; static __inline__ void atomic_add(int i, atomic_t *v) { __asm__ __volatile__( - LOCK_PREFIX "addl %1,%0" + LOCK "addl %1,%0" :"=m" (v->counter) :"ir" (i), "m" (v->counter)); } @@ -67,7 +67,7 @@ static __inline__ void atomic_add(int i, atomic_t *v) static __inline__ void atomic_sub(int i, atomic_t *v) { __asm__ __volatile__( - LOCK_PREFIX "subl %1,%0" + LOCK "subl %1,%0" :"=m" (v->counter) :"ir" (i), "m" (v->counter)); } @@ -86,7 +86,7 @@ static __inline__ int atomic_sub_and_test(int i, atomic_t *v) unsigned char c; __asm__ __volatile__( - LOCK_PREFIX "subl %2,%0; sete %1" + LOCK "subl %2,%0; sete %1" :"=m" (v->counter), "=qm" (c) :"ir" (i), "m" (v->counter) : "memory"); return c; @@ -101,7 +101,7 @@ static __inline__ int atomic_sub_and_test(int i, atomic_t *v) static __inline__ void atomic_inc(atomic_t *v) { __asm__ __volatile__( - LOCK_PREFIX "incl %0" + LOCK "incl %0" :"=m" (v->counter) :"m" (v->counter)); } @@ -115,7 +115,7 @@ static __inline__ void atomic_inc(atomic_t *v) static __inline__ void atomic_dec(atomic_t *v) { __asm__ __volatile__( - LOCK_PREFIX "decl %0" + LOCK "decl %0" :"=m" (v->counter) :"m" (v->counter)); } @@ -133,7 +133,7 @@ static __inline__ int atomic_dec_and_test(atomic_t *v) unsigned char c; __asm__ __volatile__( - LOCK_PREFIX "decl %0; sete %1" + LOCK "decl %0; sete %1" :"=m" (v->counter), "=qm" (c) :"m" (v->counter) : "memory"); return c != 0; @@ -152,7 +152,7 @@ static __inline__ int atomic_inc_and_test(atomic_t *v) unsigned char c; __asm__ __volatile__( - LOCK_PREFIX "incl %0; sete %1" + LOCK "incl %0; sete %1" :"=m" (v->counter), "=qm" (c) :"m" (v->counter) : "memory"); return c != 0; @@ -172,7 +172,7 @@ static __inline__ int atomic_add_negative(int i, atomic_t *v) unsigned char c; __asm__ __volatile__( - LOCK_PREFIX "addl %2,%0; sets %1" + LOCK "addl %2,%0; sets %1" :"=m" (v->counter), "=qm" (c) :"ir" (i), "m" (v->counter) : "memory"); return c; @@ -189,7 +189,7 @@ static __inline__ int atomic_add_return(int i, atomic_t *v) { int __i = i; __asm__ __volatile__( - LOCK_PREFIX "xaddl %0, %1;" + LOCK "xaddl %0, %1;" :"=r"(i) :"m"(v->counter), "0"(i)); return i + __i; @@ -237,7 +237,7 @@ typedef struct { volatile long counter; } atomic64_t; static __inline__ void atomic64_add(long i, atomic64_t *v) { __asm__ __volatile__( - LOCK_PREFIX "addq %1,%0" + LOCK "addq %1,%0" :"=m" (v->counter) :"ir" (i), "m" (v->counter)); } @@ -252,7 +252,7 @@ static __inline__ void atomic64_add(long i, atomic64_t *v) static __inline__ void atomic64_sub(long i, atomic64_t *v) { __asm__ __volatile__( - LOCK_PREFIX "subq %1,%0" + LOCK "subq %1,%0" :"=m" (v->counter) :"ir" (i), "m" (v->counter)); } @@ -271,7 +271,7 @@ static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v) unsigned char c; __asm__ __volatile__( - LOCK_PREFIX "subq %2,%0; sete %1" + LOCK "subq %2,%0; sete %1" :"=m" (v->counter), "=qm" (c) :"ir" (i), "m" (v->counter) : "memory"); return c; @@ -286,7 +286,7 @@ static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v) static __inline__ void atomic64_inc(atomic64_t *v) { __asm__ __volatile__( - LOCK_PREFIX "incq %0" + LOCK "incq %0" :"=m" (v->counter) :"m" (v->counter)); } @@ -300,7 +300,7 @@ static __inline__ void atomic64_inc(atomic64_t *v) static __inline__ void atomic64_dec(atomic64_t *v) { __asm__ __volatile__( - LOCK_PREFIX "decq %0" + LOCK "decq %0" :"=m" (v->counter) :"m" (v->counter)); } @@ -318,7 +318,7 @@ static __inline__ int atomic64_dec_and_test(atomic64_t *v) unsigned char c; __asm__ __volatile__( - LOCK_PREFIX "decq %0; sete %1" + LOCK "decq %0; sete %1" :"=m" (v->counter), "=qm" (c) :"m" (v->counter) : "memory"); return c != 0; @@ -337,7 +337,7 @@ static __inline__ int atomic64_inc_and_test(atomic64_t *v) unsigned char c; __asm__ __volatile__( - LOCK_PREFIX "incq %0; sete %1" + LOCK "incq %0; sete %1" :"=m" (v->counter), "=qm" (c) :"m" (v->counter) : "memory"); return c != 0; @@ -357,7 +357,7 @@ static __inline__ int atomic64_add_negative(long i, atomic64_t *v) unsigned char c; __asm__ __volatile__( - LOCK_PREFIX "addq %2,%0; sets %1" + LOCK "addq %2,%0; sets %1" :"=m" (v->counter), "=qm" (c) :"ir" (i), "m" (v->counter) : "memory"); return c; @@ -374,7 +374,7 @@ static __inline__ long atomic64_add_return(long i, atomic64_t *v) { long __i = i; __asm__ __volatile__( - LOCK_PREFIX "xaddq %0, %1;" + LOCK "xaddq %0, %1;" :"=r"(i) :"m"(v->counter), "0"(i)); return i + __i; @@ -418,11 +418,11 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t *v) /* These are x86-specific, used by some header files */ #define atomic_clear_mask(mask, addr) \ -__asm__ __volatile__(LOCK_PREFIX "andl %0,%1" \ +__asm__ __volatile__(LOCK "andl %0,%1" \ : : "r" (~(mask)),"m" (*addr) : "memory") #define atomic_set_mask(mask, addr) \ -__asm__ __volatile__(LOCK_PREFIX "orl %0,%1" \ +__asm__ __volatile__(LOCK "orl %0,%1" \ : : "r" ((unsigned)mask),"m" (*(addr)) : "memory") /* Atomic operations are already serializing on x86 */ diff --git a/trunk/include/asm-x86_64/bitops.h b/trunk/include/asm-x86_64/bitops.h index f7ba57b1cc08..e9bf933d25d0 100644 --- a/trunk/include/asm-x86_64/bitops.h +++ b/trunk/include/asm-x86_64/bitops.h @@ -5,7 +5,12 @@ * Copyright 1992, Linus Torvalds. */ -#include + +#ifdef CONFIG_SMP +#define LOCK_PREFIX "lock ; " +#else +#define LOCK_PREFIX "" +#endif #define ADDR (*(volatile long *) addr) diff --git a/trunk/include/asm-x86_64/calgary.h b/trunk/include/asm-x86_64/calgary.h deleted file mode 100644 index 6e1654f30986..000000000000 --- a/trunk/include/asm-x86_64/calgary.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Derived from include/asm-powerpc/iommu.h - * - * Copyright (C) 2006 Jon Mason , IBM Corporation - * Copyright (C) 2006 Muli Ben-Yehuda , IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _ASM_X86_64_CALGARY_H -#define _ASM_X86_64_CALGARY_H - -#include -#include -#include -#include -#include - -struct iommu_table { - unsigned long it_base; /* mapped address of tce table */ - unsigned long it_hint; /* Hint for next alloc */ - unsigned long *it_map; /* A simple allocation bitmap for now */ - spinlock_t it_lock; /* Protects it_map */ - unsigned int it_size; /* Size of iommu table in entries */ - unsigned char it_busno; /* Bus number this table belongs to */ - void __iomem *bbar; - u64 tar_val; - struct timer_list watchdog_timer; -}; - -#define TCE_TABLE_SIZE_UNSPECIFIED ~0 -#define TCE_TABLE_SIZE_64K 0 -#define TCE_TABLE_SIZE_128K 1 -#define TCE_TABLE_SIZE_256K 2 -#define TCE_TABLE_SIZE_512K 3 -#define TCE_TABLE_SIZE_1M 4 -#define TCE_TABLE_SIZE_2M 5 -#define TCE_TABLE_SIZE_4M 6 -#define TCE_TABLE_SIZE_8M 7 - -#ifdef CONFIG_CALGARY_IOMMU -extern int calgary_iommu_init(void); -extern void detect_calgary(void); -#else -static inline int calgary_iommu_init(void) { return 1; } -static inline void detect_calgary(void) { return; } -#endif - -static inline unsigned int bus_to_phb(unsigned char busno) -{ - return ((busno % 15 == 0) ? 0 : busno / 2 + 1); -} - -#endif /* _ASM_X86_64_CALGARY_H */ diff --git a/trunk/include/asm-x86_64/cpufeature.h b/trunk/include/asm-x86_64/cpufeature.h index ee792faaca01..662964b74e34 100644 --- a/trunk/include/asm-x86_64/cpufeature.h +++ b/trunk/include/asm-x86_64/cpufeature.h @@ -46,7 +46,6 @@ #define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */ #define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ #define X86_FEATURE_FXSR_OPT (1*32+25) /* FXSR optimizations */ -#define X86_FEATURE_RDTSCP (1*32+27) /* RDTSCP */ #define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ #define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ #define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */ @@ -66,8 +65,6 @@ #define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */ #define X86_FEATURE_SYNC_RDTSC (3*32+6) /* RDTSC syncs CPU core */ #define X86_FEATURE_FXSAVE_LEAK (3*32+7) /* FIP/FOP/FDP leaks through FXSAVE */ -#define X86_FEATURE_UP (3*32+8) /* SMP kernel running on UP */ -#define X86_FEATURE_ARCH_PERFMON (3*32+9) /* Intel Architectural PerfMon */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ diff --git a/trunk/include/asm-x86_64/dma-mapping.h b/trunk/include/asm-x86_64/dma-mapping.h index b6da83dcc7a6..498f66df36b9 100644 --- a/trunk/include/asm-x86_64/dma-mapping.h +++ b/trunk/include/asm-x86_64/dma-mapping.h @@ -55,13 +55,6 @@ extern dma_addr_t bad_dma_address; extern struct dma_mapping_ops* dma_ops; extern int iommu_merge; -static inline int valid_dma_direction(int dma_direction) -{ - return ((dma_direction == DMA_BIDIRECTIONAL) || - (dma_direction == DMA_TO_DEVICE) || - (dma_direction == DMA_FROM_DEVICE)); -} - static inline int dma_mapping_error(dma_addr_t dma_addr) { if (dma_ops->mapping_error) @@ -79,7 +72,6 @@ static inline dma_addr_t dma_map_single(struct device *hwdev, void *ptr, size_t size, int direction) { - BUG_ON(!valid_dma_direction(direction)); return dma_ops->map_single(hwdev, ptr, size, direction); } @@ -87,7 +79,6 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size, int direction) { - BUG_ON(!valid_dma_direction(direction)); dma_ops->unmap_single(dev, addr, size, direction); } @@ -100,7 +91,6 @@ static inline void dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle, size_t size, int direction) { - BUG_ON(!valid_dma_direction(direction)); if (dma_ops->sync_single_for_cpu) dma_ops->sync_single_for_cpu(hwdev, dma_handle, size, direction); @@ -111,7 +101,6 @@ static inline void dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle, size_t size, int direction) { - BUG_ON(!valid_dma_direction(direction)); if (dma_ops->sync_single_for_device) dma_ops->sync_single_for_device(hwdev, dma_handle, size, direction); @@ -122,7 +111,6 @@ static inline void dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle, unsigned long offset, size_t size, int direction) { - BUG_ON(!valid_dma_direction(direction)); if (dma_ops->sync_single_range_for_cpu) { dma_ops->sync_single_range_for_cpu(hwdev, dma_handle, offset, size, direction); } @@ -134,7 +122,6 @@ static inline void dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle, unsigned long offset, size_t size, int direction) { - BUG_ON(!valid_dma_direction(direction)); if (dma_ops->sync_single_range_for_device) dma_ops->sync_single_range_for_device(hwdev, dma_handle, offset, size, direction); @@ -146,7 +133,6 @@ static inline void dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg, int nelems, int direction) { - BUG_ON(!valid_dma_direction(direction)); if (dma_ops->sync_sg_for_cpu) dma_ops->sync_sg_for_cpu(hwdev, sg, nelems, direction); flush_write_buffers(); @@ -156,7 +142,6 @@ static inline void dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg, int nelems, int direction) { - BUG_ON(!valid_dma_direction(direction)); if (dma_ops->sync_sg_for_device) { dma_ops->sync_sg_for_device(hwdev, sg, nelems, direction); } @@ -167,7 +152,6 @@ dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg, static inline int dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, int direction) { - BUG_ON(!valid_dma_direction(direction)); return dma_ops->map_sg(hwdev, sg, nents, direction); } @@ -175,7 +159,6 @@ static inline void dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, int direction) { - BUG_ON(!valid_dma_direction(direction)); dma_ops->unmap_sg(hwdev, sg, nents, direction); } diff --git a/trunk/include/asm-x86_64/dma.h b/trunk/include/asm-x86_64/dma.h index a37c16f06289..c556208d3dd7 100644 --- a/trunk/include/asm-x86_64/dma.h +++ b/trunk/include/asm-x86_64/dma.h @@ -1,4 +1,4 @@ -/* +/* $Id: dma.h,v 1.1.1.1 2001/04/19 20:00:38 ak Exp $ * linux/include/asm/dma.h: Defines for using and allocating dma channels. * Written by Hennus Bergman, 1992. * High DMA channel support & info by Hannu Savolainen diff --git a/trunk/include/asm-x86_64/floppy.h b/trunk/include/asm-x86_64/floppy.h index 32ff5d132714..006291e89b4a 100644 --- a/trunk/include/asm-x86_64/floppy.h +++ b/trunk/include/asm-x86_64/floppy.h @@ -144,11 +144,11 @@ static int vdma_get_dma_residue(unsigned int dummy) static int fd_request_irq(void) { if(can_use_virtual_dma) - return request_irq(FLOPPY_IRQ, floppy_hardint, - IRQF_DISABLED, "floppy", NULL); + return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT, + "floppy", NULL); else - return request_irq(FLOPPY_IRQ, floppy_interrupt, - IRQF_DISABLED, "floppy", NULL); + return request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT, + "floppy", NULL); } static unsigned long dma_mem_alloc(unsigned long size) diff --git a/trunk/include/asm-x86_64/gart-mapping.h b/trunk/include/asm-x86_64/gart-mapping.h new file mode 100644 index 000000000000..ada497b0b55b --- /dev/null +++ b/trunk/include/asm-x86_64/gart-mapping.h @@ -0,0 +1,16 @@ +#ifndef _X8664_GART_MAPPING_H +#define _X8664_GART_MAPPING_H 1 + +#include +#include + +struct device; + +extern void* +gart_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp); + +extern int +gart_dma_supported(struct device *hwdev, u64 mask); + +#endif /* _X8664_GART_MAPPING_H */ diff --git a/trunk/include/asm-x86_64/hpet.h b/trunk/include/asm-x86_64/hpet.h index b39098408b69..18ff7ee9e774 100644 --- a/trunk/include/asm-x86_64/hpet.h +++ b/trunk/include/asm-x86_64/hpet.h @@ -55,7 +55,7 @@ extern int is_hpet_enabled(void); extern int hpet_rtc_timer_init(void); -extern int apic_is_clustered_box(void); +extern int oem_force_hpet_timer(void); extern int hpet_use_timer; diff --git a/trunk/include/asm-x86_64/hw_irq.h b/trunk/include/asm-x86_64/hw_irq.h index 48a4a5364e85..3de96fd86a70 100644 --- a/trunk/include/asm-x86_64/hw_irq.h +++ b/trunk/include/asm-x86_64/hw_irq.h @@ -12,6 +12,8 @@ * * * hacked by Andi Kleen for x86-64. + * + * $Id: hw_irq.h,v 1.24 2001/09/14 20:55:03 vojtech Exp $ */ #ifndef __ASSEMBLY__ @@ -124,9 +126,18 @@ asmlinkage void IRQ_NAME(nr); \ __asm__( \ "\n.p2align\n" \ "IRQ" #nr "_interrupt:\n\t" \ - "push $~(" #nr ") ; " \ + "push $" #nr "-256 ; " \ "jmp common_interrupt"); +#if defined(CONFIG_X86_IO_APIC) +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { + if (IO_APIC_IRQ(i)) + send_IPI_self(IO_APIC_VECTOR(i)); +} +#else +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} +#endif + #define platform_legacy_irq(irq) ((irq) < 16) #endif diff --git a/trunk/include/asm-x86_64/ia32_unistd.h b/trunk/include/asm-x86_64/ia32_unistd.h index 5b52ce507338..b4f4b172b15a 100644 --- a/trunk/include/asm-x86_64/ia32_unistd.h +++ b/trunk/include/asm-x86_64/ia32_unistd.h @@ -4,15 +4,317 @@ /* * This file contains the system call numbers of the ia32 port, * this is for the kernel only. - * Only add syscalls here where some part of the kernel needs to know - * the number. This should be otherwise in sync with asm-i386/unistd.h. -AK */ #define __NR_ia32_restart_syscall 0 #define __NR_ia32_exit 1 +#define __NR_ia32_fork 2 #define __NR_ia32_read 3 #define __NR_ia32_write 4 -#define __NR_ia32_sigreturn 119 +#define __NR_ia32_open 5 +#define __NR_ia32_close 6 +#define __NR_ia32_waitpid 7 +#define __NR_ia32_creat 8 +#define __NR_ia32_link 9 +#define __NR_ia32_unlink 10 +#define __NR_ia32_execve 11 +#define __NR_ia32_chdir 12 +#define __NR_ia32_time 13 +#define __NR_ia32_mknod 14 +#define __NR_ia32_chmod 15 +#define __NR_ia32_lchown 16 +#define __NR_ia32_break 17 +#define __NR_ia32_oldstat 18 +#define __NR_ia32_lseek 19 +#define __NR_ia32_getpid 20 +#define __NR_ia32_mount 21 +#define __NR_ia32_umount 22 +#define __NR_ia32_setuid 23 +#define __NR_ia32_getuid 24 +#define __NR_ia32_stime 25 +#define __NR_ia32_ptrace 26 +#define __NR_ia32_alarm 27 +#define __NR_ia32_oldfstat 28 +#define __NR_ia32_pause 29 +#define __NR_ia32_utime 30 +#define __NR_ia32_stty 31 +#define __NR_ia32_gtty 32 +#define __NR_ia32_access 33 +#define __NR_ia32_nice 34 +#define __NR_ia32_ftime 35 +#define __NR_ia32_sync 36 +#define __NR_ia32_kill 37 +#define __NR_ia32_rename 38 +#define __NR_ia32_mkdir 39 +#define __NR_ia32_rmdir 40 +#define __NR_ia32_dup 41 +#define __NR_ia32_pipe 42 +#define __NR_ia32_times 43 +#define __NR_ia32_prof 44 +#define __NR_ia32_brk 45 +#define __NR_ia32_setgid 46 +#define __NR_ia32_getgid 47 +#define __NR_ia32_signal 48 +#define __NR_ia32_geteuid 49 +#define __NR_ia32_getegid 50 +#define __NR_ia32_acct 51 +#define __NR_ia32_umount2 52 +#define __NR_ia32_lock 53 +#define __NR_ia32_ioctl 54 +#define __NR_ia32_fcntl 55 +#define __NR_ia32_mpx 56 +#define __NR_ia32_setpgid 57 +#define __NR_ia32_ulimit 58 +#define __NR_ia32_oldolduname 59 +#define __NR_ia32_umask 60 +#define __NR_ia32_chroot 61 +#define __NR_ia32_ustat 62 +#define __NR_ia32_dup2 63 +#define __NR_ia32_getppid 64 +#define __NR_ia32_getpgrp 65 +#define __NR_ia32_setsid 66 +#define __NR_ia32_sigaction 67 +#define __NR_ia32_sgetmask 68 +#define __NR_ia32_ssetmask 69 +#define __NR_ia32_setreuid 70 +#define __NR_ia32_setregid 71 +#define __NR_ia32_sigsuspend 72 +#define __NR_ia32_sigpending 73 +#define __NR_ia32_sethostname 74 +#define __NR_ia32_setrlimit 75 +#define __NR_ia32_getrlimit 76 /* Back compatible 2Gig limited rlimit */ +#define __NR_ia32_getrusage 77 +#define __NR_ia32_gettimeofday 78 +#define __NR_ia32_settimeofday 79 +#define __NR_ia32_getgroups 80 +#define __NR_ia32_setgroups 81 +#define __NR_ia32_select 82 +#define __NR_ia32_symlink 83 +#define __NR_ia32_oldlstat 84 +#define __NR_ia32_readlink 85 +#define __NR_ia32_uselib 86 +#define __NR_ia32_swapon 87 +#define __NR_ia32_reboot 88 +#define __NR_ia32_readdir 89 +#define __NR_ia32_mmap 90 +#define __NR_ia32_munmap 91 +#define __NR_ia32_truncate 92 +#define __NR_ia32_ftruncate 93 +#define __NR_ia32_fchmod 94 +#define __NR_ia32_fchown 95 +#define __NR_ia32_getpriority 96 +#define __NR_ia32_setpriority 97 +#define __NR_ia32_profil 98 +#define __NR_ia32_statfs 99 +#define __NR_ia32_fstatfs 100 +#define __NR_ia32_ioperm 101 +#define __NR_ia32_socketcall 102 +#define __NR_ia32_syslog 103 +#define __NR_ia32_setitimer 104 +#define __NR_ia32_getitimer 105 +#define __NR_ia32_stat 106 +#define __NR_ia32_lstat 107 +#define __NR_ia32_fstat 108 +#define __NR_ia32_olduname 109 +#define __NR_ia32_iopl 110 +#define __NR_ia32_vhangup 111 +#define __NR_ia32_idle 112 +#define __NR_ia32_vm86old 113 +#define __NR_ia32_wait4 114 +#define __NR_ia32_swapoff 115 +#define __NR_ia32_sysinfo 116 +#define __NR_ia32_ipc 117 +#define __NR_ia32_fsync 118 +#define __NR_ia32_sigreturn 119 +#define __NR_ia32_clone 120 +#define __NR_ia32_setdomainname 121 +#define __NR_ia32_uname 122 +#define __NR_ia32_modify_ldt 123 +#define __NR_ia32_adjtimex 124 +#define __NR_ia32_mprotect 125 +#define __NR_ia32_sigprocmask 126 +#define __NR_ia32_create_module 127 +#define __NR_ia32_init_module 128 +#define __NR_ia32_delete_module 129 +#define __NR_ia32_get_kernel_syms 130 +#define __NR_ia32_quotactl 131 +#define __NR_ia32_getpgid 132 +#define __NR_ia32_fchdir 133 +#define __NR_ia32_bdflush 134 +#define __NR_ia32_sysfs 135 +#define __NR_ia32_personality 136 +#define __NR_ia32_afs_syscall 137 /* Syscall for Andrew File System */ +#define __NR_ia32_setfsuid 138 +#define __NR_ia32_setfsgid 139 +#define __NR_ia32__llseek 140 +#define __NR_ia32_getdents 141 +#define __NR_ia32__newselect 142 +#define __NR_ia32_flock 143 +#define __NR_ia32_msync 144 +#define __NR_ia32_readv 145 +#define __NR_ia32_writev 146 +#define __NR_ia32_getsid 147 +#define __NR_ia32_fdatasync 148 +#define __NR_ia32__sysctl 149 +#define __NR_ia32_mlock 150 +#define __NR_ia32_munlock 151 +#define __NR_ia32_mlockall 152 +#define __NR_ia32_munlockall 153 +#define __NR_ia32_sched_setparam 154 +#define __NR_ia32_sched_getparam 155 +#define __NR_ia32_sched_setscheduler 156 +#define __NR_ia32_sched_getscheduler 157 +#define __NR_ia32_sched_yield 158 +#define __NR_ia32_sched_get_priority_max 159 +#define __NR_ia32_sched_get_priority_min 160 +#define __NR_ia32_sched_rr_get_interval 161 +#define __NR_ia32_nanosleep 162 +#define __NR_ia32_mremap 163 +#define __NR_ia32_setresuid 164 +#define __NR_ia32_getresuid 165 +#define __NR_ia32_vm86 166 +#define __NR_ia32_query_module 167 +#define __NR_ia32_poll 168 +#define __NR_ia32_nfsservctl 169 +#define __NR_ia32_setresgid 170 +#define __NR_ia32_getresgid 171 +#define __NR_ia32_prctl 172 #define __NR_ia32_rt_sigreturn 173 +#define __NR_ia32_rt_sigaction 174 +#define __NR_ia32_rt_sigprocmask 175 +#define __NR_ia32_rt_sigpending 176 +#define __NR_ia32_rt_sigtimedwait 177 +#define __NR_ia32_rt_sigqueueinfo 178 +#define __NR_ia32_rt_sigsuspend 179 +#define __NR_ia32_pread 180 +#define __NR_ia32_pwrite 181 +#define __NR_ia32_chown 182 +#define __NR_ia32_getcwd 183 +#define __NR_ia32_capget 184 +#define __NR_ia32_capset 185 +#define __NR_ia32_sigaltstack 186 +#define __NR_ia32_sendfile 187 +#define __NR_ia32_getpmsg 188 /* some people actually want streams */ +#define __NR_ia32_putpmsg 189 /* some people actually want streams */ +#define __NR_ia32_vfork 190 +#define __NR_ia32_ugetrlimit 191 /* SuS compliant getrlimit */ +#define __NR_ia32_mmap2 192 +#define __NR_ia32_truncate64 193 +#define __NR_ia32_ftruncate64 194 +#define __NR_ia32_stat64 195 +#define __NR_ia32_lstat64 196 +#define __NR_ia32_fstat64 197 +#define __NR_ia32_lchown32 198 +#define __NR_ia32_getuid32 199 +#define __NR_ia32_getgid32 200 +#define __NR_ia32_geteuid32 201 +#define __NR_ia32_getegid32 202 +#define __NR_ia32_setreuid32 203 +#define __NR_ia32_setregid32 204 +#define __NR_ia32_getgroups32 205 +#define __NR_ia32_setgroups32 206 +#define __NR_ia32_fchown32 207 +#define __NR_ia32_setresuid32 208 +#define __NR_ia32_getresuid32 209 +#define __NR_ia32_setresgid32 210 +#define __NR_ia32_getresgid32 211 +#define __NR_ia32_chown32 212 +#define __NR_ia32_setuid32 213 +#define __NR_ia32_setgid32 214 +#define __NR_ia32_setfsuid32 215 +#define __NR_ia32_setfsgid32 216 +#define __NR_ia32_pivot_root 217 +#define __NR_ia32_mincore 218 +#define __NR_ia32_madvise 219 +#define __NR_ia32_madvise1 219 /* delete when C lib stub is removed */ +#define __NR_ia32_getdents64 220 +#define __NR_ia32_fcntl64 221 +#define __NR_ia32_tuxcall 222 +#define __NR_ia32_security 223 +#define __NR_ia32_gettid 224 +#define __NR_ia32_readahead 225 +#define __NR_ia32_setxattr 226 +#define __NR_ia32_lsetxattr 227 +#define __NR_ia32_fsetxattr 228 +#define __NR_ia32_getxattr 229 +#define __NR_ia32_lgetxattr 230 +#define __NR_ia32_fgetxattr 231 +#define __NR_ia32_listxattr 232 +#define __NR_ia32_llistxattr 233 +#define __NR_ia32_flistxattr 234 +#define __NR_ia32_removexattr 235 +#define __NR_ia32_lremovexattr 236 +#define __NR_ia32_fremovexattr 237 +#define __NR_ia32_tkill 238 +#define __NR_ia32_sendfile64 239 +#define __NR_ia32_futex 240 +#define __NR_ia32_sched_setaffinity 241 +#define __NR_ia32_sched_getaffinity 242 +#define __NR_ia32_set_thread_area 243 +#define __NR_ia32_get_thread_area 244 +#define __NR_ia32_io_setup 245 +#define __NR_ia32_io_destroy 246 +#define __NR_ia32_io_getevents 247 +#define __NR_ia32_io_submit 248 +#define __NR_ia32_io_cancel 249 +#define __NR_ia32_exit_group 252 +#define __NR_ia32_lookup_dcookie 253 +#define __NR_ia32_sys_epoll_create 254 +#define __NR_ia32_sys_epoll_ctl 255 +#define __NR_ia32_sys_epoll_wait 256 +#define __NR_ia32_remap_file_pages 257 +#define __NR_ia32_set_tid_address 258 +#define __NR_ia32_timer_create 259 +#define __NR_ia32_timer_settime (__NR_ia32_timer_create+1) +#define __NR_ia32_timer_gettime (__NR_ia32_timer_create+2) +#define __NR_ia32_timer_getoverrun (__NR_ia32_timer_create+3) +#define __NR_ia32_timer_delete (__NR_ia32_timer_create+4) +#define __NR_ia32_clock_settime (__NR_ia32_timer_create+5) +#define __NR_ia32_clock_gettime (__NR_ia32_timer_create+6) +#define __NR_ia32_clock_getres (__NR_ia32_timer_create+7) +#define __NR_ia32_clock_nanosleep (__NR_ia32_timer_create+8) +#define __NR_ia32_statfs64 268 +#define __NR_ia32_fstatfs64 269 +#define __NR_ia32_tgkill 270 +#define __NR_ia32_utimes 271 +#define __NR_ia32_fadvise64_64 272 +#define __NR_ia32_vserver 273 +#define __NR_ia32_mbind 274 +#define __NR_ia32_get_mempolicy 275 +#define __NR_ia32_set_mempolicy 276 +#define __NR_ia32_mq_open 277 +#define __NR_ia32_mq_unlink (__NR_ia32_mq_open+1) +#define __NR_ia32_mq_timedsend (__NR_ia32_mq_open+2) +#define __NR_ia32_mq_timedreceive (__NR_ia32_mq_open+3) +#define __NR_ia32_mq_notify (__NR_ia32_mq_open+4) +#define __NR_ia32_mq_getsetattr (__NR_ia32_mq_open+5) +#define __NR_ia32_kexec 283 +#define __NR_ia32_waitid 284 +/* #define __NR_sys_setaltroot 285 */ +#define __NR_ia32_add_key 286 +#define __NR_ia32_request_key 287 +#define __NR_ia32_keyctl 288 +#define __NR_ia32_ioprio_set 289 +#define __NR_ia32_ioprio_get 290 +#define __NR_ia32_inotify_init 291 +#define __NR_ia32_inotify_add_watch 292 +#define __NR_ia32_inotify_rm_watch 293 +#define __NR_ia32_migrate_pages 294 +#define __NR_ia32_openat 295 +#define __NR_ia32_mkdirat 296 +#define __NR_ia32_mknodat 297 +#define __NR_ia32_fchownat 298 +#define __NR_ia32_futimesat 299 +#define __NR_ia32_fstatat64 300 +#define __NR_ia32_unlinkat 301 +#define __NR_ia32_renameat 302 +#define __NR_ia32_linkat 303 +#define __NR_ia32_symlinkat 304 +#define __NR_ia32_readlinkat 305 +#define __NR_ia32_fchmodat 306 +#define __NR_ia32_faccessat 307 +#define __NR_ia32_pselect6 308 +#define __NR_ia32_ppoll 309 +#define __NR_ia32_unshare 310 #endif /* _ASM_X86_64_IA32_UNISTD_H_ */ diff --git a/trunk/include/asm-x86_64/intel_arch_perfmon.h b/trunk/include/asm-x86_64/intel_arch_perfmon.h deleted file mode 100644 index 59c396431569..000000000000 --- a/trunk/include/asm-x86_64/intel_arch_perfmon.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef X86_64_INTEL_ARCH_PERFMON_H -#define X86_64_INTEL_ARCH_PERFMON_H 1 - -#define MSR_ARCH_PERFMON_PERFCTR0 0xc1 -#define MSR_ARCH_PERFMON_PERFCTR1 0xc2 - -#define MSR_ARCH_PERFMON_EVENTSEL0 0x186 -#define MSR_ARCH_PERFMON_EVENTSEL1 0x187 - -#define ARCH_PERFMON_EVENTSEL0_ENABLE (1 << 22) -#define ARCH_PERFMON_EVENTSEL_INT (1 << 20) -#define ARCH_PERFMON_EVENTSEL_OS (1 << 17) -#define ARCH_PERFMON_EVENTSEL_USR (1 << 16) - -#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL (0x3c) -#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8) -#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT (1 << 0) - -#endif /* X86_64_INTEL_ARCH_PERFMON_H */ diff --git a/trunk/include/asm-x86_64/k8.h b/trunk/include/asm-x86_64/k8.h deleted file mode 100644 index 699dd6961eda..000000000000 --- a/trunk/include/asm-x86_64/k8.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _ASM_K8_H -#define _ASM_K8_H 1 - -#include - -extern struct pci_device_id k8_nb_ids[]; - -extern int early_is_k8_nb(u32 value); -extern struct pci_dev **k8_northbridges; -extern int num_k8_northbridges; -extern int cache_k8_northbridges(void); -extern void k8_flush_garts(void); - -#endif diff --git a/trunk/include/asm-x86_64/kdebug.h b/trunk/include/asm-x86_64/kdebug.h index cd52c7f33bca..cf795631d9b4 100644 --- a/trunk/include/asm-x86_64/kdebug.h +++ b/trunk/include/asm-x86_64/kdebug.h @@ -15,8 +15,6 @@ struct die_args { extern int register_die_notifier(struct notifier_block *); extern int unregister_die_notifier(struct notifier_block *); -extern int register_page_fault_notifier(struct notifier_block *); -extern int unregister_page_fault_notifier(struct notifier_block *); extern struct atomic_notifier_head die_chain; /* Grossly misnamed. */ diff --git a/trunk/include/asm-x86_64/kprobes.h b/trunk/include/asm-x86_64/kprobes.h index d36febd9bb18..98a1e95ddb98 100644 --- a/trunk/include/asm-x86_64/kprobes.h +++ b/trunk/include/asm-x86_64/kprobes.h @@ -43,7 +43,6 @@ typedef u8 kprobe_opcode_t; #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry #define ARCH_SUPPORTS_KRETPROBES -#define ARCH_INACTIVE_KPROBE_COUNT 1 void kretprobe_trampoline(void); extern void arch_remove_kprobe(struct kprobe *p); diff --git a/trunk/include/asm-x86_64/local.h b/trunk/include/asm-x86_64/local.h index e769e6200225..cd17945bf218 100644 --- a/trunk/include/asm-x86_64/local.h +++ b/trunk/include/asm-x86_64/local.h @@ -59,26 +59,12 @@ static inline void local_sub(long i, local_t *v) * This could be done better if we moved the per cpu data directly * after GS. */ - -/* Need to disable preemption for the cpu local counters otherwise we could - still access a variable of a previous CPU in a non atomic way. */ -#define cpu_local_wrap_v(v) \ - ({ local_t res__; \ - preempt_disable(); \ - res__ = (v); \ - preempt_enable(); \ - res__; }) -#define cpu_local_wrap(v) \ - ({ preempt_disable(); \ - v; \ - preempt_enable(); }) \ - -#define cpu_local_read(v) cpu_local_wrap_v(local_read(&__get_cpu_var(v))) -#define cpu_local_set(v, i) cpu_local_wrap(local_set(&__get_cpu_var(v), (i))) -#define cpu_local_inc(v) cpu_local_wrap(local_inc(&__get_cpu_var(v))) -#define cpu_local_dec(v) cpu_local_wrap(local_dec(&__get_cpu_var(v))) -#define cpu_local_add(i, v) cpu_local_wrap(local_add((i), &__get_cpu_var(v))) -#define cpu_local_sub(i, v) cpu_local_wrap(local_sub((i), &__get_cpu_var(v))) +#define cpu_local_read(v) local_read(&__get_cpu_var(v)) +#define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i)) +#define cpu_local_inc(v) local_inc(&__get_cpu_var(v)) +#define cpu_local_dec(v) local_dec(&__get_cpu_var(v)) +#define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v)) +#define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v)) #define __cpu_local_inc(v) cpu_local_inc(v) #define __cpu_local_dec(v) cpu_local_dec(v) diff --git a/trunk/include/asm-x86_64/mce.h b/trunk/include/asm-x86_64/mce.h index d13687dfd691..7229785094e3 100644 --- a/trunk/include/asm-x86_64/mce.h +++ b/trunk/include/asm-x86_64/mce.h @@ -67,22 +67,13 @@ struct mce_log { /* Software defined banks */ #define MCE_EXTENDED_BANK 128 #define MCE_THERMAL_BANK MCE_EXTENDED_BANK + 0 - -#define K8_MCE_THRESHOLD_BASE (MCE_EXTENDED_BANK + 1) /* MCE_AMD */ -#define K8_MCE_THRESHOLD_BANK_0 (MCE_THRESHOLD_BASE + 0 * 9) -#define K8_MCE_THRESHOLD_BANK_1 (MCE_THRESHOLD_BASE + 1 * 9) -#define K8_MCE_THRESHOLD_BANK_2 (MCE_THRESHOLD_BASE + 2 * 9) -#define K8_MCE_THRESHOLD_BANK_3 (MCE_THRESHOLD_BASE + 3 * 9) -#define K8_MCE_THRESHOLD_BANK_4 (MCE_THRESHOLD_BASE + 4 * 9) -#define K8_MCE_THRESHOLD_BANK_5 (MCE_THRESHOLD_BASE + 5 * 9) -#define K8_MCE_THRESHOLD_DRAM_ECC (MCE_THRESHOLD_BANK_4 + 0) +#define MCE_THRESHOLD_BASE MCE_EXTENDED_BANK + 1 /* MCE_AMD */ +#define MCE_THRESHOLD_DRAM_ECC MCE_THRESHOLD_BASE + 4 #ifdef __KERNEL__ #include void mce_log(struct mce *m); -DECLARE_PER_CPU(struct sys_device, device_mce); - #ifdef CONFIG_X86_MCE_INTEL void mce_intel_feature_init(struct cpuinfo_x86 *c); #else diff --git a/trunk/include/asm-x86_64/mutex.h b/trunk/include/asm-x86_64/mutex.h index 06fab6de2a88..11fbee2bd6c0 100644 --- a/trunk/include/asm-x86_64/mutex.h +++ b/trunk/include/asm-x86_64/mutex.h @@ -24,7 +24,7 @@ do { \ typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ \ __asm__ __volatile__( \ - LOCK_PREFIX " decl (%%rdi) \n" \ + LOCK " decl (%%rdi) \n" \ " js 2f \n" \ "1: \n" \ \ @@ -74,7 +74,7 @@ do { \ typecheck_fn(fastcall void (*)(atomic_t *), fail_fn); \ \ __asm__ __volatile__( \ - LOCK_PREFIX " incl (%%rdi) \n" \ + LOCK " incl (%%rdi) \n" \ " jle 2f \n" \ "1: \n" \ \ diff --git a/trunk/include/asm-x86_64/nmi.h b/trunk/include/asm-x86_64/nmi.h index efb45c894d76..d3abfc6a8fd5 100644 --- a/trunk/include/asm-x86_64/nmi.h +++ b/trunk/include/asm-x86_64/nmi.h @@ -5,27 +5,26 @@ #define ASM_NMI_H #include -#include struct pt_regs; - + typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu); - -/** + +/** * set_nmi_callback * * Set a handler for an NMI. Only one handler may be * set. Return 1 if the NMI was handled. */ void set_nmi_callback(nmi_callback_t callback); - -/** + +/** * unset_nmi_callback * * Remove the handler previously set. */ void unset_nmi_callback(void); - + #ifdef CONFIG_PM /** Replace the PM callback routine for NMI. */ @@ -57,21 +56,4 @@ extern int unknown_nmi_panic; extern int check_nmi_watchdog(void); -extern void setup_apic_nmi_watchdog (void); -extern int reserve_lapic_nmi(void); -extern void release_lapic_nmi(void); -extern void disable_timer_nmi_watchdog(void); -extern void enable_timer_nmi_watchdog(void); -extern void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason); - -extern void nmi_watchdog_default(void); -extern int setup_nmi_watchdog(char *); - -extern unsigned int nmi_watchdog; -#define NMI_DEFAULT -1 -#define NMI_NONE 0 -#define NMI_IO_APIC 1 -#define NMI_LOCAL_APIC 2 -#define NMI_INVALID 3 - #endif /* ASM_NMI_H */ diff --git a/trunk/include/asm-x86_64/pci.h b/trunk/include/asm-x86_64/pci.h index 49c5e9280598..2db0620d5449 100644 --- a/trunk/include/asm-x86_64/pci.h +++ b/trunk/include/asm-x86_64/pci.h @@ -39,8 +39,8 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq); #include #include #include +#include /* for have_iommu */ -extern void pci_iommu_alloc(void); extern int iommu_setup(char *opt); /* The PCI address space does equal the physical memory @@ -52,7 +52,7 @@ extern int iommu_setup(char *opt); */ #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) -#if defined(CONFIG_IOMMU) || defined(CONFIG_CALGARY_IOMMU) +#ifdef CONFIG_GART_IOMMU /* * x86-64 always supports DAC, but sometimes it is useful to force diff --git a/trunk/include/asm-x86_64/pgtable.h b/trunk/include/asm-x86_64/pgtable.h index a31ab4e68a9b..31e83c3bd022 100644 --- a/trunk/include/asm-x86_64/pgtable.h +++ b/trunk/include/asm-x86_64/pgtable.h @@ -337,8 +337,14 @@ static inline int pmd_large(pmd_t pte) { /* to find an entry in a page-table-directory. */ #define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) #define pud_offset(pgd, address) ((pud_t *) pgd_page(*(pgd)) + pud_index(address)) +#define pud_offset_k(pgd, addr) pud_offset(pgd, addr) #define pud_present(pud) (pud_val(pud) & _PAGE_PRESENT) +static inline pud_t *__pud_offset_k(pud_t *pud, unsigned long address) +{ + return pud + pud_index(address); +} + /* PMD - Level 2 access */ #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK)) #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) diff --git a/trunk/include/asm-x86_64/processor.h b/trunk/include/asm-x86_64/processor.h index 3b3c1217fe61..3061a38a3b1d 100644 --- a/trunk/include/asm-x86_64/processor.h +++ b/trunk/include/asm-x86_64/processor.h @@ -69,11 +69,7 @@ struct cpuinfo_x86 { cpumask_t llc_shared_map; /* cpus sharing the last level cache */ #endif __u8 apicid; -#ifdef CONFIG_SMP __u8 booted_cores; /* number of cores as seen by OS */ - __u8 phys_proc_id; /* Physical Processor id. */ - __u8 cpu_core_id; /* Core id. */ -#endif } ____cacheline_aligned; #define X86_VENDOR_INTEL 0 @@ -100,7 +96,6 @@ extern char ignore_irq13; extern void identify_cpu(struct cpuinfo_x86 *); extern void print_cpu_info(struct cpuinfo_x86 *); extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c); -extern unsigned short num_cache_leaves; /* * EFLAGS bits diff --git a/trunk/include/asm-x86_64/proto.h b/trunk/include/asm-x86_64/proto.h index 038fe1f47e6f..8abf2a43c944 100644 --- a/trunk/include/asm-x86_64/proto.h +++ b/trunk/include/asm-x86_64/proto.h @@ -37,6 +37,7 @@ extern void ia32_sysenter_target(void); extern void config_acpi_tables(void); extern void ia32_syscall(void); +extern void iommu_hole_init(void); extern int pmtimer_mark_offset(void); extern void pmtimer_resume(void); @@ -74,7 +75,7 @@ extern void main_timer_handler(struct pt_regs *regs); extern unsigned long end_pfn_map; -extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long * rsp); +extern void show_trace(unsigned long * rsp); extern void show_registers(struct pt_regs *regs); extern void exception_table_check(void); @@ -100,9 +101,13 @@ extern int unsynchronized_tsc(void); extern void select_idle_routine(const struct cpuinfo_x86 *c); +extern void gart_parse_options(char *); +extern void __init no_iommu_init(void); + extern unsigned long table_start, table_end; extern int exception_trace; +extern int force_iommu, no_iommu; extern int using_apic_timer; extern int disable_apic; extern unsigned cpu_khz; @@ -111,13 +116,7 @@ extern int skip_ioapic_setup; extern int acpi_ht; extern int acpi_disabled; -extern void no_iommu_init(void); -extern int force_iommu, no_iommu; -extern int iommu_detected; -#ifdef CONFIG_IOMMU -extern void gart_iommu_init(void); -extern void gart_parse_options(char *); -extern void iommu_hole_init(void); +#ifdef CONFIG_GART_IOMMU extern int fallback_aper_order; extern int fallback_aper_force; extern int iommu_aperture; diff --git a/trunk/include/asm-x86_64/rwlock.h b/trunk/include/asm-x86_64/rwlock.h index dea0e9459264..9942cc393064 100644 --- a/trunk/include/asm-x86_64/rwlock.h +++ b/trunk/include/asm-x86_64/rwlock.h @@ -24,7 +24,7 @@ #define RW_LOCK_BIAS_STR "0x01000000" #define __build_read_lock_ptr(rw, helper) \ - asm volatile(LOCK_PREFIX "subl $1,(%0)\n\t" \ + asm volatile(LOCK "subl $1,(%0)\n\t" \ "js 2f\n" \ "1:\n" \ LOCK_SECTION_START("") \ @@ -34,7 +34,7 @@ ::"a" (rw) : "memory") #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK_PREFIX "subl $1,%0\n\t" \ + asm volatile(LOCK "subl $1,%0\n\t" \ "js 2f\n" \ "1:\n" \ LOCK_SECTION_START("") \ @@ -54,7 +54,7 @@ } while (0) #define __build_write_lock_ptr(rw, helper) \ - asm volatile(LOCK_PREFIX "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ + asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ "jnz 2f\n" \ "1:\n" \ LOCK_SECTION_START("") \ @@ -64,7 +64,7 @@ ::"a" (rw) : "memory") #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK_PREFIX "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \ + asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \ "jnz 2f\n" \ "1:\n" \ LOCK_SECTION_START("") \ diff --git a/trunk/include/asm-x86_64/semaphore.h b/trunk/include/asm-x86_64/semaphore.h index 064df08b9a0f..a389aa6fe80f 100644 --- a/trunk/include/asm-x86_64/semaphore.h +++ b/trunk/include/asm-x86_64/semaphore.h @@ -106,7 +106,7 @@ static inline void down(struct semaphore * sem) __asm__ __volatile__( "# atomic down operation\n\t" - LOCK_PREFIX "decl %0\n\t" /* --sem->count */ + LOCK "decl %0\n\t" /* --sem->count */ "js 2f\n" "1:\n" LOCK_SECTION_START("") @@ -130,7 +130,7 @@ static inline int down_interruptible(struct semaphore * sem) __asm__ __volatile__( "# atomic interruptible down operation\n\t" - LOCK_PREFIX "decl %1\n\t" /* --sem->count */ + LOCK "decl %1\n\t" /* --sem->count */ "js 2f\n\t" "xorl %0,%0\n" "1:\n" @@ -154,7 +154,7 @@ static inline int down_trylock(struct semaphore * sem) __asm__ __volatile__( "# atomic interruptible down operation\n\t" - LOCK_PREFIX "decl %1\n\t" /* --sem->count */ + LOCK "decl %1\n\t" /* --sem->count */ "js 2f\n\t" "xorl %0,%0\n" "1:\n" @@ -178,7 +178,7 @@ static inline void up(struct semaphore * sem) { __asm__ __volatile__( "# atomic up operation\n\t" - LOCK_PREFIX "incl %0\n\t" /* ++sem->count */ + LOCK "incl %0\n\t" /* ++sem->count */ "jle 2f\n" "1:\n" LOCK_SECTION_START("") diff --git a/trunk/include/asm-x86_64/signal.h b/trunk/include/asm-x86_64/signal.h index cef7a7d51b7e..f8d55798535a 100644 --- a/trunk/include/asm-x86_64/signal.h +++ b/trunk/include/asm-x86_64/signal.h @@ -83,6 +83,7 @@ typedef unsigned long sigset_t; * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -102,6 +103,7 @@ typedef unsigned long sigset_t; #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 diff --git a/trunk/include/asm-x86_64/smp.h b/trunk/include/asm-x86_64/smp.h index 6805e1feb300..7686b9b25aef 100644 --- a/trunk/include/asm-x86_64/smp.h +++ b/trunk/include/asm-x86_64/smp.h @@ -53,6 +53,8 @@ extern int smp_call_function_single(int cpuid, void (*func) (void *info), extern cpumask_t cpu_sibling_map[NR_CPUS]; extern cpumask_t cpu_core_map[NR_CPUS]; +extern u8 phys_proc_id[NR_CPUS]; +extern u8 cpu_core_id[NR_CPUS]; extern u8 cpu_llc_id[NR_CPUS]; #define SMP_TRAMPOLINE_BASE 0x6000 diff --git a/trunk/include/asm-x86_64/socket.h b/trunk/include/asm-x86_64/socket.h index b46702607933..f2cdbeae5d5b 100644 --- a/trunk/include/asm-x86_64/socket.h +++ b/trunk/include/asm-x86_64/socket.h @@ -48,6 +48,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _ASM_SOCKET_H */ diff --git a/trunk/include/asm-x86_64/spinlock.h b/trunk/include/asm-x86_64/spinlock.h index 8d3421996f94..5d8a5e3589ff 100644 --- a/trunk/include/asm-x86_64/spinlock.h +++ b/trunk/include/asm-x86_64/spinlock.h @@ -31,19 +31,15 @@ "jmp 1b\n" \ LOCK_SECTION_END -#define __raw_spin_lock_string_up \ - "\n\tdecl %0" - #define __raw_spin_unlock_string \ "movl $1,%0" \ :"=m" (lock->slock) : : "memory" static inline void __raw_spin_lock(raw_spinlock_t *lock) { - alternative_smp( - __raw_spin_lock_string, - __raw_spin_lock_string_up, - "=m" (lock->slock) : : "memory"); + __asm__ __volatile__( + __raw_spin_lock_string + :"=m" (lock->slock) : : "memory"); } #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) diff --git a/trunk/include/asm-x86_64/string.h b/trunk/include/asm-x86_64/string.h index 9505d9f4bead..ee6bf275349e 100644 --- a/trunk/include/asm-x86_64/string.h +++ b/trunk/include/asm-x86_64/string.h @@ -6,8 +6,7 @@ /* Written 2002 by Andi Kleen */ /* Only used for special circumstances. Stolen from i386/string.h */ -static __always_inline void * -__inline_memcpy(void * to, const void * from, size_t n) +static inline void * __inline_memcpy(void * to, const void * from, size_t n) { unsigned long d0, d1, d2; __asm__ __volatile__( diff --git a/trunk/include/asm-x86_64/system.h b/trunk/include/asm-x86_64/system.h index 68e559f3631c..f48e0dad8b3d 100644 --- a/trunk/include/asm-x86_64/system.h +++ b/trunk/include/asm-x86_64/system.h @@ -3,10 +3,15 @@ #include #include -#include #ifdef __KERNEL__ +#ifdef CONFIG_SMP +#define LOCK_PREFIX "lock ; " +#else +#define LOCK_PREFIX "" +#endif + #define __STR(x) #x #define STR(x) __STR(x) @@ -29,7 +34,7 @@ "thread_return:\n\t" \ "movq %%gs:%P[pda_pcurrent],%%rsi\n\t" \ "movq %P[thread_info](%%rsi),%%r8\n\t" \ - LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ + LOCK "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ "movq %%rax,%%rdi\n\t" \ "jc ret_from_fork\n\t" \ RESTORE_CONTEXT \ @@ -64,6 +69,82 @@ extern void load_gs_index(unsigned); ".previous" \ : :"r" (value), "r" (0)) +#ifdef __KERNEL__ +struct alt_instr { + __u8 *instr; /* original instruction */ + __u8 *replacement; + __u8 cpuid; /* cpuid bit set for replacement */ + __u8 instrlen; /* length of original instruction */ + __u8 replacementlen; /* length of new instruction, <= instrlen */ + __u8 pad[5]; +}; +#endif + +/* + * Alternative instructions for different CPU types or capabilities. + * + * This allows to use optimized instructions even on generic binary + * kernels. + * + * length of oldinstr must be longer or equal the length of newinstr + * It can be padded with nops as needed. + * + * For non barrier like inlines please define new variants + * without volatile and memory clobber. + */ +#define alternative(oldinstr, newinstr, feature) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align 8\n" \ + " .quad 661b\n" /* label */ \ + " .quad 663f\n" /* new instruction */ \ + " .byte %c0\n" /* feature bit */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .altinstr_replacement,\"ax\"\n" \ + "663:\n\t" newinstr "\n664:\n" /* replacement */ \ + ".previous" :: "i" (feature) : "memory") + +/* + * Alternative inline assembly with input. + * + * Peculiarities: + * No memory clobber here. + * Argument numbers start with 1. + * Best is to use constraints that are fixed size (like (%1) ... "r") + * If you use variable sized constraints like "m" or "g" in the + * replacement make sure to pad to the worst case length. + */ +#define alternative_input(oldinstr, newinstr, feature, input...) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align 8\n" \ + " .quad 661b\n" /* label */ \ + " .quad 663f\n" /* new instruction */ \ + " .byte %c0\n" /* feature bit */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .altinstr_replacement,\"ax\"\n" \ + "663:\n\t" newinstr "\n664:\n" /* replacement */ \ + ".previous" :: "i" (feature), ##input) + +/* Like alternative_input, but with a single output argument */ +#define alternative_io(oldinstr, newinstr, feature, output, input...) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align 8\n" \ + " .quad 661b\n" /* label */ \ + " .quad 663f\n" /* new instruction */ \ + " .byte %c[feat]\n" /* feature bit */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .altinstr_replacement,\"ax\"\n" \ + "663:\n\t" newinstr "\n664:\n" /* replacement */ \ + ".previous" : output : [feat] "i" (feature), ##input) + /* * Clear and set 'TS' bit respectively */ @@ -285,6 +366,5 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, void cpu_idle_wait(void); extern unsigned long arch_align_stack(unsigned long sp); -extern void free_init_pages(char *what, unsigned long begin, unsigned long end); #endif diff --git a/trunk/include/asm-x86_64/tce.h b/trunk/include/asm-x86_64/tce.h deleted file mode 100644 index ee51d31528d6..000000000000 --- a/trunk/include/asm-x86_64/tce.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2006 Muli Ben-Yehuda , IBM Corporation - * Copyright (C) 2006 Jon Mason , IBM Corporation - * - * This file is derived from asm-powerpc/tce.h. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _ASM_X86_64_TCE_H -#define _ASM_X86_64_TCE_H - -extern void* tce_table_kva[]; -extern unsigned int specified_table_size; -struct iommu_table; - -#define TCE_ENTRY_SIZE 8 /* in bytes */ - -#define TCE_READ_SHIFT 0 -#define TCE_WRITE_SHIFT 1 -#define TCE_HUBID_SHIFT 2 /* unused */ -#define TCE_RSVD_SHIFT 8 /* unused */ -#define TCE_RPN_SHIFT 12 -#define TCE_UNUSED_SHIFT 48 /* unused */ - -#define TCE_RPN_MASK 0x0000fffffffff000ULL - -extern void tce_build(struct iommu_table *tbl, unsigned long index, - unsigned int npages, unsigned long uaddr, int direction); -extern void tce_free(struct iommu_table *tbl, long index, unsigned int npages); -extern void* alloc_tce_table(void); -extern void free_tce_table(void *tbl); -extern int build_tce_table(struct pci_dev *dev, void __iomem *bbar); - -#endif /* _ASM_X86_64_TCE_H */ diff --git a/trunk/include/asm-x86_64/thread_info.h b/trunk/include/asm-x86_64/thread_info.h index 2029b00351f3..4ac0e0a36934 100644 --- a/trunk/include/asm-x86_64/thread_info.h +++ b/trunk/include/asm-x86_64/thread_info.h @@ -73,21 +73,8 @@ static inline struct thread_info *stack_thread_info(void) } /* thread information allocation */ -#ifdef CONFIG_DEBUG_STACK_USAGE -#define alloc_thread_info(tsk) \ - ({ \ - struct thread_info *ret; \ - \ - ret = ((struct thread_info *) __get_free_pages(GFP_KERNEL,THREAD_ORDER)); \ - if (ret) \ - memset(ret, 0, THREAD_SIZE); \ - ret; \ - }) -#else #define alloc_thread_info(tsk) \ ((struct thread_info *) __get_free_pages(GFP_KERNEL,THREAD_ORDER)) -#endif - #define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER) #else /* !__ASSEMBLY__ */ @@ -114,7 +101,7 @@ static inline struct thread_info *stack_thread_info(void) #define TIF_IRET 5 /* force IRET */ #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ #define TIF_SECCOMP 8 /* secure computing */ -/* 16 free */ +#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_IA32 17 /* 32bit process */ #define TIF_FORK 18 /* ret_from_fork */ #define TIF_ABI_PENDING 19 @@ -128,6 +115,7 @@ static inline struct thread_info *stack_thread_info(void) #define _TIF_IRET (1<thread_info->status & TS_POLLING) #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-x86_64/topology.h b/trunk/include/asm-x86_64/topology.h index 6e7a2e976b04..80c4e44d011c 100644 --- a/trunk/include/asm-x86_64/topology.h +++ b/trunk/include/asm-x86_64/topology.h @@ -7,6 +7,8 @@ #include #include +/* Map the K8 CPU local memory controllers to a simple 1:1 CPU:NODE topology */ + extern cpumask_t cpu_online_map; extern unsigned char cpu_to_node[]; @@ -55,12 +57,12 @@ extern int __node_distance(int, int); #endif #ifdef CONFIG_SMP -#define topology_physical_package_id(cpu) (cpu_data[cpu].phys_proc_id) -#define topology_core_id(cpu) (cpu_data[cpu].cpu_core_id) +#define topology_physical_package_id(cpu) \ + (phys_proc_id[cpu] == BAD_APICID ? -1 : phys_proc_id[cpu]) +#define topology_core_id(cpu) \ + (cpu_core_id[cpu] == BAD_APICID ? 0 : cpu_core_id[cpu]) #define topology_core_siblings(cpu) (cpu_core_map[cpu]) #define topology_thread_siblings(cpu) (cpu_sibling_map[cpu]) -#define mc_capable() (boot_cpu_data.x86_max_cores > 1) -#define smt_capable() (smp_num_siblings > 1) #endif #include diff --git a/trunk/include/asm-x86_64/unwind.h b/trunk/include/asm-x86_64/unwind.h deleted file mode 100644 index f3e7124effe3..000000000000 --- a/trunk/include/asm-x86_64/unwind.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef _ASM_X86_64_UNWIND_H -#define _ASM_X86_64_UNWIND_H - -/* - * Copyright (C) 2002-2006 Novell, Inc. - * Jan Beulich - * This code is released under version 2 of the GNU GPL. - */ - -#ifdef CONFIG_STACK_UNWIND - -#include -#include -#include -#include - -struct unwind_frame_info -{ - struct pt_regs regs; - struct task_struct *task; -}; - -#define UNW_PC(frame) (frame)->regs.rip -#define UNW_SP(frame) (frame)->regs.rsp -#ifdef CONFIG_FRAME_POINTER -#define UNW_FP(frame) (frame)->regs.rbp -#define FRAME_RETADDR_OFFSET 8 -#define FRAME_LINK_OFFSET 0 -#define STACK_BOTTOM(tsk) (((tsk)->thread.rsp0 - 1) & ~(THREAD_SIZE - 1)) -#define STACK_TOP(tsk) ((tsk)->thread.rsp0) -#endif -/* Might need to account for the special exception and interrupt handling - stacks here, since normally - EXCEPTION_STACK_ORDER < THREAD_ORDER < IRQSTACK_ORDER, - but the construct is needed only for getting across the stack switch to - the interrupt stack - thus considering the IRQ stack itself is unnecessary, - and the overhead of comparing against all exception handling stacks seems - not desirable. */ -#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1)) - -#define UNW_REGISTER_INFO \ - PTREGS_INFO(rax), \ - PTREGS_INFO(rdx), \ - PTREGS_INFO(rcx), \ - PTREGS_INFO(rbx), \ - PTREGS_INFO(rsi), \ - PTREGS_INFO(rdi), \ - PTREGS_INFO(rbp), \ - PTREGS_INFO(rsp), \ - PTREGS_INFO(r8), \ - PTREGS_INFO(r9), \ - PTREGS_INFO(r10), \ - PTREGS_INFO(r11), \ - PTREGS_INFO(r12), \ - PTREGS_INFO(r13), \ - PTREGS_INFO(r14), \ - PTREGS_INFO(r15), \ - PTREGS_INFO(rip) - -static inline void arch_unw_init_frame_info(struct unwind_frame_info *info, - /*const*/ struct pt_regs *regs) -{ - info->regs = *regs; -} - -static inline void arch_unw_init_blocked(struct unwind_frame_info *info) -{ - extern const char thread_return[]; - - memset(&info->regs, 0, sizeof(info->regs)); - info->regs.rip = (unsigned long)thread_return; - info->regs.cs = __KERNEL_CS; - __get_user(info->regs.rbp, (unsigned long *)info->task->thread.rsp); - info->regs.rsp = info->task->thread.rsp; - info->regs.ss = __KERNEL_DS; -} - -extern int arch_unwind_init_running(struct unwind_frame_info *, - int (*callback)(struct unwind_frame_info *, - void *arg), - void *arg); - -static inline int arch_unw_user_mode(const struct unwind_frame_info *info) -{ -#if 0 /* This can only work when selector register saves/restores - are properly annotated (and tracked in UNW_REGISTER_INFO). */ - return user_mode(&info->regs); -#else - return (long)info->regs.rip >= 0 - || (info->regs.rip >= VSYSCALL_START && info->regs.rip < VSYSCALL_END) - || (long)info->regs.rsp >= 0; -#endif -} - -#else - -#define UNW_PC(frame) ((void)(frame), 0) - -static inline int arch_unw_user_mode(const void *info) -{ - return 0; -} - -#endif - -#endif /* _ASM_X86_64_UNWIND_H */ diff --git a/trunk/include/asm-xtensa/hw_irq.h b/trunk/include/asm-xtensa/hw_irq.h index 3ddbea759b2b..ccf436249eaa 100644 --- a/trunk/include/asm-xtensa/hw_irq.h +++ b/trunk/include/asm-xtensa/hw_irq.h @@ -11,4 +11,8 @@ #ifndef _XTENSA_HW_IRQ_H #define _XTENSA_HW_IRQ_H +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) +{ +} + #endif diff --git a/trunk/include/asm-xtensa/signal.h b/trunk/include/asm-xtensa/signal.h index 633ba73bc4d2..a99c9aec64ec 100644 --- a/trunk/include/asm-xtensa/signal.h +++ b/trunk/include/asm-xtensa/signal.h @@ -75,6 +75,7 @@ typedef struct { * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. * SA_RESETHAND clears the handler when the signal is delivered. @@ -94,6 +95,7 @@ typedef struct { #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND +#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */ #define SA_RESTORER 0x04000000 @@ -107,6 +109,19 @@ typedef struct { #define SIGSTKSZ 8192 #ifndef __ASSEMBLY__ +#ifdef __KERNEL__ + +/* + * These values of sa_flags are used only by the kernel as part of the + * irq handling routines. + * + * SA_INTERRUPT is also used by the irq handling routines. + * SA_SHIRQ is for shared interrupt support on PCI and EISA. + */ +#define SA_SAMPLE_RANDOM SA_RESTART +#define SA_SHIRQ 0x04000000 +#define SA_PROBEIRQ 0x08000000 +#endif #define SIG_BLOCK 0 /* for blocking signals */ #define SIG_UNBLOCK 1 /* for unblocking signals */ diff --git a/trunk/include/asm-xtensa/socket.h b/trunk/include/asm-xtensa/socket.h index 971d231be60e..00f83f3a6d72 100644 --- a/trunk/include/asm-xtensa/socket.h +++ b/trunk/include/asm-xtensa/socket.h @@ -59,6 +59,5 @@ #define SO_ACCEPTCONN 30 #define SO_PEERSEC 31 -#define SO_PASSSEC 34 #endif /* _XTENSA_SOCKET_H */ diff --git a/trunk/include/keys/user-type.h b/trunk/include/keys/user-type.h index c37c34275a44..a3dae1803f45 100644 --- a/trunk/include/keys/user-type.h +++ b/trunk/include/keys/user-type.h @@ -37,7 +37,6 @@ extern struct key_type key_type_user; extern int user_instantiate(struct key *key, const void *data, size_t datalen); extern int user_update(struct key *key, const void *data, size_t datalen); extern int user_match(const struct key *key, const void *criterion); -extern void user_revoke(struct key *key); extern void user_destroy(struct key *key); extern void user_describe(const struct key *user, struct seq_file *m); extern long user_read(const struct key *key, diff --git a/trunk/include/linux/ac97_codec.h b/trunk/include/linux/ac97_codec.h index 2ed2fd855133..c35833824e11 100644 --- a/trunk/include/linux/ac97_codec.h +++ b/trunk/include/linux/ac97_codec.h @@ -259,7 +259,7 @@ struct ac97_codec { int type; u32 model; - unsigned int modem:1; + int modem:1; struct ac97_ops *codec_ops; diff --git a/trunk/include/linux/acpi.h b/trunk/include/linux/acpi.h index 88b5dfd8ee12..90d6df1551ed 100644 --- a/trunk/include/linux/acpi.h +++ b/trunk/include/linux/acpi.h @@ -528,18 +528,12 @@ static inline void acpi_set_cstate_limit(unsigned int new_limit) { return; } #ifdef CONFIG_ACPI_NUMA int acpi_get_pxm(acpi_handle handle); -int acpi_get_node(acpi_handle *handle); #else static inline int acpi_get_pxm(acpi_handle handle) { return 0; } -static inline int acpi_get_node(acpi_handle *handle) -{ - return 0; -} #endif -extern int acpi_paddr_to_node(u64 start_addr, u64 size); extern int pnpacpi_disabled; diff --git a/trunk/include/linux/atmdev.h b/trunk/include/linux/atmdev.h index 41788a31c438..1eb238affb12 100644 --- a/trunk/include/linux/atmdev.h +++ b/trunk/include/linux/atmdev.h @@ -7,7 +7,6 @@ #define LINUX_ATMDEV_H -#include #include #include #include @@ -359,7 +358,6 @@ struct atm_dev { struct proc_dir_entry *proc_entry; /* proc entry */ char *proc_name; /* proc entry name */ #endif - struct class_device class_dev; /* sysfs class device */ struct list_head dev_list; /* linkage */ }; @@ -461,7 +459,7 @@ static inline void atm_dev_put(struct atm_dev *dev) BUG_ON(!test_bit(ATM_DF_REMOVED, &dev->flags)); if (dev->ops->dev_close) dev->ops->dev_close(dev); - class_device_put(&dev->class_dev); + kfree(dev); } } diff --git a/trunk/include/linux/audit.h b/trunk/include/linux/audit.h index b27d7debc5a1..e051ff9c5b50 100644 --- a/trunk/include/linux/audit.h +++ b/trunk/include/linux/audit.h @@ -122,17 +122,10 @@ /* Rule structure sizes -- if these change, different AUDIT_ADD and * AUDIT_LIST commands must be implemented. */ #define AUDIT_MAX_FIELDS 64 -#define AUDIT_MAX_KEY_LEN 32 #define AUDIT_BITMASK_SIZE 64 #define AUDIT_WORD(nr) ((__u32)((nr)/32)) #define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32)) -#define AUDIT_SYSCALL_CLASSES 16 -#define AUDIT_CLASS_DIR_WRITE 0 -#define AUDIT_CLASS_DIR_WRITE_32 1 -#define AUDIT_CLASS_CHATTR 2 -#define AUDIT_CLASS_CHATTR_32 3 - /* This bitmask is used to validate user input. It represents all bits that * are currently used in an audit field constant understood by the kernel. * If you are adding a new #define AUDIT_, please ensure that @@ -157,17 +150,12 @@ #define AUDIT_PERS 10 #define AUDIT_ARCH 11 #define AUDIT_MSGTYPE 12 -#define AUDIT_SUBJ_USER 13 /* security label user */ -#define AUDIT_SUBJ_ROLE 14 /* security label role */ -#define AUDIT_SUBJ_TYPE 15 /* security label type */ -#define AUDIT_SUBJ_SEN 16 /* security label sensitivity label */ -#define AUDIT_SUBJ_CLR 17 /* security label clearance label */ +#define AUDIT_SE_USER 13 /* security label user */ +#define AUDIT_SE_ROLE 14 /* security label role */ +#define AUDIT_SE_TYPE 15 /* security label type */ +#define AUDIT_SE_SEN 16 /* security label sensitivity label */ +#define AUDIT_SE_CLR 17 /* security label clearance label */ #define AUDIT_PPID 18 -#define AUDIT_OBJ_USER 19 -#define AUDIT_OBJ_ROLE 20 -#define AUDIT_OBJ_TYPE 21 -#define AUDIT_OBJ_LEV_LOW 22 -#define AUDIT_OBJ_LEV_HIGH 23 /* These are ONLY useful when checking * at syscall exit time (AUDIT_AT_EXIT). */ @@ -183,8 +171,6 @@ #define AUDIT_ARG2 (AUDIT_ARG0+2) #define AUDIT_ARG3 (AUDIT_ARG0+3) -#define AUDIT_FILTERKEY 210 - #define AUDIT_NEGATE 0x80000000 /* These are the supported operators. @@ -313,7 +299,6 @@ struct mqstat; #define AUDITSC_SUCCESS 1 #define AUDITSC_FAILURE 2 #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) -extern int __init audit_register_class(int class, unsigned *list); #ifdef CONFIG_AUDITSYSCALL /* These are defined in auditsc.c */ /* Public API */ diff --git a/trunk/include/linux/bitmap.h b/trunk/include/linux/bitmap.h index dcc5de7cc487..d9ed27969855 100644 --- a/trunk/include/linux/bitmap.h +++ b/trunk/include/linux/bitmap.h @@ -24,9 +24,6 @@ * The available bitmap operations and their rough meaning in the * case that the bitmap is a single unsigned long are thus: * - * Note that nbits should be always a compile time evaluable constant. - * Otherwise many inlines will generate horrible code. - * * bitmap_zero(dst, nbits) *dst = 0UL * bitmap_fill(dst, nbits) *dst = ~0UL * bitmap_copy(dst, src, nbits) *dst = *src @@ -247,8 +244,6 @@ static inline int bitmap_full(const unsigned long *src, int nbits) static inline int bitmap_weight(const unsigned long *src, int nbits) { - if (nbits <= BITS_PER_LONG) - return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits)); return __bitmap_weight(src, nbits); } diff --git a/trunk/include/linux/buffer_head.h b/trunk/include/linux/buffer_head.h index 737e407d0cd1..fb7e9b7ccbe3 100644 --- a/trunk/include/linux/buffer_head.h +++ b/trunk/include/linux/buffer_head.h @@ -149,6 +149,7 @@ void create_empty_buffers(struct page *, unsigned long, unsigned long b_state); void end_buffer_read_sync(struct buffer_head *bh, int uptodate); void end_buffer_write_sync(struct buffer_head *bh, int uptodate); +void end_buffer_async_write(struct buffer_head *bh, int uptodate); /* Things to do with buffers at mapping->private_list */ void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode); @@ -213,7 +214,6 @@ int nobh_truncate_page(struct address_space *, loff_t); int nobh_writepage(struct page *page, get_block_t *get_block, struct writeback_control *wbc); -void buffer_init(void); /* * inline definitions diff --git a/trunk/include/linux/clocksource.h b/trunk/include/linux/clocksource.h deleted file mode 100644 index d852024ed095..000000000000 --- a/trunk/include/linux/clocksource.h +++ /dev/null @@ -1,185 +0,0 @@ -/* linux/include/linux/clocksource.h - * - * This file contains the structure definitions for clocksources. - * - * If you are not a clocksource, or timekeeping code, you should - * not be including this file! - */ -#ifndef _LINUX_CLOCKSOURCE_H -#define _LINUX_CLOCKSOURCE_H - -#include -#include -#include -#include -#include -#include - -/* clocksource cycle base type */ -typedef u64 cycle_t; - -/** - * struct clocksource - hardware abstraction for a free running counter - * Provides mostly state-free accessors to the underlying hardware. - * - * @name: ptr to clocksource name - * @list: list head for registration - * @rating: rating value for selection (higher is better) - * To avoid rating inflation the following - * list should give you a guide as to how - * to assign your clocksource a rating - * 1-99: Unfit for real use - * Only available for bootup and testing purposes. - * 100-199: Base level usability. - * Functional for real use, but not desired. - * 200-299: Good. - * A correct and usable clocksource. - * 300-399: Desired. - * A reasonably fast and accurate clocksource. - * 400-499: Perfect - * The ideal clocksource. A must-use where - * available. - * @read: returns a cycle value - * @mask: bitmask for two's complement - * subtraction of non 64 bit counters - * @mult: cycle to nanosecond multiplier - * @shift: cycle to nanosecond divisor (power of two) - * @update_callback: called when safe to alter clocksource values - * @is_continuous: defines if clocksource is free-running. - * @cycle_interval: Used internally by timekeeping core, please ignore. - * @xtime_interval: Used internally by timekeeping core, please ignore. - */ -struct clocksource { - char *name; - struct list_head list; - int rating; - cycle_t (*read)(void); - cycle_t mask; - u32 mult; - u32 shift; - int (*update_callback)(void); - int is_continuous; - - /* timekeeping specific data, ignore */ - cycle_t cycle_last, cycle_interval; - u64 xtime_nsec, xtime_interval; - s64 error; -}; - -/* simplify initialization of mask field */ -#define CLOCKSOURCE_MASK(bits) (cycle_t)(bits<64 ? ((1ULL<read(); -} - -/** - * cyc2ns - converts clocksource cycles to nanoseconds - * @cs: Pointer to clocksource - * @cycles: Cycles - * - * Uses the clocksource and ntp ajdustment to convert cycle_ts to nanoseconds. - * - * XXX - This could use some mult_lxl_ll() asm optimization - */ -static inline s64 cyc2ns(struct clocksource *cs, cycle_t cycles) -{ - u64 ret = (u64)cycles; - ret = (ret * cs->mult) >> cs->shift; - return ret; -} - -/** - * clocksource_calculate_interval - Calculates a clocksource interval struct - * - * @c: Pointer to clocksource. - * @length_nsec: Desired interval length in nanoseconds. - * - * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment - * pair and interval request. - * - * Unless you're the timekeeping code, you should not be using this! - */ -static inline void clocksource_calculate_interval(struct clocksource *c, - unsigned long length_nsec) -{ - u64 tmp; - - /* XXX - All of this could use a whole lot of optimization */ - tmp = length_nsec; - tmp <<= c->shift; - tmp += c->mult/2; - do_div(tmp, c->mult); - - c->cycle_interval = (cycle_t)tmp; - if (c->cycle_interval == 0) - c->cycle_interval = 1; - - c->xtime_interval = (u64)c->cycle_interval * c->mult; -} - - -/* used to install a new clocksource */ -int clocksource_register(struct clocksource*); -void clocksource_reselect(void); -struct clocksource* clocksource_get_next(void); - -#endif /* _LINUX_CLOCKSOURCE_H */ diff --git a/trunk/include/linux/coda_linux.h b/trunk/include/linux/coda_linux.h index be512cc98791..7b5c5df5cb69 100644 --- a/trunk/include/linux/coda_linux.h +++ b/trunk/include/linux/coda_linux.h @@ -27,8 +27,8 @@ extern struct inode_operations coda_dir_inode_operations; extern struct inode_operations coda_file_inode_operations; extern struct inode_operations coda_ioctl_inode_operations; -extern const struct address_space_operations coda_file_aops; -extern const struct address_space_operations coda_symlink_aops; +extern struct address_space_operations coda_file_aops; +extern struct address_space_operations coda_symlink_aops; extern const struct file_operations coda_dir_operations; extern const struct file_operations coda_file_operations; diff --git a/trunk/include/linux/compat.h b/trunk/include/linux/compat.h index 9760753e662b..dda1697ec753 100644 --- a/trunk/include/linux/compat.h +++ b/trunk/include/linux/compat.h @@ -226,7 +226,5 @@ static inline int compat_timespec_compare(struct compat_timespec *lhs, asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); -extern int compat_printk(const char *fmt, ...); - #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ diff --git a/trunk/include/linux/compat_ioctl.h b/trunk/include/linux/compat_ioctl.h index 269d000bb2a3..89ab677cb993 100644 --- a/trunk/include/linux/compat_ioctl.h +++ b/trunk/include/linux/compat_ioctl.h @@ -567,6 +567,11 @@ COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOSUBVER) COMPATIBLE_IOCTL(AUTOFS_IOC_ASKREGHOST) COMPATIBLE_IOCTL(AUTOFS_IOC_TOGGLEREGHOST) COMPATIBLE_IOCTL(AUTOFS_IOC_ASKUMOUNT) +/* DEVFS */ +COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV) +COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK) +COMPATIBLE_IOCTL(DEVFSDIOC_RELEASE_EVENT_QUEUE) +COMPATIBLE_IOCTL(DEVFSDIOC_SET_DEBUG_MASK) /* Raw devices */ COMPATIBLE_IOCTL(RAW_SETBIND) COMPATIBLE_IOCTL(RAW_GETBIND) @@ -668,11 +673,6 @@ COMPATIBLE_IOCTL(CAPI_SET_FLAGS) COMPATIBLE_IOCTL(CAPI_CLR_FLAGS) COMPATIBLE_IOCTL(CAPI_NCCI_OPENCOUNT) COMPATIBLE_IOCTL(CAPI_NCCI_GETUNIT) -/* Siemens Gigaset */ -COMPATIBLE_IOCTL(GIGASET_REDIR) -COMPATIBLE_IOCTL(GIGASET_CONFIG) -COMPATIBLE_IOCTL(GIGASET_BRKCHARS) -COMPATIBLE_IOCTL(GIGASET_VERSION) /* Misc. */ COMPATIBLE_IOCTL(0x41545900) /* ATYIO_CLKR */ COMPATIBLE_IOCTL(0x41545901) /* ATYIO_CLKW */ diff --git a/trunk/include/linux/console.h b/trunk/include/linux/console.h index 3bdf2155e565..d0f8a8009490 100644 --- a/trunk/include/linux/console.h +++ b/trunk/include/linux/console.h @@ -63,11 +63,9 @@ extern const struct consw vga_con; /* VGA text console */ extern const struct consw newport_con; /* SGI Newport console */ extern const struct consw prom_con; /* SPARC PROM console */ -int con_is_bound(const struct consw *csw); -int register_con_driver(const struct consw *csw, int first, int last); -int unregister_con_driver(const struct consw *csw); int take_over_console(const struct consw *sw, int first, int last, int deflt); void give_up_console(const struct consw *sw); + /* scroll */ #define SM_UP (1) #define SM_DOWN (2) diff --git a/trunk/include/linux/cpu.h b/trunk/include/linux/cpu.h index 44a11f1ccaf2..08d50c53aab4 100644 --- a/trunk/include/linux/cpu.h +++ b/trunk/include/linux/cpu.h @@ -31,23 +31,17 @@ struct cpu { struct sys_device sysdev; }; -extern int register_cpu(struct cpu *cpu, int num); +extern int register_cpu(struct cpu *, int, struct node *); extern struct sys_device *get_cpu_sysdev(unsigned cpu); #ifdef CONFIG_HOTPLUG_CPU -extern void unregister_cpu(struct cpu *cpu); +extern void unregister_cpu(struct cpu *, struct node *); #endif struct notifier_block; #ifdef CONFIG_SMP /* Need to know about CPUs going up/down? */ extern int register_cpu_notifier(struct notifier_block *nb); -#ifdef CONFIG_HOTPLUG_CPU extern void unregister_cpu_notifier(struct notifier_block *nb); -#else -static inline void unregister_cpu_notifier(struct notifier_block *nb) -{ -} -#endif extern int current_in_cpu_hotplug(void); int cpu_up(unsigned int cpu); @@ -79,17 +73,13 @@ extern int lock_cpu_hotplug_interruptible(void); { .notifier_call = fn, .priority = pri }; \ register_cpu_notifier(&fn##_nb); \ } -#define register_hotcpu_notifier(nb) register_cpu_notifier(nb) -#define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb) int cpu_down(unsigned int cpu); #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu)) #else #define lock_cpu_hotplug() do { } while (0) #define unlock_cpu_hotplug() do { } while (0) #define lock_cpu_hotplug_interruptible() 0 -#define hotcpu_notifier(fn, pri) do { } while (0) -#define register_hotcpu_notifier(nb) do { } while (0) -#define unregister_hotcpu_notifier(nb) do { } while (0) +#define hotcpu_notifier(fn, pri) /* CPUs don't go offline once they're online w/o CONFIG_HOTPLUG_CPU */ static inline int cpu_is_offline(int cpu) { return 0; } diff --git a/trunk/include/linux/cpufreq.h b/trunk/include/linux/cpufreq.h index 35e137636b0b..466fbe9e4899 100644 --- a/trunk/include/linux/cpufreq.h +++ b/trunk/include/linux/cpufreq.h @@ -100,10 +100,8 @@ struct cpufreq_policy { #define CPUFREQ_INCOMPATIBLE (1) #define CPUFREQ_NOTIFY (2) -#define CPUFREQ_SHARED_TYPE_NONE (0) /* None */ -#define CPUFREQ_SHARED_TYPE_HW (1) /* HW does needed coordination */ -#define CPUFREQ_SHARED_TYPE_ALL (2) /* All dependent CPUs should set freq */ -#define CPUFREQ_SHARED_TYPE_ANY (3) /* Freq can be set from any dependent CPU*/ +#define CPUFREQ_SHARED_TYPE_ALL (0) /* All dependent CPUs should set freq */ +#define CPUFREQ_SHARED_TYPE_ANY (1) /* Freq can be set from any dependent CPU */ /******************** cpufreq transition notifiers *******************/ diff --git a/trunk/include/linux/crypto.h b/trunk/include/linux/crypto.h index 7f946241b879..5a0470e36111 100644 --- a/trunk/include/linux/crypto.h +++ b/trunk/include/linux/crypto.h @@ -66,7 +66,7 @@ struct crypto_tfm; struct cipher_desc { struct crypto_tfm *tfm; - void (*crfn)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); + void (*crfn)(void *ctx, u8 *dst, const u8 *src); unsigned int (*prfn)(const struct cipher_desc *desc, u8 *dst, const u8 *src, unsigned int nbytes); void *info; @@ -79,10 +79,10 @@ struct cipher_desc { struct cipher_alg { unsigned int cia_min_keysize; unsigned int cia_max_keysize; - int (*cia_setkey)(struct crypto_tfm *tfm, const u8 *key, + int (*cia_setkey)(void *ctx, const u8 *key, unsigned int keylen, u32 *flags); - void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); - void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); + void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src); + void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src); unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc, u8 *dst, const u8 *src, @@ -100,19 +100,20 @@ struct cipher_alg { struct digest_alg { unsigned int dia_digestsize; - void (*dia_init)(struct crypto_tfm *tfm); - void (*dia_update)(struct crypto_tfm *tfm, const u8 *data, - unsigned int len); - void (*dia_final)(struct crypto_tfm *tfm, u8 *out); - int (*dia_setkey)(struct crypto_tfm *tfm, const u8 *key, + void (*dia_init)(void *ctx); + void (*dia_update)(void *ctx, const u8 *data, unsigned int len); + void (*dia_final)(void *ctx, u8 *out); + int (*dia_setkey)(void *ctx, const u8 *key, unsigned int keylen, u32 *flags); }; struct compress_alg { - int (*coa_compress)(struct crypto_tfm *tfm, const u8 *src, - unsigned int slen, u8 *dst, unsigned int *dlen); - int (*coa_decompress)(struct crypto_tfm *tfm, const u8 *src, - unsigned int slen, u8 *dst, unsigned int *dlen); + int (*coa_init)(void *ctx); + void (*coa_exit)(void *ctx); + int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); + int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); }; #define cra_cipher cra_u.cipher @@ -128,17 +129,14 @@ struct crypto_alg { int cra_priority; - char cra_name[CRYPTO_MAX_ALG_NAME]; - char cra_driver_name[CRYPTO_MAX_ALG_NAME]; + const char cra_name[CRYPTO_MAX_ALG_NAME]; + const char cra_driver_name[CRYPTO_MAX_ALG_NAME]; union { struct cipher_alg cipher; struct digest_alg digest; struct compress_alg compress; } cra_u; - - int (*cra_init)(struct crypto_tfm *tfm); - void (*cra_exit)(struct crypto_tfm *tfm); struct module *cra_module; }; diff --git a/trunk/include/linux/devfs_fs.h b/trunk/include/linux/devfs_fs.h new file mode 100644 index 000000000000..de236f431877 --- /dev/null +++ b/trunk/include/linux/devfs_fs.h @@ -0,0 +1,41 @@ +#ifndef _LINUX_DEVFS_FS_H +#define _LINUX_DEVFS_FS_H + +#include + +#define DEVFSD_PROTOCOL_REVISION_KERNEL 5 + +#define DEVFSD_IOCTL_BASE 'd' + +/* These are the various ioctls */ +#define DEVFSDIOC_GET_PROTO_REV _IOR(DEVFSD_IOCTL_BASE, 0, int) +#define DEVFSDIOC_SET_EVENT_MASK _IOW(DEVFSD_IOCTL_BASE, 2, int) +#define DEVFSDIOC_RELEASE_EVENT_QUEUE _IOW(DEVFSD_IOCTL_BASE, 3, int) +#define DEVFSDIOC_SET_DEBUG_MASK _IOW(DEVFSD_IOCTL_BASE, 4, int) + +#define DEVFSD_NOTIFY_REGISTERED 0 +#define DEVFSD_NOTIFY_UNREGISTERED 1 +#define DEVFSD_NOTIFY_ASYNC_OPEN 2 +#define DEVFSD_NOTIFY_CLOSE 3 +#define DEVFSD_NOTIFY_LOOKUP 4 +#define DEVFSD_NOTIFY_CHANGE 5 +#define DEVFSD_NOTIFY_CREATE 6 +#define DEVFSD_NOTIFY_DELETE 7 + +#define DEVFS_PATHLEN 1024 /* Never change this otherwise the + binary interface will change */ + +struct devfsd_notify_struct { /* Use native C types to ensure same types in kernel and user space */ + unsigned int type; /* DEVFSD_NOTIFY_* value */ + unsigned int mode; /* Mode of the inode or device entry */ + unsigned int major; /* Major number of device entry */ + unsigned int minor; /* Minor number of device entry */ + unsigned int uid; /* Uid of process, inode or device entry */ + unsigned int gid; /* Gid of process, inode or device entry */ + unsigned int overrun_count; /* Number of lost events */ + unsigned int namelen; /* Number of characters not including '\0' */ + /* The device name MUST come last */ + char devname[DEVFS_PATHLEN]; /* This will be '\0' terminated */ +}; + +#endif /* _LINUX_DEVFS_FS_H */ diff --git a/trunk/include/linux/devfs_fs_kernel.h b/trunk/include/linux/devfs_fs_kernel.h new file mode 100644 index 000000000000..0d74a6f22abc --- /dev/null +++ b/trunk/include/linux/devfs_fs_kernel.h @@ -0,0 +1,57 @@ +#ifndef _LINUX_DEVFS_FS_KERNEL_H +#define _LINUX_DEVFS_FS_KERNEL_H + +#include +#include +#include + +#include + +#define DEVFS_SUPER_MAGIC 0x1373 + +#ifdef CONFIG_DEVFS_FS +extern int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) + __attribute__ ((format(printf, 3, 4))); +extern int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) + __attribute__ ((format(printf, 3, 4))); +extern int devfs_mk_symlink(const char *name, const char *link); +extern int devfs_mk_dir(const char *fmt, ...) + __attribute__ ((format(printf, 1, 2))); +extern void devfs_remove(const char *fmt, ...) + __attribute__ ((format(printf, 1, 2))); +extern int devfs_register_tape(const char *name); +extern void devfs_unregister_tape(int num); +extern void mount_devfs_fs(void); +#else /* CONFIG_DEVFS_FS */ +static inline int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) +{ + return 0; +} +static inline int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) +{ + return 0; +} +static inline int devfs_mk_symlink(const char *name, const char *link) +{ + return 0; +} +static inline int devfs_mk_dir(const char *fmt, ...) +{ + return 0; +} +static inline void devfs_remove(const char *fmt, ...) +{ +} +static inline int devfs_register_tape(const char *name) +{ + return -1; +} +static inline void devfs_unregister_tape(int num) +{ +} +static inline void mount_devfs_fs(void) +{ + return; +} +#endif /* CONFIG_DEVFS_FS */ +#endif /* _LINUX_DEVFS_FS_KERNEL_H */ diff --git a/trunk/include/linux/device-mapper.h b/trunk/include/linux/device-mapper.h index e3d1c33d1558..aee10b2ea4c6 100644 --- a/trunk/include/linux/device-mapper.h +++ b/trunk/include/linux/device-mapper.h @@ -8,12 +8,9 @@ #ifndef _LINUX_DEVICE_MAPPER_H #define _LINUX_DEVICE_MAPPER_H -#ifdef __KERNEL__ - struct dm_target; struct dm_table; struct dm_dev; -struct mapped_device; typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t; @@ -81,7 +78,7 @@ void dm_put_device(struct dm_target *ti, struct dm_dev *d); struct target_type { const char *name; struct module *module; - unsigned version[3]; + unsigned version[3]; dm_ctr_fn ctr; dm_dtr_fn dtr; dm_map_fn map; @@ -131,108 +128,4 @@ struct dm_target { int dm_register_target(struct target_type *t); int dm_unregister_target(struct target_type *t); - -/*----------------------------------------------------------------- - * Functions for creating and manipulating mapped devices. - * Drop the reference with dm_put when you finish with the object. - *---------------------------------------------------------------*/ - -/* - * DM_ANY_MINOR chooses the next available minor number. - */ -#define DM_ANY_MINOR (-1) -int dm_create(int minor, struct mapped_device **md); - -/* - * Reference counting for md. - */ -struct mapped_device *dm_get_md(dev_t dev); -void dm_get(struct mapped_device *md); -void dm_put(struct mapped_device *md); - -/* - * An arbitrary pointer may be stored alongside a mapped device. - */ -void dm_set_mdptr(struct mapped_device *md, void *ptr); -void *dm_get_mdptr(struct mapped_device *md); - -/* - * A device can still be used while suspended, but I/O is deferred. - */ -int dm_suspend(struct mapped_device *md, int with_lockfs); -int dm_resume(struct mapped_device *md); - -/* - * Event functions. - */ -uint32_t dm_get_event_nr(struct mapped_device *md); -int dm_wait_event(struct mapped_device *md, int event_nr); - -/* - * Info functions. - */ -const char *dm_device_name(struct mapped_device *md); -struct gendisk *dm_disk(struct mapped_device *md); -int dm_suspended(struct mapped_device *md); - -/* - * Geometry functions. - */ -int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo); -int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo); - - -/*----------------------------------------------------------------- - * Functions for manipulating device-mapper tables. - *---------------------------------------------------------------*/ - -/* - * First create an empty table. - */ -int dm_table_create(struct dm_table **result, int mode, - unsigned num_targets, struct mapped_device *md); - -/* - * Then call this once for each target. - */ -int dm_table_add_target(struct dm_table *t, const char *type, - sector_t start, sector_t len, char *params); - -/* - * Finally call this to make the table ready for use. - */ -int dm_table_complete(struct dm_table *t); - -/* - * Table reference counting. - */ -struct dm_table *dm_get_table(struct mapped_device *md); -void dm_table_get(struct dm_table *t); -void dm_table_put(struct dm_table *t); - -/* - * Queries - */ -sector_t dm_table_get_size(struct dm_table *t); -unsigned int dm_table_get_num_targets(struct dm_table *t); -int dm_table_get_mode(struct dm_table *t); -struct mapped_device *dm_table_get_md(struct dm_table *t); - -/* - * Trigger an event. - */ -void dm_table_event(struct dm_table *t); - -/* - * The device must be suspended before calling this method. - */ -int dm_swap_table(struct mapped_device *md, struct dm_table *t); - -/* - * Prepare a table for a device that will error all I/O. - * To make it active, call dm_suspend(), dm_swap_table() then dm_resume(). - */ -int dm_create_error_table(struct dm_table **result, struct mapped_device *md); - -#endif /* __KERNEL__ */ -#endif /* _LINUX_DEVICE_MAPPER_H */ +#endif /* _LINUX_DEVICE_MAPPER_H */ diff --git a/trunk/include/linux/dm-ioctl.h b/trunk/include/linux/dm-ioctl.h index 9623bb625090..c67c6786612a 100644 --- a/trunk/include/linux/dm-ioctl.h +++ b/trunk/include/linux/dm-ioctl.h @@ -285,9 +285,9 @@ typedef char ioctl_struct[308]; #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 7 +#define DM_VERSION_MINOR 6 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2006-06-24)" +#define DM_VERSION_EXTRA "-ioctl (2006-02-17)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ @@ -314,7 +314,7 @@ typedef char ioctl_struct[308]; #define DM_BUFFER_FULL_FLAG (1 << 8) /* Out */ /* - * This flag is now ignored. + * Set this to improve performance when you aren't going to use open_count. */ #define DM_SKIP_BDGET_FLAG (1 << 9) /* In */ diff --git a/trunk/include/linux/dmaengine.h b/trunk/include/linux/dmaengine.h index 272010a6078a..78b236ca04f8 100644 --- a/trunk/include/linux/dmaengine.h +++ b/trunk/include/linux/dmaengine.h @@ -20,7 +20,7 @@ */ #ifndef DMAENGINE_H #define DMAENGINE_H - +#include #ifdef CONFIG_DMA_ENGINE #include diff --git a/trunk/include/linux/dqblk_xfs.h b/trunk/include/linux/dqblk_xfs.h index 527504c11c5e..2fda1b2aabd9 100644 --- a/trunk/include/linux/dqblk_xfs.h +++ b/trunk/include/linux/dqblk_xfs.h @@ -125,14 +125,14 @@ typedef struct fs_disk_quota { /* * fs_quota_stat is the struct returned in Q_XGETQSTAT for a given file system. - * Provides a centralized way to get meta information about the quota subsystem. + * Provides a centralized way to get meta infomation about the quota subsystem. * eg. space taken up for user and group quotas, number of dquots currently * incore. */ #define FS_QSTAT_VERSION 1 /* fs_quota_stat.qs_version */ /* - * Some basic information about 'quota files'. + * Some basic infomation about 'quota files'. */ typedef struct fs_qfilestat { __u64 qfs_ino; /* inode number */ diff --git a/trunk/include/linux/efs_fs.h b/trunk/include/linux/efs_fs.h index 278ef4495819..fbfa6b52e2fb 100644 --- a/trunk/include/linux/efs_fs.h +++ b/trunk/include/linux/efs_fs.h @@ -38,7 +38,7 @@ struct statfs; extern struct inode_operations efs_dir_inode_operations; extern const struct file_operations efs_dir_operations; -extern const struct address_space_operations efs_symlink_aops; +extern struct address_space_operations efs_symlink_aops; extern void efs_read_inode(struct inode *); extern efs_block_t efs_map_block(struct inode *, efs_block_t); diff --git a/trunk/include/linux/elf-em.h b/trunk/include/linux/elf-em.h index 6a5796c81c90..114a96d25652 100644 --- a/trunk/include/linux/elf-em.h +++ b/trunk/include/linux/elf-em.h @@ -11,12 +11,7 @@ #define EM_486 6 /* Perhaps disused */ #define EM_860 7 #define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */ - /* Next two are historical and binaries and - modules of these types will be rejected by - Linux. */ -#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ #define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ - #define EM_PARISC 15 /* HPPA */ #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ #define EM_PPC 20 /* PowerPC */ diff --git a/trunk/include/linux/err.h b/trunk/include/linux/err.h index cd3b367f7445..ff71d2af5da3 100644 --- a/trunk/include/linux/err.h +++ b/trunk/include/linux/err.h @@ -13,9 +13,7 @@ * This should be a per-architecture thing, to allow different * error and pointer decisions. */ -#define MAX_ERRNO 4095 - -#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) +#define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L) static inline void *ERR_PTR(long error) { diff --git a/trunk/include/linux/fb.h b/trunk/include/linux/fb.h index ffefeeeeca93..f1281687e549 100644 --- a/trunk/include/linux/fb.h +++ b/trunk/include/linux/fb.h @@ -380,6 +380,7 @@ struct fb_cursor { #include #include #include +#include #include #include #include @@ -503,19 +504,23 @@ struct fb_cursor_user { #define FB_EVENT_MODE_DELETE 0x04 /* A driver registered itself */ #define FB_EVENT_FB_REGISTERED 0x05 -/* A driver unregistered itself */ -#define FB_EVENT_FB_UNREGISTERED 0x06 /* CONSOLE-SPECIFIC: get console to framebuffer mapping */ -#define FB_EVENT_GET_CONSOLE_MAP 0x07 +#define FB_EVENT_GET_CONSOLE_MAP 0x06 /* CONSOLE-SPECIFIC: set console to framebuffer mapping */ -#define FB_EVENT_SET_CONSOLE_MAP 0x08 +#define FB_EVENT_SET_CONSOLE_MAP 0x07 /* A display blank is requested */ -#define FB_EVENT_BLANK 0x09 +#define FB_EVENT_BLANK 0x08 /* Private modelist is to be replaced */ -#define FB_EVENT_NEW_MODELIST 0x0A +#define FB_EVENT_NEW_MODELIST 0x09 /* The resolution of the passed in fb_info about to change and all vc's should be changed */ -#define FB_EVENT_MODE_CHANGE_ALL 0x0B +#define FB_EVENT_MODE_CHANGE_ALL 0x0A +/* CONSOLE-SPECIFIC: set console rotation */ +#define FB_EVENT_SET_CON_ROTATE 0x0B +/* CONSOLE-SPECIFIC: get console rotation */ +#define FB_EVENT_GET_CON_ROTATE 0x0C +/* CONSOLE-SPECIFIC: rotate all consoles */ +#define FB_EVENT_SET_CON_ROTATE_ALL 0x0D struct fb_event { struct fb_info *info; @@ -557,7 +562,7 @@ struct fb_pixmap { * Frame buffer operations * * LOCKING NOTE: those functions must _ALL_ be called with the console - * semaphore held, this is the only suitable locking mechanism we have + * semaphore held, this is the only suitable locking mecanism we have * in 2.6. Some may be called at interrupt time at this point though. */ @@ -887,6 +892,7 @@ extern int fb_get_color_depth(struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix); extern int fb_get_options(char *name, char **option); extern int fb_new_modelist(struct fb_info *info); +extern int fb_con_duit(struct fb_info *info, int event, void *data); extern struct fb_info *registered_fb[FB_MAX]; extern int num_registered_fb; diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index e04a5cfe874f..2d8b348c1192 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -392,7 +392,7 @@ struct address_space { unsigned int truncate_count; /* Cover race condition with truncate */ unsigned long nrpages; /* number of total pages */ pgoff_t writeback_index;/* writeback starts here */ - const struct address_space_operations *a_ops; /* methods */ + struct address_space_operations *a_ops; /* methods */ unsigned long flags; /* error bits/gfp mask */ struct backing_dev_info *backing_dev_info; /* device readahead, etc */ spinlock_t private_lock; /* for use by the address_space */ @@ -1405,7 +1405,7 @@ extern void bd_forget(struct inode *inode); extern void bdput(struct block_device *); extern struct block_device *open_by_devnum(dev_t, unsigned); extern const struct file_operations def_blk_fops; -extern const struct address_space_operations def_blk_aops; +extern struct address_space_operations def_blk_aops; extern const struct file_operations def_chr_fops; extern const struct file_operations bad_sock_fops; extern const struct file_operations def_fifo_fops; diff --git a/trunk/include/linux/futex.h b/trunk/include/linux/futex.h index 34c3a215f2cd..966a5b3da439 100644 --- a/trunk/include/linux/futex.h +++ b/trunk/include/linux/futex.h @@ -12,9 +12,6 @@ #define FUTEX_REQUEUE 3 #define FUTEX_CMP_REQUEUE 4 #define FUTEX_WAKE_OP 5 -#define FUTEX_LOCK_PI 6 -#define FUTEX_UNLOCK_PI 7 -#define FUTEX_TRYLOCK_PI 8 /* * Support for robust futexes: the kernel cleans up held futexes at @@ -93,21 +90,18 @@ struct robust_list_head { */ #define ROBUST_LIST_LIMIT 2048 -long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout, - u32 __user *uaddr2, u32 val2, u32 val3); +long do_futex(unsigned long uaddr, int op, int val, + unsigned long timeout, unsigned long uaddr2, int val2, + int val3); extern int handle_futex_death(u32 __user *uaddr, struct task_struct *curr); #ifdef CONFIG_FUTEX extern void exit_robust_list(struct task_struct *curr); -extern void exit_pi_state_list(struct task_struct *curr); #else static inline void exit_robust_list(struct task_struct *curr) { } -static inline void exit_pi_state_list(struct task_struct *curr) -{ -} #endif #define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */ diff --git a/trunk/include/linux/genhd.h b/trunk/include/linux/genhd.h index e4af57e87c17..3498a0c68184 100644 --- a/trunk/include/linux/genhd.h +++ b/trunk/include/linux/genhd.h @@ -112,6 +112,8 @@ struct gendisk { sector_t capacity; int flags; + char devfs_name[64]; /* devfs crap */ + int number; /* more of the same */ struct device *driverfs_dev; struct kobject kobj; struct kobject *holder_dir; diff --git a/trunk/include/linux/hw_random.h b/trunk/include/linux/hw_random.h deleted file mode 100644 index 21ea7610e177..000000000000 --- a/trunk/include/linux/hw_random.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - Hardware Random Number Generator - - Please read Documentation/hw_random.txt for details on use. - - ---------------------------------------------------------- - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - */ - -#ifndef LINUX_HWRANDOM_H_ -#define LINUX_HWRANDOM_H_ -#ifdef __KERNEL__ - -#include -#include - -/** - * struct hwrng - Hardware Random Number Generator driver - * @name: Unique RNG name. - * @init: Initialization callback (can be NULL). - * @cleanup: Cleanup callback (can be NULL). - * @data_present: Callback to determine if data is available - * on the RNG. If NULL, it is assumed that - * there is always data available. - * @data_read: Read data from the RNG device. - * Returns the number of lower random bytes in "data". - * Must not be NULL. - * @priv: Private data, for use by the RNG driver. - */ -struct hwrng { - const char *name; - int (*init)(struct hwrng *rng); - void (*cleanup)(struct hwrng *rng); - int (*data_present)(struct hwrng *rng); - int (*data_read)(struct hwrng *rng, u32 *data); - unsigned long priv; - - /* internal. */ - struct list_head list; -}; - -/** Register a new Hardware Random Number Generator driver. */ -extern int hwrng_register(struct hwrng *rng); -/** Unregister a Hardware Random Number Generator driver. */ -extern void hwrng_unregister(struct hwrng *rng); - -#endif /* __KERNEL__ */ -#endif /* LINUX_HWRANDOM_H_ */ diff --git a/trunk/include/linux/ide.h b/trunk/include/linux/ide.h index 285316c836b5..ef7bef207f48 100644 --- a/trunk/include/linux/ide.h +++ b/trunk/include/linux/ide.h @@ -552,6 +552,7 @@ typedef struct ide_drive_s { struct hd_driveid *id; /* drive model identification info */ struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ struct ide_settings_s *settings;/* /proc/ide/ drive settings */ + char devfs_name[64]; /* devfs crap */ struct hwif_s *hwif; /* actually (ide_hwif_t *) */ @@ -792,7 +793,6 @@ typedef struct hwif_s { unsigned auto_poll : 1; /* supports nop auto-poll */ unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */ unsigned no_io_32bit : 1; /* 1 = can not do 32-bit IO ops */ - unsigned err_stops_fifo : 1; /* 1=data FIFO is cleared by an error */ struct device gendev; struct completion gendev_rel_comp; /* To deal with device release() */ diff --git a/trunk/include/linux/idr.h b/trunk/include/linux/idr.h index f559a719dbe8..d37c8d808b0f 100644 --- a/trunk/include/linux/idr.h +++ b/trunk/include/linux/idr.h @@ -78,7 +78,6 @@ void *idr_find(struct idr *idp, int id); int idr_pre_get(struct idr *idp, gfp_t gfp_mask); int idr_get_new(struct idr *idp, void *ptr, int *id); int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id); -void *idr_replace(struct idr *idp, void *ptr, int id); void idr_remove(struct idr *idp, int id); void idr_destroy(struct idr *idp); void idr_init(struct idr *idp); diff --git a/trunk/include/linux/init_task.h b/trunk/include/linux/init_task.h index 3a256957fb56..41ecbb847f32 100644 --- a/trunk/include/linux/init_task.h +++ b/trunk/include/linux/init_task.h @@ -87,7 +87,6 @@ extern struct group_info init_groups; .lock_depth = -1, \ .prio = MAX_PRIO-20, \ .static_prio = MAX_PRIO-20, \ - .normal_prio = MAX_PRIO-20, \ .policy = SCHED_NORMAL, \ .cpus_allowed = CPU_MASK_ALL, \ .mm = NULL, \ @@ -120,11 +119,10 @@ extern struct group_info init_groups; .signal = {{0}}}, \ .blocked = {{0}}, \ .alloc_lock = SPIN_LOCK_UNLOCKED, \ + .proc_lock = SPIN_LOCK_UNLOCKED, \ .journal_info = NULL, \ .cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \ .fs_excl = ATOMIC_INIT(0), \ - .pi_lock = SPIN_LOCK_UNLOCKED, \ - INIT_RT_MUTEXES(tsk) \ } diff --git a/trunk/include/linux/input.h b/trunk/include/linux/input.h index 56f1e0e1e598..b32c2b6e53f6 100644 --- a/trunk/include/linux/input.h +++ b/trunk/include/linux/input.h @@ -232,8 +232,7 @@ struct input_absinfo { #define KEY_PAUSE 119 #define KEY_KPCOMMA 121 -#define KEY_HANGEUL 122 -#define KEY_HANGUEL KEY_HANGEUL +#define KEY_HANGUEL 122 #define KEY_HANJA 123 #define KEY_YEN 124 #define KEY_LEFTMETA 125 @@ -1006,7 +1005,6 @@ static inline void init_input_dev(struct input_dev *dev) } struct input_dev *input_allocate_device(void); -void input_free_device(struct input_dev *dev); static inline struct input_dev *input_get_device(struct input_dev *dev) { @@ -1018,6 +1016,12 @@ static inline void input_put_device(struct input_dev *dev) class_device_put(&dev->cdev); } +static inline void input_free_device(struct input_dev *dev) +{ + if (dev) + input_put_device(dev); +} + int input_register_device(struct input_dev *); void input_unregister_device(struct input_dev *); diff --git a/trunk/include/linux/interrupt.h b/trunk/include/linux/interrupt.h index cf682a73a6f9..70741e170114 100644 --- a/trunk/include/linux/interrupt.h +++ b/trunk/include/linux/interrupt.h @@ -14,53 +14,6 @@ #include #include -/* - * These correspond to the IORESOURCE_IRQ_* defines in - * linux/ioport.h to select the interrupt line behaviour. When - * requesting an interrupt without specifying a IRQF_TRIGGER, the - * setting should be assumed to be "as already configured", which - * may be as per machine or firmware initialisation. - */ -#define IRQF_TRIGGER_NONE 0x00000000 -#define IRQF_TRIGGER_RISING 0x00000001 -#define IRQF_TRIGGER_FALLING 0x00000002 -#define IRQF_TRIGGER_HIGH 0x00000004 -#define IRQF_TRIGGER_LOW 0x00000008 -#define IRQF_TRIGGER_MASK (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | \ - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING) -#define IRQF_TRIGGER_PROBE 0x00000010 - -/* - * These flags used only by the kernel as part of the - * irq handling routines. - * - * IRQF_DISABLED - keep irqs disabled when calling the action handler - * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator - * IRQF_SHARED - allow sharing the irq among several devices - * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur - * IRQF_TIMER - Flag to mark this interrupt as timer interrupt - */ -#define IRQF_DISABLED 0x00000020 -#define IRQF_SAMPLE_RANDOM 0x00000040 -#define IRQF_SHARED 0x00000080 -#define IRQF_PROBE_SHARED 0x00000100 -#define IRQF_TIMER 0x00000200 - -/* - * Migration helpers. Scheduled for removal in 1/2007 - * Do not use for new code ! - */ -#define SA_INTERRUPT IRQF_DISABLED -#define SA_SAMPLE_RANDOM IRQF_SAMPLE_RANDOM -#define SA_SHIRQ IRQF_SHARED -#define SA_PROBEIRQ IRQF_PROBE_SHARED - -#define SA_TRIGGER_LOW IRQF_TRIGGER_LOW -#define SA_TRIGGER_HIGH IRQF_TRIGGER_HIGH -#define SA_TRIGGER_FALLING IRQF_TRIGGER_FALLING -#define SA_TRIGGER_RISING IRQF_TRIGGER_RISING -#define SA_TRIGGER_MASK IRQF_TRIGGER_MASK - struct irqaction { irqreturn_t (*handler)(int, void *, struct pt_regs *); unsigned long flags; @@ -83,20 +36,6 @@ extern void free_irq(unsigned int, void *); extern void disable_irq_nosync(unsigned int irq); extern void disable_irq(unsigned int irq); extern void enable_irq(unsigned int irq); - -/* IRQ wakeup (PM) control: */ -extern int set_irq_wake(unsigned int irq, unsigned int on); - -static inline int enable_irq_wake(unsigned int irq) -{ - return set_irq_wake(irq, 1); -} - -static inline int disable_irq_wake(unsigned int irq) -{ - return set_irq_wake(irq, 0); -} - #endif #ifndef __ARCH_SET_SOFTIRQ_PENDING diff --git a/trunk/include/linux/ioport.h b/trunk/include/linux/ioport.h index 87a9fc039b47..cd6bd001ba4e 100644 --- a/trunk/include/linux/ioport.h +++ b/trunk/include/linux/ioport.h @@ -9,15 +9,13 @@ #define _LINUX_IOPORT_H #include -#include /* * Resources are tree-like, allowing * nesting etc.. */ struct resource { - resource_size_t start; - resource_size_t end; const char *name; + unsigned long start, end; unsigned long flags; struct resource *parent, *sibling, *child; }; @@ -98,37 +96,31 @@ extern struct resource * ____request_resource(struct resource *root, struct reso extern int release_resource(struct resource *new); extern __deprecated_for_modules int insert_resource(struct resource *parent, struct resource *new); extern int allocate_resource(struct resource *root, struct resource *new, - resource_size_t size, resource_size_t min, - resource_size_t max, resource_size_t align, + unsigned long size, + unsigned long min, unsigned long max, + unsigned long align, void (*alignf)(void *, struct resource *, - resource_size_t, resource_size_t), + unsigned long, unsigned long), void *alignf_data); -int adjust_resource(struct resource *res, resource_size_t start, - resource_size_t size); - -/* get registered SYSTEM_RAM resources in specified area */ -extern int find_next_system_ram(struct resource *res); +int adjust_resource(struct resource *res, unsigned long start, + unsigned long size); /* Convenience shorthand with allocation */ #define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name)) #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name)) #define rename_region(region, newname) do { (region)->name = (newname); } while (0) -extern struct resource * __request_region(struct resource *, - resource_size_t start, - resource_size_t n, const char *name); +extern struct resource * __request_region(struct resource *, unsigned long start, unsigned long n, const char *name); /* Compatibility cruft */ #define release_region(start,n) __release_region(&ioport_resource, (start), (n)) #define check_mem_region(start,n) __check_region(&iomem_resource, (start), (n)) #define release_mem_region(start,n) __release_region(&iomem_resource, (start), (n)) -extern int __check_region(struct resource *, resource_size_t, resource_size_t); -extern void __release_region(struct resource *, resource_size_t, - resource_size_t); +extern int __check_region(struct resource *, unsigned long, unsigned long); +extern void __release_region(struct resource *, unsigned long, unsigned long); -static inline int __deprecated check_region(resource_size_t s, - resource_size_t n) +static inline int __deprecated check_region(unsigned long s, unsigned long n) { return __check_region(&ioport_resource, s, n); } diff --git a/trunk/include/linux/ipmi.h b/trunk/include/linux/ipmi.h index d09fbeabf1dc..5653b2f23b6a 100644 --- a/trunk/include/linux/ipmi.h +++ b/trunk/include/linux/ipmi.h @@ -210,7 +210,11 @@ struct kernel_ipmi_msg #include #include #include + +#ifdef CONFIG_PROC_FS #include +extern struct proc_dir_entry *proc_ipmi_root; +#endif /* CONFIG_PROC_FS */ /* Opaque type for a IPMI message user. One of these is needed to send and receive messages. */ diff --git a/trunk/include/linux/irq.h b/trunk/include/linux/irq.h index 95d7aa7954d2..676e00dfb21a 100644 --- a/trunk/include/linux/irq.h +++ b/trunk/include/linux/irq.h @@ -1,5 +1,5 @@ -#ifndef _LINUX_IRQ_H -#define _LINUX_IRQ_H +#ifndef __irq_h +#define __irq_h /* * Please do not include this file in generic code. There is currently @@ -11,7 +11,7 @@ #include -#ifndef CONFIG_S390 +#if !defined(CONFIG_S390) #include #include @@ -24,168 +24,84 @@ /* * IRQ line status. - * - * Bits 0-16 are reserved for the IRQF_* bits in linux/interrupt.h - * - * IRQ types */ -#define IRQ_TYPE_NONE 0x00000000 /* Default, unspecified type */ -#define IRQ_TYPE_EDGE_RISING 0x00000001 /* Edge rising type */ -#define IRQ_TYPE_EDGE_FALLING 0x00000002 /* Edge falling type */ -#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) -#define IRQ_TYPE_LEVEL_HIGH 0x00000004 /* Level high type */ -#define IRQ_TYPE_LEVEL_LOW 0x00000008 /* Level low type */ -#define IRQ_TYPE_SENSE_MASK 0x0000000f /* Mask of the above */ -#define IRQ_TYPE_PROBE 0x00000010 /* Probing in progress */ - -/* Internal flags */ -#define IRQ_INPROGRESS 0x00010000 /* IRQ handler active - do not enter! */ -#define IRQ_DISABLED 0x00020000 /* IRQ disabled - do not enter! */ -#define IRQ_PENDING 0x00040000 /* IRQ pending - replay on enable */ -#define IRQ_REPLAY 0x00080000 /* IRQ has been replayed but not acked yet */ -#define IRQ_AUTODETECT 0x00100000 /* IRQ is being autodetected */ -#define IRQ_WAITING 0x00200000 /* IRQ not yet seen - for autodetection */ -#define IRQ_LEVEL 0x00400000 /* IRQ level triggered */ -#define IRQ_MASKED 0x00800000 /* IRQ masked - shouldn't be seen again */ -#ifdef CONFIG_IRQ_PER_CPU -# define IRQ_PER_CPU 0x01000000 /* IRQ is per CPU */ +#define IRQ_INPROGRESS 1 /* IRQ handler active - do not enter! */ +#define IRQ_DISABLED 2 /* IRQ disabled - do not enter! */ +#define IRQ_PENDING 4 /* IRQ pending - replay on enable */ +#define IRQ_REPLAY 8 /* IRQ has been replayed but not acked yet */ +#define IRQ_AUTODETECT 16 /* IRQ is being autodetected */ +#define IRQ_WAITING 32 /* IRQ not yet seen - for autodetection */ +#define IRQ_LEVEL 64 /* IRQ level triggered */ +#define IRQ_MASKED 128 /* IRQ masked - shouldn't be seen again */ +#if defined(ARCH_HAS_IRQ_PER_CPU) +# define IRQ_PER_CPU 256 /* IRQ is per CPU */ # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU) #else # define CHECK_IRQ_PER_CPU(var) 0 #endif -#define IRQ_NOPROBE 0x02000000 /* IRQ is not valid for probing */ -#define IRQ_NOREQUEST 0x04000000 /* IRQ cannot be requested */ -#define IRQ_NOAUTOEN 0x08000000 /* IRQ will not be enabled on request irq */ -#define IRQ_DELAYED_DISABLE 0x10000000 /* IRQ disable (masking) happens delayed. */ - -struct proc_dir_entry; - -/** - * struct irq_chip - hardware interrupt chip descriptor - * - * @name: name for /proc/interrupts - * @startup: start up the interrupt (defaults to ->enable if NULL) - * @shutdown: shut down the interrupt (defaults to ->disable if NULL) - * @enable: enable the interrupt (defaults to chip->unmask if NULL) - * @disable: disable the interrupt (defaults to chip->mask if NULL) - * @ack: start of a new interrupt - * @mask: mask an interrupt source - * @mask_ack: ack and mask an interrupt source - * @unmask: unmask an interrupt source - * @eoi: end of interrupt - chip level - * @end: end of interrupt - flow level - * @set_affinity: set the CPU affinity on SMP machines - * @retrigger: resend an IRQ to the CPU - * @set_type: set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ - * @set_wake: enable/disable power-management wake-on of an IRQ - * - * @release: release function solely used by UML - * @typename: obsoleted by name, kept as migration helper +/* + * Interrupt controller descriptor. This is all we need + * to describe about the low-level hardware. */ -struct irq_chip { - const char *name; - unsigned int (*startup)(unsigned int irq); - void (*shutdown)(unsigned int irq); - void (*enable)(unsigned int irq); - void (*disable)(unsigned int irq); - - void (*ack)(unsigned int irq); - void (*mask)(unsigned int irq); - void (*mask_ack)(unsigned int irq); - void (*unmask)(unsigned int irq); - void (*eoi)(unsigned int irq); - - void (*end)(unsigned int irq); - void (*set_affinity)(unsigned int irq, cpumask_t dest); - int (*retrigger)(unsigned int irq); - int (*set_type)(unsigned int irq, unsigned int flow_type); - int (*set_wake)(unsigned int irq, unsigned int on); - +struct hw_interrupt_type { + const char * typename; + unsigned int (*startup)(unsigned int irq); + void (*shutdown)(unsigned int irq); + void (*enable)(unsigned int irq); + void (*disable)(unsigned int irq); + void (*ack)(unsigned int irq); + void (*end)(unsigned int irq); + void (*set_affinity)(unsigned int irq, cpumask_t dest); /* Currently used only by UML, might disappear one day.*/ #ifdef CONFIG_IRQ_RELEASE_METHOD - void (*release)(unsigned int irq, void *dev_id); + void (*release)(unsigned int irq, void *dev_id); #endif - /* - * For compatibility, ->typename is copied into ->name. - * Will disappear. - */ - const char *typename; }; -/** - * struct irq_desc - interrupt descriptor - * - * @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()] - * @chip: low level interrupt hardware access - * @handler_data: per-IRQ data for the irq_chip methods - * @chip_data: platform-specific per-chip private data for the chip - * methods, to allow shared chip implementations - * @action: the irq action chain - * @status: status information - * @depth: disable-depth, for nested irq_disable() calls - * @irq_count: stats field to detect stalled irqs - * @irqs_unhandled: stats field for spurious unhandled interrupts - * @lock: locking for SMP - * @affinity: IRQ affinity on SMP - * @cpu: cpu index useful for balancing - * @pending_mask: pending rebalanced interrupts - * @move_irq: need to re-target IRQ destination - * @dir: /proc/irq/ procfs entry - * @affinity_entry: /proc/irq/smp_affinity procfs entry on SMP +typedef struct hw_interrupt_type hw_irq_controller; + +/* + * This is the "IRQ descriptor", which contains various information + * about the irq, including what kind of hardware handling it has, + * whether it is disabled etc etc. * * Pad this out to 32 bytes for cache and indexing reasons. */ -struct irq_desc { - void fastcall (*handle_irq)(unsigned int irq, - struct irq_desc *desc, - struct pt_regs *regs); - struct irq_chip *chip; - void *handler_data; - void *chip_data; - struct irqaction *action; /* IRQ action list */ - unsigned int status; /* IRQ status */ - - unsigned int depth; /* nested irq disables */ - unsigned int irq_count; /* For detecting broken IRQs */ - unsigned int irqs_unhandled; - spinlock_t lock; -#ifdef CONFIG_SMP - cpumask_t affinity; - unsigned int cpu; -#endif -#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE) - cpumask_t pending_mask; - unsigned int move_irq; /* need to re-target IRQ dest */ -#endif -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *dir; +typedef struct irq_desc { + hw_irq_controller *handler; + void *handler_data; + struct irqaction *action; /* IRQ action list */ + unsigned int status; /* IRQ status */ + unsigned int depth; /* nested irq disables */ + unsigned int irq_count; /* For detecting broken interrupts */ + unsigned int irqs_unhandled; + spinlock_t lock; +#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE) + unsigned int move_irq; /* Flag need to re-target intr dest*/ #endif -} ____cacheline_aligned; +} ____cacheline_aligned irq_desc_t; -extern struct irq_desc irq_desc[NR_IRQS]; +extern irq_desc_t irq_desc [NR_IRQS]; -/* - * Migration helpers for obsolete names, they will go away: - */ -#define hw_interrupt_type irq_chip -typedef struct irq_chip hw_irq_controller; -#define no_irq_type no_irq_chip -typedef struct irq_desc irq_desc_t; +/* Return a pointer to the irq descriptor for IRQ. */ +static inline irq_desc_t * +irq_descp (int irq) +{ + return irq_desc + irq; +} -/* - * Pick up the arch-dependent methods: - */ -#include +#include /* the arch dependent stuff */ -extern int setup_irq(unsigned int irq, struct irqaction *new); +extern int setup_irq(unsigned int irq, struct irqaction * new); #ifdef CONFIG_GENERIC_HARDIRQS +extern cpumask_t irq_affinity[NR_IRQS]; #ifdef CONFIG_SMP static inline void set_native_irq_info(int irq, cpumask_t mask) { - irq_desc[irq].affinity = mask; + irq_affinity[irq] = mask; } #else static inline void set_native_irq_info(int irq, cpumask_t mask) @@ -195,7 +111,8 @@ static inline void set_native_irq_info(int irq, cpumask_t mask) #ifdef CONFIG_SMP -#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE) +#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE) +extern cpumask_t pending_irq_cpumask[NR_IRQS]; void set_pending_irq(unsigned int irq, cpumask_t mask); void move_native_irq(int irq); @@ -216,7 +133,7 @@ static inline void set_irq_info(int irq, cpumask_t mask) { } -#else /* CONFIG_PCI_MSI */ +#else // CONFIG_PCI_MSI static inline void move_irq(int irq) { @@ -227,36 +144,26 @@ static inline void set_irq_info(int irq, cpumask_t mask) { set_native_irq_info(irq, mask); } +#endif // CONFIG_PCI_MSI -#endif /* CONFIG_PCI_MSI */ - -#else /* CONFIG_GENERIC_PENDING_IRQ || CONFIG_IRQBALANCE */ - -static inline void move_irq(int irq) -{ -} - -static inline void move_native_irq(int irq) -{ -} - -static inline void set_pending_irq(unsigned int irq, cpumask_t mask) -{ -} +#else // CONFIG_GENERIC_PENDING_IRQ || CONFIG_IRQBALANCE +#define move_irq(x) +#define move_native_irq(x) +#define set_pending_irq(x,y) static inline void set_irq_info(int irq, cpumask_t mask) { set_native_irq_info(irq, mask); } -#endif /* CONFIG_GENERIC_PENDING_IRQ */ +#endif // CONFIG_GENERIC_PENDING_IRQ -#else /* CONFIG_SMP */ +#else // CONFIG_SMP #define move_irq(x) #define move_native_irq(x) -#endif /* CONFIG_SMP */ +#endif // CONFIG_SMP #ifdef CONFIG_IRQBALANCE extern void set_balance_irq_affinity(unsigned int irq, cpumask_t mask); @@ -266,139 +173,32 @@ static inline void set_balance_irq_affinity(unsigned int irq, cpumask_t mask) } #endif -#ifdef CONFIG_AUTO_IRQ_AFFINITY -extern int select_smp_affinity(unsigned int irq); -#else -static inline int select_smp_affinity(unsigned int irq) -{ - return 1; -} -#endif - extern int no_irq_affinity; - -/* Handle irq action chains: */ -extern int handle_IRQ_event(unsigned int irq, struct pt_regs *regs, - struct irqaction *action); - -/* - * Built-in IRQ handlers for various IRQ types, - * callable via desc->chip->handle_irq() - */ -extern void fastcall -handle_level_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs); -extern void fastcall -handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc, - struct pt_regs *regs); -extern void fastcall -handle_edge_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs); -extern void fastcall -handle_simple_irq(unsigned int irq, struct irq_desc *desc, - struct pt_regs *regs); -extern void fastcall -handle_percpu_irq(unsigned int irq, struct irq_desc *desc, - struct pt_regs *regs); -extern void fastcall -handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs); - -/* - * Get a descriptive string for the highlevel handler, for - * /proc/interrupts output: - */ -extern const char * -handle_irq_name(void fastcall (*handle)(unsigned int, struct irq_desc *, - struct pt_regs *)); - -/* - * Monolithic do_IRQ implementation. - * (is an explicit fastcall, because i386 4KSTACKS calls it from assembly) - */ -extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); - -/* - * Architectures call this to let the generic IRQ layer - * handle an interrupt. If the descriptor is attached to an - * irqchip-style controller then we call the ->handle_irq() handler, - * and it calls __do_IRQ() if it's attached to an irqtype-style controller. - */ -static inline void generic_handle_irq(unsigned int irq, struct pt_regs *regs) -{ - struct irq_desc *desc = irq_desc + irq; - - if (likely(desc->handle_irq)) - desc->handle_irq(irq, desc, regs); - else - __do_IRQ(irq, regs); -} - -/* Handling of unhandled and spurious interrupts: */ -extern void note_interrupt(unsigned int irq, struct irq_desc *desc, - int action_ret, struct pt_regs *regs); - -/* Resending of interrupts :*/ -void check_irq_resend(struct irq_desc *desc, unsigned int irq); - -/* Initialize /proc/irq/ */ -extern void init_irq_proc(void); - -/* Enable/disable irq debugging output: */ extern int noirqdebug_setup(char *str); -/* Checks whether the interrupt can be requested by request_irq(): */ +extern fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs, + struct irqaction *action); +extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); +extern void note_interrupt(unsigned int irq, irq_desc_t *desc, + int action_ret, struct pt_regs *regs); extern int can_request_irq(unsigned int irq, unsigned long irqflags); -/* Dummy irq-chip implementations: */ -extern struct irq_chip no_irq_chip; -extern struct irq_chip dummy_irq_chip; - -extern void -set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, - void fastcall (*handle)(unsigned int, - struct irq_desc *, - struct pt_regs *)); -extern void -__set_irq_handler(unsigned int irq, - void fastcall (*handle)(unsigned int, struct irq_desc *, - struct pt_regs *), - int is_chained); - -/* - * Set a highlevel flow handler for a given IRQ: - */ -static inline void -set_irq_handler(unsigned int irq, - void fastcall (*handle)(unsigned int, struct irq_desc *, - struct pt_regs *)) -{ - __set_irq_handler(irq, handle, 0); -} +extern void init_irq_proc(void); -/* - * Set a highlevel chained flow handler for a given IRQ. - * (a chained handler is automatically enabled and set to - * IRQ_NOREQUEST and IRQ_NOPROBE) - */ -static inline void -set_irq_chained_handler(unsigned int irq, - void fastcall (*handle)(unsigned int, struct irq_desc *, - struct pt_regs *)) +#ifdef CONFIG_AUTO_IRQ_AFFINITY +extern int select_smp_affinity(unsigned int irq); +#else +static inline int +select_smp_affinity(unsigned int irq) { - __set_irq_handler(irq, handle, 1); + return 1; } +#endif -/* Set/get chip/data for an IRQ: */ - -extern int set_irq_chip(unsigned int irq, struct irq_chip *chip); -extern int set_irq_data(unsigned int irq, void *data); -extern int set_irq_chip_data(unsigned int irq, void *data); -extern int set_irq_type(unsigned int irq, unsigned int type); - -#define get_irq_chip(irq) (irq_desc[irq].chip) -#define get_irq_chip_data(irq) (irq_desc[irq].chip_data) -#define get_irq_data(irq) (irq_desc[irq].handler_data) +#endif -#endif /* CONFIG_GENERIC_HARDIRQS */ +extern hw_irq_controller no_irq_type; /* needed in every arch ? */ -#endif /* !CONFIG_S390 */ +#endif -#endif /* _LINUX_IRQ_H */ +#endif /* __irq_h */ diff --git a/trunk/include/linux/isdn/tpam.h b/trunk/include/linux/isdn/tpam.h new file mode 100644 index 000000000000..d18dd0dc570d --- /dev/null +++ b/trunk/include/linux/isdn/tpam.h @@ -0,0 +1,55 @@ +/* $Id: tpam.h,v 1.1.2.1 2001/06/08 08:23:46 kai Exp $ + * + * Turbo PAM ISDN driver for Linux. (Kernel Driver) + * + * Copyright 2001 Stelian Pop , Alcôve + * + * For all support questions please contact: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _TPAM_H_ +#define _TPAM_H_ + +#include + +/* IOCTL commands */ +#define TPAM_CMD_DSPLOAD 0x0001 +#define TPAM_CMD_DSPSAVE 0x0002 +#define TPAM_CMD_DSPRUN 0x0003 +#define TPAM_CMD_LOOPMODEON 0x0004 +#define TPAM_CMD_LOOPMODEOFF 0x0005 + +/* addresses of debug information zones on board */ +#define TPAM_TRAPAUDIT_REGISTER 0x005493e4 +#define TPAM_NCOAUDIT_REGISTER 0x00500000 +#define TPAM_MSGAUDIT_REGISTER 0x008E30F0 + +/* length of debug information zones on board */ +#define TPAM_TRAPAUDIT_LENGTH 10000 +#define TPAM_NCOAUDIT_LENGTH 300000 +#define TPAM_NCOAUDIT_COUNT 30 +#define TPAM_MSGAUDIT_LENGTH 60000 + +/* IOCTL load/save parameter */ +typedef struct tpam_dsp_ioctl { + __u32 address; /* address to load/save data */ + __u32 data_len; /* size of data to be loaded/saved */ + __u8 data[0]; /* data */ +} tpam_dsp_ioctl; + +#endif /* _TPAM_H_ */ diff --git a/trunk/include/linux/jffs2.h b/trunk/include/linux/jffs2.h index c9c760700bc3..c6f70660b371 100644 --- a/trunk/include/linux/jffs2.h +++ b/trunk/include/linux/jffs2.h @@ -186,7 +186,6 @@ struct jffs2_raw_xref jint32_t hdr_crc; jint32_t ino; /* inode number */ jint32_t xid; /* XATTR identifier number */ - jint32_t xseqno; /* xref sequencial number */ jint32_t node_crc; } __attribute__((packed)); diff --git a/trunk/include/linux/kbd_kern.h b/trunk/include/linux/kbd_kern.h index efe0ee4cc80b..4eb851ece080 100644 --- a/trunk/include/linux/kbd_kern.h +++ b/trunk/include/linux/kbd_kern.h @@ -155,8 +155,10 @@ static inline void con_schedule_flip(struct tty_struct *t) { unsigned long flags; spin_lock_irqsave(&t->buf.lock, flags); - if (t->buf.tail != NULL) + if (t->buf.tail != NULL) { + t->buf.tail->active = 0; t->buf.tail->commit = t->buf.tail->used; + } spin_unlock_irqrestore(&t->buf.lock, flags); schedule_work(&t->buf.work); } diff --git a/trunk/include/linux/kernel.h b/trunk/include/linux/kernel.h index 5c1ec1f84eab..3c5e4c2e517d 100644 --- a/trunk/include/linux/kernel.h +++ b/trunk/include/linux/kernel.h @@ -32,7 +32,6 @@ extern const char linux_banner[]; #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) -#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) #define KERN_EMERG "<0>" /* system is unusable */ #define KERN_ALERT "<1>" /* action must be taken immediately */ @@ -337,12 +336,6 @@ struct sysinfo { /* Force a compilation error if condition is true */ #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) -/* Force a compilation error if condition is true, but also produce a - result (of value 0 and type size_t), so the expression can be used - e.g. in a structure initializer (or where-ever else comma expressions - aren't permitted). */ -#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1) - /* Trap pasters of __FUNCTION__ at compile-time */ #define __FUNCTION__ (__func__) diff --git a/trunk/include/linux/key.h b/trunk/include/linux/key.h index 169f05e4863e..e81ebf910d0b 100644 --- a/trunk/include/linux/key.h +++ b/trunk/include/linux/key.h @@ -177,8 +177,7 @@ struct key { /* * kernel managed key type definition */ -typedef int (*request_key_actor_t)(struct key *key, struct key *authkey, - const char *op, void *aux); +typedef int (*request_key_actor_t)(struct key *key, struct key *authkey, const char *op); struct key_type { /* name of the type */ @@ -249,14 +248,7 @@ extern struct key *key_alloc(struct key_type *type, const char *desc, uid_t uid, gid_t gid, struct task_struct *ctx, - key_perm_t perm, - unsigned long flags); - - -#define KEY_ALLOC_IN_QUOTA 0x0000 /* add to quota, reject if would overrun */ -#define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ -#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ - + key_perm_t perm, int not_in_quota); extern int key_payload_reserve(struct key *key, size_t datalen); extern int key_instantiate_and_link(struct key *key, const void *data, @@ -286,11 +278,6 @@ extern struct key *request_key(struct key_type *type, const char *description, const char *callout_info); -extern struct key *request_key_with_auxdata(struct key_type *type, - const char *description, - const char *callout_info, - void *aux); - extern int key_validate(struct key *key); extern key_ref_t key_create_or_update(key_ref_t keyring, @@ -298,7 +285,7 @@ extern key_ref_t key_create_or_update(key_ref_t keyring, const char *description, const void *payload, size_t plen, - unsigned long flags); + int not_in_quota); extern int key_update(key_ref_t key, const void *payload, @@ -312,7 +299,7 @@ extern int key_unlink(struct key *keyring, extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, struct task_struct *ctx, - unsigned long flags, + int not_in_quota, struct key *dest); extern int keyring_clear(struct key *keyring); diff --git a/trunk/include/linux/kobject.h b/trunk/include/linux/kobject.h index 0503b2ed8bae..2d229327959e 100644 --- a/trunk/include/linux/kobject.h +++ b/trunk/include/linux/kobject.h @@ -46,8 +46,6 @@ enum kobject_action { KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices (broken) */ KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* device offline */ KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* device online */ - KOBJ_UNDOCK = (__force kobject_action_t) 0x08, /* undocking */ - KOBJ_DOCK = (__force kobject_action_t) 0x09, /* dock */ }; struct kobject { diff --git a/trunk/include/linux/libata.h b/trunk/include/linux/libata.h index f4284bf89758..20b1cf527c60 100644 --- a/trunk/include/linux/libata.h +++ b/trunk/include/linux/libata.h @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -888,9 +887,6 @@ static inline unsigned int ata_tag_internal(unsigned int tag) return tag == ATA_MAX_QUEUE - 1; } -/* - * device helpers - */ static inline unsigned int ata_class_enabled(unsigned int class) { return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI; @@ -921,17 +917,6 @@ static inline unsigned int ata_dev_absent(const struct ata_device *dev) return ata_class_absent(dev->class); } -/* - * port helpers - */ -static inline int ata_port_max_devices(const struct ata_port *ap) -{ - if (ap->flags & ATA_FLAG_SLAVE_POSS) - return 2; - return 1; -} - - static inline u8 ata_chk_status(struct ata_port *ap) { return ap->ops->check_status(ap); diff --git a/trunk/include/linux/license.h b/trunk/include/linux/license.h deleted file mode 100644 index decdbf43cb5c..000000000000 --- a/trunk/include/linux/license.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __LICENSE_H -#define __LICENSE_H - -static inline int license_is_gpl_compatible(const char *license) -{ - return (strcmp(license, "GPL") == 0 - || strcmp(license, "GPL v2") == 0 - || strcmp(license, "GPL and additional rights") == 0 - || strcmp(license, "Dual BSD/GPL") == 0 - || strcmp(license, "Dual MIT/GPL") == 0 - || strcmp(license, "Dual MPL/GPL") == 0); -} - -#endif diff --git a/trunk/include/linux/list.h b/trunk/include/linux/list.h index 6b74adf5297f..37ca31b21bb7 100644 --- a/trunk/include/linux/list.h +++ b/trunk/include/linux/list.h @@ -4,10 +4,17 @@ #ifdef __KERNEL__ #include -#include #include #include +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + /* * Simple doubly linked list implementation. * diff --git a/trunk/include/linux/loop.h b/trunk/include/linux/loop.h index e76c7611d6cc..bf3d2345ce99 100644 --- a/trunk/include/linux/loop.h +++ b/trunk/include/linux/loop.h @@ -59,7 +59,7 @@ struct loop_device { struct bio *lo_bio; struct bio *lo_biotail; int lo_state; - struct completion lo_done; + struct task_struct *lo_thread; struct completion lo_bh_done; struct mutex lo_ctl_mutex; int lo_pending; diff --git a/trunk/include/linux/memory_hotplug.h b/trunk/include/linux/memory_hotplug.h index 218501cfaeb9..911206386171 100644 --- a/trunk/include/linux/memory_hotplug.h +++ b/trunk/include/linux/memory_hotplug.h @@ -63,76 +63,6 @@ extern int online_pages(unsigned long, unsigned long); /* reasonably generic interface to expand the physical pages in a zone */ extern int __add_pages(struct zone *zone, unsigned long start_pfn, unsigned long nr_pages); - -#ifdef CONFIG_NUMA -extern int memory_add_physaddr_to_nid(u64 start); -#else -static inline int memory_add_physaddr_to_nid(u64 start) -{ - return 0; -} -#endif - -#ifdef CONFIG_HAVE_ARCH_NODEDATA_EXTENSION -/* - * For supporting node-hotadd, we have to allocate a new pgdat. - * - * If an arch has generic style NODE_DATA(), - * node_data[nid] = kzalloc() works well. But it depends on the architecture. - * - * In general, generic_alloc_nodedata() is used. - * Now, arch_free_nodedata() is just defined for error path of node_hot_add. - * - */ -extern pg_data_t *arch_alloc_nodedata(int nid); -extern void arch_free_nodedata(pg_data_t *pgdat); -extern void arch_refresh_nodedata(int nid, pg_data_t *pgdat); - -#else /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */ - -#define arch_alloc_nodedata(nid) generic_alloc_nodedata(nid) -#define arch_free_nodedata(pgdat) generic_free_nodedata(pgdat) - -#ifdef CONFIG_NUMA -/* - * If ARCH_HAS_NODEDATA_EXTENSION=n, this func is used to allocate pgdat. - * XXX: kmalloc_node() can't work well to get new node's memory at this time. - * Because, pgdat for the new node is not allocated/initialized yet itself. - * To use new node's memory, more consideration will be necessary. - */ -#define generic_alloc_nodedata(nid) \ -({ \ - kzalloc(sizeof(pg_data_t), GFP_KERNEL); \ -}) -/* - * This definition is just for error path in node hotadd. - * For node hotremove, we have to replace this. - */ -#define generic_free_nodedata(pgdat) kfree(pgdat) - -extern pg_data_t *node_data[]; -static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat) -{ - node_data[nid] = pgdat; -} - -#else /* !CONFIG_NUMA */ - -/* never called */ -static inline pg_data_t *generic_alloc_nodedata(int nid) -{ - BUG(); - return NULL; -} -static inline void generic_free_nodedata(pg_data_t *pgdat) -{ -} -static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat) -{ -} -#endif /* CONFIG_NUMA */ -#endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */ - #else /* ! CONFIG_MEMORY_HOTPLUG */ /* * Stub functions for when hotplug is off @@ -169,8 +99,7 @@ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn, return -ENOSYS; } -extern int add_memory(int nid, u64 start, u64 size); -extern int arch_add_memory(int nid, u64 start, u64 size); +extern int add_memory(u64 start, u64 size); extern int remove_memory(u64 start, u64 size); #endif /* __LINUX_MEMORY_HOTPLUG_H */ diff --git a/trunk/include/linux/miscdevice.h b/trunk/include/linux/miscdevice.h index b03cfb91e228..5b584dafb5a6 100644 --- a/trunk/include/linux/miscdevice.h +++ b/trunk/include/linux/miscdevice.h @@ -40,6 +40,7 @@ struct miscdevice { struct list_head list; struct device *dev; struct class_device *class; + char devfs_name[64]; }; extern int misc_register(struct miscdevice * misc); diff --git a/trunk/include/linux/mm.h b/trunk/include/linux/mm.h index 75179529e399..a929ea197e48 100644 --- a/trunk/include/linux/mm.h +++ b/trunk/include/linux/mm.h @@ -36,6 +36,7 @@ extern int sysctl_legacy_va_layout; #include #include #include +#include #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n)) @@ -514,11 +515,6 @@ static inline void set_page_links(struct page *page, unsigned long zone, set_page_section(page, pfn_to_section_nr(pfn)); } -/* - * Some inline functions in vmstat.h depend on page_zone() - */ -#include - #ifndef CONFIG_DISCONTIGMEM /* The array of struct pages - for discontigmem use pgdat->lmem_map */ extern struct page *mem_map; @@ -1034,20 +1030,13 @@ static inline void vm_stat_account(struct mm_struct *mm, } #endif /* CONFIG_PROC_FS */ -static inline void -debug_check_no_locks_freed(const void *from, unsigned long len) -{ - mutex_debug_check_no_locks_freed(from, len); - rt_mutex_debug_check_no_locks_freed(from, len); -} - #ifndef CONFIG_DEBUG_PAGEALLOC static inline void kernel_map_pages(struct page *page, int numpages, int enable) { if (!PageHighMem(page) && !enable) - debug_check_no_locks_freed(page_address(page), - numpages * PAGE_SIZE); + mutex_debug_check_no_locks_freed(page_address(page), + numpages * PAGE_SIZE); } #endif @@ -1076,7 +1065,5 @@ void drop_slab(void); extern int randomize_va_space; #endif -const char *arch_vma_name(struct vm_area_struct *vma); - #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ diff --git a/trunk/include/linux/mmzone.h b/trunk/include/linux/mmzone.h index 27e748eb72b0..d6120fa69116 100644 --- a/trunk/include/linux/mmzone.h +++ b/trunk/include/linux/mmzone.h @@ -46,27 +46,6 @@ struct zone_padding { #define ZONE_PADDING(name) #endif -enum zone_stat_item { - NR_ANON_PAGES, /* Mapped anonymous pages */ - NR_FILE_MAPPED, /* pagecache pages mapped into pagetables. - only modified from process context */ - NR_FILE_PAGES, - NR_SLAB, /* Pages used by slab allocator */ - NR_PAGETABLE, /* used for pagetables */ - NR_FILE_DIRTY, - NR_WRITEBACK, - NR_UNSTABLE_NFS, /* NFS unstable pages */ - NR_BOUNCE, -#ifdef CONFIG_NUMA - NUMA_HIT, /* allocated in intended node */ - NUMA_MISS, /* allocated in non intended node */ - NUMA_FOREIGN, /* was intended here, hit elsewhere */ - NUMA_INTERLEAVE_HIT, /* interleaver preferred this zone */ - NUMA_LOCAL, /* allocation from local node */ - NUMA_OTHER, /* allocation from other node */ -#endif - NR_VM_ZONE_STAT_ITEMS }; - struct per_cpu_pages { int count; /* number of pages in the list */ int high; /* high watermark, emptying needed */ @@ -76,8 +55,13 @@ struct per_cpu_pages { struct per_cpu_pageset { struct per_cpu_pages pcp[2]; /* 0: hot. 1: cold */ -#ifdef CONFIG_SMP - s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS]; +#ifdef CONFIG_NUMA + unsigned long numa_hit; /* allocated in intended node */ + unsigned long numa_miss; /* allocated in non intended node */ + unsigned long numa_foreign; /* was intended here, hit elsewhere */ + unsigned long interleave_hit; /* interleaver prefered this zone */ + unsigned long local_node; /* allocation from local node */ + unsigned long other_node; /* allocation from other node */ #endif } ____cacheline_aligned_in_smp; @@ -181,8 +165,12 @@ struct zone { /* A count of how many reclaimers are scanning this zone */ atomic_t reclaim_in_progress; - /* Zone statistics */ - atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS]; + /* + * timestamp (in jiffies) of the last zone reclaim that did not + * result in freeing of pages. This is used to avoid repeated scans + * if all memory in the zone is in use. + */ + unsigned long last_unsuccessful_zone_reclaim; /* * prev_priority holds the scanning priority for this zone. It is diff --git a/trunk/include/linux/module.h b/trunk/include/linux/module.h index 9e9dc7c24d95..2d366098eab5 100644 --- a/trunk/include/linux/module.h +++ b/trunk/include/linux/module.h @@ -203,15 +203,6 @@ void *__symbol_get_gpl(const char *symbol); #define EXPORT_SYMBOL_GPL_FUTURE(sym) \ __EXPORT_SYMBOL(sym, "_gpl_future") - -#ifdef CONFIG_UNUSED_SYMBOLS -#define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused") -#define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl") -#else -#define EXPORT_UNUSED_SYMBOL(sym) -#define EXPORT_UNUSED_SYMBOL_GPL(sym) -#endif - #endif struct module_ref @@ -270,15 +261,6 @@ struct module unsigned int num_gpl_syms; const unsigned long *gpl_crcs; - /* unused exported symbols. */ - const struct kernel_symbol *unused_syms; - unsigned int num_unused_syms; - const unsigned long *unused_crcs; - /* GPL-only, unused exported symbols. */ - const struct kernel_symbol *unused_gpl_syms; - unsigned int num_unused_gpl_syms; - const unsigned long *unused_gpl_crcs; - /* symbols that will be GPL-only in the near future. */ const struct kernel_symbol *gpl_future_syms; unsigned int num_gpl_future_syms; @@ -303,9 +285,6 @@ struct module /* The size of the executable code in each section. */ unsigned long init_text_size, core_text_size; - /* The handle returned from unwind_add_table. */ - void *unwind_info; - /* Arch-specific module values */ struct mod_arch_specific arch; @@ -474,8 +453,6 @@ void module_remove_driver(struct device_driver *); #define EXPORT_SYMBOL(sym) #define EXPORT_SYMBOL_GPL(sym) #define EXPORT_SYMBOL_GPL_FUTURE(sym) -#define EXPORT_UNUSED_SYMBOL(sym) -#define EXPORT_UNUSED_SYMBOL_GPL(sym) /* Given an address, look for it in the exception tables. */ static inline const struct exception_table_entry * diff --git a/trunk/include/linux/net.h b/trunk/include/linux/net.h index b20c53c74413..385e68f5bd93 100644 --- a/trunk/include/linux/net.h +++ b/trunk/include/linux/net.h @@ -61,7 +61,6 @@ typedef enum { #define SOCK_ASYNC_WAITDATA 1 #define SOCK_NOSPACE 2 #define SOCK_PASSCRED 3 -#define SOCK_PASSSEC 4 #ifndef ARCH_HAS_SOCKET_TYPES /** diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 85f99f60deea..bc747e5d7138 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -313,12 +313,8 @@ struct net_device /* Segmentation offload features */ #define NETIF_F_GSO_SHIFT 16 -#define NETIF_F_GSO_MASK 0xffff0000 #define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) -#define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT) -#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) -#define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT) -#define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT) +#define NETIF_F_UFO (SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT) #define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) #define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM) @@ -547,8 +543,7 @@ struct packet_type { struct net_device *, struct packet_type *, struct net_device *); - struct sk_buff *(*gso_segment)(struct sk_buff *skb, - int features); + struct sk_buff *(*gso_segment)(struct sk_buff *skb, int sg); void *af_packet_priv; struct list_head list; }; @@ -704,6 +699,7 @@ extern int dev_hard_start_xmit(struct sk_buff *skb, extern void dev_init(void); +extern int netdev_nit; extern int netdev_budget; /* Called by rtnetlink.c:rtnl_unlock() */ @@ -973,7 +969,7 @@ extern int netdev_max_backlog; extern int weight_p; extern int netdev_set_master(struct net_device *dev, struct net_device *master); extern int skb_checksum_help(struct sk_buff *skb, int inward); -extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features); +extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg); #ifdef CONFIG_BUG extern void netdev_rx_csum_fault(struct net_device *dev); #else @@ -993,21 +989,11 @@ extern void dev_seq_stop(struct seq_file *seq, void *v); extern void linkwatch_run_queue(void); -static inline int net_gso_ok(int features, int gso_type) -{ - int feature = gso_type << NETIF_F_GSO_SHIFT; - return (features & feature) == feature; -} - -static inline int skb_gso_ok(struct sk_buff *skb, int features) -{ - return net_gso_ok(features, skb_shinfo(skb)->gso_size ? - skb_shinfo(skb)->gso_type : 0); -} - static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) { - return !skb_gso_ok(skb, dev->features); + int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT; + return skb_shinfo(skb)->gso_size && + (dev->features & feature) != feature; } #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/netpoll.h b/trunk/include/linux/netpoll.h index 1efe60c5c00c..ca5a8733000f 100644 --- a/trunk/include/linux/netpoll.h +++ b/trunk/include/linux/netpoll.h @@ -31,7 +31,6 @@ struct netpoll_info { int rx_flags; spinlock_t rx_lock; struct netpoll *rx_np; /* netpoll that registered an rx_hook */ - struct sk_buff_head arp_tx; /* list of arp requests to reply to */ }; void netpoll_poll(struct netpoll *np); diff --git a/trunk/include/linux/nfs_fs.h b/trunk/include/linux/nfs_fs.h index 55ea853d57bc..0a1740b2532e 100644 --- a/trunk/include/linux/nfs_fs.h +++ b/trunk/include/linux/nfs_fs.h @@ -9,6 +9,7 @@ #ifndef _LINUX_NFS_FS_H #define _LINUX_NFS_FS_H +#include #include #include #include @@ -334,7 +335,7 @@ extern struct inode_operations nfs_file_inode_operations; extern struct inode_operations nfs3_file_inode_operations; #endif /* CONFIG_NFS_V3 */ extern const struct file_operations nfs_file_operations; -extern const struct address_space_operations nfs_file_aops; +extern struct address_space_operations nfs_file_aops; static inline struct rpc_cred *nfs_file_cred(struct file *file) { diff --git a/trunk/include/linux/node.h b/trunk/include/linux/node.h index 81dcec84cd8f..254dc3de650b 100644 --- a/trunk/include/linux/node.h +++ b/trunk/include/linux/node.h @@ -26,25 +26,8 @@ struct node { struct sys_device sysdev; }; -extern struct node node_devices[]; - extern int register_node(struct node *, int, struct node *); extern void unregister_node(struct node *node); -extern int register_one_node(int nid); -extern void unregister_one_node(int nid); -#ifdef CONFIG_NUMA -extern int register_cpu_under_node(unsigned int cpu, unsigned int nid); -extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid); -#else -static inline int register_cpu_under_node(unsigned int cpu, unsigned int nid) -{ - return 0; -} -static inline int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) -{ - return 0; -} -#endif #define to_node(sys_device) container_of(sys_device, struct node, sysdev) diff --git a/trunk/include/linux/nsc_gpio.h b/trunk/include/linux/nsc_gpio.h deleted file mode 100644 index 135742cfada5..000000000000 --- a/trunk/include/linux/nsc_gpio.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - nsc_gpio.c - - National Semiconductor GPIO common access methods. - - struct nsc_gpio_ops abstracts the low-level access - operations for the GPIO units on 2 NSC chip families; the GEODE - integrated CPU, and the PC-8736[03456] integrated PC-peripheral - chips. - - The GPIO units on these chips have the same pin architecture, but - the access methods differ. Thus, scx200_gpio and pc8736x_gpio - implement their own versions of these routines; and use the common - file-operations routines implemented in nsc_gpio module. - - Copyright (c) 2005 Jim Cromie - - NB: this work was tested on the Geode SC-1100 and PC-87366 chips. - NSC sold the GEODE line to AMD, and the PC-8736x line to Winbond. -*/ - -struct nsc_gpio_ops { - struct module* owner; - u32 (*gpio_config) (unsigned iminor, u32 mask, u32 bits); - void (*gpio_dump) (struct nsc_gpio_ops *amp, unsigned iminor); - int (*gpio_get) (unsigned iminor); - void (*gpio_set) (unsigned iminor, int state); - void (*gpio_set_high)(unsigned iminor); - void (*gpio_set_low) (unsigned iminor); - void (*gpio_change) (unsigned iminor); - int (*gpio_current) (unsigned iminor); - struct device* dev; /* for dev_dbg() support, set in init */ -}; - -extern ssize_t nsc_gpio_write(struct file *file, const char __user *data, - size_t len, loff_t *ppos); - -extern ssize_t nsc_gpio_read(struct file *file, char __user *buf, - size_t len, loff_t *ppos); - -extern void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index); - diff --git a/trunk/include/linux/page-flags.h b/trunk/include/linux/page-flags.h index 5748642e9f36..0c076d58c676 100644 --- a/trunk/include/linux/page-flags.h +++ b/trunk/include/linux/page-flags.h @@ -5,8 +5,12 @@ #ifndef PAGE_FLAGS_H #define PAGE_FLAGS_H +#include +#include #include +#include + /* * Various page->flags bits: * @@ -98,6 +102,134 @@ #define PG_uncached 31 /* Page has been mapped as uncached */ #endif +/* + * Global page accounting. One instance per CPU. Only unsigned longs are + * allowed. + * + * - Fields can be modified with xxx_page_state and xxx_page_state_zone at + * any time safely (which protects the instance from modification by + * interrupt. + * - The __xxx_page_state variants can be used safely when interrupts are + * disabled. + * - The __xxx_page_state variants can be used if the field is only + * modified from process context and protected from preemption, or only + * modified from interrupt context. In this case, the field should be + * commented here. + */ +struct page_state { + unsigned long nr_dirty; /* Dirty writeable pages */ + unsigned long nr_writeback; /* Pages under writeback */ + unsigned long nr_unstable; /* NFS unstable pages */ + unsigned long nr_page_table_pages;/* Pages used for pagetables */ + unsigned long nr_mapped; /* mapped into pagetables. + * only modified from process context */ + unsigned long nr_slab; /* In slab */ +#define GET_PAGE_STATE_LAST nr_slab + + /* + * The below are zeroed by get_page_state(). Use get_full_page_state() + * to add up all these. + */ + unsigned long pgpgin; /* Disk reads */ + unsigned long pgpgout; /* Disk writes */ + unsigned long pswpin; /* swap reads */ + unsigned long pswpout; /* swap writes */ + + unsigned long pgalloc_high; /* page allocations */ + unsigned long pgalloc_normal; + unsigned long pgalloc_dma32; + unsigned long pgalloc_dma; + + unsigned long pgfree; /* page freeings */ + unsigned long pgactivate; /* pages moved inactive->active */ + unsigned long pgdeactivate; /* pages moved active->inactive */ + + unsigned long pgfault; /* faults (major+minor) */ + unsigned long pgmajfault; /* faults (major only) */ + + unsigned long pgrefill_high; /* inspected in refill_inactive_zone */ + unsigned long pgrefill_normal; + unsigned long pgrefill_dma32; + unsigned long pgrefill_dma; + + unsigned long pgsteal_high; /* total highmem pages reclaimed */ + unsigned long pgsteal_normal; + unsigned long pgsteal_dma32; + unsigned long pgsteal_dma; + + unsigned long pgscan_kswapd_high;/* total highmem pages scanned */ + unsigned long pgscan_kswapd_normal; + unsigned long pgscan_kswapd_dma32; + unsigned long pgscan_kswapd_dma; + + unsigned long pgscan_direct_high;/* total highmem pages scanned */ + unsigned long pgscan_direct_normal; + unsigned long pgscan_direct_dma32; + unsigned long pgscan_direct_dma; + + unsigned long pginodesteal; /* pages reclaimed via inode freeing */ + unsigned long slabs_scanned; /* slab objects scanned */ + unsigned long kswapd_steal; /* pages reclaimed by kswapd */ + unsigned long kswapd_inodesteal;/* reclaimed via kswapd inode freeing */ + unsigned long pageoutrun; /* kswapd's calls to page reclaim */ + unsigned long allocstall; /* direct reclaim calls */ + + unsigned long pgrotated; /* pages rotated to tail of the LRU */ + unsigned long nr_bounce; /* pages for bounce buffers */ +}; + +extern void get_page_state(struct page_state *ret); +extern void get_page_state_node(struct page_state *ret, int node); +extern void get_full_page_state(struct page_state *ret); +extern unsigned long read_page_state_offset(unsigned long offset); +extern void mod_page_state_offset(unsigned long offset, unsigned long delta); +extern void __mod_page_state_offset(unsigned long offset, unsigned long delta); + +#define read_page_state(member) \ + read_page_state_offset(offsetof(struct page_state, member)) + +#define mod_page_state(member, delta) \ + mod_page_state_offset(offsetof(struct page_state, member), (delta)) + +#define __mod_page_state(member, delta) \ + __mod_page_state_offset(offsetof(struct page_state, member), (delta)) + +#define inc_page_state(member) mod_page_state(member, 1UL) +#define dec_page_state(member) mod_page_state(member, 0UL - 1) +#define add_page_state(member,delta) mod_page_state(member, (delta)) +#define sub_page_state(member,delta) mod_page_state(member, 0UL - (delta)) + +#define __inc_page_state(member) __mod_page_state(member, 1UL) +#define __dec_page_state(member) __mod_page_state(member, 0UL - 1) +#define __add_page_state(member,delta) __mod_page_state(member, (delta)) +#define __sub_page_state(member,delta) __mod_page_state(member, 0UL - (delta)) + +#define page_state(member) (*__page_state(offsetof(struct page_state, member))) + +#define state_zone_offset(zone, member) \ +({ \ + unsigned offset; \ + if (is_highmem(zone)) \ + offset = offsetof(struct page_state, member##_high); \ + else if (is_normal(zone)) \ + offset = offsetof(struct page_state, member##_normal); \ + else if (is_dma32(zone)) \ + offset = offsetof(struct page_state, member##_dma32); \ + else \ + offset = offsetof(struct page_state, member##_dma); \ + offset; \ +}) + +#define __mod_page_state_zone(zone, member, delta) \ + do { \ + __mod_page_state_offset(state_zone_offset(zone, member), (delta)); \ + } while (0) + +#define mod_page_state_zone(zone, member, delta) \ + do { \ + mod_page_state_offset(state_zone_offset(zone, member), (delta)); \ + } while (0) + /* * Manipulation of page state flags */ @@ -122,14 +254,7 @@ #define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags) #define PageUptodate(page) test_bit(PG_uptodate, &(page)->flags) -#ifdef CONFIG_S390 -#define SetPageUptodate(_page) \ - do { \ - struct page *__page = (_page); \ - if (!test_and_set_bit(PG_uptodate, &__page->flags)) \ - page_test_and_clear_dirty(_page); \ - } while (0) -#else +#ifndef SetPageUptodate #define SetPageUptodate(page) set_bit(PG_uptodate, &(page)->flags) #endif #define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags) @@ -181,7 +306,7 @@ do { \ if (!test_and_set_bit(PG_writeback, \ &(page)->flags)) \ - inc_zone_page_state(page, NR_WRITEBACK); \ + inc_page_state(nr_writeback); \ } while (0) #define TestSetPageWriteback(page) \ ({ \ @@ -189,14 +314,14 @@ ret = test_and_set_bit(PG_writeback, \ &(page)->flags); \ if (!ret) \ - inc_zone_page_state(page, NR_WRITEBACK); \ + inc_page_state(nr_writeback); \ ret; \ }) #define ClearPageWriteback(page) \ do { \ if (test_and_clear_bit(PG_writeback, \ &(page)->flags)) \ - dec_zone_page_state(page, NR_WRITEBACK); \ + dec_page_state(nr_writeback); \ } while (0) #define TestClearPageWriteback(page) \ ({ \ @@ -204,7 +329,7 @@ ret = test_and_clear_bit(PG_writeback, \ &(page)->flags); \ if (ret) \ - dec_zone_page_state(page, NR_WRITEBACK); \ + dec_page_state(nr_writeback); \ ret; \ }) diff --git a/trunk/include/linux/pagemap.h b/trunk/include/linux/pagemap.h index 0a2f5d27f60e..1245df7141aa 100644 --- a/trunk/include/linux/pagemap.h +++ b/trunk/include/linux/pagemap.h @@ -113,6 +113,51 @@ int add_to_page_cache_lru(struct page *page, struct address_space *mapping, extern void remove_from_page_cache(struct page *page); extern void __remove_from_page_cache(struct page *page); +extern atomic_t nr_pagecache; + +#ifdef CONFIG_SMP + +#define PAGECACHE_ACCT_THRESHOLD max(16, NR_CPUS * 2) +DECLARE_PER_CPU(long, nr_pagecache_local); + +/* + * pagecache_acct implements approximate accounting for pagecache. + * vm_enough_memory() do not need high accuracy. Writers will keep + * an offset in their per-cpu arena and will spill that into the + * global count whenever the absolute value of the local count + * exceeds the counter's threshold. + * + * MUST be protected from preemption. + * current protection is mapping->page_lock. + */ +static inline void pagecache_acct(int count) +{ + long *local; + + local = &__get_cpu_var(nr_pagecache_local); + *local += count; + if (*local > PAGECACHE_ACCT_THRESHOLD || *local < -PAGECACHE_ACCT_THRESHOLD) { + atomic_add(*local, &nr_pagecache); + *local = 0; + } +} + +#else + +static inline void pagecache_acct(int count) +{ + atomic_add(count, &nr_pagecache); +} +#endif + +static inline unsigned long get_page_cache_size(void) +{ + int ret = atomic_read(&nr_pagecache); + if (unlikely(ret < 0)) + ret = 0; + return ret; +} + /* * Return byte-offset into filesystem object for page. */ diff --git a/trunk/include/linux/pci.h b/trunk/include/linux/pci.h index 983fca251b25..62a8c22f5f60 100644 --- a/trunk/include/linux/pci.h +++ b/trunk/include/linux/pci.h @@ -404,8 +404,8 @@ int pcibios_enable_device(struct pci_dev *, int mask); char *pcibios_setup (char *str); /* Used only when drivers/pci/setup.c is used */ -void pcibios_align_resource(void *, struct resource *, resource_size_t, - resource_size_t); +void pcibios_align_resource(void *, struct resource *, + unsigned long, unsigned long); void pcibios_update_irq(struct pci_dev *, int irq); /* Generic PCI functions used internally */ @@ -532,10 +532,10 @@ void pci_release_region(struct pci_dev *, int); /* drivers/pci/bus.c */ int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, - resource_size_t size, resource_size_t align, - resource_size_t min, unsigned int type_mask, + unsigned long size, unsigned long align, + unsigned long min, unsigned int type_mask, void (*alignf)(void *, struct resource *, - resource_size_t, resource_size_t), + unsigned long, unsigned long), void *alignf_data); void pci_enable_bridges(struct pci_bus *bus); @@ -730,8 +730,7 @@ static inline char *pci_name(struct pci_dev *pdev) */ #ifndef HAVE_ARCH_PCI_RESOURCE_TO_USER static inline void pci_resource_to_user(const struct pci_dev *dev, int bar, - const struct resource *rsrc, resource_size_t *start, - resource_size_t *end) + const struct resource *rsrc, u64 *start, u64 *end) { *start = rsrc->start; *end = rsrc->end; diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index b093479a531d..c2fd2d19938b 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -729,7 +729,6 @@ #define PCI_DEVICE_ID_TI_4450 0x8011 #define PCI_DEVICE_ID_TI_XX21_XX11 0x8031 #define PCI_DEVICE_ID_TI_X515 0x8036 -#define PCI_DEVICE_ID_TI_XX12 0x8039 #define PCI_DEVICE_ID_TI_1130 0xac12 #define PCI_DEVICE_ID_TI_1031 0xac13 #define PCI_DEVICE_ID_TI_1131 0xac15 @@ -1203,7 +1202,6 @@ #define PCI_DEVICE_ID_NVIDIA_NVENET_19 0x03EF #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3 0x03F7 -#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE 0x0448 #define PCI_DEVICE_ID_NVIDIA_NVENET_20 0x0450 #define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451 #define PCI_DEVICE_ID_NVIDIA_NVENET_22 0x0452 @@ -2172,6 +2170,7 @@ #define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815 #define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e #define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850 +#define PCI_DEVICE_ID_INTEL_GD31244 0x3200 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 #define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 diff --git a/trunk/include/linux/plist.h b/trunk/include/linux/plist.h deleted file mode 100644 index b95818a037ad..000000000000 --- a/trunk/include/linux/plist.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Descending-priority-sorted double-linked list - * - * (C) 2002-2003 Intel Corp - * Inaky Perez-Gonzalez . - * - * 2001-2005 (c) MontaVista Software, Inc. - * Daniel Walker - * - * (C) 2005 Thomas Gleixner - * - * Simplifications of the original code by - * Oleg Nesterov - * - * Licensed under the FSF's GNU Public License v2 or later. - * - * Based on simple lists (include/linux/list.h). - * - * This is a priority-sorted list of nodes; each node has a - * priority from INT_MIN (highest) to INT_MAX (lowest). - * - * Addition is O(K), removal is O(1), change of priority of a node is - * O(K) and K is the number of RT priority levels used in the system. - * (1 <= K <= 99) - * - * This list is really a list of lists: - * - * - The tier 1 list is the prio_list, different priority nodes. - * - * - The tier 2 list is the node_list, serialized nodes. - * - * Simple ASCII art explanation: - * - * |HEAD | - * | | - * |prio_list.prev|<------------------------------------| - * |prio_list.next|<->|pl|<->|pl|<--------------->|pl|<-| - * |10 | |10| |21| |21| |21| |40| (prio) - * | | | | | | | | | | | | - * | | | | | | | | | | | | - * |node_list.next|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-| - * |node_list.prev|<------------------------------------| - * - * The nodes on the prio_list list are sorted by priority to simplify - * the insertion of new nodes. There are no nodes with duplicate - * priorites on the list. - * - * The nodes on the node_list is ordered by priority and can contain - * entries which have the same priority. Those entries are ordered - * FIFO - * - * Addition means: look for the prio_list node in the prio_list - * for the priority of the node and insert it before the node_list - * entry of the next prio_list node. If it is the first node of - * that priority, add it to the prio_list in the right position and - * insert it into the serialized node_list list - * - * Removal means remove it from the node_list and remove it from - * the prio_list if the node_list list_head is non empty. In case - * of removal from the prio_list it must be checked whether other - * entries of the same priority are on the list or not. If there - * is another entry of the same priority then this entry has to - * replace the removed entry on the prio_list. If the entry which - * is removed is the only entry of this priority then a simple - * remove from both list is sufficient. - * - * INT_MIN is the highest priority, 0 is the medium highest, INT_MAX - * is lowest priority. - * - * No locking is done, up to the caller. - * - */ -#ifndef _LINUX_PLIST_H_ -#define _LINUX_PLIST_H_ - -#include -#include -#include - -struct plist_head { - struct list_head prio_list; - struct list_head node_list; -#ifdef CONFIG_DEBUG_PI_LIST - spinlock_t *lock; -#endif -}; - -struct plist_node { - int prio; - struct plist_head plist; -}; - -#ifdef CONFIG_DEBUG_PI_LIST -# define PLIST_HEAD_LOCK_INIT(_lock) .lock = _lock -#else -# define PLIST_HEAD_LOCK_INIT(_lock) -#endif - -/** - * #PLIST_HEAD_INIT - static struct plist_head initializer - * - * @head: struct plist_head variable name - */ -#define PLIST_HEAD_INIT(head, _lock) \ -{ \ - .prio_list = LIST_HEAD_INIT((head).prio_list), \ - .node_list = LIST_HEAD_INIT((head).node_list), \ - PLIST_HEAD_LOCK_INIT(&(_lock)) \ -} - -/** - * #PLIST_NODE_INIT - static struct plist_node initializer - * - * @node: struct plist_node variable name - * @__prio: initial node priority - */ -#define PLIST_NODE_INIT(node, __prio) \ -{ \ - .prio = (__prio), \ - .plist = PLIST_HEAD_INIT((node).plist, NULL), \ -} - -/** - * plist_head_init - dynamic struct plist_head initializer - * - * @head: &struct plist_head pointer - */ -static inline void -plist_head_init(struct plist_head *head, spinlock_t *lock) -{ - INIT_LIST_HEAD(&head->prio_list); - INIT_LIST_HEAD(&head->node_list); -#ifdef CONFIG_DEBUG_PI_LIST - head->lock = lock; -#endif -} - -/** - * plist_node_init - Dynamic struct plist_node initializer - * - * @node: &struct plist_node pointer - * @prio: initial node priority - */ -static inline void plist_node_init(struct plist_node *node, int prio) -{ - node->prio = prio; - plist_head_init(&node->plist, NULL); -} - -extern void plist_add(struct plist_node *node, struct plist_head *head); -extern void plist_del(struct plist_node *node, struct plist_head *head); - -/** - * plist_for_each - iterate over the plist - * - * @pos1: the type * to use as a loop counter. - * @head: the head for your list. - */ -#define plist_for_each(pos, head) \ - list_for_each_entry(pos, &(head)->node_list, plist.node_list) - -/** - * plist_for_each_entry_safe - iterate over a plist of given type safe - * against removal of list entry - * - * @pos1: the type * to use as a loop counter. - * @n1: another type * to use as temporary storage - * @head: the head for your list. - */ -#define plist_for_each_safe(pos, n, head) \ - list_for_each_entry_safe(pos, n, &(head)->node_list, plist.node_list) - -/** - * plist_for_each_entry - iterate over list of given type - * - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define plist_for_each_entry(pos, head, mem) \ - list_for_each_entry(pos, &(head)->node_list, mem.plist.node_list) - -/** - * plist_for_each_entry_safe - iterate over list of given type safe against - * removal of list entry - * - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @m: the name of the list_struct within the struct. - */ -#define plist_for_each_entry_safe(pos, n, head, m) \ - list_for_each_entry_safe(pos, n, &(head)->node_list, m.plist.node_list) - -/** - * plist_head_empty - return !0 if a plist_head is empty - * - * @head: &struct plist_head pointer - */ -static inline int plist_head_empty(const struct plist_head *head) -{ - return list_empty(&head->node_list); -} - -/** - * plist_node_empty - return !0 if plist_node is not on a list - * - * @node: &struct plist_node pointer - */ -static inline int plist_node_empty(const struct plist_node *node) -{ - return plist_head_empty(&node->plist); -} - -/* All functions below assume the plist_head is not empty. */ - -/** - * plist_first_entry - get the struct for the first entry - * - * @ptr: the &struct plist_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#ifdef CONFIG_DEBUG_PI_LIST -# define plist_first_entry(head, type, member) \ -({ \ - WARN_ON(plist_head_empty(head)); \ - container_of(plist_first(head), type, member); \ -}) -#else -# define plist_first_entry(head, type, member) \ - container_of(plist_first(head), type, member) -#endif - -/** - * plist_first - return the first node (and thus, highest priority) - * - * @head: the &struct plist_head pointer - * - * Assumes the plist is _not_ empty. - */ -static inline struct plist_node* plist_first(const struct plist_head *head) -{ - return list_entry(head->node_list.next, - struct plist_node, plist.node_list); -} - -#endif diff --git a/trunk/include/linux/pnp.h b/trunk/include/linux/pnp.h index ab8a8dd8d64c..93b0959eb40f 100644 --- a/trunk/include/linux/pnp.h +++ b/trunk/include/linux/pnp.h @@ -389,8 +389,7 @@ int pnp_start_dev(struct pnp_dev *dev); int pnp_stop_dev(struct pnp_dev *dev); int pnp_activate_dev(struct pnp_dev *dev); int pnp_disable_dev(struct pnp_dev *dev); -void pnp_resource_change(struct resource *resource, resource_size_t start, - resource_size_t size); +void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size); /* protocol helpers */ int pnp_is_active(struct pnp_dev * dev); @@ -435,9 +434,7 @@ static inline int pnp_start_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; } -static inline void pnp_resource_change(struct resource *resource, - resource_size_t start, - resource_size_t size) { } +static inline void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) { } /* protocol helpers */ static inline int pnp_is_active(struct pnp_dev * dev) { return 0; } diff --git a/trunk/include/linux/poison.h b/trunk/include/linux/poison.h deleted file mode 100644 index a5347c02432e..000000000000 --- a/trunk/include/linux/poison.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _LINUX_POISON_H -#define _LINUX_POISON_H - -/********** include/linux/list.h **********/ -/* - * These are non-NULL pointers that will result in page faults - * under normal circumstances, used to verify that nobody uses - * non-initialized list entries. - */ -#define LIST_POISON1 ((void *) 0x00100100) -#define LIST_POISON2 ((void *) 0x00200200) - -/********** mm/slab.c **********/ -/* - * Magic nums for obj red zoning. - * Placed in the first word before and the first word after an obj. - */ -#define RED_INACTIVE 0x5A2CF071UL /* when obj is inactive */ -#define RED_ACTIVE 0x170FC2A5UL /* when obj is active */ - -/* ...and for poisoning */ -#define POISON_INUSE 0x5a /* for use-uninitialised poisoning */ -#define POISON_FREE 0x6b /* for use-after-free poisoning */ -#define POISON_END 0xa5 /* end-byte of poisoning */ - -/********** arch/$ARCH/mm/init.c **********/ -#define POISON_FREE_INITMEM 0xcc - -/********** arch/x86_64/mm/init.c **********/ -#define POISON_FREE_INITDATA 0xba - -/********** arch/ia64/hp/common/sba_iommu.c **********/ -/* - * arch/ia64/hp/common/sba_iommu.c uses a 16-byte poison string with a - * value of "SBAIOMMU POISON\0" for spill-over poisoning. - */ - -/********** fs/jbd/journal.c **********/ -#define JBD_POISON_FREE 0x5b - -/********** drivers/base/dmapool.c **********/ -#define POOL_POISON_FREED 0xa7 /* !inuse */ -#define POOL_POISON_ALLOCATED 0xa9 /* !initted */ - -/********** drivers/atm/ **********/ -#define ATM_POISON_FREE 0x12 - -/********** kernel/mutexes **********/ -#define MUTEX_DEBUG_INIT 0x11 -#define MUTEX_DEBUG_FREE 0x22 - -/********** security/ **********/ -#define KEY_DESTROY 0xbd - -/********** sound/oss/ **********/ -#define OSS_POISON_FREE 0xAB - -#endif diff --git a/trunk/include/linux/proc_fs.h b/trunk/include/linux/proc_fs.h index 17e75783e3a5..5810d28fbed9 100644 --- a/trunk/include/linux/proc_fs.h +++ b/trunk/include/linux/proc_fs.h @@ -99,8 +99,9 @@ extern void proc_misc_init(void); struct mm_struct; -void proc_flush_task(struct task_struct *task); struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *); +struct dentry *proc_pid_unhash(struct task_struct *p); +void proc_pid_flush(struct dentry *proc_dentry); int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir); unsigned long task_vsize(struct mm_struct *); int task_statm(struct mm_struct *, int *, int *, int *, int *); @@ -210,7 +211,8 @@ static inline void proc_net_remove(const char *name) #define proc_net_create(name, mode, info) ({ (void)(mode), NULL; }) static inline void proc_net_remove(const char *name) {} -static inline void proc_flush_task(struct task_struct *task) { } +static inline struct dentry *proc_pid_unhash(struct task_struct *p) { return NULL; } +static inline void proc_pid_flush(struct dentry *proc_dentry) { } static inline struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, struct proc_dir_entry *parent) { return NULL; } @@ -246,8 +248,8 @@ extern void kclist_add(struct kcore_list *, void *, size_t); #endif struct proc_inode { - struct pid *pid; - int fd; + struct task_struct *task; + int type; union { int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **); int (*proc_read)(struct task_struct *task, char *page); @@ -266,10 +268,4 @@ static inline struct proc_dir_entry *PDE(const struct inode *inode) return PROC_I(inode)->pde; } -struct proc_maps_private { - struct pid *pid; - struct task_struct *task; - struct vm_area_struct *tail_vma; -}; - #endif /* _LINUX_PROC_FS_H */ diff --git a/trunk/include/linux/ptrace.h b/trunk/include/linux/ptrace.h index 8b2749a259dc..ee918bc6e18c 100644 --- a/trunk/include/linux/ptrace.h +++ b/trunk/include/linux/ptrace.h @@ -88,6 +88,7 @@ extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __us extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); extern int ptrace_attach(struct task_struct *tsk); extern int ptrace_detach(struct task_struct *, unsigned int); +extern void __ptrace_detach(struct task_struct *, unsigned int); extern void ptrace_disable(struct task_struct *); extern int ptrace_check_attach(struct task_struct *task, int kill); extern int ptrace_request(struct task_struct *child, long request, long addr, long data); diff --git a/trunk/include/linux/raid/bitmap.h b/trunk/include/linux/raid/bitmap.h index 63df898fe2e9..899437802aea 100644 --- a/trunk/include/linux/raid/bitmap.h +++ b/trunk/include/linux/raid/bitmap.h @@ -140,7 +140,6 @@ typedef __u16 bitmap_counter_t; enum bitmap_state { BITMAP_ACTIVE = 0x001, /* the bitmap is in use */ BITMAP_STALE = 0x002, /* the bitmap file is out of date or had -EIO */ - BITMAP_WRITE_ERROR = 0x004, /* A write error has occurred */ BITMAP_HOSTENDIAN = 0x8000, }; @@ -245,9 +244,15 @@ struct bitmap { unsigned long daemon_lastrun; /* jiffies of last run */ unsigned long daemon_sleep; /* how many seconds between updates? */ - atomic_t pending_writes; /* pending writes to the bitmap file */ + /* + * bitmap_writeback_daemon waits for file-pages that have been written, + * as there is no way to get a call-back when a page write completes. + */ + mdk_thread_t *writeback_daemon; + spinlock_t write_lock; wait_queue_head_t write_wait; - + struct list_head complete_pages; + mempool_t *write_pool; }; /* the bitmap API */ diff --git a/trunk/include/linux/raid/linear.h b/trunk/include/linux/raid/linear.h index ba15469daf11..7eaf290e10e7 100644 --- a/trunk/include/linux/raid/linear.h +++ b/trunk/include/linux/raid/linear.h @@ -13,10 +13,8 @@ typedef struct dev_info dev_info_t; struct linear_private_data { - struct linear_private_data *prev; /* earlier version */ dev_info_t **hash_table; sector_t hash_spacing; - sector_t array_size; int preshift; /* shift before dividing by hash_spacing */ dev_info_t disks[0]; }; diff --git a/trunk/include/linux/raid/md.h b/trunk/include/linux/raid/md.h index eb3e547c8fee..66b44e5e0d6e 100644 --- a/trunk/include/linux/raid/md.h +++ b/trunk/include/linux/raid/md.h @@ -85,6 +85,8 @@ extern void md_done_sync(mddev_t *mddev, int blocks, int ok); extern void md_error (mddev_t *mddev, mdk_rdev_t *rdev); extern void md_unplug_mddev(mddev_t *mddev); +extern void md_print_devices (void); + extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, sector_t sector, int size, struct page *page); extern void md_super_wait(mddev_t *mddev); @@ -95,5 +97,7 @@ extern void md_new_event(mddev_t *mddev); extern void md_update_sb(mddev_t * mddev); +#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); } + #endif diff --git a/trunk/include/linux/raid/md_k.h b/trunk/include/linux/raid/md_k.h index c1e0ac55bab5..e2df61f5b09a 100644 --- a/trunk/include/linux/raid/md_k.h +++ b/trunk/include/linux/raid/md_k.h @@ -40,8 +40,7 @@ typedef struct mdk_rdev_s mdk_rdev_t; * options passed in raidrun: */ -/* Currently this must fix in an 'int' */ -#define MAX_CHUNK_SIZE (1<<30) +#define MAX_CHUNK_SIZE (4096*1024) /* * MD's 'extended' device @@ -58,7 +57,6 @@ struct mdk_rdev_s struct page *sb_page; int sb_loaded; - __u64 sb_events; sector_t data_offset; /* start of data in array */ sector_t sb_offset; int sb_size; /* bytes in the superblock */ @@ -89,10 +87,6 @@ struct mdk_rdev_s * array and could again if we did a partial * resync from the bitmap */ - sector_t recovery_offset;/* If this device has been partially - * recovered, this is where we were - * up to. - */ atomic_t nr_pending; /* number of pending requests. * only maintained for arrays that @@ -188,8 +182,6 @@ struct mddev_s #define MD_RECOVERY_REQUESTED 6 #define MD_RECOVERY_CHECK 7 #define MD_RECOVERY_RESHAPE 8 -#define MD_RECOVERY_FROZEN 9 - unsigned long recovery; int in_sync; /* know to not need resync */ diff --git a/trunk/include/linux/raid/md_p.h b/trunk/include/linux/raid/md_p.h index b6ebc69bae54..f1fbae7e390e 100644 --- a/trunk/include/linux/raid/md_p.h +++ b/trunk/include/linux/raid/md_p.h @@ -265,12 +265,9 @@ struct mdp_superblock_1 { /* feature_map bits */ #define MD_FEATURE_BITMAP_OFFSET 1 -#define MD_FEATURE_RECOVERY_OFFSET 2 /* recovery_offset is present and - * must be honoured - */ #define MD_FEATURE_RESHAPE_ACTIVE 4 -#define MD_FEATURE_ALL (1|2|4) +#define MD_FEATURE_ALL 5 #endif diff --git a/trunk/include/linux/raid/raid10.h b/trunk/include/linux/raid/raid10.h index c41e56a7c090..b1103298a8c2 100644 --- a/trunk/include/linux/raid/raid10.h +++ b/trunk/include/linux/raid/raid10.h @@ -24,16 +24,11 @@ struct r10_private_data_s { int far_copies; /* number of copies layed out * at large strides across drives */ - int far_offset; /* far_copies are offset by 1 stripe - * instead of many - */ int copies; /* near_copies * far_copies. * must be <= raid_disks */ sector_t stride; /* distance between far copies. - * This is size / far_copies unless - * far_offset, in which case it is - * 1 stripe. + * This is size / far_copies */ int chunk_shift; /* shift from chunks to sectors */ diff --git a/trunk/include/linux/raid/raid5.h b/trunk/include/linux/raid/raid5.h index 20ed4c997636..914af667044f 100644 --- a/trunk/include/linux/raid/raid5.h +++ b/trunk/include/linux/raid/raid5.h @@ -212,7 +212,6 @@ struct raid5_private_data { mddev_t *mddev; struct disk_info *spare; int chunk_size, level, algorithm; - int max_degraded; int raid_disks, working_disks, failed_disks; int max_nr_stripes; diff --git a/trunk/include/linux/rcupdate.h b/trunk/include/linux/rcupdate.h index b4ca73d65891..6312758393b6 100644 --- a/trunk/include/linux/rcupdate.h +++ b/trunk/include/linux/rcupdate.h @@ -163,22 +163,14 @@ extern int rcu_needs_cpu(int cpu); * * It is illegal to block while in an RCU read-side critical section. */ -#define rcu_read_lock() \ - do { \ - preempt_disable(); \ - __acquire(RCU); \ - } while(0) +#define rcu_read_lock() preempt_disable() /** * rcu_read_unlock - marks the end of an RCU read-side critical section. * * See rcu_read_lock() for more information. */ -#define rcu_read_unlock() \ - do { \ - __release(RCU); \ - preempt_enable(); \ - } while(0) +#define rcu_read_unlock() preempt_enable() /* * So where is rcu_write_lock()? It does not exist, as there is no @@ -201,22 +193,14 @@ extern int rcu_needs_cpu(int cpu); * can use just rcu_read_lock(). * */ -#define rcu_read_lock_bh() \ - do { \ - local_bh_disable(); \ - __acquire(RCU_BH); \ - } while(0) +#define rcu_read_lock_bh() local_bh_disable() /* * rcu_read_unlock_bh - marks the end of a softirq-only RCU critical section * * See rcu_read_lock_bh() for more information. */ -#define rcu_read_unlock_bh() \ - do { \ - __release(RCU_BH); \ - local_bh_enable(); \ - } while(0) +#define rcu_read_unlock_bh() local_bh_enable() /** * rcu_dereference - fetch an RCU-protected pointer in an @@ -274,7 +258,6 @@ extern void rcu_init(void); extern void rcu_check_callbacks(int cpu, int user); extern void rcu_restart_cpu(int cpu); extern long rcu_batches_completed(void); -extern long rcu_batches_completed_bh(void); /* Exported interfaces */ extern void FASTCALL(call_rcu(struct rcu_head *head, diff --git a/trunk/include/linux/reiserfs_fs.h b/trunk/include/linux/reiserfs_fs.h index daa2d83cefe8..5676c4210e2c 100644 --- a/trunk/include/linux/reiserfs_fs.h +++ b/trunk/include/linux/reiserfs_fs.h @@ -1973,7 +1973,7 @@ void reiserfs_unmap_buffer(struct buffer_head *); /* file.c */ extern struct inode_operations reiserfs_file_inode_operations; extern const struct file_operations reiserfs_file_operations; -extern const struct address_space_operations reiserfs_address_space_operations; +extern struct address_space_operations reiserfs_address_space_operations; /* fix_nodes.c */ diff --git a/trunk/include/linux/rtc.h b/trunk/include/linux/rtc.h index 5371e4e74595..36e2bf4b4315 100644 --- a/trunk/include/linux/rtc.h +++ b/trunk/include/linux/rtc.h @@ -34,8 +34,8 @@ struct rtc_time { * alarm API. */ struct rtc_wkalrm { - unsigned char enabled; /* 0 = alarm disabled, 1 = alarm enabled */ - unsigned char pending; /* 0 = alarm not pending, 1 = alarm pending */ + unsigned char enabled; /* 0 = alarm disable, 1 = alarm disabled */ + unsigned char pending; /* 0 = alarm pending, 1 = alarm not pending */ struct rtc_time time; /* time the alarm is set to */ }; diff --git a/trunk/include/linux/rtmutex.h b/trunk/include/linux/rtmutex.h deleted file mode 100644 index fa4a3b82ba70..000000000000 --- a/trunk/include/linux/rtmutex.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * RT Mutexes: blocking mutual exclusion locks with PI support - * - * started by Ingo Molnar and Thomas Gleixner: - * - * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar - * Copyright (C) 2006, Timesys Corp., Thomas Gleixner - * - * This file contains the public data structure and API definitions. - */ - -#ifndef __LINUX_RT_MUTEX_H -#define __LINUX_RT_MUTEX_H - -#include -#include -#include - -/* - * The rt_mutex structure - * - * @wait_lock: spinlock to protect the structure - * @wait_list: pilist head to enqueue waiters in priority order - * @owner: the mutex owner - */ -struct rt_mutex { - spinlock_t wait_lock; - struct plist_head wait_list; - struct task_struct *owner; -#ifdef CONFIG_DEBUG_RT_MUTEXES - int save_state; - struct list_head held_list_entry; - unsigned long acquire_ip; - const char *name, *file; - int line; - void *magic; -#endif -}; - -struct rt_mutex_waiter; -struct hrtimer_sleeper; - -#ifdef CONFIG_DEBUG_RT_MUTEXES - extern int rt_mutex_debug_check_no_locks_freed(const void *from, - unsigned long len); - extern void rt_mutex_debug_check_no_locks_held(struct task_struct *task); -#else - static inline int rt_mutex_debug_check_no_locks_freed(const void *from, - unsigned long len) - { - return 0; - } -# define rt_mutex_debug_check_no_locks_held(task) do { } while (0) -#endif - -#ifdef CONFIG_DEBUG_RT_MUTEXES -# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname) \ - , .name = #mutexname, .file = __FILE__, .line = __LINE__ -# define rt_mutex_init(mutex) __rt_mutex_init(mutex, __FUNCTION__) - extern void rt_mutex_debug_task_free(struct task_struct *tsk); -#else -# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname) -# define rt_mutex_init(mutex) __rt_mutex_init(mutex, NULL) -# define rt_mutex_debug_task_free(t) do { } while (0) -#endif - -#define __RT_MUTEX_INITIALIZER(mutexname) \ - { .wait_lock = SPIN_LOCK_UNLOCKED \ - , .wait_list = PLIST_HEAD_INIT(mutexname.wait_list, mutexname.wait_lock) \ - , .owner = NULL \ - __DEBUG_RT_MUTEX_INITIALIZER(mutexname)} - -#define DEFINE_RT_MUTEX(mutexname) \ - struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname) - -/*** - * rt_mutex_is_locked - is the mutex locked - * @lock: the mutex to be queried - * - * Returns 1 if the mutex is locked, 0 if unlocked. - */ -static inline int rt_mutex_is_locked(struct rt_mutex *lock) -{ - return lock->owner != NULL; -} - -extern void __rt_mutex_init(struct rt_mutex *lock, const char *name); -extern void rt_mutex_destroy(struct rt_mutex *lock); - -extern void rt_mutex_lock(struct rt_mutex *lock); -extern int rt_mutex_lock_interruptible(struct rt_mutex *lock, - int detect_deadlock); -extern int rt_mutex_timed_lock(struct rt_mutex *lock, - struct hrtimer_sleeper *timeout, - int detect_deadlock); - -extern int rt_mutex_trylock(struct rt_mutex *lock); - -extern void rt_mutex_unlock(struct rt_mutex *lock); - -#ifdef CONFIG_DEBUG_RT_MUTEXES -# define INIT_RT_MUTEX_DEBUG(tsk) \ - .held_list_head = LIST_HEAD_INIT(tsk.held_list_head), \ - .held_list_lock = SPIN_LOCK_UNLOCKED -#else -# define INIT_RT_MUTEX_DEBUG(tsk) -#endif - -#ifdef CONFIG_RT_MUTEXES -# define INIT_RT_MUTEXES(tsk) \ - .pi_waiters = PLIST_HEAD_INIT(tsk.pi_waiters, tsk.pi_lock), \ - INIT_RT_MUTEX_DEBUG(tsk) -#else -# define INIT_RT_MUTEXES(tsk) -#endif - -#endif diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index aaf723308ed4..8d11d9310db0 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -73,7 +73,6 @@ struct sched_param { #include #include #include -#include #include #include @@ -84,7 +83,6 @@ struct sched_param { #include struct exec_domain; -struct futex_pi_state; /* * List of flags we want to share for kernel threads, @@ -125,7 +123,6 @@ extern unsigned long nr_running(void); extern unsigned long nr_uninterruptible(void); extern unsigned long nr_active(void); extern unsigned long nr_iowait(void); -extern unsigned long weighted_cpuload(const int cpu); /* @@ -497,11 +494,8 @@ struct signal_struct { #define MAX_PRIO (MAX_RT_PRIO + 40) -#define rt_prio(prio) unlikely((prio) < MAX_RT_PRIO) -#define rt_task(p) rt_prio((p)->prio) +#define rt_task(p) (unlikely((p)->prio < MAX_RT_PRIO)) #define batch_task(p) (unlikely((p)->policy == SCHED_BATCH)) -#define has_rt_policy(p) \ - unlikely((p)->policy != SCHED_NORMAL && (p)->policy != SCHED_BATCH) /* * Some day this will be a full-fledged user tracking system.. @@ -564,9 +558,9 @@ enum idle_type /* * sched-domains (multiprocessor balancing) declarations: */ +#ifdef CONFIG_SMP #define SCHED_LOAD_SCALE 128UL /* increase resolution of load */ -#ifdef CONFIG_SMP #define SD_LOAD_BALANCE 1 /* Do load balancing on this domain. */ #define SD_BALANCE_NEWIDLE 2 /* Balance when about to become idle */ #define SD_BALANCE_EXEC 4 /* Balance on exec */ @@ -575,11 +569,6 @@ enum idle_type #define SD_WAKE_AFFINE 32 /* Wake task to waking CPU */ #define SD_WAKE_BALANCE 64 /* Perform balancing at task wakeup */ #define SD_SHARE_CPUPOWER 128 /* Domain members share cpu power */ -#define SD_POWERSAVINGS_BALANCE 256 /* Balance for power savings */ - -#define BALANCE_FOR_POWER ((sched_mc_power_savings || sched_smt_power_savings) \ - ? SD_POWERSAVINGS_BALANCE : 0) - struct sched_group { struct sched_group *next; /* Must be a circular list */ @@ -649,7 +638,7 @@ struct sched_domain { #endif }; -extern int partition_sched_domains(cpumask_t *partition1, +extern void partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2); /* @@ -724,13 +713,10 @@ struct task_struct { int lock_depth; /* BKL lock depth */ -#ifdef CONFIG_SMP -#ifdef __ARCH_WANT_UNLOCKED_CTXSW +#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW) int oncpu; #endif -#endif - int load_weight; /* for niceness load balancing purposes */ - int prio, static_prio, normal_prio; + int prio, static_prio; struct list_head run_list; prio_array_t *array; @@ -856,20 +842,8 @@ struct task_struct { u32 self_exec_id; /* Protection of (de-)allocation: mm, files, fs, tty, keyrings */ spinlock_t alloc_lock; - - /* Protection of the PI data structures: */ - spinlock_t pi_lock; - -#ifdef CONFIG_RT_MUTEXES - /* PI waiters blocked on a rt_mutex held by this task */ - struct plist_head pi_waiters; - /* Deadlock detection and priority inheritance handling */ - struct rt_mutex_waiter *pi_blocked_on; -# ifdef CONFIG_DEBUG_RT_MUTEXES - spinlock_t held_list_lock; - struct list_head held_list_head; -# endif -#endif +/* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */ + spinlock_t proc_lock; #ifdef CONFIG_DEBUG_MUTEXES /* mutex deadlock detection */ @@ -882,6 +856,7 @@ struct task_struct { /* VM state */ struct reclaim_state *reclaim_state; + struct dentry *proc_dentry; struct backing_dev_info *backing_dev_info; struct io_context *io_context; @@ -916,8 +891,6 @@ struct task_struct { #ifdef CONFIG_COMPAT struct compat_robust_list_head __user *compat_robust_list; #endif - struct list_head pi_state_list; - struct futex_pi_state *pi_state_cache; atomic_t fs_excl; /* holding fs exclusive resources */ struct rcu_head rcu; @@ -985,7 +958,6 @@ static inline void put_task_struct(struct task_struct *t) #define PF_SPREAD_PAGE 0x01000000 /* Spread page cache over cpuset */ #define PF_SPREAD_SLAB 0x02000000 /* Spread some slab caches over cpuset */ #define PF_MEMPOLICY 0x10000000 /* Non-default NUMA mempolicy */ -#define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ /* * Only the _current_ task can read/write to tsk->flags, but other @@ -1040,19 +1012,6 @@ static inline void idle_task_exit(void) {} #endif extern void sched_idle_next(void); - -#ifdef CONFIG_RT_MUTEXES -extern int rt_mutex_getprio(task_t *p); -extern void rt_mutex_setprio(task_t *p, int prio); -extern void rt_mutex_adjust_pi(task_t *p); -#else -static inline int rt_mutex_getprio(task_t *p) -{ - return p->normal_prio; -} -# define rt_mutex_adjust_pi(p) do { } while (0) -#endif - extern void set_user_nice(task_t *p, long nice); extern int task_prio(const task_t *p); extern int task_nice(const task_t *p); @@ -1153,7 +1112,7 @@ extern int force_sig_info(int, struct siginfo *, struct task_struct *); extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp); extern int kill_pg_info(int, struct siginfo *, pid_t); extern int kill_proc_info(int, struct siginfo *, pid_t); -extern int kill_proc_info_as_uid(int, struct siginfo *, pid_t, uid_t, uid_t, u32); +extern int kill_proc_info_as_uid(int, struct siginfo *, pid_t, uid_t, uid_t); extern void do_notify_parent(struct task_struct *, int); extern void force_sig(int, struct task_struct *); extern void force_sig_specific(int, struct task_struct *); @@ -1452,11 +1411,6 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm) extern long sched_setaffinity(pid_t pid, cpumask_t new_mask); extern long sched_getaffinity(pid_t pid, cpumask_t *mask); -#include -extern int sched_mc_power_savings, sched_smt_power_savings; -extern struct sysdev_attribute attr_sched_mc_power_savings, attr_sched_smt_power_savings; -extern int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls); - extern void normalize_rt_tasks(void); #ifdef CONFIG_PM diff --git a/trunk/include/linux/scx200.h b/trunk/include/linux/scx200.h index 693c0557e70b..a22f9e173ad2 100644 --- a/trunk/include/linux/scx200.h +++ b/trunk/include/linux/scx200.h @@ -49,3 +49,10 @@ extern unsigned scx200_cb_base; #define SCx200_REV 0x3d /* Revision Register */ #define SCx200_CBA 0x3e /* Configuration Base Address Register */ #define SCx200_CBA_SCRATCH 0x64 /* Configuration Base Address Scratchpad */ + +/* + Local variables: + compile-command: "make -C ../.. bzImage modules" + c-basic-offset: 8 + End: +*/ diff --git a/trunk/include/linux/scx200_gpio.h b/trunk/include/linux/scx200_gpio.h index 90dd069cc145..30cdd648ba79 100644 --- a/trunk/include/linux/scx200_gpio.h +++ b/trunk/include/linux/scx200_gpio.h @@ -1,6 +1,6 @@ #include -u32 scx200_gpio_configure(unsigned index, u32 set, u32 clear); +u32 scx200_gpio_configure(int index, u32 set, u32 clear); extern unsigned scx200_gpio_base; extern long scx200_gpio_shadow[2]; @@ -17,7 +17,7 @@ extern long scx200_gpio_shadow[2]; /* returns the value of the GPIO pin */ -static inline int scx200_gpio_get(unsigned index) { +static inline int scx200_gpio_get(int index) { __SCx200_GPIO_BANK; __SCx200_GPIO_IOADDR + 0x04; __SCx200_GPIO_INDEX; @@ -29,7 +29,7 @@ static inline int scx200_gpio_get(unsigned index) { driven if the GPIO is configured as an output, it might not be the state of the GPIO right now if the GPIO is configured as an input) */ -static inline int scx200_gpio_current(unsigned index) { +static inline int scx200_gpio_current(int index) { __SCx200_GPIO_BANK; __SCx200_GPIO_INDEX; @@ -38,7 +38,7 @@ static inline int scx200_gpio_current(unsigned index) { /* drive the GPIO signal high */ -static inline void scx200_gpio_set_high(unsigned index) { +static inline void scx200_gpio_set_high(int index) { __SCx200_GPIO_BANK; __SCx200_GPIO_IOADDR; __SCx200_GPIO_SHADOW; @@ -49,7 +49,7 @@ static inline void scx200_gpio_set_high(unsigned index) { /* drive the GPIO signal low */ -static inline void scx200_gpio_set_low(unsigned index) { +static inline void scx200_gpio_set_low(int index) { __SCx200_GPIO_BANK; __SCx200_GPIO_IOADDR; __SCx200_GPIO_SHADOW; @@ -60,7 +60,7 @@ static inline void scx200_gpio_set_low(unsigned index) { /* drive the GPIO signal to state */ -static inline void scx200_gpio_set(unsigned index, int state) { +static inline void scx200_gpio_set(int index, int state) { __SCx200_GPIO_BANK; __SCx200_GPIO_IOADDR; __SCx200_GPIO_SHADOW; @@ -73,7 +73,7 @@ static inline void scx200_gpio_set(unsigned index, int state) { } /* toggle the GPIO signal */ -static inline void scx200_gpio_change(unsigned index) { +static inline void scx200_gpio_change(int index) { __SCx200_GPIO_BANK; __SCx200_GPIO_IOADDR; __SCx200_GPIO_SHADOW; @@ -87,3 +87,10 @@ static inline void scx200_gpio_change(unsigned index) { #undef __SCx200_GPIO_SHADOW #undef __SCx200_GPIO_INDEX #undef __SCx200_GPIO_OUT + +/* + Local variables: + compile-command: "make -C ../.. bzImage modules" + c-basic-offset: 8 + End: +*/ diff --git a/trunk/include/linux/security.h b/trunk/include/linux/security.h index f75303831d09..d2c17bd91a29 100644 --- a/trunk/include/linux/security.h +++ b/trunk/include/linux/security.h @@ -67,7 +67,7 @@ struct xfrm_state; struct xfrm_user_sec_ctx; extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb); -extern int cap_netlink_recv(struct sk_buff *skb, int cap); +extern int cap_netlink_recv(struct sk_buff *skb); /* * Values used in the task_security_ops calls @@ -567,9 +567,6 @@ struct swap_info_struct; * @p. * @p contains the task_struct for the process. * Return 0 if permission is granted. - * @task_getsecid: - * Retrieve the security identifier of the process @p. - * @p contains the task_struct for the process and place is into @secid. * @task_setgroups: * Check permission before setting the supplementary group set of the * current process. @@ -585,10 +582,6 @@ struct swap_info_struct; * @p contains the task_struct of process. * @ioprio contains the new ioprio value * Return 0 if permission is granted. - * @task_getioprio - * Check permission before getting the ioprio value of @p. - * @p contains the task_struct of process. - * Return 0 if permission is granted. * @task_setrlimit: * Check permission before setting the resource limits of the current * process for @resource to @new_rlim. The old resource limit values can @@ -622,7 +615,6 @@ struct swap_info_struct; * @p contains the task_struct for process. * @info contains the signal information. * @sig contains the signal value. - * @secid contains the sid of the process where the signal originated * Return 0 if permission is granted. * @task_wait: * Check permission before allowing a process to reap a child process @p @@ -664,7 +656,6 @@ struct swap_info_struct; * Check permission before processing the received netlink message in * @skb. * @skb contains the sk_buff structure for the netlink message. - * @cap indicates the capability required * Return 0 if permission is granted. * * Security hooks for Unix domain networking. @@ -871,7 +862,6 @@ struct swap_info_struct; * Permit allocation of a key and assign security data. Note that key does * not have a serial number assigned at this point. * @key points to the key. - * @flags is the allocation flags * Return 0 if permission is granted, -ve error otherwise. * @key_free: * Notification of destruction; free security data. @@ -1227,18 +1217,16 @@ struct security_operations { int (*task_setpgid) (struct task_struct * p, pid_t pgid); int (*task_getpgid) (struct task_struct * p); int (*task_getsid) (struct task_struct * p); - void (*task_getsecid) (struct task_struct * p, u32 * secid); int (*task_setgroups) (struct group_info *group_info); int (*task_setnice) (struct task_struct * p, int nice); int (*task_setioprio) (struct task_struct * p, int ioprio); - int (*task_getioprio) (struct task_struct * p); int (*task_setrlimit) (unsigned int resource, struct rlimit * new_rlim); int (*task_setscheduler) (struct task_struct * p, int policy, struct sched_param * lp); int (*task_getscheduler) (struct task_struct * p); int (*task_movememory) (struct task_struct * p); int (*task_kill) (struct task_struct * p, - struct siginfo * info, int sig, u32 secid); + struct siginfo * info, int sig); int (*task_wait) (struct task_struct * p); int (*task_prctl) (int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, @@ -1277,7 +1265,7 @@ struct security_operations { struct sembuf * sops, unsigned nsops, int alter); int (*netlink_send) (struct sock * sk, struct sk_buff * skb); - int (*netlink_recv) (struct sk_buff * skb, int cap); + int (*netlink_recv) (struct sk_buff * skb); /* allow module stacking */ int (*register_security) (const char *name, @@ -1336,7 +1324,7 @@ struct security_operations { /* key management security hooks */ #ifdef CONFIG_KEYS - int (*key_alloc)(struct key *key, struct task_struct *tsk, unsigned long flags); + int (*key_alloc)(struct key *key, struct task_struct *tsk); void (*key_free)(struct key *key); int (*key_permission)(key_ref_t key_ref, struct task_struct *context, @@ -1849,11 +1837,6 @@ static inline int security_task_getsid (struct task_struct *p) return security_ops->task_getsid (p); } -static inline void security_task_getsecid (struct task_struct *p, u32 *secid) -{ - security_ops->task_getsecid (p, secid); -} - static inline int security_task_setgroups (struct group_info *group_info) { return security_ops->task_setgroups (group_info); @@ -1869,11 +1852,6 @@ static inline int security_task_setioprio (struct task_struct *p, int ioprio) return security_ops->task_setioprio (p, ioprio); } -static inline int security_task_getioprio (struct task_struct *p) -{ - return security_ops->task_getioprio (p); -} - static inline int security_task_setrlimit (unsigned int resource, struct rlimit *new_rlim) { @@ -1898,10 +1876,9 @@ static inline int security_task_movememory (struct task_struct *p) } static inline int security_task_kill (struct task_struct *p, - struct siginfo *info, int sig, - u32 secid) + struct siginfo *info, int sig) { - return security_ops->task_kill (p, info, sig, secid); + return security_ops->task_kill (p, info, sig); } static inline int security_task_wait (struct task_struct *p) @@ -2054,9 +2031,9 @@ static inline int security_netlink_send(struct sock *sk, struct sk_buff * skb) return security_ops->netlink_send(sk, skb); } -static inline int security_netlink_recv(struct sk_buff * skb, int cap) +static inline int security_netlink_recv(struct sk_buff * skb) { - return security_ops->netlink_recv(skb, cap); + return security_ops->netlink_recv(skb); } /* prototypes */ @@ -2512,9 +2489,6 @@ static inline int security_task_getsid (struct task_struct *p) return 0; } -static inline void security_task_getsecid (struct task_struct *p, u32 *secid) -{ } - static inline int security_task_setgroups (struct group_info *group_info) { return 0; @@ -2530,11 +2504,6 @@ static inline int security_task_setioprio (struct task_struct *p, int ioprio) return 0; } -static inline int security_task_getioprio (struct task_struct *p) -{ - return 0; -} - static inline int security_task_setrlimit (unsigned int resource, struct rlimit *new_rlim) { @@ -2559,8 +2528,7 @@ static inline int security_task_movememory (struct task_struct *p) } static inline int security_task_kill (struct task_struct *p, - struct siginfo *info, int sig, - u32 secid) + struct siginfo *info, int sig) { return 0; } @@ -2701,9 +2669,9 @@ static inline int security_netlink_send (struct sock *sk, struct sk_buff *skb) return cap_netlink_send (sk, skb); } -static inline int security_netlink_recv (struct sk_buff *skb, int cap) +static inline int security_netlink_recv (struct sk_buff *skb) { - return cap_netlink_recv (skb, cap); + return cap_netlink_recv (skb); } static inline struct dentry *securityfs_create_dir(const char *name, @@ -3072,10 +3040,9 @@ static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid #ifdef CONFIG_KEYS #ifdef CONFIG_SECURITY static inline int security_key_alloc(struct key *key, - struct task_struct *tsk, - unsigned long flags) + struct task_struct *tsk) { - return security_ops->key_alloc(key, tsk, flags); + return security_ops->key_alloc(key, tsk); } static inline void security_key_free(struct key *key) @@ -3093,8 +3060,7 @@ static inline int security_key_permission(key_ref_t key_ref, #else static inline int security_key_alloc(struct key *key, - struct task_struct *tsk, - unsigned long flags) + struct task_struct *tsk) { return 0; } diff --git a/trunk/include/linux/serial_core.h b/trunk/include/linux/serial_core.h index fc1104a2cfa9..951c4e858274 100644 --- a/trunk/include/linux/serial_core.h +++ b/trunk/include/linux/serial_core.h @@ -336,6 +336,7 @@ struct uart_driver { struct module *owner; const char *driver_name; const char *dev_name; + const char *devfs_name; int major; int minor; int nr; diff --git a/trunk/include/linux/signal.h b/trunk/include/linux/signal.h index 117135e33d67..1e4ce7225eee 100644 --- a/trunk/include/linux/signal.h +++ b/trunk/include/linux/signal.h @@ -8,6 +8,32 @@ #include #include +/* + * These values of sa_flags are used only by the kernel as part of the + * irq handling routines. + * + * SA_INTERRUPT is also used by the irq handling routines. + * SA_SHIRQ is for shared interrupt support on PCI and EISA. + * SA_PROBEIRQ is set by callers when they expect sharing mismatches to occur + */ +#define SA_SAMPLE_RANDOM SA_RESTART +#define SA_SHIRQ 0x04000000 +#define SA_PROBEIRQ 0x08000000 + +/* + * As above, these correspond to the IORESOURCE_IRQ_* defines in + * linux/ioport.h to select the interrupt line behaviour. When + * requesting an interrupt without specifying a SA_TRIGGER, the + * setting should be assumed to be "as already configured", which + * may be as per machine or firmware initialisation. + */ +#define SA_TRIGGER_LOW 0x00000008 +#define SA_TRIGGER_HIGH 0x00000004 +#define SA_TRIGGER_FALLING 0x00000002 +#define SA_TRIGGER_RISING 0x00000001 +#define SA_TRIGGER_MASK (SA_TRIGGER_HIGH|SA_TRIGGER_LOW|\ + SA_TRIGGER_RISING|SA_TRIGGER_FALLING) + /* * Real Time signals may be queued. */ diff --git a/trunk/include/linux/skbuff.h b/trunk/include/linux/skbuff.h index 57d7d4965f9a..16eef03ce0eb 100644 --- a/trunk/include/linux/skbuff.h +++ b/trunk/include/linux/skbuff.h @@ -171,15 +171,7 @@ enum { enum { SKB_GSO_TCPV4 = 1 << 0, - SKB_GSO_UDP = 1 << 1, - - /* This indicates the skb is from an untrusted source. */ - SKB_GSO_DODGY = 1 << 2, - - /* This indicates the tcp segment has CWR set. */ - SKB_GSO_TCP_ECN = 1 << 3, - - SKB_GSO_TCPV6 = 1 << 4, + SKB_GSO_UDPV4 = 1 << 1, }; /** @@ -1306,7 +1298,8 @@ extern void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to); extern void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len); -extern struct sk_buff *skb_segment(struct sk_buff *skb, int features); +extern void skb_release_data(struct sk_buff *skb); +extern struct sk_buff *skb_segment(struct sk_buff *skb, int sg); static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, int len, void *buffer) diff --git a/trunk/include/linux/smp.h b/trunk/include/linux/smp.h index 837e8bce1349..c93c3fe4308c 100644 --- a/trunk/include/linux/smp.h +++ b/trunk/include/linux/smp.h @@ -125,6 +125,4 @@ static inline void smp_send_reschedule(int cpu) { } #define put_cpu() preempt_enable() #define put_cpu_no_resched() preempt_enable_no_resched() -void smp_setup_processor_id(void); - #endif /* __LINUX_SMP_H */ diff --git a/trunk/include/linux/spi/spi.h b/trunk/include/linux/spi/spi.h index c8bb68099eb9..e928c0dcc297 100644 --- a/trunk/include/linux/spi/spi.h +++ b/trunk/include/linux/spi/spi.h @@ -642,14 +642,10 @@ struct spi_board_info { u16 bus_num; u16 chip_select; - /* mode becomes spi_device.mode, and is essential for chips - * where the default of SPI_CS_HIGH = 0 is wrong. - */ - u8 mode; - /* ... may need additional spi_device chip config data here. * avoid stuff protocol drivers can set; but include stuff * needed to behave without being bound to a driver: + * - chipselect polarity * - quirks like clock rate mattering when not selected */ }; diff --git a/trunk/include/linux/sunrpc/gss_api.h b/trunk/include/linux/sunrpc/gss_api.h index 6e112cc5cdda..9b8bcf125c18 100644 --- a/trunk/include/linux/sunrpc/gss_api.h +++ b/trunk/include/linux/sunrpc/gss_api.h @@ -126,7 +126,7 @@ struct gss_api_mech *gss_mech_get_by_pseudoflavor(u32); /* Just increments the mechanism's reference count and returns its input: */ struct gss_api_mech * gss_mech_get(struct gss_api_mech *); -/* For every successful gss_mech_get or gss_mech_get_by_* call there must be a +/* For every succesful gss_mech_get or gss_mech_get_by_* call there must be a * corresponding call to gss_mech_put. */ void gss_mech_put(struct gss_api_mech *); diff --git a/trunk/include/linux/sunrpc/svc.h b/trunk/include/linux/sunrpc/svc.h index 7b27c09b5604..503564384545 100644 --- a/trunk/include/linux/sunrpc/svc.h +++ b/trunk/include/linux/sunrpc/svc.h @@ -159,9 +159,7 @@ struct svc_rqst { * determine what device number * to report (real or virtual) */ - int rq_sendfile_ok; /* turned off in gss privacy - * to prevent encrypting page - * cache pages */ + wait_queue_head_t rq_wait; /* synchronization */ }; diff --git a/trunk/include/linux/swap.h b/trunk/include/linux/swap.h index cf6ca6e377bd..dc3f3aa0c83e 100644 --- a/trunk/include/linux/swap.h +++ b/trunk/include/linux/swap.h @@ -189,6 +189,7 @@ extern long vm_total_pages; #ifdef CONFIG_NUMA extern int zone_reclaim_mode; +extern int zone_reclaim_interval; extern int zone_reclaim(struct zone *, gfp_t, unsigned int); #else #define zone_reclaim_mode 0 @@ -198,8 +199,6 @@ static inline int zone_reclaim(struct zone *z, gfp_t mask, unsigned int order) } #endif -extern int kswapd_run(int nid); - #ifdef CONFIG_MMU /* linux/mm/shmem.c */ extern int shmem_unuse(swp_entry_t entry, struct page *page); diff --git a/trunk/include/linux/syscalls.h b/trunk/include/linux/syscalls.h index 008f04c56737..33785b79d548 100644 --- a/trunk/include/linux/syscalls.h +++ b/trunk/include/linux/syscalls.h @@ -174,9 +174,9 @@ asmlinkage long sys_waitid(int which, pid_t pid, int options, struct rusage __user *ru); asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options); asmlinkage long sys_set_tid_address(int __user *tidptr); -asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, +asmlinkage long sys_futex(u32 __user *uaddr, int op, int val, struct timespec __user *utime, u32 __user *uaddr2, - u32 val3); + int val3); asmlinkage long sys_init_module(void __user *umod, unsigned long len, const char __user *uargs); diff --git a/trunk/include/linux/sysctl.h b/trunk/include/linux/sysctl.h index 46e4d8f2771f..6a60770984e9 100644 --- a/trunk/include/linux/sysctl.h +++ b/trunk/include/linux/sysctl.h @@ -148,12 +148,9 @@ enum KERN_SPIN_RETRY=70, /* int: number of spinlock retries */ KERN_ACPI_VIDEO_FLAGS=71, /* int: flags for setting up video after ACPI sleep */ KERN_IA64_UNALIGNED=72, /* int: ia64 unaligned userland trap enable */ - KERN_COMPAT_LOG=73, /* int: print compat layer messages */ - KERN_MAX_LOCK_DEPTH=74, }; - /* CTL_VM names: */ enum { @@ -190,7 +187,6 @@ enum VM_ZONE_RECLAIM_MODE=31, /* reclaim local zone memory before going off node */ VM_ZONE_RECLAIM_INTERVAL=32, /* time period to wait after reclaim failure */ VM_PANIC_ON_OOM=33, /* panic at out-of-memory */ - VM_VDSO_ENABLED=34, /* map VDSO into new processes? */ }; diff --git a/trunk/include/linux/time.h b/trunk/include/linux/time.h index c05f8bb9a323..0cd696cee998 100644 --- a/trunk/include/linux/time.h +++ b/trunk/include/linux/time.h @@ -28,13 +28,10 @@ struct timezone { #ifdef __KERNEL__ /* Parameters used to convert the timespec values: */ -#define MSEC_PER_SEC 1000L -#define USEC_PER_MSEC 1000L -#define NSEC_PER_USEC 1000L -#define NSEC_PER_MSEC 1000000L -#define USEC_PER_SEC 1000000L -#define NSEC_PER_SEC 1000000000L -#define FSEC_PER_SEC 1000000000000000L +#define MSEC_PER_SEC 1000L +#define USEC_PER_SEC 1000000L +#define NSEC_PER_SEC 1000000000L +#define NSEC_PER_USEC 1000L static inline int timespec_equal(struct timespec *a, struct timespec *b) { @@ -80,8 +77,6 @@ extern struct timespec xtime; extern struct timespec wall_to_monotonic; extern seqlock_t xtime_lock; -void timekeeping_init(void); - static inline unsigned long get_seconds(void) { return xtime.tv_sec; @@ -105,7 +100,6 @@ extern int do_getitimer(int which, struct itimerval *value); extern void getnstimeofday(struct timespec *tv); extern struct timespec timespec_trunc(struct timespec t, unsigned gran); -extern int timekeeping_is_continuous(void); /** * timespec_to_ns - Convert timespec to nanoseconds @@ -148,20 +142,6 @@ extern struct timespec ns_to_timespec(const s64 nsec); */ extern struct timeval ns_to_timeval(const s64 nsec); -/** - * timespec_add_ns - Adds nanoseconds to a timespec - * @a: pointer to timespec to be incremented - * @ns: unsigned nanoseconds value to be added - */ -static inline void timespec_add_ns(struct timespec *a, u64 ns) -{ - ns += a->tv_nsec; - while(unlikely(ns >= NSEC_PER_SEC)) { - ns -= NSEC_PER_SEC; - a->tv_sec++; - } - a->tv_nsec = ns; -} #endif /* __KERNEL__ */ #define NFDBITS __NFDBITS diff --git a/trunk/include/linux/timex.h b/trunk/include/linux/timex.h index 19bb6538b49e..34d3ccff7bbb 100644 --- a/trunk/include/linux/timex.h +++ b/trunk/include/linux/timex.h @@ -303,8 +303,6 @@ time_interpolator_reset(void) #endif /* !CONFIG_TIME_INTERPOLATION */ -#define TICK_LENGTH_SHIFT 32 - /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */ extern u64 current_tick_length(void); diff --git a/trunk/include/linux/topology.h b/trunk/include/linux/topology.h index ec1eca85290a..a305ae2e44b6 100644 --- a/trunk/include/linux/topology.h +++ b/trunk/include/linux/topology.h @@ -134,8 +134,7 @@ .flags = SD_LOAD_BALANCE \ | SD_BALANCE_NEWIDLE \ | SD_BALANCE_EXEC \ - | SD_WAKE_AFFINE \ - | BALANCE_FOR_POWER, \ + | SD_WAKE_AFFINE, \ .last_balance = jiffies, \ .balance_interval = 1, \ .nr_balance_failed = 0, \ diff --git a/trunk/include/linux/tty.h b/trunk/include/linux/tty.h index b3b807e4b050..cb35ca50a0a6 100644 --- a/trunk/include/linux/tty.h +++ b/trunk/include/linux/tty.h @@ -57,6 +57,7 @@ struct tty_buffer { unsigned char *flag_buf_ptr; int used; int size; + int active; int commit; int read; /* Data points here */ @@ -258,6 +259,7 @@ struct tty_struct { #define TTY_DO_WRITE_WAKEUP 5 /* Call write_wakeup after queuing new */ #define TTY_PUSH 6 /* n_tty private */ #define TTY_CLOSING 7 /* ->close() in progress */ +#define TTY_DONT_FLIP 8 /* Defer buffer flip */ #define TTY_LDISC 9 /* Line discipline attached */ #define TTY_HW_COOK_OUT 14 /* Hardware can do output cooking */ #define TTY_HW_COOK_IN 15 /* Hardware can do input cooking */ diff --git a/trunk/include/linux/tty_driver.h b/trunk/include/linux/tty_driver.h index 58c961c9e170..b368b296d035 100644 --- a/trunk/include/linux/tty_driver.h +++ b/trunk/include/linux/tty_driver.h @@ -157,6 +157,7 @@ struct tty_driver { struct cdev cdev; struct module *owner; const char *driver_name; + const char *devfs_name; const char *name; int name_base; /* offset of printed name */ int major; /* major device number */ @@ -241,15 +242,8 @@ void tty_set_operations(struct tty_driver *driver, struct tty_operations *op); * is also a promise, if the above case is true, not to signal * overruns, either.) * - * TTY_DRIVER_DYNAMIC_DEV --- if set, the individual tty devices need - * to be registered with a call to tty_register_driver() when the - * device is found in the system and unregistered with a call to - * tty_unregister_device() so the devices will be show up - * properly in sysfs. If not set, driver->num entries will be - * created by the tty core in sysfs when tty_register_driver() is - * called. This is to be used by drivers that have tty devices - * that can appear and disappear while the main tty driver is - * registered with the tty core. + * TTY_DRIVER_NO_DEVFS --- if set, do not create devfs entries. This + * is only used by tty_register_driver(). * * TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead * use dynamic memory keyed through the devpts filesystem. This @@ -258,7 +252,7 @@ void tty_set_operations(struct tty_driver *driver, struct tty_operations *op); #define TTY_DRIVER_INSTALLED 0x0001 #define TTY_DRIVER_RESET_TERMIOS 0x0002 #define TTY_DRIVER_REAL_RAW 0x0004 -#define TTY_DRIVER_DYNAMIC_DEV 0x0008 +#define TTY_DRIVER_NO_DEVFS 0x0008 #define TTY_DRIVER_DEVPTS_MEM 0x0010 /* tty driver types */ diff --git a/trunk/include/linux/tty_flip.h b/trunk/include/linux/tty_flip.h index eb677cf56106..31548303ee37 100644 --- a/trunk/include/linux/tty_flip.h +++ b/trunk/include/linux/tty_flip.h @@ -12,7 +12,7 @@ static inline int tty_insert_flip_char(struct tty_struct *tty, unsigned char ch, char flag) { struct tty_buffer *tb = tty->buf.tail; - if (tb && tb->used < tb->size) { + if (tb && tb->active && tb->used < tb->size) { tb->flag_buf_ptr[tb->used] = flag; tb->char_buf_ptr[tb->used++] = ch; return 1; diff --git a/trunk/include/linux/types.h b/trunk/include/linux/types.h index 3f235660a3cd..a5e46e783ffa 100644 --- a/trunk/include/linux/types.h +++ b/trunk/include/linux/types.h @@ -177,15 +177,8 @@ typedef __u64 __bitwise __be64; #ifdef __KERNEL__ typedef unsigned __bitwise__ gfp_t; - -#ifdef CONFIG_RESOURCES_64BIT -typedef u64 resource_size_t; -#else -typedef u32 resource_size_t; #endif -#endif /* __KERNEL__ */ - struct ustat { __kernel_daddr_t f_tfree; __kernel_ino_t f_tinode; diff --git a/trunk/include/linux/udp.h b/trunk/include/linux/udp.h index 90223f057d50..bdd39be09406 100644 --- a/trunk/include/linux/udp.h +++ b/trunk/include/linux/udp.h @@ -46,7 +46,7 @@ struct udp_sock { unsigned int corkflag; /* Cork is required */ __u16 encap_type; /* Is this an Encapsulation socket? */ /* - * Following member retains the information to create a UDP header + * Following member retains the infomation to create a UDP header * when the socket is uncorked. */ __u16 len; /* total length of pending frames */ diff --git a/trunk/include/linux/ufs_fs.h b/trunk/include/linux/ufs_fs.h index fc62887c5206..914f911325be 100644 --- a/trunk/include/linux/ufs_fs.h +++ b/trunk/include/linux/ufs_fs.h @@ -966,7 +966,7 @@ extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, extern struct inode_operations ufs_file_inode_operations; extern const struct file_operations ufs_file_operations; -extern const struct address_space_operations ufs_aops; +extern struct address_space_operations ufs_aops; /* ialloc.c */ extern void ufs_free_inode (struct inode *inode); @@ -993,7 +993,7 @@ extern void ufs_panic (struct super_block *, const char *, const char *, ...) __ extern struct inode_operations ufs_fast_symlink_inode_operations; /* truncate.c */ -extern int ufs_truncate (struct inode *, loff_t); +extern void ufs_truncate (struct inode *); static inline struct ufs_sb_info *UFS_SB(struct super_block *sb) { diff --git a/trunk/include/linux/unwind.h b/trunk/include/linux/unwind.h deleted file mode 100644 index ce48e2cd37a2..000000000000 --- a/trunk/include/linux/unwind.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef _LINUX_UNWIND_H -#define _LINUX_UNWIND_H - -/* - * Copyright (C) 2002-2006 Novell, Inc. - * Jan Beulich - * This code is released under version 2 of the GNU GPL. - * - * A simple API for unwinding kernel stacks. This is used for - * debugging and error reporting purposes. The kernel doesn't need - * full-blown stack unwinding with all the bells and whistles, so there - * is not much point in implementing the full Dwarf2 unwind API. - */ - -#include - -struct module; - -#ifdef CONFIG_STACK_UNWIND - -#include - -#ifndef ARCH_UNWIND_SECTION_NAME -#define ARCH_UNWIND_SECTION_NAME ".eh_frame" -#endif - -/* - * Initialize unwind support. - */ -extern void unwind_init(void); - -#ifdef CONFIG_MODULES - -extern void *unwind_add_table(struct module *, - const void *table_start, - unsigned long table_size); - -extern void unwind_remove_table(void *handle, int init_only); - -#endif - -extern int unwind_init_frame_info(struct unwind_frame_info *, - struct task_struct *, - /*const*/ struct pt_regs *); - -/* - * Prepare to unwind a blocked task. - */ -extern int unwind_init_blocked(struct unwind_frame_info *, - struct task_struct *); - -/* - * Prepare to unwind the currently running thread. - */ -extern int unwind_init_running(struct unwind_frame_info *, - asmlinkage int (*callback)(struct unwind_frame_info *, - void *arg), - void *arg); - -/* - * Unwind to previous to frame. Returns 0 if successful, negative - * number in case of an error. - */ -extern int unwind(struct unwind_frame_info *); - -/* - * Unwind until the return pointer is in user-land (or until an error - * occurs). Returns 0 if successful, negative number in case of - * error. - */ -extern int unwind_to_user(struct unwind_frame_info *); - -#else - -struct unwind_frame_info {}; - -static inline void unwind_init(void) {} - -#ifdef CONFIG_MODULES - -static inline void *unwind_add_table(struct module *mod, - const void *table_start, - unsigned long table_size) -{ - return NULL; -} - -#endif - -static inline void unwind_remove_table(void *handle, int init_only) -{ -} - -static inline int unwind_init_frame_info(struct unwind_frame_info *info, - struct task_struct *tsk, - const struct pt_regs *regs) -{ - return -ENOSYS; -} - -static inline int unwind_init_blocked(struct unwind_frame_info *info, - struct task_struct *tsk) -{ - return -ENOSYS; -} - -static inline int unwind_init_running(struct unwind_frame_info *info, - asmlinkage int (*cb)(struct unwind_frame_info *, - void *arg), - void *arg) -{ - return -ENOSYS; -} - -static inline int unwind(struct unwind_frame_info *info) -{ - return -ENOSYS; -} - -static inline int unwind_to_user(struct unwind_frame_info *info) -{ - return -ENOSYS; -} - -#endif - -#endif /* _LINUX_UNWIND_H */ diff --git a/trunk/include/linux/videodev2.h b/trunk/include/linux/videodev2.h index a62673dad76e..4f428547ec09 100644 --- a/trunk/include/linux/videodev2.h +++ b/trunk/include/linux/videodev2.h @@ -245,7 +245,6 @@ struct v4l2_pix_format #define V4L2_PIX_FMT_YUV420 v4l2_fourcc('Y','U','1','2') /* 12 YUV 4:2:0 */ #define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */ #define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */ -#define V4L2_PIX_FMT_HM12 v4l2_fourcc('H','M','1','2') /* 8 YUV 4:1:1 16x16 macroblocks */ /* see http://www.siliconimaging.com/RGB%20Bayer.htm */ #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ @@ -822,11 +821,6 @@ enum v4l2_mpeg_stream_type { #define V4L2_CID_MPEG_STREAM_PID_PCR (V4L2_CID_MPEG_BASE+4) #define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO (V4L2_CID_MPEG_BASE+5) #define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO (V4L2_CID_MPEG_BASE+6) -#define V4L2_CID_MPEG_STREAM_VBI_FMT (V4L2_CID_MPEG_BASE+7) -enum v4l2_mpeg_stream_vbi_fmt { - V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */ - V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, IVTV format */ -}; /* MPEG audio */ #define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ (V4L2_CID_MPEG_BASE+100) diff --git a/trunk/include/linux/vmstat.h b/trunk/include/linux/vmstat.h deleted file mode 100644 index 3e0daf54133e..000000000000 --- a/trunk/include/linux/vmstat.h +++ /dev/null @@ -1,215 +0,0 @@ -#ifndef _LINUX_VMSTAT_H -#define _LINUX_VMSTAT_H - -#include -#include -#include -#include -#include - -#ifdef CONFIG_VM_EVENT_COUNTERS -/* - * Light weight per cpu counter implementation. - * - * Counters should only be incremented and no critical kernel component - * should rely on the counter values. - * - * Counters are handled completely inline. On many platforms the code - * generated will simply be the increment of a global address. - */ - -#define FOR_ALL_ZONES(x) x##_DMA, x##_DMA32, x##_NORMAL, x##_HIGH - -enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, - FOR_ALL_ZONES(PGALLOC), - PGFREE, PGACTIVATE, PGDEACTIVATE, - PGFAULT, PGMAJFAULT, - FOR_ALL_ZONES(PGREFILL), - FOR_ALL_ZONES(PGSTEAL), - FOR_ALL_ZONES(PGSCAN_KSWAPD), - FOR_ALL_ZONES(PGSCAN_DIRECT), - PGINODESTEAL, SLABS_SCANNED, KSWAPD_STEAL, KSWAPD_INODESTEAL, - PAGEOUTRUN, ALLOCSTALL, PGROTATED, - NR_VM_EVENT_ITEMS -}; - -struct vm_event_state { - unsigned long event[NR_VM_EVENT_ITEMS]; -}; - -DECLARE_PER_CPU(struct vm_event_state, vm_event_states); - -static inline void __count_vm_event(enum vm_event_item item) -{ - __get_cpu_var(vm_event_states.event[item])++; -} - -static inline void count_vm_event(enum vm_event_item item) -{ - get_cpu_var(vm_event_states.event[item])++; - put_cpu(); -} - -static inline void __count_vm_events(enum vm_event_item item, long delta) -{ - __get_cpu_var(vm_event_states.event[item]) += delta; -} - -static inline void count_vm_events(enum vm_event_item item, long delta) -{ - get_cpu_var(vm_event_states.event[item])++; - put_cpu(); -} - -extern void all_vm_events(unsigned long *); -extern void vm_events_fold_cpu(int cpu); - -#else - -/* Disable counters */ -#define get_cpu_vm_events(e) 0L -#define count_vm_event(e) do { } while (0) -#define count_vm_events(e,d) do { } while (0) -#define __count_vm_event(e) do { } while (0) -#define __count_vm_events(e,d) do { } while (0) -#define vm_events_fold_cpu(x) do { } while (0) - -#endif /* CONFIG_VM_EVENT_COUNTERS */ - -#define __count_zone_vm_events(item, zone, delta) \ - __count_vm_events(item##_DMA + zone_idx(zone), delta) - -/* - * Zone based page accounting with per cpu differentials. - */ -extern atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS]; - -static inline void zone_page_state_add(long x, struct zone *zone, - enum zone_stat_item item) -{ - atomic_long_add(x, &zone->vm_stat[item]); - atomic_long_add(x, &vm_stat[item]); -} - -static inline unsigned long global_page_state(enum zone_stat_item item) -{ - long x = atomic_long_read(&vm_stat[item]); -#ifdef CONFIG_SMP - if (x < 0) - x = 0; -#endif - return x; -} - -static inline unsigned long zone_page_state(struct zone *zone, - enum zone_stat_item item) -{ - long x = atomic_long_read(&zone->vm_stat[item]); -#ifdef CONFIG_SMP - if (x < 0) - x = 0; -#endif - return x; -} - -#ifdef CONFIG_NUMA -/* - * Determine the per node value of a stat item. This function - * is called frequently in a NUMA machine, so try to be as - * frugal as possible. - */ -static inline unsigned long node_page_state(int node, - enum zone_stat_item item) -{ - struct zone *zones = NODE_DATA(node)->node_zones; - - return -#ifndef CONFIG_DMA_IS_NORMAL -#if !defined(CONFIG_DMA_IS_DMA32) && BITS_PER_LONG >= 64 - zone_page_state(&zones[ZONE_DMA32], item) + -#endif - zone_page_state(&zones[ZONE_NORMAL], item) + -#endif -#ifdef CONFIG_HIGHMEM - zone_page_state(&zones[ZONE_HIGHMEM], item) + -#endif - zone_page_state(&zones[ZONE_DMA], item); -} - -extern void zone_statistics(struct zonelist *, struct zone *); - -#else - -#define node_page_state(node, item) global_page_state(item) -#define zone_statistics(_zl,_z) do { } while (0) - -#endif /* CONFIG_NUMA */ - -#define __add_zone_page_state(__z, __i, __d) \ - __mod_zone_page_state(__z, __i, __d) -#define __sub_zone_page_state(__z, __i, __d) \ - __mod_zone_page_state(__z, __i,-(__d)) - -#define add_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, __d) -#define sub_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, -(__d)) - -static inline void zap_zone_vm_stats(struct zone *zone) -{ - memset(zone->vm_stat, 0, sizeof(zone->vm_stat)); -} - -extern void inc_zone_state(struct zone *, enum zone_stat_item); - -#ifdef CONFIG_SMP -void __mod_zone_page_state(struct zone *, enum zone_stat_item item, int); -void __inc_zone_page_state(struct page *, enum zone_stat_item); -void __dec_zone_page_state(struct page *, enum zone_stat_item); - -void mod_zone_page_state(struct zone *, enum zone_stat_item, int); -void inc_zone_page_state(struct page *, enum zone_stat_item); -void dec_zone_page_state(struct page *, enum zone_stat_item); - -extern void inc_zone_state(struct zone *, enum zone_stat_item); - -void refresh_cpu_vm_stats(int); -void refresh_vm_stats(void); - -#else /* CONFIG_SMP */ - -/* - * We do not maintain differentials in a single processor configuration. - * The functions directly modify the zone and global counters. - */ -static inline void __mod_zone_page_state(struct zone *zone, - enum zone_stat_item item, int delta) -{ - zone_page_state_add(delta, zone, item); -} - -static inline void __inc_zone_page_state(struct page *page, - enum zone_stat_item item) -{ - atomic_long_inc(&page_zone(page)->vm_stat[item]); - atomic_long_inc(&vm_stat[item]); -} - -static inline void __dec_zone_page_state(struct page *page, - enum zone_stat_item item) -{ - atomic_long_dec(&page_zone(page)->vm_stat[item]); - atomic_long_dec(&vm_stat[item]); -} - -/* - * We only use atomic operations to update counters. So there is no need to - * disable interrupts. - */ -#define inc_zone_page_state __inc_zone_page_state -#define dec_zone_page_state __dec_zone_page_state -#define mod_zone_page_state __mod_zone_page_state - -static inline void refresh_cpu_vm_stats(int cpu) { } -static inline void refresh_vm_stats(void) { } -#endif - -#endif /* _LINUX_VMSTAT_H */ diff --git a/trunk/include/linux/watchdog.h b/trunk/include/linux/watchdog.h index 011bcfeb9f09..1192ed8f4fe8 100644 --- a/trunk/include/linux/watchdog.h +++ b/trunk/include/linux/watchdog.h @@ -28,9 +28,6 @@ struct watchdog_info { #define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int) #define WDIOC_SETTIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 6, int) #define WDIOC_GETTIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 7, int) -#define WDIOC_SETPRETIMEOUT _IOWR(WATCHDOG_IOCTL_BASE, 8, int) -#define WDIOC_GETPRETIMEOUT _IOR(WATCHDOG_IOCTL_BASE, 9, int) -#define WDIOC_GETTIMELEFT _IOR(WATCHDOG_IOCTL_BASE, 10, int) #define WDIOF_UNKNOWN -1 /* Unknown flag error */ #define WDIOS_UNKNOWN -1 /* Unknown status error */ @@ -41,10 +38,9 @@ struct watchdog_info { #define WDIOF_EXTERN2 0x0008 /* External relay 2 */ #define WDIOF_POWERUNDER 0x0010 /* Power bad/power fault */ #define WDIOF_CARDRESET 0x0020 /* Card previously reset the CPU */ -#define WDIOF_POWEROVER 0x0040 /* Power over voltage */ -#define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */ -#define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */ -#define WDIOF_PRETIMEOUT 0x0200 /* Pretimeout (in seconds), get/set */ +#define WDIOF_POWEROVER 0x0040 /* Power over voltage */ +#define WDIOF_SETTIMEOUT 0x0080 /* Set timeout (in seconds) */ +#define WDIOF_MAGICCLOSE 0x0100 /* Supports magic close char */ #define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */ #define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */ diff --git a/trunk/include/media/cx2341x.h b/trunk/include/media/cx2341x.h index d91d88f93c8b..51fb06b4c394 100644 --- a/trunk/include/media/cx2341x.h +++ b/trunk/include/media/cx2341x.h @@ -25,13 +25,8 @@ enum cx2341x_port { CX2341X_PORT_SERIAL = 2 }; -enum cx2341x_cap { - CX2341X_CAP_HAS_SLICED_VBI = 1 << 0, -}; - struct cx2341x_mpeg_params { /* misc */ - u32 capabilities; enum cx2341x_port port; u16 width; u16 height; @@ -39,7 +34,6 @@ struct cx2341x_mpeg_params { /* stream */ enum v4l2_mpeg_stream_type stream_type; - enum v4l2_mpeg_stream_vbi_fmt stream_vbi_fmt; /* audio */ enum v4l2_mpeg_audio_sampling_freq audio_sampling_freq; @@ -89,9 +83,9 @@ int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl); const char **cx2341x_ctrl_get_menu(u32 id); int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, - struct v4l2_ext_controls *ctrls, unsigned int cmd); + struct v4l2_ext_controls *ctrls, int cmd); void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p); -void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix); +void cx2341x_log_status(struct cx2341x_mpeg_params *p, int cardid); /* Firmware names */ #define CX2341X_FIRM_ENC_FILENAME "v4l-cx2341x-enc.fw" diff --git a/trunk/include/media/tuner-types.h b/trunk/include/media/tuner-types.h index 3c43b95f4c0d..ad9c171bfa07 100644 --- a/trunk/include/media/tuner-types.h +++ b/trunk/include/media/tuner-types.h @@ -20,7 +20,6 @@ struct tuner_range { struct tuner_params { enum param_type type; - /* Many Philips based tuners have a comment like this in their * datasheet: * @@ -40,60 +39,6 @@ struct tuner_params { * static unless the control byte was sent first. */ unsigned int cb_first_if_lower_freq:1; - /* Set to 1 if this tuner uses a tda9887 */ - unsigned int has_tda9887:1; - /* Many Philips tuners use tda9887 PORT1 to select the FM radio - sensitivity. If this setting is 1, then set PORT1 to 1 to - get proper FM reception. */ - unsigned int port1_fm_high_sensitivity:1; - /* Some Philips tuners use tda9887 PORT2 to select the FM radio - sensitivity. If this setting is 1, then set PORT2 to 1 to - get proper FM reception. */ - unsigned int port2_fm_high_sensitivity:1; - /* Most tuners with a tda9887 use QSS mode. Some (cheaper) tuners - use Intercarrier mode. If this setting is 1, then the tuner - needs to be set to intercarrier mode. */ - unsigned int intercarrier_mode:1; - /* This setting sets the default value for PORT1. - 0 means inactive, 1 means active. Note: the actual bit - value written to the tda9887 is inverted. So a 0 here - means a 1 in the B6 bit. */ - unsigned int port1_active:1; - /* This setting sets the default value for PORT2. - 0 means inactive, 1 means active. Note: the actual bit - value written to the tda9887 is inverted. So a 0 here - means a 1 in the B7 bit. */ - unsigned int port2_active:1; - /* Sometimes PORT1 is inverted when the SECAM-L' standard is selected. - Set this bit to 1 if this is needed. */ - unsigned int port1_invert_for_secam_lc:1; - /* Sometimes PORT2 is inverted when the SECAM-L' standard is selected. - Set this bit to 1 if this is needed. */ - unsigned int port2_invert_for_secam_lc:1; - /* Some cards require PORT1 to be 1 for mono Radio FM and 0 for stereo. */ - unsigned int port1_set_for_fm_mono:1; - /* Default tda9887 TOP value in dB for the low band. Default is 0. - Range: -16:+15 */ - signed int default_top_low:5; - /* Default tda9887 TOP value in dB for the mid band. Default is 0. - Range: -16:+15 */ - signed int default_top_mid:5; - /* Default tda9887 TOP value in dB for the high band. Default is 0. - Range: -16:+15 */ - signed int default_top_high:5; - /* Default tda9887 TOP value in dB for SECAM-L/L' for the low band. - Default is 0. Several tuners require a different TOP value for - the SECAM-L/L' standards. Range: -16:+15 */ - signed int default_top_secam_low:5; - /* Default tda9887 TOP value in dB for SECAM-L/L' for the mid band. - Default is 0. Several tuners require a different TOP value for - the SECAM-L/L' standards. Range: -16:+15 */ - signed int default_top_secam_mid:5; - /* Default tda9887 TOP value in dB for SECAM-L/L' for the high band. - Default is 0. Several tuners require a different TOP value for - the SECAM-L/L' standards. Range: -16:+15 */ - signed int default_top_secam_high:5; - unsigned int count; struct tuner_range *ranges; diff --git a/trunk/include/media/v4l2-dev.h b/trunk/include/media/v4l2-dev.h index 62dae1a8c441..a1b473190e65 100644 --- a/trunk/include/media/v4l2-dev.h +++ b/trunk/include/media/v4l2-dev.h @@ -314,6 +314,7 @@ void *priv; /* for videodev.c intenal usage -- please don't touch */ int users; /* video_exclusive_{open|close} ... */ struct mutex lock; /* ... helper function uses these */ + char devfs_name[64]; /* devfs */ struct class_device class_dev; /* sysfs */ }; diff --git a/trunk/include/net/af_unix.h b/trunk/include/net/af_unix.h index 5ba72d95280c..795f81f9ec7f 100644 --- a/trunk/include/net/af_unix.h +++ b/trunk/include/net/af_unix.h @@ -53,16 +53,10 @@ struct unix_address { struct unix_skb_parms { struct ucred creds; /* Skb credentials */ struct scm_fp_list *fp; /* Passed files */ -#ifdef CONFIG_SECURITY_NETWORK - char *secdata; /* Security context */ - u32 seclen; /* Security length */ -#endif }; #define UNIXCB(skb) (*(struct unix_skb_parms*)&((skb)->cb)) #define UNIXCREDS(skb) (&UNIXCB((skb)).creds) -#define UNIXSECDATA(skb) (&UNIXCB((skb)).secdata) -#define UNIXSECLEN(skb) (&UNIXCB((skb)).seclen) #define unix_state_rlock(s) spin_lock(&unix_sk(s)->lock) #define unix_state_runlock(s) spin_unlock(&unix_sk(s)->lock) diff --git a/trunk/include/net/ip6_route.h b/trunk/include/net/ip6_route.h index ab29dafb1a6a..a398ae5e30f9 100644 --- a/trunk/include/net/ip6_route.h +++ b/trunk/include/net/ip6_route.h @@ -146,7 +146,7 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, struct rt6_info *rt = (struct rt6_info *) dst; write_lock(&sk->sk_dst_lock); - sk_setup_caps(sk, dst); + __sk_dst_set(sk, dst); np->daddr_cache = daddr; np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; write_unlock(&sk->sk_dst_lock); diff --git a/trunk/include/net/irda/irda_device.h b/trunk/include/net/irda/irda_device.h index bca19ca7bdd4..0575c59a5c96 100644 --- a/trunk/include/net/irda/irda_device.h +++ b/trunk/include/net/irda/irda_device.h @@ -160,7 +160,7 @@ typedef struct { int irq, irq2; /* Interrupts used */ int dma, dma2; /* DMA channel(s) used */ int fifo_size; /* FIFO size */ - int irqflags; /* interrupt flags (ie, IRQF_SHARED|IRQF_DISABLED) */ + int irqflags; /* interrupt flags (ie, SA_SHIRQ|SA_INTERRUPT) */ int direction; /* Link direction, used by some FIR drivers */ int enabled; /* Powered on? */ int suspended; /* Suspended by APM */ diff --git a/trunk/include/net/pkt_sched.h b/trunk/include/net/pkt_sched.h index 1925c65e617b..75b5b9333fc7 100644 --- a/trunk/include/net/pkt_sched.h +++ b/trunk/include/net/pkt_sched.h @@ -169,23 +169,17 @@ psched_tod_diff(int delta_sec, int bound) #define PSCHED_TADD2(tv, delta, tv_res) \ ({ \ - int __delta = (delta); \ - (tv_res) = (tv); \ - while(__delta >= USEC_PER_SEC){ \ - (tv_res).tv_sec++; \ - __delta -= USEC_PER_SEC; \ - } \ + int __delta = (tv).tv_usec + (delta); \ + (tv_res).tv_sec = (tv).tv_sec; \ + if (__delta > USEC_PER_SEC) { (tv_res).tv_sec++; __delta -= USEC_PER_SEC; } \ (tv_res).tv_usec = __delta; \ }) #define PSCHED_TADD(tv, delta) \ ({ \ - int __delta = (delta); \ - while(__delta >= USEC_PER_SEC){ \ - (tv).tv_sec++; \ - __delta -= USEC_PER_SEC; \ - } \ - (tv).tv_usec = __delta; \ + (tv).tv_usec += (delta); \ + if ((tv).tv_usec > USEC_PER_SEC) { (tv).tv_sec++; \ + (tv).tv_usec -= USEC_PER_SEC; } \ }) /* Set/check that time is in the "past perfect"; diff --git a/trunk/include/net/protocol.h b/trunk/include/net/protocol.h index a225d6371cb1..3b6dc15c68a5 100644 --- a/trunk/include/net/protocol.h +++ b/trunk/include/net/protocol.h @@ -36,8 +36,7 @@ struct net_protocol { int (*handler)(struct sk_buff *skb); void (*err_handler)(struct sk_buff *skb, u32 info); - struct sk_buff *(*gso_segment)(struct sk_buff *skb, - int features); + struct sk_buff *(*gso_segment)(struct sk_buff *skb, int sg); int no_policy; }; @@ -50,17 +49,11 @@ struct inet6_protocol struct inet6_skb_parm *opt, int type, int code, int offset, __u32 info); - - struct sk_buff *(*gso_segment)(struct sk_buff *skb, - int features); - unsigned int flags; /* INET6_PROTO_xxx */ }; #define INET6_PROTO_NOPOLICY 0x1 #define INET6_PROTO_FINAL 0x2 -/* This should be set for any extension header which is compatible with GSO. */ -#define INET6_PROTO_GSO_EXTHDR 0x4 #endif /* This is used to register socket interfaces for IP protocols. */ diff --git a/trunk/include/net/scm.h b/trunk/include/net/scm.h index 02daa097cdcd..540619cb7160 100644 --- a/trunk/include/net/scm.h +++ b/trunk/include/net/scm.h @@ -19,10 +19,6 @@ struct scm_cookie { struct ucred creds; /* Skb credentials */ struct scm_fp_list *fp; /* Passed files */ -#ifdef CONFIG_SECURITY_NETWORK - char *secdata; /* Security context */ - u32 seclen; /* Security length */ -#endif unsigned long seq; /* Connection seqno */ }; @@ -52,17 +48,6 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, return __scm_send(sock, msg, scm); } -#ifdef CONFIG_SECURITY_NETWORK -static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) -{ - if (test_bit(SOCK_PASSSEC, &sock->flags) && scm->secdata != NULL) - put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, scm->seclen, scm->secdata); -} -#else -static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) -{ } -#endif /* CONFIG_SECURITY_NETWORK */ - static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm, int flags) { @@ -77,8 +62,6 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, if (test_bit(SOCK_PASSCRED, &sock->flags)) put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); - scm_passec(sock, msg, scm); - if (!scm->fp) return; diff --git a/trunk/include/net/sock.h b/trunk/include/net/sock.h index 7b3d6b856946..2d8d6adf1616 100644 --- a/trunk/include/net/sock.h +++ b/trunk/include/net/sock.h @@ -140,7 +140,6 @@ struct sock_common { * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO) - * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) * @sk_lingertime: %SO_LINGER l_linger setting * @sk_backlog: always used with the per-socket spinlock held * @sk_callback_lock: used with the callbacks in the end of this struct @@ -212,7 +211,6 @@ struct sock { gfp_t sk_allocation; int sk_sndbuf; int sk_route_caps; - int sk_gso_type; int sk_rcvlowat; unsigned long sk_flags; unsigned long sk_lingertime; @@ -385,6 +383,7 @@ enum sock_flags { SOCK_USE_WRITE_QUEUE, /* whether to call sk->sk_write_space in sock_wfree */ SOCK_DBG, /* %SO_DEBUG setting */ SOCK_RCVTSTAMP, /* %SO_TIMESTAMP setting */ + SOCK_NO_LARGESEND, /* whether to sent large segments or not */ SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */ SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */ }; @@ -1027,20 +1026,15 @@ extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie); extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie); -static inline int sk_can_gso(const struct sock *sk) -{ - return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type); -} - static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst) { __sk_dst_set(sk, dst); sk->sk_route_caps = dst->dev->features; if (sk->sk_route_caps & NETIF_F_GSO) - sk->sk_route_caps |= NETIF_F_GSO_MASK; - if (sk_can_gso(sk)) { - if (dst->header_len) - sk->sk_route_caps &= ~NETIF_F_GSO_MASK; + sk->sk_route_caps |= NETIF_F_TSO; + if (sk->sk_route_caps & NETIF_F_TSO) { + if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len) + sk->sk_route_caps &= ~NETIF_F_TSO; else sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; } diff --git a/trunk/include/net/tcp.h b/trunk/include/net/tcp.h index 3cd803b0d7a5..ca3d38dfc00b 100644 --- a/trunk/include/net/tcp.h +++ b/trunk/include/net/tcp.h @@ -751,7 +751,7 @@ static inline int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) if (in_flight >= tp->snd_cwnd) return 1; - if (!sk_can_gso(sk)) + if (!(sk->sk_route_caps & NETIF_F_TSO)) return 0; left = tp->snd_cwnd - in_flight; @@ -1086,7 +1086,7 @@ extern struct request_sock_ops tcp_request_sock_ops; extern int tcp_v4_destroy_sock(struct sock *sk); -extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features); +extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg); #ifdef CONFIG_PROC_FS extern int tcp4_proc_init(void); diff --git a/trunk/include/net/tcp_ecn.h b/trunk/include/net/tcp_ecn.h index 4629d77173f2..c6b84397448d 100644 --- a/trunk/include/net/tcp_ecn.h +++ b/trunk/include/net/tcp_ecn.h @@ -31,9 +31,10 @@ static inline void TCP_ECN_send_syn(struct sock *sk, struct tcp_sock *tp, struct sk_buff *skb) { tp->ecn_flags = 0; - if (sysctl_tcp_ecn) { + if (sysctl_tcp_ecn && !(sk->sk_route_caps & NETIF_F_TSO)) { TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_ECE|TCPCB_FLAG_CWR; tp->ecn_flags = TCP_ECN_OK; + sock_set_flag(sk, SOCK_NO_LARGESEND); } } @@ -55,7 +56,6 @@ static inline void TCP_ECN_send(struct sock *sk, struct tcp_sock *tp, if (tp->ecn_flags&TCP_ECN_QUEUE_CWR) { tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR; skb->h.th->cwr = 1; - skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; } } else { /* ACK or retransmitted segment: clear ECT|CE */ diff --git a/trunk/include/net/tipc/tipc_bearer.h b/trunk/include/net/tipc/tipc_bearer.h index e07136d74c2f..098607cd4b78 100644 --- a/trunk/include/net/tipc/tipc_bearer.h +++ b/trunk/include/net/tipc/tipc_bearer.h @@ -49,18 +49,10 @@ #define TIPC_MEDIA_TYPE_ETH 1 -/* - * Destination address structure used by TIPC bearers when sending messages - * - * IMPORTANT: The fields of this structure MUST be stored using the specified - * byte order indicated below, as the structure is exchanged between nodes - * as part of a link setup process. - */ - struct tipc_media_addr { - __u32 type; /* bearer type (network byte order) */ + __u32 type; union { - __u8 eth_addr[6]; /* 48 bit Ethernet addr (byte array) */ + __u8 eth_addr[6]; /* Ethernet bearer */ #if 0 /* Prototypes for other possible bearer types */ diff --git a/trunk/include/sound/ac97_codec.h b/trunk/include/sound/ac97_codec.h index 758f8bf133c7..446afc3ea27f 100644 --- a/trunk/include/sound/ac97_codec.h +++ b/trunk/include/sound/ac97_codec.h @@ -265,7 +265,6 @@ /* specific - Analog Devices */ #define AC97_AD_TEST 0x5a /* test register */ -#define AC97_AD_TEST2 0x5c /* undocumented test register 2 */ #define AC97_AD_CODEC_CFG 0x70 /* codec configuration */ #define AC97_AD_JACK_SPDIF 0x72 /* Jack Sense & S/PDIF */ #define AC97_AD_SERIAL_CFG 0x74 /* Serial Configuration */ diff --git a/trunk/include/sound/ak4xxx-adda.h b/trunk/include/sound/ak4xxx-adda.h index 3d9888492026..3bf5911fe827 100644 --- a/trunk/include/sound/ak4xxx-adda.h +++ b/trunk/include/sound/ak4xxx-adda.h @@ -32,8 +32,8 @@ struct snd_akm4xxx; struct snd_ak4xxx_ops { void (*lock)(struct snd_akm4xxx *ak, int chip); void (*unlock)(struct snd_akm4xxx *ak, int chip); - void (*write)(struct snd_akm4xxx *ak, int chip, unsigned char reg, - unsigned char val); + void (*write)(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsigned char val); + // unsigned char (*read)(struct snd_akm4xxx *ak, int chip, unsigned char reg); void (*set_rate_val)(struct snd_akm4xxx *ak, unsigned int rate); }; @@ -41,40 +41,29 @@ struct snd_ak4xxx_ops { struct snd_akm4xxx { struct snd_card *card; - unsigned int num_adcs; /* AK4524 or AK4528 ADCs */ - unsigned int num_dacs; /* AK4524 or AK4528 DACs */ - unsigned char images[AK4XXX_IMAGE_SIZE]; /* saved register image */ - unsigned char ipga_gain[AK4XXX_MAX_CHIPS][2]; /* saved register image - * for IPGA (AK4528) - */ + unsigned int num_adcs; /* AK4524 or AK4528 ADCs */ + unsigned int num_dacs; /* AK4524 or AK4528 DACs */ + unsigned char images[AK4XXX_IMAGE_SIZE]; /* saved register image */ + unsigned char ipga_gain[AK4XXX_MAX_CHIPS][2]; /* saved register image for IPGA (AK4528) */ unsigned long private_value[AK4XXX_MAX_CHIPS]; /* helper for driver */ void *private_data[AK4XXX_MAX_CHIPS]; /* helper for driver */ /* template should fill the following fields */ - unsigned int idx_offset; /* control index offset */ + unsigned int idx_offset; /* control index offset */ enum { SND_AK4524, SND_AK4528, SND_AK4529, SND_AK4355, SND_AK4358, SND_AK4381 } type; - unsigned int *num_stereo; /* array of combined counts - * for the mixer - */ - char **channel_names; /* array of mixer channel names */ struct snd_ak4xxx_ops ops; }; -void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, - unsigned char val); +void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsigned char val); void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state); void snd_akm4xxx_init(struct snd_akm4xxx *ak); int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak); -#define snd_akm4xxx_get(ak,chip,reg) \ - (ak)->images[(chip) * 16 + (reg)] -#define snd_akm4xxx_set(ak,chip,reg,val) \ - ((ak)->images[(chip) * 16 + (reg)] = (val)) -#define snd_akm4xxx_get_ipga(ak,chip,reg) \ - (ak)->ipga_gain[chip][(reg)-4] -#define snd_akm4xxx_set_ipga(ak,chip,reg,val) \ - ((ak)->ipga_gain[chip][(reg)-4] = (val)) +#define snd_akm4xxx_get(ak,chip,reg) (ak)->images[(chip) * 16 + (reg)] +#define snd_akm4xxx_set(ak,chip,reg,val) ((ak)->images[(chip) * 16 + (reg)] = (val)) +#define snd_akm4xxx_get_ipga(ak,chip,reg) (ak)->ipga_gain[chip][(reg)-4] +#define snd_akm4xxx_set_ipga(ak,chip,reg,val) ((ak)->ipga_gain[chip][(reg)-4] = (val)) #endif /* __SOUND_AK4XXX_ADDA_H */ diff --git a/trunk/include/sound/initval.h b/trunk/include/sound/initval.h index 2ae76efc696f..d29e3d31d149 100644 --- a/trunk/include/sound/initval.h +++ b/trunk/include/sound/initval.h @@ -62,8 +62,7 @@ static int snd_legacy_find_free_irq(int *irq_table) { while (*irq_table != -1) { if (!request_irq(*irq_table, snd_legacy_empty_irq_handler, - IRQF_DISABLED | IRQF_PROBE_SHARED, "ALSA Test IRQ", - (void *) irq_table)) { + SA_INTERRUPT, "ALSA Test IRQ", (void *) irq_table)) { free_irq(*irq_table, (void *) irq_table); return *irq_table; } diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index a5b073a103e7..e0358f3946a1 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -1,11 +1,3 @@ -config DEFCONFIG_LIST - string - option defconfig_list - default "/lib/modules/$UNAME_RELEASE/.config" - default "/etc/kernel-config" - default "/boot/config-$UNAME_RELEASE" - default "arch/$ARCH/defconfig" - menu "Code maturity level options" config EXPERIMENTAL @@ -54,8 +46,8 @@ config LOCK_KERNEL config INIT_ENV_ARG_LIMIT int - default 32 if !UML - default 128 if UML + default 32 if !USERMODE + default 128 if USERMODE help Maximum of each of the number of arguments and environment variables passed to init from the kernel command line. @@ -244,6 +236,16 @@ config UID16 help This enables the legacy 16-bit UID syscall wrappers. +config VM86 + depends X86 + default y + bool "Enable VM86 support" if EMBEDDED + help + This option is required by programs like DOSEMU to run 16-bit legacy + code on X86 processors. It also may be needed by software like + XFree86 to initialize some video cards via BIOS. Disabling this + option saves about 6k. + config CC_OPTIMIZE_FOR_SIZE bool "Optimize for size (Look out for broken compilers!)" default y @@ -339,14 +341,9 @@ config BASE_FULL kernel data structures. This saves memory on small machines, but may reduce performance. -config RT_MUTEXES - boolean - select PLIST - config FUTEX bool "Enable futex support" if EMBEDDED default y - select RT_MUTEXES help Disabling this option will cause the kernel to be built without support for "fast userspace mutexes". The resulting kernel may not @@ -379,15 +376,6 @@ config SLAB SLOB is more space efficient but does not scale well and is more susceptible to fragmentation. -config VM_EVENT_COUNTERS - default y - bool "Enable VM event counters for /proc/vmstat" if EMBEDDED - help - VM event counters are only needed to for event counts to be - shown. They have no function for the kernel itself. This - option allows the disabling of the VM event counters. - /proc/vmstat will only show page counts. - endmenu # General setup config TINY_SHMEM diff --git a/trunk/init/Makefile b/trunk/init/Makefile index 633a268d270d..a2300078f2b7 100644 --- a/trunk/init/Makefile +++ b/trunk/init/Makefile @@ -6,6 +6,7 @@ obj-y := main.o version.o mounts.o initramfs.o obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o mounts-y := do_mounts.o +mounts-$(CONFIG_DEVFS_FS) += do_mounts_devfs.o mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o mounts-$(CONFIG_BLK_DEV_MD) += do_mounts_md.o diff --git a/trunk/init/do_mounts.c b/trunk/init/do_mounts.c index 94aeec7aa917..21b3b8f33a72 100644 --- a/trunk/init/do_mounts.c +++ b/trunk/init/do_mounts.c @@ -325,7 +325,7 @@ static int __init mount_nfs_root(void) { void *data = nfs_root_data(); - create_dev("/dev/root", ROOT_DEV); + create_dev("/dev/root", ROOT_DEV, NULL); if (data && do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0) return 1; @@ -386,7 +386,7 @@ void __init mount_root(void) change_floppy("root floppy"); } #endif - create_dev("/dev/root", ROOT_DEV); + create_dev("/dev/root", ROOT_DEV, root_device_name); mount_block_root("/dev/root", root_mountflags); } @@ -397,6 +397,8 @@ void __init prepare_namespace(void) { int is_floppy; + mount_devfs(); + if (root_delay) { printk(KERN_INFO "Waiting %dsec before mounting root device...\n", root_delay); @@ -426,8 +428,10 @@ void __init prepare_namespace(void) mount_root(); out: + umount_devfs("/dev"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); security_sb_post_mountroot(); + mount_devfs_fs (); } diff --git a/trunk/init/do_mounts.h b/trunk/init/do_mounts.h index e7f2e7fa066e..e0a7ac9649e1 100644 --- a/trunk/init/do_mounts.h +++ b/trunk/init/do_mounts.h @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -14,12 +15,25 @@ void mount_root(void); extern int root_mountflags; extern char *root_device_name; -static inline int create_dev(char *name, dev_t dev) +#ifdef CONFIG_DEVFS_FS + +void mount_devfs(void); +void umount_devfs(char *path); +int create_dev(char *name, dev_t dev, char *devfs_name); + +#else + +static inline void mount_devfs(void) {} +static inline void umount_devfs(const char *path) {} + +static inline int create_dev(char *name, dev_t dev, char *devfs_name) { sys_unlink(name); return sys_mknod(name, S_IFBLK|0600, new_encode_dev(dev)); } +#endif + #if BITS_PER_LONG == 32 static inline u32 bstat(char *name) { diff --git a/trunk/init/do_mounts_devfs.c b/trunk/init/do_mounts_devfs.c new file mode 100644 index 000000000000..cc526474690a --- /dev/null +++ b/trunk/init/do_mounts_devfs.c @@ -0,0 +1,137 @@ + +#include +#include +#include + +#include "do_mounts.h" + +void __init mount_devfs(void) +{ + sys_mount("devfs", "/dev", "devfs", 0, NULL); +} + +void __init umount_devfs(char *path) +{ + sys_umount(path, 0); +} + +/* + * If the dir will fit in *buf, return its length. If it won't fit, return + * zero. Return -ve on error. + */ +static int __init do_read_dir(int fd, void *buf, int len) +{ + long bytes, n; + char *p = buf; + sys_lseek(fd, 0, 0); + + for (bytes = 0; bytes < len; bytes += n) { + n = sys_getdents64(fd, (struct linux_dirent64 *)(p + bytes), + len - bytes); + if (n < 0) + return n; + if (n == 0) + return bytes; + } + return 0; +} + +/* + * Try to read all of a directory. Returns the contents at *p, which + * is kmalloced memory. Returns the number of bytes read at *len. Returns + * NULL on error. + */ +static void * __init read_dir(char *path, int *len) +{ + int size; + int fd = sys_open(path, 0, 0); + + *len = 0; + if (fd < 0) + return NULL; + + for (size = 1 << 9; size <= (PAGE_SIZE << MAX_ORDER); size <<= 1) { + void *p = kmalloc(size, GFP_KERNEL); + int n; + if (!p) + break; + n = do_read_dir(fd, p, size); + if (n > 0) { + sys_close(fd); + *len = n; + return p; + } + kfree(p); + if (n == -EINVAL) + continue; /* Try a larger buffer */ + if (n < 0) + break; + } + sys_close(fd); + return NULL; +} + +/* + * recursively scan , looking for a device node of type + */ +static int __init find_in_devfs(char *path, unsigned dev) +{ + char *end = path + strlen(path); + int rest = path + 64 - end; + int size; + char *p = read_dir(path, &size); + char *s; + + if (!p) + return -1; + for (s = p; s < p + size; s += ((struct linux_dirent64 *)s)->d_reclen) { + struct linux_dirent64 *d = (struct linux_dirent64 *)s; + if (strlen(d->d_name) + 2 > rest) + continue; + switch (d->d_type) { + case DT_BLK: + sprintf(end, "/%s", d->d_name); + if (bstat(path) != dev) + break; + kfree(p); + return 0; + case DT_DIR: + if (strcmp(d->d_name, ".") == 0) + break; + if (strcmp(d->d_name, "..") == 0) + break; + sprintf(end, "/%s", d->d_name); + if (find_in_devfs(path, dev) < 0) + break; + kfree(p); + return 0; + } + } + kfree(p); + return -1; +} + +/* + * create a device node called which points to + * if possible, otherwise find a device node + * which matches and make a symlink pointing to it. + */ +int __init create_dev(char *name, dev_t dev, char *devfs_name) +{ + char path[64]; + + sys_unlink(name); + if (devfs_name && devfs_name[0]) { + if (strncmp(devfs_name, "/dev/", 5) == 0) + devfs_name += 5; + sprintf(path, "/dev/%s", devfs_name); + if (sys_access(path, 0) == 0) + return sys_symlink(devfs_name, name); + } + if (!dev) + return -1; + strcpy(path, "/dev"); + if (find_in_devfs(path, new_encode_dev(dev)) < 0) + return -1; + return sys_symlink(path + 5, name); +} diff --git a/trunk/init/do_mounts_initrd.c b/trunk/init/do_mounts_initrd.c index a06f037fa000..405f9031af87 100644 --- a/trunk/init/do_mounts_initrd.c +++ b/trunk/init/do_mounts_initrd.c @@ -44,7 +44,7 @@ static void __init handle_initrd(void) int pid; real_root_dev = new_encode_dev(ROOT_DEV); - create_dev("/dev/root.old", Root_RAM0); + create_dev("/dev/root.old", Root_RAM0, NULL); /* mount initrd on rootfs' /root */ mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); sys_mkdir("/old", 0700); @@ -54,6 +54,7 @@ static void __init handle_initrd(void) sys_chdir("/root"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); + mount_devfs_fs (); current->flags |= PF_NOFREEZE; pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); @@ -70,6 +71,7 @@ static void __init handle_initrd(void) sys_chroot("."); sys_close(old_fd); sys_close(root_fd); + umount_devfs("/old/dev"); if (new_decode_dev(real_root_dev) == Root_RAM0) { sys_chdir("/old"); @@ -105,7 +107,7 @@ static void __init handle_initrd(void) int __init initrd_load(void) { if (mount_initrd) { - create_dev("/dev/ram", Root_RAM0); + create_dev("/dev/ram", Root_RAM0, NULL); /* * Load the initrd data into /dev/ram0. Execute it as initrd * unless /dev/ram0 is supposed to be our actual root device, diff --git a/trunk/init/do_mounts_md.c b/trunk/init/do_mounts_md.c index 2429e1bf8c60..f6f36806f84a 100644 --- a/trunk/init/do_mounts_md.c +++ b/trunk/init/do_mounts_md.c @@ -125,18 +125,19 @@ static void __init md_setup_drive(void) int err = 0; char *devname; mdu_disk_info_t dinfo; - char name[16]; + char name[16], devfs_name[16]; minor = md_setup_args[ent].minor; partitioned = md_setup_args[ent].partitioned; devname = md_setup_args[ent].device_names; sprintf(name, "/dev/md%s%d", partitioned?"_d":"", minor); + sprintf(devfs_name, "/dev/md/%s%d", partitioned?"d":"", minor); if (partitioned) dev = MKDEV(mdp_major, minor << MdpMinorShift); else dev = MKDEV(MD_MAJOR, minor); - create_dev(name, dev); + create_dev(name, dev, devfs_name); for (i = 0; i < MD_SB_DISKS && devname != 0; i++) { char *p; char comp_name[64]; @@ -271,7 +272,7 @@ __setup("md=", md_setup); void __init md_run_setup(void) { - create_dev("/dev/md0", MKDEV(MD_MAJOR, 0)); + create_dev("/dev/md0", MKDEV(MD_MAJOR, 0), "md/0"); if (raid_noautodetect) printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=noautodetect)\n"); else { diff --git a/trunk/init/do_mounts_rd.c b/trunk/init/do_mounts_rd.c index ed652f40f075..c2683fcd792d 100644 --- a/trunk/init/do_mounts_rd.c +++ b/trunk/init/do_mounts_rd.c @@ -262,8 +262,8 @@ int __init rd_load_disk(int n) { if (rd_prompt) change_floppy("root floppy disk to be loaded into RAM disk"); - create_dev("/dev/root", ROOT_DEV); - create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n)); + create_dev("/dev/root", ROOT_DEV, root_device_name); + create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL); return rd_load_image("/dev/root"); } diff --git a/trunk/init/initramfs.c b/trunk/init/initramfs.c index d28c1094d7e5..f81cfa40a719 100644 --- a/trunk/init/initramfs.c +++ b/trunk/init/initramfs.c @@ -30,7 +30,6 @@ static void __init free(void *where) static __initdata struct hash { int ino, minor, major; - mode_t mode; struct hash *next; char name[N_ALIGN(PATH_MAX)]; } *head[32]; @@ -42,8 +41,7 @@ static inline int hash(int major, int minor, int ino) return tmp & 31; } -static char __init *find_link(int major, int minor, int ino, - mode_t mode, char *name) +static char __init *find_link(int major, int minor, int ino, char *name) { struct hash **p, *q; for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) { @@ -53,17 +51,14 @@ static char __init *find_link(int major, int minor, int ino, continue; if ((*p)->major != major) continue; - if (((*p)->mode ^ mode) & S_IFMT) - continue; return (*p)->name; } q = (struct hash *)malloc(sizeof(struct hash)); if (!q) panic("can't allocate link hash entry"); - q->major = major; - q->minor = minor; q->ino = ino; - q->mode = mode; + q->minor = minor; + q->major = major; strcpy(q->name, name); q->next = NULL; *p = q; @@ -234,25 +229,13 @@ static int __init do_reset(void) static int __init maybe_link(void) { if (nlink >= 2) { - char *old = find_link(major, minor, ino, mode, collected); + char *old = find_link(major, minor, ino, collected); if (old) return (sys_link(old, collected) < 0) ? -1 : 1; } return 0; } -static void __init clean_path(char *path, mode_t mode) -{ - struct stat st; - - if (!sys_newlstat(path, &st) && (st.st_mode^mode) & S_IFMT) { - if (S_ISDIR(st.st_mode)) - sys_rmdir(path); - else - sys_unlink(path); - } -} - static __initdata int wfd; static int __init do_name(void) @@ -265,15 +248,9 @@ static int __init do_name(void) } if (dry_run) return 0; - clean_path(collected, mode); if (S_ISREG(mode)) { - int ml = maybe_link(); - if (ml >= 0) { - int openflags = O_WRONLY|O_CREAT; - if (ml != 1) - openflags |= O_TRUNC; - wfd = sys_open(collected, openflags, mode); - + if (maybe_link() >= 0) { + wfd = sys_open(collected, O_WRONLY|O_CREAT, mode); if (wfd >= 0) { sys_fchown(wfd, uid, gid); sys_fchmod(wfd, mode); @@ -314,7 +291,6 @@ static int __init do_copy(void) static int __init do_symlink(void) { collected[N_ALIGN(name_len) + body_len] = '\0'; - clean_path(collected, 0); sys_symlink(collected + N_ALIGN(name_len), collected); sys_lchown(collected, uid, gid); state = SkipIt; diff --git a/trunk/init/main.c b/trunk/init/main.c index b2f3b566790e..f715b9b89753 100644 --- a/trunk/init/main.c +++ b/trunk/init/main.c @@ -11,9 +11,11 @@ #define __KERNEL_SYSCALLS__ +#include #include #include #include +#include #include #include #include @@ -45,8 +47,6 @@ #include #include #include -#include -#include #include #include @@ -79,6 +79,7 @@ extern void mca_init(void); extern void sbus_init(void); extern void sysctl_init(void); extern void signals_init(void); +extern void buffer_init(void); extern void pidhash_init(void); extern void pidmap_init(void); extern void prio_tree_init(void); @@ -445,17 +446,10 @@ static void __init boot_cpu_init(void) cpu_set(cpu, cpu_possible_map); } -void __init __attribute__((weak)) smp_setup_processor_id(void) -{ -} - asmlinkage void __init start_kernel(void) { char * command_line; extern struct kernel_param __start___param[], __stop___param[]; - - smp_setup_processor_id(); - /* * Interrupts are still disabled. Do necessary setups, then * enable them @@ -488,7 +482,6 @@ asmlinkage void __init start_kernel(void) __stop___param - __start___param, &unknown_bootoption); sort_main_extable(); - unwind_init(); trap_init(); rcu_init(); init_IRQ(); @@ -497,7 +490,6 @@ asmlinkage void __init start_kernel(void) hrtimers_init(); softirq_init(); time_init(); - timekeeping_init(); /* * HACK ALERT! This is early. We're enabling the console before diff --git a/trunk/ipc/compat.c b/trunk/ipc/compat.c index 4d20cfd38f0a..a544dfbb082a 100644 --- a/trunk/ipc/compat.c +++ b/trunk/ipc/compat.c @@ -21,6 +21,7 @@ * */ #include +#include #include #include #include diff --git a/trunk/ipc/msg.c b/trunk/ipc/msg.c index cd92d342953e..00f015a092d2 100644 --- a/trunk/ipc/msg.c +++ b/trunk/ipc/msg.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include diff --git a/trunk/ipc/sem.c b/trunk/ipc/sem.c index 6013c751156f..fce0bc8b5ad6 100644 --- a/trunk/ipc/sem.c +++ b/trunk/ipc/sem.c @@ -66,6 +66,7 @@ * Dustin Kirkland */ +#include #include #include #include diff --git a/trunk/ipc/shm.c b/trunk/ipc/shm.c index 940b0c9b13aa..fe7ae73b6981 100644 --- a/trunk/ipc/shm.c +++ b/trunk/ipc/shm.c @@ -17,6 +17,7 @@ * Dustin Kirkland */ +#include #include #include #include diff --git a/trunk/ipc/util.c b/trunk/ipc/util.c index 67b6d178db6e..8193299f45f6 100644 --- a/trunk/ipc/util.c +++ b/trunk/ipc/util.c @@ -14,6 +14,7 @@ * Dustin Kirkland */ +#include #include #include #include diff --git a/trunk/kernel/Makefile b/trunk/kernel/Makefile index 82fb182f6f61..f6ef00f4f90f 100644 --- a/trunk/kernel/Makefile +++ b/trunk/kernel/Makefile @@ -10,22 +10,17 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o -obj-y += time/ obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o obj-$(CONFIG_FUTEX) += futex.o ifeq ($(CONFIG_COMPAT),y) obj-$(CONFIG_FUTEX) += futex_compat.o endif -obj-$(CONFIG_RT_MUTEXES) += rtmutex.o -obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o -obj-$(CONFIG_RT_MUTEX_TESTER) += rtmutex-tester.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o obj-$(CONFIG_SMP) += cpu.o spinlock.o obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_KALLSYMS) += kallsyms.o -obj-$(CONFIG_STACK_UNWIND) += unwind.o obj-$(CONFIG_PM) += power/ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_KEXEC) += kexec.o diff --git a/trunk/kernel/acct.c b/trunk/kernel/acct.c index f18e0b8df3e1..368c4f03fe0e 100644 --- a/trunk/kernel/acct.c +++ b/trunk/kernel/acct.c @@ -43,6 +43,7 @@ * a struct file opened for write. Fixed. 2/6/2000, AV. */ +#include #include #include #include @@ -520,7 +521,6 @@ static void do_acct_process(struct file *file) /** * acct_init_pacct - initialize a new pacct_struct - * @pacct: per-process accounting info struct to initialize */ void acct_init_pacct(struct pacct_struct *pacct) { @@ -576,7 +576,7 @@ void acct_collect(long exitcode, int group_dead) * * handles process accounting for an exiting task */ -void acct_process(void) +void acct_process() { struct file *file = NULL; diff --git a/trunk/kernel/audit.c b/trunk/kernel/audit.c index d417ca1db79b..7dfac7031bd7 100644 --- a/trunk/kernel/audit.c +++ b/trunk/kernel/audit.c @@ -445,7 +445,7 @@ void audit_send_reply(int pid, int seq, int type, int done, int multi, * Check for appropriate CAP_AUDIT_ capabilities on incoming audit * control messages. */ -static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) +static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type) { int err = 0; @@ -459,13 +459,13 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) case AUDIT_DEL: case AUDIT_DEL_RULE: case AUDIT_SIGNAL_INFO: - if (security_netlink_recv(skb, CAP_AUDIT_CONTROL)) + if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL)) err = -EPERM; break; case AUDIT_USER: case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2: - if (security_netlink_recv(skb, CAP_AUDIT_WRITE)) + if (!cap_raised(eff_cap, CAP_AUDIT_WRITE)) err = -EPERM; break; default: /* bad msg */ @@ -488,7 +488,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) char *ctx; u32 len; - err = audit_netlink_ok(skb, msg_type); + err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type); if (err) return err; @@ -818,7 +818,7 @@ static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx, */ unsigned int audit_serial(void) { - static DEFINE_SPINLOCK(serial_lock); + static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED; static unsigned int serial = 0; unsigned long flags; diff --git a/trunk/kernel/audit.h b/trunk/kernel/audit.h index 6aa33b848cf2..8323e4132a33 100644 --- a/trunk/kernel/audit.h +++ b/trunk/kernel/audit.h @@ -81,7 +81,6 @@ struct audit_krule { u32 mask[AUDIT_BITMASK_SIZE]; u32 buflen; /* for data alloc on list rules */ u32 field_count; - char *filterkey; /* ties events to rules */ struct audit_field *fields; struct audit_field *inode_f; /* quick access to an inode field */ struct audit_watch *watch; /* associated watch */ diff --git a/trunk/kernel/auditfilter.c b/trunk/kernel/auditfilter.c index 5b4e16276ca0..4c99d2c586ed 100644 --- a/trunk/kernel/auditfilter.c +++ b/trunk/kernel/auditfilter.c @@ -141,7 +141,6 @@ static inline void audit_free_rule(struct audit_entry *e) selinux_audit_rule_free(f->se_rule); } kfree(e->rule.fields); - kfree(e->rule.filterkey); kfree(e); } @@ -279,29 +278,6 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len, return 0; } -static __u32 *classes[AUDIT_SYSCALL_CLASSES]; - -int __init audit_register_class(int class, unsigned *list) -{ - __u32 *p = kzalloc(AUDIT_BITMASK_SIZE * sizeof(__u32), GFP_KERNEL); - if (!p) - return -ENOMEM; - while (*list != ~0U) { - unsigned n = *list++; - if (n >= AUDIT_BITMASK_SIZE * 32 - AUDIT_SYSCALL_CLASSES) { - kfree(p); - return -EINVAL; - } - p[AUDIT_WORD(n)] |= AUDIT_BIT(n); - } - if (class >= AUDIT_SYSCALL_CLASSES || classes[class]) { - kfree(p); - return -EINVAL; - } - classes[class] = p; - return 0; -} - /* Common user-space to kernel rule translation. */ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) { @@ -345,22 +321,6 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) for (i = 0; i < AUDIT_BITMASK_SIZE; i++) entry->rule.mask[i] = rule->mask[i]; - for (i = 0; i < AUDIT_SYSCALL_CLASSES; i++) { - int bit = AUDIT_BITMASK_SIZE * 32 - i - 1; - __u32 *p = &entry->rule.mask[AUDIT_WORD(bit)]; - __u32 *class; - - if (!(*p & AUDIT_BIT(bit))) - continue; - *p &= ~AUDIT_BIT(bit); - class = classes[i]; - if (class) { - int j; - for (j = 0; j < AUDIT_BITMASK_SIZE; j++) - entry->rule.mask[j] |= class[j]; - } - } - return entry; exit_err: @@ -509,16 +469,11 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_ARG2: case AUDIT_ARG3: break; - case AUDIT_SUBJ_USER: - case AUDIT_SUBJ_ROLE: - case AUDIT_SUBJ_TYPE: - case AUDIT_SUBJ_SEN: - case AUDIT_SUBJ_CLR: - case AUDIT_OBJ_USER: - case AUDIT_OBJ_ROLE: - case AUDIT_OBJ_TYPE: - case AUDIT_OBJ_LEV_LOW: - case AUDIT_OBJ_LEV_HIGH: + case AUDIT_SE_USER: + case AUDIT_SE_ROLE: + case AUDIT_SE_TYPE: + case AUDIT_SE_SEN: + case AUDIT_SE_CLR: str = audit_unpack_string(&bufp, &remain, f->val); if (IS_ERR(str)) goto exit_free; @@ -556,16 +511,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, if (err) goto exit_free; break; - case AUDIT_FILTERKEY: - err = -EINVAL; - if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN) - goto exit_free; - str = audit_unpack_string(&bufp, &remain, f->val); - if (IS_ERR(str)) - goto exit_free; - entry->rule.buflen += f->val; - entry->rule.filterkey = str; - break; default: goto exit_free; } @@ -655,16 +600,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) data->fields[i] = f->type; data->fieldflags[i] = f->op; switch(f->type) { - case AUDIT_SUBJ_USER: - case AUDIT_SUBJ_ROLE: - case AUDIT_SUBJ_TYPE: - case AUDIT_SUBJ_SEN: - case AUDIT_SUBJ_CLR: - case AUDIT_OBJ_USER: - case AUDIT_OBJ_ROLE: - case AUDIT_OBJ_TYPE: - case AUDIT_OBJ_LEV_LOW: - case AUDIT_OBJ_LEV_HIGH: + case AUDIT_SE_USER: + case AUDIT_SE_ROLE: + case AUDIT_SE_TYPE: + case AUDIT_SE_SEN: + case AUDIT_SE_CLR: data->buflen += data->values[i] = audit_pack_string(&bufp, f->se_str); break; @@ -672,10 +612,6 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) data->buflen += data->values[i] = audit_pack_string(&bufp, krule->watch->path); break; - case AUDIT_FILTERKEY: - data->buflen += data->values[i] = - audit_pack_string(&bufp, krule->filterkey); - break; default: data->values[i] = f->val; } @@ -703,16 +639,11 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) return 1; switch(a->fields[i].type) { - case AUDIT_SUBJ_USER: - case AUDIT_SUBJ_ROLE: - case AUDIT_SUBJ_TYPE: - case AUDIT_SUBJ_SEN: - case AUDIT_SUBJ_CLR: - case AUDIT_OBJ_USER: - case AUDIT_OBJ_ROLE: - case AUDIT_OBJ_TYPE: - case AUDIT_OBJ_LEV_LOW: - case AUDIT_OBJ_LEV_HIGH: + case AUDIT_SE_USER: + case AUDIT_SE_ROLE: + case AUDIT_SE_TYPE: + case AUDIT_SE_SEN: + case AUDIT_SE_CLR: if (strcmp(a->fields[i].se_str, b->fields[i].se_str)) return 1; break; @@ -720,11 +651,6 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) if (strcmp(a->watch->path, b->watch->path)) return 1; break; - case AUDIT_FILTERKEY: - /* both filterkeys exist based on above type compare */ - if (strcmp(a->filterkey, b->filterkey)) - return 1; - break; default: if (a->fields[i].val != b->fields[i].val) return 1; @@ -804,7 +730,6 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old, u32 fcount = old->field_count; struct audit_entry *entry; struct audit_krule *new; - char *fk; int i, err = 0; entry = audit_init_entry(fcount); @@ -828,25 +753,13 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old, * the originals will all be freed when the old rule is freed. */ for (i = 0; i < fcount; i++) { switch (new->fields[i].type) { - case AUDIT_SUBJ_USER: - case AUDIT_SUBJ_ROLE: - case AUDIT_SUBJ_TYPE: - case AUDIT_SUBJ_SEN: - case AUDIT_SUBJ_CLR: - case AUDIT_OBJ_USER: - case AUDIT_OBJ_ROLE: - case AUDIT_OBJ_TYPE: - case AUDIT_OBJ_LEV_LOW: - case AUDIT_OBJ_LEV_HIGH: + case AUDIT_SE_USER: + case AUDIT_SE_ROLE: + case AUDIT_SE_TYPE: + case AUDIT_SE_SEN: + case AUDIT_SE_CLR: err = audit_dupe_selinux_field(&new->fields[i], &old->fields[i]); - break; - case AUDIT_FILTERKEY: - fk = kstrdup(old->filterkey, GFP_KERNEL); - if (unlikely(!fk)) - err = -ENOMEM; - else - new->filterkey = fk; } if (err) { audit_free_rule(entry); @@ -1332,34 +1245,6 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) skb_queue_tail(q, skb); } -/* Log rule additions and removals */ -static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action, - struct audit_krule *rule, int res) -{ - struct audit_buffer *ab; - - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); - if (!ab) - return; - audit_log_format(ab, "auid=%u", loginuid); - if (sid) { - char *ctx = NULL; - u32 len; - if (selinux_ctxid_to_string(sid, &ctx, &len)) - audit_log_format(ab, " ssid=%u", sid); - else - audit_log_format(ab, " subj=%s", ctx); - kfree(ctx); - } - audit_log_format(ab, " %s rule key=", action); - if (rule->filterkey) - audit_log_untrustedstring(ab, rule->filterkey); - else - audit_log_format(ab, "(null)"); - audit_log_format(ab, " list=%d res=%d", rule->listnr, res); - audit_log_end(ab); -} - /** * audit_receive_filter - apply all rules to the specified message type * @type: audit message type @@ -1419,7 +1304,24 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, err = audit_add_rule(entry, &audit_filter_list[entry->rule.listnr]); - audit_log_rule_change(loginuid, sid, "add", &entry->rule, !err); + + if (sid) { + char *ctx = NULL; + u32 len; + if (selinux_ctxid_to_string(sid, &ctx, &len)) { + /* Maybe call audit_panic? */ + audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, + "auid=%u ssid=%u add rule to list=%d res=%d", + loginuid, sid, entry->rule.listnr, !err); + } else + audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, + "auid=%u subj=%s add rule to list=%d res=%d", + loginuid, ctx, entry->rule.listnr, !err); + kfree(ctx); + } else + audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, + "auid=%u add rule to list=%d res=%d", + loginuid, entry->rule.listnr, !err); if (err) audit_free_rule(entry); @@ -1435,8 +1337,24 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, err = audit_del_rule(entry, &audit_filter_list[entry->rule.listnr]); - audit_log_rule_change(loginuid, sid, "remove", &entry->rule, - !err); + + if (sid) { + char *ctx = NULL; + u32 len; + if (selinux_ctxid_to_string(sid, &ctx, &len)) { + /* Maybe call audit_panic? */ + audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, + "auid=%u ssid=%u remove rule from list=%d res=%d", + loginuid, sid, entry->rule.listnr, !err); + } else + audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, + "auid=%u subj=%s remove rule from list=%d res=%d", + loginuid, ctx, entry->rule.listnr, !err); + kfree(ctx); + } else + audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, + "auid=%u remove rule from list=%d res=%d", + loginuid, entry->rule.listnr, !err); audit_free_rule(entry); break; @@ -1596,16 +1514,11 @@ static inline int audit_rule_has_selinux(struct audit_krule *rule) for (i = 0; i < rule->field_count; i++) { struct audit_field *f = &rule->fields[i]; switch (f->type) { - case AUDIT_SUBJ_USER: - case AUDIT_SUBJ_ROLE: - case AUDIT_SUBJ_TYPE: - case AUDIT_SUBJ_SEN: - case AUDIT_SUBJ_CLR: - case AUDIT_OBJ_USER: - case AUDIT_OBJ_ROLE: - case AUDIT_OBJ_TYPE: - case AUDIT_OBJ_LEV_LOW: - case AUDIT_OBJ_LEV_HIGH: + case AUDIT_SE_USER: + case AUDIT_SE_ROLE: + case AUDIT_SE_TYPE: + case AUDIT_SE_SEN: + case AUDIT_SE_CLR: return 1; } } diff --git a/trunk/kernel/auditsc.c b/trunk/kernel/auditsc.c index ae40ac8c39e7..9ebd96fda295 100644 --- a/trunk/kernel/auditsc.c +++ b/trunk/kernel/auditsc.c @@ -186,7 +186,6 @@ struct audit_context { int auditable; /* 1 if record should be written */ int name_count; struct audit_names names[AUDIT_NAMES]; - char * filterkey; /* key for rule that triggered record */ struct dentry * pwd; struct vfsmount * pwdmnt; struct audit_context *previous; /* For nested syscalls */ @@ -321,11 +320,11 @@ static int audit_filter_rules(struct task_struct *tsk, if (ctx) result = audit_comparator(ctx->loginuid, f->op, f->val); break; - case AUDIT_SUBJ_USER: - case AUDIT_SUBJ_ROLE: - case AUDIT_SUBJ_TYPE: - case AUDIT_SUBJ_SEN: - case AUDIT_SUBJ_CLR: + case AUDIT_SE_USER: + case AUDIT_SE_ROLE: + case AUDIT_SE_TYPE: + case AUDIT_SE_SEN: + case AUDIT_SE_CLR: /* NOTE: this may return negative values indicating a temporary error. We simply treat this as a match for now to avoid losing information that @@ -342,46 +341,6 @@ static int audit_filter_rules(struct task_struct *tsk, ctx); } break; - case AUDIT_OBJ_USER: - case AUDIT_OBJ_ROLE: - case AUDIT_OBJ_TYPE: - case AUDIT_OBJ_LEV_LOW: - case AUDIT_OBJ_LEV_HIGH: - /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR - also applies here */ - if (f->se_rule) { - /* Find files that match */ - if (name) { - result = selinux_audit_rule_match( - name->osid, f->type, f->op, - f->se_rule, ctx); - } else if (ctx) { - for (j = 0; j < ctx->name_count; j++) { - if (selinux_audit_rule_match( - ctx->names[j].osid, - f->type, f->op, - f->se_rule, ctx)) { - ++result; - break; - } - } - } - /* Find ipc objects that match */ - if (ctx) { - struct audit_aux_data *aux; - for (aux = ctx->aux; aux; - aux = aux->next) { - if (aux->type == AUDIT_IPC) { - struct audit_aux_data_ipcctl *axi = (void *)aux; - if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) { - ++result; - break; - } - } - } - } - } - break; case AUDIT_ARG0: case AUDIT_ARG1: case AUDIT_ARG2: @@ -389,17 +348,11 @@ static int audit_filter_rules(struct task_struct *tsk, if (ctx) result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val); break; - case AUDIT_FILTERKEY: - /* ignore this field for filtering */ - result = 1; - break; } if (!result) return 0; } - if (rule->filterkey) - ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); switch (rule->action) { case AUDIT_NEVER: *state = AUDIT_DISABLED; break; case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; @@ -674,7 +627,6 @@ static inline void audit_free_context(struct audit_context *context) } audit_free_names(context); audit_free_aux(context); - kfree(context->filterkey); kfree(context); context = previous; } while (context); @@ -706,7 +658,8 @@ static void audit_log_task_context(struct audit_buffer *ab) return; error_path: - kfree(ctx); + if (ctx) + kfree(ctx); audit_panic("error in audit_log_task_context"); return; } @@ -783,11 +736,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts context->euid, context->suid, context->fsuid, context->egid, context->sgid, context->fsgid, tty); audit_log_task_info(ab, tsk); - if (context->filterkey) { - audit_log_format(ab, " key="); - audit_log_untrustedstring(ab, context->filterkey); - } else - audit_log_format(ab, " key=(null)"); audit_log_end(ab); for (aux = context->aux; aux; aux = aux->next) { @@ -1113,8 +1061,6 @@ void audit_syscall_exit(int valid, long return_code) } else { audit_free_names(context); audit_free_aux(context); - kfree(context->filterkey); - context->filterkey = NULL; tsk->audit_context = context; } } @@ -1421,7 +1367,7 @@ int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr) * @mqdes: MQ descriptor * @msg_len: Message length * @msg_prio: Message priority - * @u_abs_timeout: Message timeout in absolute time + * @abs_timeout: Message timeout in absolute time * * Returns 0 for success or NULL context or < 0 on error. */ @@ -1463,8 +1409,8 @@ int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, * __audit_mq_timedreceive - record audit data for a POSIX MQ timed receive * @mqdes: MQ descriptor * @msg_len: Message length - * @u_msg_prio: Message priority - * @u_abs_timeout: Message timeout in absolute time + * @msg_prio: Message priority + * @abs_timeout: Message timeout in absolute time * * Returns 0 for success or NULL context or < 0 on error. */ @@ -1612,6 +1558,7 @@ int __audit_ipc_obj(struct kern_ipc_perm *ipcp) * @uid: msgq user id * @gid: msgq group id * @mode: msgq mode (permissions) + * @ipcp: in-kernel IPC permissions * * Returns 0 for success or NULL context or < 0 on error. */ diff --git a/trunk/kernel/configs.c b/trunk/kernel/configs.c index f9e31974f4ad..009e1ebdcb88 100644 --- a/trunk/kernel/configs.c +++ b/trunk/kernel/configs.c @@ -23,6 +23,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include diff --git a/trunk/kernel/cpu.c b/trunk/kernel/cpu.c index 70fbf2e83766..fe2b8d0bfe4c 100644 --- a/trunk/kernel/cpu.c +++ b/trunk/kernel/cpu.c @@ -13,12 +13,12 @@ #include #include #include -#include +#include /* This protects CPUs going up and down... */ -static DEFINE_MUTEX(cpucontrol); +static DECLARE_MUTEX(cpucontrol); -static __cpuinitdata BLOCKING_NOTIFIER_HEAD(cpu_chain); +static BLOCKING_NOTIFIER_HEAD(cpu_chain); #ifdef CONFIG_HOTPLUG_CPU static struct task_struct *lock_cpu_hotplug_owner; @@ -30,9 +30,9 @@ static int __lock_cpu_hotplug(int interruptible) if (lock_cpu_hotplug_owner != current) { if (interruptible) - ret = mutex_lock_interruptible(&cpucontrol); + ret = down_interruptible(&cpucontrol); else - mutex_lock(&cpucontrol); + down(&cpucontrol); } /* @@ -56,7 +56,7 @@ void unlock_cpu_hotplug(void) { if (--lock_cpu_hotplug_depth == 0) { lock_cpu_hotplug_owner = NULL; - mutex_unlock(&cpucontrol); + up(&cpucontrol); } } EXPORT_SYMBOL_GPL(unlock_cpu_hotplug); @@ -69,13 +69,10 @@ EXPORT_SYMBOL_GPL(lock_cpu_hotplug_interruptible); #endif /* CONFIG_HOTPLUG_CPU */ /* Need to know about CPUs going up/down? */ -int __cpuinit register_cpu_notifier(struct notifier_block *nb) +int register_cpu_notifier(struct notifier_block *nb) { return blocking_notifier_chain_register(&cpu_chain, nb); } - -#ifdef CONFIG_HOTPLUG_CPU - EXPORT_SYMBOL(register_cpu_notifier); void unregister_cpu_notifier(struct notifier_block *nb) @@ -84,6 +81,7 @@ void unregister_cpu_notifier(struct notifier_block *nb) } EXPORT_SYMBOL(unregister_cpu_notifier); +#ifdef CONFIG_HOTPLUG_CPU static inline void check_for_tasks(int cpu) { struct task_struct *p; diff --git a/trunk/kernel/cpuset.c b/trunk/kernel/cpuset.c index c232dc077438..b602f73fb38d 100644 --- a/trunk/kernel/cpuset.c +++ b/trunk/kernel/cpuset.c @@ -18,6 +18,7 @@ * distribution for more details. */ +#include #include #include #include @@ -1063,7 +1064,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf) } /* - * Frequency meter - How fast is some event occurring? + * Frequency meter - How fast is some event occuring? * * These routines manage a digitally filtered, constant time based, * event frequency meter. There are four routines: @@ -2441,43 +2442,31 @@ void __cpuset_memory_pressure_bump(void) */ static int proc_cpuset_show(struct seq_file *m, void *v) { - struct pid *pid; struct task_struct *tsk; char *buf; - int retval; + int retval = 0; - retval = -ENOMEM; buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!buf) - goto out; - - retval = -ESRCH; - pid = m->private; - tsk = get_pid_task(pid, PIDTYPE_PID); - if (!tsk) - goto out_free; + return -ENOMEM; - retval = -EINVAL; + tsk = m->private; mutex_lock(&manage_mutex); - retval = cpuset_path(tsk->cpuset, buf, PAGE_SIZE); if (retval < 0) - goto out_unlock; + goto out; seq_puts(m, buf); seq_putc(m, '\n'); -out_unlock: +out: mutex_unlock(&manage_mutex); - put_task_struct(tsk); -out_free: kfree(buf); -out: return retval; } static int cpuset_open(struct inode *inode, struct file *file) { - struct pid *pid = PROC_I(inode)->pid; - return single_open(file, proc_cpuset_show, pid); + struct task_struct *tsk = PROC_I(inode)->task; + return single_open(file, proc_cpuset_show, tsk); } struct file_operations proc_cpuset_operations = { diff --git a/trunk/kernel/exec_domain.c b/trunk/kernel/exec_domain.c index 3c2eaea66b1e..c01cead2cfd6 100644 --- a/trunk/kernel/exec_domain.c +++ b/trunk/kernel/exec_domain.c @@ -7,6 +7,7 @@ * 2001-05-06 Complete rewrite, Christoph Hellwig (hch@infradead.org) */ +#include #include #include #include diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index 7f7ef2258553..e76bd02e930e 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -4,6 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ +#include #include #include #include @@ -136,8 +137,12 @@ void release_task(struct task_struct * p) { int zap_leader; task_t *leader; + struct dentry *proc_dentry; + repeat: atomic_dec(&p->user->processes); + spin_lock(&p->proc_lock); + proc_dentry = proc_pid_unhash(p); write_lock_irq(&tasklist_lock); ptrace_unlink(p); BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children)); @@ -166,7 +171,8 @@ void release_task(struct task_struct * p) sched_exit(p); write_unlock_irq(&tasklist_lock); - proc_flush_task(p); + spin_unlock(&p->proc_lock); + proc_pid_flush(proc_dentry); release_thread(p); call_rcu(&p->rcu, delayed_put_task_struct); @@ -924,19 +930,10 @@ fastcall NORET_TYPE void do_exit(long code) mpol_free(tsk->mempolicy); tsk->mempolicy = NULL; #endif - /* - * This must happen late, after the PID is not - * hashed anymore: - */ - if (unlikely(!list_empty(&tsk->pi_state_list))) - exit_pi_state_list(tsk); - if (unlikely(current->pi_state_cache)) - kfree(current->pi_state_cache); /* * If DEBUG_MUTEXES is on, make sure we are holding no locks: */ mutex_debug_check_no_locks_held(tsk); - rt_mutex_debug_check_no_locks_held(tsk); if (tsk->io_context) exit_io_context(); diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index 9064bf9e131b..dfd10cb370c3 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -11,6 +11,7 @@ * management can be a bitch. See 'mm/memory.c': 'copy_page_range()' */ +#include #include #include #include @@ -103,7 +104,6 @@ static kmem_cache_t *mm_cachep; void free_task(struct task_struct *tsk) { free_thread_info(tsk->thread_info); - rt_mutex_debug_task_free(tsk); free_task_struct(tsk); } EXPORT_SYMBOL(free_task); @@ -913,19 +913,6 @@ asmlinkage long sys_set_tid_address(int __user *tidptr) return current->pid; } -static inline void rt_mutex_init_task(struct task_struct *p) -{ -#ifdef CONFIG_RT_MUTEXES - spin_lock_init(&p->pi_lock); - plist_head_init(&p->pi_waiters, &p->pi_lock); - p->pi_blocked_on = NULL; -# ifdef CONFIG_DEBUG_RT_MUTEXES - spin_lock_init(&p->held_list_lock); - INIT_LIST_HEAD(&p->held_list_head); -# endif -#endif -} - /* * This creates a new process as a copy of the old one, * but does not actually start it yet. @@ -1006,10 +993,13 @@ static task_t *copy_process(unsigned long clone_flags, if (put_user(p->pid, parent_tidptr)) goto bad_fork_cleanup; + p->proc_dentry = NULL; + INIT_LIST_HEAD(&p->children); INIT_LIST_HEAD(&p->sibling); p->vfork_done = NULL; spin_lock_init(&p->alloc_lock); + spin_lock_init(&p->proc_lock); clear_tsk_thread_flag(p, TIF_SIGPENDING); init_sigpending(&p->pending); @@ -1047,8 +1037,6 @@ static task_t *copy_process(unsigned long clone_flags, mpol_fix_fork_child_flag(p); #endif - rt_mutex_init_task(p); - #ifdef CONFIG_DEBUG_MUTEXES p->blocked_on = NULL; /* not blocked yet */ #endif @@ -1091,9 +1079,6 @@ static task_t *copy_process(unsigned long clone_flags, #ifdef CONFIG_COMPAT p->compat_robust_list = NULL; #endif - INIT_LIST_HEAD(&p->pi_state_list); - p->pi_state_cache = NULL; - /* * sigaltstack should be cleared when sharing the same VM */ @@ -1174,6 +1159,18 @@ static task_t *copy_process(unsigned long clone_flags, } if (clone_flags & CLONE_THREAD) { + /* + * Important: if an exit-all has been started then + * do not create this new thread - the whole thread + * group is supposed to exit anyway. + */ + if (current->signal->flags & SIGNAL_GROUP_EXIT) { + spin_unlock(¤t->sighand->siglock); + write_unlock_irq(&tasklist_lock); + retval = -EAGAIN; + goto bad_fork_cleanup_namespace; + } + p->group_leader = current->group_leader; list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); diff --git a/trunk/kernel/futex.c b/trunk/kernel/futex.c index 15caf93e4a43..e1a380c77a5a 100644 --- a/trunk/kernel/futex.c +++ b/trunk/kernel/futex.c @@ -12,10 +12,6 @@ * (C) Copyright 2006 Red Hat Inc, All Rights Reserved * Thanks to Thomas Gleixner for suggestions, analysis and fixes. * - * PI-futex support started by Ingo Molnar and Thomas Gleixner - * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar - * Copyright (C) 2006 Timesys Corp., Thomas Gleixner - * * Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly * enough at me, Linus for the original (flawed) idea, Matthew * Kirkwood for proof-of-concept implementation. @@ -50,8 +46,6 @@ #include #include -#include "rtmutex_common.h" - #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8) /* @@ -69,7 +63,7 @@ union futex_key { int offset; } shared; struct { - unsigned long address; + unsigned long uaddr; struct mm_struct *mm; int offset; } private; @@ -80,27 +74,6 @@ union futex_key { } both; }; -/* - * Priority Inheritance state: - */ -struct futex_pi_state { - /* - * list of 'owned' pi_state instances - these have to be - * cleaned up in do_exit() if the task exits prematurely: - */ - struct list_head list; - - /* - * The PI object: - */ - struct rt_mutex pi_mutex; - - struct task_struct *owner; - atomic_t refcount; - - union futex_key key; -}; - /* * We use this hashed waitqueue instead of a normal wait_queue_t, so * we can wake only the relevant ones (hashed queues may be shared). @@ -114,19 +87,15 @@ struct futex_q { struct list_head list; wait_queue_head_t waiters; - /* Which hash list lock to use: */ + /* Which hash list lock to use. */ spinlock_t *lock_ptr; - /* Key which the futex is hashed on: */ + /* Key which the futex is hashed on. */ union futex_key key; - /* For fd, sigio sent using these: */ + /* For fd, sigio sent using these. */ int fd; struct file *filp; - - /* Optional priority inheritance state: */ - struct futex_pi_state *pi_state; - struct task_struct *task; }; /* @@ -175,9 +144,8 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2) * * Should be called with ¤t->mm->mmap_sem but NOT any spinlocks. */ -static int get_futex_key(u32 __user *uaddr, union futex_key *key) +static int get_futex_key(unsigned long uaddr, union futex_key *key) { - unsigned long address = (unsigned long)uaddr; struct mm_struct *mm = current->mm; struct vm_area_struct *vma; struct page *page; @@ -186,16 +154,16 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key) /* * The futex address must be "naturally" aligned. */ - key->both.offset = address % PAGE_SIZE; + key->both.offset = uaddr % PAGE_SIZE; if (unlikely((key->both.offset % sizeof(u32)) != 0)) return -EINVAL; - address -= key->both.offset; + uaddr -= key->both.offset; /* * The futex is hashed differently depending on whether * it's in a shared or private mapping. So check vma first. */ - vma = find_extend_vma(mm, address); + vma = find_extend_vma(mm, uaddr); if (unlikely(!vma)) return -EFAULT; @@ -216,7 +184,7 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key) */ if (likely(!(vma->vm_flags & VM_MAYSHARE))) { key->private.mm = mm; - key->private.address = address; + key->private.uaddr = uaddr; return 0; } @@ -226,7 +194,7 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key) key->shared.inode = vma->vm_file->f_dentry->d_inode; key->both.offset++; /* Bit 0 of offset indicates inode-based key. */ if (likely(!(vma->vm_flags & VM_NONLINEAR))) { - key->shared.pgoff = (((address - vma->vm_start) >> PAGE_SHIFT) + key->shared.pgoff = (((uaddr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff); return 0; } @@ -237,7 +205,7 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key) * from swap. But that's a lot of code to duplicate here * for a rare case, so we simply fetch the page. */ - err = get_user_pages(current, mm, address, 1, 0, 0, &page, NULL); + err = get_user_pages(current, mm, uaddr, 1, 0, 0, &page, NULL); if (err >= 0) { key->shared.pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); @@ -278,243 +246,17 @@ static void drop_key_refs(union futex_key *key) } } -static inline int get_futex_value_locked(u32 *dest, u32 __user *from) +static inline int get_futex_value_locked(int *dest, int __user *from) { int ret; inc_preempt_count(); - ret = __copy_from_user_inatomic(dest, from, sizeof(u32)); + ret = __copy_from_user_inatomic(dest, from, sizeof(int)); dec_preempt_count(); return ret ? -EFAULT : 0; } -/* - * Fault handling. Called with current->mm->mmap_sem held. - */ -static int futex_handle_fault(unsigned long address, int attempt) -{ - struct vm_area_struct * vma; - struct mm_struct *mm = current->mm; - - if (attempt >= 2 || !(vma = find_vma(mm, address)) || - vma->vm_start > address || !(vma->vm_flags & VM_WRITE)) - return -EFAULT; - - switch (handle_mm_fault(mm, vma, address, 1)) { - case VM_FAULT_MINOR: - current->min_flt++; - break; - case VM_FAULT_MAJOR: - current->maj_flt++; - break; - default: - return -EFAULT; - } - return 0; -} - -/* - * PI code: - */ -static int refill_pi_state_cache(void) -{ - struct futex_pi_state *pi_state; - - if (likely(current->pi_state_cache)) - return 0; - - pi_state = kmalloc(sizeof(*pi_state), GFP_KERNEL); - - if (!pi_state) - return -ENOMEM; - - memset(pi_state, 0, sizeof(*pi_state)); - INIT_LIST_HEAD(&pi_state->list); - /* pi_mutex gets initialized later */ - pi_state->owner = NULL; - atomic_set(&pi_state->refcount, 1); - - current->pi_state_cache = pi_state; - - return 0; -} - -static struct futex_pi_state * alloc_pi_state(void) -{ - struct futex_pi_state *pi_state = current->pi_state_cache; - - WARN_ON(!pi_state); - current->pi_state_cache = NULL; - - return pi_state; -} - -static void free_pi_state(struct futex_pi_state *pi_state) -{ - if (!atomic_dec_and_test(&pi_state->refcount)) - return; - - /* - * If pi_state->owner is NULL, the owner is most probably dying - * and has cleaned up the pi_state already - */ - if (pi_state->owner) { - spin_lock_irq(&pi_state->owner->pi_lock); - list_del_init(&pi_state->list); - spin_unlock_irq(&pi_state->owner->pi_lock); - - rt_mutex_proxy_unlock(&pi_state->pi_mutex, pi_state->owner); - } - - if (current->pi_state_cache) - kfree(pi_state); - else { - /* - * pi_state->list is already empty. - * clear pi_state->owner. - * refcount is at 0 - put it back to 1. - */ - pi_state->owner = NULL; - atomic_set(&pi_state->refcount, 1); - current->pi_state_cache = pi_state; - } -} - -/* - * Look up the task based on what TID userspace gave us. - * We dont trust it. - */ -static struct task_struct * futex_find_get_task(pid_t pid) -{ - struct task_struct *p; - - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - if (!p) - goto out_unlock; - if ((current->euid != p->euid) && (current->euid != p->uid)) { - p = NULL; - goto out_unlock; - } - if (p->state == EXIT_ZOMBIE || p->exit_state == EXIT_ZOMBIE) { - p = NULL; - goto out_unlock; - } - get_task_struct(p); -out_unlock: - read_unlock(&tasklist_lock); - - return p; -} - -/* - * This task is holding PI mutexes at exit time => bad. - * Kernel cleans up PI-state, but userspace is likely hosed. - * (Robust-futex cleanup is separate and might save the day for userspace.) - */ -void exit_pi_state_list(struct task_struct *curr) -{ - struct futex_hash_bucket *hb; - struct list_head *next, *head = &curr->pi_state_list; - struct futex_pi_state *pi_state; - union futex_key key; - - /* - * We are a ZOMBIE and nobody can enqueue itself on - * pi_state_list anymore, but we have to be careful - * versus waiters unqueueing themselfs - */ - spin_lock_irq(&curr->pi_lock); - while (!list_empty(head)) { - - next = head->next; - pi_state = list_entry(next, struct futex_pi_state, list); - key = pi_state->key; - spin_unlock_irq(&curr->pi_lock); - - hb = hash_futex(&key); - spin_lock(&hb->lock); - - spin_lock_irq(&curr->pi_lock); - if (head->next != next) { - spin_unlock(&hb->lock); - continue; - } - - list_del_init(&pi_state->list); - - WARN_ON(pi_state->owner != curr); - - pi_state->owner = NULL; - spin_unlock_irq(&curr->pi_lock); - - rt_mutex_unlock(&pi_state->pi_mutex); - - spin_unlock(&hb->lock); - - spin_lock_irq(&curr->pi_lock); - } - spin_unlock_irq(&curr->pi_lock); -} - -static int -lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me) -{ - struct futex_pi_state *pi_state = NULL; - struct futex_q *this, *next; - struct list_head *head; - struct task_struct *p; - pid_t pid; - - head = &hb->chain; - - list_for_each_entry_safe(this, next, head, list) { - if (match_futex (&this->key, &me->key)) { - /* - * Another waiter already exists - bump up - * the refcount and return its pi_state: - */ - pi_state = this->pi_state; - atomic_inc(&pi_state->refcount); - me->pi_state = pi_state; - - return 0; - } - } - - /* - * We are the first waiter - try to look up the real owner and - * attach the new pi_state to it: - */ - pid = uval & FUTEX_TID_MASK; - p = futex_find_get_task(pid); - if (!p) - return -ESRCH; - - pi_state = alloc_pi_state(); - - /* - * Initialize the pi_mutex in locked state and make 'p' - * the owner of it: - */ - rt_mutex_init_proxy_locked(&pi_state->pi_mutex, p); - - /* Store the key for possible exit cleanups: */ - pi_state->key = me->key; - - spin_lock_irq(&p->pi_lock); - list_add(&pi_state->list, &p->pi_state_list); - pi_state->owner = p; - spin_unlock_irq(&p->pi_lock); - - put_task_struct(p); - - me->pi_state = pi_state; - - return 0; -} - /* * The hash bucket lock must be held when this is called. * Afterwards, the futex_q must not be accessed. @@ -542,80 +284,16 @@ static void wake_futex(struct futex_q *q) q->lock_ptr = NULL; } -static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) -{ - struct task_struct *new_owner; - struct futex_pi_state *pi_state = this->pi_state; - u32 curval, newval; - - if (!pi_state) - return -EINVAL; - - new_owner = rt_mutex_next_owner(&pi_state->pi_mutex); - - /* - * This happens when we have stolen the lock and the original - * pending owner did not enqueue itself back on the rt_mutex. - * Thats not a tragedy. We know that way, that a lock waiter - * is on the fly. We make the futex_q waiter the pending owner. - */ - if (!new_owner) - new_owner = this->task; - - /* - * We pass it to the next owner. (The WAITERS bit is always - * kept enabled while there is PI state around. We must also - * preserve the owner died bit.) - */ - newval = (uval & FUTEX_OWNER_DIED) | FUTEX_WAITERS | new_owner->pid; - - inc_preempt_count(); - curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); - dec_preempt_count(); - - if (curval == -EFAULT) - return -EFAULT; - if (curval != uval) - return -EINVAL; - - list_del_init(&pi_state->owner->pi_state_list); - list_add(&pi_state->list, &new_owner->pi_state_list); - pi_state->owner = new_owner; - rt_mutex_unlock(&pi_state->pi_mutex); - - return 0; -} - -static int unlock_futex_pi(u32 __user *uaddr, u32 uval) -{ - u32 oldval; - - /* - * There is no waiter, so we unlock the futex. The owner died - * bit has not to be preserved here. We are the owner: - */ - inc_preempt_count(); - oldval = futex_atomic_cmpxchg_inatomic(uaddr, uval, 0); - dec_preempt_count(); - - if (oldval == -EFAULT) - return oldval; - if (oldval != uval) - return -EAGAIN; - - return 0; -} - /* * Wake up all waiters hashed on the physical page that is mapped * to this virtual address: */ -static int futex_wake(u32 __user *uaddr, int nr_wake) +static int futex_wake(unsigned long uaddr, int nr_wake) { - struct futex_hash_bucket *hb; - struct futex_q *this, *next; - struct list_head *head; union futex_key key; + struct futex_hash_bucket *bh; + struct list_head *head; + struct futex_q *this, *next; int ret; down_read(¤t->mm->mmap_sem); @@ -624,23 +302,19 @@ static int futex_wake(u32 __user *uaddr, int nr_wake) if (unlikely(ret != 0)) goto out; - hb = hash_futex(&key); - spin_lock(&hb->lock); - head = &hb->chain; + bh = hash_futex(&key); + spin_lock(&bh->lock); + head = &bh->chain; list_for_each_entry_safe(this, next, head, list) { if (match_futex (&this->key, &key)) { - if (this->pi_state) { - ret = -EINVAL; - break; - } wake_futex(this); if (++ret >= nr_wake) break; } } - spin_unlock(&hb->lock); + spin_unlock(&bh->lock); out: up_read(¤t->mm->mmap_sem); return ret; @@ -650,12 +324,10 @@ static int futex_wake(u32 __user *uaddr, int nr_wake) * Wake up all waiters hashed on the physical page that is mapped * to this virtual address: */ -static int -futex_wake_op(u32 __user *uaddr1, u32 __user *uaddr2, - int nr_wake, int nr_wake2, int op) +static int futex_wake_op(unsigned long uaddr1, unsigned long uaddr2, int nr_wake, int nr_wake2, int op) { union futex_key key1, key2; - struct futex_hash_bucket *hb1, *hb2; + struct futex_hash_bucket *bh1, *bh2; struct list_head *head; struct futex_q *this, *next; int ret, op_ret, attempt = 0; @@ -670,29 +342,27 @@ futex_wake_op(u32 __user *uaddr1, u32 __user *uaddr2, if (unlikely(ret != 0)) goto out; - hb1 = hash_futex(&key1); - hb2 = hash_futex(&key2); + bh1 = hash_futex(&key1); + bh2 = hash_futex(&key2); retry: - if (hb1 < hb2) - spin_lock(&hb1->lock); - spin_lock(&hb2->lock); - if (hb1 > hb2) - spin_lock(&hb1->lock); + if (bh1 < bh2) + spin_lock(&bh1->lock); + spin_lock(&bh2->lock); + if (bh1 > bh2) + spin_lock(&bh1->lock); - op_ret = futex_atomic_op_inuser(op, uaddr2); + op_ret = futex_atomic_op_inuser(op, (int __user *)uaddr2); if (unlikely(op_ret < 0)) { - u32 dummy; + int dummy; - spin_unlock(&hb1->lock); - if (hb1 != hb2) - spin_unlock(&hb2->lock); + spin_unlock(&bh1->lock); + if (bh1 != bh2) + spin_unlock(&bh2->lock); #ifndef CONFIG_MMU - /* - * we don't get EFAULT from MMU faults if we don't have an MMU, - * but we might get them from range checking - */ + /* we don't get EFAULT from MMU faults if we don't have an MMU, + * but we might get them from range checking */ ret = op_ret; goto out; #endif @@ -702,34 +372,47 @@ futex_wake_op(u32 __user *uaddr1, u32 __user *uaddr2, goto out; } - /* - * futex_atomic_op_inuser needs to both read and write + /* futex_atomic_op_inuser needs to both read and write * *(int __user *)uaddr2, but we can't modify it * non-atomically. Therefore, if get_user below is not * enough, we need to handle the fault ourselves, while - * still holding the mmap_sem. - */ + * still holding the mmap_sem. */ if (attempt++) { - if (futex_handle_fault((unsigned long)uaddr2, - attempt)) + struct vm_area_struct * vma; + struct mm_struct *mm = current->mm; + + ret = -EFAULT; + if (attempt >= 2 || + !(vma = find_vma(mm, uaddr2)) || + vma->vm_start > uaddr2 || + !(vma->vm_flags & VM_WRITE)) + goto out; + + switch (handle_mm_fault(mm, vma, uaddr2, 1)) { + case VM_FAULT_MINOR: + current->min_flt++; + break; + case VM_FAULT_MAJOR: + current->maj_flt++; + break; + default: goto out; + } goto retry; } - /* - * If we would have faulted, release mmap_sem, - * fault it in and start all over again. - */ + /* If we would have faulted, release mmap_sem, + * fault it in and start all over again. */ up_read(¤t->mm->mmap_sem); - ret = get_user(dummy, uaddr2); + ret = get_user(dummy, (int __user *)uaddr2); if (ret) return ret; goto retryfull; } - head = &hb1->chain; + head = &bh1->chain; list_for_each_entry_safe(this, next, head, list) { if (match_futex (&this->key, &key1)) { @@ -740,7 +423,7 @@ futex_wake_op(u32 __user *uaddr1, u32 __user *uaddr2, } if (op_ret > 0) { - head = &hb2->chain; + head = &bh2->chain; op_ret = 0; list_for_each_entry_safe(this, next, head, list) { @@ -753,9 +436,9 @@ futex_wake_op(u32 __user *uaddr1, u32 __user *uaddr2, ret += op_ret; } - spin_unlock(&hb1->lock); - if (hb1 != hb2) - spin_unlock(&hb2->lock); + spin_unlock(&bh1->lock); + if (bh1 != bh2) + spin_unlock(&bh2->lock); out: up_read(¤t->mm->mmap_sem); return ret; @@ -765,11 +448,11 @@ futex_wake_op(u32 __user *uaddr1, u32 __user *uaddr2, * Requeue all waiters hashed on one physical page to another * physical page. */ -static int futex_requeue(u32 __user *uaddr1, u32 __user *uaddr2, - int nr_wake, int nr_requeue, u32 *cmpval) +static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2, + int nr_wake, int nr_requeue, int *valp) { union futex_key key1, key2; - struct futex_hash_bucket *hb1, *hb2; + struct futex_hash_bucket *bh1, *bh2; struct list_head *head1; struct futex_q *this, *next; int ret, drop_count = 0; @@ -784,72 +467,68 @@ static int futex_requeue(u32 __user *uaddr1, u32 __user *uaddr2, if (unlikely(ret != 0)) goto out; - hb1 = hash_futex(&key1); - hb2 = hash_futex(&key2); + bh1 = hash_futex(&key1); + bh2 = hash_futex(&key2); - if (hb1 < hb2) - spin_lock(&hb1->lock); - spin_lock(&hb2->lock); - if (hb1 > hb2) - spin_lock(&hb1->lock); + if (bh1 < bh2) + spin_lock(&bh1->lock); + spin_lock(&bh2->lock); + if (bh1 > bh2) + spin_lock(&bh1->lock); - if (likely(cmpval != NULL)) { - u32 curval; + if (likely(valp != NULL)) { + int curval; - ret = get_futex_value_locked(&curval, uaddr1); + ret = get_futex_value_locked(&curval, (int __user *)uaddr1); if (unlikely(ret)) { - spin_unlock(&hb1->lock); - if (hb1 != hb2) - spin_unlock(&hb2->lock); + spin_unlock(&bh1->lock); + if (bh1 != bh2) + spin_unlock(&bh2->lock); - /* - * If we would have faulted, release mmap_sem, fault + /* If we would have faulted, release mmap_sem, fault * it in and start all over again. */ up_read(¤t->mm->mmap_sem); - ret = get_user(curval, uaddr1); + ret = get_user(curval, (int __user *)uaddr1); if (!ret) goto retry; return ret; } - if (curval != *cmpval) { + if (curval != *valp) { ret = -EAGAIN; goto out_unlock; } } - head1 = &hb1->chain; + head1 = &bh1->chain; list_for_each_entry_safe(this, next, head1, list) { if (!match_futex (&this->key, &key1)) continue; if (++ret <= nr_wake) { wake_futex(this); } else { - /* - * If key1 and key2 hash to the same bucket, no need to - * requeue. - */ - if (likely(head1 != &hb2->chain)) { - list_move_tail(&this->list, &hb2->chain); - this->lock_ptr = &hb2->lock; - } + list_move_tail(&this->list, &bh2->chain); + this->lock_ptr = &bh2->lock; this->key = key2; get_key_refs(&key2); drop_count++; if (ret - nr_wake >= nr_requeue) break; + /* Make sure to stop if key1 == key2 */ + if (head1 == &bh2->chain && head1 != &next->list) + head1 = &this->list; } } out_unlock: - spin_unlock(&hb1->lock); - if (hb1 != hb2) - spin_unlock(&hb2->lock); + spin_unlock(&bh1->lock); + if (bh1 != bh2) + spin_unlock(&bh2->lock); /* drop_key_refs() must be called outside the spinlocks. */ while (--drop_count >= 0) @@ -864,7 +543,7 @@ static int futex_requeue(u32 __user *uaddr1, u32 __user *uaddr2, static inline struct futex_hash_bucket * queue_lock(struct futex_q *q, int fd, struct file *filp) { - struct futex_hash_bucket *hb; + struct futex_hash_bucket *bh; q->fd = fd; q->filp = filp; @@ -872,24 +551,23 @@ queue_lock(struct futex_q *q, int fd, struct file *filp) init_waitqueue_head(&q->waiters); get_key_refs(&q->key); - hb = hash_futex(&q->key); - q->lock_ptr = &hb->lock; + bh = hash_futex(&q->key); + q->lock_ptr = &bh->lock; - spin_lock(&hb->lock); - return hb; + spin_lock(&bh->lock); + return bh; } -static inline void __queue_me(struct futex_q *q, struct futex_hash_bucket *hb) +static inline void __queue_me(struct futex_q *q, struct futex_hash_bucket *bh) { - list_add_tail(&q->list, &hb->chain); - q->task = current; - spin_unlock(&hb->lock); + list_add_tail(&q->list, &bh->chain); + spin_unlock(&bh->lock); } static inline void -queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb) +queue_unlock(struct futex_q *q, struct futex_hash_bucket *bh) { - spin_unlock(&hb->lock); + spin_unlock(&bh->lock); drop_key_refs(&q->key); } @@ -901,17 +579,16 @@ queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb) /* The key must be already stored in q->key. */ static void queue_me(struct futex_q *q, int fd, struct file *filp) { - struct futex_hash_bucket *hb; - - hb = queue_lock(q, fd, filp); - __queue_me(q, hb); + struct futex_hash_bucket *bh; + bh = queue_lock(q, fd, filp); + __queue_me(q, bh); } /* Return 1 if we were still queued (ie. 0 means we were woken) */ static int unqueue_me(struct futex_q *q) { - spinlock_t *lock_ptr; int ret = 0; + spinlock_t *lock_ptr; /* In the common case we don't take the spinlock, which is nice. */ retry: @@ -937,9 +614,6 @@ static int unqueue_me(struct futex_q *q) } WARN_ON(list_empty(&q->list)); list_del(&q->list); - - BUG_ON(q->pi_state); - spin_unlock(lock_ptr); ret = 1; } @@ -948,42 +622,21 @@ static int unqueue_me(struct futex_q *q) return ret; } -/* - * PI futexes can not be requeued and must remove themself from the - * hash bucket. The hash bucket lock is held on entry and dropped here. - */ -static void unqueue_me_pi(struct futex_q *q, struct futex_hash_bucket *hb) +static int futex_wait(unsigned long uaddr, int val, unsigned long time) { - WARN_ON(list_empty(&q->list)); - list_del(&q->list); - - BUG_ON(!q->pi_state); - free_pi_state(q->pi_state); - q->pi_state = NULL; - - spin_unlock(&hb->lock); - - drop_key_refs(&q->key); -} - -static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time) -{ - struct task_struct *curr = current; - DECLARE_WAITQUEUE(wait, curr); - struct futex_hash_bucket *hb; + DECLARE_WAITQUEUE(wait, current); + int ret, curval; struct futex_q q; - u32 uval; - int ret; + struct futex_hash_bucket *bh; - q.pi_state = NULL; retry: - down_read(&curr->mm->mmap_sem); + down_read(¤t->mm->mmap_sem); ret = get_futex_key(uaddr, &q.key); if (unlikely(ret != 0)) goto out_release_sem; - hb = queue_lock(&q, -1, NULL); + bh = queue_lock(&q, -1, NULL); /* * Access the page AFTER the futex is queued. @@ -1005,35 +658,37 @@ static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time) * We hold the mmap semaphore, so the mapping cannot have changed * since we looked it up in get_futex_key. */ - ret = get_futex_value_locked(&uval, uaddr); + + ret = get_futex_value_locked(&curval, (int __user *)uaddr); if (unlikely(ret)) { - queue_unlock(&q, hb); + queue_unlock(&q, bh); - /* - * If we would have faulted, release mmap_sem, fault it in and + /* If we would have faulted, release mmap_sem, fault it in and * start all over again. */ - up_read(&curr->mm->mmap_sem); + up_read(¤t->mm->mmap_sem); - ret = get_user(uval, uaddr); + ret = get_user(curval, (int __user *)uaddr); if (!ret) goto retry; return ret; } - ret = -EWOULDBLOCK; - if (uval != val) - goto out_unlock_release_sem; + if (curval != val) { + ret = -EWOULDBLOCK; + queue_unlock(&q, bh); + goto out_release_sem; + } /* Only actually queue if *uaddr contained val. */ - __queue_me(&q, hb); + __queue_me(&q, bh); /* * Now the futex is queued and we have checked the data, we * don't want to hold mmap_sem while we sleep. - */ - up_read(&curr->mm->mmap_sem); + */ + up_read(¤t->mm->mmap_sem); /* * There might have been scheduling since the queue_me(), as we @@ -1065,421 +720,12 @@ static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time) return 0; if (time == 0) return -ETIMEDOUT; - /* - * We expect signal_pending(current), but another thread may - * have handled it for us already. - */ + /* We expect signal_pending(current), but another thread may + * have handled it for us already. */ return -EINTR; - out_unlock_release_sem: - queue_unlock(&q, hb); - out_release_sem: - up_read(&curr->mm->mmap_sem); - return ret; -} - -/* - * Userspace tried a 0 -> TID atomic transition of the futex value - * and failed. The kernel side here does the whole locking operation: - * if there are waiters then it will block, it does PI, etc. (Due to - * races the kernel might see a 0 value of the futex too.) - */ -static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock, - struct hrtimer_sleeper *to) -{ - struct task_struct *curr = current; - struct futex_hash_bucket *hb; - u32 uval, newval, curval; - struct futex_q q; - int ret, attempt = 0; - - if (refill_pi_state_cache()) - return -ENOMEM; - - q.pi_state = NULL; - retry: - down_read(&curr->mm->mmap_sem); - - ret = get_futex_key(uaddr, &q.key); - if (unlikely(ret != 0)) - goto out_release_sem; - - hb = queue_lock(&q, -1, NULL); - - retry_locked: - /* - * To avoid races, we attempt to take the lock here again - * (by doing a 0 -> TID atomic cmpxchg), while holding all - * the locks. It will most likely not succeed. - */ - newval = current->pid; - - inc_preempt_count(); - curval = futex_atomic_cmpxchg_inatomic(uaddr, 0, newval); - dec_preempt_count(); - - if (unlikely(curval == -EFAULT)) - goto uaddr_faulted; - - /* We own the lock already */ - if (unlikely((curval & FUTEX_TID_MASK) == current->pid)) { - if (!detect && 0) - force_sig(SIGKILL, current); - ret = -EDEADLK; - goto out_unlock_release_sem; - } - - /* - * Surprise - we got the lock. Just return - * to userspace: - */ - if (unlikely(!curval)) - goto out_unlock_release_sem; - - uval = curval; - newval = uval | FUTEX_WAITERS; - - inc_preempt_count(); - curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); - dec_preempt_count(); - - if (unlikely(curval == -EFAULT)) - goto uaddr_faulted; - if (unlikely(curval != uval)) - goto retry_locked; - - /* - * We dont have the lock. Look up the PI state (or create it if - * we are the first waiter): - */ - ret = lookup_pi_state(uval, hb, &q); - - if (unlikely(ret)) { - /* - * There were no waiters and the owner task lookup - * failed. When the OWNER_DIED bit is set, then we - * know that this is a robust futex and we actually - * take the lock. This is safe as we are protected by - * the hash bucket lock. We also set the waiters bit - * unconditionally here, to simplify glibc handling of - * multiple tasks racing to acquire the lock and - * cleanup the problems which were left by the dead - * owner. - */ - if (curval & FUTEX_OWNER_DIED) { - uval = newval; - newval = current->pid | - FUTEX_OWNER_DIED | FUTEX_WAITERS; - - inc_preempt_count(); - curval = futex_atomic_cmpxchg_inatomic(uaddr, - uval, newval); - dec_preempt_count(); - - if (unlikely(curval == -EFAULT)) - goto uaddr_faulted; - if (unlikely(curval != uval)) - goto retry_locked; - ret = 0; - } - goto out_unlock_release_sem; - } - - /* - * Only actually queue now that the atomic ops are done: - */ - __queue_me(&q, hb); - - /* - * Now the futex is queued and we have checked the data, we - * don't want to hold mmap_sem while we sleep. - */ - up_read(&curr->mm->mmap_sem); - - WARN_ON(!q.pi_state); - /* - * Block on the PI mutex: - */ - if (!trylock) - ret = rt_mutex_timed_lock(&q.pi_state->pi_mutex, to, 1); - else { - ret = rt_mutex_trylock(&q.pi_state->pi_mutex); - /* Fixup the trylock return value: */ - ret = ret ? 0 : -EWOULDBLOCK; - } - - down_read(&curr->mm->mmap_sem); - spin_lock(q.lock_ptr); - - /* - * Got the lock. We might not be the anticipated owner if we - * did a lock-steal - fix up the PI-state in that case. - */ - if (!ret && q.pi_state->owner != curr) { - u32 newtid = current->pid | FUTEX_WAITERS; - - /* Owner died? */ - if (q.pi_state->owner != NULL) { - spin_lock_irq(&q.pi_state->owner->pi_lock); - list_del_init(&q.pi_state->list); - spin_unlock_irq(&q.pi_state->owner->pi_lock); - } else - newtid |= FUTEX_OWNER_DIED; - - q.pi_state->owner = current; - - spin_lock_irq(¤t->pi_lock); - list_add(&q.pi_state->list, ¤t->pi_state_list); - spin_unlock_irq(¤t->pi_lock); - - /* Unqueue and drop the lock */ - unqueue_me_pi(&q, hb); - up_read(&curr->mm->mmap_sem); - /* - * We own it, so we have to replace the pending owner - * TID. This must be atomic as we have preserve the - * owner died bit here. - */ - ret = get_user(uval, uaddr); - while (!ret) { - newval = (uval & FUTEX_OWNER_DIED) | newtid; - curval = futex_atomic_cmpxchg_inatomic(uaddr, - uval, newval); - if (curval == -EFAULT) - ret = -EFAULT; - if (curval == uval) - break; - uval = curval; - } - } else { - /* - * Catch the rare case, where the lock was released - * when we were on the way back before we locked - * the hash bucket. - */ - if (ret && q.pi_state->owner == curr) { - if (rt_mutex_trylock(&q.pi_state->pi_mutex)) - ret = 0; - } - /* Unqueue and drop the lock */ - unqueue_me_pi(&q, hb); - up_read(&curr->mm->mmap_sem); - } - - if (!detect && ret == -EDEADLK && 0) - force_sig(SIGKILL, current); - - return ret; - - out_unlock_release_sem: - queue_unlock(&q, hb); - - out_release_sem: - up_read(&curr->mm->mmap_sem); - return ret; - - uaddr_faulted: - /* - * We have to r/w *(int __user *)uaddr, but we can't modify it - * non-atomically. Therefore, if get_user below is not - * enough, we need to handle the fault ourselves, while - * still holding the mmap_sem. - */ - if (attempt++) { - if (futex_handle_fault((unsigned long)uaddr, attempt)) - goto out_unlock_release_sem; - - goto retry_locked; - } - - queue_unlock(&q, hb); - up_read(&curr->mm->mmap_sem); - - ret = get_user(uval, uaddr); - if (!ret && (uval != -EFAULT)) - goto retry; - - return ret; -} - -/* - * Restart handler - */ -static long futex_lock_pi_restart(struct restart_block *restart) -{ - struct hrtimer_sleeper timeout, *to = NULL; - int ret; - - restart->fn = do_no_restart_syscall; - - if (restart->arg2 || restart->arg3) { - to = &timeout; - hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS); - hrtimer_init_sleeper(to, current); - to->timer.expires.tv64 = ((u64)restart->arg1 << 32) | - (u64) restart->arg0; - } - - pr_debug("lock_pi restart: %p, %d (%d)\n", - (u32 __user *)restart->arg0, current->pid); - - ret = do_futex_lock_pi((u32 __user *)restart->arg0, restart->arg1, - 0, to); - - if (ret != -EINTR) - return ret; - - restart->fn = futex_lock_pi_restart; - - /* The other values are filled in */ - return -ERESTART_RESTARTBLOCK; -} - -/* - * Called from the syscall entry below. - */ -static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, - long nsec, int trylock) -{ - struct hrtimer_sleeper timeout, *to = NULL; - struct restart_block *restart; - int ret; - - if (sec != MAX_SCHEDULE_TIMEOUT) { - to = &timeout; - hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS); - hrtimer_init_sleeper(to, current); - to->timer.expires = ktime_set(sec, nsec); - } - - ret = do_futex_lock_pi(uaddr, detect, trylock, to); - - if (ret != -EINTR) - return ret; - - pr_debug("lock_pi interrupted: %p, %d (%d)\n", uaddr, current->pid); - - restart = ¤t_thread_info()->restart_block; - restart->fn = futex_lock_pi_restart; - restart->arg0 = (unsigned long) uaddr; - restart->arg1 = detect; - if (to) { - restart->arg2 = to->timer.expires.tv64 & 0xFFFFFFFF; - restart->arg3 = to->timer.expires.tv64 >> 32; - } else - restart->arg2 = restart->arg3 = 0; - - return -ERESTART_RESTARTBLOCK; -} - -/* - * Userspace attempted a TID -> 0 atomic transition, and failed. - * This is the in-kernel slowpath: we look up the PI state (if any), - * and do the rt-mutex unlock. - */ -static int futex_unlock_pi(u32 __user *uaddr) -{ - struct futex_hash_bucket *hb; - struct futex_q *this, *next; - u32 uval; - struct list_head *head; - union futex_key key; - int ret, attempt = 0; - -retry: - if (get_user(uval, uaddr)) - return -EFAULT; - /* - * We release only a lock we actually own: - */ - if ((uval & FUTEX_TID_MASK) != current->pid) - return -EPERM; - /* - * First take all the futex related locks: - */ - down_read(¤t->mm->mmap_sem); - - ret = get_futex_key(uaddr, &key); - if (unlikely(ret != 0)) - goto out; - - hb = hash_futex(&key); - spin_lock(&hb->lock); - -retry_locked: - /* - * To avoid races, try to do the TID -> 0 atomic transition - * again. If it succeeds then we can return without waking - * anyone else up: - */ - inc_preempt_count(); - uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0); - dec_preempt_count(); - - if (unlikely(uval == -EFAULT)) - goto pi_faulted; - /* - * Rare case: we managed to release the lock atomically, - * no need to wake anyone else up: - */ - if (unlikely(uval == current->pid)) - goto out_unlock; - - /* - * Ok, other tasks may need to be woken up - check waiters - * and do the wakeup if necessary: - */ - head = &hb->chain; - - list_for_each_entry_safe(this, next, head, list) { - if (!match_futex (&this->key, &key)) - continue; - ret = wake_futex_pi(uaddr, uval, this); - /* - * The atomic access to the futex value - * generated a pagefault, so retry the - * user-access and the wakeup: - */ - if (ret == -EFAULT) - goto pi_faulted; - goto out_unlock; - } - /* - * No waiters - kernel unlocks the futex: - */ - ret = unlock_futex_pi(uaddr, uval); - if (ret == -EFAULT) - goto pi_faulted; - -out_unlock: - spin_unlock(&hb->lock); -out: up_read(¤t->mm->mmap_sem); - - return ret; - -pi_faulted: - /* - * We have to r/w *(int __user *)uaddr, but we can't modify it - * non-atomically. Therefore, if get_user below is not - * enough, we need to handle the fault ourselves, while - * still holding the mmap_sem. - */ - if (attempt++) { - if (futex_handle_fault((unsigned long)uaddr, attempt)) - goto out_unlock; - - goto retry_locked; - } - - spin_unlock(&hb->lock); - up_read(¤t->mm->mmap_sem); - - ret = get_user(uval, uaddr); - if (!ret && (uval != -EFAULT)) - goto retry; - return ret; } @@ -1489,7 +735,6 @@ static int futex_close(struct inode *inode, struct file *filp) unqueue_me(q); kfree(q); - return 0; } @@ -1521,7 +766,7 @@ static struct file_operations futex_fops = { * Signal allows caller to avoid the race which would occur if they * set the sigio stuff up afterwards. */ -static int futex_fd(u32 __user *uaddr, int signal) +static int futex_fd(unsigned long uaddr, int signal) { struct futex_q *q; struct file *filp; @@ -1558,7 +803,6 @@ static int futex_fd(u32 __user *uaddr, int signal) err = -ENOMEM; goto error; } - q->pi_state = NULL; down_read(¤t->mm->mmap_sem); err = get_futex_key(uaddr, &q->key); @@ -1596,7 +840,7 @@ static int futex_fd(u32 __user *uaddr, int signal) * Implementation: user-space maintains a per-thread list of locks it * is holding. Upon do_exit(), the kernel carefully walks this list, * and marks all locks that are owned by this thread with the - * FUTEX_OWNER_DIED bit, and wakes up a waiter (if any). The list is + * FUTEX_OWNER_DEAD bit, and wakes up a waiter (if any). The list is * always manipulated with the lock held, so the list is private and * per-thread. Userspace also maintains a per-thread 'list_op_pending' * field, to allow the kernel to clean up if the thread dies after @@ -1671,7 +915,7 @@ sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr, */ int handle_futex_death(u32 __user *uaddr, struct task_struct *curr) { - u32 uval, nval; + u32 uval; retry: if (get_user(uval, uaddr)) @@ -1688,16 +932,12 @@ int handle_futex_death(u32 __user *uaddr, struct task_struct *curr) * thread-death.) The rest of the cleanup is done in * userspace. */ - nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, - uval | FUTEX_OWNER_DIED); - if (nval == -EFAULT) - return -1; - - if (nval != uval) + if (futex_atomic_cmpxchg_inatomic(uaddr, uval, + uval | FUTEX_OWNER_DIED) != uval) goto retry; if (uval & FUTEX_WAITERS) - futex_wake(uaddr, 1); + futex_wake((unsigned long)uaddr, 1); } return 0; } @@ -1738,7 +978,7 @@ void exit_robust_list(struct task_struct *curr) while (entry != &head->list) { /* * A pending lock might already be on the list, so - * don't process it twice: + * dont process it twice: */ if (entry != pending) if (handle_futex_death((void *)entry + futex_offset, @@ -1759,8 +999,8 @@ void exit_robust_list(struct task_struct *curr) } } -long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout, - u32 __user *uaddr2, u32 val2, u32 val3) +long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout, + unsigned long uaddr2, int val2, int val3) { int ret; @@ -1784,15 +1024,6 @@ long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout, case FUTEX_WAKE_OP: ret = futex_wake_op(uaddr, uaddr2, val, val2, val3); break; - case FUTEX_LOCK_PI: - ret = futex_lock_pi(uaddr, val, timeout, val2, 0); - break; - case FUTEX_UNLOCK_PI: - ret = futex_unlock_pi(uaddr); - break; - case FUTEX_TRYLOCK_PI: - ret = futex_lock_pi(uaddr, 0, timeout, val2, 1); - break; default: ret = -ENOSYS; } @@ -1800,33 +1031,29 @@ long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout, } -asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val, +asmlinkage long sys_futex(u32 __user *uaddr, int op, int val, struct timespec __user *utime, u32 __user *uaddr2, - u32 val3) + int val3) { struct timespec t; unsigned long timeout = MAX_SCHEDULE_TIMEOUT; - u32 val2 = 0; + int val2 = 0; - if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) { + if (utime && (op == FUTEX_WAIT)) { if (copy_from_user(&t, utime, sizeof(t)) != 0) return -EFAULT; if (!timespec_valid(&t)) return -EINVAL; - if (op == FUTEX_WAIT) - timeout = timespec_to_jiffies(&t) + 1; - else { - timeout = t.tv_sec; - val2 = t.tv_nsec; - } + timeout = timespec_to_jiffies(&t) + 1; } /* * requeue parameter in 'utime' if op == FUTEX_REQUEUE. */ - if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE) - val2 = (u32) (unsigned long) utime; + if (op >= FUTEX_REQUEUE) + val2 = (int) (unsigned long) utime; - return do_futex(uaddr, op, val, timeout, uaddr2, val2, val3); + return do_futex((unsigned long)uaddr, op, val, timeout, + (unsigned long)uaddr2, val2, val3); } static int futexfs_get_sb(struct file_system_type *fs_type, diff --git a/trunk/kernel/futex_compat.c b/trunk/kernel/futex_compat.c index d1d92b441fb7..1ab6a0ea3d14 100644 --- a/trunk/kernel/futex_compat.c +++ b/trunk/kernel/futex_compat.c @@ -129,20 +129,16 @@ asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout = MAX_SCHEDULE_TIMEOUT; int val2 = 0; - if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) { + if (utime && (op == FUTEX_WAIT)) { if (get_compat_timespec(&t, utime)) return -EFAULT; if (!timespec_valid(&t)) return -EINVAL; - if (op == FUTEX_WAIT) - timeout = timespec_to_jiffies(&t) + 1; - else { - timeout = t.tv_sec; - val2 = t.tv_nsec; - } + timeout = timespec_to_jiffies(&t) + 1; } - if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE) + if (op >= FUTEX_REQUEUE) val2 = (int) (unsigned long) utime; - return do_futex(uaddr, op, val, timeout, uaddr2, val2, val3); + return do_futex((unsigned long)uaddr, op, val, timeout, + (unsigned long)uaddr2, val2, val3); } diff --git a/trunk/kernel/hrtimer.c b/trunk/kernel/hrtimer.c index 8d3dc29ef41a..55601b3ce60e 100644 --- a/trunk/kernel/hrtimer.c +++ b/trunk/kernel/hrtimer.c @@ -833,7 +833,7 @@ static void migrate_hrtimers(int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __devinit hrtimer_cpu_notify(struct notifier_block *self, +static int hrtimer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -857,7 +857,7 @@ static int __devinit hrtimer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __devinitdata hrtimers_nb = { +static struct notifier_block hrtimers_nb = { .notifier_call = hrtimer_cpu_notify, }; diff --git a/trunk/kernel/irq/Makefile b/trunk/kernel/irq/Makefile index 1dab0ac3f797..9f77f50d8143 100644 --- a/trunk/kernel/irq/Makefile +++ b/trunk/kernel/irq/Makefile @@ -1,5 +1,5 @@ -obj-y := handle.o manage.o spurious.o resend.o chip.o +obj-y := handle.o manage.o spurious.o obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o diff --git a/trunk/kernel/irq/autoprobe.c b/trunk/kernel/irq/autoprobe.c index 533068cfb607..3467097ca61a 100644 --- a/trunk/kernel/irq/autoprobe.c +++ b/trunk/kernel/irq/autoprobe.c @@ -11,14 +11,12 @@ #include #include -#include "internals.h" - /* * Autodetection depends on the fact that any interrupt that * comes in on to an unassigned handler will get stuck with * "IRQ_WAITING" cleared and the interrupt disabled. */ -static DEFINE_MUTEX(probing_active); +static DECLARE_MUTEX(probe_sem); /** * probe_irq_on - begin an interrupt autodetect @@ -29,11 +27,11 @@ static DEFINE_MUTEX(probing_active); */ unsigned long probe_irq_on(void) { - struct irq_desc *desc; - unsigned long mask; + unsigned long val; + irq_desc_t *desc; unsigned int i; - mutex_lock(&probing_active); + down(&probe_sem); /* * something may have generated an irq long ago and we want to * flush such a longstanding irq before considering it as spurious. @@ -42,21 +40,8 @@ unsigned long probe_irq_on(void) desc = irq_desc + i; spin_lock_irq(&desc->lock); - if (!desc->action && !(desc->status & IRQ_NOPROBE)) { - /* - * An old-style architecture might still have - * the handle_bad_irq handler there: - */ - compat_irq_chip_set_default_handler(desc); - - /* - * Some chips need to know about probing in - * progress: - */ - if (desc->chip->set_type) - desc->chip->set_type(i, IRQ_TYPE_PROBE); - desc->chip->startup(i); - } + if (!irq_desc[i].action) + irq_desc[i].handler->startup(i); spin_unlock_irq(&desc->lock); } @@ -72,9 +57,9 @@ unsigned long probe_irq_on(void) desc = irq_desc + i; spin_lock_irq(&desc->lock); - if (!desc->action && !(desc->status & IRQ_NOPROBE)) { + if (!desc->action) { desc->status |= IRQ_AUTODETECT | IRQ_WAITING; - if (desc->chip->startup(i)) + if (desc->handler->startup(i)) desc->status |= IRQ_PENDING; } spin_unlock_irq(&desc->lock); @@ -88,11 +73,11 @@ unsigned long probe_irq_on(void) /* * Now filter out any obviously spurious interrupts */ - mask = 0; + val = 0; for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; unsigned int status; - desc = irq_desc + i; spin_lock_irq(&desc->lock); status = desc->status; @@ -100,16 +85,17 @@ unsigned long probe_irq_on(void) /* It triggered already - consider it spurious. */ if (!(status & IRQ_WAITING)) { desc->status = status & ~IRQ_AUTODETECT; - desc->chip->shutdown(i); + desc->handler->shutdown(i); } else if (i < 32) - mask |= 1 << i; + val |= 1 << i; } spin_unlock_irq(&desc->lock); } - return mask; + return val; } + EXPORT_SYMBOL(probe_irq_on); /** @@ -131,7 +117,7 @@ unsigned int probe_irq_mask(unsigned long val) mask = 0; for (i = 0; i < NR_IRQS; i++) { - struct irq_desc *desc = irq_desc + i; + irq_desc_t *desc = irq_desc + i; unsigned int status; spin_lock_irq(&desc->lock); @@ -142,11 +128,11 @@ unsigned int probe_irq_mask(unsigned long val) mask |= 1 << i; desc->status = status & ~IRQ_AUTODETECT; - desc->chip->shutdown(i); + desc->handler->shutdown(i); } spin_unlock_irq(&desc->lock); } - mutex_unlock(&probing_active); + up(&probe_sem); return mask & val; } @@ -174,7 +160,7 @@ int probe_irq_off(unsigned long val) int i, irq_found = 0, nr_irqs = 0; for (i = 0; i < NR_IRQS; i++) { - struct irq_desc *desc = irq_desc + i; + irq_desc_t *desc = irq_desc + i; unsigned int status; spin_lock_irq(&desc->lock); @@ -187,16 +173,16 @@ int probe_irq_off(unsigned long val) nr_irqs++; } desc->status = status & ~IRQ_AUTODETECT; - desc->chip->shutdown(i); + desc->handler->shutdown(i); } spin_unlock_irq(&desc->lock); } - mutex_unlock(&probing_active); + up(&probe_sem); if (nr_irqs > 1) irq_found = -irq_found; - return irq_found; } + EXPORT_SYMBOL(probe_irq_off); diff --git a/trunk/kernel/irq/chip.c b/trunk/kernel/irq/chip.c deleted file mode 100644 index 9336f2e89e40..000000000000 --- a/trunk/kernel/irq/chip.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * linux/kernel/irq/chip.c - * - * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar - * Copyright (C) 2005-2006, Thomas Gleixner, Russell King - * - * This file contains the core interrupt handling code, for irq-chip - * based architectures. - * - * Detailed information is available in Documentation/DocBook/genericirq - */ - -#include -#include -#include -#include - -#include "internals.h" - -/** - * set_irq_chip - set the irq chip for an irq - * @irq: irq number - * @chip: pointer to irq chip description structure - */ -int set_irq_chip(unsigned int irq, struct irq_chip *chip) -{ - struct irq_desc *desc; - unsigned long flags; - - if (irq >= NR_IRQS) { - printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq); - WARN_ON(1); - return -EINVAL; - } - - if (!chip) - chip = &no_irq_chip; - - desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock, flags); - irq_chip_set_defaults(chip); - desc->chip = chip; - /* - * For compatibility only: - */ - desc->chip = chip; - spin_unlock_irqrestore(&desc->lock, flags); - - return 0; -} -EXPORT_SYMBOL(set_irq_chip); - -/** - * set_irq_type - set the irq type for an irq - * @irq: irq number - * @type: interrupt type - see include/linux/interrupt.h - */ -int set_irq_type(unsigned int irq, unsigned int type) -{ - struct irq_desc *desc; - unsigned long flags; - int ret = -ENXIO; - - if (irq >= NR_IRQS) { - printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq); - return -ENODEV; - } - - desc = irq_desc + irq; - if (desc->chip->set_type) { - spin_lock_irqsave(&desc->lock, flags); - ret = desc->chip->set_type(irq, type); - spin_unlock_irqrestore(&desc->lock, flags); - } - return ret; -} -EXPORT_SYMBOL(set_irq_type); - -/** - * set_irq_data - set irq type data for an irq - * @irq: Interrupt number - * @data: Pointer to interrupt specific data - * - * Set the hardware irq controller data for an irq - */ -int set_irq_data(unsigned int irq, void *data) -{ - struct irq_desc *desc; - unsigned long flags; - - if (irq >= NR_IRQS) { - printk(KERN_ERR - "Trying to install controller data for IRQ%d\n", irq); - return -EINVAL; - } - - desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock, flags); - desc->handler_data = data; - spin_unlock_irqrestore(&desc->lock, flags); - return 0; -} -EXPORT_SYMBOL(set_irq_data); - -/** - * set_irq_chip_data - set irq chip data for an irq - * @irq: Interrupt number - * @data: Pointer to chip specific data - * - * Set the hardware irq chip data for an irq - */ -int set_irq_chip_data(unsigned int irq, void *data) -{ - struct irq_desc *desc = irq_desc + irq; - unsigned long flags; - - if (irq >= NR_IRQS || !desc->chip) { - printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq); - return -EINVAL; - } - - spin_lock_irqsave(&desc->lock, flags); - desc->chip_data = data; - spin_unlock_irqrestore(&desc->lock, flags); - - return 0; -} -EXPORT_SYMBOL(set_irq_chip_data); - -/* - * default enable function - */ -static void default_enable(unsigned int irq) -{ - struct irq_desc *desc = irq_desc + irq; - - desc->chip->unmask(irq); - desc->status &= ~IRQ_MASKED; -} - -/* - * default disable function - */ -static void default_disable(unsigned int irq) -{ - struct irq_desc *desc = irq_desc + irq; - - if (!(desc->status & IRQ_DELAYED_DISABLE)) - irq_desc[irq].chip->mask(irq); -} - -/* - * default startup function - */ -static unsigned int default_startup(unsigned int irq) -{ - irq_desc[irq].chip->enable(irq); - - return 0; -} - -/* - * Fixup enable/disable function pointers - */ -void irq_chip_set_defaults(struct irq_chip *chip) -{ - if (!chip->enable) - chip->enable = default_enable; - if (!chip->disable) - chip->disable = default_disable; - if (!chip->startup) - chip->startup = default_startup; - if (!chip->shutdown) - chip->shutdown = chip->disable; - if (!chip->name) - chip->name = chip->typename; -} - -static inline void mask_ack_irq(struct irq_desc *desc, int irq) -{ - if (desc->chip->mask_ack) - desc->chip->mask_ack(irq); - else { - desc->chip->mask(irq); - desc->chip->ack(irq); - } -} - -/** - * handle_simple_irq - Simple and software-decoded IRQs. - * @irq: the interrupt number - * @desc: the interrupt description structure for this irq - * @regs: pointer to a register structure - * - * Simple interrupts are either sent from a demultiplexing interrupt - * handler or come from hardware, where no interrupt hardware control - * is necessary. - * - * Note: The caller is expected to handle the ack, clear, mask and - * unmask issues if necessary. - */ -void fastcall -handle_simple_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) -{ - struct irqaction *action; - irqreturn_t action_ret; - const unsigned int cpu = smp_processor_id(); - - spin_lock(&desc->lock); - - if (unlikely(desc->status & IRQ_INPROGRESS)) - goto out_unlock; - desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); - kstat_cpu(cpu).irqs[irq]++; - - action = desc->action; - if (unlikely(!action || (desc->status & IRQ_DISABLED))) - goto out_unlock; - - desc->status |= IRQ_INPROGRESS; - spin_unlock(&desc->lock); - - action_ret = handle_IRQ_event(irq, regs, action); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret, regs); - - spin_lock(&desc->lock); - desc->status &= ~IRQ_INPROGRESS; -out_unlock: - spin_unlock(&desc->lock); -} - -/** - * handle_level_irq - Level type irq handler - * @irq: the interrupt number - * @desc: the interrupt description structure for this irq - * @regs: pointer to a register structure - * - * Level type interrupts are active as long as the hardware line has - * the active level. This may require to mask the interrupt and unmask - * it after the associated handler has acknowledged the device, so the - * interrupt line is back to inactive. - */ -void fastcall -handle_level_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) -{ - unsigned int cpu = smp_processor_id(); - struct irqaction *action; - irqreturn_t action_ret; - - spin_lock(&desc->lock); - mask_ack_irq(desc, irq); - - if (unlikely(desc->status & IRQ_INPROGRESS)) - goto out; - desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); - kstat_cpu(cpu).irqs[irq]++; - - /* - * If its disabled or no action available - * keep it masked and get out of here - */ - action = desc->action; - if (unlikely(!action || (desc->status & IRQ_DISABLED))) { - desc->status |= IRQ_PENDING; - goto out; - } - - desc->status |= IRQ_INPROGRESS; - desc->status &= ~IRQ_PENDING; - spin_unlock(&desc->lock); - - action_ret = handle_IRQ_event(irq, regs, action); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret, regs); - - spin_lock(&desc->lock); - desc->status &= ~IRQ_INPROGRESS; -out: - if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) - desc->chip->unmask(irq); - spin_unlock(&desc->lock); -} - -/** - * handle_fasteoi_irq - irq handler for transparent controllers - * @irq: the interrupt number - * @desc: the interrupt description structure for this irq - * @regs: pointer to a register structure - * - * Only a single callback will be issued to the chip: an ->eoi() - * call when the interrupt has been serviced. This enables support - * for modern forms of interrupt handlers, which handle the flow - * details in hardware, transparently. - */ -void fastcall -handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc, - struct pt_regs *regs) -{ - unsigned int cpu = smp_processor_id(); - struct irqaction *action; - irqreturn_t action_ret; - - spin_lock(&desc->lock); - - if (unlikely(desc->status & IRQ_INPROGRESS)) - goto out; - - desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); - kstat_cpu(cpu).irqs[irq]++; - - /* - * If its disabled or no action available - * keep it masked and get out of here - */ - action = desc->action; - if (unlikely(!action || (desc->status & IRQ_DISABLED))) { - desc->status |= IRQ_PENDING; - goto out; - } - - desc->status |= IRQ_INPROGRESS; - desc->status &= ~IRQ_PENDING; - spin_unlock(&desc->lock); - - action_ret = handle_IRQ_event(irq, regs, action); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret, regs); - - spin_lock(&desc->lock); - desc->status &= ~IRQ_INPROGRESS; -out: - desc->chip->eoi(irq); - - spin_unlock(&desc->lock); -} - -/** - * handle_edge_irq - edge type IRQ handler - * @irq: the interrupt number - * @desc: the interrupt description structure for this irq - * @regs: pointer to a register structure - * - * Interrupt occures on the falling and/or rising edge of a hardware - * signal. The occurence is latched into the irq controller hardware - * and must be acked in order to be reenabled. After the ack another - * interrupt can happen on the same source even before the first one - * is handled by the assosiacted event handler. If this happens it - * might be necessary to disable (mask) the interrupt depending on the - * controller hardware. This requires to reenable the interrupt inside - * of the loop which handles the interrupts which have arrived while - * the handler was running. If all pending interrupts are handled, the - * loop is left. - */ -void fastcall -handle_edge_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) -{ - const unsigned int cpu = smp_processor_id(); - - spin_lock(&desc->lock); - - desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); - - /* - * If we're currently running this IRQ, or its disabled, - * we shouldn't process the IRQ. Mark it pending, handle - * the necessary masking and go out - */ - if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || - !desc->action)) { - desc->status |= (IRQ_PENDING | IRQ_MASKED); - mask_ack_irq(desc, irq); - goto out_unlock; - } - - kstat_cpu(cpu).irqs[irq]++; - - /* Start handling the irq */ - desc->chip->ack(irq); - - /* Mark the IRQ currently in progress.*/ - desc->status |= IRQ_INPROGRESS; - - do { - struct irqaction *action = desc->action; - irqreturn_t action_ret; - - if (unlikely(!action)) { - desc->chip->mask(irq); - goto out_unlock; - } - - /* - * When another irq arrived while we were handling - * one, we could have masked the irq. - * Renable it, if it was not disabled in meantime. - */ - if (unlikely((desc->status & - (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) == - (IRQ_PENDING | IRQ_MASKED))) { - desc->chip->unmask(irq); - desc->status &= ~IRQ_MASKED; - } - - desc->status &= ~IRQ_PENDING; - spin_unlock(&desc->lock); - action_ret = handle_IRQ_event(irq, regs, action); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret, regs); - spin_lock(&desc->lock); - - } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); - - desc->status &= ~IRQ_INPROGRESS; -out_unlock: - spin_unlock(&desc->lock); -} - -#ifdef CONFIG_SMP -/** - * handle_percpu_IRQ - Per CPU local irq handler - * @irq: the interrupt number - * @desc: the interrupt description structure for this irq - * @regs: pointer to a register structure - * - * Per CPU interrupts on SMP machines without locking requirements - */ -void fastcall -handle_percpu_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) -{ - irqreturn_t action_ret; - - kstat_this_cpu.irqs[irq]++; - - if (desc->chip->ack) - desc->chip->ack(irq); - - action_ret = handle_IRQ_event(irq, regs, desc->action); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret, regs); - - if (desc->chip->eoi) - desc->chip->eoi(irq); -} - -#endif /* CONFIG_SMP */ - -void -__set_irq_handler(unsigned int irq, - void fastcall (*handle)(unsigned int, irq_desc_t *, - struct pt_regs *), - int is_chained) -{ - struct irq_desc *desc; - unsigned long flags; - - if (irq >= NR_IRQS) { - printk(KERN_ERR - "Trying to install type control for IRQ%d\n", irq); - return; - } - - desc = irq_desc + irq; - - if (!handle) - handle = handle_bad_irq; - - if (desc->chip == &no_irq_chip) { - printk(KERN_WARNING "Trying to install %sinterrupt handler " - "for IRQ%d\n", is_chained ? "chained " : " ", irq); - /* - * Some ARM implementations install a handler for really dumb - * interrupt hardware without setting an irq_chip. This worked - * with the ARM no_irq_chip but the check in setup_irq would - * prevent us to setup the interrupt at all. Switch it to - * dummy_irq_chip for easy transition. - */ - desc->chip = &dummy_irq_chip; - } - - spin_lock_irqsave(&desc->lock, flags); - - /* Uninstall? */ - if (handle == handle_bad_irq) { - if (desc->chip != &no_irq_chip) { - desc->chip->mask(irq); - desc->chip->ack(irq); - } - desc->status |= IRQ_DISABLED; - desc->depth = 1; - } - desc->handle_irq = handle; - - if (handle != handle_bad_irq && is_chained) { - desc->status &= ~IRQ_DISABLED; - desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE; - desc->depth = 0; - desc->chip->unmask(irq); - } - spin_unlock_irqrestore(&desc->lock, flags); -} - -void -set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, - void fastcall (*handle)(unsigned int, - struct irq_desc *, - struct pt_regs *)) -{ - set_irq_chip(irq, chip); - __set_irq_handler(irq, handle, 0); -} - -/* - * Get a descriptive string for the highlevel handler, for - * /proc/interrupts output: - */ -const char * -handle_irq_name(void fastcall (*handle)(unsigned int, struct irq_desc *, - struct pt_regs *)) -{ - if (handle == handle_level_irq) - return "level "; - if (handle == handle_fasteoi_irq) - return "fasteoi"; - if (handle == handle_edge_irq) - return "edge "; - if (handle == handle_simple_irq) - return "simple "; -#ifdef CONFIG_SMP - if (handle == handle_percpu_irq) - return "percpu "; -#endif - if (handle == handle_bad_irq) - return "bad "; - - return NULL; -} diff --git a/trunk/kernel/irq/handle.c b/trunk/kernel/irq/handle.c index 6d8b30114961..0f6530117105 100644 --- a/trunk/kernel/irq/handle.c +++ b/trunk/kernel/irq/handle.c @@ -1,13 +1,9 @@ /* * linux/kernel/irq/handle.c * - * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar - * Copyright (C) 2005-2006, Thomas Gleixner, Russell King + * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar * * This file contains the core interrupt handling code. - * - * Detailed information is available in Documentation/DocBook/genericirq - * */ #include @@ -16,28 +12,13 @@ #include #include -#if defined(CONFIG_NO_IDLE_HZ) && defined(CONFIG_ARM) -#include -#endif - #include "internals.h" -/** - * handle_bad_irq - handle spurious and unhandled irqs - */ -void fastcall -handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) -{ - print_irq_desc(irq, desc); - kstat_this_cpu.irqs[irq]++; - ack_bad_irq(irq); -} - /* * Linux has a controller-independent interrupt architecture. * Every controller has a 'controller-template', that is used * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the appropriate + * interrupt source is transparently wired to the apropriate * controller. Thus drivers need not be aware of the * interrupt-controller. * @@ -47,68 +28,41 @@ handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) * * Controller mappings for all interrupt sources: */ -struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned = { +irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = { .status = IRQ_DISABLED, - .chip = &no_irq_chip, - .handle_irq = handle_bad_irq, - .depth = 1, - .lock = SPIN_LOCK_UNLOCKED, -#ifdef CONFIG_SMP - .affinity = CPU_MASK_ALL -#endif + .handler = &no_irq_type, + .lock = SPIN_LOCK_UNLOCKED } }; /* - * What should we do if we get a hw irq event on an illegal vector? - * Each architecture has to answer this themself. + * Generic 'no controller' code */ -static void ack_bad(unsigned int irq) -{ - print_irq_desc(irq, irq_desc + irq); - ack_bad_irq(irq); -} - -/* - * NOP functions - */ -static void noop(unsigned int irq) -{ -} +static void end_none(unsigned int irq) { } +static void enable_none(unsigned int irq) { } +static void disable_none(unsigned int irq) { } +static void shutdown_none(unsigned int irq) { } +static unsigned int startup_none(unsigned int irq) { return 0; } -static unsigned int noop_ret(unsigned int irq) +static void ack_none(unsigned int irq) { - return 0; + /* + * 'what should we do if we get a hw irq event on an illegal vector'. + * each architecture has to answer this themself. + */ + ack_bad_irq(irq); } -/* - * Generic no controller implementation - */ -struct irq_chip no_irq_chip = { - .name = "none", - .startup = noop_ret, - .shutdown = noop, - .enable = noop, - .disable = noop, - .ack = ack_bad, - .end = noop, -}; - -/* - * Generic dummy implementation which can be used for - * real dumb interrupt sources - */ -struct irq_chip dummy_irq_chip = { - .name = "dummy", - .startup = noop_ret, - .shutdown = noop, - .enable = noop, - .disable = noop, - .ack = noop, - .mask = noop, - .unmask = noop, - .end = noop, +struct hw_interrupt_type no_irq_type = { + .typename = "none", + .startup = startup_none, + .shutdown = shutdown_none, + .enable = enable_none, + .disable = disable_none, + .ack = ack_none, + .end = end_none, + .set_affinity = NULL }; /* @@ -119,30 +73,16 @@ irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) return IRQ_NONE; } -/** - * handle_IRQ_event - irq action chain handler - * @irq: the interrupt number - * @regs: pointer to a register structure - * @action: the interrupt action chain for this irq - * - * Handles the action chain of an irq event +/* + * Have got an event to handle: */ -irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs, - struct irqaction *action) +fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs, + struct irqaction *action) { irqreturn_t ret, retval = IRQ_NONE; unsigned int status = 0; -#if defined(CONFIG_NO_IDLE_HZ) && defined(CONFIG_ARM) - if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) { - write_seqlock(&xtime_lock); - if (system_timer->dyn_tick->state & DYN_TICK_ENABLED) - system_timer->dyn_tick->handler(irq, 0, regs); - write_sequnlock(&xtime_lock); - } -#endif - - if (!(action->flags & IRQF_DISABLED)) + if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { @@ -153,29 +93,22 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs, action = action->next; } while (action); - if (status & IRQF_SAMPLE_RANDOM) + if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); return retval; } -/** - * __do_IRQ - original all in one highlevel IRQ handler - * @irq: the interrupt number - * @regs: pointer to a register structure - * - * __do_IRQ handles all normal device IRQ's (the special +/* + * do_IRQ handles all normal device IRQ's (the special * SMP cross-CPU interrupts have their own specific * handlers). - * - * This is the original x86 implementation which is used for every - * interrupt type. */ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs) { - struct irq_desc *desc = irq_desc + irq; - struct irqaction *action; + irq_desc_t *desc = irq_desc + irq; + struct irqaction * action; unsigned int status; kstat_this_cpu.irqs[irq]++; @@ -185,16 +118,16 @@ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs) /* * No locking required for CPU-local interrupts: */ - if (desc->chip->ack) - desc->chip->ack(irq); + if (desc->handler->ack) + desc->handler->ack(irq); action_ret = handle_IRQ_event(irq, regs, desc->action); - desc->chip->end(irq); + desc->handler->end(irq); return 1; } spin_lock(&desc->lock); - if (desc->chip->ack) - desc->chip->ack(irq); + if (desc->handler->ack) + desc->handler->ack(irq); /* * REPLAY is when Linux resends an IRQ that was dropped earlier * WAITING is used by probe to mark irqs that are being tested @@ -254,7 +187,7 @@ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs) * The ->end() handler has to deal with interrupts which got * disabled while the handler was running. */ - desc->chip->end(irq); + desc->handler->end(irq); spin_unlock(&desc->lock); return 1; diff --git a/trunk/kernel/irq/internals.h b/trunk/kernel/irq/internals.h index 08a849a22447..46feba630266 100644 --- a/trunk/kernel/irq/internals.h +++ b/trunk/kernel/irq/internals.h @@ -4,12 +4,6 @@ extern int noirqdebug; -/* Set default functions for irq_chip structures: */ -extern void irq_chip_set_defaults(struct irq_chip *chip); - -/* Set default handler: */ -extern void compat_irq_chip_set_default_handler(struct irq_desc *desc); - #ifdef CONFIG_PROC_FS extern void register_irq_proc(unsigned int irq); extern void register_handler_proc(unsigned int irq, struct irqaction *action); @@ -22,43 +16,3 @@ static inline void unregister_handler_proc(unsigned int irq, struct irqaction *action) { } #endif -/* - * Debugging printout: - */ - -#include - -#define P(f) if (desc->status & f) printk("%14s set\n", #f) - -static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc) -{ - printk("irq %d, desc: %p, depth: %d, count: %d, unhandled: %d\n", - irq, desc, desc->depth, desc->irq_count, desc->irqs_unhandled); - printk("->handle_irq(): %p, ", desc->handle_irq); - print_symbol("%s\n", (unsigned long)desc->handle_irq); - printk("->chip(): %p, ", desc->chip); - print_symbol("%s\n", (unsigned long)desc->chip); - printk("->action(): %p\n", desc->action); - if (desc->action) { - printk("->action->handler(): %p, ", desc->action->handler); - print_symbol("%s\n", (unsigned long)desc->action->handler); - } - - P(IRQ_INPROGRESS); - P(IRQ_DISABLED); - P(IRQ_PENDING); - P(IRQ_REPLAY); - P(IRQ_AUTODETECT); - P(IRQ_WAITING); - P(IRQ_LEVEL); - P(IRQ_MASKED); -#ifdef CONFIG_IRQ_PER_CPU - P(IRQ_PER_CPU); -#endif - P(IRQ_NOPROBE); - P(IRQ_NOREQUEST); - P(IRQ_NOAUTOEN); -} - -#undef P - diff --git a/trunk/kernel/irq/manage.c b/trunk/kernel/irq/manage.c index fede5fa351df..1279e3499534 100644 --- a/trunk/kernel/irq/manage.c +++ b/trunk/kernel/irq/manage.c @@ -1,12 +1,12 @@ /* * linux/kernel/irq/manage.c * - * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar - * Copyright (C) 2005-2006 Thomas Gleixner + * Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar * * This file contains driver APIs to the irq subsystem. */ +#include #include #include #include @@ -16,6 +16,12 @@ #ifdef CONFIG_SMP +cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL }; + +#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE) +cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; +#endif + /** * synchronize_irq - wait for pending IRQ handlers (on other CPUs) * @irq: interrupt number to wait for @@ -36,6 +42,7 @@ void synchronize_irq(unsigned int irq) while (desc->status & IRQ_INPROGRESS) cpu_relax(); } + EXPORT_SYMBOL(synchronize_irq); #endif @@ -53,7 +60,7 @@ EXPORT_SYMBOL(synchronize_irq); */ void disable_irq_nosync(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; + irq_desc_t *desc = irq_desc + irq; unsigned long flags; if (irq >= NR_IRQS) @@ -62,10 +69,11 @@ void disable_irq_nosync(unsigned int irq) spin_lock_irqsave(&desc->lock, flags); if (!desc->depth++) { desc->status |= IRQ_DISABLED; - desc->chip->disable(irq); + desc->handler->disable(irq); } spin_unlock_irqrestore(&desc->lock, flags); } + EXPORT_SYMBOL(disable_irq_nosync); /** @@ -82,7 +90,7 @@ EXPORT_SYMBOL(disable_irq_nosync); */ void disable_irq(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; + irq_desc_t *desc = irq_desc + irq; if (irq >= NR_IRQS) return; @@ -91,6 +99,7 @@ void disable_irq(unsigned int irq) if (desc->action) synchronize_irq(irq); } + EXPORT_SYMBOL(disable_irq); /** @@ -105,7 +114,7 @@ EXPORT_SYMBOL(disable_irq); */ void enable_irq(unsigned int irq) { - struct irq_desc *desc = irq_desc + irq; + irq_desc_t *desc = irq_desc + irq; unsigned long flags; if (irq >= NR_IRQS) @@ -114,15 +123,17 @@ void enable_irq(unsigned int irq) spin_lock_irqsave(&desc->lock, flags); switch (desc->depth) { case 0: - printk(KERN_WARNING "Unbalanced enable for IRQ %d\n", irq); WARN_ON(1); break; case 1: { unsigned int status = desc->status & ~IRQ_DISABLED; - /* Prevent probing on this irq: */ - desc->status = status | IRQ_NOPROBE; - check_irq_resend(desc, irq); + desc->status = status; + if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { + desc->status = status | IRQ_REPLAY; + hw_resend_irq(desc->handler,irq); + } + desc->handler->enable(irq); /* fall-through */ } default: @@ -130,28 +141,8 @@ void enable_irq(unsigned int irq) } spin_unlock_irqrestore(&desc->lock, flags); } -EXPORT_SYMBOL(enable_irq); -/** - * set_irq_wake - control irq power management wakeup - * @irq: interrupt to control - * @on: enable/disable power management wakeup - * - * Enable/disable power management wakeup mode - */ -int set_irq_wake(unsigned int irq, unsigned int on) -{ - struct irq_desc *desc = irq_desc + irq; - unsigned long flags; - int ret = -ENXIO; - - spin_lock_irqsave(&desc->lock, flags); - if (desc->chip->set_wake) - ret = desc->chip->set_wake(irq, on); - spin_unlock_irqrestore(&desc->lock, flags); - return ret; -} -EXPORT_SYMBOL(set_irq_wake); +EXPORT_SYMBOL(enable_irq); /* * Internal function that tells the architecture code whether a @@ -162,33 +153,22 @@ int can_request_irq(unsigned int irq, unsigned long irqflags) { struct irqaction *action; - if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST) + if (irq >= NR_IRQS) return 0; action = irq_desc[irq].action; if (action) - if (irqflags & action->flags & IRQF_SHARED) + if (irqflags & action->flags & SA_SHIRQ) action = NULL; return !action; } -void compat_irq_chip_set_default_handler(struct irq_desc *desc) -{ - /* - * If the architecture still has not overriden - * the flow handler then zap the default. This - * should catch incorrect flow-type setting. - */ - if (desc->handle_irq == &handle_bad_irq) - desc->handle_irq = NULL; -} - /* * Internal function to register an irqaction - typically used to * allocate special interrupts that are part of the architecture. */ -int setup_irq(unsigned int irq, struct irqaction *new) +int setup_irq(unsigned int irq, struct irqaction * new) { struct irq_desc *desc = irq_desc + irq; struct irqaction *old, **p; @@ -198,14 +178,14 @@ int setup_irq(unsigned int irq, struct irqaction *new) if (irq >= NR_IRQS) return -EINVAL; - if (desc->chip == &no_irq_chip) + if (desc->handler == &no_irq_type) return -ENOSYS; /* * Some drivers like serial.c use request_irq() heavily, * so we have to be careful not to interfere with a * running system. */ - if (new->flags & IRQF_SAMPLE_RANDOM) { + if (new->flags & SA_SAMPLE_RANDOM) { /* * This function might sleep, we want to call it first, * outside of the atomic block. @@ -220,24 +200,16 @@ int setup_irq(unsigned int irq, struct irqaction *new) /* * The following block of code has to be executed atomically */ - spin_lock_irqsave(&desc->lock, flags); + spin_lock_irqsave(&desc->lock,flags); p = &desc->action; - old = *p; - if (old) { - /* - * Can't share interrupts unless both agree to and are - * the same type (level, edge, polarity). So both flag - * fields must have IRQF_SHARED set and the bits which - * set the trigger type must match. - */ - if (!((old->flags & new->flags) & IRQF_SHARED) || - ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) goto mismatch; -#if defined(CONFIG_IRQ_PER_CPU) && defined(IRQF_PERCPU) +#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) /* All handlers must agree on per-cpuness */ - if ((old->flags & IRQF_PERCPU) != - (new->flags & IRQF_PERCPU)) + if ((old->flags & IRQ_PER_CPU) != (new->flags & IRQ_PER_CPU)) goto mismatch; #endif @@ -250,45 +222,20 @@ int setup_irq(unsigned int irq, struct irqaction *new) } *p = new; -#if defined(CONFIG_IRQ_PER_CPU) && defined(IRQF_PERCPU) - if (new->flags & IRQF_PERCPU) +#if defined(ARCH_HAS_IRQ_PER_CPU) && defined(SA_PERCPU_IRQ) + if (new->flags & SA_PERCPU_IRQ) desc->status |= IRQ_PER_CPU; #endif if (!shared) { - irq_chip_set_defaults(desc->chip); - - /* Setup the type (level, edge polarity) if configured: */ - if (new->flags & IRQF_TRIGGER_MASK) { - if (desc->chip && desc->chip->set_type) - desc->chip->set_type(irq, - new->flags & IRQF_TRIGGER_MASK); - else - /* - * IRQF_TRIGGER_* but the PIC does not support - * multiple flow-types? - */ - printk(KERN_WARNING "No IRQF_TRIGGER set_type " - "function for IRQ %d (%s)\n", irq, - desc->chip ? desc->chip->name : - "unknown"); - } else - compat_irq_chip_set_default_handler(desc); - - desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | - IRQ_INPROGRESS); - - if (!(desc->status & IRQ_NOAUTOEN)) { - desc->depth = 0; - desc->status &= ~IRQ_DISABLED; - if (desc->chip->startup) - desc->chip->startup(irq); - else - desc->chip->enable(irq); - } else - /* Undo nested disables: */ - desc->depth = 1; + desc->depth = 0; + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | + IRQ_WAITING | IRQ_INPROGRESS); + if (desc->handler->startup) + desc->handler->startup(irq); + else + desc->handler->enable(irq); } - spin_unlock_irqrestore(&desc->lock, flags); + spin_unlock_irqrestore(&desc->lock,flags); new->irq = irq; register_irq_proc(irq); @@ -299,8 +246,8 @@ int setup_irq(unsigned int irq, struct irqaction *new) mismatch: spin_unlock_irqrestore(&desc->lock, flags); - if (!(new->flags & IRQF_PROBE_SHARED)) { - printk(KERN_ERR "IRQ handler type mismatch for IRQ %d\n", irq); + if (!(new->flags & SA_PROBEIRQ)) { + printk(KERN_ERR "%s: irq handler mismatch\n", __FUNCTION__); dump_stack(); } return -EBUSY; @@ -331,10 +278,10 @@ void free_irq(unsigned int irq, void *dev_id) return; desc = irq_desc + irq; - spin_lock_irqsave(&desc->lock, flags); + spin_lock_irqsave(&desc->lock,flags); p = &desc->action; for (;;) { - struct irqaction *action = *p; + struct irqaction * action = *p; if (action) { struct irqaction **pp = p; @@ -348,18 +295,18 @@ void free_irq(unsigned int irq, void *dev_id) /* Currently used only by UML, might disappear one day.*/ #ifdef CONFIG_IRQ_RELEASE_METHOD - if (desc->chip->release) - desc->chip->release(irq, dev_id); + if (desc->handler->release) + desc->handler->release(irq, dev_id); #endif if (!desc->action) { desc->status |= IRQ_DISABLED; - if (desc->chip->shutdown) - desc->chip->shutdown(irq); + if (desc->handler->shutdown) + desc->handler->shutdown(irq); else - desc->chip->disable(irq); + desc->handler->disable(irq); } - spin_unlock_irqrestore(&desc->lock, flags); + spin_unlock_irqrestore(&desc->lock,flags); unregister_handler_proc(irq, action); /* Make sure it's not being used on another CPU */ @@ -367,11 +314,12 @@ void free_irq(unsigned int irq, void *dev_id) kfree(action); return; } - printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq); - spin_unlock_irqrestore(&desc->lock, flags); + printk(KERN_ERR "Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); return; } } + EXPORT_SYMBOL(free_irq); /** @@ -398,16 +346,16 @@ EXPORT_SYMBOL(free_irq); * * Flags: * - * IRQF_SHARED Interrupt is shared - * IRQF_DISABLED Disable local interrupts while processing - * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy + * SA_SHIRQ Interrupt is shared + * SA_INTERRUPT Disable local interrupts while processing + * SA_SAMPLE_RANDOM The interrupt can be used for entropy * */ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char *devname, void *dev_id) + unsigned long irqflags, const char * devname, void *dev_id) { - struct irqaction *action; + struct irqaction * action; int retval; /* @@ -416,12 +364,10 @@ int request_irq(unsigned int irq, * which interrupt is which (messes up the interrupt freeing * logic etc). */ - if ((irqflags & IRQF_SHARED) && !dev_id) + if ((irqflags & SA_SHIRQ) && !dev_id) return -EINVAL; if (irq >= NR_IRQS) return -EINVAL; - if (irq_desc[irq].status & IRQ_NOREQUEST) - return -EINVAL; if (!handler) return -EINVAL; @@ -444,5 +390,6 @@ int request_irq(unsigned int irq, return retval; } + EXPORT_SYMBOL(request_irq); diff --git a/trunk/kernel/irq/migration.c b/trunk/kernel/irq/migration.c index a57ebe9fa6f6..a12d00eb5e7c 100644 --- a/trunk/kernel/irq/migration.c +++ b/trunk/kernel/irq/migration.c @@ -3,19 +3,19 @@ void set_pending_irq(unsigned int irq, cpumask_t mask) { - struct irq_desc *desc = irq_desc + irq; + irq_desc_t *desc = irq_desc + irq; unsigned long flags; spin_lock_irqsave(&desc->lock, flags); desc->move_irq = 1; - irq_desc[irq].pending_mask = mask; + pending_irq_cpumask[irq] = mask; spin_unlock_irqrestore(&desc->lock, flags); } void move_native_irq(int irq) { - struct irq_desc *desc = irq_desc + irq; cpumask_t tmp; + irq_desc_t *desc = irq_descp(irq); if (likely(!desc->move_irq)) return; @@ -30,15 +30,15 @@ void move_native_irq(int irq) desc->move_irq = 0; - if (unlikely(cpus_empty(irq_desc[irq].pending_mask))) + if (unlikely(cpus_empty(pending_irq_cpumask[irq]))) return; - if (!desc->chip->set_affinity) + if (!desc->handler->set_affinity) return; assert_spin_locked(&desc->lock); - cpus_and(tmp, irq_desc[irq].pending_mask, cpu_online_map); + cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map); /* * If there was a valid mask to work with, please @@ -51,12 +51,12 @@ void move_native_irq(int irq) */ if (likely(!cpus_empty(tmp))) { if (likely(!(desc->status & IRQ_DISABLED))) - desc->chip->disable(irq); + desc->handler->disable(irq); - desc->chip->set_affinity(irq,tmp); + desc->handler->set_affinity(irq,tmp); if (likely(!(desc->status & IRQ_DISABLED))) - desc->chip->enable(irq); + desc->handler->enable(irq); } - cpus_clear(irq_desc[irq].pending_mask); + cpus_clear(pending_irq_cpumask[irq]); } diff --git a/trunk/kernel/irq/proc.c b/trunk/kernel/irq/proc.c index 607c7809ad01..afacd6f585fa 100644 --- a/trunk/kernel/irq/proc.c +++ b/trunk/kernel/irq/proc.c @@ -12,10 +12,15 @@ #include "internals.h" -static struct proc_dir_entry *root_irq_dir; +static struct proc_dir_entry *root_irq_dir, *irq_dir[NR_IRQS]; #ifdef CONFIG_SMP +/* + * The /proc/irq//smp_affinity values: + */ +static struct proc_dir_entry *smp_affinity_entry[NR_IRQS]; + #ifdef CONFIG_GENERIC_PENDING_IRQ void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val) { @@ -31,15 +36,15 @@ void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val) void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val) { set_balance_irq_affinity(irq, mask_val); - irq_desc[irq].affinity = mask_val; - irq_desc[irq].chip->set_affinity(irq, mask_val); + irq_affinity[irq] = mask_val; + irq_desc[irq].handler->set_affinity(irq, mask_val); } #endif static int irq_affinity_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_scnprintf(page, count, irq_desc[(long)data].affinity); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; @@ -54,7 +59,7 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer, unsigned int irq = (int)(long)data, full_count = count, err; cpumask_t new_value, tmp; - if (!irq_desc[irq].chip->set_affinity || no_irq_affinity) + if (!irq_desc[irq].handler->set_affinity || no_irq_affinity) return -EIO; err = cpumask_parse(buffer, count, new_value); @@ -97,7 +102,7 @@ void register_handler_proc(unsigned int irq, struct irqaction *action) { char name [MAX_NAMELEN]; - if (!irq_desc[irq].dir || action->dir || !action->name || + if (!irq_dir[irq] || action->dir || !action->name || !name_unique(irq, action)) return; @@ -105,7 +110,7 @@ void register_handler_proc(unsigned int irq, struct irqaction *action) snprintf(name, MAX_NAMELEN, "%s", action->name); /* create /proc/irq/1234/handler/ */ - action->dir = proc_mkdir(name, irq_desc[irq].dir); + action->dir = proc_mkdir(name, irq_dir[irq]); } #undef MAX_NAMELEN @@ -117,22 +122,22 @@ void register_irq_proc(unsigned int irq) char name [MAX_NAMELEN]; if (!root_irq_dir || - (irq_desc[irq].chip == &no_irq_chip) || - irq_desc[irq].dir) + (irq_desc[irq].handler == &no_irq_type) || + irq_dir[irq]) return; memset(name, 0, MAX_NAMELEN); sprintf(name, "%d", irq); /* create /proc/irq/1234 */ - irq_desc[irq].dir = proc_mkdir(name, root_irq_dir); + irq_dir[irq] = proc_mkdir(name, root_irq_dir); #ifdef CONFIG_SMP { struct proc_dir_entry *entry; /* create /proc/irq//smp_affinity */ - entry = create_proc_entry("smp_affinity", 0600, irq_desc[irq].dir); + entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); if (entry) { entry->nlink = 1; @@ -140,6 +145,7 @@ void register_irq_proc(unsigned int irq) entry->read_proc = irq_affinity_read_proc; entry->write_proc = irq_affinity_write_proc; } + smp_affinity_entry[irq] = entry; } #endif } @@ -149,7 +155,7 @@ void register_irq_proc(unsigned int irq) void unregister_handler_proc(unsigned int irq, struct irqaction *action) { if (action->dir) - remove_proc_entry(action->dir->name, irq_desc[irq].dir); + remove_proc_entry(action->dir->name, irq_dir[irq]); } void init_irq_proc(void) diff --git a/trunk/kernel/irq/resend.c b/trunk/kernel/irq/resend.c deleted file mode 100644 index 872f91ba2ce8..000000000000 --- a/trunk/kernel/irq/resend.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * linux/kernel/irq/resend.c - * - * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar - * Copyright (C) 2005-2006, Thomas Gleixner - * - * This file contains the IRQ-resend code - * - * If the interrupt is waiting to be processed, we try to re-run it. - * We can't directly run it from here since the caller might be in an - * interrupt-protected region. Not all irq controller chips can - * retrigger interrupts at the hardware level, so in those cases - * we allow the resending of IRQs via a tasklet. - */ - -#include -#include -#include -#include - -#include "internals.h" - -#ifdef CONFIG_HARDIRQS_SW_RESEND - -/* Bitmap to handle software resend of interrupts: */ -static DECLARE_BITMAP(irqs_resend, NR_IRQS); - -/* - * Run software resends of IRQ's - */ -static void resend_irqs(unsigned long arg) -{ - struct irq_desc *desc; - int irq; - - while (!bitmap_empty(irqs_resend, NR_IRQS)) { - irq = find_first_bit(irqs_resend, NR_IRQS); - clear_bit(irq, irqs_resend); - desc = irq_desc + irq; - local_irq_disable(); - desc->handle_irq(irq, desc, NULL); - local_irq_enable(); - } -} - -/* Tasklet to handle resend: */ -static DECLARE_TASKLET(resend_tasklet, resend_irqs, 0); - -#endif - -/* - * IRQ resend - * - * Is called with interrupts disabled and desc->lock held. - */ -void check_irq_resend(struct irq_desc *desc, unsigned int irq) -{ - unsigned int status = desc->status; - - /* - * Make sure the interrupt is enabled, before resending it: - */ - desc->chip->enable(irq); - - if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - desc->status &= ~IRQ_PENDING; - desc->status = status | IRQ_REPLAY; - - if (!desc->chip || !desc->chip->retrigger || - !desc->chip->retrigger(irq)) { -#ifdef CONFIG_HARDIRQS_SW_RESEND - /* Set it pending and activate the softirq: */ - set_bit(irq, irqs_resend); - tasklet_schedule(&resend_tasklet); -#endif - } - } -} diff --git a/trunk/kernel/irq/spurious.c b/trunk/kernel/irq/spurious.c index 417e98092cf2..b2fb3c18d06b 100644 --- a/trunk/kernel/irq/spurious.c +++ b/trunk/kernel/irq/spurious.c @@ -16,39 +16,39 @@ static int irqfixup __read_mostly; /* * Recovery handler for misrouted interrupts. */ + static int misrouted_irq(int irq, struct pt_regs *regs) { int i; + irq_desc_t *desc; int ok = 0; int work = 0; /* Did we do work for a real IRQ */ - for (i = 1; i < NR_IRQS; i++) { - struct irq_desc *desc = irq_desc + i; + for(i = 1; i < NR_IRQS; i++) { struct irqaction *action; if (i == irq) /* Already tried */ continue; - + desc = &irq_desc[i]; spin_lock(&desc->lock); + action = desc->action; /* Already running on another processor */ if (desc->status & IRQ_INPROGRESS) { /* * Already running: If it is shared get the other * CPU to go looking for our mystery interrupt too */ - if (desc->action && (desc->action->flags & IRQF_SHARED)) + if (desc->action && (desc->action->flags & SA_SHIRQ)) desc->status |= IRQ_PENDING; spin_unlock(&desc->lock); continue; } /* Honour the normal IRQ locking */ desc->status |= IRQ_INPROGRESS; - action = desc->action; spin_unlock(&desc->lock); - while (action) { /* Only shared IRQ handlers are safe to call */ - if (action->flags & IRQF_SHARED) { + if (action->flags & SA_SHIRQ) { if (action->handler(i, action->dev_id, regs) == IRQ_HANDLED) ok = 1; @@ -62,8 +62,9 @@ static int misrouted_irq(int irq, struct pt_regs *regs) /* * While we were looking for a fixup someone queued a real - * IRQ clashing with our walk: + * IRQ clashing with our walk */ + while ((desc->status & IRQ_PENDING) && action) { /* * Perform real IRQ processing for the IRQ we deferred @@ -79,8 +80,8 @@ static int misrouted_irq(int irq, struct pt_regs *regs) * If we did actual work for the real IRQ line we must let the * IRQ controller clean up too */ - if (work && desc->chip && desc->chip->end) - desc->chip->end(i); + if(work) + desc->handler->end(i); spin_unlock(&desc->lock); } /* So the caller can adjust the irq error counts */ @@ -99,8 +100,7 @@ static int misrouted_irq(int irq, struct pt_regs *regs) */ static void -__report_bad_irq(unsigned int irq, struct irq_desc *desc, - irqreturn_t action_ret) +__report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret) { struct irqaction *action; @@ -113,7 +113,6 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, } dump_stack(); printk(KERN_ERR "handlers:\n"); - action = desc->action; while (action) { printk(KERN_ERR "[<%p>]", action->handler); @@ -124,8 +123,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, } } -static void -report_bad_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret) +static void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret) { static int count = 100; @@ -135,8 +133,8 @@ report_bad_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret) } } -void note_interrupt(unsigned int irq, struct irq_desc *desc, - irqreturn_t action_ret, struct pt_regs *regs) +void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret, + struct pt_regs *regs) { if (unlikely(action_ret != IRQ_HANDLED)) { desc->irqs_unhandled++; @@ -168,8 +166,7 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, */ printk(KERN_EMERG "Disabling IRQ #%d\n", irq); desc->status |= IRQ_DISABLED; - desc->depth = 1; - desc->chip->disable(irq); + desc->handler->disable(irq); } desc->irqs_unhandled = 0; } @@ -180,7 +177,6 @@ int __init noirqdebug_setup(char *str) { noirqdebug = 1; printk(KERN_INFO "IRQ lockup detection disabled\n"); - return 1; } @@ -191,7 +187,6 @@ static int __init irqfixup_setup(char *str) irqfixup = 1; printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n"); printk(KERN_WARNING "This may impact system performance.\n"); - return 1; } diff --git a/trunk/kernel/kexec.c b/trunk/kernel/kexec.c index 50087ecf337e..58f0f382597c 100644 --- a/trunk/kernel/kexec.c +++ b/trunk/kernel/kexec.c @@ -1042,6 +1042,7 @@ asmlinkage long compat_sys_kexec_load(unsigned long entry, void crash_kexec(struct pt_regs *regs) { + struct kimage *image; int locked; @@ -1055,11 +1056,12 @@ void crash_kexec(struct pt_regs *regs) */ locked = xchg(&kexec_lock, 1); if (!locked) { - if (kexec_crash_image) { + image = xchg(&kexec_crash_image, NULL); + if (image) { struct pt_regs fixed_regs; crash_setup_regs(&fixed_regs, regs); machine_crash_shutdown(&fixed_regs); - machine_kexec(kexec_crash_image); + machine_kexec(image); } xchg(&kexec_lock, 0); } diff --git a/trunk/kernel/kmod.c b/trunk/kernel/kmod.c index 1b7157af051c..20a997c73c3d 100644 --- a/trunk/kernel/kmod.c +++ b/trunk/kernel/kmod.c @@ -20,6 +20,7 @@ */ #define __KERNEL_SYSCALLS__ +#include #include #include #include diff --git a/trunk/kernel/kprobes.c b/trunk/kernel/kprobes.c index 64aab081153b..1fbf466a29aa 100644 --- a/trunk/kernel/kprobes.c +++ b/trunk/kernel/kprobes.c @@ -47,17 +47,11 @@ static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; -static atomic_t kprobe_count; DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */ static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; -static struct notifier_block kprobe_page_fault_nb = { - .notifier_call = kprobe_exceptions_notify, - .priority = 0x7fffffff /* we need to notified first */ -}; - #ifdef __ARCH_WANT_KPROBES_INSN_SLOT /* * kprobe->ainsn.insn points to the copy of the instruction to be @@ -374,15 +368,16 @@ static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p) */ static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) { + struct kprobe *kp; + if (p->break_handler) { - if (old_p->break_handler) - return -EEXIST; + list_for_each_entry_rcu(kp, &old_p->list, list) { + if (kp->break_handler) + return -EEXIST; + } list_add_tail_rcu(&p->list, &old_p->list); - old_p->break_handler = aggr_break_handler; } else list_add_rcu(&p->list, &old_p->list); - if (p->post_handler && !old_p->post_handler) - old_p->post_handler = aggr_post_handler; return 0; } @@ -395,11 +390,9 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p) copy_kprobe(p, ap); ap->addr = p->addr; ap->pre_handler = aggr_pre_handler; + ap->post_handler = aggr_post_handler; ap->fault_handler = aggr_fault_handler; - if (p->post_handler) - ap->post_handler = aggr_post_handler; - if (p->break_handler) - ap->break_handler = aggr_break_handler; + ap->break_handler = aggr_break_handler; INIT_LIST_HEAD(&ap->list); list_add_rcu(&p->list, &ap->list); @@ -471,8 +464,6 @@ static int __kprobes __register_kprobe(struct kprobe *p, old_p = get_kprobe(p->addr); if (old_p) { ret = register_aggr_kprobe(old_p, p); - if (!ret) - atomic_inc(&kprobe_count); goto out; } @@ -483,10 +474,6 @@ static int __kprobes __register_kprobe(struct kprobe *p, hlist_add_head_rcu(&p->hlist, &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); - if (atomic_add_return(1, &kprobe_count) == \ - (ARCH_INACTIVE_KPROBE_COUNT + 1)) - register_page_fault_notifier(&kprobe_page_fault_nb); - arch_arm_kprobe(p); out: @@ -549,40 +536,14 @@ void __kprobes unregister_kprobe(struct kprobe *p) kfree(old_p); } arch_remove_kprobe(p); - } else { - mutex_lock(&kprobe_mutex); - if (p->break_handler) - old_p->break_handler = NULL; - if (p->post_handler){ - list_for_each_entry_rcu(list_p, &old_p->list, list){ - if (list_p->post_handler){ - cleanup_p = 2; - break; - } - } - if (cleanup_p == 0) - old_p->post_handler = NULL; - } - mutex_unlock(&kprobe_mutex); } - - /* Call unregister_page_fault_notifier() - * if no probes are active - */ - mutex_lock(&kprobe_mutex); - if (atomic_add_return(-1, &kprobe_count) == \ - ARCH_INACTIVE_KPROBE_COUNT) - unregister_page_fault_notifier(&kprobe_page_fault_nb); - mutex_unlock(&kprobe_mutex); - return; } static struct notifier_block kprobe_exceptions_nb = { .notifier_call = kprobe_exceptions_notify, - .priority = 0x7fffffff /* we need to be notified first */ + .priority = 0x7fffffff /* we need to notified first */ }; - int __kprobes register_jprobe(struct jprobe *jp) { /* Todo: Verify probepoint is a function entry point */ @@ -691,7 +652,6 @@ static int __init init_kprobes(void) INIT_HLIST_HEAD(&kprobe_table[i]); INIT_HLIST_HEAD(&kretprobe_inst_table[i]); } - atomic_set(&kprobe_count, 0); err = arch_init_kprobes(); if (!err) diff --git a/trunk/kernel/ksysfs.c b/trunk/kernel/ksysfs.c index e0ffe4ab0917..9e28478a17a5 100644 --- a/trunk/kernel/ksysfs.c +++ b/trunk/kernel/ksysfs.c @@ -8,6 +8,7 @@ * */ +#include #include #include #include diff --git a/trunk/kernel/module.c b/trunk/kernel/module.c index 281172f01e9a..d75275de1c28 100644 --- a/trunk/kernel/module.c +++ b/trunk/kernel/module.c @@ -1,4 +1,4 @@ -/* +/* Rewritten by Rusty Russell, on the backs of many others... Copyright (C) 2002 Richard Henderson Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM. @@ -16,6 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include @@ -39,11 +40,9 @@ #include #include #include -#include #include #include #include -#include #if 0 #define DEBUGP printk @@ -121,17 +120,9 @@ extern const struct kernel_symbol __start___ksymtab_gpl[]; extern const struct kernel_symbol __stop___ksymtab_gpl[]; extern const struct kernel_symbol __start___ksymtab_gpl_future[]; extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; -extern const struct kernel_symbol __start___ksymtab_unused[]; -extern const struct kernel_symbol __stop___ksymtab_unused[]; -extern const struct kernel_symbol __start___ksymtab_unused_gpl[]; -extern const struct kernel_symbol __stop___ksymtab_unused_gpl[]; -extern const struct kernel_symbol __start___ksymtab_gpl_future[]; -extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; extern const unsigned long __start___kcrctab[]; extern const unsigned long __start___kcrctab_gpl[]; extern const unsigned long __start___kcrctab_gpl_future[]; -extern const unsigned long __start___kcrctab_unused[]; -extern const unsigned long __start___kcrctab_unused_gpl[]; #ifndef CONFIG_MODVERSIONS #define symversion(base, idx) NULL @@ -151,17 +142,6 @@ static const struct kernel_symbol *lookup_symbol(const char *name, return NULL; } -static void printk_unused_warning(const char *name) -{ - printk(KERN_WARNING "Symbol %s is marked as UNUSED, " - "however this module is using it.\n", name); - printk(KERN_WARNING "This symbol will go away in the future.\n"); - printk(KERN_WARNING "Please evalute if this is the right api to use, " - "and if it really is, submit a report the linux kernel " - "mailinglist together with submitting your code for " - "inclusion.\n"); -} - /* Find a symbol, return value, crc and module which owns it */ static unsigned long __find_symbol(const char *name, struct module **owner, @@ -204,25 +184,6 @@ static unsigned long __find_symbol(const char *name, return ks->value; } - ks = lookup_symbol(name, __start___ksymtab_unused, - __stop___ksymtab_unused); - if (ks) { - printk_unused_warning(name); - *crc = symversion(__start___kcrctab_unused, - (ks - __start___ksymtab_unused)); - return ks->value; - } - - if (gplok) - ks = lookup_symbol(name, __start___ksymtab_unused_gpl, - __stop___ksymtab_unused_gpl); - if (ks) { - printk_unused_warning(name); - *crc = symversion(__start___kcrctab_unused_gpl, - (ks - __start___ksymtab_unused_gpl)); - return ks->value; - } - /* Now try modules. */ list_for_each_entry(mod, &modules, list) { *owner = mod; @@ -241,23 +202,6 @@ static unsigned long __find_symbol(const char *name, return ks->value; } } - ks = lookup_symbol(name, mod->unused_syms, mod->unused_syms + mod->num_unused_syms); - if (ks) { - printk_unused_warning(name); - *crc = symversion(mod->unused_crcs, (ks - mod->unused_syms)); - return ks->value; - } - - if (gplok) { - ks = lookup_symbol(name, mod->unused_gpl_syms, - mod->unused_gpl_syms + mod->num_unused_gpl_syms); - if (ks) { - printk_unused_warning(name); - *crc = symversion(mod->unused_gpl_crcs, - (ks - mod->unused_gpl_syms)); - return ks->value; - } - } ks = lookup_symbol(name, mod->gpl_future_syms, (mod->gpl_future_syms + mod->num_gpl_future_syms)); @@ -1107,8 +1051,6 @@ static void free_module(struct module *mod) remove_sect_attrs(mod); mod_kobject_remove(mod); - unwind_remove_table(mod->unwind_info, 0); - /* Arch-specific cleanup. */ module_arch_cleanup(mod); @@ -1306,6 +1248,16 @@ static void layout_sections(struct module *mod, } } +static inline int license_is_gpl_compatible(const char *license) +{ + return (strcmp(license, "GPL") == 0 + || strcmp(license, "GPL v2") == 0 + || strcmp(license, "GPL and additional rights") == 0 + || strcmp(license, "Dual BSD/GPL") == 0 + || strcmp(license, "Dual MIT/GPL") == 0 + || strcmp(license, "Dual MPL/GPL") == 0); +} + static void set_license(struct module *mod, const char *license) { if (!license) @@ -1457,27 +1409,10 @@ static struct module *load_module(void __user *umod, Elf_Ehdr *hdr; Elf_Shdr *sechdrs; char *secstrings, *args, *modmagic, *strtab = NULL; - unsigned int i; - unsigned int symindex = 0; - unsigned int strindex = 0; - unsigned int setupindex; - unsigned int exindex; - unsigned int exportindex; - unsigned int modindex; - unsigned int obsparmindex; - unsigned int infoindex; - unsigned int gplindex; - unsigned int crcindex; - unsigned int gplcrcindex; - unsigned int versindex; - unsigned int pcpuindex; - unsigned int gplfutureindex; - unsigned int gplfuturecrcindex; - unsigned int unwindex = 0; - unsigned int unusedindex; - unsigned int unusedcrcindex; - unsigned int unusedgplindex; - unsigned int unusedgplcrcindex; + unsigned int i, symindex = 0, strindex = 0, setupindex, exindex, + exportindex, modindex, obsparmindex, infoindex, gplindex, + crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex, + gplfuturecrcindex; struct module *mod; long err = 0; void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ @@ -1558,22 +1493,15 @@ static struct module *load_module(void __user *umod, exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab"); gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl"); gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future"); - unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused"); - unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl"); crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab"); gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl"); gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future"); - unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused"); - unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl"); setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); versindex = find_sec(hdr, sechdrs, secstrings, "__versions"); infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo"); pcpuindex = find_pcpusec(hdr, sechdrs, secstrings); -#ifdef ARCH_UNWIND_SECTION_NAME - unwindex = find_sec(hdr, sechdrs, secstrings, ARCH_UNWIND_SECTION_NAME); -#endif /* Don't keep modinfo section */ sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; @@ -1582,8 +1510,6 @@ static struct module *load_module(void __user *umod, sechdrs[symindex].sh_flags |= SHF_ALLOC; sechdrs[strindex].sh_flags |= SHF_ALLOC; #endif - if (unwindex) - sechdrs[unwindex].sh_flags |= SHF_ALLOC; /* Check module struct version now, before we try to use module. */ if (!check_modstruct_version(sechdrs, versindex, mod)) { @@ -1713,27 +1639,14 @@ static struct module *load_module(void __user *umod, mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / sizeof(*mod->gpl_future_syms); - mod->num_unused_syms = sechdrs[unusedindex].sh_size / - sizeof(*mod->unused_syms); - mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size / - sizeof(*mod->unused_gpl_syms); mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr; if (gplfuturecrcindex) mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; - mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr; - if (unusedcrcindex) - mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr; - mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr; - if (unusedgplcrcindex) - mod->unused_crcs = (void *)sechdrs[unusedgplcrcindex].sh_addr; - #ifdef CONFIG_MODVERSIONS if ((mod->num_syms && !crcindex) || (mod->num_gpl_syms && !gplcrcindex) || - (mod->num_gpl_future_syms && !gplfuturecrcindex) || - (mod->num_unused_syms && !unusedcrcindex) || - (mod->num_unused_gpl_syms && !unusedgplcrcindex)) { + (mod->num_gpl_future_syms && !gplfuturecrcindex)) { printk(KERN_WARNING "%s: No versions for exported symbols." " Tainting kernel.\n", mod->name); add_taint(TAINT_FORCED_MODULE); @@ -1825,11 +1738,6 @@ static struct module *load_module(void __user *umod, goto arch_cleanup; add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); - /* Size of section 0 is 0, so this works well if no unwind info. */ - mod->unwind_info = unwind_add_table(mod, - (void *)sechdrs[unwindex].sh_addr, - sechdrs[unwindex].sh_size); - /* Get rid of temporary copy */ vfree(hdr); @@ -1928,7 +1836,6 @@ sys_init_module(void __user *umod, mod->state = MODULE_STATE_LIVE; /* Drop initial reference. */ module_put(mod); - unwind_remove_table(mod->unwind_info, 1); module_free(mod, mod->module_init); mod->module_init = NULL; mod->init_size = 0; diff --git a/trunk/kernel/mutex-debug.c b/trunk/kernel/mutex-debug.c index e38e4bac97ca..f4913c376950 100644 --- a/trunk/kernel/mutex-debug.c +++ b/trunk/kernel/mutex-debug.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -154,13 +153,13 @@ void show_held_locks(struct task_struct *filter) continue; count++; cursor = curr->next; - debug_spin_unlock_restore(&debug_mutex_lock, flags); + debug_spin_lock_restore(&debug_mutex_lock, flags); printk("\n#%03d: ", count); printk_lock(lock, filter ? 0 : 1); goto next; } - debug_spin_unlock_restore(&debug_mutex_lock, flags); + debug_spin_lock_restore(&debug_mutex_lock, flags); printk("\n"); } @@ -317,7 +316,7 @@ void mutex_debug_check_no_locks_held(struct task_struct *task) continue; list_del_init(curr); DEBUG_OFF(); - debug_spin_unlock_restore(&debug_mutex_lock, flags); + debug_spin_lock_restore(&debug_mutex_lock, flags); printk("BUG: %s/%d, lock held at task exit time!\n", task->comm, task->pid); @@ -326,7 +325,7 @@ void mutex_debug_check_no_locks_held(struct task_struct *task) printk("exiting task is not even the owner??\n"); return; } - debug_spin_unlock_restore(&debug_mutex_lock, flags); + debug_spin_lock_restore(&debug_mutex_lock, flags); } /* @@ -353,7 +352,7 @@ void mutex_debug_check_no_locks_freed(const void *from, unsigned long len) continue; list_del_init(curr); DEBUG_OFF(); - debug_spin_unlock_restore(&debug_mutex_lock, flags); + debug_spin_lock_restore(&debug_mutex_lock, flags); printk("BUG: %s/%d, active lock [%p(%p-%p)] freed!\n", current->comm, current->pid, lock, from, to); @@ -363,7 +362,7 @@ void mutex_debug_check_no_locks_freed(const void *from, unsigned long len) printk("freeing task is not even the owner??\n"); return; } - debug_spin_unlock_restore(&debug_mutex_lock, flags); + debug_spin_lock_restore(&debug_mutex_lock, flags); } /* @@ -382,7 +381,7 @@ void debug_mutex_set_owner(struct mutex *lock, void debug_mutex_init_waiter(struct mutex_waiter *waiter) { - memset(waiter, MUTEX_DEBUG_INIT, sizeof(*waiter)); + memset(waiter, 0x11, sizeof(*waiter)); waiter->magic = waiter; INIT_LIST_HEAD(&waiter->list); } @@ -398,7 +397,7 @@ void debug_mutex_wake_waiter(struct mutex *lock, struct mutex_waiter *waiter) void debug_mutex_free_waiter(struct mutex_waiter *waiter) { DEBUG_WARN_ON(!list_empty(&waiter->list)); - memset(waiter, MUTEX_DEBUG_FREE, sizeof(*waiter)); + memset(waiter, 0x22, sizeof(*waiter)); } void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter, diff --git a/trunk/kernel/mutex-debug.h b/trunk/kernel/mutex-debug.h index a5196c36a5fd..fd384050acb1 100644 --- a/trunk/kernel/mutex-debug.h +++ b/trunk/kernel/mutex-debug.h @@ -46,6 +46,21 @@ extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter, extern void debug_mutex_unlock(struct mutex *lock); extern void debug_mutex_init(struct mutex *lock, const char *name); +#define debug_spin_lock(lock) \ + do { \ + local_irq_disable(); \ + if (debug_mutex_on) \ + spin_lock(lock); \ + } while (0) + +#define debug_spin_unlock(lock) \ + do { \ + if (debug_mutex_on) \ + spin_unlock(lock); \ + local_irq_enable(); \ + preempt_check_resched(); \ + } while (0) + #define debug_spin_lock_save(lock, flags) \ do { \ local_irq_save(flags); \ @@ -53,7 +68,7 @@ extern void debug_mutex_init(struct mutex *lock, const char *name); spin_lock(lock); \ } while (0) -#define debug_spin_unlock_restore(lock, flags) \ +#define debug_spin_lock_restore(lock, flags) \ do { \ if (debug_mutex_on) \ spin_unlock(lock); \ @@ -61,20 +76,20 @@ extern void debug_mutex_init(struct mutex *lock, const char *name); preempt_check_resched(); \ } while (0) -#define spin_lock_mutex(lock, flags) \ +#define spin_lock_mutex(lock) \ do { \ struct mutex *l = container_of(lock, struct mutex, wait_lock); \ \ DEBUG_WARN_ON(in_interrupt()); \ - debug_spin_lock_save(&debug_mutex_lock, flags); \ + debug_spin_lock(&debug_mutex_lock); \ spin_lock(lock); \ DEBUG_WARN_ON(l->magic != l); \ } while (0) -#define spin_unlock_mutex(lock, flags) \ +#define spin_unlock_mutex(lock) \ do { \ spin_unlock(lock); \ - debug_spin_unlock_restore(&debug_mutex_lock, flags); \ + debug_spin_unlock(&debug_mutex_lock); \ } while (0) #define DEBUG_OFF() \ diff --git a/trunk/kernel/mutex.c b/trunk/kernel/mutex.c index 7043db21bbce..5449b210d9ed 100644 --- a/trunk/kernel/mutex.c +++ b/trunk/kernel/mutex.c @@ -125,11 +125,10 @@ __mutex_lock_common(struct mutex *lock, long state __IP_DECL__) struct task_struct *task = current; struct mutex_waiter waiter; unsigned int old_val; - unsigned long flags; debug_mutex_init_waiter(&waiter); - spin_lock_mutex(&lock->wait_lock, flags); + spin_lock_mutex(&lock->wait_lock); debug_mutex_add_waiter(lock, &waiter, task->thread_info, ip); @@ -158,7 +157,7 @@ __mutex_lock_common(struct mutex *lock, long state __IP_DECL__) if (unlikely(state == TASK_INTERRUPTIBLE && signal_pending(task))) { mutex_remove_waiter(lock, &waiter, task->thread_info); - spin_unlock_mutex(&lock->wait_lock, flags); + spin_unlock_mutex(&lock->wait_lock); debug_mutex_free_waiter(&waiter); return -EINTR; @@ -166,9 +165,9 @@ __mutex_lock_common(struct mutex *lock, long state __IP_DECL__) __set_task_state(task, state); /* didnt get the lock, go to sleep: */ - spin_unlock_mutex(&lock->wait_lock, flags); + spin_unlock_mutex(&lock->wait_lock); schedule(); - spin_lock_mutex(&lock->wait_lock, flags); + spin_lock_mutex(&lock->wait_lock); } /* got the lock - rejoice! */ @@ -179,7 +178,7 @@ __mutex_lock_common(struct mutex *lock, long state __IP_DECL__) if (likely(list_empty(&lock->wait_list))) atomic_set(&lock->count, 0); - spin_unlock_mutex(&lock->wait_lock, flags); + spin_unlock_mutex(&lock->wait_lock); debug_mutex_free_waiter(&waiter); @@ -204,11 +203,10 @@ static fastcall noinline void __mutex_unlock_slowpath(atomic_t *lock_count __IP_DECL__) { struct mutex *lock = container_of(lock_count, struct mutex, count); - unsigned long flags; DEBUG_WARN_ON(lock->owner != current_thread_info()); - spin_lock_mutex(&lock->wait_lock, flags); + spin_lock_mutex(&lock->wait_lock); /* * some architectures leave the lock unlocked in the fastpath failure @@ -233,7 +231,7 @@ __mutex_unlock_slowpath(atomic_t *lock_count __IP_DECL__) debug_mutex_clear_owner(lock); - spin_unlock_mutex(&lock->wait_lock, flags); + spin_unlock_mutex(&lock->wait_lock); } /* @@ -278,10 +276,9 @@ __mutex_lock_interruptible_slowpath(atomic_t *lock_count __IP_DECL__) static inline int __mutex_trylock_slowpath(atomic_t *lock_count) { struct mutex *lock = container_of(lock_count, struct mutex, count); - unsigned long flags; int prev; - spin_lock_mutex(&lock->wait_lock, flags); + spin_lock_mutex(&lock->wait_lock); prev = atomic_xchg(&lock->count, -1); if (likely(prev == 1)) @@ -290,7 +287,7 @@ static inline int __mutex_trylock_slowpath(atomic_t *lock_count) if (likely(list_empty(&lock->wait_list))) atomic_set(&lock->count, 0); - spin_unlock_mutex(&lock->wait_lock, flags); + spin_unlock_mutex(&lock->wait_lock); return prev == 1; } diff --git a/trunk/kernel/mutex.h b/trunk/kernel/mutex.h index 069189947257..00fe84e7b672 100644 --- a/trunk/kernel/mutex.h +++ b/trunk/kernel/mutex.h @@ -9,10 +9,8 @@ * !CONFIG_DEBUG_MUTEXES case. Most of them are NOPs: */ -#define spin_lock_mutex(lock, flags) \ - do { spin_lock(lock); (void)(flags); } while (0) -#define spin_unlock_mutex(lock, flags) \ - do { spin_unlock(lock); (void)(flags); } while (0) +#define spin_lock_mutex(lock) spin_lock(lock) +#define spin_unlock_mutex(lock) spin_unlock(lock) #define mutex_remove_waiter(lock, waiter, ti) \ __list_del((waiter)->list.prev, (waiter)->list.next) diff --git a/trunk/kernel/panic.c b/trunk/kernel/panic.c index ab13f0f668b5..cc2a4c9c36ac 100644 --- a/trunk/kernel/panic.c +++ b/trunk/kernel/panic.c @@ -8,6 +8,7 @@ * This function is used through-out the kernel (including mm and fs) * to indicate a major problem. */ +#include #include #include #include diff --git a/trunk/kernel/params.c b/trunk/kernel/params.c index 91aea7aa532e..af43ecdc8d9b 100644 --- a/trunk/kernel/params.c +++ b/trunk/kernel/params.c @@ -15,6 +15,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include diff --git a/trunk/kernel/power/Kconfig b/trunk/kernel/power/Kconfig index ae44a70aae8a..fc311a4673a2 100644 --- a/trunk/kernel/power/Kconfig +++ b/trunk/kernel/power/Kconfig @@ -38,22 +38,13 @@ config PM_DEBUG config PM_TRACE bool "Suspend/resume event tracing" - depends on PM && PM_DEBUG && X86_32 && EXPERIMENTAL - default n + depends on PM && PM_DEBUG && X86_32 + default y ---help--- This enables some cheesy code to save the last PM event point in the RTC across reboots, so that you can debug a machine that just hangs during suspend (or more commonly, during resume). - To use this debugging feature you should attempt to suspend the machine, - then reboot it, then run - - dmesg -s 1000000 | grep 'hash matches' - - CAUTION: this option will cause your machine's real-time clock to be - set to an invalid time after a resume. - - config SOFTWARE_SUSPEND bool "Software Suspend" depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP) @@ -100,6 +91,18 @@ config PM_STD_PARTITION suspended image to. It will simply pick the first available swap device. +config SWSUSP_ENCRYPT + bool "Encrypt suspend image" + depends on SOFTWARE_SUSPEND && CRYPTO=y && (CRYPTO_AES=y || CRYPTO_AES_586=y || CRYPTO_AES_X86_64=y) + default "" + ---help--- + To prevent data gathering from swap after resume you can encrypt + the suspend image with a temporary key that is deleted on + resume. + + Note that the temporary key is stored unencrypted on disk while the + system is suspended. + config SUSPEND_SMP bool depends on HOTPLUG_CPU && X86 && PM diff --git a/trunk/kernel/printk.c b/trunk/kernel/printk.c index 39ae24d2a415..95b7fe17f124 100644 --- a/trunk/kernel/printk.c +++ b/trunk/kernel/printk.c @@ -26,6 +26,7 @@ #include #include #include /* For in_interrupt() */ +#include #include #include #include diff --git a/trunk/kernel/profile.c b/trunk/kernel/profile.c index d5bd75e7501c..68afe121e507 100644 --- a/trunk/kernel/profile.c +++ b/trunk/kernel/profile.c @@ -13,6 +13,7 @@ * to resolve timer interrupt livelocks, William Irwin, Oracle, 2004 */ +#include #include #include #include @@ -298,7 +299,7 @@ void profile_hit(int type, void *__pc) } #ifdef CONFIG_HOTPLUG_CPU -static int __devinit profile_cpu_callback(struct notifier_block *info, +static int profile_cpu_callback(struct notifier_block *info, unsigned long action, void *__cpu) { int node, cpu = (unsigned long)__cpu; diff --git a/trunk/kernel/ptrace.c b/trunk/kernel/ptrace.c index 335c5b932e14..921c22ad16e4 100644 --- a/trunk/kernel/ptrace.c +++ b/trunk/kernel/ptrace.c @@ -120,18 +120,8 @@ int ptrace_check_attach(struct task_struct *child, int kill) static int may_attach(struct task_struct *task) { - /* May we inspect the given task? - * This check is used both for attaching with ptrace - * and for allowing access to sensitive information in /proc. - * - * ptrace_attach denies several cases that /proc allows - * because setting up the necessary parent/child relationship - * or halting the specified task is impossible. - */ - int dumpable = 0; - /* Don't let security modules deny introspection */ - if (task == current) - return 0; + if (!task->mm) + return -EPERM; if (((current->uid != task->euid) || (current->uid != task->suid) || (current->uid != task->uid) || @@ -140,9 +130,7 @@ static int may_attach(struct task_struct *task) (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) return -EPERM; smp_rmb(); - if (task->mm) - dumpable = task->mm->dumpable; - if (!dumpable && !capable(CAP_SYS_PTRACE)) + if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) return -EPERM; return security_ptrace(current, task); @@ -188,8 +176,6 @@ int ptrace_attach(struct task_struct *task) goto repeat; } - if (!task->mm) - goto bad; /* the same process cannot be attached many times */ if (task->ptrace & PT_PTRACED) goto bad; @@ -214,7 +200,7 @@ int ptrace_attach(struct task_struct *task) return retval; } -static inline void __ptrace_detach(struct task_struct *child, unsigned int data) +void __ptrace_detach(struct task_struct *child, unsigned int data) { child->exit_code = data; /* .. re-parent .. */ @@ -233,7 +219,6 @@ int ptrace_detach(struct task_struct *child, unsigned int data) ptrace_disable(child); write_lock_irq(&tasklist_lock); - /* protect against de_thread()->release_task() */ if (child->ptrace) __ptrace_detach(child, data); write_unlock_irq(&tasklist_lock); diff --git a/trunk/kernel/rcupdate.c b/trunk/kernel/rcupdate.c index f464f5ae3f11..20e9710fc21c 100644 --- a/trunk/kernel/rcupdate.c +++ b/trunk/kernel/rcupdate.c @@ -182,15 +182,6 @@ long rcu_batches_completed(void) return rcu_ctrlblk.completed; } -/* - * Return the number of RCU batches processed thus far. Useful - * for debug and statistics. - */ -long rcu_batches_completed_bh(void) -{ - return rcu_bh_ctrlblk.completed; -} - static void rcu_barrier_callback(struct rcu_head *notused) { if (atomic_dec_and_test(&rcu_barrier_cpu_count)) @@ -548,7 +539,7 @@ static void __devinit rcu_online_cpu(int cpu) tasklet_init(&per_cpu(rcu_tasklet, cpu), rcu_process_callbacks, 0UL); } -static int __devinit rcu_cpu_notify(struct notifier_block *self, +static int rcu_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -565,7 +556,7 @@ static int __devinit rcu_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __devinitdata rcu_nb = { +static struct notifier_block rcu_nb = { .notifier_call = rcu_cpu_notify, }; @@ -628,7 +619,6 @@ module_param(qlowmark, int, 0); module_param(rsinterval, int, 0); #endif EXPORT_SYMBOL_GPL(rcu_batches_completed); -EXPORT_SYMBOL_GPL(rcu_batches_completed_bh); EXPORT_SYMBOL_GPL(call_rcu); EXPORT_SYMBOL_GPL(call_rcu_bh); EXPORT_SYMBOL_GPL(synchronize_rcu); diff --git a/trunk/kernel/rcutorture.c b/trunk/kernel/rcutorture.c index 4d1c3d247127..8154e7589d12 100644 --- a/trunk/kernel/rcutorture.c +++ b/trunk/kernel/rcutorture.c @@ -1,5 +1,5 @@ /* - * Read-Copy Update module-based torture test facility + * Read-Copy Update /proc-based torture test facility * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -53,7 +53,6 @@ static int stat_interval; /* Interval between stats, in seconds. */ static int verbose; /* Print more debug info. */ static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */ static int shuffle_interval = 5; /* Interval between shuffles (in sec)*/ -static char *torture_type = "rcu"; /* What to torture. */ module_param(nreaders, int, 0); MODULE_PARM_DESC(nreaders, "Number of RCU reader threads"); @@ -65,16 +64,13 @@ module_param(test_no_idle_hz, bool, 0); MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs"); module_param(shuffle_interval, int, 0); MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles"); -module_param(torture_type, charp, 0); -MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh)"); - -#define TORTURE_FLAG "-torture:" +#define TORTURE_FLAG "rcutorture: " #define PRINTK_STRING(s) \ - do { printk(KERN_ALERT "%s" TORTURE_FLAG s "\n", torture_type); } while (0) + do { printk(KERN_ALERT TORTURE_FLAG s "\n"); } while (0) #define VERBOSE_PRINTK_STRING(s) \ - do { if (verbose) printk(KERN_ALERT "%s" TORTURE_FLAG s "\n", torture_type); } while (0) + do { if (verbose) printk(KERN_ALERT TORTURE_FLAG s "\n"); } while (0) #define VERBOSE_PRINTK_ERRSTRING(s) \ - do { if (verbose) printk(KERN_ALERT "%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0) + do { if (verbose) printk(KERN_ALERT TORTURE_FLAG "!!! " s "\n"); } while (0) static char printk_buf[4096]; @@ -143,71 +139,6 @@ rcu_torture_free(struct rcu_torture *p) spin_unlock_bh(&rcu_torture_lock); } -struct rcu_random_state { - unsigned long rrs_state; - unsigned long rrs_count; -}; - -#define RCU_RANDOM_MULT 39916801 /* prime */ -#define RCU_RANDOM_ADD 479001701 /* prime */ -#define RCU_RANDOM_REFRESH 10000 - -#define DEFINE_RCU_RANDOM(name) struct rcu_random_state name = { 0, 0 } - -/* - * Crude but fast random-number generator. Uses a linear congruential - * generator, with occasional help from get_random_bytes(). - */ -static long -rcu_random(struct rcu_random_state *rrsp) -{ - long refresh; - - if (--rrsp->rrs_count < 0) { - get_random_bytes(&refresh, sizeof(refresh)); - rrsp->rrs_state += refresh; - rrsp->rrs_count = RCU_RANDOM_REFRESH; - } - rrsp->rrs_state = rrsp->rrs_state * RCU_RANDOM_MULT + RCU_RANDOM_ADD; - return swahw32(rrsp->rrs_state); -} - -/* - * Operations vector for selecting different types of tests. - */ - -struct rcu_torture_ops { - void (*init)(void); - void (*cleanup)(void); - int (*readlock)(void); - void (*readunlock)(int idx); - int (*completed)(void); - void (*deferredfree)(struct rcu_torture *p); - int (*stats)(char *page); - char *name; -}; -static struct rcu_torture_ops *cur_ops = NULL; - -/* - * Definitions for rcu torture testing. - */ - -static int rcu_torture_read_lock(void) -{ - rcu_read_lock(); - return 0; -} - -static void rcu_torture_read_unlock(int idx) -{ - rcu_read_unlock(); -} - -static int rcu_torture_completed(void) -{ - return rcu_batches_completed(); -} - static void rcu_torture_cb(struct rcu_head *p) { @@ -227,64 +158,38 @@ rcu_torture_cb(struct rcu_head *p) rp->rtort_mbtest = 0; rcu_torture_free(rp); } else - cur_ops->deferredfree(rp); -} - -static void rcu_torture_deferred_free(struct rcu_torture *p) -{ - call_rcu(&p->rtort_rcu, rcu_torture_cb); + call_rcu(p, rcu_torture_cb); } -static struct rcu_torture_ops rcu_ops = { - .init = NULL, - .cleanup = NULL, - .readlock = rcu_torture_read_lock, - .readunlock = rcu_torture_read_unlock, - .completed = rcu_torture_completed, - .deferredfree = rcu_torture_deferred_free, - .stats = NULL, - .name = "rcu" +struct rcu_random_state { + unsigned long rrs_state; + unsigned long rrs_count; }; -/* - * Definitions for rcu_bh torture testing. - */ - -static int rcu_bh_torture_read_lock(void) -{ - rcu_read_lock_bh(); - return 0; -} +#define RCU_RANDOM_MULT 39916801 /* prime */ +#define RCU_RANDOM_ADD 479001701 /* prime */ +#define RCU_RANDOM_REFRESH 10000 -static void rcu_bh_torture_read_unlock(int idx) -{ - rcu_read_unlock_bh(); -} +#define DEFINE_RCU_RANDOM(name) struct rcu_random_state name = { 0, 0 } -static int rcu_bh_torture_completed(void) +/* + * Crude but fast random-number generator. Uses a linear congruential + * generator, with occasional help from get_random_bytes(). + */ +static long +rcu_random(struct rcu_random_state *rrsp) { - return rcu_batches_completed_bh(); -} + long refresh; -static void rcu_bh_torture_deferred_free(struct rcu_torture *p) -{ - call_rcu_bh(&p->rtort_rcu, rcu_torture_cb); + if (--rrsp->rrs_count < 0) { + get_random_bytes(&refresh, sizeof(refresh)); + rrsp->rrs_state += refresh; + rrsp->rrs_count = RCU_RANDOM_REFRESH; + } + rrsp->rrs_state = rrsp->rrs_state * RCU_RANDOM_MULT + RCU_RANDOM_ADD; + return swahw32(rrsp->rrs_state); } -static struct rcu_torture_ops rcu_bh_ops = { - .init = NULL, - .cleanup = NULL, - .readlock = rcu_bh_torture_read_lock, - .readunlock = rcu_bh_torture_read_unlock, - .completed = rcu_bh_torture_completed, - .deferredfree = rcu_bh_torture_deferred_free, - .stats = NULL, - .name = "rcu_bh" -}; - -static struct rcu_torture_ops *torture_ops[] = - { &rcu_ops, &rcu_bh_ops, NULL }; - /* * RCU torture writer kthread. Repeatedly substitutes a new structure * for that pointed to by rcu_torture_current, freeing the old structure @@ -304,6 +209,8 @@ rcu_torture_writer(void *arg) do { schedule_timeout_uninterruptible(1); + if (rcu_batches_completed() == oldbatch) + continue; if ((rp = rcu_torture_alloc()) == NULL) continue; rp->rtort_pipe_count = 0; @@ -318,10 +225,10 @@ rcu_torture_writer(void *arg) i = RCU_TORTURE_PIPE_LEN; atomic_inc(&rcu_torture_wcount[i]); old_rp->rtort_pipe_count++; - cur_ops->deferredfree(old_rp); + call_rcu(&old_rp->rtort_rcu, rcu_torture_cb); } rcu_torture_current_version++; - oldbatch = cur_ops->completed(); + oldbatch = rcu_batches_completed(); } while (!kthread_should_stop() && !fullstop); VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping"); while (!kthread_should_stop()) @@ -339,7 +246,6 @@ static int rcu_torture_reader(void *arg) { int completed; - int idx; DEFINE_RCU_RANDOM(rand); struct rcu_torture *p; int pipe_count; @@ -348,12 +254,12 @@ rcu_torture_reader(void *arg) set_user_nice(current, 19); do { - idx = cur_ops->readlock(); - completed = cur_ops->completed(); + rcu_read_lock(); + completed = rcu_batches_completed(); p = rcu_dereference(rcu_torture_current); if (p == NULL) { /* Wait for rcu_torture_writer to get underway */ - cur_ops->readunlock(idx); + rcu_read_unlock(); schedule_timeout_interruptible(HZ); continue; } @@ -367,14 +273,14 @@ rcu_torture_reader(void *arg) pipe_count = RCU_TORTURE_PIPE_LEN; } ++__get_cpu_var(rcu_torture_count)[pipe_count]; - completed = cur_ops->completed() - completed; + completed = rcu_batches_completed() - completed; if (completed > RCU_TORTURE_PIPE_LEN) { /* Should not happen, but... */ completed = RCU_TORTURE_PIPE_LEN; } ++__get_cpu_var(rcu_torture_batch)[completed]; preempt_enable(); - cur_ops->readunlock(idx); + rcu_read_unlock(); schedule(); } while (!kthread_should_stop() && !fullstop); VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping"); @@ -405,7 +311,7 @@ rcu_torture_printk(char *page) if (pipesummary[i] != 0) break; } - cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG); + cnt += sprintf(&page[cnt], "rcutorture: "); cnt += sprintf(&page[cnt], "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d " "rtmbe: %d", @@ -418,7 +324,7 @@ rcu_torture_printk(char *page) atomic_read(&n_rcu_torture_mberror)); if (atomic_read(&n_rcu_torture_mberror) != 0) cnt += sprintf(&page[cnt], " !!!"); - cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG); + cnt += sprintf(&page[cnt], "\nrcutorture: "); if (i > 1) { cnt += sprintf(&page[cnt], "!!! "); atomic_inc(&n_rcu_torture_error); @@ -426,19 +332,17 @@ rcu_torture_printk(char *page) cnt += sprintf(&page[cnt], "Reader Pipe: "); for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) cnt += sprintf(&page[cnt], " %ld", pipesummary[i]); - cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG); + cnt += sprintf(&page[cnt], "\nrcutorture: "); cnt += sprintf(&page[cnt], "Reader Batch: "); - for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) + for (i = 0; i < RCU_TORTURE_PIPE_LEN; i++) cnt += sprintf(&page[cnt], " %ld", batchsummary[i]); - cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG); + cnt += sprintf(&page[cnt], "\nrcutorture: "); cnt += sprintf(&page[cnt], "Free-Block Circulation: "); for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { cnt += sprintf(&page[cnt], " %d", atomic_read(&rcu_torture_wcount[i])); } cnt += sprintf(&page[cnt], "\n"); - if (cur_ops->stats != NULL) - cnt += cur_ops->stats(&page[cnt]); return cnt; } @@ -540,11 +444,11 @@ rcu_torture_shuffle(void *arg) static inline void rcu_torture_print_module_parms(char *tag) { - printk(KERN_ALERT "%s" TORTURE_FLAG "--- %s: nreaders=%d " + printk(KERN_ALERT TORTURE_FLAG "--- %s: nreaders=%d " "stat_interval=%d verbose=%d test_no_idle_hz=%d " "shuffle_interval = %d\n", - torture_type, tag, nrealreaders, stat_interval, verbose, - test_no_idle_hz, shuffle_interval); + tag, nrealreaders, stat_interval, verbose, test_no_idle_hz, + shuffle_interval); } static void @@ -589,9 +493,6 @@ rcu_torture_cleanup(void) rcu_barrier(); rcu_torture_stats_print(); /* -After- the stats thread is stopped! */ - - if (cur_ops->cleanup != NULL) - cur_ops->cleanup(); if (atomic_read(&n_rcu_torture_error)) rcu_torture_print_module_parms("End of test: FAILURE"); else @@ -607,20 +508,6 @@ rcu_torture_init(void) /* Process args and tell the world that the torturer is on the job. */ - for (i = 0; cur_ops = torture_ops[i], cur_ops != NULL; i++) { - cur_ops = torture_ops[i]; - if (strcmp(torture_type, cur_ops->name) == 0) { - break; - } - } - if (cur_ops == NULL) { - printk(KERN_ALERT "rcutorture: invalid torture type: \"%s\"\n", - torture_type); - return (-EINVAL); - } - if (cur_ops->init != NULL) - cur_ops->init(); /* no "goto unwind" prior to this point!!! */ - if (nreaders >= 0) nrealreaders = nreaders; else diff --git a/trunk/kernel/resource.c b/trunk/kernel/resource.c index 129cf046e561..e3080fcc66a3 100644 --- a/trunk/kernel/resource.c +++ b/trunk/kernel/resource.c @@ -7,6 +7,7 @@ * Arbitrary resource management. */ +#include #include #include #include @@ -22,18 +23,20 @@ struct resource ioport_resource = { .name = "PCI IO", - .start = 0, + .start = 0x0000, .end = IO_SPACE_LIMIT, .flags = IORESOURCE_IO, }; + EXPORT_SYMBOL(ioport_resource); struct resource iomem_resource = { .name = "PCI mem", - .start = 0, - .end = -1, + .start = 0UL, + .end = ~0UL, .flags = IORESOURCE_MEM, }; + EXPORT_SYMBOL(iomem_resource); static DEFINE_RWLOCK(resource_lock); @@ -80,10 +83,10 @@ static int r_show(struct seq_file *m, void *v) for (depth = 0, p = r; depth < MAX_IORES_LEVEL; depth++, p = p->parent) if (p->parent == root) break; - seq_printf(m, "%*s%0*llx-%0*llx : %s\n", + seq_printf(m, "%*s%0*lx-%0*lx : %s\n", depth * 2, "", - width, (unsigned long long) r->start, - width, (unsigned long long) r->end, + width, r->start, + width, r->end, r->name ? r->name : ""); return 0; } @@ -148,8 +151,8 @@ __initcall(ioresources_init); /* Return the conflict entry if you can't request it */ static struct resource * __request_resource(struct resource *root, struct resource *new) { - resource_size_t start = new->start; - resource_size_t end = new->end; + unsigned long start = new->start; + unsigned long end = new->end; struct resource *tmp, **p; if (end < start) @@ -229,52 +232,15 @@ int release_resource(struct resource *old) EXPORT_SYMBOL(release_resource); -#ifdef CONFIG_MEMORY_HOTPLUG -/* - * Finds the lowest memory reosurce exists within [res->start.res->end) - * the caller must specify res->start, res->end, res->flags. - * If found, returns 0, res is overwritten, if not found, returns -1. - */ -int find_next_system_ram(struct resource *res) -{ - resource_size_t start, end; - struct resource *p; - - BUG_ON(!res); - - start = res->start; - end = res->end; - - read_lock(&resource_lock); - for (p = iomem_resource.child; p ; p = p->sibling) { - /* system ram is just marked as IORESOURCE_MEM */ - if (p->flags != res->flags) - continue; - if (p->start > end) { - p = NULL; - break; - } - if (p->start >= start) - break; - } - read_unlock(&resource_lock); - if (!p) - return -1; - /* copy data */ - res->start = p->start; - res->end = p->end; - return 0; -} -#endif - /* * Find empty slot in the resource tree given range and alignment. */ static int find_resource(struct resource *root, struct resource *new, - resource_size_t size, resource_size_t min, - resource_size_t max, resource_size_t align, + unsigned long size, + unsigned long min, unsigned long max, + unsigned long align, void (*alignf)(void *, struct resource *, - resource_size_t, resource_size_t), + unsigned long, unsigned long), void *alignf_data) { struct resource *this = root->child; @@ -316,10 +282,11 @@ static int find_resource(struct resource *root, struct resource *new, * Allocate empty slot in the resource tree given range and alignment. */ int allocate_resource(struct resource *root, struct resource *new, - resource_size_t size, resource_size_t min, - resource_size_t max, resource_size_t align, + unsigned long size, + unsigned long min, unsigned long max, + unsigned long align, void (*alignf)(void *, struct resource *, - resource_size_t, resource_size_t), + unsigned long, unsigned long), void *alignf_data) { int err; @@ -411,10 +378,10 @@ EXPORT_SYMBOL(insert_resource); * arguments. Returns -EBUSY if it can't fit. Existing children of * the resource are assumed to be immutable. */ -int adjust_resource(struct resource *res, resource_size_t start, resource_size_t size) +int adjust_resource(struct resource *res, unsigned long start, unsigned long size) { struct resource *tmp, *parent = res->parent; - resource_size_t end = start + size - 1; + unsigned long end = start + size - 1; int result = -EBUSY; write_lock(&resource_lock); @@ -461,9 +428,7 @@ EXPORT_SYMBOL(adjust_resource); * * Release-region releases a matching busy region. */ -struct resource * __request_region(struct resource *parent, - resource_size_t start, resource_size_t n, - const char *name) +struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name) { struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); @@ -499,8 +464,7 @@ struct resource * __request_region(struct resource *parent, EXPORT_SYMBOL(__request_region); -int __check_region(struct resource *parent, resource_size_t start, - resource_size_t n) +int __check_region(struct resource *parent, unsigned long start, unsigned long n) { struct resource * res; @@ -515,11 +479,10 @@ int __check_region(struct resource *parent, resource_size_t start, EXPORT_SYMBOL(__check_region); -void __release_region(struct resource *parent, resource_size_t start, - resource_size_t n) +void __release_region(struct resource *parent, unsigned long start, unsigned long n) { struct resource **p; - resource_size_t end; + unsigned long end; p = &parent->child; end = start + n - 1; @@ -548,9 +511,7 @@ void __release_region(struct resource *parent, resource_size_t start, write_unlock(&resource_lock); - printk(KERN_WARNING "Trying to free nonexistent resource " - "<%016llx-%016llx>\n", (unsigned long long)start, - (unsigned long long)end); + printk(KERN_WARNING "Trying to free nonexistent resource <%08lx-%08lx>\n", start, end); } EXPORT_SYMBOL(__release_region); diff --git a/trunk/kernel/rtmutex-debug.c b/trunk/kernel/rtmutex-debug.c deleted file mode 100644 index 4aa8a2c9f453..000000000000 --- a/trunk/kernel/rtmutex-debug.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * RT-Mutexes: blocking mutual exclusion locks with PI support - * - * started by Ingo Molnar and Thomas Gleixner: - * - * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar - * Copyright (C) 2006 Timesys Corp., Thomas Gleixner - * - * This code is based on the rt.c implementation in the preempt-rt tree. - * Portions of said code are - * - * Copyright (C) 2004 LynuxWorks, Inc., Igor Manyilov, Bill Huey - * Copyright (C) 2006 Esben Nielsen - * Copyright (C) 2006 Kihon Technologies Inc., - * Steven Rostedt - * - * See rt.c in preempt-rt for proper credits and further information - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rtmutex_common.h" - -#ifdef CONFIG_DEBUG_RT_MUTEXES -# include "rtmutex-debug.h" -#else -# include "rtmutex.h" -#endif - -# define TRACE_WARN_ON(x) WARN_ON(x) -# define TRACE_BUG_ON(x) BUG_ON(x) - -# define TRACE_OFF() \ -do { \ - if (rt_trace_on) { \ - rt_trace_on = 0; \ - console_verbose(); \ - if (spin_is_locked(¤t->pi_lock)) \ - spin_unlock(¤t->pi_lock); \ - if (spin_is_locked(¤t->held_list_lock)) \ - spin_unlock(¤t->held_list_lock); \ - } \ -} while (0) - -# define TRACE_OFF_NOLOCK() \ -do { \ - if (rt_trace_on) { \ - rt_trace_on = 0; \ - console_verbose(); \ - } \ -} while (0) - -# define TRACE_BUG_LOCKED() \ -do { \ - TRACE_OFF(); \ - BUG(); \ -} while (0) - -# define TRACE_WARN_ON_LOCKED(c) \ -do { \ - if (unlikely(c)) { \ - TRACE_OFF(); \ - WARN_ON(1); \ - } \ -} while (0) - -# define TRACE_BUG_ON_LOCKED(c) \ -do { \ - if (unlikely(c)) \ - TRACE_BUG_LOCKED(); \ -} while (0) - -#ifdef CONFIG_SMP -# define SMP_TRACE_BUG_ON_LOCKED(c) TRACE_BUG_ON_LOCKED(c) -#else -# define SMP_TRACE_BUG_ON_LOCKED(c) do { } while (0) -#endif - -/* - * deadlock detection flag. We turn it off when we detect - * the first problem because we dont want to recurse back - * into the tracing code when doing error printk or - * executing a BUG(): - */ -int rt_trace_on = 1; - -void deadlock_trace_off(void) -{ - rt_trace_on = 0; -} - -static void printk_task(task_t *p) -{ - if (p) - printk("%16s:%5d [%p, %3d]", p->comm, p->pid, p, p->prio); - else - printk(""); -} - -static void printk_task_short(task_t *p) -{ - if (p) - printk("%s/%d [%p, %3d]", p->comm, p->pid, p, p->prio); - else - printk(""); -} - -static void printk_lock(struct rt_mutex *lock, int print_owner) -{ - if (lock->name) - printk(" [%p] {%s}\n", - lock, lock->name); - else - printk(" [%p] {%s:%d}\n", - lock, lock->file, lock->line); - - if (print_owner && rt_mutex_owner(lock)) { - printk(".. ->owner: %p\n", lock->owner); - printk(".. held by: "); - printk_task(rt_mutex_owner(lock)); - printk("\n"); - } - if (rt_mutex_owner(lock)) { - printk("... acquired at: "); - print_symbol("%s\n", lock->acquire_ip); - } -} - -static void printk_waiter(struct rt_mutex_waiter *w) -{ - printk("-------------------------\n"); - printk("| waiter struct %p:\n", w); - printk("| w->list_entry: [DP:%p/%p|SP:%p/%p|PRI:%d]\n", - w->list_entry.plist.prio_list.prev, w->list_entry.plist.prio_list.next, - w->list_entry.plist.node_list.prev, w->list_entry.plist.node_list.next, - w->list_entry.prio); - printk("| w->pi_list_entry: [DP:%p/%p|SP:%p/%p|PRI:%d]\n", - w->pi_list_entry.plist.prio_list.prev, w->pi_list_entry.plist.prio_list.next, - w->pi_list_entry.plist.node_list.prev, w->pi_list_entry.plist.node_list.next, - w->pi_list_entry.prio); - printk("\n| lock:\n"); - printk_lock(w->lock, 1); - printk("| w->ti->task:\n"); - printk_task(w->task); - printk("| blocked at: "); - print_symbol("%s\n", w->ip); - printk("-------------------------\n"); -} - -static void show_task_locks(task_t *p) -{ - switch (p->state) { - case TASK_RUNNING: printk("R"); break; - case TASK_INTERRUPTIBLE: printk("S"); break; - case TASK_UNINTERRUPTIBLE: printk("D"); break; - case TASK_STOPPED: printk("T"); break; - case EXIT_ZOMBIE: printk("Z"); break; - case EXIT_DEAD: printk("X"); break; - default: printk("?"); break; - } - printk_task(p); - if (p->pi_blocked_on) { - struct rt_mutex *lock = p->pi_blocked_on->lock; - - printk(" blocked on:"); - printk_lock(lock, 1); - } else - printk(" (not blocked)\n"); -} - -void rt_mutex_show_held_locks(task_t *task, int verbose) -{ - struct list_head *curr, *cursor = NULL; - struct rt_mutex *lock; - task_t *t; - unsigned long flags; - int count = 0; - - if (!rt_trace_on) - return; - - if (verbose) { - printk("------------------------------\n"); - printk("| showing all locks held by: | ("); - printk_task_short(task); - printk("):\n"); - printk("------------------------------\n"); - } - -next: - spin_lock_irqsave(&task->held_list_lock, flags); - list_for_each(curr, &task->held_list_head) { - if (cursor && curr != cursor) - continue; - lock = list_entry(curr, struct rt_mutex, held_list_entry); - t = rt_mutex_owner(lock); - WARN_ON(t != task); - count++; - cursor = curr->next; - spin_unlock_irqrestore(&task->held_list_lock, flags); - - printk("\n#%03d: ", count); - printk_lock(lock, 0); - goto next; - } - spin_unlock_irqrestore(&task->held_list_lock, flags); - - printk("\n"); -} - -void rt_mutex_show_all_locks(void) -{ - task_t *g, *p; - int count = 10; - int unlock = 1; - - printk("\n"); - printk("----------------------\n"); - printk("| showing all tasks: |\n"); - printk("----------------------\n"); - - /* - * Here we try to get the tasklist_lock as hard as possible, - * if not successful after 2 seconds we ignore it (but keep - * trying). This is to enable a debug printout even if a - * tasklist_lock-holding task deadlocks or crashes. - */ -retry: - if (!read_trylock(&tasklist_lock)) { - if (count == 10) - printk("hm, tasklist_lock locked, retrying... "); - if (count) { - count--; - printk(" #%d", 10-count); - mdelay(200); - goto retry; - } - printk(" ignoring it.\n"); - unlock = 0; - } - if (count != 10) - printk(" locked it.\n"); - - do_each_thread(g, p) { - show_task_locks(p); - if (!unlock) - if (read_trylock(&tasklist_lock)) - unlock = 1; - } while_each_thread(g, p); - - printk("\n"); - - printk("-----------------------------------------\n"); - printk("| showing all locks held in the system: |\n"); - printk("-----------------------------------------\n"); - - do_each_thread(g, p) { - rt_mutex_show_held_locks(p, 0); - if (!unlock) - if (read_trylock(&tasklist_lock)) - unlock = 1; - } while_each_thread(g, p); - - - printk("=============================================\n\n"); - - if (unlock) - read_unlock(&tasklist_lock); -} - -void rt_mutex_debug_check_no_locks_held(task_t *task) -{ - struct rt_mutex_waiter *w; - struct list_head *curr; - struct rt_mutex *lock; - - if (!rt_trace_on) - return; - if (!rt_prio(task->normal_prio) && rt_prio(task->prio)) { - printk("BUG: PI priority boost leaked!\n"); - printk_task(task); - printk("\n"); - } - if (list_empty(&task->held_list_head)) - return; - - spin_lock(&task->pi_lock); - plist_for_each_entry(w, &task->pi_waiters, pi_list_entry) { - TRACE_OFF(); - - printk("hm, PI interest held at exit time? Task:\n"); - printk_task(task); - printk_waiter(w); - return; - } - spin_unlock(&task->pi_lock); - - list_for_each(curr, &task->held_list_head) { - lock = list_entry(curr, struct rt_mutex, held_list_entry); - - printk("BUG: %s/%d, lock held at task exit time!\n", - task->comm, task->pid); - printk_lock(lock, 1); - if (rt_mutex_owner(lock) != task) - printk("exiting task is not even the owner??\n"); - } -} - -int rt_mutex_debug_check_no_locks_freed(const void *from, unsigned long len) -{ - const void *to = from + len; - struct list_head *curr; - struct rt_mutex *lock; - unsigned long flags; - void *lock_addr; - - if (!rt_trace_on) - return 0; - - spin_lock_irqsave(¤t->held_list_lock, flags); - list_for_each(curr, ¤t->held_list_head) { - lock = list_entry(curr, struct rt_mutex, held_list_entry); - lock_addr = lock; - if (lock_addr < from || lock_addr >= to) - continue; - TRACE_OFF(); - - printk("BUG: %s/%d, active lock [%p(%p-%p)] freed!\n", - current->comm, current->pid, lock, from, to); - dump_stack(); - printk_lock(lock, 1); - if (rt_mutex_owner(lock) != current) - printk("freeing task is not even the owner??\n"); - return 1; - } - spin_unlock_irqrestore(¤t->held_list_lock, flags); - - return 0; -} - -void rt_mutex_debug_task_free(struct task_struct *task) -{ - WARN_ON(!plist_head_empty(&task->pi_waiters)); - WARN_ON(task->pi_blocked_on); -} - -/* - * We fill out the fields in the waiter to store the information about - * the deadlock. We print when we return. act_waiter can be NULL in - * case of a remove waiter operation. - */ -void debug_rt_mutex_deadlock(int detect, struct rt_mutex_waiter *act_waiter, - struct rt_mutex *lock) -{ - struct task_struct *task; - - if (!rt_trace_on || detect || !act_waiter) - return; - - task = rt_mutex_owner(act_waiter->lock); - if (task && task != current) { - act_waiter->deadlock_task_pid = task->pid; - act_waiter->deadlock_lock = lock; - } -} - -void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter) -{ - struct task_struct *task; - - if (!waiter->deadlock_lock || !rt_trace_on) - return; - - task = find_task_by_pid(waiter->deadlock_task_pid); - if (!task) - return; - - TRACE_OFF_NOLOCK(); - - printk("\n============================================\n"); - printk( "[ BUG: circular locking deadlock detected! ]\n"); - printk( "--------------------------------------------\n"); - printk("%s/%d is deadlocking current task %s/%d\n\n", - task->comm, task->pid, current->comm, current->pid); - - printk("\n1) %s/%d is trying to acquire this lock:\n", - current->comm, current->pid); - printk_lock(waiter->lock, 1); - - printk("... trying at: "); - print_symbol("%s\n", waiter->ip); - - printk("\n2) %s/%d is blocked on this lock:\n", task->comm, task->pid); - printk_lock(waiter->deadlock_lock, 1); - - rt_mutex_show_held_locks(current, 1); - rt_mutex_show_held_locks(task, 1); - - printk("\n%s/%d's [blocked] stackdump:\n\n", task->comm, task->pid); - show_stack(task, NULL); - printk("\n%s/%d's [current] stackdump:\n\n", - current->comm, current->pid); - dump_stack(); - rt_mutex_show_all_locks(); - printk("[ turning off deadlock detection." - "Please report this trace. ]\n\n"); - local_irq_disable(); -} - -void debug_rt_mutex_lock(struct rt_mutex *lock __IP_DECL__) -{ - unsigned long flags; - - if (rt_trace_on) { - TRACE_WARN_ON_LOCKED(!list_empty(&lock->held_list_entry)); - - spin_lock_irqsave(¤t->held_list_lock, flags); - list_add_tail(&lock->held_list_entry, ¤t->held_list_head); - spin_unlock_irqrestore(¤t->held_list_lock, flags); - - lock->acquire_ip = ip; - } -} - -void debug_rt_mutex_unlock(struct rt_mutex *lock) -{ - unsigned long flags; - - if (rt_trace_on) { - TRACE_WARN_ON_LOCKED(rt_mutex_owner(lock) != current); - TRACE_WARN_ON_LOCKED(list_empty(&lock->held_list_entry)); - - spin_lock_irqsave(¤t->held_list_lock, flags); - list_del_init(&lock->held_list_entry); - spin_unlock_irqrestore(¤t->held_list_lock, flags); - } -} - -void debug_rt_mutex_proxy_lock(struct rt_mutex *lock, - struct task_struct *powner __IP_DECL__) -{ - unsigned long flags; - - if (rt_trace_on) { - TRACE_WARN_ON_LOCKED(!list_empty(&lock->held_list_entry)); - - spin_lock_irqsave(&powner->held_list_lock, flags); - list_add_tail(&lock->held_list_entry, &powner->held_list_head); - spin_unlock_irqrestore(&powner->held_list_lock, flags); - - lock->acquire_ip = ip; - } -} - -void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock) -{ - unsigned long flags; - - if (rt_trace_on) { - struct task_struct *owner = rt_mutex_owner(lock); - - TRACE_WARN_ON_LOCKED(!owner); - TRACE_WARN_ON_LOCKED(list_empty(&lock->held_list_entry)); - - spin_lock_irqsave(&owner->held_list_lock, flags); - list_del_init(&lock->held_list_entry); - spin_unlock_irqrestore(&owner->held_list_lock, flags); - } -} - -void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter) -{ - memset(waiter, 0x11, sizeof(*waiter)); - plist_node_init(&waiter->list_entry, MAX_PRIO); - plist_node_init(&waiter->pi_list_entry, MAX_PRIO); -} - -void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter) -{ - TRACE_WARN_ON(!plist_node_empty(&waiter->list_entry)); - TRACE_WARN_ON(!plist_node_empty(&waiter->pi_list_entry)); - TRACE_WARN_ON(waiter->task); - memset(waiter, 0x22, sizeof(*waiter)); -} - -void debug_rt_mutex_init(struct rt_mutex *lock, const char *name) -{ - void *addr = lock; - - if (rt_trace_on) { - rt_mutex_debug_check_no_locks_freed(addr, - sizeof(struct rt_mutex)); - INIT_LIST_HEAD(&lock->held_list_entry); - lock->name = name; - } -} - -void rt_mutex_deadlock_account_lock(struct rt_mutex *lock, task_t *task) -{ -} - -void rt_mutex_deadlock_account_unlock(struct task_struct *task) -{ -} - diff --git a/trunk/kernel/rtmutex-debug.h b/trunk/kernel/rtmutex-debug.h deleted file mode 100644 index 7612fbc62d70..000000000000 --- a/trunk/kernel/rtmutex-debug.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * RT-Mutexes: blocking mutual exclusion locks with PI support - * - * started by Ingo Molnar and Thomas Gleixner: - * - * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar - * Copyright (C) 2006, Timesys Corp., Thomas Gleixner - * - * This file contains macros used solely by rtmutex.c. Debug version. - */ - -#define __IP_DECL__ , unsigned long ip -#define __IP__ , ip -#define __RET_IP__ , (unsigned long)__builtin_return_address(0) - -extern void -rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task); -extern void rt_mutex_deadlock_account_unlock(struct task_struct *task); -extern void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter); -extern void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter); -extern void debug_rt_mutex_init(struct rt_mutex *lock, const char *name); -extern void debug_rt_mutex_lock(struct rt_mutex *lock __IP_DECL__); -extern void debug_rt_mutex_unlock(struct rt_mutex *lock); -extern void debug_rt_mutex_proxy_lock(struct rt_mutex *lock, - struct task_struct *powner __IP_DECL__); -extern void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock); -extern void debug_rt_mutex_deadlock(int detect, struct rt_mutex_waiter *waiter, - struct rt_mutex *lock); -extern void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter); -# define debug_rt_mutex_reset_waiter(w) \ - do { (w)->deadlock_lock = NULL; } while (0) - -static inline int debug_rt_mutex_detect_deadlock(struct rt_mutex_waiter *waiter, - int detect) -{ - return (waiter != NULL); -} diff --git a/trunk/kernel/rtmutex-tester.c b/trunk/kernel/rtmutex-tester.c deleted file mode 100644 index e82c2f848249..000000000000 --- a/trunk/kernel/rtmutex-tester.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * RT-Mutex-tester: scriptable tester for rt mutexes - * - * started by Thomas Gleixner: - * - * Copyright (C) 2006, Timesys Corp., Thomas Gleixner - * - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rtmutex.h" - -#define MAX_RT_TEST_THREADS 8 -#define MAX_RT_TEST_MUTEXES 8 - -static spinlock_t rttest_lock; -static atomic_t rttest_event; - -struct test_thread_data { - int opcode; - int opdata; - int mutexes[MAX_RT_TEST_MUTEXES]; - int bkl; - int event; - struct sys_device sysdev; -}; - -static struct test_thread_data thread_data[MAX_RT_TEST_THREADS]; -static task_t *threads[MAX_RT_TEST_THREADS]; -static struct rt_mutex mutexes[MAX_RT_TEST_MUTEXES]; - -enum test_opcodes { - RTTEST_NOP = 0, - RTTEST_SCHEDOT, /* 1 Sched other, data = nice */ - RTTEST_SCHEDRT, /* 2 Sched fifo, data = prio */ - RTTEST_LOCK, /* 3 Lock uninterruptible, data = lockindex */ - RTTEST_LOCKNOWAIT, /* 4 Lock uninterruptible no wait in wakeup, data = lockindex */ - RTTEST_LOCKINT, /* 5 Lock interruptible, data = lockindex */ - RTTEST_LOCKINTNOWAIT, /* 6 Lock interruptible no wait in wakeup, data = lockindex */ - RTTEST_LOCKCONT, /* 7 Continue locking after the wakeup delay */ - RTTEST_UNLOCK, /* 8 Unlock, data = lockindex */ - RTTEST_LOCKBKL, /* 9 Lock BKL */ - RTTEST_UNLOCKBKL, /* 10 Unlock BKL */ - RTTEST_SIGNAL, /* 11 Signal other test thread, data = thread id */ - RTTEST_RESETEVENT = 98, /* 98 Reset event counter */ - RTTEST_RESET = 99, /* 99 Reset all pending operations */ -}; - -static int handle_op(struct test_thread_data *td, int lockwakeup) -{ - int i, id, ret = -EINVAL; - - switch(td->opcode) { - - case RTTEST_NOP: - return 0; - - case RTTEST_LOCKCONT: - td->mutexes[td->opdata] = 1; - td->event = atomic_add_return(1, &rttest_event); - return 0; - - case RTTEST_RESET: - for (i = 0; i < MAX_RT_TEST_MUTEXES; i++) { - if (td->mutexes[i] == 4) { - rt_mutex_unlock(&mutexes[i]); - td->mutexes[i] = 0; - } - } - - if (!lockwakeup && td->bkl == 4) { - unlock_kernel(); - td->bkl = 0; - } - return 0; - - case RTTEST_RESETEVENT: - atomic_set(&rttest_event, 0); - return 0; - - default: - if (lockwakeup) - return ret; - } - - switch(td->opcode) { - - case RTTEST_LOCK: - case RTTEST_LOCKNOWAIT: - id = td->opdata; - if (id < 0 || id >= MAX_RT_TEST_MUTEXES) - return ret; - - td->mutexes[id] = 1; - td->event = atomic_add_return(1, &rttest_event); - rt_mutex_lock(&mutexes[id]); - td->event = atomic_add_return(1, &rttest_event); - td->mutexes[id] = 4; - return 0; - - case RTTEST_LOCKINT: - case RTTEST_LOCKINTNOWAIT: - id = td->opdata; - if (id < 0 || id >= MAX_RT_TEST_MUTEXES) - return ret; - - td->mutexes[id] = 1; - td->event = atomic_add_return(1, &rttest_event); - ret = rt_mutex_lock_interruptible(&mutexes[id], 0); - td->event = atomic_add_return(1, &rttest_event); - td->mutexes[id] = ret ? 0 : 4; - return ret ? -EINTR : 0; - - case RTTEST_UNLOCK: - id = td->opdata; - if (id < 0 || id >= MAX_RT_TEST_MUTEXES || td->mutexes[id] != 4) - return ret; - - td->event = atomic_add_return(1, &rttest_event); - rt_mutex_unlock(&mutexes[id]); - td->event = atomic_add_return(1, &rttest_event); - td->mutexes[id] = 0; - return 0; - - case RTTEST_LOCKBKL: - if (td->bkl) - return 0; - td->bkl = 1; - lock_kernel(); - td->bkl = 4; - return 0; - - case RTTEST_UNLOCKBKL: - if (td->bkl != 4) - break; - unlock_kernel(); - td->bkl = 0; - return 0; - - default: - break; - } - return ret; -} - -/* - * Schedule replacement for rtsem_down(). Only called for threads with - * PF_MUTEX_TESTER set. - * - * This allows us to have finegrained control over the event flow. - * - */ -void schedule_rt_mutex_test(struct rt_mutex *mutex) -{ - int tid, op, dat; - struct test_thread_data *td; - - /* We have to lookup the task */ - for (tid = 0; tid < MAX_RT_TEST_THREADS; tid++) { - if (threads[tid] == current) - break; - } - - BUG_ON(tid == MAX_RT_TEST_THREADS); - - td = &thread_data[tid]; - - op = td->opcode; - dat = td->opdata; - - switch (op) { - case RTTEST_LOCK: - case RTTEST_LOCKINT: - case RTTEST_LOCKNOWAIT: - case RTTEST_LOCKINTNOWAIT: - if (mutex != &mutexes[dat]) - break; - - if (td->mutexes[dat] != 1) - break; - - td->mutexes[dat] = 2; - td->event = atomic_add_return(1, &rttest_event); - break; - - case RTTEST_LOCKBKL: - default: - break; - } - - schedule(); - - - switch (op) { - case RTTEST_LOCK: - case RTTEST_LOCKINT: - if (mutex != &mutexes[dat]) - return; - - if (td->mutexes[dat] != 2) - return; - - td->mutexes[dat] = 3; - td->event = atomic_add_return(1, &rttest_event); - break; - - case RTTEST_LOCKNOWAIT: - case RTTEST_LOCKINTNOWAIT: - if (mutex != &mutexes[dat]) - return; - - if (td->mutexes[dat] != 2) - return; - - td->mutexes[dat] = 1; - td->event = atomic_add_return(1, &rttest_event); - return; - - case RTTEST_LOCKBKL: - return; - default: - return; - } - - td->opcode = 0; - - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - - if (td->opcode > 0) { - int ret; - - set_current_state(TASK_RUNNING); - ret = handle_op(td, 1); - set_current_state(TASK_INTERRUPTIBLE); - if (td->opcode == RTTEST_LOCKCONT) - break; - td->opcode = ret; - } - - /* Wait for the next command to be executed */ - schedule(); - } - - /* Restore previous command and data */ - td->opcode = op; - td->opdata = dat; -} - -static int test_func(void *data) -{ - struct test_thread_data *td = data; - int ret; - - current->flags |= PF_MUTEX_TESTER; - allow_signal(SIGHUP); - - for(;;) { - - set_current_state(TASK_INTERRUPTIBLE); - - if (td->opcode > 0) { - set_current_state(TASK_RUNNING); - ret = handle_op(td, 0); - set_current_state(TASK_INTERRUPTIBLE); - td->opcode = ret; - } - - /* Wait for the next command to be executed */ - schedule(); - - if (signal_pending(current)) - flush_signals(current); - - if(kthread_should_stop()) - break; - } - return 0; -} - -/** - * sysfs_test_command - interface for test commands - * @dev: thread reference - * @buf: command for actual step - * @count: length of buffer - * - * command syntax: - * - * opcode:data - */ -static ssize_t sysfs_test_command(struct sys_device *dev, const char *buf, - size_t count) -{ - struct sched_param schedpar; - struct test_thread_data *td; - char cmdbuf[32]; - int op, dat, tid, ret; - - td = container_of(dev, struct test_thread_data, sysdev); - tid = td->sysdev.id; - - /* strings from sysfs write are not 0 terminated! */ - if (count >= sizeof(cmdbuf)) - return -EINVAL; - - /* strip of \n: */ - if (buf[count-1] == '\n') - count--; - if (count < 1) - return -EINVAL; - - memcpy(cmdbuf, buf, count); - cmdbuf[count] = 0; - - if (sscanf(cmdbuf, "%d:%d", &op, &dat) != 2) - return -EINVAL; - - switch (op) { - case RTTEST_SCHEDOT: - schedpar.sched_priority = 0; - ret = sched_setscheduler(threads[tid], SCHED_NORMAL, &schedpar); - if (ret) - return ret; - set_user_nice(current, 0); - break; - - case RTTEST_SCHEDRT: - schedpar.sched_priority = dat; - ret = sched_setscheduler(threads[tid], SCHED_FIFO, &schedpar); - if (ret) - return ret; - break; - - case RTTEST_SIGNAL: - send_sig(SIGHUP, threads[tid], 0); - break; - - default: - if (td->opcode > 0) - return -EBUSY; - td->opdata = dat; - td->opcode = op; - wake_up_process(threads[tid]); - } - - return count; -} - -/** - * sysfs_test_status - sysfs interface for rt tester - * @dev: thread to query - * @buf: char buffer to be filled with thread status info - */ -static ssize_t sysfs_test_status(struct sys_device *dev, char *buf) -{ - struct test_thread_data *td; - char *curr = buf; - task_t *tsk; - int i; - - td = container_of(dev, struct test_thread_data, sysdev); - tsk = threads[td->sysdev.id]; - - spin_lock(&rttest_lock); - - curr += sprintf(curr, - "O: %4d, E:%8d, S: 0x%08lx, P: %4d, N: %4d, B: %p, K: %d, M:", - td->opcode, td->event, tsk->state, - (MAX_RT_PRIO - 1) - tsk->prio, - (MAX_RT_PRIO - 1) - tsk->normal_prio, - tsk->pi_blocked_on, td->bkl); - - for (i = MAX_RT_TEST_MUTEXES - 1; i >=0 ; i--) - curr += sprintf(curr, "%d", td->mutexes[i]); - - spin_unlock(&rttest_lock); - - curr += sprintf(curr, ", T: %p, R: %p\n", tsk, - mutexes[td->sysdev.id].owner); - - return curr - buf; -} - -static SYSDEV_ATTR(status, 0600, sysfs_test_status, NULL); -static SYSDEV_ATTR(command, 0600, NULL, sysfs_test_command); - -static struct sysdev_class rttest_sysclass = { - set_kset_name("rttest"), -}; - -static int init_test_thread(int id) -{ - thread_data[id].sysdev.cls = &rttest_sysclass; - thread_data[id].sysdev.id = id; - - threads[id] = kthread_run(test_func, &thread_data[id], "rt-test-%d", id); - if (IS_ERR(threads[id])) - return PTR_ERR(threads[id]); - - return sysdev_register(&thread_data[id].sysdev); -} - -static int init_rttest(void) -{ - int ret, i; - - spin_lock_init(&rttest_lock); - - for (i = 0; i < MAX_RT_TEST_MUTEXES; i++) - rt_mutex_init(&mutexes[i]); - - ret = sysdev_class_register(&rttest_sysclass); - if (ret) - return ret; - - for (i = 0; i < MAX_RT_TEST_THREADS; i++) { - ret = init_test_thread(i); - if (ret) - break; - ret = sysdev_create_file(&thread_data[i].sysdev, &attr_status); - if (ret) - break; - ret = sysdev_create_file(&thread_data[i].sysdev, &attr_command); - if (ret) - break; - } - - printk("Initializing RT-Tester: %s\n", ret ? "Failed" : "OK" ); - - return ret; -} - -device_initcall(init_rttest); diff --git a/trunk/kernel/rtmutex.c b/trunk/kernel/rtmutex.c deleted file mode 100644 index 45d61016da57..000000000000 --- a/trunk/kernel/rtmutex.c +++ /dev/null @@ -1,990 +0,0 @@ -/* - * RT-Mutexes: simple blocking mutual exclusion locks with PI support - * - * started by Ingo Molnar and Thomas Gleixner. - * - * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar - * Copyright (C) 2005-2006 Timesys Corp., Thomas Gleixner - * Copyright (C) 2005 Kihon Technologies Inc., Steven Rostedt - * Copyright (C) 2006 Esben Nielsen - */ -#include -#include -#include -#include - -#include "rtmutex_common.h" - -#ifdef CONFIG_DEBUG_RT_MUTEXES -# include "rtmutex-debug.h" -#else -# include "rtmutex.h" -#endif - -/* - * lock->owner state tracking: - * - * lock->owner holds the task_struct pointer of the owner. Bit 0 and 1 - * are used to keep track of the "owner is pending" and "lock has - * waiters" state. - * - * owner bit1 bit0 - * NULL 0 0 lock is free (fast acquire possible) - * NULL 0 1 invalid state - * NULL 1 0 Transitional State* - * NULL 1 1 invalid state - * taskpointer 0 0 lock is held (fast release possible) - * taskpointer 0 1 task is pending owner - * taskpointer 1 0 lock is held and has waiters - * taskpointer 1 1 task is pending owner and lock has more waiters - * - * Pending ownership is assigned to the top (highest priority) - * waiter of the lock, when the lock is released. The thread is woken - * up and can now take the lock. Until the lock is taken (bit 0 - * cleared) a competing higher priority thread can steal the lock - * which puts the woken up thread back on the waiters list. - * - * The fast atomic compare exchange based acquire and release is only - * possible when bit 0 and 1 of lock->owner are 0. - * - * (*) There's a small time where the owner can be NULL and the - * "lock has waiters" bit is set. This can happen when grabbing the lock. - * To prevent a cmpxchg of the owner releasing the lock, we need to set this - * bit before looking at the lock, hence the reason this is a transitional - * state. - */ - -static void -rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner, - unsigned long mask) -{ - unsigned long val = (unsigned long)owner | mask; - - if (rt_mutex_has_waiters(lock)) - val |= RT_MUTEX_HAS_WAITERS; - - lock->owner = (struct task_struct *)val; -} - -static inline void clear_rt_mutex_waiters(struct rt_mutex *lock) -{ - lock->owner = (struct task_struct *) - ((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS); -} - -static void fixup_rt_mutex_waiters(struct rt_mutex *lock) -{ - if (!rt_mutex_has_waiters(lock)) - clear_rt_mutex_waiters(lock); -} - -/* - * We can speed up the acquire/release, if the architecture - * supports cmpxchg and if there's no debugging state to be set up - */ -#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES) -# define rt_mutex_cmpxchg(l,c,n) (cmpxchg(&l->owner, c, n) == c) -static inline void mark_rt_mutex_waiters(struct rt_mutex *lock) -{ - unsigned long owner, *p = (unsigned long *) &lock->owner; - - do { - owner = *p; - } while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner); -} -#else -# define rt_mutex_cmpxchg(l,c,n) (0) -static inline void mark_rt_mutex_waiters(struct rt_mutex *lock) -{ - lock->owner = (struct task_struct *) - ((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS); -} -#endif - -/* - * Calculate task priority from the waiter list priority - * - * Return task->normal_prio when the waiter list is empty or when - * the waiter is not allowed to do priority boosting - */ -int rt_mutex_getprio(struct task_struct *task) -{ - if (likely(!task_has_pi_waiters(task))) - return task->normal_prio; - - return min(task_top_pi_waiter(task)->pi_list_entry.prio, - task->normal_prio); -} - -/* - * Adjust the priority of a task, after its pi_waiters got modified. - * - * This can be both boosting and unboosting. task->pi_lock must be held. - */ -static void __rt_mutex_adjust_prio(struct task_struct *task) -{ - int prio = rt_mutex_getprio(task); - - if (task->prio != prio) - rt_mutex_setprio(task, prio); -} - -/* - * Adjust task priority (undo boosting). Called from the exit path of - * rt_mutex_slowunlock() and rt_mutex_slowlock(). - * - * (Note: We do this outside of the protection of lock->wait_lock to - * allow the lock to be taken while or before we readjust the priority - * of task. We do not use the spin_xx_mutex() variants here as we are - * outside of the debug path.) - */ -static void rt_mutex_adjust_prio(struct task_struct *task) -{ - unsigned long flags; - - spin_lock_irqsave(&task->pi_lock, flags); - __rt_mutex_adjust_prio(task); - spin_unlock_irqrestore(&task->pi_lock, flags); -} - -/* - * Max number of times we'll walk the boosting chain: - */ -int max_lock_depth = 1024; - -/* - * Adjust the priority chain. Also used for deadlock detection. - * Decreases task's usage by one - may thus free the task. - * Returns 0 or -EDEADLK. - */ -static int rt_mutex_adjust_prio_chain(task_t *task, - int deadlock_detect, - struct rt_mutex *orig_lock, - struct rt_mutex_waiter *orig_waiter, - struct task_struct *top_task - __IP_DECL__) -{ - struct rt_mutex *lock; - struct rt_mutex_waiter *waiter, *top_waiter = orig_waiter; - int detect_deadlock, ret = 0, depth = 0; - unsigned long flags; - - detect_deadlock = debug_rt_mutex_detect_deadlock(orig_waiter, - deadlock_detect); - - /* - * The (de)boosting is a step by step approach with a lot of - * pitfalls. We want this to be preemptible and we want hold a - * maximum of two locks per step. So we have to check - * carefully whether things change under us. - */ - again: - if (++depth > max_lock_depth) { - static int prev_max; - - /* - * Print this only once. If the admin changes the limit, - * print a new message when reaching the limit again. - */ - if (prev_max != max_lock_depth) { - prev_max = max_lock_depth; - printk(KERN_WARNING "Maximum lock depth %d reached " - "task: %s (%d)\n", max_lock_depth, - top_task->comm, top_task->pid); - } - put_task_struct(task); - - return deadlock_detect ? -EDEADLK : 0; - } - retry: - /* - * Task can not go away as we did a get_task() before ! - */ - spin_lock_irqsave(&task->pi_lock, flags); - - waiter = task->pi_blocked_on; - /* - * Check whether the end of the boosting chain has been - * reached or the state of the chain has changed while we - * dropped the locks. - */ - if (!waiter || !waiter->task) - goto out_unlock_pi; - - if (top_waiter && (!task_has_pi_waiters(task) || - top_waiter != task_top_pi_waiter(task))) - goto out_unlock_pi; - - /* - * When deadlock detection is off then we check, if further - * priority adjustment is necessary. - */ - if (!detect_deadlock && waiter->list_entry.prio == task->prio) - goto out_unlock_pi; - - lock = waiter->lock; - if (!spin_trylock(&lock->wait_lock)) { - spin_unlock_irqrestore(&task->pi_lock, flags); - cpu_relax(); - goto retry; - } - - /* Deadlock detection */ - if (lock == orig_lock || rt_mutex_owner(lock) == top_task) { - debug_rt_mutex_deadlock(deadlock_detect, orig_waiter, lock); - spin_unlock(&lock->wait_lock); - ret = deadlock_detect ? -EDEADLK : 0; - goto out_unlock_pi; - } - - top_waiter = rt_mutex_top_waiter(lock); - - /* Requeue the waiter */ - plist_del(&waiter->list_entry, &lock->wait_list); - waiter->list_entry.prio = task->prio; - plist_add(&waiter->list_entry, &lock->wait_list); - - /* Release the task */ - spin_unlock_irqrestore(&task->pi_lock, flags); - put_task_struct(task); - - /* Grab the next task */ - task = rt_mutex_owner(lock); - spin_lock_irqsave(&task->pi_lock, flags); - - if (waiter == rt_mutex_top_waiter(lock)) { - /* Boost the owner */ - plist_del(&top_waiter->pi_list_entry, &task->pi_waiters); - waiter->pi_list_entry.prio = waiter->list_entry.prio; - plist_add(&waiter->pi_list_entry, &task->pi_waiters); - __rt_mutex_adjust_prio(task); - - } else if (top_waiter == waiter) { - /* Deboost the owner */ - plist_del(&waiter->pi_list_entry, &task->pi_waiters); - waiter = rt_mutex_top_waiter(lock); - waiter->pi_list_entry.prio = waiter->list_entry.prio; - plist_add(&waiter->pi_list_entry, &task->pi_waiters); - __rt_mutex_adjust_prio(task); - } - - get_task_struct(task); - spin_unlock_irqrestore(&task->pi_lock, flags); - - top_waiter = rt_mutex_top_waiter(lock); - spin_unlock(&lock->wait_lock); - - if (!detect_deadlock && waiter != top_waiter) - goto out_put_task; - - goto again; - - out_unlock_pi: - spin_unlock_irqrestore(&task->pi_lock, flags); - out_put_task: - put_task_struct(task); - return ret; -} - -/* - * Optimization: check if we can steal the lock from the - * assigned pending owner [which might not have taken the - * lock yet]: - */ -static inline int try_to_steal_lock(struct rt_mutex *lock) -{ - struct task_struct *pendowner = rt_mutex_owner(lock); - struct rt_mutex_waiter *next; - unsigned long flags; - - if (!rt_mutex_owner_pending(lock)) - return 0; - - if (pendowner == current) - return 1; - - spin_lock_irqsave(&pendowner->pi_lock, flags); - if (current->prio >= pendowner->prio) { - spin_unlock_irqrestore(&pendowner->pi_lock, flags); - return 0; - } - - /* - * Check if a waiter is enqueued on the pending owners - * pi_waiters list. Remove it and readjust pending owners - * priority. - */ - if (likely(!rt_mutex_has_waiters(lock))) { - spin_unlock_irqrestore(&pendowner->pi_lock, flags); - return 1; - } - - /* No chain handling, pending owner is not blocked on anything: */ - next = rt_mutex_top_waiter(lock); - plist_del(&next->pi_list_entry, &pendowner->pi_waiters); - __rt_mutex_adjust_prio(pendowner); - spin_unlock_irqrestore(&pendowner->pi_lock, flags); - - /* - * We are going to steal the lock and a waiter was - * enqueued on the pending owners pi_waiters queue. So - * we have to enqueue this waiter into - * current->pi_waiters list. This covers the case, - * where current is boosted because it holds another - * lock and gets unboosted because the booster is - * interrupted, so we would delay a waiter with higher - * priority as current->normal_prio. - * - * Note: in the rare case of a SCHED_OTHER task changing - * its priority and thus stealing the lock, next->task - * might be current: - */ - if (likely(next->task != current)) { - spin_lock_irqsave(¤t->pi_lock, flags); - plist_add(&next->pi_list_entry, ¤t->pi_waiters); - __rt_mutex_adjust_prio(current); - spin_unlock_irqrestore(¤t->pi_lock, flags); - } - return 1; -} - -/* - * Try to take an rt-mutex - * - * This fails - * - when the lock has a real owner - * - when a different pending owner exists and has higher priority than current - * - * Must be called with lock->wait_lock held. - */ -static int try_to_take_rt_mutex(struct rt_mutex *lock __IP_DECL__) -{ - /* - * We have to be careful here if the atomic speedups are - * enabled, such that, when - * - no other waiter is on the lock - * - the lock has been released since we did the cmpxchg - * the lock can be released or taken while we are doing the - * checks and marking the lock with RT_MUTEX_HAS_WAITERS. - * - * The atomic acquire/release aware variant of - * mark_rt_mutex_waiters uses a cmpxchg loop. After setting - * the WAITERS bit, the atomic release / acquire can not - * happen anymore and lock->wait_lock protects us from the - * non-atomic case. - * - * Note, that this might set lock->owner = - * RT_MUTEX_HAS_WAITERS in the case the lock is not contended - * any more. This is fixed up when we take the ownership. - * This is the transitional state explained at the top of this file. - */ - mark_rt_mutex_waiters(lock); - - if (rt_mutex_owner(lock) && !try_to_steal_lock(lock)) - return 0; - - /* We got the lock. */ - debug_rt_mutex_lock(lock __IP__); - - rt_mutex_set_owner(lock, current, 0); - - rt_mutex_deadlock_account_lock(lock, current); - - return 1; -} - -/* - * Task blocks on lock. - * - * Prepare waiter and propagate pi chain - * - * This must be called with lock->wait_lock held. - */ -static int task_blocks_on_rt_mutex(struct rt_mutex *lock, - struct rt_mutex_waiter *waiter, - int detect_deadlock - __IP_DECL__) -{ - struct rt_mutex_waiter *top_waiter = waiter; - task_t *owner = rt_mutex_owner(lock); - int boost = 0, res; - unsigned long flags; - - spin_lock_irqsave(¤t->pi_lock, flags); - __rt_mutex_adjust_prio(current); - waiter->task = current; - waiter->lock = lock; - plist_node_init(&waiter->list_entry, current->prio); - plist_node_init(&waiter->pi_list_entry, current->prio); - - /* Get the top priority waiter on the lock */ - if (rt_mutex_has_waiters(lock)) - top_waiter = rt_mutex_top_waiter(lock); - plist_add(&waiter->list_entry, &lock->wait_list); - - current->pi_blocked_on = waiter; - - spin_unlock_irqrestore(¤t->pi_lock, flags); - - if (waiter == rt_mutex_top_waiter(lock)) { - spin_lock_irqsave(&owner->pi_lock, flags); - plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters); - plist_add(&waiter->pi_list_entry, &owner->pi_waiters); - - __rt_mutex_adjust_prio(owner); - if (owner->pi_blocked_on) { - boost = 1; - /* gets dropped in rt_mutex_adjust_prio_chain()! */ - get_task_struct(owner); - } - spin_unlock_irqrestore(&owner->pi_lock, flags); - } - else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) { - spin_lock_irqsave(&owner->pi_lock, flags); - if (owner->pi_blocked_on) { - boost = 1; - /* gets dropped in rt_mutex_adjust_prio_chain()! */ - get_task_struct(owner); - } - spin_unlock_irqrestore(&owner->pi_lock, flags); - } - if (!boost) - return 0; - - spin_unlock(&lock->wait_lock); - - res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter, - current __IP__); - - spin_lock(&lock->wait_lock); - - return res; -} - -/* - * Wake up the next waiter on the lock. - * - * Remove the top waiter from the current tasks waiter list and from - * the lock waiter list. Set it as pending owner. Then wake it up. - * - * Called with lock->wait_lock held. - */ -static void wakeup_next_waiter(struct rt_mutex *lock) -{ - struct rt_mutex_waiter *waiter; - struct task_struct *pendowner; - unsigned long flags; - - spin_lock_irqsave(¤t->pi_lock, flags); - - waiter = rt_mutex_top_waiter(lock); - plist_del(&waiter->list_entry, &lock->wait_list); - - /* - * Remove it from current->pi_waiters. We do not adjust a - * possible priority boost right now. We execute wakeup in the - * boosted mode and go back to normal after releasing - * lock->wait_lock. - */ - plist_del(&waiter->pi_list_entry, ¤t->pi_waiters); - pendowner = waiter->task; - waiter->task = NULL; - - rt_mutex_set_owner(lock, pendowner, RT_MUTEX_OWNER_PENDING); - - spin_unlock_irqrestore(¤t->pi_lock, flags); - - /* - * Clear the pi_blocked_on variable and enqueue a possible - * waiter into the pi_waiters list of the pending owner. This - * prevents that in case the pending owner gets unboosted a - * waiter with higher priority than pending-owner->normal_prio - * is blocked on the unboosted (pending) owner. - */ - spin_lock_irqsave(&pendowner->pi_lock, flags); - - WARN_ON(!pendowner->pi_blocked_on); - WARN_ON(pendowner->pi_blocked_on != waiter); - WARN_ON(pendowner->pi_blocked_on->lock != lock); - - pendowner->pi_blocked_on = NULL; - - if (rt_mutex_has_waiters(lock)) { - struct rt_mutex_waiter *next; - - next = rt_mutex_top_waiter(lock); - plist_add(&next->pi_list_entry, &pendowner->pi_waiters); - } - spin_unlock_irqrestore(&pendowner->pi_lock, flags); - - wake_up_process(pendowner); -} - -/* - * Remove a waiter from a lock - * - * Must be called with lock->wait_lock held - */ -static void remove_waiter(struct rt_mutex *lock, - struct rt_mutex_waiter *waiter __IP_DECL__) -{ - int first = (waiter == rt_mutex_top_waiter(lock)); - int boost = 0; - task_t *owner = rt_mutex_owner(lock); - unsigned long flags; - - spin_lock_irqsave(¤t->pi_lock, flags); - plist_del(&waiter->list_entry, &lock->wait_list); - waiter->task = NULL; - current->pi_blocked_on = NULL; - spin_unlock_irqrestore(¤t->pi_lock, flags); - - if (first && owner != current) { - - spin_lock_irqsave(&owner->pi_lock, flags); - - plist_del(&waiter->pi_list_entry, &owner->pi_waiters); - - if (rt_mutex_has_waiters(lock)) { - struct rt_mutex_waiter *next; - - next = rt_mutex_top_waiter(lock); - plist_add(&next->pi_list_entry, &owner->pi_waiters); - } - __rt_mutex_adjust_prio(owner); - - if (owner->pi_blocked_on) { - boost = 1; - /* gets dropped in rt_mutex_adjust_prio_chain()! */ - get_task_struct(owner); - } - spin_unlock_irqrestore(&owner->pi_lock, flags); - } - - WARN_ON(!plist_node_empty(&waiter->pi_list_entry)); - - if (!boost) - return; - - spin_unlock(&lock->wait_lock); - - rt_mutex_adjust_prio_chain(owner, 0, lock, NULL, current __IP__); - - spin_lock(&lock->wait_lock); -} - -/* - * Recheck the pi chain, in case we got a priority setting - * - * Called from sched_setscheduler - */ -void rt_mutex_adjust_pi(struct task_struct *task) -{ - struct rt_mutex_waiter *waiter; - unsigned long flags; - - spin_lock_irqsave(&task->pi_lock, flags); - - waiter = task->pi_blocked_on; - if (!waiter || waiter->list_entry.prio == task->prio) { - spin_unlock_irqrestore(&task->pi_lock, flags); - return; - } - - /* gets dropped in rt_mutex_adjust_prio_chain()! */ - get_task_struct(task); - spin_unlock_irqrestore(&task->pi_lock, flags); - - rt_mutex_adjust_prio_chain(task, 0, NULL, NULL, task __RET_IP__); -} - -/* - * Slow path lock function: - */ -static int __sched -rt_mutex_slowlock(struct rt_mutex *lock, int state, - struct hrtimer_sleeper *timeout, - int detect_deadlock __IP_DECL__) -{ - struct rt_mutex_waiter waiter; - int ret = 0; - - debug_rt_mutex_init_waiter(&waiter); - waiter.task = NULL; - - spin_lock(&lock->wait_lock); - - /* Try to acquire the lock again: */ - if (try_to_take_rt_mutex(lock __IP__)) { - spin_unlock(&lock->wait_lock); - return 0; - } - - set_current_state(state); - - /* Setup the timer, when timeout != NULL */ - if (unlikely(timeout)) - hrtimer_start(&timeout->timer, timeout->timer.expires, - HRTIMER_ABS); - - for (;;) { - /* Try to acquire the lock: */ - if (try_to_take_rt_mutex(lock __IP__)) - break; - - /* - * TASK_INTERRUPTIBLE checks for signals and - * timeout. Ignored otherwise. - */ - if (unlikely(state == TASK_INTERRUPTIBLE)) { - /* Signal pending? */ - if (signal_pending(current)) - ret = -EINTR; - if (timeout && !timeout->task) - ret = -ETIMEDOUT; - if (ret) - break; - } - - /* - * waiter.task is NULL the first time we come here and - * when we have been woken up by the previous owner - * but the lock got stolen by a higher prio task. - */ - if (!waiter.task) { - ret = task_blocks_on_rt_mutex(lock, &waiter, - detect_deadlock __IP__); - /* - * If we got woken up by the owner then start loop - * all over without going into schedule to try - * to get the lock now: - */ - if (unlikely(!waiter.task)) - continue; - - if (unlikely(ret)) - break; - } - - spin_unlock(&lock->wait_lock); - - debug_rt_mutex_print_deadlock(&waiter); - - if (waiter.task) - schedule_rt_mutex(lock); - - spin_lock(&lock->wait_lock); - set_current_state(state); - } - - set_current_state(TASK_RUNNING); - - if (unlikely(waiter.task)) - remove_waiter(lock, &waiter __IP__); - - /* - * try_to_take_rt_mutex() sets the waiter bit - * unconditionally. We might have to fix that up. - */ - fixup_rt_mutex_waiters(lock); - - spin_unlock(&lock->wait_lock); - - /* Remove pending timer: */ - if (unlikely(timeout)) - hrtimer_cancel(&timeout->timer); - - /* - * Readjust priority, when we did not get the lock. We might - * have been the pending owner and boosted. Since we did not - * take the lock, the PI boost has to go. - */ - if (unlikely(ret)) - rt_mutex_adjust_prio(current); - - debug_rt_mutex_free_waiter(&waiter); - - return ret; -} - -/* - * Slow path try-lock function: - */ -static inline int -rt_mutex_slowtrylock(struct rt_mutex *lock __IP_DECL__) -{ - int ret = 0; - - spin_lock(&lock->wait_lock); - - if (likely(rt_mutex_owner(lock) != current)) { - - ret = try_to_take_rt_mutex(lock __IP__); - /* - * try_to_take_rt_mutex() sets the lock waiters - * bit unconditionally. Clean this up. - */ - fixup_rt_mutex_waiters(lock); - } - - spin_unlock(&lock->wait_lock); - - return ret; -} - -/* - * Slow path to release a rt-mutex: - */ -static void __sched -rt_mutex_slowunlock(struct rt_mutex *lock) -{ - spin_lock(&lock->wait_lock); - - debug_rt_mutex_unlock(lock); - - rt_mutex_deadlock_account_unlock(current); - - if (!rt_mutex_has_waiters(lock)) { - lock->owner = NULL; - spin_unlock(&lock->wait_lock); - return; - } - - wakeup_next_waiter(lock); - - spin_unlock(&lock->wait_lock); - - /* Undo pi boosting if necessary: */ - rt_mutex_adjust_prio(current); -} - -/* - * debug aware fast / slowpath lock,trylock,unlock - * - * The atomic acquire/release ops are compiled away, when either the - * architecture does not support cmpxchg or when debugging is enabled. - */ -static inline int -rt_mutex_fastlock(struct rt_mutex *lock, int state, - int detect_deadlock, - int (*slowfn)(struct rt_mutex *lock, int state, - struct hrtimer_sleeper *timeout, - int detect_deadlock __IP_DECL__)) -{ - if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) { - rt_mutex_deadlock_account_lock(lock, current); - return 0; - } else - return slowfn(lock, state, NULL, detect_deadlock __RET_IP__); -} - -static inline int -rt_mutex_timed_fastlock(struct rt_mutex *lock, int state, - struct hrtimer_sleeper *timeout, int detect_deadlock, - int (*slowfn)(struct rt_mutex *lock, int state, - struct hrtimer_sleeper *timeout, - int detect_deadlock __IP_DECL__)) -{ - if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) { - rt_mutex_deadlock_account_lock(lock, current); - return 0; - } else - return slowfn(lock, state, timeout, detect_deadlock __RET_IP__); -} - -static inline int -rt_mutex_fasttrylock(struct rt_mutex *lock, - int (*slowfn)(struct rt_mutex *lock __IP_DECL__)) -{ - if (likely(rt_mutex_cmpxchg(lock, NULL, current))) { - rt_mutex_deadlock_account_lock(lock, current); - return 1; - } - return slowfn(lock __RET_IP__); -} - -static inline void -rt_mutex_fastunlock(struct rt_mutex *lock, - void (*slowfn)(struct rt_mutex *lock)) -{ - if (likely(rt_mutex_cmpxchg(lock, current, NULL))) - rt_mutex_deadlock_account_unlock(current); - else - slowfn(lock); -} - -/** - * rt_mutex_lock - lock a rt_mutex - * - * @lock: the rt_mutex to be locked - */ -void __sched rt_mutex_lock(struct rt_mutex *lock) -{ - might_sleep(); - - rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, 0, rt_mutex_slowlock); -} -EXPORT_SYMBOL_GPL(rt_mutex_lock); - -/** - * rt_mutex_lock_interruptible - lock a rt_mutex interruptible - * - * @lock: the rt_mutex to be locked - * @detect_deadlock: deadlock detection on/off - * - * Returns: - * 0 on success - * -EINTR when interrupted by a signal - * -EDEADLK when the lock would deadlock (when deadlock detection is on) - */ -int __sched rt_mutex_lock_interruptible(struct rt_mutex *lock, - int detect_deadlock) -{ - might_sleep(); - - return rt_mutex_fastlock(lock, TASK_INTERRUPTIBLE, - detect_deadlock, rt_mutex_slowlock); -} -EXPORT_SYMBOL_GPL(rt_mutex_lock_interruptible); - -/** - * rt_mutex_lock_interruptible_ktime - lock a rt_mutex interruptible - * the timeout structure is provided - * by the caller - * - * @lock: the rt_mutex to be locked - * @timeout: timeout structure or NULL (no timeout) - * @detect_deadlock: deadlock detection on/off - * - * Returns: - * 0 on success - * -EINTR when interrupted by a signal - * -ETIMEOUT when the timeout expired - * -EDEADLK when the lock would deadlock (when deadlock detection is on) - */ -int -rt_mutex_timed_lock(struct rt_mutex *lock, struct hrtimer_sleeper *timeout, - int detect_deadlock) -{ - might_sleep(); - - return rt_mutex_timed_fastlock(lock, TASK_INTERRUPTIBLE, timeout, - detect_deadlock, rt_mutex_slowlock); -} -EXPORT_SYMBOL_GPL(rt_mutex_timed_lock); - -/** - * rt_mutex_trylock - try to lock a rt_mutex - * - * @lock: the rt_mutex to be locked - * - * Returns 1 on success and 0 on contention - */ -int __sched rt_mutex_trylock(struct rt_mutex *lock) -{ - return rt_mutex_fasttrylock(lock, rt_mutex_slowtrylock); -} -EXPORT_SYMBOL_GPL(rt_mutex_trylock); - -/** - * rt_mutex_unlock - unlock a rt_mutex - * - * @lock: the rt_mutex to be unlocked - */ -void __sched rt_mutex_unlock(struct rt_mutex *lock) -{ - rt_mutex_fastunlock(lock, rt_mutex_slowunlock); -} -EXPORT_SYMBOL_GPL(rt_mutex_unlock); - -/*** - * rt_mutex_destroy - mark a mutex unusable - * @lock: the mutex to be destroyed - * - * This function marks the mutex uninitialized, and any subsequent - * use of the mutex is forbidden. The mutex must not be locked when - * this function is called. - */ -void rt_mutex_destroy(struct rt_mutex *lock) -{ - WARN_ON(rt_mutex_is_locked(lock)); -#ifdef CONFIG_DEBUG_RT_MUTEXES - lock->magic = NULL; -#endif -} - -EXPORT_SYMBOL_GPL(rt_mutex_destroy); - -/** - * __rt_mutex_init - initialize the rt lock - * - * @lock: the rt lock to be initialized - * - * Initialize the rt lock to unlocked state. - * - * Initializing of a locked rt lock is not allowed - */ -void __rt_mutex_init(struct rt_mutex *lock, const char *name) -{ - lock->owner = NULL; - spin_lock_init(&lock->wait_lock); - plist_head_init(&lock->wait_list, &lock->wait_lock); - - debug_rt_mutex_init(lock, name); -} -EXPORT_SYMBOL_GPL(__rt_mutex_init); - -/** - * rt_mutex_init_proxy_locked - initialize and lock a rt_mutex on behalf of a - * proxy owner - * - * @lock: the rt_mutex to be locked - * @proxy_owner:the task to set as owner - * - * No locking. Caller has to do serializing itself - * Special API call for PI-futex support - */ -void rt_mutex_init_proxy_locked(struct rt_mutex *lock, - struct task_struct *proxy_owner) -{ - __rt_mutex_init(lock, NULL); - debug_rt_mutex_proxy_lock(lock, proxy_owner __RET_IP__); - rt_mutex_set_owner(lock, proxy_owner, 0); - rt_mutex_deadlock_account_lock(lock, proxy_owner); -} - -/** - * rt_mutex_proxy_unlock - release a lock on behalf of owner - * - * @lock: the rt_mutex to be locked - * - * No locking. Caller has to do serializing itself - * Special API call for PI-futex support - */ -void rt_mutex_proxy_unlock(struct rt_mutex *lock, - struct task_struct *proxy_owner) -{ - debug_rt_mutex_proxy_unlock(lock); - rt_mutex_set_owner(lock, NULL, 0); - rt_mutex_deadlock_account_unlock(proxy_owner); -} - -/** - * rt_mutex_next_owner - return the next owner of the lock - * - * @lock: the rt lock query - * - * Returns the next owner of the lock or NULL - * - * Caller has to serialize against other accessors to the lock - * itself. - * - * Special API call for PI-futex support - */ -struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock) -{ - if (!rt_mutex_has_waiters(lock)) - return NULL; - - return rt_mutex_top_waiter(lock)->task; -} diff --git a/trunk/kernel/rtmutex.h b/trunk/kernel/rtmutex.h deleted file mode 100644 index 1e0fca13ff72..000000000000 --- a/trunk/kernel/rtmutex.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * RT-Mutexes: blocking mutual exclusion locks with PI support - * - * started by Ingo Molnar and Thomas Gleixner: - * - * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar - * Copyright (C) 2006, Timesys Corp., Thomas Gleixner - * - * This file contains macros used solely by rtmutex.c. - * Non-debug version. - */ - -#define __IP_DECL__ -#define __IP__ -#define __RET_IP__ -#define rt_mutex_deadlock_check(l) (0) -#define rt_mutex_deadlock_account_lock(m, t) do { } while (0) -#define rt_mutex_deadlock_account_unlock(l) do { } while (0) -#define debug_rt_mutex_init_waiter(w) do { } while (0) -#define debug_rt_mutex_free_waiter(w) do { } while (0) -#define debug_rt_mutex_lock(l) do { } while (0) -#define debug_rt_mutex_proxy_lock(l,p) do { } while (0) -#define debug_rt_mutex_proxy_unlock(l) do { } while (0) -#define debug_rt_mutex_unlock(l) do { } while (0) -#define debug_rt_mutex_init(m, n) do { } while (0) -#define debug_rt_mutex_deadlock(d, a ,l) do { } while (0) -#define debug_rt_mutex_print_deadlock(w) do { } while (0) -#define debug_rt_mutex_detect_deadlock(w,d) (d) -#define debug_rt_mutex_reset_waiter(w) do { } while (0) diff --git a/trunk/kernel/rtmutex_common.h b/trunk/kernel/rtmutex_common.h deleted file mode 100644 index 9c75856e791e..000000000000 --- a/trunk/kernel/rtmutex_common.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * RT Mutexes: blocking mutual exclusion locks with PI support - * - * started by Ingo Molnar and Thomas Gleixner: - * - * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar - * Copyright (C) 2006, Timesys Corp., Thomas Gleixner - * - * This file contains the private data structure and API definitions. - */ - -#ifndef __KERNEL_RTMUTEX_COMMON_H -#define __KERNEL_RTMUTEX_COMMON_H - -#include - -/* - * The rtmutex in kernel tester is independent of rtmutex debugging. We - * call schedule_rt_mutex_test() instead of schedule() for the tasks which - * belong to the tester. That way we can delay the wakeup path of those - * threads to provoke lock stealing and testing of complex boosting scenarios. - */ -#ifdef CONFIG_RT_MUTEX_TESTER - -extern void schedule_rt_mutex_test(struct rt_mutex *lock); - -#define schedule_rt_mutex(_lock) \ - do { \ - if (!(current->flags & PF_MUTEX_TESTER)) \ - schedule(); \ - else \ - schedule_rt_mutex_test(_lock); \ - } while (0) - -#else -# define schedule_rt_mutex(_lock) schedule() -#endif - -/* - * This is the control structure for tasks blocked on a rt_mutex, - * which is allocated on the kernel stack on of the blocked task. - * - * @list_entry: pi node to enqueue into the mutex waiters list - * @pi_list_entry: pi node to enqueue into the mutex owner waiters list - * @task: task reference to the blocked task - */ -struct rt_mutex_waiter { - struct plist_node list_entry; - struct plist_node pi_list_entry; - struct task_struct *task; - struct rt_mutex *lock; -#ifdef CONFIG_DEBUG_RT_MUTEXES - unsigned long ip; - pid_t deadlock_task_pid; - struct rt_mutex *deadlock_lock; -#endif -}; - -/* - * Various helpers to access the waiters-plist: - */ -static inline int rt_mutex_has_waiters(struct rt_mutex *lock) -{ - return !plist_head_empty(&lock->wait_list); -} - -static inline struct rt_mutex_waiter * -rt_mutex_top_waiter(struct rt_mutex *lock) -{ - struct rt_mutex_waiter *w; - - w = plist_first_entry(&lock->wait_list, struct rt_mutex_waiter, - list_entry); - BUG_ON(w->lock != lock); - - return w; -} - -static inline int task_has_pi_waiters(struct task_struct *p) -{ - return !plist_head_empty(&p->pi_waiters); -} - -static inline struct rt_mutex_waiter * -task_top_pi_waiter(struct task_struct *p) -{ - return plist_first_entry(&p->pi_waiters, struct rt_mutex_waiter, - pi_list_entry); -} - -/* - * lock->owner state tracking: - */ -#define RT_MUTEX_OWNER_PENDING 1UL -#define RT_MUTEX_HAS_WAITERS 2UL -#define RT_MUTEX_OWNER_MASKALL 3UL - -static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock) -{ - return (struct task_struct *) - ((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL); -} - -static inline struct task_struct *rt_mutex_real_owner(struct rt_mutex *lock) -{ - return (struct task_struct *) - ((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS); -} - -static inline unsigned long rt_mutex_owner_pending(struct rt_mutex *lock) -{ - return (unsigned long)lock->owner & RT_MUTEX_OWNER_PENDING; -} - -/* - * PI-futex support (proxy locking functions, etc.): - */ -extern struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock); -extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock, - struct task_struct *proxy_owner); -extern void rt_mutex_proxy_unlock(struct rt_mutex *lock, - struct task_struct *proxy_owner); -#endif diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index d5e37072ea54..f06d059edef5 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -168,21 +168,15 @@ */ #define SCALE_PRIO(x, prio) \ - max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE) + max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO/2), MIN_TIMESLICE) -static unsigned int static_prio_timeslice(int static_prio) +static unsigned int task_timeslice(task_t *p) { - if (static_prio < NICE_TO_PRIO(0)) - return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio); + if (p->static_prio < NICE_TO_PRIO(0)) + return SCALE_PRIO(DEF_TIMESLICE*4, p->static_prio); else - return SCALE_PRIO(DEF_TIMESLICE, static_prio); + return SCALE_PRIO(DEF_TIMESLICE, p->static_prio); } - -static inline unsigned int task_timeslice(task_t *p) -{ - return static_prio_timeslice(p->static_prio); -} - #define task_hot(p, now, sd) ((long long) ((now) - (p)->last_ran) \ < (long long) (sd)->cache_hot_time) @@ -190,11 +184,13 @@ static inline unsigned int task_timeslice(task_t *p) * These are the runqueue data structures: */ +#define BITMAP_SIZE ((((MAX_PRIO+1+7)/8)+sizeof(long)-1)/sizeof(long)) + typedef struct runqueue runqueue_t; struct prio_array { unsigned int nr_active; - DECLARE_BITMAP(bitmap, MAX_PRIO+1); /* include 1 bit for delimiter */ + unsigned long bitmap[BITMAP_SIZE]; struct list_head queue[MAX_PRIO]; }; @@ -213,7 +209,6 @@ struct runqueue { * remote CPUs use both these fields when doing load calculation. */ unsigned long nr_running; - unsigned long raw_weighted_load; #ifdef CONFIG_SMP unsigned long cpu_load[3]; #endif @@ -244,6 +239,7 @@ struct runqueue { task_t *migration_thread; struct list_head migration_queue; + int cpu; #endif #ifdef CONFIG_SCHEDSTATS @@ -354,31 +350,12 @@ static inline void finish_lock_switch(runqueue_t *rq, task_t *prev) } #endif /* __ARCH_WANT_UNLOCKED_CTXSW */ -/* - * __task_rq_lock - lock the runqueue a given task resides on. - * Must be called interrupts disabled. - */ -static inline runqueue_t *__task_rq_lock(task_t *p) - __acquires(rq->lock) -{ - struct runqueue *rq; - -repeat_lock_task: - rq = task_rq(p); - spin_lock(&rq->lock); - if (unlikely(rq != task_rq(p))) { - spin_unlock(&rq->lock); - goto repeat_lock_task; - } - return rq; -} - /* * task_rq_lock - lock the runqueue a given task resides on and disable * interrupts. Note the ordering: we can safely lookup the task_rq without * explicitly disabling preemption. */ -static runqueue_t *task_rq_lock(task_t *p, unsigned long *flags) +static inline runqueue_t *task_rq_lock(task_t *p, unsigned long *flags) __acquires(rq->lock) { struct runqueue *rq; @@ -394,12 +371,6 @@ static runqueue_t *task_rq_lock(task_t *p, unsigned long *flags) return rq; } -static inline void __task_rq_unlock(runqueue_t *rq) - __releases(rq->lock) -{ - spin_unlock(&rq->lock); -} - static inline void task_rq_unlock(runqueue_t *rq, unsigned long *flags) __releases(rq->lock) { @@ -663,7 +634,7 @@ static inline void enqueue_task_head(struct task_struct *p, prio_array_t *array) } /* - * __normal_prio - return the priority that is based on the static + * effective_prio - return the priority that is based on the static * priority but is modified by bonuses/penalties. * * We scale the actual sleep average [0 .... MAX_SLEEP_AVG] @@ -676,11 +647,13 @@ static inline void enqueue_task_head(struct task_struct *p, prio_array_t *array) * * Both properties are important to certain workloads. */ - -static inline int __normal_prio(task_t *p) +static int effective_prio(task_t *p) { int bonus, prio; + if (rt_task(p)) + return p->prio; + bonus = CURRENT_BONUS(p) - MAX_BONUS / 2; prio = p->static_prio - bonus; @@ -691,106 +664,6 @@ static inline int __normal_prio(task_t *p) return prio; } -/* - * To aid in avoiding the subversion of "niceness" due to uneven distribution - * of tasks with abnormal "nice" values across CPUs the contribution that - * each task makes to its run queue's load is weighted according to its - * scheduling class and "nice" value. For SCHED_NORMAL tasks this is just a - * scaled version of the new time slice allocation that they receive on time - * slice expiry etc. - */ - -/* - * Assume: static_prio_timeslice(NICE_TO_PRIO(0)) == DEF_TIMESLICE - * If static_prio_timeslice() is ever changed to break this assumption then - * this code will need modification - */ -#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE -#define LOAD_WEIGHT(lp) \ - (((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO) -#define PRIO_TO_LOAD_WEIGHT(prio) \ - LOAD_WEIGHT(static_prio_timeslice(prio)) -#define RTPRIO_TO_LOAD_WEIGHT(rp) \ - (PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + LOAD_WEIGHT(rp)) - -static void set_load_weight(task_t *p) -{ - if (has_rt_policy(p)) { -#ifdef CONFIG_SMP - if (p == task_rq(p)->migration_thread) - /* - * The migration thread does the actual balancing. - * Giving its load any weight will skew balancing - * adversely. - */ - p->load_weight = 0; - else -#endif - p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority); - } else - p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio); -} - -static inline void inc_raw_weighted_load(runqueue_t *rq, const task_t *p) -{ - rq->raw_weighted_load += p->load_weight; -} - -static inline void dec_raw_weighted_load(runqueue_t *rq, const task_t *p) -{ - rq->raw_weighted_load -= p->load_weight; -} - -static inline void inc_nr_running(task_t *p, runqueue_t *rq) -{ - rq->nr_running++; - inc_raw_weighted_load(rq, p); -} - -static inline void dec_nr_running(task_t *p, runqueue_t *rq) -{ - rq->nr_running--; - dec_raw_weighted_load(rq, p); -} - -/* - * Calculate the expected normal priority: i.e. priority - * without taking RT-inheritance into account. Might be - * boosted by interactivity modifiers. Changes upon fork, - * setprio syscalls, and whenever the interactivity - * estimator recalculates. - */ -static inline int normal_prio(task_t *p) -{ - int prio; - - if (has_rt_policy(p)) - prio = MAX_RT_PRIO-1 - p->rt_priority; - else - prio = __normal_prio(p); - return prio; -} - -/* - * Calculate the current priority, i.e. the priority - * taken into account by the scheduler. This value might - * be boosted by RT tasks, or might be boosted by - * interactivity modifiers. Will be RT if the task got - * RT-boosted. If not then it returns p->normal_prio. - */ -static int effective_prio(task_t *p) -{ - p->normal_prio = normal_prio(p); - /* - * If we are RT tasks or we were boosted to RT priority, - * keep the priority unchanged. Otherwise, update priority - * to the normal priority: - */ - if (!rt_prio(p->prio)) - return p->normal_prio; - return p->prio; -} - /* * __activate_task - move a task to the runqueue. */ @@ -801,7 +674,7 @@ static void __activate_task(task_t *p, runqueue_t *rq) if (batch_task(p)) target = rq->expired; enqueue_task(p, target); - inc_nr_running(p, rq); + rq->nr_running++; } /* @@ -810,45 +683,39 @@ static void __activate_task(task_t *p, runqueue_t *rq) static inline void __activate_idle_task(task_t *p, runqueue_t *rq) { enqueue_task_head(p, rq->active); - inc_nr_running(p, rq); + rq->nr_running++; } -/* - * Recalculate p->normal_prio and p->prio after having slept, - * updating the sleep-average too: - */ static int recalc_task_prio(task_t *p, unsigned long long now) { /* Caller must always ensure 'now >= p->timestamp' */ - unsigned long sleep_time = now - p->timestamp; + unsigned long long __sleep_time = now - p->timestamp; + unsigned long sleep_time; if (batch_task(p)) sleep_time = 0; + else { + 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)) { /* - * This ceiling is set to the lowest priority that would allow - * a task to be reinserted into the active array on timeslice - * completion. + * User tasks that sleep a long time are categorised as + * idle. They will only have their sleep_avg increased to a + * level that makes them just interactive priority to stay + * active yet prevent them suddenly becoming cpu hogs and + * starving other processes. */ - unsigned long ceiling = INTERACTIVE_SLEEP(p); + if (p->mm && sleep_time > INTERACTIVE_SLEEP(p)) { + unsigned long ceiling; - if (p->mm && sleep_time > ceiling && p->sleep_avg < ceiling) { - /* - * Prevents user tasks from achieving best priority - * with one single large enough sleep. - */ - p->sleep_avg = ceiling; - /* - * Using INTERACTIVE_SLEEP() as a ceiling places a - * nice(0) task 1ms sleep away from promotion, and - * gives it 700ms to round-robin with no chance of - * being demoted. This is more than generous, so - * mark this sleep as non-interactive to prevent the - * on-runqueue bonus logic from intervening should - * this task not receive cpu immediately. - */ - p->sleep_type = SLEEP_NONINTERACTIVE; + ceiling = JIFFIES_TO_NS(MAX_SLEEP_AVG - + DEF_TIMESLICE); + if (p->sleep_avg < ceiling) + p->sleep_avg = ceiling; } else { /* * Tasks waking from uninterruptible sleep are @@ -856,12 +723,12 @@ static int recalc_task_prio(task_t *p, unsigned long long now) * are likely to be waiting on I/O */ if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) { - if (p->sleep_avg >= ceiling) + if (p->sleep_avg >= INTERACTIVE_SLEEP(p)) sleep_time = 0; else if (p->sleep_avg + sleep_time >= - ceiling) { - p->sleep_avg = ceiling; - sleep_time = 0; + INTERACTIVE_SLEEP(p)) { + p->sleep_avg = INTERACTIVE_SLEEP(p); + sleep_time = 0; } } @@ -875,9 +742,9 @@ static int recalc_task_prio(task_t *p, unsigned long long now) */ p->sleep_avg += sleep_time; + if (p->sleep_avg > NS_MAX_SLEEP_AVG) + p->sleep_avg = NS_MAX_SLEEP_AVG; } - if (p->sleep_avg > NS_MAX_SLEEP_AVG) - p->sleep_avg = NS_MAX_SLEEP_AVG; } return effective_prio(p); @@ -938,7 +805,7 @@ static void activate_task(task_t *p, runqueue_t *rq, int local) */ static void deactivate_task(struct task_struct *p, runqueue_t *rq) { - dec_nr_running(p, rq); + rq->nr_running--; dequeue_task(p, p->array); p->array = NULL; } @@ -951,11 +818,6 @@ static void deactivate_task(struct task_struct *p, runqueue_t *rq) * the target CPU. */ #ifdef CONFIG_SMP - -#ifndef tsk_is_polling -#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG) -#endif - static void resched_task(task_t *p) { int cpu; @@ -971,9 +833,9 @@ static void resched_task(task_t *p) if (cpu == smp_processor_id()) return; - /* NEED_RESCHED must be visible before we test polling */ + /* NEED_RESCHED must be visible before we test POLLING_NRFLAG */ smp_mb(); - if (!tsk_is_polling(p)) + if (!test_tsk_thread_flag(p, TIF_POLLING_NRFLAG)) smp_send_reschedule(cpu); } #else @@ -993,12 +855,6 @@ inline int task_curr(const task_t *p) return cpu_curr(task_cpu(p)) == p; } -/* Used instead of source_load when we know the type == 0 */ -unsigned long weighted_cpuload(const int cpu) -{ - return cpu_rq(cpu)->raw_weighted_load; -} - #ifdef CONFIG_SMP typedef struct { struct list_head list; @@ -1088,8 +944,7 @@ void kick_process(task_t *p) } /* - * Return a low guess at the load of a migration-source cpu weighted - * according to the scheduling class and "nice" value. + * Return a low guess at the load of a migration-source cpu. * * We want to under-estimate the load of migration sources, to * balance conservatively. @@ -1097,36 +952,24 @@ void kick_process(task_t *p) static inline unsigned long source_load(int cpu, int type) { runqueue_t *rq = cpu_rq(cpu); - + unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE; if (type == 0) - return rq->raw_weighted_load; + return load_now; - return min(rq->cpu_load[type-1], rq->raw_weighted_load); + return min(rq->cpu_load[type-1], load_now); } /* - * Return a high guess at the load of a migration-target cpu weighted - * according to the scheduling class and "nice" value. + * Return a high guess at the load of a migration-target cpu */ static inline unsigned long target_load(int cpu, int type) { runqueue_t *rq = cpu_rq(cpu); - + unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE; if (type == 0) - return rq->raw_weighted_load; + return load_now; - return max(rq->cpu_load[type-1], rq->raw_weighted_load); -} - -/* - * Return the average load per task on the cpu's run queue - */ -static inline unsigned long cpu_avg_load_per_task(int cpu) -{ - runqueue_t *rq = cpu_rq(cpu); - unsigned long n = rq->nr_running; - - return n ? rq->raw_weighted_load / n : SCHED_LOAD_SCALE; + return max(rq->cpu_load[type-1], load_now); } /* @@ -1199,7 +1042,7 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu) cpus_and(tmp, group->cpumask, p->cpus_allowed); for_each_cpu_mask(i, tmp) { - load = weighted_cpuload(i); + load = source_load(i, 0); if (load < min_load || (load == min_load && i == this_cpu)) { min_load = load; @@ -1226,15 +1069,9 @@ static int sched_balance_self(int cpu, int flag) struct task_struct *t = current; struct sched_domain *tmp, *sd = NULL; - for_each_domain(cpu, tmp) { - /* - * If power savings logic is enabled for a domain, stop there. - */ - if (tmp->flags & SD_POWERSAVINGS_BALANCE) - break; + for_each_domain(cpu, tmp) if (tmp->flags & flag) sd = tmp; - } while (sd) { cpumask_t span; @@ -1384,19 +1221,17 @@ static int try_to_wake_up(task_t *p, unsigned int state, int sync) if (this_sd->flags & SD_WAKE_AFFINE) { unsigned long tl = this_load; - unsigned long tl_per_task = cpu_avg_load_per_task(this_cpu); - /* * If sync wakeup then subtract the (maximum possible) * effect of the currently running task from the load * of the current CPU: */ if (sync) - tl -= current->load_weight; + tl -= SCHED_LOAD_SCALE; if ((tl <= load && - tl + target_load(cpu, idx) <= tl_per_task) || - 100*(tl + p->load_weight) <= imbalance*load) { + tl + target_load(cpu, idx) <= SCHED_LOAD_SCALE) || + 100*(tl + SCHED_LOAD_SCALE) <= imbalance*load) { /* * This domain has SD_WAKE_AFFINE and * p is cache cold in this domain, and @@ -1513,12 +1348,6 @@ void fastcall sched_fork(task_t *p, int clone_flags) * event cannot wake it up and insert it on the runqueue either. */ p->state = TASK_RUNNING; - - /* - * Make sure we do not leak PI boosting priority to the child: - */ - p->prio = current->normal_prio; - INIT_LIST_HEAD(&p->run_list); p->array = NULL; #ifdef CONFIG_SCHEDSTATS @@ -1598,11 +1427,10 @@ void fastcall wake_up_new_task(task_t *p, unsigned long clone_flags) __activate_task(p, rq); else { p->prio = current->prio; - p->normal_prio = current->normal_prio; list_add_tail(&p->run_list, ¤t->run_list); p->array = current->array; p->array->nr_active++; - inc_nr_running(p, rq); + rq->nr_running++; } set_need_resched(); } else @@ -1820,8 +1648,7 @@ unsigned long nr_uninterruptible(void) unsigned long long nr_context_switches(void) { - int i; - unsigned long long sum = 0; + unsigned long long i, sum = 0; for_each_possible_cpu(i) sum += cpu_rq(i)->nr_switches; @@ -1859,6 +1686,9 @@ unsigned long nr_active(void) /* * double_rq_lock - safely lock two runqueues * + * We must take them in cpu order to match code in + * dependent_sleeper and wake_dependent_sleeper. + * * Note this does not disable interrupts like task_rq_lock, * you need to do so manually before calling. */ @@ -1870,7 +1700,7 @@ static void double_rq_lock(runqueue_t *rq1, runqueue_t *rq2) spin_lock(&rq1->lock); __acquire(rq2->lock); /* Fake it out ;) */ } else { - if (rq1 < rq2) { + if (rq1->cpu < rq2->cpu) { spin_lock(&rq1->lock); spin_lock(&rq2->lock); } else { @@ -1906,7 +1736,7 @@ static void double_lock_balance(runqueue_t *this_rq, runqueue_t *busiest) __acquires(this_rq->lock) { if (unlikely(!spin_trylock(&busiest->lock))) { - if (busiest < this_rq) { + if (busiest->cpu < this_rq->cpu) { spin_unlock(&this_rq->lock); spin_lock(&busiest->lock); spin_lock(&this_rq->lock); @@ -1969,9 +1799,9 @@ void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p, runqueue_t *this_rq, prio_array_t *this_array, int this_cpu) { dequeue_task(p, src_array); - dec_nr_running(p, src_rq); + src_rq->nr_running--; set_task_cpu(p, this_cpu); - inc_nr_running(p, this_rq); + this_rq->nr_running++; enqueue_task(p, this_array); p->timestamp = (p->timestamp - src_rq->timestamp_last_tick) + this_rq->timestamp_last_tick; @@ -2018,42 +1848,26 @@ int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu, return 1; } -#define rq_best_prio(rq) min((rq)->curr->prio, (rq)->best_expired_prio) /* - * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted - * load from busiest to this_rq, as part of a balancing operation within - * "domain". Returns the number of tasks moved. + * move_tasks tries to move up to max_nr_move tasks from busiest to this_rq, + * as part of a balancing operation within "domain". Returns the number of + * tasks moved. * * Called with both runqueues locked. */ static int move_tasks(runqueue_t *this_rq, int this_cpu, runqueue_t *busiest, - unsigned long max_nr_move, unsigned long max_load_move, - struct sched_domain *sd, enum idle_type idle, - int *all_pinned) + unsigned long max_nr_move, struct sched_domain *sd, + enum idle_type idle, int *all_pinned) { prio_array_t *array, *dst_array; struct list_head *head, *curr; - int idx, pulled = 0, pinned = 0, this_best_prio, busiest_best_prio; - int busiest_best_prio_seen; - int skip_for_load; /* skip the task based on weighted load issues */ - long rem_load_move; + int idx, pulled = 0, pinned = 0; task_t *tmp; - if (max_nr_move == 0 || max_load_move == 0) + if (max_nr_move == 0) goto out; - rem_load_move = max_load_move; pinned = 1; - this_best_prio = rq_best_prio(this_rq); - busiest_best_prio = rq_best_prio(busiest); - /* - * Enable handling of the case where there is more than one task - * with the best priority. If the current running task is one - * of those with prio==busiest_best_prio we know it won't be moved - * and therefore it's safe to override the skip (based on load) of - * any task we find with that prio. - */ - busiest_best_prio_seen = busiest_best_prio == busiest->curr->prio; /* * We first consider expired tasks. Those will likely not be @@ -2093,17 +1907,7 @@ static int move_tasks(runqueue_t *this_rq, int this_cpu, runqueue_t *busiest, curr = curr->prev; - /* - * To help distribute high priority tasks accross CPUs we don't - * skip a task if it will be the highest priority task (i.e. smallest - * prio value) on its new queue regardless of its load weight - */ - skip_for_load = tmp->load_weight > rem_load_move; - if (skip_for_load && idx < this_best_prio) - skip_for_load = !busiest_best_prio_seen && idx == busiest_best_prio; - if (skip_for_load || - !can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) { - busiest_best_prio_seen |= idx == busiest_best_prio; + if (!can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) { if (curr != head) goto skip_queue; idx++; @@ -2117,15 +1921,9 @@ static int move_tasks(runqueue_t *this_rq, int this_cpu, runqueue_t *busiest, pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu); pulled++; - rem_load_move -= tmp->load_weight; - /* - * We only want to steal up to the prescribed number of tasks - * and the prescribed amount of weighted load. - */ - if (pulled < max_nr_move && rem_load_move > 0) { - if (idx < this_best_prio) - this_best_prio = idx; + /* We only want to steal up to the prescribed number of tasks. */ + if (pulled < max_nr_move) { if (curr != head) goto skip_queue; idx++; @@ -2146,7 +1944,7 @@ static int move_tasks(runqueue_t *this_rq, int this_cpu, runqueue_t *busiest, /* * find_busiest_group finds and returns the busiest CPU group within the - * domain. It calculates and returns the amount of weighted load which should be + * domain. It calculates and returns the number of tasks which should be * moved to restore balance via the imbalance parameter. */ static struct sched_group * @@ -2156,19 +1954,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups; unsigned long max_load, avg_load, total_load, this_load, total_pwr; unsigned long max_pull; - unsigned long busiest_load_per_task, busiest_nr_running; - unsigned long this_load_per_task, this_nr_running; int load_idx; -#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - int power_savings_balance = 1; - unsigned long leader_nr_running = 0, min_load_per_task = 0; - unsigned long min_nr_running = ULONG_MAX; - struct sched_group *group_min = NULL, *group_leader = NULL; -#endif max_load = this_load = total_load = total_pwr = 0; - busiest_load_per_task = busiest_nr_running = 0; - this_load_per_task = this_nr_running = 0; if (idle == NOT_IDLE) load_idx = sd->busy_idx; else if (idle == NEWLY_IDLE) @@ -2177,19 +1965,16 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, load_idx = sd->idle_idx; do { - unsigned long load, group_capacity; + unsigned long load; int local_group; int i; - unsigned long sum_nr_running, sum_weighted_load; local_group = cpu_isset(this_cpu, group->cpumask); /* Tally up the load of all CPUs in the group */ - sum_weighted_load = sum_nr_running = avg_load = 0; + avg_load = 0; for_each_cpu_mask(i, group->cpumask) { - runqueue_t *rq = cpu_rq(i); - if (*sd_idle && !idle_cpu(i)) *sd_idle = 0; @@ -2200,8 +1985,6 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, load = source_load(i, load_idx); avg_load += load; - sum_nr_running += rq->nr_running; - sum_weighted_load += rq->raw_weighted_load; } total_load += avg_load; @@ -2210,80 +1993,17 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, /* Adjust by relative CPU power of the group */ avg_load = (avg_load * SCHED_LOAD_SCALE) / group->cpu_power; - group_capacity = group->cpu_power / SCHED_LOAD_SCALE; - if (local_group) { this_load = avg_load; this = group; - this_nr_running = sum_nr_running; - this_load_per_task = sum_weighted_load; - } else if (avg_load > max_load && - sum_nr_running > group_capacity) { + } else if (avg_load > max_load) { max_load = avg_load; busiest = group; - busiest_nr_running = sum_nr_running; - busiest_load_per_task = sum_weighted_load; } - -#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - /* - * Busy processors will not participate in power savings - * balance. - */ - if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE)) - goto group_next; - - /* - * If the local group is idle or completely loaded - * no need to do power savings balance at this domain - */ - if (local_group && (this_nr_running >= group_capacity || - !this_nr_running)) - power_savings_balance = 0; - - /* - * If a group is already running at full capacity or idle, - * don't include that group in power savings calculations - */ - if (!power_savings_balance || sum_nr_running >= group_capacity - || !sum_nr_running) - goto group_next; - - /* - * Calculate the group which has the least non-idle load. - * This is the group from where we need to pick up the load - * for saving power - */ - if ((sum_nr_running < min_nr_running) || - (sum_nr_running == min_nr_running && - first_cpu(group->cpumask) < - first_cpu(group_min->cpumask))) { - group_min = group; - min_nr_running = sum_nr_running; - min_load_per_task = sum_weighted_load / - sum_nr_running; - } - - /* - * Calculate the group which is almost near its - * capacity but still has some space to pick up some load - * from other group and save more power - */ - if (sum_nr_running <= group_capacity - 1) - if (sum_nr_running > leader_nr_running || - (sum_nr_running == leader_nr_running && - first_cpu(group->cpumask) > - first_cpu(group_leader->cpumask))) { - group_leader = group; - leader_nr_running = sum_nr_running; - } - -group_next: -#endif group = group->next; } while (group != sd->groups); - if (!busiest || this_load >= max_load || busiest_nr_running == 0) + if (!busiest || this_load >= max_load || max_load <= SCHED_LOAD_SCALE) goto out_balanced; avg_load = (SCHED_LOAD_SCALE * total_load) / total_pwr; @@ -2292,7 +2012,6 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, 100*max_load <= sd->imbalance_pct*this_load) goto out_balanced; - busiest_load_per_task /= busiest_nr_running; /* * We're trying to get all the cpus to the average_load, so we don't * want to push ourselves above the average load, nor do we wish to @@ -2304,50 +2023,21 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * by pulling tasks to us. Be careful of negative numbers as they'll * appear as very large values with unsigned longs. */ - if (max_load <= busiest_load_per_task) - goto out_balanced; - - /* - * In the presence of smp nice balancing, certain scenarios can have - * max load less than avg load(as we skip the groups at or below - * its cpu_power, while calculating max_load..) - */ - if (max_load < avg_load) { - *imbalance = 0; - goto small_imbalance; - } /* Don't want to pull so many tasks that a group would go idle */ - max_pull = min(max_load - avg_load, max_load - busiest_load_per_task); + max_pull = min(max_load - avg_load, max_load - SCHED_LOAD_SCALE); /* How much load to actually move to equalise the imbalance */ *imbalance = min(max_pull * busiest->cpu_power, (avg_load - this_load) * this->cpu_power) / SCHED_LOAD_SCALE; - /* - * if *imbalance is less than the average load per runnable task - * there is no gaurantee that any tasks will be moved so we'll have - * a think about bumping its value to force at least one task to be - * moved - */ - if (*imbalance < busiest_load_per_task) { - unsigned long pwr_now, pwr_move; + if (*imbalance < SCHED_LOAD_SCALE) { + unsigned long pwr_now = 0, pwr_move = 0; unsigned long tmp; - unsigned int imbn; - -small_imbalance: - pwr_move = pwr_now = 0; - imbn = 2; - if (this_nr_running) { - this_load_per_task /= this_nr_running; - if (busiest_load_per_task > this_load_per_task) - imbn = 1; - } else - this_load_per_task = SCHED_LOAD_SCALE; - if (max_load - this_load >= busiest_load_per_task * imbn) { - *imbalance = busiest_load_per_task; + if (max_load - this_load >= SCHED_LOAD_SCALE*2) { + *imbalance = 1; return busiest; } @@ -2357,47 +2047,39 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * moving them. */ - pwr_now += busiest->cpu_power * - min(busiest_load_per_task, max_load); - pwr_now += this->cpu_power * - min(this_load_per_task, this_load); + pwr_now += busiest->cpu_power*min(SCHED_LOAD_SCALE, max_load); + pwr_now += this->cpu_power*min(SCHED_LOAD_SCALE, this_load); pwr_now /= SCHED_LOAD_SCALE; /* Amount of load we'd subtract */ - tmp = busiest_load_per_task*SCHED_LOAD_SCALE/busiest->cpu_power; + tmp = SCHED_LOAD_SCALE*SCHED_LOAD_SCALE/busiest->cpu_power; if (max_load > tmp) - pwr_move += busiest->cpu_power * - min(busiest_load_per_task, max_load - tmp); + pwr_move += busiest->cpu_power*min(SCHED_LOAD_SCALE, + max_load - tmp); /* Amount of load we'd add */ if (max_load*busiest->cpu_power < - busiest_load_per_task*SCHED_LOAD_SCALE) + SCHED_LOAD_SCALE*SCHED_LOAD_SCALE) tmp = max_load*busiest->cpu_power/this->cpu_power; else - tmp = busiest_load_per_task*SCHED_LOAD_SCALE/this->cpu_power; - pwr_move += this->cpu_power*min(this_load_per_task, this_load + tmp); + tmp = SCHED_LOAD_SCALE*SCHED_LOAD_SCALE/this->cpu_power; + pwr_move += this->cpu_power*min(SCHED_LOAD_SCALE, this_load + tmp); pwr_move /= SCHED_LOAD_SCALE; /* Move if we gain throughput */ if (pwr_move <= pwr_now) goto out_balanced; - *imbalance = busiest_load_per_task; + *imbalance = 1; + return busiest; } + /* Get rid of the scaling factor, rounding down as we divide */ + *imbalance = *imbalance / SCHED_LOAD_SCALE; return busiest; out_balanced: -#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) - if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE)) - goto ret; - if (this == group_leader && group_leader != group_min) { - *imbalance = min_load_per_task; - return group_min; - } -ret: -#endif *imbalance = 0; return NULL; } @@ -2406,21 +2088,18 @@ find_busiest_group(struct sched_domain *sd, int this_cpu, * find_busiest_queue - find the busiest runqueue among the cpus in group. */ static runqueue_t *find_busiest_queue(struct sched_group *group, - enum idle_type idle, unsigned long imbalance) + enum idle_type idle) { - unsigned long max_load = 0; - runqueue_t *busiest = NULL, *rqi; + unsigned long load, max_load = 0; + runqueue_t *busiest = NULL; int i; for_each_cpu_mask(i, group->cpumask) { - rqi = cpu_rq(i); - - if (rqi->nr_running == 1 && rqi->raw_weighted_load > imbalance) - continue; + load = source_load(i, 0); - if (rqi->raw_weighted_load > max_load) { - max_load = rqi->raw_weighted_load; - busiest = rqi; + if (load > max_load) { + max_load = load; + busiest = cpu_rq(i); } } @@ -2433,7 +2112,6 @@ static runqueue_t *find_busiest_queue(struct sched_group *group, */ #define MAX_PINNED_INTERVAL 512 -#define minus_1_or_zero(n) ((n) > 0 ? (n) - 1 : 0) /* * Check this_cpu to ensure it is balanced within domain. Attempt to move * tasks if there is an imbalance. @@ -2450,8 +2128,7 @@ static int load_balance(int this_cpu, runqueue_t *this_rq, int active_balance = 0; int sd_idle = 0; - if (idle != NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER && - !sched_smt_power_savings) + if (idle != NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER) sd_idle = 1; schedstat_inc(sd, lb_cnt[idle]); @@ -2462,7 +2139,7 @@ static int load_balance(int this_cpu, runqueue_t *this_rq, goto out_balanced; } - busiest = find_busiest_queue(group, idle, imbalance); + busiest = find_busiest_queue(group, idle); if (!busiest) { schedstat_inc(sd, lb_nobusyq[idle]); goto out_balanced; @@ -2482,7 +2159,6 @@ static int load_balance(int this_cpu, runqueue_t *this_rq, */ double_rq_lock(this_rq, busiest); nr_moved = move_tasks(this_rq, this_cpu, busiest, - minus_1_or_zero(busiest->nr_running), imbalance, sd, idle, &all_pinned); double_rq_unlock(this_rq, busiest); @@ -2540,8 +2216,7 @@ static int load_balance(int this_cpu, runqueue_t *this_rq, sd->balance_interval *= 2; } - if (!nr_moved && !sd_idle && sd->flags & SD_SHARE_CPUPOWER && - !sched_smt_power_savings) + if (!nr_moved && !sd_idle && sd->flags & SD_SHARE_CPUPOWER) return -1; return nr_moved; @@ -2556,7 +2231,7 @@ static int load_balance(int this_cpu, runqueue_t *this_rq, (sd->balance_interval < sd->max_interval)) sd->balance_interval *= 2; - if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER && !sched_smt_power_savings) + if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER) return -1; return 0; } @@ -2577,7 +2252,7 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq, int nr_moved = 0; int sd_idle = 0; - if (sd->flags & SD_SHARE_CPUPOWER && !sched_smt_power_savings) + if (sd->flags & SD_SHARE_CPUPOWER) sd_idle = 1; schedstat_inc(sd, lb_cnt[NEWLY_IDLE]); @@ -2587,7 +2262,7 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq, goto out_balanced; } - busiest = find_busiest_queue(group, NEWLY_IDLE, imbalance); + busiest = find_busiest_queue(group, NEWLY_IDLE); if (!busiest) { schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]); goto out_balanced; @@ -2602,7 +2277,6 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq, /* Attempt to move tasks */ double_lock_balance(this_rq, busiest); nr_moved = move_tasks(this_rq, this_cpu, busiest, - minus_1_or_zero(busiest->nr_running), imbalance, sd, NEWLY_IDLE, NULL); spin_unlock(&busiest->lock); } @@ -2618,7 +2292,7 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq, out_balanced: schedstat_inc(sd, lb_balanced[NEWLY_IDLE]); - if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER && !sched_smt_power_savings) + if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER) return -1; sd->nr_balance_failed = 0; return 0; @@ -2673,19 +2347,17 @@ static void active_load_balance(runqueue_t *busiest_rq, int busiest_cpu) double_lock_balance(busiest_rq, target_rq); /* Search for an sd spanning us and the target CPU. */ - for_each_domain(target_cpu, sd) { + for_each_domain(target_cpu, sd) if ((sd->flags & SD_LOAD_BALANCE) && cpu_isset(busiest_cpu, sd->span)) break; - } if (unlikely(sd == NULL)) goto out; schedstat_inc(sd, alb_cnt); - if (move_tasks(target_rq, target_cpu, busiest_rq, 1, - RTPRIO_TO_LOAD_WEIGHT(100), sd, SCHED_IDLE, NULL)) + if (move_tasks(target_rq, target_cpu, busiest_rq, 1, sd, SCHED_IDLE, NULL)) schedstat_inc(sd, alb_pushed); else schedstat_inc(sd, alb_failed); @@ -2713,7 +2385,7 @@ static void rebalance_tick(int this_cpu, runqueue_t *this_rq, struct sched_domain *sd; int i; - this_load = this_rq->raw_weighted_load; + this_load = this_rq->nr_running * SCHED_LOAD_SCALE; /* Update our load */ for (i = 0; i < 3; i++) { unsigned long new_load = this_load; @@ -3014,35 +2686,48 @@ static inline void wakeup_busy_runqueue(runqueue_t *rq) resched_task(rq->idle); } -/* - * Called with interrupt disabled and this_rq's runqueue locked. - */ -static void wake_sleeping_dependent(int this_cpu) +static void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq) { struct sched_domain *tmp, *sd = NULL; + cpumask_t sibling_map; int i; - for_each_domain(this_cpu, tmp) { - if (tmp->flags & SD_SHARE_CPUPOWER) { + for_each_domain(this_cpu, tmp) + if (tmp->flags & SD_SHARE_CPUPOWER) sd = tmp; - break; - } - } if (!sd) return; - for_each_cpu_mask(i, sd->span) { - runqueue_t *smt_rq = cpu_rq(i); + /* + * Unlock the current runqueue because we have to lock in + * CPU order to avoid deadlocks. Caller knows that we might + * unlock. We keep IRQs disabled. + */ + spin_unlock(&this_rq->lock); - if (i == this_cpu) - continue; - if (unlikely(!spin_trylock(&smt_rq->lock))) - continue; + sibling_map = sd->span; + + for_each_cpu_mask(i, sibling_map) + spin_lock(&cpu_rq(i)->lock); + /* + * We clear this CPU from the mask. This both simplifies the + * inner loop and keps this_rq locked when we exit: + */ + cpu_clear(this_cpu, sibling_map); + + for_each_cpu_mask(i, sibling_map) { + runqueue_t *smt_rq = cpu_rq(i); wakeup_busy_runqueue(smt_rq); - spin_unlock(&smt_rq->lock); } + + for_each_cpu_mask(i, sibling_map) + spin_unlock(&cpu_rq(i)->lock); + /* + * We exit with this_cpu's rq still held and IRQs + * still disabled: + */ } /* @@ -3055,46 +2740,52 @@ static inline unsigned long smt_slice(task_t *p, struct sched_domain *sd) return p->time_slice * (100 - sd->per_cpu_gain) / 100; } -/* - * To minimise lock contention and not have to drop this_rq's runlock we only - * trylock the sibling runqueues and bypass those runqueues if we fail to - * acquire their lock. As we only trylock the normal locking order does not - * need to be obeyed. - */ -static int dependent_sleeper(int this_cpu, runqueue_t *this_rq, task_t *p) +static int dependent_sleeper(int this_cpu, runqueue_t *this_rq) { struct sched_domain *tmp, *sd = NULL; + cpumask_t sibling_map; + prio_array_t *array; int ret = 0, i; + task_t *p; - /* kernel/rt threads do not participate in dependent sleeping */ - if (!p->mm || rt_task(p)) - return 0; - - for_each_domain(this_cpu, tmp) { - if (tmp->flags & SD_SHARE_CPUPOWER) { + for_each_domain(this_cpu, tmp) + if (tmp->flags & SD_SHARE_CPUPOWER) sd = tmp; - break; - } - } if (!sd) return 0; - for_each_cpu_mask(i, sd->span) { - runqueue_t *smt_rq; - task_t *smt_curr; + /* + * The same locking rules and details apply as for + * wake_sleeping_dependent(): + */ + spin_unlock(&this_rq->lock); + sibling_map = sd->span; + for_each_cpu_mask(i, sibling_map) + spin_lock(&cpu_rq(i)->lock); + cpu_clear(this_cpu, sibling_map); - if (i == this_cpu) - continue; + /* + * Establish next task to be run - it might have gone away because + * we released the runqueue lock above: + */ + if (!this_rq->nr_running) + goto out_unlock; + array = this_rq->active; + if (!array->nr_active) + array = this_rq->expired; + BUG_ON(!array->nr_active); - smt_rq = cpu_rq(i); - if (unlikely(!spin_trylock(&smt_rq->lock))) - continue; + p = list_entry(array->queue[sched_find_first_bit(array->bitmap)].next, + task_t, run_list); - smt_curr = smt_rq->curr; + for_each_cpu_mask(i, sibling_map) { + runqueue_t *smt_rq = cpu_rq(i); + task_t *smt_curr = smt_rq->curr; - if (!smt_curr->mm) - goto unlock; + /* Kernel threads do not participate in dependent sleeping */ + if (!p->mm || !smt_curr->mm || rt_task(p)) + goto check_smt_task; /* * If a user task with lower static priority than the @@ -3112,24 +2803,49 @@ static int dependent_sleeper(int this_cpu, runqueue_t *this_rq, task_t *p) if ((jiffies % DEF_TIMESLICE) > (sd->per_cpu_gain * DEF_TIMESLICE / 100)) ret = 1; - } else { + } else if (smt_curr->static_prio < p->static_prio && !TASK_PREEMPTS_CURR(p, smt_rq) && smt_slice(smt_curr, sd) > task_timeslice(p)) ret = 1; + +check_smt_task: + if ((!smt_curr->mm && smt_curr != smt_rq->idle) || + rt_task(smt_curr)) + continue; + if (!p->mm) { + wakeup_busy_runqueue(smt_rq); + continue; + } + + /* + * Reschedule a lower priority task on the SMT sibling for + * it to be put to sleep, or wake it up if it has been put to + * sleep for priority reasons to see if it should run now. + */ + if (rt_task(p)) { + if ((jiffies % DEF_TIMESLICE) > + (sd->per_cpu_gain * DEF_TIMESLICE / 100)) + resched_task(smt_curr); + } else { + if (TASK_PREEMPTS_CURR(p, smt_rq) && + smt_slice(p, sd) > task_timeslice(smt_curr)) + resched_task(smt_curr); + else + wakeup_busy_runqueue(smt_rq); } -unlock: - spin_unlock(&smt_rq->lock); } +out_unlock: + for_each_cpu_mask(i, sibling_map) + spin_unlock(&cpu_rq(i)->lock); return ret; } #else -static inline void wake_sleeping_dependent(int this_cpu) +static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq) { } -static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq, - task_t *p) +static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq) { return 0; } @@ -3251,13 +2967,32 @@ asmlinkage void __sched schedule(void) cpu = smp_processor_id(); if (unlikely(!rq->nr_running)) { +go_idle: idle_balance(cpu, rq); if (!rq->nr_running) { next = rq->idle; rq->expired_timestamp = 0; - wake_sleeping_dependent(cpu); + wake_sleeping_dependent(cpu, rq); + /* + * wake_sleeping_dependent() might have released + * the runqueue, so break out if we got new + * tasks meanwhile: + */ + if (!rq->nr_running) + goto switch_tasks; + } + } else { + if (dependent_sleeper(cpu, rq)) { + next = rq->idle; goto switch_tasks; } + /* + * dependent_sleeper() releases and reacquires the runqueue + * lock, hence go into the idle loop if the rq went + * empty meanwhile: + */ + if (unlikely(!rq->nr_running)) + goto go_idle; } array = rq->active; @@ -3295,8 +3030,6 @@ asmlinkage void __sched schedule(void) } } next->sleep_type = SLEEP_NORMAL; - if (dependent_sleeper(cpu, rq, next)) - next = rq->idle; switch_tasks: if (next == rq->idle) schedstat_inc(rq, sched_goidle); @@ -3740,65 +3473,12 @@ long fastcall __sched sleep_on_timeout(wait_queue_head_t *q, long timeout) EXPORT_SYMBOL(sleep_on_timeout); -#ifdef CONFIG_RT_MUTEXES - -/* - * rt_mutex_setprio - set the current priority of a task - * @p: task - * @prio: prio value (kernel-internal form) - * - * This function changes the 'effective' priority of a task. It does - * not touch ->normal_prio like __setscheduler(). - * - * Used by the rt_mutex code to implement priority inheritance logic. - */ -void rt_mutex_setprio(task_t *p, int prio) -{ - unsigned long flags; - prio_array_t *array; - runqueue_t *rq; - int oldprio; - - BUG_ON(prio < 0 || prio > MAX_PRIO); - - rq = task_rq_lock(p, &flags); - - oldprio = p->prio; - array = p->array; - if (array) - dequeue_task(p, array); - p->prio = prio; - - if (array) { - /* - * If changing to an RT priority then queue it - * in the active array! - */ - if (rt_task(p)) - array = rq->active; - enqueue_task(p, array); - /* - * Reschedule if we are currently running on this runqueue and - * our priority decreased, or if we are not currently running on - * this runqueue and our priority is higher than the current's - */ - if (task_running(rq, p)) { - if (p->prio > oldprio) - resched_task(rq->curr); - } else if (TASK_PREEMPTS_CURR(p, rq)) - resched_task(rq->curr); - } - task_rq_unlock(rq, &flags); -} - -#endif - void set_user_nice(task_t *p, long nice) { unsigned long flags; prio_array_t *array; runqueue_t *rq; - int old_prio, delta; + int old_prio, new_prio, delta; if (TASK_NICE(p) == nice || nice < -20 || nice > 19) return; @@ -3813,25 +3493,22 @@ void set_user_nice(task_t *p, long nice) * it wont have any effect on scheduling until the task is * not SCHED_NORMAL/SCHED_BATCH: */ - if (has_rt_policy(p)) { + if (rt_task(p)) { p->static_prio = NICE_TO_PRIO(nice); goto out_unlock; } array = p->array; - if (array) { + if (array) dequeue_task(p, array); - dec_raw_weighted_load(rq, p); - } - p->static_prio = NICE_TO_PRIO(nice); - set_load_weight(p); old_prio = p->prio; - p->prio = effective_prio(p); - delta = p->prio - old_prio; + new_prio = NICE_TO_PRIO(nice); + delta = new_prio - old_prio; + p->static_prio = NICE_TO_PRIO(nice); + p->prio += delta; if (array) { enqueue_task(p, array); - inc_raw_weighted_load(rq, p); /* * If the task increased its priority or is running and * lowered its priority, then reschedule its CPU: @@ -3842,6 +3519,7 @@ void set_user_nice(task_t *p, long nice) out_unlock: task_rq_unlock(rq, &flags); } + EXPORT_SYMBOL(set_user_nice); /* @@ -3956,15 +3634,16 @@ static void __setscheduler(struct task_struct *p, int policy, int prio) BUG_ON(p->array); p->policy = policy; p->rt_priority = prio; - p->normal_prio = normal_prio(p); - /* we are holding p->pi_lock already */ - p->prio = rt_mutex_getprio(p); - /* - * SCHED_BATCH tasks are treated as perpetual CPU hogs: - */ - if (policy == SCHED_BATCH) - p->sleep_avg = 0; - set_load_weight(p); + if (policy != SCHED_NORMAL && policy != SCHED_BATCH) { + p->prio = MAX_RT_PRIO-1 - p->rt_priority; + } else { + p->prio = p->static_prio; + /* + * SCHED_BATCH tasks are treated as perpetual CPU hogs: + */ + if (policy == SCHED_BATCH) + p->sleep_avg = 0; + } } /** @@ -3983,8 +3662,6 @@ int sched_setscheduler(struct task_struct *p, int policy, unsigned long flags; runqueue_t *rq; - /* may grab non-irq protected spin_locks */ - BUG_ON(in_interrupt()); recheck: /* double check policy once rq lock held */ if (policy < 0) @@ -4032,21 +3709,15 @@ int sched_setscheduler(struct task_struct *p, int policy, retval = security_task_setscheduler(p, policy, param); if (retval) return retval; - /* - * make sure no PI-waiters arrive (or leave) while we are - * changing the priority of the task: - */ - spin_lock_irqsave(&p->pi_lock, flags); /* * To be able to change p->policy safely, the apropriate * runqueue lock must be held. */ - rq = __task_rq_lock(p); + rq = task_rq_lock(p, &flags); /* recheck policy now with rq lock held */ if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { policy = oldpolicy = -1; - __task_rq_unlock(rq); - spin_unlock_irqrestore(&p->pi_lock, flags); + task_rq_unlock(rq, &flags); goto recheck; } array = p->array; @@ -4067,11 +3738,7 @@ int sched_setscheduler(struct task_struct *p, int policy, } else if (TASK_PREEMPTS_CURR(p, rq)) resched_task(rq->curr); } - __task_rq_unlock(rq); - spin_unlock_irqrestore(&p->pi_lock, flags); - - rt_mutex_adjust_pi(p); - + task_rq_unlock(rq, &flags); return 0; } EXPORT_SYMBOL_GPL(sched_setscheduler); @@ -4093,10 +3760,8 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) read_unlock_irq(&tasklist_lock); return -ESRCH; } - get_task_struct(p); - read_unlock_irq(&tasklist_lock); retval = sched_setscheduler(p, policy, &lparam); - put_task_struct(p); + read_unlock_irq(&tasklist_lock); return retval; } @@ -4386,16 +4051,7 @@ asmlinkage long sys_sched_yield(void) return 0; } -static inline int __resched_legal(void) -{ - if (unlikely(preempt_count())) - return 0; - if (unlikely(system_state != SYSTEM_RUNNING)) - return 0; - return 1; -} - -static void __cond_resched(void) +static inline void __cond_resched(void) { #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP __might_sleep(__FILE__, __LINE__); @@ -4405,6 +4061,10 @@ static void __cond_resched(void) * PREEMPT_ACTIVE, which could trigger a second * cond_resched() call. */ + if (unlikely(preempt_count())) + return; + if (unlikely(system_state != SYSTEM_RUNNING)) + return; do { add_preempt_count(PREEMPT_ACTIVE); schedule(); @@ -4414,12 +4074,13 @@ static void __cond_resched(void) int __sched cond_resched(void) { - if (need_resched() && __resched_legal()) { + if (need_resched()) { __cond_resched(); return 1; } return 0; } + EXPORT_SYMBOL(cond_resched); /* @@ -4440,7 +4101,7 @@ int cond_resched_lock(spinlock_t *lock) ret = 1; spin_lock(lock); } - if (need_resched() && __resched_legal()) { + if (need_resched()) { _raw_spin_unlock(lock); preempt_enable_no_resched(); __cond_resched(); @@ -4449,13 +4110,14 @@ int cond_resched_lock(spinlock_t *lock) } return ret; } + EXPORT_SYMBOL(cond_resched_lock); int __sched cond_resched_softirq(void) { BUG_ON(!in_softirq()); - if (need_resched() && __resched_legal()) { + if (need_resched()) { __local_bh_enable(); __cond_resched(); local_bh_disable(); @@ -4463,8 +4125,10 @@ int __sched cond_resched_softirq(void) } return 0; } + EXPORT_SYMBOL(cond_resched_softirq); + /** * yield - yield the current processor to other threads. * @@ -4583,7 +4247,7 @@ long sys_sched_rr_get_interval(pid_t pid, struct timespec __user *interval) if (retval) goto out_unlock; - jiffies_to_timespec(p->policy == SCHED_FIFO ? + jiffies_to_timespec(p->policy & SCHED_FIFO ? 0 : task_timeslice(p), &t); read_unlock(&tasklist_lock); retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0; @@ -4709,7 +4373,7 @@ void __devinit init_idle(task_t *idle, int cpu) idle->timestamp = sched_clock(); idle->sleep_avg = 0; idle->array = NULL; - idle->prio = idle->normal_prio = MAX_PRIO; + idle->prio = MAX_PRIO; idle->state = TASK_RUNNING; idle->cpus_allowed = cpumask_of_cpu(cpu); set_task_cpu(idle, cpu); @@ -4805,16 +4469,13 @@ EXPORT_SYMBOL_GPL(set_cpus_allowed); * * So we race with normal scheduler movements, but that's OK, as long * as the task is no longer on this CPU. - * - * Returns non-zero if task was successfully migrated. */ -static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) +static void __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) { runqueue_t *rq_dest, *rq_src; - int ret = 0; if (unlikely(cpu_is_offline(dest_cpu))) - return ret; + return; rq_src = cpu_rq(src_cpu); rq_dest = cpu_rq(dest_cpu); @@ -4842,10 +4503,9 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) if (TASK_PREEMPTS_CURR(p, rq_dest)) resched_task(rq_dest->curr); } - ret = 1; + out: double_rq_unlock(rq_src, rq_dest); - return ret; } /* @@ -4915,12 +4575,9 @@ static int migration_thread(void *data) /* Figure out where task on dead CPU should go, use force if neccessary. */ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk) { - runqueue_t *rq; - unsigned long flags; int dest_cpu; cpumask_t mask; -restart: /* On same node? */ mask = node_to_cpumask(cpu_to_node(dead_cpu)); cpus_and(mask, mask, tsk->cpus_allowed); @@ -4932,10 +4589,8 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk) /* No more Mr. Nice Guy. */ if (dest_cpu == NR_CPUS) { - rq = task_rq_lock(tsk, &flags); cpus_setall(tsk->cpus_allowed); dest_cpu = any_online_cpu(tsk->cpus_allowed); - task_rq_unlock(rq, &flags); /* * Don't tell them about moving exiting tasks or @@ -4947,8 +4602,7 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk) "longer affine to cpu%d\n", tsk->pid, tsk->comm, dead_cpu); } - if (!__migrate_task(tsk, dead_cpu, dest_cpu)) - goto restart; + __migrate_task(tsk, dead_cpu, dest_cpu); } /* @@ -5075,9 +4729,8 @@ static void migrate_dead_tasks(unsigned int dead_cpu) * migration_call - callback that gets triggered when a CPU is added. * Here we can start up the necessary migration thread for the new CPU. */ -static int __cpuinit migration_call(struct notifier_block *nfb, - unsigned long action, - void *hcpu) +static int migration_call(struct notifier_block *nfb, unsigned long action, + void *hcpu) { int cpu = (long)hcpu; struct task_struct *p; @@ -5147,7 +4800,7 @@ static int __cpuinit migration_call(struct notifier_block *nfb, /* Register at highest priority so that task migration (migrate_all_tasks) * happens before everything else. */ -static struct notifier_block __cpuinitdata migration_notifier = { +static struct notifier_block migration_notifier = { .notifier_call = migration_call, .priority = 10 }; @@ -5948,7 +5601,6 @@ static cpumask_t sched_domain_node_span(int node) } #endif -int sched_smt_power_savings = 0, sched_mc_power_savings = 0; /* * At the moment, CONFIG_SCHED_SMT is never defined, but leave it in so we * can switch it on easily if needed. @@ -5964,7 +5616,7 @@ static int cpu_to_cpu_group(int cpu) #ifdef CONFIG_SCHED_MC static DEFINE_PER_CPU(struct sched_domain, core_domains); -static struct sched_group *sched_group_core_bycpu[NR_CPUS]; +static struct sched_group sched_group_core[NR_CPUS]; #endif #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT) @@ -5980,7 +5632,7 @@ static int cpu_to_core_group(int cpu) #endif static DEFINE_PER_CPU(struct sched_domain, phys_domains); -static struct sched_group *sched_group_phys_bycpu[NR_CPUS]; +static struct sched_group sched_group_phys[NR_CPUS]; static int cpu_to_phys_group(int cpu) { #if defined(CONFIG_SCHED_MC) @@ -6037,74 +5689,13 @@ static void init_numa_sched_groups_power(struct sched_group *group_head) } #endif -/* Free memory allocated for various sched_group structures */ -static void free_sched_groups(const cpumask_t *cpu_map) -{ - int cpu; -#ifdef CONFIG_NUMA - int i; - - for_each_cpu_mask(cpu, *cpu_map) { - struct sched_group *sched_group_allnodes - = sched_group_allnodes_bycpu[cpu]; - struct sched_group **sched_group_nodes - = sched_group_nodes_bycpu[cpu]; - - if (sched_group_allnodes) { - kfree(sched_group_allnodes); - sched_group_allnodes_bycpu[cpu] = NULL; - } - - if (!sched_group_nodes) - continue; - - for (i = 0; i < MAX_NUMNODES; i++) { - cpumask_t nodemask = node_to_cpumask(i); - struct sched_group *oldsg, *sg = sched_group_nodes[i]; - - cpus_and(nodemask, nodemask, *cpu_map); - if (cpus_empty(nodemask)) - continue; - - if (sg == NULL) - continue; - sg = sg->next; -next_sg: - oldsg = sg; - sg = sg->next; - kfree(oldsg); - if (oldsg != sched_group_nodes[i]) - goto next_sg; - } - kfree(sched_group_nodes); - sched_group_nodes_bycpu[cpu] = NULL; - } -#endif - for_each_cpu_mask(cpu, *cpu_map) { - if (sched_group_phys_bycpu[cpu]) { - kfree(sched_group_phys_bycpu[cpu]); - sched_group_phys_bycpu[cpu] = NULL; - } -#ifdef CONFIG_SCHED_MC - if (sched_group_core_bycpu[cpu]) { - kfree(sched_group_core_bycpu[cpu]); - sched_group_core_bycpu[cpu] = NULL; - } -#endif - } -} - /* * Build sched domains for a given set of cpus and attach the sched domains * to the individual cpus */ -static int build_sched_domains(const cpumask_t *cpu_map) +void build_sched_domains(const cpumask_t *cpu_map) { int i; - struct sched_group *sched_group_phys = NULL; -#ifdef CONFIG_SCHED_MC - struct sched_group *sched_group_core = NULL; -#endif #ifdef CONFIG_NUMA struct sched_group **sched_group_nodes = NULL; struct sched_group *sched_group_allnodes = NULL; @@ -6112,11 +5703,11 @@ static int build_sched_domains(const cpumask_t *cpu_map) /* * Allocate the per-node list of sched groups */ - sched_group_nodes = kzalloc(sizeof(struct sched_group*)*MAX_NUMNODES, - GFP_KERNEL); + sched_group_nodes = kmalloc(sizeof(struct sched_group*)*MAX_NUMNODES, + GFP_ATOMIC); if (!sched_group_nodes) { printk(KERN_WARNING "Can not alloc sched group node list\n"); - return -ENOMEM; + return; } sched_group_nodes_bycpu[first_cpu(*cpu_map)] = sched_group_nodes; #endif @@ -6142,7 +5733,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) if (!sched_group_allnodes) { printk(KERN_WARNING "Can not alloc allnodes sched group\n"); - goto error; + break; } sched_group_allnodes_bycpu[i] = sched_group_allnodes; @@ -6163,18 +5754,6 @@ static int build_sched_domains(const cpumask_t *cpu_map) cpus_and(sd->span, sd->span, *cpu_map); #endif - if (!sched_group_phys) { - sched_group_phys - = kmalloc(sizeof(struct sched_group) * NR_CPUS, - GFP_KERNEL); - if (!sched_group_phys) { - printk (KERN_WARNING "Can not alloc phys sched" - "group\n"); - goto error; - } - sched_group_phys_bycpu[i] = sched_group_phys; - } - p = sd; sd = &per_cpu(phys_domains, i); group = cpu_to_phys_group(i); @@ -6184,18 +5763,6 @@ static int build_sched_domains(const cpumask_t *cpu_map) sd->groups = &sched_group_phys[group]; #ifdef CONFIG_SCHED_MC - if (!sched_group_core) { - sched_group_core - = kmalloc(sizeof(struct sched_group) * NR_CPUS, - GFP_KERNEL); - if (!sched_group_core) { - printk (KERN_WARNING "Can not alloc core sched" - "group\n"); - goto error; - } - sched_group_core_bycpu[i] = sched_group_core; - } - p = sd; sd = &per_cpu(core_domains, i); group = cpu_to_core_group(i); @@ -6279,21 +5846,24 @@ static int build_sched_domains(const cpumask_t *cpu_map) domainspan = sched_domain_node_span(i); cpus_and(domainspan, domainspan, *cpu_map); - sg = kmalloc_node(sizeof(struct sched_group), GFP_KERNEL, i); - if (!sg) { - printk(KERN_WARNING "Can not alloc domain group for " - "node %d\n", i); - goto error; - } + sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL); sched_group_nodes[i] = sg; for_each_cpu_mask(j, nodemask) { struct sched_domain *sd; sd = &per_cpu(node_domains, j); sd->groups = sg; + if (sd->groups == NULL) { + /* Turn off balancing if we have no groups */ + sd->flags = 0; + } + } + if (!sg) { + printk(KERN_WARNING + "Can not alloc domain group for node %d\n", i); + continue; } sg->cpu_power = 0; sg->cpumask = nodemask; - sg->next = sg; cpus_or(covered, covered, nodemask); prev = sg; @@ -6312,90 +5882,54 @@ static int build_sched_domains(const cpumask_t *cpu_map) if (cpus_empty(tmp)) continue; - sg = kmalloc_node(sizeof(struct sched_group), - GFP_KERNEL, i); + sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL); if (!sg) { printk(KERN_WARNING "Can not alloc domain group for node %d\n", j); - goto error; + break; } sg->cpu_power = 0; sg->cpumask = tmp; - sg->next = prev->next; cpus_or(covered, covered, tmp); prev->next = sg; prev = sg; } + prev->next = sched_group_nodes[i]; } #endif /* Calculate CPU power for physical packages and nodes */ -#ifdef CONFIG_SCHED_SMT for_each_cpu_mask(i, *cpu_map) { + int power; struct sched_domain *sd; +#ifdef CONFIG_SCHED_SMT sd = &per_cpu(cpu_domains, i); - sd->groups->cpu_power = SCHED_LOAD_SCALE; - } + power = SCHED_LOAD_SCALE; + sd->groups->cpu_power = power; #endif #ifdef CONFIG_SCHED_MC - for_each_cpu_mask(i, *cpu_map) { - int power; - struct sched_domain *sd; sd = &per_cpu(core_domains, i); - if (sched_smt_power_savings) - power = SCHED_LOAD_SCALE * cpus_weight(sd->groups->cpumask); - else - power = SCHED_LOAD_SCALE + (cpus_weight(sd->groups->cpumask)-1) + power = SCHED_LOAD_SCALE + (cpus_weight(sd->groups->cpumask)-1) * SCHED_LOAD_SCALE / 10; sd->groups->cpu_power = power; - } -#endif - for_each_cpu_mask(i, *cpu_map) { - struct sched_domain *sd; -#ifdef CONFIG_SCHED_MC sd = &per_cpu(phys_domains, i); - if (i != first_cpu(sd->groups->cpumask)) - continue; - sd->groups->cpu_power = 0; - if (sched_mc_power_savings || sched_smt_power_savings) { - int j; - - for_each_cpu_mask(j, sd->groups->cpumask) { - struct sched_domain *sd1; - sd1 = &per_cpu(core_domains, j); - /* - * for each core we will add once - * to the group in physical domain - */ - if (j != first_cpu(sd1->groups->cpumask)) - continue; - - if (sched_smt_power_savings) - sd->groups->cpu_power += sd1->groups->cpu_power; - else - sd->groups->cpu_power += SCHED_LOAD_SCALE; - } - } else - /* - * This has to be < 2 * SCHED_LOAD_SCALE - * Lets keep it SCHED_LOAD_SCALE, so that - * while calculating NUMA group's cpu_power - * we can simply do - * numa_group->cpu_power += phys_group->cpu_power; - * - * See "only add power once for each physical pkg" - * comment below - */ - sd->groups->cpu_power = SCHED_LOAD_SCALE; + /* + * This has to be < 2 * SCHED_LOAD_SCALE + * Lets keep it SCHED_LOAD_SCALE, so that + * while calculating NUMA group's cpu_power + * we can simply do + * numa_group->cpu_power += phys_group->cpu_power; + * + * See "only add power once for each physical pkg" + * comment below + */ + sd->groups->cpu_power = SCHED_LOAD_SCALE; #else - int power; sd = &per_cpu(phys_domains, i); - if (sched_smt_power_savings) - power = SCHED_LOAD_SCALE * cpus_weight(sd->groups->cpumask); - else - power = SCHED_LOAD_SCALE; + power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE * + (cpus_weight(sd->groups->cpumask)-1) / 10; sd->groups->cpu_power = power; #endif } @@ -6423,20 +5957,13 @@ static int build_sched_domains(const cpumask_t *cpu_map) * Tune cache-hot values: */ calibrate_migration_costs(cpu_map); - - return 0; - -error: - free_sched_groups(cpu_map); - return -ENOMEM; } /* * Set up scheduler domains and groups. Callers must hold the hotplug lock. */ -static int arch_init_sched_domains(const cpumask_t *cpu_map) +static void arch_init_sched_domains(const cpumask_t *cpu_map) { cpumask_t cpu_default_map; - int err; /* * Setup mask for cpus without special case scheduling requirements. @@ -6445,14 +5972,51 @@ static int arch_init_sched_domains(const cpumask_t *cpu_map) */ cpus_andnot(cpu_default_map, *cpu_map, cpu_isolated_map); - err = build_sched_domains(&cpu_default_map); - - return err; + build_sched_domains(&cpu_default_map); } static void arch_destroy_sched_domains(const cpumask_t *cpu_map) { - free_sched_groups(cpu_map); +#ifdef CONFIG_NUMA + int i; + int cpu; + + for_each_cpu_mask(cpu, *cpu_map) { + struct sched_group *sched_group_allnodes + = sched_group_allnodes_bycpu[cpu]; + struct sched_group **sched_group_nodes + = sched_group_nodes_bycpu[cpu]; + + if (sched_group_allnodes) { + kfree(sched_group_allnodes); + sched_group_allnodes_bycpu[cpu] = NULL; + } + + if (!sched_group_nodes) + continue; + + for (i = 0; i < MAX_NUMNODES; i++) { + cpumask_t nodemask = node_to_cpumask(i); + struct sched_group *oldsg, *sg = sched_group_nodes[i]; + + cpus_and(nodemask, nodemask, *cpu_map); + if (cpus_empty(nodemask)) + continue; + + if (sg == NULL) + continue; + sg = sg->next; +next_sg: + oldsg = sg; + sg = sg->next; + kfree(oldsg); + if (oldsg != sched_group_nodes[i]) + goto next_sg; + } + kfree(sched_group_nodes); + sched_group_nodes_bycpu[cpu] = NULL; + } +#endif } /* @@ -6477,10 +6041,9 @@ static void detach_destroy_domains(const cpumask_t *cpu_map) * correct sched domains * Call with hotplug lock held */ -int partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2) +void partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2) { cpumask_t change_map; - int err = 0; cpus_and(*partition1, *partition1, cpu_online_map); cpus_and(*partition2, *partition2, cpu_online_map); @@ -6489,87 +6052,11 @@ int partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2) /* Detach sched domains from all of the affected cpus */ detach_destroy_domains(&change_map); if (!cpus_empty(*partition1)) - err = build_sched_domains(partition1); - if (!err && !cpus_empty(*partition2)) - err = build_sched_domains(partition2); - - return err; -} - -#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) -int arch_reinit_sched_domains(void) -{ - int err; - - lock_cpu_hotplug(); - detach_destroy_domains(&cpu_online_map); - err = arch_init_sched_domains(&cpu_online_map); - unlock_cpu_hotplug(); - - return err; -} - -static ssize_t sched_power_savings_store(const char *buf, size_t count, int smt) -{ - int ret; - - if (buf[0] != '0' && buf[0] != '1') - return -EINVAL; - - if (smt) - sched_smt_power_savings = (buf[0] == '1'); - else - sched_mc_power_savings = (buf[0] == '1'); - - ret = arch_reinit_sched_domains(); - - return ret ? ret : count; + build_sched_domains(partition1); + if (!cpus_empty(*partition2)) + build_sched_domains(partition2); } -int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls) -{ - int err = 0; -#ifdef CONFIG_SCHED_SMT - if (smt_capable()) - err = sysfs_create_file(&cls->kset.kobj, - &attr_sched_smt_power_savings.attr); -#endif -#ifdef CONFIG_SCHED_MC - if (!err && mc_capable()) - err = sysfs_create_file(&cls->kset.kobj, - &attr_sched_mc_power_savings.attr); -#endif - return err; -} -#endif - -#ifdef CONFIG_SCHED_MC -static ssize_t sched_mc_power_savings_show(struct sys_device *dev, char *page) -{ - return sprintf(page, "%u\n", sched_mc_power_savings); -} -static ssize_t sched_mc_power_savings_store(struct sys_device *dev, const char *buf, size_t count) -{ - return sched_power_savings_store(buf, count, 0); -} -SYSDEV_ATTR(sched_mc_power_savings, 0644, sched_mc_power_savings_show, - sched_mc_power_savings_store); -#endif - -#ifdef CONFIG_SCHED_SMT -static ssize_t sched_smt_power_savings_show(struct sys_device *dev, char *page) -{ - return sprintf(page, "%u\n", sched_smt_power_savings); -} -static ssize_t sched_smt_power_savings_store(struct sys_device *dev, const char *buf, size_t count) -{ - return sched_power_savings_store(buf, count, 1); -} -SYSDEV_ATTR(sched_smt_power_savings, 0644, sched_smt_power_savings_show, - sched_smt_power_savings_store); -#endif - - #ifdef CONFIG_HOTPLUG_CPU /* * Force a reinitialization of the sched domains hierarchy. The domains @@ -6651,6 +6138,7 @@ void __init sched_init(void) rq->push_cpu = 0; rq->migration_thread = NULL; INIT_LIST_HEAD(&rq->migration_queue); + rq->cpu = i; #endif atomic_set(&rq->nr_iowait, 0); @@ -6665,7 +6153,6 @@ void __init sched_init(void) } } - set_load_weight(&init_task); /* * The boot idle thread does lazy MMU switching as well: */ @@ -6712,12 +6199,11 @@ void normalize_rt_tasks(void) runqueue_t *rq; read_lock_irq(&tasklist_lock); - for_each_process(p) { + for_each_process (p) { if (!rt_task(p)) continue; - spin_lock_irqsave(&p->pi_lock, flags); - rq = __task_rq_lock(p); + rq = task_rq_lock(p, &flags); array = p->array; if (array) @@ -6728,8 +6214,7 @@ void normalize_rt_tasks(void) resched_task(rq->curr); } - __task_rq_unlock(rq); - spin_unlock_irqrestore(&p->pi_lock, flags); + task_rq_unlock(rq, &flags); } read_unlock_irq(&tasklist_lock); } diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index 7fe874d12fae..1b3c921737e2 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -10,6 +10,7 @@ * to allow signals to be sent reliably. */ +#include #include #include #include @@ -583,7 +584,7 @@ static int check_kill_permission(int sig, struct siginfo *info, && !capable(CAP_KILL)) return error; - error = security_task_kill(t, info, sig, 0); + error = security_task_kill(t, info, sig); if (!error) audit_signal_info(sig, t); /* Let audit system see the signal */ return error; @@ -1106,7 +1107,7 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid) /* like kill_proc_info(), but doesn't use uid/euid of "current" */ int kill_proc_info_as_uid(int sig, struct siginfo *info, pid_t pid, - uid_t uid, uid_t euid, u32 secid) + uid_t uid, uid_t euid) { int ret = -EINVAL; struct task_struct *p; @@ -1126,9 +1127,6 @@ int kill_proc_info_as_uid(int sig, struct siginfo *info, pid_t pid, ret = -EPERM; goto out_unlock; } - ret = security_task_kill(p, info, sig, secid); - if (ret) - goto out_unlock; if (sig && p->sighand) { unsigned long flags; spin_lock_irqsave(&p->sighand->siglock, flags); @@ -1533,35 +1531,6 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why) spin_unlock_irqrestore(&sighand->siglock, flags); } -static inline int may_ptrace_stop(void) -{ - if (!likely(current->ptrace & PT_PTRACED)) - return 0; - - if (unlikely(current->parent == current->real_parent && - (current->ptrace & PT_ATTACHED))) - return 0; - - if (unlikely(current->signal == current->parent->signal) && - unlikely(current->signal->flags & SIGNAL_GROUP_EXIT)) - return 0; - - /* - * Are we in the middle of do_coredump? - * If so and our tracer is also part of the coredump stopping - * is a deadlock situation, and pointless because our tracer - * is dead so don't allow us to stop. - * If SIGKILL was already sent before the caller unlocked - * ->siglock we must see ->core_waiters != 0. Otherwise it - * is safe to enter schedule(). - */ - if (unlikely(current->mm->core_waiters) && - unlikely(current->mm == current->parent->mm)) - return 0; - - return 1; -} - /* * This must be called with current->sighand->siglock held. * @@ -1590,7 +1559,11 @@ static void ptrace_stop(int exit_code, int nostop_code, siginfo_t *info) spin_unlock_irq(¤t->sighand->siglock); try_to_freeze(); read_lock(&tasklist_lock); - if (may_ptrace_stop()) { + if (likely(current->ptrace & PT_PTRACED) && + likely(current->parent != current->real_parent || + !(current->ptrace & PT_ATTACHED)) && + (likely(current->parent->signal != current->signal) || + !unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))) { do_notify_parent_cldstop(current, CLD_TRAPPED); read_unlock(&tasklist_lock); schedule(); diff --git a/trunk/kernel/softirq.c b/trunk/kernel/softirq.c index 8f03e3b89b55..9e2f1c6e73d7 100644 --- a/trunk/kernel/softirq.c +++ b/trunk/kernel/softirq.c @@ -446,7 +446,7 @@ static void takeover_tasklets(unsigned int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __devinit cpu_callback(struct notifier_block *nfb, +static int cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -486,7 +486,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __devinitdata cpu_nfb = { +static struct notifier_block cpu_nfb = { .notifier_call = cpu_callback }; diff --git a/trunk/kernel/softlockup.c b/trunk/kernel/softlockup.c index 6b76caa22981..b5c3b94e01ce 100644 --- a/trunk/kernel/softlockup.c +++ b/trunk/kernel/softlockup.c @@ -104,7 +104,7 @@ static int watchdog(void * __bind_cpu) /* * Create/destroy watchdog threads as CPUs come and go: */ -static int __devinit +static int cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { int hotcpu = (unsigned long)hcpu; @@ -142,7 +142,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block __devinitdata cpu_nfb = { +static struct notifier_block cpu_nfb = { .notifier_call = cpu_callback }; diff --git a/trunk/kernel/spinlock.c b/trunk/kernel/spinlock.c index b31e54eadf56..d1b810782bc4 100644 --- a/trunk/kernel/spinlock.c +++ b/trunk/kernel/spinlock.c @@ -9,6 +9,7 @@ * SMP and the DEBUG_SPINLOCK cases. (UP-nondebug inlines them) */ +#include #include #include #include diff --git a/trunk/kernel/sys.c b/trunk/kernel/sys.c index dbb3b9c7ea64..2d5179c67cec 100644 --- a/trunk/kernel/sys.c +++ b/trunk/kernel/sys.c @@ -4,6 +4,7 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ +#include #include #include #include diff --git a/trunk/kernel/sysctl.c b/trunk/kernel/sysctl.c index 99a58f279077..2c0e65819448 100644 --- a/trunk/kernel/sysctl.c +++ b/trunk/kernel/sysctl.c @@ -18,6 +18,7 @@ * Removed it and replaced it with older style, 03/23/00, Bill Wendling */ +#include #include #include #include @@ -72,7 +73,6 @@ extern int printk_ratelimit_burst; extern int pid_max_min, pid_max_max; extern int sysctl_drop_caches; extern int percpu_pagelist_fraction; -extern int compat_log; #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86) int unknown_nmi_panic; @@ -132,10 +132,6 @@ extern int acct_parm[]; extern int no_unaligned_warning; #endif -#ifdef CONFIG_RT_MUTEXES -extern int max_lock_depth; -#endif - static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t, ctl_table *, void **); static int proc_doutsstring(ctl_table *table, int write, struct file *filp, @@ -681,27 +677,6 @@ static ctl_table kern_table[] = { .proc_handler = &proc_dointvec, }, #endif -#ifdef CONFIG_COMPAT - { - .ctl_name = KERN_COMPAT_LOG, - .procname = "compat-log", - .data = &compat_log, - .maxlen = sizeof (int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, -#endif -#ifdef CONFIG_RT_MUTEXES - { - .ctl_name = KERN_MAX_LOCK_DEPTH, - .procname = "max_lock_depth", - .data = &max_lock_depth, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, -#endif - { .ctl_name = 0 } }; @@ -932,17 +907,14 @@ static ctl_table vm_table[] = { .strategy = &sysctl_intvec, .extra1 = &zero, }, -#endif -#ifdef CONFIG_X86_32 { - .ctl_name = VM_VDSO_ENABLED, - .procname = "vdso_enabled", - .data = &vdso_enabled, - .maxlen = sizeof(vdso_enabled), + .ctl_name = VM_ZONE_RECLAIM_INTERVAL, + .procname = "zone_reclaim_interval", + .data = &zone_reclaim_interval, + .maxlen = sizeof(zone_reclaim_interval), .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec, - .extra1 = &zero, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, }, #endif { .ctl_name = 0 } diff --git a/trunk/kernel/time.c b/trunk/kernel/time.c index 5bd489747643..b00ddc71cedb 100644 --- a/trunk/kernel/time.c +++ b/trunk/kernel/time.c @@ -523,7 +523,6 @@ EXPORT_SYMBOL(do_gettimeofday); #else -#ifndef CONFIG_GENERIC_TIME /* * Simulate gettimeofday using do_gettimeofday which only allows a timeval * and therefore only yields usec accuracy @@ -538,7 +537,6 @@ void getnstimeofday(struct timespec *tv) } EXPORT_SYMBOL_GPL(getnstimeofday); #endif -#endif /* Converts Gregorian date to seconds since 1970-01-01 00:00:00. * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 diff --git a/trunk/kernel/time/Makefile b/trunk/kernel/time/Makefile deleted file mode 100644 index e1dfd8e86cce..000000000000 --- a/trunk/kernel/time/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y += clocksource.o jiffies.o diff --git a/trunk/kernel/time/clocksource.c b/trunk/kernel/time/clocksource.c deleted file mode 100644 index 74eca5939bd9..000000000000 --- a/trunk/kernel/time/clocksource.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * linux/kernel/time/clocksource.c - * - * This file contains the functions which manage clocksource drivers. - * - * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * TODO WishList: - * o Allow clocksource drivers to be unregistered - * o get rid of clocksource_jiffies extern - */ - -#include -#include -#include -#include - -/* XXX - Would like a better way for initializing curr_clocksource */ -extern struct clocksource clocksource_jiffies; - -/*[Clocksource internal variables]--------- - * curr_clocksource: - * currently selected clocksource. Initialized to clocksource_jiffies. - * next_clocksource: - * pending next selected clocksource. - * clocksource_list: - * linked list with the registered clocksources - * clocksource_lock: - * protects manipulations to curr_clocksource and next_clocksource - * and the clocksource_list - * override_name: - * Name of the user-specified clocksource. - */ -static struct clocksource *curr_clocksource = &clocksource_jiffies; -static struct clocksource *next_clocksource; -static LIST_HEAD(clocksource_list); -static DEFINE_SPINLOCK(clocksource_lock); -static char override_name[32]; -static int finished_booting; - -/* clocksource_done_booting - Called near the end of bootup - * - * Hack to avoid lots of clocksource churn at boot time - */ -static int __init clocksource_done_booting(void) -{ - finished_booting = 1; - return 0; -} - -late_initcall(clocksource_done_booting); - -/** - * clocksource_get_next - Returns the selected clocksource - * - */ -struct clocksource *clocksource_get_next(void) -{ - unsigned long flags; - - spin_lock_irqsave(&clocksource_lock, flags); - if (next_clocksource && finished_booting) { - curr_clocksource = next_clocksource; - next_clocksource = NULL; - } - spin_unlock_irqrestore(&clocksource_lock, flags); - - return curr_clocksource; -} - -/** - * select_clocksource - Finds the best registered clocksource. - * - * Private function. Must hold clocksource_lock when called. - * - * Looks through the list of registered clocksources, returning - * the one with the highest rating value. If there is a clocksource - * name that matches the override string, it returns that clocksource. - */ -static struct clocksource *select_clocksource(void) -{ - struct clocksource *best = NULL; - struct list_head *tmp; - - list_for_each(tmp, &clocksource_list) { - struct clocksource *src; - - src = list_entry(tmp, struct clocksource, list); - if (!best) - best = src; - - /* check for override: */ - if (strlen(src->name) == strlen(override_name) && - !strcmp(src->name, override_name)) { - best = src; - break; - } - /* pick the highest rating: */ - if (src->rating > best->rating) - best = src; - } - - return best; -} - -/** - * is_registered_source - Checks if clocksource is registered - * @c: pointer to a clocksource - * - * Private helper function. Must hold clocksource_lock when called. - * - * Returns one if the clocksource is already registered, zero otherwise. - */ -static int is_registered_source(struct clocksource *c) -{ - int len = strlen(c->name); - struct list_head *tmp; - - list_for_each(tmp, &clocksource_list) { - struct clocksource *src; - - src = list_entry(tmp, struct clocksource, list); - if (strlen(src->name) == len && !strcmp(src->name, c->name)) - return 1; - } - - return 0; -} - -/** - * clocksource_register - Used to install new clocksources - * @t: clocksource to be registered - * - * Returns -EBUSY if registration fails, zero otherwise. - */ -int clocksource_register(struct clocksource *c) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&clocksource_lock, flags); - /* check if clocksource is already registered */ - if (is_registered_source(c)) { - printk("register_clocksource: Cannot register %s. " - "Already registered!", c->name); - ret = -EBUSY; - } else { - /* register it */ - list_add(&c->list, &clocksource_list); - /* scan the registered clocksources, and pick the best one */ - next_clocksource = select_clocksource(); - } - spin_unlock_irqrestore(&clocksource_lock, flags); - return ret; -} -EXPORT_SYMBOL(clocksource_register); - -/** - * clocksource_reselect - Rescan list for next clocksource - * - * A quick helper function to be used if a clocksource changes its - * rating. Forces the clocksource list to be re-scanned for the best - * clocksource. - */ -void clocksource_reselect(void) -{ - unsigned long flags; - - spin_lock_irqsave(&clocksource_lock, flags); - next_clocksource = select_clocksource(); - spin_unlock_irqrestore(&clocksource_lock, flags); -} -EXPORT_SYMBOL(clocksource_reselect); - -/** - * sysfs_show_current_clocksources - sysfs interface for current clocksource - * @dev: unused - * @buf: char buffer to be filled with clocksource list - * - * Provides sysfs interface for listing current clocksource. - */ -static ssize_t -sysfs_show_current_clocksources(struct sys_device *dev, char *buf) -{ - char *curr = buf; - - spin_lock_irq(&clocksource_lock); - curr += sprintf(curr, "%s ", curr_clocksource->name); - spin_unlock_irq(&clocksource_lock); - - curr += sprintf(curr, "\n"); - - return curr - buf; -} - -/** - * sysfs_override_clocksource - interface for manually overriding clocksource - * @dev: unused - * @buf: name of override clocksource - * @count: length of buffer - * - * Takes input from sysfs interface for manually overriding the default - * clocksource selction. - */ -static ssize_t sysfs_override_clocksource(struct sys_device *dev, - const char *buf, size_t count) -{ - size_t ret = count; - /* strings from sysfs write are not 0 terminated! */ - if (count >= sizeof(override_name)) - return -EINVAL; - - /* strip of \n: */ - if (buf[count-1] == '\n') - count--; - if (count < 1) - return -EINVAL; - - spin_lock_irq(&clocksource_lock); - - /* copy the name given: */ - memcpy(override_name, buf, count); - override_name[count] = 0; - - /* try to select it: */ - next_clocksource = select_clocksource(); - - spin_unlock_irq(&clocksource_lock); - - return ret; -} - -/** - * sysfs_show_available_clocksources - sysfs interface for listing clocksource - * @dev: unused - * @buf: char buffer to be filled with clocksource list - * - * Provides sysfs interface for listing registered clocksources - */ -static ssize_t -sysfs_show_available_clocksources(struct sys_device *dev, char *buf) -{ - struct list_head *tmp; - char *curr = buf; - - spin_lock_irq(&clocksource_lock); - list_for_each(tmp, &clocksource_list) { - struct clocksource *src; - - src = list_entry(tmp, struct clocksource, list); - curr += sprintf(curr, "%s ", src->name); - } - spin_unlock_irq(&clocksource_lock); - - curr += sprintf(curr, "\n"); - - return curr - buf; -} - -/* - * Sysfs setup bits: - */ -static SYSDEV_ATTR(current_clocksource, 0600, sysfs_show_current_clocksources, - sysfs_override_clocksource); - -static SYSDEV_ATTR(available_clocksource, 0600, - sysfs_show_available_clocksources, NULL); - -static struct sysdev_class clocksource_sysclass = { - set_kset_name("clocksource"), -}; - -static struct sys_device device_clocksource = { - .id = 0, - .cls = &clocksource_sysclass, -}; - -static int __init init_clocksource_sysfs(void) -{ - int error = sysdev_class_register(&clocksource_sysclass); - - if (!error) - error = sysdev_register(&device_clocksource); - if (!error) - error = sysdev_create_file( - &device_clocksource, - &attr_current_clocksource); - if (!error) - error = sysdev_create_file( - &device_clocksource, - &attr_available_clocksource); - return error; -} - -device_initcall(init_clocksource_sysfs); - -/** - * boot_override_clocksource - boot clock override - * @str: override name - * - * Takes a clocksource= boot argument and uses it - * as the clocksource override name. - */ -static int __init boot_override_clocksource(char* str) -{ - unsigned long flags; - spin_lock_irqsave(&clocksource_lock, flags); - if (str) - strlcpy(override_name, str, sizeof(override_name)); - spin_unlock_irqrestore(&clocksource_lock, flags); - return 1; -} - -__setup("clocksource=", boot_override_clocksource); - -/** - * boot_override_clock - Compatibility layer for deprecated boot option - * @str: override name - * - * DEPRECATED! Takes a clock= boot argument and uses it - * as the clocksource override name - */ -static int __init boot_override_clock(char* str) -{ - if (!strcmp(str, "pmtmr")) { - printk("Warning: clock=pmtmr is deprecated. " - "Use clocksource=acpi_pm.\n"); - return boot_override_clocksource("acpi_pm"); - } - printk("Warning! clock= boot option is deprecated. " - "Use clocksource=xyz\n"); - return boot_override_clocksource(str); -} - -__setup("clock=", boot_override_clock); diff --git a/trunk/kernel/time/jiffies.c b/trunk/kernel/time/jiffies.c deleted file mode 100644 index 126bb30c4afe..000000000000 --- a/trunk/kernel/time/jiffies.c +++ /dev/null @@ -1,73 +0,0 @@ -/*********************************************************************** -* linux/kernel/time/jiffies.c -* -* This file contains the jiffies based clocksource. -* -* Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -* -************************************************************************/ -#include -#include -#include - -/* The Jiffies based clocksource is the lowest common - * denominator clock source which should function on - * all systems. It has the same coarse resolution as - * the timer interrupt frequency HZ and it suffers - * inaccuracies caused by missed or lost timer - * interrupts and the inability for the timer - * interrupt hardware to accuratly tick at the - * requested HZ value. It is also not reccomended - * for "tick-less" systems. - */ -#define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/ACTHZ)) - -/* Since jiffies uses a simple NSEC_PER_JIFFY multiplier - * conversion, the .shift value could be zero. However - * this would make NTP adjustments impossible as they are - * in units of 1/2^.shift. Thus we use JIFFIES_SHIFT to - * shift both the nominator and denominator the same - * amount, and give ntp adjustments in units of 1/2^8 - * - * The value 8 is somewhat carefully chosen, as anything - * larger can result in overflows. NSEC_PER_JIFFY grows as - * HZ shrinks, so values greater then 8 overflow 32bits when - * HZ=100. - */ -#define JIFFIES_SHIFT 8 - -static cycle_t jiffies_read(void) -{ - return (cycle_t) jiffies; -} - -struct clocksource clocksource_jiffies = { - .name = "jiffies", - .rating = 0, /* lowest rating*/ - .read = jiffies_read, - .mask = 0xffffffff, /*32bits*/ - .mult = NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */ - .shift = JIFFIES_SHIFT, - .is_continuous = 0, /* tick based, not free running */ -}; - -static int __init init_jiffies_clocksource(void) -{ - return clocksource_register(&clocksource_jiffies); -} - -module_init(init_jiffies_clocksource); diff --git a/trunk/kernel/timer.c b/trunk/kernel/timer.c index 5a8960253063..eb97371b87d8 100644 --- a/trunk/kernel/timer.c +++ b/trunk/kernel/timer.c @@ -597,6 +597,7 @@ long time_tolerance = MAXFREQ; /* frequency tolerance (ppm) */ long time_precision = 1; /* clock precision (us) */ long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */ long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */ +static long time_phase; /* phase offset (scaled us) */ long time_freq = (((NSEC_PER_SEC + HZ/2) % HZ - HZ/2) << SHIFT_USEC) / NSEC_PER_USEC; /* frequency offset (scaled ppm)*/ static long time_adj; /* tick adjust (scaled 1 / HZ) */ @@ -746,14 +747,27 @@ static long adjtime_adjustment(void) } /* in the NTP reference this is called "hardclock()" */ -static void update_ntp_one_tick(void) +static void update_wall_time_one_tick(void) { - long time_adjust_step; + long time_adjust_step, delta_nsec; time_adjust_step = adjtime_adjustment(); if (time_adjust_step) /* Reduce by this step the amount of time left */ time_adjust -= time_adjust_step; + delta_nsec = tick_nsec + time_adjust_step * 1000; + /* + * Advance the phase, once it gets to one microsecond, then + * advance the tick more. + */ + time_phase += time_adj; + if ((time_phase >= FINENSEC) || (time_phase <= -FINENSEC)) { + long ltemp = shift_right(time_phase, (SHIFT_SCALE - 10)); + time_phase -= ltemp << (SHIFT_SCALE - 10); + delta_nsec += ltemp; + } + xtime.tv_nsec += delta_nsec; + time_interpolator_update(delta_nsec); /* Changes by adjtime() do not take effect till next tick. */ if (time_next_adjust != 0) { @@ -766,378 +780,36 @@ static void update_ntp_one_tick(void) * Return how long ticks are at the moment, that is, how much time * update_wall_time_one_tick will add to xtime next time we call it * (assuming no calls to do_adjtimex in the meantime). - * The return value is in fixed-point nanoseconds shifted by the - * specified number of bits to the right of the binary point. + * The return value is in fixed-point nanoseconds with SHIFT_SCALE-10 + * bits to the right of the binary point. * This function has no side-effects. */ u64 current_tick_length(void) { long delta_nsec; - u64 ret; - /* calculate the finest interval NTP will allow. - * ie: nanosecond value shifted by (SHIFT_SCALE - 10) - */ delta_nsec = tick_nsec + adjtime_adjustment() * 1000; - ret = (u64)delta_nsec << TICK_LENGTH_SHIFT; - ret += (s64)time_adj << (TICK_LENGTH_SHIFT - (SHIFT_SCALE - 10)); - - return ret; -} - -/* XXX - all of this timekeeping code should be later moved to time.c */ -#include -static struct clocksource *clock; /* pointer to current clocksource */ - -#ifdef CONFIG_GENERIC_TIME -/** - * __get_nsec_offset - Returns nanoseconds since last call to periodic_hook - * - * private function, must hold xtime_lock lock when being - * called. Returns the number of nanoseconds since the - * last call to update_wall_time() (adjusted by NTP scaling) - */ -static inline s64 __get_nsec_offset(void) -{ - cycle_t cycle_now, cycle_delta; - s64 ns_offset; - - /* read clocksource: */ - cycle_now = clocksource_read(clock); - - /* calculate the delta since the last update_wall_time: */ - cycle_delta = (cycle_now - clock->cycle_last) & clock->mask; - - /* convert to nanoseconds: */ - ns_offset = cyc2ns(clock, cycle_delta); - - return ns_offset; -} - -/** - * __get_realtime_clock_ts - Returns the time of day in a timespec - * @ts: pointer to the timespec to be set - * - * Returns the time of day in a timespec. Used by - * do_gettimeofday() and get_realtime_clock_ts(). - */ -static inline void __get_realtime_clock_ts(struct timespec *ts) -{ - unsigned long seq; - s64 nsecs; - - do { - seq = read_seqbegin(&xtime_lock); - - *ts = xtime; - nsecs = __get_nsec_offset(); - - } while (read_seqretry(&xtime_lock, seq)); - - timespec_add_ns(ts, nsecs); -} - -/** - * getnstimeofday - Returns the time of day in a timespec - * @ts: pointer to the timespec to be set - * - * Returns the time of day in a timespec. - */ -void getnstimeofday(struct timespec *ts) -{ - __get_realtime_clock_ts(ts); -} - -EXPORT_SYMBOL(getnstimeofday); - -/** - * do_gettimeofday - Returns the time of day in a timeval - * @tv: pointer to the timeval to be set - * - * NOTE: Users should be converted to using get_realtime_clock_ts() - */ -void do_gettimeofday(struct timeval *tv) -{ - struct timespec now; - - __get_realtime_clock_ts(&now); - tv->tv_sec = now.tv_sec; - tv->tv_usec = now.tv_nsec/1000; -} - -EXPORT_SYMBOL(do_gettimeofday); -/** - * do_settimeofday - Sets the time of day - * @tv: pointer to the timespec variable containing the new time - * - * Sets the time of day to the new time and update NTP and notify hrtimers - */ -int do_settimeofday(struct timespec *tv) -{ - unsigned long flags; - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - write_seqlock_irqsave(&xtime_lock, flags); - - nsec -= __get_nsec_offset(); - - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - ntp_clear(); - - write_sequnlock_irqrestore(&xtime_lock, flags); - - /* signal hrtimers about time change */ - clock_was_set(); - - return 0; -} - -EXPORT_SYMBOL(do_settimeofday); - -/** - * change_clocksource - Swaps clocksources if a new one is available - * - * Accumulates current time interval and initializes new clocksource - */ -static int change_clocksource(void) -{ - struct clocksource *new; - cycle_t now; - u64 nsec; - new = clocksource_get_next(); - if (clock != new) { - now = clocksource_read(new); - nsec = __get_nsec_offset(); - timespec_add_ns(&xtime, nsec); - - clock = new; - clock->cycle_last = now; - printk(KERN_INFO "Time: %s clocksource has been installed.\n", - clock->name); - return 1; - } else if (clock->update_callback) { - return clock->update_callback(); - } - return 0; -} -#else -#define change_clocksource() (0) -#endif - -/** - * timeofday_is_continuous - check to see if timekeeping is free running - */ -int timekeeping_is_continuous(void) -{ - unsigned long seq; - int ret; - - do { - seq = read_seqbegin(&xtime_lock); - - ret = clock->is_continuous; - - } while (read_seqretry(&xtime_lock, seq)); - - return ret; -} - -/* - * timekeeping_init - Initializes the clocksource and common timekeeping values - */ -void __init timekeeping_init(void) -{ - unsigned long flags; - - write_seqlock_irqsave(&xtime_lock, flags); - clock = clocksource_get_next(); - clocksource_calculate_interval(clock, tick_nsec); - clock->cycle_last = clocksource_read(clock); - ntp_clear(); - write_sequnlock_irqrestore(&xtime_lock, flags); -} - - -/* - * timekeeping_resume - Resumes the generic timekeeping subsystem. - * @dev: unused - * - * This is for the generic clocksource timekeeping. - * xtime/wall_to_monotonic/jiffies/wall_jiffies/etc are - * still managed by arch specific suspend/resume code. - */ -static int timekeeping_resume(struct sys_device *dev) -{ - unsigned long flags; - - write_seqlock_irqsave(&xtime_lock, flags); - /* restart the last cycle value */ - clock->cycle_last = clocksource_read(clock); - write_sequnlock_irqrestore(&xtime_lock, flags); - return 0; -} - -/* sysfs resume/suspend bits for timekeeping */ -static struct sysdev_class timekeeping_sysclass = { - .resume = timekeeping_resume, - set_kset_name("timekeeping"), -}; - -static struct sys_device device_timer = { - .id = 0, - .cls = &timekeeping_sysclass, -}; - -static int __init timekeeping_init_device(void) -{ - int error = sysdev_class_register(&timekeeping_sysclass); - if (!error) - error = sysdev_register(&device_timer); - return error; -} - -device_initcall(timekeeping_init_device); - -/* - * If the error is already larger, we look ahead another tick, - * to compensate for late or lost adjustments. - */ -static __always_inline int clocksource_bigadjust(int sign, s64 error, s64 *interval, s64 *offset) -{ - int adj; - - /* - * As soon as the machine is synchronized to the external time - * source this should be the common case. - */ - error >>= 2; - if (likely(sign > 0 ? error <= *interval : error >= *interval)) - return sign; - - /* - * An extra look ahead dampens the effect of the current error, - * which can grow quite large with continously late updates, as - * it would dominate the adjustment value and can lead to - * oscillation. - */ - error += current_tick_length() >> (TICK_LENGTH_SHIFT - clock->shift + 1); - error -= clock->xtime_interval >> 1; - - adj = 0; - while (1) { - error >>= 1; - if (sign > 0 ? error <= *interval : error >= *interval) - break; - adj++; - } - - /* - * Add the current adjustments to the error and take the offset - * into account, the latter can cause the error to be hardly - * reduced at the next tick. Check the error again if there's - * room for another adjustment, thus further reducing the error - * which otherwise had to be corrected at the next update. - */ - error = (error << 1) - *interval + *offset; - if (sign > 0 ? error > *interval : error < *interval) - adj++; - - *interval <<= adj; - *offset <<= adj; - return sign << adj; -} - -/* - * Adjust the multiplier to reduce the error value, - * this is optimized for the most common adjustments of -1,0,1, - * for other values we can do a bit more work. - */ -static void clocksource_adjust(struct clocksource *clock, s64 offset) -{ - s64 error, interval = clock->cycle_interval; - int adj; - - error = clock->error >> (TICK_LENGTH_SHIFT - clock->shift - 1); - if (error > interval) { - adj = clocksource_bigadjust(1, error, &interval, &offset); - } else if (error < -interval) { - interval = -interval; - offset = -offset; - adj = clocksource_bigadjust(-1, error, &interval, &offset); - } else - return; - - clock->mult += adj; - clock->xtime_interval += interval; - clock->xtime_nsec -= offset; - clock->error -= (interval - offset) << (TICK_LENGTH_SHIFT - clock->shift); + return ((u64) delta_nsec << (SHIFT_SCALE - 10)) + time_adj; } /* - * update_wall_time - Uses the current clocksource to increment the wall time - * - * Called from the timer interrupt, must hold a write on xtime_lock. + * Using a loop looks inefficient, but "ticks" is + * usually just one (we shouldn't be losing ticks, + * we're doing this this way mainly for interrupt + * latency reasons, not because we think we'll + * have lots of lost timer ticks */ -static void update_wall_time(void) +static void update_wall_time(unsigned long ticks) { - cycle_t offset; - - clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift; - -#ifdef CONFIG_GENERIC_TIME - offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask; -#else - offset = clock->cycle_interval; -#endif - - /* normally this loop will run just once, however in the - * case of lost or late ticks, it will accumulate correctly. - */ - while (offset >= clock->cycle_interval) { - /* accumulate one interval */ - clock->xtime_nsec += clock->xtime_interval; - clock->cycle_last += clock->cycle_interval; - offset -= clock->cycle_interval; - - if (clock->xtime_nsec >= (u64)NSEC_PER_SEC << clock->shift) { - clock->xtime_nsec -= (u64)NSEC_PER_SEC << clock->shift; + do { + ticks--; + update_wall_time_one_tick(); + if (xtime.tv_nsec >= 1000000000) { + xtime.tv_nsec -= 1000000000; xtime.tv_sec++; second_overflow(); } - - /* interpolator bits */ - time_interpolator_update(clock->xtime_interval - >> clock->shift); - /* increment the NTP state machine */ - update_ntp_one_tick(); - - /* accumulate error between NTP and clock interval */ - clock->error += current_tick_length(); - clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift); - } - - /* correct the clock when NTP error is too big */ - clocksource_adjust(clock, offset); - - /* store full nanoseconds into xtime */ - xtime.tv_nsec = clock->xtime_nsec >> clock->shift; - clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift; - - /* check to see if there is a new clocksource to use */ - if (change_clocksource()) { - clock->error = 0; - clock->xtime_nsec = 0; - clocksource_calculate_interval(clock, tick_nsec); - } + } while (ticks); } /* @@ -1243,8 +915,10 @@ static inline void update_times(void) unsigned long ticks; ticks = jiffies - wall_jiffies; - wall_jiffies += ticks; - update_wall_time(); + if (ticks) { + wall_jiffies += ticks; + update_wall_time(ticks); + } calc_load(ticks); } @@ -1652,7 +1326,7 @@ static void __devinit migrate_timers(int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __devinit timer_cpu_notify(struct notifier_block *self, +static int timer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -1672,7 +1346,7 @@ static int __devinit timer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __devinitdata timers_nb = { +static struct notifier_block timers_nb = { .notifier_call = timer_cpu_notify, }; diff --git a/trunk/kernel/unwind.c b/trunk/kernel/unwind.c deleted file mode 100644 index f69c804c8e62..000000000000 --- a/trunk/kernel/unwind.c +++ /dev/null @@ -1,918 +0,0 @@ -/* - * Copyright (C) 2002-2006 Novell, Inc. - * Jan Beulich - * This code is released under version 2 of the GNU GPL. - * - * A simple API for unwinding kernel stacks. This is used for - * debugging and error reporting purposes. The kernel doesn't need - * full-blown stack unwinding with all the bells and whistles, so there - * is not much point in implementing the full Dwarf2 unwind API. - */ - -#include -#include -#include -#include -#include -#include -#include - -extern char __start_unwind[], __end_unwind[]; - -#define MAX_STACK_DEPTH 8 - -#define EXTRA_INFO(f) { \ - BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \ - % FIELD_SIZEOF(struct unwind_frame_info, f)) \ - + offsetof(struct unwind_frame_info, f) \ - / FIELD_SIZEOF(struct unwind_frame_info, f), \ - FIELD_SIZEOF(struct unwind_frame_info, f) \ - } -#define PTREGS_INFO(f) EXTRA_INFO(regs.f) - -static const struct { - unsigned offs:BITS_PER_LONG / 2; - unsigned width:BITS_PER_LONG / 2; -} reg_info[] = { - UNW_REGISTER_INFO -}; - -#undef PTREGS_INFO -#undef EXTRA_INFO - -#ifndef REG_INVALID -#define REG_INVALID(r) (reg_info[r].width == 0) -#endif - -#define DW_CFA_nop 0x00 -#define DW_CFA_set_loc 0x01 -#define DW_CFA_advance_loc1 0x02 -#define DW_CFA_advance_loc2 0x03 -#define DW_CFA_advance_loc4 0x04 -#define DW_CFA_offset_extended 0x05 -#define DW_CFA_restore_extended 0x06 -#define DW_CFA_undefined 0x07 -#define DW_CFA_same_value 0x08 -#define DW_CFA_register 0x09 -#define DW_CFA_remember_state 0x0a -#define DW_CFA_restore_state 0x0b -#define DW_CFA_def_cfa 0x0c -#define DW_CFA_def_cfa_register 0x0d -#define DW_CFA_def_cfa_offset 0x0e -#define DW_CFA_def_cfa_expression 0x0f -#define DW_CFA_expression 0x10 -#define DW_CFA_offset_extended_sf 0x11 -#define DW_CFA_def_cfa_sf 0x12 -#define DW_CFA_def_cfa_offset_sf 0x13 -#define DW_CFA_val_offset 0x14 -#define DW_CFA_val_offset_sf 0x15 -#define DW_CFA_val_expression 0x16 -#define DW_CFA_lo_user 0x1c -#define DW_CFA_GNU_window_save 0x2d -#define DW_CFA_GNU_args_size 0x2e -#define DW_CFA_GNU_negative_offset_extended 0x2f -#define DW_CFA_hi_user 0x3f - -#define DW_EH_PE_FORM 0x07 -#define DW_EH_PE_native 0x00 -#define DW_EH_PE_leb128 0x01 -#define DW_EH_PE_data2 0x02 -#define DW_EH_PE_data4 0x03 -#define DW_EH_PE_data8 0x04 -#define DW_EH_PE_signed 0x08 -#define DW_EH_PE_ADJUST 0x70 -#define DW_EH_PE_abs 0x00 -#define DW_EH_PE_pcrel 0x10 -#define DW_EH_PE_textrel 0x20 -#define DW_EH_PE_datarel 0x30 -#define DW_EH_PE_funcrel 0x40 -#define DW_EH_PE_aligned 0x50 -#define DW_EH_PE_indirect 0x80 -#define DW_EH_PE_omit 0xff - -typedef unsigned long uleb128_t; -typedef signed long sleb128_t; - -static struct unwind_table { - struct { - unsigned long pc; - unsigned long range; - } core, init; - const void *address; - unsigned long size; - struct unwind_table *link; - const char *name; -} root_table, *last_table; - -struct unwind_item { - enum item_location { - Nowhere, - Memory, - Register, - Value - } where; - uleb128_t value; -}; - -struct unwind_state { - uleb128_t loc, org; - const u8 *cieStart, *cieEnd; - uleb128_t codeAlign; - sleb128_t dataAlign; - struct cfa { - uleb128_t reg, offs; - } cfa; - struct unwind_item regs[ARRAY_SIZE(reg_info)]; - unsigned stackDepth:8; - unsigned version:8; - const u8 *label; - const u8 *stack[MAX_STACK_DEPTH]; -}; - -static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 }; - -static struct unwind_table *find_table(unsigned long pc) -{ - struct unwind_table *table; - - for (table = &root_table; table; table = table->link) - if ((pc >= table->core.pc - && pc < table->core.pc + table->core.range) - || (pc >= table->init.pc - && pc < table->init.pc + table->init.range)) - break; - - return table; -} - -static void init_unwind_table(struct unwind_table *table, - const char *name, - const void *core_start, - unsigned long core_size, - const void *init_start, - unsigned long init_size, - const void *table_start, - unsigned long table_size) -{ - table->core.pc = (unsigned long)core_start; - table->core.range = core_size; - table->init.pc = (unsigned long)init_start; - table->init.range = init_size; - table->address = table_start; - table->size = table_size; - table->link = NULL; - table->name = name; -} - -void __init unwind_init(void) -{ - init_unwind_table(&root_table, "kernel", - _text, _end - _text, - NULL, 0, - __start_unwind, __end_unwind - __start_unwind); -} - -#ifdef CONFIG_MODULES - -/* Must be called with module_mutex held. */ -void *unwind_add_table(struct module *module, - const void *table_start, - unsigned long table_size) -{ - struct unwind_table *table; - - if (table_size <= 0) - return NULL; - - table = kmalloc(sizeof(*table), GFP_KERNEL); - if (!table) - return NULL; - - init_unwind_table(table, module->name, - module->module_core, module->core_size, - module->module_init, module->init_size, - table_start, table_size); - - if (last_table) - last_table->link = table; - else - root_table.link = table; - last_table = table; - - return table; -} - -struct unlink_table_info -{ - struct unwind_table *table; - int init_only; -}; - -static int unlink_table(void *arg) -{ - struct unlink_table_info *info = arg; - struct unwind_table *table = info->table, *prev; - - for (prev = &root_table; prev->link && prev->link != table; prev = prev->link) - ; - - if (prev->link) { - if (info->init_only) { - table->init.pc = 0; - table->init.range = 0; - info->table = NULL; - } else { - prev->link = table->link; - if (!prev->link) - last_table = prev; - } - } else - info->table = NULL; - - return 0; -} - -/* Must be called with module_mutex held. */ -void unwind_remove_table(void *handle, int init_only) -{ - struct unwind_table *table = handle; - struct unlink_table_info info; - - if (!table || table == &root_table) - return; - - if (init_only && table == last_table) { - table->init.pc = 0; - table->init.range = 0; - return; - } - - info.table = table; - info.init_only = init_only; - stop_machine_run(unlink_table, &info, NR_CPUS); - - if (info.table) - kfree(table); -} - -#endif /* CONFIG_MODULES */ - -static uleb128_t get_uleb128(const u8 **pcur, const u8 *end) -{ - const u8 *cur = *pcur; - uleb128_t value; - unsigned shift; - - for (shift = 0, value = 0; cur < end; shift += 7) { - if (shift + 7 > 8 * sizeof(value) - && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) { - cur = end + 1; - break; - } - value |= (uleb128_t)(*cur & 0x7f) << shift; - if (!(*cur++ & 0x80)) - break; - } - *pcur = cur; - - return value; -} - -static sleb128_t get_sleb128(const u8 **pcur, const u8 *end) -{ - const u8 *cur = *pcur; - sleb128_t value; - unsigned shift; - - for (shift = 0, value = 0; cur < end; shift += 7) { - if (shift + 7 > 8 * sizeof(value) - && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) { - cur = end + 1; - break; - } - value |= (sleb128_t)(*cur & 0x7f) << shift; - if (!(*cur & 0x80)) { - value |= -(*cur++ & 0x40) << shift; - break; - } - } - *pcur = cur; - - return value; -} - -static unsigned long read_pointer(const u8 **pLoc, - const void *end, - signed ptrType) -{ - unsigned long value = 0; - union { - const u8 *p8; - const u16 *p16u; - const s16 *p16s; - const u32 *p32u; - const s32 *p32s; - const unsigned long *pul; - } ptr; - - if (ptrType < 0 || ptrType == DW_EH_PE_omit) - return 0; - ptr.p8 = *pLoc; - switch(ptrType & DW_EH_PE_FORM) { - case DW_EH_PE_data2: - if (end < (const void *)(ptr.p16u + 1)) - return 0; - if(ptrType & DW_EH_PE_signed) - value = get_unaligned(ptr.p16s++); - else - value = get_unaligned(ptr.p16u++); - break; - case DW_EH_PE_data4: -#ifdef CONFIG_64BIT - if (end < (const void *)(ptr.p32u + 1)) - return 0; - if(ptrType & DW_EH_PE_signed) - value = get_unaligned(ptr.p32s++); - else - value = get_unaligned(ptr.p32u++); - break; - case DW_EH_PE_data8: - BUILD_BUG_ON(sizeof(u64) != sizeof(value)); -#else - BUILD_BUG_ON(sizeof(u32) != sizeof(value)); -#endif - case DW_EH_PE_native: - if (end < (const void *)(ptr.pul + 1)) - return 0; - value = get_unaligned(ptr.pul++); - break; - case DW_EH_PE_leb128: - BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value)); - value = ptrType & DW_EH_PE_signed - ? get_sleb128(&ptr.p8, end) - : get_uleb128(&ptr.p8, end); - if ((const void *)ptr.p8 > end) - return 0; - break; - default: - return 0; - } - switch(ptrType & DW_EH_PE_ADJUST) { - case DW_EH_PE_abs: - break; - case DW_EH_PE_pcrel: - value += (unsigned long)*pLoc; - break; - default: - return 0; - } - if ((ptrType & DW_EH_PE_indirect) - && __get_user(value, (unsigned long *)value)) - return 0; - *pLoc = ptr.p8; - - return value; -} - -static signed fde_pointer_type(const u32 *cie) -{ - const u8 *ptr = (const u8 *)(cie + 2); - unsigned version = *ptr; - - if (version != 1) - return -1; /* unsupported */ - if (*++ptr) { - const char *aug; - const u8 *end = (const u8 *)(cie + 1) + *cie; - uleb128_t len; - - /* check if augmentation size is first (and thus present) */ - if (*ptr != 'z') - return -1; - /* check if augmentation string is nul-terminated */ - if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL) - return -1; - ++ptr; /* skip terminator */ - get_uleb128(&ptr, end); /* skip code alignment */ - get_sleb128(&ptr, end); /* skip data alignment */ - /* skip return address column */ - version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end); - len = get_uleb128(&ptr, end); /* augmentation length */ - if (ptr + len < ptr || ptr + len > end) - return -1; - end = ptr + len; - while (*++aug) { - if (ptr >= end) - return -1; - switch(*aug) { - case 'L': - ++ptr; - break; - case 'P': { - signed ptrType = *ptr++; - - if (!read_pointer(&ptr, end, ptrType) || ptr > end) - return -1; - } - break; - case 'R': - return *ptr; - default: - return -1; - } - } - } - return DW_EH_PE_native|DW_EH_PE_abs; -} - -static int advance_loc(unsigned long delta, struct unwind_state *state) -{ - state->loc += delta * state->codeAlign; - - return delta > 0; -} - -static void set_rule(uleb128_t reg, - enum item_location where, - uleb128_t value, - struct unwind_state *state) -{ - if (reg < ARRAY_SIZE(state->regs)) { - state->regs[reg].where = where; - state->regs[reg].value = value; - } -} - -static int processCFI(const u8 *start, - const u8 *end, - unsigned long targetLoc, - signed ptrType, - struct unwind_state *state) -{ - union { - const u8 *p8; - const u16 *p16; - const u32 *p32; - } ptr; - int result = 1; - - if (start != state->cieStart) { - state->loc = state->org; - result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state); - if (targetLoc == 0 && state->label == NULL) - return result; - } - for (ptr.p8 = start; result && ptr.p8 < end; ) { - switch(*ptr.p8 >> 6) { - uleb128_t value; - - case 0: - switch(*ptr.p8++) { - case DW_CFA_nop: - break; - case DW_CFA_set_loc: - if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0) - result = 0; - break; - case DW_CFA_advance_loc1: - result = ptr.p8 < end && advance_loc(*ptr.p8++, state); - break; - case DW_CFA_advance_loc2: - result = ptr.p8 <= end + 2 - && advance_loc(*ptr.p16++, state); - break; - case DW_CFA_advance_loc4: - result = ptr.p8 <= end + 4 - && advance_loc(*ptr.p32++, state); - break; - case DW_CFA_offset_extended: - value = get_uleb128(&ptr.p8, end); - set_rule(value, Memory, get_uleb128(&ptr.p8, end), state); - break; - case DW_CFA_val_offset: - value = get_uleb128(&ptr.p8, end); - set_rule(value, Value, get_uleb128(&ptr.p8, end), state); - break; - case DW_CFA_offset_extended_sf: - value = get_uleb128(&ptr.p8, end); - set_rule(value, Memory, get_sleb128(&ptr.p8, end), state); - break; - case DW_CFA_val_offset_sf: - value = get_uleb128(&ptr.p8, end); - set_rule(value, Value, get_sleb128(&ptr.p8, end), state); - break; - case DW_CFA_restore_extended: - case DW_CFA_undefined: - case DW_CFA_same_value: - set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state); - break; - case DW_CFA_register: - value = get_uleb128(&ptr.p8, end); - set_rule(value, - Register, - get_uleb128(&ptr.p8, end), state); - break; - case DW_CFA_remember_state: - if (ptr.p8 == state->label) { - state->label = NULL; - return 1; - } - if (state->stackDepth >= MAX_STACK_DEPTH) - return 0; - state->stack[state->stackDepth++] = ptr.p8; - break; - case DW_CFA_restore_state: - if (state->stackDepth) { - const uleb128_t loc = state->loc; - const u8 *label = state->label; - - state->label = state->stack[state->stackDepth - 1]; - memcpy(&state->cfa, &badCFA, sizeof(state->cfa)); - memset(state->regs, 0, sizeof(state->regs)); - state->stackDepth = 0; - result = processCFI(start, end, 0, ptrType, state); - state->loc = loc; - state->label = label; - } else - return 0; - break; - case DW_CFA_def_cfa: - state->cfa.reg = get_uleb128(&ptr.p8, end); - /*nobreak*/ - case DW_CFA_def_cfa_offset: - state->cfa.offs = get_uleb128(&ptr.p8, end); - break; - case DW_CFA_def_cfa_sf: - state->cfa.reg = get_uleb128(&ptr.p8, end); - /*nobreak*/ - case DW_CFA_def_cfa_offset_sf: - state->cfa.offs = get_sleb128(&ptr.p8, end) - * state->dataAlign; - break; - case DW_CFA_def_cfa_register: - state->cfa.reg = get_uleb128(&ptr.p8, end); - break; - /*todo case DW_CFA_def_cfa_expression: */ - /*todo case DW_CFA_expression: */ - /*todo case DW_CFA_val_expression: */ - case DW_CFA_GNU_args_size: - get_uleb128(&ptr.p8, end); - break; - case DW_CFA_GNU_negative_offset_extended: - value = get_uleb128(&ptr.p8, end); - set_rule(value, - Memory, - (uleb128_t)0 - get_uleb128(&ptr.p8, end), state); - break; - case DW_CFA_GNU_window_save: - default: - result = 0; - break; - } - break; - case 1: - result = advance_loc(*ptr.p8++ & 0x3f, state); - break; - case 2: - value = *ptr.p8++ & 0x3f; - set_rule(value, Memory, get_uleb128(&ptr.p8, end), state); - break; - case 3: - set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state); - break; - } - if (ptr.p8 > end) - result = 0; - if (result && targetLoc != 0 && targetLoc < state->loc) - return 1; - } - - return result - && ptr.p8 == end - && (targetLoc == 0 - || (/*todo While in theory this should apply, gcc in practice omits - everything past the function prolog, and hence the location - never reaches the end of the function. - targetLoc < state->loc &&*/ state->label == NULL)); -} - -/* Unwind to previous to frame. Returns 0 if successful, negative - * number in case of an error. */ -int unwind(struct unwind_frame_info *frame) -{ -#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs]) - const u32 *fde = NULL, *cie = NULL; - const u8 *ptr = NULL, *end = NULL; - unsigned long startLoc = 0, endLoc = 0, cfa; - unsigned i; - signed ptrType = -1; - uleb128_t retAddrReg = 0; - struct unwind_table *table; - struct unwind_state state; - - if (UNW_PC(frame) == 0) - return -EINVAL; - if ((table = find_table(UNW_PC(frame))) != NULL - && !(table->size & (sizeof(*fde) - 1))) { - unsigned long tableSize = table->size; - - for (fde = table->address; - tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde; - tableSize -= sizeof(*fde) + *fde, - fde += 1 + *fde / sizeof(*fde)) { - if (!*fde || (*fde & (sizeof(*fde) - 1))) - break; - if (!fde[1]) - continue; /* this is a CIE */ - if ((fde[1] & (sizeof(*fde) - 1)) - || fde[1] > (unsigned long)(fde + 1) - - (unsigned long)table->address) - continue; /* this is not a valid FDE */ - cie = fde + 1 - fde[1] / sizeof(*fde); - if (*cie <= sizeof(*cie) + 4 - || *cie >= fde[1] - sizeof(*fde) - || (*cie & (sizeof(*cie) - 1)) - || cie[1] - || (ptrType = fde_pointer_type(cie)) < 0) { - cie = NULL; /* this is not a (valid) CIE */ - continue; - } - ptr = (const u8 *)(fde + 2); - startLoc = read_pointer(&ptr, - (const u8 *)(fde + 1) + *fde, - ptrType); - endLoc = startLoc - + read_pointer(&ptr, - (const u8 *)(fde + 1) + *fde, - ptrType & DW_EH_PE_indirect - ? ptrType - : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed)); - if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc) - break; - cie = NULL; - } - } - if (cie != NULL) { - memset(&state, 0, sizeof(state)); - state.cieEnd = ptr; /* keep here temporarily */ - ptr = (const u8 *)(cie + 2); - end = (const u8 *)(cie + 1) + *cie; - if ((state.version = *ptr) != 1) - cie = NULL; /* unsupported version */ - else if (*++ptr) { - /* check if augmentation size is first (and thus present) */ - if (*ptr == 'z') { - /* check for ignorable (or already handled) - * nul-terminated augmentation string */ - while (++ptr < end && *ptr) - if (strchr("LPR", *ptr) == NULL) - break; - } - if (ptr >= end || *ptr) - cie = NULL; - } - ++ptr; - } - if (cie != NULL) { - /* get code aligment factor */ - state.codeAlign = get_uleb128(&ptr, end); - /* get data aligment factor */ - state.dataAlign = get_sleb128(&ptr, end); - if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end) - cie = NULL; - else { - retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end); - /* skip augmentation */ - if (((const char *)(cie + 2))[1] == 'z') - ptr += get_uleb128(&ptr, end); - if (ptr > end - || retAddrReg >= ARRAY_SIZE(reg_info) - || REG_INVALID(retAddrReg) - || reg_info[retAddrReg].width != sizeof(unsigned long)) - cie = NULL; - } - } - if (cie != NULL) { - state.cieStart = ptr; - ptr = state.cieEnd; - state.cieEnd = end; - end = (const u8 *)(fde + 1) + *fde; - /* skip augmentation */ - if (((const char *)(cie + 2))[1] == 'z') { - uleb128_t augSize = get_uleb128(&ptr, end); - - if ((ptr += augSize) > end) - fde = NULL; - } - } - if (cie == NULL || fde == NULL) { -#ifdef CONFIG_FRAME_POINTER - unsigned long top, bottom; -#endif - -#ifdef CONFIG_FRAME_POINTER - top = STACK_TOP(frame->task); - bottom = STACK_BOTTOM(frame->task); -# if FRAME_RETADDR_OFFSET < 0 - if (UNW_SP(frame) < top - && UNW_FP(frame) <= UNW_SP(frame) - && bottom < UNW_FP(frame) -# else - if (UNW_SP(frame) > top - && UNW_FP(frame) >= UNW_SP(frame) - && bottom > UNW_FP(frame) -# endif - && !((UNW_SP(frame) | UNW_FP(frame)) - & (sizeof(unsigned long) - 1))) { - unsigned long link; - - if (!__get_user(link, - (unsigned long *)(UNW_FP(frame) - + FRAME_LINK_OFFSET)) -# if FRAME_RETADDR_OFFSET < 0 - && link > bottom && link < UNW_FP(frame) -# else - && link > UNW_FP(frame) && link < bottom -# endif - && !(link & (sizeof(link) - 1)) - && !__get_user(UNW_PC(frame), - (unsigned long *)(UNW_FP(frame) - + FRAME_RETADDR_OFFSET))) { - UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET -# if FRAME_RETADDR_OFFSET < 0 - - -# else - + -# endif - sizeof(UNW_PC(frame)); - UNW_FP(frame) = link; - return 0; - } - } -#endif - return -ENXIO; - } - state.org = startLoc; - memcpy(&state.cfa, &badCFA, sizeof(state.cfa)); - /* process instructions */ - if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state) - || state.loc > endLoc - || state.regs[retAddrReg].where == Nowhere - || state.cfa.reg >= ARRAY_SIZE(reg_info) - || reg_info[state.cfa.reg].width != sizeof(unsigned long) - || state.cfa.offs % sizeof(unsigned long)) - return -EIO; - /* update frame */ - cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs; - startLoc = min((unsigned long)UNW_SP(frame), cfa); - endLoc = max((unsigned long)UNW_SP(frame), cfa); - if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) { - startLoc = min(STACK_LIMIT(cfa), cfa); - endLoc = max(STACK_LIMIT(cfa), cfa); - } -#ifndef CONFIG_64BIT -# define CASES CASE(8); CASE(16); CASE(32) -#else -# define CASES CASE(8); CASE(16); CASE(32); CASE(64) -#endif - for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { - if (REG_INVALID(i)) { - if (state.regs[i].where == Nowhere) - continue; - return -EIO; - } - switch(state.regs[i].where) { - default: - break; - case Register: - if (state.regs[i].value >= ARRAY_SIZE(reg_info) - || REG_INVALID(state.regs[i].value) - || reg_info[i].width > reg_info[state.regs[i].value].width) - return -EIO; - switch(reg_info[state.regs[i].value].width) { -#define CASE(n) \ - case sizeof(u##n): \ - state.regs[i].value = FRAME_REG(state.regs[i].value, \ - const u##n); \ - break - CASES; -#undef CASE - default: - return -EIO; - } - break; - } - } - for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { - if (REG_INVALID(i)) - continue; - switch(state.regs[i].where) { - case Nowhere: - if (reg_info[i].width != sizeof(UNW_SP(frame)) - || &FRAME_REG(i, __typeof__(UNW_SP(frame))) - != &UNW_SP(frame)) - continue; - UNW_SP(frame) = cfa; - break; - case Register: - switch(reg_info[i].width) { -#define CASE(n) case sizeof(u##n): \ - FRAME_REG(i, u##n) = state.regs[i].value; \ - break - CASES; -#undef CASE - default: - return -EIO; - } - break; - case Value: - if (reg_info[i].width != sizeof(unsigned long)) - return -EIO; - FRAME_REG(i, unsigned long) = cfa + state.regs[i].value - * state.dataAlign; - break; - case Memory: { - unsigned long addr = cfa + state.regs[i].value - * state.dataAlign; - - if ((state.regs[i].value * state.dataAlign) - % sizeof(unsigned long) - || addr < startLoc - || addr + sizeof(unsigned long) < addr - || addr + sizeof(unsigned long) > endLoc) - return -EIO; - switch(reg_info[i].width) { -#define CASE(n) case sizeof(u##n): \ - __get_user(FRAME_REG(i, u##n), (u##n *)addr); \ - break - CASES; -#undef CASE - default: - return -EIO; - } - } - break; - } - } - - return 0; -#undef CASES -#undef FRAME_REG -} -EXPORT_SYMBOL(unwind); - -int unwind_init_frame_info(struct unwind_frame_info *info, - struct task_struct *tsk, - /*const*/ struct pt_regs *regs) -{ - info->task = tsk; - arch_unw_init_frame_info(info, regs); - - return 0; -} -EXPORT_SYMBOL(unwind_init_frame_info); - -/* - * Prepare to unwind a blocked task. - */ -int unwind_init_blocked(struct unwind_frame_info *info, - struct task_struct *tsk) -{ - info->task = tsk; - arch_unw_init_blocked(info); - - return 0; -} -EXPORT_SYMBOL(unwind_init_blocked); - -/* - * Prepare to unwind the currently running thread. - */ -int unwind_init_running(struct unwind_frame_info *info, - asmlinkage int (*callback)(struct unwind_frame_info *, - void *arg), - void *arg) -{ - info->task = current; - - return arch_unwind_init_running(info, callback, arg); -} -EXPORT_SYMBOL(unwind_init_running); - -/* - * Unwind until the return pointer is in user-land (or until an error - * occurs). Returns 0 if successful, negative number in case of - * error. - */ -int unwind_to_user(struct unwind_frame_info *info) -{ - while (!arch_unw_user_mode(info)) { - int err = unwind(info); - - if (err < 0) - return err; - } - - return 0; -} -EXPORT_SYMBOL(unwind_to_user); diff --git a/trunk/kernel/wait.c b/trunk/kernel/wait.c index 5985d866531f..791681cfea98 100644 --- a/trunk/kernel/wait.c +++ b/trunk/kernel/wait.c @@ -3,6 +3,7 @@ * * (C) 2004 William Irwin, Oracle */ +#include #include #include #include diff --git a/trunk/kernel/workqueue.c b/trunk/kernel/workqueue.c index 59f0b42bd89e..565cf7a1febd 100644 --- a/trunk/kernel/workqueue.c +++ b/trunk/kernel/workqueue.c @@ -559,7 +559,7 @@ static void take_over_work(struct workqueue_struct *wq, unsigned int cpu) } /* We're holding the cpucontrol mutex here */ -static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, +static int workqueue_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { diff --git a/trunk/lib/Kconfig b/trunk/lib/Kconfig index f6299342b882..3de93357f5ab 100644 --- a/trunk/lib/Kconfig +++ b/trunk/lib/Kconfig @@ -86,10 +86,4 @@ config TEXTSEARCH_BM config TEXTSEARCH_FSM tristate -# -# plist support is select#ed if needed -# -config PLIST - boolean - endmenu diff --git a/trunk/lib/Kconfig.debug b/trunk/lib/Kconfig.debug index e4fcbd12cf6e..ccb0c1fdf1b5 100644 --- a/trunk/lib/Kconfig.debug +++ b/trunk/lib/Kconfig.debug @@ -23,22 +23,6 @@ config MAGIC_SYSRQ keys are documented in . Don't say Y unless you really know what this hack does. -config UNUSED_SYMBOLS - bool "Enable unused/obsolete exported symbols" - default y if X86 - help - Unused but exported symbols make the kernel needlessly bigger. For - that reason most of these unused exports will soon be removed. This - option is provided temporarily to provide a transition period in case - some external kernel module needs one of these symbols anyway. If you - encounter such a case in your module, consider if you are actually - using the right API. (rationale: since nobody in the kernel is using - this in a module, there is a pretty good chance it's actually the - wrong interface to use). If you really need the symbol, please send a - mail to the linux kernel mailing list mentioning the symbol and why - you really need it, and what the merge plan to the mainline kernel for - your module is. - config DEBUG_KERNEL bool "Kernel debugging" help @@ -123,24 +107,6 @@ config DEBUG_MUTEXES This allows mutex semantics violations and mutex related deadlocks (lockups) to be detected and reported automatically. -config DEBUG_RT_MUTEXES - bool "RT Mutex debugging, deadlock detection" - depends on DEBUG_KERNEL && RT_MUTEXES - help - This allows rt mutex semantics violations and rt mutex related - deadlocks (lockups) to be detected and reported automatically. - -config DEBUG_PI_LIST - bool - default y - depends on DEBUG_RT_MUTEXES - -config RT_MUTEX_TESTER - bool "Built-in scriptable tester for rt-mutexes" - depends on DEBUG_KERNEL && RT_MUTEXES - help - This option enables a rt-mutex tester. - config DEBUG_SPINLOCK bool "Spinlock debugging" depends on DEBUG_KERNEL @@ -222,22 +188,14 @@ config FRAME_POINTER config UNWIND_INFO bool "Compile the kernel with frame unwind information" - depends on !IA64 && !PARISC - depends on !MODULES || !(MIPS || PPC || SUPERH || V850) + depends on !IA64 + depends on !MODULES || !(MIPS || PARISC || PPC || SUPERH || V850) help If you say Y here the resulting kernel image will be slightly larger but not slower, and it will give very useful debugging information. If you don't debug the kernel, you can say N, but we may not be able to solve problems without frame unwind information or frame pointers. -config STACK_UNWIND - bool "Stack unwind support" - depends on UNWIND_INFO - depends on X86 - help - This enables more precise stack traces, omitting all unrelated - occurrences of pointers into kernel code from the dump. - config FORCED_INLINING bool "Force gcc to inline functions marked 'inline'" depends on DEBUG_KERNEL diff --git a/trunk/lib/Makefile b/trunk/lib/Makefile index 10c13c9d7824..79358ad1f113 100644 --- a/trunk/lib/Makefile +++ b/trunk/lib/Makefile @@ -25,7 +25,6 @@ lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o lib-$(CONFIG_GENERIC_HWEIGHT) += hweight.o obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o -obj-$(CONFIG_PLIST) += plist.o obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o ifneq ($(CONFIG_HAVE_DEC_LOCK),y) diff --git a/trunk/lib/bust_spinlocks.c b/trunk/lib/bust_spinlocks.c index a2055bc3ef62..6bb7319e09a0 100644 --- a/trunk/lib/bust_spinlocks.c +++ b/trunk/lib/bust_spinlocks.c @@ -7,6 +7,7 @@ * and panic() information from reaching the user. */ +#include #include #include #include diff --git a/trunk/lib/extable.c b/trunk/lib/extable.c index 463f4560f16d..01c08b5836f5 100644 --- a/trunk/lib/extable.c +++ b/trunk/lib/extable.c @@ -9,6 +9,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/lib/idr.c b/trunk/lib/idr.c index 4d096819511a..de19030a999b 100644 --- a/trunk/lib/idr.c +++ b/trunk/lib/idr.c @@ -29,7 +29,6 @@ #include #include #endif -#include #include #include @@ -399,48 +398,6 @@ void *idr_find(struct idr *idp, int id) } EXPORT_SYMBOL(idr_find); -/** - * idr_replace - replace pointer for given id - * @idp: idr handle - * @ptr: pointer you want associated with the id - * @id: lookup key - * - * Replace the pointer registered with an id and return the old value. - * A -ENOENT return indicates that @id was not found. - * A -EINVAL return indicates that @id was not within valid constraints. - * - * The caller must serialize vs idr_find(), idr_get_new(), and idr_remove(). - */ -void *idr_replace(struct idr *idp, void *ptr, int id) -{ - int n; - struct idr_layer *p, *old_p; - - n = idp->layers * IDR_BITS; - p = idp->top; - - id &= MAX_ID_MASK; - - if (id >= (1 << n)) - return ERR_PTR(-EINVAL); - - n -= IDR_BITS; - while ((n > 0) && p) { - p = p->ary[(id >> n) & IDR_MASK]; - n -= IDR_BITS; - } - - n = id & IDR_MASK; - if (unlikely(p == NULL || !test_bit(n, &p->bitmap))) - return ERR_PTR(-ENOENT); - - old_p = p->ary[n]; - p->ary[n] = ptr; - - return old_p; -} -EXPORT_SYMBOL(idr_replace); - static void idr_cache_ctor(void * idr_layer, kmem_cache_t *idr_layer_cache, unsigned long flags) { diff --git a/trunk/lib/kernel_lock.c b/trunk/lib/kernel_lock.c index e713e86811ae..cb5490ec00f2 100644 --- a/trunk/lib/kernel_lock.c +++ b/trunk/lib/kernel_lock.c @@ -14,7 +14,7 @@ * The 'big kernel semaphore' * * This mutex is taken and released recursively by lock_kernel() - * and unlock_kernel(). It is transparently dropped and reacquired + * and unlock_kernel(). It is transparently dropped and reaquired * over schedule(). It is used to protect legacy code that hasn't * been migrated to a proper locking design yet. * @@ -92,7 +92,7 @@ void __lockfunc unlock_kernel(void) * The 'big kernel lock' * * This spinlock is taken and released recursively by lock_kernel() - * and unlock_kernel(). It is transparently dropped and reacquired + * and unlock_kernel(). It is transparently dropped and reaquired * over schedule(). It is used to protect legacy code that hasn't * been migrated to a proper locking design yet. * diff --git a/trunk/lib/kobject_uevent.c b/trunk/lib/kobject_uevent.c index 2b1530fc573b..7f20e7b857cb 100644 --- a/trunk/lib/kobject_uevent.c +++ b/trunk/lib/kobject_uevent.c @@ -50,10 +50,6 @@ static char *action_to_string(enum kobject_action action) return "offline"; case KOBJ_ONLINE: return "online"; - case KOBJ_DOCK: - return "dock"; - case KOBJ_UNDOCK: - return "undock"; default: return NULL; } diff --git a/trunk/lib/plist.c b/trunk/lib/plist.c deleted file mode 100644 index 3074a02272f3..000000000000 --- a/trunk/lib/plist.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * lib/plist.c - * - * Descending-priority-sorted double-linked list - * - * (C) 2002-2003 Intel Corp - * Inaky Perez-Gonzalez . - * - * 2001-2005 (c) MontaVista Software, Inc. - * Daniel Walker - * - * (C) 2005 Thomas Gleixner - * - * Simplifications of the original code by - * Oleg Nesterov - * - * Licensed under the FSF's GNU Public License v2 or later. - * - * Based on simple lists (include/linux/list.h). - * - * This file contains the add / del functions which are considered to - * be too large to inline. See include/linux/plist.h for further - * information. - */ - -#include -#include - -#ifdef CONFIG_DEBUG_PI_LIST - -static void plist_check_prev_next(struct list_head *t, struct list_head *p, - struct list_head *n) -{ - if (n->prev != p || p->next != n) { - printk("top: %p, n: %p, p: %p\n", t, t->next, t->prev); - printk("prev: %p, n: %p, p: %p\n", p, p->next, p->prev); - printk("next: %p, n: %p, p: %p\n", n, n->next, n->prev); - WARN_ON(1); - } -} - -static void plist_check_list(struct list_head *top) -{ - struct list_head *prev = top, *next = top->next; - - plist_check_prev_next(top, prev, next); - while (next != top) { - prev = next; - next = prev->next; - plist_check_prev_next(top, prev, next); - } -} - -static void plist_check_head(struct plist_head *head) -{ - WARN_ON(!head->lock); - if (head->lock) - WARN_ON_SMP(!spin_is_locked(head->lock)); - plist_check_list(&head->prio_list); - plist_check_list(&head->node_list); -} - -#else -# define plist_check_head(h) do { } while (0) -#endif - -/** - * plist_add - add @node to @head - * - * @node: &struct plist_node pointer - * @head: &struct plist_head pointer - */ -void plist_add(struct plist_node *node, struct plist_head *head) -{ - struct plist_node *iter; - - plist_check_head(head); - WARN_ON(!plist_node_empty(node)); - - list_for_each_entry(iter, &head->prio_list, plist.prio_list) { - if (node->prio < iter->prio) - goto lt_prio; - else if (node->prio == iter->prio) { - iter = list_entry(iter->plist.prio_list.next, - struct plist_node, plist.prio_list); - goto eq_prio; - } - } - -lt_prio: - list_add_tail(&node->plist.prio_list, &iter->plist.prio_list); -eq_prio: - list_add_tail(&node->plist.node_list, &iter->plist.node_list); - - plist_check_head(head); -} - -/** - * plist_del - Remove a @node from plist. - * - * @node: &struct plist_node pointer - entry to be removed - * @head: &struct plist_head pointer - list head - */ -void plist_del(struct plist_node *node, struct plist_head *head) -{ - plist_check_head(head); - - if (!list_empty(&node->plist.prio_list)) { - struct plist_node *next = plist_first(&node->plist); - - list_move_tail(&next->plist.prio_list, &node->plist.prio_list); - list_del_init(&node->plist.prio_list); - } - - list_del_init(&node->plist.node_list); - - plist_check_head(head); -} diff --git a/trunk/lib/semaphore-sleepers.c b/trunk/lib/semaphore-sleepers.c index 128180523860..4d5f18889fa5 100644 --- a/trunk/lib/semaphore-sleepers.c +++ b/trunk/lib/semaphore-sleepers.c @@ -12,6 +12,7 @@ * * rw semaphores implemented November 1999 by Benjamin LaHaise */ +#include #include #include #include diff --git a/trunk/lib/spinlock_debug.c b/trunk/lib/spinlock_debug.c index 93c15ee3f8ea..d8b6bb419d49 100644 --- a/trunk/lib/spinlock_debug.c +++ b/trunk/lib/spinlock_debug.c @@ -6,6 +6,7 @@ * DEBUG_SPINLOCK. */ +#include #include #include #include diff --git a/trunk/lib/textsearch.c b/trunk/lib/textsearch.c index 2cb4a437942e..6f3093efbd7b 100644 --- a/trunk/lib/textsearch.c +++ b/trunk/lib/textsearch.c @@ -93,6 +93,7 @@ * ========================================================================== */ +#include #include #include #include diff --git a/trunk/lib/ts_bm.c b/trunk/lib/ts_bm.c index 0110e4414805..c4c1ac5fbd1a 100644 --- a/trunk/lib/ts_bm.c +++ b/trunk/lib/ts_bm.c @@ -35,6 +35,7 @@ * matchings spread over multiple fragments, then go BM. */ +#include #include #include #include diff --git a/trunk/lib/ts_fsm.c b/trunk/lib/ts_fsm.c index 87847c2ae9e2..ca3211206eef 100644 --- a/trunk/lib/ts_fsm.c +++ b/trunk/lib/ts_fsm.c @@ -26,6 +26,7 @@ * however while in strict mode the average runtime can be better. */ +#include #include #include #include diff --git a/trunk/lib/ts_kmp.c b/trunk/lib/ts_kmp.c index 3ced628cab4b..7fd45451b44a 100644 --- a/trunk/lib/ts_kmp.c +++ b/trunk/lib/ts_kmp.c @@ -30,6 +30,7 @@ * [2] See finite automation theory */ +#include #include #include #include diff --git a/trunk/lib/vsprintf.c b/trunk/lib/vsprintf.c index bed7229378f2..797428afd111 100644 --- a/trunk/lib/vsprintf.c +++ b/trunk/lib/vsprintf.c @@ -489,7 +489,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) if (str < end) *str = '\0'; else - end[-1] = '\0'; + *end = '\0'; } /* the trailing null byte doesn't count towards the total */ return str-buf; diff --git a/trunk/lib/zlib_inflate/inffast.c b/trunk/lib/zlib_inflate/inffast.c index d84560c076d8..02a16eacb72d 100644 --- a/trunk/lib/zlib_inflate/inffast.c +++ b/trunk/lib/zlib_inflate/inffast.c @@ -63,10 +63,10 @@ bytes, which is the maximum length that can be coded. inflate_fast() requires strm->avail_out >= 258 for each loop to avoid checking for output space. - - - @start: inflate()'s starting value for strm->avail_out */ -void inflate_fast(z_streamp strm, unsigned start) +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state *state; unsigned char *in; /* local strm->next_in */ diff --git a/trunk/lib/zlib_inflate/inftrees.c b/trunk/lib/zlib_inflate/inftrees.c index 3fe6ce5b53e5..62343c53bf7e 100644 --- a/trunk/lib/zlib_inflate/inftrees.c +++ b/trunk/lib/zlib_inflate/inftrees.c @@ -8,6 +8,15 @@ #define MAXBITS 15 +const char inflate_copyright[] = + " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + /* Build a set of tables to decode the provided canonical Huffman code. The code lengths are lens[0..codes-1]. The result starts at *table, @@ -20,8 +29,13 @@ table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ -int zlib_inflate_table(codetype type, unsigned short *lens, unsigned codes, - code **table, unsigned *bits, unsigned short *work) +int zlib_inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short *lens; +unsigned codes; +code **table; +unsigned *bits; +unsigned short *work; { unsigned len; /* a code's length in bits */ unsigned sym; /* index of code symbols */ diff --git a/trunk/mm/Kconfig b/trunk/mm/Kconfig index 8f5b45615f7b..66e65ab39426 100644 --- a/trunk/mm/Kconfig +++ b/trunk/mm/Kconfig @@ -115,8 +115,7 @@ config SPARSEMEM_EXTREME # eventually, we can have this option just 'select SPARSEMEM' config MEMORY_HOTPLUG bool "Allow for memory hot-add" - depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND && ARCH_ENABLE_MEMORY_HOTPLUG - depends on (IA64 || X86 || PPC64) + depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND comment "Memory hotplug is currently incompatible with Software Suspend" depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND @@ -146,9 +145,3 @@ config MIGRATION while the virtual addresses are not changed. This is useful for example on NUMA systems to put pages nearer to the processors accessing the page. - -config RESOURCES_64BIT - bool "64 bit Memory and IO resources (EXPERIMENTAL)" if (!64BIT && EXPERIMENTAL) - default 64BIT - help - This option allows memory and IO resources to be 64 bit. diff --git a/trunk/mm/Makefile b/trunk/mm/Makefile index 9dd824c11eeb..0b8f73f2ed16 100644 --- a/trunk/mm/Makefile +++ b/trunk/mm/Makefile @@ -10,7 +10,7 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ page_alloc.o page-writeback.o pdflush.o \ readahead.o swap.o truncate.o vmscan.o \ - prio_tree.o util.o mmzone.o vmstat.o $(mmu-y) + prio_tree.o util.o mmzone.o $(mmu-y) obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o obj-$(CONFIG_HUGETLBFS) += hugetlb.o diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index d087fc3d3281..9c7334bafda8 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -9,6 +9,7 @@ * most "normal" filesystems (but you don't /have/ to use this: * the NFS filesystem used to do this differently, for example) */ +#include #include #include #include @@ -119,7 +120,7 @@ void __remove_from_page_cache(struct page *page) radix_tree_delete(&mapping->page_tree, page->index); page->mapping = NULL; mapping->nrpages--; - __dec_zone_page_state(page, NR_FILE_PAGES); + pagecache_acct(-1); } void remove_from_page_cache(struct page *page) @@ -448,7 +449,7 @@ int add_to_page_cache(struct page *page, struct address_space *mapping, page->mapping = mapping; page->index = offset; mapping->nrpages++; - __inc_zone_page_state(page, NR_FILE_PAGES); + pagecache_acct(1); } write_unlock_irq(&mapping->tree_lock); radix_tree_preload_end(); @@ -1415,7 +1416,7 @@ struct page *filemap_nopage(struct vm_area_struct *area, */ if (!did_readaround) { majmin = VM_FAULT_MAJOR; - count_vm_event(PGMAJFAULT); + inc_page_state(pgmajfault); } did_readaround = 1; ra_pages = max_sane_readahead(file->f_ra.ra_pages); @@ -1486,7 +1487,7 @@ struct page *filemap_nopage(struct vm_area_struct *area, page_not_uptodate: if (!did_readaround) { majmin = VM_FAULT_MAJOR; - count_vm_event(PGMAJFAULT); + inc_page_state(pgmajfault); } lock_page(page); @@ -2068,7 +2069,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, { struct file *file = iocb->ki_filp; struct address_space * mapping = file->f_mapping; - const struct address_space_operations *a_ops = mapping->a_ops; + struct address_space_operations *a_ops = mapping->a_ops; struct inode *inode = mapping->host; long status = 0; struct page *page; @@ -2094,21 +2095,14 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, do { unsigned long index; unsigned long offset; + unsigned long maxlen; size_t copied; offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */ index = pos >> PAGE_CACHE_SHIFT; bytes = PAGE_CACHE_SIZE - offset; - - /* Limit the size of the copy to the caller's write size */ - bytes = min(bytes, count); - - /* - * Limit the size of the copy to that of the current segment, - * because fault_in_pages_readable() doesn't know how to walk - * segments. - */ - bytes = min(bytes, cur_iov->iov_len - iov_base); + if (bytes > count) + bytes = count; /* * Bring in the user page that we will copy from _first_. @@ -2116,7 +2110,10 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, * same page as we're writing to, without it being marked * up-to-date. */ - fault_in_pages_readable(buf, bytes); + maxlen = cur_iov->iov_len - iov_base; + if (maxlen > bytes) + maxlen = bytes; + fault_in_pages_readable(buf, maxlen); page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec); if (!page) { @@ -2124,12 +2121,6 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, break; } - if (unlikely(bytes == 0)) { - status = 0; - copied = 0; - goto zero_length_segment; - } - status = a_ops->prepare_write(file, page, offset, offset+bytes); if (unlikely(status)) { loff_t isize = i_size_read(inode); @@ -2159,8 +2150,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov, page_cache_release(page); continue; } -zero_length_segment: - if (likely(copied >= 0)) { + if (likely(copied > 0)) { if (!status) status = copied; @@ -2225,7 +2215,7 @@ __generic_file_aio_write_nolock(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t *ppos) { struct file *file = iocb->ki_filp; - const struct address_space * mapping = file->f_mapping; + struct address_space * mapping = file->f_mapping; size_t ocount; /* original count */ size_t count; /* after file limit checks */ struct inode *inode = mapping->host; diff --git a/trunk/mm/filemap.h b/trunk/mm/filemap.h index 3f2a343c6015..536979fb4ba7 100644 --- a/trunk/mm/filemap.h +++ b/trunk/mm/filemap.h @@ -88,7 +88,7 @@ filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes) const struct iovec *iov = *iovp; size_t base = *basep; - do { + while (bytes) { int copy = min(bytes, iov->iov_len - base); bytes -= copy; @@ -97,7 +97,7 @@ filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes) iov++; base = 0; } - } while (bytes); + } *iovp = iov; *basep = base; } diff --git a/trunk/mm/filemap_xip.c b/trunk/mm/filemap_xip.c index b4fd0d7c9bfb..b960ac8e5918 100644 --- a/trunk/mm/filemap_xip.c +++ b/trunk/mm/filemap_xip.c @@ -273,7 +273,7 @@ __xip_file_write(struct file *filp, const char __user *buf, size_t count, loff_t pos, loff_t *ppos) { struct address_space * mapping = filp->f_mapping; - const struct address_space_operations *a_ops = mapping->a_ops; + struct address_space_operations *a_ops = mapping->a_ops; struct inode *inode = mapping->host; long status = 0; struct page *page; diff --git a/trunk/mm/highmem.c b/trunk/mm/highmem.c index 9b2a5403c447..9b274fdf9d08 100644 --- a/trunk/mm/highmem.c +++ b/trunk/mm/highmem.c @@ -315,8 +315,8 @@ static void bounce_end_io(struct bio *bio, mempool_t *pool, int err) if (bvec->bv_page == org_vec->bv_page) continue; - dec_zone_page_state(bvec->bv_page, NR_BOUNCE); - mempool_free(bvec->bv_page, pool); + mempool_free(bvec->bv_page, pool); + dec_page_state(nr_bounce); } bio_endio(bio_orig, bio_orig->bi_size, err); @@ -397,7 +397,7 @@ static void __blk_queue_bounce(request_queue_t *q, struct bio **bio_orig, to->bv_page = mempool_alloc(pool, q->bounce_gfp); to->bv_len = from->bv_len; to->bv_offset = from->bv_offset; - inc_zone_page_state(to->bv_page, NR_BOUNCE); + inc_page_state(nr_bounce); if (rw == WRITE) { char *vto, *vfrom; diff --git a/trunk/mm/memory.c b/trunk/mm/memory.c index 7e2a4b1580e3..247b5c312b9b 100644 --- a/trunk/mm/memory.c +++ b/trunk/mm/memory.c @@ -126,7 +126,7 @@ static void free_pte_range(struct mmu_gather *tlb, pmd_t *pmd) pmd_clear(pmd); pte_lock_deinit(page); pte_free_tlb(tlb, page); - dec_zone_page_state(page, NR_PAGETABLE); + dec_page_state(nr_page_table_pages); tlb->mm->nr_ptes--; } @@ -311,7 +311,7 @@ int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address) pte_free(new); } else { mm->nr_ptes++; - inc_zone_page_state(new, NR_PAGETABLE); + inc_page_state(nr_page_table_pages); pmd_populate(mm, pmd, new); } spin_unlock(&mm->page_table_lock); @@ -1951,7 +1951,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, /* Had to read the page from swap area: Major fault */ ret = VM_FAULT_MAJOR; - count_vm_event(PGMAJFAULT); + inc_page_state(pgmajfault); grab_swap_token(); } @@ -2324,7 +2324,7 @@ int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, __set_current_state(TASK_RUNNING); - count_vm_event(PGFAULT); + inc_page_state(pgfault); if (unlikely(is_vm_hugetlb_page(vma))) return hugetlb_fault(mm, vma, address, write_access); diff --git a/trunk/mm/memory_hotplug.c b/trunk/mm/memory_hotplug.c index 01c9fb97c619..841a077d5aeb 100644 --- a/trunk/mm/memory_hotplug.c +++ b/trunk/mm/memory_hotplug.c @@ -4,6 +4,7 @@ * Copyright (C) */ +#include #include #include #include @@ -20,7 +21,6 @@ #include #include #include -#include #include @@ -126,9 +126,6 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) unsigned long i; unsigned long flags; unsigned long onlined_pages = 0; - struct resource res; - u64 section_end; - unsigned long start_pfn; struct zone *zone; int need_zonelists_rebuild = 0; @@ -151,27 +148,10 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) if (!populated_zone(zone)) need_zonelists_rebuild = 1; - res.start = (u64)pfn << PAGE_SHIFT; - res.end = res.start + ((u64)nr_pages << PAGE_SHIFT) - 1; - res.flags = IORESOURCE_MEM; /* we just need system ram */ - section_end = res.end; - - while (find_next_system_ram(&res) >= 0) { - start_pfn = (unsigned long)(res.start >> PAGE_SHIFT); - nr_pages = (unsigned long) - ((res.end + 1 - res.start) >> PAGE_SHIFT); - - if (PageReserved(pfn_to_page(start_pfn))) { - /* this region's page is not onlined now */ - for (i = 0; i < nr_pages; i++) { - struct page *page = pfn_to_page(start_pfn + i); - online_page(page); - onlined_pages++; - } - } - - res.start = res.end + 1; - res.end = section_end; + for (i = 0; i < nr_pages; i++) { + struct page *page = pfn_to_page(pfn + i); + online_page(page); + onlined_pages++; } zone->present_pages += onlined_pages; zone->zone_pgdat->node_present_pages += onlined_pages; @@ -183,100 +163,3 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) vm_total_pages = nr_free_pagecache_pages(); return 0; } - -static pg_data_t *hotadd_new_pgdat(int nid, u64 start) -{ - struct pglist_data *pgdat; - unsigned long zones_size[MAX_NR_ZONES] = {0}; - unsigned long zholes_size[MAX_NR_ZONES] = {0}; - unsigned long start_pfn = start >> PAGE_SHIFT; - - pgdat = arch_alloc_nodedata(nid); - if (!pgdat) - return NULL; - - arch_refresh_nodedata(nid, pgdat); - - /* we can use NODE_DATA(nid) from here */ - - /* init node's zones as empty zones, we don't have any present pages.*/ - free_area_init_node(nid, pgdat, zones_size, start_pfn, zholes_size); - - return pgdat; -} - -static void rollback_node_hotadd(int nid, pg_data_t *pgdat) -{ - arch_refresh_nodedata(nid, NULL); - arch_free_nodedata(pgdat); - return; -} - -/* add this memory to iomem resource */ -static void register_memory_resource(u64 start, u64 size) -{ - struct resource *res; - - res = kzalloc(sizeof(struct resource), GFP_KERNEL); - BUG_ON(!res); - - res->name = "System RAM"; - res->start = start; - res->end = start + size - 1; - res->flags = IORESOURCE_MEM; - if (request_resource(&iomem_resource, res) < 0) { - printk("System RAM resource %llx - %llx cannot be added\n", - (unsigned long long)res->start, (unsigned long long)res->end); - kfree(res); - } -} - - - -int add_memory(int nid, u64 start, u64 size) -{ - pg_data_t *pgdat = NULL; - int new_pgdat = 0; - int ret; - - if (!node_online(nid)) { - pgdat = hotadd_new_pgdat(nid, start); - if (!pgdat) - return -ENOMEM; - new_pgdat = 1; - ret = kswapd_run(nid); - if (ret) - goto error; - } - - /* call arch's memory hotadd */ - ret = arch_add_memory(nid, start, size); - - if (ret < 0) - goto error; - - /* we online node here. we can't roll back from here. */ - node_set_online(nid); - - if (new_pgdat) { - ret = register_one_node(nid); - /* - * If sysfs file of new node can't create, cpu on the node - * can't be hot-added. There is no rollback way now. - * So, check by BUG_ON() to catch it reluctantly.. - */ - BUG_ON(ret); - } - - /* register this memory as resource */ - register_memory_resource(start, size); - - return ret; -error: - /* rollback pgdat allocation and others */ - if (new_pgdat) - rollback_node_hotadd(nid, pgdat); - - return ret; -} -EXPORT_SYMBOL_GPL(add_memory); diff --git a/trunk/mm/mempolicy.c b/trunk/mm/mempolicy.c index e07e27e846a2..73e0f23b7f51 100644 --- a/trunk/mm/mempolicy.c +++ b/trunk/mm/mempolicy.c @@ -1209,8 +1209,10 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, zl = NODE_DATA(nid)->node_zonelists + gfp_zone(gfp); page = __alloc_pages(gfp, order, zl); - if (page && page_zone(page) == zl->zones[0]) - inc_zone_page_state(page, NUMA_INTERLEAVE_HIT); + if (page && page_zone(page) == zl->zones[0]) { + zone_pcp(zl->zones[0],get_cpu())->interleave_hit++; + put_cpu(); + } return page; } @@ -1819,7 +1821,7 @@ static inline void check_huge_range(struct vm_area_struct *vma, int show_numa_map(struct seq_file *m, void *v) { - struct proc_maps_private *priv = m->private; + struct task_struct *task = m->private; struct vm_area_struct *vma = v; struct numa_maps *md; struct file *file = vma->vm_file; @@ -1835,7 +1837,7 @@ int show_numa_map(struct seq_file *m, void *v) return 0; mpol_to_str(buffer, sizeof(buffer), - get_vma_policy(priv->task, vma, vma->vm_start)); + get_vma_policy(task, vma, vma->vm_start)); seq_printf(m, "%08lx %s", vma->vm_start, buffer); @@ -1889,7 +1891,7 @@ int show_numa_map(struct seq_file *m, void *v) kfree(md); if (m->count < m->size) - m->version = (vma != priv->tail_vma) ? vma->vm_start : 0; + m->version = (vma != get_gate_vma(task)) ? vma->vm_start : 0; return 0; } diff --git a/trunk/mm/mmap.c b/trunk/mm/mmap.c index c1868ecdbc5f..6446c6134b04 100644 --- a/trunk/mm/mmap.c +++ b/trunk/mm/mmap.c @@ -96,7 +96,7 @@ int __vm_enough_memory(long pages, int cap_sys_admin) if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { unsigned long n; - free = global_page_state(NR_FILE_PAGES); + free = get_page_cache_size(); free += nr_swap_pages; /* diff --git a/trunk/mm/mmzone.c b/trunk/mm/mmzone.c index 0959ee1a4795..b022370e612e 100644 --- a/trunk/mm/mmzone.c +++ b/trunk/mm/mmzone.c @@ -5,6 +5,7 @@ */ +#include #include #include #include diff --git a/trunk/mm/nommu.c b/trunk/mm/nommu.c index 5151c44a8257..029fadac0fb5 100644 --- a/trunk/mm/nommu.c +++ b/trunk/mm/nommu.c @@ -1122,7 +1122,7 @@ int __vm_enough_memory(long pages, int cap_sys_admin) if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) { unsigned long n; - free = global_page_state(NR_FILE_PAGES); + free = get_page_cache_size(); free += nr_swap_pages; /* diff --git a/trunk/mm/page-writeback.c b/trunk/mm/page-writeback.c index e630188ccc40..8ccf6f1b1473 100644 --- a/trunk/mm/page-writeback.c +++ b/trunk/mm/page-writeback.c @@ -99,6 +99,22 @@ EXPORT_SYMBOL(laptop_mode); static void background_writeout(unsigned long _min_pages); +struct writeback_state +{ + unsigned long nr_dirty; + unsigned long nr_unstable; + unsigned long nr_mapped; + unsigned long nr_writeback; +}; + +static void get_writeback_state(struct writeback_state *wbs) +{ + wbs->nr_dirty = read_page_state(nr_dirty); + wbs->nr_unstable = read_page_state(nr_unstable); + wbs->nr_mapped = read_page_state(nr_mapped); + wbs->nr_writeback = read_page_state(nr_writeback); +} + /* * Work out the current dirty-memory clamping and background writeout * thresholds. @@ -117,8 +133,8 @@ static void background_writeout(unsigned long _min_pages); * clamping level. */ static void -get_dirty_limits(long *pbackground, long *pdirty, - struct address_space *mapping) +get_dirty_limits(struct writeback_state *wbs, long *pbackground, long *pdirty, + struct address_space *mapping) { int background_ratio; /* Percentages */ int dirty_ratio; @@ -128,6 +144,8 @@ get_dirty_limits(long *pbackground, long *pdirty, unsigned long available_memory = total_pages; struct task_struct *tsk; + get_writeback_state(wbs); + #ifdef CONFIG_HIGHMEM /* * If this mapping can only allocate from low memory, @@ -138,9 +156,7 @@ get_dirty_limits(long *pbackground, long *pdirty, #endif - unmapped_ratio = 100 - ((global_page_state(NR_FILE_MAPPED) + - global_page_state(NR_ANON_PAGES)) * 100) / - total_pages; + unmapped_ratio = 100 - (wbs->nr_mapped * 100) / total_pages; dirty_ratio = vm_dirty_ratio; if (dirty_ratio > unmapped_ratio / 2) @@ -173,6 +189,7 @@ get_dirty_limits(long *pbackground, long *pdirty, */ static void balance_dirty_pages(struct address_space *mapping) { + struct writeback_state wbs; long nr_reclaimable; long background_thresh; long dirty_thresh; @@ -190,12 +207,11 @@ static void balance_dirty_pages(struct address_space *mapping) .range_cyclic = 1, }; - get_dirty_limits(&background_thresh, &dirty_thresh, mapping); - nr_reclaimable = global_page_state(NR_FILE_DIRTY) + - global_page_state(NR_UNSTABLE_NFS); - if (nr_reclaimable + global_page_state(NR_WRITEBACK) <= - dirty_thresh) - break; + get_dirty_limits(&wbs, &background_thresh, + &dirty_thresh, mapping); + nr_reclaimable = wbs.nr_dirty + wbs.nr_unstable; + if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh) + break; if (!dirty_exceeded) dirty_exceeded = 1; @@ -208,14 +224,11 @@ static void balance_dirty_pages(struct address_space *mapping) */ if (nr_reclaimable) { writeback_inodes(&wbc); - get_dirty_limits(&background_thresh, - &dirty_thresh, mapping); - nr_reclaimable = global_page_state(NR_FILE_DIRTY) + - global_page_state(NR_UNSTABLE_NFS); - if (nr_reclaimable + - global_page_state(NR_WRITEBACK) - <= dirty_thresh) - break; + get_dirty_limits(&wbs, &background_thresh, + &dirty_thresh, mapping); + nr_reclaimable = wbs.nr_dirty + wbs.nr_unstable; + if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh) + break; pages_written += write_chunk - wbc.nr_to_write; if (pages_written >= write_chunk) break; /* We've done our duty */ @@ -223,9 +236,8 @@ static void balance_dirty_pages(struct address_space *mapping) blk_congestion_wait(WRITE, HZ/10); } - if (nr_reclaimable + global_page_state(NR_WRITEBACK) - <= dirty_thresh && dirty_exceeded) - dirty_exceeded = 0; + if (nr_reclaimable + wbs.nr_writeback <= dirty_thresh && dirty_exceeded) + dirty_exceeded = 0; if (writeback_in_progress(bdi)) return; /* pdflush is already working this queue */ @@ -287,11 +299,12 @@ EXPORT_SYMBOL(balance_dirty_pages_ratelimited_nr); void throttle_vm_writeout(void) { + struct writeback_state wbs; long background_thresh; long dirty_thresh; for ( ; ; ) { - get_dirty_limits(&background_thresh, &dirty_thresh, NULL); + get_dirty_limits(&wbs, &background_thresh, &dirty_thresh, NULL); /* * Boost the allowable dirty threshold a bit for page @@ -299,9 +312,8 @@ void throttle_vm_writeout(void) */ dirty_thresh += dirty_thresh / 10; /* wheeee... */ - if (global_page_state(NR_UNSTABLE_NFS) + - global_page_state(NR_WRITEBACK) <= dirty_thresh) - break; + if (wbs.nr_unstable + wbs.nr_writeback <= dirty_thresh) + break; blk_congestion_wait(WRITE, HZ/10); } } @@ -324,12 +336,12 @@ static void background_writeout(unsigned long _min_pages) }; for ( ; ; ) { + struct writeback_state wbs; long background_thresh; long dirty_thresh; - get_dirty_limits(&background_thresh, &dirty_thresh, NULL); - if (global_page_state(NR_FILE_DIRTY) + - global_page_state(NR_UNSTABLE_NFS) < background_thresh + get_dirty_limits(&wbs, &background_thresh, &dirty_thresh, NULL); + if (wbs.nr_dirty + wbs.nr_unstable < background_thresh && min_pages <= 0) break; wbc.encountered_congestion = 0; @@ -353,9 +365,12 @@ static void background_writeout(unsigned long _min_pages) */ int wakeup_pdflush(long nr_pages) { - if (nr_pages == 0) - nr_pages = global_page_state(NR_FILE_DIRTY) + - global_page_state(NR_UNSTABLE_NFS); + if (nr_pages == 0) { + struct writeback_state wbs; + + get_writeback_state(&wbs); + nr_pages = wbs.nr_dirty + wbs.nr_unstable; + } return pdflush_operation(background_writeout, nr_pages); } @@ -386,6 +401,7 @@ static void wb_kupdate(unsigned long arg) unsigned long start_jif; unsigned long next_jif; long nr_to_write; + struct writeback_state wbs; struct writeback_control wbc = { .bdi = NULL, .sync_mode = WB_SYNC_NONE, @@ -398,11 +414,11 @@ static void wb_kupdate(unsigned long arg) sync_supers(); + get_writeback_state(&wbs); oldest_jif = jiffies - dirty_expire_interval; start_jif = jiffies; next_jif = start_jif + dirty_writeback_interval; - nr_to_write = global_page_state(NR_FILE_DIRTY) + - global_page_state(NR_UNSTABLE_NFS) + + nr_to_write = wbs.nr_dirty + wbs.nr_unstable + (inodes_stat.nr_inodes - inodes_stat.nr_unused); while (nr_to_write > 0) { wbc.encountered_congestion = 0; @@ -500,14 +516,14 @@ static void set_ratelimit(void) ratelimit_pages = (4096 * 1024) / PAGE_CACHE_SIZE; } -static int __cpuinit +static int ratelimit_handler(struct notifier_block *self, unsigned long u, void *v) { set_ratelimit(); return 0; } -static struct notifier_block __cpuinitdata ratelimit_nb = { +static struct notifier_block ratelimit_nb = { .notifier_call = ratelimit_handler, .next = NULL, }; @@ -624,8 +640,7 @@ int __set_page_dirty_nobuffers(struct page *page) if (mapping2) { /* Race with truncate? */ BUG_ON(mapping2 != mapping); if (mapping_cap_account_dirty(mapping)) - __inc_zone_page_state(page, - NR_FILE_DIRTY); + inc_page_state(nr_dirty); radix_tree_tag_set(&mapping->page_tree, page_index(page), PAGECACHE_TAG_DIRTY); } @@ -712,9 +727,9 @@ int test_clear_page_dirty(struct page *page) radix_tree_tag_clear(&mapping->page_tree, page_index(page), PAGECACHE_TAG_DIRTY); - if (mapping_cap_account_dirty(mapping)) - __dec_zone_page_state(page, NR_FILE_DIRTY); write_unlock_irqrestore(&mapping->tree_lock, flags); + if (mapping_cap_account_dirty(mapping)) + dec_page_state(nr_dirty); return 1; } write_unlock_irqrestore(&mapping->tree_lock, flags); @@ -745,7 +760,7 @@ int clear_page_dirty_for_io(struct page *page) if (mapping) { if (TestClearPageDirty(page)) { if (mapping_cap_account_dirty(mapping)) - dec_zone_page_state(page, NR_FILE_DIRTY); + dec_page_state(nr_dirty); return 1; } return 0; diff --git a/trunk/mm/page_alloc.c b/trunk/mm/page_alloc.c index 3e792a583f3b..6c1174fcf52c 100644 --- a/trunk/mm/page_alloc.c +++ b/trunk/mm/page_alloc.c @@ -14,6 +14,7 @@ * (lots of bits borrowed from Ingo Molnar & Andrew Morton) */ +#include #include #include #include @@ -265,7 +266,7 @@ static inline void rmv_page_order(struct page *page) * satisfies the following equation: * P = B & ~(1 << O) * - * Assumption: *_mem_map is contiguous at least up to MAX_ORDER + * Assumption: *_mem_map is contigious at least up to MAX_ORDER */ static inline struct page * __page_find_buddy(struct page *page, unsigned long page_idx, unsigned int order) @@ -445,8 +446,8 @@ static void __free_pages_ok(struct page *page, unsigned int order) arch_free_page(page, order); if (!PageHighMem(page)) - debug_check_no_locks_freed(page_address(page), - PAGE_SIZE<zone_pgdat; + pg_data_t *orig = zonelist->zones[0]->zone_pgdat; + struct per_cpu_pageset *p; + + p = zone_pcp(z, cpu); + if (pg == orig) { + p->numa_hit++; + } else { + p->numa_miss++; + zone_pcp(zonelist->zones[0], cpu)->numa_foreign++; + } + if (pg == NODE_DATA(numa_node_id())) + p->local_node++; + else + p->other_node++; +#endif +} + /* * Free a 0-order page */ @@ -728,7 +750,7 @@ static void fastcall free_hot_cold_page(struct page *page, int cold) pcp = &zone_pcp(zone, get_cpu())->pcp[cold]; local_irq_save(flags); - __count_vm_event(PGFREE); + __inc_page_state(pgfree); list_add(&page->lru, &pcp->list); pcp->count++; if (pcp->count >= pcp->high) { @@ -804,8 +826,8 @@ static struct page *buffered_rmqueue(struct zonelist *zonelist, goto failed; } - __count_zone_vm_events(PGALLOC, zone, 1 << order); - zone_statistics(zonelist, zone); + __mod_page_state_zone(zone, pgalloc, 1 << order); + zone_statistics(zonelist, zone, cpu); local_irq_restore(flags); put_cpu(); @@ -1209,6 +1231,141 @@ static void show_node(struct zone *zone) #define show_node(zone) do { } while (0) #endif +/* + * Accumulate the page_state information across all CPUs. + * The result is unavoidably approximate - it can change + * during and after execution of this function. + */ +static DEFINE_PER_CPU(struct page_state, page_states) = {0}; + +atomic_t nr_pagecache = ATOMIC_INIT(0); +EXPORT_SYMBOL(nr_pagecache); +#ifdef CONFIG_SMP +DEFINE_PER_CPU(long, nr_pagecache_local) = 0; +#endif + +static void __get_page_state(struct page_state *ret, int nr, cpumask_t *cpumask) +{ + unsigned cpu; + + memset(ret, 0, nr * sizeof(unsigned long)); + cpus_and(*cpumask, *cpumask, cpu_online_map); + + for_each_cpu_mask(cpu, *cpumask) { + unsigned long *in; + unsigned long *out; + unsigned off; + unsigned next_cpu; + + in = (unsigned long *)&per_cpu(page_states, cpu); + + next_cpu = next_cpu(cpu, *cpumask); + if (likely(next_cpu < NR_CPUS)) + prefetch(&per_cpu(page_states, next_cpu)); + + out = (unsigned long *)ret; + for (off = 0; off < nr; off++) + *out++ += *in++; + } +} + +void get_page_state_node(struct page_state *ret, int node) +{ + int nr; + cpumask_t mask = node_to_cpumask(node); + + nr = offsetof(struct page_state, GET_PAGE_STATE_LAST); + nr /= sizeof(unsigned long); + + __get_page_state(ret, nr+1, &mask); +} + +void get_page_state(struct page_state *ret) +{ + int nr; + cpumask_t mask = CPU_MASK_ALL; + + nr = offsetof(struct page_state, GET_PAGE_STATE_LAST); + nr /= sizeof(unsigned long); + + __get_page_state(ret, nr + 1, &mask); +} + +void get_full_page_state(struct page_state *ret) +{ + cpumask_t mask = CPU_MASK_ALL; + + __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long), &mask); +} + +unsigned long read_page_state_offset(unsigned long offset) +{ + unsigned long ret = 0; + int cpu; + + for_each_online_cpu(cpu) { + unsigned long in; + + in = (unsigned long)&per_cpu(page_states, cpu) + offset; + ret += *((unsigned long *)in); + } + return ret; +} + +void __mod_page_state_offset(unsigned long offset, unsigned long delta) +{ + void *ptr; + + ptr = &__get_cpu_var(page_states); + *(unsigned long *)(ptr + offset) += delta; +} +EXPORT_SYMBOL(__mod_page_state_offset); + +void mod_page_state_offset(unsigned long offset, unsigned long delta) +{ + unsigned long flags; + void *ptr; + + local_irq_save(flags); + ptr = &__get_cpu_var(page_states); + *(unsigned long *)(ptr + offset) += delta; + local_irq_restore(flags); +} +EXPORT_SYMBOL(mod_page_state_offset); + +void __get_zone_counts(unsigned long *active, unsigned long *inactive, + unsigned long *free, struct pglist_data *pgdat) +{ + struct zone *zones = pgdat->node_zones; + int i; + + *active = 0; + *inactive = 0; + *free = 0; + for (i = 0; i < MAX_NR_ZONES; i++) { + *active += zones[i].nr_active; + *inactive += zones[i].nr_inactive; + *free += zones[i].free_pages; + } +} + +void get_zone_counts(unsigned long *active, + unsigned long *inactive, unsigned long *free) +{ + struct pglist_data *pgdat; + + *active = 0; + *inactive = 0; + *free = 0; + for_each_online_pgdat(pgdat) { + unsigned long l, m, n; + __get_zone_counts(&l, &m, &n, pgdat); + *active += l; + *inactive += m; + *free += n; + } +} + void si_meminfo(struct sysinfo *val) { val->totalram = totalram_pages; @@ -1249,6 +1406,7 @@ void si_meminfo_node(struct sysinfo *val, int nid) */ void show_free_areas(void) { + struct page_state ps; int cpu, temperature; unsigned long active; unsigned long inactive; @@ -1280,6 +1438,7 @@ void show_free_areas(void) } } + get_page_state(&ps); get_zone_counts(&active, &inactive, &free); printk("Free pages: %11ukB (%ukB HighMem)\n", @@ -1290,13 +1449,13 @@ void show_free_areas(void) "unstable:%lu free:%u slab:%lu mapped:%lu pagetables:%lu\n", active, inactive, - global_page_state(NR_FILE_DIRTY), - global_page_state(NR_WRITEBACK), - global_page_state(NR_UNSTABLE_NFS), + ps.nr_dirty, + ps.nr_writeback, + ps.nr_unstable, nr_free_pages(), - global_page_state(NR_SLAB), - global_page_state(NR_FILE_MAPPED), - global_page_state(NR_PAGETABLE)); + ps.nr_slab, + ps.nr_mapped, + ps.nr_page_table_pages); for_each_zone(zone) { int i; @@ -1850,7 +2009,7 @@ static inline void free_zone_pagesets(int cpu) } } -static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb, +static int pageset_cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -1872,7 +2031,7 @@ static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb, return ret; } -static struct notifier_block __cpuinitdata pageset_notifier = +static struct notifier_block pageset_notifier = { &pageset_cpuup_callback, NULL, 0 }; void __init setup_per_cpu_pageset(void) @@ -2021,7 +2180,6 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat, zone->nr_scan_inactive = 0; zone->nr_active = 0; zone->nr_inactive = 0; - zap_zone_vm_stats(zone); atomic_set(&zone->reclaim_in_progress, 0); if (!size) continue; @@ -2095,18 +2253,307 @@ void __init free_area_init(unsigned long *zones_size) __pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL); } +#ifdef CONFIG_PROC_FS + +#include + +static void *frag_start(struct seq_file *m, loff_t *pos) +{ + pg_data_t *pgdat; + loff_t node = *pos; + for (pgdat = first_online_pgdat(); + pgdat && node; + pgdat = next_online_pgdat(pgdat)) + --node; + + return pgdat; +} + +static void *frag_next(struct seq_file *m, void *arg, loff_t *pos) +{ + pg_data_t *pgdat = (pg_data_t *)arg; + + (*pos)++; + return next_online_pgdat(pgdat); +} + +static void frag_stop(struct seq_file *m, void *arg) +{ +} + +/* + * This walks the free areas for each zone. + */ +static int frag_show(struct seq_file *m, void *arg) +{ + pg_data_t *pgdat = (pg_data_t *)arg; + struct zone *zone; + struct zone *node_zones = pgdat->node_zones; + unsigned long flags; + int order; + + for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) { + if (!populated_zone(zone)) + continue; + + spin_lock_irqsave(&zone->lock, flags); + seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name); + for (order = 0; order < MAX_ORDER; ++order) + seq_printf(m, "%6lu ", zone->free_area[order].nr_free); + spin_unlock_irqrestore(&zone->lock, flags); + seq_putc(m, '\n'); + } + return 0; +} + +struct seq_operations fragmentation_op = { + .start = frag_start, + .next = frag_next, + .stop = frag_stop, + .show = frag_show, +}; + +/* + * Output information about zones in @pgdat. + */ +static int zoneinfo_show(struct seq_file *m, void *arg) +{ + pg_data_t *pgdat = arg; + struct zone *zone; + struct zone *node_zones = pgdat->node_zones; + unsigned long flags; + + for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) { + int i; + + if (!populated_zone(zone)) + continue; + + spin_lock_irqsave(&zone->lock, flags); + seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name); + seq_printf(m, + "\n pages free %lu" + "\n min %lu" + "\n low %lu" + "\n high %lu" + "\n active %lu" + "\n inactive %lu" + "\n scanned %lu (a: %lu i: %lu)" + "\n spanned %lu" + "\n present %lu", + zone->free_pages, + zone->pages_min, + zone->pages_low, + zone->pages_high, + zone->nr_active, + zone->nr_inactive, + zone->pages_scanned, + zone->nr_scan_active, zone->nr_scan_inactive, + zone->spanned_pages, + zone->present_pages); + seq_printf(m, + "\n protection: (%lu", + zone->lowmem_reserve[0]); + for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++) + seq_printf(m, ", %lu", zone->lowmem_reserve[i]); + seq_printf(m, + ")" + "\n pagesets"); + for_each_online_cpu(i) { + struct per_cpu_pageset *pageset; + int j; + + pageset = zone_pcp(zone, i); + for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) { + if (pageset->pcp[j].count) + break; + } + if (j == ARRAY_SIZE(pageset->pcp)) + continue; + for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) { + seq_printf(m, + "\n cpu: %i pcp: %i" + "\n count: %i" + "\n high: %i" + "\n batch: %i", + i, j, + pageset->pcp[j].count, + pageset->pcp[j].high, + pageset->pcp[j].batch); + } +#ifdef CONFIG_NUMA + seq_printf(m, + "\n numa_hit: %lu" + "\n numa_miss: %lu" + "\n numa_foreign: %lu" + "\n interleave_hit: %lu" + "\n local_node: %lu" + "\n other_node: %lu", + pageset->numa_hit, + pageset->numa_miss, + pageset->numa_foreign, + pageset->interleave_hit, + pageset->local_node, + pageset->other_node); +#endif + } + seq_printf(m, + "\n all_unreclaimable: %u" + "\n prev_priority: %i" + "\n temp_priority: %i" + "\n start_pfn: %lu", + zone->all_unreclaimable, + zone->prev_priority, + zone->temp_priority, + zone->zone_start_pfn); + spin_unlock_irqrestore(&zone->lock, flags); + seq_putc(m, '\n'); + } + return 0; +} + +struct seq_operations zoneinfo_op = { + .start = frag_start, /* iterate over all zones. The same as in + * fragmentation. */ + .next = frag_next, + .stop = frag_stop, + .show = zoneinfo_show, +}; + +static char *vmstat_text[] = { + "nr_dirty", + "nr_writeback", + "nr_unstable", + "nr_page_table_pages", + "nr_mapped", + "nr_slab", + + "pgpgin", + "pgpgout", + "pswpin", + "pswpout", + + "pgalloc_high", + "pgalloc_normal", + "pgalloc_dma32", + "pgalloc_dma", + + "pgfree", + "pgactivate", + "pgdeactivate", + + "pgfault", + "pgmajfault", + + "pgrefill_high", + "pgrefill_normal", + "pgrefill_dma32", + "pgrefill_dma", + + "pgsteal_high", + "pgsteal_normal", + "pgsteal_dma32", + "pgsteal_dma", + + "pgscan_kswapd_high", + "pgscan_kswapd_normal", + "pgscan_kswapd_dma32", + "pgscan_kswapd_dma", + + "pgscan_direct_high", + "pgscan_direct_normal", + "pgscan_direct_dma32", + "pgscan_direct_dma", + + "pginodesteal", + "slabs_scanned", + "kswapd_steal", + "kswapd_inodesteal", + "pageoutrun", + "allocstall", + + "pgrotated", + "nr_bounce", +}; + +static void *vmstat_start(struct seq_file *m, loff_t *pos) +{ + struct page_state *ps; + + if (*pos >= ARRAY_SIZE(vmstat_text)) + return NULL; + + ps = kmalloc(sizeof(*ps), GFP_KERNEL); + m->private = ps; + if (!ps) + return ERR_PTR(-ENOMEM); + get_full_page_state(ps); + ps->pgpgin /= 2; /* sectors -> kbytes */ + ps->pgpgout /= 2; + return (unsigned long *)ps + *pos; +} + +static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos) +{ + (*pos)++; + if (*pos >= ARRAY_SIZE(vmstat_text)) + return NULL; + return (unsigned long *)m->private + *pos; +} + +static int vmstat_show(struct seq_file *m, void *arg) +{ + unsigned long *l = arg; + unsigned long off = l - (unsigned long *)m->private; + + seq_printf(m, "%s %lu\n", vmstat_text[off], *l); + return 0; +} + +static void vmstat_stop(struct seq_file *m, void *arg) +{ + kfree(m->private); + m->private = NULL; +} + +struct seq_operations vmstat_op = { + .start = vmstat_start, + .next = vmstat_next, + .stop = vmstat_stop, + .show = vmstat_show, +}; + +#endif /* CONFIG_PROC_FS */ + #ifdef CONFIG_HOTPLUG_CPU static int page_alloc_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { int cpu = (unsigned long)hcpu; + long *count; + unsigned long *src, *dest; if (action == CPU_DEAD) { + int i; + + /* Drain local pagecache count. */ + count = &per_cpu(nr_pagecache_local, cpu); + atomic_add(*count, &nr_pagecache); + *count = 0; local_irq_disable(); __drain_pages(cpu); - vm_events_fold_cpu(cpu); + + /* Add dead cpu's page_states to our own. */ + dest = (unsigned long *)&__get_cpu_var(page_states); + src = (unsigned long *)&per_cpu(page_states, cpu); + + for (i = 0; i < sizeof(struct page_state)/sizeof(unsigned long); + i++) { + dest[i] += src[i]; + src[i] = 0; + } + local_irq_enable(); - refresh_cpu_vm_stats(cpu); } return NOTIFY_OK; } diff --git a/trunk/mm/page_io.c b/trunk/mm/page_io.c index 88029948d00a..bb2b0d53889c 100644 --- a/trunk/mm/page_io.c +++ b/trunk/mm/page_io.c @@ -101,7 +101,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) } if (wbc->sync_mode == WB_SYNC_ALL) rw |= (1 << BIO_RW_SYNC); - count_vm_event(PSWPOUT); + inc_page_state(pswpout); set_page_writeback(page); unlock_page(page); submit_bio(rw, bio); @@ -123,7 +123,7 @@ int swap_readpage(struct file *file, struct page *page) ret = -ENOMEM; goto out; } - count_vm_event(PSWPIN); + inc_page_state(pswpin); submit_bio(READ, bio); out: return ret; diff --git a/trunk/mm/readahead.c b/trunk/mm/readahead.c index aa7ec424656a..e39e416860d7 100644 --- a/trunk/mm/readahead.c +++ b/trunk/mm/readahead.c @@ -390,8 +390,8 @@ int do_page_cache_readahead(struct address_space *mapping, struct file *filp, * Read 'nr_to_read' pages starting at page 'offset'. If the flag 'block' * is set wait till the read completes. Otherwise attempt to read without * blocking. - * Returns 1 meaning 'success' if read is successful without switching off - * readahead mode. Otherwise return failure. + * Returns 1 meaning 'success' if read is succesfull without switching off + * readhaead mode. Otherwise return failure. */ static int blockable_page_cache_readahead(struct address_space *mapping, struct file *filp, diff --git a/trunk/mm/rmap.c b/trunk/mm/rmap.c index 40158b59729e..e76909e880ca 100644 --- a/trunk/mm/rmap.c +++ b/trunk/mm/rmap.c @@ -455,7 +455,7 @@ static void __page_set_anon_rmap(struct page *page, * nr_mapped state can be updated without turning off * interrupts because it is not modified via interrupt. */ - __inc_zone_page_state(page, NR_ANON_PAGES); + __inc_page_state(nr_mapped); } /** @@ -499,7 +499,7 @@ void page_add_new_anon_rmap(struct page *page, void page_add_file_rmap(struct page *page) { if (atomic_inc_and_test(&page->_mapcount)) - __inc_zone_page_state(page, NR_FILE_MAPPED); + __inc_page_state(nr_mapped); } /** @@ -531,8 +531,7 @@ void page_remove_rmap(struct page *page) */ if (page_test_and_clear_dirty(page)) set_page_dirty(page); - __dec_zone_page_state(page, - PageAnon(page) ? NR_ANON_PAGES : NR_FILE_MAPPED); + __dec_page_state(nr_mapped); } } diff --git a/trunk/mm/shmem.c b/trunk/mm/shmem.c index db21c51531ca..38bc3334f263 100644 --- a/trunk/mm/shmem.c +++ b/trunk/mm/shmem.c @@ -23,8 +23,10 @@ * which makes it a completely usable filesystem. */ +#include #include #include +#include #include #include #include @@ -172,7 +174,7 @@ static inline void shmem_unacct_blocks(unsigned long flags, long pages) } static struct super_operations shmem_ops; -static const struct address_space_operations shmem_aops; +static struct address_space_operations shmem_aops; static struct file_operations shmem_file_operations; static struct inode_operations shmem_inode_operations; static struct inode_operations shmem_dir_inode_operations; @@ -1044,12 +1046,12 @@ static int shmem_getpage(struct inode *inode, unsigned long idx, swappage = lookup_swap_cache(swap); if (!swappage) { shmem_swp_unmap(entry); + spin_unlock(&info->lock); /* here we actually do the io */ if (type && *type == VM_FAULT_MINOR) { - __count_vm_event(PGMAJFAULT); + inc_page_state(pgmajfault); *type = VM_FAULT_MAJOR; } - spin_unlock(&info->lock); swappage = shmem_swapin(info, swap, idx); if (!swappage) { spin_lock(&info->lock); @@ -2160,7 +2162,7 @@ static void destroy_inodecache(void) printk(KERN_INFO "shmem_inode_cache: not all structures were freed\n"); } -static const struct address_space_operations shmem_aops = { +static struct address_space_operations shmem_aops = { .writepage = shmem_writepage, .set_page_dirty = __set_page_dirty_nobuffers, #ifdef CONFIG_TMPFS @@ -2250,7 +2252,9 @@ static int __init init_tmpfs(void) printk(KERN_ERR "Could not register tmpfs\n"); goto out2; } - +#ifdef CONFIG_TMPFS + devfs_mk_dir("shm"); +#endif shm_mnt = vfs_kern_mount(&tmpfs_fs_type, MS_NOUSER, tmpfs_fs_type.name, NULL); if (IS_ERR(shm_mnt)) { diff --git a/trunk/mm/slab.c b/trunk/mm/slab.c index 3936af344542..98ac20bc0de9 100644 --- a/trunk/mm/slab.c +++ b/trunk/mm/slab.c @@ -89,7 +89,6 @@ #include #include #include -#include #include #include #include @@ -107,7 +106,6 @@ #include #include #include -#include #include #include @@ -309,13 +307,6 @@ struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS]; #define SIZE_AC 1 #define SIZE_L3 (1 + MAX_NUMNODES) -static int drain_freelist(struct kmem_cache *cache, - struct kmem_list3 *l3, int tofree); -static void free_block(struct kmem_cache *cachep, void **objpp, int len, - int node); -static void enable_cpucache(struct kmem_cache *cachep); -static void cache_reap(void *unused); - /* * This function must be completely optimized away if a constant is passed to * it. Mostly the same as what is in linux/slab.h except it returns an index. @@ -463,7 +454,7 @@ struct kmem_cache { #define STATS_DEC_ACTIVE(x) ((x)->num_active--) #define STATS_INC_ALLOCED(x) ((x)->num_allocations++) #define STATS_INC_GROWN(x) ((x)->grown++) -#define STATS_ADD_REAPED(x,y) ((x)->reaped += (y)) +#define STATS_INC_REAPED(x) ((x)->reaped++) #define STATS_SET_HIGH(x) \ do { \ if ((x)->num_active > (x)->high_mark) \ @@ -487,7 +478,7 @@ struct kmem_cache { #define STATS_DEC_ACTIVE(x) do { } while (0) #define STATS_INC_ALLOCED(x) do { } while (0) #define STATS_INC_GROWN(x) do { } while (0) -#define STATS_ADD_REAPED(x,y) do { } while (0) +#define STATS_INC_REAPED(x) do { } while (0) #define STATS_SET_HIGH(x) do { } while (0) #define STATS_INC_ERR(x) do { } while (0) #define STATS_INC_NODEALLOCS(x) do { } while (0) @@ -501,6 +492,17 @@ struct kmem_cache { #endif #if DEBUG +/* + * Magic nums for obj red zoning. + * Placed in the first word before and the first word after an obj. + */ +#define RED_INACTIVE 0x5A2CF071UL /* when obj is inactive */ +#define RED_ACTIVE 0x170FC2A5UL /* when obj is active */ + +/* ...and for poisoning */ +#define POISON_INUSE 0x5a /* for use-uninitialised poisoning */ +#define POISON_FREE 0x6b /* for use-after-free poisoning */ +#define POISON_END 0xa5 /* end-byte of poisoning */ /* * memory layout of objects: @@ -707,6 +709,12 @@ int slab_is_available(void) static DEFINE_PER_CPU(struct work_struct, reap_work); +static void free_block(struct kmem_cache *cachep, void **objpp, int len, + int node); +static void enable_cpucache(struct kmem_cache *cachep); +static void cache_reap(void *unused); +static int __node_shrink(struct kmem_cache *cachep, int node); + static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) { return cachep->array[smp_processor_id()]; @@ -1075,7 +1083,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) #endif -static int __devinit cpuup_callback(struct notifier_block *nfb, +static int cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -1242,7 +1250,10 @@ static int __devinit cpuup_callback(struct notifier_block *nfb, l3 = cachep->nodelists[node]; if (!l3) continue; - drain_freelist(cachep, l3, l3->free_objects); + spin_lock_irq(&l3->list_lock); + /* free slabs belonging to this node */ + __node_shrink(cachep, node); + spin_unlock_irq(&l3->list_lock); } mutex_unlock(&cache_chain_mutex); break; @@ -1254,9 +1265,7 @@ static int __devinit cpuup_callback(struct notifier_block *nfb, return NOTIFY_BAD; } -static struct notifier_block __cpuinitdata cpucache_notifier = { - &cpuup_callback, NULL, 0 -}; +static struct notifier_block cpucache_notifier = { &cpuup_callback, NULL, 0 }; /* * swap the static kmem_list3 with kmalloced memory @@ -1505,7 +1514,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) nr_pages = (1 << cachep->gfporder); if (cachep->flags & SLAB_RECLAIM_ACCOUNT) atomic_add(nr_pages, &slab_reclaim_pages); - add_zone_page_state(page_zone(page), NR_SLAB, nr_pages); + add_page_state(nr_slab, nr_pages); for (i = 0; i < nr_pages; i++) __SetPageSlab(page + i); return page_address(page); @@ -1520,12 +1529,12 @@ static void kmem_freepages(struct kmem_cache *cachep, void *addr) struct page *page = virt_to_page(addr); const unsigned long nr_freed = i; - sub_zone_page_state(page_zone(page), NR_SLAB, nr_freed); while (i--) { BUG_ON(!PageSlab(page)); __ClearPageSlab(page); page++; } + sub_page_state(nr_slab, nr_freed); if (current->reclaim_state) current->reclaim_state->reclaimed_slab += nr_freed; free_pages((unsigned long)addr, cachep->gfporder); @@ -2246,45 +2255,32 @@ static void drain_cpu_caches(struct kmem_cache *cachep) } } -/* - * Remove slabs from the list of free slabs. - * Specify the number of slabs to drain in tofree. - * - * Returns the actual number of slabs released. - */ -static int drain_freelist(struct kmem_cache *cache, - struct kmem_list3 *l3, int tofree) +static int __node_shrink(struct kmem_cache *cachep, int node) { - struct list_head *p; - int nr_freed; struct slab *slabp; + struct kmem_list3 *l3 = cachep->nodelists[node]; + int ret; - nr_freed = 0; - while (nr_freed < tofree && !list_empty(&l3->slabs_free)) { + for (;;) { + struct list_head *p; - spin_lock_irq(&l3->list_lock); p = l3->slabs_free.prev; - if (p == &l3->slabs_free) { - spin_unlock_irq(&l3->list_lock); - goto out; - } + if (p == &l3->slabs_free) + break; - slabp = list_entry(p, struct slab, list); + slabp = list_entry(l3->slabs_free.prev, struct slab, list); #if DEBUG BUG_ON(slabp->inuse); #endif list_del(&slabp->list); - /* - * Safe to drop the lock. The slab is no longer linked - * to the cache. - */ - l3->free_objects -= cache->num; + + l3->free_objects -= cachep->num; spin_unlock_irq(&l3->list_lock); - slab_destroy(cache, slabp); - nr_freed++; + slab_destroy(cachep, slabp); + spin_lock_irq(&l3->list_lock); } -out: - return nr_freed; + ret = !list_empty(&l3->slabs_full) || !list_empty(&l3->slabs_partial); + return ret; } static int __cache_shrink(struct kmem_cache *cachep) @@ -2297,13 +2293,11 @@ static int __cache_shrink(struct kmem_cache *cachep) check_irq_on(); for_each_online_node(i) { l3 = cachep->nodelists[i]; - if (!l3) - continue; - - drain_freelist(cachep, l3, l3->free_objects); - - ret += !list_empty(&l3->slabs_full) || - !list_empty(&l3->slabs_partial); + if (l3) { + spin_lock_irq(&l3->list_lock); + ret += __node_shrink(cachep, i); + spin_unlock_irq(&l3->list_lock); + } } return (ret ? 1 : 0); } @@ -3411,7 +3405,7 @@ void kfree(const void *objp) local_irq_save(flags); kfree_debugcheck(objp); c = virt_to_cache(objp); - debug_check_no_locks_freed(objp, obj_size(c)); + mutex_debug_check_no_locks_freed(objp, obj_size(c)); __cache_free(c, (void *)objp); local_irq_restore(flags); } @@ -3707,6 +3701,10 @@ static void cache_reap(void *unused) } list_for_each_entry(searchp, &cache_chain, next) { + struct list_head *p; + int tofree; + struct slab *slabp; + check_irq_on(); /* @@ -3731,22 +3729,47 @@ static void cache_reap(void *unused) drain_array(searchp, l3, l3->shared, 0, node); - if (l3->free_touched) + if (l3->free_touched) { l3->free_touched = 0; - else { - int freed; - - freed = drain_freelist(searchp, l3, (l3->free_limit + - 5 * searchp->num - 1) / (5 * searchp->num)); - STATS_ADD_REAPED(searchp, freed); + goto next; } + + tofree = (l3->free_limit + 5 * searchp->num - 1) / + (5 * searchp->num); + do { + /* + * Do not lock if there are no free blocks. + */ + if (list_empty(&l3->slabs_free)) + break; + + spin_lock_irq(&l3->list_lock); + p = l3->slabs_free.next; + if (p == &(l3->slabs_free)) { + spin_unlock_irq(&l3->list_lock); + break; + } + + slabp = list_entry(p, struct slab, list); + BUG_ON(slabp->inuse); + list_del(&slabp->list); + STATS_INC_REAPED(searchp); + + /* + * Safe to drop the lock. The slab is no longer linked + * to the cache. searchp cannot disappear, we hold + * cache_chain_lock + */ + l3->free_objects -= searchp->num; + spin_unlock_irq(&l3->list_lock); + slab_destroy(searchp, slabp); + } while (--tofree > 0); next: cond_resched(); } check_irq_on(); mutex_unlock(&cache_chain_mutex); next_reap_node(); - refresh_cpu_vm_stats(smp_processor_id()); /* Set up the next iteration */ schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC); } diff --git a/trunk/mm/slob.c b/trunk/mm/slob.c index 7b52b20b9607..a68255ba4553 100644 --- a/trunk/mm/slob.c +++ b/trunk/mm/slob.c @@ -29,6 +29,7 @@ * essentially no allocation space overhead. */ +#include #include #include #include diff --git a/trunk/mm/sparse.c b/trunk/mm/sparse.c index 86c52ab80878..e0a3fe48aa37 100644 --- a/trunk/mm/sparse.c +++ b/trunk/mm/sparse.c @@ -1,6 +1,7 @@ /* * sparse memory mappings. */ +#include #include #include #include @@ -44,7 +45,7 @@ static struct mem_section *sparse_index_alloc(int nid) static int sparse_index_init(unsigned long section_nr, int nid) { - static DEFINE_SPINLOCK(index_init_lock); + static spinlock_t index_init_lock = SPIN_LOCK_UNLOCKED; unsigned long root = SECTION_NR_TO_ROOT(section_nr); struct mem_section *section; int ret = 0; diff --git a/trunk/mm/swap.c b/trunk/mm/swap.c index 8fd095c4ae51..03ae2076f92f 100644 --- a/trunk/mm/swap.c +++ b/trunk/mm/swap.c @@ -86,8 +86,9 @@ int rotate_reclaimable_page(struct page *page) zone = page_zone(page); spin_lock_irqsave(&zone->lru_lock, flags); if (PageLRU(page) && !PageActive(page)) { - list_move_tail(&page->lru, &zone->inactive_list); - __count_vm_event(PGROTATED); + list_del(&page->lru); + list_add_tail(&page->lru, &zone->inactive_list); + inc_page_state(pgrotated); } if (!test_clear_page_writeback(page)) BUG(); @@ -107,7 +108,7 @@ void fastcall activate_page(struct page *page) del_page_from_inactive_list(zone, page); SetPageActive(page); add_page_to_active_list(zone, page); - __count_vm_event(PGACTIVATE); + inc_page_state(pgactivate); } spin_unlock_irq(&zone->lru_lock); } diff --git a/trunk/mm/swap_state.c b/trunk/mm/swap_state.c index fccbd9bba77b..e0e1583f32c2 100644 --- a/trunk/mm/swap_state.c +++ b/trunk/mm/swap_state.c @@ -24,7 +24,7 @@ * vmscan's shrink_list, to make sync_page look nicer, and to allow * future use of radix_tree tags in the swap cache. */ -static const struct address_space_operations swap_aops = { +static struct address_space_operations swap_aops = { .writepage = swap_writepage, .sync_page = block_sync_page, .set_page_dirty = __set_page_dirty_nobuffers, @@ -87,7 +87,7 @@ static int __add_to_swap_cache(struct page *page, swp_entry_t entry, SetPageSwapCache(page); set_page_private(page, entry.val); total_swapcache_pages++; - __inc_zone_page_state(page, NR_FILE_PAGES); + pagecache_acct(1); } write_unlock_irq(&swapper_space.tree_lock); radix_tree_preload_end(); @@ -132,7 +132,7 @@ void __delete_from_swap_cache(struct page *page) set_page_private(page, 0); ClearPageSwapCache(page); total_swapcache_pages--; - __dec_zone_page_state(page, NR_FILE_PAGES); + pagecache_acct(-1); INC_CACHE_INFO(del_total); } diff --git a/trunk/mm/swapfile.c b/trunk/mm/swapfile.c index e70d6c6d6fee..cc367f7e75d8 100644 --- a/trunk/mm/swapfile.c +++ b/trunk/mm/swapfile.c @@ -5,6 +5,7 @@ * Swap reorganised 29.12.95, Stephen Tweedie */ +#include #include #include #include diff --git a/trunk/mm/tiny-shmem.c b/trunk/mm/tiny-shmem.c index 5f2cbf0f153c..f9d6a9cc91c4 100644 --- a/trunk/mm/tiny-shmem.c +++ b/trunk/mm/tiny-shmem.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -32,6 +33,9 @@ static int __init init_tmpfs(void) { BUG_ON(register_filesystem(&tmpfs_fs_type) != 0); +#ifdef CONFIG_TMPFS + devfs_mk_dir("shm"); +#endif shm_mnt = kern_mount(&tmpfs_fs_type); BUG_ON(IS_ERR(shm_mnt)); diff --git a/trunk/mm/vmscan.c b/trunk/mm/vmscan.c index ff2ebe9458a3..72babac71dea 100644 --- a/trunk/mm/vmscan.c +++ b/trunk/mm/vmscan.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -47,6 +46,8 @@ struct scan_control { /* Incremented by the number of inactive pages that were scanned */ unsigned long nr_scanned; + unsigned long nr_mapped; /* From page_state */ + /* This context's GFP mask */ gfp_t gfp_mask; @@ -215,7 +216,7 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, break; if (shrink_ret < nr_before) ret += nr_before - shrink_ret; - count_vm_events(SLABS_SCANNED, this_scan); + mod_page_state(slabs_scanned, this_scan); total_scan -= this_scan; cond_resched(); @@ -569,7 +570,7 @@ static unsigned long shrink_page_list(struct list_head *page_list, list_splice(&ret_pages, page_list); if (pagevec_count(&freed_pvec)) __pagevec_release_nonlru(&freed_pvec); - count_vm_events(PGACTIVATE, pgactivate); + mod_page_state(pgactivate, pgactivate); return nr_reclaimed; } @@ -659,11 +660,11 @@ static unsigned long shrink_inactive_list(unsigned long max_scan, nr_reclaimed += nr_freed; local_irq_disable(); if (current_is_kswapd()) { - __count_zone_vm_events(PGSCAN_KSWAPD, zone, nr_scan); - __count_vm_events(KSWAPD_STEAL, nr_freed); + __mod_page_state_zone(zone, pgscan_kswapd, nr_scan); + __mod_page_state(kswapd_steal, nr_freed); } else - __count_zone_vm_events(PGSCAN_DIRECT, zone, nr_scan); - __count_vm_events(PGACTIVATE, nr_freed); + __mod_page_state_zone(zone, pgscan_direct, nr_scan); + __mod_page_state_zone(zone, pgsteal, nr_freed); if (nr_taken == 0) goto done; @@ -742,9 +743,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, * how much memory * is mapped. */ - mapped_ratio = ((global_page_state(NR_FILE_MAPPED) + - global_page_state(NR_ANON_PAGES)) * 100) / - vm_total_pages; + mapped_ratio = (sc->nr_mapped * 100) / vm_total_pages; /* * Now decide how much we really want to unmap some pages. The @@ -841,10 +840,11 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, } } zone->nr_active += pgmoved; + spin_unlock(&zone->lru_lock); - __count_zone_vm_events(PGREFILL, zone, pgscanned); - __count_vm_events(PGDEACTIVATE, pgdeactivate); - spin_unlock_irq(&zone->lru_lock); + __mod_page_state_zone(zone, pgrefill, pgscanned); + __mod_page_state(pgdeactivate, pgdeactivate); + local_irq_enable(); pagevec_release(&pvec); } @@ -976,7 +976,7 @@ unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask) .swappiness = vm_swappiness, }; - count_vm_event(ALLOCSTALL); + inc_page_state(allocstall); for (i = 0; zones[i] != NULL; i++) { struct zone *zone = zones[i]; @@ -989,6 +989,7 @@ unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask) } for (priority = DEF_PRIORITY; priority >= 0; priority--) { + sc.nr_mapped = read_page_state(nr_mapped); sc.nr_scanned = 0; if (!priority) disable_swap_token(); @@ -1073,7 +1074,9 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order) total_scanned = 0; nr_reclaimed = 0; sc.may_writepage = !laptop_mode; - count_vm_event(PAGEOUTRUN); + sc.nr_mapped = read_page_state(nr_mapped); + + inc_page_state(pageoutrun); for (i = 0; i < pgdat->nr_zones; i++) { struct zone *zone = pgdat->node_zones + i; @@ -1220,6 +1223,7 @@ static int kswapd(void *p) }; cpumask_t cpumask; + daemonize("kswapd%d", pgdat->node_id); cpumask = node_to_cpumask(pgdat->node_id); if (!cpus_empty(cpumask)) set_cpus_allowed(tsk, cpumask); @@ -1361,7 +1365,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages) for_each_zone(zone) lru_pages += zone->nr_active + zone->nr_inactive; - nr_slab = global_page_state(NR_SLAB); + nr_slab = read_page_state(nr_slab); /* If slab caches are huge, it's better to hit them first */ while (nr_slab >= lru_pages) { reclaim_state.reclaimed_slab = 0; @@ -1403,7 +1407,9 @@ unsigned long shrink_all_memory(unsigned long nr_pages) for (prio = DEF_PRIORITY; prio >= 0; prio--) { unsigned long nr_to_scan = nr_pages - ret; + sc.nr_mapped = read_page_state(nr_mapped); sc.nr_scanned = 0; + ret += shrink_all_zones(nr_to_scan, prio, pass, &sc); if (ret >= nr_pages) goto out; @@ -1444,7 +1450,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages) not required for correctness. So if the last cpu in a node goes away, we get changed to run anywhere: as the first one comes back, restore their cpu bindings. */ -static int __devinit cpu_callback(struct notifier_block *nfb, +static int cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { pg_data_t *pgdat; @@ -1462,35 +1468,20 @@ static int __devinit cpu_callback(struct notifier_block *nfb, } #endif /* CONFIG_HOTPLUG_CPU */ -/* - * This kswapd start function will be called by init and node-hot-add. - * On node-hot-add, kswapd will moved to proper cpus if cpus are hot-added. - */ -int kswapd_run(int nid) -{ - pg_data_t *pgdat = NODE_DATA(nid); - int ret = 0; - - if (pgdat->kswapd) - return 0; - - pgdat->kswapd = kthread_run(kswapd, pgdat, "kswapd%d", nid); - if (IS_ERR(pgdat->kswapd)) { - /* failure at boot is fatal */ - BUG_ON(system_state == SYSTEM_BOOTING); - printk("Failed to start kswapd on node %d\n",nid); - ret = -1; - } - return ret; -} - static int __init kswapd_init(void) { - int nid; + pg_data_t *pgdat; swap_setup(); - for_each_online_node(nid) - kswapd_run(nid); + for_each_online_pgdat(pgdat) { + pid_t pid; + + pid = kernel_thread(kswapd, pgdat, CLONE_KERNEL); + BUG_ON(pid < 0); + read_lock(&tasklist_lock); + pgdat->kswapd = find_task_by_pid(pid); + read_unlock(&tasklist_lock); + } hotcpu_notifier(cpu_callback, 0); return 0; } @@ -1516,6 +1507,11 @@ int zone_reclaim_mode __read_mostly; #define RECLAIM_SWAP (1<<2) /* Swap pages out during reclaim */ #define RECLAIM_SLAB (1<<3) /* Do a global slab shrink if the zone is out of memory */ +/* + * Mininum time between zone reclaim scans + */ +int zone_reclaim_interval __read_mostly = 30*HZ; + /* * Priority for ZONE_RECLAIM. This determines the fraction of pages * of a node considered for each zone_reclaim. 4 scans 1/16th of @@ -1537,6 +1533,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) struct scan_control sc = { .may_writepage = !!(zone_reclaim_mode & RECLAIM_WRITE), .may_swap = !!(zone_reclaim_mode & RECLAIM_SWAP), + .nr_mapped = read_page_state(nr_mapped), .swap_cluster_max = max_t(unsigned long, nr_pages, SWAP_CLUSTER_MAX), .gfp_mask = gfp_mask, @@ -1581,6 +1578,16 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) p->reclaim_state = NULL; current->flags &= ~(PF_MEMALLOC | PF_SWAPWRITE); + + if (nr_reclaimed == 0) { + /* + * We were unable to reclaim enough pages to stay on node. We + * now allow off node accesses for a certain time period before + * trying again to reclaim pages from the local zone. + */ + zone->last_unsuccessful_zone_reclaim = jiffies; + } + return nr_reclaimed >= nr_pages; } @@ -1590,17 +1597,13 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) int node_id; /* - * Do not reclaim if there are not enough reclaimable pages in this - * zone that would satify this allocations. - * - * All unmapped pagecache pages are reclaimable. - * - * Both counters may be temporarily off a bit so we use - * SWAP_CLUSTER_MAX as the boundary. It may also be good to - * leave a few frequently used unmapped pagecache pages around. + * Do not reclaim if there was a recent unsuccessful attempt at zone + * reclaim. In that case we let allocations go off node for the + * zone_reclaim_interval. Otherwise we would scan for each off-node + * page allocation. */ - if (zone_page_state(zone, NR_FILE_PAGES) - - zone_page_state(zone, NR_FILE_MAPPED) < SWAP_CLUSTER_MAX) + if (time_before(jiffies, + zone->last_unsuccessful_zone_reclaim + zone_reclaim_interval)) return 0; /* diff --git a/trunk/mm/vmstat.c b/trunk/mm/vmstat.c deleted file mode 100644 index 73b83d67bab6..000000000000 --- a/trunk/mm/vmstat.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * linux/mm/vmstat.c - * - * Manages VM statistics - * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds - * - * zoned VM statistics - * Copyright (C) 2006 Silicon Graphics, Inc., - * Christoph Lameter - */ - -#include -#include -#include - -void __get_zone_counts(unsigned long *active, unsigned long *inactive, - unsigned long *free, struct pglist_data *pgdat) -{ - struct zone *zones = pgdat->node_zones; - int i; - - *active = 0; - *inactive = 0; - *free = 0; - for (i = 0; i < MAX_NR_ZONES; i++) { - *active += zones[i].nr_active; - *inactive += zones[i].nr_inactive; - *free += zones[i].free_pages; - } -} - -void get_zone_counts(unsigned long *active, - unsigned long *inactive, unsigned long *free) -{ - struct pglist_data *pgdat; - - *active = 0; - *inactive = 0; - *free = 0; - for_each_online_pgdat(pgdat) { - unsigned long l, m, n; - __get_zone_counts(&l, &m, &n, pgdat); - *active += l; - *inactive += m; - *free += n; - } -} - -#ifdef CONFIG_VM_EVENT_COUNTERS -DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}}; -EXPORT_PER_CPU_SYMBOL(vm_event_states); - -static void sum_vm_events(unsigned long *ret, cpumask_t *cpumask) -{ - int cpu = 0; - int i; - - memset(ret, 0, NR_VM_EVENT_ITEMS * sizeof(unsigned long)); - - cpu = first_cpu(*cpumask); - while (cpu < NR_CPUS) { - struct vm_event_state *this = &per_cpu(vm_event_states, cpu); - - cpu = next_cpu(cpu, *cpumask); - - if (cpu < NR_CPUS) - prefetch(&per_cpu(vm_event_states, cpu)); - - - for (i = 0; i < NR_VM_EVENT_ITEMS; i++) - ret[i] += this->event[i]; - } -} - -/* - * Accumulate the vm event counters across all CPUs. - * The result is unavoidably approximate - it can change - * during and after execution of this function. -*/ -void all_vm_events(unsigned long *ret) -{ - sum_vm_events(ret, &cpu_online_map); -} - -#ifdef CONFIG_HOTPLUG -/* - * Fold the foreign cpu events into our own. - * - * This is adding to the events on one processor - * but keeps the global counts constant. - */ -void vm_events_fold_cpu(int cpu) -{ - struct vm_event_state *fold_state = &per_cpu(vm_event_states, cpu); - int i; - - for (i = 0; i < NR_VM_EVENT_ITEMS; i++) { - count_vm_events(i, fold_state->event[i]); - fold_state->event[i] = 0; - } -} -#endif /* CONFIG_HOTPLUG */ - -#endif /* CONFIG_VM_EVENT_COUNTERS */ - -/* - * Manage combined zone based / global counters - * - * vm_stat contains the global counters - */ -atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS]; -EXPORT_SYMBOL(vm_stat); - -#ifdef CONFIG_SMP - -#define STAT_THRESHOLD 32 - -/* - * Determine pointer to currently valid differential byte given a zone and - * the item number. - * - * Preemption must be off - */ -static inline s8 *diff_pointer(struct zone *zone, enum zone_stat_item item) -{ - return &zone_pcp(zone, smp_processor_id())->vm_stat_diff[item]; -} - -/* - * For use when we know that interrupts are disabled. - */ -void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item, - int delta) -{ - s8 *p; - long x; - - p = diff_pointer(zone, item); - x = delta + *p; - - if (unlikely(x > STAT_THRESHOLD || x < -STAT_THRESHOLD)) { - zone_page_state_add(x, zone, item); - x = 0; - } - - *p = x; -} -EXPORT_SYMBOL(__mod_zone_page_state); - -/* - * For an unknown interrupt state - */ -void mod_zone_page_state(struct zone *zone, enum zone_stat_item item, - int delta) -{ - unsigned long flags; - - local_irq_save(flags); - __mod_zone_page_state(zone, item, delta); - local_irq_restore(flags); -} -EXPORT_SYMBOL(mod_zone_page_state); - -/* - * Optimized increment and decrement functions. - * - * These are only for a single page and therefore can take a struct page * - * argument instead of struct zone *. This allows the inclusion of the code - * generated for page_zone(page) into the optimized functions. - * - * No overflow check is necessary and therefore the differential can be - * incremented or decremented in place which may allow the compilers to - * generate better code. - * - * The increment or decrement is known and therefore one boundary check can - * be omitted. - * - * Some processors have inc/dec instructions that are atomic vs an interrupt. - * However, the code must first determine the differential location in a zone - * based on the processor number and then inc/dec the counter. There is no - * guarantee without disabling preemption that the processor will not change - * in between and therefore the atomicity vs. interrupt cannot be exploited - * in a useful way here. - */ -static void __inc_zone_state(struct zone *zone, enum zone_stat_item item) -{ - s8 *p = diff_pointer(zone, item); - - (*p)++; - - if (unlikely(*p > STAT_THRESHOLD)) { - zone_page_state_add(*p, zone, item); - *p = 0; - } -} - -void __inc_zone_page_state(struct page *page, enum zone_stat_item item) -{ - __inc_zone_state(page_zone(page), item); -} -EXPORT_SYMBOL(__inc_zone_page_state); - -void __dec_zone_page_state(struct page *page, enum zone_stat_item item) -{ - struct zone *zone = page_zone(page); - s8 *p = diff_pointer(zone, item); - - (*p)--; - - if (unlikely(*p < -STAT_THRESHOLD)) { - zone_page_state_add(*p, zone, item); - *p = 0; - } -} -EXPORT_SYMBOL(__dec_zone_page_state); - -void inc_zone_state(struct zone *zone, enum zone_stat_item item) -{ - unsigned long flags; - - local_irq_save(flags); - __inc_zone_state(zone, item); - local_irq_restore(flags); -} - -void inc_zone_page_state(struct page *page, enum zone_stat_item item) -{ - unsigned long flags; - struct zone *zone; - - zone = page_zone(page); - local_irq_save(flags); - __inc_zone_state(zone, item); - local_irq_restore(flags); -} -EXPORT_SYMBOL(inc_zone_page_state); - -void dec_zone_page_state(struct page *page, enum zone_stat_item item) -{ - unsigned long flags; - struct zone *zone; - s8 *p; - - zone = page_zone(page); - local_irq_save(flags); - p = diff_pointer(zone, item); - - (*p)--; - - if (unlikely(*p < -STAT_THRESHOLD)) { - zone_page_state_add(*p, zone, item); - *p = 0; - } - local_irq_restore(flags); -} -EXPORT_SYMBOL(dec_zone_page_state); - -/* - * Update the zone counters for one cpu. - */ -void refresh_cpu_vm_stats(int cpu) -{ - struct zone *zone; - int i; - unsigned long flags; - - for_each_zone(zone) { - struct per_cpu_pageset *pcp; - - pcp = zone_pcp(zone, cpu); - - for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) - if (pcp->vm_stat_diff[i]) { - local_irq_save(flags); - zone_page_state_add(pcp->vm_stat_diff[i], - zone, i); - pcp->vm_stat_diff[i] = 0; - local_irq_restore(flags); - } - } -} - -static void __refresh_cpu_vm_stats(void *dummy) -{ - refresh_cpu_vm_stats(smp_processor_id()); -} - -/* - * Consolidate all counters. - * - * Note that the result is less inaccurate but still inaccurate - * if concurrent processes are allowed to run. - */ -void refresh_vm_stats(void) -{ - on_each_cpu(__refresh_cpu_vm_stats, NULL, 0, 1); -} -EXPORT_SYMBOL(refresh_vm_stats); - -#endif - -#ifdef CONFIG_NUMA -/* - * zonelist = the list of zones passed to the allocator - * z = the zone from which the allocation occurred. - * - * Must be called with interrupts disabled. - */ -void zone_statistics(struct zonelist *zonelist, struct zone *z) -{ - if (z->zone_pgdat == zonelist->zones[0]->zone_pgdat) { - __inc_zone_state(z, NUMA_HIT); - } else { - __inc_zone_state(z, NUMA_MISS); - __inc_zone_state(zonelist->zones[0], NUMA_FOREIGN); - } - if (z->zone_pgdat == NODE_DATA(numa_node_id())) - __inc_zone_state(z, NUMA_LOCAL); - else - __inc_zone_state(z, NUMA_OTHER); -} -#endif - -#ifdef CONFIG_PROC_FS - -#include - -static void *frag_start(struct seq_file *m, loff_t *pos) -{ - pg_data_t *pgdat; - loff_t node = *pos; - for (pgdat = first_online_pgdat(); - pgdat && node; - pgdat = next_online_pgdat(pgdat)) - --node; - - return pgdat; -} - -static void *frag_next(struct seq_file *m, void *arg, loff_t *pos) -{ - pg_data_t *pgdat = (pg_data_t *)arg; - - (*pos)++; - return next_online_pgdat(pgdat); -} - -static void frag_stop(struct seq_file *m, void *arg) -{ -} - -/* - * This walks the free areas for each zone. - */ -static int frag_show(struct seq_file *m, void *arg) -{ - pg_data_t *pgdat = (pg_data_t *)arg; - struct zone *zone; - struct zone *node_zones = pgdat->node_zones; - unsigned long flags; - int order; - - for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) { - if (!populated_zone(zone)) - continue; - - spin_lock_irqsave(&zone->lock, flags); - seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name); - for (order = 0; order < MAX_ORDER; ++order) - seq_printf(m, "%6lu ", zone->free_area[order].nr_free); - spin_unlock_irqrestore(&zone->lock, flags); - seq_putc(m, '\n'); - } - return 0; -} - -struct seq_operations fragmentation_op = { - .start = frag_start, - .next = frag_next, - .stop = frag_stop, - .show = frag_show, -}; - -static char *vmstat_text[] = { - /* Zoned VM counters */ - "nr_anon_pages", - "nr_mapped", - "nr_file_pages", - "nr_slab", - "nr_page_table_pages", - "nr_dirty", - "nr_writeback", - "nr_unstable", - "nr_bounce", - -#ifdef CONFIG_NUMA - "numa_hit", - "numa_miss", - "numa_foreign", - "numa_interleave", - "numa_local", - "numa_other", -#endif - -#ifdef CONFIG_VM_EVENT_COUNTERS - "pgpgin", - "pgpgout", - "pswpin", - "pswpout", - - "pgalloc_dma", - "pgalloc_dma32", - "pgalloc_normal", - "pgalloc_high", - - "pgfree", - "pgactivate", - "pgdeactivate", - - "pgfault", - "pgmajfault", - - "pgrefill_dma", - "pgrefill_dma32", - "pgrefill_normal", - "pgrefill_high", - - "pgsteal_dma", - "pgsteal_dma32", - "pgsteal_normal", - "pgsteal_high", - - "pgscan_kswapd_dma", - "pgscan_kswapd_dma32", - "pgscan_kswapd_normal", - "pgscan_kswapd_high", - - "pgscan_direct_dma", - "pgscan_direct_dma32", - "pgscan_direct_normal", - "pgscan_direct_high", - - "pginodesteal", - "slabs_scanned", - "kswapd_steal", - "kswapd_inodesteal", - "pageoutrun", - "allocstall", - - "pgrotated", -#endif -}; - -/* - * Output information about zones in @pgdat. - */ -static int zoneinfo_show(struct seq_file *m, void *arg) -{ - pg_data_t *pgdat = arg; - struct zone *zone; - struct zone *node_zones = pgdat->node_zones; - unsigned long flags; - - for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) { - int i; - - if (!populated_zone(zone)) - continue; - - spin_lock_irqsave(&zone->lock, flags); - seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name); - seq_printf(m, - "\n pages free %lu" - "\n min %lu" - "\n low %lu" - "\n high %lu" - "\n active %lu" - "\n inactive %lu" - "\n scanned %lu (a: %lu i: %lu)" - "\n spanned %lu" - "\n present %lu", - zone->free_pages, - zone->pages_min, - zone->pages_low, - zone->pages_high, - zone->nr_active, - zone->nr_inactive, - zone->pages_scanned, - zone->nr_scan_active, zone->nr_scan_inactive, - zone->spanned_pages, - zone->present_pages); - - for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) - seq_printf(m, "\n %-12s %lu", vmstat_text[i], - zone_page_state(zone, i)); - - seq_printf(m, - "\n protection: (%lu", - zone->lowmem_reserve[0]); - for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++) - seq_printf(m, ", %lu", zone->lowmem_reserve[i]); - seq_printf(m, - ")" - "\n pagesets"); - for_each_online_cpu(i) { - struct per_cpu_pageset *pageset; - int j; - - pageset = zone_pcp(zone, i); - for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) { - if (pageset->pcp[j].count) - break; - } - if (j == ARRAY_SIZE(pageset->pcp)) - continue; - for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) { - seq_printf(m, - "\n cpu: %i pcp: %i" - "\n count: %i" - "\n high: %i" - "\n batch: %i", - i, j, - pageset->pcp[j].count, - pageset->pcp[j].high, - pageset->pcp[j].batch); - } - } - seq_printf(m, - "\n all_unreclaimable: %u" - "\n prev_priority: %i" - "\n temp_priority: %i" - "\n start_pfn: %lu", - zone->all_unreclaimable, - zone->prev_priority, - zone->temp_priority, - zone->zone_start_pfn); - spin_unlock_irqrestore(&zone->lock, flags); - seq_putc(m, '\n'); - } - return 0; -} - -struct seq_operations zoneinfo_op = { - .start = frag_start, /* iterate over all zones. The same as in - * fragmentation. */ - .next = frag_next, - .stop = frag_stop, - .show = zoneinfo_show, -}; - -static void *vmstat_start(struct seq_file *m, loff_t *pos) -{ - unsigned long *v; -#ifdef CONFIG_VM_EVENT_COUNTERS - unsigned long *e; -#endif - int i; - - if (*pos >= ARRAY_SIZE(vmstat_text)) - return NULL; - -#ifdef CONFIG_VM_EVENT_COUNTERS - v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) - + sizeof(struct vm_event_state), GFP_KERNEL); -#else - v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long), - GFP_KERNEL); -#endif - m->private = v; - if (!v) - return ERR_PTR(-ENOMEM); - for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) - v[i] = global_page_state(i); -#ifdef CONFIG_VM_EVENT_COUNTERS - e = v + NR_VM_ZONE_STAT_ITEMS; - all_vm_events(e); - e[PGPGIN] /= 2; /* sectors -> kbytes */ - e[PGPGOUT] /= 2; -#endif - return v + *pos; -} - -static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos) -{ - (*pos)++; - if (*pos >= ARRAY_SIZE(vmstat_text)) - return NULL; - return (unsigned long *)m->private + *pos; -} - -static int vmstat_show(struct seq_file *m, void *arg) -{ - unsigned long *l = arg; - unsigned long off = l - (unsigned long *)m->private; - - seq_printf(m, "%s %lu\n", vmstat_text[off], *l); - return 0; -} - -static void vmstat_stop(struct seq_file *m, void *arg) -{ - kfree(m->private); - m->private = NULL; -} - -struct seq_operations vmstat_op = { - .start = vmstat_start, - .next = vmstat_next, - .stop = vmstat_stop, - .show = vmstat_show, -}; - -#endif /* CONFIG_PROC_FS */ - diff --git a/trunk/net/802/fc.c b/trunk/net/802/fc.c index 2a27e37bc4cb..282c4ab1abe6 100644 --- a/trunk/net/802/fc.c +++ b/trunk/net/802/fc.c @@ -10,6 +10,7 @@ * v 1.0 03/22/99 */ +#include #include #include #include diff --git a/trunk/net/802/fddi.c b/trunk/net/802/fddi.c index 797c6d961deb..ac242a4bc346 100644 --- a/trunk/net/802/fddi.c +++ b/trunk/net/802/fddi.c @@ -26,6 +26,7 @@ * Maciej W. Rozycki : IPv6 support */ +#include #include #include #include diff --git a/trunk/net/802/sysctl_net_802.c b/trunk/net/802/sysctl_net_802.c index ead56037398b..700129556c13 100644 --- a/trunk/net/802/sysctl_net_802.c +++ b/trunk/net/802/sysctl_net_802.c @@ -10,6 +10,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/802/tr.c b/trunk/net/802/tr.c index d7d8f40c4fed..e9dc803f2fe0 100644 --- a/trunk/net/802/tr.c +++ b/trunk/net/802/tr.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include diff --git a/trunk/net/8021q/vlanproc.c b/trunk/net/8021q/vlanproc.c index a8fc0de1f969..7b214cffc956 100644 --- a/trunk/net/8021q/vlanproc.c +++ b/trunk/net/8021q/vlanproc.c @@ -17,6 +17,7 @@ * Jan 20, 1998 Ben Greear Initial Version *****************************************************************************/ +#include #include #include /* offsetof(), etc. */ #include /* return codes */ diff --git a/trunk/net/appletalk/aarp.c b/trunk/net/appletalk/aarp.c index f3777ec5bcb9..7076097debc2 100644 --- a/trunk/net/appletalk/aarp.c +++ b/trunk/net/appletalk/aarp.c @@ -29,6 +29,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/appletalk/atalk_proc.c b/trunk/net/appletalk/atalk_proc.c index 7ae4916cd26d..dc4048dd98c1 100644 --- a/trunk/net/appletalk/atalk_proc.c +++ b/trunk/net/appletalk/atalk_proc.c @@ -8,6 +8,7 @@ * Free Software Foundation, version 2. */ +#include #include #include #include diff --git a/trunk/net/appletalk/ddp.c b/trunk/net/appletalk/ddp.c index 5ee96d4b40e9..7b1eb9a4fc96 100644 --- a/trunk/net/appletalk/ddp.c +++ b/trunk/net/appletalk/ddp.c @@ -51,6 +51,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/appletalk/sysctl_net_atalk.c b/trunk/net/appletalk/sysctl_net_atalk.c index 40b0af7437a2..af7f0604395d 100644 --- a/trunk/net/appletalk/sysctl_net_atalk.c +++ b/trunk/net/appletalk/sysctl_net_atalk.c @@ -6,6 +6,7 @@ * Dynamic registration, added aarp entries. (5/30/97 Chris Horn) */ +#include #include #include #include diff --git a/trunk/net/atm/Makefile b/trunk/net/atm/Makefile index 89656d6c0b90..d5818751f6ba 100644 --- a/trunk/net/atm/Makefile +++ b/trunk/net/atm/Makefile @@ -2,7 +2,7 @@ # Makefile for the ATM Protocol Families. # -atm-y := addr.o pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o atm_sysfs.o +atm-y := addr.o pvc.o signaling.o svc.o ioctl.o common.o atm_misc.o raw.o resources.o mpoa-objs := mpc.o mpoa_caches.o mpoa_proc.o obj-$(CONFIG_ATM) += atm.o diff --git a/trunk/net/atm/atm_sysfs.c b/trunk/net/atm/atm_sysfs.c deleted file mode 100644 index 5df4b9a068bb..000000000000 --- a/trunk/net/atm/atm_sysfs.c +++ /dev/null @@ -1,176 +0,0 @@ -/* ATM driver model support. */ - -#include -#include -#include -#include -#include -#include "common.h" -#include "resources.h" - -#define to_atm_dev(cldev) container_of(cldev, struct atm_dev, class_dev) - -static ssize_t show_type(struct class_device *cdev, char *buf) -{ - struct atm_dev *adev = to_atm_dev(cdev); - return sprintf(buf, "%s\n", adev->type); -} - -static ssize_t show_address(struct class_device *cdev, char *buf) -{ - char *pos = buf; - struct atm_dev *adev = to_atm_dev(cdev); - int i; - - for (i = 0; i < (ESI_LEN - 1); i++) - pos += sprintf(pos, "%02x:", adev->esi[i]); - pos += sprintf(pos, "%02x\n", adev->esi[i]); - - return pos - buf; -} - -static ssize_t show_atmaddress(struct class_device *cdev, char *buf) -{ - unsigned long flags; - char *pos = buf; - struct atm_dev *adev = to_atm_dev(cdev); - struct atm_dev_addr *aaddr; - int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin; - int i, j; - - spin_lock_irqsave(&adev->lock, flags); - list_for_each_entry(aaddr, &adev->local, entry) { - for(i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) { - if (j == *fmt) { - pos += sprintf(pos, "."); - ++fmt; - j = 0; - } - pos += sprintf(pos, "%02x", aaddr->addr.sas_addr.prv[i]); - } - pos += sprintf(pos, "\n"); - } - spin_unlock_irqrestore(&adev->lock, flags); - - return pos - buf; -} - -static ssize_t show_carrier(struct class_device *cdev, char *buf) -{ - char *pos = buf; - struct atm_dev *adev = to_atm_dev(cdev); - - pos += sprintf(pos, "%d\n", - adev->signal == ATM_PHY_SIG_LOST ? 0 : 1); - - return pos - buf; -} - -static ssize_t show_link_rate(struct class_device *cdev, char *buf) -{ - char *pos = buf; - struct atm_dev *adev = to_atm_dev(cdev); - int link_rate; - - /* show the link rate, not the data rate */ - switch (adev->link_rate) { - case ATM_OC3_PCR: - link_rate = 155520000; - break; - case ATM_OC12_PCR: - link_rate = 622080000; - break; - case ATM_25_PCR: - link_rate = 25600000; - break; - default: - link_rate = adev->link_rate * 8 * 53; - } - pos += sprintf(pos, "%d\n", link_rate); - - return pos - buf; -} - -static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL); -static CLASS_DEVICE_ATTR(atmaddress, S_IRUGO, show_atmaddress, NULL); -static CLASS_DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL); -static CLASS_DEVICE_ATTR(type, S_IRUGO, show_type, NULL); -static CLASS_DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL); - -static struct class_device_attribute *atm_attrs[] = { - &class_device_attr_atmaddress, - &class_device_attr_address, - &class_device_attr_carrier, - &class_device_attr_type, - &class_device_attr_link_rate, - NULL -}; - -static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size) -{ - struct atm_dev *adev; - int i = 0, len = 0; - - if (!cdev) - return -ENODEV; - - adev = to_atm_dev(cdev); - if (!adev) - return -ENODEV; - - if (add_uevent_var(envp, num_envp, &i, buf, size, &len, - "NAME=%s%d", adev->type, adev->number)) - return -ENOMEM; - - envp[i] = NULL; - return 0; -} - -static void atm_release(struct class_device *cdev) -{ - struct atm_dev *adev = to_atm_dev(cdev); - - kfree(adev); -} - -static struct class atm_class = { - .name = "atm", - .release = atm_release, - .uevent = atm_uevent, -}; - -int atm_register_sysfs(struct atm_dev *adev) -{ - struct class_device *cdev = &adev->class_dev; - int i, err; - - cdev->class = &atm_class; - class_set_devdata(cdev, adev); - - snprintf(cdev->class_id, BUS_ID_SIZE, "%s%d", adev->type, adev->number); - err = class_device_register(cdev); - if (err < 0) - return err; - - for (i = 0; atm_attrs[i]; i++) - class_device_create_file(cdev, atm_attrs[i]); - - return 0; -} - -void atm_unregister_sysfs(struct atm_dev *adev) -{ - struct class_device *cdev = &adev->class_dev; - - class_device_del(cdev); -} - -int __init atm_sysfs_init(void) -{ - return class_register(&atm_class); -} - -void __exit atm_sysfs_exit(void) -{ - class_unregister(&atm_class); -} diff --git a/trunk/net/atm/br2684.c b/trunk/net/atm/br2684.c index a487233dc466..680ccb12aae8 100644 --- a/trunk/net/atm/br2684.c +++ b/trunk/net/atm/br2684.c @@ -5,6 +5,7 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary */ #include +#include #include #include #include diff --git a/trunk/net/atm/clip.c b/trunk/net/atm/clip.c index 87a454f5c89c..f92f9c94d2c7 100644 --- a/trunk/net/atm/clip.c +++ b/trunk/net/atm/clip.c @@ -2,6 +2,7 @@ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ +#include #include #include #include /* for UINT_MAX */ diff --git a/trunk/net/atm/common.c b/trunk/net/atm/common.c index fbabff494468..ae002220fa99 100644 --- a/trunk/net/atm/common.c +++ b/trunk/net/atm/common.c @@ -3,6 +3,7 @@ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ +#include #include #include #include /* struct socket, struct proto_ops */ @@ -790,14 +791,8 @@ static int __init atm_init(void) printk(KERN_ERR "atm_proc_init() failed with %d\n",error); goto out_atmsvc_exit; } - if ((error = atm_sysfs_init()) < 0) { - printk(KERN_ERR "atm_sysfs_init() failed with %d\n",error); - goto out_atmproc_exit; - } out: return error; -out_atmproc_exit: - atm_proc_exit(); out_atmsvc_exit: atmsvc_exit(); out_atmpvc_exit: @@ -810,7 +805,6 @@ static int __init atm_init(void) static void __exit atm_exit(void) { atm_proc_exit(); - atm_sysfs_exit(); atmsvc_exit(); atmpvc_exit(); proto_unregister(&vcc_proto); diff --git a/trunk/net/atm/common.h b/trunk/net/atm/common.h index a422da7788fb..4887c317cefe 100644 --- a/trunk/net/atm/common.h +++ b/trunk/net/atm/common.h @@ -28,8 +28,6 @@ int atmpvc_init(void); void atmpvc_exit(void); int atmsvc_init(void); void atmsvc_exit(void); -int atm_sysfs_init(void); -void atm_sysfs_exit(void); #ifdef CONFIG_PROC_FS int atm_proc_init(void); diff --git a/trunk/net/atm/ioctl.c b/trunk/net/atm/ioctl.c index 8c2022c3e81d..851cfa6312af 100644 --- a/trunk/net/atm/ioctl.c +++ b/trunk/net/atm/ioctl.c @@ -4,6 +4,7 @@ /* 2003 John Levon */ +#include #include #include #include /* struct socket, struct proto_ops */ diff --git a/trunk/net/atm/lec.c b/trunk/net/atm/lec.c index 4b68a18171cf..c4fc722fef9a 100644 --- a/trunk/net/atm/lec.c +++ b/trunk/net/atm/lec.c @@ -4,6 +4,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/atm/lec.h b/trunk/net/atm/lec.h index c22a8bfa1f81..6606082b29a8 100644 --- a/trunk/net/atm/lec.h +++ b/trunk/net/atm/lec.h @@ -9,6 +9,7 @@ #ifndef _LEC_H_ #define _LEC_H_ +#include #include #include #include diff --git a/trunk/net/atm/mpc.c b/trunk/net/atm/mpc.c index 9aafe1e2f048..a48a5d580408 100644 --- a/trunk/net/atm/mpc.c +++ b/trunk/net/atm/mpc.c @@ -25,6 +25,7 @@ #include #include /* Modular too */ +#include #include #include "lec.h" @@ -1112,9 +1113,10 @@ static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_clien static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc) { + unsigned char *ip; + uint32_t dst_ip = msg->content.in_info.in_dst_ip; in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc); - dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(dst_ip)); ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry); if(entry == NULL){ diff --git a/trunk/net/atm/mpoa_proc.c b/trunk/net/atm/mpoa_proc.c index d37b8911b3ab..60834b5a14d6 100644 --- a/trunk/net/atm/mpoa_proc.c +++ b/trunk/net/atm/mpoa_proc.c @@ -1,3 +1,4 @@ +#include #ifdef CONFIG_PROC_FS #include diff --git a/trunk/net/atm/pppoatm.c b/trunk/net/atm/pppoatm.c index 76a7d8ff6c0e..1489067c1e84 100644 --- a/trunk/net/atm/pppoatm.c +++ b/trunk/net/atm/pppoatm.c @@ -34,6 +34,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/atm/proc.c b/trunk/net/atm/proc.c index 3f95b0886a6a..4041054e5282 100644 --- a/trunk/net/atm/proc.c +++ b/trunk/net/atm/proc.c @@ -8,6 +8,7 @@ * the reader. */ +#include #include /* for EXPORT_SYMBOL */ #include #include diff --git a/trunk/net/atm/pvc.c b/trunk/net/atm/pvc.c index b2148b43a426..f2c541774dcd 100644 --- a/trunk/net/atm/pvc.c +++ b/trunk/net/atm/pvc.c @@ -3,6 +3,7 @@ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ +#include #include /* struct socket, struct proto_ops */ #include /* ATM stuff */ #include /* ATM devices */ diff --git a/trunk/net/atm/resources.c b/trunk/net/atm/resources.c index de25c6408b04..18ac80698f83 100644 --- a/trunk/net/atm/resources.c +++ b/trunk/net/atm/resources.c @@ -8,6 +8,7 @@ * use the default destruct function initialized by sock_init_data */ +#include #include #include #include @@ -113,27 +114,14 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops, printk(KERN_ERR "atm_dev_register: " "atm_proc_dev_register failed for dev %s\n", type); - goto out_fail; - } - - if (atm_register_sysfs(dev) < 0) { - printk(KERN_ERR "atm_dev_register: " - "atm_register_sysfs failed for dev %s\n", - type); - atm_proc_dev_deregister(dev); - goto out_fail; + mutex_unlock(&atm_dev_mutex); + kfree(dev); + return NULL; } - list_add_tail(&dev->dev_list, &atm_devs); - -out: mutex_unlock(&atm_dev_mutex); - return dev; -out_fail: - kfree(dev); - dev = NULL; - goto out; + return dev; } @@ -152,7 +140,6 @@ void atm_dev_deregister(struct atm_dev *dev) mutex_unlock(&atm_dev_mutex); atm_dev_release_vccs(dev); - atm_unregister_sysfs(dev); atm_proc_dev_deregister(dev); atm_dev_put(dev); diff --git a/trunk/net/atm/resources.h b/trunk/net/atm/resources.h index 1d004aaaeec1..ac7222fee7a8 100644 --- a/trunk/net/atm/resources.h +++ b/trunk/net/atm/resources.h @@ -6,6 +6,7 @@ #ifndef NET_ATM_RESOURCES_H #define NET_ATM_RESOURCES_H +#include #include #include @@ -42,6 +43,4 @@ static inline void atm_proc_dev_deregister(struct atm_dev *dev) #endif /* CONFIG_PROC_FS */ -int atm_register_sysfs(struct atm_dev *adev); -void atm_unregister_sysfs(struct atm_dev *adev); #endif diff --git a/trunk/net/ax25/af_ax25.c b/trunk/net/ax25/af_ax25.c index 10a3c0aa8398..a2e0dd047e9f 100644 --- a/trunk/net/ax25/af_ax25.c +++ b/trunk/net/ax25/af_ax25.c @@ -13,6 +13,7 @@ * Copyright (C) Hans Alblas PE1AYX (hans@esrac.ele.tue.nl) * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr) */ +#include #include #include #include diff --git a/trunk/net/ax25/ax25_dev.c b/trunk/net/ax25/ax25_dev.c index 47e6e790bd67..dab77efe34a6 100644 --- a/trunk/net/ax25/ax25_dev.c +++ b/trunk/net/ax25/ax25_dev.c @@ -6,6 +6,7 @@ * * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) */ +#include #include #include #include diff --git a/trunk/net/ax25/ax25_iface.c b/trunk/net/ax25/ax25_iface.c index 77ba07c67682..3bb152710b77 100644 --- a/trunk/net/ax25/ax25_iface.c +++ b/trunk/net/ax25/ax25_iface.c @@ -6,6 +6,7 @@ * * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) */ +#include #include #include #include diff --git a/trunk/net/ax25/ax25_ip.c b/trunk/net/ax25/ax25_ip.c index 9be5c15e63d3..a0b534f80f17 100644 --- a/trunk/net/ax25/ax25_ip.c +++ b/trunk/net/ax25/ax25_ip.c @@ -6,6 +6,7 @@ * * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) */ +#include #include #include #include diff --git a/trunk/net/ax25/ax25_out.c b/trunk/net/ax25/ax25_out.c index d7736e585336..5d99852b239c 100644 --- a/trunk/net/ax25/ax25_out.c +++ b/trunk/net/ax25/ax25_out.c @@ -8,6 +8,7 @@ * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) * Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de) */ +#include #include #include #include diff --git a/trunk/net/ax25/ax25_timer.c b/trunk/net/ax25/ax25_timer.c index 72594867fab6..ec254057f212 100644 --- a/trunk/net/ax25/ax25_timer.c +++ b/trunk/net/ax25/ax25_timer.c @@ -12,6 +12,7 @@ * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr) * Copyright (C) 2002 Ralf Baechle DO1GRB (ralf@gnu.org) */ +#include #include #include #include diff --git a/trunk/net/ax25/sysctl_net_ax25.c b/trunk/net/ax25/sysctl_net_ax25.c index 369a75b160f2..bdb64c36df12 100644 --- a/trunk/net/ax25/sysctl_net_ax25.c +++ b/trunk/net/ax25/sysctl_net_ax25.c @@ -6,6 +6,7 @@ * * Copyright (C) 1996 Mike Shaver (shaver@zeroknowledge.com) */ +#include #include #include #include diff --git a/trunk/net/bluetooth/af_bluetooth.c b/trunk/net/bluetooth/af_bluetooth.c index 51f867062e1d..469eda0f0dfd 100644 --- a/trunk/net/bluetooth/af_bluetooth.c +++ b/trunk/net/bluetooth/af_bluetooth.c @@ -24,6 +24,7 @@ /* Bluetooth address family and sockets. */ +#include #include #include diff --git a/trunk/net/bluetooth/bnep/core.c b/trunk/net/bluetooth/bnep/core.c index e620061fb50f..d908d49dc9f8 100644 --- a/trunk/net/bluetooth/bnep/core.c +++ b/trunk/net/bluetooth/bnep/core.c @@ -29,6 +29,7 @@ * $Id: core.c,v 1.20 2002/08/04 21:23:58 maxk Exp $ */ +#include #include #include diff --git a/trunk/net/bluetooth/bnep/netdev.c b/trunk/net/bluetooth/bnep/netdev.c index 7f7b27db6a8f..921204f95f4a 100644 --- a/trunk/net/bluetooth/bnep/netdev.c +++ b/trunk/net/bluetooth/bnep/netdev.c @@ -29,6 +29,7 @@ * $Id: netdev.c,v 1.8 2002/08/04 21:23:58 maxk Exp $ */ +#include #include #include diff --git a/trunk/net/bluetooth/bnep/sock.c b/trunk/net/bluetooth/bnep/sock.c index 28c55835422a..2bfe796cf05d 100644 --- a/trunk/net/bluetooth/bnep/sock.c +++ b/trunk/net/bluetooth/bnep/sock.c @@ -28,6 +28,7 @@ * $Id: sock.c,v 1.4 2002/08/04 21:23:58 maxk Exp $ */ +#include #include #include diff --git a/trunk/net/bluetooth/cmtp/capi.c b/trunk/net/bluetooth/cmtp/capi.c index 6fb47e00e188..b2e7e38531c6 100644 --- a/trunk/net/bluetooth/cmtp/capi.c +++ b/trunk/net/bluetooth/cmtp/capi.c @@ -20,6 +20,7 @@ SOFTWARE IS DISCLAIMED. */ +#include #include #include diff --git a/trunk/net/bluetooth/cmtp/core.c b/trunk/net/bluetooth/cmtp/core.c index 182254a580e2..901eff7ebe74 100644 --- a/trunk/net/bluetooth/cmtp/core.c +++ b/trunk/net/bluetooth/cmtp/core.c @@ -20,6 +20,7 @@ SOFTWARE IS DISCLAIMED. */ +#include #include #include diff --git a/trunk/net/bluetooth/cmtp/sock.c b/trunk/net/bluetooth/cmtp/sock.c index 10ad7fd91d83..8f8fad23f78a 100644 --- a/trunk/net/bluetooth/cmtp/sock.c +++ b/trunk/net/bluetooth/cmtp/sock.c @@ -20,6 +20,7 @@ SOFTWARE IS DISCLAIMED. */ +#include #include #include diff --git a/trunk/net/bluetooth/hci_conn.c b/trunk/net/bluetooth/hci_conn.c index 5c0c2b1ef34a..f812ed129e58 100644 --- a/trunk/net/bluetooth/hci_conn.c +++ b/trunk/net/bluetooth/hci_conn.c @@ -24,6 +24,7 @@ /* Bluetooth HCI connection handling. */ +#include #include #include diff --git a/trunk/net/bluetooth/hci_core.c b/trunk/net/bluetooth/hci_core.c index f67240beb0dd..a49a6975092d 100644 --- a/trunk/net/bluetooth/hci_core.c +++ b/trunk/net/bluetooth/hci_core.c @@ -24,6 +24,7 @@ /* Bluetooth HCI core. */ +#include #include #include diff --git a/trunk/net/bluetooth/hci_event.c b/trunk/net/bluetooth/hci_event.c index 618bacee1b1c..eb64555d1fb3 100644 --- a/trunk/net/bluetooth/hci_event.c +++ b/trunk/net/bluetooth/hci_event.c @@ -24,6 +24,7 @@ /* Bluetooth HCI event handling. */ +#include #include #include diff --git a/trunk/net/bluetooth/hci_sock.c b/trunk/net/bluetooth/hci_sock.c index 1a35d343e08a..97bdec73d17e 100644 --- a/trunk/net/bluetooth/hci_sock.c +++ b/trunk/net/bluetooth/hci_sock.c @@ -24,6 +24,7 @@ /* Bluetooth HCI sockets. */ +#include #include #include diff --git a/trunk/net/bluetooth/hci_sysfs.c b/trunk/net/bluetooth/hci_sysfs.c index 19b234c86f33..0ed38740388c 100644 --- a/trunk/net/bluetooth/hci_sysfs.c +++ b/trunk/net/bluetooth/hci_sysfs.c @@ -1,5 +1,6 @@ /* Bluetooth HCI driver model support. */ +#include #include #include diff --git a/trunk/net/bluetooth/hidp/core.c b/trunk/net/bluetooth/hidp/core.c index b9c24a55425c..cdb9cfafd960 100644 --- a/trunk/net/bluetooth/hidp/core.c +++ b/trunk/net/bluetooth/hidp/core.c @@ -20,6 +20,7 @@ SOFTWARE IS DISCLAIMED. */ +#include #include #include diff --git a/trunk/net/bluetooth/hidp/sock.c b/trunk/net/bluetooth/hidp/sock.c index 099646e4e2ef..b8f67761b886 100644 --- a/trunk/net/bluetooth/hidp/sock.c +++ b/trunk/net/bluetooth/hidp/sock.c @@ -20,6 +20,7 @@ SOFTWARE IS DISCLAIMED. */ +#include #include #include diff --git a/trunk/net/bluetooth/l2cap.c b/trunk/net/bluetooth/l2cap.c index 770101177da1..f6b4a8085357 100644 --- a/trunk/net/bluetooth/l2cap.c +++ b/trunk/net/bluetooth/l2cap.c @@ -24,6 +24,7 @@ /* Bluetooth L2CAP core and sockets. */ +#include #include #include diff --git a/trunk/net/bluetooth/lib.c b/trunk/net/bluetooth/lib.c index e5fd0cb70ae9..ee6a66979913 100644 --- a/trunk/net/bluetooth/lib.c +++ b/trunk/net/bluetooth/lib.c @@ -24,6 +24,7 @@ /* Bluetooth kernel library. */ +#include #include #include diff --git a/trunk/net/bluetooth/rfcomm/core.c b/trunk/net/bluetooth/rfcomm/core.c index bd46e8927f29..e99010ce8bb2 100644 --- a/trunk/net/bluetooth/rfcomm/core.c +++ b/trunk/net/bluetooth/rfcomm/core.c @@ -27,6 +27,7 @@ * $Id: core.c,v 1.42 2002/10/01 23:26:25 maxk Exp $ */ +#include #include #include #include diff --git a/trunk/net/bluetooth/rfcomm/sock.c b/trunk/net/bluetooth/rfcomm/sock.c index 4e9962c8cfa6..757d2dd3b02f 100644 --- a/trunk/net/bluetooth/rfcomm/sock.c +++ b/trunk/net/bluetooth/rfcomm/sock.c @@ -27,6 +27,7 @@ * $Id: sock.c,v 1.24 2002/10/03 01:00:34 maxk Exp $ */ +#include #include #include diff --git a/trunk/net/bluetooth/rfcomm/tty.c b/trunk/net/bluetooth/rfcomm/tty.c index 2ff2d5b87c93..74368f79ee5d 100644 --- a/trunk/net/bluetooth/rfcomm/tty.c +++ b/trunk/net/bluetooth/rfcomm/tty.c @@ -27,6 +27,7 @@ * $Id: tty.c,v 1.24 2002/10/03 01:54:38 holtmann Exp $ */ +#include #include #include @@ -479,8 +480,12 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb) BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len); - tty_insert_flip_string(tty, skb->data, skb->len); - tty_flip_buffer_push(tty); + if (test_bit(TTY_DONT_FLIP, &tty->flags)) { + tty_buffer_request_room(tty, skb->len); + tty_insert_flip_string(tty, skb->data, skb->len); + tty_flip_buffer_push(tty); + } else + tty->ldisc.receive_buf(tty, skb->data, NULL, skb->len); kfree_skb(skb); } @@ -1020,12 +1025,13 @@ int rfcomm_init_ttys(void) rfcomm_tty_driver->owner = THIS_MODULE; rfcomm_tty_driver->driver_name = "rfcomm"; + rfcomm_tty_driver->devfs_name = "bluetooth/rfcomm/"; rfcomm_tty_driver->name = "rfcomm"; rfcomm_tty_driver->major = RFCOMM_TTY_MAJOR; rfcomm_tty_driver->minor_start = RFCOMM_TTY_MINOR; rfcomm_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL; - rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; rfcomm_tty_driver->init_termios = tty_std_termios; rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; tty_set_operations(rfcomm_tty_driver, &rfcomm_ops); diff --git a/trunk/net/bluetooth/sco.c b/trunk/net/bluetooth/sco.c index a5f1e44db5d3..0c2d13ad69bb 100644 --- a/trunk/net/bluetooth/sco.c +++ b/trunk/net/bluetooth/sco.c @@ -24,6 +24,7 @@ /* Bluetooth SCO sockets. */ +#include #include #include diff --git a/trunk/net/bridge/br.c b/trunk/net/bridge/br.c index 2994387999a8..654401ceb2db 100644 --- a/trunk/net/bridge/br.c +++ b/trunk/net/bridge/br.c @@ -13,6 +13,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/bridge/br_device.c b/trunk/net/bridge/br_device.c index f8dbcee80eba..2afdc7c0736c 100644 --- a/trunk/net/bridge/br_device.c +++ b/trunk/net/bridge/br_device.c @@ -184,6 +184,6 @@ void br_dev_setup(struct net_device *dev) dev->set_mac_address = br_set_mac_address; dev->priv_flags = IFF_EBRIDGE; - dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | - NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST; + dev->features = NETIF_F_SG | NETIF_F_FRAGLIST + | NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_NO_CSUM; } diff --git a/trunk/net/bridge/br_if.c b/trunk/net/bridge/br_if.c index f55ef682ef84..07956ecf545e 100644 --- a/trunk/net/bridge/br_if.c +++ b/trunk/net/bridge/br_if.c @@ -392,8 +392,7 @@ void br_features_recompute(struct net_bridge *br) features &= feature; } - br->dev->features = features | checksum | NETIF_F_LLTX | - NETIF_F_GSO_ROBUST; + br->dev->features = features | checksum | NETIF_F_LLTX; } /* called with RTNL */ diff --git a/trunk/net/bridge/netfilter/ebt_ulog.c b/trunk/net/bridge/netfilter/ebt_ulog.c index 02693a230dc1..ee5a51761260 100644 --- a/trunk/net/bridge/netfilter/ebt_ulog.c +++ b/trunk/net/bridge/netfilter/ebt_ulog.c @@ -29,6 +29,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 066a60a75280..ea2469398bd5 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -76,6 +76,7 @@ #include #include #include +#include #include #include #include @@ -229,7 +230,7 @@ extern void netdev_unregister_sysfs(struct net_device *); * For efficiency */ -static int netdev_nit; +int netdev_nit; /* * Add a protocol ID to the list. Now that the input handler is @@ -1189,14 +1190,11 @@ int skb_checksum_help(struct sk_buff *skb, int inward) /** * skb_gso_segment - Perform segmentation on skb. * @skb: buffer to segment - * @features: features for the output path (see dev->features) + * @sg: whether scatter-gather is supported on the target. * * This function segments the given skb and returns a list of segments. - * - * It may return NULL if the skb requires no segmentation. This is - * only possible when GSO is used for verifying header integrity. */ -struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) +struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg) { struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT); struct packet_type *ptype; @@ -1212,14 +1210,12 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) rcu_read_lock(); list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) { if (ptype->type == type && !ptype->dev && ptype->gso_segment) { - segs = ptype->gso_segment(skb, features); + segs = ptype->gso_segment(skb, sg); break; } } rcu_read_unlock(); - __skb_push(skb, skb->data - skb->mac.raw); - return segs; } @@ -1238,6 +1234,7 @@ void netdev_rx_csum_fault(struct net_device *dev) EXPORT_SYMBOL(netdev_rx_csum_fault); #endif +#ifdef CONFIG_HIGHMEM /* Actually, we should eliminate this check as soon as we know, that: * 1. IOMMU is present and allows to map all the memory. * 2. No high memory really exists on this machine. @@ -1245,7 +1242,6 @@ EXPORT_SYMBOL(netdev_rx_csum_fault); static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb) { -#ifdef CONFIG_HIGHMEM int i; if (dev->features & NETIF_F_HIGHDMA) @@ -1255,9 +1251,11 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb) if (PageHighMem(skb_shinfo(skb)->frags[i].page)) return 1; -#endif return 0; } +#else +#define illegal_highdma(dev, skb) (0) +#endif struct dev_gso_cb { void (*destructor)(struct sk_buff *skb); @@ -1293,15 +1291,9 @@ static int dev_gso_segment(struct sk_buff *skb) { struct net_device *dev = skb->dev; struct sk_buff *segs; - int features = dev->features & ~(illegal_highdma(dev, skb) ? - NETIF_F_SG : 0); - - segs = skb_gso_segment(skb, features); - - /* Verifying header integrity only. */ - if (!segs) - return 0; + segs = skb_gso_segment(skb, dev->features & NETIF_F_SG && + !illegal_highdma(dev, skb)); if (unlikely(IS_ERR(segs))) return PTR_ERR(segs); @@ -1318,17 +1310,13 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (netdev_nit) dev_queue_xmit_nit(skb, dev); - if (netif_needs_gso(dev, skb)) { - if (unlikely(dev_gso_segment(skb))) - goto out_kfree_skb; - if (skb->next) - goto gso; - } + if (!netif_needs_gso(dev, skb)) + return dev->hard_start_xmit(skb, dev); - return dev->hard_start_xmit(skb, dev); + if (unlikely(dev_gso_segment(skb))) + goto out_kfree_skb; } -gso: do { struct sk_buff *nskb = skb->next; int rc; @@ -1337,12 +1325,9 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) nskb->next = NULL; rc = dev->hard_start_xmit(nskb, dev); if (unlikely(rc)) { - nskb->next = skb->next; skb->next = nskb; return rc; } - if (unlikely(netif_queue_stopped(dev) && skb->next)) - return NETDEV_TX_BUSY; } while (skb->next); skb->destructor = DEV_GSO_CB(skb)->destructor; diff --git a/trunk/net/core/link_watch.c b/trunk/net/core/link_watch.c index 4b36114744c5..0f37266411b5 100644 --- a/trunk/net/core/link_watch.c +++ b/trunk/net/core/link_watch.c @@ -11,6 +11,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/core/neighbour.c b/trunk/net/core/neighbour.c index 7ad681f5e712..50a8c73caf97 100644 --- a/trunk/net/core/neighbour.c +++ b/trunk/net/core/neighbour.c @@ -15,6 +15,7 @@ * Harald Welte Add neighbour cache statistics like rtstat */ +#include #include #include #include diff --git a/trunk/net/core/net-sysfs.c b/trunk/net/core/net-sysfs.c index 13472762b18b..47a6fceb6771 100644 --- a/trunk/net/core/net-sysfs.c +++ b/trunk/net/core/net-sysfs.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/core/netpoll.c b/trunk/net/core/netpoll.c index 471da451cd48..9cb781830380 100644 --- a/trunk/net/core/netpoll.c +++ b/trunk/net/core/netpoll.c @@ -54,7 +54,6 @@ static atomic_t trapped; sizeof(struct iphdr) + sizeof(struct ethhdr)) static void zap_completion_queue(void); -static void arp_reply(struct sk_buff *skb); static void queue_process(void *p) { @@ -154,22 +153,6 @@ static void poll_napi(struct netpoll *np) } } -static void service_arp_queue(struct netpoll_info *npi) -{ - struct sk_buff *skb; - - if (unlikely(!npi)) - return; - - skb = skb_dequeue(&npi->arp_tx); - - while (skb != NULL) { - arp_reply(skb); - skb = skb_dequeue(&npi->arp_tx); - } - return; -} - void netpoll_poll(struct netpoll *np) { if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller) @@ -180,8 +163,6 @@ void netpoll_poll(struct netpoll *np) if (np->dev->poll) poll_napi(np); - service_arp_queue(np->dev->npinfo); - zap_completion_queue(); } @@ -298,10 +279,14 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) * network drivers do not expect to be called if the queue is * stopped. */ - status = NETDEV_TX_BUSY; - if (!netif_queue_stopped(np->dev)) - status = np->dev->hard_start_xmit(skb, np->dev); + if (netif_queue_stopped(np->dev)) { + netif_tx_unlock(np->dev); + netpoll_poll(np); + udelay(50); + continue; + } + status = np->dev->hard_start_xmit(skb, np->dev); netif_tx_unlock(np->dev); /* success */ @@ -461,9 +446,7 @@ int __netpoll_rx(struct sk_buff *skb) int proto, len, ulen; struct iphdr *iph; struct udphdr *uh; - struct netpoll_info *npi = skb->dev->npinfo; - struct netpoll *np = npi->rx_np; - + struct netpoll *np = skb->dev->npinfo->rx_np; if (!np) goto out; @@ -473,7 +456,7 @@ int __netpoll_rx(struct sk_buff *skb) /* check if netpoll clients need ARP */ if (skb->protocol == __constant_htons(ETH_P_ARP) && atomic_read(&trapped)) { - skb_queue_tail(&npi->arp_tx, skb); + arp_reply(skb); return 1; } @@ -668,7 +651,6 @@ int netpoll_setup(struct netpoll *np) npinfo->poll_owner = -1; npinfo->tries = MAX_RETRIES; spin_lock_init(&npinfo->rx_lock); - skb_queue_head_init(&npinfo->arp_tx); } else npinfo = ndev->npinfo; diff --git a/trunk/net/core/rtnetlink.c b/trunk/net/core/rtnetlink.c index 20e5bb73f147..3fcfa9c59e1f 100644 --- a/trunk/net/core/rtnetlink.c +++ b/trunk/net/core/rtnetlink.c @@ -16,6 +16,7 @@ * Vitaly E. Lavrov RTA_OK arithmetics was wrong. */ +#include #include #include #include @@ -662,7 +663,7 @@ rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) sz_idx = type>>2; kind = type&3; - if (kind != 2 && security_netlink_recv(skb, CAP_NET_ADMIN)) { + if (kind != 2 && security_netlink_recv(skb)) { *errp = -EPERM; return -1; } diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index 7cfbdb215ba2..8e5044ba3ab6 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -38,6 +38,7 @@ * The functions in this file will not compile correctly with gcc 2.4.x */ +#include #include #include #include @@ -271,7 +272,7 @@ static void skb_clone_fraglist(struct sk_buff *skb) skb_get(list); } -static void skb_release_data(struct sk_buff *skb) +void skb_release_data(struct sk_buff *skb) { if (!skb->cloned || !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1, @@ -1738,15 +1739,12 @@ unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, unsigned int to, struct ts_config *config, struct ts_state *state) { - unsigned int ret; - config->get_next_block = skb_ts_get_next_block; config->finish = skb_ts_finish; skb_prepare_seq_read(skb, from, to, TS_SKB_CB(state)); - ret = textsearch_find(config, state); - return (ret <= to - from ? ret : UINT_MAX); + return textsearch_find(config, state); } /** @@ -1847,13 +1845,13 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum); /** * skb_segment - Perform protocol segmentation on skb. * @skb: buffer to segment - * @features: features for the output path (see dev->features) + * @sg: whether scatter-gather can be used for generated segments * * This function performs segmentation on the given skb. It returns * the segment at the given position. It returns NULL if there are * no more segments to generate, or when an error is encountered. */ -struct sk_buff *skb_segment(struct sk_buff *skb, int features) +struct sk_buff *skb_segment(struct sk_buff *skb, int sg) { struct sk_buff *segs = NULL; struct sk_buff *tail = NULL; @@ -1862,7 +1860,6 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) unsigned int offset = doffset; unsigned int headroom; unsigned int len; - int sg = features & NETIF_F_SG; int nfrags = skb_shinfo(skb)->nr_frags; int err = -ENOMEM; int i = 0; diff --git a/trunk/net/core/sock.c b/trunk/net/core/sock.c index 533b9317144b..5d820c376653 100644 --- a/trunk/net/core/sock.c +++ b/trunk/net/core/sock.c @@ -92,6 +92,7 @@ */ #include +#include #include #include #include @@ -564,13 +565,6 @@ int sock_setsockopt(struct socket *sock, int level, int optname, ret = -ENONET; break; - case SO_PASSSEC: - if (valbool) - set_bit(SOCK_PASSSEC, &sock->flags); - else - clear_bit(SOCK_PASSSEC, &sock->flags); - break; - /* We implement the SO_SNDLOWAT etc to not be settable (1003.1g 5.3) */ default: @@ -729,10 +723,6 @@ int sock_getsockopt(struct socket *sock, int level, int optname, v.val = sk->sk_state == TCP_LISTEN; break; - case SO_PASSSEC: - v.val = test_bit(SOCK_PASSSEC, &sock->flags) ? 1 : 0; - break; - case SO_PEERSEC: return security_socket_getpeersec_stream(sock, optval, optlen, len); diff --git a/trunk/net/core/sysctl_net_core.c b/trunk/net/core/sysctl_net_core.c index 02534131d88e..710453656721 100644 --- a/trunk/net/core/sysctl_net_core.c +++ b/trunk/net/core/sysctl_net_core.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include diff --git a/trunk/net/dccp/ackvec.h b/trunk/net/dccp/ackvec.h index 0adf4b56c34c..ec7a89bb7b39 100644 --- a/trunk/net/dccp/ackvec.h +++ b/trunk/net/dccp/ackvec.h @@ -11,6 +11,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include diff --git a/trunk/net/dccp/ccids/ccid2.c b/trunk/net/dccp/ccids/ccid2.c index e9615627dcd6..d4f9e2d33453 100644 --- a/trunk/net/dccp/ccids/ccid2.c +++ b/trunk/net/dccp/ccids/ccid2.c @@ -30,6 +30,7 @@ * - jiffies wrapping */ +#include #include "../ccid.h" #include "../dccp.h" #include "ccid2.h" diff --git a/trunk/net/dccp/ccids/ccid3.c b/trunk/net/dccp/ccids/ccid3.c index c39bff706cfc..b4a51d0355a5 100644 --- a/trunk/net/dccp/ccids/ccid3.c +++ b/trunk/net/dccp/ccids/ccid3.c @@ -34,6 +34,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include "../ccid.h" #include "../dccp.h" #include "lib/packet_history.h" diff --git a/trunk/net/dccp/ccids/ccid3.h b/trunk/net/dccp/ccids/ccid3.h index 5ade4f668b22..f18b96d4e5a2 100644 --- a/trunk/net/dccp/ccids/ccid3.h +++ b/trunk/net/dccp/ccids/ccid3.h @@ -36,6 +36,7 @@ #ifndef _DCCP_CCID3_H_ #define _DCCP_CCID3_H_ +#include #include #include #include diff --git a/trunk/net/dccp/ccids/lib/loss_interval.c b/trunk/net/dccp/ccids/lib/loss_interval.c index 5d7b7d864385..4c01a54143ad 100644 --- a/trunk/net/dccp/ccids/lib/loss_interval.c +++ b/trunk/net/dccp/ccids/lib/loss_interval.c @@ -11,6 +11,7 @@ * (at your option) any later version. */ +#include #include #include "loss_interval.h" diff --git a/trunk/net/dccp/ccids/lib/loss_interval.h b/trunk/net/dccp/ccids/lib/loss_interval.h index 43bf78269d1d..417d9d82df3e 100644 --- a/trunk/net/dccp/ccids/lib/loss_interval.h +++ b/trunk/net/dccp/ccids/lib/loss_interval.h @@ -13,6 +13,7 @@ * any later version. */ +#include #include #include #include diff --git a/trunk/net/dccp/ccids/lib/packet_history.c b/trunk/net/dccp/ccids/lib/packet_history.c index ad98d6a322eb..d3f9d2053830 100644 --- a/trunk/net/dccp/ccids/lib/packet_history.c +++ b/trunk/net/dccp/ccids/lib/packet_history.c @@ -34,6 +34,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include diff --git a/trunk/net/dccp/ccids/lib/packet_history.h b/trunk/net/dccp/ccids/lib/packet_history.h index 673c209e4e85..122e96737ff6 100644 --- a/trunk/net/dccp/ccids/lib/packet_history.h +++ b/trunk/net/dccp/ccids/lib/packet_history.h @@ -37,6 +37,7 @@ #ifndef _DCCP_PKT_HIST_ #define _DCCP_PKT_HIST_ +#include #include #include #include diff --git a/trunk/net/dccp/ccids/lib/tfrc_equation.c b/trunk/net/dccp/ccids/lib/tfrc_equation.c index 4fd2ebebf5a0..add3cae65e2d 100644 --- a/trunk/net/dccp/ccids/lib/tfrc_equation.c +++ b/trunk/net/dccp/ccids/lib/tfrc_equation.c @@ -12,6 +12,7 @@ * (at your option) any later version. */ +#include #include #include diff --git a/trunk/net/dccp/dccp.h b/trunk/net/dccp/dccp.h index d00a2f4ee5dd..1fe509148689 100644 --- a/trunk/net/dccp/dccp.h +++ b/trunk/net/dccp/dccp.h @@ -12,6 +12,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include diff --git a/trunk/net/dccp/diag.c b/trunk/net/dccp/diag.c index 0f3745585a94..0f25dc395967 100644 --- a/trunk/net/dccp/diag.c +++ b/trunk/net/dccp/diag.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ +#include #include #include diff --git a/trunk/net/dccp/feat.c b/trunk/net/dccp/feat.c index a1b0682ee77c..b39e2a597889 100644 --- a/trunk/net/dccp/feat.c +++ b/trunk/net/dccp/feat.c @@ -10,6 +10,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include "dccp.h" diff --git a/trunk/net/dccp/input.c b/trunk/net/dccp/input.c index 7f9dc6ac58c9..bfc53665516b 100644 --- a/trunk/net/dccp/input.c +++ b/trunk/net/dccp/input.c @@ -10,6 +10,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include diff --git a/trunk/net/dccp/ipv4.c b/trunk/net/dccp/ipv4.c index c3073e7e81d3..f2c011fd2ba1 100644 --- a/trunk/net/dccp/ipv4.c +++ b/trunk/net/dccp/ipv4.c @@ -10,6 +10,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/dccp/ipv6.c b/trunk/net/dccp/ipv6.c index ff42bc43263d..65e2ab0886e6 100644 --- a/trunk/net/dccp/ipv6.c +++ b/trunk/net/dccp/ipv6.c @@ -12,6 +12,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/dccp/ipv6.h b/trunk/net/dccp/ipv6.h index 6eef81fdbe56..e4d4e9309270 100644 --- a/trunk/net/dccp/ipv6.h +++ b/trunk/net/dccp/ipv6.h @@ -11,6 +11,7 @@ * published by the Free Software Foundation. */ +#include #include #include diff --git a/trunk/net/dccp/minisocks.c b/trunk/net/dccp/minisocks.c index 9045438d6b36..c0349e5b0551 100644 --- a/trunk/net/dccp/minisocks.c +++ b/trunk/net/dccp/minisocks.c @@ -10,6 +10,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/dccp/options.c b/trunk/net/dccp/options.c index c3cda1e39aa8..e9feb2a0c770 100644 --- a/trunk/net/dccp/options.c +++ b/trunk/net/dccp/options.c @@ -11,6 +11,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/dccp/output.c b/trunk/net/dccp/output.c index 58669beee132..7409e4a3abdf 100644 --- a/trunk/net/dccp/output.c +++ b/trunk/net/dccp/output.c @@ -10,6 +10,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/dccp/proto.c b/trunk/net/dccp/proto.c index f4f0627ea41c..5317fd3e6691 100644 --- a/trunk/net/dccp/proto.c +++ b/trunk/net/dccp/proto.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include diff --git a/trunk/net/dccp/sysctl.c b/trunk/net/dccp/sysctl.c index c1ba9451bc3d..64c89e9c229e 100644 --- a/trunk/net/dccp/sysctl.c +++ b/trunk/net/dccp/sysctl.c @@ -9,6 +9,7 @@ * as published by the Free Software Foundation. */ +#include #include #include diff --git a/trunk/net/dccp/timer.c b/trunk/net/dccp/timer.c index 8447742f5615..5244415e5f18 100644 --- a/trunk/net/dccp/timer.c +++ b/trunk/net/dccp/timer.c @@ -10,6 +10,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include diff --git a/trunk/net/decnet/af_decnet.c b/trunk/net/decnet/af_decnet.c index 5486247735f6..2b289ef20ab3 100644 --- a/trunk/net/decnet/af_decnet.c +++ b/trunk/net/decnet/af_decnet.c @@ -99,6 +99,7 @@ Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat dn_bind fixes *******************************************************************************/ +#include #include #include #include diff --git a/trunk/net/decnet/dn_dev.c b/trunk/net/decnet/dn_dev.c index 98a25208440d..a26ff9f44576 100644 --- a/trunk/net/decnet/dn_dev.c +++ b/trunk/net/decnet/dn_dev.c @@ -24,6 +24,7 @@ * devices. All mtu based now. */ +#include #include #include #include diff --git a/trunk/net/decnet/dn_fib.c b/trunk/net/decnet/dn_fib.c index 0375077391b7..bd4ce8681a12 100644 --- a/trunk/net/decnet/dn_fib.c +++ b/trunk/net/decnet/dn_fib.c @@ -17,6 +17,7 @@ * this code was copied from it. * */ +#include #include #include #include diff --git a/trunk/net/decnet/dn_neigh.c b/trunk/net/decnet/dn_neigh.c index 5ce9c9e0565c..66e230c3b328 100644 --- a/trunk/net/decnet/dn_neigh.c +++ b/trunk/net/decnet/dn_neigh.c @@ -24,6 +24,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/decnet/dn_nsp_in.c b/trunk/net/decnet/dn_nsp_in.c index 86f7f3b28e70..a2ba9db1c376 100644 --- a/trunk/net/decnet/dn_nsp_in.c +++ b/trunk/net/decnet/dn_nsp_in.c @@ -45,6 +45,7 @@ GNU General Public License for more details. *******************************************************************************/ +#include #include #include #include diff --git a/trunk/net/decnet/dn_route.c b/trunk/net/decnet/dn_route.c index 1355614ec11b..5abf7057af00 100644 --- a/trunk/net/decnet/dn_route.c +++ b/trunk/net/decnet/dn_route.c @@ -55,6 +55,7 @@ GNU General Public License for more details. *******************************************************************************/ +#include #include #include #include diff --git a/trunk/net/decnet/dn_rules.c b/trunk/net/decnet/dn_rules.c index 06e785fe5757..446faafe2065 100644 --- a/trunk/net/decnet/dn_rules.c +++ b/trunk/net/decnet/dn_rules.c @@ -13,6 +13,7 @@ * Changes: * */ +#include #include #include #include diff --git a/trunk/net/decnet/dn_table.c b/trunk/net/decnet/dn_table.c index 37d9d0a1ac8c..0ebc46af1bdd 100644 --- a/trunk/net/decnet/dn_table.c +++ b/trunk/net/decnet/dn_table.c @@ -12,6 +12,7 @@ * Changes: * */ +#include #include #include #include diff --git a/trunk/net/decnet/netfilter/dn_rtmsg.c b/trunk/net/decnet/netfilter/dn_rtmsg.c index 8b99bd33540d..74133ecd7700 100644 --- a/trunk/net/decnet/netfilter/dn_rtmsg.c +++ b/trunk/net/decnet/netfilter/dn_rtmsg.c @@ -107,7 +107,7 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb) if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) return; - if (security_netlink_recv(skb, CAP_NET_ADMIN)) + if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) RCV_SKB_FAIL(-EPERM); /* Eventually we might send routing messages too */ diff --git a/trunk/net/decnet/sysctl_net_decnet.c b/trunk/net/decnet/sysctl_net_decnet.c index e246f054f368..bda5920215fd 100644 --- a/trunk/net/decnet/sysctl_net_decnet.c +++ b/trunk/net/decnet/sysctl_net_decnet.c @@ -13,6 +13,7 @@ * Steve Whitehouse - Memory buffer settings, like the tcp ones * */ +#include #include #include #include diff --git a/trunk/net/econet/af_econet.c b/trunk/net/econet/af_econet.c index 309ae4c6549a..868265619dbb 100644 --- a/trunk/net/econet/af_econet.c +++ b/trunk/net/econet/af_econet.c @@ -9,6 +9,7 @@ * */ +#include #include #include diff --git a/trunk/net/ethernet/eth.c b/trunk/net/ethernet/eth.c index 387c71c584ee..c971f14712ec 100644 --- a/trunk/net/ethernet/eth.c +++ b/trunk/net/ethernet/eth.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/ieee80211/ieee80211_crypt_ccmp.c b/trunk/net/ieee80211/ieee80211_crypt_ccmp.c index 492647382ad0..78b2d13e80e3 100644 --- a/trunk/net/ieee80211/ieee80211_crypt_ccmp.c +++ b/trunk/net/ieee80211/ieee80211_crypt_ccmp.c @@ -9,6 +9,7 @@ * more details. */ +#include #include #include #include diff --git a/trunk/net/ieee80211/ieee80211_crypt_tkip.c b/trunk/net/ieee80211/ieee80211_crypt_tkip.c index 34dba0ba545d..3fa5df2e1f0b 100644 --- a/trunk/net/ieee80211/ieee80211_crypt_tkip.c +++ b/trunk/net/ieee80211/ieee80211_crypt_tkip.c @@ -9,6 +9,7 @@ * more details. */ +#include #include #include #include diff --git a/trunk/net/ieee80211/ieee80211_crypt_wep.c b/trunk/net/ieee80211/ieee80211_crypt_wep.c index c5a87724aabe..649e581fa565 100644 --- a/trunk/net/ieee80211/ieee80211_crypt_wep.c +++ b/trunk/net/ieee80211/ieee80211_crypt_wep.c @@ -9,6 +9,7 @@ * more details. */ +#include #include #include #include diff --git a/trunk/net/ieee80211/ieee80211_geo.c b/trunk/net/ieee80211/ieee80211_geo.c index 305a09de85a5..192243ab35ed 100644 --- a/trunk/net/ieee80211/ieee80211_geo.c +++ b/trunk/net/ieee80211/ieee80211_geo.c @@ -24,6 +24,7 @@ ******************************************************************************/ #include +#include #include #include #include diff --git a/trunk/net/ieee80211/ieee80211_module.c b/trunk/net/ieee80211/ieee80211_module.c index 13b1e5fff7e4..2cb84d84f671 100644 --- a/trunk/net/ieee80211/ieee80211_module.c +++ b/trunk/net/ieee80211/ieee80211_module.c @@ -31,6 +31,7 @@ *******************************************************************************/ #include +#include #include #include #include diff --git a/trunk/net/ieee80211/ieee80211_rx.c b/trunk/net/ieee80211/ieee80211_rx.c index 47ccf159372c..2bf567fd5a17 100644 --- a/trunk/net/ieee80211/ieee80211_rx.c +++ b/trunk/net/ieee80211/ieee80211_rx.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/ieee80211/ieee80211_tx.c b/trunk/net/ieee80211/ieee80211_tx.c index de148ae594f3..6a5de1b84459 100644 --- a/trunk/net/ieee80211/ieee80211_tx.c +++ b/trunk/net/ieee80211/ieee80211_tx.c @@ -24,6 +24,7 @@ ******************************************************************************/ #include +#include #include #include #include diff --git a/trunk/net/ipv4/af_inet.c b/trunk/net/ipv4/af_inet.c index 8d157157bf8e..461216b47948 100644 --- a/trunk/net/ipv4/af_inet.c +++ b/trunk/net/ipv4/af_inet.c @@ -1097,7 +1097,7 @@ int inet_sk_rebuild_header(struct sock *sk) EXPORT_SYMBOL(inet_sk_rebuild_header); -static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) +static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg) { struct sk_buff *segs = ERR_PTR(-EINVAL); struct iphdr *iph; @@ -1126,10 +1126,10 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features) rcu_read_lock(); ops = rcu_dereference(inet_protos[proto]); if (ops && ops->gso_segment) - segs = ops->gso_segment(skb, features); + segs = ops->gso_segment(skb, sg); rcu_read_unlock(); - if (!segs || unlikely(IS_ERR(segs))) + if (IS_ERR(segs)) goto out; skb = segs; diff --git a/trunk/net/ipv4/ah4.c b/trunk/net/ipv4/ah4.c index 8e748be36c5a..c7782230080d 100644 --- a/trunk/net/ipv4/ah4.c +++ b/trunk/net/ipv4/ah4.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/trunk/net/ipv4/arp.c b/trunk/net/ipv4/arp.c index 7b51b3bdb548..4749d504c629 100644 --- a/trunk/net/ipv4/arp.c +++ b/trunk/net/ipv4/arp.c @@ -80,6 +80,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/ipv4/datagram.c b/trunk/net/ipv4/datagram.c index ec5da4fbd9f4..c1b42b5257f8 100644 --- a/trunk/net/ipv4/datagram.c +++ b/trunk/net/ipv4/datagram.c @@ -11,6 +11,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv4/devinet.c b/trunk/net/ipv4/devinet.c index a7c65e9e5ec9..54419b27686f 100644 --- a/trunk/net/ipv4/devinet.c +++ b/trunk/net/ipv4/devinet.c @@ -27,6 +27,7 @@ * if no match found. */ +#include #include #include diff --git a/trunk/net/ipv4/esp4.c b/trunk/net/ipv4/esp4.c index 4e112738b3fa..9bbdd4494551 100644 --- a/trunk/net/ipv4/esp4.c +++ b/trunk/net/ipv4/esp4.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/trunk/net/ipv4/fib_frontend.c b/trunk/net/ipv4/fib_frontend.c index ba2a70745a63..31387abf53a2 100644 --- a/trunk/net/ipv4/fib_frontend.c +++ b/trunk/net/ipv4/fib_frontend.c @@ -15,6 +15,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv4/fib_hash.c b/trunk/net/ipv4/fib_hash.c index 3c1d32ad35f2..e2890ec8159e 100644 --- a/trunk/net/ipv4/fib_hash.c +++ b/trunk/net/ipv4/fib_hash.c @@ -15,6 +15,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv4/fib_rules.c b/trunk/net/ipv4/fib_rules.c index 6c642d11d4ca..ec566f3e66c7 100644 --- a/trunk/net/ipv4/fib_rules.c +++ b/trunk/net/ipv4/fib_rules.c @@ -19,6 +19,7 @@ * Marc Boucher : routing by fwmark */ +#include #include #include #include diff --git a/trunk/net/ipv4/fib_semantics.c b/trunk/net/ipv4/fib_semantics.c index 5f87533684d5..0f4145babb14 100644 --- a/trunk/net/ipv4/fib_semantics.c +++ b/trunk/net/ipv4/fib_semantics.c @@ -15,6 +15,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv4/fib_trie.c b/trunk/net/ipv4/fib_trie.c index 1cb65305e102..95a639f2e3db 100644 --- a/trunk/net/ipv4/fib_trie.c +++ b/trunk/net/ipv4/fib_trie.c @@ -52,6 +52,7 @@ #define VERSION "0.407" +#include #include #include #include diff --git a/trunk/net/ipv4/icmp.c b/trunk/net/ipv4/icmp.c index 4c86ac3d882d..017900172f7d 100644 --- a/trunk/net/ipv4/icmp.c +++ b/trunk/net/ipv4/icmp.c @@ -64,6 +64,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/ipv4/igmp.c b/trunk/net/ipv4/igmp.c index d299c8e547d6..ab680c851aa2 100644 --- a/trunk/net/ipv4/igmp.c +++ b/trunk/net/ipv4/igmp.c @@ -72,6 +72,7 @@ * Vinay Kulkarni */ +#include #include #include #include diff --git a/trunk/net/ipv4/inet_connection_sock.c b/trunk/net/ipv4/inet_connection_sock.c index e50a1bfd7ccc..9a01bb81f8bf 100644 --- a/trunk/net/ipv4/inet_connection_sock.c +++ b/trunk/net/ipv4/inet_connection_sock.c @@ -13,6 +13,7 @@ * 2 of the License, or(at your option) any later version. */ +#include #include #include diff --git a/trunk/net/ipv4/inet_diag.c b/trunk/net/ipv4/inet_diag.c index 8e7e41b66c79..457db99c76df 100644 --- a/trunk/net/ipv4/inet_diag.c +++ b/trunk/net/ipv4/inet_diag.c @@ -11,6 +11,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv4/inet_hashtables.c b/trunk/net/ipv4/inet_hashtables.c index 95fac5532994..ee9b5515b9ae 100644 --- a/trunk/net/ipv4/inet_hashtables.c +++ b/trunk/net/ipv4/inet_hashtables.c @@ -13,6 +13,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv4/inet_timewait_sock.c b/trunk/net/ipv4/inet_timewait_sock.c index cdd805344c61..417f126c749e 100644 --- a/trunk/net/ipv4/inet_timewait_sock.c +++ b/trunk/net/ipv4/inet_timewait_sock.c @@ -8,6 +8,7 @@ * From code orinally in TCP */ +#include #include #include diff --git a/trunk/net/ipv4/ip_forward.c b/trunk/net/ipv4/ip_forward.c index a22d11d2911c..9f0bb529ab70 100644 --- a/trunk/net/ipv4/ip_forward.c +++ b/trunk/net/ipv4/ip_forward.c @@ -21,6 +21,7 @@ * Mike McLagan : Routing by source */ +#include #include #include #include diff --git a/trunk/net/ipv4/ip_fragment.c b/trunk/net/ipv4/ip_fragment.c index b84b53a47526..da734c439179 100644 --- a/trunk/net/ipv4/ip_fragment.c +++ b/trunk/net/ipv4/ip_fragment.c @@ -23,6 +23,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/ipv4/ip_gre.c b/trunk/net/ipv4/ip_gre.c index 6ff9b10d9563..ab99bebdcdc8 100644 --- a/trunk/net/ipv4/ip_gre.c +++ b/trunk/net/ipv4/ip_gre.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/ipv4/ip_input.c b/trunk/net/ipv4/ip_input.c index e1a7dba2fa8a..c9026dbf4c93 100644 --- a/trunk/net/ipv4/ip_input.c +++ b/trunk/net/ipv4/ip_input.c @@ -121,6 +121,7 @@ #include #include #include +#include #include #include diff --git a/trunk/net/ipv4/ip_output.c b/trunk/net/ipv4/ip_output.c index ca0e714613fb..7624fd1d8f9f 100644 --- a/trunk/net/ipv4/ip_output.c +++ b/trunk/net/ipv4/ip_output.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -743,7 +744,7 @@ static inline int ip_ufo_append_data(struct sock *sk, if (!err) { /* specify the length of each IP datagram fragment*/ skb_shinfo(skb)->gso_size = mtu - fragheaderlen; - skb_shinfo(skb)->gso_type = SKB_GSO_UDP; + skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; __skb_queue_tail(&sk->sk_write_queue, skb); return 0; @@ -1088,7 +1089,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, if ((sk->sk_protocol == IPPROTO_UDP) && (rt->u.dst.dev->features & NETIF_F_UFO)) { skb_shinfo(skb)->gso_size = mtu - fragheaderlen; - skb_shinfo(skb)->gso_type = SKB_GSO_UDP; + skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; } diff --git a/trunk/net/ipv4/ip_sockglue.c b/trunk/net/ipv4/ip_sockglue.c index 84f43a3c9098..12e0bf19f24a 100644 --- a/trunk/net/ipv4/ip_sockglue.c +++ b/trunk/net/ipv4/ip_sockglue.c @@ -17,6 +17,7 @@ * Mike McLagan : Routing by source */ +#include #include #include #include diff --git a/trunk/net/ipv4/ipcomp.c b/trunk/net/ipv4/ipcomp.c index 8e0374847532..3ed8b57a1002 100644 --- a/trunk/net/ipv4/ipcomp.c +++ b/trunk/net/ipv4/ipcomp.c @@ -13,6 +13,7 @@ * - Compression stats. * - Adaptive compression. */ +#include #include #include #include diff --git a/trunk/net/ipv4/ipip.c b/trunk/net/ipv4/ipip.c index 3291d5192aad..ea398ee43f28 100644 --- a/trunk/net/ipv4/ipip.c +++ b/trunk/net/ipv4/ipip.c @@ -94,6 +94,7 @@ #include +#include #include #include #include diff --git a/trunk/net/ipv4/ipmr.c b/trunk/net/ipv4/ipmr.c index ba33f8621c67..717ab7d6d7b6 100644 --- a/trunk/net/ipv4/ipmr.c +++ b/trunk/net/ipv4/ipmr.c @@ -28,6 +28,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/ipv4/ipvs/ip_vs_est.c b/trunk/net/ipv4/ipvs/ip_vs_est.c index 4c1940381ba0..c453e1e57f4b 100644 --- a/trunk/net/ipv4/ipvs/ip_vs_est.c +++ b/trunk/net/ipv4/ipvs/ip_vs_est.c @@ -13,6 +13,7 @@ * Changes: * */ +#include #include #include #include diff --git a/trunk/net/ipv4/multipath_drr.c b/trunk/net/ipv4/multipath_drr.c index 252e837b17a5..db67373f9b34 100644 --- a/trunk/net/ipv4/multipath_drr.c +++ b/trunk/net/ipv4/multipath_drr.c @@ -12,6 +12,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv4/multipath_random.c b/trunk/net/ipv4/multipath_random.c index b8c289f247cb..5249dbe7c559 100644 --- a/trunk/net/ipv4/multipath_random.c +++ b/trunk/net/ipv4/multipath_random.c @@ -12,6 +12,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv4/multipath_rr.c b/trunk/net/ipv4/multipath_rr.c index bba5abe5542d..b6cd2870478f 100644 --- a/trunk/net/ipv4/multipath_rr.c +++ b/trunk/net/ipv4/multipath_rr.c @@ -12,6 +12,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv4/multipath_wrandom.c b/trunk/net/ipv4/multipath_wrandom.c index d25ec4ae09e5..342d0b9098f5 100644 --- a/trunk/net/ipv4/multipath_wrandom.c +++ b/trunk/net/ipv4/multipath_wrandom.c @@ -12,6 +12,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/Kconfig b/trunk/net/ipv4/netfilter/Kconfig index ef0b5aac5838..e1d7f5fbc526 100644 --- a/trunk/net/ipv4/netfilter/Kconfig +++ b/trunk/net/ipv4/netfilter/Kconfig @@ -332,7 +332,7 @@ config IP_NF_MATCH_HASHLIMIT help This option adds a new iptables `hashlimit' match. - As opposed to `limit', this match dynamically creates a hash table + As opposed to `limit', this match dynamically crates a hash table of limit buckets, based on your selection of source/destination ip addresses and/or ports. diff --git a/trunk/net/ipv4/netfilter/arp_tables.c b/trunk/net/ipv4/netfilter/arp_tables.c index 80c73ca90116..d0d19192026d 100644 --- a/trunk/net/ipv4/netfilter/arp_tables.c +++ b/trunk/net/ipv4/netfilter/arp_tables.c @@ -9,6 +9,7 @@ * */ +#include #include #include #include @@ -1119,8 +1120,7 @@ int arpt_register_table(struct arpt_table *table, return ret; } - ret = xt_register_table(table, &bootstrap, newinfo); - if (ret != 0) { + if (xt_register_table(table, &bootstrap, newinfo) != 0) { xt_free_table_info(newinfo); return ret; } diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_core.c b/trunk/net/ipv4/netfilter/ip_conntrack_core.c index aa459177c3f8..7e4cf9a4d15f 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_core.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_core.c @@ -17,6 +17,7 @@ * - export ip_conntrack[_expect]_{find_get,put} functions * */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c b/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c index 1d18c863f064..4dcf526c3944 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c @@ -8,6 +8,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/trunk/net/ipv4/netfilter/ip_conntrack_helper_h323.c index af35235672d5..0665674218c6 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -11,6 +11,7 @@ * For more information, please see http://nath323.sourceforge.net/ */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/trunk/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index b020a33e65e9..8ccfe17bb253 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_helper_pptp.c @@ -46,6 +46,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_irc.c b/trunk/net/ipv4/netfilter/ip_conntrack_irc.c index 44889075f3b2..a2ac5ce544b2 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_irc.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_irc.c @@ -22,6 +22,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_gre.c index 4ee016c427b4..21ee124c0463 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_gre.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_gre.c @@ -23,6 +23,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c index 2d3612cd5f18..0416073c5600 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c @@ -254,7 +254,7 @@ static int do_basic_checks(struct ip_conntrack *conntrack, } DEBUGP("Basic checks passed\n"); - return count == 0; + return 0; } static int new_state(enum ip_conntrack_dir dir, diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index fb920e76ec10..c5c2ce5cdeb8 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -19,6 +19,7 @@ * version 2.2 */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c b/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c index 7bd3c22003a2..88445aac3f28 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -12,6 +12,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_nat_helper.c b/trunk/net/ipv4/netfilter/ip_nat_helper.c index cbcaa45370ae..5d506e0564d5 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_helper.c +++ b/trunk/net/ipv4/netfilter/ip_nat_helper.c @@ -15,6 +15,7 @@ * - make ip_nat_resize_packet more generic (TCP and UDP) * - add ip_nat_mangle_udp_packet */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_nat_helper_pptp.c b/trunk/net/ipv4/netfilter/ip_nat_helper_pptp.c index 1d149964dc38..f3977726ff09 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_helper_pptp.c +++ b/trunk/net/ipv4/netfilter/ip_nat_helper_pptp.c @@ -35,6 +35,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_nat_proto_gre.c b/trunk/net/ipv4/netfilter/ip_nat_proto_gre.c index 38acfdf540eb..96ceabaec402 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_proto_gre.c +++ b/trunk/net/ipv4/netfilter/ip_nat_proto_gre.c @@ -23,6 +23,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_nat_snmp_basic.c b/trunk/net/ipv4/netfilter/ip_nat_snmp_basic.c index 0b1b416759cc..d20d557f915a 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_snmp_basic.c +++ b/trunk/net/ipv4/netfilter/ip_nat_snmp_basic.c @@ -43,6 +43,7 @@ * 2000-08-06: Convert to new helper API (Harald Welte). * */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_nat_standalone.c b/trunk/net/ipv4/netfilter/ip_nat_standalone.c index 17de077a7901..67e676783da9 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_standalone.c +++ b/trunk/net/ipv4/netfilter/ip_nat_standalone.c @@ -18,6 +18,7 @@ * - now capable of multiple expectations for one master * */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_queue.c b/trunk/net/ipv4/netfilter/ip_queue.c index 198ac36db861..b93f0494362f 100644 --- a/trunk/net/ipv4/netfilter/ip_queue.c +++ b/trunk/net/ipv4/netfilter/ip_queue.c @@ -457,19 +457,11 @@ dev_cmp(struct ipq_queue_entry *entry, unsigned long ifindex) if (entry->info->indev) if (entry->info->indev->ifindex == ifindex) return 1; + if (entry->info->outdev) if (entry->info->outdev->ifindex == ifindex) return 1; -#ifdef CONFIG_BRIDGE_NETFILTER - if (entry->skb->nf_bridge) { - if (entry->skb->nf_bridge->physindev && - entry->skb->nf_bridge->physindev->ifindex == ifindex) - return 1; - if (entry->skb->nf_bridge->physoutdev && - entry->skb->nf_bridge->physoutdev->ifindex == ifindex) - return 1; - } -#endif + return 0; } @@ -515,7 +507,7 @@ ipq_rcv_skb(struct sk_buff *skb) if (type <= IPQM_BASE) return; - if (security_netlink_recv(skb, CAP_NET_ADMIN)) + if (security_netlink_recv(skb)) RCV_SKB_FAIL(-EPERM); write_lock_bh(&queue_lock); diff --git a/trunk/net/ipv4/netfilter/ip_tables.c b/trunk/net/ipv4/netfilter/ip_tables.c index fc5bdd5eb7d3..706c0025ec5e 100644 --- a/trunk/net/ipv4/netfilter/ip_tables.c +++ b/trunk/net/ipv4/netfilter/ip_tables.c @@ -14,6 +14,7 @@ * 08 Oct 2005 Harald Welte * - Generalize into "x_tables" layer and "{ip,ip6,arp}_tables" */ +#include #include #include #include @@ -2112,8 +2113,7 @@ int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl) return ret; } - ret = xt_register_table(table, &bootstrap, newinfo); - if (ret != 0) { + if (xt_register_table(table, &bootstrap, newinfo) != 0) { xt_free_table_info(newinfo); return ret; } diff --git a/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c b/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c index cbffeae3f565..dbc83c5d7aa6 100644 --- a/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -10,6 +10,7 @@ * */ #include +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c b/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c index ebd94f2abf0d..8b3e7f99b861 100644 --- a/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ipt_NETMAP.c b/trunk/net/ipv4/netfilter/ipt_NETMAP.c index 736c4b5a86a7..2fcf1075b027 100644 --- a/trunk/net/ipv4/netfilter/ipt_NETMAP.c +++ b/trunk/net/ipv4/netfilter/ipt_NETMAP.c @@ -10,6 +10,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ipt_REJECT.c b/trunk/net/ipv4/netfilter/ipt_REJECT.c index 269bc2067cb8..431a3ce6f7b7 100644 --- a/trunk/net/ipv4/netfilter/ipt_REJECT.c +++ b/trunk/net/ipv4/netfilter/ipt_REJECT.c @@ -12,6 +12,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ipt_ULOG.c b/trunk/net/ipv4/netfilter/ipt_ULOG.c index d7dd7fe7051c..c84cc03389d8 100644 --- a/trunk/net/ipv4/netfilter/ipt_ULOG.c +++ b/trunk/net/ipv4/netfilter/ipt_ULOG.c @@ -47,6 +47,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/iptable_mangle.c b/trunk/net/ipv4/netfilter/iptable_mangle.c index 4e7998beda63..397b95cc026b 100644 --- a/trunk/net/ipv4/netfilter/iptable_mangle.c +++ b/trunk/net/ipv4/netfilter/iptable_mangle.c @@ -10,6 +10,7 @@ * * Extended to all five netfilter hooks by Brad Chapman & Harald Welte */ +#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/trunk/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 0af803df82b0..8cc8e1b36778 100644 --- a/trunk/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/trunk/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -14,6 +14,7 @@ * Derived from net/ipv4/netfilter/ip_conntrack_standalone.c */ +#include #include #include #include diff --git a/trunk/net/ipv4/protocol.c b/trunk/net/ipv4/protocol.c index 05f5114828ea..291831e792af 100644 --- a/trunk/net/ipv4/protocol.c +++ b/trunk/net/ipv4/protocol.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index da44fabf4dc5..60b11aece5c3 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -64,6 +64,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv4/sysctl_net_ipv4.c b/trunk/net/ipv4/sysctl_net_ipv4.c index 70cea9d08a38..ce4cd5f35511 100644 --- a/trunk/net/ipv4/sysctl_net_ipv4.c +++ b/trunk/net/ipv4/sysctl_net_ipv4.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index 804458712d88..0e029c4e2903 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -247,6 +247,7 @@ * TCP_CLOSE socket is finished */ +#include #include #include #include @@ -642,7 +643,7 @@ static inline int select_size(struct sock *sk, struct tcp_sock *tp) int tmp = tp->mss_cache; if (sk->sk_route_caps & NETIF_F_SG) { - if (sk_can_gso(sk)) + if (sk->sk_route_caps & NETIF_F_TSO) tmp = 0; else { int pgbreak = SKB_MAX_HEAD(MAX_TCP_HEADER); @@ -2144,7 +2145,7 @@ int compat_tcp_getsockopt(struct sock *sk, int level, int optname, EXPORT_SYMBOL(compat_tcp_getsockopt); #endif -struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) +struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg) { struct sk_buff *segs = ERR_PTR(-EINVAL); struct tcphdr *th; @@ -2165,25 +2166,15 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) if (!pskb_may_pull(skb, thlen)) goto out; - oldlen = (u16)~skb->len; + oldlen = ~htonl(skb->len); __skb_pull(skb, thlen); - if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { - /* Packet is from an untrusted source, reset gso_segs. */ - int mss = skb_shinfo(skb)->gso_size; - - skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss; - - segs = NULL; - goto out; - } - - segs = skb_segment(skb, features); + segs = skb_segment(skb, sg); if (IS_ERR(segs)) goto out; len = skb_shinfo(skb)->gso_size; - delta = htonl(oldlen + (thlen + len)); + delta = csum_add(oldlen, htonl(thlen + len)); skb = segs; th = skb->h.th; @@ -2192,10 +2183,10 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) do { th->fin = th->psh = 0; - th->check = ~csum_fold(th->check + delta); - if (skb->ip_summed != CHECKSUM_HW) - th->check = csum_fold(csum_partial(skb->h.raw, thlen, - skb->csum)); + if (skb->ip_summed == CHECKSUM_NONE) { + th->check = csum_fold(csum_partial( + skb->h.raw, thlen, csum_add(skb->csum, delta))); + } seq += len; skb = skb->next; @@ -2205,16 +2196,15 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) th->cwr = 0; } while (skb->next); - delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len); - th->check = ~csum_fold(th->check + delta); - if (skb->ip_summed != CHECKSUM_HW) - th->check = csum_fold(csum_partial(skb->h.raw, thlen, - skb->csum)); + if (skb->ip_summed == CHECKSUM_NONE) { + delta = csum_add(oldlen, htonl(skb->tail - skb->h.raw)); + th->check = csum_fold(csum_partial( + skb->h.raw, thlen, csum_add(skb->csum, delta))); + } out: return segs; } -EXPORT_SYMBOL(tcp_tso_segment); extern void __skb_cb_too_small_for_tcp(int, int); extern struct tcp_congestion_ops tcp_reno; diff --git a/trunk/net/ipv4/tcp_bic.c b/trunk/net/ipv4/tcp_bic.c index b0134ab08379..b2d9021ad22b 100644 --- a/trunk/net/ipv4/tcp_bic.c +++ b/trunk/net/ipv4/tcp_bic.c @@ -12,6 +12,7 @@ * this behaves the same as the original Reno. */ +#include #include #include #include diff --git a/trunk/net/ipv4/tcp_cong.c b/trunk/net/ipv4/tcp_cong.c index 5765f9d03174..857eefc52aab 100644 --- a/trunk/net/ipv4/tcp_cong.c +++ b/trunk/net/ipv4/tcp_cong.c @@ -6,6 +6,7 @@ * Copyright (C) 2005 Stephen Hemminger */ +#include #include #include #include diff --git a/trunk/net/ipv4/tcp_cubic.c b/trunk/net/ipv4/tcp_cubic.c index 2be27980ca78..78b7a6b9e4de 100644 --- a/trunk/net/ipv4/tcp_cubic.c +++ b/trunk/net/ipv4/tcp_cubic.c @@ -12,6 +12,7 @@ * this behaves the same as the original Reno. */ +#include #include #include #include diff --git a/trunk/net/ipv4/tcp_diag.c b/trunk/net/ipv4/tcp_diag.c index 57c5f0b10e6c..c148c1081880 100644 --- a/trunk/net/ipv4/tcp_diag.c +++ b/trunk/net/ipv4/tcp_diag.c @@ -11,6 +11,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include @@ -25,10 +26,7 @@ static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, const struct tcp_sock *tp = tcp_sk(sk); struct tcp_info *info = _info; - if (sk->sk_state == TCP_LISTEN) - r->idiag_rqueue = sk->sk_ack_backlog; - else - r->idiag_rqueue = tp->rcv_nxt - tp->copied_seq; + r->idiag_rqueue = tp->rcv_nxt - tp->copied_seq; r->idiag_wqueue = tp->write_seq - tp->snd_una; if (info != NULL) tcp_get_info(sk, info); diff --git a/trunk/net/ipv4/tcp_highspeed.c b/trunk/net/ipv4/tcp_highspeed.c index aaa1538c0692..1120245b2373 100644 --- a/trunk/net/ipv4/tcp_highspeed.c +++ b/trunk/net/ipv4/tcp_highspeed.c @@ -6,6 +6,7 @@ * John Heffner */ +#include #include #include diff --git a/trunk/net/ipv4/tcp_htcp.c b/trunk/net/ipv4/tcp_htcp.c index 6edfe5e4510e..3d92c1859267 100644 --- a/trunk/net/ipv4/tcp_htcp.c +++ b/trunk/net/ipv4/tcp_htcp.c @@ -6,6 +6,7 @@ * http://www.hamilton.ie/net/htcp3.pdf */ +#include #include #include #include diff --git a/trunk/net/ipv4/tcp_hybla.c b/trunk/net/ipv4/tcp_hybla.c index 7406e0c5fb8e..40dbb3877510 100644 --- a/trunk/net/ipv4/tcp_hybla.c +++ b/trunk/net/ipv4/tcp_hybla.c @@ -10,6 +10,7 @@ * root at danielinux.net */ +#include #include #include diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index 738dad9f7d49..94fe5b1f9dcb 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -63,6 +63,7 @@ * Pasi Sarolahti: F-RTO for dealing with spurious RTOs */ +#include #include #include #include @@ -4177,6 +4178,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, */ TCP_ECN_rcv_synack(tp, th); + if (tp->ecn_flags&TCP_ECN_OK) + sock_set_flag(sk, SOCK_NO_LARGESEND); tp->snd_wl1 = TCP_SKB_CB(skb)->seq; tcp_ack(sk, skb, FLAG_SLOWPATH); @@ -4319,6 +4322,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, tp->max_window = tp->snd_wnd; TCP_ECN_rcv_syn(tp, th); + if (tp->ecn_flags&TCP_ECN_OK) + sock_set_flag(sk, SOCK_NO_LARGESEND); tcp_mtup_init(sk); tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index 8355b729fa95..25ecc6e2478b 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -52,6 +52,7 @@ * a single port at the same time. */ +#include #include #include @@ -241,7 +242,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) goto failure; /* OK, now commit destination to socket. */ - sk->sk_gso_type = SKB_GSO_TCPV4; sk_setup_caps(sk, &rt->u.dst); if (!tp->write_seq) @@ -884,7 +884,6 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, if (!newsk) goto exit; - newsk->sk_gso_type = SKB_GSO_TCPV4; sk_setup_caps(newsk, dst); newtp = tcp_sk(newsk); @@ -1727,8 +1726,7 @@ static void get_tcp4_sock(struct sock *sp, char *tmpbuf, int i) sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " "%08X %5d %8d %lu %d %p %u %u %u %u %d", i, src, srcp, dest, destp, sp->sk_state, - tp->write_seq - tp->snd_una, - (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq), + tp->write_seq - tp->snd_una, tp->rcv_nxt - tp->copied_seq, timer_active, jiffies_to_clock_t(timer_expires - jiffies), icsk->icsk_retransmits, diff --git a/trunk/net/ipv4/tcp_minisocks.c b/trunk/net/ipv4/tcp_minisocks.c index e0851697ad5e..2b9b7f6c7f7c 100644 --- a/trunk/net/ipv4/tcp_minisocks.c +++ b/trunk/net/ipv4/tcp_minisocks.c @@ -20,6 +20,7 @@ * Jorge Cwik, */ +#include #include #include #include @@ -439,6 +440,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; newtp->rx_opt.mss_clamp = req->mss; TCP_ECN_openreq_child(newtp, req); + if (newtp->ecn_flags&TCP_ECN_OK) + sock_set_flag(newsk, SOCK_NO_LARGESEND); TCP_INC_STATS_BH(TCP_MIB_PASSIVEOPENS); } diff --git a/trunk/net/ipv4/tcp_output.c b/trunk/net/ipv4/tcp_output.c index 5c08ea20a18d..bdd71db8bf90 100644 --- a/trunk/net/ipv4/tcp_output.c +++ b/trunk/net/ipv4/tcp_output.c @@ -510,7 +510,8 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now) { - if (skb->len <= mss_now || !sk_can_gso(sk)) { + if (skb->len <= mss_now || + !(sk->sk_route_caps & NETIF_F_TSO)) { /* Avoid the costly divide in the normal * non-TSO case. */ @@ -524,7 +525,7 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned factor /= mss_now; skb_shinfo(skb)->gso_segs = factor; skb_shinfo(skb)->gso_size = mss_now; - skb_shinfo(skb)->gso_type = sk->sk_gso_type; + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; } } @@ -823,7 +824,9 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed) mss_now = tp->mss_cache; - if (large_allowed && sk_can_gso(sk) && !tp->urg_mode) + if (large_allowed && + (sk->sk_route_caps & NETIF_F_TSO) && + !tp->urg_mode) doing_tso = 1; if (dst) { @@ -2041,6 +2044,8 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, memset(th, 0, sizeof(struct tcphdr)); th->syn = 1; th->ack = 1; + if (dst->dev->features&NETIF_F_TSO) + ireq->ecn_ok = 0; TCP_ECN_make_synack(req, th); th->source = inet_sk(sk)->sport; th->dest = ireq->rmt_port; diff --git a/trunk/net/ipv4/tcp_scalable.c b/trunk/net/ipv4/tcp_scalable.c index 4624501e9680..26d7486ee501 100644 --- a/trunk/net/ipv4/tcp_scalable.c +++ b/trunk/net/ipv4/tcp_scalable.c @@ -5,6 +5,7 @@ * John Heffner */ +#include #include #include diff --git a/trunk/net/ipv4/tcp_vegas.c b/trunk/net/ipv4/tcp_vegas.c index 490360b5b4bf..3b7403495052 100644 --- a/trunk/net/ipv4/tcp_vegas.c +++ b/trunk/net/ipv4/tcp_vegas.c @@ -31,6 +31,7 @@ * assumed senders never went idle. */ +#include #include #include #include diff --git a/trunk/net/ipv4/tcp_westwood.c b/trunk/net/ipv4/tcp_westwood.c index 5446312ffd2a..4247da1384bf 100644 --- a/trunk/net/ipv4/tcp_westwood.c +++ b/trunk/net/ipv4/tcp_westwood.c @@ -21,6 +21,7 @@ * ssthresh after packet loss. The probing phase is as the original Reno. */ +#include #include #include #include diff --git a/trunk/net/ipv4/udp.c b/trunk/net/ipv4/udp.c index 9bfcddad695b..3f93292b0ad8 100644 --- a/trunk/net/ipv4/udp.c +++ b/trunk/net/ipv4/udp.c @@ -91,6 +91,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/ipv4/xfrm4_policy.c b/trunk/net/ipv4/xfrm4_policy.c index 8f50eae47d03..c0465284dfac 100644 --- a/trunk/net/ipv4/xfrm4_policy.c +++ b/trunk/net/ipv4/xfrm4_policy.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index c250d0af10d7..4da664538f52 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -40,6 +40,7 @@ * status etc. */ +#include #include #include #include diff --git a/trunk/net/ipv6/af_inet6.c b/trunk/net/ipv6/af_inet6.c index 5a0ba58b86cc..e19457fe4f6e 100644 --- a/trunk/net/ipv6/af_inet6.c +++ b/trunk/net/ipv6/af_inet6.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -659,6 +660,8 @@ int inet6_sk_rebuild_header(struct sock *sk) } ip6_dst_store(sk, dst, NULL); + sk->sk_route_caps = dst->dev->features & + ~(NETIF_F_IP_CSUM | NETIF_F_TSO); } return 0; diff --git a/trunk/net/ipv6/ah6.c b/trunk/net/ipv6/ah6.c index 9d4831bd4335..d31c0d6c0448 100644 --- a/trunk/net/ipv6/ah6.c +++ b/trunk/net/ipv6/ah6.c @@ -24,6 +24,7 @@ * This file is derived from net/ipv4/ah.c. */ +#include #include #include #include diff --git a/trunk/net/ipv6/anycast.c b/trunk/net/ipv6/anycast.c index f6881d7a0385..39ec528923f6 100644 --- a/trunk/net/ipv6/anycast.c +++ b/trunk/net/ipv6/anycast.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/ipv6/esp6.c b/trunk/net/ipv6/esp6.c index a278d5e862fe..a15a6f320f70 100644 --- a/trunk/net/ipv6/esp6.c +++ b/trunk/net/ipv6/esp6.c @@ -24,6 +24,7 @@ * This file is derived from net/ipv4/esp.c */ +#include #include #include #include diff --git a/trunk/net/ipv6/exthdrs.c b/trunk/net/ipv6/exthdrs.c index 9d0ee7f0eeb5..a18d4256372c 100644 --- a/trunk/net/ipv6/exthdrs.c +++ b/trunk/net/ipv6/exthdrs.c @@ -179,7 +179,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) static struct inet6_protocol destopt_protocol = { .handler = ipv6_destopt_rcv, - .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR, + .flags = INET6_PROTO_NOPOLICY, }; void __init ipv6_destopt_init(void) @@ -340,7 +340,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) static struct inet6_protocol rthdr_protocol = { .handler = ipv6_rthdr_rcv, - .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR, + .flags = INET6_PROTO_NOPOLICY, }; void __init ipv6_rthdr_init(void) diff --git a/trunk/net/ipv6/inet6_connection_sock.c b/trunk/net/ipv6/inet6_connection_sock.c index 5c950cc79d80..eb2865d5ae28 100644 --- a/trunk/net/ipv6/inet6_connection_sock.c +++ b/trunk/net/ipv6/inet6_connection_sock.c @@ -13,6 +13,7 @@ * 2 of the License, or(at your option) any later version. */ +#include #include #include #include @@ -186,6 +187,8 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) } ip6_dst_store(sk, dst, NULL); + sk->sk_route_caps = dst->dev->features & + ~(NETIF_F_IP_CSUM | NETIF_F_TSO); } skb->dst = dst_clone(dst); diff --git a/trunk/net/ipv6/inet6_hashtables.c b/trunk/net/ipv6/inet6_hashtables.c index d2f3fc990bfa..2ae84c961678 100644 --- a/trunk/net/ipv6/inet6_hashtables.c +++ b/trunk/net/ipv6/inet6_hashtables.c @@ -14,6 +14,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include diff --git a/trunk/net/ipv6/ip6_fib.c b/trunk/net/ipv6/ip6_fib.c index 764221220afd..2cb6149349bf 100644 --- a/trunk/net/ipv6/ip6_fib.c +++ b/trunk/net/ipv6/ip6_fib.c @@ -19,6 +19,7 @@ * remove ip6_null_entry from the top of * routing table. */ +#include #include #include #include diff --git a/trunk/net/ipv6/ip6_flowlabel.c b/trunk/net/ipv6/ip6_flowlabel.c index 1d672b0547f2..f9ca63912fbf 100644 --- a/trunk/net/ipv6/ip6_flowlabel.c +++ b/trunk/net/ipv6/ip6_flowlabel.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/ipv6/ip6_input.c b/trunk/net/ipv6/ip6_input.c index df8f051c0fce..aceee252503d 100644 --- a/trunk/net/ipv6/ip6_input.c +++ b/trunk/net/ipv6/ip6_input.c @@ -84,9 +84,14 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt */ IP6CB(skb)->iif = skb->dst ? ((struct rt6_info *)skb->dst)->rt6i_idev->dev->ifindex : dev->ifindex; - if (unlikely(!pskb_may_pull(skb, sizeof(*hdr)))) + if (skb->len < sizeof(struct ipv6hdr)) goto err; + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) { + IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + goto drop; + } + hdr = skb->nh.ipv6h; if (hdr->version != 6) diff --git a/trunk/net/ipv6/ip6_output.c b/trunk/net/ipv6/ip6_output.c index 2c5b44575af0..abb94de33768 100644 --- a/trunk/net/ipv6/ip6_output.c +++ b/trunk/net/ipv6/ip6_output.c @@ -28,6 +28,7 @@ * for datagram xmit */ +#include #include #include #include @@ -229,7 +230,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, skb->priority = sk->sk_priority; mtu = dst_mtu(dst); - if ((skb->len <= mtu) || ipfragok || skb_shinfo(skb)->gso_size) { + if ((skb->len <= mtu) || ipfragok) { IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); @@ -834,7 +835,7 @@ static inline int ip6_ufo_append_data(struct sock *sk, /* specify the length of each IP datagram fragment*/ skb_shinfo(skb)->gso_size = mtu - fragheaderlen - sizeof(struct frag_hdr); - skb_shinfo(skb)->gso_type = SKB_GSO_UDP; + skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4; ipv6_select_ident(skb, &fhdr); skb_shinfo(skb)->ip6_frag_id = fhdr.identification; __skb_queue_tail(&sk->sk_write_queue, skb); diff --git a/trunk/net/ipv6/ip6_tunnel.c b/trunk/net/ipv6/ip6_tunnel.c index bc77c0e1a943..a995796b5a57 100644 --- a/trunk/net/ipv6/ip6_tunnel.c +++ b/trunk/net/ipv6/ip6_tunnel.c @@ -19,6 +19,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/ipv6/ipcomp6.c b/trunk/net/ipv6/ipcomp6.c index b285b0357084..f28cd37feed3 100644 --- a/trunk/net/ipv6/ipcomp6.c +++ b/trunk/net/ipv6/ipcomp6.c @@ -30,6 +30,7 @@ * The decompression of IP datagram MUST be done after the reassembly, * AH/ESP processing. */ +#include #include #include #include diff --git a/trunk/net/ipv6/ipv6_sockglue.c b/trunk/net/ipv6/ipv6_sockglue.c index c28e5c287447..4c20eeb3d568 100644 --- a/trunk/net/ipv6/ipv6_sockglue.c +++ b/trunk/net/ipv6/ipv6_sockglue.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -57,71 +58,9 @@ DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics) __read_mostly; -static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features) -{ - struct sk_buff *segs = ERR_PTR(-EINVAL); - struct ipv6hdr *ipv6h; - struct inet6_protocol *ops; - int proto; - - if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h)))) - goto out; - - ipv6h = skb->nh.ipv6h; - proto = ipv6h->nexthdr; - __skb_pull(skb, sizeof(*ipv6h)); - - rcu_read_lock(); - for (;;) { - struct ipv6_opt_hdr *opth; - int len; - - if (proto != NEXTHDR_HOP) { - ops = rcu_dereference(inet6_protos[proto]); - - if (unlikely(!ops)) - goto unlock; - - if (!(ops->flags & INET6_PROTO_GSO_EXTHDR)) - break; - } - - if (unlikely(!pskb_may_pull(skb, 8))) - goto unlock; - - opth = (void *)skb->data; - len = opth->hdrlen * 8 + 8; - - if (unlikely(!pskb_may_pull(skb, len))) - goto unlock; - - proto = opth->nexthdr; - __skb_pull(skb, len); - } - - skb->h.raw = skb->data; - if (likely(ops->gso_segment)) - segs = ops->gso_segment(skb, features); - -unlock: - rcu_read_unlock(); - - if (unlikely(IS_ERR(segs))) - goto out; - - for (skb = segs; skb; skb = skb->next) { - ipv6h = skb->nh.ipv6h; - ipv6h->payload_len = htons(skb->len - skb->mac_len); - } - -out: - return segs; -} - static struct packet_type ipv6_packet_type = { .type = __constant_htons(ETH_P_IPV6), .func = ipv6_rcv, - .gso_segment = ipv6_gso_segment, }; struct ip6_ra_chain *ip6_ra_chain; diff --git a/trunk/net/ipv6/ipv6_syms.c b/trunk/net/ipv6/ipv6_syms.c index dd4d1ce77769..16482785bdfd 100644 --- a/trunk/net/ipv6/ipv6_syms.c +++ b/trunk/net/ipv6/ipv6_syms.c @@ -1,4 +1,5 @@ +#include #include #include #include diff --git a/trunk/net/ipv6/mcast.c b/trunk/net/ipv6/mcast.c index 9d697d4dcffc..6e871afbb2c7 100644 --- a/trunk/net/ipv6/mcast.c +++ b/trunk/net/ipv6/mcast.c @@ -28,6 +28,7 @@ * - MLDv2 support */ +#include #include #include #include diff --git a/trunk/net/ipv6/ndisc.c b/trunk/net/ipv6/ndisc.c index b50055b9278d..dfa20d3be9b6 100644 --- a/trunk/net/ipv6/ndisc.c +++ b/trunk/net/ipv6/ndisc.c @@ -48,6 +48,7 @@ #endif #include +#include #include #include #include diff --git a/trunk/net/ipv6/netfilter/ip6_queue.c b/trunk/net/ipv6/netfilter/ip6_queue.c index 968a14be0d05..b4b7d441af25 100644 --- a/trunk/net/ipv6/netfilter/ip6_queue.c +++ b/trunk/net/ipv6/netfilter/ip6_queue.c @@ -505,7 +505,7 @@ ipq_rcv_skb(struct sk_buff *skb) if (type <= IPQM_BASE) return; - if (security_netlink_recv(skb, CAP_NET_ADMIN)) + if (security_netlink_recv(skb)) RCV_SKB_FAIL(-EPERM); write_lock_bh(&queue_lock); diff --git a/trunk/net/ipv6/netfilter/ip6_tables.c b/trunk/net/ipv6/netfilter/ip6_tables.c index 7ef143c0ebf6..2e72f89a7019 100644 --- a/trunk/net/ipv6/netfilter/ip6_tables.c +++ b/trunk/net/ipv6/netfilter/ip6_tables.c @@ -19,6 +19,7 @@ */ #include +#include #include #include #include @@ -1280,8 +1281,7 @@ int ip6t_register_table(struct xt_table *table, return ret; } - ret = xt_register_table(table, &bootstrap, newinfo); - if (ret != 0) { + if (xt_register_table(table, &bootstrap, newinfo) != 0) { xt_free_table_info(newinfo); return ret; } diff --git a/trunk/net/ipv6/netfilter/ip6t_REJECT.c b/trunk/net/ipv6/netfilter/ip6t_REJECT.c index 8629ba195d2d..de1175c27f6d 100644 --- a/trunk/net/ipv6/netfilter/ip6t_REJECT.c +++ b/trunk/net/ipv6/netfilter/ip6t_REJECT.c @@ -15,6 +15,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/trunk/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index c2ab38ff46af..2a71c3b669f1 100644 --- a/trunk/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/trunk/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -20,6 +20,7 @@ * structures. */ +#include #include #include #include diff --git a/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c b/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c index 00d5583807f7..c32a029e43f0 100644 --- a/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -14,6 +14,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv6/proc.c b/trunk/net/ipv6/proc.c index efee7a6301a8..779ddf77f4d4 100644 --- a/trunk/net/ipv6/proc.c +++ b/trunk/net/ipv6/proc.c @@ -17,6 +17,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv6/reassembly.c b/trunk/net/ipv6/reassembly.c index 4e299c69e1c6..eef985e010ea 100644 --- a/trunk/net/ipv6/reassembly.c +++ b/trunk/net/ipv6/reassembly.c @@ -28,6 +28,7 @@ * YOSHIFUJI,H. @USAGI Always remove fragment header to * calculate ICV correctly. */ +#include #include #include #include diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index 87c39c978cd0..8a777932786d 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -348,7 +349,7 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, (strict & RT6_SELECT_F_REACHABLE) && last && last != rt0) { /* no entries matched; do round-robin */ - static DEFINE_SPINLOCK(lock); + static spinlock_t lock = SPIN_LOCK_UNLOCKED; spin_lock(&lock); *head = rt0->u.next; rt0->u.next = last->u.next; diff --git a/trunk/net/ipv6/sit.c b/trunk/net/ipv6/sit.c index c56aeece2bf5..6578c3080f47 100644 --- a/trunk/net/ipv6/sit.c +++ b/trunk/net/ipv6/sit.c @@ -18,6 +18,7 @@ * Nate Thompson : 6to4 support */ +#include #include #include #include diff --git a/trunk/net/ipv6/sysctl_net_ipv6.c b/trunk/net/ipv6/sysctl_net_ipv6.c index 7a4639db1346..8eff9fa1e983 100644 --- a/trunk/net/ipv6/sysctl_net_ipv6.c +++ b/trunk/net/ipv6/sysctl_net_ipv6.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index 5bdcb9002cf7..a50eb306e9e2 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -26,6 +26,7 @@ */ #include +#include #include #include #include @@ -269,8 +270,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, ipv6_addr_copy(&np->saddr, saddr); inet->rcv_saddr = LOOPBACK4_IPV6; - sk->sk_gso_type = SKB_GSO_TCPV6; ip6_dst_store(sk, dst, NULL); + sk->sk_route_caps = dst->dev->features & + ~(NETIF_F_IP_CSUM | NETIF_F_TSO); icsk->icsk_ext_hdr_len = 0; if (np->opt) @@ -928,8 +930,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, * comment in that function for the gory details. -acme */ - sk->sk_gso_type = SKB_GSO_TCPV6; ip6_dst_store(newsk, dst, NULL); + newsk->sk_route_caps = dst->dev->features & + ~(NETIF_F_IP_CSUM | NETIF_F_TSO); newtcp6sk = (struct tcp6_sock *)newsk; inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; @@ -1466,8 +1469,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) dest->s6_addr32[0], dest->s6_addr32[1], dest->s6_addr32[2], dest->s6_addr32[3], destp, sp->sk_state, - tp->write_seq-tp->snd_una, - (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq), + tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq, timer_active, jiffies_to_clock_t(timer_expires - jiffies), icsk->icsk_retransmits, @@ -1603,7 +1605,6 @@ struct proto tcpv6_prot = { static struct inet6_protocol tcpv6_protocol = { .handler = tcp_v6_rcv, .err_handler = tcp_v6_err, - .gso_segment = tcp_tso_segment, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index ccc57f434cd3..8d3432a70f3a 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -23,6 +23,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/ipv6/xfrm6_policy.c b/trunk/net/ipv6/xfrm6_policy.c index 73cd250aecbb..ee715f2691e9 100644 --- a/trunk/net/ipv6/xfrm6_policy.c +++ b/trunk/net/ipv6/xfrm6_policy.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/ipv6/xfrm6_tunnel.c b/trunk/net/ipv6/xfrm6_tunnel.c index 6b44fe8516c3..d37768e5064f 100644 --- a/trunk/net/ipv6/xfrm6_tunnel.c +++ b/trunk/net/ipv6/xfrm6_tunnel.c @@ -21,6 +21,7 @@ * Based on net/ipv4/xfrm4_tunnel.c * */ +#include #include #include #include diff --git a/trunk/net/ipx/af_ipx.c b/trunk/net/ipx/af_ipx.c index aa34ff4b707c..811d998725bc 100644 --- a/trunk/net/ipx/af_ipx.c +++ b/trunk/net/ipx/af_ipx.c @@ -28,6 +28,7 @@ * See net/ipx/ChangeLog. */ +#include #include #include #include diff --git a/trunk/net/ipx/ipx_proc.c b/trunk/net/ipx/ipx_proc.c index 4c0c71206e54..1f73d9ea434d 100644 --- a/trunk/net/ipx/ipx_proc.c +++ b/trunk/net/ipx/ipx_proc.c @@ -4,6 +4,7 @@ * Copyright(C) Arnaldo Carvalho de Melo , 2002 */ +#include #include #ifdef CONFIG_PROC_FS #include diff --git a/trunk/net/ipx/ipx_route.c b/trunk/net/ipx/ipx_route.c index a30dbb1e08fb..bba3431cd9a5 100644 --- a/trunk/net/ipx/ipx_route.c +++ b/trunk/net/ipx/ipx_route.c @@ -7,6 +7,7 @@ * See net/ipx/ChangeLog. */ +#include #include #include #include diff --git a/trunk/net/ipx/sysctl_net_ipx.c b/trunk/net/ipx/sysctl_net_ipx.c index fa574735c76f..510eda96d10a 100644 --- a/trunk/net/ipx/sysctl_net_ipx.c +++ b/trunk/net/ipx/sysctl_net_ipx.c @@ -6,6 +6,7 @@ * Added /proc/sys/net/ipx/ipx_pprop_broadcasting - acme March 4, 2001 */ +#include #include #include diff --git a/trunk/net/irda/af_irda.c b/trunk/net/irda/af_irda.c index 7fae48a53bff..2f37c9f35e27 100644 --- a/trunk/net/irda/af_irda.c +++ b/trunk/net/irda/af_irda.c @@ -42,6 +42,7 @@ * ********************************************************************/ +#include #include #include #include diff --git a/trunk/net/irda/ircomm/ircomm_core.c b/trunk/net/irda/ircomm/ircomm_core.c index 9c4a902a9dba..286881978858 100644 --- a/trunk/net/irda/ircomm/ircomm_core.c +++ b/trunk/net/irda/ircomm/ircomm_core.c @@ -29,6 +29,7 @@ * ********************************************************************/ +#include #include #include #include diff --git a/trunk/net/irda/ircomm/ircomm_tty.c b/trunk/net/irda/ircomm/ircomm_tty.c index b400f27851fc..6f20b4206e08 100644 --- a/trunk/net/irda/ircomm/ircomm_tty.c +++ b/trunk/net/irda/ircomm/ircomm_tty.c @@ -30,6 +30,7 @@ * ********************************************************************/ +#include #include #include #include @@ -123,6 +124,7 @@ static int __init ircomm_tty_init(void) driver->owner = THIS_MODULE; driver->driver_name = "ircomm"; driver->name = "ircomm"; + driver->devfs_name = "ircomm"; driver->major = IRCOMM_TTY_MAJOR; driver->minor_start = IRCOMM_TTY_MINOR; driver->type = TTY_DRIVER_TYPE_SERIAL; diff --git a/trunk/net/irda/irda_device.c b/trunk/net/irda/irda_device.c index ba40e5495f58..e3debbdb67f5 100644 --- a/trunk/net/irda/irda_device.c +++ b/trunk/net/irda/irda_device.c @@ -29,6 +29,7 @@ * ********************************************************************/ +#include #include #include #include diff --git a/trunk/net/irda/iriap.c b/trunk/net/irda/iriap.c index a0472652a44e..2d2e2b1919f4 100644 --- a/trunk/net/irda/iriap.c +++ b/trunk/net/irda/iriap.c @@ -24,6 +24,7 @@ * ********************************************************************/ +#include #include #include #include diff --git a/trunk/net/irda/irlan/irlan_client.c b/trunk/net/irda/irlan/irlan_client.c index 95cf1234ea17..f8e6cb0db04b 100644 --- a/trunk/net/irda/irlan/irlan_client.c +++ b/trunk/net/irda/irlan/irlan_client.c @@ -173,14 +173,13 @@ void irlan_client_discovery_indication(discinfo_t *discovery, rcu_read_lock(); self = irlan_get_any(); if (self) { - IRDA_ASSERT(self->magic == IRLAN_MAGIC, goto out;); + IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;); IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __FUNCTION__ , daddr); irlan_client_wakeup(self, saddr, daddr); } -IRDA_ASSERT_LABEL(out:) rcu_read_unlock(); } diff --git a/trunk/net/irda/irlan/irlan_common.c b/trunk/net/irda/irlan/irlan_common.c index bd659dd545ac..657d12210578 100644 --- a/trunk/net/irda/irlan/irlan_common.c +++ b/trunk/net/irda/irlan/irlan_common.c @@ -23,6 +23,7 @@ * ********************************************************************/ +#include #include #include diff --git a/trunk/net/irda/irlan/irlan_eth.c b/trunk/net/irda/irlan/irlan_eth.c index b0ccc455b747..953e255d2bc8 100644 --- a/trunk/net/irda/irlan/irlan_eth.c +++ b/trunk/net/irda/irlan/irlan_eth.c @@ -25,6 +25,7 @@ * ********************************************************************/ +#include #include #include #include diff --git a/trunk/net/irda/irlap.c b/trunk/net/irda/irlap.c index cade355ac8af..a16528657b4c 100644 --- a/trunk/net/irda/irlap.c +++ b/trunk/net/irda/irlap.c @@ -29,6 +29,7 @@ * ********************************************************************/ +#include #include #include #include diff --git a/trunk/net/irda/irlap_event.c b/trunk/net/irda/irlap_event.c index 99faff68c399..a505b5457608 100644 --- a/trunk/net/irda/irlap_event.c +++ b/trunk/net/irda/irlap_event.c @@ -25,6 +25,7 @@ * ********************************************************************/ +#include #include #include #include diff --git a/trunk/net/irda/irlmp.c b/trunk/net/irda/irlmp.c index 129ad64c15bb..57ea160f470b 100644 --- a/trunk/net/irda/irlmp.c +++ b/trunk/net/irda/irlmp.c @@ -24,6 +24,7 @@ * ********************************************************************/ +#include #include #include #include diff --git a/trunk/net/irda/irlmp_event.c b/trunk/net/irda/irlmp_event.c index 4c90dd1b4503..26649f6528e6 100644 --- a/trunk/net/irda/irlmp_event.c +++ b/trunk/net/irda/irlmp_event.c @@ -24,6 +24,7 @@ * ********************************************************************/ +#include #include #include diff --git a/trunk/net/irda/irlmp_frame.c b/trunk/net/irda/irlmp_frame.c index 39761a1d18f5..91cd268172fa 100644 --- a/trunk/net/irda/irlmp_frame.c +++ b/trunk/net/irda/irlmp_frame.c @@ -24,6 +24,7 @@ * ********************************************************************/ +#include #include #include diff --git a/trunk/net/irda/irmod.c b/trunk/net/irda/irmod.c index 2869b16e417d..634901dd156f 100644 --- a/trunk/net/irda/irmod.c +++ b/trunk/net/irda/irmod.c @@ -31,6 +31,7 @@ * Jean II */ +#include #include #include diff --git a/trunk/net/irda/irnet/irnet.h b/trunk/net/irda/irnet/irnet.h index 80887528e77e..e4fe1e80029c 100644 --- a/trunk/net/irda/irnet/irnet.h +++ b/trunk/net/irda/irnet/irnet.h @@ -244,10 +244,12 @@ #include #include #include +#include #include #include #include #include +#include #include /* isspace() */ #include #include diff --git a/trunk/net/irda/irsysctl.c b/trunk/net/irda/irsysctl.c index 86805c3d8324..1b1c4193359a 100644 --- a/trunk/net/irda/irsysctl.c +++ b/trunk/net/irda/irsysctl.c @@ -23,6 +23,7 @@ * ********************************************************************/ +#include #include #include #include diff --git a/trunk/net/irda/irttp.c b/trunk/net/irda/irttp.c index 49c51c5f1a86..8aff254cb418 100644 --- a/trunk/net/irda/irttp.c +++ b/trunk/net/irda/irttp.c @@ -24,6 +24,7 @@ * ********************************************************************/ +#include #include #include #include diff --git a/trunk/net/irda/qos.c b/trunk/net/irda/qos.c index 95a69c013ee8..ddfb5c502a90 100644 --- a/trunk/net/irda/qos.c +++ b/trunk/net/irda/qos.c @@ -30,6 +30,7 @@ * ********************************************************************/ +#include #include #include diff --git a/trunk/net/irda/timer.c b/trunk/net/irda/timer.c index 3871a2b911f9..0e17f976add6 100644 --- a/trunk/net/irda/timer.c +++ b/trunk/net/irda/timer.c @@ -25,6 +25,7 @@ ********************************************************************/ #include +#include #include #include diff --git a/trunk/net/key/af_key.c b/trunk/net/key/af_key.c index 3a95b2ee4690..d5e2121ea207 100644 --- a/trunk/net/key/af_key.c +++ b/trunk/net/key/af_key.c @@ -14,6 +14,7 @@ * Derek Atkins */ +#include #include #include #include diff --git a/trunk/net/llc/af_llc.c b/trunk/net/llc/af_llc.c index d6cfe84d521b..75c9b1480801 100644 --- a/trunk/net/llc/af_llc.c +++ b/trunk/net/llc/af_llc.c @@ -20,6 +20,7 @@ * * See the GNU General Public License for more details. */ +#include #include #include #include diff --git a/trunk/net/llc/llc_if.c b/trunk/net/llc/llc_if.c index a89917130a7b..5ae47be7dde0 100644 --- a/trunk/net/llc/llc_if.c +++ b/trunk/net/llc/llc_if.c @@ -11,6 +11,7 @@ * * See the GNU General Public License for more details. */ +#include #include #include #include diff --git a/trunk/net/llc/llc_proc.c b/trunk/net/llc/llc_proc.c index 19308fece3ad..bd531cb235a7 100644 --- a/trunk/net/llc/llc_proc.c +++ b/trunk/net/llc/llc_proc.c @@ -12,6 +12,7 @@ * See the GNU General Public License for more details. */ +#include #include #include #include diff --git a/trunk/net/llc/llc_station.c b/trunk/net/llc/llc_station.c index 8275bd33bd9d..f37dbf8ef126 100644 --- a/trunk/net/llc/llc_station.c +++ b/trunk/net/llc/llc_station.c @@ -11,6 +11,7 @@ * * See the GNU General Public License for more details. */ +#include #include #include #include diff --git a/trunk/net/llc/sysctl_net_llc.c b/trunk/net/llc/sysctl_net_llc.c index 45d7dd92a088..d1eaddb13633 100644 --- a/trunk/net/llc/sysctl_net_llc.c +++ b/trunk/net/llc/sysctl_net_llc.c @@ -4,6 +4,7 @@ * Arnaldo Carvalho de Melo */ +#include #include #include #include diff --git a/trunk/net/netfilter/Kconfig b/trunk/net/netfilter/Kconfig index 42a178aa30f9..b1622b7de1cf 100644 --- a/trunk/net/netfilter/Kconfig +++ b/trunk/net/netfilter/Kconfig @@ -411,10 +411,7 @@ config NETFILTER_XT_MATCH_STATISTIC tristate '"statistic" match support' depends on NETFILTER_XTABLES help - This option adds a `statistic' match, which allows you to match - on packets periodically or randomly with a given percentage. - - To compile it as a module, choose M here. If unsure, say N. + statistic module config NETFILTER_XT_MATCH_STRING tristate '"string" match support' diff --git a/trunk/net/netfilter/core.c b/trunk/net/netfilter/core.c index 5d29d5e23624..8455a32ea5c4 100644 --- a/trunk/net/netfilter/core.c +++ b/trunk/net/netfilter/core.c @@ -10,6 +10,7 @@ * 15-Mar-2000: Added NF_REPEAT --RR. * 08-May-2003: Internal logging interface added by Jozsef Kadlecsik. */ +#include #include #include #include diff --git a/trunk/net/netfilter/nf_conntrack_core.c b/trunk/net/netfilter/nf_conntrack_core.c index 8f2261965a68..cd299f4b7db1 100644 --- a/trunk/net/netfilter/nf_conntrack_core.c +++ b/trunk/net/netfilter/nf_conntrack_core.c @@ -29,6 +29,7 @@ * Derived from net/ipv4/netfilter/ip_conntrack_core.c */ +#include #include #include #include diff --git a/trunk/net/netfilter/nf_conntrack_ftp.c b/trunk/net/netfilter/nf_conntrack_ftp.c index 960972d225f9..11d3be243536 100644 --- a/trunk/net/netfilter/nf_conntrack_ftp.c +++ b/trunk/net/netfilter/nf_conntrack_ftp.c @@ -15,6 +15,7 @@ * Derived from net/ipv4/netfilter/ip_conntrack_ftp.c */ +#include #include #include #include diff --git a/trunk/net/netfilter/nf_conntrack_l3proto_generic.c b/trunk/net/netfilter/nf_conntrack_l3proto_generic.c index 21e0bc91cf23..3fc58e454d4e 100644 --- a/trunk/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/trunk/net/netfilter/nf_conntrack_l3proto_generic.c @@ -15,6 +15,7 @@ * Yasuyuki Kozakai @USAGI */ +#include #include #include #include diff --git a/trunk/net/netfilter/nf_conntrack_netlink.c b/trunk/net/netfilter/nf_conntrack_netlink.c index af4845971f70..b8c7c567c9df 100644 --- a/trunk/net/netfilter/nf_conntrack_netlink.c +++ b/trunk/net/netfilter/nf_conntrack_netlink.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include diff --git a/trunk/net/netfilter/nf_conntrack_proto_sctp.c b/trunk/net/netfilter/nf_conntrack_proto_sctp.c index 9bd8a7877fd5..0c6da496cfa9 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_sctp.c +++ b/trunk/net/netfilter/nf_conntrack_proto_sctp.c @@ -28,8 +28,6 @@ #include #include #include -#include -#include #include #include @@ -261,7 +259,7 @@ static int do_basic_checks(struct nf_conn *conntrack, } DEBUGP("Basic checks passed\n"); - return count == 0; + return 0; } static int new_state(enum ip_conntrack_dir dir, diff --git a/trunk/net/netfilter/nf_conntrack_proto_tcp.c b/trunk/net/netfilter/nf_conntrack_proto_tcp.c index af8adcba23a7..12fb7c0a1509 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_tcp.c +++ b/trunk/net/netfilter/nf_conntrack_proto_tcp.c @@ -24,6 +24,7 @@ * version 2.2 */ +#include #include #include #include diff --git a/trunk/net/netfilter/nf_conntrack_standalone.c b/trunk/net/netfilter/nf_conntrack_standalone.c index 5fcab2ef231f..e34c574f0351 100644 --- a/trunk/net/netfilter/nf_conntrack_standalone.c +++ b/trunk/net/netfilter/nf_conntrack_standalone.c @@ -17,6 +17,7 @@ * Derived from net/ipv4/netfilter/ip_conntrack_standalone.c */ +#include #include #include #include diff --git a/trunk/net/netfilter/nf_internals.h b/trunk/net/netfilter/nf_internals.h index 86e392bfe833..6bdee2910617 100644 --- a/trunk/net/netfilter/nf_internals.h +++ b/trunk/net/netfilter/nf_internals.h @@ -1,6 +1,7 @@ #ifndef _NF_INTERNALS_H #define _NF_INTERNALS_H +#include #include #include #include diff --git a/trunk/net/netfilter/nf_log.c b/trunk/net/netfilter/nf_log.c index 8901b3a07f7e..3e76bd0824a2 100644 --- a/trunk/net/netfilter/nf_log.c +++ b/trunk/net/netfilter/nf_log.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/trunk/net/netfilter/nf_queue.c b/trunk/net/netfilter/nf_queue.c index bb6fcee452ca..ee8f70889f47 100644 --- a/trunk/net/netfilter/nf_queue.c +++ b/trunk/net/netfilter/nf_queue.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/trunk/net/netfilter/nf_sockopt.c b/trunk/net/netfilter/nf_sockopt.c index c2e44e90e437..0a63d7dac7be 100644 --- a/trunk/net/netfilter/nf_sockopt.c +++ b/trunk/net/netfilter/nf_sockopt.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/trunk/net/netfilter/nfnetlink.c b/trunk/net/netfilter/nfnetlink.c index 52fdfa2686c9..b88e82a1a987 100644 --- a/trunk/net/netfilter/nfnetlink.c +++ b/trunk/net/netfilter/nfnetlink.c @@ -14,6 +14,7 @@ * of the GNU General Public License, incorporated herein by reference. */ +#include #include #include #include @@ -228,7 +229,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, NFNL_SUBSYS_ID(nlh->nlmsg_type), NFNL_MSG_TYPE(nlh->nlmsg_type)); - if (security_netlink_recv(skb, CAP_NET_ADMIN)) { + if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) { DEBUGP("missing CAP_NET_ADMIN\n"); *errp = -EPERM; return -1; diff --git a/trunk/net/netfilter/nfnetlink_queue.c b/trunk/net/netfilter/nfnetlink_queue.c index 49ef41e34c48..86a4ac33de34 100644 --- a/trunk/net/netfilter/nfnetlink_queue.c +++ b/trunk/net/netfilter/nfnetlink_queue.c @@ -680,19 +680,11 @@ dev_cmp(struct nfqnl_queue_entry *entry, unsigned long ifindex) if (entinf->indev) if (entinf->indev->ifindex == ifindex) return 1; + if (entinf->outdev) if (entinf->outdev->ifindex == ifindex) return 1; -#ifdef CONFIG_BRIDGE_NETFILTER - if (entry->skb->nf_bridge) { - if (entry->skb->nf_bridge->physindev && - entry->skb->nf_bridge->physindev->ifindex == ifindex) - return 1; - if (entry->skb->nf_bridge->physoutdev && - entry->skb->nf_bridge->physoutdev->ifindex == ifindex) - return 1; - } -#endif + return 0; } diff --git a/trunk/net/netfilter/x_tables.c b/trunk/net/netfilter/x_tables.c index 174e8f970095..99293c63ff73 100644 --- a/trunk/net/netfilter/x_tables.c +++ b/trunk/net/netfilter/x_tables.c @@ -13,6 +13,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/netfilter/xt_policy.c b/trunk/net/netfilter/xt_policy.c index ba1ca03abad3..a3aa62fbda6f 100644 --- a/trunk/net/netfilter/xt_policy.c +++ b/trunk/net/netfilter/xt_policy.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/netfilter/xt_sctp.c b/trunk/net/netfilter/xt_sctp.c index 843383e01d41..9316c753692f 100644 --- a/trunk/net/netfilter/xt_sctp.c +++ b/trunk/net/netfilter/xt_sctp.c @@ -151,7 +151,7 @@ match(const struct sk_buff *skb, && SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) && (ntohs(sh->dest) <= info->dpts[1])), XT_SCTP_DEST_PORTS, info->flags, info->invflags) - && SCCHECK(match_packet(skb, protoff + sizeof (sctp_sctphdr_t), + && SCCHECK(match_packet(skb, protoff, info->chunkmap, info->chunk_match_type, info->flag_info, info->flag_count, hotdrop), diff --git a/trunk/net/netfilter/xt_tcpudp.c b/trunk/net/netfilter/xt_tcpudp.c index a9a63aa68936..1b61dac9c873 100644 --- a/trunk/net/netfilter/xt_tcpudp.c +++ b/trunk/net/netfilter/xt_tcpudp.c @@ -260,7 +260,7 @@ static int __init xt_tcpudp_init(void) return ret; out_unreg_udp: - xt_unregister_match(&udp_matchstruct); + xt_unregister_match(&tcp_matchstruct); out_unreg_tcp6: xt_unregister_match(&tcp6_matchstruct); out_unreg_tcp: diff --git a/trunk/net/netlink/af_netlink.c b/trunk/net/netlink/af_netlink.c index 70cee82a98bf..3862e73d14d7 100644 --- a/trunk/net/netlink/af_netlink.c +++ b/trunk/net/netlink/af_netlink.c @@ -21,6 +21,7 @@ * mandatory if CONFIG_NET=y these days */ +#include #include #include diff --git a/trunk/net/netlink/attr.c b/trunk/net/netlink/attr.c index dddbd15135a8..fffef4ab276f 100644 --- a/trunk/net/netlink/attr.c +++ b/trunk/net/netlink/attr.c @@ -5,6 +5,7 @@ * Alexey Kuznetsov */ +#include #include #include #include diff --git a/trunk/net/netlink/genetlink.c b/trunk/net/netlink/genetlink.c index a298f77cc3e3..f329b72578f5 100644 --- a/trunk/net/netlink/genetlink.c +++ b/trunk/net/netlink/genetlink.c @@ -5,6 +5,7 @@ * Thomas Graf */ +#include #include #include #include @@ -319,7 +320,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, goto errout; } - if ((ops->flags & GENL_ADMIN_PERM) && security_netlink_recv(skb, CAP_NET_ADMIN)) { + if ((ops->flags & GENL_ADMIN_PERM) && security_netlink_recv(skb)) { err = -EPERM; goto errout; } diff --git a/trunk/net/netrom/af_netrom.c b/trunk/net/netrom/af_netrom.c index eba6df054b1f..3669cb953e6e 100644 --- a/trunk/net/netrom/af_netrom.c +++ b/trunk/net/netrom/af_netrom.c @@ -8,6 +8,7 @@ * Copyright Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk) * Copyright Darryl Miles G7LED (dlm@g7led.demon.co.uk) */ +#include #include #include #include diff --git a/trunk/net/netrom/nr_dev.c b/trunk/net/netrom/nr_dev.c index 9b8eb54971ab..621e5586ab03 100644 --- a/trunk/net/netrom/nr_dev.c +++ b/trunk/net/netrom/nr_dev.c @@ -6,6 +6,7 @@ * * Copyright Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) */ +#include #include #include #include diff --git a/trunk/net/netrom/nr_route.c b/trunk/net/netrom/nr_route.c index c11737f472d6..b3b9097c87c7 100644 --- a/trunk/net/netrom/nr_route.c +++ b/trunk/net/netrom/nr_route.c @@ -725,17 +725,15 @@ void nr_link_failed(ax25_cb *ax25, int reason) struct nr_node *nr_node = NULL; spin_lock_bh(&nr_neigh_list_lock); - nr_neigh_for_each(s, node, &nr_neigh_list) { + nr_neigh_for_each(s, node, &nr_neigh_list) if (s->ax25 == ax25) { nr_neigh_hold(s); nr_neigh = s; break; } - } spin_unlock_bh(&nr_neigh_list_lock); - if (nr_neigh == NULL) - return; + if (nr_neigh == NULL) return; nr_neigh->ax25 = NULL; ax25_cb_put(ax25); @@ -745,13 +743,11 @@ void nr_link_failed(ax25_cb *ax25, int reason) return; } spin_lock_bh(&nr_node_list_lock); - nr_node_for_each(nr_node, node, &nr_node_list) { + nr_node_for_each(nr_node, node, &nr_node_list) nr_node_lock(nr_node); - if (nr_node->which < nr_node->count && - nr_node->routes[nr_node->which].neighbour == nr_neigh) + if (nr_node->which < nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh) nr_node->which++; nr_node_unlock(nr_node); - } spin_unlock_bh(&nr_node_list_lock); nr_neigh_put(nr_neigh); } diff --git a/trunk/net/packet/af_packet.c b/trunk/net/packet/af_packet.c index f9cef3671593..9db7dbdb16e6 100644 --- a/trunk/net/packet/af_packet.c +++ b/trunk/net/packet/af_packet.c @@ -49,6 +49,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/rose/af_rose.c b/trunk/net/rose/af_rose.c index 7799fe82aeb6..55564efccf11 100644 --- a/trunk/net/rose/af_rose.c +++ b/trunk/net/rose/af_rose.c @@ -10,6 +10,7 @@ * Copyright (C) Tomi Manninen OH2BNS (oh2bns@sral.fi) */ +#include #include #include #include diff --git a/trunk/net/rose/rose_dev.c b/trunk/net/rose/rose_dev.c index 9d0bf2a1ea3f..2a1bf8e119e5 100644 --- a/trunk/net/rose/rose_dev.c +++ b/trunk/net/rose/rose_dev.c @@ -6,6 +6,7 @@ * * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) */ +#include #include #include #include diff --git a/trunk/net/rxrpc/call.c b/trunk/net/rxrpc/call.c index d07122b57e0d..c4aeb7d40266 100644 --- a/trunk/net/rxrpc/call.c +++ b/trunk/net/rxrpc/call.c @@ -1098,7 +1098,8 @@ static void rxrpc_call_receive_data_packet(struct rxrpc_call *call, call->app_ready_seq = pmsg->seq; call->app_ready_qty += pmsg->dsize; - list_move_tail(&pmsg->link, &call->app_readyq); + list_del_init(&pmsg->link); + list_add_tail(&pmsg->link, &call->app_readyq); } /* see if we've got the last packet yet */ diff --git a/trunk/net/rxrpc/connection.c b/trunk/net/rxrpc/connection.c index 573b572f8f91..0e0a4553499f 100644 --- a/trunk/net/rxrpc/connection.c +++ b/trunk/net/rxrpc/connection.c @@ -402,7 +402,8 @@ void rxrpc_put_connection(struct rxrpc_connection *conn) /* move to graveyard queue */ _debug("burying connection: {%08x}", ntohl(conn->conn_id)); - list_move_tail(&conn->link, &peer->conn_graveyard); + list_del(&conn->link); + list_add_tail(&conn->link, &peer->conn_graveyard); rxrpc_krxtimod_add_timer(&conn->timeout, rxrpc_conn_timeout * HZ); diff --git a/trunk/net/rxrpc/krxsecd.c b/trunk/net/rxrpc/krxsecd.c index cea4eb5e2497..1aadd026d354 100644 --- a/trunk/net/rxrpc/krxsecd.c +++ b/trunk/net/rxrpc/krxsecd.c @@ -160,7 +160,8 @@ void rxrpc_krxsecd_clear_transport(struct rxrpc_transport *trans) list_for_each_safe(_p, _n, &rxrpc_krxsecd_initmsgq) { msg = list_entry(_p, struct rxrpc_message, link); if (msg->trans == trans) { - list_move_tail(&msg->link, &tmp); + list_del(&msg->link); + list_add_tail(&msg->link, &tmp); atomic_dec(&rxrpc_krxsecd_qcount); } } diff --git a/trunk/net/rxrpc/rxrpc_syms.c b/trunk/net/rxrpc/rxrpc_syms.c index 9896fd87a4d4..56adf16fed0c 100644 --- a/trunk/net/rxrpc/rxrpc_syms.c +++ b/trunk/net/rxrpc/rxrpc_syms.c @@ -9,6 +9,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include diff --git a/trunk/net/rxrpc/sysctl.c b/trunk/net/rxrpc/sysctl.c index 6374df7e77d1..fbf98729c748 100644 --- a/trunk/net/rxrpc/sysctl.c +++ b/trunk/net/rxrpc/sysctl.c @@ -9,6 +9,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/net/sched/Kconfig b/trunk/net/sched/Kconfig index 8298ea9ffe19..13eeee582886 100644 --- a/trunk/net/sched/Kconfig +++ b/trunk/net/sched/Kconfig @@ -305,7 +305,7 @@ config NET_CLS_U32 tristate "Universal 32bit comparisons w/ hashing (U32)" select NET_CLS ---help--- - Say Y here to be able to classify packets using a universal + Say Y here to be able to classify packetes using a universal 32bit pieces based comparison scheme. To compile this code as a module, choose M here: the @@ -485,7 +485,7 @@ config NET_ACT_IPT tristate "IPtables targets" depends on NET_CLS_ACT && NETFILTER && IP_NF_IPTABLES ---help--- - Say Y here to be able to invoke iptables targets after successful + Say Y here to be able to invoke iptables targets after succesful classification. To compile this code as a module, choose M here: the @@ -537,8 +537,8 @@ config NET_ESTIMATOR ---help--- Say Y here to allow using rate estimators to estimate the current rate-of-flow for network devices, queues, etc. This module is - automatically selected if needed but can be selected manually for - statistical purposes. + automaticaly selected if needed but can be selected manually for + statstical purposes. endif # NET_SCHED diff --git a/trunk/net/sched/act_api.c b/trunk/net/sched/act_api.c index 5b9397b33238..2ffa11c6e8de 100644 --- a/trunk/net/sched/act_api.c +++ b/trunk/net/sched/act_api.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/sched/act_gact.c b/trunk/net/sched/act_gact.c index e75a147ad60f..a1e68f78dcc2 100644 --- a/trunk/net/sched/act_gact.c +++ b/trunk/net/sched/act_gact.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/sched/act_ipt.c b/trunk/net/sched/act_ipt.c index d799e01248c4..37640c6fc014 100644 --- a/trunk/net/sched/act_ipt.c +++ b/trunk/net/sched/act_ipt.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/sched/act_mirred.c b/trunk/net/sched/act_mirred.c index fc562047ecc5..4fcccbd50885 100644 --- a/trunk/net/sched/act_mirred.c +++ b/trunk/net/sched/act_mirred.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/sched/act_pedit.c b/trunk/net/sched/act_pedit.c index 58b3a8652042..1742a68e0122 100644 --- a/trunk/net/sched/act_pedit.c +++ b/trunk/net/sched/act_pedit.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/sched/act_police.c b/trunk/net/sched/act_police.c index 47e00bd9625e..24c348fa8922 100644 --- a/trunk/net/sched/act_police.c +++ b/trunk/net/sched/act_police.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/sched/act_simple.c b/trunk/net/sched/act_simple.c index 17105c82537f..e5f2e1f431e2 100644 --- a/trunk/net/sched/act_simple.c +++ b/trunk/net/sched/act_simple.c @@ -10,6 +10,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/sched/cls_api.c b/trunk/net/sched/cls_api.c index 7e14f14058e9..b4d89fbb3782 100644 --- a/trunk/net/sched/cls_api.c +++ b/trunk/net/sched/cls_api.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/sched/cls_basic.c b/trunk/net/sched/cls_basic.c index 61507f006b11..dfb300bb6baa 100644 --- a/trunk/net/sched/cls_basic.c +++ b/trunk/net/sched/cls_basic.c @@ -9,6 +9,7 @@ * Authors: Thomas Graf */ +#include #include #include #include diff --git a/trunk/net/sched/cls_fw.c b/trunk/net/sched/cls_fw.c index d41de91fc4f6..75470486e405 100644 --- a/trunk/net/sched/cls_fw.c +++ b/trunk/net/sched/cls_fw.c @@ -18,6 +18,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/sched/cls_route.c b/trunk/net/sched/cls_route.c index c2e71900f7bd..520ff716dab2 100644 --- a/trunk/net/sched/cls_route.c +++ b/trunk/net/sched/cls_route.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/sched/cls_rsvp.h b/trunk/net/sched/cls_rsvp.h index ba8741971629..572f06be3b02 100644 --- a/trunk/net/sched/cls_rsvp.h +++ b/trunk/net/sched/cls_rsvp.h @@ -65,6 +65,7 @@ Well, as result, despite its simplicity, we get a pretty powerful classification engine. */ +#include struct rsvp_head { diff --git a/trunk/net/sched/cls_tcindex.c b/trunk/net/sched/cls_tcindex.c index 7870e7bb0bac..9f921174c8ab 100644 --- a/trunk/net/sched/cls_tcindex.c +++ b/trunk/net/sched/cls_tcindex.c @@ -4,6 +4,7 @@ * Written 1998,1999 by Werner Almesberger, EPFL ICA */ +#include #include #include #include diff --git a/trunk/net/sched/cls_u32.c b/trunk/net/sched/cls_u32.c index d712edcd1bcf..78e052591fa9 100644 --- a/trunk/net/sched/cls_u32.c +++ b/trunk/net/sched/cls_u32.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/sched/em_cmp.c b/trunk/net/sched/em_cmp.c index 8ed93c39b4ea..bf1f00f8b1bf 100644 --- a/trunk/net/sched/em_cmp.c +++ b/trunk/net/sched/em_cmp.c @@ -9,6 +9,7 @@ * Authors: Thomas Graf */ +#include #include #include #include diff --git a/trunk/net/sched/em_meta.c b/trunk/net/sched/em_meta.c index 698372954f4d..700844d49d79 100644 --- a/trunk/net/sched/em_meta.c +++ b/trunk/net/sched/em_meta.c @@ -58,6 +58,7 @@ * only available if that subsytem is enabled in the kernel. */ +#include #include #include #include diff --git a/trunk/net/sched/em_nbyte.c b/trunk/net/sched/em_nbyte.c index cc80babfd79f..71ea926a9f09 100644 --- a/trunk/net/sched/em_nbyte.c +++ b/trunk/net/sched/em_nbyte.c @@ -9,6 +9,7 @@ * Authors: Thomas Graf */ +#include #include #include #include diff --git a/trunk/net/sched/em_text.c b/trunk/net/sched/em_text.c index aa17d8f7c4c8..77beabc91fa3 100644 --- a/trunk/net/sched/em_text.c +++ b/trunk/net/sched/em_text.c @@ -9,6 +9,7 @@ * Authors: Thomas Graf */ +#include #include #include #include diff --git a/trunk/net/sched/em_u32.c b/trunk/net/sched/em_u32.c index e3ddfce0ac8d..34e7e51e601e 100644 --- a/trunk/net/sched/em_u32.c +++ b/trunk/net/sched/em_u32.c @@ -12,6 +12,7 @@ * Based on net/sched/cls_u32.c */ +#include #include #include #include diff --git a/trunk/net/sched/ematch.c b/trunk/net/sched/ematch.c index 2405a86093a2..5cb956b721e8 100644 --- a/trunk/net/sched/ematch.c +++ b/trunk/net/sched/ematch.c @@ -81,6 +81,7 @@ * open up a beer to watch the compilation going. */ +#include #include #include #include diff --git a/trunk/net/sched/sch_api.c b/trunk/net/sched/sch_api.c index c7844bacbbcb..31570b9a6e9a 100644 --- a/trunk/net/sched/sch_api.c +++ b/trunk/net/sched/sch_api.c @@ -15,6 +15,7 @@ * Jamal Hadi Salim : 990601: ingress support */ +#include #include #include #include diff --git a/trunk/net/sched/sch_atm.c b/trunk/net/sched/sch_atm.c index dbf44da0912f..ac7cb60d1e25 100644 --- a/trunk/net/sched/sch_atm.c +++ b/trunk/net/sched/sch_atm.c @@ -3,6 +3,7 @@ /* Written 1998-2000 by Werner Almesberger, EPFL ICA */ +#include #include #include #include diff --git a/trunk/net/sched/sch_blackhole.c b/trunk/net/sched/sch_blackhole.c index cb0c456aa349..81f0b8346d17 100644 --- a/trunk/net/sched/sch_blackhole.c +++ b/trunk/net/sched/sch_blackhole.c @@ -11,6 +11,7 @@ * Note: Quantum tunneling is not supported. */ +#include #include #include #include diff --git a/trunk/net/sched/sch_cbq.c b/trunk/net/sched/sch_cbq.c index 80b7f6a8d008..6cd81708bf71 100644 --- a/trunk/net/sched/sch_cbq.c +++ b/trunk/net/sched/sch_cbq.c @@ -10,6 +10,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/sched/sch_dsmark.c b/trunk/net/sched/sch_dsmark.c index 11c8a2119b96..f6320ca70493 100644 --- a/trunk/net/sched/sch_dsmark.c +++ b/trunk/net/sched/sch_dsmark.c @@ -3,6 +3,7 @@ /* Written 1998-2000 by Werner Almesberger, EPFL ICA */ +#include #include #include #include diff --git a/trunk/net/sched/sch_fifo.c b/trunk/net/sched/sch_fifo.c index c2689f4ba8de..033083bf0e74 100644 --- a/trunk/net/sched/sch_fifo.c +++ b/trunk/net/sched/sch_fifo.c @@ -9,6 +9,7 @@ * Authors: Alexey Kuznetsov, */ +#include #include #include #include diff --git a/trunk/net/sched/sch_generic.c b/trunk/net/sched/sch_generic.c index d735f51686a1..74d4a1dceeec 100644 --- a/trunk/net/sched/sch_generic.c +++ b/trunk/net/sched/sch_generic.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/net/sched/sch_gred.c b/trunk/net/sched/sch_gred.c index 0cafdd5feb1b..29a2dd9f3029 100644 --- a/trunk/net/sched/sch_gred.c +++ b/trunk/net/sched/sch_gred.c @@ -18,6 +18,7 @@ * For all the glorious comments look at include/net/red.h */ +#include #include #include #include diff --git a/trunk/net/sched/sch_hfsc.c b/trunk/net/sched/sch_hfsc.c index 6b1b4a981e88..f1c7bd29f2cd 100644 --- a/trunk/net/sched/sch_hfsc.c +++ b/trunk/net/sched/sch_hfsc.c @@ -50,6 +50,7 @@ */ #include +#include #include #include #include diff --git a/trunk/net/sched/sch_htb.c b/trunk/net/sched/sch_htb.c index 34afe41fa2f3..3ec95df4a85e 100644 --- a/trunk/net/sched/sch_htb.c +++ b/trunk/net/sched/sch_htb.c @@ -27,6 +27,7 @@ * * $Id: sch_htb.c,v 1.25 2003/12/07 11:08:25 devik Exp devik $ */ +#include #include #include #include diff --git a/trunk/net/sched/sch_ingress.c b/trunk/net/sched/sch_ingress.c index c3242f727d41..8edc32a6ad2f 100644 --- a/trunk/net/sched/sch_ingress.c +++ b/trunk/net/sched/sch_ingress.c @@ -7,6 +7,7 @@ * Authors: Jamal Hadi Salim 1999 */ +#include #include #include #include diff --git a/trunk/net/sched/sch_netem.c b/trunk/net/sched/sch_netem.c index c5bd8064e6d8..5a4a4d0ae502 100644 --- a/trunk/net/sched/sch_netem.c +++ b/trunk/net/sched/sch_netem.c @@ -13,6 +13,7 @@ * Catalin(ux aka Dino) BOIE */ +#include #include #include #include diff --git a/trunk/net/sched/sch_prio.c b/trunk/net/sched/sch_prio.c index a5fa03c0c19b..3395ca7bcadf 100644 --- a/trunk/net/sched/sch_prio.c +++ b/trunk/net/sched/sch_prio.c @@ -11,6 +11,7 @@ * Init -- EINVAL when opt undefined */ +#include #include #include #include diff --git a/trunk/net/sched/sch_red.c b/trunk/net/sched/sch_red.c index d65cadddea69..2be563cba72b 100644 --- a/trunk/net/sched/sch_red.c +++ b/trunk/net/sched/sch_red.c @@ -14,6 +14,7 @@ * J Hadi Salim 980816: ECN support */ +#include #include #include #include diff --git a/trunk/net/sched/sch_sfq.c b/trunk/net/sched/sch_sfq.c index d0d6e595a78c..e057768f68b4 100644 --- a/trunk/net/sched/sch_sfq.c +++ b/trunk/net/sched/sch_sfq.c @@ -9,6 +9,7 @@ * Authors: Alexey Kuznetsov, */ +#include #include #include #include diff --git a/trunk/net/sched/sch_tbf.c b/trunk/net/sched/sch_tbf.c index d9a5d298d755..d8e03c74ca76 100644 --- a/trunk/net/sched/sch_tbf.c +++ b/trunk/net/sched/sch_tbf.c @@ -12,6 +12,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/sctp/socket.c b/trunk/net/sctp/socket.c index 0a2c71d0d8aa..b811691c35bf 100644 --- a/trunk/net/sctp/socket.c +++ b/trunk/net/sctp/socket.c @@ -57,6 +57,7 @@ * be incorporated into the next SCTP release. */ +#include #include #include #include diff --git a/trunk/net/socket.c b/trunk/net/socket.c index b4848ce0d6ac..565f5e8d1191 100644 --- a/trunk/net/socket.c +++ b/trunk/net/socket.c @@ -58,6 +58,7 @@ * Based upon Swansea University Computer Society NET3.039 */ +#include #include #include #include diff --git a/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c b/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c index b8714a87b34c..129e2bd36aff 100644 --- a/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -169,7 +169,7 @@ gss_import_sec_context_kerberos(const void *p, } ctx_id->internal_ctx_id = ctx; - dprintk("RPC: Successfully imported new context.\n"); + dprintk("RPC: Succesfully imported new context.\n"); return 0; out_err_free_key2: diff --git a/trunk/net/sunrpc/auth_gss/gss_krb5_seal.c b/trunk/net/sunrpc/auth_gss/gss_krb5_seal.c index 2f312164d6d5..f43311221a72 100644 --- a/trunk/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/trunk/net/sunrpc/auth_gss/gss_krb5_seal.c @@ -70,7 +70,7 @@ # define RPCDBG_FACILITY RPCDBG_AUTH #endif -DEFINE_SPINLOCK(krb5_seq_lock); +spinlock_t krb5_seq_lock = SPIN_LOCK_UNLOCKED; u32 gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text, diff --git a/trunk/net/sunrpc/auth_gss/gss_mech_switch.c b/trunk/net/sunrpc/auth_gss/gss_mech_switch.c index d88468d21c37..f8bac6ccd524 100644 --- a/trunk/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/trunk/net/sunrpc/auth_gss/gss_mech_switch.c @@ -224,8 +224,7 @@ EXPORT_SYMBOL(gss_service_to_auth_domain_name); void gss_mech_put(struct gss_api_mech * gm) { - if (gm) - module_put(gm->gm_owner); + module_put(gm->gm_owner); } EXPORT_SYMBOL(gss_mech_put); @@ -308,7 +307,8 @@ gss_delete_sec_context(struct gss_ctx **context_handle) (*context_handle)->mech_type->gm_ops ->gss_delete_sec_context((*context_handle) ->internal_ctx_id); - gss_mech_put((*context_handle)->mech_type); + if ((*context_handle)->mech_type) + gss_mech_put((*context_handle)->mech_type); kfree(*context_handle); *context_handle=NULL; return GSS_S_COMPLETE; diff --git a/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c b/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c index 3d0432aa45c1..5bf11ccba7cd 100644 --- a/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c @@ -201,7 +201,7 @@ gss_import_sec_context_spkm3(const void *p, size_t len, ctx_id->internal_ctx_id = ctx; - dprintk("Successfully imported new spkm context.\n"); + dprintk("Succesfully imported new spkm context.\n"); return 0; out_err_free_key2: diff --git a/trunk/net/sunrpc/auth_gss/svcauth_gss.c b/trunk/net/sunrpc/auth_gss/svcauth_gss.c index 94217ec9e2dd..d51e316c5821 100644 --- a/trunk/net/sunrpc/auth_gss/svcauth_gss.c +++ b/trunk/net/sunrpc/auth_gss/svcauth_gss.c @@ -425,7 +425,6 @@ static int rsc_parse(struct cache_detail *cd, struct rsc rsci, *rscp = NULL; time_t expiry; int status = -EINVAL; - struct gss_api_mech *gm = NULL; memset(&rsci, 0, sizeof(rsci)); /* context handle */ @@ -454,6 +453,7 @@ static int rsc_parse(struct cache_detail *cd, set_bit(CACHE_NEGATIVE, &rsci.h.flags); else { int N, i; + struct gss_api_mech *gm; /* gid */ if (get_int(&mesg, &rsci.cred.cr_gid)) @@ -488,17 +488,21 @@ static int rsc_parse(struct cache_detail *cd, status = -EINVAL; /* mech-specific data: */ len = qword_get(&mesg, buf, mlen); - if (len < 0) + if (len < 0) { + gss_mech_put(gm); goto out; + } status = gss_import_sec_context(buf, len, gm, &rsci.mechctx); - if (status) + if (status) { + gss_mech_put(gm); goto out; + } + gss_mech_put(gm); } rsci.h.expiry_time = expiry; rscp = rsc_update(&rsci, rscp); status = 0; out: - gss_mech_put(gm); rsc_free(&rsci); if (rscp) cache_put(&rscp->h, &rsc_cache); @@ -832,74 +836,6 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx) return stat; } -static inline int -total_buf_len(struct xdr_buf *buf) -{ - return buf->head[0].iov_len + buf->page_len + buf->tail[0].iov_len; -} - -static void -fix_priv_head(struct xdr_buf *buf, int pad) -{ - if (buf->page_len == 0) { - /* We need to adjust head and buf->len in tandem in this - * case to make svc_defer() work--it finds the original - * buffer start using buf->len - buf->head[0].iov_len. */ - buf->head[0].iov_len -= pad; - } -} - -static int -unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx) -{ - u32 priv_len, maj_stat; - int pad, saved_len, remaining_len, offset; - - rqstp->rq_sendfile_ok = 0; - - priv_len = ntohl(svc_getu32(&buf->head[0])); - if (rqstp->rq_deferred) { - /* Already decrypted last time through! The sequence number - * check at out_seq is unnecessary but harmless: */ - goto out_seq; - } - /* buf->len is the number of bytes from the original start of the - * request to the end, where head[0].iov_len is just the bytes - * not yet read from the head, so these two values are different: */ - remaining_len = total_buf_len(buf); - if (priv_len > remaining_len) - return -EINVAL; - pad = remaining_len - priv_len; - buf->len -= pad; - fix_priv_head(buf, pad); - - /* Maybe it would be better to give gss_unwrap a length parameter: */ - saved_len = buf->len; - buf->len = priv_len; - maj_stat = gss_unwrap(ctx, 0, buf); - pad = priv_len - buf->len; - buf->len = saved_len; - buf->len -= pad; - /* The upper layers assume the buffer is aligned on 4-byte boundaries. - * In the krb5p case, at least, the data ends up offset, so we need to - * move it around. */ - /* XXX: This is very inefficient. It would be better to either do - * this while we encrypt, or maybe in the receive code, if we can peak - * ahead and work out the service and mechanism there. */ - offset = buf->head[0].iov_len % 4; - if (offset) { - buf->buflen = RPCSVC_MAXPAYLOAD; - xdr_shift_buf(buf, offset); - fix_priv_head(buf, pad); - } - if (maj_stat != GSS_S_COMPLETE) - return -EINVAL; -out_seq: - if (ntohl(svc_getu32(&buf->head[0])) != seq) - return -EINVAL; - return 0; -} - struct gss_svc_data { /* decoded gss client cred: */ struct rpc_gss_wire_cred clcred; @@ -1115,14 +1051,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp) svc_putu32(resv, 0); break; case RPC_GSS_SVC_PRIVACY: - if (unwrap_priv_data(rqstp, &rqstp->rq_arg, - gc->gc_seq, rsci->mechctx)) - goto auth_err; - /* placeholders for length and seq. number: */ - svcdata->body_start = resv->iov_base + resv->iov_len; - svc_putu32(resv, 0); - svc_putu32(resv, 0); - break; + /* currently unsupported */ default: goto auth_err; } @@ -1147,8 +1076,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp) return ret; } -static inline int -svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp) +static int +svcauth_gss_release(struct svc_rqst *rqstp) { struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data; struct rpc_gss_wire_cred *gc = &gsd->clcred; @@ -1160,147 +1089,69 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp) int integ_offset, integ_len; int stat = -EINVAL; - p = gsd->body_start; - gsd->body_start = NULL; - /* move accept_stat to right place: */ - memcpy(p, p + 2, 4); - /* Don't wrap in failure case: */ - /* Counting on not getting here if call was not even accepted! */ - if (*p != rpc_success) { - resbuf->head[0].iov_len -= 2 * 4; - goto out; - } - p++; - integ_offset = (u8 *)(p + 1) - (u8 *)resbuf->head[0].iov_base; - integ_len = resbuf->len - integ_offset; - BUG_ON(integ_len % 4); - *p++ = htonl(integ_len); - *p++ = htonl(gc->gc_seq); - if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, - integ_len)) - BUG(); - if (resbuf->page_len == 0 - && resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE - < PAGE_SIZE) { - BUG_ON(resbuf->tail[0].iov_len); - /* Use head for everything */ - resv = &resbuf->head[0]; - } else if (resbuf->tail[0].iov_base == NULL) { - if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE) - goto out_err; - resbuf->tail[0].iov_base = resbuf->head[0].iov_base - + resbuf->head[0].iov_len; - resbuf->tail[0].iov_len = 0; - rqstp->rq_restailpage = 0; - resv = &resbuf->tail[0]; - } else { - resv = &resbuf->tail[0]; - } - mic.data = (u8 *)resv->iov_base + resv->iov_len + 4; - if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic)) - goto out_err; - svc_putu32(resv, htonl(mic.len)); - memset(mic.data + mic.len, 0, - round_up_to_quad(mic.len) - mic.len); - resv->iov_len += XDR_QUADLEN(mic.len) << 2; - /* not strictly required: */ - resbuf->len += XDR_QUADLEN(mic.len) << 2; - BUG_ON(resv->iov_len > PAGE_SIZE); -out: - stat = 0; -out_err: - return stat; -} - -static inline int -svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp) -{ - struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data; - struct rpc_gss_wire_cred *gc = &gsd->clcred; - struct xdr_buf *resbuf = &rqstp->rq_res; - struct page **inpages = NULL; - u32 *p; - int offset, *len; - int pad; - - p = gsd->body_start; - gsd->body_start = NULL; - /* move accept_stat to right place: */ - memcpy(p, p + 2, 4); - /* Don't wrap in failure case: */ - /* Counting on not getting here if call was not even accepted! */ - if (*p != rpc_success) { - resbuf->head[0].iov_len -= 2 * 4; - return 0; - } - p++; - len = p++; - offset = (u8 *)p - (u8 *)resbuf->head[0].iov_base; - *p++ = htonl(gc->gc_seq); - inpages = resbuf->pages; - /* XXX: Would be better to write some xdr helper functions for - * nfs{2,3,4}xdr.c that place the data right, instead of copying: */ - if (resbuf->tail[0].iov_base && rqstp->rq_restailpage == 0) { - BUG_ON(resbuf->tail[0].iov_base >= resbuf->head[0].iov_base - + PAGE_SIZE); - BUG_ON(resbuf->tail[0].iov_base < resbuf->head[0].iov_base); - if (resbuf->tail[0].iov_len + resbuf->head[0].iov_len - + 2 * RPC_MAX_AUTH_SIZE > PAGE_SIZE) - return -ENOMEM; - memmove(resbuf->tail[0].iov_base + RPC_MAX_AUTH_SIZE, - resbuf->tail[0].iov_base, - resbuf->tail[0].iov_len); - resbuf->tail[0].iov_base += RPC_MAX_AUTH_SIZE; - } - if (resbuf->tail[0].iov_base == NULL) { - if (resbuf->head[0].iov_len + 2*RPC_MAX_AUTH_SIZE > PAGE_SIZE) - return -ENOMEM; - resbuf->tail[0].iov_base = resbuf->head[0].iov_base - + resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE; - resbuf->tail[0].iov_len = 0; - rqstp->rq_restailpage = 0; - } - if (gss_wrap(gsd->rsci->mechctx, offset, resbuf, inpages)) - return -ENOMEM; - *len = htonl(resbuf->len - offset); - pad = 3 - ((resbuf->len - offset - 1)&3); - p = (u32 *)(resbuf->tail[0].iov_base + resbuf->tail[0].iov_len); - memset(p, 0, pad); - resbuf->tail[0].iov_len += pad; - resbuf->len += pad; - return 0; -} - -static int -svcauth_gss_release(struct svc_rqst *rqstp) -{ - struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data; - struct rpc_gss_wire_cred *gc = &gsd->clcred; - struct xdr_buf *resbuf = &rqstp->rq_res; - int stat = -EINVAL; - if (gc->gc_proc != RPC_GSS_PROC_DATA) goto out; /* Release can be called twice, but we only wrap once. */ if (gsd->body_start == NULL) goto out; /* normally not set till svc_send, but we need it here: */ - /* XXX: what for? Do we mess it up the moment we call svc_putu32 - * or whatever? */ - resbuf->len = total_buf_len(resbuf); + resbuf->len = resbuf->head[0].iov_len + + resbuf->page_len + resbuf->tail[0].iov_len; switch (gc->gc_svc) { case RPC_GSS_SVC_NONE: break; case RPC_GSS_SVC_INTEGRITY: - stat = svcauth_gss_wrap_resp_integ(rqstp); - if (stat) + p = gsd->body_start; + gsd->body_start = NULL; + /* move accept_stat to right place: */ + memcpy(p, p + 2, 4); + /* don't wrap in failure case: */ + /* Note: counting on not getting here if call was not even + * accepted! */ + if (*p != rpc_success) { + resbuf->head[0].iov_len -= 2 * 4; + goto out; + } + p++; + integ_offset = (u8 *)(p + 1) - (u8 *)resbuf->head[0].iov_base; + integ_len = resbuf->len - integ_offset; + BUG_ON(integ_len % 4); + *p++ = htonl(integ_len); + *p++ = htonl(gc->gc_seq); + if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, + integ_len)) + BUG(); + if (resbuf->page_len == 0 + && resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE + < PAGE_SIZE) { + BUG_ON(resbuf->tail[0].iov_len); + /* Use head for everything */ + resv = &resbuf->head[0]; + } else if (resbuf->tail[0].iov_base == NULL) { + if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE + > PAGE_SIZE) + goto out_err; + resbuf->tail[0].iov_base = + resbuf->head[0].iov_base + + resbuf->head[0].iov_len; + resbuf->tail[0].iov_len = 0; + rqstp->rq_restailpage = 0; + resv = &resbuf->tail[0]; + } else { + resv = &resbuf->tail[0]; + } + mic.data = (u8 *)resv->iov_base + resv->iov_len + 4; + if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic)) goto out_err; + svc_putu32(resv, htonl(mic.len)); + memset(mic.data + mic.len, 0, + round_up_to_quad(mic.len) - mic.len); + resv->iov_len += XDR_QUADLEN(mic.len) << 2; + /* not strictly required: */ + resbuf->len += XDR_QUADLEN(mic.len) << 2; + BUG_ON(resv->iov_len > PAGE_SIZE); break; case RPC_GSS_SVC_PRIVACY: - stat = svcauth_gss_wrap_resp_priv(rqstp); - if (stat) - goto out_err; - break; default: goto out_err; } diff --git a/trunk/net/sunrpc/pmap_clnt.c b/trunk/net/sunrpc/pmap_clnt.c index 623180f224c9..d25b054ec921 100644 --- a/trunk/net/sunrpc/pmap_clnt.c +++ b/trunk/net/sunrpc/pmap_clnt.c @@ -6,6 +6,7 @@ * Copyright (C) 1996, Olaf Kirch */ +#include #include #include #include diff --git a/trunk/net/sunrpc/rpc_pipe.c b/trunk/net/sunrpc/rpc_pipe.c index 6db6006616c6..dafe793c774e 100644 --- a/trunk/net/sunrpc/rpc_pipe.c +++ b/trunk/net/sunrpc/rpc_pipe.c @@ -8,6 +8,7 @@ * Copyright (c) 2002, Trond Myklebust * */ +#include #include #include #include diff --git a/trunk/net/sunrpc/sunrpc_syms.c b/trunk/net/sunrpc/sunrpc_syms.c index f38f939ce95f..769114f0f886 100644 --- a/trunk/net/sunrpc/sunrpc_syms.c +++ b/trunk/net/sunrpc/sunrpc_syms.c @@ -6,6 +6,7 @@ * Copyright (C) 1997 Olaf Kirch */ +#include #include #include diff --git a/trunk/net/sunrpc/svc.c b/trunk/net/sunrpc/svc.c index 01ba60a49572..b08419e1fc68 100644 --- a/trunk/net/sunrpc/svc.c +++ b/trunk/net/sunrpc/svc.c @@ -280,10 +280,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp) rqstp->rq_res.page_base = 0; rqstp->rq_res.page_len = 0; rqstp->rq_res.buflen = PAGE_SIZE; - rqstp->rq_res.tail[0].iov_base = NULL; rqstp->rq_res.tail[0].iov_len = 0; - /* Will be turned off only in gss privacy case: */ - rqstp->rq_sendfile_ok = 1; /* tcp needs a space for the record length... */ if (rqstp->rq_prot == IPPROTO_TCP) svc_putu32(resv, 0); diff --git a/trunk/net/sunrpc/sysctl.c b/trunk/net/sunrpc/sysctl.c index d89b048ad6bb..1065904841fd 100644 --- a/trunk/net/sunrpc/sysctl.c +++ b/trunk/net/sunrpc/sysctl.c @@ -7,6 +7,7 @@ * impossible at the moment. */ +#include #include #include #include diff --git a/trunk/net/sysctl_net.c b/trunk/net/sysctl_net.c index cd4eafbab1b8..58a1b6b42ddd 100644 --- a/trunk/net/sysctl_net.c +++ b/trunk/net/sysctl_net.c @@ -12,6 +12,7 @@ * */ +#include #include #include diff --git a/trunk/net/tipc/bcast.c b/trunk/net/tipc/bcast.c index 1bb75703f384..2c4ecbe50082 100644 --- a/trunk/net/tipc/bcast.c +++ b/trunk/net/tipc/bcast.c @@ -49,19 +49,13 @@ #include "name_table.h" #include "bcast.h" + #define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ #define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ #define BCLINK_LOG_BUF_SIZE 0 -/* - * Loss rate for incoming broadcast frames; used to test retransmission code. - * Set to N to cause every N'th frame to be discarded; 0 => don't discard any. - */ - -#define TIPC_BCAST_LOSS_RATE 0 - /** * struct bcbearer_pair - a pair of bearers used by broadcast link * @primary: pointer to primary bearer @@ -81,14 +75,7 @@ struct bcbearer_pair { * @bearer: (non-standard) broadcast bearer structure * @media: (non-standard) broadcast media structure * @bpairs: array of bearer pairs - * @bpairs_temp: temporary array of bearer pairs used by tipc_bcbearer_sort() - * @remains: temporary node map used by tipc_bcbearer_send() - * @remains_new: temporary node map used tipc_bcbearer_send() - * - * Note: The fields labelled "temporary" are incorporated into the bearer - * to avoid consuming potentially limited stack space through the use of - * large local variables within multicast routines. Concurrent access is - * prevented through use of the spinlock "bc_lock". + * @bpairs_temp: array of bearer pairs used during creation of "bpairs" */ struct bcbearer { @@ -96,8 +83,6 @@ struct bcbearer { struct media media; struct bcbearer_pair bpairs[MAX_BEARERS]; struct bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1]; - struct node_map remains; - struct node_map remains_new; }; /** @@ -117,7 +102,7 @@ struct bclink { static struct bcbearer *bcbearer = NULL; static struct bclink *bclink = NULL; static struct link *bcl = NULL; -static DEFINE_SPINLOCK(bc_lock); +static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED; char tipc_bclink_name[] = "multicast-link"; @@ -180,18 +165,21 @@ static int bclink_ack_allowed(u32 n) * @after: sequence number of last packet to *not* retransmit * @to: sequence number of last packet to retransmit * - * Called with bc_lock locked + * Called with 'node' locked, bc_lock unlocked */ static void bclink_retransmit_pkt(u32 after, u32 to) { struct sk_buff *buf; + spin_lock_bh(&bc_lock); buf = bcl->first_out; while (buf && less_eq(buf_seqno(buf), after)) { buf = buf->next; } - tipc_link_retransmit(bcl, buf, mod(to - after)); + if (buf != NULL) + tipc_link_retransmit(bcl, buf, mod(to - after)); + spin_unlock_bh(&bc_lock); } /** @@ -358,10 +346,8 @@ static void tipc_bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 g for (; buf; buf = buf->next) { u32 seqno = buf_seqno(buf); - if (mod(seqno - prev) != 1) { + if (mod(seqno - prev) != 1) buf = NULL; - break; - } if (seqno == gap_after) break; prev = seqno; @@ -413,10 +399,7 @@ int tipc_bclink_send_msg(struct sk_buff *buf) */ void tipc_bclink_recv_pkt(struct sk_buff *buf) -{ -#if (TIPC_BCAST_LOSS_RATE) - static int rx_count = 0; -#endif +{ struct tipc_msg *msg = buf_msg(buf); struct node* node = tipc_node_find(msg_prevnode(msg)); u32 next_in; @@ -437,13 +420,9 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) tipc_node_lock(node); tipc_bclink_acknowledge(node, msg_bcast_ack(msg)); tipc_node_unlock(node); - spin_lock_bh(&bc_lock); bcl->stats.recv_nacks++; - bcl->owner->next = node; /* remember requestor */ bclink_retransmit_pkt(msg_bcgap_after(msg), msg_bcgap_to(msg)); - bcl->owner->next = NULL; - spin_unlock_bh(&bc_lock); } else { tipc_bclink_peek_nack(msg_destnode(msg), msg_bcast_tag(msg), @@ -454,14 +433,6 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) return; } -#if (TIPC_BCAST_LOSS_RATE) - if (++rx_count == TIPC_BCAST_LOSS_RATE) { - rx_count = 0; - buf_discard(buf); - return; - } -#endif - tipc_node_lock(node); receive: deferred = node->bclink.deferred_head; @@ -560,8 +531,12 @@ static int tipc_bcbearer_send(struct sk_buff *buf, { static int send_count = 0; + struct node_map *remains; + struct node_map *remains_new; + struct node_map *remains_tmp; int bp_index; int swap_time; + int err; /* Prepare buffer for broadcasting (if first time trying to send it) */ @@ -582,7 +557,9 @@ static int tipc_bcbearer_send(struct sk_buff *buf, /* Send buffer over bearers until all targets reached */ - bcbearer->remains = tipc_cltr_bcast_nodes; + remains = kmalloc(sizeof(struct node_map), GFP_ATOMIC); + remains_new = kmalloc(sizeof(struct node_map), GFP_ATOMIC); + *remains = tipc_cltr_bcast_nodes; for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { struct bearer *p = bcbearer->bpairs[bp_index].primary; @@ -591,8 +568,8 @@ static int tipc_bcbearer_send(struct sk_buff *buf, if (!p) break; /* no more bearers to try */ - tipc_nmap_diff(&bcbearer->remains, &p->nodes, &bcbearer->remains_new); - if (bcbearer->remains_new.count == bcbearer->remains.count) + tipc_nmap_diff(remains, &p->nodes, remains_new); + if (remains_new->count == remains->count) continue; /* bearer pair doesn't add anything */ if (!p->publ.blocked && @@ -610,17 +587,27 @@ static int tipc_bcbearer_send(struct sk_buff *buf, bcbearer->bpairs[bp_index].primary = s; bcbearer->bpairs[bp_index].secondary = p; update: - if (bcbearer->remains_new.count == 0) - return TIPC_OK; + if (remains_new->count == 0) { + err = TIPC_OK; + goto out; + } - bcbearer->remains = bcbearer->remains_new; + /* swap map */ + remains_tmp = remains; + remains = remains_new; + remains_new = remains_tmp; } /* Unable to reach all targets */ bcbearer->bearer.publ.blocked = 1; bcl->stats.bearer_congs++; - return ~TIPC_OK; + err = ~TIPC_OK; + + out: + kfree(remains_new); + kfree(remains); + return err; } /** @@ -778,7 +765,7 @@ int tipc_bclink_init(void) bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC); if (!bcbearer || !bclink) { nomem: - warn("Multicast link creation failed, no memory\n"); + warn("Memory squeeze; Failed to create multicast link\n"); kfree(bcbearer); bcbearer = NULL; kfree(bclink); @@ -796,7 +783,7 @@ int tipc_bclink_init(void) memset(bclink, 0, sizeof(struct bclink)); INIT_LIST_HEAD(&bcl->waiting_ports); bcl->next_out_no = 1; - spin_lock_init(&bclink->node.lock); + bclink->node.lock = SPIN_LOCK_UNLOCKED; bcl->owner = &bclink->node; bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); diff --git a/trunk/net/tipc/bcast.h b/trunk/net/tipc/bcast.h index b243d9d495f0..0e3be2ab3307 100644 --- a/trunk/net/tipc/bcast.h +++ b/trunk/net/tipc/bcast.h @@ -180,7 +180,7 @@ static inline void tipc_port_list_add(struct port_list *pl_ptr, u32 port) if (!item->next) { item->next = kmalloc(sizeof(*item), GFP_ATOMIC); if (!item->next) { - warn("Incomplete multicast delivery, no memory\n"); + warn("Memory squeeze: multicast destination port list is incomplete\n"); return; } item->next->next = NULL; diff --git a/trunk/net/tipc/bearer.c b/trunk/net/tipc/bearer.c index 7ef17a449cfd..e213a8e54855 100644 --- a/trunk/net/tipc/bearer.c +++ b/trunk/net/tipc/bearer.c @@ -112,42 +112,39 @@ int tipc_register_media(u32 media_type, goto exit; if (!media_name_valid(name)) { - warn("Media <%s> rejected, illegal name\n", name); + warn("Media registration error: illegal name <%s>\n", name); goto exit; } if (!bcast_addr) { - warn("Media <%s> rejected, no broadcast address\n", name); + warn("Media registration error: no broadcast address supplied\n"); goto exit; } if ((bearer_priority < TIPC_MIN_LINK_PRI) && (bearer_priority > TIPC_MAX_LINK_PRI)) { - warn("Media <%s> rejected, illegal priority (%u)\n", name, - bearer_priority); + warn("Media registration error: priority %u\n", bearer_priority); goto exit; } if ((link_tolerance < TIPC_MIN_LINK_TOL) || (link_tolerance > TIPC_MAX_LINK_TOL)) { - warn("Media <%s> rejected, illegal tolerance (%u)\n", name, - link_tolerance); + warn("Media registration error: tolerance %u\n", link_tolerance); goto exit; } media_id = media_count++; if (media_id >= MAX_MEDIA) { - warn("Media <%s> rejected, media limit reached (%u)\n", name, - MAX_MEDIA); + warn("Attempt to register more than %u media\n", MAX_MEDIA); media_count--; goto exit; } for (i = 0; i < media_id; i++) { if (media_list[i].type_id == media_type) { - warn("Media <%s> rejected, duplicate type (%u)\n", name, + warn("Attempt to register second media with type %u\n", media_type); media_count--; goto exit; } if (!strcmp(name, media_list[i].name)) { - warn("Media <%s> rejected, duplicate name\n", name); + warn("Attempt to re-register media name <%s>\n", name); media_count--; goto exit; } @@ -286,9 +283,6 @@ static struct bearer *bearer_find(const char *name) struct bearer *b_ptr; u32 i; - if (tipc_mode != TIPC_NET_MODE) - return NULL; - for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) { if (b_ptr->active && (!strcmp(b_ptr->publ.name, name))) return b_ptr; @@ -481,33 +475,26 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) u32 i; int res = -EINVAL; - if (tipc_mode != TIPC_NET_MODE) { - warn("Bearer <%s> rejected, not supported in standalone mode\n", - name); + if (tipc_mode != TIPC_NET_MODE) return -ENOPROTOOPT; - } - if (!bearer_name_validate(name, &b_name)) { - warn("Bearer <%s> rejected, illegal name\n", name); - return -EINVAL; - } - if (!tipc_addr_domain_valid(bcast_scope) || - !in_scope(bcast_scope, tipc_own_addr)) { - warn("Bearer <%s> rejected, illegal broadcast scope\n", name); + + if (!bearer_name_validate(name, &b_name) || + !tipc_addr_domain_valid(bcast_scope) || + !in_scope(bcast_scope, tipc_own_addr)) return -EINVAL; - } + if ((priority < TIPC_MIN_LINK_PRI || priority > TIPC_MAX_LINK_PRI) && - (priority != TIPC_MEDIA_LINK_PRI)) { - warn("Bearer <%s> rejected, illegal priority\n", name); + (priority != TIPC_MEDIA_LINK_PRI)) return -EINVAL; - } write_lock_bh(&tipc_net_lock); + if (!tipc_bearers) + goto failed; m_ptr = media_find(b_name.media_name); if (!m_ptr) { - warn("Bearer <%s> rejected, media <%s> not registered\n", name, - b_name.media_name); + warn("No media <%s>\n", b_name.media_name); goto failed; } @@ -523,24 +510,23 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) continue; } if (!strcmp(name, tipc_bearers[i].publ.name)) { - warn("Bearer <%s> rejected, already enabled\n", name); + warn("Bearer <%s> already enabled\n", name); goto failed; } if ((tipc_bearers[i].priority == priority) && (++with_this_prio > 2)) { if (priority-- == 0) { - warn("Bearer <%s> rejected, duplicate priority\n", - name); + warn("Third bearer <%s> with priority %u, unable to lower to %u\n", + name, priority + 1, priority); goto failed; } - warn("Bearer <%s> priority adjustment required %u->%u\n", + warn("Third bearer <%s> with priority %u, lowering to %u\n", name, priority + 1, priority); goto restart; } } if (bearer_id >= MAX_BEARERS) { - warn("Bearer <%s> rejected, bearer limit reached (%u)\n", - name, MAX_BEARERS); + warn("Attempt to enable more than %d bearers\n", MAX_BEARERS); goto failed; } @@ -550,7 +536,7 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) strcpy(b_ptr->publ.name, name); res = m_ptr->enable_bearer(&b_ptr->publ); if (res) { - warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); + warn("Failed to enable bearer <%s>\n", name); goto failed; } @@ -566,7 +552,7 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr, bcast_scope, 2); } - spin_lock_init(&b_ptr->publ.lock); + b_ptr->publ.lock = SPIN_LOCK_UNLOCKED; write_unlock_bh(&tipc_net_lock); info("Enabled bearer <%s>, discovery domain %s, priority %u\n", name, addr_string_fill(addr_string, bcast_scope), priority); @@ -587,6 +573,9 @@ int tipc_block_bearer(const char *name) struct link *l_ptr; struct link *temp_l_ptr; + if (tipc_mode != TIPC_NET_MODE) + return -ENOPROTOOPT; + read_lock_bh(&tipc_net_lock); b_ptr = bearer_find(name); if (!b_ptr) { @@ -595,7 +584,6 @@ int tipc_block_bearer(const char *name) return -EINVAL; } - info("Blocking bearer <%s>\n", name); spin_lock_bh(&b_ptr->publ.lock); b_ptr->publ.blocked = 1; list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { @@ -607,6 +595,7 @@ int tipc_block_bearer(const char *name) } spin_unlock_bh(&b_ptr->publ.lock); read_unlock_bh(&tipc_net_lock); + info("Blocked bearer <%s>\n", name); return TIPC_OK; } @@ -622,13 +611,15 @@ static int bearer_disable(const char *name) struct link *l_ptr; struct link *temp_l_ptr; + if (tipc_mode != TIPC_NET_MODE) + return -ENOPROTOOPT; + b_ptr = bearer_find(name); if (!b_ptr) { warn("Attempt to disable unknown bearer <%s>\n", name); return -EINVAL; } - info("Disabling bearer <%s>\n", name); tipc_disc_stop_link_req(b_ptr->link_req); spin_lock_bh(&b_ptr->publ.lock); b_ptr->link_req = NULL; @@ -644,6 +635,7 @@ static int bearer_disable(const char *name) tipc_link_delete(l_ptr); } spin_unlock_bh(&b_ptr->publ.lock); + info("Disabled bearer <%s>\n", name); memset(b_ptr, 0, sizeof(struct bearer)); return TIPC_OK; } diff --git a/trunk/net/tipc/cluster.c b/trunk/net/tipc/cluster.c index 1dcb6940e338..1aed81584e96 100644 --- a/trunk/net/tipc/cluster.c +++ b/trunk/net/tipc/cluster.c @@ -60,10 +60,8 @@ struct cluster *tipc_cltr_create(u32 addr) int alloc; c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC); - if (c_ptr == NULL) { - warn("Cluster creation failure, no memory\n"); + if (c_ptr == NULL) return NULL; - } memset(c_ptr, 0, sizeof(*c_ptr)); c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); @@ -72,32 +70,30 @@ struct cluster *tipc_cltr_create(u32 addr) else max_nodes = tipc_max_nodes + 1; alloc = sizeof(void *) * (max_nodes + 1); - c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC); if (c_ptr->nodes == NULL) { - warn("Cluster creation failure, no memory for node area\n"); kfree(c_ptr); return NULL; } - memset(c_ptr->nodes, 0, alloc); - + memset(c_ptr->nodes, 0, alloc); if (in_own_cluster(addr)) tipc_local_nodes = c_ptr->nodes; c_ptr->highest_slave = LOWEST_SLAVE - 1; c_ptr->highest_node = 0; z_ptr = tipc_zone_find(tipc_zone(addr)); - if (!z_ptr) { + if (z_ptr == NULL) { z_ptr = tipc_zone_create(addr); } - if (!z_ptr) { - kfree(c_ptr->nodes); + if (z_ptr != NULL) { + tipc_zone_attach_cluster(z_ptr, c_ptr); + c_ptr->owner = z_ptr; + } + else { kfree(c_ptr); - return NULL; + c_ptr = NULL; } - tipc_zone_attach_cluster(z_ptr, c_ptr); - c_ptr->owner = z_ptr; return c_ptr; } diff --git a/trunk/net/tipc/config.c b/trunk/net/tipc/config.c index 285e1bc2d880..48b5de2dbe60 100644 --- a/trunk/net/tipc/config.c +++ b/trunk/net/tipc/config.c @@ -63,7 +63,7 @@ struct manager { static struct manager mng = { 0}; -static DEFINE_SPINLOCK(config_lock); +static spinlock_t config_lock = SPIN_LOCK_UNLOCKED; static const void *req_tlv_area; /* request message TLV area */ static int req_tlv_space; /* request message TLV area size */ @@ -291,22 +291,13 @@ static struct sk_buff *cfg_set_own_addr(void) if (!tipc_addr_node_valid(addr)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (node address)"); - if (tipc_mode == TIPC_NET_MODE) + if (tipc_own_addr) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (cannot change node address once assigned)"); - tipc_own_addr = addr; - - /* - * Must release all spinlocks before calling start_net() because - * Linux version of TIPC calls eth_media_start() which calls - * register_netdevice_notifier() which may block! - * - * Temporarily releasing the lock should be harmless for non-Linux TIPC, - * but Linux version of eth_media_start() should really be reworked - * so that it can be called with spinlocks held. - */ spin_unlock_bh(&config_lock); + tipc_core_stop_net(); + tipc_own_addr = addr; tipc_core_start_net(); spin_lock_bh(&config_lock); return tipc_cfg_reply_none(); @@ -359,21 +350,50 @@ static struct sk_buff *cfg_set_max_subscriptions(void) static struct sk_buff *cfg_set_max_ports(void) { + int orig_mode; u32 value; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); - if (value == tipc_max_ports) - return tipc_cfg_reply_none(); if (value != delimit(value, 127, 65535)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max ports must be 127-65535)"); - if (tipc_mode != TIPC_NOT_RUNNING) + + if (value == tipc_max_ports) + return tipc_cfg_reply_none(); + + if (atomic_read(&tipc_user_count) > 2) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change max ports while TIPC is active)"); + " (cannot change max ports while TIPC users exist)"); + + spin_unlock_bh(&config_lock); + orig_mode = tipc_get_mode(); + if (orig_mode == TIPC_NET_MODE) + tipc_core_stop_net(); + tipc_core_stop(); tipc_max_ports = value; + tipc_core_start(); + if (orig_mode == TIPC_NET_MODE) + tipc_core_start_net(); + spin_lock_bh(&config_lock); + return tipc_cfg_reply_none(); +} + +static struct sk_buff *set_net_max(int value, int *parameter) +{ + int orig_mode; + + if (value != *parameter) { + orig_mode = tipc_get_mode(); + if (orig_mode == TIPC_NET_MODE) + tipc_core_stop_net(); + *parameter = value; + if (orig_mode == TIPC_NET_MODE) + tipc_core_start_net(); + } + return tipc_cfg_reply_none(); } @@ -385,16 +405,10 @@ static struct sk_buff *cfg_set_max_zones(void) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); - if (value == tipc_max_zones) - return tipc_cfg_reply_none(); if (value != delimit(value, 1, 255)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max zones must be 1-255)"); - if (tipc_mode == TIPC_NET_MODE) - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change max zones once TIPC has joined a network)"); - tipc_max_zones = value; - return tipc_cfg_reply_none(); + return set_net_max(value, &tipc_max_zones); } static struct sk_buff *cfg_set_max_clusters(void) @@ -405,8 +419,8 @@ static struct sk_buff *cfg_set_max_clusters(void) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); - if (value != delimit(value, 1, 1)) - return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE + if (value != 1) + return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED " (max clusters fixed at 1)"); return tipc_cfg_reply_none(); } @@ -419,16 +433,10 @@ static struct sk_buff *cfg_set_max_nodes(void) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); - if (value == tipc_max_nodes) - return tipc_cfg_reply_none(); if (value != delimit(value, 8, 2047)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (max nodes must be 8-2047)"); - if (tipc_mode == TIPC_NET_MODE) - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change max nodes once TIPC has joined a network)"); - tipc_max_nodes = value; - return tipc_cfg_reply_none(); + return set_net_max(value, &tipc_max_nodes); } static struct sk_buff *cfg_set_max_slaves(void) @@ -453,16 +461,15 @@ static struct sk_buff *cfg_set_netid(void) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); value = *(u32 *)TLV_DATA(req_tlv_area); value = ntohl(value); - if (value == tipc_net_id) - return tipc_cfg_reply_none(); if (value != delimit(value, 1, 9999)) return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE " (network id must be 1-9999)"); - if (tipc_mode == TIPC_NET_MODE) + + if (tipc_own_addr) return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (cannot change network id once TIPC has joined a network)"); - tipc_net_id = value; - return tipc_cfg_reply_none(); + " (cannot change network id once part of network)"); + + return set_net_max(value, &tipc_net_id); } struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, @@ -642,7 +649,7 @@ static void cfg_named_msg_event(void *userdata, if ((size < sizeof(*req_hdr)) || (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { - warn("Invalid configuration message discarded\n"); + warn("discarded invalid configuration message\n"); return; } diff --git a/trunk/net/tipc/core.c b/trunk/net/tipc/core.c index 0539a8362858..3d0a8ee4e1d3 100644 --- a/trunk/net/tipc/core.c +++ b/trunk/net/tipc/core.c @@ -2,7 +2,7 @@ * net/tipc/core.c: TIPC module code * * Copyright (c) 2003-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems + * Copyright (c) 2005, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,7 +57,7 @@ void tipc_socket_stop(void); int tipc_netlink_start(void); void tipc_netlink_stop(void); -#define TIPC_MOD_VER "1.6.1" +#define MOD_NAME "tipc_start: " #ifndef CONFIG_TIPC_ZONES #define CONFIG_TIPC_ZONES 3 @@ -191,15 +191,14 @@ static int __init tipc_init(void) int res; tipc_log_reinit(CONFIG_TIPC_LOG); - info("Activated (version " TIPC_MOD_VER - " compiled " __DATE__ " " __TIME__ ")\n"); + info("Activated (compiled " __DATE__ " " __TIME__ ")\n"); tipc_own_addr = 0; tipc_remote_management = 1; tipc_max_publications = 10000; tipc_max_subscriptions = 2000; tipc_max_ports = delimit(CONFIG_TIPC_PORTS, 127, 65536); - tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 255); + tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 511); tipc_max_clusters = delimit(CONFIG_TIPC_CLUSTERS, 1, 1); tipc_max_nodes = delimit(CONFIG_TIPC_NODES, 8, 2047); tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047); @@ -225,7 +224,6 @@ module_exit(tipc_exit); MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION(TIPC_MOD_VER); /* Native TIPC API for kernel-space applications (see tipc.h) */ diff --git a/trunk/net/tipc/core.h b/trunk/net/tipc/core.h index 86f54f3512f1..1f2e8b27a13f 100644 --- a/trunk/net/tipc/core.h +++ b/trunk/net/tipc/core.h @@ -2,7 +2,7 @@ * net/tipc/core.h: Include file for TIPC global declarations * * Copyright (c) 2005-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems + * Copyright (c) 2005, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -111,6 +111,10 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); #else +#ifndef DBG_OUTPUT +#define DBG_OUTPUT NULL +#endif + /* * TIPC debug support not included: * - system messages are printed to system console @@ -125,19 +129,6 @@ void tipc_dump(struct print_buf*,const char *fmt, ...); #define msg_dbg(msg,txt) do {} while (0) #define dump(fmt,arg...) do {} while (0) - -/* - * TIPC_OUTPUT is defined to be the system console, while DBG_OUTPUT is - * the null print buffer. Thes ensures that any system or debug messages - * that are generated without using the above macros are handled correctly. - */ - -#undef TIPC_OUTPUT -#define TIPC_OUTPUT TIPC_CONS - -#undef DBG_OUTPUT -#define DBG_OUTPUT NULL - #endif @@ -318,7 +309,7 @@ static inline struct sk_buff *buf_acquire(u32 size) * buf_discard - frees a TIPC message buffer * @skb: message buffer * - * Frees a message buffer. If passed NULL, just returns. + * Frees a new buffer. If passed NULL, just returns. */ static inline void buf_discard(struct sk_buff *skb) diff --git a/trunk/net/tipc/dbg.c b/trunk/net/tipc/dbg.c index 55130655e1ed..26ef95d5fe38 100644 --- a/trunk/net/tipc/dbg.c +++ b/trunk/net/tipc/dbg.c @@ -41,7 +41,7 @@ #define MAX_STRING 512 static char print_string[MAX_STRING]; -static DEFINE_SPINLOCK(print_lock); +static spinlock_t print_lock = SPIN_LOCK_UNLOCKED; static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; struct print_buf *TIPC_CONS = &cons_buf; diff --git a/trunk/net/tipc/discover.c b/trunk/net/tipc/discover.c index 2b8441203120..92601385e5f5 100644 --- a/trunk/net/tipc/discover.c +++ b/trunk/net/tipc/discover.c @@ -2,7 +2,7 @@ * net/tipc/discover.c * * Copyright (c) 2003-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems + * Copyright (c) 2005, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -176,6 +176,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf) n_ptr = tipc_node_create(orig); } if (n_ptr == NULL) { + warn("Memory squeeze; Failed to create node\n"); return; } spin_lock_bh(&n_ptr->lock); @@ -190,8 +191,10 @@ void tipc_disc_recv_msg(struct sk_buff *buf) } addr = &link->media_addr; if (memcmp(addr, &media_addr, sizeof(*addr))) { - warn("Resetting link <%s>, peer interface address changed\n", - link->name); + char addr_string[16]; + + warn("New bearer address for %s\n", + addr_string_fill(addr_string, orig)); memcpy(addr, &media_addr, sizeof(*addr)); tipc_link_reset(link); } @@ -267,8 +270,8 @@ static void disc_timeout(struct link_req *req) /* leave timer interval "as is" if already at a "normal" rate */ } else { req->timer_intv *= 2; - if (req->timer_intv > TIPC_LINK_REQ_FAST) - req->timer_intv = TIPC_LINK_REQ_FAST; + if (req->timer_intv > TIPC_LINK_REQ_SLOW) + req->timer_intv = TIPC_LINK_REQ_SLOW; if ((req->timer_intv == TIPC_LINK_REQ_FAST) && (req->bearer->nodes.count)) req->timer_intv = TIPC_LINK_REQ_SLOW; diff --git a/trunk/net/tipc/eth_media.c b/trunk/net/tipc/eth_media.c index 682da4a28041..7a252785f727 100644 --- a/trunk/net/tipc/eth_media.c +++ b/trunk/net/tipc/eth_media.c @@ -2,7 +2,7 @@ * net/tipc/eth_media.c: Ethernet bearer support for TIPC * * Copyright (c) 2001-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems + * Copyright (c) 2005, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -98,19 +98,17 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev, u32 size; if (likely(eb_ptr->bearer)) { - if (likely(!dev->promiscuity) || - !memcmp(buf->mac.raw,dev->dev_addr,ETH_ALEN) || - !memcmp(buf->mac.raw,dev->broadcast,ETH_ALEN)) { - size = msg_size((struct tipc_msg *)buf->data); - skb_trim(buf, size); - if (likely(buf->len == size)) { - buf->next = NULL; - tipc_recv_msg(buf, eb_ptr->bearer); - return TIPC_OK; - } + size = msg_size((struct tipc_msg *)buf->data); + skb_trim(buf, size); + if (likely(buf->len == size)) { + buf->next = NULL; + tipc_recv_msg(buf, eb_ptr->bearer); + } else { + kfree_skb(buf); } + } else { + kfree_skb(buf); } - kfree_skb(buf); return TIPC_OK; } @@ -127,7 +125,8 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) /* Find device with specified name */ - while (dev && dev->name && strncmp(dev->name, driver_name, IFNAMSIZ)) { + while (dev && dev->name && + (memcmp(dev->name, driver_name, strlen(dev->name)))) { dev = dev->next; } if (!dev) @@ -253,9 +252,7 @@ int tipc_eth_media_start(void) if (eth_started) return -EINVAL; - bcast_addr.type = htonl(TIPC_MEDIA_TYPE_ETH); - memset(&bcast_addr.dev_addr, 0xff, ETH_ALEN); - + memset(&bcast_addr, 0xff, sizeof(bcast_addr)); memset(eth_bearers, 0, sizeof(eth_bearers)); res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth", diff --git a/trunk/net/tipc/handler.c b/trunk/net/tipc/handler.c index ae6ddf00a1aa..966f70a1b608 100644 --- a/trunk/net/tipc/handler.c +++ b/trunk/net/tipc/handler.c @@ -44,7 +44,7 @@ struct queue_item { static kmem_cache_t *tipc_queue_item_cache; static struct list_head signal_queue_head; -static DEFINE_SPINLOCK(qitem_lock); +static spinlock_t qitem_lock = SPIN_LOCK_UNLOCKED; static int handler_enabled = 0; static void process_signal_queue(unsigned long dummy); diff --git a/trunk/net/tipc/link.c b/trunk/net/tipc/link.c index c6831c75cfa4..784b24b6d102 100644 --- a/trunk/net/tipc/link.c +++ b/trunk/net/tipc/link.c @@ -2,7 +2,7 @@ * net/tipc/link.c: TIPC link code * * Copyright (c) 1996-2006, Ericsson AB - * Copyright (c) 2004-2006, Wind River Systems + * Copyright (c) 2004-2005, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -419,7 +419,7 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, l_ptr = (struct link *)kmalloc(sizeof(*l_ptr), GFP_ATOMIC); if (!l_ptr) { - warn("Link creation failed, no memory\n"); + warn("Memory squeeze; Failed to create link\n"); return NULL; } memset(l_ptr, 0, sizeof(*l_ptr)); @@ -469,7 +469,7 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer, if (!pb) { kfree(l_ptr); - warn("Link creation failed, no memory for print buffer\n"); + warn("Memory squeeze; Failed to create link\n"); return NULL; } tipc_printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE); @@ -574,6 +574,7 @@ void tipc_link_wakeup_ports(struct link *l_ptr, int all) break; list_del_init(&p_ptr->wait_list); p_ptr->congested_link = NULL; + assert(p_ptr->wakeup); spin_lock_bh(p_ptr->publ.lock); p_ptr->publ.congested = 0; p_ptr->wakeup(&p_ptr->publ); @@ -690,7 +691,6 @@ void tipc_link_reset(struct link *l_ptr) struct sk_buff *buf; u32 prev_state = l_ptr->state; u32 checkpoint = l_ptr->next_in_no; - int was_active_link = tipc_link_is_active(l_ptr); msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1); @@ -712,7 +712,7 @@ void tipc_link_reset(struct link *l_ptr) tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name); dbg_link_dump(); #endif - if (was_active_link && tipc_node_has_active_links(l_ptr->owner) && + if (tipc_node_has_active_links(l_ptr->owner) && l_ptr->owner->permit_changeover) { l_ptr->reset_checkpoint = checkpoint; l_ptr->exp_msg_count = START_CHANGEOVER; @@ -755,7 +755,7 @@ void tipc_link_reset(struct link *l_ptr) static void link_activate(struct link *l_ptr) { - l_ptr->next_in_no = l_ptr->stats.recv_info = 1; + l_ptr->next_in_no = 1; tipc_node_link_up(l_ptr->owner, l_ptr); tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); link_send_event(tipc_cfg_link_event, l_ptr, 1); @@ -820,8 +820,6 @@ static void link_state_event(struct link *l_ptr, unsigned event) break; case RESET_MSG: dbg_link("RES -> RR\n"); - info("Resetting link <%s>, requested by peer\n", - l_ptr->name); tipc_link_reset(l_ptr); l_ptr->state = RESET_RESET; l_ptr->fsm_msg_cnt = 0; @@ -846,8 +844,6 @@ static void link_state_event(struct link *l_ptr, unsigned event) break; case RESET_MSG: dbg_link("RES -> RR\n"); - info("Resetting link <%s>, requested by peer " - "while probing\n", l_ptr->name); tipc_link_reset(l_ptr); l_ptr->state = RESET_RESET; l_ptr->fsm_msg_cnt = 0; @@ -879,8 +875,6 @@ static void link_state_event(struct link *l_ptr, unsigned event) } else { /* Link has failed */ dbg_link("-> RU (%u probes unanswered)\n", l_ptr->fsm_msg_cnt); - warn("Resetting link <%s>, peer not responding\n", - l_ptr->name); tipc_link_reset(l_ptr); l_ptr->state = RESET_UNKNOWN; l_ptr->fsm_msg_cnt = 0; @@ -988,18 +982,17 @@ static int link_bundle_buf(struct link *l_ptr, struct tipc_msg *bundler_msg = buf_msg(bundler); struct tipc_msg *msg = buf_msg(buf); u32 size = msg_size(msg); - u32 bundle_size = msg_size(bundler_msg); - u32 to_pos = align(bundle_size); - u32 pad = to_pos - bundle_size; + u32 to_pos = align(msg_size(bundler_msg)); + u32 rest = link_max_pkt(l_ptr) - to_pos; if (msg_user(bundler_msg) != MSG_BUNDLER) return 0; if (msg_type(bundler_msg) != OPEN_MSG) return 0; - if (skb_tailroom(bundler) < (pad + size)) + if (rest < align(size)) return 0; - skb_put(bundler, pad + size); + skb_put(bundler, (to_pos - msg_size(bundler_msg)) + size); memcpy(bundler->data + to_pos, buf->data, size); msg_set_size(bundler_msg, to_pos + size); msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1); @@ -1057,7 +1050,7 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) msg_dbg(msg, "TIPC: Congestion, throwing away\n"); buf_discard(buf); if (imp > CONN_MANAGER) { - warn("Resetting link <%s>, send queue full", l_ptr->name); + warn("Resetting <%s>, send queue full", l_ptr->name); tipc_link_reset(l_ptr); } return dsz; @@ -1142,13 +1135,9 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) if (n_ptr) { tipc_node_lock(n_ptr); l_ptr = n_ptr->active_links[selector & 1]; + dbg("tipc_link_send: found link %x for dest %x\n", l_ptr, dest); if (l_ptr) { - dbg("tipc_link_send: found link %x for dest %x\n", l_ptr, dest); res = tipc_link_send_buf(l_ptr, buf); - } else { - dbg("Attempt to send msg to unreachable node:\n"); - msg_dbg(buf_msg(buf),">>>"); - buf_discard(buf); } tipc_node_unlock(n_ptr); } else { @@ -1253,6 +1242,8 @@ int tipc_link_send_sections_fast(struct port *sender, int res; u32 selector = msg_origport(hdr) & 1; + assert(destaddr != tipc_own_addr); + again: /* * Try building message using port's max_pkt hint. @@ -1613,121 +1604,40 @@ void tipc_link_push_queue(struct link *l_ptr) tipc_bearer_schedule(l_ptr->b_ptr, l_ptr); } -static void link_reset_all(unsigned long addr) -{ - struct node *n_ptr; - char addr_string[16]; - u32 i; - - read_lock_bh(&tipc_net_lock); - n_ptr = tipc_node_find((u32)addr); - if (!n_ptr) { - read_unlock_bh(&tipc_net_lock); - return; /* node no longer exists */ - } - - tipc_node_lock(n_ptr); - - warn("Resetting all links to %s\n", - addr_string_fill(addr_string, n_ptr->addr)); - - for (i = 0; i < MAX_BEARERS; i++) { - if (n_ptr->links[i]) { - link_print(n_ptr->links[i], TIPC_OUTPUT, - "Resetting link\n"); - tipc_link_reset(n_ptr->links[i]); - } - } - - tipc_node_unlock(n_ptr); - read_unlock_bh(&tipc_net_lock); -} - -static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf) -{ - struct tipc_msg *msg = buf_msg(buf); - - warn("Retransmission failure on link <%s>\n", l_ptr->name); - tipc_msg_print(TIPC_OUTPUT, msg, ">RETR-FAIL>"); - - if (l_ptr->addr) { - - /* Handle failure on standard link */ - - link_print(l_ptr, TIPC_OUTPUT, "Resetting link\n"); - tipc_link_reset(l_ptr); - - } else { - - /* Handle failure on broadcast link */ - - struct node *n_ptr; - char addr_string[16]; - - tipc_printf(TIPC_OUTPUT, "Msg seq number: %u, ", msg_seqno(msg)); - tipc_printf(TIPC_OUTPUT, "Outstanding acks: %u\n", (u32)TIPC_SKB_CB(buf)->handle); - - n_ptr = l_ptr->owner->next; - tipc_node_lock(n_ptr); - - addr_string_fill(addr_string, n_ptr->addr); - tipc_printf(TIPC_OUTPUT, "Multicast link info for %s\n", addr_string); - tipc_printf(TIPC_OUTPUT, "Supported: %d, ", n_ptr->bclink.supported); - tipc_printf(TIPC_OUTPUT, "Acked: %u\n", n_ptr->bclink.acked); - tipc_printf(TIPC_OUTPUT, "Last in: %u, ", n_ptr->bclink.last_in); - tipc_printf(TIPC_OUTPUT, "Gap after: %u, ", n_ptr->bclink.gap_after); - tipc_printf(TIPC_OUTPUT, "Gap to: %u\n", n_ptr->bclink.gap_to); - tipc_printf(TIPC_OUTPUT, "Nack sync: %u\n\n", n_ptr->bclink.nack_sync); - - tipc_k_signal((Handler)link_reset_all, (unsigned long)n_ptr->addr); - - tipc_node_unlock(n_ptr); - - l_ptr->stale_count = 0; - } -} - void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, u32 retransmits) { struct tipc_msg *msg; - if (!buf) - return; - - msg = buf_msg(buf); - dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); - if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) { - if (!skb_cloned(buf)) { - msg_dbg(msg, ">NO_RETR->BCONG>"); - dbg_print_link(l_ptr, " "); - l_ptr->retransm_queue_head = msg_seqno(msg); - l_ptr->retransm_queue_size = retransmits; - return; - } else { - /* Don't retransmit if driver already has the buffer */ - } - } else { - /* Detect repeated retransmit failures on uncongested bearer */ - - if (l_ptr->last_retransmitted == msg_seqno(msg)) { - if (++l_ptr->stale_count > 100) { - link_retransmit_failure(l_ptr, buf); - return; - } - } else { - l_ptr->last_retransmitted = msg_seqno(msg); - l_ptr->stale_count = 1; - } + if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) { + msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>"); + dbg_print_link(l_ptr, " "); + l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); + l_ptr->retransm_queue_size = retransmits; + return; } - while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { msg = buf_msg(buf); msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { + /* Catch if retransmissions fail repeatedly: */ + if (l_ptr->last_retransmitted == msg_seqno(msg)) { + if (++l_ptr->stale_count > 100) { + tipc_msg_print(TIPC_CONS, buf_msg(buf), ">RETR>"); + info("...Retransmitted %u times\n", + l_ptr->stale_count); + link_print(l_ptr, TIPC_CONS, "Resetting Link\n"); + tipc_link_reset(l_ptr); + break; + } + } else { + l_ptr->stale_count = 0; + } + l_ptr->last_retransmitted = msg_seqno(msg); + msg_dbg(buf_msg(buf), ">RETR>"); buf = buf->next; retransmits--; @@ -1740,7 +1650,6 @@ void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, return; } } - l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0; } @@ -1811,11 +1720,6 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) link_recv_non_seq(buf); continue; } - - if (unlikely(!msg_short(msg) && - (msg_destnode(msg) != tipc_own_addr))) - goto cont; - n_ptr = tipc_node_find(msg_prevnode(msg)); if (unlikely(!n_ptr)) goto cont; @@ -2236,7 +2140,7 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) if (msg_linkprio(msg) && (msg_linkprio(msg) != l_ptr->priority)) { - warn("Resetting link <%s>, priority change %u->%u\n", + warn("Changing prio <%s>: %u->%u\n", l_ptr->name, l_ptr->priority, msg_linkprio(msg)); l_ptr->priority = msg_linkprio(msg); tipc_link_reset(l_ptr); /* Enforce change to take effect */ @@ -2305,22 +2209,17 @@ void tipc_link_tunnel(struct link *l_ptr, u32 length = msg_size(msg); tunnel = l_ptr->owner->active_links[selector & 1]; - if (!tipc_link_is_up(tunnel)) { - warn("Link changeover error, " - "tunnel link no longer available\n"); + if (!tipc_link_is_up(tunnel)) return; - } msg_set_size(tunnel_hdr, length + INT_H_SIZE); buf = buf_acquire(length + INT_H_SIZE); - if (!buf) { - warn("Link changeover error, " - "unable to send tunnel msg\n"); + if (!buf) return; - } memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE); memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length); dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); msg_dbg(buf_msg(buf), ">SEND>"); + assert(tunnel); tipc_link_send_buf(tunnel, buf); } @@ -2336,27 +2235,23 @@ void tipc_link_changeover(struct link *l_ptr) u32 msgcount = l_ptr->out_queue_size; struct sk_buff *crs = l_ptr->first_out; struct link *tunnel = l_ptr->owner->active_links[0]; + int split_bundles = tipc_node_has_redundant_links(l_ptr->owner); struct tipc_msg tunnel_hdr; - int split_bundles; if (!tunnel) return; - if (!l_ptr->owner->permit_changeover) { - warn("Link changeover error, " - "peer did not permit changeover\n"); + if (!l_ptr->owner->permit_changeover) return; - } msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); msg_set_msgcnt(&tunnel_hdr, msgcount); - dbg("Link changeover requires %u tunnel messages\n", msgcount); - if (!l_ptr->first_out) { struct sk_buff *buf; + assert(!msgcount); buf = buf_acquire(INT_H_SIZE); if (buf) { memcpy(buf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); @@ -2366,15 +2261,10 @@ void tipc_link_changeover(struct link *l_ptr) msg_dbg(&tunnel_hdr, "EMPTY>SEND>"); tipc_link_send_buf(tunnel, buf); } else { - warn("Link changeover error, " - "unable to send changeover msg\n"); + warn("Memory squeeze; link changeover failed\n"); } return; } - - split_bundles = (l_ptr->owner->active_links[0] != - l_ptr->owner->active_links[1]); - while (crs) { struct tipc_msg *msg = buf_msg(crs); @@ -2420,8 +2310,7 @@ void tipc_link_send_duplicate(struct link *l_ptr, struct link *tunnel) msg_set_size(&tunnel_hdr, length + INT_H_SIZE); outbuf = buf_acquire(length + INT_H_SIZE); if (outbuf == NULL) { - warn("Link changeover error, " - "unable to send duplicate msg\n"); + warn("Memory squeeze; buffer duplication failed\n"); return; } memcpy(outbuf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); @@ -2475,15 +2364,11 @@ static int link_recv_changeover_msg(struct link **l_ptr, u32 msg_count = msg_msgcnt(tunnel_msg); dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)]; + assert(dest_link != *l_ptr); if (!dest_link) { msg_dbg(tunnel_msg, "NOLINK/\n", - (*l_ptr)->name); - goto exit; - } dbg("%c<-%c:", dest_link->b_ptr->net_plane, (*l_ptr)->b_ptr->net_plane); *l_ptr = dest_link; @@ -2496,7 +2381,7 @@ static int link_recv_changeover_msg(struct link **l_ptr, } *buf = buf_extract(tunnel_buf,INT_H_SIZE); if (*buf == NULL) { - warn("Link changeover error, duplicate msg dropped\n"); + warn("Memory squeeze; failed to extract msg\n"); goto exit; } msg_dbg(tunnel_msg, "TNL, changeover initiated by peer\n", - dest_link->name); tipc_link_reset(dest_link); dest_link->exp_msg_count = msg_count; - dbg("Expecting %u tunnelled messages\n", msg_count); if (!msg_count) goto exit; } else if (dest_link->exp_msg_count == START_CHANGEOVER) { msg_dbg(tunnel_msg, "BLK/FIRST/exp_msg_count = msg_count; - dbg("Expecting %u tunnelled messages\n", msg_count); if (!msg_count) goto exit; } @@ -2526,8 +2407,6 @@ static int link_recv_changeover_msg(struct link **l_ptr, /* Receive original message */ if (dest_link->exp_msg_count == 0) { - warn("Link switchover error, " - "got too many tunnelled messages\n"); msg_dbg(tunnel_msg, "OVERDUE/DROP/type, publ->lower, publ->upper); publ->key += 1222345; p = tipc_nametbl_remove_publ(publ->type, publ->lower, publ->node, publ->ref, publ->key); + assert(p == publ); write_unlock_bh(&tipc_nametbl_lock); - - if (p != publ) { - err("Unable to remove publication from failed node\n" - "(type=%u, lower=%u, node=0x%x, ref=%u, key=%u)\n", - publ->type, publ->lower, publ->node, publ->ref, publ->key); - } - - if (p) { - kfree(p); - } + kfree(publ); } /** @@ -283,15 +275,9 @@ void tipc_named_recv(struct sk_buff *buf) if (publ) { tipc_nodesub_unsubscribe(&publ->subscr); kfree(publ); - } else { - err("Unable to remove publication by node 0x%x\n" - "(type=%u, lower=%u, ref=%u, key=%u)\n", - msg_orignode(msg), - ntohl(item->type), ntohl(item->lower), - ntohl(item->ref), ntohl(item->key)); } } else { - warn("Unrecognized name table message received\n"); + warn("tipc_named_recv: unknown msg\n"); } item++; } diff --git a/trunk/net/tipc/name_table.c b/trunk/net/tipc/name_table.c index a6926ff07bcc..d129422fc5c2 100644 --- a/trunk/net/tipc/name_table.c +++ b/trunk/net/tipc/name_table.c @@ -71,7 +71,7 @@ struct sub_seq { * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type'; * sub-sequences are sorted in ascending order * @alloc: number of sub-sequences currently in array - * @first_free: array index of first unused sub-sequence entry + * @first_free: upper bound of highest sub-sequence + 1 * @ns_list: links to adjacent name sequences in hash chain * @subscriptions: list of subscriptions for this 'type' * @lock: spinlock controlling access to name sequence structure @@ -101,7 +101,7 @@ struct name_table { static struct name_table table = { NULL } ; static atomic_t rsv_publ_ok = ATOMIC_INIT(0); -DEFINE_RWLOCK(tipc_nametbl_lock); +rwlock_t tipc_nametbl_lock = RW_LOCK_UNLOCKED; static int hash(int x) @@ -120,7 +120,7 @@ static struct publication *publ_create(u32 type, u32 lower, u32 upper, struct publication *publ = (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC); if (publ == NULL) { - warn("Publication creation failure, no memory\n"); + warn("Memory squeeze; failed to create publication\n"); return NULL; } @@ -165,17 +165,17 @@ static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_hea struct sub_seq *sseq = tipc_subseq_alloc(1); if (!nseq || !sseq) { - warn("Name sequence creation failed, no memory\n"); + warn("Memory squeeze; failed to create name sequence\n"); kfree(nseq); kfree(sseq); return NULL; } memset(nseq, 0, sizeof(*nseq)); - spin_lock_init(&nseq->lock); + nseq->lock = SPIN_LOCK_UNLOCKED; nseq->type = type; nseq->sseqs = sseq; - dbg("tipc_nameseq_create(): nseq = %p, type %u, ssseqs %p, ff: %u\n", + dbg("tipc_nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n", nseq, type, nseq->sseqs, nseq->first_free); nseq->alloc = 1; INIT_HLIST_NODE(&nseq->ns_list); @@ -253,16 +253,16 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, struct sub_seq *sseq; int created_subseq = 0; + assert(nseq->first_free <= nseq->alloc); sseq = nameseq_find_subseq(nseq, lower); - dbg("nameseq_ins: for seq %p, {%u,%u}, found sseq %p\n", + dbg("nameseq_ins: for seq %x,<%u,%u>, found sseq %x\n", nseq, type, lower, sseq); if (sseq) { /* Lower end overlaps existing entry => need an exact match */ if ((sseq->lower != lower) || (sseq->upper != upper)) { - warn("Cannot publish {%u,%u,%u}, overlap error\n", - type, lower, upper); + warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); return NULL; } } else { @@ -277,27 +277,25 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, if ((inspos < nseq->first_free) && (upper >= nseq->sseqs[inspos].lower)) { - warn("Cannot publish {%u,%u,%u}, overlap error\n", - type, lower, upper); + warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); return NULL; } /* Ensure there is space for new sub-sequence */ if (nseq->first_free == nseq->alloc) { - struct sub_seq *sseqs = tipc_subseq_alloc(nseq->alloc * 2); - - if (!sseqs) { - warn("Cannot publish {%u,%u,%u}, no memory\n", - type, lower, upper); + struct sub_seq *sseqs = nseq->sseqs; + nseq->sseqs = tipc_subseq_alloc(nseq->alloc * 2); + if (nseq->sseqs != NULL) { + memcpy(nseq->sseqs, sseqs, + nseq->alloc * sizeof (struct sub_seq)); + kfree(sseqs); + dbg("Allocated %u sseqs\n", nseq->alloc); + nseq->alloc *= 2; + } else { + warn("Memory squeeze; failed to create sub-sequence\n"); return NULL; } - dbg("Allocated %u more sseqs\n", nseq->alloc); - memcpy(sseqs, nseq->sseqs, - nseq->alloc * sizeof(struct sub_seq)); - kfree(nseq->sseqs); - nseq->sseqs = sseqs; - nseq->alloc *= 2; } dbg("Have %u sseqs for type %u\n", nseq->alloc, type); @@ -313,7 +311,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, sseq->upper = upper; created_subseq = 1; } - dbg("inserting {%u,%u,%u} from <0x%x:%u> into sseq %p(%u,%u) of seq %p\n", + dbg("inserting (%u %u %u) from %x:%u into sseq %x(%u,%u) of seq %x\n", type, lower, upper, node, port, sseq, sseq->lower, sseq->upper, nseq); @@ -322,7 +320,7 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, publ = publ_create(type, lower, upper, scope, node, port, key); if (!publ) return NULL; - dbg("inserting publ %p, node=0x%x publ->node=0x%x, subscr->node=%p\n", + dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n", publ, node, publ->node, publ->subscr.node); if (!sseq->zone_list) @@ -369,34 +367,37 @@ static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq, /** * tipc_nameseq_remove_publ - - * - * NOTE: There may be cases where TIPC is asked to remove a publication - * that is not in the name table. For example, if another node issues a - * publication for a name sequence that overlaps an existing name sequence - * the publication will not be recorded, which means the publication won't - * be found when the name sequence is later withdrawn by that node. - * A failed withdraw request simply returns a failure indication and lets the - * caller issue any error or warning messages associated with such a problem. */ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst, u32 node, u32 ref, u32 key) { struct publication *publ; - struct publication *curr; struct publication *prev; struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); struct sub_seq *free; struct subscription *s, *st; int removed_subseq = 0; - if (!sseq) - return NULL; + assert(nseq); - dbg("tipc_nameseq_remove_publ: seq: %p, sseq %p, {%u,%u}, key %u\n", - nseq, sseq, nseq->type, inst, key); + if (!sseq) { + int i; - /* Remove publication from zone scope list */ + warn("Withdraw unknown <%u,%u>?\n", nseq->type, inst); + assert(nseq->sseqs); + dbg("Dumping subseqs %x for %x, alloc = %u,ff=%u\n", + nseq->sseqs, nseq, nseq->alloc, + nseq->first_free); + for (i = 0; i < nseq->first_free; i++) { + dbg("Subseq %u(%x): lower = %u,upper = %u\n", + i, &nseq->sseqs[i], nseq->sseqs[i].lower, + nseq->sseqs[i].upper); + } + return NULL; + } + dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n", + nseq, sseq, nseq->type, inst, key); prev = sseq->zone_list; publ = sseq->zone_list->zone_list_next; @@ -404,12 +405,7 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i (publ->node && (publ->node != node))) { prev = publ; publ = publ->zone_list_next; - if (prev == sseq->zone_list) { - - /* Prevent endless loop if publication not found */ - - return NULL; - } + assert(prev != sseq->zone_list); } if (publ != sseq->zone_list) prev->zone_list_next = publ->zone_list_next; @@ -420,24 +416,14 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i sseq->zone_list = NULL; } - /* Remove publication from cluster scope list, if present */ - if (in_own_cluster(node)) { prev = sseq->cluster_list; - curr = sseq->cluster_list->cluster_list_next; - while (curr != publ) { - prev = curr; - curr = curr->cluster_list_next; - if (prev == sseq->cluster_list) { - - /* Prevent endless loop for malformed list */ - - err("Unable to de-list cluster publication\n" - "{%u%u}, node=0x%x, ref=%u, key=%u)\n", - publ->type, publ->lower, publ->node, - publ->ref, publ->key); - goto end_cluster; - } + publ = sseq->cluster_list->cluster_list_next; + while ((publ->key != key) || (publ->ref != ref) || + (publ->node && (publ->node != node))) { + prev = publ; + publ = publ->cluster_list_next; + assert(prev != sseq->cluster_list); } if (publ != sseq->cluster_list) prev->cluster_list_next = publ->cluster_list_next; @@ -448,26 +434,15 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i sseq->cluster_list = NULL; } } -end_cluster: - - /* Remove publication from node scope list, if present */ if (node == tipc_own_addr) { prev = sseq->node_list; - curr = sseq->node_list->node_list_next; - while (curr != publ) { - prev = curr; - curr = curr->node_list_next; - if (prev == sseq->node_list) { - - /* Prevent endless loop for malformed list */ - - err("Unable to de-list node publication\n" - "{%u%u}, node=0x%x, ref=%u, key=%u)\n", - publ->type, publ->lower, publ->node, - publ->ref, publ->key); - goto end_node; - } + publ = sseq->node_list->node_list_next; + while ((publ->key != key) || (publ->ref != ref) || + (publ->node && (publ->node != node))) { + prev = publ; + publ = publ->node_list_next; + assert(prev != sseq->node_list); } if (publ != sseq->node_list) prev->node_list_next = publ->node_list_next; @@ -478,18 +453,22 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i sseq->node_list = NULL; } } -end_node: + assert(!publ->node || (publ->node == node)); + assert(publ->ref == ref); + assert(publ->key == key); - /* Contract subseq list if no more publications for that subseq */ - - if (!sseq->zone_list) { + /* + * Contract subseq list if no more publications: + */ + if (!sseq->node_list && !sseq->cluster_list && !sseq->zone_list) { free = &nseq->sseqs[nseq->first_free--]; memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq)); removed_subseq = 1; } - /* Notify any waiting subscriptions */ - + /* + * Any subscriptions waiting ? + */ list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { tipc_subscr_report_overlap(s, publ->lower, @@ -499,7 +478,6 @@ static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 i publ->node, removed_subseq); } - return publ; } @@ -552,7 +530,7 @@ static struct name_seq *nametbl_find_seq(u32 type) seq_head = &table.types[hash(type)]; hlist_for_each_entry(ns, seq_node, seq_head, ns_list) { if (ns->type == type) { - dbg("found %p\n", ns); + dbg("found %x\n", ns); return ns; } } @@ -565,21 +543,22 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, { struct name_seq *seq = nametbl_find_seq(type); - dbg("tipc_nametbl_insert_publ: {%u,%u,%u} found %p\n", type, lower, upper, seq); + dbg("ins_publ: <%u,%x,%x> found %x\n", type, lower, upper, seq); if (lower > upper) { - warn("Failed to publish illegal {%u,%u,%u}\n", + warn("Failed to publish illegal <%u,%u,%u>\n", type, lower, upper); return NULL; } - dbg("Publishing {%u,%u,%u} from 0x%x\n", type, lower, upper, node); + dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node); if (!seq) { seq = tipc_nameseq_create(type, &table.types[hash(type)]); - dbg("tipc_nametbl_insert_publ: created %p\n", seq); + dbg("tipc_nametbl_insert_publ: created %x\n", seq); } if (!seq) return NULL; + assert(seq->type == type); return tipc_nameseq_insert_publ(seq, type, lower, upper, scope, node, port, key); } @@ -593,7 +572,7 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, if (!seq) return NULL; - dbg("Withdrawing {%u,%u} from 0x%x\n", type, lower, node); + dbg("Withdrawing <%u,%u> from %x\n", type, lower, node); publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key); if (!seq->first_free && list_empty(&seq->subscriptions)) { @@ -759,12 +738,12 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, struct publication *publ; if (table.local_publ_count >= tipc_max_publications) { - warn("Publication failed, local publication limit reached (%u)\n", + warn("Failed publish: max %u local publication\n", tipc_max_publications); return NULL; } if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) { - warn("Publication failed, reserved name {%u,%u,%u}\n", + warn("Failed to publish reserved name <%u,%u,%u>\n", type, lower, upper); return NULL; } @@ -788,10 +767,10 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) { struct publication *publ; - dbg("tipc_nametbl_withdraw: {%u,%u}, key=%u\n", type, lower, key); + dbg("tipc_nametbl_withdraw:<%d,%d,%d>\n", type, lower, key); write_lock_bh(&tipc_nametbl_lock); publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); - if (likely(publ)) { + if (publ) { table.local_publ_count--; if (publ->scope != TIPC_NODE_SCOPE) tipc_named_withdraw(publ); @@ -801,9 +780,6 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) return 1; } write_unlock_bh(&tipc_nametbl_lock); - err("Unable to remove local publication\n" - "(type=%u, lower=%u, ref=%u, key=%u)\n", - type, lower, ref, key); return 0; } @@ -811,7 +787,8 @@ int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) * tipc_nametbl_subscribe - add a subscription object to the name table */ -void tipc_nametbl_subscribe(struct subscription *s) +void +tipc_nametbl_subscribe(struct subscription *s) { u32 type = s->seq.type; struct name_seq *seq; @@ -823,13 +800,11 @@ void tipc_nametbl_subscribe(struct subscription *s) } if (seq){ spin_lock_bh(&seq->lock); - dbg("tipc_nametbl_subscribe:found %p for {%u,%u,%u}\n", + dbg("tipc_nametbl_subscribe:found %x for <%u,%u,%u>\n", seq, type, s->seq.lower, s->seq.upper); + assert(seq->type == type); tipc_nameseq_subscribe(seq, s); spin_unlock_bh(&seq->lock); - } else { - warn("Failed to create subscription for {%u,%u,%u}\n", - s->seq.type, s->seq.lower, s->seq.upper); } write_unlock_bh(&tipc_nametbl_lock); } @@ -838,7 +813,8 @@ void tipc_nametbl_subscribe(struct subscription *s) * tipc_nametbl_unsubscribe - remove a subscription object from name table */ -void tipc_nametbl_unsubscribe(struct subscription *s) +void +tipc_nametbl_unsubscribe(struct subscription *s) { struct name_seq *seq; @@ -1073,20 +1049,35 @@ int tipc_nametbl_init(void) void tipc_nametbl_stop(void) { + struct hlist_head *seq_head; + struct hlist_node *seq_node; + struct hlist_node *tmp; + struct name_seq *seq; u32 i; if (!table.types) return; - /* Verify name table is empty, then release it */ - write_lock_bh(&tipc_nametbl_lock); for (i = 0; i < tipc_nametbl_size; i++) { - if (!hlist_empty(&table.types[i])) - err("tipc_nametbl_stop(): hash chain %u is non-null\n", i); + seq_head = &table.types[i]; + hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) { + struct sub_seq *sseq = seq->sseqs; + + for (; sseq != &seq->sseqs[seq->first_free]; sseq++) { + struct publication *publ = sseq->zone_list; + assert(publ); + do { + struct publication *next = + publ->zone_list_next; + kfree(publ); + publ = next; + } + while (publ != sseq->zone_list); + } + } } kfree(table.types); table.types = NULL; write_unlock_bh(&tipc_nametbl_lock); } - diff --git a/trunk/net/tipc/net.c b/trunk/net/tipc/net.c index e5a359ab4930..f7c8223ddf7d 100644 --- a/trunk/net/tipc/net.c +++ b/trunk/net/tipc/net.c @@ -115,7 +115,7 @@ * - A local spin_lock protecting the queue of subscriber events. */ -DEFINE_RWLOCK(tipc_net_lock); +rwlock_t tipc_net_lock = RW_LOCK_UNLOCKED; struct network tipc_net = { NULL }; struct node *tipc_net_select_remote_node(u32 addr, u32 ref) diff --git a/trunk/net/tipc/node.c b/trunk/net/tipc/node.c index fc6d09630ccd..0d5db06e203f 100644 --- a/trunk/net/tipc/node.c +++ b/trunk/net/tipc/node.c @@ -2,7 +2,7 @@ * net/tipc/node.c: TIPC node management routines * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems + * Copyright (c) 2005, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -61,37 +61,34 @@ struct node *tipc_node_create(u32 addr) struct node **curr_node; n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC); - if (!n_ptr) { - warn("Node creation failed, no memory\n"); - return NULL; - } - - c_ptr = tipc_cltr_find(addr); - if (!c_ptr) { - c_ptr = tipc_cltr_create(addr); - } - if (!c_ptr) { - kfree(n_ptr); - return NULL; - } - - memset(n_ptr, 0, sizeof(*n_ptr)); - n_ptr->addr = addr; - spin_lock_init(&n_ptr->lock); - INIT_LIST_HEAD(&n_ptr->nsub); - n_ptr->owner = c_ptr; - tipc_cltr_attach_node(c_ptr, n_ptr); - n_ptr->last_router = -1; - - /* Insert node into ordered list */ - for (curr_node = &tipc_nodes; *curr_node; - curr_node = &(*curr_node)->next) { - if (addr < (*curr_node)->addr) { - n_ptr->next = *curr_node; - break; - } - } - (*curr_node) = n_ptr; + if (n_ptr != NULL) { + memset(n_ptr, 0, sizeof(*n_ptr)); + n_ptr->addr = addr; + n_ptr->lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&n_ptr->nsub); + + c_ptr = tipc_cltr_find(addr); + if (c_ptr == NULL) + c_ptr = tipc_cltr_create(addr); + if (c_ptr != NULL) { + n_ptr->owner = c_ptr; + tipc_cltr_attach_node(c_ptr, n_ptr); + n_ptr->last_router = -1; + + /* Insert node into ordered list */ + for (curr_node = &tipc_nodes; *curr_node; + curr_node = &(*curr_node)->next) { + if (addr < (*curr_node)->addr) { + n_ptr->next = *curr_node; + break; + } + } + (*curr_node) = n_ptr; + } else { + kfree(n_ptr); + n_ptr = NULL; + } + } return n_ptr; } @@ -125,8 +122,6 @@ void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr) { struct link **active = &n_ptr->active_links[0]; - n_ptr->working_links++; - info("Established link <%s> on network plane %c\n", l_ptr->name, l_ptr->b_ptr->net_plane); @@ -137,7 +132,7 @@ void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr) return; } if (l_ptr->priority < active[0]->priority) { - info("New link <%s> becomes standby\n", l_ptr->name); + info("Link is standby\n"); return; } tipc_link_send_duplicate(active[0], l_ptr); @@ -145,9 +140,8 @@ void tipc_node_link_up(struct node *n_ptr, struct link *l_ptr) active[0] = l_ptr; return; } - info("Old link <%s> becomes standby\n", active[0]->name); - if (active[1] != active[0]) - info("Old link <%s> becomes standby\n", active[1]->name); + info("Link <%s> on network plane %c becomes standby\n", + active[0]->name, active[0]->b_ptr->net_plane); active[0] = active[1] = l_ptr; } @@ -187,8 +181,6 @@ void tipc_node_link_down(struct node *n_ptr, struct link *l_ptr) { struct link **active; - n_ptr->working_links--; - if (!tipc_link_is_active(l_ptr)) { info("Lost standby link <%s> on network plane %c\n", l_ptr->name, l_ptr->b_ptr->net_plane); @@ -218,7 +210,8 @@ int tipc_node_has_active_links(struct node *n_ptr) int tipc_node_has_redundant_links(struct node *n_ptr) { - return (n_ptr->working_links > 1); + return (tipc_node_has_active_links(n_ptr) && + (n_ptr->active_links[0] != n_ptr->active_links[1])); } static int tipc_node_has_active_routes(struct node *n_ptr) @@ -241,6 +234,7 @@ struct node *tipc_node_attach_link(struct link *l_ptr) u32 bearer_id = l_ptr->b_ptr->identity; char addr_string[16]; + assert(bearer_id < MAX_BEARERS); if (n_ptr->link_cnt >= 2) { char addr_string[16]; @@ -255,7 +249,7 @@ struct node *tipc_node_attach_link(struct link *l_ptr) n_ptr->link_cnt++; return n_ptr; } - err("Attempt to establish second link on <%s> to %s \n", + err("Attempt to establish second link on <%s> to <%s> \n", l_ptr->b_ptr->publ.name, addr_string_fill(addr_string, l_ptr->addr)); } @@ -320,7 +314,7 @@ static void node_established_contact(struct node *n_ptr) struct cluster *c_ptr; dbg("node_established_contact:-> %x\n", n_ptr->addr); - if (!tipc_node_has_active_routes(n_ptr) && in_own_cluster(n_ptr->addr)) { + if (!tipc_node_has_active_routes(n_ptr)) { tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr); } @@ -592,7 +586,6 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) struct sk_buff *buf; struct node *n_ptr; struct tipc_node_info node_info; - u32 payload_size; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); @@ -609,11 +602,8 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) /* For now, get space for all other nodes (will need to modify this when slave nodes are supported */ - payload_size = TLV_SPACE(sizeof(node_info)) * (tipc_max_nodes - 1); - if (payload_size > 32768u) - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (too many nodes)"); - buf = tipc_cfg_reply_alloc(payload_size); + buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) * + (tipc_max_nodes - 1)); if (!buf) return NULL; @@ -637,7 +627,6 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) struct sk_buff *buf; struct node *n_ptr; struct tipc_link_info link_info; - u32 payload_size; if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); @@ -650,15 +639,12 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) if (!tipc_nodes) return tipc_cfg_reply_none(); - - /* Get space for all unicast links + multicast link */ - - payload_size = TLV_SPACE(sizeof(link_info)) * - (tipc_net.zones[tipc_zone(tipc_own_addr)]->links + 1); - if (payload_size > 32768u) - return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED - " (too many links)"); - buf = tipc_cfg_reply_alloc(payload_size); + + /* For now, get space for 2 links to all other nodes + bcast link + (will need to modify this when slave nodes are supported */ + + buf = tipc_cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) * + (2 * (tipc_max_nodes - 1) + 1)); if (!buf) return NULL; diff --git a/trunk/net/tipc/node.h b/trunk/net/tipc/node.h index a07cc79ea637..781126e084ae 100644 --- a/trunk/net/tipc/node.h +++ b/trunk/net/tipc/node.h @@ -51,7 +51,6 @@ * @nsub: list of "node down" subscriptions monitoring node * @active_links: pointers to active links to node * @links: pointers to all links to node - * @working_links: number of working links to node (both active and standby) * @link_cnt: number of links to node * @permit_changeover: non-zero if node has redundant links to this system * @routers: bitmap (used for multicluster communication) @@ -77,7 +76,6 @@ struct node { struct link *active_links[2]; struct link *links[MAX_BEARERS]; int link_cnt; - int working_links; int permit_changeover; u32 routers[512/32]; int last_router; diff --git a/trunk/net/tipc/node_subscr.c b/trunk/net/tipc/node_subscr.c index cc3fff3dec4f..cff4068cc755 100644 --- a/trunk/net/tipc/node_subscr.c +++ b/trunk/net/tipc/node_subscr.c @@ -47,19 +47,18 @@ void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr, void *usr_handle, net_ev_handler handle_down) { - if (addr == tipc_own_addr) { - node_sub->node = NULL; + node_sub->node = NULL; + if (addr == tipc_own_addr) return; - } - - node_sub->node = tipc_node_find(addr); - if (!node_sub->node) { - warn("Node subscription rejected, unknown node 0x%x\n", addr); + if (!tipc_addr_node_valid(addr)) { + warn("node_subscr with illegal %x\n", addr); return; } + node_sub->handle_node_down = handle_down; node_sub->usr_handle = usr_handle; - + node_sub->node = tipc_node_find(addr); + assert(node_sub->node); tipc_node_lock(node_sub->node); list_add_tail(&node_sub->nodesub_list, &node_sub->node->nsub); tipc_node_unlock(node_sub->node); diff --git a/trunk/net/tipc/port.c b/trunk/net/tipc/port.c index 3251c8d8e53c..67e96cb1e825 100644 --- a/trunk/net/tipc/port.c +++ b/trunk/net/tipc/port.c @@ -57,8 +57,8 @@ static struct sk_buff *msg_queue_head = NULL; static struct sk_buff *msg_queue_tail = NULL; -DEFINE_SPINLOCK(tipc_port_list_lock); -static DEFINE_SPINLOCK(queue_lock); +spinlock_t tipc_port_list_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(ports); static void port_handle_node_down(unsigned long ref); @@ -168,6 +168,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp) struct port_list *item = dp; int cnt = 0; + assert(buf); msg = buf_msg(buf); /* Create destination port list, if one wasn't supplied */ @@ -195,7 +196,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp) struct sk_buff *b = skb_clone(buf, GFP_ATOMIC); if (b == NULL) { - warn("Unable to deliver multicast message(s)\n"); + warn("Buffer allocation failure\n"); msg_dbg(msg, "LOST:"); goto exit; } @@ -227,14 +228,14 @@ u32 tipc_createport_raw(void *usr_handle, u32 ref; p_ptr = kmalloc(sizeof(*p_ptr), GFP_ATOMIC); - if (!p_ptr) { - warn("Port creation failed, no memory\n"); + if (p_ptr == NULL) { + warn("Memory squeeze; failed to create port\n"); return 0; } memset(p_ptr, 0, sizeof(*p_ptr)); ref = tipc_ref_acquire(p_ptr, &p_ptr->publ.lock); if (!ref) { - warn("Port creation failed, reference table exhausted\n"); + warn("Reference Table Exhausted\n"); kfree(p_ptr); return 0; } @@ -809,20 +810,18 @@ static void port_dispatcher_sigh(void *dummy) void *usr_handle; int connected; int published; - u32 message_type; struct sk_buff *next = buf->next; struct tipc_msg *msg = buf_msg(buf); u32 dref = msg_destport(msg); - message_type = msg_type(msg); - if (message_type > TIPC_DIRECT_MSG) - goto reject; /* Unsupported message type */ - p_ptr = tipc_port_lock(dref); - if (!p_ptr) - goto reject; /* Port deleted while msg in queue */ - + if (!p_ptr) { + /* Port deleted while msg in queue */ + tipc_reject_msg(buf, TIPC_ERR_NO_PORT); + buf = next; + continue; + } orig.ref = msg_origport(msg); orig.node = msg_orignode(msg); up_ptr = p_ptr->user_port; @@ -833,7 +832,7 @@ static void port_dispatcher_sigh(void *dummy) if (unlikely(msg_errcode(msg))) goto err; - switch (message_type) { + switch (msg_type(msg)) { case TIPC_CONN_MSG:{ tipc_conn_msg_event cb = up_ptr->conn_msg_cb; @@ -875,7 +874,6 @@ static void port_dispatcher_sigh(void *dummy) &orig); break; } - case TIPC_MCAST_MSG: case TIPC_NAMED_MSG:{ tipc_named_msg_event cb = up_ptr->named_msg_cb; @@ -888,8 +886,7 @@ static void port_dispatcher_sigh(void *dummy) goto reject; dseq.type = msg_nametype(msg); dseq.lower = msg_nameinst(msg); - dseq.upper = (message_type == TIPC_NAMED_MSG) - ? dseq.lower : msg_nameupper(msg); + dseq.upper = dseq.lower; skb_pull(buf, msg_hdr_sz(msg)); cb(usr_handle, dref, &buf, msg_data(msg), msg_data_sz(msg), msg_importance(msg), @@ -902,7 +899,7 @@ static void port_dispatcher_sigh(void *dummy) buf = next; continue; err: - switch (message_type) { + switch (msg_type(msg)) { case TIPC_CONN_MSG:{ tipc_conn_shutdown_event cb = @@ -934,7 +931,6 @@ static void port_dispatcher_sigh(void *dummy) msg_data_sz(msg), msg_errcode(msg), &orig); break; } - case TIPC_MCAST_MSG: case TIPC_NAMED_MSG:{ tipc_named_msg_err_event cb = up_ptr->named_err_cb; @@ -944,8 +940,7 @@ static void port_dispatcher_sigh(void *dummy) break; dseq.type = msg_nametype(msg); dseq.lower = msg_nameinst(msg); - dseq.upper = (message_type == TIPC_NAMED_MSG) - ? dseq.lower : msg_nameupper(msg); + dseq.upper = dseq.lower; skb_pull(buf, msg_hdr_sz(msg)); cb(usr_handle, dref, &buf, msg_data(msg), msg_data_sz(msg), msg_errcode(msg), &dseq); @@ -1059,8 +1054,7 @@ int tipc_createport(u32 user_ref, u32 ref; up_ptr = (struct user_port *)kmalloc(sizeof(*up_ptr), GFP_ATOMIC); - if (!up_ptr) { - warn("Port creation failed, no memory\n"); + if (up_ptr == NULL) { return -ENOMEM; } ref = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, importance); @@ -1171,6 +1165,8 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) p_ptr = tipc_port_lock(ref); if (!p_ptr) return -EINVAL; + if (!p_ptr->publ.published) + goto exit; if (!seq) { list_for_each_entry_safe(publ, tpubl, &p_ptr->publications, pport_list) { @@ -1197,6 +1193,7 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) } if (list_empty(&p_ptr->publications)) p_ptr->publ.published = 0; +exit: tipc_port_unlock(p_ptr); return res; } diff --git a/trunk/net/tipc/ref.c b/trunk/net/tipc/ref.c index 596d3c8ff750..33bbf5095094 100644 --- a/trunk/net/tipc/ref.c +++ b/trunk/net/tipc/ref.c @@ -63,7 +63,7 @@ struct ref_table tipc_ref_table = { NULL }; -static DEFINE_RWLOCK(ref_table_lock); +static rwlock_t ref_table_lock = RW_LOCK_UNLOCKED; /** * tipc_ref_table_init - create reference table for objects @@ -87,7 +87,7 @@ int tipc_ref_table_init(u32 requested_size, u32 start) index_mask = sz - 1; for (i = sz - 1; i >= 0; i--) { table[i].object = NULL; - spin_lock_init(&table[i].lock); + table[i].lock = SPIN_LOCK_UNLOCKED; table[i].data.next_plus_upper = (start & ~index_mask) + i - 1; } tipc_ref_table.entries = table; @@ -127,14 +127,7 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock) u32 next_plus_upper; u32 reference = 0; - if (!object) { - err("Attempt to acquire reference to non-existent object\n"); - return 0; - } - if (!tipc_ref_table.entries) { - err("Reference table not found during acquisition attempt\n"); - return 0; - } + assert(tipc_ref_table.entries && object); write_lock_bh(&ref_table_lock); if (tipc_ref_table.first_free) { @@ -169,28 +162,15 @@ void tipc_ref_discard(u32 ref) u32 index; u32 index_mask; - if (!ref) { - err("Attempt to discard reference 0\n"); - return; - } - if (!tipc_ref_table.entries) { - err("Reference table not found during discard attempt\n"); - return; - } + assert(tipc_ref_table.entries); + assert(ref != 0); write_lock_bh(&ref_table_lock); index_mask = tipc_ref_table.index_mask; index = ref & index_mask; entry = &(tipc_ref_table.entries[index]); - - if (!entry->object) { - err("Attempt to discard reference to non-existent object\n"); - goto exit; - } - if (entry->data.reference != ref) { - err("Attempt to discard non-existent reference\n"); - goto exit; - } + assert(entry->object != 0); + assert(entry->data.reference == ref); /* mark entry as unused */ entry->object = NULL; @@ -204,7 +184,6 @@ void tipc_ref_discard(u32 ref) /* increment upper bits of entry to invalidate subsequent references */ entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1); -exit: write_unlock_bh(&ref_table_lock); } diff --git a/trunk/net/tipc/socket.c b/trunk/net/tipc/socket.c index 32d778448a00..648a734e6044 100644 --- a/trunk/net/tipc/socket.c +++ b/trunk/net/tipc/socket.c @@ -169,6 +169,12 @@ static int tipc_create(struct socket *sock, int protocol) struct sock *sk; u32 ref; + if ((sock->type != SOCK_STREAM) && + (sock->type != SOCK_SEQPACKET) && + (sock->type != SOCK_DGRAM) && + (sock->type != SOCK_RDM)) + return -EPROTOTYPE; + if (unlikely(protocol != 0)) return -EPROTONOSUPPORT; @@ -193,9 +199,6 @@ static int tipc_create(struct socket *sock, int protocol) sock->ops = &msg_ops; sock->state = SS_READY; break; - default: - tipc_deleteport(ref); - return -EPROTOTYPE; } sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1); @@ -423,7 +426,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr))) return -EFAULT; - if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN))) + if ((ntohs(hdr.tcm_type) & 0xC000) & (!capable(CAP_NET_ADMIN))) return -EACCES; return 0; @@ -434,7 +437,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) * @iocb: (unused) * @sock: socket structure * @m: message to send - * @total_len: length of message + * @total_len: (unused) * * Message must have an destination specified explicitly. * Used for SOCK_RDM and SOCK_DGRAM messages, @@ -455,8 +458,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, if (unlikely(!dest)) return -EDESTADDRREQ; - if (unlikely((m->msg_namelen < sizeof(*dest)) || - (dest->family != AF_TIPC))) + if (unlikely(dest->family != AF_TIPC)) return -EINVAL; needs_conn = (sock->state != SS_READY); @@ -468,10 +470,6 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, if ((tsock->p->published) || ((sock->type == SOCK_STREAM) && (total_len != 0))) return -EOPNOTSUPP; - if (dest->addrtype == TIPC_ADDR_NAME) { - tsock->p->conn_type = dest->addr.name.name.type; - tsock->p->conn_instance = dest->addr.name.name.instance; - } } if (down_interruptible(&tsock->sem)) @@ -540,7 +538,7 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, * @iocb: (unused) * @sock: socket structure * @m: message to send - * @total_len: length of message + * @total_len: (unused) * * Used for SOCK_SEQPACKET messages and SOCK_STREAM data. * @@ -563,15 +561,15 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, return -ERESTARTSYS; } - do { - if (unlikely(sock->state != SS_CONNECTED)) { - if (sock->state == SS_DISCONNECTING) - res = -EPIPE; - else - res = -ENOTCONN; - goto exit; - } + if (unlikely(sock->state != SS_CONNECTED)) { + if (sock->state == SS_DISCONNECTING) + res = -EPIPE; + else + res = -ENOTCONN; + goto exit; + } + do { res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov); if (likely(res != -ELINKCONG)) { exit: @@ -599,8 +597,7 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, * * Used for SOCK_STREAM data. * - * Returns the number of bytes sent on success (or partial success), - * or errno if no data sent + * Returns the number of bytes sent on success, or errno otherwise */ @@ -614,7 +611,6 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, char __user *curr_start; int curr_left; int bytes_to_send; - int bytes_sent; int res; if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE)) @@ -637,11 +633,11 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, * of small iovec entries into send_packet(). */ - curr_iov = m->msg_iov; - curr_iovlen = m->msg_iovlen; + my_msg = *m; + curr_iov = my_msg.msg_iov; + curr_iovlen = my_msg.msg_iovlen; my_msg.msg_iov = &my_iov; my_msg.msg_iovlen = 1; - bytes_sent = 0; while (curr_iovlen--) { curr_start = curr_iov->iov_base; @@ -652,18 +648,16 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, ? curr_left : TIPC_MAX_USER_MSG_SIZE; my_iov.iov_base = curr_start; my_iov.iov_len = bytes_to_send; - if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) { - return bytes_sent ? bytes_sent : res; - } + if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) + return res; curr_left -= bytes_to_send; curr_start += bytes_to_send; - bytes_sent += bytes_to_send; } curr_iov++; } - return bytes_sent; + return total_len; } /** @@ -733,7 +727,6 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, u32 anc_data[3]; u32 err; u32 dest_type; - int has_name; int res; if (likely(m->msg_controllen == 0)) @@ -745,10 +738,10 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, if (unlikely(err)) { anc_data[0] = err; anc_data[1] = msg_data_sz(msg); - if ((res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data))) + if ((res = put_cmsg(m, SOL_SOCKET, TIPC_ERRINFO, 8, anc_data))) return res; if (anc_data[1] && - (res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], + (res = put_cmsg(m, SOL_SOCKET, TIPC_RETDATA, anc_data[1], msg_data(msg)))) return res; } @@ -758,28 +751,25 @@ static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG; switch (dest_type) { case TIPC_NAMED_MSG: - has_name = 1; anc_data[0] = msg_nametype(msg); anc_data[1] = msg_namelower(msg); anc_data[2] = msg_namelower(msg); break; case TIPC_MCAST_MSG: - has_name = 1; anc_data[0] = msg_nametype(msg); anc_data[1] = msg_namelower(msg); anc_data[2] = msg_nameupper(msg); break; case TIPC_CONN_MSG: - has_name = (tport->conn_type != 0); anc_data[0] = tport->conn_type; anc_data[1] = tport->conn_instance; anc_data[2] = tport->conn_instance; break; default: - has_name = 0; + anc_data[0] = 0; } - if (has_name && - (res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data))) + if (anc_data[0] && + (res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data))) return res; return 0; @@ -970,7 +960,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, restart: if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && (flags & MSG_DONTWAIT))) { - res = -EWOULDBLOCK; + res = (sz_copied == 0) ? -EWOULDBLOCK : 0; goto exit; } @@ -1061,7 +1051,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, exit: up(&tsock->sem); - return sz_copied ? sz_copied : res; + return res ? res : sz_copied; } /** @@ -1246,8 +1236,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, if (sock->state == SS_READY) return -EOPNOTSUPP; - /* Issue Posix-compliant error code if socket is in the wrong state */ - + /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */ if (sock->state == SS_LISTENING) return -EOPNOTSUPP; if (sock->state == SS_CONNECTING) @@ -1255,20 +1244,13 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, if (sock->state != SS_UNCONNECTED) return -EISCONN; - /* - * Reject connection attempt using multicast address - * - * Note: send_msg() validates the rest of the address fields, - * so there's no need to do it here - */ - - if (dst->addrtype == TIPC_ADDR_MCAST) + if ((dst->family != AF_TIPC) || + ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID))) return -EINVAL; /* Send a 'SYN-' to destination */ m.msg_name = dest; - m.msg_namelen = destlen; if ((res = send_msg(NULL, sock, &m, 0)) < 0) { sock->state = SS_DISCONNECTING; return res; @@ -1287,6 +1269,10 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, msg = buf_msg(buf); res = auto_connect(sock, tsock, msg); if (!res) { + if (dst->addrtype == TIPC_ADDR_NAME) { + tsock->p->conn_type = dst->addr.name.name.type; + tsock->p->conn_instance = dst->addr.name.name.instance; + } if (!msg_data_sz(msg)) advance_queue(tsock); } @@ -1400,7 +1386,7 @@ static int accept(struct socket *sock, struct socket *newsock, int flags) /** * shutdown - shutdown socket connection * @sock: socket structure - * @how: direction to close (unused; always treated as read + write) + * @how: direction to close (always treated as read + write) * * Terminates connection (if necessary), then purges socket's receive queue. * @@ -1483,8 +1469,7 @@ static int shutdown(struct socket *sock, int how) * Returns 0 on success, errno otherwise */ -static int setsockopt(struct socket *sock, - int lvl, int opt, char __user *ov, int ol) +static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol) { struct tipc_sock *tsock = tipc_sk(sock->sk); u32 value; @@ -1540,8 +1525,7 @@ static int setsockopt(struct socket *sock, * Returns 0 on success, errno otherwise */ -static int getsockopt(struct socket *sock, - int lvl, int opt, char __user *ov, int *ol) +static int getsockopt(struct socket *sock, int lvl, int opt, char *ov, int *ol) { struct tipc_sock *tsock = tipc_sk(sock->sk); int len; diff --git a/trunk/net/tipc/subscr.c b/trunk/net/tipc/subscr.c index e19b4bcd67ec..c5f026c7fd38 100644 --- a/trunk/net/tipc/subscr.c +++ b/trunk/net/tipc/subscr.c @@ -266,8 +266,7 @@ static void subscr_subscribe(struct tipc_subscr *s, /* Refuse subscription if global limit exceeded */ if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { - warn("Subscription rejected, subscription limit reached (%u)\n", - tipc_max_subscriptions); + warn("Failed: max %u subscriptions\n", tipc_max_subscriptions); subscr_terminate(subscriber); return; } @@ -275,8 +274,8 @@ static void subscr_subscribe(struct tipc_subscr *s, /* Allocate subscription object */ sub = kmalloc(sizeof(*sub), GFP_ATOMIC); - if (!sub) { - warn("Subscription rejected, no memory\n"); + if (sub == NULL) { + warn("Memory squeeze; ignoring subscription\n"); subscr_terminate(subscriber); return; } @@ -299,7 +298,8 @@ static void subscr_subscribe(struct tipc_subscr *s, if ((((sub->filter != TIPC_SUB_PORTS) && (sub->filter != TIPC_SUB_SERVICE))) || (sub->seq.lower > sub->seq.upper)) { - warn("Subscription rejected, illegal request\n"); + warn("Rejecting illegal subscription %u,%u,%u\n", + sub->seq.type, sub->seq.lower, sub->seq.upper); kfree(sub); subscr_terminate(subscriber); return; @@ -387,7 +387,7 @@ static void subscr_named_msg_event(void *usr_handle, dbg("subscr_named_msg_event: orig = %x own = %x,\n", orig->node, tipc_own_addr); if (size && (size != sizeof(struct tipc_subscr))) { - warn("Subscriber rejected, invalid subscription size\n"); + warn("Received tipc_subscr of invalid size\n"); return; } @@ -395,7 +395,7 @@ static void subscr_named_msg_event(void *usr_handle, subscriber = kmalloc(sizeof(struct subscriber), GFP_ATOMIC); if (subscriber == NULL) { - warn("Subscriber rejected, no memory\n"); + warn("Memory squeeze; ignoring subscriber setup\n"); return; } memset(subscriber, 0, sizeof(struct subscriber)); @@ -403,7 +403,7 @@ static void subscr_named_msg_event(void *usr_handle, INIT_LIST_HEAD(&subscriber->subscriber_list); subscriber->ref = tipc_ref_acquire(subscriber, &subscriber->lock); if (subscriber->ref == 0) { - warn("Subscriber rejected, reference table exhausted\n"); + warn("Failed to acquire subscriber reference\n"); kfree(subscriber); return; } @@ -422,7 +422,7 @@ static void subscr_named_msg_event(void *usr_handle, NULL, &subscriber->port_ref); if (subscriber->port_ref == 0) { - warn("Subscriber rejected, unable to create port\n"); + warn("Memory squeeze; failed to create subscription port\n"); tipc_ref_discard(subscriber->ref); kfree(subscriber); return; @@ -457,7 +457,7 @@ int tipc_subscr_start(void) int res = -1; memset(&topsrv, 0, sizeof (topsrv)); - spin_lock_init(&topsrv.lock); + topsrv.lock = SPIN_LOCK_UNLOCKED; INIT_LIST_HEAD(&topsrv.subscriber_list); spin_lock_bh(&topsrv.lock); diff --git a/trunk/net/tipc/user_reg.c b/trunk/net/tipc/user_reg.c index 1e3ae57c7228..3f3f933976e9 100644 --- a/trunk/net/tipc/user_reg.c +++ b/trunk/net/tipc/user_reg.c @@ -67,7 +67,7 @@ struct tipc_user { static struct tipc_user *users = NULL; static u32 next_free_user = MAX_USERID + 1; -static DEFINE_SPINLOCK(reg_lock); +static spinlock_t reg_lock = SPIN_LOCK_UNLOCKED; /** * reg_init - create TIPC user registry (but don't activate it) diff --git a/trunk/net/tipc/zone.c b/trunk/net/tipc/zone.c index 316c4872ff5b..2803e1b4f170 100644 --- a/trunk/net/tipc/zone.c +++ b/trunk/net/tipc/zone.c @@ -44,24 +44,19 @@ struct _zone *tipc_zone_create(u32 addr) { - struct _zone *z_ptr; + struct _zone *z_ptr = NULL; u32 z_num; - if (!tipc_addr_domain_valid(addr)) { - err("Zone creation failed, invalid domain 0x%x\n", addr); + if (!tipc_addr_domain_valid(addr)) return NULL; - } z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC); - if (!z_ptr) { - warn("Zone creation failed, insufficient memory\n"); - return NULL; + if (z_ptr != NULL) { + memset(z_ptr, 0, sizeof(*z_ptr)); + z_num = tipc_zone(addr); + z_ptr->addr = tipc_addr(z_num, 0, 0); + tipc_net.zones[z_num] = z_ptr; } - - memset(z_ptr, 0, sizeof(*z_ptr)); - z_num = tipc_zone(addr); - z_ptr->addr = tipc_addr(z_num, 0, 0); - tipc_net.zones[z_num] = z_ptr; return z_ptr; } diff --git a/trunk/net/tipc/zone.h b/trunk/net/tipc/zone.h index 5ab3d08602e2..267999c5a240 100644 --- a/trunk/net/tipc/zone.h +++ b/trunk/net/tipc/zone.h @@ -2,7 +2,7 @@ * net/tipc/zone.h: Include file for TIPC zone management routines * * Copyright (c) 2000-2006, Ericsson AB - * Copyright (c) 2005-2006, Wind River Systems + * Copyright (c) 2005, Wind River Systems * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,7 +45,7 @@ * struct _zone - TIPC zone structure * @addr: network address of zone * @clusters: array of pointers to all clusters within zone - * @links: number of (unicast) links to zone + * @links: (used for inter-zone communication) */ struct _zone { diff --git a/trunk/net/unix/af_unix.c b/trunk/net/unix/af_unix.c index aca650109425..d901465ce013 100644 --- a/trunk/net/unix/af_unix.c +++ b/trunk/net/unix/af_unix.c @@ -83,6 +83,7 @@ */ #include +#include #include #include #include @@ -127,30 +128,6 @@ static atomic_t unix_nr_socks = ATOMIC_INIT(0); #define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE) -#ifdef CONFIG_SECURITY_NETWORK -static void unix_get_peersec_dgram(struct sk_buff *skb) -{ - int err; - - err = security_socket_getpeersec_dgram(skb, UNIXSECDATA(skb), - UNIXSECLEN(skb)); - if (err) - *(UNIXSECDATA(skb)) = NULL; -} - -static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) -{ - scm->secdata = *UNIXSECDATA(skb); - scm->seclen = *UNIXSECLEN(skb); -} -#else -static void unix_get_peersec_dgram(struct sk_buff *skb) -{ } - -static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) -{ } -#endif /* CONFIG_SECURITY_NETWORK */ - /* * SMP locking strategy: * hash table is protected with spinlock unix_table_lock @@ -1314,8 +1291,6 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, if (siocb->scm->fp) unix_attach_fds(siocb->scm, skb); - unix_get_peersec_dgram(skb); - skb->h.raw = skb->data; err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len); if (err) @@ -1595,7 +1570,6 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, memset(&tmp_scm, 0, sizeof(tmp_scm)); } siocb->scm->creds = *UNIXCREDS(skb); - unix_set_secdata(siocb->scm, skb); if (!(flags & MSG_PEEK)) { diff --git a/trunk/net/wanrouter/af_wanpipe.c b/trunk/net/wanrouter/af_wanpipe.c index a690cf773b6a..b1265187b4a8 100644 --- a/trunk/net/wanrouter/af_wanpipe.c +++ b/trunk/net/wanrouter/af_wanpipe.c @@ -32,6 +32,7 @@ * ******************************************************************************/ +#include #include #include #include diff --git a/trunk/net/wanrouter/wanmain.c b/trunk/net/wanrouter/wanmain.c index ad8e8a797790..c34833dc7cc1 100644 --- a/trunk/net/wanrouter/wanmain.c +++ b/trunk/net/wanrouter/wanmain.c @@ -42,6 +42,7 @@ * Jun 02, 1999 Gideon Hack Updates for Linux 2.0.X and 2.2.X kernels. *****************************************************************************/ +#include #include /* offsetof(), etc. */ #include #include /* return codes */ diff --git a/trunk/net/wanrouter/wanproc.c b/trunk/net/wanrouter/wanproc.c index 930ea59463ad..c28ba5a47209 100644 --- a/trunk/net/wanrouter/wanproc.c +++ b/trunk/net/wanrouter/wanproc.c @@ -20,6 +20,7 @@ * Dec 13, 1996 Gene Kozin Initial version (based on Sangoma's WANPIPE) *****************************************************************************/ +#include #include /* __initfunc et al. */ #include /* offsetof(), etc. */ #include /* return codes */ diff --git a/trunk/net/x25/af_x25.c b/trunk/net/x25/af_x25.c index 52a2726d327f..282ce4e40d7b 100644 --- a/trunk/net/x25/af_x25.c +++ b/trunk/net/x25/af_x25.c @@ -35,6 +35,7 @@ * response */ +#include #include #include #include diff --git a/trunk/net/x25/x25_dev.c b/trunk/net/x25/x25_dev.c index 47b68a301677..adfe7b8df355 100644 --- a/trunk/net/x25/x25_dev.c +++ b/trunk/net/x25/x25_dev.c @@ -17,6 +17,7 @@ * 2000-09-04 Henner Eisen Prevent freeing a dangling skb. */ +#include #include #include #include diff --git a/trunk/net/x25/x25_proc.c b/trunk/net/x25/x25_proc.c index a11837d361d2..dfb80116c59f 100644 --- a/trunk/net/x25/x25_proc.c +++ b/trunk/net/x25/x25_proc.c @@ -17,6 +17,7 @@ * 2002/10/06 Arnaldo Carvalho de Melo seq_file support */ +#include #include #include #include diff --git a/trunk/net/x25/x25_route.c b/trunk/net/x25/x25_route.c index 2a3fe986b245..6c5d37517035 100644 --- a/trunk/net/x25/x25_route.c +++ b/trunk/net/x25/x25_route.c @@ -17,6 +17,7 @@ * X.25 001 Jonathan Naylor Started coding. */ +#include #include #include #include diff --git a/trunk/net/xfrm/xfrm_algo.c b/trunk/net/xfrm/xfrm_algo.c index 04e1aea58bc9..6ed3302312fb 100644 --- a/trunk/net/xfrm/xfrm_algo.c +++ b/trunk/net/xfrm/xfrm_algo.c @@ -9,6 +9,7 @@ * any later version. */ +#include #include #include #include diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index 405b741dff43..b8936926c24b 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -13,6 +13,7 @@ * */ +#include #include #include #include diff --git a/trunk/net/xfrm/xfrm_state.c b/trunk/net/xfrm/xfrm_state.c index 43f00fc28a3d..17b29ec3c417 100644 --- a/trunk/net/xfrm/xfrm_state.c +++ b/trunk/net/xfrm/xfrm_state.c @@ -1164,6 +1164,8 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu) return res; } +EXPORT_SYMBOL(xfrm_state_mtu); + int xfrm_init_state(struct xfrm_state *x) { struct xfrm_state_afinfo *afinfo; diff --git a/trunk/net/xfrm/xfrm_user.c b/trunk/net/xfrm/xfrm_user.c index 3e6a722d072e..c21dc26141ea 100644 --- a/trunk/net/xfrm/xfrm_user.c +++ b/trunk/net/xfrm/xfrm_user.c @@ -1435,7 +1435,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *err link = &xfrm_dispatch[type]; /* All operations require privileges, even GET */ - if (security_netlink_recv(skb, CAP_NET_ADMIN)) { + if (security_netlink_recv(skb)) { *errp = -EPERM; return -1; } diff --git a/trunk/scripts/Kbuild.include b/trunk/scripts/Kbuild.include index 2180c88cfe89..b0d067be7390 100644 --- a/trunk/scripts/Kbuild.include +++ b/trunk/scripts/Kbuild.include @@ -12,10 +12,6 @@ space := $(empty) $(empty) # contain a comma depfile = $(subst $(comma),_,$(@D)/.$(@F).d) -### -# filename of target with directory and extension stripped -basetarget = $(basename $(notdir $@)) - ### # Escape single quote for use in echo statements escsq = $(subst $(squote),'\$(squote)',$1) diff --git a/trunk/scripts/Makefile.build b/trunk/scripts/Makefile.build index 3cb445cc7432..e48e60da3040 100644 --- a/trunk/scripts/Makefile.build +++ b/trunk/scripts/Makefile.build @@ -8,7 +8,7 @@ PHONY := __build __build: # Read .config if it exist, otherwise ignore --include include/config/auto.conf +-include .config include scripts/Kbuild.include @@ -117,7 +117,7 @@ $(real-objs-m:.o=.lst): quiet_modtag := [M] $(obj-m) : quiet_modtag := [M] # Default for not multi-part modules -modname = $(basetarget) +modname = $(*F) $(multi-objs-m) : modname = $(modname-multi) $(multi-objs-m:.o=.i) : modname = $(modname-multi) @@ -140,15 +140,6 @@ cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $< %.i: %.c FORCE $(call if_changed_dep,cc_i_c) -quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ -cmd_cc_symtypes_c = \ - $(CPP) -D__GENKSYMS__ $(c_flags) $< \ - | $(GENKSYMS) -T $@ >/dev/null; \ - test -s $@ || rm -f $@ - -%.symtypes : %.c FORCE - $(call if_changed_dep,cc_symtypes_c) - # C (.c) files # The C file is compiled and updated dependency information is generated. # (See cmd_cc_o_c + relevant part of rule_cc_o_c) @@ -175,8 +166,7 @@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< cmd_modversions = \ if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ $(CPP) -D__GENKSYMS__ $(c_flags) $< \ - | $(GENKSYMS) $(if $(KBUILD_SYMTYPES), \ - -T $(@D)/$(@F:.o=.symtypes)) -a $(ARCH) \ + | $(GENKSYMS) -a $(ARCH) \ > $(@D)/.tmp_$(@F:.o=.ver); \ \ $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ diff --git a/trunk/scripts/Makefile.host b/trunk/scripts/Makefile.host index 18ecd4d5df7f..2d519704b8fd 100644 --- a/trunk/scripts/Makefile.host +++ b/trunk/scripts/Makefile.host @@ -33,8 +33,8 @@ __hostprogs := $(sort $(hostprogs-y)$(hostprogs-m)) # hostprogs-y := tools/build may have been specified. Retreive directory -host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) -host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs)))) +obj-dirs += $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) +obj-dirs := $(strip $(sort $(filter-out ./,$(obj-dirs)))) # C code @@ -73,17 +73,13 @@ host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti)) host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs)) host-cshlib := $(addprefix $(obj)/,$(host-cshlib)) host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs)) -host-objdirs := $(addprefix $(obj)/,$(host-objdirs)) - -obj-dirs += $(host-objdirs) +obj-dirs := $(addprefix $(obj)/,$(obj-dirs)) ##### # Handle options to gcc. Support building with separate output directory -_hostc_flags = $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \ - $(HOSTCFLAGS_$(basetarget).o) -_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \ - $(HOSTCXXFLAGS_$(basetarget).o) +_hostc_flags = $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) $(HOSTCFLAGS_$(*F).o) +_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) $(HOSTCXXFLAGS_$(*F).o) ifeq ($(KBUILD_SRC),) __hostc_flags = $(_hostc_flags) diff --git a/trunk/scripts/Makefile.lib b/trunk/scripts/Makefile.lib index fc498fee68ed..2cb4935e85d1 100644 --- a/trunk/scripts/Makefile.lib +++ b/trunk/scripts/Makefile.lib @@ -82,12 +82,12 @@ obj-dirs := $(addprefix $(obj)/,$(obj-dirs)) # than one module. In that case KBUILD_MODNAME will be set to foo_bar, # where foo and bar are the name of the modules. name-fix = $(subst $(comma),_,$(subst -,_,$1)) -basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(*F)))" modname_flags = $(if $(filter 1,$(words $(modname))),\ -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") -_c_flags = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(basetarget).o) -_a_flags = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(basetarget).o) +_c_flags = $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F).o) +_a_flags = $(AFLAGS) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o) _cpp_flags = $(CPPFLAGS) $(EXTRA_CPPFLAGS) $(CPPFLAGS_$(@F)) # If building the kernel in a separate objtree expand all occurrences diff --git a/trunk/scripts/Makefile.modinst b/trunk/scripts/Makefile.modinst index f0ff248f5e6f..2686dd5dce8c 100644 --- a/trunk/scripts/Makefile.modinst +++ b/trunk/scripts/Makefile.modinst @@ -17,7 +17,7 @@ __modinst: $(modules) @: quiet_cmd_modules_install = INSTALL $@ - cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) + cmd_modules_install = mkdir -p $(2); cp $@ $(2) # Modules built outside the kernel source tree go into extra by default INSTALL_MOD_DIR ?= extra diff --git a/trunk/scripts/Makefile.modpost b/trunk/scripts/Makefile.modpost index a49550205dcc..0e056cffffdb 100644 --- a/trunk/scripts/Makefile.modpost +++ b/trunk/scripts/Makefile.modpost @@ -35,7 +35,7 @@ PHONY := _modpost _modpost: __modpost -include include/config/auto.conf +include .config include scripts/Kbuild.include include scripts/Makefile.lib @@ -72,7 +72,7 @@ $(modules:.ko=.mod.c): __modpost ; # Step 5), compile all *.mod.c files # modname is set to make c_flags define KBUILD_MODNAME -modname = $(notdir $(@:.mod.o=)) +modname = $(*F) quiet_cmd_cc_o_c = CC $@ cmd_cc_o_c = $(CC) $(c_flags) $(CFLAGS_MODULE) \ diff --git a/trunk/scripts/basic/Makefile b/trunk/scripts/basic/Makefile index 2f60070f9733..f22e94c3a2d1 100644 --- a/trunk/scripts/basic/Makefile +++ b/trunk/scripts/basic/Makefile @@ -1,15 +1,17 @@ ### # Makefile.basic list the most basic programs used during the build process. # The programs listed herein is what is needed to do the basic stuff, -# such as fix dependency file. +# such as splitting .config and fix dependency file. # This initial step is needed to avoid files to be recompiled # when kernel configuration changes (which is what happens when # .config is included by main Makefile. # --------------------------------------------------------------------------- # fixdep: Used to generate dependency information during build process +# split-include: Divide all config symbols up in a number of files in +# include/config/... # docproc: Used in Documentation/docbook -hostprogs-y := fixdep docproc +hostprogs-y := fixdep split-include docproc always := $(hostprogs-y) # fixdep is needed to compile other host programs diff --git a/trunk/scripts/basic/split-include.c b/trunk/scripts/basic/split-include.c new file mode 100644 index 000000000000..459c45276cb1 --- /dev/null +++ b/trunk/scripts/basic/split-include.c @@ -0,0 +1,226 @@ +/* + * split-include.c + * + * Copyright abandoned, Michael Chastain, . + * This is a C version of syncdep.pl by Werner Almesberger. + * + * This program takes autoconf.h as input and outputs a directory full + * of one-line include files, merging onto the old values. + * + * Think of the configuration options as key-value pairs. Then there + * are five cases: + * + * key old value new value action + * + * KEY-1 VALUE-1 VALUE-1 leave file alone + * KEY-2 VALUE-2A VALUE-2B write VALUE-2B into file + * KEY-3 - VALUE-3 write VALUE-3 into file + * KEY-4 VALUE-4 - write an empty file + * KEY-5 (empty) - leave old empty file alone + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define ERROR_EXIT(strExit) \ + { \ + const int errnoSave = errno; \ + fprintf(stderr, "%s: ", str_my_name); \ + errno = errnoSave; \ + perror((strExit)); \ + exit(1); \ + } + + + +int main(int argc, const char * argv []) +{ + const char * str_my_name; + const char * str_file_autoconf; + const char * str_dir_config; + + FILE * fp_config; + FILE * fp_target; + FILE * fp_find; + + int buffer_size; + + char * line; + char * old_line; + char * list_target; + char * ptarget; + + struct stat stat_buf; + + /* Check arg count. */ + if (argc != 3) + { + fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]); + exit(1); + } + + str_my_name = argv[0]; + str_file_autoconf = argv[1]; + str_dir_config = argv[2]; + + /* Find a buffer size. */ + if (stat(str_file_autoconf, &stat_buf) != 0) + ERROR_EXIT(str_file_autoconf); + buffer_size = 2 * stat_buf.st_size + 4096; + + /* Allocate buffers. */ + if ( (line = malloc(buffer_size)) == NULL + || (old_line = malloc(buffer_size)) == NULL + || (list_target = malloc(buffer_size)) == NULL ) + ERROR_EXIT(str_file_autoconf); + + /* Open autoconfig file. */ + if ((fp_config = fopen(str_file_autoconf, "r")) == NULL) + ERROR_EXIT(str_file_autoconf); + + /* Make output directory if needed. */ + if (stat(str_dir_config, &stat_buf) != 0) + { + if (mkdir(str_dir_config, 0755) != 0) + ERROR_EXIT(str_dir_config); + } + + /* Change to output directory. */ + if (chdir(str_dir_config) != 0) + ERROR_EXIT(str_dir_config); + + /* Put initial separator into target list. */ + ptarget = list_target; + *ptarget++ = '\n'; + + /* Read config lines. */ + while (fgets(line, buffer_size, fp_config)) + { + const char * str_config; + int is_same; + int itarget; + + if (line[0] != '#') + continue; + if ((str_config = strstr(line, "CONFIG_")) == NULL) + continue; + + /* Make the output file name. */ + str_config += sizeof("CONFIG_") - 1; + for (itarget = 0; !isspace(str_config[itarget]); itarget++) + { + int c = (unsigned char) str_config[itarget]; + if (isupper(c)) c = tolower(c); + if (c == '_') c = '/'; + ptarget[itarget] = c; + } + ptarget[itarget++] = '.'; + ptarget[itarget++] = 'h'; + ptarget[itarget++] = '\0'; + + /* Check for existing file. */ + is_same = 0; + if ((fp_target = fopen(ptarget, "r")) != NULL) + { + fgets(old_line, buffer_size, fp_target); + if (fclose(fp_target) != 0) + ERROR_EXIT(ptarget); + if (!strcmp(line, old_line)) + is_same = 1; + } + + if (!is_same) + { + /* Auto-create directories. */ + int islash; + for (islash = 0; islash < itarget; islash++) + { + if (ptarget[islash] == '/') + { + ptarget[islash] = '\0'; + if (stat(ptarget, &stat_buf) != 0 + && mkdir(ptarget, 0755) != 0) + ERROR_EXIT( ptarget ); + ptarget[islash] = '/'; + } + } + + /* Write the file. */ + if ((fp_target = fopen(ptarget, "w" )) == NULL) + ERROR_EXIT(ptarget); + fputs(line, fp_target); + if (ferror(fp_target) || fclose(fp_target) != 0) + ERROR_EXIT(ptarget); + } + + /* Update target list */ + ptarget += itarget; + *(ptarget-1) = '\n'; + } + + /* + * Close autoconfig file. + * Terminate the target list. + */ + if (fclose(fp_config) != 0) + ERROR_EXIT(str_file_autoconf); + *ptarget = '\0'; + + /* + * Fix up existing files which have no new value. + * This is Case 4 and Case 5. + * + * I re-read the tree and filter it against list_target. + * This is crude. But it avoids data copies. Also, list_target + * is compact and contiguous, so it easily fits into cache. + * + * Notice that list_target contains strings separated by \n, + * with a \n before the first string and after the last. + * fgets gives the incoming names a terminating \n. + * So by having an initial \n, strstr will find exact matches. + */ + + fp_find = popen("find * -type f -name \"*.h\" -print", "r"); + if (fp_find == 0) + ERROR_EXIT( "find" ); + + line[0] = '\n'; + while (fgets(line+1, buffer_size, fp_find)) + { + if (strstr(list_target, line) == NULL) + { + /* + * This is an old file with no CONFIG_* flag in autoconf.h. + */ + + /* First strip the \n. */ + line[strlen(line)-1] = '\0'; + + /* Grab size. */ + if (stat(line+1, &stat_buf) != 0) + ERROR_EXIT(line); + + /* If file is not empty, make it empty and give it a fresh date. */ + if (stat_buf.st_size != 0) + { + if ((fp_target = fopen(line+1, "w")) == NULL) + ERROR_EXIT(line); + if (fclose(fp_target) != 0) + ERROR_EXIT(line); + } + } + } + + if (pclose(fp_find) != 0) + ERROR_EXIT("find"); + + return 0; +} diff --git a/trunk/scripts/export_report.pl b/trunk/scripts/export_report.pl deleted file mode 100644 index 9ed00d9bb0a7..000000000000 --- a/trunk/scripts/export_report.pl +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/perl -w -# -# (C) Copyright IBM Corporation 2006. -# Released under GPL v2. -# Author : Ram Pai (linuxram@us.ibm.com) -# -# Usage: export_report.pl -k Module.symvers [-o report_file ] -f *.mod.c -# - -use Getopt::Std; -use strict; - -sub numerically { - my $no1 = (split /\s+/, $a)[1]; - my $no2 = (split /\s+/, $b)[1]; - return $no1 <=> $no2; -} - -sub alphabetically { - my ($module1, $value1) = @{$a}; - my ($module2, $value2) = @{$b}; - return $value1 <=> $value2 || $module2 cmp $module1; -} - -sub print_depends_on { - my ($href) = @_; - print "\n"; - while (my ($mod, $list) = each %$href) { - print "\t$mod:\n"; - foreach my $sym (sort numerically @{$list}) { - my ($symbol, $no) = split /\s+/, $sym; - printf("\t\t%-25s\t%-25d\n", $symbol, $no); - } - print "\n"; - } - print "\n"; - print "~"x80 , "\n"; -} - -sub usage { - print "Usage: @_ -h -k Module.symvers [ -o outputfile ] \n", - "\t-f: treat all the non-option argument as .mod.c files. ", - "Recommend using this as the last option\n", - "\t-h: print detailed help\n", - "\t-k: the path to Module.symvers file. By default uses ", - "the file from the current directory\n", - "\t-o outputfile: output the report to outputfile\n"; - exit 0; -} - -sub collectcfiles { - my @file = `cat .tmp_versions/*.mod | grep '.*\.ko\$'`; - @file = grep {s/\.ko/.mod.c/} @file; - chomp @file; - return @file; -} - -my (%SYMBOL, %MODULE, %opt, @allcfiles); - -if (not getopts('hk:o:f',\%opt) or defined $opt{'h'}) { - usage($0); -} - -if (defined $opt{'f'}) { - @allcfiles = @ARGV; -} else { - @allcfiles = collectcfiles(); -} - -if (not defined $opt{'k'}) { - $opt{'k'} = "Module.symvers"; -} - -unless (open(MODULE_SYMVERS, $opt{'k'})) { - die "Sorry, cannot open $opt{'k'}: $!\n"; -} - -if (defined $opt{'o'}) { - unless (open(OUTPUT_HANDLE, ">$opt{'o'}")) { - die "Sorry, cannot open $opt{'o'} $!\n"; - } - select OUTPUT_HANDLE; -} -# -# collect all the symbols and their attributes from the -# Module.symvers file -# -while ( ) { - chomp; - my (undef, $symbol, $module, $gpl) = split; - $SYMBOL { $symbol } = [ $module , "0" , $symbol, $gpl]; -} -close(MODULE_SYMVERS); - -# -# collect the usage count of each symbol. -# -foreach my $thismod (@allcfiles) { - unless (open(MODULE_MODULE, $thismod)) { - print "Sorry, cannot open $thismod: $!\n"; - next; - } - my $state=0; - while ( ) { - chomp; - if ($state eq 0) { - $state = 1 if ($_ =~ /static const struct modversion_info/); - next; - } - if ($state eq 1) { - $state = 2 if ($_ =~ /__attribute__\(\(section\("__versions"\)\)\)/); - next; - } - if ($state eq 2) { - if ( $_ !~ /0x[0-9a-f]{7,8},/ ) { - next; - } - my $sym = (split /([,"])/,)[4]; - my ($module, $value, $symbol, $gpl) = @{$SYMBOL{$sym}}; - $SYMBOL{ $sym } = [ $module, $value+1, $symbol, $gpl]; - push(@{$MODULE{$thismod}} , $sym); - } - } - if ($state ne 2) { - print "WARNING:$thismod is not built with CONFIG_MODVERSION enabled\n"; - } - close(MODULE_MODULE); -} - -print "\tThis file reports the exported symbols usage patterns by in-tree\n", - "\t\t\t\tmodules\n"; -printf("%s\n\n\n","x"x80); -printf("\t\t\t\tINDEX\n\n\n"); -printf("SECTION 1: Usage counts of all exported symbols\n"); -printf("SECTION 2: List of modules and the exported symbols they use\n"); -printf("%s\n\n\n","x"x80); -printf("SECTION 1:\tThe exported symbols and their usage count\n\n"); -printf("%-25s\t%-25s\t%-5s\t%-25s\n", "Symbol", "Module", "Usage count", - "export type"); - -# -# print the list of unused exported symbols -# -foreach my $list (sort alphabetically values(%SYMBOL)) { - my ($module, $value, $symbol, $gpl) = @{$list}; - printf("%-25s\t%-25s\t%-10s\t", $symbol, $module, $value); - if (defined $gpl) { - printf("%-25s\n",$gpl); - } else { - printf("\n"); - } -} -printf("%s\n\n\n","x"x80); - -printf("SECTION 2:\n\tThis section reports export-symbol-usage of in-kernel -modules. Each module lists the modules, and the symbols from that module that -it uses. Each listed symbol reports the number of modules using it\n"); - -print "~"x80 , "\n"; -while (my ($thismod, $list) = each %MODULE) { - my %depends; - $thismod =~ s/\.mod\.c/.ko/; - print "\t\t\t$thismod\n"; - foreach my $symbol (@{$list}) { - my ($module, $value, undef, $gpl) = @{$SYMBOL{$symbol}}; - push (@{$depends{"$module"}}, "$symbol $value"); - } - print_depends_on(\%depends); -} diff --git a/trunk/scripts/genksyms/genksyms.c b/trunk/scripts/genksyms/genksyms.c index b0381823e404..5b0344e20d61 100644 --- a/trunk/scripts/genksyms/genksyms.c +++ b/trunk/scripts/genksyms/genksyms.c @@ -42,7 +42,7 @@ static FILE *debugfile; int cur_line = 1; char *cur_filename; -static int flag_debug, flag_dump_defs, flag_dump_types, flag_warnings; +static int flag_debug, flag_dump_defs, flag_warnings; static const char *arch = ""; static const char *mod_prefix = ""; @@ -50,7 +50,6 @@ static int errors; static int nsyms; static struct symbol *expansion_trail; -static struct symbol *visited_symbols; static const char *const symbol_type_name[] = { "normal", "typedef", "enum", "struct", "union" @@ -177,7 +176,6 @@ struct symbol *add_symbol(const char *name, enum symbol_type type, sym->type = type; sym->defn = defn; sym->expansion_trail = NULL; - sym->visited = NULL; sym->is_extern = is_extern; sym->hash_next = symtab[h]; @@ -238,11 +236,26 @@ static int equal_list(struct string_list *a, struct string_list *b) static void print_node(FILE * f, struct string_list *list) { - if (list->tag != SYM_NORMAL) { - putc(symbol_type_name[list->tag][0], f); + switch (list->tag) { + case SYM_STRUCT: + putc('s', f); + goto printit; + case SYM_UNION: + putc('u', f); + goto printit; + case SYM_ENUM: + putc('e', f); + goto printit; + case SYM_TYPEDEF: + putc('t', f); + goto printit; + + printit: putc('#', f); + case SYM_NORMAL: + fputs(list->string, f); + break; } - fputs(list->string, f); } static void print_list(FILE * f, struct string_list *list) @@ -274,9 +287,9 @@ static void print_list(FILE * f, struct string_list *list) } } -static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) +static unsigned long expand_and_crc_list(struct string_list *list, + unsigned long crc) { - struct string_list *list = sym->defn; struct string_list **e, **b; struct string_list *tmp, **tmp2; int elem = 1; @@ -319,7 +332,7 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) } else { subsym->expansion_trail = expansion_trail; expansion_trail = subsym; - crc = expand_and_crc_sym(subsym, crc); + crc = expand_and_crc_list(subsym->defn, crc); } break; @@ -369,22 +382,12 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc) } else { subsym->expansion_trail = expansion_trail; expansion_trail = subsym; - crc = expand_and_crc_sym(subsym, crc); + crc = expand_and_crc_list(subsym->defn, crc); } break; } } - { - static struct symbol **end = &visited_symbols; - - if (!sym->visited) { - *end = sym; - end = &sym->visited; - sym->visited = (struct symbol *)-1L; - } - } - return crc; } @@ -403,7 +406,7 @@ void export_symbol(const char *name) expansion_trail = (struct symbol *)-1L; - crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff; + crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff; sym = expansion_trail; while (sym != (struct symbol *)-1L) { @@ -461,7 +464,6 @@ static void genksyms_usage(void) int main(int argc, char **argv) { - FILE *dumpfile = NULL; int o; #ifdef __GNU_LIBRARY__ @@ -471,16 +473,15 @@ int main(int argc, char **argv) {"warnings", 0, 0, 'w'}, {"quiet", 0, 0, 'q'}, {"dump", 0, 0, 'D'}, - {"dump-types", 1, 0, 'T'}, {"version", 0, 0, 'V'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; - while ((o = getopt_long(argc, argv, "a:dwqVDT:k:p:", + while ((o = getopt_long(argc, argv, "a:dwqVDk:p:", &long_opts[0], NULL)) != EOF) #else /* __GNU_LIBRARY__ */ - while ((o = getopt(argc, argv, "a:dwqVDT:k:p:")) != EOF) + while ((o = getopt(argc, argv, "a:dwqVDk:p:")) != EOF) #endif /* __GNU_LIBRARY__ */ switch (o) { case 'a': @@ -501,14 +502,6 @@ int main(int argc, char **argv) case 'D': flag_dump_defs = 1; break; - case 'T': - flag_dump_types = 1; - dumpfile = fopen(optarg, "w"); - if (!dumpfile) { - perror(optarg); - return 1; - } - break; case 'h': genksyms_usage(); return 0; @@ -531,24 +524,6 @@ int main(int argc, char **argv) yyparse(); - if (flag_dump_types && visited_symbols) { - while (visited_symbols != (struct symbol *)-1L) { - struct symbol *sym = visited_symbols; - - if (sym->type != SYM_NORMAL) { - putc(symbol_type_name[sym->type][0], dumpfile); - putc('#', dumpfile); - } - fputs(sym->name, dumpfile); - putc(' ', dumpfile); - print_list(dumpfile, sym->defn); - putc('\n', dumpfile); - - visited_symbols = sym->visited; - sym->visited = NULL; - } - } - if (flag_debug) { fprintf(debugfile, "Hash table occupancy %d/%d = %g\n", nsyms, HASH_BUCKETS, diff --git a/trunk/scripts/genksyms/genksyms.h b/trunk/scripts/genksyms/genksyms.h index 2668287aa498..ab6f34f38735 100644 --- a/trunk/scripts/genksyms/genksyms.h +++ b/trunk/scripts/genksyms/genksyms.h @@ -41,7 +41,6 @@ struct symbol { enum symbol_type type; struct string_list *defn; struct symbol *expansion_trail; - struct symbol *visited; int is_extern; }; diff --git a/trunk/scripts/genksyms/lex.c_shipped b/trunk/scripts/genksyms/lex.c_shipped index 37ba98241b96..1218053ee960 100644 --- a/trunk/scripts/genksyms/lex.c_shipped +++ b/trunk/scripts/genksyms/lex.c_shipped @@ -2023,7 +2023,7 @@ repeat: break; default: - exit(1); + abort(); } fini: diff --git a/trunk/scripts/genksyms/lex.l b/trunk/scripts/genksyms/lex.l index 5e544a06678b..fe0dfeedf0ff 100644 --- a/trunk/scripts/genksyms/lex.l +++ b/trunk/scripts/genksyms/lex.l @@ -392,7 +392,7 @@ repeat: break; default: - exit(1); + abort(); } fini: diff --git a/trunk/scripts/kconfig/conf.c b/trunk/scripts/kconfig/conf.c index 4dcb8867b5f4..8012d1076876 100644 --- a/trunk/scripts/kconfig/conf.c +++ b/trunk/scripts/kconfig/conf.c @@ -539,7 +539,6 @@ int main(int ac, char **av) name = av[i]; if (!name) { printf(_("%s: Kconfig file missing\n"), av[0]); - exit(1); } conf_parse(name); //zconfdump(stdout); @@ -574,7 +573,7 @@ int main(int ac, char **av) case set_random: name = getenv("KCONFIG_ALLCONFIG"); if (name && !stat(name, &tmpstat)) { - conf_read_simple(name, S_DEF_USER); + conf_read_simple(name); break; } switch (input_mode) { @@ -585,9 +584,9 @@ int main(int ac, char **av) default: break; } if (!stat(name, &tmpstat)) - conf_read_simple(name, S_DEF_USER); + conf_read_simple(name); else if (!stat("all.config", &tmpstat)) - conf_read_simple("all.config", S_DEF_USER); + conf_read_simple("all.config"); break; default: break; @@ -600,15 +599,7 @@ int main(int ac, char **av) input_mode = ask_silent; valid_stdin = 1; } - } else if (sym_change_count) { - name = getenv("KCONFIG_NOSILENTUPDATE"); - if (name && *name) { - fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n")); - return 1; - } - } else - goto skip_check; - + } do { conf_cnt = 0; check_conf(&rootmenu); @@ -617,11 +608,5 @@ int main(int ac, char **av) fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); return 1; } -skip_check: - if (input_mode == ask_silent && conf_write_autoconf()) { - fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n")); - return 1; - } - return 0; } diff --git a/trunk/scripts/kconfig/confdata.c b/trunk/scripts/kconfig/confdata.c index 2ee48c377b66..1b5df589f3ae 100644 --- a/trunk/scripts/kconfig/confdata.c +++ b/trunk/scripts/kconfig/confdata.c @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -21,8 +20,19 @@ static void conf_warning(const char *fmt, ...) static const char *conf_filename; static int conf_lineno, conf_warnings, conf_unsaved; +const char conf_def_filename[] = ".config"; + const char conf_defname[] = "arch/$ARCH/defconfig"; +const char *conf_confnames[] = { + ".config", + "/lib/modules/$UNAME_RELEASE/.config", + "/etc/kernel-config", + "/boot/config-$UNAME_RELEASE", + conf_defname, + NULL, +}; + static void conf_warning(const char *fmt, ...) { va_list ap; @@ -34,13 +44,6 @@ static void conf_warning(const char *fmt, ...) conf_warnings++; } -const char *conf_get_configname(void) -{ - char *name = getenv("KCONFIG_CONFIG"); - - return name ? name : ".config"; -} - static char *conf_expand_value(const char *in) { struct symbol *sym; @@ -83,65 +86,51 @@ char *conf_get_default_confname(void) return name; } -int conf_read_simple(const char *name, int def) +int conf_read_simple(const char *name) { FILE *in = NULL; char line[1024]; char *p, *p2; struct symbol *sym; - int i, def_flags; + int i; if (name) { in = zconf_fopen(name); } else { - struct property *prop; - - name = conf_get_configname(); - in = zconf_fopen(name); - if (in) - goto load; - sym_change_count++; - if (!sym_defconfig_list) - return 1; - - for_all_defaults(sym_defconfig_list, prop) { - if (expr_calc_value(prop->visible.expr) == no || - prop->expr->type != E_SYMBOL) - continue; - name = conf_expand_value(prop->expr->left.sym->name); + const char **names = conf_confnames; + while ((name = *names++)) { + name = conf_expand_value(name); in = zconf_fopen(name); if (in) { printf(_("#\n" - "# using defaults found in %s\n" - "#\n"), name); - goto load; + "# using defaults found in %s\n" + "#\n"), name); + break; } } } if (!in) return 1; -load: conf_filename = name; conf_lineno = 0; conf_warnings = 0; conf_unsaved = 0; - def_flags = SYMBOL_DEF << def; for_all_symbols(i, sym) { - sym->flags |= SYMBOL_CHANGED; - sym->flags &= ~(def_flags|SYMBOL_VALID); + sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED; if (sym_is_choice(sym)) - sym->flags |= def_flags; + sym->flags &= ~SYMBOL_NEW; + sym->flags &= ~SYMBOL_VALID; switch (sym->type) { case S_INT: case S_HEX: case S_STRING: - if (sym->def[def].val) - free(sym->def[def].val); + if (sym->user.val) + free(sym->user.val); default: - sym->def[def].val = NULL; - sym->def[def].tri = no; + sym->user.val = NULL; + sym->user.tri = no; } } @@ -158,26 +147,19 @@ int conf_read_simple(const char *name, int def) *p++ = 0; if (strncmp(p, "is not set", 10)) continue; - if (def == S_DEF_USER) { - sym = sym_find(line + 9); - if (!sym) { - conf_warning("trying to assign nonexistent symbol %s", line + 9); - break; - } - } else { - sym = sym_lookup(line + 9, 0); - if (sym->type == S_UNKNOWN) - sym->type = S_BOOLEAN; - } - if (sym->flags & def_flags) { + sym = sym_find(line + 9); + if (!sym) { + conf_warning("trying to assign nonexistent symbol %s", line + 9); + break; + } else if (!(sym->flags & SYMBOL_NEW)) { conf_warning("trying to reassign symbol %s", sym->name); break; } switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: - sym->def[def].tri = no; - sym->flags |= def_flags; + sym->user.tri = no; + sym->flags &= ~SYMBOL_NEW; break; default: ; @@ -195,48 +177,34 @@ int conf_read_simple(const char *name, int def) p2 = strchr(p, '\n'); if (p2) *p2 = 0; - if (def == S_DEF_USER) { - sym = sym_find(line + 7); - if (!sym) { - conf_warning("trying to assign nonexistent symbol %s", line + 7); - break; - } - } else { - sym = sym_lookup(line + 7, 0); - if (sym->type == S_UNKNOWN) - sym->type = S_OTHER; - } - if (sym->flags & def_flags) { + sym = sym_find(line + 7); + if (!sym) { + conf_warning("trying to assign nonexistent symbol %s", line + 7); + break; + } else if (!(sym->flags & SYMBOL_NEW)) { conf_warning("trying to reassign symbol %s", sym->name); break; } switch (sym->type) { case S_TRISTATE: if (p[0] == 'm') { - sym->def[def].tri = mod; - sym->flags |= def_flags; + sym->user.tri = mod; + sym->flags &= ~SYMBOL_NEW; break; } case S_BOOLEAN: if (p[0] == 'y') { - sym->def[def].tri = yes; - sym->flags |= def_flags; + sym->user.tri = yes; + sym->flags &= ~SYMBOL_NEW; break; } if (p[0] == 'n') { - sym->def[def].tri = no; - sym->flags |= def_flags; + sym->user.tri = no; + sym->flags &= ~SYMBOL_NEW; break; } conf_warning("symbol value '%s' invalid for %s", p, sym->name); break; - case S_OTHER: - if (*p != '"') { - for (p2 = p; *p2 && !isspace(*p2); p2++) - ; - sym->type = S_STRING; - goto done; - } case S_STRING: if (*p++ != '"') break; @@ -253,10 +221,9 @@ int conf_read_simple(const char *name, int def) } case S_INT: case S_HEX: - done: if (sym_string_valid(sym, p)) { - sym->def[def].val = strdup(p); - sym->flags |= def_flags; + sym->user.val = strdup(p); + sym->flags &= ~SYMBOL_NEW; } else { conf_warning("symbol value '%s' invalid for %s", p, sym->name); continue; @@ -274,24 +241,24 @@ int conf_read_simple(const char *name, int def) } if (sym && sym_is_choice_value(sym)) { struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); - switch (sym->def[def].tri) { + switch (sym->user.tri) { case no: break; case mod: - if (cs->def[def].tri == yes) { + if (cs->user.tri == yes) { conf_warning("%s creates inconsistent choice state", sym->name); - cs->flags &= ~def_flags; + cs->flags |= SYMBOL_NEW; } break; case yes: - if (cs->def[def].tri != no) { + if (cs->user.tri != no) { conf_warning("%s creates inconsistent choice state", sym->name); - cs->flags &= ~def_flags; + cs->flags |= SYMBOL_NEW; } else - cs->def[def].val = sym; + cs->user.val = sym; break; } - cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri); + cs->user.tri = E_OR(cs->user.tri, sym->user.tri); } } fclose(in); @@ -306,11 +273,9 @@ int conf_read(const char *name) struct symbol *sym; struct property *prop; struct expr *e; - int i, flags; - - sym_change_count = 0; + int i; - if (conf_read_simple(name, S_DEF_USER)) + if (conf_read_simple(name)) return 1; for_all_symbols(i, sym) { @@ -322,12 +287,12 @@ int conf_read(const char *name) switch (sym->type) { case S_BOOLEAN: case S_TRISTATE: - if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) + if (sym->user.tri != sym_get_tristate_value(sym)) break; if (!sym_is_choice(sym)) goto sym_ok; default: - if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) + if (!strcmp(sym->curr.val, sym->user.val)) goto sym_ok; break; } @@ -339,13 +304,15 @@ int conf_read(const char *name) sym_ok: if (sym_has_value(sym) && !sym_is_choice_value(sym)) { if (sym->visible == no) - sym->flags &= ~SYMBOL_DEF_USER; + sym->flags |= SYMBOL_NEW; switch (sym->type) { case S_STRING: case S_INT: case S_HEX: - if (!sym_string_within_range(sym, sym->def[S_DEF_USER].val)) - sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); + if (!sym_string_within_range(sym, sym->user.val)) { + sym->flags |= SYMBOL_NEW; + sym->flags &= ~SYMBOL_VALID; + } default: break; } @@ -353,21 +320,19 @@ int conf_read(const char *name) if (!sym_is_choice(sym)) continue; prop = sym_get_choice_prop(sym); - flags = sym->flags; for (e = prop->expr; e; e = e->left.expr) if (e->right.sym->visible != no) - flags &= e->right.sym->flags; - sym->flags |= flags & SYMBOL_DEF_USER; + sym->flags |= e->right.sym->flags & SYMBOL_NEW; } - sym_change_count += conf_warnings || conf_unsaved; + sym_change_count = conf_warnings || conf_unsaved; return 0; } int conf_write(const char *name) { - FILE *out; + FILE *out, *out_h; struct symbol *sym; struct menu *menu; const char *basename; @@ -386,7 +351,7 @@ int conf_write(const char *name) if (!stat(name, &st) && S_ISDIR(st.st_mode)) { strcpy(dirname, name); strcat(dirname, "/"); - basename = conf_get_configname(); + basename = conf_def_filename; } else if ((slash = strrchr(name, '/'))) { int size = slash - name + 1; memcpy(dirname, name, size); @@ -394,24 +359,23 @@ int conf_write(const char *name) if (slash[1]) basename = slash + 1; else - basename = conf_get_configname(); + basename = conf_def_filename; } else basename = name; } else - basename = conf_get_configname(); + basename = conf_def_filename; - sprintf(newname, "%s%s", dirname, basename); - env = getenv("KCONFIG_OVERWRITECONFIG"); - if (!env || !*env) { - sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); - out = fopen(tmpname, "w"); - } else { - *tmpname = 0; - out = fopen(newname, "w"); - } + sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid()); + out = fopen(newname, "w"); if (!out) return 1; - + out_h = NULL; + if (!name) { + out_h = fopen(".tmpconfig.h", "w"); + if (!out_h) + return 1; + file_write_dep(NULL); + } sym = sym_lookup("KERNELVERSION", 0); sym_calc_value(sym); time(&now); @@ -427,6 +391,16 @@ int conf_write(const char *name) sym_get_string_value(sym), use_timestamp ? "# " : "", use_timestamp ? ctime(&now) : ""); + if (out_h) + fprintf(out_h, "/*\n" + " * Automatically generated C config: don't edit\n" + " * Linux kernel version: %s\n" + "%s%s" + " */\n" + "#define AUTOCONF_INCLUDED\n", + sym_get_string_value(sym), + use_timestamp ? " * " : "", + use_timestamp ? ctime(&now) : ""); if (!sym_change_count) sym_clear_all_valid(); @@ -442,6 +416,11 @@ int conf_write(const char *name) "#\n" "# %s\n" "#\n", str); + if (out_h) + fprintf(out_h, "\n" + "/*\n" + " * %s\n" + " */\n", str); } else if (!(sym->flags & SYMBOL_CHOICE)) { sym_calc_value(sym); if (!(sym->flags & SYMBOL_WRITE)) @@ -459,39 +438,59 @@ int conf_write(const char *name) switch (sym_get_tristate_value(sym)) { case no: fprintf(out, "# CONFIG_%s is not set\n", sym->name); + if (out_h) + fprintf(out_h, "#undef CONFIG_%s\n", sym->name); break; case mod: fprintf(out, "CONFIG_%s=m\n", sym->name); + if (out_h) + fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); break; case yes: fprintf(out, "CONFIG_%s=y\n", sym->name); + if (out_h) + fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); break; } break; case S_STRING: + // fix me str = sym_get_string_value(sym); fprintf(out, "CONFIG_%s=\"", sym->name); - while (1) { + if (out_h) + fprintf(out_h, "#define CONFIG_%s \"", sym->name); + do { l = strcspn(str, "\"\\"); if (l) { fwrite(str, l, 1, out); - str += l; + if (out_h) + fwrite(str, l, 1, out_h); } - if (!*str) - break; - fprintf(out, "\\%c", *str++); - } + str += l; + while (*str == '\\' || *str == '"') { + fprintf(out, "\\%c", *str); + if (out_h) + fprintf(out_h, "\\%c", *str); + str++; + } + } while (*str); fputs("\"\n", out); + if (out_h) + fputs("\"\n", out_h); break; case S_HEX: str = sym_get_string_value(sym); if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { fprintf(out, "CONFIG_%s=%s\n", sym->name, str); + if (out_h) + fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); break; } case S_INT: str = sym_get_string_value(sym); fprintf(out, "CONFIG_%s=%s\n", sym->name, str); + if (out_h) + fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); break; } } @@ -511,253 +510,21 @@ int conf_write(const char *name) } } fclose(out); - - if (*tmpname) { - strcat(dirname, name ? name : conf_get_configname()); - strcat(dirname, ".old"); - rename(newname, dirname); - if (rename(tmpname, newname)) - return 1; + if (out_h) { + fclose(out_h); + rename(".tmpconfig.h", "include/linux/autoconf.h"); } - - printf(_("#\n" - "# configuration written to %s\n" - "#\n"), newname); - - sym_change_count = 0; - - return 0; -} - -int conf_split_config(void) -{ - char *name, path[128]; - char *s, *d, c; - struct symbol *sym; - struct stat sb; - int res, i, fd; - - name = getenv("KCONFIG_AUTOCONFIG"); - if (!name) - name = "include/config/auto.conf"; - conf_read_simple(name, S_DEF_AUTO); - - if (chdir("include/config")) - return 1; - - res = 0; - for_all_symbols(i, sym) { - sym_calc_value(sym); - if ((sym->flags & SYMBOL_AUTO) || !sym->name) - continue; - if (sym->flags & SYMBOL_WRITE) { - if (sym->flags & SYMBOL_DEF_AUTO) { - /* - * symbol has old and new value, - * so compare them... - */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - if (sym_get_tristate_value(sym) == - sym->def[S_DEF_AUTO].tri) - continue; - break; - case S_STRING: - case S_HEX: - case S_INT: - if (!strcmp(sym_get_string_value(sym), - sym->def[S_DEF_AUTO].val)) - continue; - break; - default: - break; - } - } else { - /* - * If there is no old value, only 'no' (unset) - * is allowed as new value. - */ - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - if (sym_get_tristate_value(sym) == no) - continue; - break; - default: - break; - } - } - } else if (!(sym->flags & SYMBOL_DEF_AUTO)) - /* There is neither an old nor a new value. */ - continue; - /* else - * There is an old value, but no new value ('no' (unset) - * isn't saved in auto.conf, so the old value is always - * different from 'no'). - */ - - /* Replace all '_' and append ".h" */ - s = sym->name; - d = path; - while ((c = *s++)) { - c = tolower(c); - *d++ = (c == '_') ? '/' : c; - } - strcpy(d, ".h"); - - /* Assume directory path already exists. */ - fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - if (errno != ENOENT) { - res = 1; - break; - } - /* - * Create directory components, - * unless they exist already. - */ - d = path; - while ((d = strchr(d, '/'))) { - *d = 0; - if (stat(path, &sb) && mkdir(path, 0755)) { - res = 1; - goto out; - } - *d++ = '/'; - } - /* Try it again. */ - fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - res = 1; - break; - } - } - close(fd); + if (!name || basename != conf_def_filename) { + if (!name) + name = conf_def_filename; + sprintf(tmpname, "%s.old", name); + rename(name, tmpname); } -out: - if (chdir("../..")) + sprintf(tmpname, "%s%s", dirname, basename); + if (rename(newname, tmpname)) return 1; - return res; -} - -int conf_write_autoconf(void) -{ - struct symbol *sym; - const char *str; - char *name; - FILE *out, *out_h; - time_t now; - int i, l; - - sym_clear_all_valid(); - - file_write_dep("include/config/auto.conf.cmd"); - - if (conf_split_config()) - return 1; - - out = fopen(".tmpconfig", "w"); - if (!out) - return 1; - - out_h = fopen(".tmpconfig.h", "w"); - if (!out_h) { - fclose(out); - return 1; - } - - sym = sym_lookup("KERNELVERSION", 0); - sym_calc_value(sym); - time(&now); - fprintf(out, "#\n" - "# Automatically generated make config: don't edit\n" - "# Linux kernel version: %s\n" - "# %s" - "#\n", - sym_get_string_value(sym), ctime(&now)); - fprintf(out_h, "/*\n" - " * Automatically generated C config: don't edit\n" - " * Linux kernel version: %s\n" - " * %s" - " */\n" - "#define AUTOCONF_INCLUDED\n", - sym_get_string_value(sym), ctime(&now)); - - for_all_symbols(i, sym) { - sym_calc_value(sym); - if (!(sym->flags & SYMBOL_WRITE) || !sym->name) - continue; - switch (sym->type) { - case S_BOOLEAN: - case S_TRISTATE: - switch (sym_get_tristate_value(sym)) { - case no: - break; - case mod: - fprintf(out, "CONFIG_%s=m\n", sym->name); - fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); - break; - case yes: - fprintf(out, "CONFIG_%s=y\n", sym->name); - fprintf(out_h, "#define CONFIG_%s 1\n", sym->name); - break; - } - break; - case S_STRING: - str = sym_get_string_value(sym); - fprintf(out, "CONFIG_%s=\"", sym->name); - fprintf(out_h, "#define CONFIG_%s \"", sym->name); - while (1) { - l = strcspn(str, "\"\\"); - if (l) { - fwrite(str, l, 1, out); - fwrite(str, l, 1, out_h); - str += l; - } - if (!*str) - break; - fprintf(out, "\\%c", *str); - fprintf(out_h, "\\%c", *str); - str++; - } - fputs("\"\n", out); - fputs("\"\n", out_h); - break; - case S_HEX: - str = sym_get_string_value(sym); - if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { - fprintf(out, "CONFIG_%s=%s\n", sym->name, str); - fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str); - break; - } - case S_INT: - str = sym_get_string_value(sym); - fprintf(out, "CONFIG_%s=%s\n", sym->name, str); - fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str); - break; - default: - break; - } - } - fclose(out); - fclose(out_h); - - name = getenv("KCONFIG_AUTOHEADER"); - if (!name) - name = "include/linux/autoconf.h"; - if (rename(".tmpconfig.h", name)) - return 1; - name = getenv("KCONFIG_AUTOCONFIG"); - if (!name) - name = "include/config/auto.conf"; - /* - * This must be the last step, kbuild has a dependency on auto.conf - * and this marks the successful completion of the previous steps. - */ - if (rename(".tmpconfig", name)) - return 1; + sym_change_count = 0; return 0; } diff --git a/trunk/scripts/kconfig/expr.c b/trunk/scripts/kconfig/expr.c index 6f98dbfe70cf..30e4f9d69c2f 100644 --- a/trunk/scripts/kconfig/expr.c +++ b/trunk/scripts/kconfig/expr.c @@ -145,8 +145,7 @@ static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct e return; } if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && - e1->left.sym == e2->left.sym && - (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) + e1->left.sym == e2->left.sym && (e1->left.sym->flags & (SYMBOL_YES|SYMBOL_NO))) return; if (!expr_eq(e1, e2)) return; @@ -1013,73 +1012,73 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2) #endif } -void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) +void expr_print(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken) { if (!e) { - fn(data, NULL, "y"); + fn(data, "y"); return; } if (expr_compare_type(prevtoken, e->type) > 0) - fn(data, NULL, "("); + fn(data, "("); switch (e->type) { case E_SYMBOL: if (e->left.sym->name) - fn(data, e->left.sym, e->left.sym->name); + fn(data, e->left.sym->name); else - fn(data, NULL, ""); + fn(data, ""); break; case E_NOT: - fn(data, NULL, "!"); + fn(data, "!"); expr_print(e->left.expr, fn, data, E_NOT); break; case E_EQUAL: - fn(data, e->left.sym, e->left.sym->name); - fn(data, NULL, "="); - fn(data, e->right.sym, e->right.sym->name); + fn(data, e->left.sym->name); + fn(data, "="); + fn(data, e->right.sym->name); break; case E_UNEQUAL: - fn(data, e->left.sym, e->left.sym->name); - fn(data, NULL, "!="); - fn(data, e->right.sym, e->right.sym->name); + fn(data, e->left.sym->name); + fn(data, "!="); + fn(data, e->right.sym->name); break; case E_OR: expr_print(e->left.expr, fn, data, E_OR); - fn(data, NULL, " || "); + fn(data, " || "); expr_print(e->right.expr, fn, data, E_OR); break; case E_AND: expr_print(e->left.expr, fn, data, E_AND); - fn(data, NULL, " && "); + fn(data, " && "); expr_print(e->right.expr, fn, data, E_AND); break; case E_CHOICE: - fn(data, e->right.sym, e->right.sym->name); + fn(data, e->right.sym->name); if (e->left.expr) { - fn(data, NULL, " ^ "); + fn(data, " ^ "); expr_print(e->left.expr, fn, data, E_CHOICE); } break; case E_RANGE: - fn(data, NULL, "["); - fn(data, e->left.sym, e->left.sym->name); - fn(data, NULL, " "); - fn(data, e->right.sym, e->right.sym->name); - fn(data, NULL, "]"); + fn(data, "["); + fn(data, e->left.sym->name); + fn(data, " "); + fn(data, e->right.sym->name); + fn(data, "]"); break; default: { char buf[32]; sprintf(buf, "", e->type); - fn(data, NULL, buf); + fn(data, buf); break; } } if (expr_compare_type(prevtoken, e->type) > 0) - fn(data, NULL, ")"); + fn(data, ")"); } -static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) +static void expr_print_file_helper(void *data, const char *str) { fwrite(str, strlen(str), 1, data); } @@ -1089,7 +1088,7 @@ void expr_fprint(struct expr *e, FILE *out) expr_print(e, expr_print_file_helper, out, E_NONE); } -static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str) +static void expr_print_gstr_helper(void *data, const char *str) { str_append((struct gstr*)data, str); } diff --git a/trunk/scripts/kconfig/expr.h b/trunk/scripts/kconfig/expr.h index 6084525f604b..1b36ef18c48d 100644 --- a/trunk/scripts/kconfig/expr.h +++ b/trunk/scripts/kconfig/expr.h @@ -63,18 +63,12 @@ enum symbol_type { S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER }; -enum { - S_DEF_USER, /* main user value */ - S_DEF_AUTO, -}; - struct symbol { struct symbol *next; char *name; char *help; enum symbol_type type; - struct symbol_value curr; - struct symbol_value def[4]; + struct symbol_value curr, user; tristate visible; int flags; struct property *prop; @@ -84,7 +78,10 @@ struct symbol { #define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) -#define SYMBOL_CONST 0x0001 +#define SYMBOL_YES 0x0001 +#define SYMBOL_MOD 0x0002 +#define SYMBOL_NO 0x0004 +#define SYMBOL_CONST 0x0007 #define SYMBOL_CHECK 0x0008 #define SYMBOL_CHOICE 0x0010 #define SYMBOL_CHOICEVAL 0x0020 @@ -93,14 +90,10 @@ struct symbol { #define SYMBOL_OPTIONAL 0x0100 #define SYMBOL_WRITE 0x0200 #define SYMBOL_CHANGED 0x0400 +#define SYMBOL_NEW 0x0800 #define SYMBOL_AUTO 0x1000 #define SYMBOL_CHECKED 0x2000 #define SYMBOL_WARNED 0x8000 -#define SYMBOL_DEF 0x10000 -#define SYMBOL_DEF_USER 0x10000 -#define SYMBOL_DEF_AUTO 0x20000 -#define SYMBOL_DEF3 0x40000 -#define SYMBOL_DEF4 0x80000 #define SYMBOL_MAXLENGTH 256 #define SYMBOL_HASHSIZE 257 @@ -156,7 +149,6 @@ struct file *lookup_file(const char *name); extern struct symbol symbol_yes, symbol_no, symbol_mod; extern struct symbol *modules_sym; -extern struct symbol *sym_defconfig_list; extern int cdebug; struct expr *expr_alloc_symbol(struct symbol *sym); struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); diff --git a/trunk/scripts/kconfig/gconf.c b/trunk/scripts/kconfig/gconf.c index 7b0d3a93d5c0..665bd5300a19 100644 --- a/trunk/scripts/kconfig/gconf.c +++ b/trunk/scripts/kconfig/gconf.c @@ -114,6 +114,12 @@ const char *dbg_print_flags(int val) bzero(buf, 256); + if (val & SYMBOL_YES) + strcat(buf, "yes/"); + if (val & SYMBOL_MOD) + strcat(buf, "mod/"); + if (val & SYMBOL_NO) + strcat(buf, "no/"); if (val & SYMBOL_CONST) strcat(buf, "const/"); if (val & SYMBOL_CHECK) @@ -132,6 +138,8 @@ const char *dbg_print_flags(int val) strcat(buf, "write/"); if (val & SYMBOL_CHANGED) strcat(buf, "changed/"); + if (val & SYMBOL_NEW) + strcat(buf, "new/"); if (val & SYMBOL_AUTO) strcat(buf, "auto/"); @@ -1184,7 +1192,9 @@ static gchar **fill_row(struct menu *menu) row[COL_OPTION] = g_strdup_printf("%s %s", menu_get_prompt(menu), - sym && sym_has_value(sym) ? "(NEW)" : ""); + sym ? (sym-> + flags & SYMBOL_NEW ? "(NEW)" : "") : + ""); if (show_all && !menu_is_visible(menu)) row[COL_COLOR] = g_strdup("DarkGray"); diff --git a/trunk/scripts/kconfig/lex.zconf.c_shipped b/trunk/scripts/kconfig/lex.zconf.c_shipped index 800f8c71c407..24e3c8cbb7ac 100644 --- a/trunk/scripts/kconfig/lex.zconf.c_shipped +++ b/trunk/scripts/kconfig/lex.zconf.c_shipped @@ -8,7 +8,7 @@ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 33 +#define YY_FLEX_SUBMINOR_VERSION 31 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif @@ -30,15 +30,7 @@ /* C99 systems have . Non-C99 systems may or may not. */ -#if __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; @@ -142,10 +134,6 @@ typedef unsigned int flex_uint32_t; #define YY_BUF_SIZE 16384 #endif -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; @@ -279,7 +267,7 @@ int zconfleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; -static int yy_init = 0; /* whether we need to initialize */ +static int yy_init = 1; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow zconfwrap()'s to do buffer switches @@ -832,8 +820,6 @@ void alloc_string(const char *str, int size) #define YY_EXTRA_TYPE void * #endif -static int yy_init_globals (void ); - /* Macros after this point can all be overridden by user definitions in * section 1. */ @@ -956,9 +942,9 @@ YY_DECL int str = 0; int ts, i; - if ( !(yy_init) ) + if ( (yy_init) ) { - (yy_init) = 1; + (yy_init) = 0; #ifdef YY_USER_INIT YY_USER_INIT; @@ -1466,7 +1452,7 @@ static int yy_get_next_buffer (void) else { - int num_to_read = + size_t num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) @@ -1983,16 +1969,16 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) /** Setup the input buffer state to scan a string. The next call to zconflex() will * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan + * @param yy_str a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * zconf_scan_bytes() instead. */ -YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr ) +YY_BUFFER_STATE zconf_scan_string (yyconst char * yy_str ) { - return zconf_scan_bytes(yystr,strlen(yystr) ); + return zconf_scan_bytes(yy_str,strlen(yy_str) ); } /** Setup the input buffer state to scan the given bytes. The next call to zconflex() will @@ -2002,7 +1988,7 @@ YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr ) * * @return the newly allocated buffer state object. */ -YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +YY_BUFFER_STATE zconf_scan_bytes (yyconst char * bytes, int len ) { YY_BUFFER_STATE b; char *buf; @@ -2010,15 +1996,15 @@ YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, int _yybytes_len ) int i; /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; + n = len + 2; buf = (char *) zconfalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" ); - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; b = zconf_scan_buffer(buf,n ); if ( ! b ) @@ -2139,34 +2125,6 @@ void zconfset_debug (int bdebug ) zconf_flex_debug = bdebug ; } -static int yy_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from zconflex_destroy(), so don't allocate here. - */ - - (yy_buffer_stack) = 0; - (yy_buffer_stack_top) = 0; - (yy_buffer_stack_max) = 0; - (yy_c_buf_p) = (char *) 0; - (yy_init) = 0; - (yy_start) = 0; - -/* Defined in main.c */ -#ifdef YY_STDINIT - zconfin = stdin; - zconfout = stdout; -#else - zconfin = (FILE *) 0; - zconfout = (FILE *) 0; -#endif - - /* For future reference: Set errno on error, since we are called by - * zconflex_init() - */ - return 0; -} - /* zconflex_destroy is for both reentrant and non-reentrant scanners. */ int zconflex_destroy (void) { @@ -2182,10 +2140,6 @@ int zconflex_destroy (void) zconffree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * zconflex() is called, initialization will occur. */ - yy_init_globals( ); - return 0; } @@ -2197,7 +2151,7 @@ int zconflex_destroy (void) static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; - for ( i = 0; i < n; ++i ) + for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif @@ -2206,7 +2160,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) static int yy_flex_strlen (yyconst char * s ) { register int n; - for ( n = 0; s[n]; ++n ) + for ( n = 0; s[n]; ++n ) ; return n; @@ -2237,6 +2191,19 @@ void zconffree (void * ptr ) #define YYTABLES_NAME "yytables" +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef yytext_ptr +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + void zconf_starthelp(void) { new_string(); diff --git a/trunk/scripts/kconfig/lkc.h b/trunk/scripts/kconfig/lkc.h index 2628023a1fe1..527f60c99c50 100644 --- a/trunk/scripts/kconfig/lkc.h +++ b/trunk/scripts/kconfig/lkc.h @@ -40,10 +40,6 @@ extern "C" { #define TF_COMMAND 0x0001 #define TF_PARAM 0x0002 -#define TF_OPTION 0x0004 - -#define T_OPT_MODULES 1 -#define T_OPT_DEFCONFIG_LIST 2 struct kconf_id { int name; @@ -64,6 +60,8 @@ int zconf_lineno(void); char *zconf_curname(void); /* confdata.c */ +extern const char conf_def_filename[]; + char *conf_get_default_confname(void); /* kconfig_load.c */ @@ -80,7 +78,6 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); -void menu_add_option(int token, char *arg); void menu_finalize(struct menu *parent); void menu_set_type(int type); @@ -102,7 +99,6 @@ const char *str_get(struct gstr *gs); /* symbol.c */ void sym_init(void); void sym_clear_all_valid(void); -void sym_set_all_changed(void); void sym_set_changed(struct symbol *sym); struct symbol *sym_check_deps(struct symbol *sym); struct property *prop_alloc(enum prop_type type, struct symbol *sym); @@ -141,7 +137,7 @@ static inline bool sym_is_optional(struct symbol *sym) static inline bool sym_has_value(struct symbol *sym) { - return sym->flags & SYMBOL_DEF_USER ? true : false; + return sym->flags & SYMBOL_NEW ? false : true; } #ifdef __cplusplus diff --git a/trunk/scripts/kconfig/lkc_proto.h b/trunk/scripts/kconfig/lkc_proto.h index a263746cfa7d..b6a389c5fcbd 100644 --- a/trunk/scripts/kconfig/lkc_proto.h +++ b/trunk/scripts/kconfig/lkc_proto.h @@ -2,9 +2,8 @@ /* confdata.c */ P(conf_parse,void,(const char *name)); P(conf_read,int,(const char *name)); -P(conf_read_simple,int,(const char *name, int)); +P(conf_read_simple,int,(const char *name)); P(conf_write,int,(const char *name)); -P(conf_write_autoconf,int,(void)); /* menu.c */ P(rootmenu,struct menu,); @@ -39,4 +38,4 @@ P(prop_get_type_name,const char *,(enum prop_type type)); /* expr.c */ P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); -P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)); +P(expr_print,void,(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken)); diff --git a/trunk/scripts/kconfig/lxdialog/checklist.c b/trunk/scripts/kconfig/lxdialog/checklist.c index 79886413b6d5..be0200e9cdaf 100644 --- a/trunk/scripts/kconfig/lxdialog/checklist.c +++ b/trunk/scripts/kconfig/lxdialog/checklist.c @@ -187,12 +187,9 @@ int dialog_checklist(const char *title, const char *prompt, int height, /* Print the list */ for (i = 0; i < max_choice; i++) { - if (i != choice) - print_item(list, items[(scroll + i) * 3 + 1], - status[i + scroll], i, 0); + print_item(list, items[(scroll + i) * 3 + 1], + status[i + scroll], i, i == choice); } - print_item(list, items[(scroll + choice) * 3 + 1], - status[choice + scroll], choice, 1); print_arrows(dialog, choice, item_no, scroll, box_y, box_x + check_x + 5, list_height); diff --git a/trunk/scripts/kconfig/menu.c b/trunk/scripts/kconfig/menu.c index c86c27f2c761..0fce20cb7f3c 100644 --- a/trunk/scripts/kconfig/menu.c +++ b/trunk/scripts/kconfig/menu.c @@ -114,7 +114,7 @@ void menu_set_type(int type) sym->type = type; return; } - menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", + menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n", sym->name ? sym->name : "", sym_type_name(sym->type), sym_type_name(type)); } @@ -124,20 +124,15 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e struct property *prop = prop_alloc(type, current_entry->sym); prop->menu = current_entry; + prop->text = prompt; prop->expr = expr; prop->visible.expr = menu_check_dep(dep); if (prompt) { - if (isspace(*prompt)) { - prop_warn(prop, "leading whitespace ignored"); - while (isspace(*prompt)) - prompt++; - } if (current_entry->prompt) - prop_warn(prop, "prompt redefined"); + menu_warn(current_entry, "prompt redefined\n"); current_entry->prompt = prop; } - prop->text = prompt; return prop; } @@ -157,24 +152,6 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); } -void menu_add_option(int token, char *arg) -{ - struct property *prop; - - switch (token) { - case T_OPT_MODULES: - prop = prop_alloc(P_DEFAULT, modules_sym); - prop->expr = expr_alloc_symbol(current_entry->sym); - break; - case T_OPT_DEFCONFIG_LIST: - if (!sym_defconfig_list) - sym_defconfig_list = current_entry->sym; - else if (sym_defconfig_list != current_entry->sym) - zconf_error("trying to redefine defconfig symbol"); - break; - } -} - static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) { return sym2->type == S_INT || sym2->type == S_HEX || @@ -348,10 +325,11 @@ void menu_finalize(struct menu *parent) if (sym && !(sym->flags & SYMBOL_WARNED)) { if (sym->type == S_UNKNOWN) - menu_warn(parent, "config symbol defined without type"); + menu_warn(parent, "config symbol defined " + "without type\n"); if (sym_is_choice(sym) && !parent->prompt) - menu_warn(parent, "choice must have a prompt"); + menu_warn(parent, "choice must have a prompt\n"); /* Check properties connected to this symbol */ sym_check_prop(sym); diff --git a/trunk/scripts/kconfig/qconf.cc b/trunk/scripts/kconfig/qconf.cc index 393f3749f330..4590cd31623f 100644 --- a/trunk/scripts/kconfig/qconf.cc +++ b/trunk/scripts/kconfig/qconf.cc @@ -6,20 +6,16 @@ #include #include #include -#include #include #include #include -#include +#include #include -#include -#include #include #include #include #include #include -#include #include #include @@ -36,16 +32,32 @@ #endif static QApplication *configApp; -static ConfigSettings *configSettings; static inline QString qgettext(const char* str) { - return QString::fromLocal8Bit(gettext(str)); + return QString::fromLocal8Bit(gettext(str)); } static inline QString qgettext(const QString& str) { - return QString::fromLocal8Bit(gettext(str.latin1())); + return QString::fromLocal8Bit(gettext(str.latin1())); +} + +ConfigSettings::ConfigSettings() + : showAll(false), showName(false), showRange(false), showData(false) +{ +} + +#if QT_VERSION >= 300 +/** + * Reads the list column settings from the application settings. + */ +void ConfigSettings::readListSettings() +{ + showAll = readBoolEntry("/kconfig/qconf/showAll", false); + showName = readBoolEntry("/kconfig/qconf/showName", false); + showRange = readBoolEntry("/kconfig/qconf/showRange", false); + showData = readBoolEntry("/kconfig/qconf/showData", false); } /** @@ -76,7 +88,76 @@ bool ConfigSettings::writeSizes(const QString& key, const QValueList& value stringList.push_back(QString::number(*it)); return writeEntry(key, stringList); } +#endif + + +/* + * update all the children of a menu entry + * removes/adds the entries from the parent widget as necessary + * + * parent: either the menu list widget or a menu entry widget + * menu: entry to be updated + */ +template +void ConfigList::updateMenuList(P* parent, struct menu* menu) +{ + struct menu* child; + ConfigItem* item; + ConfigItem* last; + bool visible; + enum prop_type type; + if (!menu) { + while ((item = parent->firstChild())) + delete item; + return; + } + + last = parent->firstChild(); + if (last && !last->goParent) + last = 0; + for (child = menu->list; child; child = child->next) { + item = last ? last->nextSibling() : parent->firstChild(); + type = child->prompt ? child->prompt->type : P_UNKNOWN; + + switch (mode) { + case menuMode: + if (!(child->flags & MENU_ROOT)) + goto hide; + break; + case symbolMode: + if (child->flags & MENU_ROOT) + goto hide; + break; + default: + break; + } + + visible = menu_is_visible(child); + if (showAll || visible) { + if (!item || item->menu != child) + item = new ConfigItem(parent, last, child, visible); + else + item->testUpdateMenu(visible); + + if (mode == fullMode || mode == menuMode || type != P_MENU) + updateMenuList(item, child); + else + updateMenuList(item, 0); + last = item; + continue; + } + hide: + if (item && item->menu == child) { + last = parent->firstChild(); + if (last == item) + last = 0; + else while (last->nextSibling() != item) + last = last->nextSibling(); + delete item; + } + } +} #if QT_VERSION >= 300 /* @@ -274,12 +355,6 @@ ConfigItem::~ConfigItem(void) } } -ConfigLineEdit::ConfigLineEdit(ConfigView* parent) - : Parent(parent) -{ - connect(this, SIGNAL(lostFocus()), SLOT(hide())); -} - void ConfigLineEdit::show(ConfigItem* i) { item = i; @@ -310,14 +385,14 @@ void ConfigLineEdit::keyPressEvent(QKeyEvent* e) hide(); } -ConfigList::ConfigList(ConfigView* p, const char *name) - : Parent(p, name), +ConfigList::ConfigList(ConfigView* p, ConfigMainWindow* cv, ConfigSettings* configSettings) + : Parent(p), cview(cv), updateAll(false), symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void), showAll(false), showName(false), showRange(false), showData(false), - rootEntry(0), headerPopup(0) + rootEntry(0) { int i; @@ -331,14 +406,11 @@ ConfigList::ConfigList(ConfigView* p, const char *name) connect(this, SIGNAL(selectionChanged(void)), SLOT(updateSelection(void))); - if (name) { - configSettings->beginGroup(name); - showAll = configSettings->readBoolEntry("/showAll", false); - showName = configSettings->readBoolEntry("/showName", false); - showRange = configSettings->readBoolEntry("/showRange", false); - showData = configSettings->readBoolEntry("/showData", false); - configSettings->endGroup(); - connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + if (configSettings) { + showAll = configSettings->showAll; + showName = configSettings->showName; + showRange = configSettings->showRange; + showData = configSettings->showData; } for (i = 0; i < colNr; i++) @@ -369,30 +441,6 @@ void ConfigList::reinit(void) updateListAll(); } -void ConfigList::saveSettings(void) -{ - if (name()) { - configSettings->beginGroup(name()); - configSettings->writeEntry("/showName", showName); - configSettings->writeEntry("/showRange", showRange); - configSettings->writeEntry("/showData", showData); - configSettings->writeEntry("/showAll", showAll); - configSettings->endGroup(); - } -} - -ConfigItem* ConfigList::findConfigItem(struct menu *menu) -{ - ConfigItem* item = (ConfigItem*)menu->data; - - for (; item; item = item->nextItem) { - if (this == item->listView()) - break; - } - - return item; -} - void ConfigList::updateSelection(void) { struct menu *menu; @@ -402,8 +450,9 @@ void ConfigList::updateSelection(void) if (!item) return; + cview->setHelp(item); + menu = item->menu; - emit menuChanged(menu); if (!menu) return; type = menu->prompt ? menu->prompt->type : P_UNKNOWN; @@ -415,20 +464,8 @@ void ConfigList::updateList(ConfigItem* item) { ConfigItem* last = 0; - if (!rootEntry) { - if (mode != listMode) - goto update; - QListViewItemIterator it(this); - ConfigItem* item; - - for (; it.current(); ++it) { - item = (ConfigItem*)it.current(); - if (!item->menu) - continue; - item->testUpdateMenu(menu_is_visible(item->menu)); - } - return; - } + if (!rootEntry) + goto update; if (rootEntry != &rootmenu && (mode == singleMode || (mode == symbolMode && rootEntry->parent != &rootmenu))) { @@ -454,6 +491,14 @@ void ConfigList::updateList(ConfigItem* item) triggerUpdate(); } +void ConfigList::setAllOpen(bool open) +{ + QListViewItemIterator it(this); + + for (; it.current(); it++) + it.current()->setOpen(open); +} + void ConfigList::setValue(ConfigItem* item, tristate val) { struct symbol* sym; @@ -536,7 +581,6 @@ void ConfigList::setRootMenu(struct menu *menu) rootEntry = menu; updateListAll(); setSelected(currentItem(), hasFocus()); - ensureItemVisible(currentItem()); } void ConfigList::setParentMenu(void) @@ -559,74 +603,6 @@ void ConfigList::setParentMenu(void) } } -/* - * update all the children of a menu entry - * removes/adds the entries from the parent widget as necessary - * - * parent: either the menu list widget or a menu entry widget - * menu: entry to be updated - */ -template -void ConfigList::updateMenuList(P* parent, struct menu* menu) -{ - struct menu* child; - ConfigItem* item; - ConfigItem* last; - bool visible; - enum prop_type type; - - if (!menu) { - while ((item = parent->firstChild())) - delete item; - return; - } - - last = parent->firstChild(); - if (last && !last->goParent) - last = 0; - for (child = menu->list; child; child = child->next) { - item = last ? last->nextSibling() : parent->firstChild(); - type = child->prompt ? child->prompt->type : P_UNKNOWN; - - switch (mode) { - case menuMode: - if (!(child->flags & MENU_ROOT)) - goto hide; - break; - case symbolMode: - if (child->flags & MENU_ROOT) - goto hide; - break; - default: - break; - } - - visible = menu_is_visible(child); - if (showAll || visible) { - if (!item || item->menu != child) - item = new ConfigItem(parent, last, child, visible); - else - item->testUpdateMenu(visible); - - if (mode == fullMode || mode == menuMode || type != P_MENU) - updateMenuList(item, child); - else - updateMenuList(item, 0); - last = item; - continue; - } - hide: - if (item && item->menu == child) { - last = parent->firstChild(); - if (last == item) - last = 0; - else while (last->nextSibling() != item) - last = last->nextSibling(); - delete item; - } - } -} - void ConfigList::keyPressEvent(QKeyEvent* ev) { QListViewItem* i = currentItem(); @@ -634,7 +610,7 @@ void ConfigList::keyPressEvent(QKeyEvent* ev) struct menu *menu; enum prop_type type; - if (ev->key() == Key_Escape && mode != fullMode && mode != listMode) { + if (ev->key() == Key_Escape && mode != fullMode) { emit parentSelected(); ev->accept(); return; @@ -779,62 +755,23 @@ void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e) void ConfigList::focusInEvent(QFocusEvent *e) { - struct menu *menu = NULL; - Parent::focusInEvent(e); - ConfigItem* item = (ConfigItem *)currentItem(); - if (item) { - setSelected(item, TRUE); - menu = item->menu; - } - emit gotFocus(menu); -} + QListViewItem* item = currentItem(); + if (!item) + return; -void ConfigList::contextMenuEvent(QContextMenuEvent *e) -{ - if (e->y() <= header()->geometry().bottom()) { - if (!headerPopup) { - QAction *action; - - headerPopup = new QPopupMenu(this); - action = new QAction("Show Name", 0, this); - action->setToggleAction(TRUE); - connect(action, SIGNAL(toggled(bool)), - parent(), SLOT(setShowName(bool))); - connect(parent(), SIGNAL(showNameChanged(bool)), - action, SLOT(setOn(bool))); - action->setOn(showName); - action->addTo(headerPopup); - action = new QAction("Show Range", 0, this); - action->setToggleAction(TRUE); - connect(action, SIGNAL(toggled(bool)), - parent(), SLOT(setShowRange(bool))); - connect(parent(), SIGNAL(showRangeChanged(bool)), - action, SLOT(setOn(bool))); - action->setOn(showRange); - action->addTo(headerPopup); - action = new QAction("Show Data", 0, this); - action->setToggleAction(TRUE); - connect(action, SIGNAL(toggled(bool)), - parent(), SLOT(setShowData(bool))); - connect(parent(), SIGNAL(showDataChanged(bool)), - action, SLOT(setOn(bool))); - action->setOn(showData); - action->addTo(headerPopup); - } - headerPopup->exec(e->globalPos()); - e->accept(); - } else - e->ignore(); + setSelected(item, TRUE); + emit gotFocus(); } ConfigView* ConfigView::viewList; -ConfigView::ConfigView(QWidget* parent, const char *name) - : Parent(parent, name) +ConfigView::ConfigView(QWidget* parent, ConfigMainWindow* cview, + ConfigSettings *configSettings) + : Parent(parent) { - list = new ConfigList(this, name); + list = new ConfigList(this, cview, configSettings); lineEdit = new ConfigLineEdit(this); lineEdit->hide(); @@ -854,50 +791,6 @@ ConfigView::~ConfigView(void) } } -void ConfigView::setShowAll(bool b) -{ - if (list->showAll != b) { - list->showAll = b; - list->updateListAll(); - emit showAllChanged(b); - } -} - -void ConfigView::setShowName(bool b) -{ - if (list->showName != b) { - list->showName = b; - list->reinit(); - emit showNameChanged(b); - } -} - -void ConfigView::setShowRange(bool b) -{ - if (list->showRange != b) { - list->showRange = b; - list->reinit(); - emit showRangeChanged(b); - } -} - -void ConfigView::setShowData(bool b) -{ - if (list->showData != b) { - list->showData = b; - list->reinit(); - emit showDataChanged(b); - } -} - -void ConfigList::setAllOpen(bool open) -{ - QListViewItemIterator it(this); - - for (; it.current(); it++) - it.current()->setOpen(open); -} - void ConfigView::updateList(ConfigItem* item) { ConfigView* v; @@ -914,347 +807,6 @@ void ConfigView::updateListAll(void) v->list->updateListAll(); } -ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) - : Parent(parent, name), menu(0) -{ - if (name) { - configSettings->beginGroup(name); - _showDebug = configSettings->readBoolEntry("/showDebug", false); - configSettings->endGroup(); - connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); - } -} - -void ConfigInfoView::saveSettings(void) -{ - if (name()) { - configSettings->beginGroup(name()); - configSettings->writeEntry("/showDebug", showDebug()); - configSettings->endGroup(); - } -} - -void ConfigInfoView::setShowDebug(bool b) -{ - if (_showDebug != b) { - _showDebug = b; - if (menu) - menuInfo(); - else if (sym) - symbolInfo(); - emit showDebugChanged(b); - } -} - -void ConfigInfoView::setInfo(struct menu *m) -{ - if (menu == m) - return; - menu = m; - if (!menu) - clear(); - else - menuInfo(); -} - -void ConfigInfoView::setSource(const QString& name) -{ - const char *p = name.latin1(); - - menu = NULL; - sym = NULL; - - switch (p[0]) { - case 'm': - struct menu *m; - - if (sscanf(p, "m%p", &m) == 1 && menu != m) { - menu = m; - menuInfo(); - emit menuSelected(menu); - } - break; - case 's': - struct symbol *s; - - if (sscanf(p, "s%p", &s) == 1 && sym != s) { - sym = s; - symbolInfo(); - } - break; - } -} - -void ConfigInfoView::symbolInfo(void) -{ - QString str; - - str += "Symbol: "; - str += print_filter(sym->name); - str += "

value: "; - str += print_filter(sym_get_string_value(sym)); - str += "
visibility: "; - str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n"; - str += "
"; - str += debug_info(sym); - - setText(str); -} - -void ConfigInfoView::menuInfo(void) -{ - struct symbol* sym; - QString head, debug, help; - - sym = menu->sym; - if (sym) { - if (menu->prompt) { - head += ""; - head += print_filter(_(menu->prompt->text)); - head += ""; - if (sym->name) { - head += " ("; - if (showDebug()) - head += QString().sprintf("
", sym); - head += print_filter(sym->name); - if (showDebug()) - head += ""; - head += ")"; - } - } else if (sym->name) { - head += ""; - if (showDebug()) - head += QString().sprintf("", sym); - head += print_filter(sym->name); - if (showDebug()) - head += ""; - head += ""; - } - head += "

"; - - if (showDebug()) - debug = debug_info(sym); - - help = print_filter(_(sym->help)); - } else if (menu->prompt) { - head += ""; - head += print_filter(_(menu->prompt->text)); - head += "

"; - if (showDebug()) { - if (menu->prompt->visible.expr) { - debug += "  dep: "; - expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); - debug += "

"; - } - } - } - if (showDebug()) - debug += QString().sprintf("defined at %s:%d

", menu->file->name, menu->lineno); - - setText(head + debug + help); -} - -QString ConfigInfoView::debug_info(struct symbol *sym) -{ - QString debug; - - debug += "type: "; - debug += print_filter(sym_type_name(sym->type)); - if (sym_is_choice(sym)) - debug += " (choice)"; - debug += "
"; - if (sym->rev_dep.expr) { - debug += "reverse dep: "; - expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE); - debug += "
"; - } - for (struct property *prop = sym->prop; prop; prop = prop->next) { - switch (prop->type) { - case P_PROMPT: - case P_MENU: - debug += QString().sprintf("prompt: ", prop->menu); - debug += print_filter(_(prop->text)); - debug += "
"; - break; - case P_DEFAULT: - debug += "default: "; - expr_print(prop->expr, expr_print_help, &debug, E_NONE); - debug += "
"; - break; - case P_CHOICE: - if (sym_is_choice(sym)) { - debug += "choice: "; - expr_print(prop->expr, expr_print_help, &debug, E_NONE); - debug += "
"; - } - break; - case P_SELECT: - debug += "select: "; - expr_print(prop->expr, expr_print_help, &debug, E_NONE); - debug += "
"; - break; - case P_RANGE: - debug += "range: "; - expr_print(prop->expr, expr_print_help, &debug, E_NONE); - debug += "
"; - break; - default: - debug += "unknown property: "; - debug += prop_get_type_name(prop->type); - debug += "
"; - } - if (prop->visible.expr) { - debug += "    dep: "; - expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); - debug += "
"; - } - } - debug += "
"; - - return debug; -} - -QString ConfigInfoView::print_filter(const QString &str) -{ - QRegExp re("[<>&\"\\n]"); - QString res = str; - for (int i = 0; (i = res.find(re, i)) >= 0;) { - switch (res[i].latin1()) { - case '<': - res.replace(i, 1, "<"); - i += 4; - break; - case '>': - res.replace(i, 1, ">"); - i += 4; - break; - case '&': - res.replace(i, 1, "&"); - i += 5; - break; - case '"': - res.replace(i, 1, """); - i += 6; - break; - case '\n': - res.replace(i, 1, "
"); - i += 4; - break; - } - } - return res; -} - -void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str) -{ - QString* text = reinterpret_cast(data); - QString str2 = print_filter(str); - - if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) { - *text += QString().sprintf("", sym); - *text += str2; - *text += ""; - } else - *text += str2; -} - -QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos) -{ - QPopupMenu* popup = Parent::createPopupMenu(pos); - QAction* action = new QAction("Show Debug Info", 0, popup); - action->setToggleAction(TRUE); - connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); - connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); - action->setOn(showDebug()); - popup->insertSeparator(); - action->addTo(popup); - return popup; -} - -void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e) -{ - Parent::contentsContextMenuEvent(e); -} - -ConfigSearchWindow::ConfigSearchWindow(QWidget* parent, const char *name) - : Parent(parent, name), result(NULL) -{ - setCaption("Search Config"); - - QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6); - QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6); - layout2->addWidget(new QLabel("Find:", this)); - editField = new QLineEdit(this); - connect(editField, SIGNAL(returnPressed()), SLOT(search())); - layout2->addWidget(editField); - searchButton = new QPushButton("Search", this); - searchButton->setAutoDefault(FALSE); - connect(searchButton, SIGNAL(clicked()), SLOT(search())); - layout2->addWidget(searchButton); - layout1->addLayout(layout2); - - split = new QSplitter(this); - split->setOrientation(QSplitter::Vertical); - list = new ConfigView(split, name); - list->list->mode = listMode; - info = new ConfigInfoView(split, name); - connect(list->list, SIGNAL(menuChanged(struct menu *)), - info, SLOT(setInfo(struct menu *))); - layout1->addWidget(split); - - if (name) { - int x, y, width, height; - bool ok; - - configSettings->beginGroup(name); - width = configSettings->readNumEntry("/window width", parent->width() / 2); - height = configSettings->readNumEntry("/window height", parent->height() / 2); - resize(width, height); - x = configSettings->readNumEntry("/window x", 0, &ok); - if (ok) - y = configSettings->readNumEntry("/window y", 0, &ok); - if (ok) - move(x, y); - QValueList sizes = configSettings->readSizes("/split", &ok); - if (ok) - split->setSizes(sizes); - configSettings->endGroup(); - connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); - } -} - -void ConfigSearchWindow::saveSettings(void) -{ - if (name()) { - configSettings->beginGroup(name()); - configSettings->writeEntry("/window x", pos().x()); - configSettings->writeEntry("/window y", pos().y()); - configSettings->writeEntry("/window width", size().width()); - configSettings->writeEntry("/window height", size().height()); - configSettings->writeSizes("/split", split->sizes()); - configSettings->endGroup(); - } -} - -void ConfigSearchWindow::search(void) -{ - struct symbol **p; - struct property *prop; - ConfigItem *lastItem = NULL; - - free(result); - list->list->clear(); - - result = sym_re_search(editField->text().latin1()); - if (!result) - return; - for (p = result; *p; p++) { - for_all_prompts((*p), prop) - lastItem = new ConfigItem(list->list, lastItem, prop->menu, - menu_is_visible(prop->menu)); - } -} - /* * Construct the complete config widget */ @@ -1266,30 +818,42 @@ ConfigMainWindow::ConfigMainWindow(void) QWidget *d = configApp->desktop(); - width = configSettings->readNumEntry("/window width", d->width() - 64); - height = configSettings->readNumEntry("/window height", d->height() - 64); + ConfigSettings* configSettings = new ConfigSettings(); +#if QT_VERSION >= 300 + width = configSettings->readNumEntry("/kconfig/qconf/window width", d->width() - 64); + height = configSettings->readNumEntry("/kconfig/qconf/window height", d->height() - 64); resize(width, height); - x = configSettings->readNumEntry("/window x", 0, &ok); + x = configSettings->readNumEntry("/kconfig/qconf/window x", 0, &ok); if (ok) - y = configSettings->readNumEntry("/window y", 0, &ok); + y = configSettings->readNumEntry("/kconfig/qconf/window y", 0, &ok); if (ok) move(x, y); + showDebug = configSettings->readBoolEntry("/kconfig/qconf/showDebug", false); + + // read list settings into configSettings, will be used later for ConfigList setup + configSettings->readListSettings(); +#else + width = d->width() - 64; + height = d->height() - 64; + resize(width, height); + showDebug = false; +#endif split1 = new QSplitter(this); split1->setOrientation(QSplitter::Horizontal); setCentralWidget(split1); - menuView = new ConfigView(split1, "menu"); + menuView = new ConfigView(split1, this, configSettings); menuList = menuView->list; split2 = new QSplitter(split1); split2->setOrientation(QSplitter::Vertical); // create config tree - configView = new ConfigView(split2, "config"); + configView = new ConfigView(split2, this, configSettings); configList = configView->list; - helpText = new ConfigInfoView(split2, "help"); + helpText = new QTextView(split2); helpText->setTextFormat(Qt::RichText); setTabOrder(configList, helpText); @@ -1309,8 +873,6 @@ ConfigMainWindow::ConfigMainWindow(void) connect(saveAction, SIGNAL(activated()), SLOT(saveConfig())); QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this); connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs())); - QAction *searchAction = new QAction("Search", "&Search", CTRL+Key_F, this); - connect(searchAction, SIGNAL(activated()), SLOT(searchConfig())); QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this); connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView())); QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this); @@ -1320,29 +882,24 @@ ConfigMainWindow::ConfigMainWindow(void) QAction *showNameAction = new QAction(NULL, "Show Name", 0, this); showNameAction->setToggleAction(TRUE); - connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); - connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool))); - showNameAction->setOn(configView->showName()); + showNameAction->setOn(configList->showName); + connect(showNameAction, SIGNAL(toggled(bool)), SLOT(setShowName(bool))); QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this); showRangeAction->setToggleAction(TRUE); - connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); - connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool))); showRangeAction->setOn(configList->showRange); + connect(showRangeAction, SIGNAL(toggled(bool)), SLOT(setShowRange(bool))); QAction *showDataAction = new QAction(NULL, "Show Data", 0, this); showDataAction->setToggleAction(TRUE); - connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); - connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool))); showDataAction->setOn(configList->showData); + connect(showDataAction, SIGNAL(toggled(bool)), SLOT(setShowData(bool))); QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this); showAllAction->setToggleAction(TRUE); - connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool))); - connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool))); showAllAction->setOn(configList->showAll); + connect(showAllAction, SIGNAL(toggled(bool)), SLOT(setShowAll(bool))); QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this); showDebugAction->setToggleAction(TRUE); - connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); - connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool))); - showDebugAction->setOn(helpText->showDebug()); + showDebugAction->setOn(showDebug); + connect(showDebugAction, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this); connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro())); @@ -1366,8 +923,6 @@ ConfigMainWindow::ConfigMainWindow(void) saveAction->addTo(config); saveAsAction->addTo(config); config->insertSeparator(); - searchAction->addTo(config); - config->insertSeparator(); quitAction->addTo(config); // create options menu @@ -1387,27 +942,20 @@ ConfigMainWindow::ConfigMainWindow(void) showIntroAction->addTo(helpMenu); showAboutAction->addTo(helpMenu); - connect(configList, SIGNAL(menuChanged(struct menu *)), - helpText, SLOT(setInfo(struct menu *))); connect(configList, SIGNAL(menuSelected(struct menu *)), SLOT(changeMenu(struct menu *))); connect(configList, SIGNAL(parentSelected()), SLOT(goBack())); - connect(menuList, SIGNAL(menuChanged(struct menu *)), - helpText, SLOT(setInfo(struct menu *))); connect(menuList, SIGNAL(menuSelected(struct menu *)), SLOT(changeMenu(struct menu *))); - connect(configList, SIGNAL(gotFocus(struct menu *)), - helpText, SLOT(setInfo(struct menu *))); - connect(menuList, SIGNAL(gotFocus(struct menu *)), - helpText, SLOT(setInfo(struct menu *))); - connect(menuList, SIGNAL(gotFocus(struct menu *)), + connect(configList, SIGNAL(gotFocus(void)), + SLOT(listFocusChanged(void))); + connect(menuList, SIGNAL(gotFocus(void)), SLOT(listFocusChanged(void))); - connect(helpText, SIGNAL(menuSelected(struct menu *)), - SLOT(setMenuLink(struct menu *))); - QString listMode = configSettings->readEntry("/listMode", "symbol"); +#if QT_VERSION >= 300 + QString listMode = configSettings->readEntry("/kconfig/qconf/listMode", "symbol"); if (listMode == "single") showSingleView(); else if (listMode == "full") @@ -1416,13 +964,162 @@ ConfigMainWindow::ConfigMainWindow(void) showSplitView(); // UI setup done, restore splitter positions - QValueList sizes = configSettings->readSizes("/split1", &ok); + QValueList sizes = configSettings->readSizes("/kconfig/qconf/split1", &ok); if (ok) split1->setSizes(sizes); - sizes = configSettings->readSizes("/split2", &ok); + sizes = configSettings->readSizes("/kconfig/qconf/split2", &ok); if (ok) split2->setSizes(sizes); +#else + showSplitView(); +#endif + delete configSettings; +} + +static QString print_filter(const QString &str) +{ + QRegExp re("[<>&\"\\n]"); + QString res = str; + for (int i = 0; (i = res.find(re, i)) >= 0;) { + switch (res[i].latin1()) { + case '<': + res.replace(i, 1, "<"); + i += 4; + break; + case '>': + res.replace(i, 1, ">"); + i += 4; + break; + case '&': + res.replace(i, 1, "&"); + i += 5; + break; + case '"': + res.replace(i, 1, """); + i += 6; + break; + case '\n': + res.replace(i, 1, "
"); + i += 4; + break; + } + } + return res; +} + +static void expr_print_help(void *data, const char *str) +{ + reinterpret_cast(data)->append(print_filter(str)); +} + +/* + * display a new help entry as soon as a new menu entry is selected + */ +void ConfigMainWindow::setHelp(QListViewItem* item) +{ + struct symbol* sym; + struct menu* menu = 0; + + configList->parent()->lineEdit->hide(); + if (item) + menu = ((ConfigItem*)item)->menu; + if (!menu) { + helpText->setText(QString::null); + return; + } + + QString head, debug, help; + menu = ((ConfigItem*)item)->menu; + sym = menu->sym; + if (sym) { + if (menu->prompt) { + head += ""; + head += print_filter(_(menu->prompt->text)); + head += ""; + if (sym->name) { + head += " ("; + head += print_filter(_(sym->name)); + head += ")"; + } + } else if (sym->name) { + head += ""; + head += print_filter(_(sym->name)); + head += ""; + } + head += "

"; + + if (showDebug) { + debug += "type: "; + debug += print_filter(sym_type_name(sym->type)); + if (sym_is_choice(sym)) + debug += " (choice)"; + debug += "
"; + if (sym->rev_dep.expr) { + debug += "reverse dep: "; + expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + for (struct property *prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_PROMPT: + case P_MENU: + debug += "prompt: "; + debug += print_filter(_(prop->text)); + debug += "
"; + break; + case P_DEFAULT: + debug += "default: "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + break; + case P_CHOICE: + if (sym_is_choice(sym)) { + debug += "choice: "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + break; + case P_SELECT: + debug += "select: "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + break; + case P_RANGE: + debug += "range: "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + break; + default: + debug += "unknown property: "; + debug += prop_get_type_name(prop->type); + debug += "
"; + } + if (prop->visible.expr) { + debug += "    dep: "; + expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + } + debug += "
"; + } + + help = print_filter(_(sym->help)); + } else if (menu->prompt) { + head += ""; + head += print_filter(_(menu->prompt->text)); + head += "

"; + if (showDebug) { + if (menu->prompt->visible.expr) { + debug += "  dep: "; + expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); + debug += "

"; + } + } + } + if (showDebug) + debug += QString().sprintf("defined at %s:%d

", menu->file->name, menu->lineno); + helpText->setText(head + debug + help); } void ConfigMainWindow::loadConfig(void) @@ -1450,73 +1147,21 @@ void ConfigMainWindow::saveConfigAs(void) QMessageBox::information(this, "qconf", "Unable to save configuration!"); } -void ConfigMainWindow::searchConfig(void) -{ - if (!searchWindow) - searchWindow = new ConfigSearchWindow(this, "search"); - searchWindow->show(); -} - void ConfigMainWindow::changeMenu(struct menu *menu) { configList->setRootMenu(menu); backAction->setEnabled(TRUE); } -void ConfigMainWindow::setMenuLink(struct menu *menu) +void ConfigMainWindow::listFocusChanged(void) { - struct menu *parent; - ConfigList* list = NULL; - ConfigItem* item; - - if (!menu_is_visible(menu) && !configView->showAll()) - return; - - switch (configList->mode) { - case singleMode: - list = configList; - parent = menu_get_parent_menu(menu); - if (!parent) - return; - list->setRootMenu(parent); - break; - case symbolMode: - if (menu->flags & MENU_ROOT) { - configList->setRootMenu(menu); + if (menuList->hasFocus()) { + if (menuList->mode == menuMode) configList->clearSelection(); - list = menuList; - } else { - list = configList; - parent = menu_get_parent_menu(menu->parent); - if (!parent) - return; - item = menuList->findConfigItem(parent); - if (item) { - menuList->setSelected(item, TRUE); - menuList->ensureItemVisible(item); - } - list->setRootMenu(parent); - } - break; - case fullMode: - list = configList; - break; + setHelp(menuList->selectedItem()); + } else if (configList->hasFocus()) { + setHelp(configList->selectedItem()); } - - if (list) { - item = list->findConfigItem(menu); - if (item) { - list->setSelected(item, TRUE); - list->ensureItemVisible(item); - list->setFocus(); - } - } -} - -void ConfigMainWindow::listFocusChanged(void) -{ - if (menuList->mode == menuMode) - configList->clearSelection(); } void ConfigMainWindow::goBack(void) @@ -1578,6 +1223,53 @@ void ConfigMainWindow::showFullView(void) configList->setFocus(); } +void ConfigMainWindow::setShowAll(bool b) +{ + if (configList->showAll == b) + return; + configList->showAll = b; + configList->updateListAll(); + menuList->showAll = b; + menuList->updateListAll(); +} + +void ConfigMainWindow::setShowDebug(bool b) +{ + if (showDebug == b) + return; + showDebug = b; +} + +void ConfigMainWindow::setShowName(bool b) +{ + if (configList->showName == b) + return; + configList->showName = b; + configList->reinit(); + menuList->showName = b; + menuList->reinit(); +} + +void ConfigMainWindow::setShowRange(bool b) +{ + if (configList->showRange == b) + return; + configList->showRange = b; + configList->reinit(); + menuList->showRange = b; + menuList->reinit(); +} + +void ConfigMainWindow::setShowData(bool b) +{ + if (configList->showData == b) + return; + configList->showData = b; + configList->reinit(); + menuList->showData = b; + menuList->reinit(); +} + /* * ask for saving configuration before quitting * TODO ask only when something changed @@ -1632,10 +1324,17 @@ void ConfigMainWindow::showAbout(void) void ConfigMainWindow::saveSettings(void) { - configSettings->writeEntry("/window x", pos().x()); - configSettings->writeEntry("/window y", pos().y()); - configSettings->writeEntry("/window width", size().width()); - configSettings->writeEntry("/window height", size().height()); +#if QT_VERSION >= 300 + ConfigSettings *configSettings = new ConfigSettings; + configSettings->writeEntry("/kconfig/qconf/window x", pos().x()); + configSettings->writeEntry("/kconfig/qconf/window y", pos().y()); + configSettings->writeEntry("/kconfig/qconf/window width", size().width()); + configSettings->writeEntry("/kconfig/qconf/window height", size().height()); + configSettings->writeEntry("/kconfig/qconf/showName", configList->showName); + configSettings->writeEntry("/kconfig/qconf/showRange", configList->showRange); + configSettings->writeEntry("/kconfig/qconf/showData", configList->showData); + configSettings->writeEntry("/kconfig/qconf/showAll", configList->showAll); + configSettings->writeEntry("/kconfig/qconf/showDebug", showDebug); QString entry; switch(configList->mode) { @@ -1651,10 +1350,13 @@ void ConfigMainWindow::saveSettings(void) entry = "full"; break; } - configSettings->writeEntry("/listMode", entry); + configSettings->writeEntry("/kconfig/qconf/listMode", entry); - configSettings->writeSizes("/split1", split1->sizes()); - configSettings->writeSizes("/split2", split2->sizes()); + configSettings->writeSizes("/kconfig/qconf/split1", split1->sizes()); + configSettings->writeSizes("/kconfig/qconf/split2", split2->sizes()); + + delete configSettings; +#endif } void fixup_rootmenu(struct menu *menu) @@ -1712,19 +1414,13 @@ int main(int ac, char** av) conf_read(NULL); //zconfdump(stdout); - configSettings = new ConfigSettings(); - configSettings->beginGroup("/kconfig/qconf"); v = new ConfigMainWindow(); //zconfdump(stdout); - configApp->setMainWidget(v); + v->show(); configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit())); configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings())); - v->show(); configApp->exec(); - configSettings->endGroup(); - delete configSettings; - return 0; } diff --git a/trunk/scripts/kconfig/qconf.h b/trunk/scripts/kconfig/qconf.h index 6a9e3b14c227..e52f3e90bf0c 100644 --- a/trunk/scripts/kconfig/qconf.h +++ b/trunk/scripts/kconfig/qconf.h @@ -7,25 +7,9 @@ #if QT_VERSION >= 300 #include #else -class QSettings { -public: - void beginGroup(const QString& group) { } - void endGroup(void) { } - bool readBoolEntry(const QString& key, bool def = FALSE, bool* ok = 0) const - { if (ok) *ok = FALSE; return def; } - int readNumEntry(const QString& key, int def = 0, bool* ok = 0) const - { if (ok) *ok = FALSE; return def; } - QString readEntry(const QString& key, const QString& def = QString::null, bool* ok = 0) const - { if (ok) *ok = FALSE; return def; } - QStringList readListEntry(const QString& key, bool* ok = 0) const - { if (ok) *ok = FALSE; return QStringList(); } - template - bool writeEntry(const QString& key, t value) - { return TRUE; } -}; +class QSettings { }; #endif -class ConfigView; class ConfigList; class ConfigItem; class ConfigLineEdit; @@ -34,38 +18,64 @@ class ConfigMainWindow; class ConfigSettings : public QSettings { public: + ConfigSettings(); + +#if QT_VERSION >= 300 + void readListSettings(); QValueList readSizes(const QString& key, bool *ok); bool writeSizes(const QString& key, const QValueList& value); +#endif + + bool showAll; + bool showName; + bool showRange; + bool showData; +}; + +class ConfigView : public QVBox { + Q_OBJECT + typedef class QVBox Parent; +public: + ConfigView(QWidget* parent, ConfigMainWindow* cview, ConfigSettings* configSettings); + ~ConfigView(void); + static void updateList(ConfigItem* item); + static void updateListAll(void); + +public: + ConfigList* list; + ConfigLineEdit* lineEdit; + + static ConfigView* viewList; + ConfigView* nextView; }; enum colIdx { promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr }; enum listMode { - singleMode, menuMode, symbolMode, fullMode, listMode + singleMode, menuMode, symbolMode, fullMode }; class ConfigList : public QListView { Q_OBJECT typedef class QListView Parent; public: - ConfigList(ConfigView* p, const char *name = 0); + ConfigList(ConfigView* p, ConfigMainWindow* cview, ConfigSettings *configSettings); void reinit(void); ConfigView* parent(void) const { return (ConfigView*)Parent::parent(); } - ConfigItem* findConfigItem(struct menu *); protected: + ConfigMainWindow* cview; + void keyPressEvent(QKeyEvent *e); void contentsMousePressEvent(QMouseEvent *e); void contentsMouseReleaseEvent(QMouseEvent *e); void contentsMouseMoveEvent(QMouseEvent *e); void contentsMouseDoubleClickEvent(QMouseEvent *e); void focusInEvent(QFocusEvent *e); - void contextMenuEvent(QContextMenuEvent *e); - public slots: void setRootMenu(struct menu *menu); @@ -73,12 +83,10 @@ public slots: void setValue(ConfigItem* item, tristate val); void changeValue(ConfigItem* item); void updateSelection(void); - void saveSettings(void); signals: - void menuChanged(struct menu *menu); void menuSelected(struct menu *menu); void parentSelected(void); - void gotFocus(struct menu *); + void gotFocus(void); public: void updateListAll(void) @@ -129,7 +137,6 @@ public slots: struct menu *rootEntry; QColorGroup disabledColorGroup; QColorGroup inactivedColorGroup; - QPopupMenu* headerPopup; private: int colMap[colNr]; @@ -201,7 +208,9 @@ class ConfigLineEdit : public QLineEdit { Q_OBJECT typedef class QLineEdit Parent; public: - ConfigLineEdit(ConfigView* parent); + ConfigLineEdit(ConfigView* parent) + : Parent(parent) + { } ConfigView* parent(void) const { return (ConfigView*)Parent::parent(); @@ -213,104 +222,26 @@ class ConfigLineEdit : public QLineEdit { ConfigItem *item; }; -class ConfigView : public QVBox { - Q_OBJECT - typedef class QVBox Parent; -public: - ConfigView(QWidget* parent, const char *name = 0); - ~ConfigView(void); - static void updateList(ConfigItem* item); - static void updateListAll(void); - - bool showAll(void) const { return list->showAll; } - bool showName(void) const { return list->showName; } - bool showRange(void) const { return list->showRange; } - bool showData(void) const { return list->showData; } -public slots: - void setShowAll(bool); - void setShowName(bool); - void setShowRange(bool); - void setShowData(bool); -signals: - void showAllChanged(bool); - void showNameChanged(bool); - void showRangeChanged(bool); - void showDataChanged(bool); -public: - ConfigList* list; - ConfigLineEdit* lineEdit; - - static ConfigView* viewList; - ConfigView* nextView; -}; - -class ConfigInfoView : public QTextBrowser { - Q_OBJECT - typedef class QTextBrowser Parent; -public: - ConfigInfoView(QWidget* parent, const char *name = 0); - bool showDebug(void) const { return _showDebug; } - -public slots: - void setInfo(struct menu *menu); - void saveSettings(void); - void setSource(const QString& name); - void setShowDebug(bool); - -signals: - void showDebugChanged(bool); - void menuSelected(struct menu *); - -protected: - void symbolInfo(void); - void menuInfo(void); - QString debug_info(struct symbol *sym); - static QString print_filter(const QString &str); - static void expr_print_help(void *data, struct symbol *sym, const char *str); - QPopupMenu* createPopupMenu(const QPoint& pos); - void contentsContextMenuEvent(QContextMenuEvent *e); - - struct symbol *sym; - struct menu *menu; - bool _showDebug; -}; - -class ConfigSearchWindow : public QDialog { - Q_OBJECT - typedef class QDialog Parent; -public: - ConfigSearchWindow(QWidget* parent, const char *name = 0); - -public slots: - void saveSettings(void); - void search(void); - -protected: - QLineEdit* editField; - QPushButton* searchButton; - QSplitter* split; - ConfigView* list; - ConfigInfoView* info; - - struct symbol **result; -}; - class ConfigMainWindow : public QMainWindow { Q_OBJECT public: ConfigMainWindow(void); public slots: + void setHelp(QListViewItem* item); void changeMenu(struct menu *); - void setMenuLink(struct menu *); void listFocusChanged(void); void goBack(void); void loadConfig(void); void saveConfig(void); void saveConfigAs(void); - void searchConfig(void); void showSingleView(void); void showSplitView(void); void showFullView(void); + void setShowAll(bool); + void setShowDebug(bool); + void setShowRange(bool); + void setShowName(bool); + void setShowData(bool); void showIntro(void); void showAbout(void); void saveSettings(void); @@ -318,14 +249,15 @@ public slots: protected: void closeEvent(QCloseEvent *e); - ConfigSearchWindow *searchWindow; ConfigView *menuView; ConfigList *menuList; ConfigView *configView; ConfigList *configList; - ConfigInfoView *helpText; + QTextView *helpText; QToolBar *toolBar; QAction *backAction; QSplitter* split1; QSplitter* split2; + + bool showDebug; }; diff --git a/trunk/scripts/kconfig/symbol.c b/trunk/scripts/kconfig/symbol.c index ee225ced2ce4..3d7877afccd5 100644 --- a/trunk/scripts/kconfig/symbol.c +++ b/trunk/scripts/kconfig/symbol.c @@ -15,15 +15,15 @@ struct symbol symbol_yes = { .name = "y", .curr = { "y", yes }, - .flags = SYMBOL_CONST|SYMBOL_VALID, + .flags = SYMBOL_YES|SYMBOL_VALID, }, symbol_mod = { .name = "m", .curr = { "m", mod }, - .flags = SYMBOL_CONST|SYMBOL_VALID, + .flags = SYMBOL_MOD|SYMBOL_VALID, }, symbol_no = { .name = "n", .curr = { "n", no }, - .flags = SYMBOL_CONST|SYMBOL_VALID, + .flags = SYMBOL_NO|SYMBOL_VALID, }, symbol_empty = { .name = "", .curr = { "", no }, @@ -31,7 +31,6 @@ struct symbol symbol_yes = { }; int sym_change_count; -struct symbol *sym_defconfig_list; struct symbol *modules_sym; tristate modules_val; @@ -228,7 +227,7 @@ static struct symbol *sym_calc_choice(struct symbol *sym) struct expr *e; /* is the user choice visible? */ - def_sym = sym->def[S_DEF_USER].val; + def_sym = sym->user.val; if (def_sym) { sym_calc_visibility(def_sym); if (def_sym->visible != no) @@ -307,7 +306,7 @@ void sym_calc_value(struct symbol *sym) } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) { sym->flags |= SYMBOL_WRITE; if (sym_has_value(sym)) - newval.tri = sym->def[S_DEF_USER].tri; + newval.tri = sym->user.tri; else if (!sym_is_choice(sym)) { prop = sym_get_default_prop(sym); if (prop) @@ -330,7 +329,7 @@ void sym_calc_value(struct symbol *sym) if (sym->visible != no) { sym->flags |= SYMBOL_WRITE; if (sym_has_value(sym)) { - newval.val = sym->def[S_DEF_USER].val; + newval.val = sym->user.val; break; } } @@ -353,13 +352,10 @@ void sym_calc_value(struct symbol *sym) sym->curr.val = sym_calc_choice(sym); sym_validate_range(sym); - if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { + if (memcmp(&oldval, &sym->curr, sizeof(oldval))) sym_set_changed(sym); - if (modules_sym == sym) { - sym_set_all_changed(); - modules_val = modules_sym->curr.tri; - } - } + if (modules_sym == sym) + modules_val = modules_sym->curr.tri; if (sym_is_choice(sym)) { int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); @@ -430,8 +426,8 @@ bool sym_set_tristate_value(struct symbol *sym, tristate val) if (oldval != val && !sym_tristate_within_range(sym, val)) return false; - if (!(sym->flags & SYMBOL_DEF_USER)) { - sym->flags |= SYMBOL_DEF_USER; + if (sym->flags & SYMBOL_NEW) { + sym->flags &= ~SYMBOL_NEW; sym_set_changed(sym); } /* @@ -443,18 +439,21 @@ bool sym_set_tristate_value(struct symbol *sym, tristate val) struct property *prop; struct expr *e; - cs->def[S_DEF_USER].val = sym; - cs->flags |= SYMBOL_DEF_USER; + cs->user.val = sym; + cs->flags &= ~SYMBOL_NEW; prop = sym_get_choice_prop(cs); for (e = prop->expr; e; e = e->left.expr) { if (e->right.sym->visible != no) - e->right.sym->flags |= SYMBOL_DEF_USER; + e->right.sym->flags &= ~SYMBOL_NEW; } } - sym->def[S_DEF_USER].tri = val; - if (oldval != val) + sym->user.tri = val; + if (oldval != val) { sym_clear_all_valid(); + if (sym == modules_sym) + sym_set_all_changed(); + } return true; } @@ -592,20 +591,20 @@ bool sym_set_string_value(struct symbol *sym, const char *newval) if (!sym_string_within_range(sym, newval)) return false; - if (!(sym->flags & SYMBOL_DEF_USER)) { - sym->flags |= SYMBOL_DEF_USER; + if (sym->flags & SYMBOL_NEW) { + sym->flags &= ~SYMBOL_NEW; sym_set_changed(sym); } - oldval = sym->def[S_DEF_USER].val; + oldval = sym->user.val; size = strlen(newval) + 1; if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { size += 2; - sym->def[S_DEF_USER].val = val = malloc(size); + sym->user.val = val = malloc(size); *val++ = '0'; *val++ = 'x'; } else if (!oldval || strcmp(oldval, newval)) - sym->def[S_DEF_USER].val = val = malloc(size); + sym->user.val = val = malloc(size); else return true; @@ -680,6 +679,7 @@ struct symbol *sym_lookup(const char *name, int isconst) memset(symbol, 0, sizeof(*symbol)); symbol->name = new_name; symbol->type = S_UNKNOWN; + symbol->flags = SYMBOL_NEW; if (isconst) symbol->flags |= SYMBOL_CONST; diff --git a/trunk/scripts/kconfig/util.c b/trunk/scripts/kconfig/util.c index e3f28b9d59f4..656d2c87d661 100644 --- a/trunk/scripts/kconfig/util.c +++ b/trunk/scripts/kconfig/util.c @@ -44,9 +44,7 @@ int file_write_dep(const char *name) else fprintf(out, "\t%s\n", file->name); } - fprintf(out, "\ninclude/config/auto.conf: \\\n" - "\t$(deps_config)\n\n" - "$(deps_config): ;\n"); + fprintf(out, "\n.config include/linux/autoconf.h: $(deps_config)\n\n$(deps_config):\n"); fclose(out); rename("..config.tmp", name); return 0; diff --git a/trunk/scripts/kconfig/zconf.gperf b/trunk/scripts/kconfig/zconf.gperf index 9b44c80dd899..b03220600b3a 100644 --- a/trunk/scripts/kconfig/zconf.gperf +++ b/trunk/scripts/kconfig/zconf.gperf @@ -39,8 +39,5 @@ string, T_TYPE, TF_COMMAND, S_STRING select, T_SELECT, TF_COMMAND enable, T_SELECT, TF_COMMAND range, T_RANGE, TF_COMMAND -option, T_OPTION, TF_COMMAND on, T_ON, TF_PARAM -modules, T_OPT_MODULES, TF_OPTION -defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION %% diff --git a/trunk/scripts/kconfig/zconf.hash.c_shipped b/trunk/scripts/kconfig/zconf.hash.c_shipped index 47c8b5babf34..345f0fc07ca3 100644 --- a/trunk/scripts/kconfig/zconf.hash.c_shipped +++ b/trunk/scripts/kconfig/zconf.hash.c_shipped @@ -53,10 +53,10 @@ kconf_id_hash (register const char *str, register unsigned int len) 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 25, 30, 15, - 0, 15, 0, 47, 5, 15, 47, 47, 30, 20, - 5, 0, 25, 15, 0, 0, 10, 35, 47, 47, - 5, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 25, 10, 15, + 0, 0, 5, 47, 0, 0, 47, 47, 0, 10, + 0, 20, 20, 20, 5, 0, 0, 20, 47, 47, + 20, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, @@ -88,75 +88,69 @@ kconf_id_hash (register const char *str, register unsigned int len) struct kconf_id_strings_t { - char kconf_id_strings_str2[sizeof("on")]; - char kconf_id_strings_str6[sizeof("string")]; - char kconf_id_strings_str7[sizeof("default")]; - char kconf_id_strings_str8[sizeof("def_bool")]; + char kconf_id_strings_str2[sizeof("if")]; + char kconf_id_strings_str3[sizeof("int")]; + char kconf_id_strings_str4[sizeof("help")]; + char kconf_id_strings_str5[sizeof("endif")]; + char kconf_id_strings_str6[sizeof("select")]; + char kconf_id_strings_str7[sizeof("endmenu")]; + char kconf_id_strings_str8[sizeof("tristate")]; + char kconf_id_strings_str9[sizeof("endchoice")]; char kconf_id_strings_str10[sizeof("range")]; - char kconf_id_strings_str11[sizeof("def_boolean")]; - char kconf_id_strings_str12[sizeof("def_tristate")]; - char kconf_id_strings_str13[sizeof("hex")]; - char kconf_id_strings_str14[sizeof("defconfig_list")]; - char kconf_id_strings_str16[sizeof("option")]; - char kconf_id_strings_str17[sizeof("if")]; - char kconf_id_strings_str18[sizeof("optional")]; - char kconf_id_strings_str20[sizeof("endif")]; - char kconf_id_strings_str21[sizeof("choice")]; - char kconf_id_strings_str22[sizeof("endmenu")]; - char kconf_id_strings_str23[sizeof("requires")]; - char kconf_id_strings_str24[sizeof("endchoice")]; - char kconf_id_strings_str26[sizeof("config")]; - char kconf_id_strings_str27[sizeof("modules")]; - char kconf_id_strings_str28[sizeof("int")]; - char kconf_id_strings_str29[sizeof("menu")]; - char kconf_id_strings_str31[sizeof("prompt")]; - char kconf_id_strings_str32[sizeof("depends")]; - char kconf_id_strings_str33[sizeof("tristate")]; + char kconf_id_strings_str11[sizeof("string")]; + char kconf_id_strings_str12[sizeof("default")]; + char kconf_id_strings_str13[sizeof("def_bool")]; + char kconf_id_strings_str14[sizeof("menu")]; + char kconf_id_strings_str16[sizeof("def_boolean")]; + char kconf_id_strings_str17[sizeof("def_tristate")]; + char kconf_id_strings_str18[sizeof("mainmenu")]; + char kconf_id_strings_str20[sizeof("menuconfig")]; + char kconf_id_strings_str21[sizeof("config")]; + char kconf_id_strings_str22[sizeof("on")]; + char kconf_id_strings_str23[sizeof("hex")]; + char kconf_id_strings_str26[sizeof("source")]; + char kconf_id_strings_str27[sizeof("depends")]; + char kconf_id_strings_str28[sizeof("optional")]; + char kconf_id_strings_str31[sizeof("enable")]; + char kconf_id_strings_str32[sizeof("comment")]; + char kconf_id_strings_str33[sizeof("requires")]; char kconf_id_strings_str34[sizeof("bool")]; - char kconf_id_strings_str35[sizeof("menuconfig")]; - char kconf_id_strings_str36[sizeof("select")]; char kconf_id_strings_str37[sizeof("boolean")]; - char kconf_id_strings_str39[sizeof("help")]; - char kconf_id_strings_str41[sizeof("source")]; - char kconf_id_strings_str42[sizeof("comment")]; - char kconf_id_strings_str43[sizeof("mainmenu")]; - char kconf_id_strings_str46[sizeof("enable")]; + char kconf_id_strings_str41[sizeof("choice")]; + char kconf_id_strings_str46[sizeof("prompt")]; }; static struct kconf_id_strings_t kconf_id_strings_contents = { - "on", + "if", + "int", + "help", + "endif", + "select", + "endmenu", + "tristate", + "endchoice", + "range", "string", "default", "def_bool", - "range", + "menu", "def_boolean", "def_tristate", + "mainmenu", + "menuconfig", + "config", + "on", "hex", - "defconfig_list", - "option", - "if", + "source", + "depends", "optional", - "endif", - "choice", - "endmenu", + "enable", + "comment", "requires", - "endchoice", - "config", - "modules", - "int", - "menu", - "prompt", - "depends", - "tristate", "bool", - "menuconfig", - "select", "boolean", - "help", - "source", - "comment", - "mainmenu", - "enable" + "choice", + "prompt" }; #define kconf_id_strings ((const char *) &kconf_id_strings_contents) #ifdef __GNUC__ @@ -167,9 +161,9 @@ kconf_id_lookup (register const char *str, register unsigned int len) { enum { - TOTAL_KEYWORDS = 33, + TOTAL_KEYWORDS = 30, MIN_WORD_LENGTH = 2, - MAX_WORD_LENGTH = 14, + MAX_WORD_LENGTH = 12, MIN_HASH_VALUE = 2, MAX_HASH_VALUE = 46 }; @@ -177,48 +171,43 @@ kconf_id_lookup (register const char *str, register unsigned int len) static struct kconf_id wordlist[] = { {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM}, - {-1}, {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_TYPE, TF_COMMAND, S_STRING}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, - {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_IF, TF_COMMAND|TF_PARAM}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_TYPE, TF_COMMAND, S_INT}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str4, T_HELP, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_SELECT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TYPE, TF_COMMAND, S_TRISTATE}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_TRISTATE}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_TYPE, TF_COMMAND, S_HEX}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_OPT_DEFCONFIG_LIST,TF_OPTION}, - {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_OPTION, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_IF, TF_COMMAND|TF_PARAM}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPTIONAL, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_TYPE, TF_COMMAND, S_STRING}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_MENU, TF_COMMAND}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20, T_ENDIF, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_CHOICE, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ENDMENU, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_REQUIRES, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str24, T_ENDCHOICE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_MAINMENU, TF_COMMAND}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_CONFIG, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_INT}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND}, - {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_PROMPT, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_DEPENDS, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_TYPE, TF_COMMAND, S_TRISTATE}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20, T_MENUCONFIG, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_CONFIG, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ON, TF_PARAM}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_HEX}, + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SOURCE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_DEPENDS, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_OPTIONAL, TF_COMMAND}, + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_REQUIRES, TF_COMMAND}, {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str34, T_TYPE, TF_COMMAND, S_BOOLEAN}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_MENUCONFIG, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_SELECT, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_TYPE, TF_COMMAND, S_BOOLEAN}, - {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39, T_HELP, TF_COMMAND}, - {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SOURCE, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_COMMENT, TF_COMMAND}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43, T_MAINMENU, TF_COMMAND}, {-1}, {-1}, - {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_SELECT, TF_COMMAND} + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {-1}, {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_CHOICE, TF_COMMAND}, + {-1}, {-1}, {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_PROMPT, TF_COMMAND} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/trunk/scripts/kconfig/zconf.tab.c_shipped b/trunk/scripts/kconfig/zconf.tab.c_shipped index 2fb0a4fc61d0..ea7755da82f5 100644 --- a/trunk/scripts/kconfig/zconf.tab.c_shipped +++ b/trunk/scripts/kconfig/zconf.tab.c_shipped @@ -1,7 +1,7 @@ -/* A Bison parser, made by GNU Bison 2.1. */ +/* A Bison parser, made by GNU Bison 2.0. */ /* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,8 +15,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. @@ -36,9 +36,6 @@ /* Identify Bison output. */ #define YYBISON 1 -/* Bison version. */ -#define YYBISON_VERSION "2.1" - /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -85,21 +82,19 @@ T_DEFAULT = 276, T_SELECT = 277, T_RANGE = 278, - T_OPTION = 279, - T_ON = 280, - T_WORD = 281, - T_WORD_QUOTE = 282, - T_UNEQUAL = 283, - T_CLOSE_PAREN = 284, - T_OPEN_PAREN = 285, - T_EOL = 286, - T_OR = 287, - T_AND = 288, - T_EQUAL = 289, - T_NOT = 290 + T_ON = 279, + T_WORD = 280, + T_WORD_QUOTE = 281, + T_UNEQUAL = 282, + T_CLOSE_PAREN = 283, + T_OPEN_PAREN = 284, + T_EOL = 285, + T_OR = 286, + T_AND = 287, + T_EQUAL = 288, + T_NOT = 289 }; #endif -/* Tokens. */ #define T_MAINMENU 258 #define T_MENU 259 #define T_ENDMENU 260 @@ -121,18 +116,17 @@ #define T_DEFAULT 276 #define T_SELECT 277 #define T_RANGE 278 -#define T_OPTION 279 -#define T_ON 280 -#define T_WORD 281 -#define T_WORD_QUOTE 282 -#define T_UNEQUAL 283 -#define T_CLOSE_PAREN 284 -#define T_OPEN_PAREN 285 -#define T_EOL 286 -#define T_OR 287 -#define T_AND 288 -#define T_EQUAL 289 -#define T_NOT 290 +#define T_ON 279 +#define T_WORD 280 +#define T_WORD_QUOTE 281 +#define T_UNEQUAL 282 +#define T_CLOSE_PAREN 283 +#define T_OPEN_PAREN 284 +#define T_EOL 285 +#define T_OR 286 +#define T_AND 287 +#define T_EQUAL 288 +#define T_NOT 289 @@ -193,11 +187,6 @@ static struct menu *current_menu, *current_entry; # define YYERROR_VERBOSE 0 #endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 -#endif - #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) typedef union YYSTYPE { @@ -208,7 +197,7 @@ typedef union YYSTYPE { struct menu *menu; struct kconf_id *id; } YYSTYPE; -/* Line 196 of yacc.c. */ +/* Line 190 of yacc.c. */ # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -220,36 +209,17 @@ typedef union YYSTYPE { /* Copy the second part of user declarations. */ -/* Line 219 of yacc.c. */ +/* Line 213 of yacc.c. */ -#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) -# define YYSIZE_T __SIZE_TYPE__ -#endif -#if ! defined (YYSIZE_T) && defined (size_t) -# define YYSIZE_T size_t -#endif -#if ! defined (YYSIZE_T) && (defined (__STDC__) || defined (__cplusplus)) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -#endif -#if ! defined (YYSIZE_T) -# define YYSIZE_T unsigned int -#endif +#if ! defined (yyoverflow) || YYERROR_VERBOSE -#ifndef YY_ -# if YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) -# endif +# ifndef YYFREE +# define YYFREE free # endif -# ifndef YY_ -# define YY_(msgid) msgid +# ifndef YYMALLOC +# define YYMALLOC malloc # endif -#endif - -#if ! defined (yyoverflow) || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -259,10 +229,6 @@ typedef union YYSTYPE { # define YYSTACK_ALLOC __builtin_alloca # else # define YYSTACK_ALLOC alloca -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYINCLUDED_STDLIB_H -# endif # endif # endif # endif @@ -270,39 +236,13 @@ typedef union YYSTYPE { # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2005 */ -# endif # else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1) -# endif -# ifdef __cplusplus -extern "C" { -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \ - && (defined (__STDC__) || defined (__cplusplus))) -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \ - && (defined (__STDC__) || defined (__cplusplus))) -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifdef __cplusplus -} -# endif # endif #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ @@ -337,7 +277,7 @@ union yyalloc # define YYCOPY(To, From, Count) \ do \ { \ - YYSIZE_T yyi; \ + register YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ @@ -372,22 +312,22 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 275 +#define YYLAST 264 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 36 +#define YYNTOKENS 35 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 45 +#define YYNNTS 42 /* YYNRULES -- Number of rules. */ -#define YYNRULES 110 +#define YYNRULES 104 /* YYNRULES -- Number of states. */ -#define YYNSTATES 183 +#define YYNSTATES 175 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 290 +#define YYMAXUTOK 289 -#define YYTRANSLATE(YYX) \ +#define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ @@ -421,8 +361,7 @@ static const unsigned char yytranslate[] = 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35 + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34 }; #if YYDEBUG @@ -433,75 +372,72 @@ static const unsigned short int yyprhs[] = 0, 0, 3, 5, 6, 9, 12, 15, 20, 23, 28, 33, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 67, 70, 74, 77, - 81, 84, 85, 88, 91, 94, 97, 100, 103, 107, - 112, 117, 122, 128, 132, 133, 137, 138, 141, 144, - 147, 149, 153, 154, 157, 160, 163, 166, 169, 174, - 178, 181, 186, 187, 190, 194, 196, 200, 201, 204, - 207, 210, 214, 217, 219, 223, 224, 227, 230, 233, - 237, 241, 244, 247, 250, 251, 254, 257, 260, 265, - 269, 273, 274, 277, 279, 281, 284, 287, 290, 292, - 295, 296, 299, 301, 305, 309, 313, 316, 320, 324, - 326 + 81, 84, 85, 88, 91, 94, 97, 100, 104, 109, + 114, 119, 125, 128, 131, 133, 137, 138, 141, 144, + 147, 150, 153, 158, 162, 165, 170, 171, 174, 178, + 180, 184, 185, 188, 191, 194, 198, 201, 203, 207, + 208, 211, 214, 217, 221, 225, 228, 231, 234, 235, + 238, 241, 244, 249, 253, 257, 258, 261, 263, 265, + 268, 271, 274, 276, 279, 280, 283, 285, 289, 293, + 297, 300, 304, 308, 310 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yysigned_char yyrhs[] = { - 37, 0, -1, 38, -1, -1, 38, 40, -1, 38, - 54, -1, 38, 65, -1, 38, 3, 75, 77, -1, - 38, 76, -1, 38, 26, 1, 31, -1, 38, 39, - 1, 31, -1, 38, 1, 31, -1, 16, -1, 19, + 36, 0, -1, 37, -1, -1, 37, 39, -1, 37, + 50, -1, 37, 61, -1, 37, 3, 71, 73, -1, + 37, 72, -1, 37, 25, 1, 30, -1, 37, 38, + 1, 30, -1, 37, 1, 30, -1, 16, -1, 19, -1, 20, -1, 22, -1, 18, -1, 23, -1, 21, - -1, 31, -1, 60, -1, 69, -1, 43, -1, 45, - -1, 67, -1, 26, 1, 31, -1, 1, 31, -1, - 10, 26, 31, -1, 42, 46, -1, 11, 26, 31, - -1, 44, 46, -1, -1, 46, 47, -1, 46, 48, - -1, 46, 73, -1, 46, 71, -1, 46, 41, -1, - 46, 31, -1, 20, 74, 31, -1, 19, 75, 78, - 31, -1, 21, 79, 78, 31, -1, 22, 26, 78, - 31, -1, 23, 80, 80, 78, 31, -1, 24, 49, - 31, -1, -1, 49, 26, 50, -1, -1, 34, 75, - -1, 7, 31, -1, 51, 55, -1, 76, -1, 52, - 57, 53, -1, -1, 55, 56, -1, 55, 73, -1, - 55, 71, -1, 55, 31, -1, 55, 41, -1, 19, - 75, 78, 31, -1, 20, 74, 31, -1, 18, 31, - -1, 21, 26, 78, 31, -1, -1, 57, 40, -1, - 14, 79, 77, -1, 76, -1, 58, 61, 59, -1, - -1, 61, 40, -1, 61, 65, -1, 61, 54, -1, - 4, 75, 31, -1, 62, 72, -1, 76, -1, 63, - 66, 64, -1, -1, 66, 40, -1, 66, 65, -1, - 66, 54, -1, 6, 75, 31, -1, 9, 75, 31, - -1, 68, 72, -1, 12, 31, -1, 70, 13, -1, - -1, 72, 73, -1, 72, 31, -1, 72, 41, -1, - 16, 25, 79, 31, -1, 16, 79, 31, -1, 17, - 79, 31, -1, -1, 75, 78, -1, 26, -1, 27, - -1, 5, 31, -1, 8, 31, -1, 15, 31, -1, - 31, -1, 77, 31, -1, -1, 14, 79, -1, 80, - -1, 80, 34, 80, -1, 80, 28, 80, -1, 30, - 79, 29, -1, 35, 79, -1, 79, 32, 79, -1, - 79, 33, 79, -1, 26, -1, 27, -1 + -1, 30, -1, 56, -1, 65, -1, 42, -1, 44, + -1, 63, -1, 25, 1, 30, -1, 1, 30, -1, + 10, 25, 30, -1, 41, 45, -1, 11, 25, 30, + -1, 43, 45, -1, -1, 45, 46, -1, 45, 69, + -1, 45, 67, -1, 45, 40, -1, 45, 30, -1, + 20, 70, 30, -1, 19, 71, 74, 30, -1, 21, + 75, 74, 30, -1, 22, 25, 74, 30, -1, 23, + 76, 76, 74, 30, -1, 7, 30, -1, 47, 51, + -1, 72, -1, 48, 53, 49, -1, -1, 51, 52, + -1, 51, 69, -1, 51, 67, -1, 51, 30, -1, + 51, 40, -1, 19, 71, 74, 30, -1, 20, 70, + 30, -1, 18, 30, -1, 21, 25, 74, 30, -1, + -1, 53, 39, -1, 14, 75, 73, -1, 72, -1, + 54, 57, 55, -1, -1, 57, 39, -1, 57, 61, + -1, 57, 50, -1, 4, 71, 30, -1, 58, 68, + -1, 72, -1, 59, 62, 60, -1, -1, 62, 39, + -1, 62, 61, -1, 62, 50, -1, 6, 71, 30, + -1, 9, 71, 30, -1, 64, 68, -1, 12, 30, + -1, 66, 13, -1, -1, 68, 69, -1, 68, 30, + -1, 68, 40, -1, 16, 24, 75, 30, -1, 16, + 75, 30, -1, 17, 75, 30, -1, -1, 71, 74, + -1, 25, -1, 26, -1, 5, 30, -1, 8, 30, + -1, 15, 30, -1, 30, -1, 73, 30, -1, -1, + 14, 75, -1, 76, -1, 76, 33, 76, -1, 76, + 27, 76, -1, 29, 75, 28, -1, 34, 75, -1, + 75, 31, 75, -1, 75, 32, 75, -1, 25, -1, + 26, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const unsigned short int yyrline[] = { - 0, 105, 105, 107, 109, 110, 111, 112, 113, 114, - 115, 119, 123, 123, 123, 123, 123, 123, 123, 127, - 128, 129, 130, 131, 132, 136, 137, 143, 151, 157, - 165, 175, 177, 178, 179, 180, 181, 182, 185, 193, - 199, 209, 215, 221, 224, 226, 237, 238, 243, 252, - 257, 265, 268, 270, 271, 272, 273, 274, 277, 283, - 294, 300, 310, 312, 317, 325, 333, 336, 338, 339, - 340, 345, 352, 357, 365, 368, 370, 371, 372, 375, - 383, 390, 397, 403, 410, 412, 413, 414, 417, 422, - 427, 435, 437, 442, 443, 446, 447, 448, 452, 453, - 456, 457, 460, 461, 462, 463, 464, 465, 466, 469, - 470 + 0, 103, 103, 105, 107, 108, 109, 110, 111, 112, + 113, 117, 121, 121, 121, 121, 121, 121, 121, 125, + 126, 127, 128, 129, 130, 134, 135, 141, 149, 155, + 163, 173, 175, 176, 177, 178, 179, 182, 190, 196, + 206, 212, 220, 229, 234, 242, 245, 247, 248, 249, + 250, 251, 254, 260, 271, 277, 287, 289, 294, 302, + 310, 313, 315, 316, 317, 322, 329, 334, 342, 345, + 347, 348, 349, 352, 360, 367, 374, 380, 387, 389, + 390, 391, 394, 399, 404, 412, 414, 419, 420, 423, + 424, 425, 429, 430, 433, 434, 437, 438, 439, 440, + 441, 442, 443, 446, 447 }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { @@ -509,18 +445,17 @@ static const char *const yytname[] = "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", - "T_SELECT", "T_RANGE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", - "T_UNEQUAL", "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", - "T_EQUAL", "T_NOT", "$accept", "input", "stmt_list", "option_name", - "common_stmt", "option_error", "config_entry_start", "config_stmt", + "T_SELECT", "T_RANGE", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", + "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL", + "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt", + "option_error", "config_entry_start", "config_stmt", "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", - "config_option", "symbol_option", "symbol_option_list", - "symbol_option_arg", "choice", "choice_entry", "choice_end", - "choice_stmt", "choice_option_list", "choice_option", "choice_block", - "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry", - "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment", - "comment_stmt", "help_start", "help", "depends_list", "depends", - "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol", 0 + "config_option", "choice", "choice_entry", "choice_end", "choice_stmt", + "choice_option_list", "choice_option", "choice_block", "if_entry", + "if_end", "if_stmt", "if_block", "menu", "menu_entry", "menu_end", + "menu_stmt", "menu_block", "source_stmt", "comment", "comment_stmt", + "help_start", "help", "depends_list", "depends", "prompt_stmt_opt", + "prompt", "end", "nl", "if_expr", "expr", "symbol", 0 }; #endif @@ -532,25 +467,24 @@ static const unsigned short int yytoknum[] = 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290 + 285, 286, 287, 288, 289 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const unsigned char yyr1[] = { - 0, 36, 37, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 39, 39, 39, 39, 39, 39, 39, 40, - 40, 40, 40, 40, 40, 41, 41, 42, 43, 44, - 45, 46, 46, 46, 46, 46, 46, 46, 47, 47, - 47, 47, 47, 48, 49, 49, 50, 50, 51, 52, - 53, 54, 55, 55, 55, 55, 55, 55, 56, 56, - 56, 56, 57, 57, 58, 59, 60, 61, 61, 61, - 61, 62, 63, 64, 65, 66, 66, 66, 66, 67, - 68, 69, 70, 71, 72, 72, 72, 72, 73, 73, - 73, 74, 74, 75, 75, 76, 76, 76, 77, 77, - 78, 78, 79, 79, 79, 79, 79, 79, 79, 80, - 80 + 0, 35, 36, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 38, 38, 38, 38, 38, 38, 38, 39, + 39, 39, 39, 39, 39, 40, 40, 41, 42, 43, + 44, 45, 45, 45, 45, 45, 45, 46, 46, 46, + 46, 46, 47, 48, 49, 50, 51, 51, 51, 51, + 51, 51, 52, 52, 52, 52, 53, 53, 54, 55, + 56, 57, 57, 57, 57, 58, 59, 60, 61, 62, + 62, 62, 62, 63, 64, 65, 66, 67, 68, 68, + 68, 68, 69, 69, 69, 70, 70, 71, 71, 72, + 72, 72, 73, 73, 74, 74, 75, 75, 75, 75, + 75, 75, 75, 76, 76 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -559,15 +493,14 @@ static const unsigned char yyr2[] = 0, 2, 1, 0, 2, 2, 2, 4, 2, 4, 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 3, 2, 3, - 2, 0, 2, 2, 2, 2, 2, 2, 3, 4, - 4, 4, 5, 3, 0, 3, 0, 2, 2, 2, - 1, 3, 0, 2, 2, 2, 2, 2, 4, 3, - 2, 4, 0, 2, 3, 1, 3, 0, 2, 2, - 2, 3, 2, 1, 3, 0, 2, 2, 2, 3, - 3, 2, 2, 2, 0, 2, 2, 2, 4, 3, - 3, 0, 2, 1, 1, 2, 2, 2, 1, 2, - 0, 2, 1, 3, 3, 3, 2, 3, 3, 1, - 1 + 2, 0, 2, 2, 2, 2, 2, 3, 4, 4, + 4, 5, 2, 2, 1, 3, 0, 2, 2, 2, + 2, 2, 4, 3, 2, 4, 0, 2, 3, 1, + 3, 0, 2, 2, 2, 3, 2, 1, 3, 0, + 2, 2, 2, 3, 3, 2, 2, 2, 0, 2, + 2, 2, 4, 3, 3, 0, 2, 1, 1, 2, + 2, 2, 1, 2, 0, 2, 1, 3, 3, 3, + 2, 3, 3, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -578,164 +511,175 @@ static const unsigned char yydefact[] = 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 16, 13, 14, 18, 15, 17, 0, 19, 0, 4, 31, 22, 31, - 23, 52, 62, 5, 67, 20, 84, 75, 6, 24, - 84, 21, 8, 11, 93, 94, 0, 0, 95, 0, - 48, 96, 0, 0, 0, 109, 110, 0, 0, 0, - 102, 97, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 98, 7, 71, 79, 80, 27, 29, 0, - 106, 0, 0, 64, 0, 0, 9, 10, 0, 0, - 0, 0, 0, 91, 0, 0, 0, 44, 0, 37, - 36, 32, 33, 0, 35, 34, 0, 0, 91, 0, - 56, 57, 53, 55, 54, 63, 51, 50, 68, 70, - 66, 69, 65, 86, 87, 85, 76, 78, 74, 77, - 73, 99, 105, 107, 108, 104, 103, 26, 82, 0, - 0, 0, 100, 0, 100, 100, 100, 0, 0, 0, - 83, 60, 100, 0, 100, 0, 89, 90, 0, 0, - 38, 92, 0, 0, 100, 46, 43, 25, 0, 59, - 0, 88, 101, 39, 40, 41, 0, 0, 45, 58, - 61, 42, 47 + 23, 46, 56, 5, 61, 20, 78, 69, 6, 24, + 78, 21, 8, 11, 87, 88, 0, 0, 89, 0, + 42, 90, 0, 0, 0, 103, 104, 0, 0, 0, + 96, 91, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 92, 7, 65, 73, 74, 27, 29, 0, + 100, 0, 0, 58, 0, 0, 9, 10, 0, 0, + 0, 0, 0, 85, 0, 0, 0, 0, 36, 35, + 32, 0, 34, 33, 0, 0, 85, 0, 50, 51, + 47, 49, 48, 57, 45, 44, 62, 64, 60, 63, + 59, 80, 81, 79, 70, 72, 68, 71, 67, 93, + 99, 101, 102, 98, 97, 26, 76, 0, 0, 0, + 94, 0, 94, 94, 94, 0, 0, 77, 54, 94, + 0, 94, 0, 83, 84, 0, 0, 37, 86, 0, + 0, 94, 25, 0, 53, 0, 82, 95, 38, 39, + 40, 0, 52, 55, 41 }; /* YYDEFGOTO[NTERM-NUM]. */ static const short int yydefgoto[] = { - -1, 1, 2, 25, 26, 100, 27, 28, 29, 30, - 64, 101, 102, 148, 178, 31, 32, 116, 33, 66, - 112, 67, 34, 120, 35, 68, 36, 37, 128, 38, - 70, 39, 40, 41, 103, 104, 69, 105, 143, 144, - 42, 73, 159, 59, 60 + -1, 1, 2, 25, 26, 99, 27, 28, 29, 30, + 64, 100, 31, 32, 114, 33, 66, 110, 67, 34, + 118, 35, 68, 36, 37, 126, 38, 70, 39, 40, + 41, 101, 102, 69, 103, 141, 142, 42, 73, 156, + 59, 60 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -135 +#define YYPACT_NINF -78 static const short int yypact[] = { - -135, 2, 170, -135, -14, 56, 56, -8, 56, 24, - 67, 56, 7, 14, 62, 97, -135, -135, -135, -135, - -135, -135, -135, 156, -135, 166, -135, -135, -135, -135, - -135, -135, -135, -135, -135, -135, -135, -135, -135, -135, - -135, -135, -135, -135, -135, -135, 138, 151, -135, 152, - -135, -135, 163, 167, 176, -135, -135, 62, 62, 185, - -19, -135, 188, 190, 42, 103, 194, 85, 70, 222, - 70, 132, -135, 191, -135, -135, -135, -135, -135, 127, - -135, 62, 62, 191, 104, 104, -135, -135, 193, 203, - 9, 62, 56, 56, 62, 161, 104, -135, 196, -135, - -135, -135, -135, 233, -135, -135, 204, 56, 56, 221, - -135, -135, -135, -135, -135, -135, -135, -135, -135, -135, - -135, -135, -135, -135, -135, -135, -135, -135, -135, -135, - -135, -135, -135, 219, -135, -135, -135, -135, -135, 62, - 209, 212, 240, 224, 240, -1, 240, 104, 41, 225, - -135, -135, 240, 226, 240, 218, -135, -135, 62, 227, - -135, -135, 228, 229, 240, 230, -135, -135, 231, -135, - 232, -135, 112, -135, -135, -135, 234, 56, -135, -135, - -135, -135, -135 + -78, 2, 159, -78, -21, 0, 0, -12, 0, 1, + 4, 0, 27, 38, 60, 58, -78, -78, -78, -78, + -78, -78, -78, 100, -78, 104, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, 86, 113, -78, 114, + -78, -78, 125, 127, 128, -78, -78, 60, 60, 210, + 65, -78, 141, 142, 39, 103, 182, 200, 6, 66, + 6, 131, -78, 146, -78, -78, -78, -78, -78, 196, + -78, 60, 60, 146, 40, 40, -78, -78, 155, 156, + -2, 60, 0, 0, 60, 105, 40, 194, -78, -78, + -78, 206, -78, -78, 183, 0, 0, 195, -78, -78, + -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, + -78, 197, -78, -78, -78, -78, -78, 60, 213, 216, + 212, 203, 212, 190, 212, 40, 208, -78, -78, 212, + 222, 212, 219, -78, -78, 60, 223, -78, -78, 224, + 225, 212, -78, 226, -78, 227, -78, 47, -78, -78, + -78, 228, -78, -78, -78 }; /* YYPGOTO[NTERM-NUM]. */ static const short int yypgoto[] = { - -135, -135, -135, -135, 94, -45, -135, -135, -135, -135, - 237, -135, -135, -135, -135, -135, -135, -135, -54, -135, - -135, -135, -135, -135, -135, -135, -135, -135, -135, 1, - -135, -135, -135, -135, -135, 195, 235, -44, 159, -5, - 98, 210, -134, -53, -77 + -78, -78, -78, -78, 164, -36, -78, -78, -78, -78, + 230, -78, -78, -78, -78, 29, -78, -78, -78, -78, + -78, -78, -78, -78, -78, -78, 59, -78, -78, -78, + -78, -78, 198, 220, 24, 157, -5, 169, 202, 74, + -53, -77 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -82 +#define YYTABLE_NINF -76 static const short int yytable[] = { - 46, 47, 3, 49, 79, 80, 52, 135, 136, 84, - 161, 162, 163, 158, 119, 85, 127, 43, 168, 147, - 170, 111, 114, 48, 124, 125, 124, 125, 133, 134, - 176, 81, 82, 53, 139, 55, 56, 140, 141, 57, - 54, 145, -28, 88, 58, -28, -28, -28, -28, -28, - -28, -28, -28, -28, 89, 50, -28, -28, 90, 91, - -28, 92, 93, 94, 95, 96, 97, 165, 98, 121, - 164, 129, 166, 99, 6, 7, 8, 9, 10, 11, - 12, 13, 44, 45, 14, 15, 155, 142, 55, 56, - 7, 8, 57, 10, 11, 12, 13, 58, 51, 14, - 15, 24, 152, -30, 88, 172, -30, -30, -30, -30, - -30, -30, -30, -30, -30, 89, 24, -30, -30, 90, - 91, -30, 92, 93, 94, 95, 96, 97, 61, 98, - 55, 56, -81, 88, 99, -81, -81, -81, -81, -81, - -81, -81, -81, -81, 81, 82, -81, -81, 90, 91, - -81, -81, -81, -81, -81, -81, 132, 62, 98, 81, - 82, 115, 118, 123, 126, 117, 122, 63, 130, 72, - -2, 4, 182, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 74, 75, 14, 15, 16, 146, 17, 18, - 19, 20, 21, 22, 76, 88, 23, 149, 77, -49, - -49, 24, -49, -49, -49, -49, 89, 78, -49, -49, - 90, 91, 106, 107, 108, 109, 72, 81, 82, 86, - 98, 87, 131, 88, 137, 110, -72, -72, -72, -72, - -72, -72, -72, -72, 138, 151, -72, -72, 90, 91, - 156, 81, 82, 157, 81, 82, 150, 154, 98, 171, - 81, 82, 82, 123, 158, 160, 167, 169, 173, 174, - 175, 113, 179, 180, 177, 181, 65, 153, 0, 83, - 0, 0, 0, 0, 0, 71 + 46, 47, 3, 49, 79, 80, 52, 133, 134, 43, + 6, 7, 8, 9, 10, 11, 12, 13, 48, 145, + 14, 15, 137, 55, 56, 44, 45, 57, 131, 132, + 109, 50, 58, 122, 51, 122, 24, 138, 139, -28, + 88, 143, -28, -28, -28, -28, -28, -28, -28, -28, + -28, 89, 53, -28, -28, 90, 91, -28, 92, 93, + 94, 95, 96, 54, 97, 55, 56, 88, 161, 98, + -66, -66, -66, -66, -66, -66, -66, -66, 81, 82, + -66, -66, 90, 91, 152, 55, 56, 140, 61, 57, + 112, 97, 84, 123, 58, 123, 121, 117, 85, 125, + 149, 62, 167, -30, 88, 63, -30, -30, -30, -30, + -30, -30, -30, -30, -30, 89, 72, -30, -30, 90, + 91, -30, 92, 93, 94, 95, 96, 119, 97, 127, + 144, -75, 88, 98, -75, -75, -75, -75, -75, -75, + -75, -75, -75, 74, 75, -75, -75, 90, 91, -75, + -75, -75, -75, -75, -75, 76, 97, 77, 78, -2, + 4, 121, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 86, 87, 14, 15, 16, 129, 17, 18, 19, + 20, 21, 22, 88, 23, 135, 136, -43, -43, 24, + -43, -43, -43, -43, 89, 146, -43, -43, 90, 91, + 104, 105, 106, 107, 155, 7, 8, 97, 10, 11, + 12, 13, 108, 148, 14, 15, 158, 159, 160, 147, + 151, 81, 82, 163, 130, 165, 155, 81, 82, 82, + 24, 113, 116, 157, 124, 171, 115, 120, 162, 128, + 72, 81, 82, 153, 81, 82, 154, 81, 82, 166, + 81, 82, 164, 168, 169, 170, 172, 173, 174, 65, + 71, 83, 0, 150, 111 }; static const short int yycheck[] = { - 5, 6, 0, 8, 57, 58, 11, 84, 85, 28, - 144, 145, 146, 14, 68, 34, 70, 31, 152, 96, - 154, 66, 66, 31, 69, 69, 71, 71, 81, 82, - 164, 32, 33, 26, 25, 26, 27, 90, 91, 30, - 26, 94, 0, 1, 35, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 31, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 26, 26, 68, - 147, 70, 31, 31, 4, 5, 6, 7, 8, 9, - 10, 11, 26, 27, 14, 15, 139, 92, 26, 27, - 5, 6, 30, 8, 9, 10, 11, 35, 31, 14, - 15, 31, 107, 0, 1, 158, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 31, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 31, 26, - 26, 27, 0, 1, 31, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 32, 33, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 29, 1, 26, 32, - 33, 67, 68, 31, 70, 67, 68, 1, 70, 31, - 0, 1, 177, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 31, 31, 14, 15, 16, 26, 18, 19, - 20, 21, 22, 23, 31, 1, 26, 1, 31, 5, - 6, 31, 8, 9, 10, 11, 12, 31, 14, 15, - 16, 17, 18, 19, 20, 21, 31, 32, 33, 31, - 26, 31, 31, 1, 31, 31, 4, 5, 6, 7, - 8, 9, 10, 11, 31, 31, 14, 15, 16, 17, - 31, 32, 33, 31, 32, 33, 13, 26, 26, 31, - 32, 33, 33, 31, 14, 31, 31, 31, 31, 31, - 31, 66, 31, 31, 34, 31, 29, 108, -1, 59, - -1, -1, -1, -1, -1, 40 + 5, 6, 0, 8, 57, 58, 11, 84, 85, 30, + 4, 5, 6, 7, 8, 9, 10, 11, 30, 96, + 14, 15, 24, 25, 26, 25, 26, 29, 81, 82, + 66, 30, 34, 69, 30, 71, 30, 90, 91, 0, + 1, 94, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 25, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 25, 25, 25, 26, 1, 145, 30, + 4, 5, 6, 7, 8, 9, 10, 11, 31, 32, + 14, 15, 16, 17, 137, 25, 26, 92, 30, 29, + 66, 25, 27, 69, 34, 71, 30, 68, 33, 70, + 105, 1, 155, 0, 1, 1, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 30, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 68, 25, 70, + 25, 0, 1, 30, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 30, 30, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 30, 25, 30, 30, 0, + 1, 30, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 30, 30, 14, 15, 16, 30, 18, 19, 20, + 21, 22, 23, 1, 25, 30, 30, 5, 6, 30, + 8, 9, 10, 11, 12, 1, 14, 15, 16, 17, + 18, 19, 20, 21, 14, 5, 6, 25, 8, 9, + 10, 11, 30, 30, 14, 15, 142, 143, 144, 13, + 25, 31, 32, 149, 28, 151, 14, 31, 32, 32, + 30, 67, 68, 30, 70, 161, 67, 68, 30, 70, + 30, 31, 32, 30, 31, 32, 30, 31, 32, 30, + 31, 32, 30, 30, 30, 30, 30, 30, 30, 29, + 40, 59, -1, 106, 66 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const unsigned char yystos[] = { - 0, 37, 38, 0, 1, 3, 4, 5, 6, 7, + 0, 36, 37, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 18, 19, 20, - 21, 22, 23, 26, 31, 39, 40, 42, 43, 44, - 45, 51, 52, 54, 58, 60, 62, 63, 65, 67, - 68, 69, 76, 31, 26, 27, 75, 75, 31, 75, - 31, 31, 75, 26, 26, 26, 27, 30, 35, 79, - 80, 31, 1, 1, 46, 46, 55, 57, 61, 72, - 66, 72, 31, 77, 31, 31, 31, 31, 31, 79, - 79, 32, 33, 77, 28, 34, 31, 31, 1, 12, - 16, 17, 19, 20, 21, 22, 23, 24, 26, 31, - 41, 47, 48, 70, 71, 73, 18, 19, 20, 21, - 31, 41, 56, 71, 73, 40, 53, 76, 40, 54, - 59, 65, 76, 31, 41, 73, 40, 54, 64, 65, - 76, 31, 29, 79, 79, 80, 80, 31, 31, 25, - 79, 79, 75, 74, 75, 79, 26, 80, 49, 1, - 13, 31, 75, 74, 26, 79, 31, 31, 14, 78, - 31, 78, 78, 78, 80, 26, 31, 31, 78, 31, - 78, 31, 79, 31, 31, 31, 78, 34, 50, 31, - 31, 31, 75 + 21, 22, 23, 25, 30, 38, 39, 41, 42, 43, + 44, 47, 48, 50, 54, 56, 58, 59, 61, 63, + 64, 65, 72, 30, 25, 26, 71, 71, 30, 71, + 30, 30, 71, 25, 25, 25, 26, 29, 34, 75, + 76, 30, 1, 1, 45, 45, 51, 53, 57, 68, + 62, 68, 30, 73, 30, 30, 30, 30, 30, 75, + 75, 31, 32, 73, 27, 33, 30, 30, 1, 12, + 16, 17, 19, 20, 21, 22, 23, 25, 30, 40, + 46, 66, 67, 69, 18, 19, 20, 21, 30, 40, + 52, 67, 69, 39, 49, 72, 39, 50, 55, 61, + 72, 30, 40, 69, 39, 50, 60, 61, 72, 30, + 28, 75, 75, 76, 76, 30, 30, 24, 75, 75, + 71, 70, 71, 75, 25, 76, 1, 13, 30, 71, + 70, 25, 75, 30, 30, 14, 74, 30, 74, 74, + 74, 76, 30, 74, 30, 74, 30, 75, 30, 30, + 30, 74, 30, 30, 30 }; +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) @@ -765,8 +709,8 @@ do \ goto yybackup; \ } \ else \ - { \ - yyerror (YY_("syntax error: cannot back up")); \ + { \ + yyerror ("syntax error: cannot back up");\ YYERROR; \ } \ while (0) @@ -845,7 +789,7 @@ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ - yysymprint (stderr, \ + yysymprint (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ @@ -893,13 +837,13 @@ yy_reduce_print (yyrule) #endif { int yyi; - unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu), ", + unsigned int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", yyrule - 1, yylno); /* Print the symbols being reduced, and their result. */ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) - YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); - YYFPRINTF (stderr, "-> %s\n", yytname[yyr1[yyrule]]); + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); } # define YY_REDUCE_PRINT(Rule) \ @@ -928,7 +872,7 @@ int yydebug; if the built-in stack extension method is used). Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH @@ -952,7 +896,7 @@ yystrlen (yystr) const char *yystr; # endif { - const char *yys = yystr; + register const char *yys = yystr; while (*yys++ != '\0') continue; @@ -977,8 +921,8 @@ yystpcpy (yydest, yysrc) const char *yysrc; # endif { - char *yyd = yydest; - const char *yys = yysrc; + register char *yyd = yydest; + register const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; @@ -988,55 +932,7 @@ yystpcpy (yydest, yysrc) # endif # endif -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - size_t yyn = 0; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (! yyres) - return yystrlen (yystr); - - return yystpcpy (yyres, yystr) - yyres; -} -# endif - -#endif /* YYERROR_VERBOSE */ +#endif /* !YYERROR_VERBOSE */ @@ -1102,7 +998,7 @@ yydestruct (yymsg, yytype, yyvaluep) switch (yytype) { - case 52: /* "choice_entry" */ + case 48: /* choice_entry */ { fprintf(stderr, "%s:%d: missing end statement for this entry\n", @@ -1112,7 +1008,7 @@ yydestruct (yymsg, yytype, yyvaluep) }; break; - case 58: /* "if_entry" */ + case 54: /* if_entry */ { fprintf(stderr, "%s:%d: missing end statement for this entry\n", @@ -1122,7 +1018,7 @@ yydestruct (yymsg, yytype, yyvaluep) }; break; - case 63: /* "menu_entry" */ + case 59: /* menu_entry */ { fprintf(stderr, "%s:%d: missing end statement for this entry\n", @@ -1186,13 +1082,13 @@ yyparse (void) #else int yyparse () - ; + #endif #endif { - int yystate; - int yyn; + register int yystate; + register int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; @@ -1210,12 +1106,12 @@ yyparse () /* The state stack. */ short int yyssa[YYINITDEPTH]; short int *yyss = yyssa; - short int *yyssp; + register short int *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp; + register YYSTYPE *yyvsp; @@ -1247,6 +1143,9 @@ yyparse () yyssp = yyss; yyvsp = yyvs; + + yyvsp[0] = yylval; + goto yysetstate; /*------------------------------------------------------------. @@ -1279,7 +1178,7 @@ yyparse () data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), + yyoverflow ("parser stack overflow", &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), @@ -1290,11 +1189,11 @@ yyparse () } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; + goto yyoverflowlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; + goto yyoverflowlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; @@ -1304,7 +1203,7 @@ yyparse () union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) - goto yyexhaustedlab; + goto yyoverflowlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); @@ -1504,7 +1403,7 @@ yyreduce: ;} break; - case 38: + case 37: { menu_set_type((yyvsp[-2].id)->stype); @@ -1514,7 +1413,7 @@ yyreduce: ;} break; - case 39: + case 38: { menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); @@ -1522,7 +1421,7 @@ yyreduce: ;} break; - case 40: + case 39: { menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr)); @@ -1534,7 +1433,7 @@ yyreduce: ;} break; - case 41: + case 40: { menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr)); @@ -1542,7 +1441,7 @@ yyreduce: ;} break; - case 42: + case 41: { menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr)); @@ -1550,29 +1449,7 @@ yyreduce: ;} break; - case 45: - - { - struct kconf_id *id = kconf_id_lookup((yyvsp[-1].string), strlen((yyvsp[-1].string))); - if (id && id->flags & TF_OPTION) - menu_add_option(id->token, (yyvsp[0].string)); - else - zconfprint("warning: ignoring unknown option %s", (yyvsp[-1].string)); - free((yyvsp[-1].string)); -;} - break; - - case 46: - - { (yyval.string) = NULL; ;} - break; - - case 47: - - { (yyval.string) = (yyvsp[0].string); ;} - break; - - case 48: + case 42: { struct symbol *sym = sym_lookup(NULL, 0); @@ -1583,14 +1460,14 @@ yyreduce: ;} break; - case 49: + case 43: { (yyval.menu) = menu_add_menu(); ;} break; - case 50: + case 44: { if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) { @@ -1600,7 +1477,7 @@ yyreduce: ;} break; - case 58: + case 52: { menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr)); @@ -1608,7 +1485,7 @@ yyreduce: ;} break; - case 59: + case 53: { if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) { @@ -1621,7 +1498,7 @@ yyreduce: ;} break; - case 60: + case 54: { current_entry->sym->flags |= SYMBOL_OPTIONAL; @@ -1629,7 +1506,7 @@ yyreduce: ;} break; - case 61: + case 55: { if ((yyvsp[-3].id)->stype == S_UNKNOWN) { @@ -1641,7 +1518,7 @@ yyreduce: ;} break; - case 64: + case 58: { printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); @@ -1651,7 +1528,7 @@ yyreduce: ;} break; - case 65: + case 59: { if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) { @@ -1661,7 +1538,7 @@ yyreduce: ;} break; - case 71: + case 65: { menu_add_entry(NULL); @@ -1670,14 +1547,14 @@ yyreduce: ;} break; - case 72: + case 66: { (yyval.menu) = menu_add_menu(); ;} break; - case 73: + case 67: { if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) { @@ -1687,7 +1564,7 @@ yyreduce: ;} break; - case 79: + case 73: { printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string)); @@ -1695,7 +1572,7 @@ yyreduce: ;} break; - case 80: + case 74: { menu_add_entry(NULL); @@ -1704,14 +1581,14 @@ yyreduce: ;} break; - case 81: + case 75: { menu_end_entry(); ;} break; - case 82: + case 76: { printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); @@ -1719,14 +1596,14 @@ yyreduce: ;} break; - case 83: + case 77: { current_entry->sym->help = (yyvsp[0].string); ;} break; - case 88: + case 82: { menu_add_dep((yyvsp[-1].expr)); @@ -1734,7 +1611,7 @@ yyreduce: ;} break; - case 89: + case 83: { menu_add_dep((yyvsp[-1].expr)); @@ -1742,7 +1619,7 @@ yyreduce: ;} break; - case 90: + case 84: { menu_add_dep((yyvsp[-1].expr)); @@ -1750,88 +1627,87 @@ yyreduce: ;} break; - case 92: + case 86: { menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr)); ;} break; - case 95: + case 89: { (yyval.id) = (yyvsp[-1].id); ;} break; - case 96: + case 90: { (yyval.id) = (yyvsp[-1].id); ;} break; - case 97: + case 91: { (yyval.id) = (yyvsp[-1].id); ;} break; - case 100: + case 94: { (yyval.expr) = NULL; ;} break; - case 101: + case 95: { (yyval.expr) = (yyvsp[0].expr); ;} break; - case 102: + case 96: { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;} break; - case 103: + case 97: { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} break; - case 104: + case 98: { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;} break; - case 105: + case 99: { (yyval.expr) = (yyvsp[-1].expr); ;} break; - case 106: + case 100: { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); ;} break; - case 107: + case 101: { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; - case 108: + case 102: { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; - case 109: + case 103: { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); ;} break; - case 110: + case 104: { (yyval.symbol) = sym_lookup((yyvsp[0].string), 1); free((yyvsp[0].string)); ;} break; - default: break; } -/* Line 1126 of yacc.c. */ +/* Line 1037 of yacc.c. */ yyvsp -= yylen; @@ -1871,36 +1747,12 @@ yyerrlab: if (YYPACT_NINF < yyn && yyn < YYLAST) { + YYSIZE_T yysize = 0; int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - char *yymsg = 0; -# define YYERROR_VERBOSE_ARGS_MAXIMUM 5 - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + const char* yyprefix; + char *yymsg; int yyx; -#if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -#endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; - /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; @@ -1908,68 +1760,48 @@ yyerrlab: /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; - - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); + int yycount = 0; + yyprefix = ", expecting "; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); + yycount += 1; + if (yycount == 5) { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; + yysize = 0; break; } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= yysize1 < yysize; - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; } - - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= yysize1 < yysize; - yysize = yysize1; - - if (!yysize_overflow && yysize <= YYSTACK_ALLOC_MAXIMUM) - yymsg = (char *) YYSTACK_ALLOC (yysize); - if (yymsg) + yysize += (sizeof ("syntax error, unexpected ") + + yystrlen (yytname[yytype])); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yymsg; - int yyi = 0; - while ((*yyp = *yyf)) + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yyp = yystpcpy (yyp, yyprefix); + yyp = yystpcpy (yyp, yytname[yyx]); + yyprefix = " or "; + } } yyerror (yymsg); YYSTACK_FREE (yymsg); } else - { - yyerror (YY_("syntax error")); - goto yyexhaustedlab; - } + yyerror ("syntax error; also virtual memory exhausted"); } else #endif /* YYERROR_VERBOSE */ - yyerror (YY_("syntax error")); + yyerror ("syntax error"); } @@ -1981,9 +1813,18 @@ yyerrlab: if (yychar <= YYEOF) { - /* Return failure if at end of input. */ + /* If at end of input, pop the error token, + then the rest of the stack, then return failure. */ if (yychar == YYEOF) - YYABORT; + for (;;) + { + + YYPOPSTACK; + if (yyssp == yyss) + YYABORT; + yydestruct ("Error: popping", + yystos[*yyssp], yyvsp); + } } else { @@ -2002,11 +1843,12 @@ yyerrlab: `---------------------------------------------------*/ yyerrorlab: - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ +#ifdef __GNUC__ + /* Pacify GCC when the user code never invokes YYERROR and the label + yyerrorlab therefore never appears in user code. */ if (0) goto yyerrorlab; +#endif yyvsp -= yylen; yyssp -= yylen; @@ -2069,29 +1911,23 @@ yyacceptlab: | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: + yydestruct ("Error: discarding lookahead", + yytoken, &yylval); + yychar = YYEMPTY; yyresult = 1; goto yyreturn; #ifndef yyoverflow -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (YY_("memory exhausted")); +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); yyresult = 2; /* Fall through. */ #endif yyreturn: - if (yychar != YYEOF && yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp); - YYPOPSTACK; - } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); @@ -2112,9 +1948,7 @@ void conf_parse(const char *name) sym_init(); menu_init(); - modules_sym = sym_lookup(NULL, 0); - modules_sym->type = S_BOOLEAN; - modules_sym->flags |= SYMBOL_AUTO; + modules_sym = sym_lookup("MODULES", 0); rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); #if YYDEBUG @@ -2124,12 +1958,6 @@ void conf_parse(const char *name) zconfparse(); if (zconfnerrs) exit(1); - if (!modules_sym->prop) { - struct property *prop; - - prop = prop_alloc(P_DEFAULT, modules_sym); - prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); - } menu_finalize(&rootmenu); for_all_symbols(i, sym) { sym_check_deps(sym); diff --git a/trunk/scripts/kconfig/zconf.y b/trunk/scripts/kconfig/zconf.y index ab44feb3c600..1f61fba6aa28 100644 --- a/trunk/scripts/kconfig/zconf.y +++ b/trunk/scripts/kconfig/zconf.y @@ -71,7 +71,6 @@ static struct menu *current_menu, *current_entry; %token T_DEFAULT %token T_SELECT %token T_RANGE -%token T_OPTION %token T_ON %token T_WORD %token T_WORD_QUOTE @@ -92,7 +91,6 @@ static struct menu *current_menu, *current_entry; %type end %type option_name %type if_entry menu_entry choice_entry -%type symbol_option_arg %destructor { fprintf(stderr, "%s:%d: missing end statement for this entry\n", @@ -175,7 +173,6 @@ menuconfig_stmt: menuconfig_entry_start config_option_list config_option_list: /* empty */ | config_option_list config_option - | config_option_list symbol_option | config_option_list depends | config_option_list help | config_option_list option_error @@ -218,26 +215,6 @@ config_option: T_RANGE symbol symbol if_expr T_EOL printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); }; -symbol_option: T_OPTION symbol_option_list T_EOL -; - -symbol_option_list: - /* empty */ - | symbol_option_list T_WORD symbol_option_arg -{ - struct kconf_id *id = kconf_id_lookup($2, strlen($2)); - if (id && id->flags & TF_OPTION) - menu_add_option(id->token, $3); - else - zconfprint("warning: ignoring unknown option %s", $2); - free($2); -}; - -symbol_option_arg: - /* empty */ { $$ = NULL; } - | T_EQUAL prompt { $$ = $2; } -; - /* choice entry */ choice: T_CHOICE T_EOL @@ -481,9 +458,7 @@ void conf_parse(const char *name) sym_init(); menu_init(); - modules_sym = sym_lookup(NULL, 0); - modules_sym->type = S_BOOLEAN; - modules_sym->flags |= SYMBOL_AUTO; + modules_sym = sym_lookup("MODULES", 0); rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); #if YYDEBUG @@ -493,12 +468,6 @@ void conf_parse(const char *name) zconfparse(); if (zconfnerrs) exit(1); - if (!modules_sym->prop) { - struct property *prop; - - prop = prop_alloc(P_DEFAULT, modules_sym); - prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); - } menu_finalize(&rootmenu); for_all_symbols(i, sym) { sym_check_deps(sym); diff --git a/trunk/scripts/kernel-doc b/trunk/scripts/kernel-doc index f9460a6218de..00e21297aefe 100755 --- a/trunk/scripts/kernel-doc +++ b/trunk/scripts/kernel-doc @@ -1056,8 +1056,7 @@ sub output_struct_man(%) { # pointer-to-function print ".BI \" ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n"; } elsif ($type =~ m/^(.*?)\s*(:.*)/) { - # bitfield - print ".BI \" ".$1."\ \" ".$parameter.$2." \""."\"\n;\n"; + print ".BI \" ".$1."\" ".$parameter.$2." \""."\"\n;\n"; } else { $type =~ s/([^\*])$/$1 /; print ".BI \" ".$type."\" ".$parameter." \""."\"\n;\n"; @@ -1119,10 +1118,7 @@ sub output_function_text(%) { my %args = %{$_[0]}; my ($parameter, $section); - print "Name:\n\n"; - print $args{'function'}." - ".$args{'purpose'}."\n"; - - print "\nSynopsis:\n\n"; + print "Function:\n\n"; my $start=$args{'functiontype'}." ".$args{'function'}." ("; print $start; my $count = 0; @@ -1173,7 +1169,6 @@ sub output_enum_text(%) { my $count; print "Enum:\n\n"; - print "enum ".$args{'enum'}." - ".$args{'purpose'}."\n\n"; print "enum ".$args{'enum'}." {\n"; $count = 0; foreach $parameter (@{$args{'parameterlist'}}) { @@ -1202,7 +1197,7 @@ sub output_typedef_text(%) { my $count; print "Typedef:\n\n"; - print "typedef ".$args{'typedef'}." - ".$args{'purpose'}."\n"; + print "typedef ".$args{'typedef'}."\n"; output_section_text(@_); } @@ -1211,7 +1206,7 @@ sub output_struct_text(%) { my %args = %{$_[0]}; my ($parameter); - print $args{'type'}." ".$args{'struct'}." - ".$args{'purpose'}."\n\n"; + print $args{'type'}." ".$args{'struct'}.":\n\n"; print $args{'type'}." ".$args{'struct'}." {\n"; foreach $parameter (@{$args{'parameterlist'}}) { if ($parameter =~ /^#/) { diff --git a/trunk/scripts/mod/mk_elfconfig.c b/trunk/scripts/mod/mk_elfconfig.c index 725d61c0fb43..3c92c83733f4 100644 --- a/trunk/scripts/mod/mk_elfconfig.c +++ b/trunk/scripts/mod/mk_elfconfig.c @@ -28,7 +28,7 @@ main(int argc, char **argv) printf("#define KERNEL_ELFCLASS ELFCLASS64\n"); break; default: - exit(1); + abort(); } switch (ei[EI_DATA]) { case ELFDATA2LSB: @@ -38,7 +38,7 @@ main(int argc, char **argv) printf("#define KERNEL_ELFDATA ELFDATA2MSB\n"); break; default: - exit(1); + abort(); } if (sizeof(unsigned long) == 4) { @@ -53,7 +53,7 @@ main(int argc, char **argv) else if (memcmp(endian_test.c, "\x02\x01", 2) == 0) printf("#define HOST_ELFDATA ELFDATA2LSB\n"); else - exit(1); + abort(); if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0)) printf("#define MODULE_SYMBOL_PREFIX \"_\"\n"); diff --git a/trunk/scripts/mod/modpost.c b/trunk/scripts/mod/modpost.c index dfde0e87a765..d0f86ed43f7a 100644 --- a/trunk/scripts/mod/modpost.c +++ b/trunk/scripts/mod/modpost.c @@ -13,7 +13,6 @@ #include #include "modpost.h" -#include "../../include/linux/license.h" /* Are we using CONFIG_MODVERSIONS? */ int modversions = 0; @@ -23,11 +22,6 @@ int have_vmlinux = 0; static int all_versions = 0; /* If we are modposting external module set to 1 */ static int external_module = 0; -/* How a symbol is exported */ -enum export { - export_plain, export_unused, export_gpl, - export_unused_gpl, export_gpl_future, export_unknown -}; void fatal(const char *fmt, ...) { @@ -103,7 +97,6 @@ static struct module *new_module(char *modname) /* add to list */ mod->name = p; - mod->gpl_compatible = -1; mod->next = modules; modules = mod; @@ -125,7 +118,6 @@ struct symbol { unsigned int kernel:1; /* 1 if symbol is from kernel * (only for external modules) **/ unsigned int preloaded:1; /* 1 if symbol from Module.symvers */ - enum export export; /* Type of export */ char name[0]; }; @@ -161,8 +153,7 @@ static struct symbol *alloc_symbol(const char *name, unsigned int weak, } /* For the hash of exported symbols */ -static struct symbol *new_symbol(const char *name, struct module *module, - enum export export) +static struct symbol *new_symbol(const char *name, struct module *module) { unsigned int hash; struct symbol *new; @@ -170,7 +161,6 @@ static struct symbol *new_symbol(const char *name, struct module *module, hash = tdb_hash(name) % SYMBOL_HASH_SIZE; new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); new->module = module; - new->export = export; return new; } @@ -189,63 +179,16 @@ static struct symbol *find_symbol(const char *name) return NULL; } -static struct { - const char *str; - enum export export; -} export_list[] = { - { .str = "EXPORT_SYMBOL", .export = export_plain }, - { .str = "EXPORT_UNUSED_SYMBOL", .export = export_unused }, - { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, - { .str = "EXPORT_UNUSED_SYMBOL_GPL", .export = export_unused_gpl }, - { .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future }, - { .str = "(unknown)", .export = export_unknown }, -}; - - -static const char *export_str(enum export ex) -{ - return export_list[ex].str; -} - -static enum export export_no(const char * s) -{ - int i; - if (!s) - return export_unknown; - for (i = 0; export_list[i].export != export_unknown; i++) { - if (strcmp(export_list[i].str, s) == 0) - return export_list[i].export; - } - return export_unknown; -} - -static enum export export_from_sec(struct elf_info *elf, Elf_Section sec) -{ - if (sec == elf->export_sec) - return export_plain; - else if (sec == elf->export_unused_sec) - return export_unused; - else if (sec == elf->export_gpl_sec) - return export_gpl; - else if (sec == elf->export_unused_gpl_sec) - return export_unused_gpl; - else if (sec == elf->export_gpl_future_sec) - return export_gpl_future; - else - return export_unknown; -} - /** * Add an exported symbol - it may have already been added without a * CRC, in this case just update the CRC **/ -static struct symbol *sym_add_exported(const char *name, struct module *mod, - enum export export) +static struct symbol *sym_add_exported(const char *name, struct module *mod) { struct symbol *s = find_symbol(name); if (!s) { - s = new_symbol(name, mod, export); + s = new_symbol(name, mod); } else { if (!s->preloaded) { warn("%s: '%s' exported twice. Previous export " @@ -257,17 +200,16 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, s->preloaded = 0; s->vmlinux = is_vmlinux(mod->name); s->kernel = 0; - s->export = export; return s; } static void sym_update_crc(const char *name, struct module *mod, - unsigned int crc, enum export export) + unsigned int crc) { struct symbol *s = find_symbol(name); if (!s) - s = new_symbol(name, mod, export); + s = new_symbol(name, mod); s->crc = crc; s->crc_valid = 1; } @@ -341,7 +283,7 @@ static void parse_elf(struct elf_info *info, const char *filename) hdr = grab_file(filename, &info->size); if (!hdr) { perror(filename); - exit(1); + abort(); } info->hdr = hdr; if (info->size < sizeof(*hdr)) @@ -367,25 +309,13 @@ static void parse_elf(struct elf_info *info, const char *filename) for (i = 1; i < hdr->e_shnum; i++) { const char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - const char *secname; if (sechdrs[i].sh_offset > info->size) goto truncated; - secname = secstrings + sechdrs[i].sh_name; - if (strcmp(secname, ".modinfo") == 0) { + if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) { info->modinfo = (void *)hdr + sechdrs[i].sh_offset; info->modinfo_len = sechdrs[i].sh_size; - } else if (strcmp(secname, "__ksymtab") == 0) - info->export_sec = i; - else if (strcmp(secname, "__ksymtab_unused") == 0) - info->export_unused_sec = i; - else if (strcmp(secname, "__ksymtab_gpl") == 0) - info->export_gpl_sec = i; - else if (strcmp(secname, "__ksymtab_unused_gpl") == 0) - info->export_unused_gpl_sec = i; - else if (strcmp(secname, "__ksymtab_gpl_future") == 0) - info->export_gpl_future_sec = i; - + } if (sechdrs[i].sh_type != SHT_SYMTAB) continue; @@ -423,7 +353,6 @@ static void handle_modversions(struct module *mod, struct elf_info *info, Elf_Sym *sym, const char *symname) { unsigned int crc; - enum export export = export_from_sec(info, sym->st_shndx); switch (sym->st_shndx) { case SHN_COMMON: @@ -433,8 +362,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info, /* CRC'd symbol */ if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) { crc = (unsigned int) sym->st_value; - sym_update_crc(symname + strlen(CRC_PFX), mod, crc, - export); + sym_update_crc(symname + strlen(CRC_PFX), mod, crc); } break; case SHN_UNDEF: @@ -478,8 +406,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info, default: /* All exported symbols */ if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) { - sym_add_exported(symname + strlen(KSYMTAB_PFX), mod, - export); + sym_add_exported(symname + strlen(KSYMTAB_PFX), mod); } if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) mod->has_init = 1; @@ -510,18 +437,13 @@ static char *next_string(char *string, unsigned long *secsize) return string; } -static char *get_next_modinfo(void *modinfo, unsigned long modinfo_len, - const char *tag, char *info) +static char *get_modinfo(void *modinfo, unsigned long modinfo_len, + const char *tag) { char *p; unsigned int taglen = strlen(tag); unsigned long size = modinfo_len; - if (info) { - size -= info - (char *)modinfo; - modinfo = next_string(info, &size); - } - for (p = modinfo; p; p = next_string(p, &size)) { if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') return p + taglen + 1; @@ -529,13 +451,6 @@ static char *get_next_modinfo(void *modinfo, unsigned long modinfo_len, return NULL; } -static char *get_modinfo(void *modinfo, unsigned long modinfo_len, - const char *tag) - -{ - return get_next_modinfo(modinfo, modinfo_len, tag, NULL); -} - /** * Test if string s ends in string sub * return 0 if match @@ -906,10 +821,6 @@ static int init_section_ref_ok(const char *name) ".pci_fixup_final", ".pdr", "__param", - "__ex_table", - ".fixup", - ".smp_locks", - ".plt", /* seen on ARCH=um build on x86_64. Harmless */ NULL }; /* Start of section names */ @@ -935,8 +846,6 @@ static int init_section_ref_ok(const char *name) for (s = namelist3; *s; s++) if (strstr(name, *s) != NULL) return 1; - if (strrcmp(name, ".init") == 0) - return 1; return 0; } @@ -983,10 +892,6 @@ static int exit_section_ref_ok(const char *name) ".exitcall.exit", ".eh_frame", ".stab", - "__ex_table", - ".fixup", - ".smp_locks", - ".plt", /* seen on ARCH=um build on x86_64. Harmless */ NULL }; /* Start of section names */ @@ -1016,7 +921,6 @@ static void read_symbols(char *modname) { const char *symname; char *version; - char *license; struct module *mod; struct elf_info info = { }; Elf_Sym *sym; @@ -1032,18 +936,6 @@ static void read_symbols(char *modname) mod->skip = 1; } - license = get_modinfo(info.modinfo, info.modinfo_len, "license"); - while (license) { - if (license_is_gpl_compatible(license)) - mod->gpl_compatible = 1; - else { - mod->gpl_compatible = 0; - break; - } - license = get_next_modinfo(info.modinfo, info.modinfo_len, - "license", license); - } - for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { symname = info.strtab + sym->st_name; @@ -1100,67 +992,6 @@ void buf_write(struct buffer *buf, const char *s, int len) buf->pos += len; } -static void check_for_gpl_usage(enum export exp, const char *m, const char *s) -{ - const char *e = is_vmlinux(m) ?"":".ko"; - - switch (exp) { - case export_gpl: - fatal("modpost: GPL-incompatible module %s%s " - "uses GPL-only symbol '%s'\n", m, e, s); - break; - case export_unused_gpl: - fatal("modpost: GPL-incompatible module %s%s " - "uses GPL-only symbol marked UNUSED '%s'\n", m, e, s); - break; - case export_gpl_future: - warn("modpost: GPL-incompatible module %s%s " - "uses future GPL-only symbol '%s'\n", m, e, s); - break; - case export_plain: - case export_unused: - case export_unknown: - /* ignore */ - break; - } -} - -static void check_for_unused(enum export exp, const char* m, const char* s) -{ - const char *e = is_vmlinux(m) ?"":".ko"; - - switch (exp) { - case export_unused: - case export_unused_gpl: - warn("modpost: module %s%s " - "uses symbol '%s' marked UNUSED\n", m, e, s); - break; - default: - /* ignore */ - break; - } -} - -static void check_exports(struct module *mod) -{ - struct symbol *s, *exp; - - for (s = mod->unres; s; s = s->next) { - const char *basename; - exp = find_symbol(s->name); - if (!exp || exp->module == mod) - continue; - basename = strrchr(mod->name, '/'); - if (basename) - basename++; - else - basename = mod->name; - if (!mod->gpl_compatible) - check_for_gpl_usage(exp->export, basename, exp->name); - check_for_unused(exp->export, basename, exp->name); - } -} - /** * Header for the generated file **/ @@ -1311,9 +1142,6 @@ static void write_if_changed(struct buffer *b, const char *fname) fclose(file); } -/* parse Module.symvers file. line format: - * 0x12345678symbolmodule[[export]something] - **/ static void read_dump(const char *fname, unsigned int kernel) { unsigned long size, pos = 0; @@ -1325,7 +1153,7 @@ static void read_dump(const char *fname, unsigned int kernel) return; while ((line = get_next_line(&pos, file, size))) { - char *symname, *modname, *d, *export, *end; + char *symname, *modname, *d; unsigned int crc; struct module *mod; struct symbol *s; @@ -1336,10 +1164,8 @@ static void read_dump(const char *fname, unsigned int kernel) if (!(modname = strchr(symname, '\t'))) goto fail; *modname++ = '\0'; - if ((export = strchr(modname, '\t')) != NULL) - *export++ = '\0'; - if (export && ((end = strchr(export, '\t')) != NULL)) - *end = '\0'; + if (strchr(modname, '\t')) + goto fail; crc = strtoul(line, &d, 16); if (*symname == '\0' || *modname == '\0' || *d != '\0') goto fail; @@ -1351,10 +1177,10 @@ static void read_dump(const char *fname, unsigned int kernel) mod = new_module(NOFAIL(strdup(modname))); mod->skip = 1; } - s = sym_add_exported(symname, mod, export_no(export)); + s = sym_add_exported(symname, mod); s->kernel = kernel; s->preloaded = 1; - sym_update_crc(symname, mod, crc, export_no(export)); + sym_update_crc(symname, mod, crc); } return; fail: @@ -1384,10 +1210,9 @@ static void write_dump(const char *fname) symbol = symbolhash[n]; while (symbol) { if (dump_sym(symbol)) - buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n", + buf_printf(&buf, "0x%08x\t%s\t%s\n", symbol->crc, symbol->name, - symbol->module->name, - export_str(symbol->export)); + symbol->module->name); symbol = symbol->next; } } @@ -1435,12 +1260,6 @@ int main(int argc, char **argv) read_symbols(argv[optind++]); } - for (mod = modules; mod; mod = mod->next) { - if (mod->skip) - continue; - check_exports(mod); - } - for (mod = modules; mod; mod = mod->next) { if (mod->skip) continue; diff --git a/trunk/scripts/mod/modpost.h b/trunk/scripts/mod/modpost.h index d398c61e55ef..861d866fcd83 100644 --- a/trunk/scripts/mod/modpost.h +++ b/trunk/scripts/mod/modpost.h @@ -100,7 +100,6 @@ buf_write(struct buffer *buf, const char *s, int len); struct module { struct module *next; const char *name; - int gpl_compatible; struct symbol *unres; int seen; int skip; @@ -116,11 +115,6 @@ struct elf_info { Elf_Shdr *sechdrs; Elf_Sym *symtab_start; Elf_Sym *symtab_stop; - Elf_Section export_sec; - Elf_Section export_unused_sec; - Elf_Section export_gpl_sec; - Elf_Section export_unused_gpl_sec; - Elf_Section export_gpl_future_sec; const char *strtab; char *modinfo; unsigned int modinfo_len; diff --git a/trunk/scripts/package/mkspec b/trunk/scripts/package/mkspec index df892841b118..0b1038737548 100755 --- a/trunk/scripts/package/mkspec +++ b/trunk/scripts/package/mkspec @@ -73,13 +73,8 @@ echo "%ifarch ia64" echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE" echo 'ln -s '"efi/vmlinuz-$KERNELRELEASE" '$RPM_BUILD_ROOT'"/boot/" echo "%else" -echo "%ifarch ppc64" -echo "cp vmlinux arch/powerpc/boot" -echo "cp arch/powerpc/boot/"'$KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE" -echo "%else" echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE" echo "%endif" -echo "%endif" echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE" diff --git a/trunk/scripts/rt-tester/check-all.sh b/trunk/scripts/rt-tester/check-all.sh deleted file mode 100644 index 43098afe7431..000000000000 --- a/trunk/scripts/rt-tester/check-all.sh +++ /dev/null @@ -1,22 +0,0 @@ - - -function testit () -{ - printf "%-30s: " $1 - ./rt-tester.py $1 | grep Pass -} - -testit t2-l1-2rt-sameprio.tst -testit t2-l1-pi.tst -testit t2-l1-signal.tst -#testit t2-l2-2rt-deadlock.tst -testit t3-l1-pi-1rt.tst -testit t3-l1-pi-2rt.tst -testit t3-l1-pi-3rt.tst -testit t3-l1-pi-signal.tst -testit t3-l1-pi-steal.tst -testit t3-l2-pi.tst -testit t4-l2-pi-deboost.tst -testit t5-l4-pi-boost-deboost.tst -testit t5-l4-pi-boost-deboost-setsched.tst - diff --git a/trunk/scripts/rt-tester/rt-tester.py b/trunk/scripts/rt-tester/rt-tester.py deleted file mode 100644 index 4c79660793cf..000000000000 --- a/trunk/scripts/rt-tester/rt-tester.py +++ /dev/null @@ -1,222 +0,0 @@ -#!/usr/bin/env python -# -# rt-mutex tester -# -# (C) 2006 Thomas Gleixner -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -import os -import sys -import getopt -import shutil -import string - -# Globals -quiet = 0 -test = 0 -comments = 0 - -sysfsprefix = "/sys/devices/system/rttest/rttest" -statusfile = "/status" -commandfile = "/command" - -# Command opcodes -cmd_opcodes = { - "schedother" : "1", - "schedfifo" : "2", - "lock" : "3", - "locknowait" : "4", - "lockint" : "5", - "lockintnowait" : "6", - "lockcont" : "7", - "unlock" : "8", - "lockbkl" : "9", - "unlockbkl" : "10", - "signal" : "11", - "resetevent" : "98", - "reset" : "99", - } - -test_opcodes = { - "prioeq" : ["P" , "eq" , None], - "priolt" : ["P" , "lt" , None], - "priogt" : ["P" , "gt" , None], - "nprioeq" : ["N" , "eq" , None], - "npriolt" : ["N" , "lt" , None], - "npriogt" : ["N" , "gt" , None], - "unlocked" : ["M" , "eq" , 0], - "trylock" : ["M" , "eq" , 1], - "blocked" : ["M" , "eq" , 2], - "blockedwake" : ["M" , "eq" , 3], - "locked" : ["M" , "eq" , 4], - "opcodeeq" : ["O" , "eq" , None], - "opcodelt" : ["O" , "lt" , None], - "opcodegt" : ["O" , "gt" , None], - "eventeq" : ["E" , "eq" , None], - "eventlt" : ["E" , "lt" , None], - "eventgt" : ["E" , "gt" , None], - } - -# Print usage information -def usage(): - print "rt-tester.py <-c -h -q -t> " - print " -c display comments after first command" - print " -h help" - print " -q quiet mode" - print " -t test mode (syntax check)" - print " testfile: read test specification from testfile" - print " otherwise from stdin" - return - -# Print progress when not in quiet mode -def progress(str): - if not quiet: - print str - -# Analyse a status value -def analyse(val, top, arg): - - intval = int(val) - - if top[0] == "M": - intval = intval / (10 ** int(arg)) - intval = intval % 10 - argval = top[2] - elif top[0] == "O": - argval = int(cmd_opcodes.get(arg, arg)) - else: - argval = int(arg) - - # progress("%d %s %d" %(intval, top[1], argval)) - - if top[1] == "eq" and intval == argval: - return 1 - if top[1] == "lt" and intval < argval: - return 1 - if top[1] == "gt" and intval > argval: - return 1 - return 0 - -# Parse the commandline -try: - (options, arguments) = getopt.getopt(sys.argv[1:],'chqt') -except getopt.GetoptError, ex: - usage() - sys.exit(1) - -# Parse commandline options -for option, value in options: - if option == "-c": - comments = 1 - elif option == "-q": - quiet = 1 - elif option == "-t": - test = 1 - elif option == '-h': - usage() - sys.exit(0) - -# Select the input source -if arguments: - try: - fd = open(arguments[0]) - except Exception,ex: - sys.stderr.write("File not found %s\n" %(arguments[0])) - sys.exit(1) -else: - fd = sys.stdin - -linenr = 0 - -# Read the test patterns -while 1: - - linenr = linenr + 1 - line = fd.readline() - if not len(line): - break - - line = line.strip() - parts = line.split(":") - - if not parts or len(parts) < 1: - continue - - if len(parts[0]) == 0: - continue - - if parts[0].startswith("#"): - if comments > 1: - progress(line) - continue - - if comments == 1: - comments = 2 - - progress(line) - - cmd = parts[0].strip().lower() - opc = parts[1].strip().lower() - tid = parts[2].strip() - dat = parts[3].strip() - - try: - # Test or wait for a status value - if cmd == "t" or cmd == "w": - testop = test_opcodes[opc] - - fname = "%s%s%s" %(sysfsprefix, tid, statusfile) - if test: - print fname - continue - - while 1: - query = 1 - fsta = open(fname, 'r') - status = fsta.readline().strip() - fsta.close() - stat = status.split(",") - for s in stat: - s = s.strip() - if s.startswith(testop[0]): - # Seperate status value - val = s[2:].strip() - query = analyse(val, testop, dat) - break - if query or cmd == "t": - break - - progress(" " + status) - - if not query: - sys.stderr.write("Test failed in line %d\n" %(linenr)) - sys.exit(1) - - # Issue a command to the tester - elif cmd == "c": - cmdnr = cmd_opcodes[opc] - # Build command string and sys filename - cmdstr = "%s:%s" %(cmdnr, dat) - fname = "%s%s%s" %(sysfsprefix, tid, commandfile) - if test: - print fname - continue - fcmd = open(fname, 'w') - fcmd.write(cmdstr) - fcmd.close() - - except Exception,ex: - sys.stderr.write(str(ex)) - sys.stderr.write("\nSyntax error in line %d\n" %(linenr)) - if not test: - fd.close() - sys.exit(1) - -# Normal exit pass -print "Pass" -sys.exit(0) - - diff --git a/trunk/scripts/rt-tester/t2-l1-2rt-sameprio.tst b/trunk/scripts/rt-tester/t2-l1-2rt-sameprio.tst deleted file mode 100644 index 8821f27cc8be..000000000000 --- a/trunk/scripts/rt-tester/t2-l1-2rt-sameprio.tst +++ /dev/null @@ -1,99 +0,0 @@ -# -# RT-Mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal 0 -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 2 threads 1 lock -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedfifo: 0: 80 -C: schedfifo: 1: 80 - -# T0 lock L0 -C: locknowait: 0: 0 -C: locknowait: 1: 0 -W: locked: 0: 0 -W: blocked: 1: 0 -T: prioeq: 0: 80 - -# T0 unlock L0 -C: unlock: 0: 0 -W: locked: 1: 0 - -# Verify T0 -W: unlocked: 0: 0 -T: prioeq: 0: 80 - -# Unlock -C: unlock: 1: 0 -W: unlocked: 1: 0 - -# T1,T0 lock L0 -C: locknowait: 1: 0 -C: locknowait: 0: 0 -W: locked: 1: 0 -W: blocked: 0: 0 -T: prioeq: 1: 80 - -# T1 unlock L0 -C: unlock: 1: 0 -W: locked: 0: 0 - -# Verify T1 -W: unlocked: 1: 0 -T: prioeq: 1: 80 - -# Unlock and exit -C: unlock: 0: 0 -W: unlocked: 0: 0 - diff --git a/trunk/scripts/rt-tester/t2-l1-pi.tst b/trunk/scripts/rt-tester/t2-l1-pi.tst deleted file mode 100644 index cde1f189a02b..000000000000 --- a/trunk/scripts/rt-tester/t2-l1-pi.tst +++ /dev/null @@ -1,82 +0,0 @@ -# -# RT-Mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal 0 -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 2 threads 1 lock with priority inversion -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedother: 0: 0 -C: schedfifo: 1: 80 - -# T0 lock L0 -C: locknowait: 0: 0 -W: locked: 0: 0 - -# T1 lock L0 -C: locknowait: 1: 0 -W: blocked: 1: 0 -T: prioeq: 0: 80 - -# T0 unlock L0 -C: unlock: 0: 0 -W: locked: 1: 0 - -# Verify T1 -W: unlocked: 0: 0 -T: priolt: 0: 1 - -# Unlock and exit -C: unlock: 1: 0 -W: unlocked: 1: 0 - diff --git a/trunk/scripts/rt-tester/t2-l1-signal.tst b/trunk/scripts/rt-tester/t2-l1-signal.tst deleted file mode 100644 index 3ab0bfc49950..000000000000 --- a/trunk/scripts/rt-tester/t2-l1-signal.tst +++ /dev/null @@ -1,77 +0,0 @@ -# -# RT-Mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal 0 -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 2 threads 1 lock with priority inversion -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedother: 0: 0 -C: schedother: 1: 0 - -# T0 lock L0 -C: locknowait: 0: 0 -W: locked: 0: 0 - -# T1 lock L0 -C: lockintnowait: 1: 0 -W: blocked: 1: 0 - -# Interrupt T1 -C: signal: 1: 0 -W: unlocked: 1: 0 -T: opcodeeq: 1: -4 - -# Unlock and exit -C: unlock: 0: 0 -W: unlocked: 0: 0 diff --git a/trunk/scripts/rt-tester/t2-l2-2rt-deadlock.tst b/trunk/scripts/rt-tester/t2-l2-2rt-deadlock.tst deleted file mode 100644 index f4b5d5d6215f..000000000000 --- a/trunk/scripts/rt-tester/t2-l2-2rt-deadlock.tst +++ /dev/null @@ -1,89 +0,0 @@ -# -# RT-Mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal 0 -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 2 threads 2 lock -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedfifo: 0: 80 -C: schedfifo: 1: 80 - -# T0 lock L0 -C: locknowait: 0: 0 -W: locked: 0: 0 - -# T1 lock L1 -C: locknowait: 1: 1 -W: locked: 1: 1 - -# T0 lock L1 -C: lockintnowait: 0: 1 -W: blocked: 0: 1 - -# T1 lock L0 -C: lockintnowait: 1: 0 -W: blocked: 1: 0 - -# Make deadlock go away -C: signal: 1: 0 -W: unlocked: 1: 0 -C: signal: 0: 0 -W: unlocked: 0: 1 - -# Unlock and exit -C: unlock: 0: 0 -W: unlocked: 0: 0 -C: unlock: 1: 1 -W: unlocked: 1: 1 - diff --git a/trunk/scripts/rt-tester/t3-l1-pi-1rt.tst b/trunk/scripts/rt-tester/t3-l1-pi-1rt.tst deleted file mode 100644 index 63440ca2cce9..000000000000 --- a/trunk/scripts/rt-tester/t3-l1-pi-1rt.tst +++ /dev/null @@ -1,92 +0,0 @@ -# -# rt-mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal thread to signal (0-7) -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 3 threads 1 lock PI -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedother: 0: 0 -C: schedother: 1: 0 -C: schedfifo: 2: 82 - -# T0 lock L0 -C: locknowait: 0: 0 -W: locked: 0: 0 - -# T1 lock L0 -C: locknowait: 1: 0 -W: blocked: 1: 0 -T: priolt: 0: 1 - -# T2 lock L0 -C: locknowait: 2: 0 -W: blocked: 2: 0 -T: prioeq: 0: 82 - -# T0 unlock L0 -C: unlock: 0: 0 - -# Wait until T2 got the lock -W: locked: 2: 0 -W: unlocked: 0: 0 -T: priolt: 0: 1 - -# T2 unlock L0 -C: unlock: 2: 0 - -W: unlocked: 2: 0 -W: locked: 1: 0 - -C: unlock: 1: 0 -W: unlocked: 1: 0 diff --git a/trunk/scripts/rt-tester/t3-l1-pi-2rt.tst b/trunk/scripts/rt-tester/t3-l1-pi-2rt.tst deleted file mode 100644 index e5816fe67df3..000000000000 --- a/trunk/scripts/rt-tester/t3-l1-pi-2rt.tst +++ /dev/null @@ -1,93 +0,0 @@ -# -# rt-mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal thread to signal (0-7) -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 3 threads 1 lock PI -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedother: 0: 0 -C: schedfifo: 1: 81 -C: schedfifo: 2: 82 - -# T0 lock L0 -C: locknowait: 0: 0 -W: locked: 0: 0 - -# T1 lock L0 -C: locknowait: 1: 0 -W: blocked: 1: 0 -T: prioeq: 0: 81 - -# T2 lock L0 -C: locknowait: 2: 0 -W: blocked: 2: 0 -T: prioeq: 0: 82 -T: prioeq: 1: 81 - -# T0 unlock L0 -C: unlock: 0: 0 - -# Wait until T2 got the lock -W: locked: 2: 0 -W: unlocked: 0: 0 -T: priolt: 0: 1 - -# T2 unlock L0 -C: unlock: 2: 0 - -W: unlocked: 2: 0 -W: locked: 1: 0 - -C: unlock: 1: 0 -W: unlocked: 1: 0 diff --git a/trunk/scripts/rt-tester/t3-l1-pi-3rt.tst b/trunk/scripts/rt-tester/t3-l1-pi-3rt.tst deleted file mode 100644 index 718b82b5d3bb..000000000000 --- a/trunk/scripts/rt-tester/t3-l1-pi-3rt.tst +++ /dev/null @@ -1,92 +0,0 @@ -# -# rt-mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal thread to signal (0-7) -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 3 threads 1 lock PI -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedfifo: 0: 80 -C: schedfifo: 1: 81 -C: schedfifo: 2: 82 - -# T0 lock L0 -C: locknowait: 0: 0 -W: locked: 0: 0 - -# T1 lock L0 -C: locknowait: 1: 0 -W: blocked: 1: 0 -T: prioeq: 0: 81 - -# T2 lock L0 -C: locknowait: 2: 0 -W: blocked: 2: 0 -T: prioeq: 0: 82 - -# T0 unlock L0 -C: unlock: 0: 0 - -# Wait until T2 got the lock -W: locked: 2: 0 -W: unlocked: 0: 0 -T: prioeq: 0: 80 - -# T2 unlock L0 -C: unlock: 2: 0 - -W: locked: 1: 0 -W: unlocked: 2: 0 - -C: unlock: 1: 0 -W: unlocked: 1: 0 diff --git a/trunk/scripts/rt-tester/t3-l1-pi-signal.tst b/trunk/scripts/rt-tester/t3-l1-pi-signal.tst deleted file mode 100644 index c6e213563498..000000000000 --- a/trunk/scripts/rt-tester/t3-l1-pi-signal.tst +++ /dev/null @@ -1,98 +0,0 @@ -# -# rt-mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal thread to signal (0-7) -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# Reset event counter -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set priorities -C: schedother: 0: 0 -C: schedfifo: 1: 80 -C: schedfifo: 2: 81 - -# T0 lock L0 -C: lock: 0: 0 -W: locked: 0: 0 - -# T1 lock L0, no wait in the wakeup path -C: locknowait: 1: 0 -W: blocked: 1: 0 -T: prioeq: 0: 80 -T: prioeq: 1: 80 - -# T2 lock L0 interruptible, no wait in the wakeup path -C: lockintnowait: 2: 0 -W: blocked: 2: 0 -T: prioeq: 0: 81 -T: prioeq: 1: 80 - -# Interrupt T2 -C: signal: 2: 2 -W: unlocked: 2: 0 -T: prioeq: 1: 80 -T: prioeq: 0: 80 - -T: locked: 0: 0 -T: blocked: 1: 0 - -# T0 unlock L0 -C: unlock: 0: 0 - -# Wait until T1 has locked L0 and exit -W: locked: 1: 0 -W: unlocked: 0: 0 -T: priolt: 0: 1 - -C: unlock: 1: 0 -W: unlocked: 1: 0 - - - diff --git a/trunk/scripts/rt-tester/t3-l1-pi-steal.tst b/trunk/scripts/rt-tester/t3-l1-pi-steal.tst deleted file mode 100644 index f53749d59d79..000000000000 --- a/trunk/scripts/rt-tester/t3-l1-pi-steal.tst +++ /dev/null @@ -1,96 +0,0 @@ -# -# rt-mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal thread to signal (0-7) -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 3 threads 1 lock PI steal pending ownership -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedother: 0: 0 -C: schedfifo: 1: 80 -C: schedfifo: 2: 81 - -# T0 lock L0 -C: lock: 0: 0 -W: locked: 0: 0 - -# T1 lock L0 -C: lock: 1: 0 -W: blocked: 1: 0 -T: prioeq: 0: 80 - -# T0 unlock L0 -C: unlock: 0: 0 - -# Wait until T1 is in the wakeup loop -W: blockedwake: 1: 0 -T: priolt: 0: 1 - -# T2 lock L0 -C: lock: 2: 0 -# T1 leave wakeup loop -C: lockcont: 1: 0 - -# T2 must have the lock and T1 must be blocked -W: locked: 2: 0 -W: blocked: 1: 0 - -# T2 unlock L0 -C: unlock: 2: 0 - -# Wait until T1 is in the wakeup loop and let it run -W: blockedwake: 1: 0 -C: lockcont: 1: 0 -W: locked: 1: 0 -C: unlock: 1: 0 -W: unlocked: 1: 0 diff --git a/trunk/scripts/rt-tester/t3-l2-pi.tst b/trunk/scripts/rt-tester/t3-l2-pi.tst deleted file mode 100644 index cdc3e4fd7bac..000000000000 --- a/trunk/scripts/rt-tester/t3-l2-pi.tst +++ /dev/null @@ -1,92 +0,0 @@ -# -# rt-mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal thread to signal (0-7) -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 3 threads 2 lock PI -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedother: 0: 0 -C: schedother: 1: 0 -C: schedfifo: 2: 82 - -# T0 lock L0 -C: locknowait: 0: 0 -W: locked: 0: 0 - -# T1 lock L0 -C: locknowait: 1: 0 -W: blocked: 1: 0 -T: priolt: 0: 1 - -# T2 lock L0 -C: locknowait: 2: 0 -W: blocked: 2: 0 -T: prioeq: 0: 82 - -# T0 unlock L0 -C: unlock: 0: 0 - -# Wait until T2 got the lock -W: locked: 2: 0 -W: unlocked: 0: 0 -T: priolt: 0: 1 - -# T2 unlock L0 -C: unlock: 2: 0 - -W: unlocked: 2: 0 -W: locked: 1: 0 - -C: unlock: 1: 0 -W: unlocked: 1: 0 diff --git a/trunk/scripts/rt-tester/t4-l2-pi-deboost.tst b/trunk/scripts/rt-tester/t4-l2-pi-deboost.tst deleted file mode 100644 index baa14137f473..000000000000 --- a/trunk/scripts/rt-tester/t4-l2-pi-deboost.tst +++ /dev/null @@ -1,123 +0,0 @@ -# -# rt-mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal thread to signal (0-7) -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 4 threads 2 lock PI -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedother: 0: 0 -C: schedother: 1: 0 -C: schedfifo: 2: 82 -C: schedfifo: 3: 83 - -# T0 lock L0 -C: locknowait: 0: 0 -W: locked: 0: 0 - -# T1 lock L1 -C: locknowait: 1: 1 -W: locked: 1: 1 - -# T3 lock L0 -C: lockintnowait: 3: 0 -W: blocked: 3: 0 -T: prioeq: 0: 83 - -# T0 lock L1 -C: lock: 0: 1 -W: blocked: 0: 1 -T: prioeq: 1: 83 - -# T1 unlock L1 -C: unlock: 1: 1 - -# Wait until T0 is in the wakeup code -W: blockedwake: 0: 1 - -# Verify that T1 is unboosted -W: unlocked: 1: 1 -T: priolt: 1: 1 - -# T2 lock L1 (T0 is boosted and pending owner !) -C: locknowait: 2: 1 -W: blocked: 2: 1 -T: prioeq: 0: 83 - -# Interrupt T3 and wait until T3 returned -C: signal: 3: 0 -W: unlocked: 3: 0 - -# Verify prio of T0 (still pending owner, -# but T2 is enqueued due to the previous boost by T3 -T: prioeq: 0: 82 - -# Let T0 continue -C: lockcont: 0: 1 -W: locked: 0: 1 - -# Unlock L1 and let T2 get L1 -C: unlock: 0: 1 -W: locked: 2: 1 - -# Verify that T0 is unboosted -W: unlocked: 0: 1 -T: priolt: 0: 1 - -# Unlock everything and exit -C: unlock: 2: 1 -W: unlocked: 2: 1 - -C: unlock: 0: 0 -W: unlocked: 0: 0 - diff --git a/trunk/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst b/trunk/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst deleted file mode 100644 index e6ec0c81b54d..000000000000 --- a/trunk/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst +++ /dev/null @@ -1,183 +0,0 @@ -# -# rt-mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal thread to signal (0-7) -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 5 threads 4 lock PI - modify priority of blocked threads -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedother: 0: 0 -C: schedfifo: 1: 81 -C: schedfifo: 2: 82 -C: schedfifo: 3: 83 -C: schedfifo: 4: 84 - -# T0 lock L0 -C: locknowait: 0: 0 -W: locked: 0: 0 - -# T1 lock L1 -C: locknowait: 1: 1 -W: locked: 1: 1 - -# T1 lock L0 -C: lockintnowait: 1: 0 -W: blocked: 1: 0 -T: prioeq: 0: 81 - -# T2 lock L2 -C: locknowait: 2: 2 -W: locked: 2: 2 - -# T2 lock L1 -C: lockintnowait: 2: 1 -W: blocked: 2: 1 -T: prioeq: 0: 82 -T: prioeq: 1: 82 - -# T3 lock L3 -C: locknowait: 3: 3 -W: locked: 3: 3 - -# T3 lock L2 -C: lockintnowait: 3: 2 -W: blocked: 3: 2 -T: prioeq: 0: 83 -T: prioeq: 1: 83 -T: prioeq: 2: 83 - -# T4 lock L3 -C: lockintnowait: 4: 3 -W: blocked: 4: 3 -T: prioeq: 0: 84 -T: prioeq: 1: 84 -T: prioeq: 2: 84 -T: prioeq: 3: 84 - -# Reduce prio of T4 -C: schedfifo: 4: 80 -T: prioeq: 0: 83 -T: prioeq: 1: 83 -T: prioeq: 2: 83 -T: prioeq: 3: 83 -T: prioeq: 4: 80 - -# Increase prio of T4 -C: schedfifo: 4: 84 -T: prioeq: 0: 84 -T: prioeq: 1: 84 -T: prioeq: 2: 84 -T: prioeq: 3: 84 -T: prioeq: 4: 84 - -# Reduce prio of T3 -C: schedfifo: 3: 80 -T: prioeq: 0: 84 -T: prioeq: 1: 84 -T: prioeq: 2: 84 -T: prioeq: 3: 84 -T: prioeq: 4: 84 - -# Increase prio of T3 -C: schedfifo: 3: 85 -T: prioeq: 0: 85 -T: prioeq: 1: 85 -T: prioeq: 2: 85 -T: prioeq: 3: 85 -T: prioeq: 4: 84 - -# Reduce prio of T3 -C: schedfifo: 3: 83 -T: prioeq: 0: 84 -T: prioeq: 1: 84 -T: prioeq: 2: 84 -T: prioeq: 3: 84 -T: prioeq: 4: 84 - -# Signal T4 -C: signal: 4: 0 -W: unlocked: 4: 3 -T: prioeq: 0: 83 -T: prioeq: 1: 83 -T: prioeq: 2: 83 -T: prioeq: 3: 83 - -# Signal T3 -C: signal: 3: 0 -W: unlocked: 3: 2 -T: prioeq: 0: 82 -T: prioeq: 1: 82 -T: prioeq: 2: 82 - -# Signal T2 -C: signal: 2: 0 -W: unlocked: 2: 1 -T: prioeq: 0: 81 -T: prioeq: 1: 81 - -# Signal T1 -C: signal: 1: 0 -W: unlocked: 1: 0 -T: priolt: 0: 1 - -# Unlock and exit -C: unlock: 3: 3 -C: unlock: 2: 2 -C: unlock: 1: 1 -C: unlock: 0: 0 - -W: unlocked: 3: 3 -W: unlocked: 2: 2 -W: unlocked: 1: 1 -W: unlocked: 0: 0 - diff --git a/trunk/scripts/rt-tester/t5-l4-pi-boost-deboost.tst b/trunk/scripts/rt-tester/t5-l4-pi-boost-deboost.tst deleted file mode 100644 index ca64f8bbf4bc..000000000000 --- a/trunk/scripts/rt-tester/t5-l4-pi-boost-deboost.tst +++ /dev/null @@ -1,143 +0,0 @@ -# -# rt-mutex test -# -# Op: C(ommand)/T(est)/W(ait) -# | opcode -# | | threadid: 0-7 -# | | | opcode argument -# | | | | -# C: lock: 0: 0 -# -# Commands -# -# opcode opcode argument -# schedother nice value -# schedfifo priority -# lock lock nr (0-7) -# locknowait lock nr (0-7) -# lockint lock nr (0-7) -# lockintnowait lock nr (0-7) -# lockcont lock nr (0-7) -# unlock lock nr (0-7) -# lockbkl lock nr (0-7) -# unlockbkl lock nr (0-7) -# signal thread to signal (0-7) -# reset 0 -# resetevent 0 -# -# Tests / Wait -# -# opcode opcode argument -# -# prioeq priority -# priolt priority -# priogt priority -# nprioeq normal priority -# npriolt normal priority -# npriogt normal priority -# locked lock nr (0-7) -# blocked lock nr (0-7) -# blockedwake lock nr (0-7) -# unlocked lock nr (0-7) -# lockedbkl dont care -# blockedbkl dont care -# unlockedbkl dont care -# opcodeeq command opcode or number -# opcodelt number -# opcodegt number -# eventeq number -# eventgt number -# eventlt number - -# -# 5 threads 4 lock PI -# -C: resetevent: 0: 0 -W: opcodeeq: 0: 0 - -# Set schedulers -C: schedother: 0: 0 -C: schedfifo: 1: 81 -C: schedfifo: 2: 82 -C: schedfifo: 3: 83 -C: schedfifo: 4: 84 - -# T0 lock L0 -C: locknowait: 0: 0 -W: locked: 0: 0 - -# T1 lock L1 -C: locknowait: 1: 1 -W: locked: 1: 1 - -# T1 lock L0 -C: lockintnowait: 1: 0 -W: blocked: 1: 0 -T: prioeq: 0: 81 - -# T2 lock L2 -C: locknowait: 2: 2 -W: locked: 2: 2 - -# T2 lock L1 -C: lockintnowait: 2: 1 -W: blocked: 2: 1 -T: prioeq: 0: 82 -T: prioeq: 1: 82 - -# T3 lock L3 -C: locknowait: 3: 3 -W: locked: 3: 3 - -# T3 lock L2 -C: lockintnowait: 3: 2 -W: blocked: 3: 2 -T: prioeq: 0: 83 -T: prioeq: 1: 83 -T: prioeq: 2: 83 - -# T4 lock L3 -C: lockintnowait: 4: 3 -W: blocked: 4: 3 -T: prioeq: 0: 84 -T: prioeq: 1: 84 -T: prioeq: 2: 84 -T: prioeq: 3: 84 - -# Signal T4 -C: signal: 4: 0 -W: unlocked: 4: 3 -T: prioeq: 0: 83 -T: prioeq: 1: 83 -T: prioeq: 2: 83 -T: prioeq: 3: 83 - -# Signal T3 -C: signal: 3: 0 -W: unlocked: 3: 2 -T: prioeq: 0: 82 -T: prioeq: 1: 82 -T: prioeq: 2: 82 - -# Signal T2 -C: signal: 2: 0 -W: unlocked: 2: 1 -T: prioeq: 0: 81 -T: prioeq: 1: 81 - -# Signal T1 -C: signal: 1: 0 -W: unlocked: 1: 0 -T: priolt: 0: 1 - -# Unlock and exit -C: unlock: 3: 3 -C: unlock: 2: 2 -C: unlock: 1: 1 -C: unlock: 0: 0 - -W: unlocked: 3: 3 -W: unlocked: 2: 2 -W: unlocked: 1: 1 -W: unlocked: 0: 0 - diff --git a/trunk/scripts/setlocalversion b/trunk/scripts/setlocalversion index 82e4993f0a73..9a23825218f2 100644 --- a/trunk/scripts/setlocalversion +++ b/trunk/scripts/setlocalversion @@ -11,12 +11,12 @@ cd "${1:-.}" || usage # Check for git and a git repo. if head=`git rev-parse --verify HEAD 2>/dev/null`; then # Do we have an untagged version? - if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then + if [ "`git name-rev --tags HEAD`" = "HEAD undefined" ]; then printf '%s%s' -g `echo "$head" | cut -c1-8` fi # Are there uncommitted changes? - if git diff-index HEAD | read dummy; then + if git diff-files | read dummy; then printf '%s' -dirty fi fi diff --git a/trunk/security/Kconfig b/trunk/security/Kconfig index 67785df264e5..34f593410d57 100644 --- a/trunk/security/Kconfig +++ b/trunk/security/Kconfig @@ -22,22 +22,16 @@ config KEYS If you are unsure as to whether this is required, answer N. config KEYS_DEBUG_PROC_KEYS - bool "Enable the /proc/keys file by which keys may be viewed" + bool "Enable the /proc/keys file by which all keys may be viewed" depends on KEYS help - This option turns on support for the /proc/keys file - through which - can be listed all the keys on the system that are viewable by the - reading process. + This option turns on support for the /proc/keys file through which + all the keys on the system can be listed. - The only keys included in the list are those that grant View - permission to the reading process whether or not it possesses them. - Note that LSM security checks are still performed, and may further - filter out keys that the current process is not authorised to view. - - Only key attributes are listed here; key payloads are not included in - the resulting table. - - If you are unsure as to whether this is required, answer N. + This option is a slight security risk in that it makes it possible + for anyone to see all the keys on the system. Normally the manager + pretends keys that are inaccessible to a process don't exist as far + as that process is concerned. config SECURITY bool "Enable different security models" diff --git a/trunk/security/capability.c b/trunk/security/capability.c index b868e7eda5f0..f9b35cc0b248 100644 --- a/trunk/security/capability.c +++ b/trunk/security/capability.c @@ -8,6 +8,7 @@ * */ +#include #include #include #include diff --git a/trunk/security/commoncap.c b/trunk/security/commoncap.c index f50fc298cf80..841eb4e5c62b 100644 --- a/trunk/security/commoncap.c +++ b/trunk/security/commoncap.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -32,9 +33,9 @@ int cap_netlink_send(struct sock *sk, struct sk_buff *skb) EXPORT_SYMBOL(cap_netlink_send); -int cap_netlink_recv(struct sk_buff *skb, int cap) +int cap_netlink_recv(struct sk_buff *skb) { - if (!cap_raised(NETLINK_CB(skb).eff_cap, cap)) + if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) return -EPERM; return 0; } diff --git a/trunk/security/dummy.c b/trunk/security/dummy.c index bbbfda70e131..c3c5493581e2 100644 --- a/trunk/security/dummy.c +++ b/trunk/security/dummy.c @@ -15,6 +15,7 @@ #undef DEBUG #include +#include #include #include #include @@ -505,9 +506,6 @@ static int dummy_task_getsid (struct task_struct *p) return 0; } -static void dummy_task_getsecid (struct task_struct *p, u32 *secid) -{ } - static int dummy_task_setgroups (struct group_info *group_info) { return 0; @@ -523,11 +521,6 @@ static int dummy_task_setioprio (struct task_struct *p, int ioprio) return 0; } -static int dummy_task_getioprio (struct task_struct *p) -{ - return 0; -} - static int dummy_task_setrlimit (unsigned int resource, struct rlimit *new_rlim) { return 0; @@ -555,7 +548,7 @@ static int dummy_task_wait (struct task_struct *p) } static int dummy_task_kill (struct task_struct *p, struct siginfo *info, - int sig, u32 secid) + int sig) { return 0; } @@ -682,9 +675,9 @@ static int dummy_netlink_send (struct sock *sk, struct sk_buff *skb) return 0; } -static int dummy_netlink_recv (struct sk_buff *skb, int cap) +static int dummy_netlink_recv (struct sk_buff *skb) { - if (!cap_raised (NETLINK_CB (skb).eff_cap, cap)) + if (!cap_raised (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN)) return -EPERM; return 0; } @@ -877,8 +870,7 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz } #ifdef CONFIG_KEYS -static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx, - unsigned long flags) +static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx) { return 0; } @@ -988,11 +980,9 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, task_setpgid); set_to_dummy_if_null(ops, task_getpgid); set_to_dummy_if_null(ops, task_getsid); - set_to_dummy_if_null(ops, task_getsecid); set_to_dummy_if_null(ops, task_setgroups); set_to_dummy_if_null(ops, task_setnice); set_to_dummy_if_null(ops, task_setioprio); - set_to_dummy_if_null(ops, task_getioprio); set_to_dummy_if_null(ops, task_setrlimit); set_to_dummy_if_null(ops, task_setscheduler); set_to_dummy_if_null(ops, task_getscheduler); diff --git a/trunk/security/inode.c b/trunk/security/inode.c index 47eb63480dac..98a0df500dc6 100644 --- a/trunk/security/inode.c +++ b/trunk/security/inode.c @@ -13,6 +13,7 @@ */ /* #define DEBUG */ +#include #include #include #include diff --git a/trunk/security/keys/internal.h b/trunk/security/keys/internal.h index 1bb416f4bbce..e066e6057955 100644 --- a/trunk/security/keys/internal.h +++ b/trunk/security/keys/internal.h @@ -99,9 +99,7 @@ extern int install_process_keyring(struct task_struct *tsk); extern struct key *request_key_and_link(struct key_type *type, const char *description, const char *callout_info, - void *aux, - struct key *dest_keyring, - unsigned long flags); + struct key *dest_keyring); /* * request_key authorisation diff --git a/trunk/security/keys/key.c b/trunk/security/keys/key.c index 80de8c3e9cc3..51f851557389 100644 --- a/trunk/security/keys/key.c +++ b/trunk/security/keys/key.c @@ -11,16 +11,15 @@ #include #include -#include #include #include #include #include -#include #include #include "internal.h" static kmem_cache_t *key_jar; +static key_serial_t key_serial_next = 3; struct rb_root key_serial_tree; /* tree of keys indexed by serial */ DEFINE_SPINLOCK(key_serial_lock); @@ -170,24 +169,23 @@ static void __init __key_insert_serial(struct key *key) /*****************************************************************************/ /* * assign a key the next unique serial number - * - these are assigned randomly to avoid security issues through covert - * channel problems + * - we work through all the serial numbers between 2 and 2^31-1 in turn and + * then wrap */ static inline void key_alloc_serial(struct key *key) { struct rb_node *parent, **p; struct key *xkey; - /* propose a random serial number and look for a hole for it in the - * serial number tree */ - do { - get_random_bytes(&key->serial, sizeof(key->serial)); - - key->serial >>= 1; /* negative numbers are not permitted */ - } while (key->serial < 3); - spin_lock(&key_serial_lock); + /* propose a likely serial number and look for a hole for it in the + * serial number tree */ + key->serial = key_serial_next; + if (key->serial < 3) + key->serial = 3; + key_serial_next = key->serial + 1; + parent = NULL; p = &key_serial_tree.rb_node; @@ -206,11 +204,12 @@ static inline void key_alloc_serial(struct key *key) /* we found a key with the proposed serial number - walk the tree from * that point looking for the next unused serial number */ -serial_exists: + serial_exists: for (;;) { - key->serial++; + key->serial = key_serial_next; if (key->serial < 2) key->serial = 2; + key_serial_next = key->serial + 1; if (!rb_parent(parent)) p = &key_serial_tree.rb_node; @@ -229,7 +228,7 @@ static inline void key_alloc_serial(struct key *key) } /* we've found a suitable hole - arrange for this key to occupy it */ -insert_here: + insert_here: rb_link_node(&key->serial_node, parent, p); rb_insert_color(&key->serial_node, &key_serial_tree); @@ -249,7 +248,7 @@ static inline void key_alloc_serial(struct key *key) */ struct key *key_alloc(struct key_type *type, const char *desc, uid_t uid, gid_t gid, struct task_struct *ctx, - key_perm_t perm, unsigned long flags) + key_perm_t perm, int not_in_quota) { struct key_user *user = NULL; struct key *key; @@ -270,14 +269,12 @@ struct key *key_alloc(struct key_type *type, const char *desc, /* check that the user's quota permits allocation of another key and * its description */ - if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { + if (!not_in_quota) { spin_lock(&user->lock); - if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) { - if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || - user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES - ) - goto no_quota; - } + if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || + user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES + ) + goto no_quota; user->qnkeys++; user->qnbytes += quotalen; @@ -311,7 +308,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->payload.data = NULL; key->security = NULL; - if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) + if (!not_in_quota) key->flags |= 1 << KEY_FLAG_IN_QUOTA; memset(&key->type_data, 0, sizeof(key->type_data)); @@ -321,7 +318,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, #endif /* let the security module know about the key */ - ret = security_key_alloc(key, ctx, flags); + ret = security_key_alloc(key, ctx); if (ret < 0) goto security_error; @@ -335,7 +332,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, security_error: kfree(key->description); kmem_cache_free(key_jar, key); - if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { + if (!not_in_quota) { spin_lock(&user->lock); user->qnkeys--; user->qnbytes -= quotalen; @@ -348,7 +345,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, no_memory_3: kmem_cache_free(key_jar, key); no_memory_2: - if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { + if (!not_in_quota) { spin_lock(&user->lock); user->qnkeys--; user->qnbytes -= quotalen; @@ -764,7 +761,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, const char *description, const void *payload, size_t plen, - unsigned long flags) + int not_in_quota) { struct key_type *ktype; struct key *keyring, *key = NULL; @@ -825,7 +822,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, /* allocate a new key */ key = key_alloc(ktype, description, current->fsuid, current->fsgid, - current, perm, flags); + current, perm, not_in_quota); if (IS_ERR(key)) { key_ref = ERR_PTR(PTR_ERR(key)); goto error_3; @@ -989,7 +986,7 @@ void unregister_key_type(struct key_type *ktype) if (key->type == ktype) { if (ktype->destroy) ktype->destroy(key); - memset(&key->payload, KEY_DESTROY, sizeof(key->payload)); + memset(&key->payload, 0xbd, sizeof(key->payload)); } } diff --git a/trunk/security/keys/keyctl.c b/trunk/security/keys/keyctl.c index d9ca15c109cc..ed71d86d2ce2 100644 --- a/trunk/security/keys/keyctl.c +++ b/trunk/security/keys/keyctl.c @@ -102,7 +102,7 @@ asmlinkage long sys_add_key(const char __user *_type, /* create or update the requested key and add it to the target * keyring */ key_ref = key_create_or_update(keyring_ref, type, description, - payload, plen, KEY_ALLOC_IN_QUOTA); + payload, plen, 0); if (!IS_ERR(key_ref)) { ret = key_ref_to_ptr(key_ref)->serial; key_ref_put(key_ref); @@ -183,9 +183,8 @@ asmlinkage long sys_request_key(const char __user *_type, } /* do the search */ - key = request_key_and_link(ktype, description, callout_info, NULL, - key_ref_to_ptr(dest_ref), - KEY_ALLOC_IN_QUOTA); + key = request_key_and_link(ktype, description, callout_info, + key_ref_to_ptr(dest_ref)); if (IS_ERR(key)) { ret = PTR_ERR(key); goto error5; @@ -673,7 +672,6 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) */ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) { - struct key_user *newowner, *zapowner = NULL; struct key *key; key_ref_t key_ref; long ret; @@ -697,50 +695,19 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) if (!capable(CAP_SYS_ADMIN)) { /* only the sysadmin can chown a key to some other UID */ if (uid != (uid_t) -1 && key->uid != uid) - goto error_put; + goto no_access; /* only the sysadmin can set the key's GID to a group other * than one of those that the current process subscribes to */ if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid)) - goto error_put; + goto no_access; } - /* change the UID */ + /* change the UID (have to update the quotas) */ if (uid != (uid_t) -1 && uid != key->uid) { - ret = -ENOMEM; - newowner = key_user_lookup(uid); - if (!newowner) - goto error_put; - - /* transfer the quota burden to the new user */ - if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { - spin_lock(&newowner->lock); - if (newowner->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || - newowner->qnbytes + key->quotalen >= - KEYQUOTA_MAX_BYTES) - goto quota_overrun; - - newowner->qnkeys++; - newowner->qnbytes += key->quotalen; - spin_unlock(&newowner->lock); - - spin_lock(&key->user->lock); - key->user->qnkeys--; - key->user->qnbytes -= key->quotalen; - spin_unlock(&key->user->lock); - } - - atomic_dec(&key->user->nkeys); - atomic_inc(&newowner->nkeys); - - if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { - atomic_dec(&key->user->nikeys); - atomic_inc(&newowner->nikeys); - } - - zapowner = key->user; - key->user = newowner; - key->uid = uid; + /* don't support UID changing yet */ + ret = -EOPNOTSUPP; + goto no_access; } /* change the GID */ @@ -749,20 +716,12 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) ret = 0; -error_put: + no_access: up_write(&key->sem); key_put(key); - if (zapowner) - key_user_put(zapowner); -error: + error: return ret; -quota_overrun: - spin_unlock(&newowner->lock); - zapowner = newowner; - ret = -EDQUOT; - goto error_put; - } /* end keyctl_chown_key() */ /*****************************************************************************/ diff --git a/trunk/security/keys/keyring.c b/trunk/security/keys/keyring.c index e8d02acc51e7..1357207fc9df 100644 --- a/trunk/security/keys/keyring.c +++ b/trunk/security/keys/keyring.c @@ -49,7 +49,6 @@ static inline unsigned keyring_hash(const char *desc) static int keyring_instantiate(struct key *keyring, const void *data, size_t datalen); static int keyring_match(const struct key *keyring, const void *criterion); -static void keyring_revoke(struct key *keyring); static void keyring_destroy(struct key *keyring); static void keyring_describe(const struct key *keyring, struct seq_file *m); static long keyring_read(const struct key *keyring, @@ -60,7 +59,6 @@ struct key_type key_type_keyring = { .def_datalen = sizeof(struct keyring_list), .instantiate = keyring_instantiate, .match = keyring_match, - .revoke = keyring_revoke, .destroy = keyring_destroy, .describe = keyring_describe, .read = keyring_read, @@ -242,7 +240,7 @@ static long keyring_read(const struct key *keyring, * allocate a keyring and link into the destination keyring */ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, - struct task_struct *ctx, unsigned long flags, + struct task_struct *ctx, int not_in_quota, struct key *dest) { struct key *keyring; @@ -251,7 +249,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, keyring = key_alloc(&key_type_keyring, description, uid, gid, ctx, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, - flags); + not_in_quota); if (!IS_ERR(keyring)) { ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); @@ -955,22 +953,3 @@ int keyring_clear(struct key *keyring) } /* end keyring_clear() */ EXPORT_SYMBOL(keyring_clear); - -/*****************************************************************************/ -/* - * dispose of the links from a revoked keyring - * - called with the key sem write-locked - */ -static void keyring_revoke(struct key *keyring) -{ - struct keyring_list *klist = keyring->payload.subscriptions; - - /* adjust the quota */ - key_payload_reserve(keyring, 0); - - if (klist) { - rcu_assign_pointer(keyring->payload.subscriptions, NULL); - call_rcu(&klist->rcu, keyring_clear_rcu_disposal); - } - -} /* end keyring_revoke() */ diff --git a/trunk/security/keys/proc.c b/trunk/security/keys/proc.c index 686a9ee0c5de..12b750e51fbf 100644 --- a/trunk/security/keys/proc.c +++ b/trunk/security/keys/proc.c @@ -137,13 +137,6 @@ static int proc_keys_show(struct seq_file *m, void *v) struct timespec now; unsigned long timo; char xbuf[12]; - int rc; - - /* check whether the current task is allowed to view the key (assuming - * non-possession) */ - rc = key_task_permission(make_key_ref(key, 0), current, KEY_VIEW); - if (rc < 0) - return 0; now = current_kernel_time(); diff --git a/trunk/security/keys/process_keys.c b/trunk/security/keys/process_keys.c index 32150cf7c37f..4d9825f9962c 100644 --- a/trunk/security/keys/process_keys.c +++ b/trunk/security/keys/process_keys.c @@ -77,8 +77,7 @@ int alloc_uid_keyring(struct user_struct *user, /* concoct a default session keyring */ sprintf(buf, "_uid_ses.%u", user->uid); - session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, - KEY_ALLOC_IN_QUOTA, NULL); + session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, NULL); if (IS_ERR(session_keyring)) { ret = PTR_ERR(session_keyring); goto error; @@ -88,8 +87,8 @@ int alloc_uid_keyring(struct user_struct *user, * keyring */ sprintf(buf, "_uid.%u", user->uid); - uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, - KEY_ALLOC_IN_QUOTA, session_keyring); + uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, + session_keyring); if (IS_ERR(uid_keyring)) { key_put(session_keyring); ret = PTR_ERR(uid_keyring); @@ -145,8 +144,7 @@ int install_thread_keyring(struct task_struct *tsk) sprintf(buf, "_tid.%u", tsk->pid); - keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, - KEY_ALLOC_QUOTA_OVERRUN, NULL); + keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error; @@ -180,8 +178,7 @@ int install_process_keyring(struct task_struct *tsk) if (!tsk->signal->process_keyring) { sprintf(buf, "_pid.%u", tsk->tgid); - keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, - KEY_ALLOC_QUOTA_OVERRUN, NULL); + keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error; @@ -212,7 +209,6 @@ int install_process_keyring(struct task_struct *tsk) static int install_session_keyring(struct task_struct *tsk, struct key *keyring) { - unsigned long flags; struct key *old; char buf[20]; @@ -222,12 +218,7 @@ static int install_session_keyring(struct task_struct *tsk, if (!keyring) { sprintf(buf, "_ses.%u", tsk->tgid); - flags = KEY_ALLOC_QUOTA_OVERRUN; - if (tsk->signal->session_keyring) - flags = KEY_ALLOC_IN_QUOTA; - - keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, - flags, NULL); + keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); if (IS_ERR(keyring)) return PTR_ERR(keyring); } @@ -737,8 +728,7 @@ long join_session_keyring(const char *name) keyring = find_keyring_by_name(name, 0); if (PTR_ERR(keyring) == -ENOKEY) { /* not found - try and create a new one */ - keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, - KEY_ALLOC_IN_QUOTA, NULL); + keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 0, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error2; diff --git a/trunk/security/keys/request_key.c b/trunk/security/keys/request_key.c index f573ac189a0a..eab66a06ca53 100644 --- a/trunk/security/keys/request_key.c +++ b/trunk/security/keys/request_key.c @@ -1,6 +1,6 @@ /* request_key.c: request a key from userspace * - * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -33,8 +33,7 @@ DECLARE_WAIT_QUEUE_HEAD(request_key_conswq); */ static int call_sbin_request_key(struct key *key, struct key *authkey, - const char *op, - void *aux) + const char *op) { struct task_struct *tsk = current; key_serial_t prkey, sskey; @@ -49,8 +48,8 @@ static int call_sbin_request_key(struct key *key, /* allocate a new session keyring */ sprintf(desc, "_req.%u", key->serial); - keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current, - KEY_ALLOC_QUOTA_OVERRUN, NULL); + keyring = keyring_alloc(desc, current->fsuid, current->fsgid, + current, 1, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error_alloc; @@ -127,9 +126,7 @@ static int call_sbin_request_key(struct key *key, */ static struct key *__request_key_construction(struct key_type *type, const char *description, - const char *callout_info, - void *aux, - unsigned long flags) + const char *callout_info) { request_key_actor_t actor; struct key_construction cons; @@ -137,12 +134,12 @@ static struct key *__request_key_construction(struct key_type *type, struct key *key, *authkey; int ret, negated; - kenter("%s,%s,%s,%lx", type->name, description, callout_info, flags); + kenter("%s,%s,%s", type->name, description, callout_info); /* create a key and add it to the queue */ key = key_alloc(type, description, - current->fsuid, current->fsgid, current, KEY_POS_ALL, - flags); + current->fsuid, current->fsgid, + current, KEY_POS_ALL, 0); if (IS_ERR(key)) goto alloc_failed; @@ -166,7 +163,7 @@ static struct key *__request_key_construction(struct key_type *type, actor = call_sbin_request_key; if (type->request_key) actor = type->request_key; - ret = actor(key, authkey, "create", aux); + ret = actor(key, authkey, "create"); if (ret < 0) goto request_failed; @@ -260,18 +257,16 @@ static struct key *__request_key_construction(struct key_type *type, */ static struct key *request_key_construction(struct key_type *type, const char *description, - const char *callout_info, - void *aux, struct key_user *user, - unsigned long flags) + const char *callout_info) { struct key_construction *pcons; struct key *key, *ckey; DECLARE_WAITQUEUE(myself, current); - kenter("%s,%s,{%d},%s,%lx", - type->name, description, user->uid, callout_info, flags); + kenter("%s,%s,{%d},%s", + type->name, description, user->uid, callout_info); /* see if there's such a key under construction already */ down_write(&key_construction_sem); @@ -287,8 +282,7 @@ static struct key *request_key_construction(struct key_type *type, } /* see about getting userspace to construct the key */ - key = __request_key_construction(type, description, callout_info, aux, - flags); + key = __request_key_construction(type, description, callout_info); error: kleave(" = %p", key); return key; @@ -395,17 +389,14 @@ static void request_key_link(struct key *key, struct key *dest_keyring) struct key *request_key_and_link(struct key_type *type, const char *description, const char *callout_info, - void *aux, - struct key *dest_keyring, - unsigned long flags) + struct key *dest_keyring) { struct key_user *user; struct key *key; key_ref_t key_ref; - kenter("%s,%s,%s,%p,%p,%lx", - type->name, description, callout_info, aux, - dest_keyring, flags); + kenter("%s,%s,%s,%p", + type->name, description, callout_info, dest_keyring); /* search all the process keyrings for a key */ key_ref = search_process_keyrings(type, description, type->match, @@ -438,8 +429,7 @@ struct key *request_key_and_link(struct key_type *type, /* ask userspace (returns NULL if it waited on a key * being constructed) */ key = request_key_construction(type, description, - callout_info, aux, - user, flags); + user, callout_info); if (key) break; @@ -495,28 +485,8 @@ struct key *request_key(struct key_type *type, const char *description, const char *callout_info) { - return request_key_and_link(type, description, callout_info, NULL, - NULL, KEY_ALLOC_IN_QUOTA); + return request_key_and_link(type, description, callout_info, NULL); } /* end request_key() */ EXPORT_SYMBOL(request_key); - -/*****************************************************************************/ -/* - * request a key with auxiliary data for the upcaller - * - search the process's keyrings - * - check the list of keys being created or updated - * - call out to userspace for a key if supplementary info was provided - */ -struct key *request_key_with_auxdata(struct key_type *type, - const char *description, - const char *callout_info, - void *aux) -{ - return request_key_and_link(type, description, callout_info, aux, - NULL, KEY_ALLOC_IN_QUOTA); - -} /* end request_key_with_auxdata() */ - -EXPORT_SYMBOL(request_key_with_auxdata); diff --git a/trunk/security/keys/request_key_auth.c b/trunk/security/keys/request_key_auth.c index cbf58a91b00a..cb9817ced3fd 100644 --- a/trunk/security/keys/request_key_auth.c +++ b/trunk/security/keys/request_key_auth.c @@ -187,7 +187,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) authkey = key_alloc(&key_type_request_key_auth, desc, current->fsuid, current->fsgid, current, KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | - KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA); + KEY_USR_VIEW, 1); if (IS_ERR(authkey)) { ret = PTR_ERR(authkey); goto error_alloc; diff --git a/trunk/security/keys/user_defined.c b/trunk/security/keys/user_defined.c index 5bbfdebb7acf..8e71895b97a7 100644 --- a/trunk/security/keys/user_defined.c +++ b/trunk/security/keys/user_defined.c @@ -28,7 +28,6 @@ struct key_type key_type_user = { .instantiate = user_instantiate, .update = user_update, .match = user_match, - .revoke = user_revoke, .destroy = user_destroy, .describe = user_describe, .read = user_read, @@ -68,7 +67,6 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) return ret; } /* end user_instantiate() */ - EXPORT_SYMBOL_GPL(user_instantiate); /*****************************************************************************/ @@ -143,28 +141,7 @@ EXPORT_SYMBOL_GPL(user_match); /*****************************************************************************/ /* - * dispose of the links from a revoked keyring - * - called with the key sem write-locked - */ -void user_revoke(struct key *key) -{ - struct user_key_payload *upayload = key->payload.data; - - /* clear the quota */ - key_payload_reserve(key, 0); - - if (upayload) { - rcu_assign_pointer(key->payload.data, NULL); - call_rcu(&upayload->rcu, user_update_rcu_disposal); - } - -} /* end user_revoke() */ - -EXPORT_SYMBOL(user_revoke); - -/*****************************************************************************/ -/* - * dispose of the data dangling from the corpse of a user key + * dispose of the data dangling from the corpse of a user */ void user_destroy(struct key *key) { diff --git a/trunk/security/root_plug.c b/trunk/security/root_plug.c index 38dd4f3e641f..07651def2f78 100644 --- a/trunk/security/root_plug.c +++ b/trunk/security/root_plug.c @@ -22,6 +22,7 @@ * License. */ +#include #include #include #include diff --git a/trunk/security/seclvl.c b/trunk/security/seclvl.c index c26dd7de0471..441beaf1bbc1 100644 --- a/trunk/security/seclvl.c +++ b/trunk/security/seclvl.c @@ -16,6 +16,7 @@ * (at your option) any later version. */ +#include #include #include #include diff --git a/trunk/security/security.c b/trunk/security/security.c index ee4e0701b6e0..51ef509710b9 100644 --- a/trunk/security/security.c +++ b/trunk/security/security.c @@ -12,6 +12,7 @@ */ #include +#include #include #include #include diff --git a/trunk/security/selinux/hooks.c b/trunk/security/selinux/hooks.c index 24caaeec8894..79c16e31c884 100644 --- a/trunk/security/selinux/hooks.c +++ b/trunk/security/selinux/hooks.c @@ -18,6 +18,7 @@ * as published by the Free Software Foundation. */ +#include #include #include #include @@ -68,7 +69,6 @@ #include #include #include -#include #include "avc.h" #include "objsec.h" @@ -1099,17 +1099,6 @@ static int may_create(struct inode *dir, FILESYSTEM__ASSOCIATE, &ad); } -/* Check whether a task can create a key. */ -static int may_create_key(u32 ksid, - struct task_struct *ctx) -{ - struct task_security_struct *tsec; - - tsec = ctx->security; - - return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL); -} - #define MAY_LINK 0 #define MAY_UNLINK 1 #define MAY_RMDIR 2 @@ -1532,10 +1521,8 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) /* Default to the current task SID. */ bsec->sid = tsec->sid; - /* Reset fs, key, and sock SIDs on execve. */ + /* Reset create SID on execve. */ tsec->create_sid = 0; - tsec->keycreate_sid = 0; - tsec->sockcreate_sid = 0; if (tsec->exec_sid) { newsid = tsec->exec_sid; @@ -2587,11 +2574,9 @@ static int selinux_task_alloc_security(struct task_struct *tsk) tsec2->osid = tsec1->osid; tsec2->sid = tsec1->sid; - /* Retain the exec, fs, key, and sock SIDs across fork */ + /* Retain the exec and create SIDs across fork */ tsec2->exec_sid = tsec1->exec_sid; tsec2->create_sid = tsec1->create_sid; - tsec2->keycreate_sid = tsec1->keycreate_sid; - tsec2->sockcreate_sid = tsec1->sockcreate_sid; /* Retain ptracer SID across fork, if any. This will be reset by the ptrace hook upon any @@ -2643,11 +2628,6 @@ static int selinux_task_getsid(struct task_struct *p) return task_has_perm(current, p, PROCESS__GETSESSION); } -static void selinux_task_getsecid(struct task_struct *p, u32 *secid) -{ - selinux_get_task_sid(p, secid); -} - static int selinux_task_setgroups(struct group_info *group_info) { /* See the comment for setuid above. */ @@ -2670,11 +2650,6 @@ static int selinux_task_setioprio(struct task_struct *p, int ioprio) return task_has_perm(current, p, PROCESS__SETSCHED); } -static int selinux_task_getioprio(struct task_struct *p) -{ - return task_has_perm(current, p, PROCESS__GETSCHED); -} - static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) { struct rlimit *old_rlim = current->signal->rlim + resource; @@ -2709,14 +2684,12 @@ static int selinux_task_movememory(struct task_struct *p) return task_has_perm(current, p, PROCESS__SETSCHED); } -static int selinux_task_kill(struct task_struct *p, struct siginfo *info, - int sig, u32 secid) +static int selinux_task_kill(struct task_struct *p, struct siginfo *info, int sig) { u32 perm; int rc; - struct task_security_struct *tsec; - rc = secondary_ops->task_kill(p, info, sig, secid); + rc = secondary_ops->task_kill(p, info, sig); if (rc) return rc; @@ -2727,12 +2700,8 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info, perm = PROCESS__SIGNULL; /* null signal; existence test */ else perm = signal_to_av(sig); - tsec = p->security; - if (secid) - rc = avc_has_perm(secid, tsec->sid, SECCLASS_PROCESS, perm, NULL); - else - rc = task_has_perm(current, p, perm); - return rc; + + return task_has_perm(current, p, perm); } static int selinux_task_prctl(int option, @@ -2957,14 +2926,12 @@ static int selinux_socket_create(int family, int type, { int err = 0; struct task_security_struct *tsec; - u32 newsid; if (kern) goto out; tsec = current->security; - newsid = tsec->sockcreate_sid ? : tsec->sid; - err = avc_has_perm(tsec->sid, newsid, + err = avc_has_perm(tsec->sid, tsec->sid, socket_type_to_security_class(family, type, protocol), SOCKET__CREATE, NULL); @@ -2977,14 +2944,12 @@ static void selinux_socket_post_create(struct socket *sock, int family, { struct inode_security_struct *isec; struct task_security_struct *tsec; - u32 newsid; isec = SOCK_INODE(sock)->i_security; tsec = current->security; - newsid = tsec->sockcreate_sid ? : tsec->sid; isec->sclass = socket_type_to_security_class(family, type, protocol); - isec->sid = kern ? SECINITSID_KERNEL : newsid; + isec->sid = kern ? SECINITSID_KERNEL : tsec->sid; isec->initialized = 1; return; @@ -3436,13 +3401,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen) { int err = 0; - u32 peer_sid; - - if (skb->sk->sk_family == PF_UNIX) - selinux_get_inode_sid(SOCK_INODE(skb->sk->sk_socket), - &peer_sid); - else - peer_sid = selinux_socket_getpeer_dgram(skb); + u32 peer_sid = selinux_socket_getpeer_dgram(skb); if (peer_sid == SECSID_NULL) return -EINVAL; @@ -3454,6 +3413,8 @@ static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, return 0; } + + static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) { return sk_alloc_security(sk, family, priority); @@ -3661,32 +3622,32 @@ static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum, static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) { + struct task_security_struct *tsec; + struct av_decision avd; int err; err = secondary_ops->netlink_send(sk, skb); if (err) return err; + tsec = current->security; + + avd.allowed = 0; + avc_has_perm_noaudit(tsec->sid, tsec->sid, + SECCLASS_CAPABILITY, ~0, &avd); + cap_mask(NETLINK_CB(skb).eff_cap, avd.allowed); + if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS) err = selinux_nlmsg_perm(sk, skb); return err; } -static int selinux_netlink_recv(struct sk_buff *skb, int capability) +static int selinux_netlink_recv(struct sk_buff *skb) { - int err; - struct avc_audit_data ad; - - err = secondary_ops->netlink_recv(skb, capability); - if (err) - return err; - - AVC_AUDIT_DATA_INIT(&ad, CAP); - ad.u.cap = capability; - - return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, - SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad); + if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) + return -EPERM; + return 0; } static int ipc_alloc_security(struct task_struct *task, @@ -4189,10 +4150,6 @@ static int selinux_getprocattr(struct task_struct *p, sid = tsec->exec_sid; else if (!strcmp(name, "fscreate")) sid = tsec->create_sid; - else if (!strcmp(name, "keycreate")) - sid = tsec->keycreate_sid; - else if (!strcmp(name, "sockcreate")) - sid = tsec->sockcreate_sid; else return -EINVAL; @@ -4225,10 +4182,6 @@ static int selinux_setprocattr(struct task_struct *p, error = task_has_perm(current, p, PROCESS__SETEXEC); else if (!strcmp(name, "fscreate")) error = task_has_perm(current, p, PROCESS__SETFSCREATE); - else if (!strcmp(name, "keycreate")) - error = task_has_perm(current, p, PROCESS__SETKEYCREATE); - else if (!strcmp(name, "sockcreate")) - error = task_has_perm(current, p, PROCESS__SETSOCKCREATE); else if (!strcmp(name, "current")) error = task_has_perm(current, p, PROCESS__SETCURRENT); else @@ -4258,13 +4211,6 @@ static int selinux_setprocattr(struct task_struct *p, tsec->exec_sid = sid; else if (!strcmp(name, "fscreate")) tsec->create_sid = sid; - else if (!strcmp(name, "keycreate")) { - error = may_create_key(sid, p); - if (error) - return error; - tsec->keycreate_sid = sid; - } else if (!strcmp(name, "sockcreate")) - tsec->sockcreate_sid = sid; else if (!strcmp(name, "current")) { struct av_decision avd; @@ -4318,8 +4264,7 @@ static int selinux_setprocattr(struct task_struct *p, #ifdef CONFIG_KEYS -static int selinux_key_alloc(struct key *k, struct task_struct *tsk, - unsigned long flags) +static int selinux_key_alloc(struct key *k, struct task_struct *tsk) { struct task_security_struct *tsec = tsk->security; struct key_security_struct *ksec; @@ -4329,10 +4274,7 @@ static int selinux_key_alloc(struct key *k, struct task_struct *tsk, return -ENOMEM; ksec->obj = k; - if (tsec->keycreate_sid) - ksec->sid = tsec->keycreate_sid; - else - ksec->sid = tsec->sid; + ksec->sid = tsec->sid; k->security = ksec; return 0; @@ -4449,11 +4391,9 @@ static struct security_operations selinux_ops = { .task_setpgid = selinux_task_setpgid, .task_getpgid = selinux_task_getpgid, .task_getsid = selinux_task_getsid, - .task_getsecid = selinux_task_getsecid, .task_setgroups = selinux_task_setgroups, .task_setnice = selinux_task_setnice, .task_setioprio = selinux_task_setioprio, - .task_getioprio = selinux_task_getioprio, .task_setrlimit = selinux_task_setrlimit, .task_setscheduler = selinux_task_setscheduler, .task_getscheduler = selinux_task_getscheduler, @@ -4573,10 +4513,8 @@ static __init int selinux_init(void) #ifdef CONFIG_KEYS /* Add security information to initial keyrings */ - selinux_key_alloc(&root_user_keyring, current, - KEY_ALLOC_NOT_IN_QUOTA); - selinux_key_alloc(&root_session_keyring, current, - KEY_ALLOC_NOT_IN_QUOTA); + security_key_alloc(&root_user_keyring, current); + security_key_alloc(&root_session_keyring, current); #endif return 0; diff --git a/trunk/security/selinux/include/av_perm_to_string.h b/trunk/security/selinux/include/av_perm_to_string.h index 7c9b58380833..bc020bde6c86 100644 --- a/trunk/security/selinux/include/av_perm_to_string.h +++ b/trunk/security/selinux/include/av_perm_to_string.h @@ -72,8 +72,6 @@ S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem") S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack") S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") - S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate") - S_(SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, "setsockcreate") S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") S_(SECCLASS_MSG, MSG__SEND, "send") S_(SECCLASS_MSG, MSG__RECEIVE, "receive") @@ -250,4 +248,3 @@ S_(SECCLASS_KEY, KEY__SEARCH, "search") S_(SECCLASS_KEY, KEY__LINK, "link") S_(SECCLASS_KEY, KEY__SETATTR, "setattr") - S_(SECCLASS_KEY, KEY__CREATE, "create") diff --git a/trunk/security/selinux/include/av_permissions.h b/trunk/security/selinux/include/av_permissions.h index 69fd4b48202c..1205227a3a33 100644 --- a/trunk/security/selinux/include/av_permissions.h +++ b/trunk/security/selinux/include/av_permissions.h @@ -467,8 +467,6 @@ #define PROCESS__EXECMEM 0x02000000UL #define PROCESS__EXECSTACK 0x04000000UL #define PROCESS__EXECHEAP 0x08000000UL -#define PROCESS__SETKEYCREATE 0x10000000UL -#define PROCESS__SETSOCKCREATE 0x20000000UL #define IPC__CREATE 0x00000001UL #define IPC__DESTROY 0x00000002UL @@ -968,4 +966,4 @@ #define KEY__SEARCH 0x00000008UL #define KEY__LINK 0x00000010UL #define KEY__SETATTR 0x00000020UL -#define KEY__CREATE 0x00000040UL + diff --git a/trunk/security/selinux/include/objsec.h b/trunk/security/selinux/include/objsec.h index cf54a304169a..8f5547ad1856 100644 --- a/trunk/security/selinux/include/objsec.h +++ b/trunk/security/selinux/include/objsec.h @@ -32,8 +32,6 @@ struct task_security_struct { u32 sid; /* current SID */ u32 exec_sid; /* exec SID */ u32 create_sid; /* fscreate SID */ - u32 keycreate_sid; /* keycreate SID */ - u32 sockcreate_sid; /* fscreate SID */ u32 ptrace_sid; /* SID of ptrace parent */ }; diff --git a/trunk/security/selinux/selinuxfs.c b/trunk/security/selinux/selinuxfs.c index 00534c302ba2..7029bbc9bef8 100644 --- a/trunk/security/selinux/selinuxfs.c +++ b/trunk/security/selinux/selinuxfs.c @@ -9,6 +9,7 @@ * the Free Software Foundation, version 2. */ +#include #include #include #include diff --git a/trunk/security/selinux/ss/services.c b/trunk/security/selinux/ss/services.c index d2e80e62ff0c..e9548bc049e1 100644 --- a/trunk/security/selinux/ss/services.c +++ b/trunk/security/selinux/ss/services.c @@ -1845,20 +1845,15 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, return -ENOTSUPP; switch (field) { - case AUDIT_SUBJ_USER: - case AUDIT_SUBJ_ROLE: - case AUDIT_SUBJ_TYPE: - case AUDIT_OBJ_USER: - case AUDIT_OBJ_ROLE: - case AUDIT_OBJ_TYPE: + case AUDIT_SE_USER: + case AUDIT_SE_ROLE: + case AUDIT_SE_TYPE: /* only 'equals' and 'not equals' fit user, role, and type */ if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) return -EINVAL; break; - case AUDIT_SUBJ_SEN: - case AUDIT_SUBJ_CLR: - case AUDIT_OBJ_LEV_LOW: - case AUDIT_OBJ_LEV_HIGH: + case AUDIT_SE_SEN: + case AUDIT_SE_CLR: /* we do not allow a range, indicated by the presense of '-' */ if (strchr(rulestr, '-')) return -EINVAL; @@ -1879,34 +1874,29 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, tmprule->au_seqno = latest_granting; switch (field) { - case AUDIT_SUBJ_USER: - case AUDIT_OBJ_USER: + case AUDIT_SE_USER: userdatum = hashtab_search(policydb.p_users.table, rulestr); if (!userdatum) rc = -EINVAL; else tmprule->au_ctxt.user = userdatum->value; break; - case AUDIT_SUBJ_ROLE: - case AUDIT_OBJ_ROLE: + case AUDIT_SE_ROLE: roledatum = hashtab_search(policydb.p_roles.table, rulestr); if (!roledatum) rc = -EINVAL; else tmprule->au_ctxt.role = roledatum->value; break; - case AUDIT_SUBJ_TYPE: - case AUDIT_OBJ_TYPE: + case AUDIT_SE_TYPE: typedatum = hashtab_search(policydb.p_types.table, rulestr); if (!typedatum) rc = -EINVAL; else tmprule->au_ctxt.type = typedatum->value; break; - case AUDIT_SUBJ_SEN: - case AUDIT_SUBJ_CLR: - case AUDIT_OBJ_LEV_LOW: - case AUDIT_OBJ_LEV_HIGH: + case AUDIT_SE_SEN: + case AUDIT_SE_CLR: rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC); break; } @@ -1958,8 +1948,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, /* a field/op pair that is not caught here will simply fall through without a match */ switch (field) { - case AUDIT_SUBJ_USER: - case AUDIT_OBJ_USER: + case AUDIT_SE_USER: switch (op) { case AUDIT_EQUAL: match = (ctxt->user == rule->au_ctxt.user); @@ -1969,8 +1958,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, break; } break; - case AUDIT_SUBJ_ROLE: - case AUDIT_OBJ_ROLE: + case AUDIT_SE_ROLE: switch (op) { case AUDIT_EQUAL: match = (ctxt->role == rule->au_ctxt.role); @@ -1980,8 +1968,7 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, break; } break; - case AUDIT_SUBJ_TYPE: - case AUDIT_OBJ_TYPE: + case AUDIT_SE_TYPE: switch (op) { case AUDIT_EQUAL: match = (ctxt->type == rule->au_ctxt.type); @@ -1991,12 +1978,9 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, break; } break; - case AUDIT_SUBJ_SEN: - case AUDIT_SUBJ_CLR: - case AUDIT_OBJ_LEV_LOW: - case AUDIT_OBJ_LEV_HIGH: - level = ((field == AUDIT_SUBJ_SEN || - field == AUDIT_OBJ_LEV_LOW) ? + case AUDIT_SE_SEN: + case AUDIT_SE_CLR: + level = (field == AUDIT_SE_SEN ? &ctxt->range.level[0] : &ctxt->range.level[1]); switch (op) { case AUDIT_EQUAL: diff --git a/trunk/security/selinux/xfrm.c b/trunk/security/selinux/xfrm.c index 6c985ced8102..6633fb059313 100644 --- a/trunk/security/selinux/xfrm.c +++ b/trunk/security/selinux/xfrm.c @@ -26,6 +26,7 @@ * 2. Emulating a reasonable SO_PEERSEC across machines * 3. Testing addition of sk_policy's with security context via setsockopt */ +#include #include #include #include diff --git a/trunk/sound/Makefile b/trunk/sound/Makefile index 1f60797afa8a..a682ea30f0c9 100644 --- a/trunk/sound/Makefile +++ b/trunk/sound/Makefile @@ -4,8 +4,7 @@ obj-$(CONFIG_SOUND) += soundcore.o obj-$(CONFIG_SOUND_PRIME) += oss/ obj-$(CONFIG_DMASOUND) += oss/ -obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ -obj-$(CONFIG_SND_AOA) += aoa/ +obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ aoa/ ifeq ($(CONFIG_SND),y) obj-y += last.o diff --git a/trunk/sound/aoa/Kconfig b/trunk/sound/aoa/Kconfig index 2f4334d19ccd..a85194fe0b06 100644 --- a/trunk/sound/aoa/Kconfig +++ b/trunk/sound/aoa/Kconfig @@ -3,8 +3,7 @@ menu "Apple Onboard Audio driver" config SND_AOA tristate "Apple Onboard Audio driver" - depends on SND - select SND_PCM + depends on SOUND && SND_PCM ---help--- This option enables the new driver for the various Apple Onboard Audio components. diff --git a/trunk/sound/aoa/core/snd-aoa-gpio-feature.c b/trunk/sound/aoa/core/snd-aoa-gpio-feature.c index 7ae0c0bdfad8..2c6eb7784cc9 100644 --- a/trunk/sound/aoa/core/snd-aoa-gpio-feature.c +++ b/trunk/sound/aoa/core/snd-aoa-gpio-feature.c @@ -112,7 +112,12 @@ static struct device_node *get_gpio(char *name, static void get_irq(struct device_node * np, int *irqptr) { - *irqptr = irq_of_parse_and_map(np, 0); + *irqptr = -1; + if (!np) + return; + if (np->n_intrs != 1) + return; + *irqptr = np->intrs[0].line; } /* 0x4 is outenable, 0x1 is out, thus 4 or 5 */ @@ -202,17 +207,6 @@ static void ftr_handle_notify(void *data) mutex_unlock(¬if->mutex); } -static void gpio_enable_dual_edge(int gpio) -{ - int v; - - if (gpio == -1) - return; - v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0); - v |= 0x80; /* enable dual edge */ - pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, gpio, v); -} - static void ftr_gpio_init(struct gpio_runtime *rt) { get_gpio("headphone-mute", NULL, @@ -240,10 +234,6 @@ static void ftr_gpio_init(struct gpio_runtime *rt) &linein_detect_gpio, &linein_detect_gpio_activestate); - gpio_enable_dual_edge(headphone_detect_gpio); - gpio_enable_dual_edge(lineout_detect_gpio); - gpio_enable_dual_edge(linein_detect_gpio); - get_irq(headphone_detect_node, &headphone_detect_irq); get_irq(lineout_detect_node, &lineout_detect_irq); get_irq(linein_detect_node, &linein_detect_irq); diff --git a/trunk/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/trunk/sound/aoa/fabrics/snd-aoa-fabric-layout.c index cbc8a3b5cea4..04a7238e9494 100644 --- a/trunk/sound/aoa/fabrics/snd-aoa-fabric-layout.c +++ b/trunk/sound/aoa/fabrics/snd-aoa-fabric-layout.c @@ -94,7 +94,6 @@ MODULE_ALIAS("sound-layout-82"); MODULE_ALIAS("sound-layout-84"); MODULE_ALIAS("sound-layout-86"); MODULE_ALIAS("sound-layout-92"); -MODULE_ALIAS("sound-layout-96"); /* onyx with all but microphone connected */ static struct codec_connection onyx_connections_nomic[] = { @@ -382,13 +381,6 @@ static struct layout layouts[] = { .connections = toonie_connections, }, }, - { - .layout_id = 96, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, /* unknown, untested, but this comes from Apple */ { .layout_id = 41, .codecs[0] = { @@ -487,6 +479,12 @@ static struct layout layouts[] = { .connections = onyx_connections_noheadphones, }, }, + { .layout_id = 96, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, { .layout_id = 98, .codecs[0] = { .name = "toonie", diff --git a/trunk/sound/aoa/soundbus/Kconfig b/trunk/sound/aoa/soundbus/Kconfig index 7368b7ddfe0d..d532d27a9f54 100644 --- a/trunk/sound/aoa/soundbus/Kconfig +++ b/trunk/sound/aoa/soundbus/Kconfig @@ -1,7 +1,6 @@ config SND_AOA_SOUNDBUS tristate "Apple Soundbus support" - depends on SOUND - select SND_PCM + depends on SOUND && SND_PCM && EXPERIMENTAL ---help--- This option enables the generic driver for the soundbus support on Apple machines. diff --git a/trunk/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/trunk/sound/aoa/soundbus/i2sbus/i2sbus-core.c index 01c0724335a3..f268dacdaa00 100644 --- a/trunk/sound/aoa/soundbus/i2sbus/i2sbus-core.c +++ b/trunk/sound/aoa/soundbus/i2sbus/i2sbus-core.c @@ -129,7 +129,7 @@ static int i2sbus_add_dev(struct macio_dev *macio, if (strncmp(np->name, "i2s-", 4)) return 0; - if (macio_irq_count(macio) != 3) + if (np->n_intrs != 3) return 0; dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL); @@ -183,10 +183,9 @@ static int i2sbus_add_dev(struct macio_dev *macio, snprintf(dev->rnames[i], sizeof(dev->rnames[i]), rnames[i], np->name); } for (i=0;i<3;i++) { - if (request_irq(macio_irq(macio, i), ints[i], 0, - dev->rnames[i], dev)) + if (request_irq(np->intrs[i].line, ints[i], 0, dev->rnames[i], dev)) goto err; - dev->interrupts[i] = macio_irq(macio, i); + dev->interrupts[i] = np->intrs[i].line; } for (i=0;i<3;i++) { diff --git a/trunk/sound/arm/aaci.c b/trunk/sound/arm/aaci.c index 8435fdd1c87c..5f22d70fefc0 100644 --- a/trunk/sound/arm/aaci.c +++ b/trunk/sound/arm/aaci.c @@ -360,7 +360,7 @@ static int aaci_pcm_open(struct aaci *aaci, struct snd_pcm_substream *substream, if (ret) goto out; - ret = request_irq(aaci->dev->irq[0], aaci_irq, IRQF_SHARED|IRQF_DISABLED, + ret = request_irq(aaci->dev->irq[0], aaci_irq, SA_SHIRQ|SA_INTERRUPT, DRIVER_NAME, aaci); if (ret) goto out; @@ -779,9 +779,8 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev) strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver)); strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), - "%s at 0x%016llx, irq %d", - card->shortname, (unsigned long long)dev->res.start, - dev->irq[0]); + "%s at 0x%08lx, irq %d", + card->shortname, dev->res.start, dev->irq[0]); aaci = card->private_data; mutex_init(&aaci->ac97_sem); diff --git a/trunk/sound/arm/sa11xx-uda1341.c b/trunk/sound/arm/sa11xx-uda1341.c index c79a9afd0955..b88fb0c5a68a 100644 --- a/trunk/sound/arm/sa11xx-uda1341.c +++ b/trunk/sound/arm/sa11xx-uda1341.c @@ -59,6 +59,7 @@ * ***************************************************************************************************/ +#include #include #include #include diff --git a/trunk/sound/core/Kconfig b/trunk/sound/core/Kconfig index b2927523d79d..4262a1c87731 100644 --- a/trunk/sound/core/Kconfig +++ b/trunk/sound/core/Kconfig @@ -122,8 +122,8 @@ config SND_SEQ_RTCTIMER_DEFAULT If in doubt, say Y. config SND_DYNAMIC_MINORS - bool "Dynamic device file minor numbers" - depends on SND + bool "Dynamic device file minor numbers (EXPERIMENTAL)" + depends on SND && EXPERIMENTAL help If you say Y here, the minor numbers of ALSA device files in /dev/snd/ are allocated dynamically. This allows you to have diff --git a/trunk/sound/core/info.c b/trunk/sound/core/info.c index 340332c6d973..10c1772bf3ea 100644 --- a/trunk/sound/core/info.c +++ b/trunk/sound/core/info.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/trunk/sound/core/memalloc.c b/trunk/sound/core/memalloc.c index bc0bd0910a62..3fc6f97075ed 100644 --- a/trunk/sound/core/memalloc.c +++ b/trunk/sound/core/memalloc.c @@ -21,6 +21,7 @@ * */ +#include #include #include #include diff --git a/trunk/sound/core/seq/seq_memory.h b/trunk/sound/core/seq/seq_memory.h index 63e91431a29f..39c60d9e1efc 100644 --- a/trunk/sound/core/seq/seq_memory.h +++ b/trunk/sound/core/seq/seq_memory.h @@ -31,7 +31,7 @@ struct snd_seq_event_cell { struct snd_seq_event_cell *next; /* next cell */ }; -/* design note: the pool is a contiguous block of memory, if we dynamicly +/* design note: the pool is a contigious block of memory, if we dynamicly want to add additional cells to the pool be better store this in another pool as we need to know the base address of the pool when releasing memory. */ diff --git a/trunk/sound/core/seq/seq_ports.c b/trunk/sound/core/seq/seq_ports.c index d467b4f0ff2b..334579a9f268 100644 --- a/trunk/sound/core/seq/seq_ports.c +++ b/trunk/sound/core/seq/seq_ports.c @@ -322,8 +322,10 @@ int snd_seq_delete_all_ports(struct snd_seq_client *client) mutex_lock(&client->ports_mutex); write_lock_irqsave(&client->ports_lock, flags); if (! list_empty(&client->ports_list_head)) { - list_add(&deleted_list, &client->ports_list_head); - list_del_init(&client->ports_list_head); + __list_add(&deleted_list, + client->ports_list_head.prev, + client->ports_list_head.next); + INIT_LIST_HEAD(&client->ports_list_head); } else { INIT_LIST_HEAD(&deleted_list); } diff --git a/trunk/sound/core/sgbuf.c b/trunk/sound/core/sgbuf.c index 6e4d4ab34632..74745da9deb6 100644 --- a/trunk/sound/core/sgbuf.c +++ b/trunk/sound/core/sgbuf.c @@ -19,6 +19,7 @@ * */ +#include #include #include #include diff --git a/trunk/sound/core/sound.c b/trunk/sound/core/sound.c index 264f2efd1af8..cd862728346c 100644 --- a/trunk/sound/core/sound.c +++ b/trunk/sound/core/sound.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #define SNDRV_OS_MINORS 256 @@ -41,6 +42,7 @@ int snd_major; EXPORT_SYMBOL(snd_major); static int cards_limit = 1; +static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO; MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("Advanced Linux Sound Architecture driver for soundcards."); @@ -49,6 +51,10 @@ module_param(major, int, 0444); MODULE_PARM_DESC(major, "Major # for sound driver."); module_param(cards_limit, int, 0444); MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards."); +#ifdef CONFIG_DEVFS_FS +module_param(device_mode, int, 0444); +MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs."); +#endif MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR); /* this one holds the actual max. card number currently available. @@ -267,6 +273,8 @@ int snd_register_device(int type, struct snd_card *card, int dev, return minor; } snd_minors[minor] = preg; + if (type != SNDRV_DEVICE_TYPE_CONTROL || preg->card >= cards_limit) + devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name); if (card) device = card->dev; class_device_create(sound_class, NULL, MKDEV(major, minor), device, "%s", name); @@ -306,6 +314,9 @@ int snd_unregister_device(int type, struct snd_card *card, int dev) return -EINVAL; } + if (mptr->type != SNDRV_DEVICE_TYPE_CONTROL || + mptr->card >= cards_limit) /* created in sound.c */ + devfs_remove("snd/%s", mptr->name); class_device_destroy(sound_class, MKDEV(major, minor)); snd_minors[minor] = NULL; @@ -400,17 +411,24 @@ int __exit snd_minor_info_done(void) static int __init alsa_sound_init(void) { + short controlnum; + snd_major = major; snd_ecards_limit = cards_limit; + devfs_mk_dir("snd"); if (register_chrdev(major, "alsa", &snd_fops)) { snd_printk(KERN_ERR "unable to register native major device number %d\n", major); + devfs_remove("snd"); return -EIO; } if (snd_info_init() < 0) { unregister_chrdev(major, "alsa"); + devfs_remove("snd"); return -ENOMEM; } snd_info_minor_register(); + for (controlnum = 0; controlnum < cards_limit; controlnum++) + devfs_mk_cdev(MKDEV(major, controlnum<<5), S_IFCHR | device_mode, "snd/controlC%d", controlnum); #ifndef MODULE printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"); #endif @@ -419,10 +437,16 @@ static int __init alsa_sound_init(void) static void __exit alsa_sound_exit(void) { + short controlnum; + + for (controlnum = 0; controlnum < cards_limit; controlnum++) + devfs_remove("snd/controlC%d", controlnum); + snd_info_minor_unregister(); snd_info_done(); if (unregister_chrdev(major, "alsa") != 0) snd_printk(KERN_ERR "unable to unregister major device number %d\n", major); + devfs_remove("snd"); } module_init(alsa_sound_init) diff --git a/trunk/sound/drivers/mpu401/mpu401.c b/trunk/sound/drivers/mpu401/mpu401.c index 17cc105b26fc..d3cbbb047582 100644 --- a/trunk/sound/drivers/mpu401/mpu401.c +++ b/trunk/sound/drivers/mpu401/mpu401.c @@ -83,7 +83,7 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard) if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0, - irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0, NULL)) < 0) { + irq[dev], irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL)) < 0) { printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]); goto _err; } @@ -160,9 +160,8 @@ static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device, return -ENODEV; } if (pnp_port_len(device, 0) < IO_EXTENT) { - snd_printk(KERN_ERR "PnP port length is %llu, expected %d\n", - (unsigned long long)pnp_port_len(device, 0), - IO_EXTENT); + snd_printk(KERN_ERR "PnP port length is %ld, expected %d\n", + pnp_port_len(device, 0), IO_EXTENT); return -ENODEV; } port[dev] = pnp_port_start(device, 0); diff --git a/trunk/sound/drivers/mtpav.c b/trunk/sound/drivers/mtpav.c index e064d6c5685b..474eed06e70f 100644 --- a/trunk/sound/drivers/mtpav.c +++ b/trunk/sound/drivers/mtpav.c @@ -590,7 +590,7 @@ static int __init snd_mtpav_get_ISA(struct mtpav * mcard) return -EBUSY; } mcard->port = port; - if (request_irq(irq, snd_mtpav_irqh, IRQF_DISABLED, "MOTU MTPAV", mcard)) { + if (request_irq(irq, snd_mtpav_irqh, SA_INTERRUPT, "MOTU MTPAV", mcard)) { snd_printk("MTVAP IRQ %d busy\n", irq); return -EBUSY; } diff --git a/trunk/sound/drivers/serial-u16550.c b/trunk/sound/drivers/serial-u16550.c index 52afb4bd2079..2330fec505da 100644 --- a/trunk/sound/drivers/serial-u16550.c +++ b/trunk/sound/drivers/serial-u16550.c @@ -795,7 +795,7 @@ static int __init snd_uart16550_create(struct snd_card *card, if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { if (request_irq(irq, snd_uart16550_interrupt, - IRQF_DISABLED, "Serial MIDI", (void *) uart)) { + SA_INTERRUPT, "Serial MIDI", (void *) uart)) { snd_printk("irq %d busy. Using Polling.\n", irq); } else { uart->irq = irq; diff --git a/trunk/sound/i2c/other/ak4xxx-adda.c b/trunk/sound/i2c/other/ak4xxx-adda.c index dc7cc2001b74..045e32a311e0 100644 --- a/trunk/sound/i2c/other/ak4xxx-adda.c +++ b/trunk/sound/i2c/other/ak4xxx-adda.c @@ -34,8 +34,7 @@ MODULE_AUTHOR("Jaroslav Kysela , Takashi Iwai "); MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); MODULE_LICENSE("GPL"); -void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, - unsigned char val) +void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsigned char val) { ak->ops.lock(ak, chip); ak->ops.write(ak, chip, reg, val); @@ -53,67 +52,6 @@ void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, ak->ops.unlock(ak, chip); } -EXPORT_SYMBOL(snd_akm4xxx_write); - -/* reset procedure for AK4524 and AK4528 */ -static void ak4524_reset(struct snd_akm4xxx *ak, int state) -{ - unsigned int chip; - unsigned char reg, maxreg; - - if (ak->type == SND_AK4528) - maxreg = 0x06; - else - maxreg = 0x08; - for (chip = 0; chip < ak->num_dacs/2; chip++) { - snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); - if (state) - continue; - /* DAC volumes */ - for (reg = 0x04; reg < maxreg; reg++) - snd_akm4xxx_write(ak, chip, reg, - snd_akm4xxx_get(ak, chip, reg)); - if (ak->type == SND_AK4528) - continue; - /* IPGA */ - for (reg = 0x04; reg < 0x06; reg++) - snd_akm4xxx_write(ak, chip, reg, - snd_akm4xxx_get_ipga(ak, chip, reg)); - } -} - -/* reset procedure for AK4355 and AK4358 */ -static void ak4355_reset(struct snd_akm4xxx *ak, int state) -{ - unsigned char reg; - - if (state) { - snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ - return; - } - for (reg = 0x00; reg < 0x0b; reg++) - if (reg != 0x01) - snd_akm4xxx_write(ak, 0, reg, - snd_akm4xxx_get(ak, 0, reg)); - snd_akm4xxx_write(ak, 0, 0x01, 0x01); /* un-reset, unmute */ -} - -/* reset procedure for AK4381 */ -static void ak4381_reset(struct snd_akm4xxx *ak, int state) -{ - unsigned int chip; - unsigned char reg; - - for (chip = 0; chip < ak->num_dacs/2; chip++) { - snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); - if (state) - continue; - for (reg = 0x01; reg < 0x05; reg++) - snd_akm4xxx_write(ak, chip, reg, - snd_akm4xxx_get(ak, chip, reg)); - } -} - /* * reset the AKM codecs * @state: 1 = reset codec, 0 = restore the registers @@ -122,26 +60,52 @@ static void ak4381_reset(struct snd_akm4xxx *ak, int state) */ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state) { + unsigned int chip; + unsigned char reg; + switch (ak->type) { case SND_AK4524: case SND_AK4528: - ak4524_reset(ak, state); + for (chip = 0; chip < ak->num_dacs/2; chip++) { + snd_akm4xxx_write(ak, chip, 0x01, state ? 0x00 : 0x03); + if (state) + continue; + /* DAC volumes */ + for (reg = 0x04; reg < (ak->type == SND_AK4528 ? 0x06 : 0x08); reg++) + snd_akm4xxx_write(ak, chip, reg, snd_akm4xxx_get(ak, chip, reg)); + if (ak->type == SND_AK4528) + continue; + /* IPGA */ + for (reg = 0x04; reg < 0x06; reg++) + snd_akm4xxx_write(ak, chip, reg, snd_akm4xxx_get_ipga(ak, chip, reg)); + } break; case SND_AK4529: /* FIXME: needed for ak4529? */ break; case SND_AK4355: case SND_AK4358: - ak4355_reset(ak, state); + if (state) { + snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */ + return; + } + for (reg = 0x00; reg < 0x0b; reg++) + if (reg != 0x01) + snd_akm4xxx_write(ak, 0, reg, snd_akm4xxx_get(ak, 0, reg)); + snd_akm4xxx_write(ak, 0, 0x01, 0x01); /* un-reset, unmute */ break; case SND_AK4381: - ak4381_reset(ak, state); + for (chip = 0; chip < ak->num_dacs/2; chip++) { + snd_akm4xxx_write(ak, chip, 0x00, state ? 0x0c : 0x0f); + if (state) + continue; + for (reg = 0x01; reg < 0x05; reg++) + snd_akm4xxx_write(ak, chip, reg, snd_akm4xxx_get(ak, chip, reg)); + } break; } } -EXPORT_SYMBOL(snd_akm4xxx_reset); - /* * initialize all the ak4xxx chips */ @@ -189,8 +153,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) }; static unsigned char inits_ak4355[] = { 0x01, 0x02, /* 1: reset and soft-mute */ - 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, - * disable DZF, sharp roll-off, RSTN#=0 */ + 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, disable DZF, sharp roll-off, RSTN#=0 */ 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */ // 0x02, 0x2e, /* quad speed */ 0x03, 0x01, /* 3: de-emphasis off */ @@ -206,8 +169,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) }; static unsigned char inits_ak4358[] = { 0x01, 0x02, /* 1: reset and soft-mute */ - 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, - * disable DZF, sharp roll-off, RSTN#=0 */ + 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, disable DZF, sharp roll-off, RSTN#=0 */ 0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */ // 0x02, 0x2e, /* quad speed */ 0x03, 0x01, /* 3: de-emphasis off */ @@ -225,8 +187,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) }; static unsigned char inits_ak4381[] = { 0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */ - 0x01, 0x02, /* 1: de-emphasis off, normal speed, - * sharp roll-off, DZF off */ + 0x01, 0x02, /* 1: de-emphasis off, normal speed, sharp roll-off, DZF off */ // 0x01, 0x12, /* quad speed */ 0x02, 0x00, /* 2: DZF disabled */ 0x03, 0x00, /* 3: LATT 0 */ @@ -278,15 +239,12 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) } } -EXPORT_SYMBOL(snd_akm4xxx_init); - #define AK_GET_CHIP(val) (((val) >> 8) & 0xff) #define AK_GET_ADDR(val) ((val) & 0xff) #define AK_GET_SHIFT(val) (((val) >> 16) & 0x7f) #define AK_GET_INVERT(val) (((val) >> 23) & 1) #define AK_GET_MASK(val) (((val) >> 24) & 0xff) -#define AK_COMPOSE(chip,addr,shift,mask) \ - (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24)) +#define AK_COMPOSE(chip,addr,shift,mask) (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24)) #define AK_INVERT (1<<23) static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol, @@ -334,64 +292,6 @@ static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, return change; } -static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - unsigned int mask = AK_GET_MASK(kcontrol->private_value); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = mask; - return 0; -} - -static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - int invert = AK_GET_INVERT(kcontrol->private_value); - unsigned int mask = AK_GET_MASK(kcontrol->private_value); - unsigned char val = snd_akm4xxx_get(ak, chip, addr); - - ucontrol->value.integer.value[0] = invert ? mask - val : val; - - val = snd_akm4xxx_get(ak, chip, addr+1); - ucontrol->value.integer.value[1] = invert ? mask - val : val; - - return 0; -} - -static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - int invert = AK_GET_INVERT(kcontrol->private_value); - unsigned int mask = AK_GET_MASK(kcontrol->private_value); - unsigned char nval = ucontrol->value.integer.value[0] % (mask+1); - int change0, change1; - - if (invert) - nval = mask - nval; - change0 = snd_akm4xxx_get(ak, chip, addr) != nval; - if (change0) - snd_akm4xxx_write(ak, chip, addr, nval); - - nval = ucontrol->value.integer.value[1] % (mask+1); - if (invert) - nval = mask - nval; - change1 = snd_akm4xxx_get(ak, chip, addr+1) != nval; - if (change1) - snd_akm4xxx_write(ak, chip, addr+1, nval); - - - return change0 || change1; -} - static int snd_akm4xxx_ipga_gain_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -408,8 +308,7 @@ static int snd_akm4xxx_ipga_gain_get(struct snd_kcontrol *kcontrol, struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); int chip = AK_GET_CHIP(kcontrol->private_value); int addr = AK_GET_ADDR(kcontrol->private_value); - ucontrol->value.integer.value[0] = - snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f; + ucontrol->value.integer.value[0] = snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f; return 0; } @@ -437,8 +336,7 @@ static int snd_akm4xxx_deemphasis_info(struct snd_kcontrol *kcontrol, uinfo->value.enumerated.items = 4; if (uinfo->value.enumerated.item >= 4) uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0; } @@ -449,8 +347,7 @@ static int snd_akm4xxx_deemphasis_get(struct snd_kcontrol *kcontrol, int chip = AK_GET_CHIP(kcontrol->private_value); int addr = AK_GET_ADDR(kcontrol->private_value); int shift = AK_GET_SHIFT(kcontrol->private_value); - ucontrol->value.enumerated.item[0] = - (snd_akm4xxx_get(ak, chip, addr) >> shift) & 3; + ucontrol->value.enumerated.item[0] = (snd_akm4xxx_get(ak, chip, addr) >> shift) & 3; return 0; } @@ -464,8 +361,7 @@ static int snd_akm4xxx_deemphasis_put(struct snd_kcontrol *kcontrol, unsigned char nval = ucontrol->value.enumerated.item[0] & 3; int change; - nval = (nval << shift) | - (snd_akm4xxx_get(ak, chip, addr) & ~(3 << shift)); + nval = (nval << shift) | (snd_akm4xxx_get(ak, chip, addr) & ~(3 << shift)); change = snd_akm4xxx_get(ak, chip, addr) != nval; if (change) snd_akm4xxx_write(ak, chip, addr, nval); @@ -481,86 +377,51 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) unsigned int idx, num_emphs; struct snd_kcontrol *ctl; int err; - int mixer_ch = 0; - int num_stereo; ctl = kmalloc(sizeof(*ctl), GFP_KERNEL); if (! ctl) return -ENOMEM; - for (idx = 0; idx < ak->num_dacs; ) { + for (idx = 0; idx < ak->num_dacs; ++idx) { memset(ctl, 0, sizeof(*ctl)); - if (ak->channel_names == NULL) { - strcpy(ctl->id.name, "DAC Volume"); - num_stereo = 1; - ctl->id.index = mixer_ch + ak->idx_offset * 2; - } else { - strcpy(ctl->id.name, ak->channel_names[mixer_ch]); - num_stereo = ak->num_stereo[mixer_ch]; - ctl->id.index = 0; - } + strcpy(ctl->id.name, "DAC Volume"); + ctl->id.index = idx + ak->idx_offset * 2; ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; ctl->count = 1; - if (num_stereo == 2) { - ctl->info = snd_akm4xxx_stereo_volume_info; - ctl->get = snd_akm4xxx_stereo_volume_get; - ctl->put = snd_akm4xxx_stereo_volume_put; - } else { - ctl->info = snd_akm4xxx_volume_info; - ctl->get = snd_akm4xxx_volume_get; - ctl->put = snd_akm4xxx_volume_put; - } + ctl->info = snd_akm4xxx_volume_info; + ctl->get = snd_akm4xxx_volume_get; + ctl->put = snd_akm4xxx_volume_put; switch (ak->type) { case SND_AK4524: - /* register 6 & 7 */ - ctl->private_value = - AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); + ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */ break; case SND_AK4528: - /* register 4 & 5 */ - ctl->private_value = - AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); + ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */ break; case SND_AK4529: { - /* registers 2-7 and b,c */ - int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; - ctl->private_value = - AK_COMPOSE(0, val, 0, 255) | AK_INVERT; + int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; /* registers 2-7 and b,c */ + ctl->private_value = AK_COMPOSE(0, val, 0, 255) | AK_INVERT; break; } case SND_AK4355: - /* register 4-9, chip #0 only */ - ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); + ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */ break; case SND_AK4358: if (idx >= 6) - /* register 4-9, chip #0 only */ - ctl->private_value = - AK_COMPOSE(0, idx + 5, 0, 255); + ctl->private_value = AK_COMPOSE(0, idx + 5, 0, 255); /* register 4-9, chip #0 only */ else - /* register 4-9, chip #0 only */ - ctl->private_value = - AK_COMPOSE(0, idx + 4, 0, 255); + ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */ break; case SND_AK4381: - /* register 3 & 4 */ - ctl->private_value = - AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); + ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); /* register 3 & 4 */ break; default: err = -EINVAL; goto __error; } - ctl->private_data = ak; - err = snd_ctl_add(ak->card, - snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| - SNDRV_CTL_ELEM_ACCESS_WRITE)); - if (err < 0) + if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0) goto __error; - - idx += num_stereo; - mixer_ch++; } for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) { memset(ctl, 0, sizeof(*ctl)); @@ -571,14 +432,9 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) ctl->info = snd_akm4xxx_volume_info; ctl->get = snd_akm4xxx_volume_get; ctl->put = snd_akm4xxx_volume_put; - /* register 4 & 5 */ - ctl->private_value = - AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); + ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); /* register 4 & 5 */ ctl->private_data = ak; - err = snd_ctl_add(ak->card, - snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| - SNDRV_CTL_ELEM_ACCESS_WRITE)); - if (err < 0) + if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0) goto __error; memset(ctl, 0, sizeof(*ctl)); @@ -589,13 +445,9 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) ctl->info = snd_akm4xxx_ipga_gain_info; ctl->get = snd_akm4xxx_ipga_gain_get; ctl->put = snd_akm4xxx_ipga_gain_put; - /* register 4 & 5 */ - ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); + ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); /* register 4 & 5 */ ctl->private_data = ak; - err = snd_ctl_add(ak->card, - snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| - SNDRV_CTL_ELEM_ACCESS_WRITE)); - if (err < 0) + if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0) goto __error; } if (ak->type == SND_AK4355 || ak->type == SND_AK4358) @@ -614,13 +466,11 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) switch (ak->type) { case SND_AK4524: case SND_AK4528: - /* register 3 */ - ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); + ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); /* register 3 */ break; case SND_AK4529: { int shift = idx == 3 ? 6 : (2 - idx) * 2; - /* register 8 with shift */ - ctl->private_value = AK_COMPOSE(0, 8, shift, 0); + ctl->private_value = AK_COMPOSE(0, 8, shift, 0); /* register 8 with shift */ break; } case SND_AK4355: @@ -632,10 +482,7 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) break; } ctl->private_data = ak; - err = snd_ctl_add(ak->card, - snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| - SNDRV_CTL_ELEM_ACCESS_WRITE)); - if (err < 0) + if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0) goto __error; } err = 0; @@ -645,8 +492,6 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) return err; } -EXPORT_SYMBOL(snd_akm4xxx_build_controls); - static int __init alsa_akm4xxx_module_init(void) { return 0; @@ -658,3 +503,8 @@ static void __exit alsa_akm4xxx_module_exit(void) module_init(alsa_akm4xxx_module_init) module_exit(alsa_akm4xxx_module_exit) + +EXPORT_SYMBOL(snd_akm4xxx_write); +EXPORT_SYMBOL(snd_akm4xxx_reset); +EXPORT_SYMBOL(snd_akm4xxx_init); +EXPORT_SYMBOL(snd_akm4xxx_build_controls); diff --git a/trunk/sound/isa/ad1816a/ad1816a.c b/trunk/sound/isa/ad1816a/ad1816a.c index b33a5fb59ec2..31f299aed281 100644 --- a/trunk/sound/isa/ad1816a/ad1816a.c +++ b/trunk/sound/isa/ad1816a/ad1816a.c @@ -232,7 +232,7 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard if (mpu_port[dev] > 0) { if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - mpu_port[dev], 0, mpu_irq[dev], IRQF_DISABLED, + mpu_port[dev], 0, mpu_irq[dev], SA_INTERRUPT, NULL) < 0) printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", mpu_port[dev]); } diff --git a/trunk/sound/isa/ad1816a/ad1816a_lib.c b/trunk/sound/isa/ad1816a/ad1816a_lib.c index 8fcf2c151823..fd8fe16c09ee 100644 --- a/trunk/sound/isa/ad1816a/ad1816a_lib.c +++ b/trunk/sound/isa/ad1816a/ad1816a_lib.c @@ -599,7 +599,7 @@ int __devinit snd_ad1816a_create(struct snd_card *card, snd_ad1816a_free(chip); return -EBUSY; } - if (request_irq(irq, snd_ad1816a_interrupt, IRQF_DISABLED, "AD1816A", (void *) chip)) { + if (request_irq(irq, snd_ad1816a_interrupt, SA_INTERRUPT, "AD1816A", (void *) chip)) { snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq); snd_ad1816a_free(chip); return -EBUSY; diff --git a/trunk/sound/isa/ad1848/ad1848_lib.c b/trunk/sound/isa/ad1848/ad1848_lib.c index e711f87d5fd1..e0f8baa843b9 100644 --- a/trunk/sound/isa/ad1848/ad1848_lib.c +++ b/trunk/sound/isa/ad1848/ad1848_lib.c @@ -902,7 +902,7 @@ int snd_ad1848_create(struct snd_card *card, snd_ad1848_free(chip); return -EBUSY; } - if (request_irq(irq, snd_ad1848_interrupt, IRQF_DISABLED, "AD1848", (void *) chip)) { + if (request_irq(irq, snd_ad1848_interrupt, SA_INTERRUPT, "AD1848", (void *) chip)) { snd_printk(KERN_ERR "ad1848: can't grab IRQ %d\n", irq); snd_ad1848_free(chip); return -EBUSY; diff --git a/trunk/sound/isa/als100.c b/trunk/sound/isa/als100.c index f2bcfb2cf5f5..a52bd8a14c9b 100644 --- a/trunk/sound/isa/als100.c +++ b/trunk/sound/isa/als100.c @@ -250,7 +250,7 @@ static int __devinit snd_card_als100_probe(int dev, if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { if (snd_mpu401_uart_new(card, 0, MPU401_HW_ALS100, mpu_port[dev], 0, - mpu_irq[dev], IRQF_DISABLED, + mpu_irq[dev], SA_INTERRUPT, NULL) < 0) snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]); } diff --git a/trunk/sound/isa/azt2320.c b/trunk/sound/isa/azt2320.c index b615538a928d..15e59283aac6 100644 --- a/trunk/sound/isa/azt2320.c +++ b/trunk/sound/isa/azt2320.c @@ -279,7 +279,7 @@ static int __devinit snd_card_azt2320_probe(int dev, if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) { if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320, mpu_port[dev], 0, - mpu_irq[dev], IRQF_DISABLED, + mpu_irq[dev], SA_INTERRUPT, NULL) < 0) snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]); } diff --git a/trunk/sound/isa/cs423x/cs4231.c b/trunk/sound/isa/cs423x/cs4231.c index 696a5c86bcfa..397310f358b7 100644 --- a/trunk/sound/isa/cs423x/cs4231.c +++ b/trunk/sound/isa/cs423x/cs4231.c @@ -122,7 +122,7 @@ static int __init snd_cs4231_probe(struct platform_device *pdev) if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, mpu_port[dev], 0, mpu_irq[dev], - mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0, + mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0) printk(KERN_WARNING "cs4231: MPU401 not detected\n"); } diff --git a/trunk/sound/isa/cs423x/cs4231_lib.c b/trunk/sound/isa/cs423x/cs4231_lib.c index fbb20176cca4..823db8246701 100644 --- a/trunk/sound/isa/cs423x/cs4231_lib.c +++ b/trunk/sound/isa/cs423x/cs4231_lib.c @@ -1454,7 +1454,7 @@ int snd_cs4231_create(struct snd_card *card, return -ENODEV; } chip->cport = cport; - if (!(hwshare & CS4231_HWSHARE_IRQ) && request_irq(irq, snd_cs4231_interrupt, IRQF_DISABLED, "CS4231", (void *) chip)) { + if (!(hwshare & CS4231_HWSHARE_IRQ) && request_irq(irq, snd_cs4231_interrupt, SA_INTERRUPT, "CS4231", (void *) chip)) { snd_printk(KERN_ERR "cs4231: can't grab IRQ %d\n", irq); snd_cs4231_free(chip); return -EBUSY; diff --git a/trunk/sound/isa/cs423x/cs4236.c b/trunk/sound/isa/cs423x/cs4236.c index 07ffd5c22e81..f7fa779347ff 100644 --- a/trunk/sound/isa/cs423x/cs4236.c +++ b/trunk/sound/isa/cs423x/cs4236.c @@ -535,7 +535,7 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev) if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232, mpu_port[dev], 0, mpu_irq[dev], - mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0, NULL) < 0) + mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0) printk(KERN_WARNING IDENT ": MPU401 not detected\n"); } diff --git a/trunk/sound/isa/dt019x.c b/trunk/sound/isa/dt019x.c index c20a4b1b1536..0acb4e5da47f 100644 --- a/trunk/sound/isa/dt019x.c +++ b/trunk/sound/isa/dt019x.c @@ -240,7 +240,7 @@ static int __devinit snd_card_dt019x_probe(int dev, struct pnp_card_link *pcard, MPU401_HW_MPU401, mpu_port[dev], 0, mpu_irq[dev], - mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0, + mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0) snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx ?\n", mpu_port[dev]); } diff --git a/trunk/sound/isa/es1688/es1688.c b/trunk/sound/isa/es1688/es1688.c index 7f29f56e405b..e90689ee162f 100644 --- a/trunk/sound/isa/es1688/es1688.c +++ b/trunk/sound/isa/es1688/es1688.c @@ -153,7 +153,7 @@ static int __init snd_es1688_probe(struct platform_device *pdev) if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, chip->mpu_port, 0, xmpu_irq, - IRQF_DISABLED, + SA_INTERRUPT, NULL)) < 0) goto _err; } diff --git a/trunk/sound/isa/es1688/es1688_lib.c b/trunk/sound/isa/es1688/es1688_lib.c index 7e985d3bc510..702ad51ee9d5 100644 --- a/trunk/sound/isa/es1688/es1688_lib.c +++ b/trunk/sound/isa/es1688/es1688_lib.c @@ -659,7 +659,7 @@ int snd_es1688_create(struct snd_card *card, snd_es1688_free(chip); return -EBUSY; } - if (request_irq(irq, snd_es1688_interrupt, IRQF_DISABLED, "ES1688", (void *) chip)) { + if (request_irq(irq, snd_es1688_interrupt, SA_INTERRUPT, "ES1688", (void *) chip)) { snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq); snd_es1688_free(chip); return -EBUSY; diff --git a/trunk/sound/isa/es18xx.c b/trunk/sound/isa/es18xx.c index 34998de9968c..e6945db8ed1b 100644 --- a/trunk/sound/isa/es18xx.c +++ b/trunk/sound/isa/es18xx.c @@ -1837,7 +1837,7 @@ static int __devinit snd_es18xx_new_device(struct snd_card *card, return -EBUSY; } - if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx", (void *) chip)) { + if (request_irq(irq, snd_es18xx_interrupt, SA_INTERRUPT, "ES18xx", (void *) chip)) { snd_es18xx_free(chip); snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq); return -EBUSY; @@ -2088,8 +2088,7 @@ static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard, kfree(cfg); return -EAGAIN; } - snd_printdd("pnp: port=0x%llx\n", - (unsigned long long)pnp_port_start(acard->devc, 0)); + snd_printdd("pnp: port=0x%lx\n", pnp_port_start(acard->devc, 0)); /* PnP initialization */ pdev = acard->dev; pnp_init_resource_table(cfg); diff --git a/trunk/sound/isa/gus/gus_main.c b/trunk/sound/isa/gus/gus_main.c index b680fddf0d74..53eeaf37007d 100644 --- a/trunk/sound/isa/gus/gus_main.c +++ b/trunk/sound/isa/gus/gus_main.c @@ -179,7 +179,7 @@ int snd_gus_create(struct snd_card *card, snd_gus_free(gus); return -EBUSY; } - if (irq >= 0 && request_irq(irq, snd_gus_interrupt, IRQF_DISABLED, "GUS GF1", (void *) gus)) { + if (irq >= 0 && request_irq(irq, snd_gus_interrupt, SA_INTERRUPT, "GUS GF1", (void *) gus)) { snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq); snd_gus_free(gus); return -EBUSY; diff --git a/trunk/sound/isa/gus/gusextreme.c b/trunk/sound/isa/gus/gusextreme.c index 22cdddbfd824..05852fcc613b 100644 --- a/trunk/sound/isa/gus/gusextreme.c +++ b/trunk/sound/isa/gus/gusextreme.c @@ -301,7 +301,7 @@ static int __init snd_gusextreme_probe(struct platform_device *pdev) (err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688, es1688->mpu_port, 0, xmpu_irq, - IRQF_DISABLED, + SA_INTERRUPT, NULL)) < 0) goto out; diff --git a/trunk/sound/isa/gus/gusmax.c b/trunk/sound/isa/gus/gusmax.c index ac11cae8589a..fcf2c8fe6f94 100644 --- a/trunk/sound/isa/gus/gusmax.c +++ b/trunk/sound/isa/gus/gusmax.c @@ -292,7 +292,7 @@ static int __init snd_gusmax_probe(struct platform_device *pdev) goto _err; } - if (request_irq(xirq, snd_gusmax_interrupt, IRQF_DISABLED, "GUS MAX", (void *)maxcard)) { + if (request_irq(xirq, snd_gusmax_interrupt, SA_INTERRUPT, "GUS MAX", (void *)maxcard)) { snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); err = -EBUSY; goto _err; diff --git a/trunk/sound/isa/gus/interwave.c b/trunk/sound/isa/gus/interwave.c index ea69f25506fb..866300f2acbb 100644 --- a/trunk/sound/isa/gus/interwave.c +++ b/trunk/sound/isa/gus/interwave.c @@ -611,10 +611,10 @@ static int __devinit snd_interwave_pnp(int dev, struct snd_interwave *iwcard, if (dma2[dev] >= 0) dma2[dev] = pnp_dma(pdev, 1); irq[dev] = pnp_irq(pdev, 0); - snd_printdd("isapnp IW: sb port=0x%llx, gf1 port=0x%llx, codec port=0x%llx\n", - (unsigned long long)pnp_port_start(pdev, 0), - (unsigned long long)pnp_port_start(pdev, 1), - (unsigned long long)pnp_port_start(pdev, 2)); + snd_printdd("isapnp IW: sb port=0x%lx, gf1 port=0x%lx, codec port=0x%lx\n", + pnp_port_start(pdev, 0), + pnp_port_start(pdev, 1), + pnp_port_start(pdev, 2)); snd_printdd("isapnp IW: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]); #ifdef SNDRV_STB /* Tone Control initialization */ @@ -706,7 +706,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev) if ((err = snd_gus_initialize(gus)) < 0) return err; - if (request_irq(xirq, snd_interwave_interrupt, IRQF_DISABLED, + if (request_irq(xirq, snd_interwave_interrupt, SA_INTERRUPT, "InterWave", iwcard)) { snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq); return -EBUSY; diff --git a/trunk/sound/isa/opl3sa2.c b/trunk/sound/isa/opl3sa2.c index 4031b61b797f..647a996791e9 100644 --- a/trunk/sound/isa/opl3sa2.c +++ b/trunk/sound/isa/opl3sa2.c @@ -683,7 +683,7 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev) chip->single_dma = 1; if ((err = snd_opl3sa2_detect(chip)) < 0) return err; - if (request_irq(xirq, snd_opl3sa2_interrupt, IRQF_DISABLED, "OPL3-SA2", chip)) { + if (request_irq(xirq, snd_opl3sa2_interrupt, SA_INTERRUPT, "OPL3-SA2", chip)) { snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq); return -ENODEV; } diff --git a/trunk/sound/isa/opti9xx/miro.c b/trunk/sound/isa/opti9xx/miro.c index 1dd98375ac85..283817f2de75 100644 --- a/trunk/sound/isa/opti9xx/miro.c +++ b/trunk/sound/isa/opti9xx/miro.c @@ -1382,7 +1382,7 @@ static int __init snd_miro_probe(struct platform_device *devptr) rmidi = NULL; else if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - miro->mpu_port, 0, miro->mpu_irq, IRQF_DISABLED, + miro->mpu_port, 0, miro->mpu_irq, SA_INTERRUPT, &rmidi))) snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", miro->mpu_port); diff --git a/trunk/sound/isa/opti9xx/opti92x-ad1848.c b/trunk/sound/isa/opti9xx/opti92x-ad1848.c index 9d528ae00bff..8ee0d70536f9 100644 --- a/trunk/sound/isa/opti9xx/opti92x-ad1848.c +++ b/trunk/sound/isa/opti9xx/opti92x-ad1848.c @@ -1291,7 +1291,7 @@ static int snd_opti93x_create(struct snd_card *card, struct snd_opti9xx *chip, } codec->dma2 = chip->dma2; - if (request_irq(chip->irq, snd_opti93x_interrupt, IRQF_DISABLED, DRIVER_NAME" - WSS", codec)) { + if (request_irq(chip->irq, snd_opti93x_interrupt, SA_INTERRUPT, DRIVER_NAME" - WSS", codec)) { snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq); snd_opti93x_free(codec); return -EBUSY; @@ -1863,7 +1863,7 @@ static int __init snd_opti9xx_probe(struct snd_card *card) rmidi = NULL; else if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, - chip->mpu_port, 0, chip->mpu_irq, IRQF_DISABLED, + chip->mpu_port, 0, chip->mpu_irq, SA_INTERRUPT, &rmidi))) snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", chip->mpu_port); diff --git a/trunk/sound/isa/sb/sb16.c b/trunk/sound/isa/sb/sb16.c index d64e67f2bafa..7f7f05fa518a 100644 --- a/trunk/sound/isa/sb/sb16.c +++ b/trunk/sound/isa/sb/sb16.c @@ -327,8 +327,7 @@ static int __devinit snd_card_sb16_pnp(int dev, struct snd_card_sb16 *acard, goto __wt_error; } awe_port[dev] = pnp_port_start(pdev, 0); - snd_printdd("pnp SB16: wavetable port=0x%llx\n", - (unsigned long long)pnp_port_start(pdev, 0)); + snd_printdd("pnp SB16: wavetable port=0x%lx\n", pnp_port_start(pdev, 0)); } else { __wt_error: if (pdev) { diff --git a/trunk/sound/isa/sb/sb_common.c b/trunk/sound/isa/sb/sb_common.c index f17de2bdd9e0..f343a8211d2d 100644 --- a/trunk/sound/isa/sb/sb_common.c +++ b/trunk/sound/isa/sb/sb_common.c @@ -232,7 +232,7 @@ int snd_sbdsp_create(struct snd_card *card, chip->port = port; if (request_irq(irq, irq_handler, hardware == SB_HW_ALS4000 ? - IRQF_DISABLED | IRQF_SHARED : IRQF_DISABLED, + SA_INTERRUPT | SA_SHIRQ : SA_INTERRUPT, "SoundBlaster", (void *) chip)) { snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq); snd_sbdsp_free(chip); diff --git a/trunk/sound/isa/sgalaxy.c b/trunk/sound/isa/sgalaxy.c index 8742fa517491..09c8e8c6b5e3 100644 --- a/trunk/sound/isa/sgalaxy.c +++ b/trunk/sound/isa/sgalaxy.c @@ -147,7 +147,7 @@ static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma) if (tmp < 0) return -EINVAL; - if (request_irq(irq, snd_sgalaxy_dummy_interrupt, IRQF_DISABLED, "sgalaxy", NULL)) { + if (request_irq(irq, snd_sgalaxy_dummy_interrupt, SA_INTERRUPT, "sgalaxy", NULL)) { snd_printk(KERN_ERR "sgalaxy: can't grab irq %d\n", irq); return -EIO; } diff --git a/trunk/sound/isa/sscape.c b/trunk/sound/isa/sscape.c index b1f25823c652..27271c9446dc 100644 --- a/trunk/sound/isa/sscape.c +++ b/trunk/sound/isa/sscape.c @@ -900,7 +900,7 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l if ((err = snd_mpu401_uart_new(card, devnum, MPU401_HW_MPU401, port, MPU401_INFO_INTEGRATED, - irq, IRQF_DISABLED, + irq, SA_INTERRUPT, &rawmidi)) == 0) { struct snd_mpu401 *mpu = (struct snd_mpu401 *) rawmidi->private_data; mpu->open_input = mpu401_open; diff --git a/trunk/sound/isa/wavefront/wavefront.c b/trunk/sound/isa/wavefront/wavefront.c index a8f8d2fa9d76..9eb27082c659 100644 --- a/trunk/sound/isa/wavefront/wavefront.c +++ b/trunk/sound/isa/wavefront/wavefront.c @@ -467,7 +467,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) return -EBUSY; } if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt, - IRQF_DISABLED, "ICS2115", acard)) { + SA_INTERRUPT, "ICS2115", acard)) { snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]); return -EBUSY; } @@ -497,7 +497,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) if ((err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232, cs4232_mpu_port[dev], 0, cs4232_mpu_irq[dev], - IRQF_DISABLED, + SA_INTERRUPT, NULL)) < 0) { snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n"); return err; diff --git a/trunk/sound/mips/au1x00.c b/trunk/sound/mips/au1x00.c index c31b38659221..cf476fe1ac56 100644 --- a/trunk/sound/mips/au1x00.c +++ b/trunk/sound/mips/au1x00.c @@ -465,13 +465,13 @@ snd_au1000_pcm_new(struct snd_au1000 *au1000) flags = claim_dma_lock(); if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX, - "AC97 TX", au1000_dma_interrupt, IRQF_DISABLED, + "AC97 TX", au1000_dma_interrupt, SA_INTERRUPT, au1000->stream[PLAYBACK])) < 0) { release_dma_lock(flags); return -EBUSY; } if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX, - "AC97 RX", au1000_dma_interrupt, IRQF_DISABLED, + "AC97 RX", au1000_dma_interrupt, SA_INTERRUPT, au1000->stream[CAPTURE])) < 0){ release_dma_lock(flags); return -EBUSY; diff --git a/trunk/sound/oss/Kconfig b/trunk/sound/oss/Kconfig index f4980ca5c05c..95754e2f71b8 100644 --- a/trunk/sound/oss/Kconfig +++ b/trunk/sound/oss/Kconfig @@ -493,19 +493,6 @@ config SOUND_CS4232 See for more information on configuring this card. -config SOUND_SSCAPE - tristate "Ensoniq SoundScape support" - depends on SOUND_OSS - help - Answer Y if you have a sound card based on the Ensoniq SoundScape - chipset. Such cards are being manufactured at least by Ensoniq, Spea - and Reveal (Reveal makes also other cards). - - If you compile the driver into the kernel, you have to add - "sscape=,,,," to the kernel command - line. - - config SOUND_VMIDI tristate "Loopback MIDI device support" depends on SOUND_OSS @@ -852,6 +839,6 @@ config SOUND_SH_DAC_AUDIO depends on SOUND_PRIME && CPU_SH3 config SOUND_SH_DAC_AUDIO_CHANNEL - int "DAC channel" + int " DAC channel" default "1" depends on SOUND_SH_DAC_AUDIO diff --git a/trunk/sound/oss/ad1816.c b/trunk/sound/oss/ad1816.c index 29057836c644..95586de02028 100644 --- a/trunk/sound/oss/ad1816.c +++ b/trunk/sound/oss/ad1816.c @@ -41,6 +41,7 @@ */ +#include #include #include #include diff --git a/trunk/sound/oss/ad1848.c b/trunk/sound/oss/ad1848.c index 3b45e11e5303..e04fa49b0dc8 100644 --- a/trunk/sound/oss/ad1848.c +++ b/trunk/sound/oss/ad1848.c @@ -41,6 +41,7 @@ * Tested. Believed fully functional. */ +#include #include #include #include diff --git a/trunk/sound/oss/ad1889.c b/trunk/sound/oss/ad1889.c index f56f870b4840..a4ca7569e700 100644 --- a/trunk/sound/oss/ad1889.c +++ b/trunk/sound/oss/ad1889.c @@ -26,6 +26,7 @@ * * $Id: ad1889.c,v 1.3 2002/10/19 21:31:44 grundler Exp $ */ +#include #include #include #include @@ -1010,7 +1011,7 @@ static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_devic goto out2; } - if (request_irq(pcidev->irq, ad1889_interrupt, IRQF_SHARED, DEVNAME, dev) != 0) { + if (request_irq(pcidev->irq, ad1889_interrupt, SA_SHIRQ, DEVNAME, dev) != 0) { printk(KERN_ERR DEVNAME ": unable to request interrupt\n"); goto out3; } diff --git a/trunk/sound/oss/aedsp16.c b/trunk/sound/oss/aedsp16.c index 51e1fde62e8d..b556263a57f5 100644 --- a/trunk/sound/oss/aedsp16.c +++ b/trunk/sound/oss/aedsp16.c @@ -23,6 +23,7 @@ * Include the main OSS Lite header file. It include all the os, OSS Lite, etc * headers needed by this source. */ +#include #include #include #include diff --git a/trunk/sound/oss/ali5455.c b/trunk/sound/oss/ali5455.c index 70dcd703a66f..62bb936b1f3d 100644 --- a/trunk/sound/oss/ali5455.c +++ b/trunk/sound/oss/ali5455.c @@ -3460,7 +3460,7 @@ static int __devinit ali_probe(struct pci_dev *pci_dev, card->channel[4].num = 4; /* claim our iospace and irq */ request_region(card->iobase, 256, card_names[pci_id->driver_data]); - if (request_irq(card->irq, &ali_interrupt, IRQF_SHARED, + if (request_irq(card->irq, &ali_interrupt, SA_SHIRQ, card_names[pci_id->driver_data], card)) { printk(KERN_ERR "ali_audio: unable to allocate irq %d\n", card->irq); diff --git a/trunk/sound/oss/au1000.c b/trunk/sound/oss/au1000.c index e3796231452a..eacb0aef21e1 100644 --- a/trunk/sound/oss/au1000.c +++ b/trunk/sound/oss/au1000.c @@ -2015,14 +2015,14 @@ static int __devinit au1000_probe(void) if ((s->dma_dac.dmanr = request_au1000_dma(DMA_ID_AC97C_TX, "audio DAC", dac_dma_interrupt, - IRQF_DISABLED, s)) < 0) { + SA_INTERRUPT, s)) < 0) { err("Can't get DAC DMA"); goto err_dma1; } if ((s->dma_adc.dmanr = request_au1000_dma(DMA_ID_AC97C_RX, "audio ADC", adc_dma_interrupt, - IRQF_DISABLED, s)) < 0) { + SA_INTERRUPT, s)) < 0) { err("Can't get ADC DMA"); goto err_dma2; } diff --git a/trunk/sound/oss/btaudio.c b/trunk/sound/oss/btaudio.c index 324a81fd3a3b..bfe3b534ef30 100644 --- a/trunk/sound/oss/btaudio.c +++ b/trunk/sound/oss/btaudio.c @@ -966,7 +966,7 @@ static int __devinit btaudio_probe(struct pci_dev *pci_dev, btwrite(~0U, REG_INT_STAT); pci_set_master(pci_dev); - if ((rc = request_irq(bta->irq, btaudio_irq, IRQF_SHARED|IRQF_DISABLED, + if ((rc = request_irq(bta->irq, btaudio_irq, SA_SHIRQ|SA_INTERRUPT, "btaudio",(void *)bta)) < 0) { printk(KERN_WARNING "btaudio: can't request irq (rc=%d)\n",rc); diff --git a/trunk/sound/oss/cmpci.c b/trunk/sound/oss/cmpci.c index ea51aafaf401..de60a059ff5f 100644 --- a/trunk/sound/oss/cmpci.c +++ b/trunk/sound/oss/cmpci.c @@ -3122,7 +3122,7 @@ static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id wrmixer(s, DSP_MIX_DATARESETIDX, 0); /* request irq */ - if ((ret = request_irq(s->irq, cm_interrupt, IRQF_SHARED, "cmpci", s))) { + if ((ret = request_irq(s->irq, cm_interrupt, SA_SHIRQ, "cmpci", s))) { printk(KERN_ERR "cmpci: irq %u in use\n", s->irq); goto err_irq; } diff --git a/trunk/sound/oss/cs4232.c b/trunk/sound/oss/cs4232.c index b6924c7f1484..c7f86f09c28d 100644 --- a/trunk/sound/oss/cs4232.c +++ b/trunk/sound/oss/cs4232.c @@ -47,6 +47,7 @@ * Marcus Meissner Added ISA PnP support. */ +#include #include #include #include @@ -404,7 +405,7 @@ static const struct pnp_device_id cs4232_pnp_table[] = { MODULE_DEVICE_TABLE(pnp, cs4232_pnp_table); -static int __init cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) +static int cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { struct address_info *isapnpcfg; diff --git a/trunk/sound/oss/cs4281/cs4281m.c b/trunk/sound/oss/cs4281/cs4281m.c index 0400a416dc93..0004442f9b7e 100644 --- a/trunk/sound/oss/cs4281/cs4281m.c +++ b/trunk/sound/oss/cs4281/cs4281m.c @@ -4346,7 +4346,7 @@ static int __devinit cs4281_probe(struct pci_dev *pcidev, s->pcidev = pcidev; s->irq = pcidev->irq; if (request_irq - (s->irq, cs4281_interrupt, IRQF_SHARED, "Crystal CS4281", s)) { + (s->irq, cs4281_interrupt, SA_SHIRQ, "Crystal CS4281", s)) { CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR "cs4281: irq %u in use\n", s->irq)); goto err_irq; diff --git a/trunk/sound/oss/cs46xx.c b/trunk/sound/oss/cs46xx.c index 5195bf933cb8..994c71e986e4 100644 --- a/trunk/sound/oss/cs46xx.c +++ b/trunk/sound/oss/cs46xx.c @@ -5177,7 +5177,7 @@ static int __devinit cs46xx_probe(struct pci_dev *pci_dev, card->ba1.name.reg == 0) goto fail2; - if (request_irq(card->irq, &cs_interrupt, IRQF_SHARED, "cs46xx", card)) { + if (request_irq(card->irq, &cs_interrupt, SA_SHIRQ, "cs46xx", card)) { printk(KERN_ERR "cs46xx: unable to allocate irq %d\n", card->irq); goto fail2; } diff --git a/trunk/sound/oss/dmabuf.c b/trunk/sound/oss/dmabuf.c index 15ce7119c5f4..baf4244a54f2 100644 --- a/trunk/sound/oss/dmabuf.c +++ b/trunk/sound/oss/dmabuf.c @@ -547,7 +547,7 @@ int DMAbuf_activate_recording(int dev, struct dma_buffparms *dmap) } return 0; } -/* acquires lock */ +/* aquires lock */ int DMAbuf_getrdbuffer(int dev, char **buf, int *len, int dontblock) { struct audio_operations *adev = audio_devs[dev]; @@ -821,7 +821,7 @@ static int find_output_space(int dev, char **buf, int *size) *size = len & ~SAMPLE_ROUNDUP; return (*size > 0); } -/* acquires lock */ +/* aquires lock */ int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock) { struct audio_operations *adev = audio_devs[dev]; @@ -855,7 +855,7 @@ int DMAbuf_getwrbuffer(int dev, char **buf, int *size, int dontblock) spin_unlock_irqrestore(&dmap->lock,flags); return 0; } -/* has to acquire dmap->lock */ +/* has to aquire dmap->lock */ int DMAbuf_move_wrpointer(int dev, int l) { struct audio_operations *adev = audio_devs[dev]; diff --git a/trunk/sound/oss/dmasound/dmasound.h b/trunk/sound/oss/dmasound/dmasound.h index 25dd5a318eb4..a1b0b92af4b5 100644 --- a/trunk/sound/oss/dmasound/dmasound.h +++ b/trunk/sound/oss/dmasound/dmasound.h @@ -13,6 +13,7 @@ #define _dmasound_h_ #include +#include #define SND_NDEVS 256 /* Number of supported devices */ #define SND_DEV_CTL 0 /* Control port /dev/mixer */ diff --git a/trunk/sound/oss/dmasound/dmasound_awacs.c b/trunk/sound/oss/dmasound/dmasound_awacs.c index 4359903f4376..c8e210326893 100644 --- a/trunk/sound/oss/dmasound/dmasound_awacs.c +++ b/trunk/sound/oss/dmasound/dmasound_awacs.c @@ -67,6 +67,7 @@ #include #include +#include #include #include #include @@ -374,7 +375,10 @@ setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int* *gpio_pol = *pp; else *gpio_pol = 1; - return irq_of_parse_and_map(np, 0); + if (np->n_intrs > 0) + return np->intrs[0].line; + + return 0; } static inline void @@ -2861,13 +2865,14 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); * other info if necessary (early AWACS we want to read chip ids) */ - if (of_get_address(io, 2, NULL, NULL) == NULL) { + if (of_get_address(io, 2, NULL, NULL) == NULL || io->n_intrs < 3) { /* OK - maybe we need to use the 'awacs' node (on earlier * machines). */ if (awacs_node) { io = awacs_node ; - if (of_get_address(io, 2, NULL, NULL) == NULL) { + if (of_get_address(io, 2, NULL, NULL) == NULL || + io->n_intrs < 3) { printk("dmasound_pmac: can't use %s\n", io->full_name); return -ENODEV; @@ -2936,9 +2941,9 @@ printk("dmasound_pmac: couldn't find a Codec we can handle\n"); if (awacs_revision == AWACS_SCREAMER && awacs) awacs_recalibrate(); - awacs_irq = irq_of_parse_and_map(io, 0); - awacs_tx_irq = irq_of_parse_and_map(io, 1); - awacs_rx_irq = irq_of_parse_and_map(io, 2); + awacs_irq = io->intrs[0].line; + awacs_tx_irq = io->intrs[1].line; + awacs_rx_irq = io->intrs[2].line; /* Hack for legacy crap that will be killed someday */ awacs_node = io; diff --git a/trunk/sound/oss/dmasound/dmasound_paula.c b/trunk/sound/oss/dmasound/dmasound_paula.c index 68e1d8f6c359..494070a3f870 100644 --- a/trunk/sound/oss/dmasound/dmasound_paula.c +++ b/trunk/sound/oss/dmasound/dmasound_paula.c @@ -16,6 +16,7 @@ #include +#include #include #include #include diff --git a/trunk/sound/oss/emu10k1/main.c b/trunk/sound/oss/emu10k1/main.c index c4ce94d6e10c..3721c5857b90 100644 --- a/trunk/sound/oss/emu10k1/main.c +++ b/trunk/sound/oss/emu10k1/main.c @@ -1301,7 +1301,7 @@ static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_dev card->pci_dev = pci_dev; /* Reserve IRQ Line */ - if (request_irq(card->irq, emu10k1_interrupt, IRQF_SHARED, card_names[pci_id->driver_data], card)) { + if (request_irq(card->irq, emu10k1_interrupt, SA_SHIRQ, card_names[pci_id->driver_data], card)) { printk(KERN_ERR "emu10k1: IRQ in use\n"); ret = -EBUSY; goto err_irq; diff --git a/trunk/sound/oss/es1370.c b/trunk/sound/oss/es1370.c index 13f483149737..094f569cc6e0 100644 --- a/trunk/sound/oss/es1370.c +++ b/trunk/sound/oss/es1370.c @@ -2650,7 +2650,7 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic ret = -EBUSY; goto err_region; } - if ((ret=request_irq(s->irq, es1370_interrupt, IRQF_SHARED, "es1370",s))) { + if ((ret=request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370",s))) { printk(KERN_ERR "es1370: irq %u in use\n", s->irq); goto err_irq; } diff --git a/trunk/sound/oss/es1371.c b/trunk/sound/oss/es1371.c index a2ffe723dad5..4400c8538686 100644 --- a/trunk/sound/oss/es1371.c +++ b/trunk/sound/oss/es1371.c @@ -2905,7 +2905,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic res = -EBUSY; goto err_region; } - if ((res=request_irq(s->irq, es1371_interrupt, IRQF_SHARED, "es1371",s))) { + if ((res=request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371",s))) { printk(KERN_ERR PFX "irq %u in use\n", s->irq); goto err_irq; } diff --git a/trunk/sound/oss/esssolo1.c b/trunk/sound/oss/esssolo1.c index 82f40a0a5c9c..6861563d7525 100644 --- a/trunk/sound/oss/esssolo1.c +++ b/trunk/sound/oss/esssolo1.c @@ -2392,7 +2392,7 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device printk(KERN_ERR "solo1: io ports in use\n"); goto err_region4; } - if ((ret=request_irq(s->irq,solo1_interrupt,IRQF_SHARED,"ESS Solo1",s))) { + if ((ret=request_irq(s->irq,solo1_interrupt,SA_SHIRQ,"ESS Solo1",s))) { printk(KERN_ERR "solo1: irq %u in use\n", s->irq); goto err_irq; } diff --git a/trunk/sound/oss/forte.c b/trunk/sound/oss/forte.c index ea1c0207aef2..0294eec8ad90 100644 --- a/trunk/sound/oss/forte.c +++ b/trunk/sound/oss/forte.c @@ -2026,7 +2026,7 @@ forte_probe (struct pci_dev *pci_dev, const struct pci_device_id *pci_id) chip->iobase = pci_resource_start (pci_dev, 0); chip->irq = pci_dev->irq; - if (request_irq (chip->irq, forte_interrupt, IRQF_SHARED, DRIVER_NAME, + if (request_irq (chip->irq, forte_interrupt, SA_SHIRQ, DRIVER_NAME, chip)) { printk (KERN_WARNING PFX "Unable to reserve IRQ"); ret = -EIO; @@ -2035,9 +2035,8 @@ forte_probe (struct pci_dev *pci_dev, const struct pci_device_id *pci_id) pci_set_drvdata (pci_dev, chip); - printk (KERN_INFO PFX "FM801 chip found at 0x%04lX-0x%16llX IRQ %u\n", - chip->iobase, (unsigned long long)pci_resource_end (pci_dev, 0), - chip->irq); + printk (KERN_INFO PFX "FM801 chip found at 0x%04lX-0x%04lX IRQ %u\n", + chip->iobase, pci_resource_end (pci_dev, 0), chip->irq); /* Power it up */ if ((ret = forte_chip_init (chip)) == 0) diff --git a/trunk/sound/oss/hal2.c b/trunk/sound/oss/hal2.c index 80ab402dae9a..dd4f59d30a3a 100644 --- a/trunk/sound/oss/hal2.c +++ b/trunk/sound/oss/hal2.c @@ -1479,7 +1479,7 @@ static int hal2_init_card(struct hal2_card **phal2, struct hpc3_regs *hpc3) hpc3->pbus_dmacfg[hal2->dac.pbus.pbusnr][0] = 0x8208844; hpc3->pbus_dmacfg[hal2->adc.pbus.pbusnr][0] = 0x8208844; - if (request_irq(SGI_HPCDMA_IRQ, hal2_interrupt, IRQF_SHARED, + if (request_irq(SGI_HPCDMA_IRQ, hal2_interrupt, SA_SHIRQ, hal2str, hal2)) { printk(KERN_ERR "HAL2: Can't get irq %d\n", SGI_HPCDMA_IRQ); ret = -EAGAIN; diff --git a/trunk/sound/oss/i810_audio.c b/trunk/sound/oss/i810_audio.c index ddcddc2347f7..dd2b871cdac5 100644 --- a/trunk/sound/oss/i810_audio.c +++ b/trunk/sound/oss/i810_audio.c @@ -3413,7 +3413,7 @@ static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device goto out_iospace; } - if (request_irq(card->irq, &i810_interrupt, IRQF_SHARED, + if (request_irq(card->irq, &i810_interrupt, SA_SHIRQ, card_names[pci_id->driver_data], card)) { printk(KERN_ERR "i810_audio: unable to allocate irq %d\n", card->irq); goto out_iospace; diff --git a/trunk/sound/oss/ite8172.c b/trunk/sound/oss/ite8172.c index 68aab3605d74..00ac1c95a429 100644 --- a/trunk/sound/oss/ite8172.c +++ b/trunk/sound/oss/ite8172.c @@ -2019,7 +2019,7 @@ static int __devinit it8172_probe(struct pci_dev *pcidev, s->io, s->io + pci_resource_len(pcidev,0)-1); goto err_region; } - if (request_irq(s->irq, it8172_interrupt, IRQF_DISABLED, + if (request_irq(s->irq, it8172_interrupt, SA_INTERRUPT, IT8172_MODULE_NAME, s)) { err("irq %u in use", s->irq); goto err_irq; diff --git a/trunk/sound/oss/kahlua.c b/trunk/sound/oss/kahlua.c index 12e7b3038be2..2835a7c038ef 100644 --- a/trunk/sound/oss/kahlua.c +++ b/trunk/sound/oss/kahlua.c @@ -27,6 +27,7 @@ * same manner. */ +#include #include #include #include diff --git a/trunk/sound/oss/maestro.c b/trunk/sound/oss/maestro.c index 1d98d100d739..e647f2f86279 100644 --- a/trunk/sound/oss/maestro.c +++ b/trunk/sound/oss/maestro.c @@ -3545,7 +3545,7 @@ maestro_probe(struct pci_dev *pcidev,const struct pci_device_id *pdid) mixer_push_state(card); } - if((ret=request_irq(card->irq, ess_interrupt, IRQF_SHARED, card_names[card_type], card))) + if((ret=request_irq(card->irq, ess_interrupt, SA_SHIRQ, card_names[card_type], card))) { printk(KERN_ERR "maestro: unable to allocate irq %d,\n", card->irq); unregister_sound_mixer(card->dev_mixer); diff --git a/trunk/sound/oss/maestro3.c b/trunk/sound/oss/maestro3.c index 5548e3cff7ce..4a5e4237a110 100644 --- a/trunk/sound/oss/maestro3.c +++ b/trunk/sound/oss/maestro3.c @@ -2694,7 +2694,7 @@ static int __devinit m3_probe(struct pci_dev *pci_dev, const struct pci_device_i } } - if(request_irq(card->irq, m3_interrupt, IRQF_SHARED, card_names[card->card_type], card)) { + if(request_irq(card->irq, m3_interrupt, SA_SHIRQ, card_names[card->card_type], card)) { printk(KERN_ERR PFX "unable to allocate irq %d,\n", card->irq); diff --git a/trunk/sound/oss/msnd_classic.h b/trunk/sound/oss/msnd_classic.h index 7ffea5267f96..83c3c46ffffe 100644 --- a/trunk/sound/oss/msnd_classic.h +++ b/trunk/sound/oss/msnd_classic.h @@ -30,6 +30,7 @@ #ifndef __MSND_CLASSIC_H #define __MSND_CLASSIC_H +#include #define DSP_NUMIO 0x10 diff --git a/trunk/sound/oss/msnd_pinnacle.c b/trunk/sound/oss/msnd_pinnacle.c index 6d7763dae895..0c2db657badd 100644 --- a/trunk/sound/oss/msnd_pinnacle.c +++ b/trunk/sound/oss/msnd_pinnacle.c @@ -39,6 +39,7 @@ ********************************************************************/ #include +#include #include #include #include diff --git a/trunk/sound/oss/msnd_pinnacle.h b/trunk/sound/oss/msnd_pinnacle.h index cce911487004..e85aef4a55e0 100644 --- a/trunk/sound/oss/msnd_pinnacle.h +++ b/trunk/sound/oss/msnd_pinnacle.h @@ -30,6 +30,7 @@ #ifndef __MSND_PINNACLE_H #define __MSND_PINNACLE_H +#include #define DSP_NUMIO 0x08 diff --git a/trunk/sound/oss/nec_vrc5477.c b/trunk/sound/oss/nec_vrc5477.c index 6f7f2f0423e4..21c1954d9108 100644 --- a/trunk/sound/oss/nec_vrc5477.c +++ b/trunk/sound/oss/nec_vrc5477.c @@ -1909,7 +1909,7 @@ static int __devinit vrc5477_ac97_probe(struct pci_dev *pcidev, s->io, s->io + pci_resource_len(pcidev,0)-1); goto err_region; } - if (request_irq(s->irq, vrc5477_ac97_interrupt, IRQF_DISABLED, + if (request_irq(s->irq, vrc5477_ac97_interrupt, SA_INTERRUPT, VRC5477_AC97_MODULE_NAME, s)) { printk(KERN_ERR PFX "irq %u in use\n", s->irq); goto err_irq; diff --git a/trunk/sound/oss/nm256_audio.c b/trunk/sound/oss/nm256_audio.c index 7760dddf2b32..6e662ac009ae 100644 --- a/trunk/sound/oss/nm256_audio.c +++ b/trunk/sound/oss/nm256_audio.c @@ -733,7 +733,7 @@ static int nm256_grabInterrupt (struct nm256_info *card) { if (card->has_irq++ == 0) { - if (request_irq (card->irq, card->introutine, IRQF_SHARED, + if (request_irq (card->irq, card->introutine, SA_SHIRQ, "NM256_audio", card) < 0) { printk (KERN_ERR "NM256: can't obtain IRQ %d\n", card->irq); return -1; diff --git a/trunk/sound/oss/opl3sa2.c b/trunk/sound/oss/opl3sa2.c index aec05a2bfc87..0e161c6a0477 100644 --- a/trunk/sound/oss/opl3sa2.c +++ b/trunk/sound/oss/opl3sa2.c @@ -64,6 +64,7 @@ * */ +#include #include #include #include diff --git a/trunk/sound/oss/pas2_card.c b/trunk/sound/oss/pas2_card.c index 97666007b274..c9696dc9fdf9 100644 --- a/trunk/sound/oss/pas2_card.c +++ b/trunk/sound/oss/pas2_card.c @@ -4,6 +4,7 @@ * Detection routine for the Pro Audio Spectrum cards. */ +#include #include #include #include diff --git a/trunk/sound/oss/pss.c b/trunk/sound/oss/pss.c index 37ee234b587c..a617ccb40e00 100644 --- a/trunk/sound/oss/pss.c +++ b/trunk/sound/oss/pss.c @@ -57,6 +57,7 @@ */ +#include #include #include #include diff --git a/trunk/sound/oss/rme96xx.c b/trunk/sound/oss/rme96xx.c index f17d25b6f836..a1ec9d131ab3 100644 --- a/trunk/sound/oss/rme96xx.c +++ b/trunk/sound/oss/rme96xx.c @@ -994,7 +994,7 @@ static int __devinit rme96xx_probe(struct pci_dev *pcidev, const struct pci_devi if (pci_enable_device(pcidev)) goto err_irq; - if (request_irq(s->irq, rme96xx_interrupt, IRQF_SHARED, "rme96xx", s)) { + if (request_irq(s->irq, rme96xx_interrupt, SA_SHIRQ, "rme96xx", s)) { printk(KERN_ERR RME_MESS" irq %u in use\n", s->irq); goto err_irq; } diff --git a/trunk/sound/oss/sb_card.c b/trunk/sound/oss/sb_card.c index 8666291c0052..4708cbdc3149 100644 --- a/trunk/sound/oss/sb_card.c +++ b/trunk/sound/oss/sb_card.c @@ -22,6 +22,7 @@ * 02-07-2003 Bug made it into first release. Take two. */ +#include #include #include #include diff --git a/trunk/sound/oss/sb_common.c b/trunk/sound/oss/sb_common.c index 35bab6e2f998..5f955e3d2e26 100644 --- a/trunk/sound/oss/sb_common.c +++ b/trunk/sound/oss/sb_common.c @@ -26,6 +26,7 @@ * Chris Rankin */ +#include #include #include #include @@ -677,7 +678,7 @@ int sb_dsp_init(struct address_info *hw_config, struct module *owner) * will get shared PCI irq lines we must cope. */ - int i=(devc->caps&SB_PCI_IRQ)?IRQF_SHARED:0; + int i=(devc->caps&SB_PCI_IRQ)?SA_SHIRQ:0; if (request_irq(hw_config->irq, sbintr, i, "soundblaster", devc) < 0) { diff --git a/trunk/sound/oss/sb_ess.c b/trunk/sound/oss/sb_ess.c index 180e95c87e3e..fae05fe3de43 100644 --- a/trunk/sound/oss/sb_ess.c +++ b/trunk/sound/oss/sb_ess.c @@ -97,19 +97,19 @@ * * The documentation is an adventure: it's close but not fully accurate. I * found out that after a reset some registers are *NOT* reset, though the - * docs say the would be. Interesting ones are 0x7f, 0x7d and 0x7a. They are - * related to the Audio 2 channel. I also was surprised about the consequences + * docs say the would be. Interresting ones are 0x7f, 0x7d and 0x7a. They are + * related to the Audio 2 channel. I also was suprised about the consequenses * of writing 0x00 to 0x7f (which should be done by reset): The ES1887 moves * into ES1888 mode. This means that it claims IRQ 11, which happens to be my * ISDN adapter. Needless to say it no longer worked. I now understand why * after rebooting 0x7f already was 0x05, the value of my choice: the BIOS * did it. * - * Oh, and this is another trap: in ES1887 docs mixer register 0x70 is - * described as if it's exactly the same as register 0xa1. This is *NOT* true. - * The description of 0x70 in ES1869 docs is accurate however. + * Oh, and this is another trap: in ES1887 docs mixer register 0x70 is decribed + * as if it's exactly the same as register 0xa1. This is *NOT* true. The + * description of 0x70 in ES1869 docs is accurate however. * Well, the assumption about ES1869 was wrong: register 0x70 is very much - * like register 0xa1, except that bit 7 is always 1, whatever you want + * like register 0xa1, except that bit 7 is allways 1, whatever you want * it to be. * * When using audio 2 mixer register 0x72 seems te be meaningless. Only 0xa2 @@ -117,10 +117,10 @@ * * Software reset not being able to reset all registers is great! Especially * the fact that register 0x78 isn't reset is great when you wanna change back - * to single dma operation (simplex): audio 2 is still operational, and uses - * the same dma as audio 1: your ess changes into a funny echo machine. + * to single dma operation (simplex): audio 2 is still operation, and uses the + * same dma as audio 1: your ess changes into a funny echo machine. * - * Received the news that ES1688 is detected as a ES1788. Did some thinking: + * Received the new that ES1688 is detected as a ES1788. Did some thinking: * the ES1887 detection scheme suggests in step 2 to try if bit 3 of register * 0x64 can be changed. This is inaccurate, first I inverted the * check: "If * can be modified, it's a 1688", which lead to a correct detection @@ -135,7 +135,7 @@ * About recognition of ESS chips * * The distinction of ES688, ES1688, ES1788, ES1887 and ES1888 is described in - * a (preliminary ??) datasheet on ES1887. Its aim is to identify ES1887, but + * a (preliminary ??) datasheet on ES1887. It's aim is to identify ES1887, but * during detection the text claims that "this chip may be ..." when a step * fails. This scheme is used to distinct between the above chips. * It appears however that some PnP chips like ES1868 are recognized as ES1788 @@ -156,9 +156,9 @@ * * The existing ES1688 support didn't take care of the ES1688+ recording * levels very well. Whenever a device was selected (recmask) for recording - * its recording level was loud, and it couldn't be changed. The fact that + * it's recording level was loud, and it couldn't be changed. The fact that * internal register 0xb4 could take care of RECLEV, didn't work meaning until - * its value was restored every time the chip was reset; this reset the + * it's value was restored every time the chip was reset; this reset the * value of 0xb4 too. I guess that's what 4front also had (have?) trouble with. * * About ES1887 support: @@ -169,9 +169,9 @@ * the latter case the recording volumes are 0. * Now recording levels of inputs can be controlled, by changing the playback * levels. Futhermore several devices can be recorded together (which is not - * possible with the ES1688). + * possible with the ES1688. * Besides the separate recording level control for each input, the common - * recording level can also be controlled by RECLEV as described above. + * recordig level can also be controlled by RECLEV as described above. * * Not only ES1887 have this recording mixer. I know the following from the * documentation: diff --git a/trunk/sound/oss/sh_dac_audio.c b/trunk/sound/oss/sh_dac_audio.c index 7b168d85f4ab..3f7427cd195a 100644 --- a/trunk/sound/oss/sh_dac_audio.c +++ b/trunk/sound/oss/sh_dac_audio.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -297,7 +298,7 @@ static int __init dac_audio_init(void) dac_audio_set_rate(); retval = - request_irq(TIMER1_IRQ, timer1_interrupt, IRQF_DISABLED, MODNAME, 0); + request_irq(TIMER1_IRQ, timer1_interrupt, SA_INTERRUPT, MODNAME, 0); if (retval < 0) { printk(KERN_ERR "sh_dac_audio: IRQ %d request failed\n", TIMER1_IRQ); diff --git a/trunk/sound/oss/sonicvibes.c b/trunk/sound/oss/sonicvibes.c index 8ea532d40198..42bd276cfc39 100644 --- a/trunk/sound/oss/sonicvibes.c +++ b/trunk/sound/oss/sonicvibes.c @@ -2632,7 +2632,7 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id wrindir(s, SV_CIPCMSR1, ((8000 * 65536 / FULLRATE) >> 8) & 0xff); wrindir(s, SV_CIADCOUTPUT, 0); /* request irq */ - if ((ret=request_irq(s->irq,sv_interrupt,IRQF_SHARED,"S3 SonicVibes",s))) { + if ((ret=request_irq(s->irq,sv_interrupt,SA_SHIRQ,"S3 SonicVibes",s))) { printk(KERN_ERR "sv: irq %u in use\n", s->irq); goto err_irq; } diff --git a/trunk/sound/oss/sound_config.h b/trunk/sound/oss/sound_config.h index 1a00a3210616..9f912b8a2969 100644 --- a/trunk/sound/oss/sound_config.h +++ b/trunk/sound/oss/sound_config.h @@ -14,6 +14,7 @@ #ifndef _SOUND_CONFIG_H_ #define _SOUND_CONFIG_H_ +#include #include #include diff --git a/trunk/sound/oss/soundcard.c b/trunk/sound/oss/soundcard.c index 0860d6789715..d33bb464f70e 100644 --- a/trunk/sound/oss/soundcard.c +++ b/trunk/sound/oss/soundcard.c @@ -22,6 +22,7 @@ * Christoph Hellwig : Some cleanup work (2000/03/01) */ +#include #include "sound_config.h" #include @@ -37,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -562,6 +564,9 @@ static int __init oss_init(void) sound_dmap_flag = (dmabuf > 0 ? 1 : 0); for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { + devfs_mk_cdev(MKDEV(SOUND_MAJOR, dev_list[i].minor), + S_IFCHR | dev_list[i].mode, + "sound/%s", dev_list[i].name); class_device_create(sound_class, NULL, MKDEV(SOUND_MAJOR, dev_list[i].minor), NULL, "%s", dev_list[i].name); @@ -569,10 +574,15 @@ static int __init oss_init(void) if (!dev_list[i].num) continue; - for (j = 1; j < *dev_list[i].num; j++) + for (j = 1; j < *dev_list[i].num; j++) { + devfs_mk_cdev(MKDEV(SOUND_MAJOR, + dev_list[i].minor + (j*0x10)), + S_IFCHR | dev_list[i].mode, + "sound/%s%d", dev_list[i].name, j); class_device_create(sound_class, NULL, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)), NULL, "%s%d", dev_list[i].name, j); + } } if (sound_nblocks >= 1024) @@ -586,11 +596,14 @@ static void __exit oss_cleanup(void) int i, j; for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { + devfs_remove("sound/%s", dev_list[i].name); class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor)); if (!dev_list[i].num) continue; - for (j = 1; j < *dev_list[i].num; j++) + for (j = 1; j < *dev_list[i].num; j++) { + devfs_remove("sound/%s%d", dev_list[i].name, j); class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10))); + } } unregister_sound_special(1); diff --git a/trunk/sound/oss/trident.c b/trunk/sound/oss/trident.c index 2813e4c8e365..e61a454a8150 100644 --- a/trunk/sound/oss/trident.c +++ b/trunk/sound/oss/trident.c @@ -194,6 +194,7 @@ * sem - guard dmabuf, write re-entry etc */ +#include #include #include #include @@ -4472,7 +4473,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) /* claim our irq */ rc = -ENODEV; - if (request_irq(card->irq, &trident_interrupt, IRQF_SHARED, + if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ, card_names[pci_id->driver_data], card)) { printk(KERN_ERR "trident: unable to allocate irq %d\n", card->irq); diff --git a/trunk/sound/oss/via82cxxx_audio.c b/trunk/sound/oss/via82cxxx_audio.c index 08d8c94d01b2..1a921ee71aba 100644 --- a/trunk/sound/oss/via82cxxx_audio.c +++ b/trunk/sound/oss/via82cxxx_audio.c @@ -18,12 +18,12 @@ #define VIA_VERSION "1.9.1-ac4-2.5" +#include #include #include #include #include #include -#include #include #include #include @@ -308,7 +308,7 @@ struct via_info { unsigned sixchannel: 1; /* 8233/35 with 6 channel support */ unsigned volume: 1; - unsigned locked_rate : 1; + int locked_rate : 1; int mixer_vol; /* 8233/35 volume - not yet implemented */ @@ -2013,7 +2013,7 @@ static int via_interrupt_init (struct via_info *card) tmp8 |= VIA_CR48_FM_TRAP_TO_NMI; pci_write_config_byte (card->pdev, VIA_FM_NMI_CTRL, tmp8); } - if (request_irq (card->pdev->irq, via_interrupt, IRQF_SHARED, VIA_MODULE_NAME, card)) { + if (request_irq (card->pdev->irq, via_interrupt, SA_SHIRQ, VIA_MODULE_NAME, card)) { printk (KERN_ERR PFX "unable to obtain IRQ %d, aborting\n", card->pdev->irq); DPRINTK ("EXIT, returning -EBUSY\n"); @@ -2022,7 +2022,7 @@ static int via_interrupt_init (struct via_info *card) } else { - if (request_irq (card->pdev->irq, via_new_interrupt, IRQF_SHARED, VIA_MODULE_NAME, card)) { + if (request_irq (card->pdev->irq, via_new_interrupt, SA_SHIRQ, VIA_MODULE_NAME, card)) { printk (KERN_ERR PFX "unable to obtain IRQ %d, aborting\n", card->pdev->irq); DPRINTK ("EXIT, returning -EBUSY\n"); @@ -3522,7 +3522,7 @@ static int __devinit via_init_one (struct pci_dev *pdev, const struct pci_device err_out_kfree: #ifndef VIA_NDEBUG - memset (card, OSS_POISON_FREE, sizeof (*card)); /* poison memory */ + memset (card, 0xAB, sizeof (*card)); /* poison memory */ #endif kfree (card); @@ -3559,7 +3559,7 @@ static void __devexit via_remove_one (struct pci_dev *pdev) via_ac97_cleanup (card); #ifndef VIA_NDEBUG - memset (card, OSS_POISON_FREE, sizeof (*card)); /* poison memory */ + memset (card, 0xAB, sizeof (*card)); /* poison memory */ #endif kfree (card); diff --git a/trunk/sound/oss/vidc.c b/trunk/sound/oss/vidc.c index 8932d89408ef..00fe5cec9dc1 100644 --- a/trunk/sound/oss/vidc.c +++ b/trunk/sound/oss/vidc.c @@ -17,6 +17,7 @@ * We currently support a mixer device, but it is currently non-functional. */ +#include #include #include #include diff --git a/trunk/sound/oss/waveartist.c b/trunk/sound/oss/waveartist.c index 22d26624b34a..afcb524a40eb 100644 --- a/trunk/sound/oss/waveartist.c +++ b/trunk/sound/oss/waveartist.c @@ -35,6 +35,7 @@ #include #include +#include #include #include #include diff --git a/trunk/sound/oss/wavfront.c b/trunk/sound/oss/wavfront.c index 1dec3958cc7b..b1a4eeb9dc08 100644 --- a/trunk/sound/oss/wavfront.c +++ b/trunk/sound/oss/wavfront.c @@ -2268,7 +2268,7 @@ static int __init wavefront_hw_reset (void) } if (request_irq (dev.irq, wavefrontintr, - IRQF_DISABLED|IRQF_SHARED, + SA_INTERRUPT|SA_SHIRQ, "wavefront synth", &dev) < 0) { printk (KERN_WARNING LOGNAME "IRQ %d not available!\n", dev.irq); diff --git a/trunk/sound/oss/wf_midi.c b/trunk/sound/oss/wf_midi.c index 3f3a390014ca..7b167b74375b 100644 --- a/trunk/sound/oss/wf_midi.c +++ b/trunk/sound/oss/wf_midi.c @@ -820,7 +820,7 @@ int __init install_wf_mpu (void) /* OK, now we're configured to handle an interrupt ... */ - if (request_irq (phys_dev->irq, wf_mpuintr, IRQF_DISABLED|IRQF_SHARED, + if (request_irq (phys_dev->irq, wf_mpuintr, SA_INTERRUPT|SA_SHIRQ, "wavefront midi", phys_dev) < 0) { printk (KERN_ERR "WF-MPU: Failed to allocate IRQ%d\n", diff --git a/trunk/sound/oss/ymfpci.c b/trunk/sound/oss/ymfpci.c index 6e22472df952..bf90c124a7e6 100644 --- a/trunk/sound/oss/ymfpci.c +++ b/trunk/sound/oss/ymfpci.c @@ -2573,7 +2573,7 @@ static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_devi goto out_disable_dsp; ymf_memload(codec); - if (request_irq(pcidev->irq, ymf_interrupt, IRQF_SHARED, "ymfpci", codec) != 0) { + if (request_irq(pcidev->irq, ymf_interrupt, SA_SHIRQ, "ymfpci", codec) != 0) { printk(KERN_ERR "ymfpci: unable to request IRQ %d\n", pcidev->irq); goto out_memfree; diff --git a/trunk/sound/pci/Kconfig b/trunk/sound/pci/Kconfig index 23e54cedfd4a..d37346b12dc0 100644 --- a/trunk/sound/pci/Kconfig +++ b/trunk/sound/pci/Kconfig @@ -233,143 +233,6 @@ config SND_CS5535AUDIO To compile this driver as a module, choose M here: the module will be called snd-cs5535audio. -config SND_DARLA20 - tristate "(Echoaudio) Darla20" - depends on SND - depends on FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Darla. - - To compile this driver as a module, choose M here: the module - will be called snd-darla20 - -config SND_GINA20 - tristate "(Echoaudio) Gina20" - depends on SND - depends on FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Gina. - - To compile this driver as a module, choose M here: the module - will be called snd-gina20 - -config SND_LAYLA20 - tristate "(Echoaudio) Layla20" - depends on SND - depends on FW_LOADER - select SND_RAWMIDI - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Layla. - - To compile this driver as a module, choose M here: the module - will be called snd-layla20 - -config SND_DARLA24 - tristate "(Echoaudio) Darla24" - depends on SND - depends on FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Darla24. - - To compile this driver as a module, choose M here: the module - will be called snd-darla24 - -config SND_GINA24 - tristate "(Echoaudio) Gina24" - depends on SND - depends on FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Gina24. - - To compile this driver as a module, choose M here: the module - will be called snd-gina24 - -config SND_LAYLA24 - tristate "(Echoaudio) Layla24" - depends on SND - depends on FW_LOADER - select SND_RAWMIDI - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Layla24. - - To compile this driver as a module, choose M here: the module - will be called snd-layla24 - -config SND_MONA - tristate "(Echoaudio) Mona" - depends on SND - depends on FW_LOADER - select SND_RAWMIDI - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Mona. - - To compile this driver as a module, choose M here: the module - will be called snd-mona - -config SND_MIA - tristate "(Echoaudio) Mia" - depends on SND - depends on FW_LOADER - select SND_RAWMIDI - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Mia and Mia-midi. - - To compile this driver as a module, choose M here: the module - will be called snd-mia - -config SND_ECHO3G - tristate "(Echoaudio) 3G cards" - depends on SND - depends on FW_LOADER - select SND_RAWMIDI - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Gina3G and Layla3G. - - To compile this driver as a module, choose M here: the module - will be called snd-echo3g - -config SND_INDIGO - tristate "(Echoaudio) Indigo" - depends on SND - depends on FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Indigo. - - To compile this driver as a module, choose M here: the module - will be called snd-indigo - -config SND_INDIGOIO - tristate "(Echoaudio) Indigo IO" - depends on SND - depends on FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Indigo IO. - - To compile this driver as a module, choose M here: the module - will be called snd-indigoio - -config SND_INDIGODJ - tristate "(Echoaudio) Indigo DJ" - depends on SND - depends on FW_LOADER - select SND_PCM - help - Say 'Y' or 'M' to include support for Echoaudio Indigo DJ. - - To compile this driver as a module, choose M here: the module - will be called snd-indigodj - config SND_EMU10K1 tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)" depends on SND @@ -557,8 +420,8 @@ config SND_INTEL8X0 will be called snd-intel8x0. config SND_INTEL8X0M - tristate "Intel/SiS/nVidia/AMD MC97 Modem" - depends on SND + tristate "Intel/SiS/nVidia/AMD MC97 Modem (EXPERIMENTAL)" + depends on SND && EXPERIMENTAL select SND_AC97_CODEC help Say Y here to include support for the integrated MC97 modem on diff --git a/trunk/sound/pci/Makefile b/trunk/sound/pci/Makefile index e06736da9ef1..cba5105aafea 100644 --- a/trunk/sound/pci/Makefile +++ b/trunk/sound/pci/Makefile @@ -57,7 +57,6 @@ obj-$(CONFIG_SND) += \ ca0106/ \ cs46xx/ \ cs5535audio/ \ - echoaudio/ \ emu10k1/ \ hda/ \ ice1712/ \ diff --git a/trunk/sound/pci/ac97/ac97_patch.c b/trunk/sound/pci/ac97/ac97_patch.c index 094cfc1f3a19..7f197c780816 100644 --- a/trunk/sound/pci/ac97/ac97_patch.c +++ b/trunk/sound/pci/ac97/ac97_patch.c @@ -1824,8 +1824,6 @@ static const struct snd_kcontrol_new snd_ac97_ad1888_controls[] = { .get = snd_ac97_ad1888_lohpsel_get, .put = snd_ac97_ad1888_lohpsel_put }, - AC97_SINGLE("V_REFOUT Enable", AC97_AD_MISC, 2, 1, 1), - AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1), AC97_SINGLE("Spread Front to Surround and Center/LFE", AC97_AD_MISC, 7, 1, 0), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, diff --git a/trunk/sound/pci/ad1889.c b/trunk/sound/pci/ad1889.c index f7aef8c9cf43..d42bf4570367 100644 --- a/trunk/sound/pci/ad1889.c +++ b/trunk/sound/pci/ad1889.c @@ -947,7 +947,7 @@ snd_ad1889_create(struct snd_card *card, spin_lock_init(&chip->lock); /* only now can we call ad1889_free */ if (request_irq(pci->irq, snd_ad1889_interrupt, - IRQF_DISABLED|IRQF_SHARED, card->driver, (void*)chip)) { + SA_INTERRUPT|SA_SHIRQ, card->driver, (void*)chip)) { printk(KERN_ERR PFX "cannot obtain IRQ %d\n", pci->irq); snd_ad1889_free(chip); return -EBUSY; diff --git a/trunk/sound/pci/ali5451/ali5451.c b/trunk/sound/pci/ali5451/ali5451.c index e0a815e53d1c..5dfdbf6657f2 100644 --- a/trunk/sound/pci/ali5451/ali5451.c +++ b/trunk/sound/pci/ali5451/ali5451.c @@ -2185,7 +2185,7 @@ static int __devinit snd_ali_resources(struct snd_ali *codec) return err; codec->port = pci_resource_start(codec->pci, 0); - if (request_irq(codec->pci->irq, snd_ali_card_interrupt, IRQF_DISABLED|IRQF_SHARED, "ALI 5451", (void *)codec)) { + if (request_irq(codec->pci->irq, snd_ali_card_interrupt, SA_INTERRUPT|SA_SHIRQ, "ALI 5451", (void *)codec)) { snd_printk(KERN_ERR "Unable to request irq.\n"); return -EBUSY; } diff --git a/trunk/sound/pci/als300.c b/trunk/sound/pci/als300.c index a9c38963188a..901b08ae9174 100644 --- a/trunk/sound/pci/als300.c +++ b/trunk/sound/pci/als300.c @@ -724,7 +724,7 @@ static int __devinit snd_als300_create(snd_card_t *card, else irq_handler = snd_als300_interrupt; - if (request_irq(pci->irq, irq_handler, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, irq_handler, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_als300_free(chip); diff --git a/trunk/sound/pci/atiixp.c b/trunk/sound/pci/atiixp.c index 9fbb065a810b..f18a8c0e4688 100644 --- a/trunk/sound/pci/atiixp.c +++ b/trunk/sound/pci/atiixp.c @@ -1578,7 +1578,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card, return -EIO; } - if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_atiixp_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_atiixp_free(chip); diff --git a/trunk/sound/pci/atiixp_modem.c b/trunk/sound/pci/atiixp_modem.c index 7dcf4941dce2..40739057076b 100644 --- a/trunk/sound/pci/atiixp_modem.c +++ b/trunk/sound/pci/atiixp_modem.c @@ -1251,7 +1251,7 @@ static int __devinit snd_atiixp_create(struct snd_card *card, return -EIO; } - if (request_irq(pci->irq, snd_atiixp_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_atiixp_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_atiixp_free(chip); diff --git a/trunk/sound/pci/au88x0/au88x0.c b/trunk/sound/pci/au88x0/au88x0.c index ef189d7f09d3..8a3b118989bf 100644 --- a/trunk/sound/pci/au88x0/au88x0.c +++ b/trunk/sound/pci/au88x0/au88x0.c @@ -197,7 +197,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip) } if ((err = request_irq(pci->irq, vortex_interrupt, - IRQF_DISABLED | IRQF_SHARED, CARD_NAME_SHORT, + SA_INTERRUPT | SA_SHIRQ, CARD_NAME_SHORT, chip)) != 0) { printk(KERN_ERR "cannot grab irq\n"); goto irq_out; diff --git a/trunk/sound/pci/azt3328.c b/trunk/sound/pci/azt3328.c index 15447a3216dd..6e62dafb66cd 100644 --- a/trunk/sound/pci/azt3328.c +++ b/trunk/sound/pci/azt3328.c @@ -1724,7 +1724,7 @@ snd_azf3328_create(struct snd_card *card, chip->synth_port = pci_resource_start(pci, 3); chip->mixer_port = pci_resource_start(pci, 4); - if (request_irq(pci->irq, snd_azf3328_interrupt, IRQF_DISABLED|IRQF_SHARED, card->shortname, (void *)chip)) { + if (request_irq(pci->irq, snd_azf3328_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); err = -EBUSY; goto out_err; diff --git a/trunk/sound/pci/bt87x.c b/trunk/sound/pci/bt87x.c index 4d4277d045aa..c33642d8d9a1 100644 --- a/trunk/sound/pci/bt87x.c +++ b/trunk/sound/pci/bt87x.c @@ -747,7 +747,7 @@ static int __devinit snd_bt87x_create(struct snd_card *card, snd_bt87x_writel(chip, REG_INT_MASK, 0); snd_bt87x_writel(chip, REG_INT_STAT, MY_INTERRUPTS); - if (request_irq(pci->irq, snd_bt87x_interrupt, IRQF_DISABLED | IRQF_SHARED, + if (request_irq(pci->irq, snd_bt87x_interrupt, SA_INTERRUPT | SA_SHIRQ, "Bt87x audio", chip)) { snd_bt87x_free(chip); snd_printk(KERN_ERR "cannot grab irq\n"); @@ -888,9 +888,8 @@ static int __devinit snd_bt87x_probe(struct pci_dev *pci, strcpy(card->driver, "Bt87x"); sprintf(card->shortname, "Brooktree Bt%x", pci->device); - sprintf(card->longname, "%s at %#llx, irq %i", - card->shortname, (unsigned long long)pci_resource_start(pci, 0), - chip->irq); + sprintf(card->longname, "%s at %#lx, irq %i", + card->shortname, pci_resource_start(pci, 0), chip->irq); strcpy(card->mixername, "Bt87x"); err = snd_card_register(card); diff --git a/trunk/sound/pci/ca0106/ca0106_main.c b/trunk/sound/pci/ca0106/ca0106_main.c index a30c019bab64..59bf9bd02534 100644 --- a/trunk/sound/pci/ca0106/ca0106_main.c +++ b/trunk/sound/pci/ca0106/ca0106_main.c @@ -1268,7 +1268,7 @@ static int __devinit snd_ca0106_create(struct snd_card *card, } if (request_irq(pci->irq, snd_ca0106_interrupt, - IRQF_DISABLED|IRQF_SHARED, "snd_ca0106", + SA_INTERRUPT|SA_SHIRQ, "snd_ca0106", (void *)chip)) { snd_ca0106_free(chip); printk(KERN_ERR "cannot grab irq\n"); diff --git a/trunk/sound/pci/cmipci.c b/trunk/sound/pci/cmipci.c index 03766ad74998..0938c158b5c9 100644 --- a/trunk/sound/pci/cmipci.c +++ b/trunk/sound/pci/cmipci.c @@ -2862,7 +2862,7 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc cm->iobase = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_cmipci_interrupt, - IRQF_DISABLED|IRQF_SHARED, card->driver, cm)) { + SA_INTERRUPT|SA_SHIRQ, card->driver, cm)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_cmipci_free(cm); return -EBUSY; diff --git a/trunk/sound/pci/cs4281.c b/trunk/sound/pci/cs4281.c index d1802487f5be..e77a4ce314b7 100644 --- a/trunk/sound/pci/cs4281.c +++ b/trunk/sound/pci/cs4281.c @@ -1386,7 +1386,7 @@ static int __devinit snd_cs4281_create(struct snd_card *card, return -ENOMEM; } - if (request_irq(pci->irq, snd_cs4281_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS4281", chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_cs4281_free(chip); diff --git a/trunk/sound/pci/cs46xx/cs46xx_lib.c b/trunk/sound/pci/cs46xx/cs46xx_lib.c index 894545ea41fd..5c2114439204 100644 --- a/trunk/sound/pci/cs46xx/cs46xx_lib.c +++ b/trunk/sound/pci/cs46xx/cs46xx_lib.c @@ -3853,7 +3853,7 @@ int __devinit snd_cs46xx_create(struct snd_card *card, } } - if (request_irq(pci->irq, snd_cs46xx_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_cs46xx_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS46XX", chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_cs46xx_free(chip); diff --git a/trunk/sound/pci/cs5535audio/cs5535audio.c b/trunk/sound/pci/cs5535audio/cs5535audio.c index c12b24c679f2..91c18a11fe87 100644 --- a/trunk/sound/pci/cs5535audio/cs5535audio.c +++ b/trunk/sound/pci/cs5535audio/cs5535audio.c @@ -321,7 +321,7 @@ static int __devinit snd_cs5535audio_create(struct snd_card *card, cs5535au->port = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_cs5535audio_interrupt, - IRQF_DISABLED|IRQF_SHARED, "CS5535 Audio", cs5535au)) { + SA_INTERRUPT|SA_SHIRQ, "CS5535 Audio", cs5535au)) { snd_printk("unable to grab IRQ %d\n", pci->irq); err = -EBUSY; goto sndfail; diff --git a/trunk/sound/pci/cs5535audio/cs5535audio_pcm.c b/trunk/sound/pci/cs5535audio/cs5535audio_pcm.c index 5450a9e8f133..f0a48693d687 100644 --- a/trunk/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/trunk/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -143,7 +143,7 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au, if (dma->periods == periods && dma->period_bytes == period_bytes) return 0; - /* the u32 cast is okay because in snd*create we successfully told + /* the u32 cast is okay because in snd*create we succesfully told pci alloc that we're only 32 bit capable so the uppper will be 0 */ addr = (u32) substream->runtime->dma_addr; desc_addr = (u32) dma->desc_buf.addr; diff --git a/trunk/sound/pci/echoaudio/Makefile b/trunk/sound/pci/echoaudio/Makefile deleted file mode 100644 index 7b576aeb3f8d..000000000000 --- a/trunk/sound/pci/echoaudio/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# Makefile for ALSA Echoaudio soundcard drivers -# Copyright (c) 2003 by Giuliano Pochini -# - -snd-darla20-objs := darla20.o -snd-gina20-objs := gina20.o -snd-layla20-objs := layla20.o -snd-darla24-objs := darla24.o -snd-gina24-objs := gina24.o -snd-layla24-objs := layla24.o -snd-mona-objs := mona.o -snd-mia-objs := mia.o -snd-echo3g-objs := echo3g.o -snd-indigo-objs := indigo.o -snd-indigoio-objs := indigoio.o -snd-indigodj-objs := indigodj.o - -obj-$(CONFIG_SND_DARLA20) += snd-darla20.o -obj-$(CONFIG_SND_GINA20) += snd-gina20.o -obj-$(CONFIG_SND_LAYLA20) += snd-layla20.o -obj-$(CONFIG_SND_DARLA24) += snd-darla24.o -obj-$(CONFIG_SND_GINA24) += snd-gina24.o -obj-$(CONFIG_SND_LAYLA24) += snd-layla24.o -obj-$(CONFIG_SND_MONA) += snd-mona.o -obj-$(CONFIG_SND_MIA) += snd-mia.o -obj-$(CONFIG_SND_ECHO3G) += snd-echo3g.o -obj-$(CONFIG_SND_INDIGO) += snd-indigo.o -obj-$(CONFIG_SND_INDIGOIO) += snd-indigoio.o -obj-$(CONFIG_SND_INDIGODJ) += snd-indigodj.o diff --git a/trunk/sound/pci/echoaudio/darla20.c b/trunk/sound/pci/echoaudio/darla20.c deleted file mode 100644 index b7108e29a668..000000000000 --- a/trunk/sound/pci/echoaudio/darla20.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define ECHOGALS_FAMILY -#define ECHOCARD_DARLA20 -#define ECHOCARD_NAME "Darla20" -#define ECHOCARD_HAS_MONITOR - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 2 */ -#define PX_DIGITAL_IN 10 /* 0 */ -#define PX_NUM 10 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 8 */ -#define BX_DIGITAL_OUT 8 /* 0 */ -#define BX_ANALOG_IN 8 /* 2 */ -#define BX_DIGITAL_IN 10 /* 0 */ -#define BX_NUM 10 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_DARLA20_DSP 0 - -static const struct firmware card_fw[] = { - {0, "darla20_dsp.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0010, 0, 0, 0}, /* DSP 56301 Darla20 rev.0 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "darla20_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" diff --git a/trunk/sound/pci/echoaudio/darla20_dsp.c b/trunk/sound/pci/echoaudio/darla20_dsp.c deleted file mode 100644 index 4159e3bc186f..000000000000 --- a/trunk/sound/pci/echoaudio/darla20_dsp.c +++ /dev/null @@ -1,125 +0,0 @@ -/*************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Darla20\n")); - snd_assert((subdevice_id & 0xfff0) == DARLA20, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = &card_fw[FW_DARLA20_DSP]; - chip->spdif_status = GD_SPDIF_STATUS_UNDEF; - chip->clock_state = GD_CLOCK_UNDEF; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -/* The Darla20 has no external clock sources */ -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - return ECHO_CLOCK_BIT_INTERNAL; -} - - - -/* The Darla20 has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u8 clock_state, spdif_status; - - if (wait_handshake(chip)) - return -EIO; - - switch (rate) { - case 44100: - clock_state = GD_CLOCK_44; - spdif_status = GD_SPDIF_STATUS_44; - break; - case 48000: - clock_state = GD_CLOCK_48; - spdif_status = GD_SPDIF_STATUS_48; - break; - default: - clock_state = GD_CLOCK_NOCHANGE; - spdif_status = GD_SPDIF_STATUS_NOCHANGE; - break; - } - - if (chip->clock_state == clock_state) - clock_state = GD_CLOCK_NOCHANGE; - if (spdif_status == chip->spdif_status) - spdif_status = GD_SPDIF_STATUS_NOCHANGE; - - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->comm_page->gd_clock_state = clock_state; - chip->comm_page->gd_spdif_status = spdif_status; - chip->comm_page->gd_resampler_state = 3; /* magic number - should always be 3 */ - - /* Save the new audio state if it changed */ - if (clock_state != GD_CLOCK_NOCHANGE) - chip->clock_state = clock_state; - if (spdif_status != GD_SPDIF_STATUS_NOCHANGE) - chip->spdif_status = spdif_status; - chip->sample_rate = rate; - - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); -} diff --git a/trunk/sound/pci/echoaudio/darla24.c b/trunk/sound/pci/echoaudio/darla24.c deleted file mode 100644 index e59a982ee361..000000000000 --- a/trunk/sound/pci/echoaudio/darla24.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define ECHOGALS_FAMILY -#define ECHOCARD_DARLA24 -#define ECHOCARD_NAME "Darla24" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_SUPER_INTERLEAVE - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 2 */ -#define PX_DIGITAL_IN 10 /* 0 */ -#define PX_NUM 10 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 8 */ -#define BX_DIGITAL_OUT 8 /* 0 */ -#define BX_ANALOG_IN 8 /* 2 */ -#define BX_DIGITAL_IN 10 /* 0 */ -#define BX_NUM 10 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_DARLA24_DSP 0 - -static const struct firmware card_fw[] = { - {0, "darla24_dsp.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0040, 0, 0, 0}, /* DSP 56301 Darla24 rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0041, 0, 0, 0}, /* DSP 56301 Darla24 rev.1 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_8000_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "darla24_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" diff --git a/trunk/sound/pci/echoaudio/darla24_dsp.c b/trunk/sound/pci/echoaudio/darla24_dsp.c deleted file mode 100644 index 79938eed7e9c..000000000000 --- a/trunk/sound/pci/echoaudio/darla24_dsp.c +++ /dev/null @@ -1,156 +0,0 @@ -/*************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Darla24\n")); - snd_assert((subdevice_id & 0xfff0) == DARLA24, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = &card_fw[FW_DARLA24_DSP]; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | - ECHO_CLOCK_BIT_ESYNC; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_ESYNC) - clock_bits |= ECHO_CLOCK_BIT_ESYNC; - - return clock_bits; -} - - - -/* The Darla24 has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u8 clock; - - switch (rate) { - case 96000: - clock = GD24_96000; - break; - case 88200: - clock = GD24_88200; - break; - case 48000: - clock = GD24_48000; - break; - case 44100: - clock = GD24_44100; - break; - case 32000: - clock = GD24_32000; - break; - case 22050: - clock = GD24_22050; - break; - case 16000: - clock = GD24_16000; - break; - case 11025: - clock = GD24_11025; - break; - case 8000: - clock = GD24_8000; - break; - default: - DE_ACT(("set_sample_rate: Error, invalid sample rate %d\n", - rate)); - return -EINVAL; - } - - if (wait_handshake(chip)) - return -EIO; - - DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock)); - chip->sample_rate = rate; - - /* Override the sample rate if this card is set to Echo sync. */ - if (chip->input_clock == ECHO_CLOCK_ESYNC) - clock = GD24_EXT_SYNC; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP ? */ - chip->comm_page->gd_clock_state = clock; - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - snd_assert(clock == ECHO_CLOCK_INTERNAL || - clock == ECHO_CLOCK_ESYNC, return -EINVAL); - chip->input_clock = clock; - return set_sample_rate(chip, chip->sample_rate); -} - diff --git a/trunk/sound/pci/echoaudio/echo3g.c b/trunk/sound/pci/echoaudio/echo3g.c deleted file mode 100644 index 12099fe1547d..000000000000 --- a/trunk/sound/pci/echoaudio/echo3g.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define ECHO3G_FAMILY -#define ECHOCARD_ECHO3G -#define ECHOCARD_NAME "Echo3G" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_ASIC -#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH -#define ECHOCARD_HAS_ADAT 6 -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 -#define ECHOCARD_HAS_MIDI -#define ECHOCARD_HAS_PHANTOM_POWER - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 -#define PX_DIGITAL_OUT chip->px_digital_out -#define PX_ANALOG_IN chip->px_analog_in -#define PX_DIGITAL_IN chip->px_digital_in -#define PX_NUM chip->px_num - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 -#define BX_DIGITAL_OUT chip->bx_digital_out -#define BX_ANALOG_IN chip->bx_analog_in -#define BX_DIGITAL_IN chip->bx_digital_in -#define BX_NUM chip->bx_num - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_361_LOADER 0 -#define FW_ECHO3G_DSP 1 -#define FW_3G_ASIC 2 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "echo3g_dsp.fw"}, - {0, "3g_asic.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x0100, 0, 0, 0}, /* Echo 3G */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000 | - SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 32000, - .rate_max = 100000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, -}; - -#include "echo3g_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio_3g.c" -#include "echoaudio.c" -#include "midi.c" diff --git a/trunk/sound/pci/echoaudio/echo3g_dsp.c b/trunk/sound/pci/echoaudio/echo3g_dsp.c deleted file mode 100644 index d26a1d1f3ed1..000000000000 --- a/trunk/sound/pci/echoaudio/echo3g_dsp.c +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - -static int load_asic(struct echoaudio *chip); -static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode); -static int set_digital_mode(struct echoaudio *chip, u8 mode); -static int check_asic_status(struct echoaudio *chip); -static int set_sample_rate(struct echoaudio *chip, u32 rate); -static int set_input_clock(struct echoaudio *chip, u16 clock); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int set_phantom_power(struct echoaudio *chip, char on); -static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq, - char force); - -#include - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - local_irq_enable(); - DE_INIT(("init_hw() - Echo3G\n")); - snd_assert((subdevice_id & 0xfff0) == ECHO3G, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->comm_page->e3g_frq_register = - __constant_cpu_to_le32((E3G_MAGIC_NUMBER / 48000) - 2); - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->has_midi = TRUE; - chip->dsp_code_to_load = &card_fw[FW_ECHO3G_DSP]; - - /* Load the DSP code and the ASIC on the PCI card and get - what type of external box is attached */ - err = load_firmware(chip); - - if (err < 0) { - return err; - } else if (err == E3G_GINA3G_BOX_TYPE) { - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | - ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_ADAT; - chip->card_name = "Gina3G"; - chip->px_digital_out = chip->bx_digital_out = 6; - chip->px_analog_in = chip->bx_analog_in = 14; - chip->px_digital_in = chip->bx_digital_in = 16; - chip->px_num = chip->bx_num = 24; - chip->has_phantom_power = TRUE; - chip->hasnt_input_nominal_level = TRUE; - } else if (err == E3G_LAYLA3G_BOX_TYPE) { - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | - ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_ADAT | - ECHO_CLOCK_BIT_WORD; - chip->card_name = "Layla3G"; - chip->px_digital_out = chip->bx_digital_out = 8; - chip->px_analog_in = chip->bx_analog_in = 16; - chip->px_digital_in = chip->bx_digital_in = 24; - chip->px_num = chip->bx_num = 32; - } else { - return -ENODEV; - } - - chip->digital_modes = ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | - ECHOCAPS_HAS_DIGITAL_MODE_ADAT; - chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - chip->professional_spdif = FALSE; - chip->non_audio_spdif = FALSE; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); - snd_assert(err >= 0, return err); - err = set_phantom_power(chip, 0); - snd_assert(err >= 0, return err); - err = set_professional_spdif(chip, TRUE); - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static int set_phantom_power(struct echoaudio *chip, char on) -{ - u32 control_reg = le32_to_cpu(chip->comm_page->control_register); - - if (on) - control_reg |= E3G_PHANTOM_POWER; - else - control_reg &= ~E3G_PHANTOM_POWER; - - chip->phantom_power = on; - return write_control_reg(chip, control_reg, - le32_to_cpu(chip->comm_page->e3g_frq_register), - 0); -} diff --git a/trunk/sound/pci/echoaudio/echoaudio.c b/trunk/sound/pci/echoaudio/echoaudio.c deleted file mode 100644 index 27a8dbe6f6a8..000000000000 --- a/trunk/sound/pci/echoaudio/echoaudio.c +++ /dev/null @@ -1,2196 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -MODULE_AUTHOR("Giuliano Pochini "); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Echoaudio " ECHOCARD_NAME " soundcards driver"); -MODULE_SUPPORTED_DEVICE("{{Echoaudio," ECHOCARD_NAME "}}"); -MODULE_DEVICE_TABLE(pci, snd_echo_ids); - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for " ECHOCARD_NAME " soundcard."); -module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for " ECHOCARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable " ECHOCARD_NAME " soundcard."); - -static unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999}; - -static int get_firmware(const struct firmware **fw_entry, - const struct firmware *frm, struct echoaudio *chip) -{ - int err; - char name[30]; - DE_ACT(("firmware requested: %s\n", frm->data)); - snprintf(name, sizeof(name), "ea/%s", frm->data); - if ((err = request_firmware(fw_entry, name, pci_device(chip))) < 0) - snd_printk(KERN_ERR "get_firmware(): Firmware not available (%d)\n", err); - return err; -} - -static void free_firmware(const struct firmware *fw_entry) -{ - release_firmware(fw_entry); - DE_ACT(("firmware released\n")); -} - - - -/****************************************************************************** - PCM interface -******************************************************************************/ - -static void audiopipe_free(struct snd_pcm_runtime *runtime) -{ - struct audiopipe *pipe = runtime->private_data; - - if (pipe->sgpage.area) - snd_dma_free_pages(&pipe->sgpage); - kfree(pipe); -} - - - -static int hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_mask fmt; - - snd_mask_any(&fmt); - -#ifndef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - /* >=2 channels cannot be S32_BE */ - if (c->min == 2) { - fmt.bits[0] &= ~SNDRV_PCM_FMTBIT_S32_BE; - return snd_mask_refine(f, &fmt); - } -#endif - /* > 2 channels cannot be U8 and S32_BE */ - if (c->min > 2) { - fmt.bits[0] &= ~(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_BE); - return snd_mask_refine(f, &fmt); - } - /* Mono is ok with any format */ - return 0; -} - - - -static int hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_interval ch; - - snd_interval_any(&ch); - - /* S32_BE is mono (and stereo) only */ - if (f->bits[0] == SNDRV_PCM_FMTBIT_S32_BE) { - ch.min = 1; -#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - ch.max = 2; -#else - ch.max = 1; -#endif - ch.integer = 1; - return snd_interval_refine(c, &ch); - } - /* U8 can be only mono or stereo */ - if (f->bits[0] == SNDRV_PCM_FMTBIT_U8) { - ch.min = 1; - ch.max = 2; - ch.integer = 1; - return snd_interval_refine(c, &ch); - } - /* S16_LE, S24_3LE and S32_LE support any number of channels. */ - return 0; -} - - - -static int hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_mask fmt; - u64 fmask; - snd_mask_any(&fmt); - - fmask = fmt.bits[0] + ((u64)fmt.bits[1] << 32); - - /* >2 channels must be S16_LE, S24_3LE or S32_LE */ - if (c->min > 2) { - fmask &= SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE; - /* 1 channel must be S32_BE or S32_LE */ - } else if (c->max == 1) - fmask &= SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE; -#ifndef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - /* 2 channels cannot be S32_BE */ - else if (c->min == 2 && c->max == 2) - fmask &= ~SNDRV_PCM_FMTBIT_S32_BE; -#endif - else - return 0; - - fmt.bits[0] &= (u32)fmask; - fmt.bits[1] &= (u32)(fmask >> 32); - return snd_mask_refine(f, &fmt); -} - - - -static int hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_interval ch; - u64 fmask; - - snd_interval_any(&ch); - ch.integer = 1; - fmask = f->bits[0] + ((u64)f->bits[1] << 32); - - /* S32_BE is mono (and stereo) only */ - if (fmask == SNDRV_PCM_FMTBIT_S32_BE) { - ch.min = 1; -#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - ch.max = 2; -#else - ch.max = 1; -#endif - /* U8 is stereo only */ - } else if (fmask == SNDRV_PCM_FMTBIT_U8) - ch.min = ch.max = 2; - /* S16_LE and S24_3LE must be at least stereo */ - else if (!(fmask & ~(SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE))) - ch.min = 2; - else - return 0; - - return snd_interval_refine(c, &ch); -} - - - -/* Since the sample rate is a global setting, do allow the user to change the -sample rate only if there is only one pcm device open. */ -static int hw_rule_sample_rate(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct echoaudio *chip = rule->private; - struct snd_interval fixed; - - if (!chip->can_set_rate) { - snd_interval_any(&fixed); - fixed.min = fixed.max = chip->sample_rate; - return snd_interval_refine(rate, &fixed); - } - return 0; -} - - -static int pcm_open(struct snd_pcm_substream *substream, - signed char max_channels) -{ - struct echoaudio *chip; - struct snd_pcm_runtime *runtime; - struct audiopipe *pipe; - int err, i; - - if (max_channels <= 0) - return -EAGAIN; - - chip = snd_pcm_substream_chip(substream); - runtime = substream->runtime; - - if (!(pipe = kmalloc(sizeof(struct audiopipe), GFP_KERNEL))) - return -ENOMEM; - memset(pipe, 0, sizeof(struct audiopipe)); - pipe->index = -1; /* Not configured yet */ - - /* Set up hw capabilities and contraints */ - memcpy(&pipe->hw, &pcm_hardware_skel, sizeof(struct snd_pcm_hardware)); - DE_HWP(("max_channels=%d\n", max_channels)); - pipe->constr.list = channels_list; - pipe->constr.mask = 0; - for (i = 0; channels_list[i] <= max_channels; i++); - pipe->constr.count = i; - if (pipe->hw.channels_max > max_channels) - pipe->hw.channels_max = max_channels; - if (chip->digital_mode == DIGITAL_MODE_ADAT) { - pipe->hw.rate_max = 48000; - pipe->hw.rates &= SNDRV_PCM_RATE_8000_48000; - } - - runtime->hw = pipe->hw; - runtime->private_data = pipe; - runtime->private_free = audiopipe_free; - snd_pcm_set_sync(substream); - - /* Only mono and any even number of channels are allowed */ - if ((err = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &pipe->constr)) < 0) - return err; - - /* All periods should have the same size */ - if ((err = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; - - /* The hw accesses memory in chunks 32 frames long and they should be - 32-bytes-aligned. It's not a requirement, but it seems that IRQs are - generated with a resolution of 32 frames. Thus we need the following */ - if ((err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_SIZE, - 32)) < 0) - return err; - if ((err = snd_pcm_hw_constraint_step(runtime, 0, - SNDRV_PCM_HW_PARAM_BUFFER_SIZE, - 32)) < 0) - return err; - - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - hw_rule_sample_rate, chip, - SNDRV_PCM_HW_PARAM_RATE, -1)) < 0) - return err; - - /* Finally allocate a page for the scatter-gather list */ - if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - PAGE_SIZE, &pipe->sgpage)) < 0) { - DE_HWP(("s-g list allocation failed\n")); - return err; - } - - return 0; -} - - - -static int pcm_analog_in_open(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - int err; - - DE_ACT(("pcm_analog_in_open\n")); - if ((err = pcm_open(substream, num_analog_busses_in(chip) - - substream->number)) < 0) - return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_capture_channels_by_format, NULL, - SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) - return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_capture_format_by_channels, NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) - return err; - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; - DE_HWP(("pcm_analog_in_open cs=%d oc=%d r=%d\n", - chip->can_set_rate, atomic_read(&chip->opencount), - chip->sample_rate)); - return 0; -} - - - -static int pcm_analog_out_open(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - int max_channels, err; - -#ifdef ECHOCARD_HAS_VMIXER - max_channels = num_pipes_out(chip); -#else - max_channels = num_analog_busses_out(chip); -#endif - DE_ACT(("pcm_analog_out_open\n")); - if ((err = pcm_open(substream, max_channels - substream->number)) < 0) - return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_playback_channels_by_format, - NULL, - SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) - return err; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_playback_format_by_channels, - NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) - return err; - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; - DE_HWP(("pcm_analog_out_open cs=%d oc=%d r=%d\n", - chip->can_set_rate, atomic_read(&chip->opencount), - chip->sample_rate)); - return 0; -} - - - -#ifdef ECHOCARD_HAS_DIGITAL_IO - -static int pcm_digital_in_open(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - int err, max_channels; - - DE_ACT(("pcm_digital_in_open\n")); - max_channels = num_digital_busses_in(chip) - substream->number; - down(&chip->mode_mutex); - if (chip->digital_mode == DIGITAL_MODE_ADAT) - err = pcm_open(substream, max_channels); - else /* If the card has ADAT, subtract the 6 channels - * that S/PDIF doesn't have - */ - err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT); - - if (err < 0) - goto din_exit; - - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_capture_channels_by_format, NULL, - SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) - goto din_exit; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_capture_format_by_channels, NULL, - SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) - goto din_exit; - - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; - -din_exit: - up(&chip->mode_mutex); - return err; -} - - - -#ifndef ECHOCARD_HAS_VMIXER /* See the note in snd_echo_new_pcm() */ - -static int pcm_digital_out_open(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - int err, max_channels; - - DE_ACT(("pcm_digital_out_open\n")); - max_channels = num_digital_busses_out(chip) - substream->number; - down(&chip->mode_mutex); - if (chip->digital_mode == DIGITAL_MODE_ADAT) - err = pcm_open(substream, max_channels); - else /* If the card has ADAT, subtract the 6 channels - * that S/PDIF doesn't have - */ - err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT); - - if (err < 0) - goto dout_exit; - - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - hw_rule_playback_channels_by_format, - NULL, SNDRV_PCM_HW_PARAM_FORMAT, - -1)) < 0) - goto dout_exit; - if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_FORMAT, - hw_rule_playback_format_by_channels, - NULL, SNDRV_PCM_HW_PARAM_CHANNELS, - -1)) < 0) - goto dout_exit; - atomic_inc(&chip->opencount); - if (atomic_read(&chip->opencount) > 1 && chip->rate_set) - chip->can_set_rate=0; -dout_exit: - up(&chip->mode_mutex); - return err; -} - -#endif /* !ECHOCARD_HAS_VMIXER */ - -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - - - -static int pcm_close(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - int oc; - - /* Nothing to do here. Audio is already off and pipe will be - * freed by its callback - */ - DE_ACT(("pcm_close\n")); - - atomic_dec(&chip->opencount); - oc = atomic_read(&chip->opencount); - DE_ACT(("pcm_close oc=%d cs=%d rs=%d\n", oc, - chip->can_set_rate, chip->rate_set)); - if (oc < 2) - chip->can_set_rate = 1; - if (oc == 0) - chip->rate_set = 0; - DE_ACT(("pcm_close2 oc=%d cs=%d rs=%d\n", oc, - chip->can_set_rate,chip->rate_set)); - - return 0; -} - - - -/* Channel allocation and scatter-gather list setup */ -static int init_engine(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params, - int pipe_index, int interleave) -{ - struct echoaudio *chip; - int err, per, rest, page, edge, offs; - struct snd_sg_buf *sgbuf; - struct audiopipe *pipe; - - chip = snd_pcm_substream_chip(substream); - pipe = (struct audiopipe *) substream->runtime->private_data; - - /* Sets up che hardware. If it's already initialized, reset and - * redo with the new parameters - */ - spin_lock_irq(&chip->lock); - if (pipe->index >= 0) { - DE_HWP(("hwp_ie free(%d)\n", pipe->index)); - err = free_pipes(chip, pipe); - snd_assert(!err); - chip->substream[pipe->index] = NULL; - } - - err = allocate_pipes(chip, pipe, pipe_index, interleave); - if (err < 0) { - spin_unlock_irq(&chip->lock); - DE_ACT((KERN_NOTICE "allocate_pipes(%d) err=%d\n", - pipe_index, err)); - return err; - } - spin_unlock_irq(&chip->lock); - DE_ACT((KERN_NOTICE "allocate_pipes()=%d\n", pipe_index)); - - DE_HWP(("pcm_hw_params (bufsize=%dB periods=%d persize=%dB)\n", - params_buffer_bytes(hw_params), params_periods(hw_params), - params_period_bytes(hw_params))); - err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (err < 0) { - snd_printk(KERN_ERR "malloc_pages err=%d\n", err); - spin_lock_irq(&chip->lock); - free_pipes(chip, pipe); - spin_unlock_irq(&chip->lock); - pipe->index = -1; - return err; - } - - sgbuf = snd_pcm_substream_sgbuf(substream); - - DE_HWP(("pcm_hw_params table size=%d pages=%d\n", - sgbuf->size, sgbuf->pages)); - sglist_init(chip, pipe); - edge = PAGE_SIZE; - for (offs = page = per = 0; offs < params_buffer_bytes(hw_params); - per++) { - rest = params_period_bytes(hw_params); - if (offs + rest > params_buffer_bytes(hw_params)) - rest = params_buffer_bytes(hw_params) - offs; - while (rest) { - if (rest <= edge - offs) { - sglist_add_mapping(chip, pipe, - snd_sgbuf_get_addr(sgbuf, offs), - rest); - sglist_add_irq(chip, pipe); - offs += rest; - rest = 0; - } else { - sglist_add_mapping(chip, pipe, - snd_sgbuf_get_addr(sgbuf, offs), - edge - offs); - rest -= edge - offs; - offs = edge; - } - if (offs == edge) { - edge += PAGE_SIZE; - page++; - } - } - } - - /* Close the ring buffer */ - sglist_wrap(chip, pipe); - - /* This stuff is used by the irq handler, so it must be - * initialized before chip->substream - */ - chip->last_period[pipe_index] = 0; - pipe->last_counter = 0; - pipe->position = 0; - smp_wmb(); - chip->substream[pipe_index] = substream; - chip->rate_set = 1; - spin_lock_irq(&chip->lock); - set_sample_rate(chip, hw_params->rate_num / hw_params->rate_den); - spin_unlock_irq(&chip->lock); - DE_HWP(("pcm_hw_params ok\n")); - return 0; -} - - - -static int pcm_analog_in_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - - return init_engine(substream, hw_params, px_analog_in(chip) + - substream->number, params_channels(hw_params)); -} - - - -static int pcm_analog_out_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return init_engine(substream, hw_params, substream->number, - params_channels(hw_params)); -} - - - -#ifdef ECHOCARD_HAS_DIGITAL_IO - -static int pcm_digital_in_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - - return init_engine(substream, hw_params, px_digital_in(chip) + - substream->number, params_channels(hw_params)); -} - - - -#ifndef ECHOCARD_HAS_VMIXER /* See the note in snd_echo_new_pcm() */ -static int pcm_digital_out_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - - return init_engine(substream, hw_params, px_digital_out(chip) + - substream->number, params_channels(hw_params)); -} -#endif /* !ECHOCARD_HAS_VMIXER */ - -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - - - -static int pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip; - struct audiopipe *pipe; - - chip = snd_pcm_substream_chip(substream); - pipe = (struct audiopipe *) substream->runtime->private_data; - - spin_lock_irq(&chip->lock); - if (pipe->index >= 0) { - DE_HWP(("pcm_hw_free(%d)\n", pipe->index)); - free_pipes(chip, pipe); - chip->substream[pipe->index] = NULL; - pipe->index = -1; - } - spin_unlock_irq(&chip->lock); - - DE_HWP(("pcm_hw_freed\n")); - snd_pcm_lib_free_pages(substream); - return 0; -} - - - -static int pcm_prepare(struct snd_pcm_substream *substream) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct audioformat format; - int pipe_index = ((struct audiopipe *)runtime->private_data)->index; - - DE_HWP(("Prepare rate=%d format=%d channels=%d\n", - runtime->rate, runtime->format, runtime->channels)); - format.interleave = runtime->channels; - format.data_are_bigendian = 0; - format.mono_to_stereo = 0; - switch (runtime->format) { - case SNDRV_PCM_FORMAT_U8: - format.bits_per_sample = 8; - break; - case SNDRV_PCM_FORMAT_S16_LE: - format.bits_per_sample = 16; - break; - case SNDRV_PCM_FORMAT_S24_3LE: - format.bits_per_sample = 24; - break; - case SNDRV_PCM_FORMAT_S32_BE: - format.data_are_bigendian = 1; - case SNDRV_PCM_FORMAT_S32_LE: - format.bits_per_sample = 32; - break; - default: - DE_HWP(("Prepare error: unsupported format %d\n", - runtime->format)); - return -EINVAL; - } - - snd_assert(pipe_index < px_num(chip), return -EINVAL); - snd_assert(is_pipe_allocated(chip, pipe_index), return -EINVAL); - set_audio_format(chip, pipe_index, &format); - return 0; -} - - - -static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct echoaudio *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - struct audiopipe *pipe = runtime->private_data; - int i, err; - u32 channelmask = 0; - struct list_head *pos; - struct snd_pcm_substream *s; - - snd_pcm_group_for_each(pos, substream) { - s = snd_pcm_group_substream_entry(pos); - for (i = 0; i < DSP_MAXPIPES; i++) { - if (s == chip->substream[i]) { - channelmask |= 1 << i; - snd_pcm_trigger_done(s, substream); - } - } - } - - spin_lock(&chip->lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - DE_ACT(("pcm_trigger start\n")); - for (i = 0; i < DSP_MAXPIPES; i++) { - if (channelmask & (1 << i)) { - pipe = chip->substream[i]->runtime->private_data; - switch (pipe->state) { - case PIPE_STATE_STOPPED: - chip->last_period[i] = 0; - pipe->last_counter = 0; - pipe->position = 0; - *pipe->dma_counter = 0; - case PIPE_STATE_PAUSED: - pipe->state = PIPE_STATE_STARTED; - break; - case PIPE_STATE_STARTED: - break; - } - } - } - err = start_transport(chip, channelmask, - chip->pipe_cyclic_mask); - break; - case SNDRV_PCM_TRIGGER_STOP: - DE_ACT(("pcm_trigger stop\n")); - for (i = 0; i < DSP_MAXPIPES; i++) { - if (channelmask & (1 << i)) { - pipe = chip->substream[i]->runtime->private_data; - pipe->state = PIPE_STATE_STOPPED; - } - } - err = stop_transport(chip, channelmask); - break; - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - DE_ACT(("pcm_trigger pause\n")); - for (i = 0; i < DSP_MAXPIPES; i++) { - if (channelmask & (1 << i)) { - pipe = chip->substream[i]->runtime->private_data; - pipe->state = PIPE_STATE_PAUSED; - } - } - err = pause_transport(chip, channelmask); - break; - default: - err = -EINVAL; - } - spin_unlock(&chip->lock); - return err; -} - - - -static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct audiopipe *pipe = runtime->private_data; - size_t cnt, bufsize, pos; - - cnt = le32_to_cpu(*pipe->dma_counter); - pipe->position += cnt - pipe->last_counter; - pipe->last_counter = cnt; - bufsize = substream->runtime->buffer_size; - pos = bytes_to_frames(substream->runtime, pipe->position); - - while (pos >= bufsize) { - pipe->position -= frames_to_bytes(substream->runtime, bufsize); - pos -= bufsize; - } - return pos; -} - - - -/* pcm *_ops structures */ -static struct snd_pcm_ops analog_playback_ops = { - .open = pcm_analog_out_open, - .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_analog_out_hw_params, - .hw_free = pcm_hw_free, - .prepare = pcm_prepare, - .trigger = pcm_trigger, - .pointer = pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; -static struct snd_pcm_ops analog_capture_ops = { - .open = pcm_analog_in_open, - .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_analog_in_hw_params, - .hw_free = pcm_hw_free, - .prepare = pcm_prepare, - .trigger = pcm_trigger, - .pointer = pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; -#ifdef ECHOCARD_HAS_DIGITAL_IO -#ifndef ECHOCARD_HAS_VMIXER -static struct snd_pcm_ops digital_playback_ops = { - .open = pcm_digital_out_open, - .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_digital_out_hw_params, - .hw_free = pcm_hw_free, - .prepare = pcm_prepare, - .trigger = pcm_trigger, - .pointer = pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; -#endif /* !ECHOCARD_HAS_VMIXER */ -static struct snd_pcm_ops digital_capture_ops = { - .open = pcm_digital_in_open, - .close = pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = pcm_digital_in_hw_params, - .hw_free = pcm_hw_free, - .prepare = pcm_prepare, - .trigger = pcm_trigger, - .pointer = pcm_pointer, - .page = snd_pcm_sgbuf_ops_page, -}; -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - - - -/* Preallocate memory only for the first substream because it's the most - * used one - */ -static int snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev) -{ - struct snd_pcm_substream *ss; - int stream, err; - - for (stream = 0; stream < 2; stream++) - for (ss = pcm->streams[stream].substream; ss; ss = ss->next) { - err = snd_pcm_lib_preallocate_pages(ss, SNDRV_DMA_TYPE_DEV_SG, - dev, - ss->number ? 0 : 128<<10, - 256<<10); - if (err < 0) - return err; - } - return 0; -} - - - -/*<--snd_echo_probe() */ -static int __devinit snd_echo_new_pcm(struct echoaudio *chip) -{ - struct snd_pcm *pcm; - int err; - -#ifdef ECHOCARD_HAS_VMIXER - /* This card has a Vmixer, that is there is no direct mapping from PCM - streams to physical outputs. The user can mix the streams as he wishes - via control interface and it's possible to send any stream to any - output, thus it makes no sense to keep analog and digital outputs - separated */ - - /* PCM#0 Virtual outputs and analog inputs */ - if ((err = snd_pcm_new(chip->card, "PCM", 0, num_pipes_out(chip), - num_analog_busses_in(chip), &pcm)) < 0) - return err; - pcm->private_data = chip; - chip->analog_pcm = pcm; - strcpy(pcm->name, chip->card->shortname); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops); - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) - return err; - DE_INIT(("Analog PCM ok\n")); - -#ifdef ECHOCARD_HAS_DIGITAL_IO - /* PCM#1 Digital inputs, no outputs */ - if ((err = snd_pcm_new(chip->card, "Digital PCM", 1, 0, - num_digital_busses_in(chip), &pcm)) < 0) - return err; - pcm->private_data = chip; - chip->digital_pcm = pcm; - strcpy(pcm->name, chip->card->shortname); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops); - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) - return err; - DE_INIT(("Digital PCM ok\n")); -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - -#else /* ECHOCARD_HAS_VMIXER */ - - /* The card can manage substreams formed by analog and digital channels - at the same time, but I prefer to keep analog and digital channels - separated, because that mixed thing is confusing and useless. So we - register two PCM devices: */ - - /* PCM#0 Analog i/o */ - if ((err = snd_pcm_new(chip->card, "Analog PCM", 0, - num_analog_busses_out(chip), - num_analog_busses_in(chip), &pcm)) < 0) - return err; - pcm->private_data = chip; - chip->analog_pcm = pcm; - strcpy(pcm->name, chip->card->shortname); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops); - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) - return err; - DE_INIT(("Analog PCM ok\n")); - -#ifdef ECHOCARD_HAS_DIGITAL_IO - /* PCM#1 Digital i/o */ - if ((err = snd_pcm_new(chip->card, "Digital PCM", 1, - num_digital_busses_out(chip), - num_digital_busses_in(chip), &pcm)) < 0) - return err; - pcm->private_data = chip; - chip->digital_pcm = pcm; - strcpy(pcm->name, chip->card->shortname); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &digital_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops); - if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) - return err; - DE_INIT(("Digital PCM ok\n")); -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - -#endif /* ECHOCARD_HAS_VMIXER */ - - return 0; -} - - - - -/****************************************************************************** - Control interface -******************************************************************************/ - -/******************* PCM output volume *******************/ -static int snd_echo_output_gain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = num_busses_out(chip); - uinfo->value.integer.min = ECHOGAIN_MINOUT; - uinfo->value.integer.max = ECHOGAIN_MAXOUT; - return 0; -} - -static int snd_echo_output_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c; - - chip = snd_kcontrol_chip(kcontrol); - for (c = 0; c < num_busses_out(chip); c++) - ucontrol->value.integer.value[c] = chip->output_gain[c]; - return 0; -} - -static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c, changed, gain; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); - for (c = 0; c < num_busses_out(chip); c++) { - gain = ucontrol->value.integer.value[c]; - /* Ignore out of range values */ - if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) - continue; - if (chip->output_gain[c] != gain) { - set_output_gain(chip, c, gain); - changed = 1; - } - } - if (changed) - update_output_line_level(chip); - spin_unlock_irq(&chip->lock); - return changed; -} - -#ifdef ECHOCARD_HAS_VMIXER -/* On Vmixer cards this one controls the line-out volume */ -static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = { - .name = "Line Playback Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_echo_output_gain_info, - .get = snd_echo_output_gain_get, - .put = snd_echo_output_gain_put, -}; -#else -static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = { - .name = "PCM Playback Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_echo_output_gain_info, - .get = snd_echo_output_gain_get, - .put = snd_echo_output_gain_put, -}; -#endif - - - -#ifdef ECHOCARD_HAS_INPUT_GAIN - -/******************* Analog input volume *******************/ -static int snd_echo_input_gain_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = num_analog_busses_in(chip); - uinfo->value.integer.min = ECHOGAIN_MININP; - uinfo->value.integer.max = ECHOGAIN_MAXINP; - return 0; -} - -static int snd_echo_input_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c; - - chip = snd_kcontrol_chip(kcontrol); - for (c = 0; c < num_analog_busses_in(chip); c++) - ucontrol->value.integer.value[c] = chip->input_gain[c]; - return 0; -} - -static int snd_echo_input_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c, gain, changed; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); - for (c = 0; c < num_analog_busses_in(chip); c++) { - gain = ucontrol->value.integer.value[c]; - /* Ignore out of range values */ - if (gain < ECHOGAIN_MININP || gain > ECHOGAIN_MAXINP) - continue; - if (chip->input_gain[c] != gain) { - set_input_gain(chip, c, gain); - changed = 1; - } - } - if (changed) - update_input_line_level(chip); - spin_unlock_irq(&chip->lock); - return changed; -} - -static struct snd_kcontrol_new snd_echo_line_input_gain __devinitdata = { - .name = "Line Capture Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_echo_input_gain_info, - .get = snd_echo_input_gain_get, - .put = snd_echo_input_gain_put, -}; - -#endif /* ECHOCARD_HAS_INPUT_GAIN */ - - - -#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL - -/************ Analog output nominal level (+4dBu / -10dBV) ***************/ -static int snd_echo_output_nominal_info (struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = num_analog_busses_out(chip); - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_echo_output_nominal_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c; - - chip = snd_kcontrol_chip(kcontrol); - for (c = 0; c < num_analog_busses_out(chip); c++) - ucontrol->value.integer.value[c] = chip->nominal_level[c]; - return 0; -} - -static int snd_echo_output_nominal_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c, changed; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); - for (c = 0; c < num_analog_busses_out(chip); c++) { - if (chip->nominal_level[c] != ucontrol->value.integer.value[c]) { - set_nominal_level(chip, c, - ucontrol->value.integer.value[c]); - changed = 1; - } - } - if (changed) - update_output_line_level(chip); - spin_unlock_irq(&chip->lock); - return changed; -} - -static struct snd_kcontrol_new snd_echo_output_nominal_level __devinitdata = { - .name = "Line Playback Switch (-10dBV)", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_echo_output_nominal_info, - .get = snd_echo_output_nominal_get, - .put = snd_echo_output_nominal_put, -}; - -#endif /* ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL */ - - - -#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL - -/*************** Analog input nominal level (+4dBu / -10dBV) ***************/ -static int snd_echo_input_nominal_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = num_analog_busses_in(chip); - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_echo_input_nominal_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c; - - chip = snd_kcontrol_chip(kcontrol); - for (c = 0; c < num_analog_busses_in(chip); c++) - ucontrol->value.integer.value[c] = - chip->nominal_level[bx_analog_in(chip) + c]; - return 0; -} - -static int snd_echo_input_nominal_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int c, changed; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); - for (c = 0; c < num_analog_busses_in(chip); c++) { - if (chip->nominal_level[bx_analog_in(chip) + c] != - ucontrol->value.integer.value[c]) { - set_nominal_level(chip, bx_analog_in(chip) + c, - ucontrol->value.integer.value[c]); - changed = 1; - } - } - if (changed) - update_output_line_level(chip); /* "Output" is not a mistake - * here. - */ - spin_unlock_irq(&chip->lock); - return changed; -} - -static struct snd_kcontrol_new snd_echo_intput_nominal_level __devinitdata = { - .name = "Line Capture Switch (-10dBV)", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_echo_input_nominal_info, - .get = snd_echo_input_nominal_get, - .put = snd_echo_input_nominal_put, -}; - -#endif /* ECHOCARD_HAS_INPUT_NOMINAL_LEVEL */ - - - -#ifdef ECHOCARD_HAS_MONITOR - -/******************* Monitor mixer *******************/ -static int snd_echo_mixer_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = ECHOGAIN_MINOUT; - uinfo->value.integer.max = ECHOGAIN_MAXOUT; - uinfo->dimen.d[0] = num_busses_out(chip); - uinfo->dimen.d[1] = num_busses_in(chip); - return 0; -} - -static int snd_echo_mixer_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = - chip->monitor_gain[ucontrol->id.index / num_busses_in(chip)] - [ucontrol->id.index % num_busses_in(chip)]; - return 0; -} - -static int snd_echo_mixer_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int changed, gain; - short out, in; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - out = ucontrol->id.index / num_busses_in(chip); - in = ucontrol->id.index % num_busses_in(chip); - gain = ucontrol->value.integer.value[0]; - if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) - return -EINVAL; - if (chip->monitor_gain[out][in] != gain) { - spin_lock_irq(&chip->lock); - set_monitor_gain(chip, out, in, gain); - update_output_line_level(chip); - spin_unlock_irq(&chip->lock); - changed = 1; - } - return changed; -} - -static struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = { - .name = "Monitor Mixer Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_echo_mixer_info, - .get = snd_echo_mixer_get, - .put = snd_echo_mixer_put, -}; - -#endif /* ECHOCARD_HAS_MONITOR */ - - - -#ifdef ECHOCARD_HAS_VMIXER - -/******************* Vmixer *******************/ -static int snd_echo_vmixer_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = ECHOGAIN_MINOUT; - uinfo->value.integer.max = ECHOGAIN_MAXOUT; - uinfo->dimen.d[0] = num_busses_out(chip); - uinfo->dimen.d[1] = num_pipes_out(chip); - return 0; -} - -static int snd_echo_vmixer_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = - chip->vmixer_gain[ucontrol->id.index / num_pipes_out(chip)] - [ucontrol->id.index % num_pipes_out(chip)]; - return 0; -} - -static int snd_echo_vmixer_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int gain, changed; - short vch, out; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - out = ucontrol->id.index / num_pipes_out(chip); - vch = ucontrol->id.index % num_pipes_out(chip); - gain = ucontrol->value.integer.value[0]; - if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) - return -EINVAL; - if (chip->vmixer_gain[out][vch] != ucontrol->value.integer.value[0]) { - spin_lock_irq(&chip->lock); - set_vmixer_gain(chip, out, vch, ucontrol->value.integer.value[0]); - update_vmixer_level(chip); - spin_unlock_irq(&chip->lock); - changed = 1; - } - return changed; -} - -static struct snd_kcontrol_new snd_echo_vmixer __devinitdata = { - .name = "VMixer Volume", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .info = snd_echo_vmixer_info, - .get = snd_echo_vmixer_get, - .put = snd_echo_vmixer_put, -}; - -#endif /* ECHOCARD_HAS_VMIXER */ - - - -#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH - -/******************* Digital mode switch *******************/ -static int snd_echo_digital_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *names[4] = { - "S/PDIF Coaxial", "S/PDIF Optical", "ADAT Optical", - "S/PDIF Cdrom" - }; - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->value.enumerated.items = chip->num_digital_modes; - uinfo->count = 1; - if (uinfo->value.enumerated.item >= chip->num_digital_modes) - uinfo->value.enumerated.item = chip->num_digital_modes - 1; - strcpy(uinfo->value.enumerated.name, names[ - chip->digital_mode_list[uinfo->value.enumerated.item]]); - return 0; -} - -static int snd_echo_digital_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int i, mode; - - chip = snd_kcontrol_chip(kcontrol); - mode = chip->digital_mode; - for (i = chip->num_digital_modes - 1; i >= 0; i--) - if (mode == chip->digital_mode_list[i]) { - ucontrol->value.enumerated.item[0] = i; - break; - } - return 0; -} - -static int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int changed; - unsigned short emode, dmode; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - - emode = ucontrol->value.enumerated.item[0]; - if (emode >= chip->num_digital_modes) - return -EINVAL; - dmode = chip->digital_mode_list[emode]; - - if (dmode != chip->digital_mode) { - /* mode_mutex is required to make this operation atomic wrt - pcm_digital_*_open() and set_input_clock() functions. */ - down(&chip->mode_mutex); - - /* Do not allow the user to change the digital mode when a pcm - device is open because it also changes the number of channels - and the allowed sample rates */ - if (atomic_read(&chip->opencount)) { - changed = -EAGAIN; - } else { - changed = set_digital_mode(chip, dmode); - /* If we had to change the clock source, report it */ - if (changed > 0 && chip->clock_src_ctl) { - snd_ctl_notify(chip->card, - SNDRV_CTL_EVENT_MASK_VALUE, - &chip->clock_src_ctl->id); - DE_ACT(("SDM() =%d\n", changed)); - } - if (changed >= 0) - changed = 1; /* No errors */ - } - up(&chip->mode_mutex); - } - return changed; -} - -static struct snd_kcontrol_new snd_echo_digital_mode_switch __devinitdata = { - .name = "Digital mode Switch", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .info = snd_echo_digital_mode_info, - .get = snd_echo_digital_mode_get, - .put = snd_echo_digital_mode_put, -}; - -#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */ - - - -#ifdef ECHOCARD_HAS_DIGITAL_IO - -/******************* S/PDIF mode switch *******************/ -static int snd_echo_spdif_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *names[2] = {"Consumer", "Professional"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->value.enumerated.items = 2; - uinfo->count = 1; - if (uinfo->value.enumerated.item) - uinfo->value.enumerated.item = 1; - strcpy(uinfo->value.enumerated.name, - names[uinfo->value.enumerated.item]); - return 0; -} - -static int snd_echo_spdif_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.enumerated.item[0] = !!chip->professional_spdif; - return 0; -} - -static int snd_echo_spdif_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int mode; - - chip = snd_kcontrol_chip(kcontrol); - mode = !!ucontrol->value.enumerated.item[0]; - if (mode != chip->professional_spdif) { - spin_lock_irq(&chip->lock); - set_professional_spdif(chip, mode); - spin_unlock_irq(&chip->lock); - return 1; - } - return 0; -} - -static struct snd_kcontrol_new snd_echo_spdif_mode_switch __devinitdata = { - .name = "S/PDIF mode Switch", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .info = snd_echo_spdif_mode_info, - .get = snd_echo_spdif_mode_get, - .put = snd_echo_spdif_mode_put, -}; - -#endif /* ECHOCARD_HAS_DIGITAL_IO */ - - - -#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK - -/******************* Select input clock source *******************/ -static int snd_echo_clock_source_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *names[8] = { - "Internal", "Word", "Super", "S/PDIF", "ADAT", "ESync", - "ESync96", "MTC" - }; - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->value.enumerated.items = chip->num_clock_sources; - uinfo->count = 1; - if (uinfo->value.enumerated.item >= chip->num_clock_sources) - uinfo->value.enumerated.item = chip->num_clock_sources - 1; - strcpy(uinfo->value.enumerated.name, names[ - chip->clock_source_list[uinfo->value.enumerated.item]]); - return 0; -} - -static int snd_echo_clock_source_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int i, clock; - - chip = snd_kcontrol_chip(kcontrol); - clock = chip->input_clock; - - for (i = 0; i < chip->num_clock_sources; i++) - if (clock == chip->clock_source_list[i]) - ucontrol->value.enumerated.item[0] = i; - - return 0; -} - -static int snd_echo_clock_source_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int changed; - unsigned int eclock, dclock; - - changed = 0; - chip = snd_kcontrol_chip(kcontrol); - eclock = ucontrol->value.enumerated.item[0]; - if (eclock >= chip->input_clock_types) - return -EINVAL; - dclock = chip->clock_source_list[eclock]; - if (chip->input_clock != dclock) { - down(&chip->mode_mutex); - spin_lock_irq(&chip->lock); - if ((changed = set_input_clock(chip, dclock)) == 0) - changed = 1; /* no errors */ - spin_unlock_irq(&chip->lock); - up(&chip->mode_mutex); - } - - if (changed < 0) - DE_ACT(("seticlk val%d err 0x%x\n", dclock, changed)); - - return changed; -} - -static struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = { - .name = "Sample Clock Source", - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .info = snd_echo_clock_source_info, - .get = snd_echo_clock_source_get, - .put = snd_echo_clock_source_put, -}; - -#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */ - - - -#ifdef ECHOCARD_HAS_PHANTOM_POWER - -/******************* Phantom power switch *******************/ -static int snd_echo_phantom_power_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_echo_phantom_power_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = chip->phantom_power; - return 0; -} - -static int snd_echo_phantom_power_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip = snd_kcontrol_chip(kcontrol); - int power, changed = 0; - - power = !!ucontrol->value.integer.value[0]; - if (chip->phantom_power != power) { - spin_lock_irq(&chip->lock); - changed = set_phantom_power(chip, power); - spin_unlock_irq(&chip->lock); - if (changed == 0) - changed = 1; /* no errors */ - } - return changed; -} - -static struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = { - .name = "Phantom power Switch", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .info = snd_echo_phantom_power_info, - .get = snd_echo_phantom_power_get, - .put = snd_echo_phantom_power_put, -}; - -#endif /* ECHOCARD_HAS_PHANTOM_POWER */ - - - -#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE - -/******************* Digital input automute switch *******************/ -static int snd_echo_automute_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_echo_automute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip = snd_kcontrol_chip(kcontrol); - - ucontrol->value.integer.value[0] = chip->digital_in_automute; - return 0; -} - -static int snd_echo_automute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip = snd_kcontrol_chip(kcontrol); - int automute, changed = 0; - - automute = !!ucontrol->value.integer.value[0]; - if (chip->digital_in_automute != automute) { - spin_lock_irq(&chip->lock); - changed = set_input_auto_mute(chip, automute); - spin_unlock_irq(&chip->lock); - if (changed == 0) - changed = 1; /* no errors */ - } - return changed; -} - -static struct snd_kcontrol_new snd_echo_automute_switch __devinitdata = { - .name = "Digital Capture Switch (automute)", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .info = snd_echo_automute_info, - .get = snd_echo_automute_get, - .put = snd_echo_automute_put, -}; - -#endif /* ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE */ - - - -/******************* VU-meters switch *******************/ -static int snd_echo_vumeters_switch_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - spin_lock_irq(&chip->lock); - set_meters_on(chip, ucontrol->value.integer.value[0]); - spin_unlock_irq(&chip->lock); - return 1; -} - -static struct snd_kcontrol_new snd_echo_vumeters_switch __devinitdata = { - .name = "VU-meters Switch", - .iface = SNDRV_CTL_ELEM_IFACE_CARD, - .access = SNDRV_CTL_ELEM_ACCESS_WRITE, - .info = snd_echo_vumeters_switch_info, - .put = snd_echo_vumeters_switch_put, -}; - - - -/***** Read VU-meters (input, output, analog and digital together) *****/ -static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 96; - uinfo->value.integer.min = ECHOGAIN_MINOUT; - uinfo->value.integer.max = 0; -#ifdef ECHOCARD_HAS_VMIXER - uinfo->dimen.d[0] = 3; /* Out, In, Virt */ -#else - uinfo->dimen.d[0] = 2; /* Out, In */ -#endif - uinfo->dimen.d[1] = 16; /* 16 channels */ - uinfo->dimen.d[2] = 2; /* 0=level, 1=peak */ - return 0; -} - -static int snd_echo_vumeters_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - get_audio_meters(chip, ucontrol->value.integer.value); - return 0; -} - -static struct snd_kcontrol_new snd_echo_vumeters __devinitdata = { - .name = "VU-meters", - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_echo_vumeters_info, - .get = snd_echo_vumeters_get, -}; - - - -/*** Channels info - it exports informations about the number of channels ***/ -static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct echoaudio *chip; - - chip = snd_kcontrol_chip(kcontrol); - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 6; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1 << ECHO_CLOCK_NUMBER; - return 0; -} - -static int snd_echo_channels_info_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct echoaudio *chip; - int detected, clocks, bit, src; - - chip = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = num_busses_in(chip); - ucontrol->value.integer.value[1] = num_analog_busses_in(chip); - ucontrol->value.integer.value[2] = num_busses_out(chip); - ucontrol->value.integer.value[3] = num_analog_busses_out(chip); - ucontrol->value.integer.value[4] = num_pipes_out(chip); - - /* Compute the bitmask of the currently valid input clocks */ - detected = detect_input_clocks(chip); - clocks = 0; - src = chip->num_clock_sources - 1; - for (bit = ECHO_CLOCK_NUMBER - 1; bit >= 0; bit--) - if (detected & (1 << bit)) - for (; src >= 0; src--) - if (bit == chip->clock_source_list[src]) { - clocks |= 1 << src; - break; - } - ucontrol->value.integer.value[5] = clocks; - - return 0; -} - -static struct snd_kcontrol_new snd_echo_channels_info __devinitdata = { - .name = "Channels info", - .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, - .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = snd_echo_channels_info_info, - .get = snd_echo_channels_info_get, -}; - - - - -/****************************************************************************** - IRQ Handler -******************************************************************************/ - -static irqreturn_t snd_echo_interrupt(int irq, void *dev_id, - struct pt_regs *regs) -{ - struct echoaudio *chip = dev_id; - struct snd_pcm_substream *substream; - int period, ss, st; - - spin_lock(&chip->lock); - st = service_irq(chip); - if (st < 0) { - spin_unlock(&chip->lock); - return IRQ_NONE; - } - /* The hardware doesn't tell us which substream caused the irq, - thus we have to check all running substreams. */ - for (ss = 0; ss < DSP_MAXPIPES; ss++) { - if ((substream = chip->substream[ss])) { - period = pcm_pointer(substream) / - substream->runtime->period_size; - if (period != chip->last_period[ss]) { - chip->last_period[ss] = period; - spin_unlock(&chip->lock); - snd_pcm_period_elapsed(substream); - spin_lock(&chip->lock); - } - } - } - spin_unlock(&chip->lock); - -#ifdef ECHOCARD_HAS_MIDI - if (st > 0 && chip->midi_in) { - snd_rawmidi_receive(chip->midi_in, chip->midi_buffer, st); - DE_MID(("rawmidi_iread=%d\n", st)); - } -#endif - return IRQ_HANDLED; -} - - - - -/****************************************************************************** - Module construction / destruction -******************************************************************************/ - -static int snd_echo_free(struct echoaudio *chip) -{ - DE_INIT(("Stop DSP...\n")); - if (chip->comm_page) { - rest_in_peace(chip); - snd_dma_free_pages(&chip->commpage_dma_buf); - } - DE_INIT(("Stopped.\n")); - - if (chip->irq >= 0) - free_irq(chip->irq, (void *)chip); - - if (chip->dsp_registers) - iounmap(chip->dsp_registers); - - if (chip->iores) - release_and_free_resource(chip->iores); - - DE_INIT(("MMIO freed.\n")); - - pci_disable_device(chip->pci); - - /* release chip data */ - kfree(chip); - DE_INIT(("Chip freed.\n")); - return 0; -} - - - -static int snd_echo_dev_free(struct snd_device *device) -{ - struct echoaudio *chip = device->device_data; - - DE_INIT(("snd_echo_dev_free()...\n")); - return snd_echo_free(chip); -} - - - -/* <--snd_echo_probe() */ -static __devinit int snd_echo_create(struct snd_card *card, - struct pci_dev *pci, - struct echoaudio **rchip) -{ - struct echoaudio *chip; - int err; - size_t sz; - static struct snd_device_ops ops = { - .dev_free = snd_echo_dev_free, - }; - - *rchip = NULL; - - pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0xC0); - - if ((err = pci_enable_device(pci)) < 0) - return err; - pci_set_master(pci); - - /* allocate a chip-specific data */ - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) { - pci_disable_device(pci); - return -ENOMEM; - } - DE_INIT(("chip=%p\n", chip)); - - spin_lock_init(&chip->lock); - chip->card = card; - chip->pci = pci; - chip->irq = -1; - - /* PCI resource allocation */ - chip->dsp_registers_phys = pci_resource_start(pci, 0); - sz = pci_resource_len(pci, 0); - if (sz > PAGE_SIZE) - sz = PAGE_SIZE; /* We map only the required part */ - - if ((chip->iores = request_mem_region(chip->dsp_registers_phys, sz, - ECHOCARD_NAME)) == NULL) { - snd_echo_free(chip); - snd_printk(KERN_ERR "cannot get memory region\n"); - return -EBUSY; - } - chip->dsp_registers = (volatile u32 __iomem *) - ioremap_nocache(chip->dsp_registers_phys, sz); - - if (request_irq(pci->irq, snd_echo_interrupt, IRQF_DISABLED | IRQF_SHARED, - ECHOCARD_NAME, (void *)chip)) { - snd_echo_free(chip); - snd_printk(KERN_ERR "cannot grab irq\n"); - return -EBUSY; - } - chip->irq = pci->irq; - DE_INIT(("pci=%p irq=%d subdev=%04x Init hardware...\n", - chip->pci, chip->irq, chip->pci->subsystem_device)); - - /* Create the DSP comm page - this is the area of memory used for most - of the communication with the DSP, which accesses it via bus mastering */ - if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), - sizeof(struct comm_page), - &chip->commpage_dma_buf) < 0) { - snd_echo_free(chip); - snd_printk(KERN_ERR "cannot allocate the comm page\n"); - return -ENOMEM; - } - chip->comm_page_phys = chip->commpage_dma_buf.addr; - chip->comm_page = (struct comm_page *)chip->commpage_dma_buf.area; - - err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device); - if (err) { - DE_INIT(("init_hw err=%d\n", err)); - snd_echo_free(chip); - return err; - } - DE_INIT(("Card init OK\n")); - - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_echo_free(chip); - return err; - } - atomic_set(&chip->opencount, 0); - init_MUTEX(&chip->mode_mutex); - chip->can_set_rate = 1; - *rchip = chip; - /* Init done ! */ - return 0; -} - - - -/* constructor */ -static int __devinit snd_echo_probe(struct pci_dev *pci, - const struct pci_device_id *pci_id) -{ - static int dev; - struct snd_card *card; - struct echoaudio *chip; - char *dsp; - int i, err; - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) { - dev++; - return -ENOENT; - } - - DE_INIT(("Echoaudio driver starting...\n")); - i = 0; - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; - - if ((err = snd_echo_create(card, pci, &chip)) < 0) { - snd_card_free(card); - return err; - } - - strcpy(card->driver, "Echo_" ECHOCARD_NAME); - strcpy(card->shortname, chip->card_name); - - dsp = "56301"; - if (pci_id->device == 0x3410) - dsp = "56361"; - - sprintf(card->longname, "%s rev.%d (DSP%s) at 0x%lx irq %i", - card->shortname, pci_id->subdevice & 0x000f, dsp, - chip->dsp_registers_phys, chip->irq); - - if ((err = snd_echo_new_pcm(chip)) < 0) { - snd_printk(KERN_ERR "new pcm error %d\n", err); - snd_card_free(card); - return err; - } - -#ifdef ECHOCARD_HAS_MIDI - if (chip->has_midi) { /* Some Mia's do not have midi */ - if ((err = snd_echo_midi_create(card, chip)) < 0) { - snd_printk(KERN_ERR "new midi error %d\n", err); - snd_card_free(card); - return err; - } - } -#endif - -#ifdef ECHOCARD_HAS_VMIXER - snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip); - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_output_gain, chip))) < 0) - goto ctl_error; - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0) - goto ctl_error; -#else - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_pcm_output_gain, chip))) < 0) - goto ctl_error; -#endif - -#ifdef ECHOCARD_HAS_INPUT_GAIN - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip))) < 0) - goto ctl_error; -#endif - -#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL - if (!chip->hasnt_input_nominal_level) - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_intput_nominal_level, chip))) < 0) - goto ctl_error; -#endif - -#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_output_nominal_level, chip))) < 0) - goto ctl_error; -#endif - - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters_switch, chip))) < 0) - goto ctl_error; - - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters, chip))) < 0) - goto ctl_error; - -#ifdef ECHOCARD_HAS_MONITOR - snd_echo_monitor_mixer.count = num_busses_in(chip) * num_busses_out(chip); - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_monitor_mixer, chip))) < 0) - goto ctl_error; -#endif - -#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_automute_switch, chip))) < 0) - goto ctl_error; -#endif - - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_channels_info, chip))) < 0) - goto ctl_error; - -#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH - /* Creates a list of available digital modes */ - chip->num_digital_modes = 0; - for (i = 0; i < 6; i++) - if (chip->digital_modes & (1 << i)) - chip->digital_mode_list[chip->num_digital_modes++] = i; - - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_digital_mode_switch, chip))) < 0) - goto ctl_error; -#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */ - -#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK - /* Creates a list of available clock sources */ - chip->num_clock_sources = 0; - for (i = 0; i < 10; i++) - if (chip->input_clock_types & (1 << i)) - chip->clock_source_list[chip->num_clock_sources++] = i; - - if (chip->num_clock_sources > 1) { - chip->clock_src_ctl = snd_ctl_new1(&snd_echo_clock_source_switch, chip); - if ((err = snd_ctl_add(chip->card, chip->clock_src_ctl)) < 0) - goto ctl_error; - } -#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */ - -#ifdef ECHOCARD_HAS_DIGITAL_IO - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_spdif_mode_switch, chip))) < 0) - goto ctl_error; -#endif - -#ifdef ECHOCARD_HAS_PHANTOM_POWER - if (chip->has_phantom_power) - if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_phantom_power_switch, chip))) < 0) - goto ctl_error; -#endif - - if ((err = snd_card_register(card)) < 0) { - snd_card_free(card); - goto ctl_error; - } - snd_printk(KERN_INFO "Card registered: %s\n", card->longname); - - pci_set_drvdata(pci, chip); - dev++; - return 0; - -ctl_error: - snd_printk(KERN_ERR "new control error %d\n", err); - snd_card_free(card); - return err; -} - - - -static void __devexit snd_echo_remove(struct pci_dev *pci) -{ - struct echoaudio *chip; - - chip = pci_get_drvdata(pci); - if (chip) - snd_card_free(chip->card); - pci_set_drvdata(pci, NULL); -} - - - -/****************************************************************************** - Everything starts and ends here -******************************************************************************/ - -/* pci_driver definition */ -static struct pci_driver driver = { - .name = "Echoaudio " ECHOCARD_NAME, - .id_table = snd_echo_ids, - .probe = snd_echo_probe, - .remove = __devexit_p(snd_echo_remove), -}; - - - -/* initialization of the module */ -static int __init alsa_card_echo_init(void) -{ - return pci_register_driver(&driver); -} - - - -/* clean up the module */ -static void __exit alsa_card_echo_exit(void) -{ - pci_unregister_driver(&driver); -} - - -module_init(alsa_card_echo_init) -module_exit(alsa_card_echo_exit) diff --git a/trunk/sound/pci/echoaudio/echoaudio.h b/trunk/sound/pci/echoaudio/echoaudio.h deleted file mode 100644 index 7e88c968e22f..000000000000 --- a/trunk/sound/pci/echoaudio/echoaudio.h +++ /dev/null @@ -1,590 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - **************************************************************************** - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - - **************************************************************************** - - - Here's a block diagram of how most of the cards work: - - +-----------+ - record | |<-------------------- Inputs - <-------| | | - PCI | Transport | | - bus | engine | \|/ - ------->| | +-------+ - play | |--->|monitor|-------> Outputs - +-----------+ | mixer | - +-------+ - - The lines going to and from the PCI bus represent "pipes". A pipe performs - audio transport - moving audio data to and from buffers on the host via - bus mastering. - - The inputs and outputs on the right represent input and output "busses." - A bus is a physical, real connection to the outside world. An example - of a bus would be the 1/4" analog connectors on the back of Layla or - an RCA S/PDIF connector. - - For most cards, there is a one-to-one correspondence between outputs - and busses; that is, each individual pipe is hard-wired to a single bus. - - Cards that work this way are Darla20, Gina20, Layla20, Darla24, Gina24, - Layla24, Mona, and Indigo. - - - Mia has a feature called "virtual outputs." - - - +-----------+ - record | |<----------------------------- Inputs - <-------| | | - PCI | Transport | | - bus | engine | \|/ - ------->| | +------+ +-------+ - play | |-->|vmixer|-->|monitor|-------> Outputs - +-----------+ +------+ | mixer | - +-------+ - - - Obviously, the difference here is the box labeled "vmixer." Vmixer is - short for "virtual output mixer." For Mia, pipes are *not* hard-wired - to a single bus; the vmixer lets you mix any pipe to any bus in any - combination. - - Note, however, that the left-hand side of the diagram is unchanged. - Transport works exactly the same way - the difference is in the mixer stage. - - - Pipes and busses are numbered starting at zero. - - - - Pipe index - ========== - - A number of calls in CEchoGals refer to a "pipe index". A pipe index is - a unique number for a pipe that unambiguously refers to a playback or record - pipe. Pipe indices are numbered starting with analog outputs, followed by - digital outputs, then analog inputs, then digital inputs. - - Take Gina24 as an example: - - Pipe index - - 0-7 Analog outputs (0 .. FirstDigitalBusOut-1) - 8-15 Digital outputs (FirstDigitalBusOut .. NumBussesOut-1) - 16-17 Analog inputs - 18-25 Digital inputs - - - You get the pipe index by calling CEchoGals::OpenAudio; the other transport - functions take the pipe index as a parameter. If you need a pipe index for - some other reason, use the handy Makepipe_index method. - - - Some calls take a CChannelMask parameter; CChannelMask is a handy way to - group pipe indices. - - - - Digital mode switch - =================== - - Some cards (right now, Gina24, Layla24, and Mona) have a Digital Mode Switch - or DMS. Cards with a DMS can be set to one of three mutually exclusive - digital modes: S/PDIF RCA, S/PDIF optical, or ADAT optical. - - This may create some confusion since ADAT optical is 8 channels wide and - S/PDIF is only two channels wide. Gina24, Layla24, and Mona handle this - by acting as if they always have 8 digital outs and ins. If you are in - either S/PDIF mode, the last 6 channels don't do anything - data sent - out these channels is thrown away and you will always record zeros. - - Note that with Gina24, Layla24, and Mona, sample rates above 50 kHz are - only available if you have the card configured for S/PDIF optical or S/PDIF - RCA. - - - - Double speed mode - ================= - - Some of the cards support 88.2 kHz and 96 kHz sampling (Darla24, Gina24, - Layla24, Mona, Mia, and Indigo). For these cards, the driver sometimes has - to worry about "double speed mode"; double speed mode applies whenever the - sampling rate is above 50 kHz. - - For instance, Mona and Layla24 support word clock sync. However, they - actually support two different word clock modes - single speed (below - 50 kHz) and double speed (above 50 kHz). The hardware detects if a single - or double speed word clock signal is present; the generic code uses that - information to determine which mode to use. - - The generic code takes care of all this for you. -*/ - - -#ifndef _ECHOAUDIO_H_ -#define _ECHOAUDIO_H_ - - -#define TRUE 1 -#define FALSE 0 - -#include "echoaudio_dsp.h" - - - -/*********************************************************************** - - PCI configuration space - -***********************************************************************/ - -/* - * PCI vendor ID and device IDs for the hardware - */ -#define VENDOR_ID 0x1057 -#define DEVICE_ID_56301 0x1801 -#define DEVICE_ID_56361 0x3410 -#define SUBVENDOR_ID 0xECC0 - - -/* - * Valid Echo PCI subsystem card IDs - */ -#define DARLA20 0x0010 -#define GINA20 0x0020 -#define LAYLA20 0x0030 -#define DARLA24 0x0040 -#define GINA24 0x0050 -#define LAYLA24 0x0060 -#define MONA 0x0070 -#define MIA 0x0080 -#define INDIGO 0x0090 -#define INDIGO_IO 0x00a0 -#define INDIGO_DJ 0x00b0 -#define ECHO3G 0x0100 - - -/************************************************************************ - - Array sizes and so forth - -***********************************************************************/ - -/* - * Sizes - */ -#define ECHO_MAXAUDIOINPUTS 32 /* Max audio input channels */ -#define ECHO_MAXAUDIOOUTPUTS 32 /* Max audio output channels */ -#define ECHO_MAXAUDIOPIPES 32 /* Max number of input and output - * pipes */ -#define E3G_MAX_OUTPUTS 16 -#define ECHO_MAXMIDIJACKS 1 /* Max MIDI ports */ -#define ECHO_MIDI_QUEUE_SZ 512 /* Max MIDI input queue entries */ -#define ECHO_MTC_QUEUE_SZ 32 /* Max MIDI time code input queue - * entries */ - -/* - * MIDI activity indicator timeout - */ -#define MIDI_ACTIVITY_TIMEOUT_USEC 200000 - - -/**************************************************************************** - - Clocks - -*****************************************************************************/ - -/* - * Clock numbers - */ -#define ECHO_CLOCK_INTERNAL 0 -#define ECHO_CLOCK_WORD 1 -#define ECHO_CLOCK_SUPER 2 -#define ECHO_CLOCK_SPDIF 3 -#define ECHO_CLOCK_ADAT 4 -#define ECHO_CLOCK_ESYNC 5 -#define ECHO_CLOCK_ESYNC96 6 -#define ECHO_CLOCK_MTC 7 -#define ECHO_CLOCK_NUMBER 8 -#define ECHO_CLOCKS 0xffff - -/* - * Clock bit numbers - used to report capabilities and whatever clocks - * are being detected dynamically. - */ -#define ECHO_CLOCK_BIT_INTERNAL (1 << ECHO_CLOCK_INTERNAL) -#define ECHO_CLOCK_BIT_WORD (1 << ECHO_CLOCK_WORD) -#define ECHO_CLOCK_BIT_SUPER (1 << ECHO_CLOCK_SUPER) -#define ECHO_CLOCK_BIT_SPDIF (1 << ECHO_CLOCK_SPDIF) -#define ECHO_CLOCK_BIT_ADAT (1 << ECHO_CLOCK_ADAT) -#define ECHO_CLOCK_BIT_ESYNC (1 << ECHO_CLOCK_ESYNC) -#define ECHO_CLOCK_BIT_ESYNC96 (1 << ECHO_CLOCK_ESYNC96) -#define ECHO_CLOCK_BIT_MTC (1<comm_page->handshake = 0; -} - -static inline u32 get_dsp_register(struct echoaudio *chip, u32 index) -{ - return readl(&chip->dsp_registers[index]); -} - -static inline void set_dsp_register(struct echoaudio *chip, u32 index, - u32 value) -{ - writel(value, &chip->dsp_registers[index]); -} - - -/* Pipe and bus indexes. PX_* and BX_* are defined as chip->px_* and chip->bx_* -for 3G cards because they depend on the external box. They are integer -constants for all other cards. -Never use those defines directly, use the following functions instead. */ - -static inline int px_digital_out(const struct echoaudio *chip) -{ - return PX_DIGITAL_OUT; -} - -static inline int px_analog_in(const struct echoaudio *chip) -{ - return PX_ANALOG_IN; -} - -static inline int px_digital_in(const struct echoaudio *chip) -{ - return PX_DIGITAL_IN; -} - -static inline int px_num(const struct echoaudio *chip) -{ - return PX_NUM; -} - -static inline int bx_digital_out(const struct echoaudio *chip) -{ - return BX_DIGITAL_OUT; -} - -static inline int bx_analog_in(const struct echoaudio *chip) -{ - return BX_ANALOG_IN; -} - -static inline int bx_digital_in(const struct echoaudio *chip) -{ - return BX_DIGITAL_IN; -} - -static inline int bx_num(const struct echoaudio *chip) -{ - return BX_NUM; -} - -static inline int num_pipes_out(const struct echoaudio *chip) -{ - return px_analog_in(chip); -} - -static inline int num_pipes_in(const struct echoaudio *chip) -{ - return px_num(chip) - px_analog_in(chip); -} - -static inline int num_busses_out(const struct echoaudio *chip) -{ - return bx_analog_in(chip); -} - -static inline int num_busses_in(const struct echoaudio *chip) -{ - return bx_num(chip) - bx_analog_in(chip); -} - -static inline int num_analog_busses_out(const struct echoaudio *chip) -{ - return bx_digital_out(chip); -} - -static inline int num_analog_busses_in(const struct echoaudio *chip) -{ - return bx_digital_in(chip) - bx_analog_in(chip); -} - -static inline int num_digital_busses_out(const struct echoaudio *chip) -{ - return num_busses_out(chip) - num_analog_busses_out(chip); -} - -static inline int num_digital_busses_in(const struct echoaudio *chip) -{ - return num_busses_in(chip) - num_analog_busses_in(chip); -} - -/* The monitor array is a one-dimensional array; compute the offset - * into the array */ -static inline int monitor_index(const struct echoaudio *chip, int out, int in) -{ - return out * num_busses_in(chip) + in; -} - - -#ifndef pci_device -#define pci_device(chip) (&chip->pci->dev) -#endif - - -#endif /* _ECHOAUDIO_H_ */ diff --git a/trunk/sound/pci/echoaudio/echoaudio_3g.c b/trunk/sound/pci/echoaudio/echoaudio_3g.c deleted file mode 100644 index 9f439ea459f4..000000000000 --- a/trunk/sound/pci/echoaudio/echoaudio_3g.c +++ /dev/null @@ -1,431 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - - -/* These functions are common for all "3G" cards */ - - -static int check_asic_status(struct echoaudio *chip) -{ - u32 box_status; - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->ext_box_status = - __constant_cpu_to_le32(E3G_ASIC_NOT_LOADED); - chip->asic_loaded = FALSE; - clear_handshake(chip); - send_vector(chip, DSP_VC_TEST_ASIC); - - if (wait_handshake(chip)) { - chip->dsp_code = NULL; - return -EIO; - } - - box_status = le32_to_cpu(chip->comm_page->ext_box_status); - DE_INIT(("box_status=%x\n", box_status)); - if (box_status == E3G_ASIC_NOT_LOADED) - return -ENODEV; - - chip->asic_loaded = TRUE; - return box_status & E3G_BOX_TYPE_MASK; -} - - - -static inline u32 get_frq_reg(struct echoaudio *chip) -{ - return le32_to_cpu(chip->comm_page->e3g_frq_register); -} - - - -/* Most configuration of 3G cards is accomplished by writing the control -register. write_control_reg sends the new control register value to the DSP. */ -static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq, - char force) -{ - if (wait_handshake(chip)) - return -EIO; - - DE_ACT(("WriteControlReg: Setting 0x%x, 0x%x\n", ctl, frq)); - - ctl = cpu_to_le32(ctl); - frq = cpu_to_le32(frq); - - if (ctl != chip->comm_page->control_register || - frq != chip->comm_page->e3g_frq_register || force) { - chip->comm_page->e3g_frq_register = frq; - chip->comm_page->control_register = ctl; - clear_handshake(chip); - return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); - } - - DE_ACT(("WriteControlReg: not written, no change\n")); - return 0; -} - - - -/* Set the digital mode - currently for Gina24, Layla24, Mona, 3G */ -static int set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u8 previous_mode; - int err, i, o; - - /* All audio channels must be closed before changing the digital mode */ - snd_assert(!chip->pipe_alloc_mask, return -EAGAIN); - - snd_assert(chip->digital_modes & (1 << mode), return -EINVAL); - - previous_mode = chip->digital_mode; - err = dsp_set_digital_mode(chip, mode); - - /* If we successfully changed the digital mode from or to ADAT, - * then make sure all output, input and monitor levels are - * updated by the DSP comm object. */ - if (err >= 0 && previous_mode != mode && - (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { - spin_lock_irq(&chip->lock); - for (o = 0; o < num_busses_out(chip); o++) - for (i = 0; i < num_busses_in(chip); i++) - set_monitor_gain(chip, o, i, - chip->monitor_gain[o][i]); - -#ifdef ECHOCARD_HAS_INPUT_GAIN - for (i = 0; i < num_busses_in(chip); i++) - set_input_gain(chip, i, chip->input_gain[i]); - update_input_line_level(chip); -#endif - - for (o = 0; o < num_busses_out(chip); o++) - set_output_gain(chip, o, chip->output_gain[o]); - update_output_line_level(chip); - spin_unlock_irq(&chip->lock); - } - - return err; -} - - - -static u32 set_spdif_bits(struct echoaudio *chip, u32 control_reg, u32 rate) -{ - control_reg &= E3G_SPDIF_FORMAT_CLEAR_MASK; - - switch (rate) { - case 32000 : - control_reg |= E3G_SPDIF_SAMPLE_RATE0 | E3G_SPDIF_SAMPLE_RATE1; - break; - case 44100 : - if (chip->professional_spdif) - control_reg |= E3G_SPDIF_SAMPLE_RATE0; - break; - case 48000 : - control_reg |= E3G_SPDIF_SAMPLE_RATE1; - break; - } - - if (chip->professional_spdif) - control_reg |= E3G_SPDIF_PRO_MODE; - - if (chip->non_audio_spdif) - control_reg |= E3G_SPDIF_NOT_AUDIO; - - control_reg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL | - E3G_SPDIF_COPY_PERMIT; - - return control_reg; -} - - - -/* Set the S/PDIF output format */ -static int set_professional_spdif(struct echoaudio *chip, char prof) -{ - u32 control_reg; - - control_reg = le32_to_cpu(chip->comm_page->control_register); - chip->professional_spdif = prof; - control_reg = set_spdif_bits(chip, control_reg, chip->sample_rate); - return write_control_reg(chip, control_reg, get_frq_reg(chip), 0); -} - - - -/* detect_input_clocks() returns a bitmask consisting of all the input clocks -currently connected to the hardware; this changes as the user connects and -disconnects clock inputs. You should use this information to determine which -clocks the user is allowed to select. */ -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - * detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD) - clock_bits |= ECHO_CLOCK_BIT_WORD; - - switch(chip->digital_mode) { - case DIGITAL_MODE_SPDIF_RCA: - case DIGITAL_MODE_SPDIF_OPTICAL: - if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - break; - case DIGITAL_MODE_ADAT: - if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_ADAT) - clock_bits |= ECHO_CLOCK_BIT_ADAT; - break; - } - - return clock_bits; -} - - - -static int load_asic(struct echoaudio *chip) -{ - int box_type, err; - - if (chip->asic_loaded) - return 0; - - /* Give the DSP a few milliseconds to settle down */ - mdelay(2); - - err = load_asic_generic(chip, DSP_FNC_LOAD_3G_ASIC, - &card_fw[FW_3G_ASIC]); - if (err < 0) - return err; - - chip->asic_code = &card_fw[FW_3G_ASIC]; - - /* Now give the new ASIC a little time to set up */ - mdelay(2); - /* See if it worked */ - box_type = check_asic_status(chip); - - /* Set up the control register if the load succeeded - - * 48 kHz, internal clock, S/PDIF RCA mode */ - if (box_type >= 0) { - err = write_control_reg(chip, E3G_48KHZ, - E3G_FREQ_REG_DEFAULT, TRUE); - if (err < 0) - return err; - } - - return box_type; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg, clock, base_rate, frq_reg; - - /* Only set the clock for internal mode. */ - if (chip->input_clock != ECHO_CLOCK_INTERNAL) { - DE_ACT(("set_sample_rate: Cannot set sample rate - " - "clock not set to CLK_CLOCKININTERNAL\n")); - /* Save the rate anyhow */ - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->sample_rate = rate; - set_input_clock(chip, chip->input_clock); - return 0; - } - - snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT, - return -EINVAL); - - clock = 0; - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= E3G_CLOCK_CLEAR_MASK; - - switch (rate) { - case 96000: - clock = E3G_96KHZ; - break; - case 88200: - clock = E3G_88KHZ; - break; - case 48000: - clock = E3G_48KHZ; - break; - case 44100: - clock = E3G_44KHZ; - break; - case 32000: - clock = E3G_32KHZ; - break; - default: - clock = E3G_CONTINUOUS_CLOCK; - if (rate > 50000) - clock |= E3G_DOUBLE_SPEED_MODE; - break; - } - - control_reg |= clock; - control_reg = set_spdif_bits(chip, control_reg, rate); - - base_rate = rate; - if (base_rate > 50000) - base_rate /= 2; - if (base_rate < 32000) - base_rate = 32000; - - frq_reg = E3G_MAGIC_NUMBER / base_rate - 2; - if (frq_reg > E3G_FREQ_REG_MAX) - frq_reg = E3G_FREQ_REG_MAX; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->sample_rate = rate; - DE_ACT(("SetSampleRate: %d clock %x\n", rate, control_reg)); - - /* Tell the DSP about it - DSP reads both control reg & freq reg */ - return write_control_reg(chip, control_reg, frq_reg, 0); -} - - - -/* Set the sample clock source to internal, S/PDIF, ADAT */ -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - u32 control_reg, clocks_from_dsp; - - DE_ACT(("set_input_clock:\n")); - - /* Mask off the clock select bits */ - control_reg = le32_to_cpu(chip->comm_page->control_register) & - E3G_CLOCK_CLEAR_MASK; - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - switch (clock) { - case ECHO_CLOCK_INTERNAL: - DE_ACT(("Set Echo3G clock to INTERNAL\n")); - chip->input_clock = ECHO_CLOCK_INTERNAL; - return set_sample_rate(chip, chip->sample_rate); - case ECHO_CLOCK_SPDIF: - if (chip->digital_mode == DIGITAL_MODE_ADAT) - return -EAGAIN; - DE_ACT(("Set Echo3G clock to SPDIF\n")); - control_reg |= E3G_SPDIF_CLOCK; - if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF96) - control_reg |= E3G_DOUBLE_SPEED_MODE; - else - control_reg &= ~E3G_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_ADAT: - if (chip->digital_mode != DIGITAL_MODE_ADAT) - return -EAGAIN; - DE_ACT(("Set Echo3G clock to ADAT\n")); - control_reg |= E3G_ADAT_CLOCK; - control_reg &= ~E3G_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_WORD: - DE_ACT(("Set Echo3G clock to WORD\n")); - control_reg |= E3G_WORD_CLOCK; - if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD96) - control_reg |= E3G_DOUBLE_SPEED_MODE; - else - control_reg &= ~E3G_DOUBLE_SPEED_MODE; - break; - default: - DE_ACT(("Input clock 0x%x not supported for Echo3G\n", clock)); - return -EINVAL; - } - - chip->input_clock = clock; - return write_control_reg(chip, control_reg, get_frq_reg(chip), 1); -} - - - -static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u32 control_reg; - int err, incompatible_clock; - - /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - case DIGITAL_MODE_SPDIF_RCA: - if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; - break; - case DIGITAL_MODE_ADAT: - if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; - break; - default: - DE_ACT(("Digital mode not supported: %d\n", mode)); - return -EINVAL; - } - - spin_lock_irq(&chip->lock); - - if (incompatible_clock) { - chip->sample_rate = 48000; - set_input_clock(chip, ECHO_CLOCK_INTERNAL); - } - - /* Clear the current digital mode */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= E3G_DIGITAL_MODE_CLEAR_MASK; - - /* Tweak the control reg */ - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - control_reg |= E3G_SPDIF_OPTICAL_MODE; - break; - case DIGITAL_MODE_SPDIF_RCA: - /* E3G_SPDIF_OPTICAL_MODE bit cleared */ - break; - case DIGITAL_MODE_ADAT: - control_reg |= E3G_ADAT_MODE; - control_reg &= ~E3G_DOUBLE_SPEED_MODE; /* @@ useless */ - break; - } - - err = write_control_reg(chip, control_reg, get_frq_reg(chip), 1); - spin_unlock_irq(&chip->lock); - if (err < 0) - return err; - chip->digital_mode = mode; - - DE_ACT(("set_digital_mode(%d)\n", chip->digital_mode)); - return incompatible_clock; -} diff --git a/trunk/sound/pci/echoaudio/echoaudio_dsp.c b/trunk/sound/pci/echoaudio/echoaudio_dsp.c deleted file mode 100644 index 42afa837d9b4..000000000000 --- a/trunk/sound/pci/echoaudio/echoaudio_dsp.c +++ /dev/null @@ -1,1125 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - -#if PAGE_SIZE < 4096 -#error PAGE_SIZE is < 4k -#endif - -static int restore_dsp_rettings(struct echoaudio *chip); - - -/* Some vector commands involve the DSP reading or writing data to and from the -comm page; if you send one of these commands to the DSP, it will complete the -command and then write a non-zero value to the Handshake field in the -comm page. This function waits for the handshake to show up. */ -static int wait_handshake(struct echoaudio *chip) -{ - int i; - - /* Wait up to 10ms for the handshake from the DSP */ - for (i = 0; i < HANDSHAKE_TIMEOUT; i++) { - /* Look for the handshake value */ - if (chip->comm_page->handshake) { - /*if (i) DE_ACT(("Handshake time: %d\n", i));*/ - return 0; - } - udelay(1); - } - - snd_printk(KERN_ERR "wait_handshake(): Timeout waiting for DSP\n"); - return -EBUSY; -} - - - -/* Much of the interaction between the DSP and the driver is done via vector -commands; send_vector writes a vector command to the DSP. Typically, this -causes the DSP to read or write fields in the comm page. -PCI posting is not required thanks to the handshake logic. */ -static int send_vector(struct echoaudio *chip, u32 command) -{ - int i; - - wmb(); /* Flush all pending writes before sending the command */ - - /* Wait up to 100ms for the "vector busy" bit to be off */ - for (i = 0; i < VECTOR_BUSY_TIMEOUT; i++) { - if (!(get_dsp_register(chip, CHI32_VECTOR_REG) & - CHI32_VECTOR_BUSY)) { - set_dsp_register(chip, CHI32_VECTOR_REG, command); - /*if (i) DE_ACT(("send_vector time: %d\n", i));*/ - return 0; - } - udelay(1); - } - - DE_ACT((KERN_ERR "timeout on send_vector\n")); - return -EBUSY; -} - - - -/* write_dsp writes a 32-bit value to the DSP; this is used almost -exclusively for loading the DSP. */ -static int write_dsp(struct echoaudio *chip, u32 data) -{ - u32 status, i; - - for (i = 0; i < 10000000; i++) { /* timeout = 10s */ - status = get_dsp_register(chip, CHI32_STATUS_REG); - if ((status & CHI32_STATUS_HOST_WRITE_EMPTY) != 0) { - set_dsp_register(chip, CHI32_DATA_REG, data); - wmb(); /* write it immediately */ - return 0; - } - udelay(1); - cond_resched(); - } - - chip->bad_board = TRUE; /* Set TRUE until DSP re-loaded */ - DE_ACT((KERN_ERR "write_dsp: Set bad_board to TRUE\n")); - return -EIO; -} - - - -/* read_dsp reads a 32-bit value from the DSP; this is used almost -exclusively for loading the DSP and checking the status of the ASIC. */ -static int read_dsp(struct echoaudio *chip, u32 *data) -{ - u32 status, i; - - for (i = 0; i < READ_DSP_TIMEOUT; i++) { - status = get_dsp_register(chip, CHI32_STATUS_REG); - if ((status & CHI32_STATUS_HOST_READ_FULL) != 0) { - *data = get_dsp_register(chip, CHI32_DATA_REG); - return 0; - } - udelay(1); - cond_resched(); - } - - chip->bad_board = TRUE; /* Set TRUE until DSP re-loaded */ - DE_INIT((KERN_ERR "read_dsp: Set bad_board to TRUE\n")); - return -EIO; -} - - - -/**************************************************************************** - Firmware loading functions - ****************************************************************************/ - -/* This function is used to read back the serial number from the DSP; -this is triggered by the SET_COMMPAGE_ADDR command. -Only some early Echogals products have serial numbers in the ROM; -the serial number is not used, but you still need to do this as -part of the DSP load process. */ -static int read_sn(struct echoaudio *chip) -{ - int i; - u32 sn[6]; - - for (i = 0; i < 5; i++) { - if (read_dsp(chip, &sn[i])) { - snd_printk(KERN_ERR "Failed to read serial number\n"); - return -EIO; - } - } - DE_INIT(("Read serial number %08x %08x %08x %08x %08x\n", - sn[0], sn[1], sn[2], sn[3], sn[4])); - return 0; -} - - - -#ifndef ECHOCARD_HAS_ASIC -/* This card has no ASIC, just return ok */ -static inline int check_asic_status(struct echoaudio *chip) -{ - chip->asic_loaded = TRUE; - return 0; -} - -#endif /* !ECHOCARD_HAS_ASIC */ - - - -#ifdef ECHOCARD_HAS_ASIC - -/* Load ASIC code - done after the DSP is loaded */ -static int load_asic_generic(struct echoaudio *chip, u32 cmd, - const struct firmware *asic) -{ - const struct firmware *fw; - int err; - u32 i, size; - u8 *code; - - if ((err = get_firmware(&fw, asic, chip)) < 0) { - snd_printk(KERN_WARNING "Firmware not found !\n"); - return err; - } - - code = (u8 *)fw->data; - size = fw->size; - - /* Send the "Here comes the ASIC" command */ - if (write_dsp(chip, cmd) < 0) - goto la_error; - - /* Write length of ASIC file in bytes */ - if (write_dsp(chip, size) < 0) - goto la_error; - - for (i = 0; i < size; i++) { - if (write_dsp(chip, code[i]) < 0) - goto la_error; - } - - DE_INIT(("ASIC loaded\n")); - free_firmware(fw); - return 0; - -la_error: - DE_INIT(("failed on write_dsp\n")); - free_firmware(fw); - return -EIO; -} - -#endif /* ECHOCARD_HAS_ASIC */ - - - -#ifdef DSP_56361 - -/* Install the resident loader for 56361 DSPs; The resident loader is on -the EPROM on the board for 56301 DSP. The resident loader is a tiny little -program that is used to load the real DSP code. */ -static int install_resident_loader(struct echoaudio *chip) -{ - u32 address; - int index, words, i; - u16 *code; - u32 status; - const struct firmware *fw; - - /* 56361 cards only! This check is required by the old 56301-based - Mona and Gina24 */ - if (chip->device_id != DEVICE_ID_56361) - return 0; - - /* Look to see if the resident loader is present. If the resident - loader is already installed, host flag 5 will be on. */ - status = get_dsp_register(chip, CHI32_STATUS_REG); - if (status & CHI32_STATUS_REG_HF5) { - DE_INIT(("Resident loader already installed; status is 0x%x\n", - status)); - return 0; - } - - if ((i = get_firmware(&fw, &card_fw[FW_361_LOADER], chip)) < 0) { - snd_printk(KERN_WARNING "Firmware not found !\n"); - return i; - } - - /* The DSP code is an array of 16 bit words. The array is divided up - into sections. The first word of each section is the size in words, - followed by the section type. - Since DSP addresses and data are 24 bits wide, they each take up two - 16 bit words in the array. - This is a lot like the other loader loop, but it's not a loop, you - don't write the memory type, and you don't write a zero at the end. */ - - /* Set DSP format bits for 24 bit mode */ - set_dsp_register(chip, CHI32_CONTROL_REG, - get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900); - - code = (u16 *)fw->data; - - /* Skip the header section; the first word in the array is the size - of the first section, so the first real section of code is pointed - to by Code[0]. */ - index = code[0]; - - /* Skip the section size, LRS block type, and DSP memory type */ - index += 3; - - /* Get the number of DSP words to write */ - words = code[index++]; - - /* Get the DSP address for this block; 24 bits, so build from two words */ - address = ((u32)code[index] << 16) + code[index + 1]; - index += 2; - - /* Write the count to the DSP */ - if (write_dsp(chip, words)) { - DE_INIT(("install_resident_loader: Failed to write word count!\n")); - goto irl_error; - } - /* Write the DSP address */ - if (write_dsp(chip, address)) { - DE_INIT(("install_resident_loader: Failed to write DSP address!\n")); - goto irl_error; - } - /* Write out this block of code to the DSP */ - for (i = 0; i < words; i++) { - u32 data; - - data = ((u32)code[index] << 16) + code[index + 1]; - if (write_dsp(chip, data)) { - DE_INIT(("install_resident_loader: Failed to write DSP code\n")); - goto irl_error; - } - index += 2; - } - - /* Wait for flag 5 to come up */ - for (i = 0; i < 200; i++) { /* Timeout is 50us * 200 = 10ms */ - udelay(50); - status = get_dsp_register(chip, CHI32_STATUS_REG); - if (status & CHI32_STATUS_REG_HF5) - break; - } - - if (i == 200) { - DE_INIT(("Resident loader failed to set HF5\n")); - goto irl_error; - } - - DE_INIT(("Resident loader successfully installed\n")); - free_firmware(fw); - return 0; - -irl_error: - free_firmware(fw); - return -EIO; -} - -#endif /* DSP_56361 */ - - -static int load_dsp(struct echoaudio *chip, u16 *code) -{ - u32 address, data; - int index, words, i; - - if (chip->dsp_code == code) { - DE_INIT(("DSP is already loaded!\n")); - return 0; - } - chip->bad_board = TRUE; /* Set TRUE until DSP loaded */ - chip->dsp_code = NULL; /* Current DSP code not loaded */ - chip->asic_loaded = FALSE; /* Loading the DSP code will reset the ASIC */ - - DE_INIT(("load_dsp: Set bad_board to TRUE\n")); - - /* If this board requires a resident loader, install it. */ -#ifdef DSP_56361 - if ((i = install_resident_loader(chip)) < 0) - return i; -#endif - - /* Send software reset command */ - if (send_vector(chip, DSP_VC_RESET) < 0) { - DE_INIT(("LoadDsp: send_vector DSP_VC_RESET failed, Critical Failure\n")); - return -EIO; - } - /* Delay 10us */ - udelay(10); - - /* Wait 10ms for HF3 to indicate that software reset is complete */ - for (i = 0; i < 1000; i++) { /* Timeout is 10us * 1000 = 10ms */ - if (get_dsp_register(chip, CHI32_STATUS_REG) & - CHI32_STATUS_REG_HF3) - break; - udelay(10); - } - - if (i == 1000) { - DE_INIT(("load_dsp: Timeout waiting for CHI32_STATUS_REG_HF3\n")); - return -EIO; - } - - /* Set DSP format bits for 24 bit mode now that soft reset is done */ - set_dsp_register(chip, CHI32_CONTROL_REG, - get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900); - - /* Main loader loop */ - - index = code[0]; - for (;;) { - int block_type, mem_type; - - /* Total Block Size */ - index++; - - /* Block Type */ - block_type = code[index]; - if (block_type == 4) /* We're finished */ - break; - - index++; - - /* Memory Type P=0,X=1,Y=2 */ - mem_type = code[index++]; - - /* Block Code Size */ - words = code[index++]; - if (words == 0) /* We're finished */ - break; - - /* Start Address */ - address = ((u32)code[index] << 16) + code[index + 1]; - index += 2; - - if (write_dsp(chip, words) < 0) { - DE_INIT(("load_dsp: failed to write number of DSP words\n")); - return -EIO; - } - if (write_dsp(chip, address) < 0) { - DE_INIT(("load_dsp: failed to write DSP address\n")); - return -EIO; - } - if (write_dsp(chip, mem_type) < 0) { - DE_INIT(("load_dsp: failed to write DSP memory type\n")); - return -EIO; - } - /* Code */ - for (i = 0; i < words; i++, index+=2) { - data = ((u32)code[index] << 16) + code[index + 1]; - if (write_dsp(chip, data) < 0) { - DE_INIT(("load_dsp: failed to write DSP data\n")); - return -EIO; - } - } - } - - if (write_dsp(chip, 0) < 0) { /* We're done!!! */ - DE_INIT(("load_dsp: Failed to write final zero\n")); - return -EIO; - } - udelay(10); - - for (i = 0; i < 5000; i++) { /* Timeout is 100us * 5000 = 500ms */ - /* Wait for flag 4 - indicates that the DSP loaded OK */ - if (get_dsp_register(chip, CHI32_STATUS_REG) & - CHI32_STATUS_REG_HF4) { - set_dsp_register(chip, CHI32_CONTROL_REG, - get_dsp_register(chip, CHI32_CONTROL_REG) & ~0x1b00); - - if (write_dsp(chip, DSP_FNC_SET_COMMPAGE_ADDR) < 0) { - DE_INIT(("load_dsp: Failed to write DSP_FNC_SET_COMMPAGE_ADDR\n")); - return -EIO; - } - - if (write_dsp(chip, chip->comm_page_phys) < 0) { - DE_INIT(("load_dsp: Failed to write comm page address\n")); - return -EIO; - } - - /* Get the serial number via slave mode. - This is triggered by the SET_COMMPAGE_ADDR command. - We don't actually use the serial number but we have to - get it as part of the DSP init voodoo. */ - if (read_sn(chip) < 0) { - DE_INIT(("load_dsp: Failed to read serial number\n")); - return -EIO; - } - - chip->dsp_code = code; /* Show which DSP code loaded */ - chip->bad_board = FALSE; /* DSP OK */ - DE_INIT(("load_dsp: OK!\n")); - return 0; - } - udelay(100); - } - - DE_INIT(("load_dsp: DSP load timed out waiting for HF4\n")); - return -EIO; -} - - - -/* load_firmware takes care of loading the DSP and any ASIC code. */ -static int load_firmware(struct echoaudio *chip) -{ - const struct firmware *fw; - int box_type, err; - - snd_assert(chip->dsp_code_to_load && chip->comm_page, return -EPERM); - - /* See if the ASIC is present and working - only if the DSP is already loaded */ - if (chip->dsp_code) { - if ((box_type = check_asic_status(chip)) >= 0) - return box_type; - /* ASIC check failed; force the DSP to reload */ - chip->dsp_code = NULL; - } - - if ((err = get_firmware(&fw, chip->dsp_code_to_load, chip)) < 0) - return err; - err = load_dsp(chip, (u16 *)fw->data); - free_firmware(fw); - if (err < 0) - return err; - - if ((box_type = load_asic(chip)) < 0) - return box_type; /* error */ - - if ((err = restore_dsp_rettings(chip)) < 0) - return err; - - return box_type; -} - - - -/**************************************************************************** - Mixer functions - ****************************************************************************/ - -#if defined(ECHOCARD_HAS_INPUT_NOMINAL_LEVEL) || \ - defined(ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL) - -/* Set the nominal level for an input or output bus (true = -10dBV, false = +4dBu) */ -static int set_nominal_level(struct echoaudio *chip, u16 index, char consumer) -{ - snd_assert(index < num_busses_out(chip) + num_busses_in(chip), - return -EINVAL); - - /* Wait for the handshake (OK even if ASIC is not loaded) */ - if (wait_handshake(chip)) - return -EIO; - - chip->nominal_level[index] = consumer; - - if (consumer) - chip->comm_page->nominal_level_mask |= cpu_to_le32(1 << index); - else - chip->comm_page->nominal_level_mask &= ~cpu_to_le32(1 << index); - - return 0; -} - -#endif /* ECHOCARD_HAS_*_NOMINAL_LEVEL */ - - - -/* Set the gain for a single physical output channel (dB). */ -static int set_output_gain(struct echoaudio *chip, u16 channel, s8 gain) -{ - snd_assert(channel < num_busses_out(chip), return -EINVAL); - - if (wait_handshake(chip)) - return -EIO; - - /* Save the new value */ - chip->output_gain[channel] = gain; - chip->comm_page->line_out_level[channel] = gain; - return 0; -} - - - -#ifdef ECHOCARD_HAS_MONITOR -/* Set the monitor level from an input bus to an output bus. */ -static int set_monitor_gain(struct echoaudio *chip, u16 output, u16 input, - s8 gain) -{ - snd_assert(output < num_busses_out(chip) && - input < num_busses_in(chip), return -EINVAL); - - if (wait_handshake(chip)) - return -EIO; - - chip->monitor_gain[output][input] = gain; - chip->comm_page->monitors[monitor_index(chip, output, input)] = gain; - return 0; -} -#endif /* ECHOCARD_HAS_MONITOR */ - - -/* Tell the DSP to read and update output, nominal & monitor levels in comm page. */ -static int update_output_line_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_OUTVOL); -} - - - -/* Tell the DSP to read and update input levels in comm page */ -static int update_input_line_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_INGAIN); -} - - - -/* set_meters_on turns the meters on or off. If meters are turned on, the DSP -will write the meter and clock detect values to the comm page at about 30Hz */ -static void set_meters_on(struct echoaudio *chip, char on) -{ - if (on && !chip->meters_enabled) { - send_vector(chip, DSP_VC_METERS_ON); - chip->meters_enabled = 1; - } else if (!on && chip->meters_enabled) { - send_vector(chip, DSP_VC_METERS_OFF); - chip->meters_enabled = 0; - memset((s8 *)chip->comm_page->vu_meter, ECHOGAIN_MUTED, - DSP_MAXPIPES); - memset((s8 *)chip->comm_page->peak_meter, ECHOGAIN_MUTED, - DSP_MAXPIPES); - } -} - - - -/* Fill out an the given array using the current values in the comm page. -Meters are written in the comm page by the DSP in this order: - Output busses - Input busses - Output pipes (vmixer cards only) - -This function assumes there are no more than 16 in/out busses or pipes -Meters is an array [3][16][2] of long. */ -static void get_audio_meters(struct echoaudio *chip, long *meters) -{ - int i, m, n; - - m = 0; - n = 0; - for (i = 0; i < num_busses_out(chip); i++, m++) { - meters[n++] = chip->comm_page->vu_meter[m]; - meters[n++] = chip->comm_page->peak_meter[m]; - } - for (; n < 32; n++) - meters[n] = 0; - -#ifdef ECHOCARD_ECHO3G - m = E3G_MAX_OUTPUTS; /* Skip unused meters */ -#endif - - for (i = 0; i < num_busses_in(chip); i++, m++) { - meters[n++] = chip->comm_page->vu_meter[m]; - meters[n++] = chip->comm_page->peak_meter[m]; - } - for (; n < 64; n++) - meters[n] = 0; - -#ifdef ECHOCARD_HAS_VMIXER - for (i = 0; i < num_pipes_out(chip); i++, m++) { - meters[n++] = chip->comm_page->vu_meter[m]; - meters[n++] = chip->comm_page->peak_meter[m]; - } -#endif - for (; n < 96; n++) - meters[n] = 0; -} - - - -static int restore_dsp_rettings(struct echoaudio *chip) -{ - int err; - DE_INIT(("restore_dsp_settings\n")); - - if ((err = check_asic_status(chip)) < 0) - return err; - - /* @ Gina20/Darla20 only. Should be harmless for other cards. */ - chip->comm_page->gd_clock_state = GD_CLOCK_UNDEF; - chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_UNDEF; - chip->comm_page->handshake = 0xffffffff; - - if ((err = set_sample_rate(chip, chip->sample_rate)) < 0) - return err; - - if (chip->meters_enabled) - if (send_vector(chip, DSP_VC_METERS_ON) < 0) - return -EIO; - -#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK - if (set_input_clock(chip, chip->input_clock) < 0) - return -EIO; -#endif - -#ifdef ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH - if (set_output_clock(chip, chip->output_clock) < 0) - return -EIO; -#endif - - if (update_output_line_level(chip) < 0) - return -EIO; - - if (update_input_line_level(chip) < 0) - return -EIO; - -#ifdef ECHOCARD_HAS_VMIXER - if (update_vmixer_level(chip) < 0) - return -EIO; -#endif - - if (wait_handshake(chip) < 0) - return -EIO; - clear_handshake(chip); - - DE_INIT(("restore_dsp_rettings done\n")); - return send_vector(chip, DSP_VC_UPDATE_FLAGS); -} - - - -/**************************************************************************** - Transport functions - ****************************************************************************/ - -/* set_audio_format() sets the format of the audio data in host memory for -this pipe. Note that _MS_ (mono-to-stereo) playback modes are not used by ALSA -but they are here because they are just mono while capturing */ -static void set_audio_format(struct echoaudio *chip, u16 pipe_index, - const struct audioformat *format) -{ - u16 dsp_format; - - dsp_format = DSP_AUDIOFORM_SS_16LE; - - /* Look for super-interleave (no big-endian and 8 bits) */ - if (format->interleave > 2) { - switch (format->bits_per_sample) { - case 16: - dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_16LE; - break; - case 24: - dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_24LE; - break; - case 32: - dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_32LE; - break; - } - dsp_format |= format->interleave; - } else if (format->data_are_bigendian) { - /* For big-endian data, only 32 bit samples are supported */ - switch (format->interleave) { - case 1: - dsp_format = DSP_AUDIOFORM_MM_32BE; - break; -#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - case 2: - dsp_format = DSP_AUDIOFORM_SS_32BE; - break; -#endif - } - } else if (format->interleave == 1 && - format->bits_per_sample == 32 && !format->mono_to_stereo) { - /* 32 bit little-endian mono->mono case */ - dsp_format = DSP_AUDIOFORM_MM_32LE; - } else { - /* Handle the other little-endian formats */ - switch (format->bits_per_sample) { - case 8: - if (format->interleave == 2) - dsp_format = DSP_AUDIOFORM_SS_8; - else - dsp_format = DSP_AUDIOFORM_MS_8; - break; - default: - case 16: - if (format->interleave == 2) - dsp_format = DSP_AUDIOFORM_SS_16LE; - else - dsp_format = DSP_AUDIOFORM_MS_16LE; - break; - case 24: - if (format->interleave == 2) - dsp_format = DSP_AUDIOFORM_SS_24LE; - else - dsp_format = DSP_AUDIOFORM_MS_24LE; - break; - case 32: - if (format->interleave == 2) - dsp_format = DSP_AUDIOFORM_SS_32LE; - else - dsp_format = DSP_AUDIOFORM_MS_32LE; - break; - } - } - DE_ACT(("set_audio_format[%d] = %x\n", pipe_index, dsp_format)); - chip->comm_page->audio_format[pipe_index] = cpu_to_le16(dsp_format); -} - - - -/* start_transport starts transport for a set of pipes. -The bits 1 in channel_mask specify what pipes to start. Only the bit of the -first channel must be set, regardless its interleave. -Same thing for pause_ and stop_ -trasport below. */ -static int start_transport(struct echoaudio *chip, u32 channel_mask, - u32 cyclic_mask) -{ - DE_ACT(("start_transport %x\n", channel_mask)); - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->cmd_start |= cpu_to_le32(channel_mask); - - if (chip->comm_page->cmd_start) { - clear_handshake(chip); - send_vector(chip, DSP_VC_START_TRANSFER); - if (wait_handshake(chip)) - return -EIO; - /* Keep track of which pipes are transporting */ - chip->active_mask |= channel_mask; - chip->comm_page->cmd_start = 0; - return 0; - } - - DE_ACT(("start_transport: No pipes to start!\n")); - return -EINVAL; -} - - - -static int pause_transport(struct echoaudio *chip, u32 channel_mask) -{ - DE_ACT(("pause_transport %x\n", channel_mask)); - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->cmd_stop |= cpu_to_le32(channel_mask); - chip->comm_page->cmd_reset = 0; - if (chip->comm_page->cmd_stop) { - clear_handshake(chip); - send_vector(chip, DSP_VC_STOP_TRANSFER); - if (wait_handshake(chip)) - return -EIO; - /* Keep track of which pipes are transporting */ - chip->active_mask &= ~channel_mask; - chip->comm_page->cmd_stop = 0; - chip->comm_page->cmd_reset = 0; - return 0; - } - - DE_ACT(("pause_transport: No pipes to stop!\n")); - return 0; -} - - - -static int stop_transport(struct echoaudio *chip, u32 channel_mask) -{ - DE_ACT(("stop_transport %x\n", channel_mask)); - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->cmd_stop |= cpu_to_le32(channel_mask); - chip->comm_page->cmd_reset |= cpu_to_le32(channel_mask); - if (chip->comm_page->cmd_reset) { - clear_handshake(chip); - send_vector(chip, DSP_VC_STOP_TRANSFER); - if (wait_handshake(chip)) - return -EIO; - /* Keep track of which pipes are transporting */ - chip->active_mask &= ~channel_mask; - chip->comm_page->cmd_stop = 0; - chip->comm_page->cmd_reset = 0; - return 0; - } - - DE_ACT(("stop_transport: No pipes to stop!\n")); - return 0; -} - - - -static inline int is_pipe_allocated(struct echoaudio *chip, u16 pipe_index) -{ - return (chip->pipe_alloc_mask & (1 << pipe_index)); -} - - - -/* Stops everything and turns off the DSP. All pipes should be already -stopped and unallocated. */ -static int rest_in_peace(struct echoaudio *chip) -{ - DE_ACT(("rest_in_peace() open=%x\n", chip->pipe_alloc_mask)); - - /* Stops all active pipes (just to be sure) */ - stop_transport(chip, chip->active_mask); - - set_meters_on(chip, FALSE); - -#ifdef ECHOCARD_HAS_MIDI - enable_midi_input(chip, FALSE); -#endif - - /* Go to sleep */ - if (chip->dsp_code) { - /* Make load_firmware do a complete reload */ - chip->dsp_code = NULL; - /* Put the DSP to sleep */ - return send_vector(chip, DSP_VC_GO_COMATOSE); - } - return 0; -} - - - -/* Fills the comm page with default values */ -static int init_dsp_comm_page(struct echoaudio *chip) -{ - /* Check if the compiler added extra padding inside the structure */ - if (offsetof(struct comm_page, midi_output) != 0xbe0) { - DE_INIT(("init_dsp_comm_page() - Invalid struct comm_page structure\n")); - return -EPERM; - } - - /* Init all the basic stuff */ - chip->card_name = ECHOCARD_NAME; - chip->bad_board = TRUE; /* Set TRUE until DSP loaded */ - chip->dsp_code = NULL; /* Current DSP code not loaded */ - chip->digital_mode = DIGITAL_MODE_NONE; - chip->input_clock = ECHO_CLOCK_INTERNAL; - chip->output_clock = ECHO_CLOCK_WORD; - chip->asic_loaded = FALSE; - memset(chip->comm_page, 0, sizeof(struct comm_page)); - - /* Init the comm page */ - chip->comm_page->comm_size = - __constant_cpu_to_le32(sizeof(struct comm_page)); - chip->comm_page->handshake = 0xffffffff; - chip->comm_page->midi_out_free_count = - __constant_cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE); - chip->comm_page->sample_rate = __constant_cpu_to_le32(44100); - chip->sample_rate = 44100; - - /* Set line levels so we don't blast any inputs on startup */ - memset(chip->comm_page->monitors, ECHOGAIN_MUTED, MONITOR_ARRAY_SIZE); - memset(chip->comm_page->vmixer, ECHOGAIN_MUTED, VMIXER_ARRAY_SIZE); - - return 0; -} - - - -/* This function initializes the several volume controls for busses and pipes. -This MUST be called after the DSP is up and running ! */ -static int init_line_levels(struct echoaudio *chip) -{ - int st, i, o; - - DE_INIT(("init_line_levels\n")); - - /* Mute output busses */ - for (i = 0; i < num_busses_out(chip); i++) - if ((st = set_output_gain(chip, i, ECHOGAIN_MUTED))) - return st; - if ((st = update_output_line_level(chip))) - return st; - -#ifdef ECHOCARD_HAS_VMIXER - /* Mute the Vmixer */ - for (i = 0; i < num_pipes_out(chip); i++) - for (o = 0; o < num_busses_out(chip); o++) - if ((st = set_vmixer_gain(chip, o, i, ECHOGAIN_MUTED))) - return st; - if ((st = update_vmixer_level(chip))) - return st; -#endif /* ECHOCARD_HAS_VMIXER */ - -#ifdef ECHOCARD_HAS_MONITOR - /* Mute the monitor mixer */ - for (o = 0; o < num_busses_out(chip); o++) - for (i = 0; i < num_busses_in(chip); i++) - if ((st = set_monitor_gain(chip, o, i, ECHOGAIN_MUTED))) - return st; - if ((st = update_output_line_level(chip))) - return st; -#endif /* ECHOCARD_HAS_MONITOR */ - -#ifdef ECHOCARD_HAS_INPUT_GAIN - for (i = 0; i < num_busses_in(chip); i++) - if ((st = set_input_gain(chip, i, ECHOGAIN_MUTED))) - return st; - if ((st = update_input_line_level(chip))) - return st; -#endif /* ECHOCARD_HAS_INPUT_GAIN */ - - return 0; -} - - - -/* This is low level part of the interrupt handler. -It returns -1 if the IRQ is not ours, or N>=0 if it is, where N is the number -of midi data in the input queue. */ -static int service_irq(struct echoaudio *chip) -{ - int st; - - /* Read the DSP status register and see if this DSP generated this interrupt */ - if (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_IRQ) { - st = 0; -#ifdef ECHOCARD_HAS_MIDI - /* Get and parse midi data if present */ - if (chip->comm_page->midi_input[0]) /* The count is at index 0 */ - st = midi_service_irq(chip); /* Returns how many midi bytes we received */ -#endif - /* Clear the hardware interrupt */ - chip->comm_page->midi_input[0] = 0; - send_vector(chip, DSP_VC_ACK_INT); - return st; - } - return -1; -} - - - - -/****************************************************************************** - Functions for opening and closing pipes - ******************************************************************************/ - -/* allocate_pipes is used to reserve audio pipes for your exclusive use. -The call will fail if some pipes are already allocated. */ -static int allocate_pipes(struct echoaudio *chip, struct audiopipe *pipe, - int pipe_index, int interleave) -{ - int i; - u32 channel_mask; - char is_cyclic; - - DE_ACT(("allocate_pipes: ch=%d int=%d\n", pipe_index, interleave)); - - if (chip->bad_board) - return -EIO; - - is_cyclic = 1; /* This driver uses cyclic buffers only */ - - for (channel_mask = i = 0; i < interleave; i++) - channel_mask |= 1 << (pipe_index + i); - if (chip->pipe_alloc_mask & channel_mask) { - DE_ACT(("allocate_pipes: channel already open\n")); - return -EAGAIN; - } - - chip->comm_page->position[pipe_index] = 0; - chip->pipe_alloc_mask |= channel_mask; - if (is_cyclic) - chip->pipe_cyclic_mask |= channel_mask; - pipe->index = pipe_index; - pipe->interleave = interleave; - pipe->state = PIPE_STATE_STOPPED; - - /* The counter register is where the DSP writes the 32 bit DMA - position for a pipe. The DSP is constantly updating this value as - it moves data. The DMA counter is in units of bytes, not samples. */ - pipe->dma_counter = &chip->comm_page->position[pipe_index]; - *pipe->dma_counter = 0; - DE_ACT(("allocate_pipes: ok\n")); - return pipe_index; -} - - - -static int free_pipes(struct echoaudio *chip, struct audiopipe *pipe) -{ - u32 channel_mask; - int i; - - DE_ACT(("free_pipes: Pipe %d\n", pipe->index)); - snd_assert(is_pipe_allocated(chip, pipe->index), return -EINVAL); - snd_assert(pipe->state == PIPE_STATE_STOPPED, return -EINVAL); - - for (channel_mask = i = 0; i < pipe->interleave; i++) - channel_mask |= 1 << (pipe->index + i); - - chip->pipe_alloc_mask &= ~channel_mask; - chip->pipe_cyclic_mask &= ~channel_mask; - return 0; -} - - - -/****************************************************************************** - Functions for managing the scatter-gather list -******************************************************************************/ - -static int sglist_init(struct echoaudio *chip, struct audiopipe *pipe) -{ - pipe->sglist_head = 0; - memset(pipe->sgpage.area, 0, PAGE_SIZE); - chip->comm_page->sglist_addr[pipe->index].addr = - cpu_to_le32(pipe->sgpage.addr); - return 0; -} - - - -static int sglist_add_mapping(struct echoaudio *chip, struct audiopipe *pipe, - dma_addr_t address, size_t length) -{ - int head = pipe->sglist_head; - struct sg_entry *list = (struct sg_entry *)pipe->sgpage.area; - - if (head < MAX_SGLIST_ENTRIES - 1) { - list[head].addr = cpu_to_le32(address); - list[head].size = cpu_to_le32(length); - pipe->sglist_head++; - } else { - DE_ACT(("SGlist: too many fragments\n")); - return -ENOMEM; - } - return 0; -} - - - -static inline int sglist_add_irq(struct echoaudio *chip, struct audiopipe *pipe) -{ - return sglist_add_mapping(chip, pipe, 0, 0); -} - - - -static inline int sglist_wrap(struct echoaudio *chip, struct audiopipe *pipe) -{ - return sglist_add_mapping(chip, pipe, pipe->sgpage.addr, 0); -} diff --git a/trunk/sound/pci/echoaudio/echoaudio_dsp.h b/trunk/sound/pci/echoaudio/echoaudio_dsp.h deleted file mode 100644 index e55ee00991ac..000000000000 --- a/trunk/sound/pci/echoaudio/echoaudio_dsp.h +++ /dev/null @@ -1,694 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - -#ifndef _ECHO_DSP_ -#define _ECHO_DSP_ - - -/**** Echogals: Darla20, Gina20, Layla20, and Darla24 ****/ -#if defined(ECHOGALS_FAMILY) - -#define NUM_ASIC_TESTS 5 -#define READ_DSP_TIMEOUT 1000000L /* one second */ - -/**** Echo24: Gina24, Layla24, Mona, Mia, Mia-midi ****/ -#elif defined(ECHO24_FAMILY) - -#define DSP_56361 /* Some Echo24 cards use the 56361 DSP */ -#define READ_DSP_TIMEOUT 100000L /* .1 second */ - -/**** 3G: Gina3G, Layla3G ****/ -#elif defined(ECHO3G_FAMILY) - -#define DSP_56361 -#define READ_DSP_TIMEOUT 100000L /* .1 second */ -#define MIN_MTC_1X_RATE 32000 - -/**** Indigo: Indigo, Indigo IO, Indigo DJ ****/ -#elif defined(INDIGO_FAMILY) - -#define DSP_56361 -#define READ_DSP_TIMEOUT 100000L /* .1 second */ - -#else - -#error No family is defined - -#endif - - - -/* - * - * Max inputs and outputs - * - */ - -#define DSP_MAXAUDIOINPUTS 16 /* Max audio input channels */ -#define DSP_MAXAUDIOOUTPUTS 16 /* Max audio output channels */ -#define DSP_MAXPIPES 32 /* Max total pipes (input + output) */ - - -/* - * - * These are the offsets for the memory-mapped DSP registers; the DSP base - * address is treated as the start of a u32 array. - */ - -#define CHI32_CONTROL_REG 4 -#define CHI32_STATUS_REG 5 -#define CHI32_VECTOR_REG 6 -#define CHI32_DATA_REG 7 - - -/* - * - * Interesting bits within the DSP registers - * - */ - -#define CHI32_VECTOR_BUSY 0x00000001 -#define CHI32_STATUS_REG_HF3 0x00000008 -#define CHI32_STATUS_REG_HF4 0x00000010 -#define CHI32_STATUS_REG_HF5 0x00000020 -#define CHI32_STATUS_HOST_READ_FULL 0x00000004 -#define CHI32_STATUS_HOST_WRITE_EMPTY 0x00000002 -#define CHI32_STATUS_IRQ 0x00000040 - - -/* - * - * DSP commands sent via slave mode; these are sent to the DSP by write_dsp() - * - */ - -#define DSP_FNC_SET_COMMPAGE_ADDR 0x02 -#define DSP_FNC_LOAD_LAYLA_ASIC 0xa0 -#define DSP_FNC_LOAD_GINA24_ASIC 0xa0 -#define DSP_FNC_LOAD_MONA_PCI_CARD_ASIC 0xa0 -#define DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC 0xa0 -#define DSP_FNC_LOAD_MONA_EXTERNAL_ASIC 0xa1 -#define DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC 0xa1 -#define DSP_FNC_LOAD_3G_ASIC 0xa0 - - -/* - * - * Defines to handle the MIDI input state engine; these are used to properly - * extract MIDI time code bytes and their timestamps from the MIDI input stream. - * - */ - -#define MIDI_IN_STATE_NORMAL 0 -#define MIDI_IN_STATE_TS_HIGH 1 -#define MIDI_IN_STATE_TS_LOW 2 -#define MIDI_IN_STATE_F1_DATA 3 -#define MIDI_IN_SKIP_DATA (-1) - - -/*---------------------------------------------------------------------------- - -Setting the sample rates on Layla24 is somewhat schizophrenic. - -For standard rates, it works exactly like Mona and Gina24. That is, for -8, 11.025, 16, 22.05, 32, 44.1, 48, 88.2, and 96 kHz, you just set the -appropriate bits in the control register and write the control register. - -In order to support MIDI time code sync (and possibly SMPTE LTC sync in -the future), Layla24 also has "continuous sample rate mode". In this mode, -Layla24 can generate any sample rate between 25 and 50 kHz inclusive, or -50 to 100 kHz inclusive for double speed mode. - -To use continuous mode: - --Set the clock select bits in the control register to 0xe (see the #define - below) - --Set double-speed mode if you want to use sample rates above 50 kHz - --Write the control register as you would normally - --Now, you need to set the frequency register. First, you need to determine the - value for the frequency register. This is given by the following formula: - -frequency_reg = (LAYLA24_MAGIC_NUMBER / sample_rate) - 2 - -Note the #define below for the magic number - --Wait for the DSP handshake --Write the frequency_reg value to the .SampleRate field of the comm page --Send the vector command SET_LAYLA24_FREQUENCY_REG (see vmonkey.h) - -Once you have set the control register up for continuous mode, you can just -write the frequency register to change the sample rate. This could be -used for MIDI time code sync. For MTC sync, the control register is set for -continuous mode. The driver then just keeps writing the -SET_LAYLA24_FREQUENCY_REG command. - ------------------------------------------------------------------------------*/ - -#define LAYLA24_MAGIC_NUMBER 677376000 -#define LAYLA24_CONTINUOUS_CLOCK 0x000e - - -/* - * - * DSP vector commands - * - */ - -#define DSP_VC_RESET 0x80ff - -#ifndef DSP_56361 - -#define DSP_VC_ACK_INT 0x8073 -#define DSP_VC_SET_VMIXER_GAIN 0x0000 /* Not used, only for compile */ -#define DSP_VC_START_TRANSFER 0x0075 /* Handshke rqd. */ -#define DSP_VC_METERS_ON 0x0079 -#define DSP_VC_METERS_OFF 0x007b -#define DSP_VC_UPDATE_OUTVOL 0x007d /* Handshke rqd. */ -#define DSP_VC_UPDATE_INGAIN 0x007f /* Handshke rqd. */ -#define DSP_VC_ADD_AUDIO_BUFFER 0x0081 /* Handshke rqd. */ -#define DSP_VC_TEST_ASIC 0x00eb -#define DSP_VC_UPDATE_CLOCKS 0x00ef /* Handshke rqd. */ -#define DSP_VC_SET_LAYLA_SAMPLE_RATE 0x00f1 /* Handshke rqd. */ -#define DSP_VC_SET_GD_AUDIO_STATE 0x00f1 /* Handshke rqd. */ -#define DSP_VC_WRITE_CONTROL_REG 0x00f1 /* Handshke rqd. */ -#define DSP_VC_MIDI_WRITE 0x00f5 /* Handshke rqd. */ -#define DSP_VC_STOP_TRANSFER 0x00f7 /* Handshke rqd. */ -#define DSP_VC_UPDATE_FLAGS 0x00fd /* Handshke rqd. */ -#define DSP_VC_GO_COMATOSE 0x00f9 - -#else /* !DSP_56361 */ - -/* Vector commands for families that use either the 56301 or 56361 */ -#define DSP_VC_ACK_INT 0x80F5 -#define DSP_VC_SET_VMIXER_GAIN 0x00DB /* Handshke rqd. */ -#define DSP_VC_START_TRANSFER 0x00DD /* Handshke rqd. */ -#define DSP_VC_METERS_ON 0x00EF -#define DSP_VC_METERS_OFF 0x00F1 -#define DSP_VC_UPDATE_OUTVOL 0x00E3 /* Handshke rqd. */ -#define DSP_VC_UPDATE_INGAIN 0x00E5 /* Handshke rqd. */ -#define DSP_VC_ADD_AUDIO_BUFFER 0x00E1 /* Handshke rqd. */ -#define DSP_VC_TEST_ASIC 0x00ED -#define DSP_VC_UPDATE_CLOCKS 0x00E9 /* Handshke rqd. */ -#define DSP_VC_SET_LAYLA24_FREQUENCY_REG 0x00E9 /* Handshke rqd. */ -#define DSP_VC_SET_LAYLA_SAMPLE_RATE 0x00EB /* Handshke rqd. */ -#define DSP_VC_SET_GD_AUDIO_STATE 0x00EB /* Handshke rqd. */ -#define DSP_VC_WRITE_CONTROL_REG 0x00EB /* Handshke rqd. */ -#define DSP_VC_MIDI_WRITE 0x00E7 /* Handshke rqd. */ -#define DSP_VC_STOP_TRANSFER 0x00DF /* Handshke rqd. */ -#define DSP_VC_UPDATE_FLAGS 0x00FB /* Handshke rqd. */ -#define DSP_VC_GO_COMATOSE 0x00d9 - -#endif /* !DSP_56361 */ - - -/* - * - * Timeouts - * - */ - -#define HANDSHAKE_TIMEOUT 20000 /* send_vector command timeout (20ms) */ -#define VECTOR_BUSY_TIMEOUT 100000 /* 100ms */ -#define MIDI_OUT_DELAY_USEC 2000 /* How long to wait after MIDI fills up */ - - -/* - * - * Flags for .Flags field in the comm page - * - */ - -#define DSP_FLAG_MIDI_INPUT 0x0001 /* Enable MIDI input */ -#define DSP_FLAG_SPDIF_NONAUDIO 0x0002 /* Sets the "non-audio" bit - * in the S/PDIF out status - * bits. Clear this flag for - * audio data; - * set it for AC3 or WMA or - * some such */ -#define DSP_FLAG_PROFESSIONAL_SPDIF 0x0008 /* 1 Professional, 0 Consumer */ - - -/* - * - * Clock detect bits reported by the DSP for Gina20, Layla20, Darla24, and Mia - * - */ - -#define GLDM_CLOCK_DETECT_BIT_WORD 0x0002 -#define GLDM_CLOCK_DETECT_BIT_SUPER 0x0004 -#define GLDM_CLOCK_DETECT_BIT_SPDIF 0x0008 -#define GLDM_CLOCK_DETECT_BIT_ESYNC 0x0010 - - -/* - * - * Clock detect bits reported by the DSP for Gina24, Mona, and Layla24 - * - */ - -#define GML_CLOCK_DETECT_BIT_WORD96 0x0002 -#define GML_CLOCK_DETECT_BIT_WORD48 0x0004 -#define GML_CLOCK_DETECT_BIT_SPDIF48 0x0008 -#define GML_CLOCK_DETECT_BIT_SPDIF96 0x0010 -#define GML_CLOCK_DETECT_BIT_WORD (GML_CLOCK_DETECT_BIT_WORD96 | GML_CLOCK_DETECT_BIT_WORD48) -#define GML_CLOCK_DETECT_BIT_SPDIF (GML_CLOCK_DETECT_BIT_SPDIF48 | GML_CLOCK_DETECT_BIT_SPDIF96) -#define GML_CLOCK_DETECT_BIT_ESYNC 0x0020 -#define GML_CLOCK_DETECT_BIT_ADAT 0x0040 - - -/* - * - * Layla clock numbers to send to DSP - * - */ - -#define LAYLA20_CLOCK_INTERNAL 0 -#define LAYLA20_CLOCK_SPDIF 1 -#define LAYLA20_CLOCK_WORD 2 -#define LAYLA20_CLOCK_SUPER 3 - - -/* - * - * Gina/Darla clock states - * - */ - -#define GD_CLOCK_NOCHANGE 0 -#define GD_CLOCK_44 1 -#define GD_CLOCK_48 2 -#define GD_CLOCK_SPDIFIN 3 -#define GD_CLOCK_UNDEF 0xff - - -/* - * - * Gina/Darla S/PDIF status bits - * - */ - -#define GD_SPDIF_STATUS_NOCHANGE 0 -#define GD_SPDIF_STATUS_44 1 -#define GD_SPDIF_STATUS_48 2 -#define GD_SPDIF_STATUS_UNDEF 0xff - - -/* - * - * Layla20 output clocks - * - */ - -#define LAYLA20_OUTPUT_CLOCK_SUPER 0 -#define LAYLA20_OUTPUT_CLOCK_WORD 1 - - -/**************************************************************************** - - Magic constants for the Darla24 hardware - - ****************************************************************************/ - -#define GD24_96000 0x0 -#define GD24_48000 0x1 -#define GD24_44100 0x2 -#define GD24_32000 0x3 -#define GD24_22050 0x4 -#define GD24_16000 0x5 -#define GD24_11025 0x6 -#define GD24_8000 0x7 -#define GD24_88200 0x8 -#define GD24_EXT_SYNC 0x9 - - -/* - * - * Return values from the DSP when ASIC is loaded - * - */ - -#define ASIC_ALREADY_LOADED 0x1 -#define ASIC_NOT_LOADED 0x0 - - -/* - * - * DSP Audio formats - * - * These are the audio formats that the DSP can transfer - * via input and output pipes. LE means little-endian, - * BE means big-endian. - * - * DSP_AUDIOFORM_MS_8 - * - * 8-bit mono unsigned samples. For playback, - * mono data is duplicated out the left and right channels - * of the output bus. The "MS" part of the name - * means mono->stereo. - * - * DSP_AUDIOFORM_MS_16LE - * - * 16-bit signed little-endian mono samples. Playback works - * like the previous code. - * - * DSP_AUDIOFORM_MS_24LE - * - * 24-bit signed little-endian mono samples. Data is packed - * three bytes per sample; if you had two samples 0x112233 and 0x445566 - * they would be stored in memory like this: 33 22 11 66 55 44. - * - * DSP_AUDIOFORM_MS_32LE - * - * 24-bit signed little-endian mono samples in a 32-bit - * container. In other words, each sample is a 32-bit signed - * integer, where the actual audio data is left-justified - * in the 32 bits and only the 24 most significant bits are valid. - * - * DSP_AUDIOFORM_SS_8 - * DSP_AUDIOFORM_SS_16LE - * DSP_AUDIOFORM_SS_24LE - * DSP_AUDIOFORM_SS_32LE - * - * Like the previous ones, except now with stereo interleaved - * data. "SS" means stereo->stereo. - * - * DSP_AUDIOFORM_MM_32LE - * - * Similar to DSP_AUDIOFORM_MS_32LE, except that the mono - * data is not duplicated out both the left and right outputs. - * This mode is used by the ASIO driver. Here, "MM" means - * mono->mono. - * - * DSP_AUDIOFORM_MM_32BE - * - * Just like DSP_AUDIOFORM_MM_32LE, but now the data is - * in big-endian format. - * - */ - -#define DSP_AUDIOFORM_MS_8 0 /* 8 bit mono */ -#define DSP_AUDIOFORM_MS_16LE 1 /* 16 bit mono */ -#define DSP_AUDIOFORM_MS_24LE 2 /* 24 bit mono */ -#define DSP_AUDIOFORM_MS_32LE 3 /* 32 bit mono */ -#define DSP_AUDIOFORM_SS_8 4 /* 8 bit stereo */ -#define DSP_AUDIOFORM_SS_16LE 5 /* 16 bit stereo */ -#define DSP_AUDIOFORM_SS_24LE 6 /* 24 bit stereo */ -#define DSP_AUDIOFORM_SS_32LE 7 /* 32 bit stereo */ -#define DSP_AUDIOFORM_MM_32LE 8 /* 32 bit mono->mono little-endian */ -#define DSP_AUDIOFORM_MM_32BE 9 /* 32 bit mono->mono big-endian */ -#define DSP_AUDIOFORM_SS_32BE 10 /* 32 bit stereo big endian */ -#define DSP_AUDIOFORM_INVALID 0xFF /* Invalid audio format */ - - -/* - * - * Super-interleave is defined as interleaving by 4 or more. Darla20 and Gina20 - * do not support super interleave. - * - * 16 bit, 24 bit, and 32 bit little endian samples are supported for super - * interleave. The interleave factor must be even. 16 - way interleave is the - * current maximum, so you can interleave by 4, 6, 8, 10, 12, 14, and 16. - * - * The actual format code is derived by taking the define below and or-ing with - * the interleave factor. So, 32 bit interleave by 6 is 0x86 and - * 16 bit interleave by 16 is (0x40 | 0x10) = 0x50. - * - */ - -#define DSP_AUDIOFORM_SUPER_INTERLEAVE_16LE 0x40 -#define DSP_AUDIOFORM_SUPER_INTERLEAVE_24LE 0xc0 -#define DSP_AUDIOFORM_SUPER_INTERLEAVE_32LE 0x80 - - -/* - * - * Gina24, Mona, and Layla24 control register defines - * - */ - -#define GML_CONVERTER_ENABLE 0x0010 -#define GML_SPDIF_PRO_MODE 0x0020 /* Professional S/PDIF == 1, - consumer == 0 */ -#define GML_SPDIF_SAMPLE_RATE0 0x0040 -#define GML_SPDIF_SAMPLE_RATE1 0x0080 -#define GML_SPDIF_TWO_CHANNEL 0x0100 /* 1 == two channels, - 0 == one channel */ -#define GML_SPDIF_NOT_AUDIO 0x0200 -#define GML_SPDIF_COPY_PERMIT 0x0400 -#define GML_SPDIF_24_BIT 0x0800 /* 1 == 24 bit, 0 == 20 bit */ -#define GML_ADAT_MODE 0x1000 /* 1 == ADAT mode, 0 == S/PDIF mode */ -#define GML_SPDIF_OPTICAL_MODE 0x2000 /* 1 == optical mode, 0 == RCA mode */ -#define GML_SPDIF_CDROM_MODE 0x3000 /* 1 == CDROM mode, - * 0 == RCA or optical mode */ -#define GML_DOUBLE_SPEED_MODE 0x4000 /* 1 == double speed, - 0 == single speed */ - -#define GML_DIGITAL_IN_AUTO_MUTE 0x800000 - -#define GML_96KHZ (0x0 | GML_DOUBLE_SPEED_MODE) -#define GML_88KHZ (0x1 | GML_DOUBLE_SPEED_MODE) -#define GML_48KHZ 0x2 -#define GML_44KHZ 0x3 -#define GML_32KHZ 0x4 -#define GML_22KHZ 0x5 -#define GML_16KHZ 0x6 -#define GML_11KHZ 0x7 -#define GML_8KHZ 0x8 -#define GML_SPDIF_CLOCK 0x9 -#define GML_ADAT_CLOCK 0xA -#define GML_WORD_CLOCK 0xB -#define GML_ESYNC_CLOCK 0xC -#define GML_ESYNCx2_CLOCK 0xD - -#define GML_CLOCK_CLEAR_MASK 0xffffbff0 -#define GML_SPDIF_RATE_CLEAR_MASK (~(GML_SPDIF_SAMPLE_RATE0|GML_SPDIF_SAMPLE_RATE1)) -#define GML_DIGITAL_MODE_CLEAR_MASK 0xffffcfff -#define GML_SPDIF_FORMAT_CLEAR_MASK 0xfffff01f - - -/* - * - * Mia sample rate and clock setting constants - * - */ - -#define MIA_32000 0x0040 -#define MIA_44100 0x0042 -#define MIA_48000 0x0041 -#define MIA_88200 0x0142 -#define MIA_96000 0x0141 - -#define MIA_SPDIF 0x00000044 -#define MIA_SPDIF96 0x00000144 - -#define MIA_MIDI_REV 1 /* Must be Mia rev 1 for MIDI support */ - - -/* - * - * 3G register bits - * - */ - -#define E3G_CONVERTER_ENABLE 0x0010 -#define E3G_SPDIF_PRO_MODE 0x0020 /* Professional S/PDIF == 1, - consumer == 0 */ -#define E3G_SPDIF_SAMPLE_RATE0 0x0040 -#define E3G_SPDIF_SAMPLE_RATE1 0x0080 -#define E3G_SPDIF_TWO_CHANNEL 0x0100 /* 1 == two channels, - 0 == one channel */ -#define E3G_SPDIF_NOT_AUDIO 0x0200 -#define E3G_SPDIF_COPY_PERMIT 0x0400 -#define E3G_SPDIF_24_BIT 0x0800 /* 1 == 24 bit, 0 == 20 bit */ -#define E3G_DOUBLE_SPEED_MODE 0x4000 /* 1 == double speed, - 0 == single speed */ -#define E3G_PHANTOM_POWER 0x8000 /* 1 == phantom power on, - 0 == phantom power off */ - -#define E3G_96KHZ (0x0 | E3G_DOUBLE_SPEED_MODE) -#define E3G_88KHZ (0x1 | E3G_DOUBLE_SPEED_MODE) -#define E3G_48KHZ 0x2 -#define E3G_44KHZ 0x3 -#define E3G_32KHZ 0x4 -#define E3G_22KHZ 0x5 -#define E3G_16KHZ 0x6 -#define E3G_11KHZ 0x7 -#define E3G_8KHZ 0x8 -#define E3G_SPDIF_CLOCK 0x9 -#define E3G_ADAT_CLOCK 0xA -#define E3G_WORD_CLOCK 0xB -#define E3G_CONTINUOUS_CLOCK 0xE - -#define E3G_ADAT_MODE 0x1000 -#define E3G_SPDIF_OPTICAL_MODE 0x2000 - -#define E3G_CLOCK_CLEAR_MASK 0xbfffbff0 -#define E3G_DIGITAL_MODE_CLEAR_MASK 0xffffcfff -#define E3G_SPDIF_FORMAT_CLEAR_MASK 0xfffff01f - -/* Clock detect bits reported by the DSP */ -#define E3G_CLOCK_DETECT_BIT_WORD96 0x0001 -#define E3G_CLOCK_DETECT_BIT_WORD48 0x0002 -#define E3G_CLOCK_DETECT_BIT_SPDIF48 0x0004 -#define E3G_CLOCK_DETECT_BIT_ADAT 0x0004 -#define E3G_CLOCK_DETECT_BIT_SPDIF96 0x0008 -#define E3G_CLOCK_DETECT_BIT_WORD (E3G_CLOCK_DETECT_BIT_WORD96|E3G_CLOCK_DETECT_BIT_WORD48) -#define E3G_CLOCK_DETECT_BIT_SPDIF (E3G_CLOCK_DETECT_BIT_SPDIF48|E3G_CLOCK_DETECT_BIT_SPDIF96) - -/* Frequency control register */ -#define E3G_MAGIC_NUMBER 677376000 -#define E3G_FREQ_REG_DEFAULT (E3G_MAGIC_NUMBER / 48000 - 2) -#define E3G_FREQ_REG_MAX 0xffff - -/* 3G external box types */ -#define E3G_GINA3G_BOX_TYPE 0x00 -#define E3G_LAYLA3G_BOX_TYPE 0x10 -#define E3G_ASIC_NOT_LOADED 0xffff -#define E3G_BOX_TYPE_MASK 0xf0 - -#define EXT_3GBOX_NC 0x01 -#define EXT_3GBOX_NOT_SET 0x02 - - -/* - * - * Gina20 & Layla20 have input gain controls for the analog inputs; - * this is the magic number for the hardware that gives you 0 dB at -10. - * - */ - -#define GL20_INPUT_GAIN_MAGIC_NUMBER 0xC8 - - -/* - * - * Defines how much time must pass between DSP load attempts - * - */ - -#define DSP_LOAD_ATTEMPT_PERIOD 1000000L /* One second */ - - -/* - * - * Size of arrays for the comm page. MAX_PLAY_TAPS and MAX_REC_TAPS are - * no longer used, but the sizes must still be right for the DSP to see - * the comm page correctly. - * - */ - -#define MONITOR_ARRAY_SIZE 0x180 -#define VMIXER_ARRAY_SIZE 0x40 -#define MIDI_OUT_BUFFER_SIZE 32 -#define MIDI_IN_BUFFER_SIZE 256 -#define MAX_PLAY_TAPS 168 -#define MAX_REC_TAPS 192 -#define DSP_MIDI_OUT_FIFO_SIZE 64 - - -/* sg_entry is a single entry for the scatter-gather list. The array of struct -sg_entry struct is read by the DSP, so all values must be little-endian. */ - -#define MAX_SGLIST_ENTRIES 512 - -struct sg_entry { - u32 addr; - u32 size; -}; - - -/**************************************************************************** - - The comm page. This structure is read and written by the DSP; the - DSP code is a firm believer in the byte offsets written in the comments - at the end of each line. This structure should not be changed. - - Any reads from or writes to this structure should be in little-endian format. - - ****************************************************************************/ - -struct comm_page { /* Base Length*/ - u32 comm_size; /* size of this object 0x000 4 */ - u32 flags; /* See Appendix A below 0x004 4 */ - u32 unused; /* Unused entry 0x008 4 */ - u32 sample_rate; /* Card sample rate in Hz 0x00c 4 */ - volatile u32 handshake; /* DSP command handshake 0x010 4 */ - u32 cmd_start; /* Chs. to start mask 0x014 4 */ - u32 cmd_stop; /* Chs. to stop mask 0x018 4 */ - u32 cmd_reset; /* Chs. to reset mask 0x01c 4 */ - u16 audio_format[DSP_MAXPIPES]; /* Chs. audio format 0x020 32*2 */ - struct sg_entry sglist_addr[DSP_MAXPIPES]; - /* Chs. Physical sglist addrs 0x060 32*8 */ - volatile u32 position[DSP_MAXPIPES]; - /* Positions for ea. ch. 0x160 32*4 */ - volatile s8 vu_meter[DSP_MAXPIPES]; - /* VU meters 0x1e0 32*1 */ - volatile s8 peak_meter[DSP_MAXPIPES]; - /* Peak meters 0x200 32*1 */ - s8 line_out_level[DSP_MAXAUDIOOUTPUTS]; - /* Output gain 0x220 16*1 */ - s8 line_in_level[DSP_MAXAUDIOINPUTS]; - /* Input gain 0x230 16*1 */ - s8 monitors[MONITOR_ARRAY_SIZE]; - /* Monitor map 0x240 0x180 */ - u32 play_coeff[MAX_PLAY_TAPS]; - /* Gina/Darla play filters - obsolete 0x3c0 168*4 */ - u32 rec_coeff[MAX_REC_TAPS]; - /* Gina/Darla record filters - obsolete 0x660 192*4 */ - volatile u16 midi_input[MIDI_IN_BUFFER_SIZE]; - /* MIDI input data transfer buffer 0x960 256*2 */ - u8 gd_clock_state; /* Chg Gina/Darla clock state 0xb60 1 */ - u8 gd_spdif_status; /* Chg. Gina/Darla S/PDIF state 0xb61 1 */ - u8 gd_resampler_state; /* Should always be 3 0xb62 1 */ - u8 filler2; /* 0xb63 1 */ - u32 nominal_level_mask; /* -10 level enable mask 0xb64 4 */ - u16 input_clock; /* Chg. Input clock state 0xb68 2 */ - u16 output_clock; /* Chg. Output clock state 0xb6a 2 */ - volatile u32 status_clocks; - /* Current Input clock state 0xb6c 4 */ - u32 ext_box_status; /* External box status 0xb70 4 */ - u32 cmd_add_buffer; /* Pipes to add (obsolete) 0xb74 4 */ - volatile u32 midi_out_free_count; - /* # of bytes free in MIDI output FIFO 0xb78 4 */ - u32 unused2; /* Cyclic pipes 0xb7c 4 */ - u32 control_register; - /* Mona, Gina24, Layla24, 3G ctrl reg 0xb80 4 */ - u32 e3g_frq_register; /* 3G frequency register 0xb84 4 */ - u8 filler[24]; /* filler 0xb88 24*1 */ - s8 vmixer[VMIXER_ARRAY_SIZE]; - /* Vmixer levels 0xba0 64*1 */ - u8 midi_output[MIDI_OUT_BUFFER_SIZE]; - /* MIDI output data 0xbe0 32*1 */ -}; - -#endif /* _ECHO_DSP_ */ diff --git a/trunk/sound/pci/echoaudio/echoaudio_gml.c b/trunk/sound/pci/echoaudio/echoaudio_gml.c deleted file mode 100644 index 3aa37e76ebab..000000000000 --- a/trunk/sound/pci/echoaudio/echoaudio_gml.c +++ /dev/null @@ -1,198 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -/* These functions are common for Gina24, Layla24 and Mona cards */ - - -/* ASIC status check - some cards have one or two ASICs that need to be -loaded. Once that load is complete, this function is called to see if -the load was successful. -If this load fails, it does not necessarily mean that the hardware is -defective - the external box may be disconnected or turned off. */ -static int check_asic_status(struct echoaudio *chip) -{ - u32 asic_status; - - send_vector(chip, DSP_VC_TEST_ASIC); - - /* The DSP will return a value to indicate whether or not the - ASIC is currently loaded */ - if (read_dsp(chip, &asic_status) < 0) { - DE_INIT(("check_asic_status: failed on read_dsp\n")); - chip->asic_loaded = FALSE; - return -EIO; - } - - chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED); - return chip->asic_loaded ? 0 : -EIO; -} - - - -/* Most configuration of Gina24, Layla24, or Mona is accomplished by writing -the control register. write_control_reg sends the new control register -value to the DSP. */ -static int write_control_reg(struct echoaudio *chip, u32 value, char force) -{ - /* Handle the digital input auto-mute */ - if (chip->digital_in_automute) - value |= GML_DIGITAL_IN_AUTO_MUTE; - else - value &= ~GML_DIGITAL_IN_AUTO_MUTE; - - DE_ACT(("write_control_reg: 0x%x\n", value)); - - /* Write the control register */ - value = cpu_to_le32(value); - if (value != chip->comm_page->control_register || force) { - if (wait_handshake(chip)) - return -EIO; - chip->comm_page->control_register = value; - clear_handshake(chip); - return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); - } - return 0; -} - - - -/* Gina24, Layla24, and Mona support digital input auto-mute. If the digital -input auto-mute is enabled, the DSP will only enable the digital inputs if -the card is syncing to a valid clock on the ADAT or S/PDIF inputs. -If the auto-mute is disabled, the digital inputs are enabled regardless of -what the input clock is set or what is connected. */ -static int set_input_auto_mute(struct echoaudio *chip, int automute) -{ - DE_ACT(("set_input_auto_mute %d\n", automute)); - - chip->digital_in_automute = automute; - - /* Re-set the input clock to the current value - indirectly causes - the auto-mute flag to be sent to the DSP */ - return set_input_clock(chip, chip->input_clock); -} - - - -/* S/PDIF coax / S/PDIF optical / ADAT - switch */ -static int set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u8 previous_mode; - int err, i, o; - - if (chip->bad_board) - return -EIO; - - /* All audio channels must be closed before changing the digital mode */ - snd_assert(!chip->pipe_alloc_mask, return -EAGAIN); - - snd_assert(chip->digital_modes & (1 << mode), return -EINVAL); - - previous_mode = chip->digital_mode; - err = dsp_set_digital_mode(chip, mode); - - /* If we successfully changed the digital mode from or to ADAT, - then make sure all output, input and monitor levels are - updated by the DSP comm object. */ - if (err >= 0 && previous_mode != mode && - (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { - spin_lock_irq(&chip->lock); - for (o = 0; o < num_busses_out(chip); o++) - for (i = 0; i < num_busses_in(chip); i++) - set_monitor_gain(chip, o, i, - chip->monitor_gain[o][i]); - -#ifdef ECHOCARD_HAS_INPUT_GAIN - for (i = 0; i < num_busses_in(chip); i++) - set_input_gain(chip, i, chip->input_gain[i]); - update_input_line_level(chip); -#endif - - for (o = 0; o < num_busses_out(chip); o++) - set_output_gain(chip, o, chip->output_gain[o]); - update_output_line_level(chip); - spin_unlock_irq(&chip->lock); - } - - return err; -} - - - -/* Set the S/PDIF output format */ -static int set_professional_spdif(struct echoaudio *chip, char prof) -{ - u32 control_reg; - int err; - - /* Clear the current S/PDIF flags */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_SPDIF_FORMAT_CLEAR_MASK; - - /* Set the new S/PDIF flags depending on the mode */ - control_reg |= GML_SPDIF_TWO_CHANNEL | GML_SPDIF_24_BIT | - GML_SPDIF_COPY_PERMIT; - if (prof) { - /* Professional mode */ - control_reg |= GML_SPDIF_PRO_MODE; - - switch (chip->sample_rate) { - case 32000: - control_reg |= GML_SPDIF_SAMPLE_RATE0 | - GML_SPDIF_SAMPLE_RATE1; - break; - case 44100: - control_reg |= GML_SPDIF_SAMPLE_RATE0; - break; - case 48000: - control_reg |= GML_SPDIF_SAMPLE_RATE1; - break; - } - } else { - /* Consumer mode */ - switch (chip->sample_rate) { - case 32000: - control_reg |= GML_SPDIF_SAMPLE_RATE0 | - GML_SPDIF_SAMPLE_RATE1; - break; - case 48000: - control_reg |= GML_SPDIF_SAMPLE_RATE1; - break; - } - } - - if ((err = write_control_reg(chip, control_reg, FALSE))) - return err; - chip->professional_spdif = prof; - DE_ACT(("set_professional_spdif to %s\n", - prof ? "Professional" : "Consumer")); - return 0; -} diff --git a/trunk/sound/pci/echoaudio/gina20.c b/trunk/sound/pci/echoaudio/gina20.c deleted file mode 100644 index 29d6d12f80ca..000000000000 --- a/trunk/sound/pci/echoaudio/gina20.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define ECHOGALS_FAMILY -#define ECHOCARD_GINA20 -#define ECHOCARD_NAME "Gina20" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_INPUT_GAIN -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT FALSE - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 2 */ -#define PX_ANALOG_IN 10 /* 2 */ -#define PX_DIGITAL_IN 12 /* 2 */ -#define PX_NUM 14 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 8 */ -#define BX_DIGITAL_OUT 8 /* 2 */ -#define BX_ANALOG_IN 10 /* 2 */ -#define BX_DIGITAL_IN 12 /* 2 */ -#define BX_NUM 14 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_GINA20_DSP 0 - -static const struct firmware card_fw[] = { - {0, "gina20_dsp.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0020, 0, 0, 0}, /* DSP 56301 Gina20 rev.0 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, - .rate_min = 44100, - .rate_max = 48000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "gina20_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" diff --git a/trunk/sound/pci/echoaudio/gina20_dsp.c b/trunk/sound/pci/echoaudio/gina20_dsp.c deleted file mode 100644 index 2757c8960843..000000000000 --- a/trunk/sound/pci/echoaudio/gina20_dsp.c +++ /dev/null @@ -1,215 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int update_flags(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Gina20\n")); - snd_assert((subdevice_id & 0xfff0) == GINA20, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = &card_fw[FW_GINA20_DSP]; - chip->spdif_status = GD_SPDIF_STATUS_UNDEF; - chip->clock_state = GD_CLOCK_UNDEF; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | - ECHO_CLOCK_BIT_SPDIF; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - - err = set_professional_spdif(chip, TRUE); - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - return clock_bits; -} - - - -/* The Gina20 has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u8 clock_state, spdif_status; - - if (wait_handshake(chip)) - return -EIO; - - switch (rate) { - case 44100: - clock_state = GD_CLOCK_44; - spdif_status = GD_SPDIF_STATUS_44; - break; - case 48000: - clock_state = GD_CLOCK_48; - spdif_status = GD_SPDIF_STATUS_48; - break; - default: - clock_state = GD_CLOCK_NOCHANGE; - spdif_status = GD_SPDIF_STATUS_NOCHANGE; - break; - } - - if (chip->clock_state == clock_state) - clock_state = GD_CLOCK_NOCHANGE; - if (spdif_status == chip->spdif_status) - spdif_status = GD_SPDIF_STATUS_NOCHANGE; - - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->comm_page->gd_clock_state = clock_state; - chip->comm_page->gd_spdif_status = spdif_status; - chip->comm_page->gd_resampler_state = 3; /* magic number - should always be 3 */ - - /* Save the new audio state if it changed */ - if (clock_state != GD_CLOCK_NOCHANGE) - chip->clock_state = clock_state; - if (spdif_status != GD_SPDIF_STATUS_NOCHANGE) - chip->spdif_status = spdif_status; - chip->sample_rate = rate; - - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - DE_ACT(("set_input_clock:\n")); - - switch (clock) { - case ECHO_CLOCK_INTERNAL: - /* Reset the audio state to unknown (just in case) */ - chip->clock_state = GD_CLOCK_UNDEF; - chip->spdif_status = GD_SPDIF_STATUS_UNDEF; - set_sample_rate(chip, chip->sample_rate); - chip->input_clock = clock; - DE_ACT(("Set Gina clock to INTERNAL\n")); - break; - case ECHO_CLOCK_SPDIF: - chip->comm_page->gd_clock_state = GD_CLOCK_SPDIFIN; - chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_NOCHANGE; - clear_handshake(chip); - send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); - chip->clock_state = GD_CLOCK_SPDIFIN; - DE_ACT(("Set Gina20 clock to SPDIF\n")); - chip->input_clock = clock; - break; - default: - return -EINVAL; - } - - return 0; -} - - - -/* Set input bus gain (one unit is 0.5dB !) */ -static int set_input_gain(struct echoaudio *chip, u16 input, int gain) -{ - snd_assert(input < num_busses_in(chip), return -EINVAL); - - if (wait_handshake(chip)) - return -EIO; - - chip->input_gain[input] = gain; - gain += GL20_INPUT_GAIN_MAGIC_NUMBER; - chip->comm_page->line_in_level[input] = gain; - return 0; -} - - - -/* Tell the DSP to reread the flags from the comm page */ -static int update_flags(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_FLAGS); -} - - - -static int set_professional_spdif(struct echoaudio *chip, char prof) -{ - DE_ACT(("set_professional_spdif %d\n", prof)); - if (prof) - chip->comm_page->flags |= - __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - else - chip->comm_page->flags &= - ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - chip->professional_spdif = prof; - return update_flags(chip); -} diff --git a/trunk/sound/pci/echoaudio/gina24.c b/trunk/sound/pci/echoaudio/gina24.c deleted file mode 100644 index e464d720d0bd..000000000000 --- a/trunk/sound/pci/echoaudio/gina24.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define ECHO24_FAMILY -#define ECHOCARD_GINA24 -#define ECHOCARD_NAME "Gina24" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_ASIC -#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE -#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT 6 -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 8 */ -#define PX_ANALOG_IN 16 /* 2 */ -#define PX_DIGITAL_IN 18 /* 8 */ -#define PX_NUM 26 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 8 */ -#define BX_DIGITAL_OUT 8 /* 8 */ -#define BX_ANALOG_IN 16 /* 2 */ -#define BX_DIGITAL_IN 18 /* 8 */ -#define BX_NUM 26 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_361_LOADER 0 -#define FW_GINA24_301_DSP 1 -#define FW_GINA24_361_DSP 2 -#define FW_GINA24_301_ASIC 3 -#define FW_GINA24_361_ASIC 4 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "gina24_301_dsp.fw"}, - {0, "gina24_361_dsp.fw"}, - {0, "gina24_301_asic.fw"}, - {0, "gina24_361_asic.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56301 Gina24 rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56301 Gina24 rev.1 */ - {0x1057, 0x3410, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56361 Gina24 rev.0 */ - {0x1057, 0x3410, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56361 Gina24 rev.1 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_8000_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. - 220 ~= (512 - 1 - (BUFFER_BYTES_MAX / PAGE_SIZE)) / 2 */ -}; - -#include "gina24_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio_gml.c" -#include "echoaudio.c" diff --git a/trunk/sound/pci/echoaudio/gina24_dsp.c b/trunk/sound/pci/echoaudio/gina24_dsp.c deleted file mode 100644 index 144fc567becf..000000000000 --- a/trunk/sound/pci/echoaudio/gina24_dsp.c +++ /dev/null @@ -1,346 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int write_control_reg(struct echoaudio *chip, u32 value, char force); -static int set_input_clock(struct echoaudio *chip, u16 clock); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int set_digital_mode(struct echoaudio *chip, u8 mode); -static int load_asic_generic(struct echoaudio *chip, u32 cmd, - const struct firmware *asic); -static int check_asic_status(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Gina24\n")); - snd_assert((subdevice_id & 0xfff0) == GINA24, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->input_clock_types = - ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96 | - ECHO_CLOCK_BIT_ADAT; - chip->professional_spdif = FALSE; - chip->digital_in_automute = TRUE; - chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - - /* Gina24 comes in both '301 and '361 flavors */ - if (chip->device_id == DEVICE_ID_56361) { - chip->dsp_code_to_load = &card_fw[FW_GINA24_361_DSP]; - chip->digital_modes = - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | - ECHOCAPS_HAS_DIGITAL_MODE_ADAT; - } else { - chip->dsp_code_to_load = &card_fw[FW_GINA24_301_DSP]; - chip->digital_modes = - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | - ECHOCAPS_HAS_DIGITAL_MODE_ADAT | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM; - } - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); - snd_assert(err >= 0, return err); - err = set_professional_spdif(chip, TRUE); - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT) - clock_bits |= ECHO_CLOCK_BIT_ADAT; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ESYNC) - clock_bits |= ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96; - - return clock_bits; -} - - - -/* Gina24 has an ASIC on the PCI card which must be loaded for anything -interesting to happen. */ -static int load_asic(struct echoaudio *chip) -{ - u32 control_reg; - int err; - const struct firmware *fw; - - if (chip->asic_loaded) - return 1; - - /* Give the DSP a few milliseconds to settle down */ - mdelay(10); - - /* Pick the correct ASIC for '301 or '361 Gina24 */ - if (chip->device_id == DEVICE_ID_56361) - fw = &card_fw[FW_GINA24_361_ASIC]; - else - fw = &card_fw[FW_GINA24_301_ASIC]; - - if ((err = load_asic_generic(chip, DSP_FNC_LOAD_GINA24_ASIC, fw)) < 0) - return err; - - chip->asic_code = fw; - - /* Now give the new ASIC a little time to set up */ - mdelay(10); - /* See if it worked */ - err = check_asic_status(chip); - - /* Set up the control register if the load succeeded - - 48 kHz, internal clock, S/PDIF RCA mode */ - if (!err) { - control_reg = GML_CONVERTER_ENABLE | GML_48KHZ; - err = write_control_reg(chip, control_reg, TRUE); - } - DE_INIT(("load_asic() done\n")); - return err; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg, clock; - - snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT, - return -EINVAL); - - /* Only set the clock for internal mode. */ - if (chip->input_clock != ECHO_CLOCK_INTERNAL) { - DE_ACT(("set_sample_rate: Cannot set sample rate - " - "clock not set to CLK_CLOCKININTERNAL\n")); - /* Save the rate anyhow */ - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->sample_rate = rate; - return 0; - } - - clock = 0; - - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK; - - switch (rate) { - case 96000: - clock = GML_96KHZ; - break; - case 88200: - clock = GML_88KHZ; - break; - case 48000: - clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1; - break; - case 44100: - clock = GML_44KHZ; - /* Professional mode ? */ - if (control_reg & GML_SPDIF_PRO_MODE) - clock |= GML_SPDIF_SAMPLE_RATE0; - break; - case 32000: - clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 | - GML_SPDIF_SAMPLE_RATE1; - break; - case 22050: - clock = GML_22KHZ; - break; - case 16000: - clock = GML_16KHZ; - break; - case 11025: - clock = GML_11KHZ; - break; - case 8000: - clock = GML_8KHZ; - break; - default: - DE_ACT(("set_sample_rate: %d invalid!\n", rate)); - return -EINVAL; - } - - control_reg |= clock; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->sample_rate = rate; - DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock)); - - return write_control_reg(chip, control_reg, FALSE); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - u32 control_reg, clocks_from_dsp; - - DE_ACT(("set_input_clock:\n")); - - /* Mask off the clock select bits */ - control_reg = le32_to_cpu(chip->comm_page->control_register) & - GML_CLOCK_CLEAR_MASK; - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - switch (clock) { - case ECHO_CLOCK_INTERNAL: - DE_ACT(("Set Gina24 clock to INTERNAL\n")); - chip->input_clock = ECHO_CLOCK_INTERNAL; - return set_sample_rate(chip, chip->sample_rate); - case ECHO_CLOCK_SPDIF: - if (chip->digital_mode == DIGITAL_MODE_ADAT) - return -EAGAIN; - DE_ACT(("Set Gina24 clock to SPDIF\n")); - control_reg |= GML_SPDIF_CLOCK; - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96) - control_reg |= GML_DOUBLE_SPEED_MODE; - else - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_ADAT: - if (chip->digital_mode != DIGITAL_MODE_ADAT) - return -EAGAIN; - DE_ACT(("Set Gina24 clock to ADAT\n")); - control_reg |= GML_ADAT_CLOCK; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_ESYNC: - DE_ACT(("Set Gina24 clock to ESYNC\n")); - control_reg |= GML_ESYNC_CLOCK; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_ESYNC96: - DE_ACT(("Set Gina24 clock to ESYNC96\n")); - control_reg |= GML_ESYNC_CLOCK | GML_DOUBLE_SPEED_MODE; - break; - default: - DE_ACT(("Input clock 0x%x not supported for Gina24\n", clock)); - return -EINVAL; - } - - chip->input_clock = clock; - return write_control_reg(chip, control_reg, TRUE); -} - - - -static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u32 control_reg; - int err, incompatible_clock; - - /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - case DIGITAL_MODE_SPDIF_CDROM: - case DIGITAL_MODE_SPDIF_RCA: - if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; - break; - case DIGITAL_MODE_ADAT: - if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; - break; - default: - DE_ACT(("Digital mode not supported: %d\n", mode)); - return -EINVAL; - } - - spin_lock_irq(&chip->lock); - - if (incompatible_clock) { /* Switch to 48KHz, internal */ - chip->sample_rate = 48000; - set_input_clock(chip, ECHO_CLOCK_INTERNAL); - } - - /* Clear the current digital mode */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_DIGITAL_MODE_CLEAR_MASK; - - /* Tweak the control reg */ - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - control_reg |= GML_SPDIF_OPTICAL_MODE; - break; - case DIGITAL_MODE_SPDIF_CDROM: - /* '361 Gina24 cards do not have the S/PDIF CD-ROM mode */ - if (chip->device_id == DEVICE_ID_56301) - control_reg |= GML_SPDIF_CDROM_MODE; - break; - case DIGITAL_MODE_SPDIF_RCA: - /* GML_SPDIF_OPTICAL_MODE bit cleared */ - break; - case DIGITAL_MODE_ADAT: - control_reg |= GML_ADAT_MODE; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - } - - err = write_control_reg(chip, control_reg, TRUE); - spin_unlock_irq(&chip->lock); - if (err < 0) - return err; - chip->digital_mode = mode; - - DE_ACT(("set_digital_mode to %d\n", chip->digital_mode)); - return incompatible_clock; -} diff --git a/trunk/sound/pci/echoaudio/indigo.c b/trunk/sound/pci/echoaudio/indigo.c deleted file mode 100644 index bfd2467099ac..000000000000 --- a/trunk/sound/pci/echoaudio/indigo.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define INDIGO_FAMILY -#define ECHOCARD_INDIGO -#define ECHOCARD_NAME "Indigo" -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_VMIXER -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 0 */ -#define PX_DIGITAL_IN 8 /* 0 */ -#define PX_NUM 8 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 2 */ -#define BX_DIGITAL_OUT 2 /* 0 */ -#define BX_ANALOG_IN 2 /* 0 */ -#define BX_DIGITAL_IN 2 /* 0 */ -#define BX_NUM 2 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_361_LOADER 0 -#define FW_INDIGO_DSP 1 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "indigo_dsp.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x0090, 0, 0, 0}, /* Indigo */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, -}; - -#include "indigo_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" - diff --git a/trunk/sound/pci/echoaudio/indigo_dsp.c b/trunk/sound/pci/echoaudio/indigo_dsp.c deleted file mode 100644 index d6ac7734609e..000000000000 --- a/trunk/sound/pci/echoaudio/indigo_dsp.c +++ /dev/null @@ -1,170 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain); -static int update_vmixer_level(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Indigo\n")); - snd_assert((subdevice_id & 0xfff0) == INDIGO, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = &card_fw[FW_INDIGO_DSP]; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - - /* Default routing of the virtual channels: all vchannels are routed - to the stereo output */ - set_vmixer_gain(chip, 0, 0, 0); - set_vmixer_gain(chip, 1, 1, 0); - set_vmixer_gain(chip, 0, 2, 0); - set_vmixer_gain(chip, 1, 3, 0); - set_vmixer_gain(chip, 0, 4, 0); - set_vmixer_gain(chip, 1, 5, 0); - set_vmixer_gain(chip, 0, 6, 0); - set_vmixer_gain(chip, 1, 7, 0); - err = update_vmixer_level(chip); - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - return ECHO_CLOCK_BIT_INTERNAL; -} - - - -/* The Indigo has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg; - - switch (rate) { - case 96000: - control_reg = MIA_96000; - break; - case 88200: - control_reg = MIA_88200; - break; - case 48000: - control_reg = MIA_48000; - break; - case 44100: - control_reg = MIA_44100; - break; - case 32000: - control_reg = MIA_32000; - break; - default: - DE_ACT(("set_sample_rate: %d invalid!\n", rate)); - return -EINVAL; - } - - /* Set the control register if it has changed */ - if (control_reg != le32_to_cpu(chip->comm_page->control_register)) { - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->comm_page->control_register = cpu_to_le32(control_reg); - chip->sample_rate = rate; - - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_CLOCKS); - } - return 0; -} - - - -/* This function routes the sound from a virtual channel to a real output */ -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain) -{ - int index; - - snd_assert(pipe < num_pipes_out(chip) && - output < num_busses_out(chip), return -EINVAL); - - if (wait_handshake(chip)) - return -EIO; - - chip->vmixer_gain[output][pipe] = gain; - index = output * num_pipes_out(chip) + pipe; - chip->comm_page->vmixer[index] = gain; - - DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); - return 0; -} - - - -/* Tell the DSP to read and update virtual mixer levels in comm page. */ -static int update_vmixer_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); -} - diff --git a/trunk/sound/pci/echoaudio/indigodj.c b/trunk/sound/pci/echoaudio/indigodj.c deleted file mode 100644 index 8ed7ff1fd875..000000000000 --- a/trunk/sound/pci/echoaudio/indigodj.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define INDIGO_FAMILY -#define ECHOCARD_INDIGO_DJ -#define ECHOCARD_NAME "Indigo DJ" -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_VMIXER -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 0 */ -#define PX_DIGITAL_IN 8 /* 0 */ -#define PX_NUM 8 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 4 */ -#define BX_DIGITAL_OUT 4 /* 0 */ -#define BX_ANALOG_IN 4 /* 0 */ -#define BX_DIGITAL_IN 4 /* 0 */ -#define BX_NUM 4 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_361_LOADER 0 -#define FW_INDIGO_DJ_DSP 1 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "indigo_dj_dsp.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x00B0, 0, 0, 0}, /* Indigo DJ*/ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 4, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, -}; - -#include "indigodj_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" - diff --git a/trunk/sound/pci/echoaudio/indigodj_dsp.c b/trunk/sound/pci/echoaudio/indigodj_dsp.c deleted file mode 100644 index 500e150b49fc..000000000000 --- a/trunk/sound/pci/echoaudio/indigodj_dsp.c +++ /dev/null @@ -1,170 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain); -static int update_vmixer_level(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Indigo DJ\n")); - snd_assert((subdevice_id & 0xfff0) == INDIGO_DJ, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = &card_fw[FW_INDIGO_DJ_DSP]; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - - /* Default routing of the virtual channels: vchannels 0-3 and - vchannels 4-7 are routed to real channels 0-4 */ - set_vmixer_gain(chip, 0, 0, 0); - set_vmixer_gain(chip, 1, 1, 0); - set_vmixer_gain(chip, 2, 2, 0); - set_vmixer_gain(chip, 3, 3, 0); - set_vmixer_gain(chip, 0, 4, 0); - set_vmixer_gain(chip, 1, 5, 0); - set_vmixer_gain(chip, 2, 6, 0); - set_vmixer_gain(chip, 3, 7, 0); - err = update_vmixer_level(chip); - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - return ECHO_CLOCK_BIT_INTERNAL; -} - - - -/* The IndigoDJ has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg; - - switch (rate) { - case 96000: - control_reg = MIA_96000; - break; - case 88200: - control_reg = MIA_88200; - break; - case 48000: - control_reg = MIA_48000; - break; - case 44100: - control_reg = MIA_44100; - break; - case 32000: - control_reg = MIA_32000; - break; - default: - DE_ACT(("set_sample_rate: %d invalid!\n", rate)); - return -EINVAL; - } - - /* Set the control register if it has changed */ - if (control_reg != le32_to_cpu(chip->comm_page->control_register)) { - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->comm_page->control_register = cpu_to_le32(control_reg); - chip->sample_rate = rate; - - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_CLOCKS); - } - return 0; -} - - - -/* This function routes the sound from a virtual channel to a real output */ -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain) -{ - int index; - - snd_assert(pipe < num_pipes_out(chip) && - output < num_busses_out(chip), return -EINVAL); - - if (wait_handshake(chip)) - return -EIO; - - chip->vmixer_gain[output][pipe] = gain; - index = output * num_pipes_out(chip) + pipe; - chip->comm_page->vmixer[index] = gain; - - DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); - return 0; -} - - - -/* Tell the DSP to read and update virtual mixer levels in comm page. */ -static int update_vmixer_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); -} - diff --git a/trunk/sound/pci/echoaudio/indigoio.c b/trunk/sound/pci/echoaudio/indigoio.c deleted file mode 100644 index a8788e959171..000000000000 --- a/trunk/sound/pci/echoaudio/indigoio.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define INDIGO_FAMILY -#define ECHOCARD_INDIGO_IO -#define ECHOCARD_NAME "Indigo IO" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_VMIXER -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 2 */ -#define PX_DIGITAL_IN 10 /* 0 */ -#define PX_NUM 10 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 2 */ -#define BX_DIGITAL_OUT 2 /* 0 */ -#define BX_ANALOG_IN 2 /* 2 */ -#define BX_DIGITAL_IN 4 /* 0 */ -#define BX_NUM 4 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_361_LOADER 0 -#define FW_INDIGO_IO_DSP 1 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "indigo_io_dsp.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x00A0, 0, 0, 0}, /* Indigo IO*/ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 32000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, -}; - -#include "indigoio_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" - diff --git a/trunk/sound/pci/echoaudio/indigoio_dsp.c b/trunk/sound/pci/echoaudio/indigoio_dsp.c deleted file mode 100644 index f3ad13d06be0..000000000000 --- a/trunk/sound/pci/echoaudio/indigoio_dsp.c +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain); -static int update_vmixer_level(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Indigo IO\n")); - snd_assert((subdevice_id & 0xfff0) == INDIGO_IO, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = &card_fw[FW_INDIGO_IO_DSP]; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - - /* Default routing of the virtual channels: all vchannels are routed - to the stereo output */ - set_vmixer_gain(chip, 0, 0, 0); - set_vmixer_gain(chip, 1, 1, 0); - set_vmixer_gain(chip, 0, 2, 0); - set_vmixer_gain(chip, 1, 3, 0); - set_vmixer_gain(chip, 0, 4, 0); - set_vmixer_gain(chip, 1, 5, 0); - set_vmixer_gain(chip, 0, 6, 0); - set_vmixer_gain(chip, 1, 7, 0); - err = update_vmixer_level(chip); - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - return ECHO_CLOCK_BIT_INTERNAL; -} - - - -/* The IndigoIO has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - if (wait_handshake(chip)) - return -EIO; - - chip->sample_rate = rate; - chip->comm_page->sample_rate = cpu_to_le32(rate); - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_CLOCKS); -} - - - -/* This function routes the sound from a virtual channel to a real output */ -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain) -{ - int index; - - snd_assert(pipe < num_pipes_out(chip) && - output < num_busses_out(chip), return -EINVAL); - - if (wait_handshake(chip)) - return -EIO; - - chip->vmixer_gain[output][pipe] = gain; - index = output * num_pipes_out(chip) + pipe; - chip->comm_page->vmixer[index] = gain; - - DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); - return 0; -} - - - -/* Tell the DSP to read and update virtual mixer levels in comm page. */ -static int update_vmixer_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); -} - diff --git a/trunk/sound/pci/echoaudio/layla20.c b/trunk/sound/pci/echoaudio/layla20.c deleted file mode 100644 index e503d74b3ba9..000000000000 --- a/trunk/sound/pci/echoaudio/layla20.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define ECHOGALS_FAMILY -#define ECHOCARD_LAYLA20 -#define ECHOCARD_NAME "Layla20" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_ASIC -#define ECHOCARD_HAS_INPUT_GAIN -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT FALSE -#define ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH -#define ECHOCARD_HAS_MIDI - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 10 */ -#define PX_DIGITAL_OUT 10 /* 2 */ -#define PX_ANALOG_IN 12 /* 8 */ -#define PX_DIGITAL_IN 20 /* 2 */ -#define PX_NUM 22 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 10 */ -#define BX_DIGITAL_OUT 10 /* 2 */ -#define BX_ANALOG_IN 12 /* 8 */ -#define BX_DIGITAL_IN 20 /* 2 */ -#define BX_NUM 22 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_LAYLA20_DSP 0 -#define FW_LAYLA20_ASIC 1 - -static const struct firmware card_fw[] = { - {0, "layla20_dsp.fw"}, - {0, "layla20_asic.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0030, 0, 0, 0}, /* DSP 56301 Layla20 rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0031, 0, 0, 0}, /* DSP 56301 Layla20 rev.1 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_CONTINUOUS, - .rate_min = 8000, - .rate_max = 50000, - .channels_min = 1, - .channels_max = 10, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - -#include "layla20_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" -#include "midi.c" diff --git a/trunk/sound/pci/echoaudio/layla20_dsp.c b/trunk/sound/pci/echoaudio/layla20_dsp.c deleted file mode 100644 index 990c9a60a0a8..000000000000 --- a/trunk/sound/pci/echoaudio/layla20_dsp.c +++ /dev/null @@ -1,290 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int read_dsp(struct echoaudio *chip, u32 *data); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int load_asic_generic(struct echoaudio *chip, u32 cmd, - const struct firmware *asic); -static int check_asic_status(struct echoaudio *chip); -static int update_flags(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Layla20\n")); - snd_assert((subdevice_id & 0xfff0) == LAYLA20, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->has_midi = TRUE; - chip->dsp_code_to_load = &card_fw[FW_LAYLA20_DSP]; - chip->input_clock_types = - ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER; - chip->output_clock_types = - ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - - err = set_professional_spdif(chip, TRUE); - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_WORD) { - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SUPER) - clock_bits |= ECHO_CLOCK_BIT_SUPER; - else - clock_bits |= ECHO_CLOCK_BIT_WORD; - } - - return clock_bits; -} - - - -/* ASIC status check - some cards have one or two ASICs that need to be -loaded. Once that load is complete, this function is called to see if -the load was successful. -If this load fails, it does not necessarily mean that the hardware is -defective - the external box may be disconnected or turned off. -This routine sometimes fails for Layla20; for Layla20, the loop runs -5 times and succeeds if it wins on three of the loops. */ -static int check_asic_status(struct echoaudio *chip) -{ - u32 asic_status; - int goodcnt, i; - - chip->asic_loaded = FALSE; - for (i = goodcnt = 0; i < 5; i++) { - send_vector(chip, DSP_VC_TEST_ASIC); - - /* The DSP will return a value to indicate whether or not - the ASIC is currently loaded */ - if (read_dsp(chip, &asic_status) < 0) { - DE_ACT(("check_asic_status: failed on read_dsp\n")); - return -EIO; - } - - if (asic_status == ASIC_ALREADY_LOADED) { - if (++goodcnt == 3) { - chip->asic_loaded = TRUE; - return 0; - } - } - } - return -EIO; -} - - - -/* Layla20 has an ASIC in the external box */ -static int load_asic(struct echoaudio *chip) -{ - int err; - - if (chip->asic_loaded) - return 0; - - err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA_ASIC, - &card_fw[FW_LAYLA20_ASIC]); - if (err < 0) - return err; - - /* Check if ASIC is alive and well. */ - return check_asic_status(chip); -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - snd_assert(rate >= 8000 && rate <= 50000, return -EINVAL); - - /* Only set the clock for internal mode. Do not return failure, - simply treat it as a non-event. */ - if (chip->input_clock != ECHO_CLOCK_INTERNAL) { - DE_ACT(("set_sample_rate: Cannot set sample rate - " - "clock not set to CLK_CLOCKININTERNAL\n")); - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->sample_rate = rate; - return 0; - } - - if (wait_handshake(chip)) - return -EIO; - - DE_ACT(("set_sample_rate(%d)\n", rate)); - chip->sample_rate = rate; - chip->comm_page->sample_rate = cpu_to_le32(rate); - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_LAYLA_SAMPLE_RATE); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock_source) -{ - u16 clock; - u32 rate; - - DE_ACT(("set_input_clock:\n")); - rate = 0; - switch (clock_source) { - case ECHO_CLOCK_INTERNAL: - DE_ACT(("Set Layla20 clock to INTERNAL\n")); - rate = chip->sample_rate; - clock = LAYLA20_CLOCK_INTERNAL; - break; - case ECHO_CLOCK_SPDIF: - DE_ACT(("Set Layla20 clock to SPDIF\n")); - clock = LAYLA20_CLOCK_SPDIF; - break; - case ECHO_CLOCK_WORD: - DE_ACT(("Set Layla20 clock to WORD\n")); - clock = LAYLA20_CLOCK_WORD; - break; - case ECHO_CLOCK_SUPER: - DE_ACT(("Set Layla20 clock to SUPER\n")); - clock = LAYLA20_CLOCK_SUPER; - break; - default: - DE_ACT(("Input clock 0x%x not supported for Layla24\n", - clock_source)); - return -EINVAL; - } - chip->input_clock = clock_source; - - chip->comm_page->input_clock = cpu_to_le16(clock); - clear_handshake(chip); - send_vector(chip, DSP_VC_UPDATE_CLOCKS); - - if (rate) - set_sample_rate(chip, rate); - - return 0; -} - - - -static int set_output_clock(struct echoaudio *chip, u16 clock) -{ - DE_ACT(("set_output_clock: %d\n", clock)); - switch (clock) { - case ECHO_CLOCK_SUPER: - clock = LAYLA20_OUTPUT_CLOCK_SUPER; - break; - case ECHO_CLOCK_WORD: - clock = LAYLA20_OUTPUT_CLOCK_WORD; - break; - default: - DE_ACT(("set_output_clock wrong clock\n")); - return -EINVAL; - } - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->output_clock = cpu_to_le16(clock); - chip->output_clock = clock; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_CLOCKS); -} - - - -/* Set input bus gain (one unit is 0.5dB !) */ -static int set_input_gain(struct echoaudio *chip, u16 input, int gain) -{ - snd_assert(input < num_busses_in(chip), return -EINVAL); - - if (wait_handshake(chip)) - return -EIO; - - chip->input_gain[input] = gain; - gain += GL20_INPUT_GAIN_MAGIC_NUMBER; - chip->comm_page->line_in_level[input] = gain; - return 0; -} - - - -/* Tell the DSP to reread the flags from the comm page */ -static int update_flags(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_FLAGS); -} - - - -static int set_professional_spdif(struct echoaudio *chip, char prof) -{ - DE_ACT(("set_professional_spdif %d\n", prof)); - if (prof) - chip->comm_page->flags |= - __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - else - chip->comm_page->flags &= - ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - chip->professional_spdif = prof; - return update_flags(chip); -} diff --git a/trunk/sound/pci/echoaudio/layla24.c b/trunk/sound/pci/echoaudio/layla24.c deleted file mode 100644 index d4581fdc841c..000000000000 --- a/trunk/sound/pci/echoaudio/layla24.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define ECHO24_FAMILY -#define ECHOCARD_LAYLA24 -#define ECHOCARD_NAME "Layla24" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_ASIC -#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE -#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT 6 -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 -#define ECHOCARD_HAS_MIDI - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 8 */ -#define PX_ANALOG_IN 16 /* 8 */ -#define PX_DIGITAL_IN 24 /* 8 */ -#define PX_NUM 32 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 8 */ -#define BX_DIGITAL_OUT 8 /* 8 */ -#define BX_ANALOG_IN 16 /* 8 */ -#define BX_DIGITAL_IN 24 /* 8 */ -#define BX_NUM 32 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_361_LOADER 0 -#define FW_LAYLA24_DSP 1 -#define FW_LAYLA24_1_ASIC 2 -#define FW_LAYLA24_2A_ASIC 3 -#define FW_LAYLA24_2S_ASIC 4 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "layla24_dsp.fw"}, - {0, "layla24_1_asic.fw"}, - {0, "layla24_2A_asic.fw"}, - {0, "layla24_2S_asic.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x0060, 0, 0, 0}, /* DSP 56361 Layla24 rev.0 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_8000_96000, - .rate_min = 8000, - .rate_max = 100000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "layla24_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio_gml.c" -#include "echoaudio.c" -#include "midi.c" diff --git a/trunk/sound/pci/echoaudio/layla24_dsp.c b/trunk/sound/pci/echoaudio/layla24_dsp.c deleted file mode 100644 index 7ec5b63d0dce..000000000000 --- a/trunk/sound/pci/echoaudio/layla24_dsp.c +++ /dev/null @@ -1,394 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int write_control_reg(struct echoaudio *chip, u32 value, char force); -static int set_input_clock(struct echoaudio *chip, u16 clock); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int set_digital_mode(struct echoaudio *chip, u8 mode); -static int load_asic_generic(struct echoaudio *chip, u32 cmd, - const struct firmware *asic); -static int check_asic_status(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Layla24\n")); - snd_assert((subdevice_id & 0xfff0) == LAYLA24, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->has_midi = TRUE; - chip->dsp_code_to_load = &card_fw[FW_LAYLA24_DSP]; - chip->input_clock_types = - ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT; - chip->digital_modes = - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | - ECHOCAPS_HAS_DIGITAL_MODE_ADAT; - chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - chip->professional_spdif = FALSE; - chip->digital_in_automute = TRUE; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - - err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); - snd_assert(err >= 0, return err); - err = set_professional_spdif(chip, TRUE); - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT) - clock_bits |= ECHO_CLOCK_BIT_ADAT; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD) - clock_bits |= ECHO_CLOCK_BIT_WORD; - - return clock_bits; -} - - - -/* Layla24 has an ASIC on the PCI card and another ASIC in the external box; -both need to be loaded. */ -static int load_asic(struct echoaudio *chip) -{ - int err; - - if (chip->asic_loaded) - return 1; - - DE_INIT(("load_asic\n")); - - /* Give the DSP a few milliseconds to settle down */ - mdelay(10); - - /* Load the ASIC for the PCI card */ - err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC, - &card_fw[FW_LAYLA24_1_ASIC]); - if (err < 0) - return err; - - chip->asic_code = &card_fw[FW_LAYLA24_2S_ASIC]; - - /* Now give the new ASIC a little time to set up */ - mdelay(10); - - /* Do the external one */ - err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC, - &card_fw[FW_LAYLA24_2S_ASIC]); - if (err < 0) - return FALSE; - - /* Now give the external ASIC a little time to set up */ - mdelay(10); - - /* See if it worked */ - err = check_asic_status(chip); - - /* Set up the control register if the load succeeded - - 48 kHz, internal clock, S/PDIF RCA mode */ - if (!err) - err = write_control_reg(chip, GML_CONVERTER_ENABLE | GML_48KHZ, - TRUE); - - DE_INIT(("load_asic() done\n")); - return err; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg, clock, base_rate; - - snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT, - return -EINVAL); - - /* Only set the clock for internal mode. */ - if (chip->input_clock != ECHO_CLOCK_INTERNAL) { - DE_ACT(("set_sample_rate: Cannot set sample rate - " - "clock not set to CLK_CLOCKININTERNAL\n")); - /* Save the rate anyhow */ - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->sample_rate = rate; - return 0; - } - - /* Get the control register & clear the appropriate bits */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK; - - clock = 0; - - switch (rate) { - case 96000: - clock = GML_96KHZ; - break; - case 88200: - clock = GML_88KHZ; - break; - case 48000: - clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1; - break; - case 44100: - clock = GML_44KHZ; - /* Professional mode */ - if (control_reg & GML_SPDIF_PRO_MODE) - clock |= GML_SPDIF_SAMPLE_RATE0; - break; - case 32000: - clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 | - GML_SPDIF_SAMPLE_RATE1; - break; - case 22050: - clock = GML_22KHZ; - break; - case 16000: - clock = GML_16KHZ; - break; - case 11025: - clock = GML_11KHZ; - break; - case 8000: - clock = GML_8KHZ; - break; - default: - /* If this is a non-standard rate, then the driver needs to - use Layla24's special "continuous frequency" mode */ - clock = LAYLA24_CONTINUOUS_CLOCK; - if (rate > 50000) { - base_rate = rate >> 1; - control_reg |= GML_DOUBLE_SPEED_MODE; - } else { - base_rate = rate; - } - - if (base_rate < 25000) - base_rate = 25000; - - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->sample_rate = - cpu_to_le32(LAYLA24_MAGIC_NUMBER / base_rate - 2); - - clear_handshake(chip); - send_vector(chip, DSP_VC_SET_LAYLA24_FREQUENCY_REG); - } - - control_reg |= clock; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP ? */ - chip->sample_rate = rate; - DE_ACT(("set_sample_rate: %d clock %d\n", rate, control_reg)); - - return write_control_reg(chip, control_reg, FALSE); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - u32 control_reg, clocks_from_dsp; - - /* Mask off the clock select bits */ - control_reg = le32_to_cpu(chip->comm_page->control_register) & - GML_CLOCK_CLEAR_MASK; - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - /* Pick the new clock */ - switch (clock) { - case ECHO_CLOCK_INTERNAL: - DE_ACT(("Set Layla24 clock to INTERNAL\n")); - chip->input_clock = ECHO_CLOCK_INTERNAL; - return set_sample_rate(chip, chip->sample_rate); - case ECHO_CLOCK_SPDIF: - if (chip->digital_mode == DIGITAL_MODE_ADAT) - return -EAGAIN; - control_reg |= GML_SPDIF_CLOCK; - /* Layla24 doesn't support 96KHz S/PDIF */ - control_reg &= ~GML_DOUBLE_SPEED_MODE; - DE_ACT(("Set Layla24 clock to SPDIF\n")); - break; - case ECHO_CLOCK_WORD: - control_reg |= GML_WORD_CLOCK; - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD96) - control_reg |= GML_DOUBLE_SPEED_MODE; - else - control_reg &= ~GML_DOUBLE_SPEED_MODE; - DE_ACT(("Set Layla24 clock to WORD\n")); - break; - case ECHO_CLOCK_ADAT: - if (chip->digital_mode != DIGITAL_MODE_ADAT) - return -EAGAIN; - control_reg |= GML_ADAT_CLOCK; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - DE_ACT(("Set Layla24 clock to ADAT\n")); - break; - default: - DE_ACT(("Input clock 0x%x not supported for Layla24\n", clock)); - return -EINVAL; - } - - chip->input_clock = clock; - return write_control_reg(chip, control_reg, TRUE); -} - - - -/* Depending on what digital mode you want, Layla24 needs different ASICs -loaded. This function checks the ASIC needed for the new mode and sees -if it matches the one already loaded. */ -static int switch_asic(struct echoaudio *chip, const struct firmware *asic) -{ - s8 *monitors; - - /* Check to see if this is already loaded */ - if (asic != chip->asic_code) { - monitors = kmalloc(MONITOR_ARRAY_SIZE, GFP_KERNEL); - if (! monitors) - return -ENOMEM; - - memcpy(monitors, chip->comm_page->monitors, MONITOR_ARRAY_SIZE); - memset(chip->comm_page->monitors, ECHOGAIN_MUTED, - MONITOR_ARRAY_SIZE); - - /* Load the desired ASIC */ - if (load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC, - asic) < 0) { - memcpy(chip->comm_page->monitors, monitors, - MONITOR_ARRAY_SIZE); - kfree(monitors); - return -EIO; - } - chip->asic_code = asic; - memcpy(chip->comm_page->monitors, monitors, MONITOR_ARRAY_SIZE); - kfree(monitors); - } - - return 0; -} - - - -static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u32 control_reg; - int err, incompatible_clock; - const struct firmware *asic; - - /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - case DIGITAL_MODE_SPDIF_RCA: - if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; - asic = &card_fw[FW_LAYLA24_2S_ASIC]; - break; - case DIGITAL_MODE_ADAT: - if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; - asic = &card_fw[FW_LAYLA24_2A_ASIC]; - break; - default: - DE_ACT(("Digital mode not supported: %d\n", mode)); - return -EINVAL; - } - - if (incompatible_clock) { /* Switch to 48KHz, internal */ - chip->sample_rate = 48000; - spin_lock_irq(&chip->lock); - set_input_clock(chip, ECHO_CLOCK_INTERNAL); - spin_unlock_irq(&chip->lock); - } - - /* switch_asic() can sleep */ - if (switch_asic(chip, asic) < 0) - return -EIO; - - spin_lock_irq(&chip->lock); - - /* Tweak the control register */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_DIGITAL_MODE_CLEAR_MASK; - - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - control_reg |= GML_SPDIF_OPTICAL_MODE; - break; - case DIGITAL_MODE_SPDIF_RCA: - /* GML_SPDIF_OPTICAL_MODE bit cleared */ - break; - case DIGITAL_MODE_ADAT: - control_reg |= GML_ADAT_MODE; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - } - - err = write_control_reg(chip, control_reg, TRUE); - spin_unlock_irq(&chip->lock); - if (err < 0) - return err; - chip->digital_mode = mode; - - DE_ACT(("set_digital_mode to %d\n", mode)); - return incompatible_clock; -} diff --git a/trunk/sound/pci/echoaudio/mia.c b/trunk/sound/pci/echoaudio/mia.c deleted file mode 100644 index be40c64263d2..000000000000 --- a/trunk/sound/pci/echoaudio/mia.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define ECHO24_FAMILY -#define ECHOCARD_MIA -#define ECHOCARD_NAME "Mia" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_VMIXER -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT FALSE -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 -#define ECHOCARD_HAS_MIDI - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 8 */ -#define PX_DIGITAL_OUT 8 /* 0 */ -#define PX_ANALOG_IN 8 /* 2 */ -#define PX_DIGITAL_IN 10 /* 2 */ -#define PX_NUM 12 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 2 */ -#define BX_DIGITAL_OUT 2 /* 2 */ -#define BX_ANALOG_IN 4 /* 2 */ -#define BX_DIGITAL_IN 6 /* 2 */ -#define BX_NUM 8 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_361_LOADER 0 -#define FW_MIA_DSP 1 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "mia_dsp.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x3410, 0xECC0, 0x0080, 0, 0, 0}, /* DSP 56361 Mia rev.0 */ - {0x1057, 0x3410, 0xECC0, 0x0081, 0, 0, 0}, /* DSP 56361 Mia rev.1 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_32000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "mia_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio.c" -#include "midi.c" diff --git a/trunk/sound/pci/echoaudio/mia_dsp.c b/trunk/sound/pci/echoaudio/mia_dsp.c deleted file mode 100644 index 891c70519096..000000000000 --- a/trunk/sound/pci/echoaudio/mia_dsp.c +++ /dev/null @@ -1,229 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int set_input_clock(struct echoaudio *chip, u16 clock); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int update_flags(struct echoaudio *chip); -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain); -static int update_vmixer_level(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Mia\n")); - snd_assert((subdevice_id & 0xfff0) == MIA, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->dsp_code_to_load = &card_fw[FW_MIA_DSP]; - /* Since this card has no ASIC, mark it as loaded so everything - works OK */ - chip->asic_loaded = TRUE; - if ((subdevice_id & 0x0000f) == MIA_MIDI_REV) - chip->has_midi = TRUE; - chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | - ECHO_CLOCK_BIT_SPDIF; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip))) - return err; - - /* Default routing of the virtual channels: vchannels 0-3 go to analog - outputs and vchannels 4-7 go to S/PDIF outputs */ - set_vmixer_gain(chip, 0, 0, 0); - set_vmixer_gain(chip, 1, 1, 0); - set_vmixer_gain(chip, 0, 2, 0); - set_vmixer_gain(chip, 1, 3, 0); - set_vmixer_gain(chip, 2, 4, 0); - set_vmixer_gain(chip, 3, 5, 0); - set_vmixer_gain(chip, 2, 6, 0); - set_vmixer_gain(chip, 3, 7, 0); - err = update_vmixer_level(chip); - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - return clock_bits; -} - - - -/* The Mia has no ASIC. Just do nothing */ -static int load_asic(struct echoaudio *chip) -{ - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg; - - switch (rate) { - case 96000: - control_reg = MIA_96000; - break; - case 88200: - control_reg = MIA_88200; - break; - case 48000: - control_reg = MIA_48000; - break; - case 44100: - control_reg = MIA_44100; - break; - case 32000: - control_reg = MIA_32000; - break; - default: - DE_ACT(("set_sample_rate: %d invalid!\n", rate)); - return -EINVAL; - } - - /* Override the clock setting if this Mia is set to S/PDIF clock */ - if (chip->input_clock == ECHO_CLOCK_SPDIF) - control_reg |= MIA_SPDIF; - - /* Set the control register if it has changed */ - if (control_reg != le32_to_cpu(chip->comm_page->control_register)) { - if (wait_handshake(chip)) - return -EIO; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->comm_page->control_register = cpu_to_le32(control_reg); - chip->sample_rate = rate; - - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_CLOCKS); - } - return 0; -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - DE_ACT(("set_input_clock(%d)\n", clock)); - snd_assert(clock == ECHO_CLOCK_INTERNAL || clock == ECHO_CLOCK_SPDIF, - return -EINVAL); - - chip->input_clock = clock; - return set_sample_rate(chip, chip->sample_rate); -} - - - -/* This function routes the sound from a virtual channel to a real output */ -static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, - int gain) -{ - int index; - - snd_assert(pipe < num_pipes_out(chip) && - output < num_busses_out(chip), return -EINVAL); - - if (wait_handshake(chip)) - return -EIO; - - chip->vmixer_gain[output][pipe] = gain; - index = output * num_pipes_out(chip) + pipe; - chip->comm_page->vmixer[index] = gain; - - DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); - return 0; -} - - - -/* Tell the DSP to read and update virtual mixer levels in comm page. */ -static int update_vmixer_level(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); -} - - - -/* Tell the DSP to reread the flags from the comm page */ -static int update_flags(struct echoaudio *chip) -{ - if (wait_handshake(chip)) - return -EIO; - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_FLAGS); -} - - - -static int set_professional_spdif(struct echoaudio *chip, char prof) -{ - DE_ACT(("set_professional_spdif %d\n", prof)); - if (prof) - chip->comm_page->flags |= - __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - else - chip->comm_page->flags &= - ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); - chip->professional_spdif = prof; - return update_flags(chip); -} - diff --git a/trunk/sound/pci/echoaudio/midi.c b/trunk/sound/pci/echoaudio/midi.c deleted file mode 100644 index e31f0f11e3a8..000000000000 --- a/trunk/sound/pci/echoaudio/midi.c +++ /dev/null @@ -1,327 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -/****************************************************************************** - MIDI lowlevel code -******************************************************************************/ - -/* Start and stop Midi input */ -static int enable_midi_input(struct echoaudio *chip, char enable) -{ - DE_MID(("enable_midi_input(%d)\n", enable)); - - if (wait_handshake(chip)) - return -EIO; - - if (enable) { - chip->mtc_state = MIDI_IN_STATE_NORMAL; - chip->comm_page->flags |= - __constant_cpu_to_le32(DSP_FLAG_MIDI_INPUT); - } else - chip->comm_page->flags &= - ~__constant_cpu_to_le32(DSP_FLAG_MIDI_INPUT); - - clear_handshake(chip); - return send_vector(chip, DSP_VC_UPDATE_FLAGS); -} - - - -/* Send a buffer full of MIDI data to the DSP -Returns how many actually written or < 0 on error */ -static int write_midi(struct echoaudio *chip, u8 *data, int bytes) -{ - snd_assert(bytes > 0 && bytes < MIDI_OUT_BUFFER_SIZE, return -EINVAL); - - if (wait_handshake(chip)) - return -EIO; - - /* HF4 indicates that it is safe to write MIDI output data */ - if (! (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4)) - return 0; - - chip->comm_page->midi_output[0] = bytes; - memcpy(&chip->comm_page->midi_output[1], data, bytes); - chip->comm_page->midi_out_free_count = 0; - clear_handshake(chip); - send_vector(chip, DSP_VC_MIDI_WRITE); - DE_MID(("write_midi: %d\n", bytes)); - return bytes; -} - - - -/* Run the state machine for MIDI input data -MIDI time code sync isn't supported by this code right now, but you still need -this state machine to parse the incoming MIDI data stream. Every time the DSP -sees a 0xF1 byte come in, it adds the DSP sample position to the MIDI data -stream. The DSP sample position is represented as a 32 bit unsigned value, -with the high 16 bits first, followed by the low 16 bits. Since these aren't -real MIDI bytes, the following logic is needed to skip them. */ -static inline int mtc_process_data(struct echoaudio *chip, short midi_byte) -{ - switch (chip->mtc_state) { - case MIDI_IN_STATE_NORMAL: - if (midi_byte == 0xF1) - chip->mtc_state = MIDI_IN_STATE_TS_HIGH; - break; - case MIDI_IN_STATE_TS_HIGH: - chip->mtc_state = MIDI_IN_STATE_TS_LOW; - return MIDI_IN_SKIP_DATA; - break; - case MIDI_IN_STATE_TS_LOW: - chip->mtc_state = MIDI_IN_STATE_F1_DATA; - return MIDI_IN_SKIP_DATA; - break; - case MIDI_IN_STATE_F1_DATA: - chip->mtc_state = MIDI_IN_STATE_NORMAL; - break; - } - return 0; -} - - - -/* This function is called from the IRQ handler and it reads the midi data -from the DSP's buffer. It returns the number of bytes received. */ -static int midi_service_irq(struct echoaudio *chip) -{ - short int count, midi_byte, i, received; - - /* The count is at index 0, followed by actual data */ - count = le16_to_cpu(chip->comm_page->midi_input[0]); - - snd_assert(count < MIDI_IN_BUFFER_SIZE, return 0); - - /* Get the MIDI data from the comm page */ - i = 1; - received = 0; - for (i = 1; i <= count; i++) { - /* Get the MIDI byte */ - midi_byte = le16_to_cpu(chip->comm_page->midi_input[i]); - - /* Parse the incoming MIDI stream. The incoming MIDI data - consists of MIDI bytes and timestamps for the MIDI time code - 0xF1 bytes. mtc_process_data() is a little state machine that - parses the stream. If you get MIDI_IN_SKIP_DATA back, then - this is a timestamp byte, not a MIDI byte, so don't store it - in the MIDI input buffer. */ - if (mtc_process_data(chip, midi_byte) == MIDI_IN_SKIP_DATA) - continue; - - chip->midi_buffer[received++] = (u8)midi_byte; - } - - return received; -} - - - - -/****************************************************************************** - MIDI interface -******************************************************************************/ - -static int snd_echo_midi_input_open(struct snd_rawmidi_substream *substream) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - chip->midi_in = substream; - DE_MID(("rawmidi_iopen\n")); - return 0; -} - - - -static void snd_echo_midi_input_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - if (up != chip->midi_input_enabled) { - spin_lock_irq(&chip->lock); - enable_midi_input(chip, up); - spin_unlock_irq(&chip->lock); - chip->midi_input_enabled = up; - } -} - - - -static int snd_echo_midi_input_close(struct snd_rawmidi_substream *substream) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - chip->midi_in = NULL; - DE_MID(("rawmidi_iclose\n")); - return 0; -} - - - -static int snd_echo_midi_output_open(struct snd_rawmidi_substream *substream) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - chip->tinuse = 0; - chip->midi_full = 0; - chip->midi_out = substream; - DE_MID(("rawmidi_oopen\n")); - return 0; -} - - - -static void snd_echo_midi_output_write(unsigned long data) -{ - struct echoaudio *chip = (struct echoaudio *)data; - unsigned long flags; - int bytes, sent, time; - unsigned char buf[MIDI_OUT_BUFFER_SIZE - 1]; - - DE_MID(("snd_echo_midi_output_write\n")); - /* No interrupts are involved: we have to check at regular intervals - if the card's output buffer has room for new data. */ - sent = bytes = 0; - spin_lock_irqsave(&chip->lock, flags); - chip->midi_full = 0; - if (chip->midi_out && !snd_rawmidi_transmit_empty(chip->midi_out)) { - bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf, - MIDI_OUT_BUFFER_SIZE - 1); - DE_MID(("Try to send %d bytes...\n", bytes)); - sent = write_midi(chip, buf, bytes); - if (sent < 0) { - snd_printk(KERN_ERR "write_midi() error %d\n", sent); - /* retry later */ - sent = 9000; - chip->midi_full = 1; - } else if (sent > 0) { - DE_MID(("%d bytes sent\n", sent)); - snd_rawmidi_transmit_ack(chip->midi_out, sent); - } else { - /* Buffer is full. DSP's internal buffer is 64 (128 ?) - bytes long. Let's wait until half of them are sent */ - DE_MID(("Full\n")); - sent = 32; - chip->midi_full = 1; - } - } - - /* We restart the timer only if there is some data left to send */ - if (!snd_rawmidi_transmit_empty(chip->midi_out) && chip->tinuse) { - /* The timer will expire slightly after the data has been - sent */ - time = (sent << 3) / 25 + 1; /* 8/25=0.32ms to send a byte */ - mod_timer(&chip->timer, jiffies + (time * HZ + 999) / 1000); - DE_MID(("Timer armed(%d)\n", ((time * HZ + 999) / 1000))); - } - spin_unlock_irqrestore(&chip->lock, flags); -} - - - -static void snd_echo_midi_output_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - DE_MID(("snd_echo_midi_output_trigger(%d)\n", up)); - spin_lock_irq(&chip->lock); - if (up) { - if (!chip->tinuse) { - init_timer(&chip->timer); - chip->timer.function = snd_echo_midi_output_write; - chip->timer.data = (unsigned long)chip; - chip->tinuse = 1; - } - } else { - if (chip->tinuse) { - del_timer(&chip->timer); - chip->tinuse = 0; - DE_MID(("Timer removed\n")); - } - } - spin_unlock_irq(&chip->lock); - - if (up && !chip->midi_full) - snd_echo_midi_output_write((unsigned long)chip); -} - - - -static int snd_echo_midi_output_close(struct snd_rawmidi_substream *substream) -{ - struct echoaudio *chip = substream->rmidi->private_data; - - chip->midi_out = NULL; - DE_MID(("rawmidi_oclose\n")); - return 0; -} - - - -static struct snd_rawmidi_ops snd_echo_midi_input = { - .open = snd_echo_midi_input_open, - .close = snd_echo_midi_input_close, - .trigger = snd_echo_midi_input_trigger, -}; - -static struct snd_rawmidi_ops snd_echo_midi_output = { - .open = snd_echo_midi_output_open, - .close = snd_echo_midi_output_close, - .trigger = snd_echo_midi_output_trigger, -}; - - - -/* <--snd_echo_probe() */ -static int __devinit snd_echo_midi_create(struct snd_card *card, - struct echoaudio *chip) -{ - int err; - - if ((err = snd_rawmidi_new(card, card->shortname, 0, 1, 1, - &chip->rmidi)) < 0) - return err; - - strcpy(chip->rmidi->name, card->shortname); - chip->rmidi->private_data = chip; - - snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_echo_midi_input); - snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_echo_midi_output); - - chip->rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; - DE_INIT(("MIDI ok\n")); - return 0; -} diff --git a/trunk/sound/pci/echoaudio/mona.c b/trunk/sound/pci/echoaudio/mona.c deleted file mode 100644 index 5dc512add372..000000000000 --- a/trunk/sound/pci/echoaudio/mona.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * ALSA driver for Echoaudio soundcards. - * Copyright (C) 2003-2004 Giuliano Pochini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#define ECHO24_FAMILY -#define ECHOCARD_MONA -#define ECHOCARD_NAME "Mona" -#define ECHOCARD_HAS_MONITOR -#define ECHOCARD_HAS_ASIC -#define ECHOCARD_HAS_SUPER_INTERLEAVE -#define ECHOCARD_HAS_DIGITAL_IO -#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE -#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH -#define ECHOCARD_HAS_EXTERNAL_CLOCK -#define ECHOCARD_HAS_ADAT 6 -#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 - -/* Pipe indexes */ -#define PX_ANALOG_OUT 0 /* 6 */ -#define PX_DIGITAL_OUT 6 /* 8 */ -#define PX_ANALOG_IN 14 /* 4 */ -#define PX_DIGITAL_IN 18 /* 8 */ -#define PX_NUM 26 - -/* Bus indexes */ -#define BX_ANALOG_OUT 0 /* 6 */ -#define BX_DIGITAL_OUT 6 /* 8 */ -#define BX_ANALOG_IN 14 /* 4 */ -#define BX_DIGITAL_IN 18 /* 8 */ -#define BX_NUM 26 - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "echoaudio.h" - -#define FW_361_LOADER 0 -#define FW_MONA_301_DSP 1 -#define FW_MONA_361_DSP 2 -#define FW_MONA_301_1_ASIC48 3 -#define FW_MONA_301_1_ASIC96 4 -#define FW_MONA_361_1_ASIC48 5 -#define FW_MONA_361_1_ASIC96 6 -#define FW_MONA_2_ASIC 7 - -static const struct firmware card_fw[] = { - {0, "loader_dsp.fw"}, - {0, "mona_301_dsp.fw"}, - {0, "mona_361_dsp.fw"}, - {0, "mona_301_1_asic_48.fw"}, - {0, "mona_301_1_asic_96.fw"}, - {0, "mona_361_1_asic_48.fw"}, - {0, "mona_361_1_asic_96.fw"}, - {0, "mona_2_asic.fw"} -}; - -static struct pci_device_id snd_echo_ids[] = { - {0x1057, 0x1801, 0xECC0, 0x0070, 0, 0, 0}, /* DSP 56301 Mona rev.0 */ - {0x1057, 0x1801, 0xECC0, 0x0071, 0, 0, 0}, /* DSP 56301 Mona rev.1 */ - {0x1057, 0x1801, 0xECC0, 0x0072, 0, 0, 0}, /* DSP 56301 Mona rev.2 */ - {0x1057, 0x3410, 0xECC0, 0x0070, 0, 0, 0}, /* DSP 56361 Mona rev.0 */ - {0x1057, 0x3410, 0xECC0, 0x0071, 0, 0, 0}, /* DSP 56361 Mona rev.1 */ - {0x1057, 0x3410, 0xECC0, 0x0072, 0, 0, 0}, /* DSP 56361 Mona rev.2 */ - {0,} -}; - -static struct snd_pcm_hardware pcm_hardware_skel = { - .info = SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_SYNC_START, - .formats = SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_3LE | - SNDRV_PCM_FMTBIT_S32_LE | - SNDRV_PCM_FMTBIT_S32_BE, - .rates = SNDRV_PCM_RATE_8000_48000 | - SNDRV_PCM_RATE_88200 | - SNDRV_PCM_RATE_96000, - .rate_min = 8000, - .rate_max = 96000, - .channels_min = 1, - .channels_max = 8, - .buffer_bytes_max = 262144, - .period_bytes_min = 32, - .period_bytes_max = 131072, - .periods_min = 2, - .periods_max = 220, - /* One page (4k) contains 512 instructions. I don't know if the hw - supports lists longer than this. In this case periods_max=220 is a - safe limit to make sure the list never exceeds 512 instructions. */ -}; - - -#include "mona_dsp.c" -#include "echoaudio_dsp.c" -#include "echoaudio_gml.c" -#include "echoaudio.c" diff --git a/trunk/sound/pci/echoaudio/mona_dsp.c b/trunk/sound/pci/echoaudio/mona_dsp.c deleted file mode 100644 index c0b4bf0be7d1..000000000000 --- a/trunk/sound/pci/echoaudio/mona_dsp.c +++ /dev/null @@ -1,428 +0,0 @@ -/**************************************************************************** - - Copyright Echo Digital Audio Corporation (c) 1998 - 2004 - All rights reserved - www.echoaudio.com - - This file is part of Echo Digital Audio's generic driver library. - - Echo Digital Audio's generic driver library is free software; - you can redistribute it and/or modify it under the terms of - the GNU General Public License as published by the Free Software - Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. - - ************************************************************************* - - Translation from C++ and adaptation for use in ALSA-Driver - were made by Giuliano Pochini - -****************************************************************************/ - - -static int write_control_reg(struct echoaudio *chip, u32 value, char force); -static int set_input_clock(struct echoaudio *chip, u16 clock); -static int set_professional_spdif(struct echoaudio *chip, char prof); -static int set_digital_mode(struct echoaudio *chip, u8 mode); -static int load_asic_generic(struct echoaudio *chip, u32 cmd, - const struct firmware *asic); -static int check_asic_status(struct echoaudio *chip); - - -static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) -{ - int err; - - DE_INIT(("init_hw() - Mona\n")); - snd_assert((subdevice_id & 0xfff0) == MONA, return -ENODEV); - - if ((err = init_dsp_comm_page(chip))) { - DE_INIT(("init_hw - could not initialize DSP comm page\n")); - return err; - } - - chip->device_id = device_id; - chip->subdevice_id = subdevice_id; - chip->bad_board = TRUE; - chip->input_clock_types = - ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | - ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT; - chip->digital_modes = - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | - ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | - ECHOCAPS_HAS_DIGITAL_MODE_ADAT; - - /* Mona comes in both '301 and '361 flavors */ - if (chip->device_id == DEVICE_ID_56361) - chip->dsp_code_to_load = &card_fw[FW_MONA_361_DSP]; - else - chip->dsp_code_to_load = &card_fw[FW_MONA_301_DSP]; - - chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; - chip->professional_spdif = FALSE; - chip->digital_in_automute = TRUE; - - if ((err = load_firmware(chip)) < 0) - return err; - chip->bad_board = FALSE; - - if ((err = init_line_levels(chip)) < 0) - return err; - - err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); - snd_assert(err >= 0, return err); - err = set_professional_spdif(chip, TRUE); - - DE_INIT(("init_hw done\n")); - return err; -} - - - -static u32 detect_input_clocks(const struct echoaudio *chip) -{ - u32 clocks_from_dsp, clock_bits; - - /* Map the DSP clock detect bits to the generic driver clock - detect bits */ - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - clock_bits = ECHO_CLOCK_BIT_INTERNAL; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF) - clock_bits |= ECHO_CLOCK_BIT_SPDIF; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT) - clock_bits |= ECHO_CLOCK_BIT_ADAT; - - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD) - clock_bits |= ECHO_CLOCK_BIT_WORD; - - return clock_bits; -} - - - -/* Mona has an ASIC on the PCI card and another ASIC in the external box; -both need to be loaded. */ -static int load_asic(struct echoaudio *chip) -{ - u32 control_reg; - int err; - const struct firmware *asic; - - if (chip->asic_loaded) - return 0; - - mdelay(10); - - if (chip->device_id == DEVICE_ID_56361) - asic = &card_fw[FW_MONA_361_1_ASIC48]; - else - asic = &card_fw[FW_MONA_301_1_ASIC48]; - - err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, asic); - if (err < 0) - return err; - - chip->asic_code = asic; - mdelay(10); - - /* Do the external one */ - err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_EXTERNAL_ASIC, - &card_fw[FW_MONA_2_ASIC]); - if (err < 0) - return err; - - mdelay(10); - err = check_asic_status(chip); - - /* Set up the control register if the load succeeded - - 48 kHz, internal clock, S/PDIF RCA mode */ - if (!err) { - control_reg = GML_CONVERTER_ENABLE | GML_48KHZ; - err = write_control_reg(chip, control_reg, TRUE); - } - - return err; -} - - - -/* Depending on what digital mode you want, Mona needs different ASICs -loaded. This function checks the ASIC needed for the new mode and sees -if it matches the one already loaded. */ -static int switch_asic(struct echoaudio *chip, char double_speed) -{ - const struct firmware *asic; - int err; - - /* Check the clock detect bits to see if this is - a single-speed clock or a double-speed clock; load - a new ASIC if necessary. */ - if (chip->device_id == DEVICE_ID_56361) { - if (double_speed) - asic = &card_fw[FW_MONA_361_1_ASIC96]; - else - asic = &card_fw[FW_MONA_361_1_ASIC48]; - } else { - if (double_speed) - asic = &card_fw[FW_MONA_301_1_ASIC96]; - else - asic = &card_fw[FW_MONA_301_1_ASIC48]; - } - - if (asic != chip->asic_code) { - /* Load the desired ASIC */ - err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, - asic); - if (err < 0) - return err; - chip->asic_code = asic; - } - - return 0; -} - - - -static int set_sample_rate(struct echoaudio *chip, u32 rate) -{ - u32 control_reg, clock; - const struct firmware *asic; - char force_write; - - /* Only set the clock for internal mode. */ - if (chip->input_clock != ECHO_CLOCK_INTERNAL) { - DE_ACT(("set_sample_rate: Cannot set sample rate - " - "clock not set to CLK_CLOCKININTERNAL\n")); - /* Save the rate anyhow */ - chip->comm_page->sample_rate = cpu_to_le32(rate); - chip->sample_rate = rate; - return 0; - } - - /* Now, check to see if the required ASIC is loaded */ - if (rate >= 88200) { - if (chip->digital_mode == DIGITAL_MODE_ADAT) - return -EINVAL; - if (chip->device_id == DEVICE_ID_56361) - asic = &card_fw[FW_MONA_361_1_ASIC96]; - else - asic = &card_fw[FW_MONA_301_1_ASIC96]; - } else { - if (chip->device_id == DEVICE_ID_56361) - asic = &card_fw[FW_MONA_361_1_ASIC48]; - else - asic = &card_fw[FW_MONA_301_1_ASIC48]; - } - - force_write = 0; - if (asic != chip->asic_code) { - int err; - /* Load the desired ASIC (load_asic_generic() can sleep) */ - spin_unlock_irq(&chip->lock); - err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, - asic); - spin_lock_irq(&chip->lock); - - if (err < 0) - return err; - chip->asic_code = asic; - force_write = 1; - } - - /* Compute the new control register value */ - clock = 0; - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_CLOCK_CLEAR_MASK; - control_reg &= GML_SPDIF_RATE_CLEAR_MASK; - - switch (rate) { - case 96000: - clock = GML_96KHZ; - break; - case 88200: - clock = GML_88KHZ; - break; - case 48000: - clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1; - break; - case 44100: - clock = GML_44KHZ; - /* Professional mode */ - if (control_reg & GML_SPDIF_PRO_MODE) - clock |= GML_SPDIF_SAMPLE_RATE0; - break; - case 32000: - clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 | - GML_SPDIF_SAMPLE_RATE1; - break; - case 22050: - clock = GML_22KHZ; - break; - case 16000: - clock = GML_16KHZ; - break; - case 11025: - clock = GML_11KHZ; - break; - case 8000: - clock = GML_8KHZ; - break; - default: - DE_ACT(("set_sample_rate: %d invalid!\n", rate)); - return -EINVAL; - } - - control_reg |= clock; - - chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ - chip->sample_rate = rate; - DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock)); - - return write_control_reg(chip, control_reg, force_write); -} - - - -static int set_input_clock(struct echoaudio *chip, u16 clock) -{ - u32 control_reg, clocks_from_dsp; - int err; - - DE_ACT(("set_input_clock:\n")); - - /* Prevent two simultaneous calls to switch_asic() */ - if (atomic_read(&chip->opencount)) - return -EAGAIN; - - /* Mask off the clock select bits */ - control_reg = le32_to_cpu(chip->comm_page->control_register) & - GML_CLOCK_CLEAR_MASK; - clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); - - switch (clock) { - case ECHO_CLOCK_INTERNAL: - DE_ACT(("Set Mona clock to INTERNAL\n")); - chip->input_clock = ECHO_CLOCK_INTERNAL; - return set_sample_rate(chip, chip->sample_rate); - case ECHO_CLOCK_SPDIF: - if (chip->digital_mode == DIGITAL_MODE_ADAT) - return -EAGAIN; - spin_unlock_irq(&chip->lock); - err = switch_asic(chip, clocks_from_dsp & - GML_CLOCK_DETECT_BIT_SPDIF96); - spin_lock_irq(&chip->lock); - if (err < 0) - return err; - DE_ACT(("Set Mona clock to SPDIF\n")); - control_reg |= GML_SPDIF_CLOCK; - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96) - control_reg |= GML_DOUBLE_SPEED_MODE; - else - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_WORD: - DE_ACT(("Set Mona clock to WORD\n")); - spin_unlock_irq(&chip->lock); - err = switch_asic(chip, clocks_from_dsp & - GML_CLOCK_DETECT_BIT_WORD96); - spin_lock_irq(&chip->lock); - if (err < 0) - return err; - control_reg |= GML_WORD_CLOCK; - if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD96) - control_reg |= GML_DOUBLE_SPEED_MODE; - else - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - case ECHO_CLOCK_ADAT: - DE_ACT(("Set Mona clock to ADAT\n")); - if (chip->digital_mode != DIGITAL_MODE_ADAT) - return -EAGAIN; - control_reg |= GML_ADAT_CLOCK; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - default: - DE_ACT(("Input clock 0x%x not supported for Mona\n", clock)); - return -EINVAL; - } - - chip->input_clock = clock; - return write_control_reg(chip, control_reg, TRUE); -} - - - -static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) -{ - u32 control_reg; - int err, incompatible_clock; - - /* Set clock to "internal" if it's not compatible with the new mode */ - incompatible_clock = FALSE; - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - case DIGITAL_MODE_SPDIF_RCA: - if (chip->input_clock == ECHO_CLOCK_ADAT) - incompatible_clock = TRUE; - break; - case DIGITAL_MODE_ADAT: - if (chip->input_clock == ECHO_CLOCK_SPDIF) - incompatible_clock = TRUE; - break; - default: - DE_ACT(("Digital mode not supported: %d\n", mode)); - return -EINVAL; - } - - spin_lock_irq(&chip->lock); - - if (incompatible_clock) { /* Switch to 48KHz, internal */ - chip->sample_rate = 48000; - set_input_clock(chip, ECHO_CLOCK_INTERNAL); - } - - /* Clear the current digital mode */ - control_reg = le32_to_cpu(chip->comm_page->control_register); - control_reg &= GML_DIGITAL_MODE_CLEAR_MASK; - - /* Tweak the control reg */ - switch (mode) { - case DIGITAL_MODE_SPDIF_OPTICAL: - control_reg |= GML_SPDIF_OPTICAL_MODE; - break; - case DIGITAL_MODE_SPDIF_RCA: - /* GML_SPDIF_OPTICAL_MODE bit cleared */ - break; - case DIGITAL_MODE_ADAT: - /* If the current ASIC is the 96KHz ASIC, switch the ASIC - and set to 48 KHz */ - if (chip->asic_code == &card_fw[FW_MONA_361_1_ASIC96] || - chip->asic_code == &card_fw[FW_MONA_301_1_ASIC96]) { - set_sample_rate(chip, 48000); - } - control_reg |= GML_ADAT_MODE; - control_reg &= ~GML_DOUBLE_SPEED_MODE; - break; - } - - err = write_control_reg(chip, control_reg, FALSE); - spin_unlock_irq(&chip->lock); - if (err < 0) - return err; - chip->digital_mode = mode; - - DE_ACT(("set_digital_mode to %d\n", mode)); - return incompatible_clock; -} diff --git a/trunk/sound/pci/emu10k1/emu10k1_main.c b/trunk/sound/pci/emu10k1/emu10k1_main.c index d6f135fe2958..42a358f989c3 100644 --- a/trunk/sound/pci/emu10k1/emu10k1_main.c +++ b/trunk/sound/pci/emu10k1/emu10k1_main.c @@ -1233,7 +1233,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card, } emu->port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_emu10k1_interrupt, IRQF_DISABLED|IRQF_SHARED, "EMU10K1", (void *)emu)) { + if (request_irq(pci->irq, snd_emu10k1_interrupt, SA_INTERRUPT|SA_SHIRQ, "EMU10K1", (void *)emu)) { err = -EBUSY; goto error; } diff --git a/trunk/sound/pci/emu10k1/emu10k1x.c b/trunk/sound/pci/emu10k1/emu10k1x.c index 2167279429b8..0fb27e4be07b 100644 --- a/trunk/sound/pci/emu10k1/emu10k1x.c +++ b/trunk/sound/pci/emu10k1/emu10k1x.c @@ -928,7 +928,7 @@ static int __devinit snd_emu10k1x_create(struct snd_card *card, } if (request_irq(pci->irq, snd_emu10k1x_interrupt, - IRQF_DISABLED|IRQF_SHARED, "EMU10K1X", + SA_INTERRUPT|SA_SHIRQ, "EMU10K1X", (void *)chip)) { snd_printk(KERN_ERR "emu10k1x: cannot grab irq %d\n", pci->irq); snd_emu10k1x_free(chip); diff --git a/trunk/sound/pci/ens1370.c b/trunk/sound/pci/ens1370.c index 7a985c868007..9d46bbee2a40 100644 --- a/trunk/sound/pci/ens1370.c +++ b/trunk/sound/pci/ens1370.c @@ -2135,7 +2135,7 @@ static int __devinit snd_ensoniq_create(struct snd_card *card, return err; } ensoniq->port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_audiopci_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_audiopci_interrupt, SA_INTERRUPT|SA_SHIRQ, "Ensoniq AudioPCI", ensoniq)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_ensoniq_free(ensoniq); diff --git a/trunk/sound/pci/es1938.c b/trunk/sound/pci/es1938.c index 1113b10259cf..ca6603fe0b11 100644 --- a/trunk/sound/pci/es1938.c +++ b/trunk/sound/pci/es1938.c @@ -1429,7 +1429,7 @@ static int es1938_resume(struct pci_dev *pci) pci_restore_state(pci); pci_enable_device(pci); request_irq(pci->irq, snd_es1938_interrupt, - IRQF_DISABLED|IRQF_SHARED, "ES1938", chip); + SA_INTERRUPT|SA_SHIRQ, "ES1938", chip); chip->irq = pci->irq; snd_es1938_chip_init(chip); @@ -1544,7 +1544,7 @@ static int __devinit snd_es1938_create(struct snd_card *card, chip->vc_port = pci_resource_start(pci, 2); chip->mpu_port = pci_resource_start(pci, 3); chip->game_port = pci_resource_start(pci, 4); - if (request_irq(pci->irq, snd_es1938_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_es1938_interrupt, SA_INTERRUPT|SA_SHIRQ, "ES1938", chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_es1938_free(chip); diff --git a/trunk/sound/pci/es1968.c b/trunk/sound/pci/es1968.c index a491c8f8a6a8..bfa0876e715e 100644 --- a/trunk/sound/pci/es1968.c +++ b/trunk/sound/pci/es1968.c @@ -2597,7 +2597,7 @@ static int __devinit snd_es1968_create(struct snd_card *card, return err; } chip->io_port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_es1968_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_es1968_interrupt, SA_INTERRUPT|SA_SHIRQ, "ESS Maestro", (void*)chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_es1968_free(chip); diff --git a/trunk/sound/pci/fm801.c b/trunk/sound/pci/fm801.c index 3aed27eace2c..0afa573dd244 100644 --- a/trunk/sound/pci/fm801.c +++ b/trunk/sound/pci/fm801.c @@ -1371,7 +1371,7 @@ static int __devinit snd_fm801_create(struct snd_card *card, return err; } chip->port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_fm801_interrupt, SA_INTERRUPT|SA_SHIRQ, "FM801", chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq); snd_fm801_free(chip); diff --git a/trunk/sound/pci/hda/hda_codec.c b/trunk/sound/pci/hda/hda_codec.c index 23201f3eeb12..8c2a8174ece1 100644 --- a/trunk/sound/pci/hda/hda_codec.c +++ b/trunk/sound/pci/hda/hda_codec.c @@ -408,9 +408,7 @@ static const struct hda_codec_preset *find_codec_preset(struct hda_codec *codec) u32 mask = preset->mask; if (! mask) mask = ~0; - if (preset->id == (codec->vendor_id & mask) && - (! preset->rev || - preset->rev == codec->revision_id)) + if (preset->id == (codec->vendor_id & mask)) return preset; } } diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c index 025af7c0c6e1..4070b5cd9b6b 100644 --- a/trunk/sound/pci/hda/hda_intel.c +++ b/trunk/sound/pci/hda/hda_intel.c @@ -1486,7 +1486,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, goto errout; } - if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, azx_interrupt, SA_INTERRUPT|SA_SHIRQ, "HDA Intel", (void*)chip)) { snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); err = -EBUSY; diff --git a/trunk/sound/pci/hda/patch_analog.c b/trunk/sound/pci/hda/patch_analog.c index 33b7d5806469..dd4e00a82b55 100644 --- a/trunk/sound/pci/hda/patch_analog.c +++ b/trunk/sound/pci/hda/patch_analog.c @@ -799,8 +799,6 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { { .pci_subvendor = 0x1043, .pci_subdevice = 0x818f, .config = AD1986A_LAPTOP }, /* ASUS P5GV-MX */ { .modelname = "laptop-eapd", .config = AD1986A_LAPTOP_EAPD }, - { .pci_subvendor = 0x144d, .pci_subdevice = 0xc023, - .config = AD1986A_LAPTOP_EAPD }, /* Samsung X60 Chane */ { .pci_subvendor = 0x144d, .pci_subdevice = 0xc024, .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1153, diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index 18d105263fea..98b9f16c26ff 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -78,7 +78,6 @@ enum { enum { ALC262_BASIC, ALC262_FUJITSU, - ALC262_HP_BPC, ALC262_AUTO, ALC262_MODEL_LAST /* last tag */ }; @@ -86,7 +85,6 @@ enum { /* ALC861 models */ enum { ALC861_3ST, - ALC660_3ST, ALC861_3ST_DIG, ALC861_6ST_DIG, ALC861_AUTO, @@ -101,17 +99,6 @@ enum { ALC882_MODEL_LAST, }; -/* ALC883 models */ -enum { - ALC883_3ST_2ch_DIG, - ALC883_3ST_6ch_DIG, - ALC883_3ST_6ch, - ALC883_6ST_DIG, - ALC888_DEMO_BOARD, - ALC883_AUTO, - ALC883_MODEL_LAST, -}; - /* for GPIO Poll */ #define GPIO_MASK 0x03 @@ -121,8 +108,7 @@ struct alc_spec { unsigned int num_mixers; const struct hda_verb *init_verbs[5]; /* initialization verbs - * don't forget NULL - * termination! + * don't forget NULL termination! */ unsigned int num_init_verbs; @@ -177,9 +163,7 @@ struct alc_spec { * configuration template - to be copied to the spec instance */ struct alc_config_preset { - struct snd_kcontrol_new *mixers[5]; /* should be identical size - * with spec - */ + struct snd_kcontrol_new *mixers[5]; /* should be identical size with spec */ const struct hda_verb *init_verbs[5]; unsigned int num_dacs; hda_nid_t *dac_nids; @@ -200,8 +184,7 @@ struct alc_config_preset { /* * input MUX handling */ -static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) +static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; @@ -211,8 +194,7 @@ static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); } -static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; @@ -222,24 +204,21 @@ static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, return 0; } -static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol, - spec->adc_nids[adc_idx], - &spec->cur_mux[adc_idx]); + spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); } /* * channel mode setting */ -static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) +static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; @@ -247,24 +226,20 @@ static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, spec->num_channel_mode); } -static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode, - spec->num_channel_mode, - spec->multiout.max_channels); + spec->num_channel_mode, spec->multiout.max_channels); } -static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, - spec->num_channel_mode, - &spec->multiout.max_channels); + spec->num_channel_mode, &spec->multiout.max_channels); } /* @@ -315,8 +290,7 @@ static signed char alc_pin_mode_dir_info[5][2] = { #define alc_pin_mode_n_items(_dir) \ (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1) -static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) +static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { unsigned int item_num = uinfo->value.enumerated.item; unsigned char dir = (kcontrol->private_value >> 16) & 0xff; @@ -331,46 +305,40 @@ static int alc_pin_mode_info(struct snd_kcontrol *kcontrol, return 0; } -static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_pin_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { unsigned int i; struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value & 0xffff; unsigned char dir = (kcontrol->private_value >> 16) & 0xff; long *valp = ucontrol->value.integer.value; - unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, - 0x00); + unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00); /* Find enumerated value for current pinctl setting */ i = alc_pin_mode_min(dir); - while (alc_pin_mode_values[i] != pinctl && i <= alc_pin_mode_max(dir)) + while (alc_pin_mode_values[i]!=pinctl && i<=alc_pin_mode_max(dir)) i++; - *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir); + *valp = i<=alc_pin_mode_max(dir)?i:alc_pin_mode_min(dir); return 0; } -static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { signed int change; struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value & 0xffff; unsigned char dir = (kcontrol->private_value >> 16) & 0xff; long val = *ucontrol->value.integer.value; - unsigned int pinctl = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, - 0x00); + unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00); - if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) + if (valalc_pin_mode_max(dir)) val = alc_pin_mode_min(dir); change = pinctl != alc_pin_mode_values[val]; if (change) { /* Set pin mode to that requested */ snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL, - alc_pin_mode_values[val]); + alc_pin_mode_values[val]); /* Also enable the retasking pin's input/output as required * for the requested pin mode. Enum values of 2 or less are @@ -383,19 +351,15 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, * this turns out to be necessary in the future. */ if (val <= 2) { - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_MUTE); - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_UNMUTE(0)); + snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_MUTE); + snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, + AMP_IN_UNMUTE(0)); } else { - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_IN_MUTE(0)); - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_UNMUTE); + snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, + AMP_IN_MUTE(0)); + snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, + AMP_OUT_UNMUTE); } } return change; @@ -414,8 +378,7 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, * needed for any "production" models. */ #ifdef CONFIG_SND_DEBUG -static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) +static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; @@ -423,38 +386,33 @@ static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, uinfo->value.integer.max = 1; return 0; } -static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value & 0xffff; unsigned char mask = (kcontrol->private_value >> 16) & 0xff; long *valp = ucontrol->value.integer.value; - unsigned int val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_DATA, 0x00); + unsigned int val = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00); *valp = (val & mask) != 0; return 0; } -static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { signed int change; struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value & 0xffff; unsigned char mask = (kcontrol->private_value >> 16) & 0xff; long val = *ucontrol->value.integer.value; - unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_GPIO_DATA, - 0x00); + unsigned int gpio_data = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00); /* Set/unset the masked GPIO bit(s) as needed */ - change = (val == 0 ? 0 : mask) != (gpio_data & mask); - if (val == 0) + change = (val==0?0:mask) != (gpio_data & mask); + if (val==0) gpio_data &= ~mask; else gpio_data |= mask; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data); + snd_hda_codec_write(codec,nid,0,AC_VERB_SET_GPIO_DATA,gpio_data); return change; } @@ -474,8 +432,7 @@ static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, * necessary. */ #ifdef CONFIG_SND_DEBUG -static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) +static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; @@ -483,39 +440,33 @@ static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol, uinfo->value.integer.max = 1; return 0; } -static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value & 0xffff; unsigned char mask = (kcontrol->private_value >> 16) & 0xff; long *valp = ucontrol->value.integer.value; - unsigned int val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_DIGI_CONVERT, 0x00); + unsigned int val = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_DIGI_CONVERT,0x00); *valp = (val & mask) != 0; return 0; } -static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { signed int change; struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = kcontrol->private_value & 0xffff; unsigned char mask = (kcontrol->private_value >> 16) & 0xff; long val = *ucontrol->value.integer.value; - unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_DIGI_CONVERT, - 0x00); + unsigned int ctrl_data = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_DIGI_CONVERT,0x00); /* Set/unset the masked control bit(s) as needed */ - change = (val == 0 ? 0 : mask) != (ctrl_data & mask); + change = (val==0?0:mask) != (ctrl_data & mask); if (val==0) ctrl_data &= ~mask; else ctrl_data |= mask; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, - ctrl_data); + snd_hda_codec_write(codec,nid,0,AC_VERB_SET_DIGI_CONVERT_1,ctrl_data); return change; } @@ -530,17 +481,14 @@ static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol, /* * set up from the preset table */ -static void setup_preset(struct alc_spec *spec, - const struct alc_config_preset *preset) +static void setup_preset(struct alc_spec *spec, const struct alc_config_preset *preset) { int i; for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++) spec->mixers[spec->num_mixers++] = preset->mixers[i]; - for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; - i++) - spec->init_verbs[spec->num_init_verbs++] = - preset->init_verbs[i]; + for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; i++) + spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i]; spec->channel_mode = preset->channel_mode; spec->num_channel_mode = preset->num_channel_mode; @@ -569,8 +517,8 @@ static void setup_preset(struct alc_spec *spec, * ALC880 3-stack model * * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) - * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, - * F-Mic = 0x1b, HP = 0x19 + * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b + * HP = 0x19 */ static hda_nid_t alc880_dac_nids[4] = { @@ -714,8 +662,7 @@ static struct snd_kcontrol_new alc880_capture_alt_mixer[] = { /* * ALC880 5-stack model * - * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), - * Side = 0x02 (0xd) + * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd) * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16 * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19 */ @@ -753,8 +700,7 @@ static struct hda_channel_mode alc880_fivestack_modes[2] = { /* * ALC880 6-stack model * - * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), - * Side = 0x05 (0x0f) + * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f) * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17, * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b */ @@ -865,8 +811,7 @@ static struct snd_kcontrol_new alc880_w810_base_mixer[] = { * Z710V model * * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d) - * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), - * Line = 0x1a + * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a */ static hda_nid_t alc880_z71v_dac_nids[1] = { @@ -1021,8 +966,7 @@ static int alc_build_controls(struct hda_codec *codec) } if (spec->multiout.dig_out_nid) { - err = snd_hda_create_spdif_out_ctls(codec, - spec->multiout.dig_out_nid); + err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); if (err < 0) return err; } @@ -1055,8 +999,8 @@ static struct hda_verb alc880_volume_init_verbs[] = { /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for front - * panel mic (mic 2) + * Note: PASD motherboards uses the Line In 2 as the input for front panel + * mic (mic 2) */ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, @@ -1210,8 +1154,8 @@ static struct hda_verb alc880_pin_z71v_init_verbs[] = { /* * 6-stack pin configuration: - * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, - * f-mic = 0x19, line = 0x1a, HP = 0x1b + * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19, + * line = 0x1a, HP = 0x1b */ static struct hda_verb alc880_pin_6stack_init_verbs[] = { {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ @@ -1643,8 +1587,8 @@ static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct alc_spec *spec = codec->spec; - return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, - stream_tag, format, substream); + return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, + format, substream); } static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, @@ -1696,8 +1640,7 @@ static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, { struct alc_spec *spec = codec->spec; - snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], - 0, 0, 0); + snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0); return 0; } @@ -1879,8 +1822,7 @@ static struct hda_channel_mode alc880_test_modes[4] = { { 8, NULL }, }; -static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) +static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "N/A", "Line Out", "HP Out", @@ -1895,8 +1837,7 @@ static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, return 0; } -static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = (hda_nid_t)kcontrol->private_value; @@ -1922,8 +1863,7 @@ static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, return 0; } -static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = (hda_nid_t)kcontrol->private_value; @@ -1941,18 +1881,15 @@ static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); new_ctl = ctls[ucontrol->value.enumerated.item[0]]; if (old_ctl != new_ctl) { - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - (ucontrol->value.enumerated.item[0] >= 3 ? - 0xb080 : 0xb000)); + ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000); return 1; } return 0; } -static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) +static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { static char *texts[] = { "Front", "Surround", "CLFE", "Side" @@ -1966,8 +1903,7 @@ static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, return 0; } -static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = (hda_nid_t)kcontrol->private_value; @@ -1978,8 +1914,7 @@ static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, return 0; } -static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) +static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = (hda_nid_t)kcontrol->private_value; @@ -2804,8 +2739,7 @@ static int patch_alc880(struct hda_codec *codec) board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); if (board_config < 0 || board_config >= ALC880_MODEL_LAST) { - printk(KERN_INFO "hda_codec: Unknown model for ALC880, " - "trying auto-probe from BIOS...\n"); + printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n"); board_config = ALC880_AUTO; } @@ -2816,9 +2750,7 @@ static int patch_alc880(struct hda_codec *codec) alc_free(codec); return err; } else if (! err) { - printk(KERN_INFO - "hda_codec: Cannot set up configuration " - "from BIOS. Using 3-stack mode...\n"); + printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n"); board_config = ALC880_3ST; } } @@ -4015,8 +3947,7 @@ static int patch_alc260(struct hda_codec *codec) board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl); if (board_config < 0 || board_config >= ALC260_MODEL_LAST) { - snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, " - "trying auto-probe from BIOS...\n"); + snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n"); board_config = ALC260_AUTO; } @@ -4027,9 +3958,7 @@ static int patch_alc260(struct hda_codec *codec) alc_free(codec); return err; } else if (! err) { - printk(KERN_INFO - "hda_codec: Cannot set up configuration " - "from BIOS. Using base mode...\n"); + printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n"); board_config = ALC260_BASIC; } } @@ -4391,12 +4320,9 @@ static struct snd_kcontrol_new alc882_capture_mixer[] = { static struct hda_board_config alc882_cfg_tbl[] = { { .modelname = "3stack-dig", .config = ALC882_3ST_DIG }, { .modelname = "6stack-dig", .config = ALC882_6ST_DIG }, - { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, - .config = ALC882_6ST_DIG }, /* MSI */ - { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, - .config = ALC882_6ST_DIG }, /* Foxconn */ - { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, - .config = ALC882_6ST_DIG }, /* ECS to Intel*/ + { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* MSI */ + { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* Foxconn */ + { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* ECS */ { .modelname = "auto", .config = ALC882_AUTO }, {} }; @@ -4513,6 +4439,10 @@ static void alc882_auto_init(struct hda_codec *codec) alc882_auto_init_analog_input(codec); } +/* + * ALC882 Headphone poll in 3.5.1a or 3.5.2 + */ + static int patch_alc882(struct hda_codec *codec) { struct alc_spec *spec; @@ -4527,8 +4457,7 @@ static int patch_alc882(struct hda_codec *codec) board_config = snd_hda_check_board_config(codec, alc882_cfg_tbl); if (board_config < 0 || board_config >= ALC882_MODEL_LAST) { - printk(KERN_INFO "hda_codec: Unknown model for ALC882, " - "trying auto-probe from BIOS...\n"); + printk(KERN_INFO "hda_codec: Unknown model for ALC882, trying auto-probe from BIOS...\n"); board_config = ALC882_AUTO; } @@ -4539,9 +4468,7 @@ static int patch_alc882(struct hda_codec *codec) alc_free(codec); return err; } else if (! err) { - printk(KERN_INFO - "hda_codec: Cannot set up configuration " - "from BIOS. Using base mode...\n"); + printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n"); board_config = ALC882_3ST_DIG; } } @@ -4582,730 +4509,62 @@ static int patch_alc882(struct hda_codec *codec) } /* - * ALC883 support - * - * ALC883 is almost identical with ALC880 but has cleaner and more flexible - * configuration. Each pin widget can choose any input DACs and a mixer. - * Each ADC is connected from a mixer of all inputs. This makes possible - * 6-channel independent captures. - * - * In addition, an independent DAC for the multi-playback (not used in this - * driver yet). - */ -#define ALC883_DIGOUT_NID 0x06 -#define ALC883_DIGIN_NID 0x0a - -static hda_nid_t alc883_dac_nids[4] = { - /* front, rear, clfe, rear_surr */ - 0x02, 0x04, 0x03, 0x05 -}; - -static hda_nid_t alc883_adc_nids[2] = { - /* ADC1-2 */ - 0x08, 0x09, -}; -/* input MUX */ -/* FIXME: should be a matrix-type input source selection */ - -static struct hda_input_mux alc883_capture_source = { - .num_items = 4, - .items = { - { "Mic", 0x0 }, - { "Front Mic", 0x1 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - }, -}; -#define alc883_mux_enum_info alc_mux_enum_info -#define alc883_mux_enum_get alc_mux_enum_get - -static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct alc_spec *spec = codec->spec; - const struct hda_input_mux *imux = spec->input_mux; - unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); - static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 }; - hda_nid_t nid = capture_mixers[adc_idx]; - unsigned int *cur_val = &spec->cur_mux[adc_idx]; - unsigned int i, idx; - - idx = ucontrol->value.enumerated.item[0]; - if (idx >= imux->num_items) - idx = imux->num_items - 1; - if (*cur_val == idx && ! codec->in_resume) - return 0; - for (i = 0; i < imux->num_items; i++) { - unsigned int v = (i == idx) ? 0x7000 : 0x7080; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - v | (imux->items[i].index << 8)); - } - *cur_val = idx; - return 1; -} -/* - * 2ch mode - */ -static struct hda_channel_mode alc883_3ST_2ch_modes[1] = { - { 2, NULL } -}; - -/* - * 2ch mode - */ -static struct hda_verb alc883_3ST_ch2_init[] = { - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, - { } /* end */ -}; - -/* - * 6ch mode - */ -static struct hda_verb alc883_3ST_ch6_init[] = { - { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 }, - { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, - { } /* end */ -}; - -static struct hda_channel_mode alc883_3ST_6ch_modes[2] = { - { 2, alc883_3ST_ch2_init }, - { 6, alc883_3ST_ch6_init }, -}; - -/* - * 6ch mode - */ -static struct hda_verb alc883_sixstack_ch6_init[] = { - { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, - { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { } /* end */ -}; - -/* - * 8ch mode + * ALC262 support */ -static struct hda_verb alc883_sixstack_ch8_init[] = { - { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - { } /* end */ -}; - -static struct hda_channel_mode alc883_sixstack_modes[2] = { - { 6, alc883_sixstack_ch6_init }, - { 8, alc883_sixstack_ch8_init }, -}; -/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 - * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b - */ +#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID +#define ALC262_DIGIN_NID ALC880_DIGIN_NID -static struct snd_kcontrol_new alc883_base_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 2, - .info = alc883_mux_enum_info, - .get = alc883_mux_enum_get, - .put = alc883_mux_enum_put, - }, - { } /* end */ -}; +#define alc262_dac_nids alc260_dac_nids +#define alc262_adc_nids alc882_adc_nids +#define alc262_adc_nids_alt alc882_adc_nids_alt -static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 2, - .info = alc883_mux_enum_info, - .get = alc883_mux_enum_get, - .put = alc883_mux_enum_put, - }, - { } /* end */ -}; +#define alc262_modes alc260_modes +#define alc262_capture_source alc882_capture_source -static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = { +static struct snd_kcontrol_new alc262_base_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 2, - .info = alc883_mux_enum_info, - .get = alc883_mux_enum_get, - .put = alc883_mux_enum_put, - }, + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), + /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), + HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */ + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), { } /* end */ }; -static struct snd_kcontrol_new alc883_chmode_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_ch_mode_info, - .get = alc_ch_mode_get, - .put = alc_ch_mode_put, - }, - { } /* end */ -}; +#define alc262_capture_mixer alc882_capture_mixer +#define alc262_capture_alt_mixer alc882_capture_alt_mixer -static struct hda_verb alc883_init_verbs[] = { - /* ADC1: mute amp left and right */ - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, +/* + * generic initialization of ADC, input mixers and output mixers + */ +static struct hda_verb alc262_init_verbs[] = { + /* + * Unmute ADC0-2 and set the default input to mic-in + */ + {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* ADC2: mute amp left and right */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* Front mixer: unmute input/output amp left and right (volume = 0) */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Rear mixer */ - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* CLFE mixer */ - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* Side mixer */ - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - - /* Front Pin: output 0 (0x0c) */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* Rear Pin: output 1 (0x0d) */ - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, - /* CLFE Pin: output 2 (0x0e) */ - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, - /* Side Pin: output 3 (0x0f) */ - {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, - /* Mic (rear) pin: input vref at 80% */ - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Front Mic pin: input vref at 80% */ - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line In pin: input */ - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, - /* Line-2 In: Headphone output (output 0 - 0x0c) */ - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* CD pin widget for input */ - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, - - /* FIXME: use matrix-type input source selection */ - /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ - /* Input mixer2 */ - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - /* Input mixer3 */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - { } -}; - -/* - * generic initialization of ADC, input mixers and output mixers - */ -static struct hda_verb alc883_auto_init_verbs[] = { - /* - * Unmute ADC0-2 and set the default input to mic-in - */ - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - - /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback - * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for front panel - * mic (mic 2) - */ - /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - - /* - * Set up output mixers (0x0c - 0x0f) - */ - /* set vol=0 to output mixers */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - /* set up input amps for analog loopback */ - /* Amp Indices: DAC = 0, mixer = 1 */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - - /* FIXME: use matrix-type input source selection */ - /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ - /* Input mixer1 */ - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - //{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - /* Input mixer2 */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - //{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - - { } -}; - -/* capture mixer elements */ -static struct snd_kcontrol_new alc883_capture_mixer[] = { - HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* The multiple "Capture Source" controls confuse alsamixer - * So call somewhat different.. - * FIXME: the controls appear in the "playback" view! - */ - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 2, - .info = alc882_mux_enum_info, - .get = alc882_mux_enum_get, - .put = alc882_mux_enum_put, - }, - { } /* end */ -}; - -/* pcm configuration: identiacal with ALC880 */ -#define alc883_pcm_analog_playback alc880_pcm_analog_playback -#define alc883_pcm_analog_capture alc880_pcm_analog_capture -#define alc883_pcm_digital_playback alc880_pcm_digital_playback -#define alc883_pcm_digital_capture alc880_pcm_digital_capture - -/* - * configuration and preset - */ -static struct hda_board_config alc883_cfg_tbl[] = { - { .modelname = "3stack-dig", .config = ALC883_3ST_2ch_DIG }, - { .modelname = "6stack-dig", .config = ALC883_6ST_DIG }, - { .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD }, - { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, - .config = ALC883_6ST_DIG }, /* MSI */ - { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, - .config = ALC883_6ST_DIG }, /* Foxconn */ - { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, - .config = ALC883_3ST_6ch_DIG }, /* ECS to Intel*/ - { .pci_subvendor = 0x108e, .pci_subdevice = 0x534d, - .config = ALC883_3ST_6ch }, - { .modelname = "auto", .config = ALC883_AUTO }, - {} -}; - -static struct alc_config_preset alc883_presets[] = { - [ALC883_3ST_2ch_DIG] = { - .mixers = { alc883_3ST_2ch_mixer }, - .init_verbs = { alc883_init_verbs }, - .num_dacs = ARRAY_SIZE(alc883_dac_nids), - .dac_nids = alc883_dac_nids, - .dig_out_nid = ALC883_DIGOUT_NID, - .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), - .adc_nids = alc883_adc_nids, - .dig_in_nid = ALC883_DIGIN_NID, - .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), - .channel_mode = alc883_3ST_2ch_modes, - .input_mux = &alc883_capture_source, - }, - [ALC883_3ST_6ch_DIG] = { - .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, - .init_verbs = { alc883_init_verbs }, - .num_dacs = ARRAY_SIZE(alc883_dac_nids), - .dac_nids = alc883_dac_nids, - .dig_out_nid = ALC883_DIGOUT_NID, - .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), - .adc_nids = alc883_adc_nids, - .dig_in_nid = ALC883_DIGIN_NID, - .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), - .channel_mode = alc883_3ST_6ch_modes, - .input_mux = &alc883_capture_source, - }, - [ALC883_3ST_6ch] = { - .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer }, - .init_verbs = { alc883_init_verbs }, - .num_dacs = ARRAY_SIZE(alc883_dac_nids), - .dac_nids = alc883_dac_nids, - .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), - .adc_nids = alc883_adc_nids, - .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), - .channel_mode = alc883_3ST_6ch_modes, - .input_mux = &alc883_capture_source, - }, - [ALC883_6ST_DIG] = { - .mixers = { alc883_base_mixer, alc883_chmode_mixer }, - .init_verbs = { alc883_init_verbs }, - .num_dacs = ARRAY_SIZE(alc883_dac_nids), - .dac_nids = alc883_dac_nids, - .dig_out_nid = ALC883_DIGOUT_NID, - .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), - .adc_nids = alc883_adc_nids, - .dig_in_nid = ALC883_DIGIN_NID, - .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), - .channel_mode = alc883_sixstack_modes, - .input_mux = &alc883_capture_source, - }, - [ALC888_DEMO_BOARD] = { - .mixers = { alc883_base_mixer, alc883_chmode_mixer }, - .init_verbs = { alc883_init_verbs }, - .num_dacs = ARRAY_SIZE(alc883_dac_nids), - .dac_nids = alc883_dac_nids, - .dig_out_nid = ALC883_DIGOUT_NID, - .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), - .adc_nids = alc883_adc_nids, - .dig_in_nid = ALC883_DIGIN_NID, - .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), - .channel_mode = alc883_sixstack_modes, - .input_mux = &alc883_capture_source, - }, -}; - - -/* - * BIOS auto configuration - */ -static void alc883_auto_set_output_and_unmute(struct hda_codec *codec, - hda_nid_t nid, int pin_type, - int dac_idx) -{ - /* set as output */ - struct alc_spec *spec = codec->spec; - int idx; - - if (spec->multiout.dac_nids[dac_idx] == 0x25) - idx = 4; - else - idx = spec->multiout.dac_nids[dac_idx] - 2; - - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - pin_type); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_UNMUTE); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx); - -} - -static void alc883_auto_init_multi_out(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int i; - - for (i = 0; i <= HDA_SIDE; i++) { - hda_nid_t nid = spec->autocfg.line_out_pins[i]; - if (nid) - alc883_auto_set_output_and_unmute(codec, nid, PIN_OUT, i); - } -} - -static void alc883_auto_init_hp_out(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - hda_nid_t pin; - - pin = spec->autocfg.hp_pin; - if (pin) /* connect to front */ - /* use dac 0 */ - alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); -} - -#define alc883_is_input_pin(nid) alc880_is_input_pin(nid) -#define ALC883_PIN_CD_NID ALC880_PIN_CD_NID - -static void alc883_auto_init_analog_input(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int i; - - for (i = 0; i < AUTO_PIN_LAST; i++) { - hda_nid_t nid = spec->autocfg.input_pins[i]; - if (alc883_is_input_pin(nid)) { - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - (i <= AUTO_PIN_FRONT_MIC ? - PIN_VREF80 : PIN_IN)); - if (nid != ALC883_PIN_CD_NID) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_AMP_GAIN_MUTE, - AMP_OUT_MUTE); - } - } -} - -/* almost identical with ALC880 parser... */ -static int alc883_parse_auto_config(struct hda_codec *codec) -{ - struct alc_spec *spec = codec->spec; - int err = alc880_parse_auto_config(codec); - - if (err < 0) - return err; - else if (err > 0) - /* hack - override the init verbs */ - spec->init_verbs[0] = alc883_auto_init_verbs; - spec->mixers[spec->num_mixers] = alc883_capture_mixer; - spec->num_mixers++; - return err; -} - -/* additional initialization for auto-configuration model */ -static void alc883_auto_init(struct hda_codec *codec) -{ - alc883_auto_init_multi_out(codec); - alc883_auto_init_hp_out(codec); - alc883_auto_init_analog_input(codec); -} - -static int patch_alc883(struct hda_codec *codec) -{ - struct alc_spec *spec; - int err, board_config; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - - board_config = snd_hda_check_board_config(codec, alc883_cfg_tbl); - if (board_config < 0 || board_config >= ALC883_MODEL_LAST) { - printk(KERN_INFO "hda_codec: Unknown model for ALC883, " - "trying auto-probe from BIOS...\n"); - board_config = ALC883_AUTO; - } - - if (board_config == ALC883_AUTO) { - /* automatic parse from the BIOS config */ - err = alc883_parse_auto_config(codec); - if (err < 0) { - alc_free(codec); - return err; - } else if (! err) { - printk(KERN_INFO - "hda_codec: Cannot set up configuration " - "from BIOS. Using base mode...\n"); - board_config = ALC883_3ST_2ch_DIG; - } - } - - if (board_config != ALC883_AUTO) - setup_preset(spec, &alc883_presets[board_config]); - - spec->stream_name_analog = "ALC883 Analog"; - spec->stream_analog_playback = &alc883_pcm_analog_playback; - spec->stream_analog_capture = &alc883_pcm_analog_capture; - - spec->stream_name_digital = "ALC883 Digital"; - spec->stream_digital_playback = &alc883_pcm_digital_playback; - spec->stream_digital_capture = &alc883_pcm_digital_capture; - - spec->adc_nids = alc883_adc_nids; - spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); - - codec->patch_ops = alc_patch_ops; - if (board_config == ALC883_AUTO) - spec->init_hook = alc883_auto_init; - - return 0; -} - -/* - * ALC262 support - */ - -#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID -#define ALC262_DIGIN_NID ALC880_DIGIN_NID - -#define alc262_dac_nids alc260_dac_nids -#define alc262_adc_nids alc882_adc_nids -#define alc262_adc_nids_alt alc882_adc_nids_alt - -#define alc262_modes alc260_modes -#define alc262_capture_source alc882_capture_source - -static struct snd_kcontrol_new alc262_base_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), - /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */ - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), - { } /* end */ -}; - -static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT), - HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT), - { } /* end */ -}; - -#define alc262_capture_mixer alc882_capture_mixer -#define alc262_capture_alt_mixer alc882_capture_alt_mixer - -/* - * generic initialization of ADC, input mixers and output mixers - */ -static struct hda_verb alc262_init_verbs[] = { - /* - * Unmute ADC0-2 and set the default input to mic-in - */ - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - - /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback - * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for front panel - * mic (mic 2) - */ - /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ + /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback + * mixer widget + * Note: PASD motherboards uses the Line In 2 as the input for front panel + * mic (mic 2) + */ + /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, @@ -5386,17 +4645,6 @@ static struct hda_input_mux alc262_fujitsu_capture_source = { }, }; -static struct hda_input_mux alc262_HP_capture_source = { - .num_items = 5, - .items = { - { "Mic", 0x0 }, - { "Front Mic", 0x3 }, - { "Line", 0x2 }, - { "CD", 0x4 }, - { "AUX IN", 0x6 }, - }, -}; - /* mute/unmute internal speaker according to the hp jack and mute state */ static void alc262_fujitsu_automute(struct hda_codec *codec, int force) { @@ -5620,93 +4868,6 @@ static struct hda_verb alc262_volume_init_verbs[] = { { } }; -static struct hda_verb alc262_HP_BPC_init_verbs[] = { - /* - * Unmute ADC0-2 and set the default input to mic-in - */ - {0x07, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x09, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - - /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback - * mixer widget - * Note: PASD motherboards uses the Line In 2 as the input for front panel - * mic (mic 2) - */ - /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */ - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)}, - {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)}, - - /* - * Set up output mixers (0x0c - 0x0e) - */ - /* set vol=0 to output mixers */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - - /* set up input amps for analog loopback */ - /* Amp Indices: DAC = 0, mixer = 1 */ - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - - {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, - {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, - - {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, - - {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, - - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, - {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, - {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, - {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, - {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, - - {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, - {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, - {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 }, - - - /* FIXME: use matrix-type input source selection */ - /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */ - /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, - {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, - /* Input mixer2 */ - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, - {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, - /* Input mixer3 */ - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, - {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, - - { } -}; - /* pcm configuration: identiacal with ALC880 */ #define alc262_pcm_analog_playback alc880_pcm_analog_playback #define alc262_pcm_analog_capture alc880_pcm_analog_capture @@ -5767,16 +4928,7 @@ static void alc262_auto_init(struct hda_codec *codec) static struct hda_board_config alc262_cfg_tbl[] = { { .modelname = "basic", .config = ALC262_BASIC }, { .modelname = "fujitsu", .config = ALC262_FUJITSU }, - { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, - .config = ALC262_FUJITSU }, - { .pci_subvendor = 0x103c, .pci_subdevice = 0x208c, - .config = ALC262_HP_BPC }, /* xw4400 */ - { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, - .config = ALC262_HP_BPC }, /* xw6400 */ - { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, - .config = ALC262_HP_BPC }, /* xw8400 */ - { .pci_subvendor = 0x103c, .pci_subdevice = 0x12fe, - .config = ALC262_HP_BPC }, /* xw9400 */ + { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, .config = ALC262_FUJITSU }, { .modelname = "auto", .config = ALC262_AUTO }, {} }; @@ -5804,16 +4956,6 @@ static struct alc_config_preset alc262_presets[] = { .input_mux = &alc262_fujitsu_capture_source, .unsol_event = alc262_fujitsu_unsol_event, }, - [ALC262_HP_BPC] = { - .mixers = { alc262_HP_BPC_mixer }, - .init_verbs = { alc262_HP_BPC_init_verbs }, - .num_dacs = ARRAY_SIZE(alc262_dac_nids), - .dac_nids = alc262_dac_nids, - .hp_nid = 0x03, - .num_channel_mode = ARRAY_SIZE(alc262_modes), - .channel_mode = alc262_modes, - .input_mux = &alc262_HP_capture_source, - }, }; static int patch_alc262(struct hda_codec *codec) @@ -5839,10 +4981,8 @@ static int patch_alc262(struct hda_codec *codec) #endif board_config = snd_hda_check_board_config(codec, alc262_cfg_tbl); - if (board_config < 0 || board_config >= ALC262_MODEL_LAST) { - printk(KERN_INFO "hda_codec: Unknown model for ALC262, " - "trying auto-probe from BIOS...\n"); + printk(KERN_INFO "hda_codec: Unknown model for ALC262, trying auto-probe from BIOS...\n"); board_config = ALC262_AUTO; } @@ -5853,9 +4993,7 @@ static int patch_alc262(struct hda_codec *codec) alc_free(codec); return err; } else if (! err) { - printk(KERN_INFO - "hda_codec: Cannot set up configuration " - "from BIOS. Using base mode...\n"); + printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n"); board_config = ALC262_BASIC; } } @@ -5896,6 +5034,7 @@ static int patch_alc262(struct hda_codec *codec) return 0; } + /* * ALC861 channel source setting (2/6 channel selection for 3-stack) */ @@ -5910,11 +5049,9 @@ static struct hda_verb alc861_threestack_ch2_init[] = { /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, -#if 0 - { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ - { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/ -#endif + { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, + { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, //mic + { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, //line in { } /* end */ }; /* @@ -5928,13 +5065,11 @@ static struct hda_verb alc861_threestack_ch6_init[] = { { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 }, - { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 }, + { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 }, - { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, -#if 0 - { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ - { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/ -#endif + { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 }, + { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, //mic + { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, //line in { } /* end */ }; @@ -6218,11 +5353,6 @@ static hda_nid_t alc861_dac_nids[4] = { 0x03, 0x06, 0x05, 0x04 }; -static hda_nid_t alc660_dac_nids[3] = { - /* front, clfe, surround */ - 0x03, 0x05, 0x06 -}; - static hda_nid_t alc861_adc_nids[1] = { /* ADC0-2 */ 0x08, @@ -6475,10 +5605,7 @@ static void alc861_auto_init(struct hda_codec *codec) */ static struct hda_board_config alc861_cfg_tbl[] = { { .modelname = "3stack", .config = ALC861_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, - .config = ALC861_3ST }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x81e7, - .config = ALC660_3ST }, + { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, .config = ALC861_3ST }, { .modelname = "3stack-dig", .config = ALC861_3ST_DIG }, { .modelname = "6stack-dig", .config = ALC861_6ST_DIG }, { .modelname = "auto", .config = ALC861_AUTO }, @@ -6521,17 +5648,6 @@ static struct alc_config_preset alc861_presets[] = { .adc_nids = alc861_adc_nids, .input_mux = &alc861_capture_source, }, - [ALC660_3ST] = { - .mixers = { alc861_3ST_mixer }, - .init_verbs = { alc861_threestack_init_verbs }, - .num_dacs = ARRAY_SIZE(alc660_dac_nids), - .dac_nids = alc660_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), - .channel_mode = alc861_threestack_modes, - .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), - .adc_nids = alc861_adc_nids, - .input_mux = &alc861_capture_source, - }, }; @@ -6548,10 +5664,8 @@ static int patch_alc861(struct hda_codec *codec) codec->spec = spec; board_config = snd_hda_check_board_config(codec, alc861_cfg_tbl); - if (board_config < 0 || board_config >= ALC861_MODEL_LAST) { - printk(KERN_INFO "hda_codec: Unknown model for ALC861, " - "trying auto-probe from BIOS...\n"); + printk(KERN_INFO "hda_codec: Unknown model for ALC861, trying auto-probe from BIOS...\n"); board_config = ALC861_AUTO; } @@ -6562,9 +5676,7 @@ static int patch_alc861(struct hda_codec *codec) alc_free(codec); return err; } else if (! err) { - printk(KERN_INFO - "hda_codec: Cannot set up configuration " - "from BIOS. Using base mode...\n"); + printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n"); board_config = ALC861_3ST_DIG; } } @@ -6595,12 +5707,8 @@ struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, - { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, + { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, - { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, - { .id = 0x10ec0861, .rev = 0x100300, .name = "ALC861", - .patch = patch_alc861 }, - { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", - .patch = patch_alc861 }, + { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 }, {} /* terminator */ }; diff --git a/trunk/sound/pci/hda/patch_sigmatel.c b/trunk/sound/pci/hda/patch_sigmatel.c index fb4bed0759d1..36f199442fdc 100644 --- a/trunk/sound/pci/hda/patch_sigmatel.c +++ b/trunk/sound/pci/hda/patch_sigmatel.c @@ -42,9 +42,6 @@ #define STAC_D945GTP3 1 #define STAC_D945GTP5 2 #define STAC_MACMINI 3 -#define STAC_D965_2112 4 -#define STAC_D965_284B 5 -#define STAC_922X_MODELS 6 /* number of 922x models */ struct sigmatel_spec { struct snd_kcontrol_new *mixers[4]; @@ -110,24 +107,10 @@ static hda_nid_t stac922x_adc_nids[2] = { 0x06, 0x07, }; -static hda_nid_t stac9227_adc_nids[2] = { - 0x07, 0x08, -}; - -#if 0 -static hda_nid_t d965_2112_dac_nids[3] = { - 0x02, 0x03, 0x05, -}; -#endif - static hda_nid_t stac922x_mux_nids[2] = { 0x12, 0x13, }; -static hda_nid_t stac9227_mux_nids[2] = { - 0x15, 0x16, -}; - static hda_nid_t stac927x_adc_nids[3] = { 0x07, 0x08, 0x09 }; @@ -190,24 +173,6 @@ static struct hda_verb stac922x_core_init[] = { {} }; -static struct hda_verb stac9227_core_init[] = { - /* set master volume and direct control */ - { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - /* unmute node 0x1b */ - { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - {} -}; - -static struct hda_verb d965_2112_core_init[] = { - /* set master volume and direct control */ - { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - /* unmute node 0x1b */ - { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - /* select node 0x03 as DAC */ - { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, - {} -}; - static struct hda_verb stac927x_core_init[] = { /* set master volume and direct control */ { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, @@ -247,21 +212,6 @@ static struct snd_kcontrol_new stac922x_mixer[] = { { } /* end */ }; -/* This needs to be generated dynamically based on sequence */ -static struct snd_kcontrol_new stac9227_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, - HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x1b, 0x0, HDA_OUTPUT), - { } /* end */ -}; - static snd_kcontrol_new_t stac927x_mixer[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -341,17 +291,11 @@ static unsigned int d945gtp5_pin_configs[10] = { 0x02a19320, 0x40000100, }; -static unsigned int d965_2112_pin_configs[10] = { - 0x0221401f, 0x40000100, 0x40000100, 0x01014011, - 0x01a19021, 0x01813024, 0x01452130, 0x40000100, - 0x02a19320, 0x40000100, -}; - -static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { - [STAC_REF] = ref922x_pin_configs, - [STAC_D945GTP3] = d945gtp3_pin_configs, - [STAC_D945GTP5] = d945gtp5_pin_configs, - [STAC_D965_2112] = d965_2112_pin_configs, +static unsigned int *stac922x_brd_tbl[] = { + ref922x_pin_configs, + d945gtp3_pin_configs, + d945gtp5_pin_configs, + NULL, /* STAC_MACMINI */ }; static struct hda_board_config stac922x_cfg_tbl[] = { @@ -386,12 +330,6 @@ static struct hda_board_config stac922x_cfg_tbl[] = { { .pci_subvendor = 0x8384, .pci_subdevice = 0x7680, .config = STAC_MACMINI }, /* Apple Mac Mini (early 2006) */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2112, - .config = STAC_D965_2112 }, - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x284b, - .config = STAC_D965_284B }, {} /* terminator */ }; @@ -775,8 +713,7 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf * A and B is not supported. */ /* fill in the dac_nids table from the parsed pin configuration */ -static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, - const struct auto_pin_cfg *cfg) +static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { struct sigmatel_spec *spec = codec->spec; hda_nid_t nid; @@ -795,13 +732,10 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, } /* add playback controls from the parsed DAC table */ -static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, - const struct auto_pin_cfg *cfg) +static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, const struct auto_pin_cfg *cfg) { char name[32]; - static const char *chname[4] = { - "Front", "Surround", NULL /*CLFE*/, "Side" - }; + static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; hda_nid_t nid; int i, err; @@ -959,12 +893,10 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out return err; if (! spec->autocfg.line_outs) return 0; /* can't find valid pin config */ - if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) return err; - if (spec->multiout.num_dacs == 0) - if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) - return err; + if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) + return err; if ((err = stac92xx_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || (err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg)) < 0 || @@ -1262,8 +1194,7 @@ static int patch_stac922x(struct hda_codec *codec) codec->spec = spec; spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " - "using BIOS defaults\n"); + snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, using BIOS defaults\n"); else if (stac922x_brd_tbl[spec->board_config] != NULL) { spec->num_pins = 10; spec->pin_nids = stac922x_pin_nids; @@ -1279,25 +1210,6 @@ static int patch_stac922x(struct hda_codec *codec) spec->mixer = stac922x_mixer; spec->multiout.dac_nids = spec->dac_nids; - - switch (spec->board_config) { - case STAC_D965_2112: - spec->adc_nids = stac9227_adc_nids; - spec->mux_nids = stac9227_mux_nids; -#if 0 - spec->multiout.dac_nids = d965_2112_dac_nids; - spec->multiout.num_dacs = ARRAY_SIZE(d965_2112_dac_nids); -#endif - spec->init = d965_2112_core_init; - spec->mixer = stac9227_mixer; - break; - case STAC_D965_284B: - spec->adc_nids = stac9227_adc_nids; - spec->mux_nids = stac9227_mux_nids; - spec->init = stac9227_core_init; - spec->mixer = stac9227_mixer; - break; - } err = stac92xx_parse_auto_config(codec, 0x08, 0x09); if (err < 0) { diff --git a/trunk/sound/pci/ice1712/ice1712.c b/trunk/sound/pci/ice1712/ice1712.c index 89a06dec4365..845907159b74 100644 --- a/trunk/sound/pci/ice1712/ice1712.c +++ b/trunk/sound/pci/ice1712/ice1712.c @@ -2606,7 +2606,7 @@ static int __devinit snd_ice1712_create(struct snd_card *card, ice->dmapath_port = pci_resource_start(pci, 2); ice->profi_port = pci_resource_start(pci, 3); - if (request_irq(pci->irq, snd_ice1712_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_ice1712_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1712", ice)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_ice1712_free(ice); diff --git a/trunk/sound/pci/ice1712/ice1724.c b/trunk/sound/pci/ice1712/ice1724.c index ad69ed7c1b81..34a58c629f47 100644 --- a/trunk/sound/pci/ice1712/ice1724.c +++ b/trunk/sound/pci/ice1712/ice1724.c @@ -2253,7 +2253,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card, ice->profi_port = pci_resource_start(pci, 1); if (request_irq(pci->irq, snd_vt1724_interrupt, - IRQF_DISABLED|IRQF_SHARED, "ICE1724", ice)) { + SA_INTERRUPT|SA_SHIRQ, "ICE1724", ice)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_vt1724_free(ice); return -EIO; diff --git a/trunk/sound/pci/ice1712/revo.c b/trunk/sound/pci/ice1712/revo.c index fec9440cb310..b5754b32b802 100644 --- a/trunk/sound/pci/ice1712/revo.c +++ b/trunk/sound/pci/ice1712/revo.c @@ -87,25 +87,12 @@ static void revo_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) * initialize the chips on M-Audio Revolution cards */ -static unsigned int revo71_num_stereo_front[] = {2}; -static char *revo71_channel_names_front[] = {"PCM Playback Volume"}; - -static unsigned int revo71_num_stereo_surround[] = {1, 1, 2, 2}; -static char *revo71_channel_names_surround[] = {"PCM Center Playback Volume", "PCM LFE Playback Volume", - "PCM Side Playback Volume", "PCM Rear Playback Volume"}; - -static unsigned int revo51_num_stereo[] = {2, 1, 1, 2}; -static char *revo51_channel_names[] = {"PCM Playback Volume", "PCM Center Playback Volume", - "PCM LFE Playback Volume", "PCM Rear Playback Volume"}; - static struct snd_akm4xxx akm_revo_front __devinitdata = { .type = SND_AK4381, .num_dacs = 2, .ops = { .set_rate_val = revo_set_rate_val - }, - .num_stereo = revo71_num_stereo_front, - .channel_names = revo71_channel_names_front + } }; static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { @@ -126,9 +113,7 @@ static struct snd_akm4xxx akm_revo_surround __devinitdata = { .num_dacs = 6, .ops = { .set_rate_val = revo_set_rate_val - }, - .num_stereo = revo71_num_stereo_surround, - .channel_names = revo71_channel_names_surround + } }; static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { @@ -148,9 +133,7 @@ static struct snd_akm4xxx akm_revo51 __devinitdata = { .num_dacs = 6, .ops = { .set_rate_val = revo_set_rate_val - }, - .num_stereo = revo51_num_stereo, - .channel_names = revo51_channel_names + } }; static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { diff --git a/trunk/sound/pci/intel8x0.c b/trunk/sound/pci/intel8x0.c index 5634bc349257..edc14475ef82 100644 --- a/trunk/sound/pci/intel8x0.c +++ b/trunk/sound/pci/intel8x0.c @@ -2475,7 +2475,7 @@ static int intel8x0_resume(struct pci_dev *pci) pci_restore_state(pci); pci_enable_device(pci); pci_set_master(pci); - request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_DISABLED|IRQF_SHARED, + request_irq(pci->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, chip); chip->irq = pci->irq; synchronize_irq(chip->irq); @@ -2848,7 +2848,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card, /* request irq after initializaing int_sta_mask, etc */ if (request_irq(pci->irq, snd_intel8x0_interrupt, - IRQF_DISABLED|IRQF_SHARED, card->shortname, chip)) { + SA_INTERRUPT|SA_SHIRQ, card->shortname, chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_intel8x0_free(chip); return -EBUSY; diff --git a/trunk/sound/pci/intel8x0m.c b/trunk/sound/pci/intel8x0m.c index f28e273ae276..24703d75b65a 100644 --- a/trunk/sound/pci/intel8x0m.c +++ b/trunk/sound/pci/intel8x0m.c @@ -1185,7 +1185,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card, } port_inited: - if (request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_intel8x0_free(chip); diff --git a/trunk/sound/pci/korg1212/korg1212.c b/trunk/sound/pci/korg1212/korg1212.c index 2b4ce002794a..6e97932de34f 100644 --- a/trunk/sound/pci/korg1212/korg1212.c +++ b/trunk/sound/pci/korg1212/korg1212.c @@ -2237,7 +2237,7 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev * } err = request_irq(pci->irq, snd_korg1212_interrupt, - IRQF_DISABLED|IRQF_SHARED, + SA_INTERRUPT|SA_SHIRQ, "korg1212", korg1212); if (err) { diff --git a/trunk/sound/pci/maestro3.c b/trunk/sound/pci/maestro3.c index 828eab59253a..1c344fbd964d 100644 --- a/trunk/sound/pci/maestro3.c +++ b/trunk/sound/pci/maestro3.c @@ -2760,7 +2760,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip); - if (request_irq(pci->irq, snd_m3_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_m3_interrupt, SA_INTERRUPT|SA_SHIRQ, card->driver, chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_m3_free(chip); diff --git a/trunk/sound/pci/mixart/mixart.c b/trunk/sound/pci/mixart/mixart.c index a4aaa7b9a231..366c4a7e65c6 100644 --- a/trunk/sound/pci/mixart/mixart.c +++ b/trunk/sound/pci/mixart/mixart.c @@ -1319,7 +1319,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, pci_resource_len(pci, i)); } - if (request_irq(pci->irq, snd_mixart_interrupt, IRQF_DISABLED|IRQF_SHARED, CARD_NAME, (void *)mgr)) { + if (request_irq(pci->irq, snd_mixart_interrupt, SA_INTERRUPT|SA_SHIRQ, CARD_NAME, (void *)mgr)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_mixart_free(mgr); return -EBUSY; diff --git a/trunk/sound/pci/nm256/nm256.c b/trunk/sound/pci/nm256/nm256.c index 56d7282e6651..b92d6600deb9 100644 --- a/trunk/sound/pci/nm256/nm256.c +++ b/trunk/sound/pci/nm256/nm256.c @@ -465,7 +465,7 @@ static int snd_nm256_acquire_irq(struct nm256 *chip) { mutex_lock(&chip->irq_mutex); if (chip->irq < 0) { - if (request_irq(chip->pci->irq, chip->interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(chip->pci->irq, chip->interrupt, SA_INTERRUPT|SA_SHIRQ, chip->card->driver, chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->pci->irq); mutex_unlock(&chip->irq_mutex); diff --git a/trunk/sound/pci/pcxhr/pcxhr.c b/trunk/sound/pci/pcxhr/pcxhr.c index ae980e11827f..8198884b51ee 100644 --- a/trunk/sound/pci/pcxhr/pcxhr.c +++ b/trunk/sound/pci/pcxhr/pcxhr.c @@ -1250,7 +1250,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id mgr->pci = pci; mgr->irq = -1; - if (request_irq(pci->irq, pcxhr_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, pcxhr_interrupt, SA_INTERRUPT|SA_SHIRQ, card_name, mgr)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); pcxhr_free(mgr); diff --git a/trunk/sound/pci/riptide/riptide.c b/trunk/sound/pci/riptide/riptide.c index 5501a08ca23a..5618ec9740bd 100644 --- a/trunk/sound/pci/riptide/riptide.c +++ b/trunk/sound/pci/riptide/riptide.c @@ -1892,7 +1892,7 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci, UNSET_AIE(hwport); if (request_irq - (pci->irq, snd_riptide_interrupt, IRQF_DISABLED | IRQF_SHARED, + (pci->irq, snd_riptide_interrupt, SA_INTERRUPT | SA_SHIRQ, "RIPTIDE", chip)) { snd_printk(KERN_ERR "Riptide: unable to grab IRQ %d\n", pci->irq); diff --git a/trunk/sound/pci/rme32.c b/trunk/sound/pci/rme32.c index 2e24b68d07aa..2cb9fe98db2f 100644 --- a/trunk/sound/pci/rme32.c +++ b/trunk/sound/pci/rme32.c @@ -1374,7 +1374,7 @@ static int __devinit snd_rme32_create(struct rme32 * rme32) return -ENOMEM; } - if (request_irq(pci->irq, snd_rme32_interrupt, IRQF_DISABLED | IRQF_SHARED, "RME32", (void *) rme32)) { + if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); return -EBUSY; } diff --git a/trunk/sound/pci/rme96.c b/trunk/sound/pci/rme96.c index fde0f3e20530..991cb18c14f3 100644 --- a/trunk/sound/pci/rme96.c +++ b/trunk/sound/pci/rme96.c @@ -1588,7 +1588,7 @@ snd_rme96_create(struct rme96 *rme96) return -ENOMEM; } - if (request_irq(pci->irq, snd_rme96_interrupt, IRQF_DISABLED|IRQF_SHARED, "RME96", (void *)rme96)) { + if (request_irq(pci->irq, snd_rme96_interrupt, SA_INTERRUPT|SA_SHIRQ, "RME96", (void *)rme96)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); return -EBUSY; } diff --git a/trunk/sound/pci/rme9652/hdsp.c b/trunk/sound/pci/rme9652/hdsp.c index 99cf86244acb..eaf3c22449ad 100644 --- a/trunk/sound/pci/rme9652/hdsp.c +++ b/trunk/sound/pci/rme9652/hdsp.c @@ -4912,7 +4912,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card, return -EBUSY; } - if (request_irq(pci->irq, snd_hdsp_interrupt, IRQF_DISABLED|IRQF_SHARED, "hdsp", (void *)hdsp)) { + if (request_irq(pci->irq, snd_hdsp_interrupt, SA_INTERRUPT|SA_SHIRQ, "hdsp", (void *)hdsp)) { snd_printk(KERN_ERR "Hammerfall-DSP: unable to use IRQ %d\n", pci->irq); return -EBUSY; } diff --git a/trunk/sound/pci/rme9652/hdspm.c b/trunk/sound/pci/rme9652/hdspm.c index 7d03ae066d53..bba1615504d3 100644 --- a/trunk/sound/pci/rme9652/hdspm.c +++ b/trunk/sound/pci/rme9652/hdspm.c @@ -3497,7 +3497,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp hdspm->port + io_extent - 1); if (request_irq(pci->irq, snd_hdspm_interrupt, - IRQF_DISABLED | IRQF_SHARED, "hdspm", + SA_INTERRUPT | SA_SHIRQ, "hdspm", (void *) hdspm)) { snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); return -EBUSY; diff --git a/trunk/sound/pci/rme9652/rme9652.c b/trunk/sound/pci/rme9652/rme9652.c index 9534e1834138..3b945e8c1b15 100644 --- a/trunk/sound/pci/rme9652/rme9652.c +++ b/trunk/sound/pci/rme9652/rme9652.c @@ -2500,7 +2500,7 @@ static int __devinit snd_rme9652_create(struct snd_card *card, return -EBUSY; } - if (request_irq(pci->irq, snd_rme9652_interrupt, IRQF_DISABLED|IRQF_SHARED, "rme9652", (void *)rme9652)) { + if (request_irq(pci->irq, snd_rme9652_interrupt, SA_INTERRUPT|SA_SHIRQ, "rme9652", (void *)rme9652)) { snd_printk(KERN_ERR "unable to request IRQ %d\n", pci->irq); return -EBUSY; } diff --git a/trunk/sound/pci/sonicvibes.c b/trunk/sound/pci/sonicvibes.c index c4303418668b..dcf402948347 100644 --- a/trunk/sound/pci/sonicvibes.c +++ b/trunk/sound/pci/sonicvibes.c @@ -1257,7 +1257,7 @@ static int __devinit snd_sonicvibes_create(struct snd_card *card, sonic->midi_port = pci_resource_start(pci, 3); sonic->game_port = pci_resource_start(pci, 4); - if (request_irq(pci->irq, snd_sonicvibes_interrupt, IRQF_DISABLED|IRQF_SHARED, "S3 SonicVibes", (void *)sonic)) { + if (request_irq(pci->irq, snd_sonicvibes_interrupt, SA_INTERRUPT|SA_SHIRQ, "S3 SonicVibes", (void *)sonic)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_sonicvibes_free(sonic); return -EBUSY; @@ -1441,10 +1441,10 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci, strcpy(card->driver, "SonicVibes"); strcpy(card->shortname, "S3 SonicVibes"); - sprintf(card->longname, "%s rev %i at 0x%llx, irq %i", + sprintf(card->longname, "%s rev %i at 0x%lx, irq %i", card->shortname, sonic->revision, - (unsigned long long)pci_resource_start(pci, 1), + pci_resource_start(pci, 1), sonic->irq); if ((err = snd_sonicvibes_pcm(sonic, 0, NULL)) < 0) { diff --git a/trunk/sound/pci/trident/trident_main.c b/trunk/sound/pci/trident/trident_main.c index 4930cc6b054d..d99ed7237750 100644 --- a/trunk/sound/pci/trident/trident_main.c +++ b/trunk/sound/pci/trident/trident_main.c @@ -3599,7 +3599,7 @@ int __devinit snd_trident_create(struct snd_card *card, } trident->port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_trident_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_trident_interrupt, SA_INTERRUPT|SA_SHIRQ, "Trident Audio", trident)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_trident_free(trident); diff --git a/trunk/sound/pci/via82xx.c b/trunk/sound/pci/via82xx.c index 37bd5eb7a380..2527bbd958c5 100644 --- a/trunk/sound/pci/via82xx.c +++ b/trunk/sound/pci/via82xx.c @@ -2281,7 +2281,7 @@ static int __devinit snd_via82xx_create(struct snd_card *card, if (request_irq(pci->irq, chip_type == TYPE_VIA8233 ? snd_via8233_interrupt : snd_via686_interrupt, - IRQF_DISABLED|IRQF_SHARED, + SA_INTERRUPT|SA_SHIRQ, card->driver, chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_via82xx_free(chip); diff --git a/trunk/sound/pci/via82xx_modem.c b/trunk/sound/pci/via82xx_modem.c index c1ede6c2a6d4..577a2b03759f 100644 --- a/trunk/sound/pci/via82xx_modem.c +++ b/trunk/sound/pci/via82xx_modem.c @@ -1118,7 +1118,7 @@ static int __devinit snd_via82xx_create(struct snd_card *card, return err; } chip->port = pci_resource_start(pci, 0); - if (request_irq(pci->irq, snd_via82xx_interrupt, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_via82xx_interrupt, SA_INTERRUPT|SA_SHIRQ, card->driver, chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_via82xx_free(chip); diff --git a/trunk/sound/pci/vx222/vx222.c b/trunk/sound/pci/vx222/vx222.c index 7deda25f7adc..0f1ebb010a5e 100644 --- a/trunk/sound/pci/vx222/vx222.c +++ b/trunk/sound/pci/vx222/vx222.c @@ -162,7 +162,7 @@ static int __devinit snd_vx222_create(struct snd_card *card, struct pci_dev *pci for (i = 0; i < 2; i++) vx->port[i] = pci_resource_start(pci, i + 1); - if (request_irq(pci->irq, snd_vx_irq_handler, IRQF_DISABLED|IRQF_SHARED, + if (request_irq(pci->irq, snd_vx_irq_handler, SA_INTERRUPT|SA_SHIRQ, CARD_NAME, (void *) chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_vx222_free(chip); diff --git a/trunk/sound/pci/ymfpci/ymfpci_main.c b/trunk/sound/pci/ymfpci/ymfpci_main.c index a55b5fd7da64..f894752523bb 100644 --- a/trunk/sound/pci/ymfpci/ymfpci_main.c +++ b/trunk/sound/pci/ymfpci/ymfpci_main.c @@ -2288,7 +2288,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card, snd_ymfpci_free(chip); return -EBUSY; } - if (request_irq(pci->irq, snd_ymfpci_interrupt, IRQF_DISABLED|IRQF_SHARED, "YMFPCI", (void *) chip)) { + if (request_irq(pci->irq, snd_ymfpci_interrupt, SA_INTERRUPT|SA_SHIRQ, "YMFPCI", (void *) chip)) { snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); snd_ymfpci_free(chip); return -EBUSY; diff --git a/trunk/sound/ppc/pmac.c b/trunk/sound/ppc/pmac.c index 641430631505..b678814975c9 100644 --- a/trunk/sound/ppc/pmac.c +++ b/trunk/sound/ppc/pmac.c @@ -1120,7 +1120,6 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) struct snd_pmac *chip; struct device_node *np; int i, err; - unsigned int irq; unsigned long ctrl_addr, txdma_addr, rxdma_addr; static struct snd_device_ops ops = { .dev_free = snd_pmac_dev_free, @@ -1154,6 +1153,10 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) if (chip->is_k2) { static char *rnames[] = { "Sound Control", "Sound DMA" }; + if (np->n_intrs < 3) { + err = -ENODEV; + goto __error; + } for (i = 0; i < 2; i ++) { if (of_address_to_resource(np->parent, i, &chip->rsrc[i])) { @@ -1167,10 +1170,9 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) chip->rsrc[i].start + 1, rnames[i]) == NULL) { printk(KERN_ERR "snd: can't request rsrc " - " %d (%s: 0x%016llx:%016llx)\n", - i, rnames[i], - (unsigned long long)chip->rsrc[i].start, - (unsigned long long)chip->rsrc[i].end); + " %d (%s: 0x%08lx:%08lx)\n", + i, rnames[i], chip->rsrc[i].start, + chip->rsrc[i].end); err = -ENODEV; goto __error; } @@ -1182,6 +1184,10 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) } else { static char *rnames[] = { "Sound Control", "Sound Tx DMA", "Sound Rx DMA" }; + if (np->n_intrs < 3) { + err = -ENODEV; + goto __error; + } for (i = 0; i < 3; i ++) { if (of_address_to_resource(np, i, &chip->rsrc[i])) { @@ -1195,10 +1201,9 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) chip->rsrc[i].start + 1, rnames[i]) == NULL) { printk(KERN_ERR "snd: can't request rsrc " - " %d (%s: 0x%016llx:%016llx)\n", - i, rnames[i], - (unsigned long long)chip->rsrc[i].start, - (unsigned long long)chip->rsrc[i].end); + " %d (%s: 0x%08lx:%08lx)\n", + i, rnames[i], chip->rsrc[i].start, + chip->rsrc[i].end); err = -ENODEV; goto __error; } @@ -1213,30 +1218,28 @@ int __init snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return) chip->playback.dma = ioremap(txdma_addr, 0x100); chip->capture.dma = ioremap(rxdma_addr, 0x100); if (chip->model <= PMAC_BURGUNDY) { - irq = irq_of_parse_and_map(np, 0); - if (request_irq(irq, snd_pmac_ctrl_intr, 0, + if (request_irq(np->intrs[0].line, snd_pmac_ctrl_intr, 0, "PMac", (void*)chip)) { - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", - irq); + snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", np->intrs[0].line); err = -EBUSY; goto __error; } - chip->irq = irq; + chip->irq = np->intrs[0].line; } - irq = irq_of_parse_and_map(np, 1); - if (request_irq(irq, snd_pmac_tx_intr, 0, "PMac Output", (void*)chip)){ - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", irq); + if (request_irq(np->intrs[1].line, snd_pmac_tx_intr, 0, + "PMac Output", (void*)chip)) { + snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", np->intrs[1].line); err = -EBUSY; goto __error; } - chip->tx_irq = irq; - irq = irq_of_parse_and_map(np, 2); - if (request_irq(irq, snd_pmac_rx_intr, 0, "PMac Input", (void*)chip)) { - snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", irq); + chip->tx_irq = np->intrs[1].line; + if (request_irq(np->intrs[2].line, snd_pmac_rx_intr, 0, + "PMac Input", (void*)chip)) { + snd_printk(KERN_ERR "pmac: unable to grab IRQ %d\n", np->intrs[2].line); err = -EBUSY; goto __error; } - chip->rx_irq = irq; + chip->rx_irq = np->intrs[2].line; snd_pmac_sound_feature(chip, 1); diff --git a/trunk/sound/ppc/toonie.c b/trunk/sound/ppc/toonie.c new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/trunk/sound/ppc/tumbler.c b/trunk/sound/ppc/tumbler.c index 692c61177678..70e4ebc70260 100644 --- a/trunk/sound/ppc/tumbler.c +++ b/trunk/sound/ppc/tumbler.c @@ -1121,7 +1121,7 @@ static long tumbler_find_device(const char *device, const char *platform, DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n", device, gp->addr, gp->active_state); - return irq_of_parse_and_map(node, 0); + return (node->n_intrs > 0) ? node->intrs[0].line : 0; } /* reset audio */ @@ -1264,16 +1264,16 @@ static int __init tumbler_init(struct snd_pmac *chip) &mix->line_mute, 1); irq = tumbler_find_device("headphone-detect", NULL, &mix->hp_detect, 0); - if (irq <= NO_IRQ) + if (irq < 0) irq = tumbler_find_device("headphone-detect", NULL, &mix->hp_detect, 1); - if (irq <= NO_IRQ) + if (irq < 0) irq = tumbler_find_device("keywest-gpio15", NULL, &mix->hp_detect, 1); mix->headphone_irq = irq; irq = tumbler_find_device("line-output-detect", NULL, &mix->line_detect, 0); - if (irq <= NO_IRQ) + if (irq < 0) irq = tumbler_find_device("line-output-detect", NULL, &mix->line_detect, 1); mix->lineout_irq = irq; diff --git a/trunk/sound/sound_core.c b/trunk/sound/sound_core.c index 62d4d0c81261..6f849720aef3 100644 --- a/trunk/sound/sound_core.c +++ b/trunk/sound/sound_core.c @@ -34,6 +34,7 @@ * locking at some point in 2.3.x. */ +#include #include #include #include @@ -43,6 +44,7 @@ #include #include #include +#include #include #define SOUND_STEP 16 @@ -170,6 +172,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati else sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP); + devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor), + S_IFCHR | mode, s->name); class_device_create(sound_class, NULL, MKDEV(SOUND_MAJOR, s->unit_minor), dev, s->name+6); return r; @@ -193,6 +197,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit) p = __sound_remove_unit(list, unit); spin_unlock(&sound_loader_lock); if (p) { + devfs_remove(p->name); class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor)); kfree(p); } @@ -565,6 +570,7 @@ static void __exit cleanup_soundcore(void) /* We have nothing to really do here - we know the lists must be empty */ unregister_chrdev(SOUND_MAJOR, "sound"); + devfs_remove("sound"); class_destroy(sound_class); } @@ -574,6 +580,7 @@ static int __init init_soundcore(void) printk(KERN_ERR "soundcore: sound device already in use.\n"); return -EBUSY; } + devfs_mk_dir ("sound"); sound_class = class_create(THIS_MODULE, "sound"); if (IS_ERR(sound_class)) return PTR_ERR(sound_class); diff --git a/trunk/sound/sparc/amd7930.c b/trunk/sound/sparc/amd7930.c index db3e22efd02e..ba1b2a3443d3 100644 --- a/trunk/sound/sparc/amd7930.c +++ b/trunk/sound/sparc/amd7930.c @@ -973,7 +973,7 @@ static int __init snd_amd7930_create(struct snd_card *card, amd7930_idle(amd); if (request_irq(irq, snd_amd7930_interrupt, - IRQF_DISABLED | IRQF_SHARED, "amd7930", amd)) { + SA_INTERRUPT | SA_SHIRQ, "amd7930", amd)) { snd_printk("amd7930-%d: Unable to grab IRQ %d\n", dev, irq); snd_amd7930_free(amd); diff --git a/trunk/sound/sparc/cs4231.c b/trunk/sound/sparc/cs4231.c index 5018fcf41df5..da54d04a3e3a 100644 --- a/trunk/sound/sparc/cs4231.c +++ b/trunk/sound/sparc/cs4231.c @@ -8,6 +8,7 @@ * Copyright (c) by Jaroslav Kysela */ +#include #include #include #include @@ -2001,7 +2002,7 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, chip->c_dma.preallocate = sbus_dma_preallocate; if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, - IRQF_SHARED, "cs4231", chip)) { + SA_SHIRQ, "cs4231", chip)) { snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %d\n", dev, sdev->irqs[0]); snd_cs4231_sbus_free(chip); @@ -2036,10 +2037,10 @@ static int __init cs4231_sbus_attach(struct sbus_dev *sdev) if (err) return err; - sprintf(card->longname, "%s at 0x%02lx:0x%016lx, irq %d", + sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %d", card->shortname, rp->flags & 0xffL, - (unsigned long long)rp->start, + rp->start, sdev->irqs[0]); if ((err = snd_cs4231_sbus_create(card, sdev, dev, &cp)) < 0) { diff --git a/trunk/sound/sparc/dbri.c b/trunk/sound/sparc/dbri.c index 59a02a0d9afc..5eecdd09a79d 100644 --- a/trunk/sound/sparc/dbri.c +++ b/trunk/sound/sparc/dbri.c @@ -46,7 +46,7 @@ * * I've tried to stick to the following function naming conventions: * snd_* ALSA stuff - * cs4215_* CS4215 codec specific stuff + * cs4215_* CS4215 codec specfic stuff * dbri_* DBRI high-level stuff * other DBRI low-level stuff */ @@ -2569,7 +2569,7 @@ static int __init snd_dbri_create(struct snd_card *card, return -EIO; } - err = request_irq(dbri->irq, snd_dbri_interrupt, IRQF_SHARED, + err = request_irq(dbri->irq, snd_dbri_interrupt, SA_SHIRQ, "DBRI audio", dbri); if (err) { printk(KERN_ERR "DBRI: Can't get irq %d\n", dbri->irq); @@ -2645,9 +2645,9 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) strcpy(card->driver, "DBRI"); strcpy(card->shortname, "Sun DBRI"); rp = &sdev->resource[0]; - sprintf(card->longname, "%s at 0x%02lx:0x%016lx, irq %d", + sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %d", card->shortname, - rp->flags & 0xffL, (unsigned long long)rp->start, irq.pri); + rp->flags & 0xffL, rp->start, irq.pri); if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) { snd_card_free(card); diff --git a/trunk/sound/usb/usbaudio.c b/trunk/sound/usb/usbaudio.c index d32d83d970cc..627de9525a32 100644 --- a/trunk/sound/usb/usbaudio.c +++ b/trunk/sound/usb/usbaudio.c @@ -3095,32 +3095,6 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev) return 0; } -/* - * C-Media CM106/CM106+ have four 16-bit internal registers that are nicely - * documented in the device's data sheet. - */ -static int snd_usb_cm106_write_int_reg(struct usb_device *dev, int reg, u16 value) -{ - u8 buf[4]; - buf[0] = 0x20; - buf[1] = value & 0xff; - buf[2] = (value >> 8) & 0xff; - buf[3] = reg; - return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT, - 0, 0, &buf, 4, 1000); -} - -static int snd_usb_cm106_boot_quirk(struct usb_device *dev) -{ - /* - * Enable line-out driver mode, set headphone source to front - * channels, enable stereo mic. - */ - return snd_usb_cm106_write_int_reg(dev, 2, 0x8004); -} - - /* * Setup quirks */ @@ -3391,12 +3365,6 @@ static void *snd_usb_audio_probe(struct usb_device *dev, goto __err_val; } - /* C-Media CM106 / Turtle Beach Audio Advantage Roadie */ - if (id == USB_ID(0x10f5, 0x0200)) { - if (snd_usb_cm106_boot_quirk(dev) < 0) - goto __err_val; - } - /* * found a config. now register to ALSA */ diff --git a/trunk/usr/Makefile b/trunk/usr/Makefile index e93824269da2..19d74e6f2685 100644 --- a/trunk/usr/Makefile +++ b/trunk/usr/Makefile @@ -21,7 +21,8 @@ ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \ $(CONFIG_INITRAMFS_SOURCE),-d) ramfs-args := \ $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \ - $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) + $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \ + $(ramfs-input) # .initramfs_data.cpio.gz.d is used to identify all files included # in initramfs and to detect if any files are added/removed.