diff options
780 files changed, 22996 insertions, 7789 deletions
| @@ -1127,8 +1127,10 @@ S: Carnegie, Pennsylvania 15106-4304 | |||
| 1127 | S: USA | 1127 | S: USA |
| 1128 | 1128 | ||
| 1129 | N: Philip Gladstone | 1129 | N: Philip Gladstone |
| 1130 | E: philip@raptor.com | 1130 | E: philip@gladstonefamily.net |
| 1131 | D: Kernel / timekeeping stuff | 1131 | D: Kernel / timekeeping stuff |
| 1132 | S: Carlisle, MA 01741 | ||
| 1133 | S: USA | ||
| 1132 | 1134 | ||
| 1133 | N: Jan-Benedict Glaw | 1135 | N: Jan-Benedict Glaw |
| 1134 | E: jbglaw@lug-owl.de | 1136 | E: jbglaw@lug-owl.de |
| @@ -3741,10 +3743,11 @@ D: Mylex DAC960 PCI RAID driver | |||
| 3741 | D: Miscellaneous kernel fixes | 3743 | D: Miscellaneous kernel fixes |
| 3742 | 3744 | ||
| 3743 | N: Alessandro Zummo | 3745 | N: Alessandro Zummo |
| 3744 | E: azummo@ita.flashnet.it | 3746 | E: a.zummo@towertech.it |
| 3745 | W: http://freepage.logicom.it/azummo/ | ||
| 3746 | D: CMI8330 support is sb_card.c | 3747 | D: CMI8330 support is sb_card.c |
| 3747 | D: ISAPnP fixes in sb_card.c | 3748 | D: ISAPnP fixes in sb_card.c |
| 3749 | D: ZyXEL omni.net lcd plus driver | ||
| 3750 | D: RTC subsystem | ||
| 3748 | S: Italy | 3751 | S: Italy |
| 3749 | 3752 | ||
| 3750 | N: Marc Zyngier | 3753 | N: Marc Zyngier |
diff --git a/Documentation/DMA-mapping.txt b/Documentation/DMA-mapping.txt index 684557474c15..ee4bb73683cd 100644 --- a/Documentation/DMA-mapping.txt +++ b/Documentation/DMA-mapping.txt | |||
| @@ -199,6 +199,8 @@ address during PCI bus mastering you might do something like: | |||
| 199 | "mydev: 24-bit DMA addressing not available.\n"); | 199 | "mydev: 24-bit DMA addressing not available.\n"); |
| 200 | goto ignore_this_device; | 200 | goto ignore_this_device; |
| 201 | } | 201 | } |
| 202 | [Better use DMA_24BIT_MASK instead of 0x00ffffff. | ||
| 203 | See linux/include/dma-mapping.h for reference.] | ||
| 202 | 204 | ||
| 203 | When pci_set_dma_mask() is successful, and returns zero, the PCI layer | 205 | When pci_set_dma_mask() is successful, and returns zero, the PCI layer |
| 204 | saves away this mask you have provided. The PCI layer will use this | 206 | saves away this mask you have provided. The PCI layer will use this |
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index b4ea51ad3610..07cb93b82ba9 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt | |||
| @@ -605,7 +605,7 @@ are the same as those shown in the preceding section, so they are omitted. | |||
| 605 | { | 605 | { |
| 606 | int cpu; | 606 | int cpu; |
| 607 | 607 | ||
| 608 | for_each_cpu(cpu) | 608 | for_each_possible_cpu(cpu) |
| 609 | run_on(cpu); | 609 | run_on(cpu); |
| 610 | } | 610 | } |
| 611 | 611 | ||
diff --git a/Documentation/arm/SA1100/Assabet b/Documentation/arm/SA1100/Assabet index cbbe5587c78d..78bc1c1b04e5 100644 --- a/Documentation/arm/SA1100/Assabet +++ b/Documentation/arm/SA1100/Assabet | |||
| @@ -26,7 +26,7 @@ Installing a bootloader | |||
| 26 | 26 | ||
| 27 | A couple of bootloaders able to boot Linux on Assabet are available: | 27 | A couple of bootloaders able to boot Linux on Assabet are available: |
| 28 | 28 | ||
| 29 | BLOB (http://www.lart.tudelft.nl/lartware/blob/) | 29 | BLOB (http://www.lartmaker.nl/lartware/blob/) |
| 30 | 30 | ||
| 31 | BLOB is a bootloader used within the LART project. Some contributed | 31 | BLOB is a bootloader used within the LART project. Some contributed |
| 32 | patches were merged into BLOB to add support for Assabet. | 32 | patches were merged into BLOB to add support for Assabet. |
diff --git a/Documentation/arm/SA1100/LART b/Documentation/arm/SA1100/LART index 2f73f513e16a..6d412b685598 100644 --- a/Documentation/arm/SA1100/LART +++ b/Documentation/arm/SA1100/LART | |||
| @@ -11,4 +11,4 @@ is under development, with plenty of others in different stages of | |||
| 11 | planning. | 11 | planning. |
| 12 | 12 | ||
| 13 | The hardware designs for this board have been released under an open license; | 13 | The hardware designs for this board have been released under an open license; |
| 14 | see the LART page at http://www.lart.tudelft.nl/ for more information. | 14 | see the LART page at http://www.lartmaker.nl/ for more information. |
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 8e63831971d5..f989a9e839b4 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt | |||
| @@ -132,8 +132,18 @@ Some new queue property settings: | |||
| 132 | limit. No highmem default. | 132 | limit. No highmem default. |
| 133 | 133 | ||
| 134 | blk_queue_max_sectors(q, max_sectors) | 134 | blk_queue_max_sectors(q, max_sectors) |
| 135 | Maximum size request you can handle in units of 512 byte | 135 | Sets two variables that limit the size of the request. |
| 136 | sectors. 255 default. | 136 | |
| 137 | - The request queue's max_sectors, which is a soft size in | ||
| 138 | in units of 512 byte sectors, and could be dynamically varied | ||
| 139 | by the core kernel. | ||
| 140 | |||
| 141 | - The request queue's max_hw_sectors, which is a hard limit | ||
| 142 | and reflects the maximum size request a driver can handle | ||
| 143 | in units of 512 byte sectors. | ||
| 144 | |||
| 145 | The default for both max_sectors and max_hw_sectors is | ||
| 146 | 255. The upper limit of max_sectors is 1024. | ||
| 137 | 147 | ||
| 138 | blk_queue_max_phys_segments(q, max_segments) | 148 | blk_queue_max_phys_segments(q, max_segments) |
| 139 | Maximum physical segments you can handle in a request. 128 | 149 | Maximum physical segments you can handle in a request. 128 |
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt index 57a09f99ecb0..1bcf69996c9d 100644 --- a/Documentation/cpu-hotplug.txt +++ b/Documentation/cpu-hotplug.txt | |||
| @@ -97,13 +97,13 @@ at which time hotplug is disabled. | |||
| 97 | 97 | ||
| 98 | You really dont need to manipulate any of the system cpu maps. They should | 98 | You really dont need to manipulate any of the system cpu maps. They should |
| 99 | be read-only for most use. When setting up per-cpu resources almost always use | 99 | be read-only for most use. When setting up per-cpu resources almost always use |
| 100 | cpu_possible_map/for_each_cpu() to iterate. | 100 | cpu_possible_map/for_each_possible_cpu() to iterate. |
| 101 | 101 | ||
| 102 | Never use anything other than cpumask_t to represent bitmap of CPUs. | 102 | Never use anything other than cpumask_t to represent bitmap of CPUs. |
| 103 | 103 | ||
| 104 | #include <linux/cpumask.h> | 104 | #include <linux/cpumask.h> |
| 105 | 105 | ||
| 106 | for_each_cpu - Iterate over cpu_possible_map | 106 | for_each_possible_cpu - Iterate over cpu_possible_map |
| 107 | for_each_online_cpu - Iterate over cpu_online_map | 107 | for_each_online_cpu - Iterate over cpu_online_map |
| 108 | for_each_present_cpu - Iterate over cpu_present_map | 108 | for_each_present_cpu - Iterate over cpu_present_map |
| 109 | for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask. | 109 | for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask. |
diff --git a/Documentation/cputopology.txt b/Documentation/cputopology.txt index ff280e2e1613..2b28e9ec4e3a 100644 --- a/Documentation/cputopology.txt +++ b/Documentation/cputopology.txt | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | 1 | ||
| 2 | Export cpu topology info by sysfs. Items (attributes) are similar | 2 | Export cpu topology info via sysfs. Items (attributes) are similar |
| 3 | to /proc/cpuinfo. | 3 | to /proc/cpuinfo. |
| 4 | 4 | ||
| 5 | 1) /sys/devices/system/cpu/cpuX/topology/physical_package_id: | 5 | 1) /sys/devices/system/cpu/cpuX/topology/physical_package_id: |
| @@ -12,7 +12,7 @@ represent the thread siblings to cpu X in the same core; | |||
| 12 | represent the thread siblings to cpu X in the same physical package; | 12 | represent the thread siblings to cpu X in the same physical package; |
| 13 | 13 | ||
| 14 | To implement it in an architecture-neutral way, a new source file, | 14 | To implement it in an architecture-neutral way, a new source file, |
| 15 | driver/base/topology.c, is to export the 5 attributes. | 15 | drivers/base/topology.c, is to export the 4 attributes. |
| 16 | 16 | ||
| 17 | If one architecture wants to support this feature, it just needs to | 17 | If one architecture wants to support this feature, it just needs to |
| 18 | implement 4 defines, typically in file include/asm-XXX/topology.h. | 18 | implement 4 defines, typically in file include/asm-XXX/topology.h. |
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX index 74052d22d868..66fdc0744fe0 100644 --- a/Documentation/filesystems/00-INDEX +++ b/Documentation/filesystems/00-INDEX | |||
| @@ -1,27 +1,47 @@ | |||
| 1 | 00-INDEX | 1 | 00-INDEX |
| 2 | - this file (info on some of the filesystems supported by linux). | 2 | - this file (info on some of the filesystems supported by linux). |
| 3 | Exporting | ||
| 4 | - explanation of how to make filesystems exportable. | ||
| 3 | Locking | 5 | Locking |
| 4 | - info on locking rules as they pertain to Linux VFS. | 6 | - info on locking rules as they pertain to Linux VFS. |
| 5 | adfs.txt | 7 | adfs.txt |
| 6 | - info and mount options for the Acorn Advanced Disc Filing System. | 8 | - info and mount options for the Acorn Advanced Disc Filing System. |
| 9 | afs.txt | ||
| 10 | - info and examples for the distributed AFS (Andrew File System) fs. | ||
| 7 | affs.txt | 11 | affs.txt |
| 8 | - info and mount options for the Amiga Fast File System. | 12 | - info and mount options for the Amiga Fast File System. |
| 13 | automount-support.txt | ||
| 14 | - information about filesystem automount support. | ||
| 15 | befs.txt | ||
| 16 | - information about the BeOS filesystem for Linux. | ||
| 9 | bfs.txt | 17 | bfs.txt |
| 10 | - info for the SCO UnixWare Boot Filesystem (BFS). | 18 | - info for the SCO UnixWare Boot Filesystem (BFS). |
| 11 | cifs.txt | 19 | cifs.txt |
| 12 | - description of the CIFS filesystem | 20 | - description of the CIFS filesystem. |
| 13 | coda.txt | 21 | coda.txt |
| 14 | - description of the CODA filesystem. | 22 | - description of the CODA filesystem. |
| 15 | configfs/ | 23 | configfs/ |
| 16 | - directory containing configfs documentation and example code. | 24 | - directory containing configfs documentation and example code. |
| 17 | cramfs.txt | 25 | cramfs.txt |
| 18 | - info on the cram filesystem for small storage (ROMs etc) | 26 | - info on the cram filesystem for small storage (ROMs etc). |
| 27 | dentry-locking.txt | ||
| 28 | - info on the RCU-based dcache locking model. | ||
| 19 | devfs/ | 29 | devfs/ |
| 20 | - directory containing devfs documentation. | 30 | - directory containing devfs documentation. |
| 31 | directory-locking | ||
| 32 | - info about the locking scheme used for directory operations. | ||
| 21 | dlmfs.txt | 33 | dlmfs.txt |
| 22 | - info on the userspace interface to the OCFS2 DLM. | 34 | - info on the userspace interface to the OCFS2 DLM. |
| 23 | ext2.txt | 35 | ext2.txt |
| 24 | - info, mount options and specifications for the Ext2 filesystem. | 36 | - info, mount options and specifications for the Ext2 filesystem. |
| 37 | ext3.txt | ||
| 38 | - info, mount options and specifications for the Ext3 filesystem. | ||
| 39 | files.txt | ||
| 40 | - info on file management in the Linux kernel. | ||
| 41 | fuse.txt | ||
| 42 | - info on the Filesystem in User SpacE including mount options. | ||
| 43 | hfs.txt | ||
| 44 | - info on the Macintosh HFS Filesystem for Linux. | ||
| 25 | hpfs.txt | 45 | hpfs.txt |
| 26 | - info and mount options for the OS/2 HPFS. | 46 | - info and mount options for the OS/2 HPFS. |
| 27 | isofs.txt | 47 | isofs.txt |
| @@ -32,23 +52,43 @@ ncpfs.txt | |||
| 32 | - info on Novell Netware(tm) filesystem using NCP protocol. | 52 | - info on Novell Netware(tm) filesystem using NCP protocol. |
| 33 | ntfs.txt | 53 | ntfs.txt |
| 34 | - info and mount options for the NTFS filesystem (Windows NT). | 54 | - info and mount options for the NTFS filesystem (Windows NT). |
| 35 | proc.txt | ||
| 36 | - info on Linux's /proc filesystem. | ||
| 37 | ocfs2.txt | 55 | ocfs2.txt |
| 38 | - info and mount options for the OCFS2 clustered filesystem. | 56 | - info and mount options for the OCFS2 clustered filesystem. |
| 57 | porting | ||
| 58 | - various information on filesystem porting. | ||
| 59 | proc.txt | ||
| 60 | - info on Linux's /proc filesystem. | ||
| 61 | ramfs-rootfs-initramfs.txt | ||
| 62 | - info on the 'in memory' filesystems ramfs, rootfs and initramfs. | ||
| 63 | reiser4.txt | ||
| 64 | - info on the Reiser4 filesystem based on dancing tree algorithms. | ||
| 65 | relayfs.txt | ||
| 66 | - info on relayfs, for efficient streaming from kernel to user space. | ||
| 39 | romfs.txt | 67 | romfs.txt |
| 40 | - Description of the ROMFS filesystem. | 68 | - description of the ROMFS filesystem. |
| 41 | smbfs.txt | 69 | smbfs.txt |
| 42 | - info on using filesystems with the SMB protocol (Windows 3.11 and NT) | 70 | - info on using filesystems with the SMB protocol (Win 3.11 and NT). |
| 71 | spufs.txt | ||
| 72 | - info and mount options for the SPU filesystem used on Cell. | ||
| 73 | sysfs-pci.txt | ||
| 74 | - info on accessing PCI device resources through sysfs. | ||
| 75 | sysfs.txt | ||
| 76 | - info on sysfs, a ram-based filesystem for exporting kernel objects. | ||
| 43 | sysv-fs.txt | 77 | sysv-fs.txt |
| 44 | - info on the SystemV/V7/Xenix/Coherent filesystem. | 78 | - info on the SystemV/V7/Xenix/Coherent filesystem. |
| 79 | tmpfs.txt | ||
| 80 | - info on tmpfs, a filesystem that holds all files in virtual memory. | ||
| 45 | udf.txt | 81 | udf.txt |
| 46 | - info and mount options for the UDF filesystem. | 82 | - info and mount options for the UDF filesystem. |
| 47 | ufs.txt | 83 | ufs.txt |
| 48 | - info on the ufs filesystem. | 84 | - info on the ufs filesystem. |
| 85 | v9fs.txt | ||
| 86 | - v9fs is a Unix implementation of the Plan 9 9p remote fs protocol. | ||
| 49 | vfat.txt | 87 | vfat.txt |
| 50 | - info on using the VFAT filesystem used in Windows NT and Windows 95 | 88 | - info on using the VFAT filesystem used in Windows NT and Windows 95 |
| 51 | vfs.txt | 89 | vfs.txt |
| 52 | - Overview of the Virtual File System | 90 | - overview of the Virtual File System |
| 53 | xfs.txt | 91 | xfs.txt |
| 54 | - info and mount options for the XFS filesystem. | 92 | - info and mount options for the XFS filesystem. |
| 93 | xip.txt | ||
| 94 | - info on execute-in-place for file mappings. | ||
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt index aa7ba00ec082..171a44ebd939 100644 --- a/Documentation/ioctl-number.txt +++ b/Documentation/ioctl-number.txt | |||
| @@ -78,8 +78,6 @@ Code Seq# Include File Comments | |||
| 78 | '#' 00-3F IEEE 1394 Subsystem Block for the entire subsystem | 78 | '#' 00-3F IEEE 1394 Subsystem Block for the entire subsystem |
| 79 | '1' 00-1F <linux/timepps.h> PPS kit from Ulrich Windl | 79 | '1' 00-1F <linux/timepps.h> PPS kit from Ulrich Windl |
| 80 | <ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/> | 80 | <ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/> |
| 81 | '6' 00-10 <asm-i386/processor.h> Intel IA32 microcode update driver | ||
| 82 | <mailto:tigran@veritas.com> | ||
| 83 | '8' all SNP8023 advanced NIC card | 81 | '8' all SNP8023 advanced NIC card |
| 84 | <mailto:mcr@solidum.com> | 82 | <mailto:mcr@solidum.com> |
| 85 | 'A' 00-1F linux/apm_bios.h | 83 | 'A' 00-1F linux/apm_bios.h |
diff --git a/Documentation/m68k/README.buddha b/Documentation/m68k/README.buddha index bf802ffc98ad..ef484a719bb9 100644 --- a/Documentation/m68k/README.buddha +++ b/Documentation/m68k/README.buddha | |||
| @@ -29,7 +29,7 @@ address is written to $4a, then the whole Byte is written to | |||
| 29 | $48, while it doesn't matter how often you're writing to $4a | 29 | $48, while it doesn't matter how often you're writing to $4a |
| 30 | as long as $48 is not touched. After $48 has been written, | 30 | as long as $48 is not touched. After $48 has been written, |
| 31 | the whole card disappears from $e8 and is mapped to the new | 31 | the whole card disappears from $e8 and is mapped to the new |
| 32 | address just written. Make shure $4a is written before $48, | 32 | address just written. Make sure $4a is written before $48, |
| 33 | otherwise your chance is only 1:16 to find the board :-). | 33 | otherwise your chance is only 1:16 to find the board :-). |
| 34 | 34 | ||
| 35 | The local memory-map is even active when mapped to $e8: | 35 | The local memory-map is even active when mapped to $e8: |
diff --git a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c index 545447ac503a..a12059886755 100644 --- a/Documentation/networking/ifenslave.c +++ b/Documentation/networking/ifenslave.c | |||
| @@ -87,7 +87,7 @@ | |||
| 87 | * would fail and generate an error message in the system log. | 87 | * would fail and generate an error message in the system log. |
| 88 | * - For opt_c: slave should not be set to the master's setting | 88 | * - For opt_c: slave should not be set to the master's setting |
| 89 | * while it is running. It was already set during enslave. To | 89 | * while it is running. It was already set during enslave. To |
| 90 | * simplify things, it is now handeled separately. | 90 | * simplify things, it is now handled separately. |
| 91 | * | 91 | * |
| 92 | * - 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com> | 92 | * - 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com> |
| 93 | * - Code cleanup and style changes | 93 | * - Code cleanup and style changes |
diff --git a/Documentation/pnp.txt b/Documentation/pnp.txt index af0f6eabfa1c..9529c9c9fd59 100644 --- a/Documentation/pnp.txt +++ b/Documentation/pnp.txt | |||
| @@ -115,6 +115,9 @@ pnp_unregister_protocol | |||
| 115 | pnp_register_driver | 115 | pnp_register_driver |
| 116 | - adds a PnP driver to the Plug and Play Layer | 116 | - adds a PnP driver to the Plug and Play Layer |
| 117 | - this includes driver model integration | 117 | - this includes driver model integration |
| 118 | - returns zero for success or a negative error number for failure; count | ||
| 119 | calls to the .add() method if you need to know how many devices bind to | ||
| 120 | the driver | ||
| 118 | 121 | ||
| 119 | pnp_unregister_driver | 122 | pnp_unregister_driver |
| 120 | - removes a PnP driver from the Plug and Play Layer | 123 | - removes a PnP driver from the Plug and Play Layer |
diff --git a/Documentation/robust-futex-ABI.txt b/Documentation/robust-futex-ABI.txt new file mode 100644 index 000000000000..8529a17ffaa1 --- /dev/null +++ b/Documentation/robust-futex-ABI.txt | |||
| @@ -0,0 +1,182 @@ | |||
| 1 | Started by Paul Jackson <pj@sgi.com> | ||
| 2 | |||
| 3 | The robust futex ABI | ||
| 4 | -------------------- | ||
| 5 | |||
| 6 | Robust_futexes provide a mechanism that is used in addition to normal | ||
| 7 | futexes, for kernel assist of cleanup of held locks on task exit. | ||
| 8 | |||
| 9 | The interesting data as to what futexes a thread is holding is kept on a | ||
| 10 | linked list in user space, where it can be updated efficiently as locks | ||
| 11 | are taken and dropped, without kernel intervention. The only additional | ||
| 12 | kernel intervention required for robust_futexes above and beyond what is | ||
| 13 | required for futexes is: | ||
| 14 | |||
| 15 | 1) a one time call, per thread, to tell the kernel where its list of | ||
| 16 | held robust_futexes begins, and | ||
| 17 | 2) internal kernel code at exit, to handle any listed locks held | ||
| 18 | by the exiting thread. | ||
| 19 | |||
| 20 | The existing normal futexes already provide a "Fast Userspace Locking" | ||
| 21 | mechanism, which handles uncontested locking without needing a system | ||
| 22 | call, and handles contested locking by maintaining a list of waiting | ||
| 23 | threads in the kernel. Options on the sys_futex(2) system call support | ||
| 24 | waiting on a particular futex, and waking up the next waiter on a | ||
| 25 | particular futex. | ||
| 26 | |||
| 27 | For robust_futexes to work, the user code (typically in a library such | ||
| 28 | as glibc linked with the application) has to manage and place the | ||
| 29 | necessary list elements exactly as the kernel expects them. If it fails | ||
| 30 | to do so, then improperly listed locks will not be cleaned up on exit, | ||
| 31 | probably causing deadlock or other such failure of the other threads | ||
| 32 | waiting on the same locks. | ||
| 33 | |||
| 34 | A thread that anticipates possibly using robust_futexes should first | ||
| 35 | issue the system call: | ||
| 36 | |||
| 37 | asmlinkage long | ||
| 38 | sys_set_robust_list(struct robust_list_head __user *head, size_t len); | ||
| 39 | |||
| 40 | The pointer 'head' points to a structure in the threads address space | ||
| 41 | consisting of three words. Each word is 32 bits on 32 bit arch's, or 64 | ||
| 42 | bits on 64 bit arch's, and local byte order. Each thread should have | ||
| 43 | its own thread private 'head'. | ||
| 44 | |||
| 45 | If a thread is running in 32 bit compatibility mode on a 64 native arch | ||
| 46 | kernel, then it can actually have two such structures - one using 32 bit | ||
| 47 | words for 32 bit compatibility mode, and one using 64 bit words for 64 | ||
| 48 | bit native mode. The kernel, if it is a 64 bit kernel supporting 32 bit | ||
| 49 | compatibility mode, will attempt to process both lists on each task | ||
| 50 | exit, if the corresponding sys_set_robust_list() call has been made to | ||
| 51 | setup that list. | ||
| 52 | |||
| 53 | The first word in the memory structure at 'head' contains a | ||
| 54 | pointer to a single linked list of 'lock entries', one per lock, | ||
| 55 | as described below. If the list is empty, the pointer will point | ||
| 56 | to itself, 'head'. The last 'lock entry' points back to the 'head'. | ||
| 57 | |||
| 58 | The second word, called 'offset', specifies the offset from the | ||
| 59 | address of the associated 'lock entry', plus or minus, of what will | ||
| 60 | be called the 'lock word', from that 'lock entry'. The 'lock word' | ||
| 61 | is always a 32 bit word, unlike the other words above. The 'lock | ||
| 62 | word' holds 3 flag bits in the upper 3 bits, and the thread id (TID) | ||
| 63 | of the thread holding the lock in the bottom 29 bits. See further | ||
| 64 | below for a description of the flag bits. | ||
| 65 | |||
| 66 | The third word, called 'list_op_pending', contains transient copy of | ||
| 67 | the address of the 'lock entry', during list insertion and removal, | ||
| 68 | and is needed to correctly resolve races should a thread exit while | ||
| 69 | in the middle of a locking or unlocking operation. | ||
| 70 | |||
| 71 | Each 'lock entry' on the single linked list starting at 'head' consists | ||
| 72 | of just a single word, pointing to the next 'lock entry', or back to | ||
| 73 | 'head' if there are no more entries. In addition, nearby to each 'lock | ||
| 74 | entry', at an offset from the 'lock entry' specified by the 'offset' | ||
| 75 | word, is one 'lock word'. | ||
| 76 | |||
| 77 | The 'lock word' is always 32 bits, and is intended to be the same 32 bit | ||
| 78 | lock variable used by the futex mechanism, in conjunction with | ||
| 79 | robust_futexes. The kernel will only be able to wakeup the next thread | ||
| 80 | waiting for a lock on a threads exit if that next thread used the futex | ||
| 81 | mechanism to register the address of that 'lock word' with the kernel. | ||
| 82 | |||
| 83 | For each futex lock currently held by a thread, if it wants this | ||
| 84 | robust_futex support for exit cleanup of that lock, it should have one | ||
| 85 | 'lock entry' on this list, with its associated 'lock word' at the | ||
| 86 | specified 'offset'. Should a thread die while holding any such locks, | ||
| 87 | the kernel will walk this list, mark any such locks with a bit | ||
| 88 | indicating their holder died, and wakeup the next thread waiting for | ||
| 89 | that lock using the futex mechanism. | ||
| 90 | |||
| 91 | When a thread has invoked the above system call to indicate it | ||
| 92 | anticipates using robust_futexes, the kernel stores the passed in 'head' | ||
| 93 | pointer for that task. The task may retrieve that value later on by | ||
| 94 | using the system call: | ||
| 95 | |||
| 96 | asmlinkage long | ||
| 97 | sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr, | ||
| 98 | size_t __user *len_ptr); | ||
| 99 | |||
| 100 | It is anticipated that threads will use robust_futexes embedded in | ||
| 101 | larger, user level locking structures, one per lock. The kernel | ||
| 102 | robust_futex mechanism doesn't care what else is in that structure, so | ||
| 103 | long as the 'offset' to the 'lock word' is the same for all | ||
| 104 | robust_futexes used by that thread. The thread should link those locks | ||
| 105 | it currently holds using the 'lock entry' pointers. It may also have | ||
| 106 | other links between the locks, such as the reverse side of a double | ||
| 107 | linked list, but that doesn't matter to the kernel. | ||
| 108 | |||
| 109 | By keeping its locks linked this way, on a list starting with a 'head' | ||
| 110 | pointer known to the kernel, the kernel can provide to a thread the | ||
| 111 | essential service available for robust_futexes, which is to help clean | ||
| 112 | up locks held at the time of (a perhaps unexpectedly) exit. | ||
| 113 | |||
| 114 | Actual locking and unlocking, during normal operations, is handled | ||
| 115 | entirely by user level code in the contending threads, and by the | ||
| 116 | existing futex mechanism to wait for, and wakeup, locks. The kernels | ||
| 117 | only essential involvement in robust_futexes is to remember where the | ||
| 118 | list 'head' is, and to walk the list on thread exit, handling locks | ||
| 119 | still held by the departing thread, as described below. | ||
| 120 | |||
| 121 | There may exist thousands of futex lock structures in a threads shared | ||
| 122 | memory, on various data structures, at a given point in time. Only those | ||
| 123 | lock structures for locks currently held by that thread should be on | ||
| 124 | that thread's robust_futex linked lock list a given time. | ||
| 125 | |||
| 126 | A given futex lock structure in a user shared memory region may be held | ||
| 127 | at different times by any of the threads with access to that region. The | ||
| 128 | thread currently holding such a lock, if any, is marked with the threads | ||
| 129 | TID in the lower 29 bits of the 'lock word'. | ||
| 130 | |||
| 131 | When adding or removing a lock from its list of held locks, in order for | ||
| 132 | the kernel to correctly handle lock cleanup regardless of when the task | ||
| 133 | exits (perhaps it gets an unexpected signal 9 in the middle of | ||
| 134 | manipulating this list), the user code must observe the following | ||
| 135 | protocol on 'lock entry' insertion and removal: | ||
| 136 | |||
| 137 | On insertion: | ||
| 138 | 1) set the 'list_op_pending' word to the address of the 'lock word' | ||
| 139 | to be inserted, | ||
| 140 | 2) acquire the futex lock, | ||
| 141 | 3) add the lock entry, with its thread id (TID) in the bottom 29 bits | ||
| 142 | of the 'lock word', to the linked list starting at 'head', and | ||
| 143 | 4) clear the 'list_op_pending' word. | ||
| 144 | |||
| 145 | On removal: | ||
| 146 | 1) set the 'list_op_pending' word to the address of the 'lock word' | ||
| 147 | to be removed, | ||
| 148 | 2) remove the lock entry for this lock from the 'head' list, | ||
| 149 | 2) release the futex lock, and | ||
| 150 | 2) clear the 'lock_op_pending' word. | ||
| 151 | |||
| 152 | On exit, the kernel will consider the address stored in | ||
| 153 | 'list_op_pending' and the address of each 'lock word' found by walking | ||
| 154 | the list starting at 'head'. For each such address, if the bottom 29 | ||
| 155 | bits of the 'lock word' at offset 'offset' from that address equals the | ||
| 156 | exiting threads TID, then the kernel will do two things: | ||
| 157 | |||
| 158 | 1) if bit 31 (0x80000000) is set in that word, then attempt a futex | ||
| 159 | wakeup on that address, which will waken the next thread that has | ||
| 160 | used to the futex mechanism to wait on that address, and | ||
| 161 | 2) atomically set bit 30 (0x40000000) in the 'lock word'. | ||
| 162 | |||
| 163 | In the above, bit 31 was set by futex waiters on that lock to indicate | ||
| 164 | they were waiting, and bit 30 is set by the kernel to indicate that the | ||
| 165 | lock owner died holding the lock. | ||
| 166 | |||
| 167 | The kernel exit code will silently stop scanning the list further if at | ||
| 168 | any point: | ||
| 169 | |||
| 170 | 1) the 'head' pointer or an subsequent linked list pointer | ||
| 171 | is not a valid address of a user space word | ||
| 172 | 2) the calculated location of the 'lock word' (address plus | ||
| 173 | 'offset') is not the valud address of a 32 bit user space | ||
| 174 | word | ||
| 175 | 3) if the list contains more than 1 million (subject to | ||
| 176 | future kernel configuration changes) elements. | ||
| 177 | |||
| 178 | When the kernel sees a list entry whose 'lock word' doesn't have the | ||
| 179 | current threads TID in the lower 29 bits, it does nothing with that | ||
| 180 | entry, and goes on to the next entry. | ||
| 181 | |||
| 182 | Bit 29 (0x20000000) of the 'lock word' is reserved for future use. | ||
diff --git a/Documentation/robust-futexes.txt b/Documentation/robust-futexes.txt new file mode 100644 index 000000000000..df82d75245a0 --- /dev/null +++ b/Documentation/robust-futexes.txt | |||
| @@ -0,0 +1,218 @@ | |||
| 1 | Started by: Ingo Molnar <mingo@redhat.com> | ||
| 2 | |||
| 3 | Background | ||
| 4 | ---------- | ||
| 5 | |||
| 6 | what are robust futexes? To answer that, we first need to understand | ||
| 7 | what futexes are: normal futexes are special types of locks that in the | ||
| 8 | noncontended case can be acquired/released from userspace without having | ||
| 9 | to enter the kernel. | ||
| 10 | |||
| 11 | A futex is in essence a user-space address, e.g. a 32-bit lock variable | ||
| 12 | field. If userspace notices contention (the lock is already owned and | ||
| 13 | someone else wants to grab it too) then the lock is marked with a value | ||
| 14 | that says "there's a waiter pending", and the sys_futex(FUTEX_WAIT) | ||
| 15 | syscall is used to wait for the other guy to release it. The kernel | ||
| 16 | creates a 'futex queue' internally, so that it can later on match up the | ||
| 17 | waiter with the waker - without them having to know about each other. | ||
| 18 | When the owner thread releases the futex, it notices (via the variable | ||
| 19 | value) that there were waiter(s) pending, and does the | ||
| 20 | sys_futex(FUTEX_WAKE) syscall to wake them up. Once all waiters have | ||
| 21 | taken and released the lock, the futex is again back to 'uncontended' | ||
| 22 | state, and there's no in-kernel state associated with it. The kernel | ||
| 23 | completely forgets that there ever was a futex at that address. This | ||
| 24 | method makes futexes very lightweight and scalable. | ||
| 25 | |||
| 26 | "Robustness" is about dealing with crashes while holding a lock: if a | ||
| 27 | process exits prematurely while holding a pthread_mutex_t lock that is | ||
| 28 | also shared with some other process (e.g. yum segfaults while holding a | ||
| 29 | pthread_mutex_t, or yum is kill -9-ed), then waiters for that lock need | ||
| 30 | to be notified that the last owner of the lock exited in some irregular | ||
| 31 | way. | ||
| 32 | |||
| 33 | To solve such types of problems, "robust mutex" userspace APIs were | ||
| 34 | created: pthread_mutex_lock() returns an error value if the owner exits | ||
| 35 | prematurely - and the new owner can decide whether the data protected by | ||
| 36 | the lock can be recovered safely. | ||
| 37 | |||
| 38 | There is a big conceptual problem with futex based mutexes though: it is | ||
| 39 | the kernel that destroys the owner task (e.g. due to a SEGFAULT), but | ||
| 40 | the kernel cannot help with the cleanup: if there is no 'futex queue' | ||
| 41 | (and in most cases there is none, futexes being fast lightweight locks) | ||
| 42 | then the kernel has no information to clean up after the held lock! | ||
| 43 | Userspace has no chance to clean up after the lock either - userspace is | ||
| 44 | the one that crashes, so it has no opportunity to clean up. Catch-22. | ||
| 45 | |||
| 46 | In practice, when e.g. yum is kill -9-ed (or segfaults), a system reboot | ||
| 47 | is needed to release that futex based lock. This is one of the leading | ||
| 48 | bugreports against yum. | ||
| 49 | |||
| 50 | To solve this problem, the traditional approach was to extend the vma | ||
| 51 | (virtual memory area descriptor) concept to have a notion of 'pending | ||
| 52 | robust futexes attached to this area'. This approach requires 3 new | ||
| 53 | syscall variants to sys_futex(): FUTEX_REGISTER, FUTEX_DEREGISTER and | ||
| 54 | FUTEX_RECOVER. At do_exit() time, all vmas are searched to see whether | ||
| 55 | they have a robust_head set. This approach has two fundamental problems | ||
| 56 | left: | ||
| 57 | |||
| 58 | - it has quite complex locking and race scenarios. The vma-based | ||
| 59 | approach had been pending for years, but they are still not completely | ||
| 60 | reliable. | ||
| 61 | |||
| 62 | - they have to scan _every_ vma at sys_exit() time, per thread! | ||
| 63 | |||
| 64 | The second disadvantage is a real killer: pthread_exit() takes around 1 | ||
| 65 | microsecond on Linux, but with thousands (or tens of thousands) of vmas | ||
| 66 | every pthread_exit() takes a millisecond or more, also totally | ||
| 67 | destroying the CPU's L1 and L2 caches! | ||
| 68 | |||
| 69 | This is very much noticeable even for normal process sys_exit_group() | ||
| 70 | calls: the kernel has to do the vma scanning unconditionally! (this is | ||
| 71 | because the kernel has no knowledge about how many robust futexes there | ||
| 72 | are to be cleaned up, because a robust futex might have been registered | ||
| 73 | in another task, and the futex variable might have been simply mmap()-ed | ||
| 74 | into this process's address space). | ||
| 75 | |||
| 76 | This huge overhead forced the creation of CONFIG_FUTEX_ROBUST so that | ||
| 77 | normal kernels can turn it off, but worse than that: the overhead makes | ||
| 78 | robust futexes impractical for any type of generic Linux distribution. | ||
| 79 | |||
| 80 | So something had to be done. | ||
| 81 | |||
| 82 | New approach to robust futexes | ||
| 83 | ------------------------------ | ||
| 84 | |||
| 85 | At the heart of this new approach there is a per-thread private list of | ||
| 86 | robust locks that userspace is holding (maintained by glibc) - which | ||
| 87 | userspace list is registered with the kernel via a new syscall [this | ||
| 88 | registration happens at most once per thread lifetime]. At do_exit() | ||
| 89 | time, the kernel checks this user-space list: are there any robust futex | ||
| 90 | locks to be cleaned up? | ||
| 91 | |||
| 92 | In the common case, at do_exit() time, there is no list registered, so | ||
| 93 | the cost of robust futexes is just a simple current->robust_list != NULL | ||
| 94 | comparison. If the thread has registered a list, then normally the list | ||
| 95 | is empty. If the thread/process crashed or terminated in some incorrect | ||
| 96 | way then the list might be non-empty: in this case the kernel carefully | ||
| 97 | walks the list [not trusting it], and marks all locks that are owned by | ||
| 98 | this thread with the FUTEX_OWNER_DEAD bit, and wakes up one waiter (if | ||
| 99 | any). | ||
| 100 | |||
| 101 | The list is guaranteed to be private and per-thread at do_exit() time, | ||
| 102 | so it can be accessed by the kernel in a lockless way. | ||
| 103 | |||
| 104 | There is one race possible though: since adding to and removing from the | ||
| 105 | list is done after the futex is acquired by glibc, there is a few | ||
| 106 | instructions window for the thread (or process) to die there, leaving | ||
| 107 | the futex hung. To protect against this possibility, userspace (glibc) | ||
| 108 | also maintains a simple per-thread 'list_op_pending' field, to allow the | ||
| 109 | kernel to clean up if the thread dies after acquiring the lock, but just | ||
| 110 | before it could have added itself to the list. Glibc sets this | ||
| 111 | list_op_pending field before it tries to acquire the futex, and clears | ||
| 112 | it after the list-add (or list-remove) has finished. | ||
| 113 | |||
| 114 | That's all that is needed - all the rest of robust-futex cleanup is done | ||
| 115 | in userspace [just like with the previous patches]. | ||
| 116 | |||
| 117 | Ulrich Drepper has implemented the necessary glibc support for this new | ||
| 118 | mechanism, which fully enables robust mutexes. | ||
| 119 | |||
| 120 | Key differences of this userspace-list based approach, compared to the | ||
| 121 | vma based method: | ||
| 122 | |||
| 123 | - it's much, much faster: at thread exit time, there's no need to loop | ||
| 124 | over every vma (!), which the VM-based method has to do. Only a very | ||
| 125 | simple 'is the list empty' op is done. | ||
| 126 | |||
| 127 | - no VM changes are needed - 'struct address_space' is left alone. | ||
| 128 | |||
| 129 | - no registration of individual locks is needed: robust mutexes dont | ||
| 130 | need any extra per-lock syscalls. Robust mutexes thus become a very | ||
| 131 | lightweight primitive - so they dont force the application designer | ||
| 132 | to do a hard choice between performance and robustness - robust | ||
| 133 | mutexes are just as fast. | ||
| 134 | |||
| 135 | - no per-lock kernel allocation happens. | ||
| 136 | |||
| 137 | - no resource limits are needed. | ||
| 138 | |||
| 139 | - no kernel-space recovery call (FUTEX_RECOVER) is needed. | ||
| 140 | |||
| 141 | - the implementation and the locking is "obvious", and there are no | ||
| 142 | interactions with the VM. | ||
| 143 | |||
| 144 | Performance | ||
| 145 | ----------- | ||
| 146 | |||
| 147 | I have benchmarked the time needed for the kernel to process a list of 1 | ||
| 148 | million (!) held locks, using the new method [on a 2GHz CPU]: | ||
| 149 | |||
| 150 | - with FUTEX_WAIT set [contended mutex]: 130 msecs | ||
| 151 | - without FUTEX_WAIT set [uncontended mutex]: 30 msecs | ||
| 152 | |||
| 153 | I have also measured an approach where glibc does the lock notification | ||
| 154 | [which it currently does for !pshared robust mutexes], and that took 256 | ||
| 155 | msecs - clearly slower, due to the 1 million FUTEX_WAKE syscalls | ||
| 156 | userspace had to do. | ||
| 157 | |||
| 158 | (1 million held locks are unheard of - we expect at most a handful of | ||
| 159 | locks to be held at a time. Nevertheless it's nice to know that this | ||
| 160 | approach scales nicely.) | ||
| 161 | |||
| 162 | Implementation details | ||
| 163 | ---------------------- | ||
| 164 | |||
| 165 | The patch adds two new syscalls: one to register the userspace list, and | ||
| 166 | one to query the registered list pointer: | ||
| 167 | |||
| 168 | asmlinkage long | ||
| 169 | sys_set_robust_list(struct robust_list_head __user *head, | ||
| 170 | size_t len); | ||
| 171 | |||
| 172 | asmlinkage long | ||
| 173 | sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr, | ||
| 174 | size_t __user *len_ptr); | ||
| 175 | |||
| 176 | List registration is very fast: the pointer is simply stored in | ||
| 177 | current->robust_list. [Note that in the future, if robust futexes become | ||
| 178 | widespread, we could extend sys_clone() to register a robust-list head | ||
| 179 | for new threads, without the need of another syscall.] | ||
| 180 | |||
| 181 | So there is virtually zero overhead for tasks not using robust futexes, | ||
| 182 | and even for robust futex users, there is only one extra syscall per | ||
| 183 | thread lifetime, and the cleanup operation, if it happens, is fast and | ||
| 184 | straightforward. The kernel doesnt have any internal distinction between | ||
| 185 | robust and normal futexes. | ||
| 186 | |||
| 187 | If a futex is found to be held at exit time, the kernel sets the | ||
| 188 | following bit of the futex word: | ||
| 189 | |||
| 190 | #define FUTEX_OWNER_DIED 0x40000000 | ||
| 191 | |||
| 192 | and wakes up the next futex waiter (if any). User-space does the rest of | ||
| 193 | the cleanup. | ||
| 194 | |||
| 195 | Otherwise, robust futexes are acquired by glibc by putting the TID into | ||
| 196 | the futex field atomically. Waiters set the FUTEX_WAITERS bit: | ||
| 197 | |||
| 198 | #define FUTEX_WAITERS 0x80000000 | ||
| 199 | |||
| 200 | and the remaining bits are for the TID. | ||
| 201 | |||
| 202 | Testing, architecture support | ||
| 203 | ----------------------------- | ||
| 204 | |||
| 205 | i've tested the new syscalls on x86 and x86_64, and have made sure the | ||
| 206 | parsing of the userspace list is robust [ ;-) ] even if the list is | ||
| 207 | deliberately corrupted. | ||
| 208 | |||
| 209 | i386 and x86_64 syscalls are wired up at the moment, and Ulrich has | ||
| 210 | tested the new glibc code (on x86_64 and i386), and it works for his | ||
| 211 | robust-mutex testcases. | ||
| 212 | |||
| 213 | All other architectures should build just fine too - but they wont have | ||
| 214 | the new syscalls yet. | ||
| 215 | |||
| 216 | Architectures need to implement the new futex_atomic_cmpxchg_inatomic() | ||
| 217 | inline function before writing up the syscalls (that function returns | ||
| 218 | -ENOSYS right now). | ||
diff --git a/Documentation/rpc-cache.txt b/Documentation/rpc-cache.txt index 2b5d4434fa5a..5f757c8cf979 100644 --- a/Documentation/rpc-cache.txt +++ b/Documentation/rpc-cache.txt | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | This document gives a brief introduction to the caching | 1 | This document gives a brief introduction to the caching |
| 2 | mechanisms in the sunrpc layer that is used, in particular, | 2 | mechanisms in the sunrpc layer that is used, in particular, |
| 3 | for NFS authentication. | 3 | for NFS authentication. |
| 4 | 4 | ||
| @@ -25,25 +25,17 @@ The common code handles such things as: | |||
| 25 | - supporting 'NEGATIVE' as well as positive entries | 25 | - supporting 'NEGATIVE' as well as positive entries |
| 26 | - allowing an EXPIRED time on cache items, and removing | 26 | - allowing an EXPIRED time on cache items, and removing |
| 27 | items after they expire, and are no longe in-use. | 27 | items after they expire, and are no longe in-use. |
| 28 | |||
| 29 | Future code extensions are expect to handle | ||
| 30 | - making requests to user-space to fill in cache entries | 28 | - making requests to user-space to fill in cache entries |
| 31 | - allowing user-space to directly set entries in the cache | 29 | - allowing user-space to directly set entries in the cache |
| 32 | - delaying RPC requests that depend on as-yet incomplete | 30 | - delaying RPC requests that depend on as-yet incomplete |
| 33 | cache entries, and replaying those requests when the cache entry | 31 | cache entries, and replaying those requests when the cache entry |
| 34 | is complete. | 32 | is complete. |
| 35 | - maintaining last-access times on cache entries | 33 | - clean out old entries as they expire. |
| 36 | - clean out old entries when the caches become full | ||
| 37 | |||
| 38 | The code for performing a cache lookup is also common, but in the form | ||
| 39 | of a template. i.e. a #define. | ||
| 40 | Each cache defines a lookup function by using the DefineCacheLookup | ||
| 41 | macro, or the simpler DefineSimpleCacheLookup macro | ||
| 42 | 34 | ||
| 43 | Creating a Cache | 35 | Creating a Cache |
| 44 | ---------------- | 36 | ---------------- |
| 45 | 37 | ||
| 46 | 1/ A cache needs a datum to cache. This is in the form of a | 38 | 1/ A cache needs a datum to store. This is in the form of a |
| 47 | structure definition that must contain a | 39 | structure definition that must contain a |
| 48 | struct cache_head | 40 | struct cache_head |
| 49 | as an element, usually the first. | 41 | as an element, usually the first. |
| @@ -51,35 +43,69 @@ Creating a Cache | |||
| 51 | Each cache element is reference counted and contains | 43 | Each cache element is reference counted and contains |
| 52 | expiry and update times for use in cache management. | 44 | expiry and update times for use in cache management. |
| 53 | 2/ A cache needs a "cache_detail" structure that | 45 | 2/ A cache needs a "cache_detail" structure that |
| 54 | describes the cache. This stores the hash table, and some | 46 | describes the cache. This stores the hash table, some |
| 55 | parameters for cache management. | 47 | parameters for cache management, and some operations detailing how |
| 56 | 3/ A cache needs a lookup function. This is created using | 48 | to work with particular cache items. |
| 57 | the DefineCacheLookup macro. This lookup function is used both | 49 | The operations requires are: |
| 58 | to find entries and to update entries. The normal mode for | 50 | struct cache_head *alloc(void) |
| 59 | updating an entry is to replace the old entry with a new | 51 | This simply allocates appropriate memory and returns |
| 60 | entry. However it is possible to allow update-in-place | 52 | a pointer to the cache_detail embedded within the |
| 61 | for those caches where it makes sense (no atomicity issues | 53 | structure |
| 62 | or indirect reference counting issue) | 54 | void cache_put(struct kref *) |
| 63 | 4/ A cache needs to be registered using cache_register(). This | 55 | This is called when the last reference to an item is |
| 64 | includes in on a list of caches that will be regularly | 56 | is dropped. The pointer passed is to the 'ref' field |
| 65 | cleaned to discard old data. For this to work, some | 57 | in the cache_head. cache_put should release any |
| 66 | thread must periodically call cache_clean | 58 | references create by 'cache_init' and, if CACHE_VALID |
| 67 | 59 | is set, any references created by cache_update. | |
| 60 | It should then release the memory allocated by | ||
| 61 | 'alloc'. | ||
| 62 | int match(struct cache_head *orig, struct cache_head *new) | ||
| 63 | test if the keys in the two structures match. Return | ||
| 64 | 1 if they do, 0 if they don't. | ||
| 65 | void init(struct cache_head *orig, struct cache_head *new) | ||
| 66 | Set the 'key' fields in 'new' from 'orig'. This may | ||
| 67 | include taking references to shared objects. | ||
| 68 | void update(struct cache_head *orig, struct cache_head *new) | ||
| 69 | Set the 'content' fileds in 'new' from 'orig'. | ||
| 70 | int cache_show(struct seq_file *m, struct cache_detail *cd, | ||
| 71 | struct cache_head *h) | ||
| 72 | Optional. Used to provide a /proc file that lists the | ||
| 73 | contents of a cache. This should show one item, | ||
| 74 | usually on just one line. | ||
| 75 | int cache_request(struct cache_detail *cd, struct cache_head *h, | ||
| 76 | char **bpp, int *blen) | ||
| 77 | Format a request to be send to user-space for an item | ||
| 78 | to be instantiated. *bpp is a buffer of size *blen. | ||
| 79 | bpp should be moved forward over the encoded message, | ||
| 80 | and *blen should be reduced to show how much free | ||
| 81 | space remains. Return 0 on success or <0 if not | ||
| 82 | enough room or other problem. | ||
| 83 | int cache_parse(struct cache_detail *cd, char *buf, int len) | ||
| 84 | A message from user space has arrived to fill out a | ||
| 85 | cache entry. It is in 'buf' of length 'len'. | ||
| 86 | cache_parse should parse this, find the item in the | ||
| 87 | cache with sunrpc_cache_lookup, and update the item | ||
| 88 | with sunrpc_cache_update. | ||
| 89 | |||
| 90 | |||
| 91 | 3/ A cache needs to be registered using cache_register(). This | ||
| 92 | includes it on a list of caches that will be regularly | ||
| 93 | cleaned to discard old data. | ||
| 94 | |||
| 68 | Using a cache | 95 | Using a cache |
| 69 | ------------- | 96 | ------------- |
| 70 | 97 | ||
| 71 | To find a value in a cache, call the lookup function passing it a the | 98 | To find a value in a cache, call sunrpc_cache_lookup passing a pointer |
| 72 | datum which contains key, and possibly content, and a flag saying | 99 | to the cache_head in a sample item with the 'key' fields filled in. |
| 73 | whether to update the cache with new data from the datum. Depending | 100 | This will be passed to ->match to identify the target entry. If no |
| 74 | on how the cache lookup function was defined, it may take an extra | 101 | entry is found, a new entry will be create, added to the cache, and |
| 75 | argument to identify the particular cache in question. | 102 | marked as not containing valid data. |
| 76 | 103 | ||
| 77 | Except in cases of kmalloc failure, the lookup function | 104 | The item returned is typically passed to cache_check which will check |
| 78 | will return a new datum which will store the key and | 105 | if the data is valid, and may initiate an up-call to get fresh data. |
| 79 | may contain valid content, or may not. | 106 | cache_check will return -ENOENT in the entry is negative or if an up |
| 80 | This datum is typically passed to cache_check which determines the | 107 | call is needed but not possible, -EAGAIN if an upcall is pending, |
| 81 | validity of the datum and may later initiate an upcall to fill | 108 | or 0 if the data is valid; |
| 82 | in the data. | ||
| 83 | 109 | ||
| 84 | cache_check can be passed a "struct cache_req *". This structure is | 110 | cache_check can be passed a "struct cache_req *". This structure is |
| 85 | typically embedded in the actual request and can be used to create a | 111 | typically embedded in the actual request and can be used to create a |
| @@ -90,6 +116,13 @@ item does become valid, the deferred copy of the request will be | |||
| 90 | revisited (->revisit). It is expected that this method will | 116 | revisited (->revisit). It is expected that this method will |
| 91 | reschedule the request for processing. | 117 | reschedule the request for processing. |
| 92 | 118 | ||
| 119 | The value returned by sunrpc_cache_lookup can also be passed to | ||
| 120 | sunrpc_cache_update to set the content for the item. A second item is | ||
| 121 | passed which should hold the content. If the item found by _lookup | ||
| 122 | has valid data, then it is discarded and a new item is created. This | ||
| 123 | saves any user of an item from worrying about content changing while | ||
| 124 | it is being inspected. If the item found by _lookup does not contain | ||
| 125 | valid data, then the content is copied across and CACHE_VALID is set. | ||
| 93 | 126 | ||
| 94 | Populating a cache | 127 | Populating a cache |
| 95 | ------------------ | 128 | ------------------ |
| @@ -114,8 +147,8 @@ should be create or updated to have the given content, and the | |||
| 114 | expiry time should be set on that item. | 147 | expiry time should be set on that item. |
| 115 | 148 | ||
| 116 | Reading from a channel is a bit more interesting. When a cache | 149 | Reading from a channel is a bit more interesting. When a cache |
| 117 | lookup fail, or when it suceeds but finds an entry that may soon | 150 | lookup fails, or when it succeeds but finds an entry that may soon |
| 118 | expiry, a request is lodged for that cache item to be updated by | 151 | expire, a request is lodged for that cache item to be updated by |
| 119 | user-space. These requests appear in the channel file. | 152 | user-space. These requests appear in the channel file. |
| 120 | 153 | ||
| 121 | Successive reads will return successive requests. | 154 | Successive reads will return successive requests. |
| @@ -130,7 +163,7 @@ Thus a user-space helper is likely to: | |||
| 130 | write a response | 163 | write a response |
| 131 | loop. | 164 | loop. |
| 132 | 165 | ||
| 133 | If it dies and needs to be restarted, any requests that have not be | 166 | If it dies and needs to be restarted, any requests that have not been |
| 134 | answered will still appear in the file and will be read by the new | 167 | answered will still appear in the file and will be read by the new |
| 135 | instance of the helper. | 168 | instance of the helper. |
| 136 | 169 | ||
| @@ -142,10 +175,9 @@ Each cache should also define a "cache_request" method which | |||
| 142 | takes a cache item and encodes a request into the buffer | 175 | takes a cache item and encodes a request into the buffer |
| 143 | provided. | 176 | provided. |
| 144 | 177 | ||
| 145 | |||
| 146 | Note: If a cache has no active readers on the channel, and has had not | 178 | Note: If a cache has no active readers on the channel, and has had not |
| 147 | active readers for more than 60 seconds, further requests will not be | 179 | active readers for more than 60 seconds, further requests will not be |
| 148 | added to the channel but instead all looks that do not find a valid | 180 | added to the channel but instead all lookups that do not find a valid |
| 149 | entry will fail. This is partly for backward compatibility: The | 181 | entry will fail. This is partly for backward compatibility: The |
| 150 | previous nfs exports table was deemed to be authoritative and a | 182 | previous nfs exports table was deemed to be authoritative and a |
| 151 | failed lookup meant a definite 'no'. | 183 | failed lookup meant a definite 'no'. |
| @@ -154,18 +186,17 @@ request/response format | |||
| 154 | ----------------------- | 186 | ----------------------- |
| 155 | 187 | ||
| 156 | While each cache is free to use it's own format for requests | 188 | While each cache is free to use it's own format for requests |
| 157 | and responses over channel, the following is recommended are | 189 | and responses over channel, the following is recommended as |
| 158 | appropriate and support routines are available to help: | 190 | appropriate and support routines are available to help: |
| 159 | Each request or response record should be printable ASCII | 191 | Each request or response record should be printable ASCII |
| 160 | with precisely one newline character which should be at the end. | 192 | with precisely one newline character which should be at the end. |
| 161 | Fields within the record should be separated by spaces, normally one. | 193 | Fields within the record should be separated by spaces, normally one. |
| 162 | If spaces, newlines, or nul characters are needed in a field they | 194 | If spaces, newlines, or nul characters are needed in a field they |
| 163 | much be quotes. two mechanisms are available: | 195 | much be quoted. two mechanisms are available: |
| 164 | 1/ If a field begins '\x' then it must contain an even number of | 196 | 1/ If a field begins '\x' then it must contain an even number of |
| 165 | hex digits, and pairs of these digits provide the bytes in the | 197 | hex digits, and pairs of these digits provide the bytes in the |
| 166 | field. | 198 | field. |
| 167 | 2/ otherwise a \ in the field must be followed by 3 octal digits | 199 | 2/ otherwise a \ in the field must be followed by 3 octal digits |
| 168 | which give the code for a byte. Other characters are treated | 200 | which give the code for a byte. Other characters are treated |
| 169 | as them selves. At the very least, space, newlines nul, and | 201 | as them selves. At the very least, space, newline, nul, and |
| 170 | '\' must be quoted in this way. | 202 | '\' must be quoted in this way. |
| 171 | |||
diff --git a/MAINTAINERS b/MAINTAINERS index f27846734b06..e5b051f0e27e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2233,6 +2233,12 @@ M: p_gortmaker@yahoo.com | |||
| 2233 | L: linux-kernel@vger.kernel.org | 2233 | L: linux-kernel@vger.kernel.org |
| 2234 | S: Maintained | 2234 | S: Maintained |
| 2235 | 2235 | ||
| 2236 | REAL TIME CLOCK (RTC) SUBSYSTEM | ||
| 2237 | P: Alessandro Zummo | ||
| 2238 | M: a.zummo@towertech.it | ||
| 2239 | L: linux-kernel@vger.kernel.org | ||
| 2240 | S: Maintained | ||
| 2241 | |||
| 2236 | REISERFS FILE SYSTEM | 2242 | REISERFS FILE SYSTEM |
| 2237 | P: Hans Reiser | 2243 | P: Hans Reiser |
| 2238 | M: reiserfs-dev@namesys.com | 2244 | M: reiserfs-dev@namesys.com |
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index b4e5f8ff2b25..dd8769670596 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/root_dev.h> | 34 | #include <linux/root_dev.h> |
| 35 | #include <linux/initrd.h> | 35 | #include <linux/initrd.h> |
| 36 | #include <linux/eisa.h> | 36 | #include <linux/eisa.h> |
| 37 | #include <linux/pfn.h> | ||
| 37 | #ifdef CONFIG_MAGIC_SYSRQ | 38 | #ifdef CONFIG_MAGIC_SYSRQ |
| 38 | #include <linux/sysrq.h> | 39 | #include <linux/sysrq.h> |
| 39 | #include <linux/reboot.h> | 40 | #include <linux/reboot.h> |
| @@ -42,7 +43,7 @@ | |||
| 42 | #include <asm/setup.h> | 43 | #include <asm/setup.h> |
| 43 | #include <asm/io.h> | 44 | #include <asm/io.h> |
| 44 | 45 | ||
| 45 | extern struct notifier_block *panic_notifier_list; | 46 | extern struct atomic_notifier_head panic_notifier_list; |
| 46 | static int alpha_panic_event(struct notifier_block *, unsigned long, void *); | 47 | static int alpha_panic_event(struct notifier_block *, unsigned long, void *); |
| 47 | static struct notifier_block alpha_panic_block = { | 48 | static struct notifier_block alpha_panic_block = { |
| 48 | alpha_panic_event, | 49 | alpha_panic_event, |
| @@ -241,9 +242,6 @@ reserve_std_resources(void) | |||
| 241 | request_resource(io, standard_io_resources+i); | 242 | request_resource(io, standard_io_resources+i); |
| 242 | } | 243 | } |
| 243 | 244 | ||
| 244 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | ||
| 245 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
| 246 | #define PFN_PHYS(x) ((x) << PAGE_SHIFT) | ||
| 247 | #define PFN_MAX PFN_DOWN(0x80000000) | 245 | #define PFN_MAX PFN_DOWN(0x80000000) |
| 248 | #define for_each_mem_cluster(memdesc, cluster, i) \ | 246 | #define for_each_mem_cluster(memdesc, cluster, i) \ |
| 249 | for ((cluster) = (memdesc)->cluster, (i) = 0; \ | 247 | for ((cluster) = (memdesc)->cluster, (i) = 0; \ |
| @@ -472,11 +470,6 @@ page_is_ram(unsigned long pfn) | |||
| 472 | return 0; | 470 | return 0; |
| 473 | } | 471 | } |
| 474 | 472 | ||
| 475 | #undef PFN_UP | ||
| 476 | #undef PFN_DOWN | ||
| 477 | #undef PFN_PHYS | ||
| 478 | #undef PFN_MAX | ||
| 479 | |||
| 480 | void __init | 473 | void __init |
| 481 | setup_arch(char **cmdline_p) | 474 | setup_arch(char **cmdline_p) |
| 482 | { | 475 | { |
| @@ -507,7 +500,8 @@ setup_arch(char **cmdline_p) | |||
| 507 | } | 500 | } |
| 508 | 501 | ||
| 509 | /* Register a call for panic conditions. */ | 502 | /* Register a call for panic conditions. */ |
| 510 | notifier_chain_register(&panic_notifier_list, &alpha_panic_block); | 503 | atomic_notifier_chain_register(&panic_notifier_list, |
| 504 | &alpha_panic_block); | ||
| 511 | 505 | ||
| 512 | #ifdef CONFIG_ALPHA_GENERIC | 506 | #ifdef CONFIG_ALPHA_GENERIC |
| 513 | /* Assume that we've booted from SRM if we haven't booted from MILO. | 507 | /* Assume that we've booted from SRM if we haven't booted from MILO. |
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c index 6b2921be1909..3859749810b4 100644 --- a/arch/alpha/kernel/time.c +++ b/arch/alpha/kernel/time.c | |||
| @@ -314,10 +314,11 @@ time_init(void) | |||
| 314 | if (!est_cycle_freq) | 314 | if (!est_cycle_freq) |
| 315 | est_cycle_freq = validate_cc_value(calibrate_cc_with_pit()); | 315 | est_cycle_freq = validate_cc_value(calibrate_cc_with_pit()); |
| 316 | 316 | ||
| 317 | cc1 = rpcc_after_update_in_progress(); | 317 | cc1 = rpcc(); |
| 318 | 318 | ||
| 319 | /* Calibrate CPU clock -- attempt #2. */ | 319 | /* Calibrate CPU clock -- attempt #2. */ |
| 320 | if (!est_cycle_freq) { | 320 | if (!est_cycle_freq) { |
| 321 | cc1 = rpcc_after_update_in_progress(); | ||
| 321 | cc2 = rpcc_after_update_in_progress(); | 322 | cc2 = rpcc_after_update_in_progress(); |
| 322 | est_cycle_freq = validate_cc_value(cc2 - cc1); | 323 | est_cycle_freq = validate_cc_value(cc2 - cc1); |
| 323 | cc1 = cc2; | 324 | cc1 = cc2; |
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c index 6d5251254f68..bf6b65c81bef 100644 --- a/arch/alpha/mm/numa.c +++ b/arch/alpha/mm/numa.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/bootmem.h> | 13 | #include <linux/bootmem.h> |
| 14 | #include <linux/swap.h> | 14 | #include <linux/swap.h> |
| 15 | #include <linux/initrd.h> | 15 | #include <linux/initrd.h> |
| 16 | #include <linux/pfn.h> | ||
| 16 | 17 | ||
| 17 | #include <asm/hwrpb.h> | 18 | #include <asm/hwrpb.h> |
| 18 | #include <asm/pgalloc.h> | 19 | #include <asm/pgalloc.h> |
| @@ -27,9 +28,6 @@ bootmem_data_t node_bdata[MAX_NUMNODES]; | |||
| 27 | #define DBGDCONT(args...) | 28 | #define DBGDCONT(args...) |
| 28 | #endif | 29 | #endif |
| 29 | 30 | ||
| 30 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | ||
| 31 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
| 32 | #define PFN_PHYS(x) ((x) << PAGE_SHIFT) | ||
| 33 | #define for_each_mem_cluster(memdesc, cluster, i) \ | 31 | #define for_each_mem_cluster(memdesc, cluster, i) \ |
| 34 | for ((cluster) = (memdesc)->cluster, (i) = 0; \ | 32 | for ((cluster) = (memdesc)->cluster, (i) = 0; \ |
| 35 | (i) < (memdesc)->numclusters; (i)++, (cluster)++) | 33 | (i) < (memdesc)->numclusters; (i)++, (cluster)++) |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index bf2e72698d02..ba46d779ede7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -8,6 +8,7 @@ mainmenu "Linux Kernel Configuration" | |||
| 8 | config ARM | 8 | config ARM |
| 9 | bool | 9 | bool |
| 10 | default y | 10 | default y |
| 11 | select RTC_LIB | ||
| 11 | help | 12 | help |
| 12 | The ARM series is a line of low-power-consumption RISC chip designs | 13 | The ARM series is a line of low-power-consumption RISC chip designs |
| 13 | licensed by ARM Ltd and targeted at embedded applications and | 14 | licensed by ARM Ltd and targeted at embedded applications and |
| @@ -152,6 +153,12 @@ config ARCH_IXP2000 | |||
| 152 | help | 153 | help |
| 153 | Support for Intel's IXP2400/2800 (XScale) family of processors. | 154 | Support for Intel's IXP2400/2800 (XScale) family of processors. |
| 154 | 155 | ||
| 156 | config ARCH_IXP23XX | ||
| 157 | bool "IXP23XX-based" | ||
| 158 | select PCI | ||
| 159 | help | ||
| 160 | Support for Intel's IXP23xx (XScale) family of processors. | ||
| 161 | |||
| 155 | config ARCH_L7200 | 162 | config ARCH_L7200 |
| 156 | bool "LinkUp-L7200" | 163 | bool "LinkUp-L7200" |
| 157 | select FIQ | 164 | select FIQ |
| @@ -273,6 +280,8 @@ source "arch/arm/mach-ixp4xx/Kconfig" | |||
| 273 | 280 | ||
| 274 | source "arch/arm/mach-ixp2000/Kconfig" | 281 | source "arch/arm/mach-ixp2000/Kconfig" |
| 275 | 282 | ||
| 283 | source "arch/arm/mach-ixp23xx/Kconfig" | ||
| 284 | |||
| 276 | source "arch/arm/mach-pxa/Kconfig" | 285 | source "arch/arm/mach-pxa/Kconfig" |
| 277 | 286 | ||
| 278 | source "arch/arm/mach-sa1100/Kconfig" | 287 | source "arch/arm/mach-sa1100/Kconfig" |
| @@ -791,7 +800,8 @@ source "drivers/acorn/block/Kconfig" | |||
| 791 | 800 | ||
| 792 | if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \ | 801 | if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \ |
| 793 | || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \ | 802 | || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \ |
| 794 | || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE | 803 | || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \ |
| 804 | || ARCH_IXP23XX | ||
| 795 | source "drivers/ide/Kconfig" | 805 | source "drivers/ide/Kconfig" |
| 796 | endif | 806 | endif |
| 797 | 807 | ||
| @@ -839,6 +849,8 @@ source "drivers/usb/Kconfig" | |||
| 839 | 849 | ||
| 840 | source "drivers/mmc/Kconfig" | 850 | source "drivers/mmc/Kconfig" |
| 841 | 851 | ||
| 852 | source "drivers/rtc/Kconfig" | ||
| 853 | |||
| 842 | endmenu | 854 | endmenu |
| 843 | 855 | ||
| 844 | source "fs/Kconfig" | 856 | source "fs/Kconfig" |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 99c0d323719a..ce3e804ea0f3 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
| @@ -57,6 +57,7 @@ tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi | |||
| 57 | tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 | 57 | tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110 |
| 58 | tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 | 58 | tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100 |
| 59 | tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale | 59 | tune-$(CONFIG_CPU_XSCALE) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale |
| 60 | tune-$(CONFIG_CPU_XSC3) :=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale | ||
| 60 | tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) | 61 | tune-$(CONFIG_CPU_V6) :=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm) |
| 61 | 62 | ||
| 62 | ifeq ($(CONFIG_AEABI),y) | 63 | ifeq ($(CONFIG_AEABI),y) |
| @@ -97,6 +98,7 @@ endif | |||
| 97 | machine-$(CONFIG_ARCH_IOP3XX) := iop3xx | 98 | machine-$(CONFIG_ARCH_IOP3XX) := iop3xx |
| 98 | machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx | 99 | machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx |
| 99 | machine-$(CONFIG_ARCH_IXP2000) := ixp2000 | 100 | machine-$(CONFIG_ARCH_IXP2000) := ixp2000 |
| 101 | machine-$(CONFIG_ARCH_IXP23XX) := ixp23xx | ||
| 100 | machine-$(CONFIG_ARCH_OMAP1) := omap1 | 102 | machine-$(CONFIG_ARCH_OMAP1) := omap1 |
| 101 | machine-$(CONFIG_ARCH_OMAP2) := omap2 | 103 | machine-$(CONFIG_ARCH_OMAP2) := omap2 |
| 102 | incdir-$(CONFIG_ARCH_OMAP) := omap | 104 | incdir-$(CONFIG_ARCH_OMAP) := omap |
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 35ffe0f4ece7..2adc1527e0eb 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile | |||
| @@ -50,10 +50,6 @@ ifeq ($(CONFIG_ARCH_AT91RM9200),y) | |||
| 50 | OBJS += head-at91rm9200.o | 50 | OBJS += head-at91rm9200.o |
| 51 | endif | 51 | endif |
| 52 | 52 | ||
| 53 | ifeq ($(CONFIG_DEBUG_ICEDCC),y) | ||
| 54 | OBJS += ice-dcc.o | ||
| 55 | endif | ||
| 56 | |||
| 57 | ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) | 53 | ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) |
| 58 | OBJS += big-endian.o | 54 | OBJS += big-endian.o |
| 59 | endif | 55 | endif |
diff --git a/arch/arm/boot/compressed/ice-dcc.S b/arch/arm/boot/compressed/ice-dcc.S deleted file mode 100644 index 104377a199bb..000000000000 --- a/arch/arm/boot/compressed/ice-dcc.S +++ /dev/null | |||
| @@ -1,17 +0,0 @@ | |||
| 1 | |||
| 2 | |||
| 3 | .text | ||
| 4 | |||
| 5 | .global icedcc_putc | ||
| 6 | |||
| 7 | icedcc_putc: | ||
| 8 | mov r2, #0x4000000 | ||
| 9 | 1: | ||
| 10 | subs r2, r2, #1 | ||
| 11 | movlt pc, r14 | ||
| 12 | mrc p14, 0, r1, c0, c0, 0 | ||
| 13 | tst r1, #2 | ||
| 14 | bne 1b | ||
| 15 | |||
| 16 | mcr p14, 0, r0, c1, c0, 0 | ||
| 17 | mov pc, r14 | ||
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c index 5ab94584baee..0af3772efcb7 100644 --- a/arch/arm/boot/compressed/misc.c +++ b/arch/arm/boot/compressed/misc.c | |||
| @@ -20,24 +20,45 @@ unsigned int __machine_arch_type; | |||
| 20 | 20 | ||
| 21 | #include <linux/string.h> | 21 | #include <linux/string.h> |
| 22 | 22 | ||
| 23 | #include <asm/arch/uncompress.h> | ||
| 24 | |||
| 25 | #ifdef STANDALONE_DEBUG | 23 | #ifdef STANDALONE_DEBUG |
| 26 | #define putstr printf | 24 | #define putstr printf |
| 27 | #endif | 25 | #else |
| 26 | |||
| 27 | static void putstr(const char *ptr); | ||
| 28 | |||
| 29 | #include <linux/compiler.h> | ||
| 30 | #include <asm/arch/uncompress.h> | ||
| 28 | 31 | ||
| 29 | #ifdef CONFIG_DEBUG_ICEDCC | 32 | #ifdef CONFIG_DEBUG_ICEDCC |
| 30 | #define putstr icedcc_putstr | 33 | static void icedcc_putc(int ch) |
| 31 | #define putc icedcc_putc | 34 | { |
| 35 | int status, i = 0x4000000; | ||
| 32 | 36 | ||
| 33 | extern void icedcc_putc(int ch); | 37 | do { |
| 38 | if (--i < 0) | ||
| 39 | return; | ||
| 34 | 40 | ||
| 35 | static void | 41 | asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (status)); |
| 36 | icedcc_putstr(const char *ptr) | 42 | } while (status & 2); |
| 43 | |||
| 44 | asm("mcr p15, 0, %0, c1, c0, 0" : : "r" (ch)); | ||
| 45 | } | ||
| 46 | |||
| 47 | #define putc(ch) icedcc_putc(ch) | ||
| 48 | #define flush() do { } while (0) | ||
| 49 | #endif | ||
| 50 | |||
| 51 | static void putstr(const char *ptr) | ||
| 37 | { | 52 | { |
| 38 | for (; *ptr != '\0'; ptr++) { | 53 | char c; |
| 39 | icedcc_putc(*ptr); | 54 | |
| 55 | while ((c = *ptr++) != '\0') { | ||
| 56 | if (c == '\n') | ||
| 57 | putc('\r'); | ||
| 58 | putc(c); | ||
| 40 | } | 59 | } |
| 60 | |||
| 61 | flush(); | ||
| 41 | } | 62 | } |
| 42 | 63 | ||
| 43 | #endif | 64 | #endif |
diff --git a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c index e851d86c212c..35c9a64ac14c 100644 --- a/arch/arm/common/rtctime.c +++ b/arch/arm/common/rtctime.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/capability.h> | 20 | #include <linux/capability.h> |
| 21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
| 22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
| 23 | #include <linux/rtc.h> | ||
| 23 | 24 | ||
| 24 | #include <asm/rtc.h> | 25 | #include <asm/rtc.h> |
| 25 | #include <asm/semaphore.h> | 26 | #include <asm/semaphore.h> |
| @@ -42,89 +43,6 @@ static struct rtc_ops *rtc_ops; | |||
| 42 | 43 | ||
| 43 | #define rtc_epoch 1900UL | 44 | #define rtc_epoch 1900UL |
| 44 | 45 | ||
| 45 | static const unsigned char days_in_month[] = { | ||
| 46 | 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 | ||
| 47 | }; | ||
| 48 | |||
| 49 | #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) | ||
| 50 | #define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400)) | ||
| 51 | |||
| 52 | static int month_days(unsigned int month, unsigned int year) | ||
| 53 | { | ||
| 54 | return days_in_month[month] + (LEAP_YEAR(year) && month == 1); | ||
| 55 | } | ||
| 56 | |||
| 57 | /* | ||
| 58 | * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. | ||
| 59 | */ | ||
| 60 | void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) | ||
| 61 | { | ||
| 62 | int days, month, year; | ||
| 63 | |||
| 64 | days = time / 86400; | ||
| 65 | time -= days * 86400; | ||
| 66 | |||
| 67 | tm->tm_wday = (days + 4) % 7; | ||
| 68 | |||
| 69 | year = 1970 + days / 365; | ||
| 70 | days -= (year - 1970) * 365 | ||
| 71 | + LEAPS_THRU_END_OF(year - 1) | ||
| 72 | - LEAPS_THRU_END_OF(1970 - 1); | ||
| 73 | if (days < 0) { | ||
| 74 | year -= 1; | ||
| 75 | days += 365 + LEAP_YEAR(year); | ||
| 76 | } | ||
| 77 | tm->tm_year = year - 1900; | ||
| 78 | tm->tm_yday = days + 1; | ||
| 79 | |||
| 80 | for (month = 0; month < 11; month++) { | ||
| 81 | int newdays; | ||
| 82 | |||
| 83 | newdays = days - month_days(month, year); | ||
| 84 | if (newdays < 0) | ||
| 85 | break; | ||
| 86 | days = newdays; | ||
| 87 | } | ||
| 88 | tm->tm_mon = month; | ||
| 89 | tm->tm_mday = days + 1; | ||
| 90 | |||
| 91 | tm->tm_hour = time / 3600; | ||
| 92 | time -= tm->tm_hour * 3600; | ||
| 93 | tm->tm_min = time / 60; | ||
| 94 | tm->tm_sec = time - tm->tm_min * 60; | ||
| 95 | } | ||
| 96 | EXPORT_SYMBOL(rtc_time_to_tm); | ||
| 97 | |||
| 98 | /* | ||
| 99 | * Does the rtc_time represent a valid date/time? | ||
| 100 | */ | ||
| 101 | int rtc_valid_tm(struct rtc_time *tm) | ||
| 102 | { | ||
| 103 | if (tm->tm_year < 70 || | ||
| 104 | tm->tm_mon >= 12 || | ||
| 105 | tm->tm_mday < 1 || | ||
| 106 | tm->tm_mday > month_days(tm->tm_mon, tm->tm_year + 1900) || | ||
| 107 | tm->tm_hour >= 24 || | ||
| 108 | tm->tm_min >= 60 || | ||
| 109 | tm->tm_sec >= 60) | ||
| 110 | return -EINVAL; | ||
| 111 | |||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | EXPORT_SYMBOL(rtc_valid_tm); | ||
| 115 | |||
| 116 | /* | ||
| 117 | * Convert Gregorian date to seconds since 01-01-1970 00:00:00. | ||
| 118 | */ | ||
| 119 | int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) | ||
| 120 | { | ||
| 121 | *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | ||
| 122 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
| 123 | |||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | EXPORT_SYMBOL(rtc_tm_to_time); | ||
| 127 | |||
| 128 | /* | 46 | /* |
| 129 | * Calculate the next alarm time given the requested alarm time mask | 47 | * Calculate the next alarm time given the requested alarm time mask |
| 130 | * and the current time. | 48 | * and the current time. |
| @@ -151,13 +69,13 @@ void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc | |||
| 151 | } | 69 | } |
| 152 | } | 70 | } |
| 153 | 71 | ||
| 154 | static inline int rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm) | 72 | static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm) |
| 155 | { | 73 | { |
| 156 | memset(tm, 0, sizeof(struct rtc_time)); | 74 | memset(tm, 0, sizeof(struct rtc_time)); |
| 157 | return ops->read_time(tm); | 75 | return ops->read_time(tm); |
| 158 | } | 76 | } |
| 159 | 77 | ||
| 160 | static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm) | 78 | static inline int rtc_arm_set_time(struct rtc_ops *ops, struct rtc_time *tm) |
| 161 | { | 79 | { |
| 162 | int ret; | 80 | int ret; |
| 163 | 81 | ||
| @@ -168,7 +86,7 @@ static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm) | |||
| 168 | return ret; | 86 | return ret; |
| 169 | } | 87 | } |
| 170 | 88 | ||
| 171 | static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) | 89 | static inline int rtc_arm_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) |
| 172 | { | 90 | { |
| 173 | int ret = -EINVAL; | 91 | int ret = -EINVAL; |
| 174 | if (ops->read_alarm) { | 92 | if (ops->read_alarm) { |
| @@ -178,7 +96,7 @@ static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) | |||
| 178 | return ret; | 96 | return ret; |
| 179 | } | 97 | } |
| 180 | 98 | ||
| 181 | static inline int rtc_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) | 99 | static inline int rtc_arm_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) |
| 182 | { | 100 | { |
| 183 | int ret = -EINVAL; | 101 | int ret = -EINVAL; |
| 184 | if (ops->set_alarm) | 102 | if (ops->set_alarm) |
| @@ -266,7 +184,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 266 | 184 | ||
| 267 | switch (cmd) { | 185 | switch (cmd) { |
| 268 | case RTC_ALM_READ: | 186 | case RTC_ALM_READ: |
| 269 | ret = rtc_read_alarm(ops, &alrm); | 187 | ret = rtc_arm_read_alarm(ops, &alrm); |
| 270 | if (ret) | 188 | if (ret) |
| 271 | break; | 189 | break; |
| 272 | ret = copy_to_user(uarg, &alrm.time, sizeof(tm)); | 190 | ret = copy_to_user(uarg, &alrm.time, sizeof(tm)); |
| @@ -288,11 +206,11 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 288 | alrm.time.tm_wday = -1; | 206 | alrm.time.tm_wday = -1; |
| 289 | alrm.time.tm_yday = -1; | 207 | alrm.time.tm_yday = -1; |
| 290 | alrm.time.tm_isdst = -1; | 208 | alrm.time.tm_isdst = -1; |
| 291 | ret = rtc_set_alarm(ops, &alrm); | 209 | ret = rtc_arm_set_alarm(ops, &alrm); |
| 292 | break; | 210 | break; |
| 293 | 211 | ||
| 294 | case RTC_RD_TIME: | 212 | case RTC_RD_TIME: |
| 295 | ret = rtc_read_time(ops, &tm); | 213 | ret = rtc_arm_read_time(ops, &tm); |
| 296 | if (ret) | 214 | if (ret) |
| 297 | break; | 215 | break; |
| 298 | ret = copy_to_user(uarg, &tm, sizeof(tm)); | 216 | ret = copy_to_user(uarg, &tm, sizeof(tm)); |
| @@ -310,7 +228,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 310 | ret = -EFAULT; | 228 | ret = -EFAULT; |
| 311 | break; | 229 | break; |
| 312 | } | 230 | } |
| 313 | ret = rtc_set_time(ops, &tm); | 231 | ret = rtc_arm_set_time(ops, &tm); |
| 314 | break; | 232 | break; |
| 315 | 233 | ||
| 316 | case RTC_EPOCH_SET: | 234 | case RTC_EPOCH_SET: |
| @@ -341,11 +259,11 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 341 | ret = -EFAULT; | 259 | ret = -EFAULT; |
| 342 | break; | 260 | break; |
| 343 | } | 261 | } |
| 344 | ret = rtc_set_alarm(ops, &alrm); | 262 | ret = rtc_arm_set_alarm(ops, &alrm); |
| 345 | break; | 263 | break; |
| 346 | 264 | ||
| 347 | case RTC_WKALM_RD: | 265 | case RTC_WKALM_RD: |
| 348 | ret = rtc_read_alarm(ops, &alrm); | 266 | ret = rtc_arm_read_alarm(ops, &alrm); |
| 349 | if (ret) | 267 | if (ret) |
| 350 | break; | 268 | break; |
| 351 | ret = copy_to_user(uarg, &alrm, sizeof(alrm)); | 269 | ret = copy_to_user(uarg, &alrm, sizeof(alrm)); |
| @@ -435,7 +353,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo | |||
| 435 | struct rtc_time tm; | 353 | struct rtc_time tm; |
| 436 | char *p = page; | 354 | char *p = page; |
| 437 | 355 | ||
| 438 | if (rtc_read_time(ops, &tm) == 0) { | 356 | if (rtc_arm_read_time(ops, &tm) == 0) { |
| 439 | p += sprintf(p, | 357 | p += sprintf(p, |
| 440 | "rtc_time\t: %02d:%02d:%02d\n" | 358 | "rtc_time\t: %02d:%02d:%02d\n" |
| 441 | "rtc_date\t: %04d-%02d-%02d\n" | 359 | "rtc_date\t: %04d-%02d-%02d\n" |
| @@ -445,7 +363,7 @@ static int rtc_read_proc(char *page, char **start, off_t off, int count, int *eo | |||
| 445 | rtc_epoch); | 363 | rtc_epoch); |
| 446 | } | 364 | } |
| 447 | 365 | ||
| 448 | if (rtc_read_alarm(ops, &alrm) == 0) { | 366 | if (rtc_arm_read_alarm(ops, &alrm) == 0) { |
| 449 | p += sprintf(p, "alrm_time\t: "); | 367 | p += sprintf(p, "alrm_time\t: "); |
| 450 | if ((unsigned int)alrm.time.tm_hour <= 24) | 368 | if ((unsigned int)alrm.time.tm_hour <= 24) |
| 451 | p += sprintf(p, "%02d:", alrm.time.tm_hour); | 369 | p += sprintf(p, "%02d:", alrm.time.tm_hour); |
diff --git a/arch/arm/configs/ixp23xx_defconfig b/arch/arm/configs/ixp23xx_defconfig new file mode 100644 index 000000000000..1a2751e9ab05 --- /dev/null +++ b/arch/arm/configs/ixp23xx_defconfig | |||
| @@ -0,0 +1,1302 @@ | |||
| 1 | # | ||
| 2 | # Automatically generated make config: don't edit | ||
| 3 | # Linux kernel version: 2.6.16 | ||
| 4 | # Tue Mar 21 03:27:20 2006 | ||
| 5 | # | ||
| 6 | CONFIG_ARM=y | ||
| 7 | CONFIG_MMU=y | ||
| 8 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | ||
| 9 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
| 10 | |||
| 11 | # | ||
| 12 | # Code maturity level options | ||
| 13 | # | ||
| 14 | CONFIG_EXPERIMENTAL=y | ||
| 15 | CONFIG_BROKEN_ON_SMP=y | ||
| 16 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
| 17 | |||
| 18 | # | ||
| 19 | # General setup | ||
| 20 | # | ||
| 21 | CONFIG_LOCALVERSION="" | ||
| 22 | CONFIG_LOCALVERSION_AUTO=y | ||
| 23 | CONFIG_SWAP=y | ||
| 24 | CONFIG_SYSVIPC=y | ||
| 25 | # CONFIG_POSIX_MQUEUE is not set | ||
| 26 | CONFIG_BSD_PROCESS_ACCT=y | ||
| 27 | # CONFIG_BSD_PROCESS_ACCT_V3 is not set | ||
| 28 | CONFIG_SYSCTL=y | ||
| 29 | # CONFIG_AUDIT is not set | ||
| 30 | # CONFIG_IKCONFIG is not set | ||
| 31 | CONFIG_INITRAMFS_SOURCE="" | ||
| 32 | CONFIG_UID16=y | ||
| 33 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | ||
| 34 | CONFIG_EMBEDDED=y | ||
| 35 | CONFIG_KALLSYMS=y | ||
| 36 | # CONFIG_KALLSYMS_ALL is not set | ||
| 37 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | ||
| 38 | CONFIG_HOTPLUG=y | ||
| 39 | CONFIG_PRINTK=y | ||
| 40 | CONFIG_BUG=y | ||
| 41 | CONFIG_ELF_CORE=y | ||
| 42 | CONFIG_BASE_FULL=y | ||
| 43 | CONFIG_FUTEX=y | ||
| 44 | CONFIG_EPOLL=y | ||
| 45 | CONFIG_SHMEM=y | ||
| 46 | CONFIG_CC_ALIGN_FUNCTIONS=0 | ||
| 47 | CONFIG_CC_ALIGN_LABELS=0 | ||
| 48 | CONFIG_CC_ALIGN_LOOPS=0 | ||
| 49 | CONFIG_CC_ALIGN_JUMPS=0 | ||
| 50 | CONFIG_SLAB=y | ||
| 51 | # CONFIG_TINY_SHMEM is not set | ||
| 52 | CONFIG_BASE_SMALL=0 | ||
| 53 | # CONFIG_SLOB is not set | ||
| 54 | CONFIG_OBSOLETE_INTERMODULE=y | ||
| 55 | |||
| 56 | # | ||
| 57 | # Loadable module support | ||
| 58 | # | ||
| 59 | CONFIG_MODULES=y | ||
| 60 | CONFIG_MODULE_UNLOAD=y | ||
| 61 | # CONFIG_MODULE_FORCE_UNLOAD is not set | ||
| 62 | CONFIG_OBSOLETE_MODPARM=y | ||
| 63 | # CONFIG_MODVERSIONS is not set | ||
| 64 | # CONFIG_MODULE_SRCVERSION_ALL is not set | ||
| 65 | CONFIG_KMOD=y | ||
| 66 | |||
| 67 | # | ||
| 68 | # Block layer | ||
| 69 | # | ||
| 70 | |||
| 71 | # | ||
| 72 | # IO Schedulers | ||
| 73 | # | ||
| 74 | CONFIG_IOSCHED_NOOP=y | ||
| 75 | CONFIG_IOSCHED_AS=y | ||
| 76 | CONFIG_IOSCHED_DEADLINE=y | ||
| 77 | CONFIG_IOSCHED_CFQ=y | ||
| 78 | CONFIG_DEFAULT_AS=y | ||
| 79 | # CONFIG_DEFAULT_DEADLINE is not set | ||
| 80 | # CONFIG_DEFAULT_CFQ is not set | ||
| 81 | # CONFIG_DEFAULT_NOOP is not set | ||
| 82 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
| 83 | |||
| 84 | # | ||
| 85 | # System Type | ||
| 86 | # | ||
| 87 | # CONFIG_ARCH_CLPS7500 is not set | ||
| 88 | # CONFIG_ARCH_CLPS711X is not set | ||
| 89 | # CONFIG_ARCH_CO285 is not set | ||
| 90 | # CONFIG_ARCH_EBSA110 is not set | ||
| 91 | # CONFIG_ARCH_EP93XX is not set | ||
| 92 | # CONFIG_ARCH_FOOTBRIDGE is not set | ||
| 93 | # CONFIG_ARCH_INTEGRATOR is not set | ||
| 94 | # CONFIG_ARCH_IOP3XX is not set | ||
| 95 | # CONFIG_ARCH_IXP4XX is not set | ||
| 96 | # CONFIG_ARCH_IXP2000 is not set | ||
| 97 | CONFIG_ARCH_IXP23XX=y | ||
| 98 | # CONFIG_ARCH_L7200 is not set | ||
| 99 | # CONFIG_ARCH_PXA is not set | ||
| 100 | # CONFIG_ARCH_RPC is not set | ||
| 101 | # CONFIG_ARCH_SA1100 is not set | ||
| 102 | # CONFIG_ARCH_S3C2410 is not set | ||
| 103 | # CONFIG_ARCH_SHARK is not set | ||
| 104 | # CONFIG_ARCH_LH7A40X is not set | ||
| 105 | # CONFIG_ARCH_OMAP is not set | ||
| 106 | # CONFIG_ARCH_VERSATILE is not set | ||
| 107 | # CONFIG_ARCH_REALVIEW is not set | ||
| 108 | # CONFIG_ARCH_IMX is not set | ||
| 109 | # CONFIG_ARCH_H720X is not set | ||
| 110 | # CONFIG_ARCH_AAEC2000 is not set | ||
| 111 | # CONFIG_ARCH_AT91RM9200 is not set | ||
| 112 | CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y | ||
| 113 | |||
| 114 | # | ||
| 115 | # Intel IXP23xx Implementation Options | ||
| 116 | # | ||
| 117 | |||
| 118 | # | ||
| 119 | # IXP23xx Platforms | ||
| 120 | # | ||
| 121 | CONFIG_MACH_ESPRESSO=y | ||
| 122 | CONFIG_MACH_IXDP2351=y | ||
| 123 | CONFIG_MACH_ROADRUNNER=y | ||
| 124 | |||
| 125 | # | ||
| 126 | # Processor Type | ||
| 127 | # | ||
| 128 | CONFIG_CPU_32=y | ||
| 129 | CONFIG_CPU_XSC3=y | ||
| 130 | CONFIG_CPU_32v5=y | ||
| 131 | CONFIG_CPU_ABRT_EV5T=y | ||
| 132 | CONFIG_CPU_CACHE_VIVT=y | ||
| 133 | CONFIG_CPU_TLB_V4WBI=y | ||
| 134 | CONFIG_IO_36=y | ||
| 135 | |||
| 136 | # | ||
| 137 | # Processor Features | ||
| 138 | # | ||
| 139 | # CONFIG_ARM_THUMB is not set | ||
| 140 | CONFIG_CPU_BIG_ENDIAN=y | ||
| 141 | |||
| 142 | # | ||
| 143 | # Bus support | ||
| 144 | # | ||
| 145 | CONFIG_PCI=y | ||
| 146 | CONFIG_PCI_LEGACY_PROC=y | ||
| 147 | # CONFIG_PCI_DEBUG is not set | ||
| 148 | |||
| 149 | # | ||
| 150 | # PCCARD (PCMCIA/CardBus) support | ||
| 151 | # | ||
| 152 | # CONFIG_PCCARD is not set | ||
| 153 | |||
| 154 | # | ||
| 155 | # Kernel Features | ||
| 156 | # | ||
| 157 | # CONFIG_PREEMPT is not set | ||
| 158 | # CONFIG_NO_IDLE_HZ is not set | ||
| 159 | CONFIG_HZ=100 | ||
| 160 | # CONFIG_AEABI is not set | ||
| 161 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set | ||
| 162 | CONFIG_SELECT_MEMORY_MODEL=y | ||
| 163 | CONFIG_FLATMEM_MANUAL=y | ||
| 164 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
| 165 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
| 166 | CONFIG_FLATMEM=y | ||
| 167 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
| 168 | # CONFIG_SPARSEMEM_STATIC is not set | ||
| 169 | CONFIG_SPLIT_PTLOCK_CPUS=4096 | ||
| 170 | CONFIG_ALIGNMENT_TRAP=y | ||
| 171 | |||
| 172 | # | ||
| 173 | # Boot options | ||
| 174 | # | ||
| 175 | CONFIG_ZBOOT_ROM_TEXT=0x0 | ||
| 176 | CONFIG_ZBOOT_ROM_BSS=0x0 | ||
| 177 | CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp" | ||
| 178 | # CONFIG_XIP_KERNEL is not set | ||
| 179 | |||
| 180 | # | ||
| 181 | # Floating point emulation | ||
| 182 | # | ||
| 183 | |||
| 184 | # | ||
| 185 | # At least one emulation must be selected | ||
| 186 | # | ||
| 187 | CONFIG_FPE_NWFPE=y | ||
| 188 | CONFIG_FPE_NWFPE_XP=y | ||
| 189 | # CONFIG_FPE_FASTFPE is not set | ||
| 190 | |||
| 191 | # | ||
| 192 | # Userspace binary formats | ||
| 193 | # | ||
| 194 | CONFIG_BINFMT_ELF=y | ||
| 195 | # CONFIG_BINFMT_AOUT is not set | ||
| 196 | # CONFIG_BINFMT_MISC is not set | ||
| 197 | # CONFIG_ARTHUR is not set | ||
| 198 | |||
| 199 | # | ||
| 200 | # Power management options | ||
| 201 | # | ||
| 202 | # CONFIG_PM is not set | ||
| 203 | # CONFIG_APM is not set | ||
| 204 | |||
| 205 | # | ||
| 206 | # Networking | ||
| 207 | # | ||
| 208 | CONFIG_NET=y | ||
| 209 | |||
| 210 | # | ||
| 211 | # Networking options | ||
| 212 | # | ||
| 213 | # CONFIG_NETDEBUG is not set | ||
| 214 | CONFIG_PACKET=y | ||
| 215 | CONFIG_PACKET_MMAP=y | ||
| 216 | CONFIG_UNIX=y | ||
| 217 | # CONFIG_NET_KEY is not set | ||
| 218 | CONFIG_INET=y | ||
| 219 | # CONFIG_IP_MULTICAST is not set | ||
| 220 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
| 221 | CONFIG_IP_FIB_HASH=y | ||
| 222 | CONFIG_IP_PNP=y | ||
| 223 | CONFIG_IP_PNP_DHCP=y | ||
| 224 | CONFIG_IP_PNP_BOOTP=y | ||
| 225 | # CONFIG_IP_PNP_RARP is not set | ||
| 226 | # CONFIG_NET_IPIP is not set | ||
| 227 | # CONFIG_NET_IPGRE is not set | ||
| 228 | # CONFIG_ARPD is not set | ||
| 229 | CONFIG_SYN_COOKIES=y | ||
| 230 | # CONFIG_INET_AH is not set | ||
| 231 | # CONFIG_INET_ESP is not set | ||
| 232 | # CONFIG_INET_IPCOMP is not set | ||
| 233 | # CONFIG_INET_TUNNEL is not set | ||
| 234 | CONFIG_INET_DIAG=y | ||
| 235 | CONFIG_INET_TCP_DIAG=y | ||
| 236 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
| 237 | CONFIG_TCP_CONG_BIC=y | ||
| 238 | # CONFIG_IPV6 is not set | ||
| 239 | # CONFIG_NETFILTER is not set | ||
| 240 | |||
| 241 | # | ||
| 242 | # DCCP Configuration (EXPERIMENTAL) | ||
| 243 | # | ||
| 244 | # CONFIG_IP_DCCP is not set | ||
| 245 | |||
| 246 | # | ||
| 247 | # SCTP Configuration (EXPERIMENTAL) | ||
| 248 | # | ||
| 249 | # CONFIG_IP_SCTP is not set | ||
| 250 | |||
| 251 | # | ||
| 252 | # TIPC Configuration (EXPERIMENTAL) | ||
| 253 | # | ||
| 254 | # CONFIG_TIPC is not set | ||
| 255 | # CONFIG_ATM is not set | ||
| 256 | # CONFIG_BRIDGE is not set | ||
| 257 | # CONFIG_VLAN_8021Q is not set | ||
| 258 | # CONFIG_DECNET is not set | ||
| 259 | # CONFIG_LLC2 is not set | ||
| 260 | # CONFIG_IPX is not set | ||
| 261 | # CONFIG_ATALK is not set | ||
| 262 | # CONFIG_X25 is not set | ||
| 263 | # CONFIG_LAPB is not set | ||
| 264 | # CONFIG_NET_DIVERT is not set | ||
| 265 | # CONFIG_ECONET is not set | ||
| 266 | # CONFIG_WAN_ROUTER is not set | ||
| 267 | |||
| 268 | # | ||
| 269 | # QoS and/or fair queueing | ||
| 270 | # | ||
| 271 | # CONFIG_NET_SCHED is not set | ||
| 272 | |||
| 273 | # | ||
| 274 | # Network testing | ||
| 275 | # | ||
| 276 | # CONFIG_NET_PKTGEN is not set | ||
| 277 | # CONFIG_HAMRADIO is not set | ||
| 278 | # CONFIG_IRDA is not set | ||
| 279 | # CONFIG_BT is not set | ||
| 280 | # CONFIG_IEEE80211 is not set | ||
| 281 | |||
| 282 | # | ||
| 283 | # Device Drivers | ||
| 284 | # | ||
| 285 | |||
| 286 | # | ||
| 287 | # Generic Driver Options | ||
| 288 | # | ||
| 289 | CONFIG_STANDALONE=y | ||
| 290 | # CONFIG_PREVENT_FIRMWARE_BUILD is not set | ||
| 291 | # CONFIG_FW_LOADER is not set | ||
| 292 | # CONFIG_DEBUG_DRIVER is not set | ||
| 293 | |||
| 294 | # | ||
| 295 | # Connector - unified userspace <-> kernelspace linker | ||
| 296 | # | ||
| 297 | # CONFIG_CONNECTOR is not set | ||
| 298 | |||
| 299 | # | ||
| 300 | # Memory Technology Devices (MTD) | ||
| 301 | # | ||
| 302 | CONFIG_MTD=y | ||
| 303 | # CONFIG_MTD_DEBUG is not set | ||
| 304 | # CONFIG_MTD_CONCAT is not set | ||
| 305 | CONFIG_MTD_PARTITIONS=y | ||
| 306 | CONFIG_MTD_REDBOOT_PARTS=y | ||
| 307 | CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 | ||
| 308 | CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y | ||
| 309 | CONFIG_MTD_REDBOOT_PARTS_READONLY=y | ||
| 310 | # CONFIG_MTD_CMDLINE_PARTS is not set | ||
| 311 | # CONFIG_MTD_AFS_PARTS is not set | ||
| 312 | |||
| 313 | # | ||
| 314 | # User Modules And Translation Layers | ||
| 315 | # | ||
| 316 | CONFIG_MTD_CHAR=y | ||
| 317 | CONFIG_MTD_BLOCK=y | ||
| 318 | # CONFIG_FTL is not set | ||
| 319 | # CONFIG_NFTL is not set | ||
| 320 | # CONFIG_INFTL is not set | ||
| 321 | # CONFIG_RFD_FTL is not set | ||
| 322 | |||
| 323 | # | ||
| 324 | # RAM/ROM/Flash chip drivers | ||
| 325 | # | ||
| 326 | CONFIG_MTD_CFI=y | ||
| 327 | # CONFIG_MTD_JEDECPROBE is not set | ||
| 328 | CONFIG_MTD_GEN_PROBE=y | ||
| 329 | # CONFIG_MTD_CFI_ADV_OPTIONS is not set | ||
| 330 | CONFIG_MTD_MAP_BANK_WIDTH_1=y | ||
| 331 | CONFIG_MTD_MAP_BANK_WIDTH_2=y | ||
| 332 | CONFIG_MTD_MAP_BANK_WIDTH_4=y | ||
| 333 | # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set | ||
| 334 | # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set | ||
| 335 | # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set | ||
| 336 | CONFIG_MTD_CFI_I1=y | ||
| 337 | CONFIG_MTD_CFI_I2=y | ||
| 338 | # CONFIG_MTD_CFI_I4 is not set | ||
| 339 | # CONFIG_MTD_CFI_I8 is not set | ||
| 340 | CONFIG_MTD_CFI_INTELEXT=y | ||
| 341 | # CONFIG_MTD_CFI_AMDSTD is not set | ||
| 342 | # CONFIG_MTD_CFI_STAA is not set | ||
| 343 | CONFIG_MTD_CFI_UTIL=y | ||
| 344 | # CONFIG_MTD_RAM is not set | ||
| 345 | # CONFIG_MTD_ROM is not set | ||
| 346 | # CONFIG_MTD_ABSENT is not set | ||
| 347 | # CONFIG_MTD_OBSOLETE_CHIPS is not set | ||
| 348 | |||
| 349 | # | ||
| 350 | # Mapping drivers for chip access | ||
| 351 | # | ||
| 352 | CONFIG_MTD_COMPLEX_MAPPINGS=y | ||
| 353 | CONFIG_MTD_PHYSMAP=y | ||
| 354 | CONFIG_MTD_PHYSMAP_START=0x0 | ||
| 355 | CONFIG_MTD_PHYSMAP_LEN=0x0 | ||
| 356 | CONFIG_MTD_PHYSMAP_BANKWIDTH=1 | ||
| 357 | # CONFIG_MTD_ARM_INTEGRATOR is not set | ||
| 358 | # CONFIG_MTD_PCI is not set | ||
| 359 | # CONFIG_MTD_PLATRAM is not set | ||
| 360 | |||
| 361 | # | ||
| 362 | # Self-contained MTD device drivers | ||
| 363 | # | ||
| 364 | # CONFIG_MTD_PMC551 is not set | ||
| 365 | # CONFIG_MTD_SLRAM is not set | ||
| 366 | # CONFIG_MTD_PHRAM is not set | ||
| 367 | # CONFIG_MTD_MTDRAM is not set | ||
| 368 | # CONFIG_MTD_BLKMTD is not set | ||
| 369 | # CONFIG_MTD_BLOCK2MTD is not set | ||
| 370 | |||
| 371 | # | ||
| 372 | # Disk-On-Chip Device Drivers | ||
| 373 | # | ||
| 374 | # CONFIG_MTD_DOC2000 is not set | ||
| 375 | # CONFIG_MTD_DOC2001 is not set | ||
| 376 | # CONFIG_MTD_DOC2001PLUS is not set | ||
| 377 | |||
| 378 | # | ||
| 379 | # NAND Flash Device Drivers | ||
| 380 | # | ||
| 381 | # CONFIG_MTD_NAND is not set | ||
| 382 | |||
| 383 | # | ||
| 384 | # OneNAND Flash Device Drivers | ||
| 385 | # | ||
| 386 | # CONFIG_MTD_ONENAND is not set | ||
| 387 | |||
| 388 | # | ||
| 389 | # Parallel port support | ||
| 390 | # | ||
| 391 | # CONFIG_PARPORT is not set | ||
| 392 | |||
| 393 | # | ||
| 394 | # Plug and Play support | ||
| 395 | # | ||
| 396 | |||
| 397 | # | ||
| 398 | # Block devices | ||
| 399 | # | ||
| 400 | # CONFIG_BLK_CPQ_DA is not set | ||
| 401 | # CONFIG_BLK_CPQ_CISS_DA is not set | ||
| 402 | # CONFIG_BLK_DEV_DAC960 is not set | ||
| 403 | # CONFIG_BLK_DEV_UMEM is not set | ||
| 404 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
| 405 | CONFIG_BLK_DEV_LOOP=y | ||
| 406 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | ||
| 407 | # CONFIG_BLK_DEV_NBD is not set | ||
| 408 | # CONFIG_BLK_DEV_SX8 is not set | ||
| 409 | # CONFIG_BLK_DEV_UB is not set | ||
| 410 | CONFIG_BLK_DEV_RAM=y | ||
| 411 | CONFIG_BLK_DEV_RAM_COUNT=16 | ||
| 412 | CONFIG_BLK_DEV_RAM_SIZE=8192 | ||
| 413 | CONFIG_BLK_DEV_INITRD=y | ||
| 414 | # CONFIG_CDROM_PKTCDVD is not set | ||
| 415 | # CONFIG_ATA_OVER_ETH is not set | ||
| 416 | |||
| 417 | # | ||
| 418 | # ATA/ATAPI/MFM/RLL support | ||
| 419 | # | ||
| 420 | CONFIG_IDE=y | ||
| 421 | CONFIG_BLK_DEV_IDE=y | ||
| 422 | |||
| 423 | # | ||
| 424 | # Please see Documentation/ide.txt for help/info on IDE drives | ||
| 425 | # | ||
| 426 | # CONFIG_BLK_DEV_IDE_SATA is not set | ||
| 427 | CONFIG_BLK_DEV_IDEDISK=y | ||
| 428 | # CONFIG_IDEDISK_MULTI_MODE is not set | ||
| 429 | # CONFIG_BLK_DEV_IDECD is not set | ||
| 430 | # CONFIG_BLK_DEV_IDETAPE is not set | ||
| 431 | # CONFIG_BLK_DEV_IDEFLOPPY is not set | ||
| 432 | # CONFIG_BLK_DEV_IDESCSI is not set | ||
| 433 | # CONFIG_IDE_TASK_IOCTL is not set | ||
| 434 | |||
| 435 | # | ||
| 436 | # IDE chipset support/bugfixes | ||
| 437 | # | ||
| 438 | CONFIG_IDE_GENERIC=y | ||
| 439 | CONFIG_BLK_DEV_IDEPCI=y | ||
| 440 | # CONFIG_IDEPCI_SHARE_IRQ is not set | ||
| 441 | # CONFIG_BLK_DEV_OFFBOARD is not set | ||
| 442 | # CONFIG_BLK_DEV_GENERIC is not set | ||
| 443 | # CONFIG_BLK_DEV_OPTI621 is not set | ||
| 444 | # CONFIG_BLK_DEV_SL82C105 is not set | ||
| 445 | CONFIG_BLK_DEV_IDEDMA_PCI=y | ||
| 446 | # CONFIG_BLK_DEV_IDEDMA_FORCED is not set | ||
| 447 | # CONFIG_IDEDMA_PCI_AUTO is not set | ||
| 448 | # CONFIG_BLK_DEV_AEC62XX is not set | ||
| 449 | # CONFIG_BLK_DEV_ALI15X3 is not set | ||
| 450 | # CONFIG_BLK_DEV_AMD74XX is not set | ||
| 451 | # CONFIG_BLK_DEV_CMD64X is not set | ||
| 452 | # CONFIG_BLK_DEV_TRIFLEX is not set | ||
| 453 | # CONFIG_BLK_DEV_CY82C693 is not set | ||
| 454 | # CONFIG_BLK_DEV_CS5520 is not set | ||
| 455 | # CONFIG_BLK_DEV_CS5530 is not set | ||
| 456 | # CONFIG_BLK_DEV_HPT34X is not set | ||
| 457 | # CONFIG_BLK_DEV_HPT366 is not set | ||
| 458 | # CONFIG_BLK_DEV_SC1200 is not set | ||
| 459 | # CONFIG_BLK_DEV_PIIX is not set | ||
| 460 | # CONFIG_BLK_DEV_IT821X is not set | ||
| 461 | # CONFIG_BLK_DEV_NS87415 is not set | ||
| 462 | # CONFIG_BLK_DEV_PDC202XX_OLD is not set | ||
| 463 | # CONFIG_BLK_DEV_PDC202XX_NEW is not set | ||
| 464 | # CONFIG_BLK_DEV_SVWKS is not set | ||
| 465 | CONFIG_BLK_DEV_SIIMAGE=y | ||
| 466 | # CONFIG_BLK_DEV_SLC90E66 is not set | ||
| 467 | # CONFIG_BLK_DEV_TRM290 is not set | ||
| 468 | # CONFIG_BLK_DEV_VIA82CXXX is not set | ||
| 469 | # CONFIG_IDE_ARM is not set | ||
| 470 | CONFIG_BLK_DEV_IDEDMA=y | ||
| 471 | # CONFIG_IDEDMA_IVB is not set | ||
| 472 | # CONFIG_IDEDMA_AUTO is not set | ||
| 473 | # CONFIG_BLK_DEV_HD is not set | ||
| 474 | |||
| 475 | # | ||
| 476 | # SCSI device support | ||
| 477 | # | ||
| 478 | # CONFIG_RAID_ATTRS is not set | ||
| 479 | CONFIG_SCSI=y | ||
| 480 | CONFIG_SCSI_PROC_FS=y | ||
| 481 | |||
| 482 | # | ||
| 483 | # SCSI support type (disk, tape, CD-ROM) | ||
| 484 | # | ||
| 485 | CONFIG_BLK_DEV_SD=y | ||
| 486 | # CONFIG_CHR_DEV_ST is not set | ||
| 487 | # CONFIG_CHR_DEV_OSST is not set | ||
| 488 | # CONFIG_BLK_DEV_SR is not set | ||
| 489 | # CONFIG_CHR_DEV_SG is not set | ||
| 490 | # CONFIG_CHR_DEV_SCH is not set | ||
| 491 | |||
| 492 | # | ||
| 493 | # Some SCSI devices (e.g. CD jukebox) support multiple LUNs | ||
| 494 | # | ||
| 495 | # CONFIG_SCSI_MULTI_LUN is not set | ||
| 496 | # CONFIG_SCSI_CONSTANTS is not set | ||
| 497 | # CONFIG_SCSI_LOGGING is not set | ||
| 498 | |||
| 499 | # | ||
| 500 | # SCSI Transport Attributes | ||
| 501 | # | ||
| 502 | # CONFIG_SCSI_SPI_ATTRS is not set | ||
| 503 | # CONFIG_SCSI_FC_ATTRS is not set | ||
| 504 | # CONFIG_SCSI_ISCSI_ATTRS is not set | ||
| 505 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
| 506 | |||
| 507 | # | ||
| 508 | # SCSI low-level drivers | ||
| 509 | # | ||
| 510 | # CONFIG_ISCSI_TCP is not set | ||
| 511 | # CONFIG_BLK_DEV_3W_XXXX_RAID is not set | ||
| 512 | # CONFIG_SCSI_3W_9XXX is not set | ||
| 513 | # CONFIG_SCSI_ACARD is not set | ||
| 514 | # CONFIG_SCSI_AACRAID is not set | ||
| 515 | # CONFIG_SCSI_AIC7XXX is not set | ||
| 516 | # CONFIG_SCSI_AIC7XXX_OLD is not set | ||
| 517 | # CONFIG_SCSI_AIC79XX is not set | ||
| 518 | # CONFIG_SCSI_DPT_I2O is not set | ||
| 519 | # CONFIG_MEGARAID_NEWGEN is not set | ||
| 520 | # CONFIG_MEGARAID_LEGACY is not set | ||
| 521 | # CONFIG_MEGARAID_SAS is not set | ||
| 522 | # CONFIG_SCSI_SATA is not set | ||
| 523 | # CONFIG_SCSI_DMX3191D is not set | ||
| 524 | # CONFIG_SCSI_FUTURE_DOMAIN is not set | ||
| 525 | # CONFIG_SCSI_IPS is not set | ||
| 526 | # CONFIG_SCSI_INITIO is not set | ||
| 527 | # CONFIG_SCSI_INIA100 is not set | ||
| 528 | # CONFIG_SCSI_SYM53C8XX_2 is not set | ||
| 529 | # CONFIG_SCSI_IPR is not set | ||
| 530 | # CONFIG_SCSI_QLOGIC_FC is not set | ||
| 531 | # CONFIG_SCSI_QLOGIC_1280 is not set | ||
| 532 | # CONFIG_SCSI_QLA_FC is not set | ||
| 533 | # CONFIG_SCSI_LPFC is not set | ||
| 534 | # CONFIG_SCSI_DC395x is not set | ||
| 535 | # CONFIG_SCSI_DC390T is not set | ||
| 536 | # CONFIG_SCSI_NSP32 is not set | ||
| 537 | # CONFIG_SCSI_DEBUG is not set | ||
| 538 | |||
| 539 | # | ||
| 540 | # Multi-device support (RAID and LVM) | ||
| 541 | # | ||
| 542 | # CONFIG_MD is not set | ||
| 543 | |||
| 544 | # | ||
| 545 | # Fusion MPT device support | ||
| 546 | # | ||
| 547 | # CONFIG_FUSION is not set | ||
| 548 | # CONFIG_FUSION_SPI is not set | ||
| 549 | # CONFIG_FUSION_FC is not set | ||
| 550 | # CONFIG_FUSION_SAS is not set | ||
| 551 | |||
| 552 | # | ||
| 553 | # IEEE 1394 (FireWire) support | ||
| 554 | # | ||
| 555 | # CONFIG_IEEE1394 is not set | ||
| 556 | |||
| 557 | # | ||
| 558 | # I2O device support | ||
| 559 | # | ||
| 560 | # CONFIG_I2O is not set | ||
| 561 | |||
| 562 | # | ||
| 563 | # Network device support | ||
| 564 | # | ||
| 565 | CONFIG_NETDEVICES=y | ||
| 566 | CONFIG_DUMMY=y | ||
| 567 | # CONFIG_BONDING is not set | ||
| 568 | # CONFIG_EQUALIZER is not set | ||
| 569 | # CONFIG_TUN is not set | ||
| 570 | |||
| 571 | # | ||
| 572 | # ARCnet devices | ||
| 573 | # | ||
| 574 | # CONFIG_ARCNET is not set | ||
| 575 | |||
| 576 | # | ||
| 577 | # PHY device support | ||
| 578 | # | ||
| 579 | # CONFIG_PHYLIB is not set | ||
| 580 | |||
| 581 | # | ||
| 582 | # Ethernet (10 or 100Mbit) | ||
| 583 | # | ||
| 584 | CONFIG_NET_ETHERNET=y | ||
| 585 | CONFIG_MII=y | ||
| 586 | # CONFIG_HAPPYMEAL is not set | ||
| 587 | # CONFIG_SUNGEM is not set | ||
| 588 | # CONFIG_CASSINI is not set | ||
| 589 | # CONFIG_NET_VENDOR_3COM is not set | ||
| 590 | # CONFIG_SMC91X is not set | ||
| 591 | # CONFIG_DM9000 is not set | ||
| 592 | |||
| 593 | # | ||
| 594 | # Tulip family network device support | ||
| 595 | # | ||
| 596 | # CONFIG_NET_TULIP is not set | ||
| 597 | # CONFIG_HP100 is not set | ||
| 598 | CONFIG_NET_PCI=y | ||
| 599 | # CONFIG_PCNET32 is not set | ||
| 600 | # CONFIG_AMD8111_ETH is not set | ||
| 601 | # CONFIG_ADAPTEC_STARFIRE is not set | ||
| 602 | # CONFIG_B44 is not set | ||
| 603 | # CONFIG_FORCEDETH is not set | ||
| 604 | # CONFIG_CS89x0 is not set | ||
| 605 | # CONFIG_DGRS is not set | ||
| 606 | # CONFIG_EEPRO100 is not set | ||
| 607 | CONFIG_E100=y | ||
| 608 | # CONFIG_FEALNX is not set | ||
| 609 | # CONFIG_NATSEMI is not set | ||
| 610 | # CONFIG_NE2K_PCI is not set | ||
| 611 | # CONFIG_8139CP is not set | ||
| 612 | # CONFIG_8139TOO is not set | ||
| 613 | # CONFIG_SIS900 is not set | ||
| 614 | # CONFIG_EPIC100 is not set | ||
| 615 | # CONFIG_SUNDANCE is not set | ||
| 616 | # CONFIG_TLAN is not set | ||
| 617 | # CONFIG_VIA_RHINE is not set | ||
| 618 | |||
| 619 | # | ||
| 620 | # Ethernet (1000 Mbit) | ||
| 621 | # | ||
| 622 | # CONFIG_ACENIC is not set | ||
| 623 | # CONFIG_DL2K is not set | ||
| 624 | CONFIG_E1000=y | ||
| 625 | CONFIG_E1000_NAPI=y | ||
| 626 | # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set | ||
| 627 | # CONFIG_NS83820 is not set | ||
| 628 | # CONFIG_HAMACHI is not set | ||
| 629 | # CONFIG_YELLOWFIN is not set | ||
| 630 | # CONFIG_R8169 is not set | ||
| 631 | # CONFIG_SIS190 is not set | ||
| 632 | # CONFIG_SKGE is not set | ||
| 633 | # CONFIG_SKY2 is not set | ||
| 634 | # CONFIG_SK98LIN is not set | ||
| 635 | # CONFIG_VIA_VELOCITY is not set | ||
| 636 | # CONFIG_TIGON3 is not set | ||
| 637 | # CONFIG_BNX2 is not set | ||
| 638 | |||
| 639 | # | ||
| 640 | # Ethernet (10000 Mbit) | ||
| 641 | # | ||
| 642 | # CONFIG_CHELSIO_T1 is not set | ||
| 643 | # CONFIG_IXGB is not set | ||
| 644 | # CONFIG_S2IO is not set | ||
| 645 | |||
| 646 | # | ||
| 647 | # Token Ring devices | ||
| 648 | # | ||
| 649 | # CONFIG_TR is not set | ||
| 650 | |||
| 651 | # | ||
| 652 | # Wireless LAN (non-hamradio) | ||
| 653 | # | ||
| 654 | # CONFIG_NET_RADIO is not set | ||
| 655 | |||
| 656 | # | ||
| 657 | # Wan interfaces | ||
| 658 | # | ||
| 659 | CONFIG_WAN=y | ||
| 660 | # CONFIG_DSCC4 is not set | ||
| 661 | # CONFIG_LANMEDIA is not set | ||
| 662 | # CONFIG_SYNCLINK_SYNCPPP is not set | ||
| 663 | CONFIG_HDLC=y | ||
| 664 | CONFIG_HDLC_RAW=y | ||
| 665 | # CONFIG_HDLC_RAW_ETH is not set | ||
| 666 | CONFIG_HDLC_CISCO=y | ||
| 667 | CONFIG_HDLC_FR=y | ||
| 668 | CONFIG_HDLC_PPP=y | ||
| 669 | |||
| 670 | # | ||
| 671 | # X.25/LAPB support is disabled | ||
| 672 | # | ||
| 673 | # CONFIG_PCI200SYN is not set | ||
| 674 | # CONFIG_WANXL is not set | ||
| 675 | # CONFIG_PC300 is not set | ||
| 676 | # CONFIG_FARSYNC is not set | ||
| 677 | CONFIG_DLCI=y | ||
| 678 | CONFIG_DLCI_COUNT=24 | ||
| 679 | CONFIG_DLCI_MAX=8 | ||
| 680 | # CONFIG_FDDI is not set | ||
| 681 | # CONFIG_HIPPI is not set | ||
| 682 | # CONFIG_PPP is not set | ||
| 683 | # CONFIG_SLIP is not set | ||
| 684 | # CONFIG_NET_FC is not set | ||
| 685 | # CONFIG_SHAPER is not set | ||
| 686 | # CONFIG_NETCONSOLE is not set | ||
| 687 | # CONFIG_NETPOLL is not set | ||
| 688 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
| 689 | |||
| 690 | # | ||
| 691 | # ISDN subsystem | ||
| 692 | # | ||
| 693 | # CONFIG_ISDN is not set | ||
| 694 | |||
| 695 | # | ||
| 696 | # Input device support | ||
| 697 | # | ||
| 698 | CONFIG_INPUT=y | ||
| 699 | |||
| 700 | # | ||
| 701 | # Userland interfaces | ||
| 702 | # | ||
| 703 | CONFIG_INPUT_MOUSEDEV=y | ||
| 704 | CONFIG_INPUT_MOUSEDEV_PSAUX=y | ||
| 705 | CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 | ||
| 706 | CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | ||
| 707 | # CONFIG_INPUT_JOYDEV is not set | ||
| 708 | # CONFIG_INPUT_TSDEV is not set | ||
| 709 | # CONFIG_INPUT_EVDEV is not set | ||
| 710 | # CONFIG_INPUT_EVBUG is not set | ||
| 711 | |||
| 712 | # | ||
| 713 | # Input Device Drivers | ||
| 714 | # | ||
| 715 | # CONFIG_INPUT_KEYBOARD is not set | ||
| 716 | # CONFIG_INPUT_MOUSE is not set | ||
| 717 | # CONFIG_INPUT_JOYSTICK is not set | ||
| 718 | # CONFIG_INPUT_TOUCHSCREEN is not set | ||
| 719 | # CONFIG_INPUT_MISC is not set | ||
| 720 | |||
| 721 | # | ||
| 722 | # Hardware I/O ports | ||
| 723 | # | ||
| 724 | # CONFIG_SERIO is not set | ||
| 725 | # CONFIG_GAMEPORT is not set | ||
| 726 | |||
| 727 | # | ||
| 728 | # Character devices | ||
| 729 | # | ||
| 730 | # CONFIG_VT is not set | ||
| 731 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
| 732 | |||
| 733 | # | ||
| 734 | # Serial drivers | ||
| 735 | # | ||
| 736 | CONFIG_SERIAL_8250=y | ||
| 737 | CONFIG_SERIAL_8250_CONSOLE=y | ||
| 738 | CONFIG_SERIAL_8250_NR_UARTS=4 | ||
| 739 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | ||
| 740 | # CONFIG_SERIAL_8250_EXTENDED is not set | ||
| 741 | |||
| 742 | # | ||
| 743 | # Non-8250 serial port support | ||
| 744 | # | ||
| 745 | CONFIG_SERIAL_CORE=y | ||
| 746 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
| 747 | # CONFIG_SERIAL_JSM is not set | ||
| 748 | CONFIG_UNIX98_PTYS=y | ||
| 749 | CONFIG_LEGACY_PTYS=y | ||
| 750 | CONFIG_LEGACY_PTY_COUNT=256 | ||
| 751 | |||
| 752 | # | ||
| 753 | # IPMI | ||
| 754 | # | ||
| 755 | # CONFIG_IPMI_HANDLER is not set | ||
| 756 | |||
| 757 | # | ||
| 758 | # Watchdog Cards | ||
| 759 | # | ||
| 760 | CONFIG_WATCHDOG=y | ||
| 761 | # CONFIG_WATCHDOG_NOWAYOUT is not set | ||
| 762 | |||
| 763 | # | ||
| 764 | # Watchdog Device Drivers | ||
| 765 | # | ||
| 766 | # CONFIG_SOFT_WATCHDOG is not set | ||
| 767 | |||
| 768 | # | ||
| 769 | # PCI-based Watchdog Cards | ||
| 770 | # | ||
| 771 | # CONFIG_PCIPCWATCHDOG is not set | ||
| 772 | # CONFIG_WDTPCI is not set | ||
| 773 | |||
| 774 | # | ||
| 775 | # USB-based Watchdog Cards | ||
| 776 | # | ||
| 777 | # CONFIG_USBPCWATCHDOG is not set | ||
| 778 | # CONFIG_NVRAM is not set | ||
| 779 | # CONFIG_RTC is not set | ||
| 780 | # CONFIG_DTLK is not set | ||
| 781 | # CONFIG_R3964 is not set | ||
| 782 | # CONFIG_APPLICOM is not set | ||
| 783 | |||
| 784 | # | ||
| 785 | # Ftape, the floppy tape device driver | ||
| 786 | # | ||
| 787 | # CONFIG_DRM is not set | ||
| 788 | # CONFIG_RAW_DRIVER is not set | ||
| 789 | |||
| 790 | # | ||
| 791 | # TPM devices | ||
| 792 | # | ||
| 793 | # CONFIG_TCG_TPM is not set | ||
| 794 | # CONFIG_TELCLOCK is not set | ||
| 795 | |||
| 796 | # | ||
| 797 | # I2C support | ||
| 798 | # | ||
| 799 | CONFIG_I2C=y | ||
| 800 | CONFIG_I2C_CHARDEV=y | ||
| 801 | |||
| 802 | # | ||
| 803 | # I2C Algorithms | ||
| 804 | # | ||
| 805 | CONFIG_I2C_ALGOBIT=y | ||
| 806 | # CONFIG_I2C_ALGOPCF is not set | ||
| 807 | # CONFIG_I2C_ALGOPCA is not set | ||
| 808 | |||
| 809 | # | ||
| 810 | # I2C Hardware Bus support | ||
| 811 | # | ||
| 812 | # CONFIG_I2C_ALI1535 is not set | ||
| 813 | # CONFIG_I2C_ALI1563 is not set | ||
| 814 | # CONFIG_I2C_ALI15X3 is not set | ||
| 815 | # CONFIG_I2C_AMD756 is not set | ||
| 816 | # CONFIG_I2C_AMD8111 is not set | ||
| 817 | # CONFIG_I2C_I801 is not set | ||
| 818 | # CONFIG_I2C_I810 is not set | ||
| 819 | # CONFIG_I2C_PIIX4 is not set | ||
| 820 | # CONFIG_I2C_NFORCE2 is not set | ||
| 821 | # CONFIG_I2C_PARPORT_LIGHT is not set | ||
| 822 | # CONFIG_I2C_PROSAVAGE is not set | ||
| 823 | # CONFIG_I2C_SAVAGE4 is not set | ||
| 824 | # CONFIG_SCx200_ACB is not set | ||
| 825 | # CONFIG_I2C_SIS5595 is not set | ||
| 826 | # CONFIG_I2C_SIS630 is not set | ||
| 827 | # CONFIG_I2C_SIS96X is not set | ||
| 828 | # CONFIG_I2C_STUB is not set | ||
| 829 | # CONFIG_I2C_VIA is not set | ||
| 830 | # CONFIG_I2C_VIAPRO is not set | ||
| 831 | # CONFIG_I2C_VOODOO3 is not set | ||
| 832 | # CONFIG_I2C_PCA_ISA is not set | ||
| 833 | |||
| 834 | # | ||
| 835 | # Miscellaneous I2C Chip support | ||
| 836 | # | ||
| 837 | # CONFIG_SENSORS_DS1337 is not set | ||
| 838 | # CONFIG_SENSORS_DS1374 is not set | ||
| 839 | CONFIG_SENSORS_EEPROM=y | ||
| 840 | # CONFIG_SENSORS_PCF8574 is not set | ||
| 841 | # CONFIG_SENSORS_PCA9539 is not set | ||
| 842 | # CONFIG_SENSORS_PCF8591 is not set | ||
| 843 | # CONFIG_SENSORS_RTC8564 is not set | ||
| 844 | # CONFIG_SENSORS_MAX6875 is not set | ||
| 845 | # CONFIG_RTC_X1205_I2C is not set | ||
| 846 | # CONFIG_I2C_DEBUG_CORE is not set | ||
| 847 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
| 848 | # CONFIG_I2C_DEBUG_BUS is not set | ||
| 849 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
| 850 | |||
| 851 | # | ||
| 852 | # SPI support | ||
| 853 | # | ||
| 854 | # CONFIG_SPI is not set | ||
| 855 | # CONFIG_SPI_MASTER is not set | ||
| 856 | |||
| 857 | # | ||
| 858 | # Dallas's 1-wire bus | ||
| 859 | # | ||
| 860 | # CONFIG_W1 is not set | ||
| 861 | |||
| 862 | # | ||
| 863 | # Hardware Monitoring support | ||
| 864 | # | ||
| 865 | CONFIG_HWMON=y | ||
| 866 | # CONFIG_HWMON_VID is not set | ||
| 867 | # CONFIG_SENSORS_ADM1021 is not set | ||
| 868 | # CONFIG_SENSORS_ADM1025 is not set | ||
| 869 | # CONFIG_SENSORS_ADM1026 is not set | ||
| 870 | # CONFIG_SENSORS_ADM1031 is not set | ||
| 871 | # CONFIG_SENSORS_ADM9240 is not set | ||
| 872 | # CONFIG_SENSORS_ASB100 is not set | ||
| 873 | # CONFIG_SENSORS_ATXP1 is not set | ||
| 874 | # CONFIG_SENSORS_DS1621 is not set | ||
| 875 | # CONFIG_SENSORS_F71805F is not set | ||
| 876 | # CONFIG_SENSORS_FSCHER is not set | ||
| 877 | # CONFIG_SENSORS_FSCPOS is not set | ||
| 878 | # CONFIG_SENSORS_GL518SM is not set | ||
| 879 | # CONFIG_SENSORS_GL520SM is not set | ||
| 880 | # CONFIG_SENSORS_IT87 is not set | ||
| 881 | # CONFIG_SENSORS_LM63 is not set | ||
| 882 | # CONFIG_SENSORS_LM75 is not set | ||
| 883 | # CONFIG_SENSORS_LM77 is not set | ||
| 884 | # CONFIG_SENSORS_LM78 is not set | ||
| 885 | # CONFIG_SENSORS_LM80 is not set | ||
| 886 | # CONFIG_SENSORS_LM83 is not set | ||
| 887 | # CONFIG_SENSORS_LM85 is not set | ||
| 888 | # CONFIG_SENSORS_LM87 is not set | ||
| 889 | # CONFIG_SENSORS_LM90 is not set | ||
| 890 | # CONFIG_SENSORS_LM92 is not set | ||
| 891 | # CONFIG_SENSORS_MAX1619 is not set | ||
| 892 | # CONFIG_SENSORS_PC87360 is not set | ||
| 893 | # CONFIG_SENSORS_SIS5595 is not set | ||
| 894 | # CONFIG_SENSORS_SMSC47M1 is not set | ||
| 895 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
| 896 | # CONFIG_SENSORS_VIA686A is not set | ||
| 897 | # CONFIG_SENSORS_VT8231 is not set | ||
| 898 | # CONFIG_SENSORS_W83781D is not set | ||
| 899 | # CONFIG_SENSORS_W83792D is not set | ||
| 900 | # CONFIG_SENSORS_W83L785TS is not set | ||
| 901 | # CONFIG_SENSORS_W83627HF is not set | ||
| 902 | # CONFIG_SENSORS_W83627EHF is not set | ||
| 903 | # CONFIG_HWMON_DEBUG_CHIP is not set | ||
| 904 | |||
| 905 | # | ||
| 906 | # Misc devices | ||
| 907 | # | ||
| 908 | |||
| 909 | # | ||
| 910 | # Multimedia Capabilities Port drivers | ||
| 911 | # | ||
| 912 | |||
| 913 | # | ||
| 914 | # Multimedia devices | ||
| 915 | # | ||
| 916 | # CONFIG_VIDEO_DEV is not set | ||
| 917 | |||
| 918 | # | ||
| 919 | # Digital Video Broadcasting Devices | ||
| 920 | # | ||
| 921 | # CONFIG_DVB is not set | ||
| 922 | |||
| 923 | # | ||
| 924 | # Graphics support | ||
| 925 | # | ||
| 926 | # CONFIG_FB is not set | ||
| 927 | |||
| 928 | # | ||
| 929 | # Sound | ||
| 930 | # | ||
| 931 | # CONFIG_SOUND is not set | ||
| 932 | |||
| 933 | # | ||
| 934 | # USB support | ||
| 935 | # | ||
| 936 | CONFIG_USB_ARCH_HAS_HCD=y | ||
| 937 | CONFIG_USB_ARCH_HAS_OHCI=y | ||
| 938 | CONFIG_USB=y | ||
| 939 | # CONFIG_USB_DEBUG is not set | ||
| 940 | |||
| 941 | # | ||
| 942 | # Miscellaneous USB options | ||
| 943 | # | ||
| 944 | # CONFIG_USB_DEVICEFS is not set | ||
| 945 | # CONFIG_USB_BANDWIDTH is not set | ||
| 946 | # CONFIG_USB_DYNAMIC_MINORS is not set | ||
| 947 | # CONFIG_USB_OTG is not set | ||
| 948 | |||
| 949 | # | ||
| 950 | # USB Host Controller Drivers | ||
| 951 | # | ||
| 952 | CONFIG_USB_EHCI_HCD=y | ||
| 953 | # CONFIG_USB_EHCI_SPLIT_ISO is not set | ||
| 954 | # CONFIG_USB_EHCI_ROOT_HUB_TT is not set | ||
| 955 | # CONFIG_USB_ISP116X_HCD is not set | ||
| 956 | CONFIG_USB_OHCI_HCD=y | ||
| 957 | # CONFIG_USB_OHCI_BIG_ENDIAN is not set | ||
| 958 | CONFIG_USB_OHCI_LITTLE_ENDIAN=y | ||
| 959 | CONFIG_USB_UHCI_HCD=y | ||
| 960 | # CONFIG_USB_SL811_HCD is not set | ||
| 961 | |||
| 962 | # | ||
| 963 | # USB Device Class drivers | ||
| 964 | # | ||
| 965 | # CONFIG_USB_ACM is not set | ||
| 966 | # CONFIG_USB_PRINTER is not set | ||
| 967 | |||
| 968 | # | ||
| 969 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' | ||
| 970 | # | ||
| 971 | |||
| 972 | # | ||
| 973 | # may also be needed; see USB_STORAGE Help for more information | ||
| 974 | # | ||
| 975 | CONFIG_USB_STORAGE=y | ||
| 976 | # CONFIG_USB_STORAGE_DEBUG is not set | ||
| 977 | # CONFIG_USB_STORAGE_DATAFAB is not set | ||
| 978 | # CONFIG_USB_STORAGE_FREECOM is not set | ||
| 979 | # CONFIG_USB_STORAGE_ISD200 is not set | ||
| 980 | # CONFIG_USB_STORAGE_DPCM is not set | ||
| 981 | # CONFIG_USB_STORAGE_USBAT is not set | ||
| 982 | # CONFIG_USB_STORAGE_SDDR09 is not set | ||
| 983 | # CONFIG_USB_STORAGE_SDDR55 is not set | ||
| 984 | # CONFIG_USB_STORAGE_JUMPSHOT is not set | ||
| 985 | # CONFIG_USB_STORAGE_ALAUDA is not set | ||
| 986 | # CONFIG_USB_LIBUSUAL is not set | ||
| 987 | |||
| 988 | # | ||
| 989 | # USB Input Devices | ||
| 990 | # | ||
| 991 | # CONFIG_USB_HID is not set | ||
| 992 | |||
| 993 | # | ||
| 994 | # USB HID Boot Protocol drivers | ||
| 995 | # | ||
| 996 | # CONFIG_USB_KBD is not set | ||
| 997 | # CONFIG_USB_MOUSE is not set | ||
| 998 | # CONFIG_USB_AIPTEK is not set | ||
| 999 | # CONFIG_USB_WACOM is not set | ||
| 1000 | # CONFIG_USB_ACECAD is not set | ||
| 1001 | # CONFIG_USB_KBTAB is not set | ||
| 1002 | # CONFIG_USB_POWERMATE is not set | ||
| 1003 | # CONFIG_USB_MTOUCH is not set | ||
| 1004 | # CONFIG_USB_ITMTOUCH is not set | ||
| 1005 | # CONFIG_USB_EGALAX is not set | ||
| 1006 | # CONFIG_USB_YEALINK is not set | ||
| 1007 | # CONFIG_USB_XPAD is not set | ||
| 1008 | # CONFIG_USB_ATI_REMOTE is not set | ||
| 1009 | # CONFIG_USB_ATI_REMOTE2 is not set | ||
| 1010 | # CONFIG_USB_KEYSPAN_REMOTE is not set | ||
| 1011 | # CONFIG_USB_APPLETOUCH is not set | ||
| 1012 | |||
| 1013 | # | ||
| 1014 | # USB Imaging devices | ||
| 1015 | # | ||
| 1016 | # CONFIG_USB_MDC800 is not set | ||
| 1017 | # CONFIG_USB_MICROTEK is not set | ||
| 1018 | |||
| 1019 | # | ||
| 1020 | # USB Multimedia devices | ||
| 1021 | # | ||
| 1022 | # CONFIG_USB_DABUSB is not set | ||
| 1023 | |||
| 1024 | # | ||
| 1025 | # Video4Linux support is needed for USB Multimedia device support | ||
| 1026 | # | ||
| 1027 | |||
| 1028 | # | ||
| 1029 | # USB Network Adapters | ||
| 1030 | # | ||
| 1031 | # CONFIG_USB_CATC is not set | ||
| 1032 | # CONFIG_USB_KAWETH is not set | ||
| 1033 | # CONFIG_USB_PEGASUS is not set | ||
| 1034 | # CONFIG_USB_RTL8150 is not set | ||
| 1035 | # CONFIG_USB_USBNET is not set | ||
| 1036 | CONFIG_USB_MON=y | ||
| 1037 | |||
| 1038 | # | ||
| 1039 | # USB port drivers | ||
| 1040 | # | ||
| 1041 | |||
| 1042 | # | ||
| 1043 | # USB Serial Converter support | ||
| 1044 | # | ||
| 1045 | # CONFIG_USB_SERIAL is not set | ||
| 1046 | |||
| 1047 | # | ||
| 1048 | # USB Miscellaneous drivers | ||
| 1049 | # | ||
| 1050 | # CONFIG_USB_EMI62 is not set | ||
| 1051 | # CONFIG_USB_EMI26 is not set | ||
| 1052 | # CONFIG_USB_AUERSWALD is not set | ||
| 1053 | # CONFIG_USB_RIO500 is not set | ||
| 1054 | # CONFIG_USB_LEGOTOWER is not set | ||
| 1055 | # CONFIG_USB_LCD is not set | ||
| 1056 | # CONFIG_USB_LED is not set | ||
| 1057 | # CONFIG_USB_CYTHERM is not set | ||
| 1058 | # CONFIG_USB_PHIDGETKIT is not set | ||
| 1059 | # CONFIG_USB_PHIDGETSERVO is not set | ||
| 1060 | # CONFIG_USB_IDMOUSE is not set | ||
| 1061 | # CONFIG_USB_SISUSBVGA is not set | ||
| 1062 | # CONFIG_USB_LD is not set | ||
| 1063 | |||
| 1064 | # | ||
| 1065 | # USB DSL modem support | ||
| 1066 | # | ||
| 1067 | |||
| 1068 | # | ||
| 1069 | # USB Gadget Support | ||
| 1070 | # | ||
| 1071 | # CONFIG_USB_GADGET is not set | ||
| 1072 | |||
| 1073 | # | ||
| 1074 | # MMC/SD Card support | ||
| 1075 | # | ||
| 1076 | # CONFIG_MMC is not set | ||
| 1077 | |||
| 1078 | # | ||
| 1079 | # File systems | ||
| 1080 | # | ||
| 1081 | CONFIG_EXT2_FS=y | ||
| 1082 | CONFIG_EXT2_FS_XATTR=y | ||
| 1083 | CONFIG_EXT2_FS_POSIX_ACL=y | ||
| 1084 | # CONFIG_EXT2_FS_SECURITY is not set | ||
| 1085 | # CONFIG_EXT2_FS_XIP is not set | ||
| 1086 | CONFIG_EXT3_FS=y | ||
| 1087 | CONFIG_EXT3_FS_XATTR=y | ||
| 1088 | CONFIG_EXT3_FS_POSIX_ACL=y | ||
| 1089 | # CONFIG_EXT3_FS_SECURITY is not set | ||
| 1090 | CONFIG_JBD=y | ||
| 1091 | # CONFIG_JBD_DEBUG is not set | ||
| 1092 | CONFIG_FS_MBCACHE=y | ||
| 1093 | # CONFIG_REISERFS_FS is not set | ||
| 1094 | # CONFIG_JFS_FS is not set | ||
| 1095 | CONFIG_FS_POSIX_ACL=y | ||
| 1096 | # CONFIG_XFS_FS is not set | ||
| 1097 | # CONFIG_OCFS2_FS is not set | ||
| 1098 | # CONFIG_MINIX_FS is not set | ||
| 1099 | # CONFIG_ROMFS_FS is not set | ||
| 1100 | CONFIG_INOTIFY=y | ||
| 1101 | # CONFIG_QUOTA is not set | ||
| 1102 | CONFIG_DNOTIFY=y | ||
| 1103 | # CONFIG_AUTOFS_FS is not set | ||
| 1104 | # CONFIG_AUTOFS4_FS is not set | ||
| 1105 | # CONFIG_FUSE_FS is not set | ||
| 1106 | |||
| 1107 | # | ||
| 1108 | # CD-ROM/DVD Filesystems | ||
| 1109 | # | ||
| 1110 | # CONFIG_ISO9660_FS is not set | ||
| 1111 | # CONFIG_UDF_FS is not set | ||
| 1112 | |||
| 1113 | # | ||
| 1114 | # DOS/FAT/NT Filesystems | ||
| 1115 | # | ||
| 1116 | CONFIG_FAT_FS=y | ||
| 1117 | CONFIG_MSDOS_FS=y | ||
| 1118 | # CONFIG_VFAT_FS is not set | ||
| 1119 | CONFIG_FAT_DEFAULT_CODEPAGE=437 | ||
| 1120 | # CONFIG_NTFS_FS is not set | ||
| 1121 | |||
| 1122 | # | ||
| 1123 | # Pseudo filesystems | ||
| 1124 | # | ||
| 1125 | CONFIG_PROC_FS=y | ||
| 1126 | CONFIG_SYSFS=y | ||
| 1127 | CONFIG_TMPFS=y | ||
| 1128 | # CONFIG_HUGETLB_PAGE is not set | ||
| 1129 | CONFIG_RAMFS=y | ||
| 1130 | # CONFIG_RELAYFS_FS is not set | ||
| 1131 | # CONFIG_CONFIGFS_FS is not set | ||
| 1132 | |||
| 1133 | # | ||
| 1134 | # Miscellaneous filesystems | ||
| 1135 | # | ||
| 1136 | # CONFIG_ADFS_FS is not set | ||
| 1137 | # CONFIG_AFFS_FS is not set | ||
| 1138 | # CONFIG_HFS_FS is not set | ||
| 1139 | # CONFIG_HFSPLUS_FS is not set | ||
| 1140 | # CONFIG_BEFS_FS is not set | ||
| 1141 | # CONFIG_BFS_FS is not set | ||
| 1142 | # CONFIG_EFS_FS is not set | ||
| 1143 | # CONFIG_JFFS_FS is not set | ||
| 1144 | CONFIG_JFFS2_FS=y | ||
| 1145 | CONFIG_JFFS2_FS_DEBUG=0 | ||
| 1146 | CONFIG_JFFS2_FS_WRITEBUFFER=y | ||
| 1147 | # CONFIG_JFFS2_SUMMARY is not set | ||
| 1148 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set | ||
| 1149 | CONFIG_JFFS2_ZLIB=y | ||
| 1150 | CONFIG_JFFS2_RTIME=y | ||
| 1151 | # CONFIG_JFFS2_RUBIN is not set | ||
| 1152 | # CONFIG_CRAMFS is not set | ||
| 1153 | # CONFIG_VXFS_FS is not set | ||
| 1154 | # CONFIG_HPFS_FS is not set | ||
| 1155 | # CONFIG_QNX4FS_FS is not set | ||
| 1156 | # CONFIG_SYSV_FS is not set | ||
| 1157 | # CONFIG_UFS_FS is not set | ||
| 1158 | |||
| 1159 | # | ||
| 1160 | # Network File Systems | ||
| 1161 | # | ||
| 1162 | CONFIG_NFS_FS=y | ||
| 1163 | CONFIG_NFS_V3=y | ||
| 1164 | # CONFIG_NFS_V3_ACL is not set | ||
| 1165 | # CONFIG_NFS_V4 is not set | ||
| 1166 | # CONFIG_NFS_DIRECTIO is not set | ||
| 1167 | # CONFIG_NFSD is not set | ||
| 1168 | CONFIG_ROOT_NFS=y | ||
| 1169 | CONFIG_LOCKD=y | ||
| 1170 | CONFIG_LOCKD_V4=y | ||
| 1171 | CONFIG_NFS_COMMON=y | ||
| 1172 | CONFIG_SUNRPC=y | ||
| 1173 | # CONFIG_RPCSEC_GSS_KRB5 is not set | ||
| 1174 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | ||
| 1175 | # CONFIG_SMB_FS is not set | ||
| 1176 | # CONFIG_CIFS is not set | ||
| 1177 | # CONFIG_NCP_FS is not set | ||
| 1178 | # CONFIG_CODA_FS is not set | ||
| 1179 | # CONFIG_AFS_FS is not set | ||
| 1180 | # CONFIG_9P_FS is not set | ||
| 1181 | |||
| 1182 | # | ||
| 1183 | # Partition Types | ||
| 1184 | # | ||
| 1185 | CONFIG_PARTITION_ADVANCED=y | ||
| 1186 | # CONFIG_ACORN_PARTITION is not set | ||
| 1187 | # CONFIG_OSF_PARTITION is not set | ||
| 1188 | # CONFIG_AMIGA_PARTITION is not set | ||
| 1189 | # CONFIG_ATARI_PARTITION is not set | ||
| 1190 | # CONFIG_MAC_PARTITION is not set | ||
| 1191 | CONFIG_MSDOS_PARTITION=y | ||
| 1192 | # CONFIG_BSD_DISKLABEL is not set | ||
| 1193 | # CONFIG_MINIX_SUBPARTITION is not set | ||
| 1194 | # CONFIG_SOLARIS_X86_PARTITION is not set | ||
| 1195 | # CONFIG_UNIXWARE_DISKLABEL is not set | ||
| 1196 | # CONFIG_LDM_PARTITION is not set | ||
| 1197 | # CONFIG_SGI_PARTITION is not set | ||
| 1198 | # CONFIG_ULTRIX_PARTITION is not set | ||
| 1199 | # CONFIG_SUN_PARTITION is not set | ||
| 1200 | # CONFIG_KARMA_PARTITION is not set | ||
| 1201 | # CONFIG_EFI_PARTITION is not set | ||
| 1202 | |||
| 1203 | # | ||
| 1204 | # Native Language Support | ||
| 1205 | # | ||
| 1206 | CONFIG_NLS=y | ||
| 1207 | CONFIG_NLS_DEFAULT="iso8859-1" | ||
| 1208 | CONFIG_NLS_CODEPAGE_437=y | ||
| 1209 | # CONFIG_NLS_CODEPAGE_737 is not set | ||
| 1210 | # CONFIG_NLS_CODEPAGE_775 is not set | ||
| 1211 | # CONFIG_NLS_CODEPAGE_850 is not set | ||
| 1212 | # CONFIG_NLS_CODEPAGE_852 is not set | ||
| 1213 | # CONFIG_NLS_CODEPAGE_855 is not set | ||
| 1214 | # CONFIG_NLS_CODEPAGE_857 is not set | ||
| 1215 | # CONFIG_NLS_CODEPAGE_860 is not set | ||
| 1216 | # CONFIG_NLS_CODEPAGE_861 is not set | ||
| 1217 | # CONFIG_NLS_CODEPAGE_862 is not set | ||
| 1218 | # CONFIG_NLS_CODEPAGE_863 is not set | ||
| 1219 | # CONFIG_NLS_CODEPAGE_864 is not set | ||
| 1220 | # CONFIG_NLS_CODEPAGE_865 is not set | ||
| 1221 | # CONFIG_NLS_CODEPAGE_866 is not set | ||
| 1222 | # CONFIG_NLS_CODEPAGE_869 is not set | ||
| 1223 | # CONFIG_NLS_CODEPAGE_936 is not set | ||
| 1224 | # CONFIG_NLS_CODEPAGE_950 is not set | ||
| 1225 | # CONFIG_NLS_CODEPAGE_932 is not set | ||
| 1226 | # CONFIG_NLS_CODEPAGE_949 is not set | ||
| 1227 | # CONFIG_NLS_CODEPAGE_874 is not set | ||
| 1228 | # CONFIG_NLS_ISO8859_8 is not set | ||
| 1229 | # CONFIG_NLS_CODEPAGE_1250 is not set | ||
| 1230 | # CONFIG_NLS_CODEPAGE_1251 is not set | ||
| 1231 | # CONFIG_NLS_ASCII is not set | ||
| 1232 | # CONFIG_NLS_ISO8859_1 is not set | ||
| 1233 | # CONFIG_NLS_ISO8859_2 is not set | ||
| 1234 | # CONFIG_NLS_ISO8859_3 is not set | ||
| 1235 | # CONFIG_NLS_ISO8859_4 is not set | ||
| 1236 | # CONFIG_NLS_ISO8859_5 is not set | ||
| 1237 | # CONFIG_NLS_ISO8859_6 is not set | ||
| 1238 | # CONFIG_NLS_ISO8859_7 is not set | ||
| 1239 | # CONFIG_NLS_ISO8859_9 is not set | ||
| 1240 | # CONFIG_NLS_ISO8859_13 is not set | ||
| 1241 | # CONFIG_NLS_ISO8859_14 is not set | ||
| 1242 | # CONFIG_NLS_ISO8859_15 is not set | ||
| 1243 | # CONFIG_NLS_KOI8_R is not set | ||
| 1244 | # CONFIG_NLS_KOI8_U is not set | ||
| 1245 | # CONFIG_NLS_UTF8 is not set | ||
| 1246 | |||
| 1247 | # | ||
| 1248 | # Profiling support | ||
| 1249 | # | ||
| 1250 | # CONFIG_PROFILING is not set | ||
| 1251 | |||
| 1252 | # | ||
| 1253 | # Kernel hacking | ||
| 1254 | # | ||
| 1255 | # CONFIG_PRINTK_TIME is not set | ||
| 1256 | CONFIG_MAGIC_SYSRQ=y | ||
| 1257 | CONFIG_DEBUG_KERNEL=y | ||
| 1258 | CONFIG_LOG_BUF_SHIFT=14 | ||
| 1259 | CONFIG_DETECT_SOFTLOCKUP=y | ||
| 1260 | # CONFIG_SCHEDSTATS is not set | ||
| 1261 | # CONFIG_DEBUG_SLAB is not set | ||
| 1262 | CONFIG_DEBUG_MUTEXES=y | ||
| 1263 | # CONFIG_DEBUG_SPINLOCK is not set | ||
| 1264 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set | ||
| 1265 | # CONFIG_DEBUG_KOBJECT is not set | ||
| 1266 | CONFIG_DEBUG_BUGVERBOSE=y | ||
| 1267 | # CONFIG_DEBUG_INFO is not set | ||
| 1268 | # CONFIG_DEBUG_FS is not set | ||
| 1269 | # CONFIG_DEBUG_VM is not set | ||
| 1270 | CONFIG_FRAME_POINTER=y | ||
| 1271 | CONFIG_FORCED_INLINING=y | ||
| 1272 | # CONFIG_RCU_TORTURE_TEST is not set | ||
| 1273 | CONFIG_DEBUG_USER=y | ||
| 1274 | # CONFIG_DEBUG_WAITQ is not set | ||
| 1275 | CONFIG_DEBUG_ERRORS=y | ||
| 1276 | CONFIG_DEBUG_LL=y | ||
| 1277 | # CONFIG_DEBUG_ICEDCC is not set | ||
| 1278 | |||
| 1279 | # | ||
| 1280 | # Security options | ||
| 1281 | # | ||
| 1282 | # CONFIG_KEYS is not set | ||
| 1283 | # CONFIG_SECURITY is not set | ||
| 1284 | |||
| 1285 | # | ||
| 1286 | # Cryptographic options | ||
| 1287 | # | ||
| 1288 | # CONFIG_CRYPTO is not set | ||
| 1289 | |||
| 1290 | # | ||
| 1291 | # Hardware crypto devices | ||
| 1292 | # | ||
| 1293 | |||
| 1294 | # | ||
| 1295 | # Library routines | ||
| 1296 | # | ||
| 1297 | # CONFIG_CRC_CCITT is not set | ||
| 1298 | # CONFIG_CRC16 is not set | ||
| 1299 | CONFIG_CRC32=y | ||
| 1300 | # CONFIG_LIBCRC32C is not set | ||
| 1301 | CONFIG_ZLIB_INFLATE=y | ||
| 1302 | CONFIG_ZLIB_DEFLATE=y | ||
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 391f3ab3ff32..7b726b627ea5 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile | |||
| @@ -18,7 +18,7 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ | |||
| 18 | 18 | ||
| 19 | # the code in uaccess.S is not preemption safe and | 19 | # the code in uaccess.S is not preemption safe and |
| 20 | # probably faster on ARMv3 only | 20 | # probably faster on ARMv3 only |
| 21 | ifeq ($CONFIG_PREEMPT,y) | 21 | ifeq ($(CONFIG_PREEMPT),y) |
| 22 | lib-y += copy_from_user.o copy_to_user.o | 22 | lib-y += copy_from_user.o copy_to_user.o |
| 23 | else | 23 | else |
| 24 | ifneq ($(CONFIG_CPU_32v3),y) | 24 | ifneq ($(CONFIG_CPU_32v3),y) |
diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S index 838e435e4922..cab355c0c1f7 100644 --- a/arch/arm/lib/copy_template.S +++ b/arch/arm/lib/copy_template.S | |||
| @@ -236,7 +236,7 @@ | |||
| 236 | 236 | ||
| 237 | 237 | ||
| 238 | /* | 238 | /* |
| 239 | * Abort preanble and completion macros. | 239 | * Abort preamble and completion macros. |
| 240 | * If a fixup handler is required then those macros must surround it. | 240 | * If a fixup handler is required then those macros must surround it. |
| 241 | * It is assumed that the fixup code will handle the private part of | 241 | * It is assumed that the fixup code will handle the private part of |
| 242 | * the exit macro. | 242 | * the exit macro. |
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 865427bfad7e..2d892e4daa07 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c | |||
| @@ -30,7 +30,9 @@ | |||
| 30 | #include <linux/time.h> | 30 | #include <linux/time.h> |
| 31 | #include <linux/timex.h> | 31 | #include <linux/timex.h> |
| 32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
| 33 | #include <linux/termios.h> | ||
| 33 | #include <linux/amba/bus.h> | 34 | #include <linux/amba/bus.h> |
| 35 | #include <linux/amba/serial.h> | ||
| 34 | 36 | ||
| 35 | #include <asm/types.h> | 37 | #include <asm/types.h> |
| 36 | #include <asm/setup.h> | 38 | #include <asm/setup.h> |
| @@ -360,6 +362,68 @@ void __init ep93xx_init_irq(void) | |||
| 360 | /************************************************************************* | 362 | /************************************************************************* |
| 361 | * EP93xx peripheral handling | 363 | * EP93xx peripheral handling |
| 362 | *************************************************************************/ | 364 | *************************************************************************/ |
| 365 | #define EP93XX_UART_MCR_OFFSET (0x0100) | ||
| 366 | |||
| 367 | static void ep93xx_uart_set_mctrl(struct amba_device *dev, | ||
| 368 | void __iomem *base, unsigned int mctrl) | ||
| 369 | { | ||
| 370 | unsigned int mcr; | ||
| 371 | |||
| 372 | mcr = 0; | ||
| 373 | if (!(mctrl & TIOCM_RTS)) | ||
| 374 | mcr |= 2; | ||
| 375 | if (!(mctrl & TIOCM_DTR)) | ||
| 376 | mcr |= 1; | ||
| 377 | |||
| 378 | __raw_writel(mcr, base + EP93XX_UART_MCR_OFFSET); | ||
| 379 | } | ||
| 380 | |||
| 381 | static struct amba_pl010_data ep93xx_uart_data = { | ||
| 382 | .set_mctrl = ep93xx_uart_set_mctrl, | ||
| 383 | }; | ||
| 384 | |||
| 385 | static struct amba_device uart1_device = { | ||
| 386 | .dev = { | ||
| 387 | .bus_id = "apb:uart1", | ||
| 388 | .platform_data = &ep93xx_uart_data, | ||
| 389 | }, | ||
| 390 | .res = { | ||
| 391 | .start = EP93XX_UART1_PHYS_BASE, | ||
| 392 | .end = EP93XX_UART1_PHYS_BASE + 0x0fff, | ||
| 393 | .flags = IORESOURCE_MEM, | ||
| 394 | }, | ||
| 395 | .irq = { IRQ_EP93XX_UART1, NO_IRQ }, | ||
| 396 | .periphid = 0x00041010, | ||
| 397 | }; | ||
| 398 | |||
| 399 | static struct amba_device uart2_device = { | ||
| 400 | .dev = { | ||
| 401 | .bus_id = "apb:uart2", | ||
| 402 | .platform_data = &ep93xx_uart_data, | ||
| 403 | }, | ||
| 404 | .res = { | ||
| 405 | .start = EP93XX_UART2_PHYS_BASE, | ||
| 406 | .end = EP93XX_UART2_PHYS_BASE + 0x0fff, | ||
| 407 | .flags = IORESOURCE_MEM, | ||
| 408 | }, | ||
| 409 | .irq = { IRQ_EP93XX_UART2, NO_IRQ }, | ||
| 410 | .periphid = 0x00041010, | ||
| 411 | }; | ||
| 412 | |||
| 413 | static struct amba_device uart3_device = { | ||
| 414 | .dev = { | ||
| 415 | .bus_id = "apb:uart3", | ||
| 416 | .platform_data = &ep93xx_uart_data, | ||
| 417 | }, | ||
| 418 | .res = { | ||
| 419 | .start = EP93XX_UART3_PHYS_BASE, | ||
| 420 | .end = EP93XX_UART3_PHYS_BASE + 0x0fff, | ||
| 421 | .flags = IORESOURCE_MEM, | ||
| 422 | }, | ||
| 423 | .irq = { IRQ_EP93XX_UART3, NO_IRQ }, | ||
| 424 | .periphid = 0x00041010, | ||
| 425 | }; | ||
| 426 | |||
| 363 | void __init ep93xx_init_devices(void) | 427 | void __init ep93xx_init_devices(void) |
| 364 | { | 428 | { |
| 365 | unsigned int v; | 429 | unsigned int v; |
| @@ -371,4 +435,8 @@ void __init ep93xx_init_devices(void) | |||
| 371 | v &= ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE; | 435 | v &= ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE; |
| 372 | __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); | 436 | __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); |
| 373 | __raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG); | 437 | __raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG); |
| 438 | |||
| 439 | amba_device_register(&uart1_device, &iomem_resource); | ||
| 440 | amba_device_register(&uart2_device, &iomem_resource); | ||
| 441 | amba_device_register(&uart3_device, &iomem_resource); | ||
| 374 | } | 442 | } |
diff --git a/arch/arm/mach-footbridge/time.c b/arch/arm/mach-footbridge/time.c index 2c64a0b0502e..5d02e95dede3 100644 --- a/arch/arm/mach-footbridge/time.c +++ b/arch/arm/mach-footbridge/time.c | |||
| @@ -34,27 +34,12 @@ static int rtc_base; | |||
| 34 | static unsigned long __init get_isa_cmos_time(void) | 34 | static unsigned long __init get_isa_cmos_time(void) |
| 35 | { | 35 | { |
| 36 | unsigned int year, mon, day, hour, min, sec; | 36 | unsigned int year, mon, day, hour, min, sec; |
| 37 | int i; | ||
| 38 | 37 | ||
| 39 | // check to see if the RTC makes sense..... | 38 | // check to see if the RTC makes sense..... |
| 40 | if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0) | 39 | if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0) |
| 41 | return mktime(1970, 1, 1, 0, 0, 0); | 40 | return mktime(1970, 1, 1, 0, 0, 0); |
| 42 | 41 | ||
| 43 | /* The Linux interpretation of the CMOS clock register contents: | 42 | do { |
| 44 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
| 45 | * RTC registers show the second which has precisely just started. | ||
| 46 | * Let's hope other operating systems interpret the RTC the same way. | ||
| 47 | */ | ||
| 48 | /* read RTC exactly on falling edge of update flag */ | ||
| 49 | for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ | ||
| 50 | if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) | ||
| 51 | break; | ||
| 52 | |||
| 53 | for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ | ||
| 54 | if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) | ||
| 55 | break; | ||
| 56 | |||
| 57 | do { /* Isn't this overkill ? UIP above should guarantee consistency */ | ||
| 58 | sec = CMOS_READ(RTC_SECONDS); | 43 | sec = CMOS_READ(RTC_SECONDS); |
| 59 | min = CMOS_READ(RTC_MINUTES); | 44 | min = CMOS_READ(RTC_MINUTES); |
| 60 | hour = CMOS_READ(RTC_HOURS); | 45 | hour = CMOS_READ(RTC_HOURS); |
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 20071a2767cc..576a5e979c00 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c | |||
| @@ -15,7 +15,9 @@ | |||
| 15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
| 16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
| 17 | #include <linux/smp.h> | 17 | #include <linux/smp.h> |
| 18 | #include <linux/termios.h> | ||
| 18 | #include <linux/amba/bus.h> | 19 | #include <linux/amba/bus.h> |
| 20 | #include <linux/amba/serial.h> | ||
| 19 | 21 | ||
| 20 | #include <asm/hardware.h> | 22 | #include <asm/hardware.h> |
| 21 | #include <asm/irq.h> | 23 | #include <asm/irq.h> |
| @@ -28,6 +30,8 @@ | |||
| 28 | 30 | ||
| 29 | #include "common.h" | 31 | #include "common.h" |
| 30 | 32 | ||
| 33 | static struct amba_pl010_data integrator_uart_data; | ||
| 34 | |||
| 31 | static struct amba_device rtc_device = { | 35 | static struct amba_device rtc_device = { |
| 32 | .dev = { | 36 | .dev = { |
| 33 | .bus_id = "mb:15", | 37 | .bus_id = "mb:15", |
| @@ -44,6 +48,7 @@ static struct amba_device rtc_device = { | |||
| 44 | static struct amba_device uart0_device = { | 48 | static struct amba_device uart0_device = { |
| 45 | .dev = { | 49 | .dev = { |
| 46 | .bus_id = "mb:16", | 50 | .bus_id = "mb:16", |
| 51 | .platform_data = &integrator_uart_data, | ||
| 47 | }, | 52 | }, |
| 48 | .res = { | 53 | .res = { |
| 49 | .start = INTEGRATOR_UART0_BASE, | 54 | .start = INTEGRATOR_UART0_BASE, |
| @@ -57,6 +62,7 @@ static struct amba_device uart0_device = { | |||
| 57 | static struct amba_device uart1_device = { | 62 | static struct amba_device uart1_device = { |
| 58 | .dev = { | 63 | .dev = { |
| 59 | .bus_id = "mb:17", | 64 | .bus_id = "mb:17", |
| 65 | .platform_data = &integrator_uart_data, | ||
| 60 | }, | 66 | }, |
| 61 | .res = { | 67 | .res = { |
| 62 | .start = INTEGRATOR_UART1_BASE, | 68 | .start = INTEGRATOR_UART1_BASE, |
| @@ -115,6 +121,46 @@ static int __init integrator_init(void) | |||
| 115 | 121 | ||
| 116 | arch_initcall(integrator_init); | 122 | arch_initcall(integrator_init); |
| 117 | 123 | ||
| 124 | /* | ||
| 125 | * On the Integrator platform, the port RTS and DTR are provided by | ||
| 126 | * bits in the following SC_CTRLS register bits: | ||
| 127 | * RTS DTR | ||
| 128 | * UART0 7 6 | ||
| 129 | * UART1 5 4 | ||
| 130 | */ | ||
| 131 | #define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) | ||
| 132 | #define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) | ||
| 133 | |||
| 134 | static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl) | ||
| 135 | { | ||
| 136 | unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask; | ||
| 137 | |||
| 138 | if (dev == &uart0_device) { | ||
| 139 | rts_mask = 1 << 4; | ||
| 140 | dtr_mask = 1 << 5; | ||
| 141 | } else { | ||
| 142 | rts_mask = 1 << 6; | ||
| 143 | dtr_mask = 1 << 7; | ||
| 144 | } | ||
| 145 | |||
| 146 | if (mctrl & TIOCM_RTS) | ||
| 147 | ctrlc |= rts_mask; | ||
| 148 | else | ||
| 149 | ctrls |= rts_mask; | ||
| 150 | |||
| 151 | if (mctrl & TIOCM_DTR) | ||
| 152 | ctrlc |= dtr_mask; | ||
| 153 | else | ||
| 154 | ctrls |= dtr_mask; | ||
| 155 | |||
| 156 | __raw_writel(ctrls, SC_CTRLS); | ||
| 157 | __raw_writel(ctrlc, SC_CTRLC); | ||
| 158 | } | ||
| 159 | |||
| 160 | static struct amba_pl010_data integrator_uart_data = { | ||
| 161 | .set_mctrl = integrator_uart_set_mctrl, | ||
| 162 | }; | ||
| 163 | |||
| 118 | #define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_CTRL_OFFSET | 164 | #define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_CTRL_OFFSET |
| 119 | 165 | ||
| 120 | static DEFINE_SPINLOCK(cm_lock); | 166 | static DEFINE_SPINLOCK(cm_lock); |
diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c index 3c22c16b38bf..bc07f52a6fd7 100644 --- a/arch/arm/mach-integrator/time.c +++ b/arch/arm/mach-integrator/time.c | |||
| @@ -40,13 +40,13 @@ static int integrator_set_rtc(void) | |||
| 40 | return 1; | 40 | return 1; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static int rtc_read_alarm(struct rtc_wkalrm *alrm) | 43 | static int integrator_rtc_read_alarm(struct rtc_wkalrm *alrm) |
| 44 | { | 44 | { |
| 45 | rtc_time_to_tm(readl(rtc_base + RTC_MR), &alrm->time); | 45 | rtc_time_to_tm(readl(rtc_base + RTC_MR), &alrm->time); |
| 46 | return 0; | 46 | return 0; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | static inline int rtc_set_alarm(struct rtc_wkalrm *alrm) | 49 | static inline int integrator_rtc_set_alarm(struct rtc_wkalrm *alrm) |
| 50 | { | 50 | { |
| 51 | unsigned long time; | 51 | unsigned long time; |
| 52 | int ret; | 52 | int ret; |
| @@ -62,7 +62,7 @@ static inline int rtc_set_alarm(struct rtc_wkalrm *alrm) | |||
| 62 | return ret; | 62 | return ret; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | static int rtc_read_time(struct rtc_time *tm) | 65 | static int integrator_rtc_read_time(struct rtc_time *tm) |
| 66 | { | 66 | { |
| 67 | rtc_time_to_tm(readl(rtc_base + RTC_DR), tm); | 67 | rtc_time_to_tm(readl(rtc_base + RTC_DR), tm); |
| 68 | return 0; | 68 | return 0; |
| @@ -76,7 +76,7 @@ static int rtc_read_time(struct rtc_time *tm) | |||
| 76 | * edge of the 1Hz clock, we must write the time one second | 76 | * edge of the 1Hz clock, we must write the time one second |
| 77 | * in advance. | 77 | * in advance. |
| 78 | */ | 78 | */ |
| 79 | static inline int rtc_set_time(struct rtc_time *tm) | 79 | static inline int integrator_rtc_set_time(struct rtc_time *tm) |
| 80 | { | 80 | { |
| 81 | unsigned long time; | 81 | unsigned long time; |
| 82 | int ret; | 82 | int ret; |
| @@ -90,10 +90,10 @@ static inline int rtc_set_time(struct rtc_time *tm) | |||
| 90 | 90 | ||
| 91 | static struct rtc_ops rtc_ops = { | 91 | static struct rtc_ops rtc_ops = { |
| 92 | .owner = THIS_MODULE, | 92 | .owner = THIS_MODULE, |
| 93 | .read_time = rtc_read_time, | 93 | .read_time = integrator_rtc_read_time, |
| 94 | .set_time = rtc_set_time, | 94 | .set_time = integrator_rtc_set_time, |
| 95 | .read_alarm = rtc_read_alarm, | 95 | .read_alarm = integrator_rtc_read_alarm, |
| 96 | .set_alarm = rtc_set_alarm, | 96 | .set_alarm = integrator_rtc_set_alarm, |
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | static irqreturn_t arm_rtc_interrupt(int irq, void *dev_id, | 99 | static irqreturn_t arm_rtc_interrupt(int irq, void *dev_id, |
diff --git a/arch/arm/mach-ixp23xx/Kconfig b/arch/arm/mach-ixp23xx/Kconfig new file mode 100644 index 000000000000..982670ec3866 --- /dev/null +++ b/arch/arm/mach-ixp23xx/Kconfig | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | if ARCH_IXP23XX | ||
| 2 | |||
| 3 | config ARCH_SUPPORTS_BIG_ENDIAN | ||
| 4 | bool | ||
| 5 | default y | ||
| 6 | |||
| 7 | menu "Intel IXP23xx Implementation Options" | ||
| 8 | |||
| 9 | comment "IXP23xx Platforms" | ||
| 10 | |||
| 11 | config MACH_ESPRESSO | ||
| 12 | bool "Support IP Fabrics Double Espresso platform" | ||
| 13 | help | ||
| 14 | |||
| 15 | config MACH_IXDP2351 | ||
| 16 | bool "Support Intel IXDP2351 platform" | ||
| 17 | help | ||
| 18 | |||
| 19 | config MACH_ROADRUNNER | ||
| 20 | bool "Support ADI RoadRunner platform" | ||
| 21 | help | ||
| 22 | |||
| 23 | endmenu | ||
| 24 | |||
| 25 | endif | ||
diff --git a/arch/arm/mach-ixp23xx/Makefile b/arch/arm/mach-ixp23xx/Makefile new file mode 100644 index 000000000000..288b371b6d03 --- /dev/null +++ b/arch/arm/mach-ixp23xx/Makefile | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | # | ||
| 2 | # Makefile for the linux kernel. | ||
| 3 | # | ||
| 4 | obj-y := core.o pci.o | ||
| 5 | obj-m := | ||
| 6 | obj-n := | ||
| 7 | obj- := | ||
| 8 | |||
| 9 | obj-$(CONFIG_MACH_ESPRESSO) += espresso.o | ||
| 10 | obj-$(CONFIG_MACH_IXDP2351) += ixdp2351.o | ||
| 11 | obj-$(CONFIG_MACH_ROADRUNNER) += roadrunner.o | ||
diff --git a/arch/arm/mach-ixp23xx/Makefile.boot b/arch/arm/mach-ixp23xx/Makefile.boot new file mode 100644 index 000000000000..d5561ad15bad --- /dev/null +++ b/arch/arm/mach-ixp23xx/Makefile.boot | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | zreladdr-y := 0x00008000 | ||
| 2 | params_phys-y := 0x00000100 | ||
diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c new file mode 100644 index 000000000000..092ee12ced42 --- /dev/null +++ b/arch/arm/mach-ixp23xx/core.c | |||
| @@ -0,0 +1,431 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-ixp23xx/core.c | ||
| 3 | * | ||
| 4 | * Core routines for IXP23xx chips | ||
| 5 | * | ||
| 6 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
| 7 | * | ||
| 8 | * Copyright 2005 (c) MontaVista Software, Inc. | ||
| 9 | * | ||
| 10 | * Based on 2.4 code Copyright 2004 (c) Intel Corporation | ||
| 11 | * | ||
| 12 | * This file is licensed under the terms of the GNU General Public | ||
| 13 | * License version 2. This program is licensed "as is" without any | ||
| 14 | * warranty of any kind, whether express or implied. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/config.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/spinlock.h> | ||
| 21 | #include <linux/sched.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/serial.h> | ||
| 24 | #include <linux/tty.h> | ||
| 25 | #include <linux/bitops.h> | ||
| 26 | #include <linux/serial.h> | ||
| 27 | #include <linux/serial_8250.h> | ||
| 28 | #include <linux/serial_core.h> | ||
| 29 | #include <linux/device.h> | ||
| 30 | #include <linux/mm.h> | ||
| 31 | #include <linux/time.h> | ||
| 32 | #include <linux/timex.h> | ||
| 33 | |||
| 34 | #include <asm/types.h> | ||
| 35 | #include <asm/setup.h> | ||
| 36 | #include <asm/memory.h> | ||
| 37 | #include <asm/hardware.h> | ||
| 38 | #include <asm/mach-types.h> | ||
| 39 | #include <asm/irq.h> | ||
| 40 | #include <asm/system.h> | ||
| 41 | #include <asm/tlbflush.h> | ||
| 42 | #include <asm/pgtable.h> | ||
| 43 | |||
| 44 | #include <asm/mach/map.h> | ||
| 45 | #include <asm/mach/time.h> | ||
| 46 | #include <asm/mach/irq.h> | ||
| 47 | #include <asm/mach/arch.h> | ||
| 48 | |||
| 49 | |||
| 50 | /************************************************************************* | ||
| 51 | * Chip specific mappings shared by all IXP23xx systems | ||
| 52 | *************************************************************************/ | ||
| 53 | static struct map_desc ixp23xx_io_desc[] __initdata = { | ||
| 54 | { /* XSI-CPP CSRs */ | ||
| 55 | .virtual = IXP23XX_XSI2CPP_CSR_VIRT, | ||
| 56 | .pfn = __phys_to_pfn(IXP23XX_XSI2CPP_CSR_PHYS), | ||
| 57 | .length = IXP23XX_XSI2CPP_CSR_SIZE, | ||
| 58 | .type = MT_DEVICE, | ||
| 59 | }, { /* Expansion Bus Config */ | ||
| 60 | .virtual = IXP23XX_EXP_CFG_VIRT, | ||
| 61 | .pfn = __phys_to_pfn(IXP23XX_EXP_CFG_PHYS), | ||
| 62 | .length = IXP23XX_EXP_CFG_SIZE, | ||
| 63 | .type = MT_DEVICE, | ||
| 64 | }, { /* UART, Interrupt ctrl, GPIO, timers, NPEs, MACS,.... */ | ||
| 65 | .virtual = IXP23XX_PERIPHERAL_VIRT, | ||
| 66 | .pfn = __phys_to_pfn(IXP23XX_PERIPHERAL_PHYS), | ||
| 67 | .length = IXP23XX_PERIPHERAL_SIZE, | ||
| 68 | .type = MT_DEVICE, | ||
| 69 | }, { /* CAP CSRs */ | ||
| 70 | .virtual = IXP23XX_CAP_CSR_VIRT, | ||
| 71 | .pfn = __phys_to_pfn(IXP23XX_CAP_CSR_PHYS), | ||
| 72 | .length = IXP23XX_CAP_CSR_SIZE, | ||
| 73 | .type = MT_DEVICE, | ||
| 74 | }, { /* MSF CSRs */ | ||
| 75 | .virtual = IXP23XX_MSF_CSR_VIRT, | ||
| 76 | .pfn = __phys_to_pfn(IXP23XX_MSF_CSR_PHYS), | ||
| 77 | .length = IXP23XX_MSF_CSR_SIZE, | ||
| 78 | .type = MT_DEVICE, | ||
| 79 | }, { /* PCI I/O Space */ | ||
| 80 | .virtual = IXP23XX_PCI_IO_VIRT, | ||
| 81 | .pfn = __phys_to_pfn(IXP23XX_PCI_IO_PHYS), | ||
| 82 | .length = IXP23XX_PCI_IO_SIZE, | ||
| 83 | .type = MT_DEVICE, | ||
| 84 | }, { /* PCI Config Space */ | ||
| 85 | .virtual = IXP23XX_PCI_CFG_VIRT, | ||
| 86 | .pfn = __phys_to_pfn(IXP23XX_PCI_CFG_PHYS), | ||
| 87 | .length = IXP23XX_PCI_CFG_SIZE, | ||
| 88 | .type = MT_DEVICE, | ||
| 89 | }, { /* PCI local CFG CSRs */ | ||
| 90 | .virtual = IXP23XX_PCI_CREG_VIRT, | ||
| 91 | .pfn = __phys_to_pfn(IXP23XX_PCI_CREG_PHYS), | ||
| 92 | .length = IXP23XX_PCI_CREG_SIZE, | ||
| 93 | .type = MT_DEVICE, | ||
| 94 | }, { /* PCI MEM Space */ | ||
| 95 | .virtual = IXP23XX_PCI_MEM_VIRT, | ||
| 96 | .pfn = __phys_to_pfn(IXP23XX_PCI_MEM_PHYS), | ||
| 97 | .length = IXP23XX_PCI_MEM_SIZE, | ||
| 98 | .type = MT_DEVICE, | ||
| 99 | } | ||
| 100 | }; | ||
| 101 | |||
| 102 | void __init ixp23xx_map_io(void) | ||
| 103 | { | ||
| 104 | iotable_init(ixp23xx_io_desc, ARRAY_SIZE(ixp23xx_io_desc)); | ||
| 105 | } | ||
| 106 | |||
| 107 | |||
| 108 | /*************************************************************************** | ||
| 109 | * IXP23xx Interrupt Handling | ||
| 110 | ***************************************************************************/ | ||
| 111 | enum ixp23xx_irq_type { | ||
| 112 | IXP23XX_IRQ_LEVEL, IXP23XX_IRQ_EDGE | ||
| 113 | }; | ||
| 114 | |||
| 115 | static void ixp23xx_config_irq(unsigned int, enum ixp23xx_irq_type); | ||
| 116 | |||
| 117 | static int ixp23xx_irq_set_type(unsigned int irq, unsigned int type) | ||
| 118 | { | ||
| 119 | int line = irq - IRQ_IXP23XX_GPIO6 + 6; | ||
| 120 | u32 int_style; | ||
| 121 | enum ixp23xx_irq_type irq_type; | ||
| 122 | volatile u32 *int_reg; | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Only GPIOs 6-15 are wired to interrupts on IXP23xx | ||
| 126 | */ | ||
| 127 | if (line < 6 || line > 15) | ||
| 128 | return -EINVAL; | ||
| 129 | |||
| 130 | switch (type) { | ||
| 131 | case IRQT_BOTHEDGE: | ||
| 132 | int_style = IXP23XX_GPIO_STYLE_TRANSITIONAL; | ||
| 133 | irq_type = IXP23XX_IRQ_EDGE; | ||
| 134 | break; | ||
| 135 | case IRQT_RISING: | ||
| 136 | int_style = IXP23XX_GPIO_STYLE_RISING_EDGE; | ||
| 137 | irq_type = IXP23XX_IRQ_EDGE; | ||
| 138 | break; | ||
| 139 | case IRQT_FALLING: | ||
| 140 | int_style = IXP23XX_GPIO_STYLE_FALLING_EDGE; | ||
| 141 | irq_type = IXP23XX_IRQ_EDGE; | ||
| 142 | break; | ||
| 143 | case IRQT_HIGH: | ||
| 144 | int_style = IXP23XX_GPIO_STYLE_ACTIVE_HIGH; | ||
| 145 | irq_type = IXP23XX_IRQ_LEVEL; | ||
| 146 | break; | ||
| 147 | case IRQT_LOW: | ||
| 148 | int_style = IXP23XX_GPIO_STYLE_ACTIVE_LOW; | ||
| 149 | irq_type = IXP23XX_IRQ_LEVEL; | ||
| 150 | break; | ||
| 151 | default: | ||
| 152 | return -EINVAL; | ||
| 153 | } | ||
| 154 | |||
| 155 | ixp23xx_config_irq(irq, irq_type); | ||
| 156 | |||
| 157 | if (line >= 8) { /* pins 8-15 */ | ||
| 158 | line -= 8; | ||
| 159 | int_reg = (volatile u32 *)IXP23XX_GPIO_GPIT2R; | ||
| 160 | } else { /* pins 0-7 */ | ||
| 161 | int_reg = (volatile u32 *)IXP23XX_GPIO_GPIT1R; | ||
| 162 | } | ||
| 163 | |||
| 164 | /* | ||
| 165 | * Clear pending interrupts | ||
| 166 | */ | ||
| 167 | *IXP23XX_GPIO_GPISR = (1 << line); | ||
| 168 | |||
| 169 | /* Clear the style for the appropriate pin */ | ||
| 170 | *int_reg &= ~(IXP23XX_GPIO_STYLE_MASK << | ||
| 171 | (line * IXP23XX_GPIO_STYLE_SIZE)); | ||
| 172 | |||
| 173 | /* Set the new style */ | ||
| 174 | *int_reg |= (int_style << (line * IXP23XX_GPIO_STYLE_SIZE)); | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | static void ixp23xx_irq_mask(unsigned int irq) | ||
| 180 | { | ||
| 181 | volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32); | ||
| 182 | |||
| 183 | *intr_reg &= ~(1 << (irq % 32)); | ||
| 184 | } | ||
| 185 | |||
| 186 | static void ixp23xx_irq_ack(unsigned int irq) | ||
| 187 | { | ||
| 188 | int line = irq - IRQ_IXP23XX_GPIO6 + 6; | ||
| 189 | |||
| 190 | if ((line < 6) || (line > 15)) | ||
| 191 | return; | ||
| 192 | |||
| 193 | *IXP23XX_GPIO_GPISR = (1 << line); | ||
| 194 | } | ||
| 195 | |||
| 196 | /* | ||
| 197 | * Level triggered interrupts on GPIO lines can only be cleared when the | ||
| 198 | * interrupt condition disappears. | ||
| 199 | */ | ||
| 200 | static void ixp23xx_irq_level_unmask(unsigned int irq) | ||
| 201 | { | ||
| 202 | volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32); | ||
| 203 | |||
| 204 | ixp23xx_irq_ack(irq); | ||
| 205 | |||
| 206 | *intr_reg |= (1 << (irq % 32)); | ||
| 207 | } | ||
| 208 | |||
| 209 | static void ixp23xx_irq_edge_unmask(unsigned int irq) | ||
| 210 | { | ||
| 211 | volatile unsigned long *intr_reg = IXP23XX_INTR_EN1 + (irq / 32); | ||
| 212 | |||
| 213 | *intr_reg |= (1 << (irq % 32)); | ||
| 214 | } | ||
| 215 | |||
| 216 | static struct irqchip ixp23xx_irq_level_chip = { | ||
| 217 | .ack = ixp23xx_irq_mask, | ||
| 218 | .mask = ixp23xx_irq_mask, | ||
| 219 | .unmask = ixp23xx_irq_level_unmask, | ||
| 220 | .set_type = ixp23xx_irq_set_type | ||
| 221 | }; | ||
| 222 | |||
| 223 | static struct irqchip ixp23xx_irq_edge_chip = { | ||
| 224 | .ack = ixp23xx_irq_ack, | ||
| 225 | .mask = ixp23xx_irq_mask, | ||
| 226 | .unmask = ixp23xx_irq_edge_unmask, | ||
| 227 | .set_type = ixp23xx_irq_set_type | ||
| 228 | }; | ||
| 229 | |||
| 230 | static void ixp23xx_pci_irq_mask(unsigned int irq) | ||
| 231 | { | ||
| 232 | *IXP23XX_PCI_XSCALE_INT_ENABLE &= ~(1 << (IRQ_IXP23XX_INTA + 27 - irq)); | ||
| 233 | } | ||
| 234 | |||
| 235 | static void ixp23xx_pci_irq_unmask(unsigned int irq) | ||
| 236 | { | ||
| 237 | *IXP23XX_PCI_XSCALE_INT_ENABLE |= (1 << (IRQ_IXP23XX_INTA + 27 - irq)); | ||
| 238 | } | ||
| 239 | |||
| 240 | /* | ||
| 241 | * TODO: Should this just be done at ASM level? | ||
| 242 | */ | ||
| 243 | static void pci_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) | ||
| 244 | { | ||
| 245 | u32 pci_interrupt; | ||
| 246 | unsigned int irqno; | ||
| 247 | struct irqdesc *int_desc; | ||
| 248 | |||
| 249 | pci_interrupt = *IXP23XX_PCI_XSCALE_INT_STATUS; | ||
| 250 | |||
| 251 | desc->chip->ack(irq); | ||
| 252 | |||
| 253 | /* See which PCI_INTA, or PCI_INTB interrupted */ | ||
| 254 | if (pci_interrupt & (1 << 26)) { | ||
| 255 | irqno = IRQ_IXP23XX_INTB; | ||
| 256 | } else if (pci_interrupt & (1 << 27)) { | ||
| 257 | irqno = IRQ_IXP23XX_INTA; | ||
| 258 | } else { | ||
| 259 | BUG(); | ||
| 260 | } | ||
| 261 | |||
| 262 | int_desc = irq_desc + irqno; | ||
| 263 | int_desc->handle(irqno, int_desc, regs); | ||
| 264 | |||
| 265 | desc->chip->unmask(irq); | ||
| 266 | } | ||
| 267 | |||
| 268 | static struct irqchip ixp23xx_pci_irq_chip = { | ||
| 269 | .ack = ixp23xx_pci_irq_mask, | ||
| 270 | .mask = ixp23xx_pci_irq_mask, | ||
| 271 | .unmask = ixp23xx_pci_irq_unmask | ||
| 272 | }; | ||
| 273 | |||
| 274 | static void ixp23xx_config_irq(unsigned int irq, enum ixp23xx_irq_type type) | ||
| 275 | { | ||
| 276 | switch (type) { | ||
| 277 | case IXP23XX_IRQ_LEVEL: | ||
| 278 | set_irq_chip(irq, &ixp23xx_irq_level_chip); | ||
| 279 | set_irq_handler(irq, do_level_IRQ); | ||
| 280 | break; | ||
| 281 | case IXP23XX_IRQ_EDGE: | ||
| 282 | set_irq_chip(irq, &ixp23xx_irq_edge_chip); | ||
| 283 | set_irq_handler(irq, do_edge_IRQ); | ||
| 284 | break; | ||
| 285 | } | ||
| 286 | set_irq_flags(irq, IRQF_VALID); | ||
| 287 | } | ||
| 288 | |||
| 289 | void __init ixp23xx_init_irq(void) | ||
| 290 | { | ||
| 291 | int irq; | ||
| 292 | |||
| 293 | /* Route everything to IRQ */ | ||
| 294 | *IXP23XX_INTR_SEL1 = 0x0; | ||
| 295 | *IXP23XX_INTR_SEL2 = 0x0; | ||
| 296 | *IXP23XX_INTR_SEL3 = 0x0; | ||
| 297 | *IXP23XX_INTR_SEL4 = 0x0; | ||
| 298 | |||
| 299 | /* Mask all sources */ | ||
| 300 | *IXP23XX_INTR_EN1 = 0x0; | ||
| 301 | *IXP23XX_INTR_EN2 = 0x0; | ||
| 302 | *IXP23XX_INTR_EN3 = 0x0; | ||
| 303 | *IXP23XX_INTR_EN4 = 0x0; | ||
| 304 | |||
| 305 | /* | ||
| 306 | * Configure all IRQs for level-sensitive operation | ||
| 307 | */ | ||
| 308 | for (irq = 0; irq <= NUM_IXP23XX_RAW_IRQS; irq++) { | ||
| 309 | ixp23xx_config_irq(irq, IXP23XX_IRQ_LEVEL); | ||
| 310 | } | ||
| 311 | |||
| 312 | for (irq = IRQ_IXP23XX_INTA; irq <= IRQ_IXP23XX_INTB; irq++) { | ||
| 313 | set_irq_chip(irq, &ixp23xx_pci_irq_chip); | ||
| 314 | set_irq_handler(irq, do_level_IRQ); | ||
| 315 | set_irq_flags(irq, IRQF_VALID); | ||
| 316 | } | ||
| 317 | |||
| 318 | set_irq_chained_handler(IRQ_IXP23XX_PCI_INT_RPH, pci_handler); | ||
| 319 | } | ||
| 320 | |||
| 321 | |||
| 322 | /************************************************************************* | ||
| 323 | * Timer-tick functions for IXP23xx | ||
| 324 | *************************************************************************/ | ||
| 325 | #define CLOCK_TICKS_PER_USEC CLOCK_TICK_RATE / (USEC_PER_SEC) | ||
| 326 | |||
| 327 | static unsigned long next_jiffy_time; | ||
| 328 | |||
| 329 | static unsigned long | ||
| 330 | ixp23xx_gettimeoffset(void) | ||
| 331 | { | ||
| 332 | unsigned long elapsed; | ||
| 333 | |||
| 334 | elapsed = *IXP23XX_TIMER_CONT - (next_jiffy_time - LATCH); | ||
| 335 | |||
| 336 | return elapsed / CLOCK_TICKS_PER_USEC; | ||
| 337 | } | ||
| 338 | |||
| 339 | static irqreturn_t | ||
| 340 | ixp23xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
| 341 | { | ||
| 342 | /* Clear Pending Interrupt by writing '1' to it */ | ||
| 343 | *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND; | ||
| 344 | while ((*IXP23XX_TIMER_CONT - next_jiffy_time) > LATCH) { | ||
| 345 | timer_tick(regs); | ||
| 346 | next_jiffy_time += LATCH; | ||
| 347 | } | ||
| 348 | |||
| 349 | return IRQ_HANDLED; | ||
| 350 | } | ||
| 351 | |||
| 352 | static struct irqaction ixp23xx_timer_irq = { | ||
| 353 | .name = "IXP23xx Timer Tick", | ||
| 354 | .handler = ixp23xx_timer_interrupt, | ||
| 355 | .flags = SA_INTERRUPT | SA_TIMER, | ||
| 356 | }; | ||
| 357 | |||
| 358 | void __init ixp23xx_init_timer(void) | ||
| 359 | { | ||
| 360 | /* Clear Pending Interrupt by writing '1' to it */ | ||
| 361 | *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND; | ||
| 362 | |||
| 363 | /* Setup the Timer counter value */ | ||
| 364 | *IXP23XX_TIMER1_RELOAD = | ||
| 365 | (LATCH & ~IXP23XX_TIMER_RELOAD_MASK) | IXP23XX_TIMER_ENABLE; | ||
| 366 | |||
| 367 | *IXP23XX_TIMER_CONT = 0; | ||
| 368 | next_jiffy_time = LATCH; | ||
| 369 | |||
| 370 | /* Connect the interrupt handler and enable the interrupt */ | ||
| 371 | setup_irq(IRQ_IXP23XX_TIMER1, &ixp23xx_timer_irq); | ||
| 372 | } | ||
| 373 | |||
| 374 | struct sys_timer ixp23xx_timer = { | ||
| 375 | .init = ixp23xx_init_timer, | ||
| 376 | .offset = ixp23xx_gettimeoffset, | ||
| 377 | }; | ||
| 378 | |||
| 379 | |||
| 380 | /************************************************************************* | ||
| 381 | * IXP23xx Platform Initializaion | ||
| 382 | *************************************************************************/ | ||
| 383 | static struct resource ixp23xx_uart_resources[] = { | ||
| 384 | { | ||
| 385 | .start = IXP23XX_UART1_PHYS, | ||
| 386 | .end = IXP23XX_UART1_PHYS + 0x0fff, | ||
| 387 | .flags = IORESOURCE_MEM | ||
| 388 | }, { | ||
| 389 | .start = IXP23XX_UART2_PHYS, | ||
| 390 | .end = IXP23XX_UART2_PHYS + 0x0fff, | ||
| 391 | .flags = IORESOURCE_MEM | ||
| 392 | } | ||
| 393 | }; | ||
| 394 | |||
| 395 | static struct plat_serial8250_port ixp23xx_uart_data[] = { | ||
| 396 | { | ||
| 397 | .mapbase = IXP23XX_UART1_PHYS, | ||
| 398 | .membase = (char *)(IXP23XX_UART1_VIRT + 3), | ||
| 399 | .irq = IRQ_IXP23XX_UART1, | ||
| 400 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, | ||
| 401 | .iotype = UPIO_MEM, | ||
| 402 | .regshift = 2, | ||
| 403 | .uartclk = IXP23XX_UART_XTAL, | ||
| 404 | }, { | ||
| 405 | .mapbase = IXP23XX_UART2_PHYS, | ||
| 406 | .membase = (char *)(IXP23XX_UART2_VIRT + 3), | ||
| 407 | .irq = IRQ_IXP23XX_UART2, | ||
| 408 | .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, | ||
| 409 | .iotype = UPIO_MEM, | ||
| 410 | .regshift = 2, | ||
| 411 | .uartclk = IXP23XX_UART_XTAL, | ||
| 412 | }, | ||
| 413 | { }, | ||
| 414 | }; | ||
| 415 | |||
| 416 | static struct platform_device ixp23xx_uart = { | ||
| 417 | .name = "serial8250", | ||
| 418 | .id = 0, | ||
| 419 | .dev.platform_data = ixp23xx_uart_data, | ||
| 420 | .num_resources = 2, | ||
| 421 | .resource = ixp23xx_uart_resources, | ||
| 422 | }; | ||
| 423 | |||
| 424 | static struct platform_device *ixp23xx_devices[] __initdata = { | ||
| 425 | &ixp23xx_uart, | ||
| 426 | }; | ||
| 427 | |||
| 428 | void __init ixp23xx_sys_init(void) | ||
| 429 | { | ||
| 430 | platform_add_devices(ixp23xx_devices, ARRAY_SIZE(ixp23xx_devices)); | ||
| 431 | } | ||
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c new file mode 100644 index 000000000000..2327c9790416 --- /dev/null +++ b/arch/arm/mach-ixp23xx/espresso.c | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-ixp23xx/espresso.c | ||
| 3 | * | ||
| 4 | * Double Espresso-specific routines | ||
| 5 | * | ||
| 6 | * Author: Lennert Buytenhek <buytenh@wantstofly.org> | ||
| 7 | * | ||
| 8 | * This file is licensed under the terms of the GNU General Public | ||
| 9 | * License version 2. This program is licensed "as is" without any | ||
| 10 | * warranty of any kind, whether express or implied. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/config.h> | ||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/spinlock.h> | ||
| 17 | #include <linux/sched.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/serial.h> | ||
| 20 | #include <linux/tty.h> | ||
| 21 | #include <linux/bitops.h> | ||
| 22 | #include <linux/ioport.h> | ||
| 23 | #include <linux/serial.h> | ||
| 24 | #include <linux/serial_8250.h> | ||
| 25 | #include <linux/serial_core.h> | ||
| 26 | #include <linux/device.h> | ||
| 27 | #include <linux/mm.h> | ||
| 28 | #include <linux/pci.h> | ||
| 29 | #include <linux/mtd/physmap.h> | ||
| 30 | |||
| 31 | #include <asm/types.h> | ||
| 32 | #include <asm/setup.h> | ||
| 33 | #include <asm/memory.h> | ||
| 34 | #include <asm/hardware.h> | ||
| 35 | #include <asm/mach-types.h> | ||
| 36 | #include <asm/irq.h> | ||
| 37 | #include <asm/system.h> | ||
| 38 | #include <asm/tlbflush.h> | ||
| 39 | #include <asm/pgtable.h> | ||
| 40 | |||
| 41 | #include <asm/mach/map.h> | ||
| 42 | #include <asm/mach/irq.h> | ||
| 43 | #include <asm/mach/arch.h> | ||
| 44 | #include <asm/mach/irq.h> | ||
| 45 | #include <asm/mach/pci.h> | ||
| 46 | |||
| 47 | static void __init espresso_init(void) | ||
| 48 | { | ||
| 49 | physmap_configure(0x90000000, 0x02000000, 2, NULL); | ||
| 50 | |||
| 51 | /* | ||
| 52 | * Mark flash as writeable. | ||
| 53 | */ | ||
| 54 | IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE; | ||
| 55 | IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE; | ||
| 56 | |||
| 57 | ixp23xx_sys_init(); | ||
| 58 | } | ||
| 59 | |||
| 60 | MACHINE_START(ESPRESSO, "IP Fabrics Double Espresso") | ||
| 61 | /* Maintainer: Lennert Buytenhek */ | ||
| 62 | .phys_io = IXP23XX_PERIPHERAL_PHYS, | ||
| 63 | .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc, | ||
| 64 | .map_io = ixp23xx_map_io, | ||
| 65 | .init_irq = ixp23xx_init_irq, | ||
| 66 | .timer = &ixp23xx_timer, | ||
| 67 | .boot_params = 0x00000100, | ||
| 68 | .init_machine = espresso_init, | ||
| 69 | MACHINE_END | ||
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c new file mode 100644 index 000000000000..00146c35daac --- /dev/null +++ b/arch/arm/mach-ixp23xx/ixdp2351.c | |||
| @@ -0,0 +1,325 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-ixp23xx/ixdp2351.c | ||
| 3 | * | ||
| 4 | * IXDP2351 board-specific routines | ||
| 5 | * | ||
| 6 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
| 7 | * | ||
| 8 | * Copyright 2005 (c) MontaVista Software, Inc. | ||
| 9 | * | ||
| 10 | * Based on 2.4 code Copyright 2004 (c) Intel Corporation | ||
| 11 | * | ||
| 12 | * This file is licensed under the terms of the GNU General Public | ||
| 13 | * License version 2. This program is licensed "as is" without any | ||
| 14 | * warranty of any kind, whether express or implied. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/config.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/spinlock.h> | ||
| 21 | #include <linux/sched.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/serial.h> | ||
| 24 | #include <linux/tty.h> | ||
| 25 | #include <linux/bitops.h> | ||
| 26 | #include <linux/ioport.h> | ||
| 27 | #include <linux/serial.h> | ||
| 28 | #include <linux/serial_8250.h> | ||
| 29 | #include <linux/serial_core.h> | ||
| 30 | #include <linux/device.h> | ||
| 31 | #include <linux/mm.h> | ||
| 32 | #include <linux/pci.h> | ||
| 33 | #include <linux/mtd/physmap.h> | ||
| 34 | |||
| 35 | #include <asm/types.h> | ||
| 36 | #include <asm/setup.h> | ||
| 37 | #include <asm/memory.h> | ||
| 38 | #include <asm/hardware.h> | ||
| 39 | #include <asm/mach-types.h> | ||
| 40 | #include <asm/irq.h> | ||
| 41 | #include <asm/system.h> | ||
| 42 | #include <asm/tlbflush.h> | ||
| 43 | #include <asm/pgtable.h> | ||
| 44 | |||
| 45 | #include <asm/mach/map.h> | ||
| 46 | #include <asm/mach/irq.h> | ||
| 47 | #include <asm/mach/arch.h> | ||
| 48 | #include <asm/mach/irq.h> | ||
| 49 | #include <asm/mach/pci.h> | ||
| 50 | |||
| 51 | /* | ||
| 52 | * IXDP2351 Interrupt Handling | ||
| 53 | */ | ||
| 54 | static void ixdp2351_inta_mask(unsigned int irq) | ||
| 55 | { | ||
| 56 | *IXDP2351_CPLD_INTA_MASK_SET_REG = IXDP2351_INTA_IRQ_MASK(irq); | ||
| 57 | } | ||
| 58 | |||
| 59 | static void ixdp2351_inta_unmask(unsigned int irq) | ||
| 60 | { | ||
| 61 | *IXDP2351_CPLD_INTA_MASK_CLR_REG = IXDP2351_INTA_IRQ_MASK(irq); | ||
| 62 | } | ||
| 63 | |||
| 64 | static void ixdp2351_inta_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) | ||
| 65 | { | ||
| 66 | u16 ex_interrupt = | ||
| 67 | *IXDP2351_CPLD_INTA_STAT_REG & IXDP2351_INTA_IRQ_VALID; | ||
| 68 | int i; | ||
| 69 | |||
| 70 | desc->chip->mask(irq); | ||
| 71 | |||
| 72 | for (i = 0; i < IXDP2351_INTA_IRQ_NUM; i++) { | ||
| 73 | if (ex_interrupt & (1 << i)) { | ||
| 74 | struct irqdesc *cpld_desc; | ||
| 75 | int cpld_irq = | ||
| 76 | IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + i); | ||
| 77 | cpld_desc = irq_desc + cpld_irq; | ||
| 78 | cpld_desc->handle(cpld_irq, cpld_desc, regs); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | desc->chip->unmask(irq); | ||
| 83 | } | ||
| 84 | |||
| 85 | static struct irqchip ixdp2351_inta_chip = { | ||
| 86 | .ack = ixdp2351_inta_mask, | ||
| 87 | .mask = ixdp2351_inta_mask, | ||
| 88 | .unmask = ixdp2351_inta_unmask | ||
| 89 | }; | ||
| 90 | |||
| 91 | static void ixdp2351_intb_mask(unsigned int irq) | ||
| 92 | { | ||
| 93 | *IXDP2351_CPLD_INTB_MASK_SET_REG = IXDP2351_INTB_IRQ_MASK(irq); | ||
| 94 | } | ||
| 95 | |||
| 96 | static void ixdp2351_intb_unmask(unsigned int irq) | ||
| 97 | { | ||
| 98 | *IXDP2351_CPLD_INTB_MASK_CLR_REG = IXDP2351_INTB_IRQ_MASK(irq); | ||
| 99 | } | ||
| 100 | |||
| 101 | static void ixdp2351_intb_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) | ||
| 102 | { | ||
| 103 | u16 ex_interrupt = | ||
| 104 | *IXDP2351_CPLD_INTB_STAT_REG & IXDP2351_INTB_IRQ_VALID; | ||
| 105 | int i; | ||
| 106 | |||
| 107 | desc->chip->ack(irq); | ||
| 108 | |||
| 109 | for (i = 0; i < IXDP2351_INTB_IRQ_NUM; i++) { | ||
| 110 | if (ex_interrupt & (1 << i)) { | ||
| 111 | struct irqdesc *cpld_desc; | ||
| 112 | int cpld_irq = | ||
| 113 | IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + i); | ||
| 114 | cpld_desc = irq_desc + cpld_irq; | ||
| 115 | cpld_desc->handle(cpld_irq, cpld_desc, regs); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | desc->chip->unmask(irq); | ||
| 120 | } | ||
| 121 | |||
| 122 | static struct irqchip ixdp2351_intb_chip = { | ||
| 123 | .ack = ixdp2351_intb_mask, | ||
| 124 | .mask = ixdp2351_intb_mask, | ||
| 125 | .unmask = ixdp2351_intb_unmask | ||
| 126 | }; | ||
| 127 | |||
| 128 | void ixdp2351_init_irq(void) | ||
| 129 | { | ||
| 130 | int irq; | ||
| 131 | |||
| 132 | /* Mask all interrupts from CPLD, disable simulation */ | ||
| 133 | *IXDP2351_CPLD_INTA_MASK_SET_REG = (u16) -1; | ||
| 134 | *IXDP2351_CPLD_INTB_MASK_SET_REG = (u16) -1; | ||
| 135 | *IXDP2351_CPLD_INTA_SIM_REG = 0; | ||
| 136 | *IXDP2351_CPLD_INTB_SIM_REG = 0; | ||
| 137 | |||
| 138 | ixp23xx_init_irq(); | ||
| 139 | |||
| 140 | for (irq = IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE); | ||
| 141 | irq < | ||
| 142 | IXP23XX_MACH_IRQ(IXDP2351_INTA_IRQ_BASE + IXDP2351_INTA_IRQ_NUM); | ||
| 143 | irq++) { | ||
| 144 | if (IXDP2351_INTA_IRQ_MASK(irq) & IXDP2351_INTA_IRQ_VALID) { | ||
| 145 | set_irq_flags(irq, IRQF_VALID); | ||
| 146 | set_irq_handler(irq, do_level_IRQ); | ||
| 147 | set_irq_chip(irq, &ixdp2351_inta_chip); | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | for (irq = IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE); | ||
| 152 | irq < | ||
| 153 | IXP23XX_MACH_IRQ(IXDP2351_INTB_IRQ_BASE + IXDP2351_INTB_IRQ_NUM); | ||
| 154 | irq++) { | ||
| 155 | if (IXDP2351_INTB_IRQ_MASK(irq) & IXDP2351_INTB_IRQ_VALID) { | ||
| 156 | set_irq_flags(irq, IRQF_VALID); | ||
| 157 | set_irq_handler(irq, do_level_IRQ); | ||
| 158 | set_irq_chip(irq, &ixdp2351_intb_chip); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | set_irq_chained_handler(IRQ_IXP23XX_INTA, &ixdp2351_inta_handler); | ||
| 163 | set_irq_chained_handler(IRQ_IXP23XX_INTB, &ixdp2351_intb_handler); | ||
| 164 | } | ||
| 165 | |||
| 166 | /* | ||
| 167 | * IXDP2351 PCI | ||
| 168 | */ | ||
| 169 | |||
| 170 | /* | ||
| 171 | * This board does not do normal PCI IRQ routing, or any | ||
| 172 | * sort of swizzling, so we just need to check where on the | ||
| 173 | * bus the device is and figure out what CPLD pin it is | ||
| 174 | * being routed to. | ||
| 175 | */ | ||
| 176 | #define DEVPIN(dev, pin) ((pin) | ((dev) << 3)) | ||
| 177 | |||
| 178 | static int __init ixdp2351_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | ||
| 179 | { | ||
| 180 | u8 bus = dev->bus->number; | ||
| 181 | u32 devpin = DEVPIN(PCI_SLOT(dev->devfn), pin); | ||
| 182 | struct pci_bus *tmp_bus = dev->bus; | ||
| 183 | |||
| 184 | /* Primary bus, no interrupts here */ | ||
| 185 | if (!bus) | ||
| 186 | return -1; | ||
| 187 | |||
| 188 | /* Lookup first leaf in bus tree */ | ||
| 189 | while ((tmp_bus->parent != NULL) && (tmp_bus->parent->parent != NULL)) | ||
| 190 | tmp_bus = tmp_bus->parent; | ||
| 191 | |||
| 192 | /* Select between known bridges */ | ||
| 193 | switch (tmp_bus->self->devfn | (tmp_bus->self->bus->number << 8)) { | ||
| 194 | /* Device is located after first bridge */ | ||
| 195 | case 0x0008: | ||
| 196 | if (tmp_bus == dev->bus) { | ||
| 197 | /* Device is located directy after first bridge */ | ||
| 198 | switch (devpin) { | ||
| 199 | /* Onboard 82546 */ | ||
| 200 | case DEVPIN(1, 1): /* Onboard 82546 ch 0 */ | ||
| 201 | return IRQ_IXDP2351_INTA_82546; | ||
| 202 | case DEVPIN(1, 2): /* Onboard 82546 ch 1 */ | ||
| 203 | return IRQ_IXDP2351_INTB_82546; | ||
| 204 | /* PMC SLOT */ | ||
| 205 | case DEVPIN(0, 1): /* PMCP INTA# */ | ||
| 206 | case DEVPIN(2, 4): /* PMCS INTD# */ | ||
| 207 | return IRQ_IXDP2351_SPCI_PMC_INTA; | ||
| 208 | case DEVPIN(0, 2): /* PMCP INTB# */ | ||
| 209 | case DEVPIN(2, 1): /* PMCS INTA# */ | ||
| 210 | return IRQ_IXDP2351_SPCI_PMC_INTB; | ||
| 211 | case DEVPIN(0, 3): /* PMCP INTC# */ | ||
| 212 | case DEVPIN(2, 2): /* PMCS INTB# */ | ||
| 213 | return IRQ_IXDP2351_SPCI_PMC_INTC; | ||
| 214 | case DEVPIN(0, 4): /* PMCP INTD# */ | ||
| 215 | case DEVPIN(2, 3): /* PMCS INTC# */ | ||
| 216 | return IRQ_IXDP2351_SPCI_PMC_INTD; | ||
| 217 | } | ||
| 218 | } else { | ||
| 219 | /* Device is located indirectly after first bridge */ | ||
| 220 | /* Not supported now */ | ||
| 221 | return -1; | ||
| 222 | } | ||
| 223 | break; | ||
| 224 | case 0x0010: | ||
| 225 | if (tmp_bus == dev->bus) { | ||
| 226 | /* Device is located directy after second bridge */ | ||
| 227 | /* Secondary bus of second bridge */ | ||
| 228 | switch (devpin) { | ||
| 229 | case DEVPIN(0, 1): /* DB#0 */ | ||
| 230 | case DEVPIN(0, 2): | ||
| 231 | case DEVPIN(0, 3): | ||
| 232 | case DEVPIN(0, 4): | ||
| 233 | return IRQ_IXDP2351_SPCI_DB_0; | ||
| 234 | case DEVPIN(1, 1): /* DB#1 */ | ||
| 235 | case DEVPIN(1, 2): | ||
| 236 | case DEVPIN(1, 3): | ||
| 237 | case DEVPIN(1, 4): | ||
| 238 | return IRQ_IXDP2351_SPCI_DB_1; | ||
| 239 | case DEVPIN(2, 1): /* FIC1 */ | ||
| 240 | case DEVPIN(2, 2): | ||
| 241 | case DEVPIN(2, 3): | ||
| 242 | case DEVPIN(2, 4): | ||
| 243 | case DEVPIN(3, 1): /* FIC2 */ | ||
| 244 | case DEVPIN(3, 2): | ||
| 245 | case DEVPIN(3, 3): | ||
| 246 | case DEVPIN(3, 4): | ||
| 247 | return IRQ_IXDP2351_SPCI_FIC; | ||
| 248 | } | ||
| 249 | } else { | ||
| 250 | /* Device is located indirectly after second bridge */ | ||
| 251 | /* Not supported now */ | ||
| 252 | return -1; | ||
| 253 | } | ||
| 254 | break; | ||
| 255 | } | ||
| 256 | |||
| 257 | return -1; | ||
| 258 | } | ||
| 259 | |||
| 260 | struct hw_pci ixdp2351_pci __initdata = { | ||
| 261 | .nr_controllers = 1, | ||
| 262 | .preinit = ixp23xx_pci_preinit, | ||
| 263 | .setup = ixp23xx_pci_setup, | ||
| 264 | .scan = ixp23xx_pci_scan_bus, | ||
| 265 | .map_irq = ixdp2351_map_irq, | ||
| 266 | }; | ||
| 267 | |||
| 268 | int __init ixdp2351_pci_init(void) | ||
| 269 | { | ||
| 270 | if (machine_is_ixdp2351()) | ||
| 271 | pci_common_init(&ixdp2351_pci); | ||
| 272 | |||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | subsys_initcall(ixdp2351_pci_init); | ||
| 277 | |||
| 278 | /* | ||
| 279 | * IXDP2351 Static Mapped I/O | ||
| 280 | */ | ||
| 281 | static struct map_desc ixdp2351_io_desc[] __initdata = { | ||
| 282 | { | ||
| 283 | .virtual = IXDP2351_NP_VIRT_BASE, | ||
| 284 | .pfn = __phys_to_pfn((u64)IXDP2351_NP_PHYS_BASE), | ||
| 285 | .length = IXDP2351_NP_PHYS_SIZE, | ||
| 286 | .type = MT_DEVICE | ||
| 287 | }, { | ||
| 288 | .virtual = IXDP2351_BB_BASE_VIRT, | ||
| 289 | .pfn = __phys_to_pfn((u64)IXDP2351_BB_BASE_PHYS), | ||
| 290 | .length = IXDP2351_BB_SIZE, | ||
| 291 | .type = MT_DEVICE | ||
| 292 | } | ||
| 293 | }; | ||
| 294 | |||
| 295 | static void __init ixdp2351_map_io(void) | ||
| 296 | { | ||
| 297 | ixp23xx_map_io(); | ||
| 298 | iotable_init(ixdp2351_io_desc, ARRAY_SIZE(ixdp2351_io_desc)); | ||
| 299 | } | ||
| 300 | |||
| 301 | static void __init ixdp2351_init(void) | ||
| 302 | { | ||
| 303 | physmap_configure(0x90000000, 0x04000000, 1, NULL); | ||
| 304 | |||
| 305 | /* | ||
| 306 | * Mark flash as writeable | ||
| 307 | */ | ||
| 308 | IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE; | ||
| 309 | IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE; | ||
| 310 | IXP23XX_EXP_CS0[2] |= IXP23XX_FLASH_WRITABLE; | ||
| 311 | IXP23XX_EXP_CS0[3] |= IXP23XX_FLASH_WRITABLE; | ||
| 312 | |||
| 313 | ixp23xx_sys_init(); | ||
| 314 | } | ||
| 315 | |||
| 316 | MACHINE_START(IXDP2351, "Intel IXDP2351 Development Platform") | ||
| 317 | /* Maintainer: MontaVista Software, Inc. */ | ||
| 318 | .phys_io = IXP23XX_PERIPHERAL_PHYS, | ||
| 319 | .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc, | ||
| 320 | .map_io = ixdp2351_map_io, | ||
| 321 | .init_irq = ixdp2351_init_irq, | ||
| 322 | .timer = &ixp23xx_timer, | ||
| 323 | .boot_params = 0x00000100, | ||
| 324 | .init_machine = ixdp2351_init, | ||
| 325 | MACHINE_END | ||
diff --git a/arch/arm/mach-ixp23xx/pci.c b/arch/arm/mach-ixp23xx/pci.c new file mode 100644 index 000000000000..5330ad78c1bb --- /dev/null +++ b/arch/arm/mach-ixp23xx/pci.c | |||
| @@ -0,0 +1,275 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-ixp23xx/pci.c | ||
| 3 | * | ||
| 4 | * PCI routines for IXP23XX based systems | ||
| 5 | * | ||
| 6 | * Copyright (c) 2005 MontaVista Software, Inc. | ||
| 7 | * | ||
| 8 | * based on original code: | ||
| 9 | * | ||
| 10 | * Author: Naeem Afzal <naeem.m.afzal@intel.com> | ||
| 11 | * Copyright 2002-2005 Intel Corp. | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or modify it | ||
| 14 | * under the terms of the GNU General Public License as published by the | ||
| 15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 16 | * option) any later version. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/config.h> | ||
| 20 | #include <linux/sched.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/pci.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/mm.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/ioport.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | #include <linux/delay.h> | ||
| 29 | |||
| 30 | #include <asm/io.h> | ||
| 31 | #include <asm/irq.h> | ||
| 32 | #include <asm/sizes.h> | ||
| 33 | #include <asm/system.h> | ||
| 34 | #include <asm/mach/pci.h> | ||
| 35 | #include <asm/mach-types.h> | ||
| 36 | #include <asm/hardware.h> | ||
| 37 | |||
| 38 | extern int (*external_fault) (unsigned long, struct pt_regs *); | ||
| 39 | |||
| 40 | static int pci_master_aborts = 0; | ||
| 41 | |||
| 42 | #ifdef DEBUG | ||
| 43 | #define DBG(x...) printk(x) | ||
| 44 | #else | ||
| 45 | #define DBG(x...) | ||
| 46 | #endif | ||
| 47 | |||
| 48 | int clear_master_aborts(void); | ||
| 49 | |||
| 50 | static u32 | ||
| 51 | *ixp23xx_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where) | ||
| 52 | { | ||
| 53 | u32 *paddress; | ||
| 54 | |||
| 55 | /* | ||
| 56 | * Must be dword aligned | ||
| 57 | */ | ||
| 58 | where &= ~3; | ||
| 59 | |||
| 60 | /* | ||
| 61 | * For top bus, generate type 0, else type 1 | ||
| 62 | */ | ||
| 63 | if (!bus_nr) { | ||
| 64 | if (PCI_SLOT(devfn) >= 8) | ||
| 65 | return 0; | ||
| 66 | |||
| 67 | paddress = (u32 *) (IXP23XX_PCI_CFG0_VIRT | ||
| 68 | | (1 << (PCI_SLOT(devfn) + 16)) | ||
| 69 | | (PCI_FUNC(devfn) << 8) | where); | ||
| 70 | } else { | ||
| 71 | paddress = (u32 *) (IXP23XX_PCI_CFG1_VIRT | ||
| 72 | | (bus_nr << 16) | ||
| 73 | | (PCI_SLOT(devfn) << 11) | ||
| 74 | | (PCI_FUNC(devfn) << 8) | where); | ||
| 75 | } | ||
| 76 | |||
| 77 | return paddress; | ||
| 78 | } | ||
| 79 | |||
| 80 | /* | ||
| 81 | * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes. | ||
| 82 | * 0 and 3 are not valid indexes... | ||
| 83 | */ | ||
| 84 | static u32 bytemask[] = { | ||
| 85 | /*0*/ 0, | ||
| 86 | /*1*/ 0xff, | ||
| 87 | /*2*/ 0xffff, | ||
| 88 | /*3*/ 0, | ||
| 89 | /*4*/ 0xffffffff, | ||
| 90 | }; | ||
| 91 | |||
| 92 | static int ixp23xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
| 93 | int where, int size, u32 *value) | ||
| 94 | { | ||
| 95 | u32 n; | ||
| 96 | u32 *addr; | ||
| 97 | |||
| 98 | n = where % 4; | ||
| 99 | |||
| 100 | DBG("In config_read(%d) %d from dev %d:%d:%d\n", size, where, | ||
| 101 | bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); | ||
| 102 | |||
| 103 | addr = ixp23xx_pci_config_addr(bus->number, devfn, where); | ||
| 104 | if (!addr) | ||
| 105 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 106 | |||
| 107 | pci_master_aborts = 0; | ||
| 108 | *value = (*addr >> (8*n)) & bytemask[size]; | ||
| 109 | if (pci_master_aborts) { | ||
| 110 | pci_master_aborts = 0; | ||
| 111 | *value = 0xffffffff; | ||
| 112 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 113 | } | ||
| 114 | |||
| 115 | return PCIBIOS_SUCCESSFUL; | ||
| 116 | } | ||
| 117 | |||
| 118 | /* | ||
| 119 | * We don't do error checking on the address for writes. | ||
| 120 | * It's assumed that the user checked for the device existing first | ||
| 121 | * by doing a read first. | ||
| 122 | */ | ||
| 123 | static int ixp23xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
| 124 | int where, int size, u32 value) | ||
| 125 | { | ||
| 126 | u32 mask; | ||
| 127 | u32 *addr; | ||
| 128 | u32 temp; | ||
| 129 | |||
| 130 | mask = ~(bytemask[size] << ((where % 0x4) * 8)); | ||
| 131 | addr = ixp23xx_pci_config_addr(bus->number, devfn, where); | ||
| 132 | if (!addr) | ||
| 133 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 134 | temp = (u32) (value) << ((where % 0x4) * 8); | ||
| 135 | *addr = (*addr & mask) | temp; | ||
| 136 | |||
| 137 | clear_master_aborts(); | ||
| 138 | |||
| 139 | return PCIBIOS_SUCCESSFUL; | ||
| 140 | } | ||
| 141 | |||
| 142 | struct pci_ops ixp23xx_pci_ops = { | ||
| 143 | .read = ixp23xx_pci_read_config, | ||
| 144 | .write = ixp23xx_pci_write_config, | ||
| 145 | }; | ||
| 146 | |||
| 147 | struct pci_bus *ixp23xx_pci_scan_bus(int nr, struct pci_sys_data *sysdata) | ||
| 148 | { | ||
| 149 | return pci_scan_bus(sysdata->busnr, &ixp23xx_pci_ops, sysdata); | ||
| 150 | } | ||
| 151 | |||
| 152 | int ixp23xx_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | ||
| 153 | { | ||
| 154 | volatile unsigned long temp; | ||
| 155 | unsigned long flags; | ||
| 156 | |||
| 157 | pci_master_aborts = 1; | ||
| 158 | |||
| 159 | local_irq_save(flags); | ||
| 160 | temp = *IXP23XX_PCI_CONTROL; | ||
| 161 | |||
| 162 | /* | ||
| 163 | * master abort and cmd tgt err | ||
| 164 | */ | ||
| 165 | if (temp & ((1 << 8) | (1 << 5))) | ||
| 166 | *IXP23XX_PCI_CONTROL = temp; | ||
| 167 | |||
| 168 | temp = *IXP23XX_PCI_CMDSTAT; | ||
| 169 | |||
| 170 | if (temp & (1 << 29)) | ||
| 171 | *IXP23XX_PCI_CMDSTAT = temp; | ||
| 172 | local_irq_restore(flags); | ||
| 173 | |||
| 174 | /* | ||
| 175 | * If it was an imprecise abort, then we need to correct the | ||
| 176 | * return address to be _after_ the instruction. | ||
| 177 | */ | ||
| 178 | if (fsr & (1 << 10)) | ||
| 179 | regs->ARM_pc += 4; | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | int clear_master_aborts(void) | ||
| 185 | { | ||
| 186 | volatile u32 temp; | ||
| 187 | |||
| 188 | temp = *IXP23XX_PCI_CONTROL; | ||
| 189 | |||
| 190 | /* | ||
| 191 | * master abort and cmd tgt err | ||
| 192 | */ | ||
| 193 | if (temp & ((1 << 8) | (1 << 5))) | ||
| 194 | *IXP23XX_PCI_CONTROL = temp; | ||
| 195 | |||
| 196 | temp = *IXP23XX_PCI_CMDSTAT; | ||
| 197 | |||
| 198 | if (temp & (1 << 29)) | ||
| 199 | *IXP23XX_PCI_CMDSTAT = temp; | ||
| 200 | |||
| 201 | return 0; | ||
| 202 | } | ||
| 203 | |||
| 204 | void __init ixp23xx_pci_preinit(void) | ||
| 205 | { | ||
| 206 | #ifdef __ARMEB__ | ||
| 207 | *IXP23XX_PCI_CONTROL |= 0x20000; /* set I/O swapping */ | ||
| 208 | #endif | ||
| 209 | /* | ||
| 210 | * ADDR_31 needs to be clear for PCI memory access to CPP memory | ||
| 211 | */ | ||
| 212 | *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_ADDR_31; | ||
| 213 | *IXP23XX_CPP2XSI_CURR_XFER_REG3 |= IXP23XX_CPP2XSI_PSH_OFF; | ||
| 214 | |||
| 215 | /* | ||
| 216 | * Select correct memory for PCI inbound transactions | ||
| 217 | */ | ||
| 218 | if (ixp23xx_cpp_boot()) { | ||
| 219 | *IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1); | ||
| 220 | } else { | ||
| 221 | *IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1); | ||
| 222 | } | ||
| 223 | |||
| 224 | hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS, | ||
| 225 | "PCI config cycle to non-existent device"); | ||
| 226 | |||
| 227 | *IXP23XX_PCI_ADDR_EXT = 0x0000e000; | ||
| 228 | } | ||
| 229 | |||
| 230 | /* | ||
| 231 | * Prevent PCI layer from seeing the inbound host-bridge resources | ||
| 232 | */ | ||
| 233 | static void __devinit pci_fixup_ixp23xx(struct pci_dev *dev) | ||
| 234 | { | ||
| 235 | int i; | ||
| 236 | |||
| 237 | dev->class &= 0xff; | ||
| 238 | dev->class |= PCI_CLASS_BRIDGE_HOST << 8; | ||
| 239 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | ||
| 240 | dev->resource[i].start = 0; | ||
| 241 | dev->resource[i].end = 0; | ||
| 242 | dev->resource[i].flags = 0; | ||
| 243 | } | ||
| 244 | } | ||
| 245 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9002, pci_fixup_ixp23xx); | ||
| 246 | |||
| 247 | /* | ||
| 248 | * IXP2300 systems often have large resource requirements, so we just | ||
| 249 | * use our own resource space. | ||
| 250 | */ | ||
| 251 | static struct resource ixp23xx_pci_mem_space = { | ||
| 252 | .start = IXP23XX_PCI_MEM_START, | ||
| 253 | .end = IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE - 1, | ||
| 254 | .flags = IORESOURCE_MEM, | ||
| 255 | .name = "PCI Mem Space" | ||
| 256 | }; | ||
| 257 | |||
| 258 | static struct resource ixp23xx_pci_io_space = { | ||
| 259 | .start = 0x00000100, | ||
| 260 | .end = 0x01ffffff, | ||
| 261 | .flags = IORESOURCE_IO, | ||
| 262 | .name = "PCI I/O Space" | ||
| 263 | }; | ||
| 264 | |||
| 265 | int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys) | ||
| 266 | { | ||
| 267 | if (nr >= 1) | ||
| 268 | return 0; | ||
| 269 | |||
| 270 | sys->resource[0] = &ixp23xx_pci_io_space; | ||
| 271 | sys->resource[1] = &ixp23xx_pci_mem_space; | ||
| 272 | sys->resource[2] = NULL; | ||
| 273 | |||
| 274 | return 1; | ||
| 275 | } | ||
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c new file mode 100644 index 000000000000..43c14e740794 --- /dev/null +++ b/arch/arm/mach-ixp23xx/roadrunner.c | |||
| @@ -0,0 +1,164 @@ | |||
| 1 | /* | ||
| 2 | * arch/arm/mach-ixp23xx/roadrunner.c | ||
| 3 | * | ||
| 4 | * RoadRunner board-specific routines | ||
| 5 | * | ||
| 6 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
| 7 | * | ||
| 8 | * Copyright 2005 (c) MontaVista Software, Inc. | ||
| 9 | * | ||
| 10 | * Based on 2.4 code Copyright 2005 (c) ADI Engineering Corporation | ||
| 11 | * | ||
| 12 | * This file is licensed under the terms of the GNU General Public | ||
| 13 | * License version 2. This program is licensed "as is" without any | ||
| 14 | * warranty of any kind, whether express or implied. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/config.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/spinlock.h> | ||
| 21 | #include <linux/sched.h> | ||
| 22 | #include <linux/interrupt.h> | ||
| 23 | #include <linux/serial.h> | ||
| 24 | #include <linux/tty.h> | ||
| 25 | #include <linux/bitops.h> | ||
| 26 | #include <linux/ioport.h> | ||
| 27 | #include <linux/serial.h> | ||
| 28 | #include <linux/serial_8250.h> | ||
| 29 | #include <linux/serial_core.h> | ||
| 30 | #include <linux/device.h> | ||
| 31 | #include <linux/mm.h> | ||
| 32 | #include <linux/pci.h> | ||
| 33 | #include <linux/mtd/physmap.h> | ||
| 34 | |||
| 35 | #include <asm/types.h> | ||
| 36 | #include <asm/setup.h> | ||
| 37 | #include <asm/memory.h> | ||
| 38 | #include <asm/hardware.h> | ||
| 39 | #include <asm/mach-types.h> | ||
| 40 | #include <asm/irq.h> | ||
| 41 | #include <asm/system.h> | ||
| 42 | #include <asm/tlbflush.h> | ||
| 43 | #include <asm/pgtable.h> | ||
| 44 | |||
| 45 | #include <asm/mach/map.h> | ||
| 46 | #include <asm/mach/irq.h> | ||
| 47 | #include <asm/mach/arch.h> | ||
| 48 | #include <asm/mach/irq.h> | ||
| 49 | #include <asm/mach/pci.h> | ||
| 50 | |||
| 51 | /* | ||
| 52 | * Interrupt mapping | ||
| 53 | */ | ||
| 54 | #define INTA IRQ_ROADRUNNER_PCI_INTA | ||
| 55 | #define INTB IRQ_ROADRUNNER_PCI_INTB | ||
| 56 | #define INTC IRQ_ROADRUNNER_PCI_INTC | ||
| 57 | #define INTD IRQ_ROADRUNNER_PCI_INTD | ||
| 58 | |||
| 59 | #define INTC_PIN IXP23XX_GPIO_PIN_11 | ||
| 60 | #define INTD_PIN IXP23XX_GPIO_PIN_12 | ||
| 61 | |||
| 62 | static int __init roadrunner_map_irq(struct pci_dev *dev, u8 idsel, u8 pin) | ||
| 63 | { | ||
| 64 | static int pci_card_slot_irq[] = {INTB, INTC, INTD, INTA}; | ||
| 65 | static int pmc_card_slot_irq[] = {INTA, INTB, INTC, INTD}; | ||
| 66 | static int usb_irq[] = {INTB, INTC, INTD, -1}; | ||
| 67 | static int mini_pci_1_irq[] = {INTB, INTC, -1, -1}; | ||
| 68 | static int mini_pci_2_irq[] = {INTC, INTD, -1, -1}; | ||
| 69 | |||
| 70 | switch(dev->bus->number) { | ||
| 71 | case 0: | ||
| 72 | switch(dev->devfn) { | ||
| 73 | case 0x0: // PCI-PCI bridge | ||
| 74 | break; | ||
| 75 | case 0x8: // PCI Card Slot | ||
| 76 | return pci_card_slot_irq[pin - 1]; | ||
| 77 | case 0x10: // PMC Slot | ||
| 78 | return pmc_card_slot_irq[pin - 1]; | ||
| 79 | case 0x18: // PMC Slot Secondary Agent | ||
| 80 | break; | ||
| 81 | case 0x20: // IXP Processor | ||
| 82 | break; | ||
| 83 | default: | ||
| 84 | return NO_IRQ; | ||
| 85 | } | ||
| 86 | break; | ||
| 87 | |||
| 88 | case 1: | ||
| 89 | switch(dev->devfn) { | ||
| 90 | case 0x0: // IDE Controller | ||
| 91 | return (pin == 1) ? INTC : -1; | ||
| 92 | case 0x8: // USB fun 0 | ||
| 93 | case 0x9: // USB fun 1 | ||
| 94 | case 0xa: // USB fun 2 | ||
| 95 | return usb_irq[pin - 1]; | ||
| 96 | case 0x10: // Mini PCI 1 | ||
| 97 | return mini_pci_1_irq[pin-1]; | ||
| 98 | case 0x18: // Mini PCI 2 | ||
| 99 | return mini_pci_2_irq[pin-1]; | ||
| 100 | case 0x20: // MEM slot | ||
| 101 | return (pin == 1) ? INTA : -1; | ||
| 102 | default: | ||
| 103 | return NO_IRQ; | ||
| 104 | } | ||
| 105 | break; | ||
| 106 | |||
| 107 | default: | ||
| 108 | return NO_IRQ; | ||
| 109 | } | ||
| 110 | |||
| 111 | return NO_IRQ; | ||
| 112 | } | ||
| 113 | |||
| 114 | static void roadrunner_pci_preinit(void) | ||
| 115 | { | ||
| 116 | set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQT_LOW); | ||
| 117 | set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQT_LOW); | ||
| 118 | |||
| 119 | ixp23xx_pci_preinit(); | ||
| 120 | } | ||
| 121 | |||
| 122 | static struct hw_pci roadrunner_pci __initdata = { | ||
| 123 | .nr_controllers = 1, | ||
| 124 | .preinit = roadrunner_pci_preinit, | ||
| 125 | .setup = ixp23xx_pci_setup, | ||
| 126 | .scan = ixp23xx_pci_scan_bus, | ||
| 127 | .map_irq = roadrunner_map_irq, | ||
| 128 | }; | ||
| 129 | |||
| 130 | static int __init roadrunner_pci_init(void) | ||
| 131 | { | ||
| 132 | if (machine_is_roadrunner()) | ||
| 133 | pci_common_init(&roadrunner_pci); | ||
| 134 | |||
| 135 | return 0; | ||
| 136 | }; | ||
| 137 | |||
| 138 | subsys_initcall(roadrunner_pci_init); | ||
| 139 | |||
| 140 | static void __init roadrunner_init(void) | ||
| 141 | { | ||
| 142 | physmap_configure(0x90000000, 0x04000000, 2, NULL); | ||
| 143 | |||
| 144 | /* | ||
| 145 | * Mark flash as writeable | ||
| 146 | */ | ||
| 147 | IXP23XX_EXP_CS0[0] |= IXP23XX_FLASH_WRITABLE; | ||
| 148 | IXP23XX_EXP_CS0[1] |= IXP23XX_FLASH_WRITABLE; | ||
| 149 | IXP23XX_EXP_CS0[2] |= IXP23XX_FLASH_WRITABLE; | ||
| 150 | IXP23XX_EXP_CS0[3] |= IXP23XX_FLASH_WRITABLE; | ||
| 151 | |||
| 152 | ixp23xx_sys_init(); | ||
| 153 | } | ||
| 154 | |||
| 155 | MACHINE_START(ROADRUNNER, "ADI Engineering RoadRunner Development Platform") | ||
| 156 | /* Maintainer: Deepak Saxena */ | ||
| 157 | .phys_io = IXP23XX_PERIPHERAL_PHYS, | ||
| 158 | .io_pg_offst = ((IXP23XX_PERIPHERAL_VIRT >> 18)) & 0xfffc, | ||
| 159 | .map_io = ixp23xx_map_io, | ||
| 160 | .init_irq = ixp23xx_init_irq, | ||
| 161 | .timer = &ixp23xx_timer, | ||
| 162 | .boot_params = 0x00000100, | ||
| 163 | .init_machine = roadrunner_init, | ||
| 164 | MACHINE_END | ||
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c index 60d5f8a3339c..7520e602d7a2 100644 --- a/arch/arm/mach-omap1/board-netstar.c +++ b/arch/arm/mach-omap1/board-netstar.c | |||
| @@ -141,7 +141,7 @@ static int __init netstar_late_init(void) | |||
| 141 | /* TODO: Setup front panel switch here */ | 141 | /* TODO: Setup front panel switch here */ |
| 142 | 142 | ||
| 143 | /* Setup panic notifier */ | 143 | /* Setup panic notifier */ |
| 144 | notifier_chain_register(&panic_notifier_list, &panic_block); | 144 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); |
| 145 | 145 | ||
| 146 | return 0; | 146 | return 0; |
| 147 | } | 147 | } |
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index bfd5fdd1a875..52e4a9d69642 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c | |||
| @@ -235,7 +235,7 @@ static struct notifier_block panic_block = { | |||
| 235 | static int __init voiceblue_setup(void) | 235 | static int __init voiceblue_setup(void) |
| 236 | { | 236 | { |
| 237 | /* Setup panic notifier */ | 237 | /* Setup panic notifier */ |
| 238 | notifier_chain_register(&panic_notifier_list, &panic_block); | 238 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); |
| 239 | 239 | ||
| 240 | return 0; | 240 | return 0; |
| 241 | } | 241 | } |
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index c1d77f5b3823..0104fd142e70 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig | |||
| @@ -10,6 +10,11 @@ config ARCH_LUBBOCK | |||
| 10 | select PXA25x | 10 | select PXA25x |
| 11 | select SA1111 | 11 | select SA1111 |
| 12 | 12 | ||
| 13 | config MACH_LOGICPD_PXA270 | ||
| 14 | bool "LogicPD PXA270 Card Engine Development Platform" | ||
| 15 | select PXA27x | ||
| 16 | select IWMMXT | ||
| 17 | |||
| 13 | config MACH_MAINSTONE | 18 | config MACH_MAINSTONE |
| 14 | bool "Intel HCDDBBVA0 Development Platform" | 19 | bool "Intel HCDDBBVA0 Development Platform" |
| 15 | select PXA27x | 20 | select PXA27x |
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 382644401a4d..4e8a983e2b83 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile | |||
| @@ -9,6 +9,7 @@ obj-$(CONFIG_PXA27x) += pxa27x.o | |||
| 9 | 9 | ||
| 10 | # Specific board support | 10 | # Specific board support |
| 11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o | 11 | obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o |
| 12 | obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o | ||
| 12 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o | 13 | obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o |
| 13 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o | 14 | obj-$(CONFIG_ARCH_PXA_IDP) += idp.o |
| 14 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o | 15 | obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o |
diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 9b48a90aefce..5efa84749f37 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c | |||
| @@ -319,6 +319,11 @@ void __init pxa_set_ficp_info(struct pxaficp_platform_data *info) | |||
| 319 | pxaficp_device.dev.platform_data = info; | 319 | pxaficp_device.dev.platform_data = info; |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | static struct platform_device pxartc_device = { | ||
| 323 | .name = "sa1100-rtc", | ||
| 324 | .id = -1, | ||
| 325 | }; | ||
| 326 | |||
| 322 | static struct platform_device *devices[] __initdata = { | 327 | static struct platform_device *devices[] __initdata = { |
| 323 | &pxamci_device, | 328 | &pxamci_device, |
| 324 | &udc_device, | 329 | &udc_device, |
| @@ -329,6 +334,7 @@ static struct platform_device *devices[] __initdata = { | |||
| 329 | &pxaficp_device, | 334 | &pxaficp_device, |
| 330 | &i2c_device, | 335 | &i2c_device, |
| 331 | &i2s_device, | 336 | &i2s_device, |
| 337 | &pxartc_device, | ||
| 332 | }; | 338 | }; |
| 333 | 339 | ||
| 334 | static int __init pxa_init(void) | 340 | static int __init pxa_init(void) |
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c new file mode 100644 index 000000000000..ec0f43a102c7 --- /dev/null +++ b/arch/arm/mach-pxa/lpd270.c | |||
| @@ -0,0 +1,393 @@ | |||
| 1 | /* | ||
| 2 | * linux/arch/arm/mach-pxa/lpd270.c | ||
| 3 | * | ||
| 4 | * Support for the LogicPD PXA270 Card Engine. | ||
| 5 | * Derived from the mainstone code, which carries these notices: | ||
| 6 | * | ||
| 7 | * Author: Nicolas Pitre | ||
| 8 | * Created: Nov 05, 2002 | ||
| 9 | * Copyright: MontaVista Software Inc. | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/sysdev.h> | ||
| 19 | #include <linux/interrupt.h> | ||
| 20 | #include <linux/sched.h> | ||
| 21 | #include <linux/bitops.h> | ||
| 22 | #include <linux/fb.h> | ||
| 23 | #include <linux/ioport.h> | ||
| 24 | #include <linux/mtd/mtd.h> | ||
| 25 | #include <linux/mtd/partitions.h> | ||
| 26 | |||
| 27 | #include <asm/types.h> | ||
| 28 | #include <asm/setup.h> | ||
| 29 | #include <asm/memory.h> | ||
| 30 | #include <asm/mach-types.h> | ||
| 31 | #include <asm/hardware.h> | ||
| 32 | #include <asm/irq.h> | ||
| 33 | #include <asm/sizes.h> | ||
| 34 | |||
| 35 | #include <asm/mach/arch.h> | ||
| 36 | #include <asm/mach/map.h> | ||
| 37 | #include <asm/mach/irq.h> | ||
| 38 | #include <asm/mach/flash.h> | ||
| 39 | |||
| 40 | #include <asm/arch/pxa-regs.h> | ||
| 41 | #include <asm/arch/lpd270.h> | ||
| 42 | #include <asm/arch/audio.h> | ||
| 43 | #include <asm/arch/pxafb.h> | ||
| 44 | #include <asm/arch/mmc.h> | ||
| 45 | #include <asm/arch/irda.h> | ||
| 46 | #include <asm/arch/ohci.h> | ||
| 47 | |||
| 48 | #include "generic.h" | ||
| 49 | |||
| 50 | |||
| 51 | static unsigned int lpd270_irq_enabled; | ||
| 52 | |||
| 53 | static void lpd270_mask_irq(unsigned int irq) | ||
| 54 | { | ||
| 55 | int lpd270_irq = irq - LPD270_IRQ(0); | ||
| 56 | |||
| 57 | __raw_writew(~(1 << lpd270_irq), LPD270_INT_STATUS); | ||
| 58 | |||
| 59 | lpd270_irq_enabled &= ~(1 << lpd270_irq); | ||
| 60 | __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK); | ||
| 61 | } | ||
| 62 | |||
| 63 | static void lpd270_unmask_irq(unsigned int irq) | ||
| 64 | { | ||
| 65 | int lpd270_irq = irq - LPD270_IRQ(0); | ||
| 66 | |||
| 67 | lpd270_irq_enabled |= 1 << lpd270_irq; | ||
| 68 | __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK); | ||
| 69 | } | ||
| 70 | |||
| 71 | static struct irqchip lpd270_irq_chip = { | ||
| 72 | .ack = lpd270_mask_irq, | ||
| 73 | .mask = lpd270_mask_irq, | ||
| 74 | .unmask = lpd270_unmask_irq, | ||
| 75 | }; | ||
| 76 | |||
| 77 | static void lpd270_irq_handler(unsigned int irq, struct irqdesc *desc, | ||
| 78 | struct pt_regs *regs) | ||
| 79 | { | ||
| 80 | unsigned long pending; | ||
| 81 | |||
| 82 | pending = __raw_readw(LPD270_INT_STATUS) & lpd270_irq_enabled; | ||
| 83 | do { | ||
| 84 | GEDR(0) = GPIO_bit(0); /* clear useless edge notification */ | ||
| 85 | if (likely(pending)) { | ||
| 86 | irq = LPD270_IRQ(0) + __ffs(pending); | ||
| 87 | desc = irq_desc + irq; | ||
| 88 | desc_handle_irq(irq, desc, regs); | ||
| 89 | |||
| 90 | pending = __raw_readw(LPD270_INT_STATUS) & | ||
| 91 | lpd270_irq_enabled; | ||
| 92 | } | ||
| 93 | } while (pending); | ||
| 94 | } | ||
| 95 | |||
| 96 | static void __init lpd270_init_irq(void) | ||
| 97 | { | ||
| 98 | int irq; | ||
| 99 | |||
| 100 | pxa_init_irq(); | ||
| 101 | |||
| 102 | __raw_writew(0, LPD270_INT_MASK); | ||
| 103 | __raw_writew(0, LPD270_INT_STATUS); | ||
| 104 | |||
| 105 | /* setup extra LogicPD PXA270 irqs */ | ||
| 106 | for (irq = LPD270_IRQ(2); irq <= LPD270_IRQ(4); irq++) { | ||
| 107 | set_irq_chip(irq, &lpd270_irq_chip); | ||
| 108 | set_irq_handler(irq, do_level_IRQ); | ||
| 109 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
| 110 | } | ||
| 111 | set_irq_chained_handler(IRQ_GPIO(0), lpd270_irq_handler); | ||
| 112 | set_irq_type(IRQ_GPIO(0), IRQT_FALLING); | ||
| 113 | } | ||
| 114 | |||
| 115 | |||
| 116 | #ifdef CONFIG_PM | ||
| 117 | static int lpd270_irq_resume(struct sys_device *dev) | ||
| 118 | { | ||
| 119 | __raw_writew(lpd270_irq_enabled, LPD270_INT_MASK); | ||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | static struct sysdev_class lpd270_irq_sysclass = { | ||
| 124 | set_kset_name("cpld_irq"), | ||
| 125 | .resume = lpd270_irq_resume, | ||
| 126 | }; | ||
| 127 | |||
| 128 | static struct sys_device lpd270_irq_device = { | ||
| 129 | .cls = &lpd270_irq_sysclass, | ||
| 130 | }; | ||
| 131 | |||
| 132 | static int __init lpd270_irq_device_init(void) | ||
| 133 | { | ||
| 134 | int ret = sysdev_class_register(&lpd270_irq_sysclass); | ||
| 135 | if (ret == 0) | ||
| 136 | ret = sysdev_register(&lpd270_irq_device); | ||
| 137 | return ret; | ||
| 138 | } | ||
| 139 | |||
| 140 | device_initcall(lpd270_irq_device_init); | ||
| 141 | #endif | ||
| 142 | |||
| 143 | |||
| 144 | static struct resource smc91x_resources[] = { | ||
| 145 | [0] = { | ||
| 146 | .start = LPD270_ETH_PHYS, | ||
| 147 | .end = (LPD270_ETH_PHYS + 0xfffff), | ||
| 148 | .flags = IORESOURCE_MEM, | ||
| 149 | }, | ||
| 150 | [1] = { | ||
| 151 | .start = LPD270_ETHERNET_IRQ, | ||
| 152 | .end = LPD270_ETHERNET_IRQ, | ||
| 153 | .flags = IORESOURCE_IRQ, | ||
| 154 | }, | ||
| 155 | }; | ||
| 156 | |||
| 157 | static struct platform_device smc91x_device = { | ||
| 158 | .name = "smc91x", | ||
| 159 | .id = 0, | ||
| 160 | .num_resources = ARRAY_SIZE(smc91x_resources), | ||
| 161 | .resource = smc91x_resources, | ||
| 162 | }; | ||
| 163 | |||
| 164 | static struct platform_device lpd270_audio_device = { | ||
| 165 | .name = "pxa2xx-ac97", | ||
| 166 | .id = -1, | ||
| 167 | }; | ||
| 168 | |||
| 169 | static struct resource lpd270_flash_resources[] = { | ||
| 170 | [0] = { | ||
| 171 | .start = PXA_CS0_PHYS, | ||
| 172 | .end = PXA_CS0_PHYS + SZ_64M - 1, | ||
| 173 | .flags = IORESOURCE_MEM, | ||
| 174 | }, | ||
| 175 | [1] = { | ||
| 176 | .start = PXA_CS1_PHYS, | ||
| 177 | .end = PXA_CS1_PHYS + SZ_64M - 1, | ||
| 178 | .flags = IORESOURCE_MEM, | ||
| 179 | }, | ||
| 180 | }; | ||
| 181 | |||
| 182 | static struct mtd_partition lpd270_flash0_partitions[] = { | ||
| 183 | { | ||
| 184 | .name = "Bootloader", | ||
| 185 | .size = 0x00040000, | ||
| 186 | .offset = 0, | ||
| 187 | .mask_flags = MTD_WRITEABLE /* force read-only */ | ||
| 188 | }, { | ||
| 189 | .name = "Kernel", | ||
| 190 | .size = 0x00400000, | ||
| 191 | .offset = 0x00040000, | ||
| 192 | }, { | ||
| 193 | .name = "Filesystem", | ||
| 194 | .size = MTDPART_SIZ_FULL, | ||
| 195 | .offset = 0x00440000 | ||
| 196 | }, | ||
| 197 | }; | ||
| 198 | |||
| 199 | static struct flash_platform_data lpd270_flash_data[2] = { | ||
| 200 | { | ||
| 201 | .name = "processor-flash", | ||
| 202 | .map_name = "cfi_probe", | ||
| 203 | .parts = lpd270_flash0_partitions, | ||
| 204 | .nr_parts = ARRAY_SIZE(lpd270_flash0_partitions), | ||
| 205 | }, { | ||
| 206 | .name = "mainboard-flash", | ||
| 207 | .map_name = "cfi_probe", | ||
| 208 | .parts = NULL, | ||
| 209 | .nr_parts = 0, | ||
| 210 | } | ||
| 211 | }; | ||
| 212 | |||
| 213 | static struct platform_device lpd270_flash_device[2] = { | ||
| 214 | { | ||
| 215 | .name = "pxa2xx-flash", | ||
| 216 | .id = 0, | ||
| 217 | .dev = { | ||
| 218 | .platform_data = &lpd270_flash_data[0], | ||
| 219 | }, | ||
| 220 | .resource = &lpd270_flash_resources[0], | ||
| 221 | .num_resources = 1, | ||
| 222 | }, { | ||
| 223 | .name = "pxa2xx-flash", | ||
| 224 | .id = 1, | ||
| 225 | .dev = { | ||
| 226 | .platform_data = &lpd270_flash_data[1], | ||
| 227 | }, | ||
| 228 | .resource = &lpd270_flash_resources[1], | ||
| 229 | .num_resources = 1, | ||
| 230 | }, | ||
| 231 | }; | ||
| 232 | |||
| 233 | static void lpd270_backlight_power(int on) | ||
| 234 | { | ||
| 235 | if (on) { | ||
| 236 | pxa_gpio_mode(GPIO16_PWM0_MD); | ||
| 237 | pxa_set_cken(CKEN0_PWM0, 1); | ||
| 238 | PWM_CTRL0 = 0; | ||
| 239 | PWM_PWDUTY0 = 0x3ff; | ||
| 240 | PWM_PERVAL0 = 0x3ff; | ||
| 241 | } else { | ||
| 242 | PWM_CTRL0 = 0; | ||
| 243 | PWM_PWDUTY0 = 0x0; | ||
| 244 | PWM_PERVAL0 = 0x3FF; | ||
| 245 | pxa_set_cken(CKEN0_PWM0, 0); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | /* 5.7" TFT QVGA (LoLo display number 1) */ | ||
| 250 | static struct pxafb_mach_info sharp_lq057q3dc02 __initdata = { | ||
| 251 | .pixclock = 100000, | ||
| 252 | .xres = 240, | ||
| 253 | .yres = 320, | ||
| 254 | .bpp = 16, | ||
| 255 | .hsync_len = 64, | ||
| 256 | .left_margin = 0x27, | ||
| 257 | .right_margin = 0x09, | ||
| 258 | .vsync_len = 0x04, | ||
| 259 | .upper_margin = 0x08, | ||
| 260 | .lower_margin = 0x14, | ||
| 261 | .sync = 0, | ||
| 262 | .lccr0 = 0x07800080, | ||
| 263 | .lccr3 = 0x04400007, | ||
| 264 | .pxafb_backlight_power = lpd270_backlight_power, | ||
| 265 | }; | ||
| 266 | |||
| 267 | /* 6.4" TFT VGA (LoLo display number 5) */ | ||
| 268 | static struct pxafb_mach_info sharp_lq64d343 __initdata = { | ||
| 269 | .pixclock = 20000, | ||
| 270 | .xres = 640, | ||
| 271 | .yres = 480, | ||
| 272 | .bpp = 16, | ||
| 273 | .hsync_len = 49, | ||
| 274 | .left_margin = 0x89, | ||
| 275 | .right_margin = 0x19, | ||
| 276 | .vsync_len = 18, | ||
| 277 | .upper_margin = 0x22, | ||
| 278 | .lower_margin = 0, | ||
| 279 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 280 | .lccr0 = 0x07800080, | ||
| 281 | .lccr3 = 0x04400001, | ||
| 282 | .pxafb_backlight_power = lpd270_backlight_power, | ||
| 283 | }; | ||
| 284 | |||
| 285 | /* 3.5" TFT QVGA (LoLo display number 8) */ | ||
| 286 | static struct pxafb_mach_info sharp_lq035q7db02_20 __initdata = { | ||
| 287 | .pixclock = 100000, | ||
| 288 | .xres = 240, | ||
| 289 | .yres = 320, | ||
| 290 | .bpp = 16, | ||
| 291 | .hsync_len = 0x34, | ||
| 292 | .left_margin = 0x09, | ||
| 293 | .right_margin = 0x09, | ||
| 294 | .vsync_len = 0x08, | ||
| 295 | .upper_margin = 0x05, | ||
| 296 | .lower_margin = 0x14, | ||
| 297 | .sync = 0, | ||
| 298 | .lccr0 = 0x07800080, | ||
| 299 | .lccr3 = 0x04400007, | ||
| 300 | .pxafb_backlight_power = lpd270_backlight_power, | ||
| 301 | }; | ||
| 302 | |||
| 303 | static struct platform_device *platform_devices[] __initdata = { | ||
| 304 | &smc91x_device, | ||
| 305 | &lpd270_audio_device, | ||
| 306 | &lpd270_flash_device[0], | ||
| 307 | &lpd270_flash_device[1], | ||
| 308 | }; | ||
| 309 | |||
| 310 | static int lpd270_ohci_init(struct device *dev) | ||
| 311 | { | ||
| 312 | /* setup Port1 GPIO pin. */ | ||
| 313 | pxa_gpio_mode(88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */ | ||
| 314 | pxa_gpio_mode(89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */ | ||
| 315 | |||
| 316 | /* Set the Power Control Polarity Low and Power Sense | ||
| 317 | Polarity Low to active low. */ | ||
| 318 | UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & | ||
| 319 | ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); | ||
| 320 | |||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | static struct pxaohci_platform_data lpd270_ohci_platform_data = { | ||
| 325 | .port_mode = PMM_PERPORT_MODE, | ||
| 326 | .init = lpd270_ohci_init, | ||
| 327 | }; | ||
| 328 | |||
| 329 | static void __init lpd270_init(void) | ||
| 330 | { | ||
| 331 | lpd270_flash_data[0].width = (BOOT_DEF & 1) ? 2 : 4; | ||
| 332 | lpd270_flash_data[1].width = 4; | ||
| 333 | |||
| 334 | /* | ||
| 335 | * System bus arbiter setting: | ||
| 336 | * - Core_Park | ||
| 337 | * - LCD_wt:DMA_wt:CORE_Wt = 2:3:4 | ||
| 338 | */ | ||
| 339 | ARB_CNTRL = ARB_CORE_PARK | 0x234; | ||
| 340 | |||
| 341 | /* | ||
| 342 | * On LogicPD PXA270, we route AC97_SYSCLK via GPIO45. | ||
| 343 | */ | ||
| 344 | pxa_gpio_mode(GPIO45_SYSCLK_AC97_MD); | ||
| 345 | |||
| 346 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); | ||
| 347 | |||
| 348 | // set_pxa_fb_info(&sharp_lq057q3dc02); | ||
| 349 | set_pxa_fb_info(&sharp_lq64d343); | ||
| 350 | // set_pxa_fb_info(&sharp_lq035q7db02_20); | ||
| 351 | |||
| 352 | pxa_set_ohci_info(&lpd270_ohci_platform_data); | ||
| 353 | } | ||
| 354 | |||
| 355 | |||
| 356 | static struct map_desc lpd270_io_desc[] __initdata = { | ||
| 357 | { | ||
| 358 | .virtual = LPD270_CPLD_VIRT, | ||
| 359 | .pfn = __phys_to_pfn(LPD270_CPLD_PHYS), | ||
| 360 | .length = LPD270_CPLD_SIZE, | ||
| 361 | .type = MT_DEVICE, | ||
| 362 | }, | ||
| 363 | }; | ||
| 364 | |||
| 365 | static void __init lpd270_map_io(void) | ||
| 366 | { | ||
| 367 | pxa_map_io(); | ||
| 368 | iotable_init(lpd270_io_desc, ARRAY_SIZE(lpd270_io_desc)); | ||
| 369 | |||
| 370 | /* initialize sleep mode regs (wake-up sources, etc) */ | ||
| 371 | PGSR0 = 0x00008800; | ||
| 372 | PGSR1 = 0x00000002; | ||
| 373 | PGSR2 = 0x0001FC00; | ||
| 374 | PGSR3 = 0x00001F81; | ||
| 375 | PWER = 0xC0000002; | ||
| 376 | PRER = 0x00000002; | ||
| 377 | PFER = 0x00000002; | ||
| 378 | |||
| 379 | /* for use I SRAM as framebuffer. */ | ||
| 380 | PSLR |= 0x00000F04; | ||
| 381 | PCFR = 0x00000066; | ||
| 382 | } | ||
| 383 | |||
| 384 | MACHINE_START(LOGICPD_PXA270, "LogicPD PXA270 Card Engine") | ||
| 385 | /* Maintainer: Peter Barada */ | ||
| 386 | .phys_io = 0x40000000, | ||
| 387 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, | ||
| 388 | .boot_params = 0xa0000100, | ||
| 389 | .map_io = lpd270_map_io, | ||
| 390 | .init_irq = lpd270_init_irq, | ||
| 391 | .timer = &pxa_timer, | ||
| 392 | .init_machine = lpd270_init, | ||
| 393 | MACHINE_END | ||
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 30ec317bbb97..0dbb079ecd25 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c | |||
| @@ -467,6 +467,8 @@ struct platform_device akitaioexp_device = { | |||
| 467 | .id = -1, | 467 | .id = -1, |
| 468 | }; | 468 | }; |
| 469 | 469 | ||
| 470 | EXPORT_SYMBOL_GPL(akitaioexp_device); | ||
| 471 | |||
| 470 | static void __init akita_init(void) | 472 | static void __init akita_init(void) |
| 471 | { | 473 | { |
| 472 | spitz_ficp_platform_data.transceiver_mode = akita_irda_transceiver_mode; | 474 | spitz_ficp_platform_data.transceiver_mode = akita_irda_transceiver_mode; |
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig index 6923316b3d0d..cd67ab1b217b 100644 --- a/arch/arm/mach-sa1100/Kconfig +++ b/arch/arm/mach-sa1100/Kconfig | |||
| @@ -111,7 +111,7 @@ config SA1100_LART | |||
| 111 | bool "LART" | 111 | bool "LART" |
| 112 | help | 112 | help |
| 113 | Say Y here if you are using the Linux Advanced Radio Terminal | 113 | Say Y here if you are using the Linux Advanced Radio Terminal |
| 114 | (also known as the LART). See <http://www.lart.tudelft.nl/> for | 114 | (also known as the LART). See <http://www.lartmaker.nl/> for |
| 115 | information on the LART. | 115 | information on the LART. |
| 116 | 116 | ||
| 117 | config SA1100_PLEB | 117 | config SA1100_PLEB |
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c index 6435b2e48ffa..d68630b74d78 100644 --- a/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/arch/arm/mach-sa1100/cpu-sa1100.c | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | * linux-2.4.5-rmk1 | 11 | * linux-2.4.5-rmk1 |
| 12 | * | 12 | * |
| 13 | * This software has been developed while working on the LART | 13 | * This software has been developed while working on the LART |
| 14 | * computing board (http://www.lart.tudelft.nl/), which is | 14 | * computing board (http://www.lartmaker.nl/), which is |
| 15 | * sponsored by the Mobile Multi-media Communications | 15 | * sponsored by the Mobile Multi-media Communications |
| 16 | * (http://www.mmc.tudelft.nl/) and Ubiquitous Communications | 16 | * (http://www.mmc.tudelft.nl/) and Ubiquitous Communications |
| 17 | * (http://www.ubicom.tudelft.nl/) projects. | 17 | * (http://www.ubicom.tudelft.nl/) projects. |
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index 2abdc419e984..9ea71551fc04 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c | |||
| @@ -324,6 +324,11 @@ void sa11x0_set_irda_data(struct irda_platform_data *irda) | |||
| 324 | sa11x0ir_device.dev.platform_data = irda; | 324 | sa11x0ir_device.dev.platform_data = irda; |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | static struct platform_device sa11x0rtc_device = { | ||
| 328 | .name = "sa1100-rtc", | ||
| 329 | .id = -1, | ||
| 330 | }; | ||
| 331 | |||
| 327 | static struct platform_device *sa11x0_devices[] __initdata = { | 332 | static struct platform_device *sa11x0_devices[] __initdata = { |
| 328 | &sa11x0udc_device, | 333 | &sa11x0udc_device, |
| 329 | &sa11x0uart1_device, | 334 | &sa11x0uart1_device, |
| @@ -333,6 +338,7 @@ static struct platform_device *sa11x0_devices[] __initdata = { | |||
| 333 | &sa11x0pcmcia_device, | 338 | &sa11x0pcmcia_device, |
| 334 | &sa11x0fb_device, | 339 | &sa11x0fb_device, |
| 335 | &sa11x0mtd_device, | 340 | &sa11x0mtd_device, |
| 341 | &sa11x0rtc_device, | ||
| 336 | }; | 342 | }; |
| 337 | 343 | ||
| 338 | static int __init sa1100_init(void) | 344 | static int __init sa1100_init(void) |
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index e680c5fd93b5..c55b739e10ba 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig | |||
| @@ -239,6 +239,17 @@ config CPU_XSCALE | |||
| 239 | select CPU_CACHE_VIVT | 239 | select CPU_CACHE_VIVT |
| 240 | select CPU_TLB_V4WBI | 240 | select CPU_TLB_V4WBI |
| 241 | 241 | ||
| 242 | # XScale Core Version 3 | ||
| 243 | config CPU_XSC3 | ||
| 244 | bool | ||
| 245 | depends on ARCH_IXP23XX | ||
| 246 | default y | ||
| 247 | select CPU_32v5 | ||
| 248 | select CPU_ABRT_EV5T | ||
| 249 | select CPU_CACHE_VIVT | ||
| 250 | select CPU_TLB_V4WBI | ||
| 251 | select IO_36 | ||
| 252 | |||
| 242 | # ARMv6 | 253 | # ARMv6 |
| 243 | config CPU_V6 | 254 | config CPU_V6 |
| 244 | bool "Support ARM V6 processor" | 255 | bool "Support ARM V6 processor" |
| @@ -361,11 +372,17 @@ config CPU_TLB_V4WBI | |||
| 361 | config CPU_TLB_V6 | 372 | config CPU_TLB_V6 |
| 362 | bool | 373 | bool |
| 363 | 374 | ||
| 375 | # | ||
| 376 | # CPU supports 36-bit I/O | ||
| 377 | # | ||
| 378 | config IO_36 | ||
| 379 | bool | ||
| 380 | |||
| 364 | comment "Processor Features" | 381 | comment "Processor Features" |
| 365 | 382 | ||
| 366 | config ARM_THUMB | 383 | config ARM_THUMB |
| 367 | bool "Support Thumb user binaries" | 384 | bool "Support Thumb user binaries" |
| 368 | depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_V6 | 385 | depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 |
| 369 | default y | 386 | default y |
| 370 | help | 387 | help |
| 371 | Say Y if you want to include kernel support for running user space | 388 | Say Y if you want to include kernel support for running user space |
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile index ffe73ba2bf17..07a538505784 100644 --- a/arch/arm/mm/Makefile +++ b/arch/arm/mm/Makefile | |||
| @@ -30,6 +30,7 @@ obj-$(CONFIG_CPU_COPY_V4WB) += copypage-v4wb.o | |||
| 30 | obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o mmu.o | 30 | obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o mmu.o |
| 31 | obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o | 31 | obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o |
| 32 | obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o | 32 | obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o |
| 33 | obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o | ||
| 33 | 34 | ||
| 34 | obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o | 35 | obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o |
| 35 | obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o | 36 | obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o |
| @@ -51,4 +52,5 @@ obj-$(CONFIG_CPU_ARM1026) += proc-arm1026.o | |||
| 51 | obj-$(CONFIG_CPU_SA110) += proc-sa110.o | 52 | obj-$(CONFIG_CPU_SA110) += proc-sa110.o |
| 52 | obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o | 53 | obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o |
| 53 | obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o | 54 | obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o |
| 55 | obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o | ||
| 54 | obj-$(CONFIG_CPU_V6) += proc-v6.o | 56 | obj-$(CONFIG_CPU_V6) += proc-v6.o |
diff --git a/arch/arm/mm/copypage-xsc3.S b/arch/arm/mm/copypage-xsc3.S new file mode 100644 index 000000000000..9a2cb4332b4c --- /dev/null +++ b/arch/arm/mm/copypage-xsc3.S | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | /* | ||
| 2 | * linux/arch/arm/lib/copypage-xsc3.S | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004 Intel Corp. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Adapted for 3rd gen XScale core, no more mini-dcache | ||
| 11 | * Author: Matt Gilbert (matthew.m.gilbert@intel.com) | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/linkage.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <asm/asm-offsets.h> | ||
| 17 | |||
| 18 | /* | ||
| 19 | * General note: | ||
| 20 | * We don't really want write-allocate cache behaviour for these functions | ||
| 21 | * since that will just eat through 8K of the cache. | ||
| 22 | */ | ||
| 23 | |||
| 24 | .text | ||
| 25 | .align 5 | ||
| 26 | /* | ||
| 27 | * XSC3 optimised copy_user_page | ||
| 28 | * r0 = destination | ||
| 29 | * r1 = source | ||
| 30 | * r2 = virtual user address of ultimate destination page | ||
| 31 | * | ||
| 32 | * The source page may have some clean entries in the cache already, but we | ||
| 33 | * can safely ignore them - break_cow() will flush them out of the cache | ||
| 34 | * if we eventually end up using our copied page. | ||
| 35 | * | ||
| 36 | */ | ||
| 37 | ENTRY(xsc3_mc_copy_user_page) | ||
| 38 | stmfd sp!, {r4, r5, lr} | ||
| 39 | mov lr, #PAGE_SZ/64-1 | ||
| 40 | |||
| 41 | pld [r1, #0] | ||
| 42 | pld [r1, #32] | ||
| 43 | 1: pld [r1, #64] | ||
| 44 | pld [r1, #96] | ||
| 45 | |||
| 46 | 2: ldrd r2, [r1], #8 | ||
| 47 | mov ip, r0 | ||
| 48 | ldrd r4, [r1], #8 | ||
| 49 | mcr p15, 0, ip, c7, c6, 1 @ invalidate | ||
| 50 | strd r2, [r0], #8 | ||
| 51 | ldrd r2, [r1], #8 | ||
| 52 | strd r4, [r0], #8 | ||
| 53 | ldrd r4, [r1], #8 | ||
| 54 | strd r2, [r0], #8 | ||
| 55 | strd r4, [r0], #8 | ||
| 56 | ldrd r2, [r1], #8 | ||
| 57 | mov ip, r0 | ||
| 58 | ldrd r4, [r1], #8 | ||
| 59 | mcr p15, 0, ip, c7, c6, 1 @ invalidate | ||
| 60 | strd r2, [r0], #8 | ||
| 61 | ldrd r2, [r1], #8 | ||
| 62 | subs lr, lr, #1 | ||
| 63 | strd r4, [r0], #8 | ||
| 64 | ldrd r4, [r1], #8 | ||
| 65 | strd r2, [r0], #8 | ||
| 66 | strd r4, [r0], #8 | ||
| 67 | bgt 1b | ||
| 68 | beq 2b | ||
| 69 | |||
| 70 | ldmfd sp!, {r4, r5, pc} | ||
| 71 | |||
| 72 | .align 5 | ||
| 73 | /* | ||
| 74 | * XScale optimised clear_user_page | ||
| 75 | * r0 = destination | ||
| 76 | * r1 = virtual user address of ultimate destination page | ||
| 77 | */ | ||
| 78 | ENTRY(xsc3_mc_clear_user_page) | ||
| 79 | mov r1, #PAGE_SZ/32 | ||
| 80 | mov r2, #0 | ||
| 81 | mov r3, #0 | ||
| 82 | 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate line | ||
| 83 | strd r2, [r0], #8 | ||
| 84 | strd r2, [r0], #8 | ||
| 85 | strd r2, [r0], #8 | ||
| 86 | strd r2, [r0], #8 | ||
| 87 | subs r1, r1, #1 | ||
| 88 | bne 1b | ||
| 89 | mov pc, lr | ||
| 90 | |||
| 91 | __INITDATA | ||
| 92 | |||
| 93 | .type xsc3_mc_user_fns, #object | ||
| 94 | ENTRY(xsc3_mc_user_fns) | ||
| 95 | .long xsc3_mc_clear_user_page | ||
| 96 | .long xsc3_mc_copy_user_page | ||
| 97 | .size xsc3_mc_user_fns, . - xsc3_mc_user_fns | ||
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index ef8d30a185a9..5e5d05bcad50 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c | |||
| @@ -557,7 +557,8 @@ void __init create_mapping(struct map_desc *md) | |||
| 557 | * supersections are only allocated for domain 0 regardless | 557 | * supersections are only allocated for domain 0 regardless |
| 558 | * of the actual domain assignments in use. | 558 | * of the actual domain assignments in use. |
| 559 | */ | 559 | */ |
| 560 | if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) { | 560 | if ((cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3()) |
| 561 | && domain == 0) { | ||
| 561 | /* | 562 | /* |
| 562 | * Align to supersection boundary if !high pages. | 563 | * Align to supersection boundary if !high pages. |
| 563 | * High pages have already been checked for proper | 564 | * High pages have already been checked for proper |
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 9a7e7c096aa9..ee6f15298735 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S | |||
| @@ -21,6 +21,14 @@ | |||
| 21 | 21 | ||
| 22 | #define D_CACHE_LINE_SIZE 32 | 22 | #define D_CACHE_LINE_SIZE 32 |
| 23 | 23 | ||
| 24 | #define TTB_C (1 << 0) | ||
| 25 | #define TTB_S (1 << 1) | ||
| 26 | #define TTB_IMP (1 << 2) | ||
| 27 | #define TTB_RGN_NC (0 << 3) | ||
| 28 | #define TTB_RGN_WBWA (1 << 3) | ||
| 29 | #define TTB_RGN_WT (2 << 3) | ||
| 30 | #define TTB_RGN_WB (3 << 3) | ||
| 31 | |||
| 24 | .macro cpsie, flags | 32 | .macro cpsie, flags |
| 25 | .ifc \flags, f | 33 | .ifc \flags, f |
| 26 | .long 0xf1080040 | 34 | .long 0xf1080040 |
| @@ -115,7 +123,7 @@ ENTRY(cpu_v6_switch_mm) | |||
| 115 | mov r2, #0 | 123 | mov r2, #0 |
| 116 | ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id | 124 | ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id |
| 117 | #ifdef CONFIG_SMP | 125 | #ifdef CONFIG_SMP |
| 118 | orr r0, r0, #2 @ set shared pgtable | 126 | orr r0, r0, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable |
| 119 | #endif | 127 | #endif |
| 120 | mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB | 128 | mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB |
| 121 | mcr p15, 0, r2, c7, c10, 4 @ drain write buffer | 129 | mcr p15, 0, r2, c7, c10, 4 @ drain write buffer |
| @@ -161,8 +169,8 @@ ENTRY(cpu_v6_set_pte) | |||
| 161 | tst r1, #L_PTE_YOUNG | 169 | tst r1, #L_PTE_YOUNG |
| 162 | biceq r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK | 170 | biceq r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK |
| 163 | 171 | ||
| 164 | @ tst r1, #L_PTE_EXEC | 172 | tst r1, #L_PTE_EXEC |
| 165 | @ orreq r2, r2, #PTE_EXT_XN | 173 | orreq r2, r2, #PTE_EXT_XN |
| 166 | 174 | ||
| 167 | tst r1, #L_PTE_PRESENT | 175 | tst r1, #L_PTE_PRESENT |
| 168 | moveq r2, #0 | 176 | moveq r2, #0 |
| @@ -221,7 +229,7 @@ __v6_setup: | |||
| 221 | mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs | 229 | mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs |
| 222 | mcr p15, 0, r0, c2, c0, 2 @ TTB control register | 230 | mcr p15, 0, r0, c2, c0, 2 @ TTB control register |
| 223 | #ifdef CONFIG_SMP | 231 | #ifdef CONFIG_SMP |
| 224 | orr r4, r4, #2 @ set shared pgtable | 232 | orr r4, r4, #TTB_RGN_WBWA|TTB_S @ mark PTWs shared, outer cacheable |
| 225 | #endif | 233 | #endif |
| 226 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 | 234 | mcr p15, 0, r4, c2, c0, 1 @ load TTB1 |
| 227 | #ifdef CONFIG_VFP | 235 | #ifdef CONFIG_VFP |
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S new file mode 100644 index 000000000000..f90513e9af0c --- /dev/null +++ b/arch/arm/mm/proc-xsc3.S | |||
| @@ -0,0 +1,498 @@ | |||
| 1 | /* | ||
| 2 | * linux/arch/arm/mm/proc-xsc3.S | ||
| 3 | * | ||
| 4 | * Original Author: Matthew Gilbert | ||
| 5 | * Current Maintainer: Deepak Saxena <dsaxena@plexity.net> | ||
| 6 | * | ||
| 7 | * Copyright 2004 (C) Intel Corp. | ||
| 8 | * Copyright 2005 (c) MontaVista Software, Inc. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * MMU functions for the Intel XScale3 Core (XSC3). The XSC3 core is an | ||
| 15 | * extension to Intel's original XScale core that adds the following | ||
| 16 | * features: | ||
| 17 | * | ||
| 18 | * - ARMv6 Supersections | ||
| 19 | * - Low Locality Reference pages (replaces mini-cache) | ||
| 20 | * - 36-bit addressing | ||
| 21 | * - L2 cache | ||
| 22 | * - Cache-coherency if chipset supports it | ||
| 23 | * | ||
| 24 | * Based on orignal XScale code by Nicolas Pitre | ||
| 25 | */ | ||
| 26 | |||
| 27 | #include <linux/linkage.h> | ||
| 28 | #include <linux/init.h> | ||
| 29 | #include <asm/assembler.h> | ||
| 30 | #include <asm/procinfo.h> | ||
| 31 | #include <asm/hardware.h> | ||
| 32 | #include <asm/pgtable.h> | ||
| 33 | #include <asm/page.h> | ||
| 34 | #include <asm/ptrace.h> | ||
| 35 | #include "proc-macros.S" | ||
| 36 | |||
| 37 | /* | ||
| 38 | * This is the maximum size of an area which will be flushed. If the | ||
| 39 | * area is larger than this, then we flush the whole cache. | ||
| 40 | */ | ||
| 41 | #define MAX_AREA_SIZE 32768 | ||
| 42 | |||
| 43 | /* | ||
| 44 | * The cache line size of the I and D cache. | ||
| 45 | */ | ||
| 46 | #define CACHELINESIZE 32 | ||
| 47 | |||
| 48 | /* | ||
| 49 | * The size of the data cache. | ||
| 50 | */ | ||
| 51 | #define CACHESIZE 32768 | ||
| 52 | |||
| 53 | /* | ||
| 54 | * Run with L2 enabled. | ||
| 55 | */ | ||
| 56 | #define L2_CACHE_ENABLE 1 | ||
| 57 | |||
| 58 | /* | ||
| 59 | * Enable the Branch Target Buffer (can cause crashes, see erratum #42.) | ||
| 60 | */ | ||
| 61 | #define BTB_ENABLE 0 | ||
| 62 | |||
| 63 | /* | ||
| 64 | * This macro is used to wait for a CP15 write and is needed | ||
| 65 | * when we have to ensure that the last operation to the co-pro | ||
| 66 | * was completed before continuing with operation. | ||
| 67 | */ | ||
| 68 | .macro cpwait_ret, lr, rd | ||
| 69 | mrc p15, 0, \rd, c2, c0, 0 @ arbitrary read of cp15 | ||
| 70 | sub pc, \lr, \rd, LSR #32 @ wait for completion and | ||
| 71 | @ flush instruction pipeline | ||
| 72 | .endm | ||
| 73 | |||
| 74 | /* | ||
| 75 | * This macro cleans & invalidates the entire xsc3 dcache by set & way. | ||
| 76 | */ | ||
| 77 | |||
| 78 | .macro clean_d_cache rd, rs | ||
| 79 | mov \rd, #0x1f00 | ||
| 80 | orr \rd, \rd, #0x00e0 | ||
| 81 | 1: mcr p15, 0, \rd, c7, c14, 2 @ clean/inv set/way | ||
| 82 | adds \rd, \rd, #0x40000000 | ||
| 83 | bcc 1b | ||
| 84 | subs \rd, \rd, #0x20 | ||
| 85 | bpl 1b | ||
| 86 | .endm | ||
| 87 | |||
| 88 | .text | ||
| 89 | |||
| 90 | /* | ||
| 91 | * cpu_xsc3_proc_init() | ||
| 92 | * | ||
| 93 | * Nothing too exciting at the moment | ||
| 94 | */ | ||
| 95 | ENTRY(cpu_xsc3_proc_init) | ||
| 96 | mov pc, lr | ||
| 97 | |||
| 98 | /* | ||
| 99 | * cpu_xsc3_proc_fin() | ||
| 100 | */ | ||
| 101 | ENTRY(cpu_xsc3_proc_fin) | ||
| 102 | str lr, [sp, #-4]! | ||
| 103 | mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE | ||
| 104 | msr cpsr_c, r0 | ||
| 105 | bl xsc3_flush_kern_cache_all @ clean caches | ||
| 106 | mrc p15, 0, r0, c1, c0, 0 @ ctrl register | ||
| 107 | bic r0, r0, #0x1800 @ ...IZ........... | ||
| 108 | bic r0, r0, #0x0006 @ .............CA. | ||
| 109 | mcr p15, 0, r0, c1, c0, 0 @ disable caches | ||
| 110 | ldr pc, [sp], #4 | ||
| 111 | |||
| 112 | /* | ||
| 113 | * cpu_xsc3_reset(loc) | ||
| 114 | * | ||
| 115 | * Perform a soft reset of the system. Put the CPU into the | ||
| 116 | * same state as it would be if it had been reset, and branch | ||
| 117 | * to what would be the reset vector. | ||
| 118 | * | ||
| 119 | * loc: location to jump to for soft reset | ||
| 120 | */ | ||
| 121 | .align 5 | ||
| 122 | ENTRY(cpu_xsc3_reset) | ||
| 123 | mov r1, #PSR_F_BIT|PSR_I_BIT|SVC_MODE | ||
| 124 | msr cpsr_c, r1 @ reset CPSR | ||
| 125 | mrc p15, 0, r1, c1, c0, 0 @ ctrl register | ||
| 126 | bic r1, r1, #0x0086 @ ........B....CA. | ||
| 127 | bic r1, r1, #0x3900 @ ..VIZ..S........ | ||
| 128 | mcr p15, 0, r1, c1, c0, 0 @ ctrl register | ||
| 129 | mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches & BTB | ||
| 130 | bic r1, r1, #0x0001 @ ...............M | ||
| 131 | mcr p15, 0, r1, c1, c0, 0 @ ctrl register | ||
| 132 | @ CAUTION: MMU turned off from this point. We count on the pipeline | ||
| 133 | @ already containing those two last instructions to survive. | ||
| 134 | mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs | ||
| 135 | mov pc, r0 | ||
| 136 | |||
| 137 | /* | ||
| 138 | * cpu_xsc3_do_idle() | ||
| 139 | * | ||
| 140 | * Cause the processor to idle | ||
| 141 | * | ||
| 142 | * For now we do nothing but go to idle mode for every case | ||
| 143 | * | ||
| 144 | * XScale supports clock switching, but using idle mode support | ||
| 145 | * allows external hardware to react to system state changes. | ||
| 146 | |||
| 147 | MMG: Come back to this one. | ||
| 148 | */ | ||
| 149 | .align 5 | ||
| 150 | |||
| 151 | ENTRY(cpu_xsc3_do_idle) | ||
| 152 | mov r0, #1 | ||
| 153 | mcr p14, 0, r0, c7, c0, 0 @ Go to IDLE | ||
| 154 | mov pc, lr | ||
| 155 | |||
| 156 | /* ================================= CACHE ================================ */ | ||
| 157 | |||
| 158 | /* | ||
| 159 | * flush_user_cache_all() | ||
| 160 | * | ||
| 161 | * Invalidate all cache entries in a particular address | ||
| 162 | * space. | ||
| 163 | */ | ||
| 164 | ENTRY(xsc3_flush_user_cache_all) | ||
| 165 | /* FALLTHROUGH */ | ||
| 166 | |||
| 167 | /* | ||
| 168 | * flush_kern_cache_all() | ||
| 169 | * | ||
| 170 | * Clean and invalidate the entire cache. | ||
| 171 | */ | ||
| 172 | ENTRY(xsc3_flush_kern_cache_all) | ||
| 173 | mov r2, #VM_EXEC | ||
| 174 | mov ip, #0 | ||
| 175 | __flush_whole_cache: | ||
| 176 | clean_d_cache r0, r1 | ||
| 177 | tst r2, #VM_EXEC | ||
| 178 | mcrne p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB | ||
| 179 | mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer | ||
| 180 | mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush | ||
| 181 | mov pc, lr | ||
| 182 | |||
| 183 | /* | ||
| 184 | * flush_user_cache_range(start, end, vm_flags) | ||
| 185 | * | ||
| 186 | * Invalidate a range of cache entries in the specified | ||
| 187 | * address space. | ||
| 188 | * | ||
| 189 | * - start - start address (may not be aligned) | ||
| 190 | * - end - end address (exclusive, may not be aligned) | ||
| 191 | * - vma - vma_area_struct describing address space | ||
| 192 | */ | ||
| 193 | .align 5 | ||
| 194 | ENTRY(xsc3_flush_user_cache_range) | ||
| 195 | mov ip, #0 | ||
| 196 | sub r3, r1, r0 @ calculate total size | ||
| 197 | cmp r3, #MAX_AREA_SIZE | ||
| 198 | bhs __flush_whole_cache | ||
| 199 | |||
| 200 | 1: tst r2, #VM_EXEC | ||
| 201 | mcrne p15, 0, r0, c7, c5, 1 @ Invalidate I cache line | ||
| 202 | mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate D cache line | ||
| 203 | add r0, r0, #CACHELINESIZE | ||
| 204 | cmp r0, r1 | ||
| 205 | blo 1b | ||
| 206 | tst r2, #VM_EXEC | ||
| 207 | mcrne p15, 0, ip, c7, c5, 6 @ Invalidate BTB | ||
| 208 | mcrne p15, 0, ip, c7, c10, 4 @ Drain Write Buffer | ||
| 209 | mcrne p15, 0, ip, c7, c5, 4 @ Prefetch Flush | ||
| 210 | mov pc, lr | ||
| 211 | |||
| 212 | /* | ||
| 213 | * coherent_kern_range(start, end) | ||
| 214 | * | ||
| 215 | * Ensure coherency between the Icache and the Dcache in the | ||
| 216 | * region described by start. If you have non-snooping | ||
| 217 | * Harvard caches, you need to implement this function. | ||
| 218 | * | ||
| 219 | * - start - virtual start address | ||
| 220 | * - end - virtual end address | ||
| 221 | * | ||
| 222 | * Note: single I-cache line invalidation isn't used here since | ||
| 223 | * it also trashes the mini I-cache used by JTAG debuggers. | ||
| 224 | */ | ||
| 225 | ENTRY(xsc3_coherent_kern_range) | ||
| 226 | /* FALLTHROUGH */ | ||
| 227 | ENTRY(xsc3_coherent_user_range) | ||
| 228 | bic r0, r0, #CACHELINESIZE - 1 | ||
| 229 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry | ||
| 230 | add r0, r0, #CACHELINESIZE | ||
| 231 | cmp r0, r1 | ||
| 232 | blo 1b | ||
| 233 | mov r0, #0 | ||
| 234 | mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB | ||
| 235 | mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer | ||
| 236 | mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush | ||
| 237 | mov pc, lr | ||
| 238 | |||
| 239 | /* | ||
| 240 | * flush_kern_dcache_page(void *page) | ||
| 241 | * | ||
| 242 | * Ensure no D cache aliasing occurs, either with itself or | ||
| 243 | * the I cache | ||
| 244 | * | ||
| 245 | * - addr - page aligned address | ||
| 246 | */ | ||
| 247 | ENTRY(xsc3_flush_kern_dcache_page) | ||
| 248 | add r1, r0, #PAGE_SZ | ||
| 249 | 1: mcr p15, 0, r0, c7, c14, 1 @ Clean/Invalidate D Cache line | ||
| 250 | add r0, r0, #CACHELINESIZE | ||
| 251 | cmp r0, r1 | ||
| 252 | blo 1b | ||
| 253 | mov r0, #0 | ||
| 254 | mcr p15, 0, r0, c7, c5, 0 @ Invalidate I cache & BTB | ||
| 255 | mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer | ||
| 256 | mcr p15, 0, r0, c7, c5, 4 @ Prefetch Flush | ||
| 257 | mov pc, lr | ||
| 258 | |||
| 259 | /* | ||
| 260 | * dma_inv_range(start, end) | ||
| 261 | * | ||
| 262 | * Invalidate (discard) the specified virtual address range. | ||
| 263 | * May not write back any entries. If 'start' or 'end' | ||
| 264 | * are not cache line aligned, those lines must be written | ||
| 265 | * back. | ||
| 266 | * | ||
| 267 | * - start - virtual start address | ||
| 268 | * - end - virtual end address | ||
| 269 | */ | ||
| 270 | ENTRY(xsc3_dma_inv_range) | ||
| 271 | tst r0, #CACHELINESIZE - 1 | ||
| 272 | bic r0, r0, #CACHELINESIZE - 1 | ||
| 273 | mcrne p15, 0, r0, c7, c10, 1 @ clean L1 D entry | ||
| 274 | mcrne p15, 1, r0, c7, c11, 1 @ clean L2 D entry | ||
| 275 | tst r1, #CACHELINESIZE - 1 | ||
| 276 | mcrne p15, 0, r1, c7, c10, 1 @ clean L1 D entry | ||
| 277 | mcrne p15, 1, r1, c7, c11, 1 @ clean L2 D entry | ||
| 278 | 1: mcr p15, 0, r0, c7, c6, 1 @ invalidate L1 D entry | ||
| 279 | mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line | ||
| 280 | add r0, r0, #CACHELINESIZE | ||
| 281 | cmp r0, r1 | ||
| 282 | blo 1b | ||
| 283 | mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer | ||
| 284 | mov pc, lr | ||
| 285 | |||
| 286 | /* | ||
| 287 | * dma_clean_range(start, end) | ||
| 288 | * | ||
| 289 | * Clean the specified virtual address range. | ||
| 290 | * | ||
| 291 | * - start - virtual start address | ||
| 292 | * - end - virtual end address | ||
| 293 | */ | ||
| 294 | ENTRY(xsc3_dma_clean_range) | ||
| 295 | bic r0, r0, #CACHELINESIZE - 1 | ||
| 296 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean L1 D entry | ||
| 297 | mcr p15, 1, r0, c7, c11, 1 @ clean L2 D entry | ||
| 298 | add r0, r0, #CACHELINESIZE | ||
| 299 | cmp r0, r1 | ||
| 300 | blo 1b | ||
| 301 | mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer | ||
| 302 | mov pc, lr | ||
| 303 | |||
| 304 | /* | ||
| 305 | * dma_flush_range(start, end) | ||
| 306 | * | ||
| 307 | * Clean and invalidate the specified virtual address range. | ||
| 308 | * | ||
| 309 | * - start - virtual start address | ||
| 310 | * - end - virtual end address | ||
| 311 | */ | ||
| 312 | ENTRY(xsc3_dma_flush_range) | ||
| 313 | bic r0, r0, #CACHELINESIZE - 1 | ||
| 314 | 1: mcr p15, 0, r0, c7, c14, 1 @ Clean/invalidate L1 D cache line | ||
| 315 | mcr p15, 1, r0, c7, c11, 1 @ Clean L2 D cache line | ||
| 316 | mcr p15, 1, r0, c7, c7, 1 @ Invalidate L2 D cache line | ||
| 317 | add r0, r0, #CACHELINESIZE | ||
| 318 | cmp r0, r1 | ||
| 319 | blo 1b | ||
| 320 | mcr p15, 0, r0, c7, c10, 4 @ Drain Write Buffer | ||
| 321 | mov pc, lr | ||
| 322 | |||
| 323 | ENTRY(xsc3_cache_fns) | ||
| 324 | .long xsc3_flush_kern_cache_all | ||
| 325 | .long xsc3_flush_user_cache_all | ||
| 326 | .long xsc3_flush_user_cache_range | ||
| 327 | .long xsc3_coherent_kern_range | ||
| 328 | .long xsc3_coherent_user_range | ||
| 329 | .long xsc3_flush_kern_dcache_page | ||
| 330 | .long xsc3_dma_inv_range | ||
| 331 | .long xsc3_dma_clean_range | ||
| 332 | .long xsc3_dma_flush_range | ||
| 333 | |||
| 334 | ENTRY(cpu_xsc3_dcache_clean_area) | ||
| 335 | 1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry | ||
| 336 | add r0, r0, #CACHELINESIZE | ||
| 337 | subs r1, r1, #CACHELINESIZE | ||
| 338 | bhi 1b | ||
| 339 | mov pc, lr | ||
| 340 | |||
| 341 | /* =============================== PageTable ============================== */ | ||
| 342 | |||
| 343 | /* | ||
| 344 | * cpu_xsc3_switch_mm(pgd) | ||
| 345 | * | ||
| 346 | * Set the translation base pointer to be as described by pgd. | ||
| 347 | * | ||
| 348 | * pgd: new page tables | ||
| 349 | */ | ||
| 350 | .align 5 | ||
| 351 | ENTRY(cpu_xsc3_switch_mm) | ||
| 352 | clean_d_cache r1, r2 | ||
| 353 | mcr p15, 0, ip, c7, c5, 0 @ Invalidate I cache & BTB | ||
| 354 | mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer | ||
| 355 | mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush | ||
| 356 | #ifdef L2_CACHE_ENABLE | ||
| 357 | orr r0, r0, #0x18 @ cache the page table in L2 | ||
| 358 | #endif | ||
| 359 | mcr p15, 0, r0, c2, c0, 0 @ load page table pointer | ||
| 360 | mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs | ||
| 361 | cpwait_ret lr, ip | ||
| 362 | |||
| 363 | /* | ||
| 364 | * cpu_xsc3_set_pte(ptep, pte) | ||
| 365 | * | ||
| 366 | * Set a PTE and flush it out | ||
| 367 | * | ||
| 368 | */ | ||
| 369 | .align 5 | ||
| 370 | ENTRY(cpu_xsc3_set_pte) | ||
| 371 | str r1, [r0], #-2048 @ linux version | ||
| 372 | |||
| 373 | bic r2, r1, #0xff0 | ||
| 374 | orr r2, r2, #PTE_TYPE_EXT @ extended page | ||
| 375 | |||
| 376 | eor r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY | ||
| 377 | |||
| 378 | tst r3, #L_PTE_USER @ User? | ||
| 379 | orrne r2, r2, #PTE_EXT_AP_URO_SRW @ yes -> user r/o, system r/w | ||
| 380 | |||
| 381 | tst r3, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty? | ||
| 382 | orreq r2, r2, #PTE_EXT_AP_UNO_SRW @ yes -> user n/a, system r/w | ||
| 383 | @ combined with user -> user r/w | ||
| 384 | |||
| 385 | #if L2_CACHE_ENABLE | ||
| 386 | @ If its cacheable it needs to be in L2 also. | ||
| 387 | eor ip, r1, #L_PTE_CACHEABLE | ||
| 388 | tst ip, #L_PTE_CACHEABLE | ||
| 389 | orreq r2, r2, #PTE_EXT_TEX(0x5) | ||
| 390 | #endif | ||
| 391 | |||
| 392 | tst r3, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young? | ||
| 393 | movne r2, #0 @ no -> fault | ||
| 394 | |||
| 395 | str r2, [r0] @ hardware version | ||
| 396 | mov ip, #0 | ||
| 397 | mcr p15, 0, r0, c7, c10, 1 @ Clean D cache line mcr | ||
| 398 | mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer | ||
| 399 | mov pc, lr | ||
| 400 | |||
| 401 | .ltorg | ||
| 402 | |||
| 403 | .align | ||
| 404 | |||
| 405 | __INIT | ||
| 406 | |||
| 407 | .type __xsc3_setup, #function | ||
| 408 | __xsc3_setup: | ||
| 409 | mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE | ||
| 410 | msr cpsr_c, r0 | ||
| 411 | mcr p15, 0, ip, c7, c7, 0 @ invalidate I, D caches & BTB | ||
| 412 | mcr p15, 0, ip, c7, c10, 4 @ Drain Write Buffer | ||
| 413 | mcr p15, 0, ip, c7, c5, 4 @ Prefetch Flush | ||
| 414 | mcr p15, 0, ip, c8, c7, 0 @ invalidate I, D TLBs | ||
| 415 | #if L2_CACHE_ENABLE | ||
| 416 | orr r4, r4, #0x18 @ cache the page table in L2 | ||
| 417 | #endif | ||
| 418 | mcr p15, 0, r4, c2, c0, 0 @ load page table pointer | ||
| 419 | mov r0, #1 @ Allow access to CP0 and CP13 | ||
| 420 | orr r0, r0, #1 << 13 @ Its undefined whether this | ||
| 421 | mcr p15, 0, r0, c15, c1, 0 @ affects USR or SVC modes | ||
| 422 | mrc p15, 0, r0, c1, c0, 1 @ get auxiliary control reg | ||
| 423 | and r0, r0, #2 @ preserve bit P bit setting | ||
| 424 | #if L2_CACHE_ENABLE | ||
| 425 | orr r0, r0, #(1 << 10) @ enable L2 for LLR cache | ||
| 426 | #endif | ||
| 427 | mcr p15, 0, r0, c1, c0, 1 @ set auxiliary control reg | ||
| 428 | mrc p15, 0, r0, c1, c0, 0 @ get control register | ||
| 429 | bic r0, r0, #0x0200 @ .... ..R. .... .... | ||
| 430 | bic r0, r0, #0x0002 @ .... .... .... ..A. | ||
| 431 | orr r0, r0, #0x0005 @ .... .... .... .C.M | ||
| 432 | #if BTB_ENABLE | ||
| 433 | orr r0, r0, #0x3900 @ ..VI Z..S .... .... | ||
| 434 | #else | ||
| 435 | orr r0, r0, #0x3100 @ ..VI ...S .... .... | ||
| 436 | #endif | ||
| 437 | #if L2_CACHE_ENABLE | ||
| 438 | orr r0, r0, #0x4000000 @ L2 enable | ||
| 439 | #endif | ||
| 440 | mov pc, lr | ||
| 441 | |||
| 442 | .size __xsc3_setup, . - __xsc3_setup | ||
| 443 | |||
| 444 | __INITDATA | ||
| 445 | |||
| 446 | /* | ||
| 447 | * Purpose : Function pointers used to access above functions - all calls | ||
| 448 | * come through these | ||
| 449 | */ | ||
| 450 | |||
| 451 | .type xsc3_processor_functions, #object | ||
| 452 | ENTRY(xsc3_processor_functions) | ||
| 453 | .word v5t_early_abort | ||
| 454 | .word cpu_xsc3_proc_init | ||
| 455 | .word cpu_xsc3_proc_fin | ||
| 456 | .word cpu_xsc3_reset | ||
| 457 | .word cpu_xsc3_do_idle | ||
| 458 | .word cpu_xsc3_dcache_clean_area | ||
| 459 | .word cpu_xsc3_switch_mm | ||
| 460 | .word cpu_xsc3_set_pte | ||
| 461 | .size xsc3_processor_functions, . - xsc3_processor_functions | ||
| 462 | |||
| 463 | .section ".rodata" | ||
| 464 | |||
| 465 | .type cpu_arch_name, #object | ||
| 466 | cpu_arch_name: | ||
| 467 | .asciz "armv5te" | ||
| 468 | .size cpu_arch_name, . - cpu_arch_name | ||
| 469 | |||
| 470 | .type cpu_elf_name, #object | ||
| 471 | cpu_elf_name: | ||
| 472 | .asciz "v5" | ||
| 473 | .size cpu_elf_name, . - cpu_elf_name | ||
| 474 | |||
| 475 | .type cpu_xsc3_name, #object | ||
| 476 | cpu_xsc3_name: | ||
| 477 | .asciz "XScale-Core3" | ||
| 478 | .size cpu_xsc3_name, . - cpu_xsc3_name | ||
| 479 | |||
| 480 | .align | ||
| 481 | |||
| 482 | .section ".proc.info.init", #alloc, #execinstr | ||
| 483 | |||
| 484 | .type __xsc3_proc_info,#object | ||
| 485 | __xsc3_proc_info: | ||
| 486 | .long 0x69056000 | ||
| 487 | .long 0xffffe000 | ||
| 488 | .long 0x00000c0e | ||
| 489 | b __xsc3_setup | ||
| 490 | .long cpu_arch_name | ||
| 491 | .long cpu_elf_name | ||
| 492 | .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP | ||
| 493 | .long cpu_xsc3_name | ||
| 494 | .long xsc3_processor_functions | ||
| 495 | .long v4wbi_tlb_fns | ||
| 496 | .long xsc3_mc_user_fns | ||
| 497 | .long xsc3_cache_fns | ||
| 498 | .size __xsc3_proc_info, . - __xsc3_proc_info | ||
diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c index e3ecaa453747..7da8a5205678 100644 --- a/arch/arm26/mm/init.c +++ b/arch/arm26/mm/init.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/initrd.h> | 23 | #include <linux/initrd.h> |
| 24 | #include <linux/bootmem.h> | 24 | #include <linux/bootmem.h> |
| 25 | #include <linux/blkdev.h> | 25 | #include <linux/blkdev.h> |
| 26 | #include <linux/pfn.h> | ||
| 26 | 27 | ||
| 27 | #include <asm/segment.h> | 28 | #include <asm/segment.h> |
| 28 | #include <asm/mach-types.h> | 29 | #include <asm/mach-types.h> |
| @@ -101,12 +102,6 @@ struct node_info { | |||
| 101 | int bootmap_pages; | 102 | int bootmap_pages; |
| 102 | }; | 103 | }; |
| 103 | 104 | ||
| 104 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
| 105 | #define PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT) | ||
| 106 | #define PFN_SIZE(x) ((x) >> PAGE_SHIFT) | ||
| 107 | #define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \ | ||
| 108 | (((unsigned long)(s)) & PAGE_MASK)) | ||
| 109 | |||
| 110 | /* | 105 | /* |
| 111 | * FIXME: We really want to avoid allocating the bootmap bitmap | 106 | * FIXME: We really want to avoid allocating the bootmap bitmap |
| 112 | * over the top of the initrd. Hopefully, this is located towards | 107 | * over the top of the initrd. Hopefully, this is located towards |
diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c index 1ba57efff60d..619a6eefd893 100644 --- a/arch/cris/kernel/setup.c +++ b/arch/cris/kernel/setup.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/seq_file.h> | 18 | #include <linux/seq_file.h> |
| 19 | #include <linux/tty.h> | 19 | #include <linux/tty.h> |
| 20 | #include <linux/utsname.h> | 20 | #include <linux/utsname.h> |
| 21 | #include <linux/pfn.h> | ||
| 21 | 22 | ||
| 22 | #include <asm/setup.h> | 23 | #include <asm/setup.h> |
| 23 | 24 | ||
| @@ -88,10 +89,6 @@ setup_arch(char **cmdline_p) | |||
| 88 | init_mm.end_data = (unsigned long) &_edata; | 89 | init_mm.end_data = (unsigned long) &_edata; |
| 89 | init_mm.brk = (unsigned long) &_end; | 90 | init_mm.brk = (unsigned long) &_end; |
| 90 | 91 | ||
| 91 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | ||
| 92 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
| 93 | #define PFN_PHYS(x) ((x) << PAGE_SHIFT) | ||
| 94 | |||
| 95 | /* min_low_pfn points to the start of DRAM, start_pfn points | 92 | /* min_low_pfn points to the start of DRAM, start_pfn points |
| 96 | * to the first DRAM pages after the kernel, and max_low_pfn | 93 | * to the first DRAM pages after the kernel, and max_low_pfn |
| 97 | * to the end of DRAM. | 94 | * to the end of DRAM. |
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index f7db71d0b913..f17bd1d2707e 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
| @@ -231,6 +231,15 @@ config SCHED_SMT | |||
| 231 | cost of slightly increased overhead in some places. If unsure say | 231 | cost of slightly increased overhead in some places. If unsure say |
| 232 | N here. | 232 | N here. |
| 233 | 233 | ||
| 234 | config SCHED_MC | ||
| 235 | bool "Multi-core scheduler support" | ||
| 236 | depends on SMP | ||
| 237 | default y | ||
| 238 | help | ||
| 239 | Multi-core scheduler support improves the CPU scheduler's decision | ||
| 240 | making when dealing with multi-core CPU chips at a cost of slightly | ||
| 241 | increased overhead in some places. If unsure say N here. | ||
| 242 | |||
| 234 | source "kernel/Kconfig.preempt" | 243 | source "kernel/Kconfig.preempt" |
| 235 | 244 | ||
| 236 | config X86_UP_APIC | 245 | config X86_UP_APIC |
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S index 2ac40c8244c4..0000a2674537 100644 --- a/arch/i386/boot/video.S +++ b/arch/i386/boot/video.S | |||
| @@ -1924,6 +1924,7 @@ skip10: movb %ah, %al | |||
| 1924 | ret | 1924 | ret |
| 1925 | 1925 | ||
| 1926 | store_edid: | 1926 | store_edid: |
| 1927 | #ifdef CONFIG_FB_FIRMWARE_EDID | ||
| 1927 | pushw %es # just save all registers | 1928 | pushw %es # just save all registers |
| 1928 | pushw %ax | 1929 | pushw %ax |
| 1929 | pushw %bx | 1930 | pushw %bx |
| @@ -1954,6 +1955,7 @@ store_edid: | |||
| 1954 | popw %bx | 1955 | popw %bx |
| 1955 | popw %ax | 1956 | popw %ax |
| 1956 | popw %es | 1957 | popw %es |
| 1958 | #endif | ||
| 1957 | ret | 1959 | ret |
| 1958 | 1960 | ||
| 1959 | # VIDEO_SELECT-only variables | 1961 | # VIDEO_SELECT-only variables |
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 7e3d6b6a4e96..a06a49075f10 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c | |||
| @@ -266,7 +266,7 @@ static void __init early_cpu_detect(void) | |||
| 266 | void __cpuinit generic_identify(struct cpuinfo_x86 * c) | 266 | void __cpuinit generic_identify(struct cpuinfo_x86 * c) |
| 267 | { | 267 | { |
| 268 | u32 tfms, xlvl; | 268 | u32 tfms, xlvl; |
| 269 | int junk; | 269 | int ebx; |
| 270 | 270 | ||
| 271 | if (have_cpuid_p()) { | 271 | if (have_cpuid_p()) { |
| 272 | /* Get vendor name */ | 272 | /* Get vendor name */ |
| @@ -282,7 +282,7 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c) | |||
| 282 | /* Intel-defined flags: level 0x00000001 */ | 282 | /* Intel-defined flags: level 0x00000001 */ |
| 283 | if ( c->cpuid_level >= 0x00000001 ) { | 283 | if ( c->cpuid_level >= 0x00000001 ) { |
| 284 | u32 capability, excap; | 284 | u32 capability, excap; |
| 285 | cpuid(0x00000001, &tfms, &junk, &excap, &capability); | 285 | cpuid(0x00000001, &tfms, &ebx, &excap, &capability); |
| 286 | c->x86_capability[0] = capability; | 286 | c->x86_capability[0] = capability; |
| 287 | c->x86_capability[4] = excap; | 287 | c->x86_capability[4] = excap; |
| 288 | c->x86 = (tfms >> 8) & 15; | 288 | c->x86 = (tfms >> 8) & 15; |
| @@ -292,6 +292,11 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c) | |||
| 292 | if (c->x86 >= 0x6) | 292 | if (c->x86 >= 0x6) |
| 293 | c->x86_model += ((tfms >> 16) & 0xF) << 4; | 293 | c->x86_model += ((tfms >> 16) & 0xF) << 4; |
| 294 | c->x86_mask = tfms & 15; | 294 | c->x86_mask = tfms & 15; |
| 295 | #ifdef CONFIG_SMP | ||
| 296 | c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0); | ||
| 297 | #else | ||
| 298 | c->apicid = (ebx >> 24) & 0xFF; | ||
| 299 | #endif | ||
| 295 | } else { | 300 | } else { |
| 296 | /* Have CPUID level 0 only - unheard of */ | 301 | /* Have CPUID level 0 only - unheard of */ |
| 297 | c->x86 = 4; | 302 | c->x86 = 4; |
| @@ -474,7 +479,6 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) | |||
| 474 | 479 | ||
| 475 | cpuid(1, &eax, &ebx, &ecx, &edx); | 480 | cpuid(1, &eax, &ebx, &ecx, &edx); |
| 476 | 481 | ||
| 477 | c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0); | ||
| 478 | 482 | ||
| 479 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) | 483 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) |
| 480 | return; | 484 | return; |
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 1e70823e1cb5..712a26bd4457 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c | |||
| @@ -1095,10 +1095,15 @@ static int __devexit powernowk8_cpu_exit (struct cpufreq_policy *pol) | |||
| 1095 | 1095 | ||
| 1096 | static unsigned int powernowk8_get (unsigned int cpu) | 1096 | static unsigned int powernowk8_get (unsigned int cpu) |
| 1097 | { | 1097 | { |
| 1098 | struct powernow_k8_data *data = powernow_data[cpu]; | 1098 | struct powernow_k8_data *data; |
| 1099 | cpumask_t oldmask = current->cpus_allowed; | 1099 | cpumask_t oldmask = current->cpus_allowed; |
| 1100 | unsigned int khz = 0; | 1100 | unsigned int khz = 0; |
| 1101 | 1101 | ||
| 1102 | data = powernow_data[first_cpu(cpu_core_map[cpu])]; | ||
| 1103 | |||
| 1104 | if (!data) | ||
| 1105 | return -EINVAL; | ||
| 1106 | |||
| 1102 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); | 1107 | set_cpus_allowed(current, cpumask_of_cpu(cpu)); |
| 1103 | if (smp_processor_id() != cpu) { | 1108 | if (smp_processor_id() != cpu) { |
| 1104 | printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu); | 1109 | printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu); |
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index 00ea899c17e1..79a7c5c87edc 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h | |||
| @@ -182,10 +182,6 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid); | |||
| 182 | 182 | ||
| 183 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index); | 183 | static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index); |
| 184 | 184 | ||
| 185 | #ifndef for_each_cpu_mask | ||
| 186 | #define for_each_cpu_mask(i,mask) for (i=0;i<1;i++) | ||
| 187 | #endif | ||
| 188 | |||
| 189 | #ifdef CONFIG_SMP | 185 | #ifdef CONFIG_SMP |
| 190 | static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[]) | 186 | static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[]) |
| 191 | { | 187 | { |
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c index ce61921369e5..9df87b03612c 100644 --- a/arch/i386/kernel/cpu/intel_cacheinfo.c +++ b/arch/i386/kernel/cpu/intel_cacheinfo.c | |||
| @@ -173,6 +173,10 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) | |||
| 173 | unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */ | 173 | unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */ |
| 174 | unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */ | 174 | unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */ |
| 175 | unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */ | 175 | unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */ |
| 176 | unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb; | ||
| 177 | #ifdef CONFIG_SMP | ||
| 178 | unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data); | ||
| 179 | #endif | ||
| 176 | 180 | ||
| 177 | if (c->cpuid_level > 3) { | 181 | if (c->cpuid_level > 3) { |
| 178 | static int is_initialized; | 182 | static int is_initialized; |
| @@ -205,9 +209,15 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) | |||
| 205 | break; | 209 | break; |
| 206 | case 2: | 210 | case 2: |
| 207 | new_l2 = this_leaf.size/1024; | 211 | new_l2 = this_leaf.size/1024; |
| 212 | num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing; | ||
| 213 | index_msb = get_count_order(num_threads_sharing); | ||
| 214 | l2_id = c->apicid >> index_msb; | ||
| 208 | break; | 215 | break; |
| 209 | case 3: | 216 | case 3: |
| 210 | new_l3 = this_leaf.size/1024; | 217 | new_l3 = this_leaf.size/1024; |
| 218 | num_threads_sharing = 1 + this_leaf.eax.split.num_threads_sharing; | ||
| 219 | index_msb = get_count_order(num_threads_sharing); | ||
| 220 | l3_id = c->apicid >> index_msb; | ||
| 211 | break; | 221 | break; |
| 212 | default: | 222 | default: |
| 213 | break; | 223 | break; |
| @@ -215,11 +225,19 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) | |||
| 215 | } | 225 | } |
| 216 | } | 226 | } |
| 217 | } | 227 | } |
| 218 | if (c->cpuid_level > 1) { | 228 | /* |
| 229 | * Don't use cpuid2 if cpuid4 is supported. For P4, we use cpuid2 for | ||
| 230 | * trace cache | ||
| 231 | */ | ||
| 232 | if ((num_cache_leaves == 0 || c->x86 == 15) && c->cpuid_level > 1) { | ||
| 219 | /* supports eax=2 call */ | 233 | /* supports eax=2 call */ |
| 220 | int i, j, n; | 234 | int i, j, n; |
| 221 | int regs[4]; | 235 | int regs[4]; |
| 222 | unsigned char *dp = (unsigned char *)regs; | 236 | unsigned char *dp = (unsigned char *)regs; |
| 237 | int only_trace = 0; | ||
| 238 | |||
| 239 | if (num_cache_leaves != 0 && c->x86 == 15) | ||
| 240 | only_trace = 1; | ||
| 223 | 241 | ||
| 224 | /* Number of times to iterate */ | 242 | /* Number of times to iterate */ |
| 225 | n = cpuid_eax(2) & 0xFF; | 243 | n = cpuid_eax(2) & 0xFF; |
| @@ -241,6 +259,8 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) | |||
| 241 | while (cache_table[k].descriptor != 0) | 259 | while (cache_table[k].descriptor != 0) |
| 242 | { | 260 | { |
| 243 | if (cache_table[k].descriptor == des) { | 261 | if (cache_table[k].descriptor == des) { |
| 262 | if (only_trace && cache_table[k].cache_type != LVL_TRACE) | ||
| 263 | break; | ||
| 244 | switch (cache_table[k].cache_type) { | 264 | switch (cache_table[k].cache_type) { |
| 245 | case LVL_1_INST: | 265 | case LVL_1_INST: |
| 246 | l1i += cache_table[k].size; | 266 | l1i += cache_table[k].size; |
| @@ -266,34 +286,45 @@ unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) | |||
| 266 | } | 286 | } |
| 267 | } | 287 | } |
| 268 | } | 288 | } |
| 289 | } | ||
| 269 | 290 | ||
| 270 | if (new_l1d) | 291 | if (new_l1d) |
| 271 | l1d = new_l1d; | 292 | l1d = new_l1d; |
| 272 | 293 | ||
| 273 | if (new_l1i) | 294 | if (new_l1i) |
| 274 | l1i = new_l1i; | 295 | l1i = new_l1i; |
| 275 | 296 | ||
| 276 | if (new_l2) | 297 | if (new_l2) { |
| 277 | l2 = new_l2; | 298 | l2 = new_l2; |
| 299 | #ifdef CONFIG_SMP | ||
| 300 | cpu_llc_id[cpu] = l2_id; | ||
| 301 | #endif | ||
| 302 | } | ||
| 278 | 303 | ||
| 279 | if (new_l3) | 304 | if (new_l3) { |
| 280 | l3 = new_l3; | 305 | l3 = new_l3; |
| 306 | #ifdef CONFIG_SMP | ||
| 307 | cpu_llc_id[cpu] = l3_id; | ||
| 308 | #endif | ||
| 309 | } | ||
| 281 | 310 | ||
| 282 | if ( trace ) | 311 | if (trace) |
| 283 | printk (KERN_INFO "CPU: Trace cache: %dK uops", trace); | 312 | printk (KERN_INFO "CPU: Trace cache: %dK uops", trace); |
| 284 | else if ( l1i ) | 313 | else if ( l1i ) |
| 285 | printk (KERN_INFO "CPU: L1 I cache: %dK", l1i); | 314 | printk (KERN_INFO "CPU: L1 I cache: %dK", l1i); |
| 286 | if ( l1d ) | ||
| 287 | printk(", L1 D cache: %dK\n", l1d); | ||
| 288 | else | ||
| 289 | printk("\n"); | ||
| 290 | if ( l2 ) | ||
| 291 | printk(KERN_INFO "CPU: L2 cache: %dK\n", l2); | ||
| 292 | if ( l3 ) | ||
| 293 | printk(KERN_INFO "CPU: L3 cache: %dK\n", l3); | ||
| 294 | 315 | ||
| 295 | c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d)); | 316 | if (l1d) |
| 296 | } | 317 | printk(", L1 D cache: %dK\n", l1d); |
| 318 | else | ||
| 319 | printk("\n"); | ||
| 320 | |||
| 321 | if (l2) | ||
| 322 | printk(KERN_INFO "CPU: L2 cache: %dK\n", l2); | ||
| 323 | |||
| 324 | if (l3) | ||
| 325 | printk(KERN_INFO "CPU: L3 cache: %dK\n", l3); | ||
| 326 | |||
| 327 | c->x86_cache_size = l3 ? l3 : (l2 ? l2 : (l1i+l1d)); | ||
| 297 | 328 | ||
| 298 | return l2; | 329 | return l2; |
| 299 | } | 330 | } |
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 311b4e7266f1..3b329af4afc5 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
| @@ -381,7 +381,7 @@ static void do_irq_balance(void) | |||
| 381 | unsigned long imbalance = 0; | 381 | unsigned long imbalance = 0; |
| 382 | cpumask_t allowed_mask, target_cpu_mask, tmp; | 382 | cpumask_t allowed_mask, target_cpu_mask, tmp; |
| 383 | 383 | ||
| 384 | for_each_cpu(i) { | 384 | for_each_possible_cpu(i) { |
| 385 | int package_index; | 385 | int package_index; |
| 386 | CPU_IRQ(i) = 0; | 386 | CPU_IRQ(i) = 0; |
| 387 | if (!cpu_online(i)) | 387 | if (!cpu_online(i)) |
| @@ -632,7 +632,7 @@ static int __init balanced_irq_init(void) | |||
| 632 | else | 632 | else |
| 633 | printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq"); | 633 | printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq"); |
| 634 | failed: | 634 | failed: |
| 635 | for_each_cpu(i) { | 635 | for_each_possible_cpu(i) { |
| 636 | kfree(irq_cpu_data[i].irq_delta); | 636 | kfree(irq_cpu_data[i].irq_delta); |
| 637 | irq_cpu_data[i].irq_delta = NULL; | 637 | irq_cpu_data[i].irq_delta = NULL; |
| 638 | kfree(irq_cpu_data[i].last_irq); | 638 | kfree(irq_cpu_data[i].last_irq); |
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index dd780a00553f..e7c138f66c5a 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c | |||
| @@ -459,26 +459,9 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_ | |||
| 459 | return ret; | 459 | return ret; |
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | static int microcode_ioctl (struct inode *inode, struct file *file, | ||
| 463 | unsigned int cmd, unsigned long arg) | ||
| 464 | { | ||
| 465 | switch (cmd) { | ||
| 466 | /* | ||
| 467 | * XXX: will be removed after microcode_ctl | ||
| 468 | * is updated to ignore failure of this ioctl() | ||
| 469 | */ | ||
| 470 | case MICROCODE_IOCFREE: | ||
| 471 | return 0; | ||
| 472 | default: | ||
| 473 | return -EINVAL; | ||
| 474 | } | ||
| 475 | return -EINVAL; | ||
| 476 | } | ||
| 477 | |||
| 478 | static struct file_operations microcode_fops = { | 462 | static struct file_operations microcode_fops = { |
| 479 | .owner = THIS_MODULE, | 463 | .owner = THIS_MODULE, |
| 480 | .write = microcode_write, | 464 | .write = microcode_write, |
| 481 | .ioctl = microcode_ioctl, | ||
| 482 | .open = microcode_open, | 465 | .open = microcode_open, |
| 483 | }; | 466 | }; |
| 484 | 467 | ||
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 9074818b9473..d43b498ec745 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c | |||
| @@ -138,12 +138,12 @@ static int __init check_nmi_watchdog(void) | |||
| 138 | if (nmi_watchdog == NMI_LOCAL_APIC) | 138 | if (nmi_watchdog == NMI_LOCAL_APIC) |
| 139 | smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0); | 139 | smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0); |
| 140 | 140 | ||
| 141 | for_each_cpu(cpu) | 141 | for_each_possible_cpu(cpu) |
| 142 | prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count; | 142 | prev_nmi_count[cpu] = per_cpu(irq_stat, cpu).__nmi_count; |
| 143 | local_irq_enable(); | 143 | local_irq_enable(); |
| 144 | mdelay((10*1000)/nmi_hz); // wait 10 ticks | 144 | mdelay((10*1000)/nmi_hz); // wait 10 ticks |
| 145 | 145 | ||
| 146 | for_each_cpu(cpu) { | 146 | for_each_possible_cpu(cpu) { |
| 147 | #ifdef CONFIG_SMP | 147 | #ifdef CONFIG_SMP |
| 148 | /* Check cpu_callin_map here because that is set | 148 | /* Check cpu_callin_map here because that is set |
| 149 | after the timer is started. */ | 149 | after the timer is started. */ |
| @@ -510,7 +510,7 @@ void touch_nmi_watchdog (void) | |||
| 510 | * Just reset the alert counters, (other CPUs might be | 510 | * Just reset the alert counters, (other CPUs might be |
| 511 | * spinning on locks we hold): | 511 | * spinning on locks we hold): |
| 512 | */ | 512 | */ |
| 513 | for_each_cpu(i) | 513 | for_each_possible_cpu(i) |
| 514 | alert_counter[i] = 0; | 514 | alert_counter[i] = 0; |
| 515 | 515 | ||
| 516 | /* | 516 | /* |
| @@ -529,7 +529,8 @@ void nmi_watchdog_tick (struct pt_regs * regs) | |||
| 529 | * always switch the stack NMI-atomically, it's safe to use | 529 | * always switch the stack NMI-atomically, it's safe to use |
| 530 | * smp_processor_id(). | 530 | * smp_processor_id(). |
| 531 | */ | 531 | */ |
| 532 | int sum, cpu = smp_processor_id(); | 532 | unsigned int sum; |
| 533 | int cpu = smp_processor_id(); | ||
| 533 | 534 | ||
| 534 | sum = per_cpu(irq_stat, cpu).apic_timer_irqs; | 535 | sum = per_cpu(irq_stat, cpu).apic_timer_irqs; |
| 535 | 536 | ||
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 6917daa159ab..8c08660b4e5d 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | #include <linux/kexec.h> | 46 | #include <linux/kexec.h> |
| 47 | #include <linux/crash_dump.h> | 47 | #include <linux/crash_dump.h> |
| 48 | #include <linux/dmi.h> | 48 | #include <linux/dmi.h> |
| 49 | #include <linux/pfn.h> | ||
| 49 | 50 | ||
| 50 | #include <video/edid.h> | 51 | #include <video/edid.h> |
| 51 | 52 | ||
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 82371d83bfa9..a6969903f2d6 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
| @@ -72,6 +72,9 @@ int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; | |||
| 72 | /* Core ID of each logical CPU */ | 72 | /* Core ID of each logical CPU */ |
| 73 | int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; | 73 | int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID}; |
| 74 | 74 | ||
| 75 | /* Last level cache ID of each logical CPU */ | ||
| 76 | int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID}; | ||
| 77 | |||
| 75 | /* representing HT siblings of each logical CPU */ | 78 | /* representing HT siblings of each logical CPU */ |
| 76 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; | 79 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; |
| 77 | EXPORT_SYMBOL(cpu_sibling_map); | 80 | EXPORT_SYMBOL(cpu_sibling_map); |
| @@ -440,6 +443,18 @@ static void __devinit smp_callin(void) | |||
| 440 | 443 | ||
| 441 | static int cpucount; | 444 | static int cpucount; |
| 442 | 445 | ||
| 446 | /* maps the cpu to the sched domain representing multi-core */ | ||
| 447 | cpumask_t cpu_coregroup_map(int cpu) | ||
| 448 | { | ||
| 449 | struct cpuinfo_x86 *c = cpu_data + cpu; | ||
| 450 | /* | ||
| 451 | * For perf, we return last level cache shared map. | ||
| 452 | * TBD: when power saving sched policy is added, we will return | ||
| 453 | * cpu_core_map when power saving policy is enabled | ||
| 454 | */ | ||
| 455 | return c->llc_shared_map; | ||
| 456 | } | ||
| 457 | |||
| 443 | /* representing cpus for which sibling maps can be computed */ | 458 | /* representing cpus for which sibling maps can be computed */ |
| 444 | static cpumask_t cpu_sibling_setup_map; | 459 | static cpumask_t cpu_sibling_setup_map; |
| 445 | 460 | ||
| @@ -459,12 +474,16 @@ set_cpu_sibling_map(int cpu) | |||
| 459 | cpu_set(cpu, cpu_sibling_map[i]); | 474 | cpu_set(cpu, cpu_sibling_map[i]); |
| 460 | cpu_set(i, cpu_core_map[cpu]); | 475 | cpu_set(i, cpu_core_map[cpu]); |
| 461 | cpu_set(cpu, cpu_core_map[i]); | 476 | cpu_set(cpu, cpu_core_map[i]); |
| 477 | cpu_set(i, c[cpu].llc_shared_map); | ||
| 478 | cpu_set(cpu, c[i].llc_shared_map); | ||
| 462 | } | 479 | } |
| 463 | } | 480 | } |
| 464 | } else { | 481 | } else { |
| 465 | cpu_set(cpu, cpu_sibling_map[cpu]); | 482 | cpu_set(cpu, cpu_sibling_map[cpu]); |
| 466 | } | 483 | } |
| 467 | 484 | ||
| 485 | cpu_set(cpu, c[cpu].llc_shared_map); | ||
| 486 | |||
| 468 | if (current_cpu_data.x86_max_cores == 1) { | 487 | if (current_cpu_data.x86_max_cores == 1) { |
| 469 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | 488 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; |
| 470 | c[cpu].booted_cores = 1; | 489 | c[cpu].booted_cores = 1; |
| @@ -472,6 +491,11 @@ set_cpu_sibling_map(int cpu) | |||
| 472 | } | 491 | } |
| 473 | 492 | ||
| 474 | for_each_cpu_mask(i, cpu_sibling_setup_map) { | 493 | for_each_cpu_mask(i, cpu_sibling_setup_map) { |
| 494 | if (cpu_llc_id[cpu] != BAD_APICID && | ||
| 495 | cpu_llc_id[cpu] == cpu_llc_id[i]) { | ||
| 496 | cpu_set(i, c[cpu].llc_shared_map); | ||
| 497 | cpu_set(cpu, c[i].llc_shared_map); | ||
| 498 | } | ||
| 475 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | 499 | if (phys_proc_id[cpu] == phys_proc_id[i]) { |
| 476 | cpu_set(i, cpu_core_map[cpu]); | 500 | cpu_set(i, cpu_core_map[cpu]); |
| 477 | cpu_set(cpu, cpu_core_map[i]); | 501 | cpu_set(cpu, cpu_core_map[i]); |
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index ac687d00a1ce..326595f3fa4d 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S | |||
| @@ -310,3 +310,5 @@ ENTRY(sys_call_table) | |||
| 310 | .long sys_pselect6 | 310 | .long sys_pselect6 |
| 311 | .long sys_ppoll | 311 | .long sys_ppoll |
| 312 | .long sys_unshare /* 310 */ | 312 | .long sys_unshare /* 310 */ |
| 313 | .long sys_set_robust_list | ||
| 314 | .long sys_get_robust_list | ||
diff --git a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c index 264edaaac315..144e94a04933 100644 --- a/arch/i386/kernel/timers/timer_pm.c +++ b/arch/i386/kernel/timers/timer_pm.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/pci.h> | ||
| 18 | #include <asm/types.h> | 19 | #include <asm/types.h> |
| 19 | #include <asm/timer.h> | 20 | #include <asm/timer.h> |
| 20 | #include <asm/smp.h> | 21 | #include <asm/smp.h> |
| @@ -45,24 +46,31 @@ static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; | |||
| 45 | 46 | ||
| 46 | #define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */ | 47 | #define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */ |
| 47 | 48 | ||
| 49 | static int pmtmr_need_workaround __read_mostly = 1; | ||
| 50 | |||
| 48 | /*helper function to safely read acpi pm timesource*/ | 51 | /*helper function to safely read acpi pm timesource*/ |
| 49 | static inline u32 read_pmtmr(void) | 52 | static inline u32 read_pmtmr(void) |
| 50 | { | 53 | { |
| 51 | u32 v1=0,v2=0,v3=0; | 54 | if (pmtmr_need_workaround) { |
| 52 | /* It has been reported that because of various broken | 55 | u32 v1, v2, v3; |
| 53 | * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time | 56 | |
| 54 | * source is not latched, so you must read it multiple | 57 | /* It has been reported that because of various broken |
| 55 | * times to insure a safe value is read. | 58 | * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time |
| 56 | */ | 59 | * source is not latched, so you must read it multiple |
| 57 | do { | 60 | * times to insure a safe value is read. |
| 58 | v1 = inl(pmtmr_ioport); | 61 | */ |
| 59 | v2 = inl(pmtmr_ioport); | 62 | do { |
| 60 | v3 = inl(pmtmr_ioport); | 63 | v1 = inl(pmtmr_ioport); |
| 61 | } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) | 64 | v2 = inl(pmtmr_ioport); |
| 62 | || (v3 > v1 && v3 < v2)); | 65 | v3 = inl(pmtmr_ioport); |
| 63 | 66 | } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) | |
| 64 | /* mask the output to 24 bits */ | 67 | || (v3 > v1 && v3 < v2)); |
| 65 | return v2 & ACPI_PM_MASK; | 68 | |
| 69 | /* mask the output to 24 bits */ | ||
| 70 | return v2 & ACPI_PM_MASK; | ||
| 71 | } | ||
| 72 | |||
| 73 | return inl(pmtmr_ioport) & ACPI_PM_MASK; | ||
| 66 | } | 74 | } |
| 67 | 75 | ||
| 68 | 76 | ||
| @@ -263,6 +271,72 @@ struct init_timer_opts __initdata timer_pmtmr_init = { | |||
| 263 | .opts = &timer_pmtmr, | 271 | .opts = &timer_pmtmr, |
| 264 | }; | 272 | }; |
| 265 | 273 | ||
| 274 | #ifdef CONFIG_PCI | ||
| 275 | /* | ||
| 276 | * PIIX4 Errata: | ||
| 277 | * | ||
| 278 | * The power management timer may return improper results when read. | ||
| 279 | * Although the timer value settles properly after incrementing, | ||
| 280 | * while incrementing there is a 3 ns window every 69.8 ns where the | ||
| 281 | * timer value is indeterminate (a 4.2% chance that the data will be | ||
| 282 | * incorrect when read). As a result, the ACPI free running count up | ||
| 283 | * timer specification is violated due to erroneous reads. | ||
| 284 | */ | ||
| 285 | static int __init pmtmr_bug_check(void) | ||
| 286 | { | ||
| 287 | static struct pci_device_id gray_list[] __initdata = { | ||
| 288 | /* these chipsets may have bug. */ | ||
| 289 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, | ||
| 290 | PCI_DEVICE_ID_INTEL_82801DB_0) }, | ||
| 291 | { }, | ||
| 292 | }; | ||
| 293 | struct pci_dev *dev; | ||
| 294 | int pmtmr_has_bug = 0; | ||
| 295 | u8 rev; | ||
| 296 | |||
| 297 | if (cur_timer != &timer_pmtmr || !pmtmr_need_workaround) | ||
| 298 | return 0; | ||
| 299 | |||
| 300 | dev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
| 301 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL); | ||
| 302 | if (dev) { | ||
| 303 | pci_read_config_byte(dev, PCI_REVISION_ID, &rev); | ||
| 304 | /* the bug has been fixed in PIIX4M */ | ||
| 305 | if (rev < 3) { | ||
| 306 | printk(KERN_WARNING "* Found PM-Timer Bug on this " | ||
| 307 | "chipset. Due to workarounds for a bug,\n" | ||
| 308 | "* this time source is slow. Consider trying " | ||
| 309 | "other time sources (clock=)\n"); | ||
| 310 | pmtmr_has_bug = 1; | ||
| 311 | } | ||
| 312 | pci_dev_put(dev); | ||
| 313 | } | ||
| 314 | |||
| 315 | if (pci_dev_present(gray_list)) { | ||
| 316 | printk(KERN_WARNING "* This chipset may have PM-Timer Bug. Due" | ||
| 317 | " to workarounds for a bug,\n" | ||
| 318 | "* this time source is slow. If you are sure your timer" | ||
| 319 | " does not have\n" | ||
| 320 | "* this bug, please use \"pmtmr_good\" to disable the " | ||
| 321 | "workaround\n"); | ||
| 322 | pmtmr_has_bug = 1; | ||
| 323 | } | ||
| 324 | |||
| 325 | if (!pmtmr_has_bug) | ||
| 326 | pmtmr_need_workaround = 0; | ||
| 327 | |||
| 328 | return 0; | ||
| 329 | } | ||
| 330 | device_initcall(pmtmr_bug_check); | ||
| 331 | #endif | ||
| 332 | |||
| 333 | static int __init pmtr_good_setup(char *__str) | ||
| 334 | { | ||
| 335 | pmtmr_need_workaround = 0; | ||
| 336 | return 1; | ||
| 337 | } | ||
| 338 | __setup("pmtmr_good", pmtr_good_setup); | ||
| 339 | |||
| 266 | MODULE_LICENSE("GPL"); | 340 | MODULE_LICENSE("GPL"); |
| 267 | MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); | 341 | MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>"); |
| 268 | MODULE_DESCRIPTION("Power Management Timer (PMTMR) as primary timing source for x86"); | 342 | MODULE_DESCRIPTION("Power Management Timer (PMTMR) as primary timing source for x86"); |
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 4624f8ca2459..6b63a5aa1e46 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
| @@ -92,22 +92,21 @@ asmlinkage void spurious_interrupt_bug(void); | |||
| 92 | asmlinkage void machine_check(void); | 92 | asmlinkage void machine_check(void); |
| 93 | 93 | ||
| 94 | static int kstack_depth_to_print = 24; | 94 | static int kstack_depth_to_print = 24; |
| 95 | struct notifier_block *i386die_chain; | 95 | ATOMIC_NOTIFIER_HEAD(i386die_chain); |
| 96 | static DEFINE_SPINLOCK(die_notifier_lock); | ||
| 97 | 96 | ||
| 98 | int register_die_notifier(struct notifier_block *nb) | 97 | int register_die_notifier(struct notifier_block *nb) |
| 99 | { | 98 | { |
| 100 | int err = 0; | ||
| 101 | unsigned long flags; | ||
| 102 | |||
| 103 | vmalloc_sync_all(); | 99 | vmalloc_sync_all(); |
| 104 | spin_lock_irqsave(&die_notifier_lock, flags); | 100 | return atomic_notifier_chain_register(&i386die_chain, nb); |
| 105 | err = notifier_chain_register(&i386die_chain, nb); | ||
| 106 | spin_unlock_irqrestore(&die_notifier_lock, flags); | ||
| 107 | return err; | ||
| 108 | } | 101 | } |
| 109 | EXPORT_SYMBOL(register_die_notifier); | 102 | EXPORT_SYMBOL(register_die_notifier); |
| 110 | 103 | ||
| 104 | int unregister_die_notifier(struct notifier_block *nb) | ||
| 105 | { | ||
| 106 | return atomic_notifier_chain_unregister(&i386die_chain, nb); | ||
| 107 | } | ||
| 108 | EXPORT_SYMBOL(unregister_die_notifier); | ||
| 109 | |||
| 111 | static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) | 110 | static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) |
| 112 | { | 111 | { |
| 113 | return p > (void *)tinfo && | 112 | return p > (void *)tinfo && |
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c index 8165626a5c30..70e560a1b79a 100644 --- a/arch/i386/mach-voyager/voyager_smp.c +++ b/arch/i386/mach-voyager/voyager_smp.c | |||
| @@ -1700,7 +1700,7 @@ after_handle_vic_irq(unsigned int irq) | |||
| 1700 | 1700 | ||
| 1701 | printk("VOYAGER SMP: CPU%d lost interrupt %d\n", | 1701 | printk("VOYAGER SMP: CPU%d lost interrupt %d\n", |
| 1702 | cpu, irq); | 1702 | cpu, irq); |
| 1703 | for_each_cpu(real_cpu, mask) { | 1703 | for_each_possible_cpu(real_cpu, mask) { |
| 1704 | 1704 | ||
| 1705 | outb(VIC_CPU_MASQUERADE_ENABLE | real_cpu, | 1705 | outb(VIC_CPU_MASQUERADE_ENABLE | real_cpu, |
| 1706 | VIC_PROCESSOR_ID); | 1706 | VIC_PROCESSOR_ID); |
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c index c4af9638dbfa..fe6eb901326e 100644 --- a/arch/i386/mm/discontig.c +++ b/arch/i386/mm/discontig.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/nodemask.h> | 31 | #include <linux/nodemask.h> |
| 32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
| 33 | #include <linux/kexec.h> | 33 | #include <linux/kexec.h> |
| 34 | #include <linux/pfn.h> | ||
| 34 | 35 | ||
| 35 | #include <asm/e820.h> | 36 | #include <asm/e820.h> |
| 36 | #include <asm/setup.h> | 37 | #include <asm/setup.h> |
| @@ -352,17 +353,6 @@ void __init zone_sizes_init(void) | |||
| 352 | { | 353 | { |
| 353 | int nid; | 354 | int nid; |
| 354 | 355 | ||
| 355 | /* | ||
| 356 | * Insert nodes into pgdat_list backward so they appear in order. | ||
| 357 | * Clobber node 0's links and NULL out pgdat_list before starting. | ||
| 358 | */ | ||
| 359 | pgdat_list = NULL; | ||
| 360 | for (nid = MAX_NUMNODES - 1; nid >= 0; nid--) { | ||
| 361 | if (!node_online(nid)) | ||
| 362 | continue; | ||
| 363 | NODE_DATA(nid)->pgdat_next = pgdat_list; | ||
| 364 | pgdat_list = NODE_DATA(nid); | ||
| 365 | } | ||
| 366 | 356 | ||
| 367 | for_each_online_node(nid) { | 357 | for_each_online_node(nid) { |
| 368 | unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; | 358 | unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; |
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c index 9db3242103be..2889567e21a1 100644 --- a/arch/i386/mm/pgtable.c +++ b/arch/i386/mm/pgtable.c | |||
| @@ -36,7 +36,7 @@ void show_mem(void) | |||
| 36 | printk(KERN_INFO "Mem-info:\n"); | 36 | printk(KERN_INFO "Mem-info:\n"); |
| 37 | show_free_areas(); | 37 | show_free_areas(); |
| 38 | printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); | 38 | printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); |
| 39 | for_each_pgdat(pgdat) { | 39 | for_each_online_pgdat(pgdat) { |
| 40 | pgdat_resize_lock(pgdat, &flags); | 40 | pgdat_resize_lock(pgdat, &flags); |
| 41 | for (i = 0; i < pgdat->node_spanned_pages; ++i) { | 41 | for (i = 0; i < pgdat->node_spanned_pages; ++i) { |
| 42 | page = pgdat_page_nr(pgdat, i); | 42 | page = pgdat_page_nr(pgdat, i); |
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c index 1accce50c2c7..1a2076ce6f6a 100644 --- a/arch/i386/oprofile/nmi_int.c +++ b/arch/i386/oprofile/nmi_int.c | |||
| @@ -122,7 +122,7 @@ static void nmi_save_registers(void * dummy) | |||
| 122 | static void free_msrs(void) | 122 | static void free_msrs(void) |
| 123 | { | 123 | { |
| 124 | int i; | 124 | int i; |
| 125 | for_each_cpu(i) { | 125 | for_each_possible_cpu(i) { |
| 126 | kfree(cpu_msrs[i].counters); | 126 | kfree(cpu_msrs[i].counters); |
| 127 | cpu_msrs[i].counters = NULL; | 127 | cpu_msrs[i].counters = NULL; |
| 128 | kfree(cpu_msrs[i].controls); | 128 | kfree(cpu_msrs[i].controls); |
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index dabd6c32641e..7c1ddc8ac443 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c | |||
| @@ -30,19 +30,19 @@ extern spinlock_t timerlist_lock; | |||
| 30 | fpswa_interface_t *fpswa_interface; | 30 | fpswa_interface_t *fpswa_interface; |
| 31 | EXPORT_SYMBOL(fpswa_interface); | 31 | EXPORT_SYMBOL(fpswa_interface); |
| 32 | 32 | ||
| 33 | struct notifier_block *ia64die_chain; | 33 | ATOMIC_NOTIFIER_HEAD(ia64die_chain); |
| 34 | 34 | ||
| 35 | int | 35 | int |
| 36 | register_die_notifier(struct notifier_block *nb) | 36 | register_die_notifier(struct notifier_block *nb) |
| 37 | { | 37 | { |
| 38 | return notifier_chain_register(&ia64die_chain, nb); | 38 | return atomic_notifier_chain_register(&ia64die_chain, nb); |
| 39 | } | 39 | } |
| 40 | EXPORT_SYMBOL_GPL(register_die_notifier); | 40 | EXPORT_SYMBOL_GPL(register_die_notifier); |
| 41 | 41 | ||
| 42 | int | 42 | int |
| 43 | unregister_die_notifier(struct notifier_block *nb) | 43 | unregister_die_notifier(struct notifier_block *nb) |
| 44 | { | 44 | { |
| 45 | return notifier_chain_unregister(&ia64die_chain, nb); | 45 | return atomic_notifier_chain_unregister(&ia64die_chain, nb); |
| 46 | } | 46 | } |
| 47 | EXPORT_SYMBOL_GPL(unregister_die_notifier); | 47 | EXPORT_SYMBOL_GPL(unregister_die_notifier); |
| 48 | 48 | ||
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 2f5e44862e91..ec9eeb89975d 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c | |||
| @@ -379,31 +379,6 @@ static void __init *memory_less_node_alloc(int nid, unsigned long pernodesize) | |||
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | /** | 381 | /** |
| 382 | * pgdat_insert - insert the pgdat into global pgdat_list | ||
| 383 | * @pgdat: the pgdat for a node. | ||
| 384 | */ | ||
| 385 | static void __init pgdat_insert(pg_data_t *pgdat) | ||
| 386 | { | ||
| 387 | pg_data_t *prev = NULL, *next; | ||
| 388 | |||
| 389 | for_each_pgdat(next) | ||
| 390 | if (pgdat->node_id < next->node_id) | ||
| 391 | break; | ||
| 392 | else | ||
| 393 | prev = next; | ||
| 394 | |||
| 395 | if (prev) { | ||
| 396 | prev->pgdat_next = pgdat; | ||
| 397 | pgdat->pgdat_next = next; | ||
| 398 | } else { | ||
| 399 | pgdat->pgdat_next = pgdat_list; | ||
| 400 | pgdat_list = pgdat; | ||
| 401 | } | ||
| 402 | |||
| 403 | return; | ||
| 404 | } | ||
| 405 | |||
| 406 | /** | ||
| 407 | * memory_less_nodes - allocate and initialize CPU only nodes pernode | 382 | * memory_less_nodes - allocate and initialize CPU only nodes pernode |
| 408 | * information. | 383 | * information. |
| 409 | */ | 384 | */ |
| @@ -560,7 +535,7 @@ void show_mem(void) | |||
| 560 | printk("Mem-info:\n"); | 535 | printk("Mem-info:\n"); |
| 561 | show_free_areas(); | 536 | show_free_areas(); |
| 562 | printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); | 537 | printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); |
| 563 | for_each_pgdat(pgdat) { | 538 | for_each_online_pgdat(pgdat) { |
| 564 | unsigned long present; | 539 | unsigned long present; |
| 565 | unsigned long flags; | 540 | unsigned long flags; |
| 566 | int shared = 0, cached = 0, reserved = 0; | 541 | int shared = 0, cached = 0, reserved = 0; |
| @@ -745,11 +720,5 @@ void __init paging_init(void) | |||
| 745 | pfn_offset, zholes_size); | 720 | pfn_offset, zholes_size); |
| 746 | } | 721 | } |
| 747 | 722 | ||
| 748 | /* | ||
| 749 | * Make memory less nodes become a member of the known nodes. | ||
| 750 | */ | ||
| 751 | for_each_node_mask(node, memory_less_mask) | ||
| 752 | pgdat_insert(mem_data[node].pgdat); | ||
| 753 | |||
| 754 | zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page)); | 723 | zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page)); |
| 755 | } | 724 | } |
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index ff4f31fcd330..2ef1151cde90 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c | |||
| @@ -600,7 +600,7 @@ mem_init (void) | |||
| 600 | kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START); | 600 | kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START); |
| 601 | kclist_add(&kcore_kernel, _stext, _end - _stext); | 601 | kclist_add(&kcore_kernel, _stext, _end - _stext); |
| 602 | 602 | ||
| 603 | for_each_pgdat(pgdat) | 603 | for_each_online_pgdat(pgdat) |
| 604 | if (pgdat->bdata->node_bootmem_map) | 604 | if (pgdat->bdata->node_bootmem_map) |
| 605 | totalram_pages += free_all_bootmem_node(pgdat); | 605 | totalram_pages += free_all_bootmem_node(pgdat); |
| 606 | 606 | ||
diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c index c686d9c12f7b..5100261310f7 100644 --- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c +++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c | |||
| @@ -93,19 +93,22 @@ static int coherence_id_open(struct inode *inode, struct file *file) | |||
| 93 | static struct proc_dir_entry | 93 | static struct proc_dir_entry |
| 94 | *sn_procfs_create_entry(const char *name, struct proc_dir_entry *parent, | 94 | *sn_procfs_create_entry(const char *name, struct proc_dir_entry *parent, |
| 95 | int (*openfunc)(struct inode *, struct file *), | 95 | int (*openfunc)(struct inode *, struct file *), |
| 96 | int (*releasefunc)(struct inode *, struct file *)) | 96 | int (*releasefunc)(struct inode *, struct file *), |
| 97 | ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *)) | ||
| 97 | { | 98 | { |
| 98 | struct proc_dir_entry *e = create_proc_entry(name, 0444, parent); | 99 | struct proc_dir_entry *e = create_proc_entry(name, 0444, parent); |
| 99 | 100 | ||
| 100 | if (e) { | 101 | if (e) { |
| 101 | e->proc_fops = (struct file_operations *)kmalloc( | 102 | struct file_operations *f; |
| 102 | sizeof(struct file_operations), GFP_KERNEL); | 103 | |
| 103 | if (e->proc_fops) { | 104 | f = kzalloc(sizeof(*f), GFP_KERNEL); |
| 104 | memset(e->proc_fops, 0, sizeof(struct file_operations)); | 105 | if (f) { |
| 105 | e->proc_fops->open = openfunc; | 106 | f->open = openfunc; |
| 106 | e->proc_fops->read = seq_read; | 107 | f->read = seq_read; |
| 107 | e->proc_fops->llseek = seq_lseek; | 108 | f->llseek = seq_lseek; |
| 108 | e->proc_fops->release = releasefunc; | 109 | f->release = releasefunc; |
| 110 | f->write = write; | ||
| 111 | e->proc_fops = f; | ||
| 109 | } | 112 | } |
| 110 | } | 113 | } |
| 111 | 114 | ||
| @@ -119,31 +122,29 @@ extern int sn_topology_release(struct inode *, struct file *); | |||
| 119 | void register_sn_procfs(void) | 122 | void register_sn_procfs(void) |
| 120 | { | 123 | { |
| 121 | static struct proc_dir_entry *sgi_proc_dir = NULL; | 124 | static struct proc_dir_entry *sgi_proc_dir = NULL; |
| 122 | struct proc_dir_entry *e; | ||
| 123 | 125 | ||
| 124 | BUG_ON(sgi_proc_dir != NULL); | 126 | BUG_ON(sgi_proc_dir != NULL); |
| 125 | if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL))) | 127 | if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL))) |
| 126 | return; | 128 | return; |
| 127 | 129 | ||
| 128 | sn_procfs_create_entry("partition_id", sgi_proc_dir, | 130 | sn_procfs_create_entry("partition_id", sgi_proc_dir, |
| 129 | partition_id_open, single_release); | 131 | partition_id_open, single_release, NULL); |
| 130 | 132 | ||
| 131 | sn_procfs_create_entry("system_serial_number", sgi_proc_dir, | 133 | sn_procfs_create_entry("system_serial_number", sgi_proc_dir, |
| 132 | system_serial_number_open, single_release); | 134 | system_serial_number_open, single_release, NULL); |
| 133 | 135 | ||
| 134 | sn_procfs_create_entry("licenseID", sgi_proc_dir, | 136 | sn_procfs_create_entry("licenseID", sgi_proc_dir, |
| 135 | licenseID_open, single_release); | 137 | licenseID_open, single_release, NULL); |
| 136 | 138 | ||
| 137 | e = sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir, | 139 | sn_procfs_create_entry("sn_force_interrupt", sgi_proc_dir, |
| 138 | sn_force_interrupt_open, single_release); | 140 | sn_force_interrupt_open, single_release, |
| 139 | if (e) | 141 | sn_force_interrupt_write_proc); |
| 140 | e->proc_fops->write = sn_force_interrupt_write_proc; | ||
| 141 | 142 | ||
| 142 | sn_procfs_create_entry("coherence_id", sgi_proc_dir, | 143 | sn_procfs_create_entry("coherence_id", sgi_proc_dir, |
| 143 | coherence_id_open, single_release); | 144 | coherence_id_open, single_release, NULL); |
| 144 | 145 | ||
| 145 | sn_procfs_create_entry("sn_topology", sgi_proc_dir, | 146 | sn_procfs_create_entry("sn_topology", sgi_proc_dir, |
| 146 | sn_topology_open, sn_topology_release); | 147 | sn_topology_open, sn_topology_release, NULL); |
| 147 | } | 148 | } |
| 148 | 149 | ||
| 149 | #endif /* CONFIG_PROC_FS */ | 150 | #endif /* CONFIG_PROC_FS */ |
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c index d742037a7ccb..0d78942b4c76 100644 --- a/arch/m32r/kernel/setup.c +++ b/arch/m32r/kernel/setup.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/tty.h> | 24 | #include <linux/tty.h> |
| 25 | #include <linux/cpu.h> | 25 | #include <linux/cpu.h> |
| 26 | #include <linux/nodemask.h> | 26 | #include <linux/nodemask.h> |
| 27 | #include <linux/pfn.h> | ||
| 27 | 28 | ||
| 28 | #include <asm/processor.h> | 29 | #include <asm/processor.h> |
| 29 | #include <asm/pgtable.h> | 30 | #include <asm/pgtable.h> |
diff --git a/arch/m32r/mm/discontig.c b/arch/m32r/mm/discontig.c index 08e727955555..cf610a7c5ff0 100644 --- a/arch/m32r/mm/discontig.c +++ b/arch/m32r/mm/discontig.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/initrd.h> | 13 | #include <linux/initrd.h> |
| 14 | #include <linux/nodemask.h> | 14 | #include <linux/nodemask.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/pfn.h> | ||
| 16 | 17 | ||
| 17 | #include <asm/setup.h> | 18 | #include <asm/setup.h> |
| 18 | 19 | ||
| @@ -137,12 +138,6 @@ unsigned long __init zone_sizes_init(void) | |||
| 137 | int nid, i; | 138 | int nid, i; |
| 138 | mem_prof_t *mp; | 139 | mem_prof_t *mp; |
| 139 | 140 | ||
| 140 | pgdat_list = NULL; | ||
| 141 | for (nid = num_online_nodes() - 1 ; nid >= 0 ; nid--) { | ||
| 142 | NODE_DATA(nid)->pgdat_next = pgdat_list; | ||
| 143 | pgdat_list = NODE_DATA(nid); | ||
| 144 | } | ||
| 145 | |||
| 146 | for_each_online_node(nid) { | 141 | for_each_online_node(nid) { |
| 147 | mp = &mem_prof[nid]; | 142 | mp = &mem_prof[nid]; |
| 148 | for (i = 0 ; i < MAX_NR_ZONES ; i++) { | 143 | for (i = 0 ; i < MAX_NR_ZONES ; i++) { |
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c index c9e7dad860b7..b71348fec1f4 100644 --- a/arch/m32r/mm/init.c +++ b/arch/m32r/mm/init.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/highmem.h> | 18 | #include <linux/highmem.h> |
| 19 | #include <linux/bitops.h> | 19 | #include <linux/bitops.h> |
| 20 | #include <linux/nodemask.h> | 20 | #include <linux/nodemask.h> |
| 21 | #include <linux/pfn.h> | ||
| 21 | #include <asm/types.h> | 22 | #include <asm/types.h> |
| 22 | #include <asm/processor.h> | 23 | #include <asm/processor.h> |
| 23 | #include <asm/page.h> | 24 | #include <asm/page.h> |
| @@ -47,7 +48,7 @@ void show_mem(void) | |||
| 47 | printk("Mem-info:\n"); | 48 | printk("Mem-info:\n"); |
| 48 | show_free_areas(); | 49 | show_free_areas(); |
| 49 | printk("Free swap: %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); | 50 | printk("Free swap: %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); |
| 50 | for_each_pgdat(pgdat) { | 51 | for_each_online_pgdat(pgdat) { |
| 51 | unsigned long flags; | 52 | unsigned long flags; |
| 52 | pgdat_resize_lock(pgdat, &flags); | 53 | pgdat_resize_lock(pgdat, &flags); |
| 53 | for (i = 0; i < pgdat->node_spanned_pages; ++i) { | 54 | for (i = 0; i < pgdat->node_spanned_pages; ++i) { |
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c index a69fe3048edc..b0e4c084df8a 100644 --- a/arch/m68k/mvme16x/rtc.c +++ b/arch/m68k/mvme16x/rtc.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/poll.h> | 17 | #include <linux/poll.h> |
| 18 | #include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */ | 18 | #include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */ |
| 19 | #include <linux/smp_lock.h> | 19 | #include <linux/smp_lock.h> |
| 20 | #include <linux/bcd.h> | ||
| 20 | #include <asm/mvme16xhw.h> | 21 | #include <asm/mvme16xhw.h> |
| 21 | 22 | ||
| 22 | #include <asm/io.h> | 23 | #include <asm/io.h> |
| @@ -31,9 +32,6 @@ | |||
| 31 | * ioctls. | 32 | * ioctls. |
| 32 | */ | 33 | */ |
| 33 | 34 | ||
| 34 | #define BCD2BIN(val) (((val)&15) + ((val)>>4)*10) | ||
| 35 | #define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) | ||
| 36 | |||
| 37 | static const unsigned char days_in_mo[] = | 35 | static const unsigned char days_in_mo[] = |
| 38 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; | 36 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
| 39 | 37 | ||
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c index 1080558c8100..307e98c29ddc 100644 --- a/arch/mips/au1000/common/setup.c +++ b/arch/mips/au1000/common/setup.c | |||
| @@ -94,7 +94,7 @@ void __init plat_setup(void) | |||
| 94 | 94 | ||
| 95 | argptr = prom_getcmdline(); | 95 | argptr = prom_getcmdline(); |
| 96 | 96 | ||
| 97 | #if defined(CONFIG_SERIAL_AU1X00_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) | 97 | #ifdef CONFIG_SERIAL_8250_CONSOLE |
| 98 | if ((argptr = strstr(argptr, "console=")) == NULL) { | 98 | if ((argptr = strstr(argptr, "console=")) == NULL) { |
| 99 | argptr = prom_getcmdline(); | 99 | argptr = prom_getcmdline(); |
| 100 | strcat(argptr, " console=ttyS0,115200"); | 100 | strcat(argptr, " console=ttyS0,115200"); |
diff --git a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c index 995896ac0e39..5dc34daa7150 100644 --- a/arch/mips/ddb5xxx/common/rtc_ds1386.c +++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c | |||
| @@ -165,6 +165,6 @@ rtc_ds1386_init(unsigned long base) | |||
| 165 | WRITE_RTC(0xB, byte); | 165 | WRITE_RTC(0xB, byte); |
| 166 | 166 | ||
| 167 | /* set the function pointers */ | 167 | /* set the function pointers */ |
| 168 | rtc_get_time = rtc_ds1386_get_time; | 168 | rtc_mips_get_time = rtc_ds1386_get_time; |
| 169 | rtc_set_time = rtc_ds1386_set_time; | 169 | rtc_mips_set_time = rtc_ds1386_set_time; |
| 170 | } | 170 | } |
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index 174822344131..74cb055d4bf6 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c | |||
| @@ -36,41 +36,13 @@ | |||
| 36 | #include <asm/dec/ioasic_addrs.h> | 36 | #include <asm/dec/ioasic_addrs.h> |
| 37 | #include <asm/dec/machtype.h> | 37 | #include <asm/dec/machtype.h> |
| 38 | 38 | ||
| 39 | |||
| 40 | /* | ||
| 41 | * Returns true if a clock update is in progress | ||
| 42 | */ | ||
| 43 | static inline unsigned char dec_rtc_is_updating(void) | ||
| 44 | { | ||
| 45 | unsigned char uip; | ||
| 46 | unsigned long flags; | ||
| 47 | |||
| 48 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 49 | uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); | ||
| 50 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 51 | return uip; | ||
| 52 | } | ||
| 53 | |||
| 54 | static unsigned long dec_rtc_get_time(void) | 39 | static unsigned long dec_rtc_get_time(void) |
| 55 | { | 40 | { |
| 56 | unsigned int year, mon, day, hour, min, sec, real_year; | 41 | unsigned int year, mon, day, hour, min, sec, real_year; |
| 57 | int i; | ||
| 58 | unsigned long flags; | 42 | unsigned long flags; |
| 59 | 43 | ||
| 60 | /* The Linux interpretation of the DS1287 clock register contents: | ||
| 61 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
| 62 | * RTC registers show the second which has precisely just started. | ||
| 63 | * Let's hope other operating systems interpret the RTC the same way. | ||
| 64 | */ | ||
| 65 | /* read RTC exactly on falling edge of update flag */ | ||
| 66 | for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ | ||
| 67 | if (dec_rtc_is_updating()) | ||
| 68 | break; | ||
| 69 | for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ | ||
| 70 | if (!dec_rtc_is_updating()) | ||
| 71 | break; | ||
| 72 | spin_lock_irqsave(&rtc_lock, flags); | 44 | spin_lock_irqsave(&rtc_lock, flags); |
| 73 | /* Isn't this overkill? UIP above should guarantee consistency */ | 45 | |
| 74 | do { | 46 | do { |
| 75 | sec = CMOS_READ(RTC_SECONDS); | 47 | sec = CMOS_READ(RTC_SECONDS); |
| 76 | min = CMOS_READ(RTC_MINUTES); | 48 | min = CMOS_READ(RTC_MINUTES); |
| @@ -78,7 +50,16 @@ static unsigned long dec_rtc_get_time(void) | |||
| 78 | day = CMOS_READ(RTC_DAY_OF_MONTH); | 50 | day = CMOS_READ(RTC_DAY_OF_MONTH); |
| 79 | mon = CMOS_READ(RTC_MONTH); | 51 | mon = CMOS_READ(RTC_MONTH); |
| 80 | year = CMOS_READ(RTC_YEAR); | 52 | year = CMOS_READ(RTC_YEAR); |
| 53 | /* | ||
| 54 | * The PROM will reset the year to either '72 or '73. | ||
| 55 | * Therefore we store the real year separately, in one | ||
| 56 | * of unused BBU RAM locations. | ||
| 57 | */ | ||
| 58 | real_year = CMOS_READ(RTC_DEC_YEAR); | ||
| 81 | } while (sec != CMOS_READ(RTC_SECONDS)); | 59 | } while (sec != CMOS_READ(RTC_SECONDS)); |
| 60 | |||
| 61 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 62 | |||
| 82 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | 63 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
| 83 | sec = BCD2BIN(sec); | 64 | sec = BCD2BIN(sec); |
| 84 | min = BCD2BIN(min); | 65 | min = BCD2BIN(min); |
| @@ -87,13 +68,7 @@ static unsigned long dec_rtc_get_time(void) | |||
| 87 | mon = BCD2BIN(mon); | 68 | mon = BCD2BIN(mon); |
| 88 | year = BCD2BIN(year); | 69 | year = BCD2BIN(year); |
| 89 | } | 70 | } |
| 90 | /* | 71 | |
| 91 | * The PROM will reset the year to either '72 or '73. | ||
| 92 | * Therefore we store the real year separately, in one | ||
| 93 | * of unused BBU RAM locations. | ||
| 94 | */ | ||
| 95 | real_year = CMOS_READ(RTC_DEC_YEAR); | ||
| 96 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 97 | year += real_year - 72 + 2000; | 72 | year += real_year - 72 + 2000; |
| 98 | 73 | ||
| 99 | return mktime(year, mon, day, hour, min, sec); | 74 | return mktime(year, mon, day, hour, min, sec); |
| @@ -193,8 +168,8 @@ static void dec_ioasic_hpt_init(unsigned int count) | |||
| 193 | 168 | ||
| 194 | void __init dec_time_init(void) | 169 | void __init dec_time_init(void) |
| 195 | { | 170 | { |
| 196 | rtc_get_time = dec_rtc_get_time; | 171 | rtc_mips_get_time = dec_rtc_get_time; |
| 197 | rtc_set_mmss = dec_rtc_set_mmss; | 172 | rtc_mips_set_mmss = dec_rtc_set_mmss; |
| 198 | 173 | ||
| 199 | mips_timer_state = dec_timer_state; | 174 | mips_timer_state = dec_timer_state; |
| 200 | mips_timer_ack = dec_timer_ack; | 175 | mips_timer_ack = dec_timer_ack; |
diff --git a/arch/mips/ite-boards/generic/time.c b/arch/mips/ite-boards/generic/time.c index f5d67ee21ac6..b79817bb6cce 100644 --- a/arch/mips/ite-boards/generic/time.c +++ b/arch/mips/ite-boards/generic/time.c | |||
| @@ -227,8 +227,8 @@ void __init it8172_time_init(void) | |||
| 227 | 227 | ||
| 228 | local_irq_restore(flags); | 228 | local_irq_restore(flags); |
| 229 | 229 | ||
| 230 | rtc_get_time = it8172_rtc_get_time; | 230 | rtc_mips_get_time = it8172_rtc_get_time; |
| 231 | rtc_set_time = it8172_rtc_set_time; | 231 | rtc_mips_set_time = it8172_rtc_set_time; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) | 234 | #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) |
diff --git a/arch/mips/ite-boards/ivr/init.c b/arch/mips/ite-boards/ivr/init.c index ea4e1935fec5..b774db035b31 100644 --- a/arch/mips/ite-boards/ivr/init.c +++ b/arch/mips/ite-boards/ivr/init.c | |||
| @@ -45,9 +45,6 @@ extern void __init prom_init_cmdline(void); | |||
| 45 | extern unsigned long __init prom_get_memsize(void); | 45 | extern unsigned long __init prom_get_memsize(void); |
| 46 | extern void __init it8172_init_ram_resource(unsigned long memsize); | 46 | extern void __init it8172_init_ram_resource(unsigned long memsize); |
| 47 | 47 | ||
| 48 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | ||
| 49 | #define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) | ||
| 50 | |||
| 51 | const char *get_system_type(void) | 48 | const char *get_system_type(void) |
| 52 | { | 49 | { |
| 53 | return "Globespan IVR"; | 50 | return "Globespan IVR"; |
diff --git a/arch/mips/ite-boards/qed-4n-s01b/init.c b/arch/mips/ite-boards/qed-4n-s01b/init.c index 56dca7e0c21d..e8ec8be66a80 100644 --- a/arch/mips/ite-boards/qed-4n-s01b/init.c +++ b/arch/mips/ite-boards/qed-4n-s01b/init.c | |||
| @@ -45,9 +45,6 @@ extern void __init prom_init_cmdline(void); | |||
| 45 | extern unsigned long __init prom_get_memsize(void); | 45 | extern unsigned long __init prom_get_memsize(void); |
| 46 | extern void __init it8172_init_ram_resource(unsigned long memsize); | 46 | extern void __init it8172_init_ram_resource(unsigned long memsize); |
| 47 | 47 | ||
| 48 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | ||
| 49 | #define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) | ||
| 50 | |||
| 51 | const char *get_system_type(void) | 48 | const char *get_system_type(void) |
| 52 | { | 49 | { |
| 53 | return "ITE QED-4N-S01B"; | 50 | return "ITE QED-4N-S01B"; |
diff --git a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c index 9a8bff153d80..a6bd3f4d3049 100644 --- a/arch/mips/jmr3927/common/rtc_ds1742.c +++ b/arch/mips/jmr3927/common/rtc_ds1742.c | |||
| @@ -159,8 +159,8 @@ rtc_ds1742_init(unsigned long base) | |||
| 159 | db_assert((rtc_base & 0xe0000000) == KSEG1); | 159 | db_assert((rtc_base & 0xe0000000) == KSEG1); |
| 160 | 160 | ||
| 161 | /* set the function pointers */ | 161 | /* set the function pointers */ |
| 162 | rtc_get_time = rtc_ds1742_get_time; | 162 | rtc_mips_get_time = rtc_ds1742_get_time; |
| 163 | rtc_set_time = rtc_ds1742_set_time; | 163 | rtc_mips_set_time = rtc_ds1742_set_time; |
| 164 | 164 | ||
| 165 | /* clear oscillator stop bit */ | 165 | /* clear oscillator stop bit */ |
| 166 | CMOS_WRITE(RTC_READ, RTC_CONTROL); | 166 | CMOS_WRITE(RTC_READ, RTC_CONTROL); |
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 0cb3b6097e0e..dcbfd27071f0 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/highmem.h> | 34 | #include <linux/highmem.h> |
| 35 | #include <linux/console.h> | 35 | #include <linux/console.h> |
| 36 | #include <linux/mmzone.h> | 36 | #include <linux/mmzone.h> |
| 37 | #include <linux/pfn.h> | ||
| 37 | 38 | ||
| 38 | #include <asm/addrspace.h> | 39 | #include <asm/addrspace.h> |
| 39 | #include <asm/bootinfo.h> | 40 | #include <asm/bootinfo.h> |
| @@ -257,10 +258,6 @@ static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_en | |||
| 257 | return 0; | 258 | return 0; |
| 258 | } | 259 | } |
| 259 | 260 | ||
| 260 | #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) | ||
| 261 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
| 262 | #define PFN_PHYS(x) ((x) << PAGE_SHIFT) | ||
| 263 | |||
| 264 | #define MAXMEM HIGHMEM_START | 261 | #define MAXMEM HIGHMEM_START |
| 265 | #define MAXMEM_PFN PFN_DOWN(MAXMEM) | 262 | #define MAXMEM_PFN PFN_DOWN(MAXMEM) |
| 266 | 263 | ||
| @@ -493,10 +490,6 @@ static inline void resource_init(void) | |||
| 493 | } | 490 | } |
| 494 | } | 491 | } |
| 495 | 492 | ||
| 496 | #undef PFN_UP | ||
| 497 | #undef PFN_DOWN | ||
| 498 | #undef PFN_PHYS | ||
| 499 | |||
| 500 | #undef MAXMEM | 493 | #undef MAXMEM |
| 501 | #undef MAXMEM_PFN | 494 | #undef MAXMEM_PFN |
| 502 | 495 | ||
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 51273b7297a7..5e51a2d8f3f0 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c | |||
| @@ -65,9 +65,9 @@ static int null_rtc_set_time(unsigned long sec) | |||
| 65 | return 0; | 65 | return 0; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | unsigned long (*rtc_get_time)(void) = null_rtc_get_time; | 68 | unsigned long (*rtc_mips_get_time)(void) = null_rtc_get_time; |
| 69 | int (*rtc_set_time)(unsigned long) = null_rtc_set_time; | 69 | int (*rtc_mips_set_time)(unsigned long) = null_rtc_set_time; |
| 70 | int (*rtc_set_mmss)(unsigned long); | 70 | int (*rtc_mips_set_mmss)(unsigned long); |
| 71 | 71 | ||
| 72 | 72 | ||
| 73 | /* usecs per counter cycle, shifted to left by 32 bits */ | 73 | /* usecs per counter cycle, shifted to left by 32 bits */ |
| @@ -440,14 +440,14 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
| 440 | 440 | ||
| 441 | /* | 441 | /* |
| 442 | * If we have an externally synchronized Linux clock, then update | 442 | * If we have an externally synchronized Linux clock, then update |
| 443 | * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be | 443 | * CMOS clock accordingly every ~11 minutes. rtc_mips_set_time() has to be |
| 444 | * called as close as possible to 500 ms before the new second starts. | 444 | * called as close as possible to 500 ms before the new second starts. |
| 445 | */ | 445 | */ |
| 446 | if (ntp_synced() && | 446 | if (ntp_synced() && |
| 447 | xtime.tv_sec > last_rtc_update + 660 && | 447 | xtime.tv_sec > last_rtc_update + 660 && |
| 448 | (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && | 448 | (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && |
| 449 | (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { | 449 | (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { |
| 450 | if (rtc_set_mmss(xtime.tv_sec) == 0) { | 450 | if (rtc_mips_set_mmss(xtime.tv_sec) == 0) { |
| 451 | last_rtc_update = xtime.tv_sec; | 451 | last_rtc_update = xtime.tv_sec; |
| 452 | } else { | 452 | } else { |
| 453 | /* do it again in 60 s */ | 453 | /* do it again in 60 s */ |
| @@ -565,7 +565,7 @@ asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs) | |||
| 565 | * b) (optional) calibrate and set the mips_hpt_frequency | 565 | * b) (optional) calibrate and set the mips_hpt_frequency |
| 566 | * (only needed if you intended to use fixed_rate_gettimeoffset | 566 | * (only needed if you intended to use fixed_rate_gettimeoffset |
| 567 | * or use cpu counter as timer interrupt source) | 567 | * or use cpu counter as timer interrupt source) |
| 568 | * 2) setup xtime based on rtc_get_time(). | 568 | * 2) setup xtime based on rtc_mips_get_time(). |
| 569 | * 3) choose a appropriate gettimeoffset routine. | 569 | * 3) choose a appropriate gettimeoffset routine. |
| 570 | * 4) calculate a couple of cached variables for later usage | 570 | * 4) calculate a couple of cached variables for later usage |
| 571 | * 5) board_timer_setup() - | 571 | * 5) board_timer_setup() - |
| @@ -633,10 +633,10 @@ void __init time_init(void) | |||
| 633 | if (board_time_init) | 633 | if (board_time_init) |
| 634 | board_time_init(); | 634 | board_time_init(); |
| 635 | 635 | ||
| 636 | if (!rtc_set_mmss) | 636 | if (!rtc_mips_set_mmss) |
| 637 | rtc_set_mmss = rtc_set_time; | 637 | rtc_mips_set_mmss = rtc_mips_set_time; |
| 638 | 638 | ||
| 639 | xtime.tv_sec = rtc_get_time(); | 639 | xtime.tv_sec = rtc_mips_get_time(); |
| 640 | xtime.tv_nsec = 0; | 640 | xtime.tv_nsec = 0; |
| 641 | 641 | ||
| 642 | set_normalized_timespec(&wall_to_monotonic, | 642 | set_normalized_timespec(&wall_to_monotonic, |
| @@ -772,8 +772,8 @@ void to_tm(unsigned long tim, struct rtc_time *tm) | |||
| 772 | 772 | ||
| 773 | EXPORT_SYMBOL(rtc_lock); | 773 | EXPORT_SYMBOL(rtc_lock); |
| 774 | EXPORT_SYMBOL(to_tm); | 774 | EXPORT_SYMBOL(to_tm); |
| 775 | EXPORT_SYMBOL(rtc_set_time); | 775 | EXPORT_SYMBOL(rtc_mips_set_time); |
| 776 | EXPORT_SYMBOL(rtc_get_time); | 776 | EXPORT_SYMBOL(rtc_mips_get_time); |
| 777 | 777 | ||
| 778 | unsigned long long sched_clock(void) | 778 | unsigned long long sched_clock(void) |
| 779 | { | 779 | { |
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c index 83eb08b7a072..bb70a8240e61 100644 --- a/arch/mips/lasat/setup.c +++ b/arch/mips/lasat/setup.c | |||
| @@ -165,7 +165,8 @@ void __init plat_setup(void) | |||
| 165 | 165 | ||
| 166 | /* Set up panic notifier */ | 166 | /* Set up panic notifier */ |
| 167 | for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++) | 167 | for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++) |
| 168 | notifier_chain_register(&panic_notifier_list, &lasat_panic_block[i]); | 168 | atomic_notifier_chain_register(&panic_notifier_list, |
| 169 | &lasat_panic_block[i]); | ||
| 169 | 170 | ||
| 170 | lasat_reboot_setup(); | 171 | lasat_reboot_setup(); |
| 171 | 172 | ||
| @@ -174,8 +175,8 @@ void __init plat_setup(void) | |||
| 174 | 175 | ||
| 175 | #ifdef CONFIG_DS1603 | 176 | #ifdef CONFIG_DS1603 |
| 176 | ds1603 = &ds_defs[mips_machtype]; | 177 | ds1603 = &ds_defs[mips_machtype]; |
| 177 | rtc_get_time = ds1603_read; | 178 | rtc_mips_get_time = ds1603_read; |
| 178 | rtc_set_time = ds1603_set; | 179 | rtc_mips_set_time = ds1603_set; |
| 179 | #endif | 180 | #endif |
| 180 | 181 | ||
| 181 | #ifdef DYNAMIC_SERIAL_INIT | 182 | #ifdef DYNAMIC_SERIAL_INIT |
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c index 873cf3141a31..c20d401ecf80 100644 --- a/arch/mips/mips-boards/atlas/atlas_setup.c +++ b/arch/mips/mips-boards/atlas/atlas_setup.c | |||
| @@ -65,7 +65,7 @@ void __init plat_setup(void) | |||
| 65 | 65 | ||
| 66 | board_time_init = mips_time_init; | 66 | board_time_init = mips_time_init; |
| 67 | board_timer_setup = mips_timer_setup; | 67 | board_timer_setup = mips_timer_setup; |
| 68 | rtc_get_time = mips_rtc_get_time; | 68 | rtc_mips_get_time = mips_rtc_get_time; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | static void __init serial_init(void) | 71 | static void __init serial_init(void) |
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c index ee5e70c95cf3..32c9210373ac 100644 --- a/arch/mips/mips-boards/generic/memory.c +++ b/arch/mips/mips-boards/generic/memory.c | |||
| @@ -49,9 +49,6 @@ static char *mtypes[3] = { | |||
| 49 | /* References to section boundaries */ | 49 | /* References to section boundaries */ |
| 50 | extern char _end; | 50 | extern char _end; |
| 51 | 51 | ||
| 52 | #define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) | ||
| 53 | |||
| 54 | |||
| 55 | struct prom_pmemblock * __init prom_getmdesc(void) | 52 | struct prom_pmemblock * __init prom_getmdesc(void) |
| 56 | { | 53 | { |
| 57 | char *memsize_str; | 54 | char *memsize_str; |
| @@ -109,10 +106,10 @@ struct prom_pmemblock * __init prom_getmdesc(void) | |||
| 109 | 106 | ||
| 110 | mdesc[3].type = yamon_dontuse; | 107 | mdesc[3].type = yamon_dontuse; |
| 111 | mdesc[3].base = 0x00100000; | 108 | mdesc[3].base = 0x00100000; |
| 112 | mdesc[3].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base; | 109 | mdesc[3].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[3].base; |
| 113 | 110 | ||
| 114 | mdesc[4].type = yamon_free; | 111 | mdesc[4].type = yamon_free; |
| 115 | mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end)); | 112 | mdesc[4].base = CPHYSADDR(PAGE_ALIGN(&_end)); |
| 116 | mdesc[4].size = memsize - mdesc[4].base; | 113 | mdesc[4].size = memsize - mdesc[4].base; |
| 117 | 114 | ||
| 118 | return &mdesc[0]; | 115 | return &mdesc[0]; |
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c index 2209e8a9de34..b8488aab6df1 100644 --- a/arch/mips/mips-boards/malta/malta_setup.c +++ b/arch/mips/mips-boards/malta/malta_setup.c | |||
| @@ -225,5 +225,5 @@ void __init plat_setup(void) | |||
| 225 | 225 | ||
| 226 | board_time_init = mips_time_init; | 226 | board_time_init = mips_time_init; |
| 227 | board_timer_setup = mips_timer_setup; | 227 | board_timer_setup = mips_timer_setup; |
| 228 | rtc_get_time = mips_rtc_get_time; | 228 | rtc_mips_get_time = mips_rtc_get_time; |
| 229 | } | 229 | } |
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mips-boards/sim/sim_mem.c index 1ec4e75656bd..e57f737bab10 100644 --- a/arch/mips/mips-boards/sim/sim_mem.c +++ b/arch/mips/mips-boards/sim/sim_mem.c | |||
| @@ -42,9 +42,6 @@ static char *mtypes[3] = { | |||
| 42 | /* References to section boundaries */ | 42 | /* References to section boundaries */ |
| 43 | extern char _end; | 43 | extern char _end; |
| 44 | 44 | ||
| 45 | #define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) | ||
| 46 | |||
| 47 | |||
| 48 | struct prom_pmemblock * __init prom_getmdesc(void) | 45 | struct prom_pmemblock * __init prom_getmdesc(void) |
| 49 | { | 46 | { |
| 50 | unsigned int memsize; | 47 | unsigned int memsize; |
| @@ -64,10 +61,10 @@ struct prom_pmemblock * __init prom_getmdesc(void) | |||
| 64 | 61 | ||
| 65 | mdesc[2].type = simmem_reserved; | 62 | mdesc[2].type = simmem_reserved; |
| 66 | mdesc[2].base = 0x00100000; | 63 | mdesc[2].base = 0x00100000; |
| 67 | mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base; | 64 | mdesc[2].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[2].base; |
| 68 | 65 | ||
| 69 | mdesc[3].type = simmem_free; | 66 | mdesc[3].type = simmem_free; |
| 70 | mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end)); | 67 | mdesc[3].base = CPHYSADDR(PAGE_ALIGN(&_end)); |
| 71 | mdesc[3].size = memsize - mdesc[3].base; | 68 | mdesc[3].size = memsize - mdesc[3].base; |
| 72 | 69 | ||
| 73 | return &mdesc[0]; | 70 | return &mdesc[0]; |
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 52f7d59fe612..ad89c442f299 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/highmem.h> | 25 | #include <linux/highmem.h> |
| 26 | #include <linux/swap.h> | 26 | #include <linux/swap.h> |
| 27 | #include <linux/proc_fs.h> | 27 | #include <linux/proc_fs.h> |
| 28 | #include <linux/pfn.h> | ||
| 28 | 29 | ||
| 29 | #include <asm/bootinfo.h> | 30 | #include <asm/bootinfo.h> |
| 30 | #include <asm/cachectl.h> | 31 | #include <asm/cachectl.h> |
| @@ -177,9 +178,6 @@ void __init paging_init(void) | |||
| 177 | free_area_init(zones_size); | 178 | free_area_init(zones_size); |
| 178 | } | 179 | } |
| 179 | 180 | ||
| 180 | #define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) | ||
| 181 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
| 182 | |||
| 183 | static inline int page_is_ram(unsigned long pagenr) | 181 | static inline int page_is_ram(unsigned long pagenr) |
| 184 | { | 182 | { |
| 185 | int i; | 183 | int i; |
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c index 3784c898db1a..91d9637143d7 100644 --- a/arch/mips/momentum/jaguar_atx/setup.c +++ b/arch/mips/momentum/jaguar_atx/setup.c | |||
| @@ -229,8 +229,8 @@ void momenco_time_init(void) | |||
| 229 | mips_hpt_frequency = cpu_clock / 2; | 229 | mips_hpt_frequency = cpu_clock / 2; |
| 230 | board_timer_setup = momenco_timer_setup; | 230 | board_timer_setup = momenco_timer_setup; |
| 231 | 231 | ||
| 232 | rtc_get_time = m48t37y_get_time; | 232 | rtc_mips_get_time = m48t37y_get_time; |
| 233 | rtc_set_time = m48t37y_set_time; | 233 | rtc_mips_set_time = m48t37y_set_time; |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | static struct resource mv_pci_io_mem0_resource = { | 236 | static struct resource mv_pci_io_mem0_resource = { |
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c index f95677f4f06f..370e75d0e75c 100644 --- a/arch/mips/momentum/ocelot_3/setup.c +++ b/arch/mips/momentum/ocelot_3/setup.c | |||
| @@ -58,6 +58,7 @@ | |||
| 58 | #include <linux/bootmem.h> | 58 | #include <linux/bootmem.h> |
| 59 | #include <linux/mv643xx.h> | 59 | #include <linux/mv643xx.h> |
| 60 | #include <linux/pm.h> | 60 | #include <linux/pm.h> |
| 61 | #include <linux/bcd.h> | ||
| 61 | 62 | ||
| 62 | #include <asm/time.h> | 63 | #include <asm/time.h> |
| 63 | #include <asm/page.h> | 64 | #include <asm/page.h> |
| @@ -131,9 +132,6 @@ void setup_wired_tlb_entries(void) | |||
| 131 | add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), (signed)0xfc000000, PM_16M); | 132 | add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), (signed)0xfc000000, PM_16M); |
| 132 | } | 133 | } |
| 133 | 134 | ||
| 134 | #define CONV_BCD_TO_BIN(val) (((val) & 0xf) + (((val) >> 4) * 10)) | ||
| 135 | #define CONV_BIN_TO_BCD(val) (((val) % 10) + (((val) / 10) << 4)) | ||
| 136 | |||
| 137 | unsigned long m48t37y_get_time(void) | 135 | unsigned long m48t37y_get_time(void) |
| 138 | { | 136 | { |
| 139 | unsigned int year, month, day, hour, min, sec; | 137 | unsigned int year, month, day, hour, min, sec; |
| @@ -143,16 +141,16 @@ unsigned long m48t37y_get_time(void) | |||
| 143 | /* stop the update */ | 141 | /* stop the update */ |
| 144 | rtc_base[0x7ff8] = 0x40; | 142 | rtc_base[0x7ff8] = 0x40; |
| 145 | 143 | ||
| 146 | year = CONV_BCD_TO_BIN(rtc_base[0x7fff]); | 144 | year = BCD2BIN(rtc_base[0x7fff]); |
| 147 | year += CONV_BCD_TO_BIN(rtc_base[0x7ff1]) * 100; | 145 | year += BCD2BIN(rtc_base[0x7ff1]) * 100; |
| 148 | 146 | ||
| 149 | month = CONV_BCD_TO_BIN(rtc_base[0x7ffe]); | 147 | month = BCD2BIN(rtc_base[0x7ffe]); |
| 150 | 148 | ||
| 151 | day = CONV_BCD_TO_BIN(rtc_base[0x7ffd]); | 149 | day = BCD2BIN(rtc_base[0x7ffd]); |
| 152 | 150 | ||
| 153 | hour = CONV_BCD_TO_BIN(rtc_base[0x7ffb]); | 151 | hour = BCD2BIN(rtc_base[0x7ffb]); |
| 154 | min = CONV_BCD_TO_BIN(rtc_base[0x7ffa]); | 152 | min = BCD2BIN(rtc_base[0x7ffa]); |
| 155 | sec = CONV_BCD_TO_BIN(rtc_base[0x7ff9]); | 153 | sec = BCD2BIN(rtc_base[0x7ff9]); |
| 156 | 154 | ||
| 157 | /* start the update */ | 155 | /* start the update */ |
| 158 | rtc_base[0x7ff8] = 0x00; | 156 | rtc_base[0x7ff8] = 0x00; |
| @@ -175,22 +173,22 @@ int m48t37y_set_time(unsigned long sec) | |||
| 175 | rtc_base[0x7ff8] = 0x80; | 173 | rtc_base[0x7ff8] = 0x80; |
| 176 | 174 | ||
| 177 | /* year */ | 175 | /* year */ |
| 178 | rtc_base[0x7fff] = CONV_BIN_TO_BCD(tm.tm_year % 100); | 176 | rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100); |
| 179 | rtc_base[0x7ff1] = CONV_BIN_TO_BCD(tm.tm_year / 100); | 177 | rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100); |
| 180 | 178 | ||
| 181 | /* month */ | 179 | /* month */ |
| 182 | rtc_base[0x7ffe] = CONV_BIN_TO_BCD(tm.tm_mon); | 180 | rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon); |
| 183 | 181 | ||
| 184 | /* day */ | 182 | /* day */ |
| 185 | rtc_base[0x7ffd] = CONV_BIN_TO_BCD(tm.tm_mday); | 183 | rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday); |
| 186 | 184 | ||
| 187 | /* hour/min/sec */ | 185 | /* hour/min/sec */ |
| 188 | rtc_base[0x7ffb] = CONV_BIN_TO_BCD(tm.tm_hour); | 186 | rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour); |
| 189 | rtc_base[0x7ffa] = CONV_BIN_TO_BCD(tm.tm_min); | 187 | rtc_base[0x7ffa] = BIN2BCD(tm.tm_min); |
| 190 | rtc_base[0x7ff9] = CONV_BIN_TO_BCD(tm.tm_sec); | 188 | rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec); |
| 191 | 189 | ||
| 192 | /* day of week -- not really used, but let's keep it up-to-date */ | 190 | /* day of week -- not really used, but let's keep it up-to-date */ |
| 193 | rtc_base[0x7ffc] = CONV_BIN_TO_BCD(tm.tm_wday + 1); | 191 | rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1); |
| 194 | 192 | ||
| 195 | /* disable writing */ | 193 | /* disable writing */ |
| 196 | rtc_base[0x7ff8] = 0x00; | 194 | rtc_base[0x7ff8] = 0x00; |
| @@ -215,8 +213,8 @@ void momenco_time_init(void) | |||
| 215 | mips_hpt_frequency = cpu_clock / 2; | 213 | mips_hpt_frequency = cpu_clock / 2; |
| 216 | board_timer_setup = momenco_timer_setup; | 214 | board_timer_setup = momenco_timer_setup; |
| 217 | 215 | ||
| 218 | rtc_get_time = m48t37y_get_time; | 216 | rtc_mips_get_time = m48t37y_get_time; |
| 219 | rtc_set_time = m48t37y_set_time; | 217 | rtc_mips_set_time = m48t37y_set_time; |
| 220 | } | 218 | } |
| 221 | 219 | ||
| 222 | /* | 220 | /* |
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c index bd02e60d037a..a3e6f5575592 100644 --- a/arch/mips/momentum/ocelot_c/setup.c +++ b/arch/mips/momentum/ocelot_c/setup.c | |||
| @@ -227,8 +227,8 @@ void momenco_time_init(void) | |||
| 227 | printk("momenco_time_init cpu_clock=%d\n", cpu_clock); | 227 | printk("momenco_time_init cpu_clock=%d\n", cpu_clock); |
| 228 | board_timer_setup = momenco_timer_setup; | 228 | board_timer_setup = momenco_timer_setup; |
| 229 | 229 | ||
| 230 | rtc_get_time = m48t37y_get_time; | 230 | rtc_mips_get_time = m48t37y_get_time; |
| 231 | rtc_set_time = m48t37y_set_time; | 231 | rtc_mips_set_time = m48t37y_set_time; |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | void __init plat_setup(void) | 234 | void __init plat_setup(void) |
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c index 8bce711575de..3f724d661bdb 100644 --- a/arch/mips/pmc-sierra/yosemite/setup.c +++ b/arch/mips/pmc-sierra/yosemite/setup.c | |||
| @@ -198,8 +198,8 @@ static void __init py_rtc_setup(void) | |||
| 198 | if (!m48t37_base) | 198 | if (!m48t37_base) |
| 199 | printk(KERN_ERR "Mapping the RTC failed\n"); | 199 | printk(KERN_ERR "Mapping the RTC failed\n"); |
| 200 | 200 | ||
| 201 | rtc_get_time = m48t37y_get_time; | 201 | rtc_mips_get_time = m48t37y_get_time; |
| 202 | rtc_set_time = m48t37y_set_time; | 202 | rtc_mips_set_time = m48t37y_set_time; |
| 203 | 203 | ||
| 204 | write_seqlock(&xtime_lock); | 204 | write_seqlock(&xtime_lock); |
| 205 | xtime.tv_sec = m48t37y_get_time(); | 205 | xtime.tv_sec = m48t37y_get_time(); |
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c index 92a3b3c15ed3..a9c58e067b53 100644 --- a/arch/mips/sgi-ip22/ip22-reset.c +++ b/arch/mips/sgi-ip22/ip22-reset.c | |||
| @@ -238,7 +238,7 @@ static int __init reboot_setup(void) | |||
| 238 | request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL); | 238 | request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL); |
| 239 | init_timer(&blink_timer); | 239 | init_timer(&blink_timer); |
| 240 | blink_timer.function = blink_timeout; | 240 | blink_timer.function = blink_timeout; |
| 241 | notifier_chain_register(&panic_notifier_list, &panic_block); | 241 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); |
| 242 | 242 | ||
| 243 | return 0; | 243 | return 0; |
| 244 | } | 244 | } |
diff --git a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c index b7300cc5c5ad..cca688ad64ad 100644 --- a/arch/mips/sgi-ip22/ip22-time.c +++ b/arch/mips/sgi-ip22/ip22-time.c | |||
| @@ -212,8 +212,8 @@ static void indy_timer_setup(struct irqaction *irq) | |||
| 212 | void __init ip22_time_init(void) | 212 | void __init ip22_time_init(void) |
| 213 | { | 213 | { |
| 214 | /* setup hookup functions */ | 214 | /* setup hookup functions */ |
| 215 | rtc_get_time = indy_rtc_get_time; | 215 | rtc_mips_get_time = indy_rtc_get_time; |
| 216 | rtc_set_time = indy_rtc_set_time; | 216 | rtc_mips_set_time = indy_rtc_set_time; |
| 217 | 217 | ||
| 218 | board_time_init = indy_time_init; | 218 | board_time_init = indy_time_init; |
| 219 | board_timer_setup = indy_timer_setup; | 219 | board_timer_setup = indy_timer_setup; |
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index e0d095daa5ed..6c00dce9f73f 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/nodemask.h> | 19 | #include <linux/nodemask.h> |
| 20 | #include <linux/swap.h> | 20 | #include <linux/swap.h> |
| 21 | #include <linux/bootmem.h> | 21 | #include <linux/bootmem.h> |
| 22 | #include <linux/pfn.h> | ||
| 22 | #include <asm/page.h> | 23 | #include <asm/page.h> |
| 23 | #include <asm/sections.h> | 24 | #include <asm/sections.h> |
| 24 | 25 | ||
| @@ -28,8 +29,6 @@ | |||
| 28 | #include <asm/sn/sn_private.h> | 29 | #include <asm/sn/sn_private.h> |
| 29 | 30 | ||
| 30 | 31 | ||
| 31 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | ||
| 32 | |||
| 33 | #define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT) | 32 | #define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT) |
| 34 | #define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT) | 33 | #define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT) |
| 35 | 34 | ||
diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index 0c948008b023..ab9d9cef089e 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c | |||
| @@ -193,7 +193,7 @@ static __init int ip32_reboot_setup(void) | |||
| 193 | 193 | ||
| 194 | init_timer(&blink_timer); | 194 | init_timer(&blink_timer); |
| 195 | blink_timer.function = blink_timeout; | 195 | blink_timer.function = blink_timeout; |
| 196 | notifier_chain_register(&panic_notifier_list, &panic_block); | 196 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); |
| 197 | 197 | ||
| 198 | request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL); | 198 | request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL); |
| 199 | 199 | ||
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c index 2f50c79b7887..a2dd8ae1ea8f 100644 --- a/arch/mips/sgi-ip32/ip32-setup.c +++ b/arch/mips/sgi-ip32/ip32-setup.c | |||
| @@ -91,8 +91,8 @@ void __init plat_setup(void) | |||
| 91 | { | 91 | { |
| 92 | board_be_init = ip32_be_init; | 92 | board_be_init = ip32_be_init; |
| 93 | 93 | ||
| 94 | rtc_get_time = mc146818_get_cmos_time; | 94 | rtc_mips_get_time = mc146818_get_cmos_time; |
| 95 | rtc_set_mmss = mc146818_set_rtc_mmss; | 95 | rtc_mips_set_mmss = mc146818_set_rtc_mmss; |
| 96 | 96 | ||
| 97 | board_time_init = ip32_time_init; | 97 | board_time_init = ip32_time_init; |
| 98 | board_timer_setup = ip32_timer_setup; | 98 | board_timer_setup = ip32_timer_setup; |
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c index b661d2425a36..4b5f74ff3edd 100644 --- a/arch/mips/sibyte/swarm/setup.c +++ b/arch/mips/sibyte/swarm/setup.c | |||
| @@ -121,14 +121,14 @@ void __init plat_setup(void) | |||
| 121 | 121 | ||
| 122 | if (xicor_probe()) { | 122 | if (xicor_probe()) { |
| 123 | printk("swarm setup: Xicor 1241 RTC detected.\n"); | 123 | printk("swarm setup: Xicor 1241 RTC detected.\n"); |
| 124 | rtc_get_time = xicor_get_time; | 124 | rtc_mips_get_time = xicor_get_time; |
| 125 | rtc_set_time = xicor_set_time; | 125 | rtc_mips_set_time = xicor_set_time; |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | if (m41t81_probe()) { | 128 | if (m41t81_probe()) { |
| 129 | printk("swarm setup: M41T81 RTC detected.\n"); | 129 | printk("swarm setup: M41T81 RTC detected.\n"); |
| 130 | rtc_get_time = m41t81_get_time; | 130 | rtc_mips_get_time = m41t81_get_time; |
| 131 | rtc_set_time = m41t81_set_time; | 131 | rtc_mips_set_time = m41t81_set_time; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | printk("This kernel optimized for " | 134 | printk("This kernel optimized for " |
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c index 1141fcd13a59..01ba6c581e3d 100644 --- a/arch/mips/sni/setup.c +++ b/arch/mips/sni/setup.c | |||
| @@ -164,8 +164,8 @@ static struct pci_controller sni_controller = { | |||
| 164 | 164 | ||
| 165 | static inline void sni_pcimt_time_init(void) | 165 | static inline void sni_pcimt_time_init(void) |
| 166 | { | 166 | { |
| 167 | rtc_get_time = mc146818_get_cmos_time; | 167 | rtc_mips_get_time = mc146818_get_cmos_time; |
| 168 | rtc_set_time = mc146818_set_rtc_mmss; | 168 | rtc_mips_set_time = mc146818_set_rtc_mmss; |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | void __init plat_setup(void) | 171 | void __init plat_setup(void) |
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c index 2ad6401d2af4..6dcf077f61a0 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c | |||
| @@ -1036,8 +1036,8 @@ toshiba_rbtx4927_time_init(void) | |||
| 1036 | 1036 | ||
| 1037 | #ifdef CONFIG_RTC_DS1742 | 1037 | #ifdef CONFIG_RTC_DS1742 |
| 1038 | 1038 | ||
| 1039 | rtc_get_time = rtc_ds1742_get_time; | 1039 | rtc_mips_get_time = rtc_ds1742_get_time; |
| 1040 | rtc_set_time = rtc_ds1742_set_time; | 1040 | rtc_mips_set_time = rtc_ds1742_set_time; |
| 1041 | 1041 | ||
| 1042 | TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, | 1042 | TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, |
| 1043 | ":rtc_ds1742_init()-\n"); | 1043 | ":rtc_ds1742_init()-\n"); |
diff --git a/arch/mips/tx4938/common/rtc_rx5c348.c b/arch/mips/tx4938/common/rtc_rx5c348.c index d249edbb6af4..07f782fc0725 100644 --- a/arch/mips/tx4938/common/rtc_rx5c348.c +++ b/arch/mips/tx4938/common/rtc_rx5c348.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/string.h> | 14 | #include <linux/string.h> |
| 15 | #include <linux/rtc.h> | 15 | #include <linux/rtc.h> |
| 16 | #include <linux/time.h> | 16 | #include <linux/time.h> |
| 17 | #include <linux/bcd.h> | ||
| 17 | #include <asm/time.h> | 18 | #include <asm/time.h> |
| 18 | #include <asm/tx4938/spi.h> | 19 | #include <asm/tx4938/spi.h> |
| 19 | 20 | ||
| @@ -77,17 +78,6 @@ spi_rtc_io(unsigned char *inbuf, unsigned char *outbuf, unsigned int count) | |||
| 77 | inbufs, incounts, outbufs, outcounts, 0); | 78 | inbufs, incounts, outbufs, outcounts, 0); |
| 78 | } | 79 | } |
| 79 | 80 | ||
| 80 | /* | ||
| 81 | * Conversion between binary and BCD. | ||
| 82 | */ | ||
| 83 | #ifndef BCD_TO_BIN | ||
| 84 | #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) | ||
| 85 | #endif | ||
| 86 | |||
| 87 | #ifndef BIN_TO_BCD | ||
| 88 | #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) | ||
| 89 | #endif | ||
| 90 | |||
| 91 | /* RTC-dependent code for time.c */ | 81 | /* RTC-dependent code for time.c */ |
| 92 | 82 | ||
| 93 | static int | 83 | static int |
| @@ -197,6 +187,6 @@ rtc_rx5c348_init(int chipid) | |||
| 197 | srtc_24h = 1; | 187 | srtc_24h = 1; |
| 198 | 188 | ||
| 199 | /* set the function pointers */ | 189 | /* set the function pointers */ |
| 200 | rtc_get_time = rtc_rx5c348_get_time; | 190 | rtc_mips_get_time = rtc_rx5c348_get_time; |
| 201 | rtc_set_time = rtc_rx5c348_set_time; | 191 | rtc_mips_set_time = rtc_rx5c348_set_time; |
| 202 | } | 192 | } |
diff --git a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c index 2a01fe1bdc98..0cea6958f427 100644 --- a/arch/parisc/kernel/pdc_chassis.c +++ b/arch/parisc/kernel/pdc_chassis.c | |||
| @@ -150,7 +150,8 @@ void __init parisc_pdc_chassis_init(void) | |||
| 150 | 150 | ||
| 151 | if (handle) { | 151 | if (handle) { |
| 152 | /* initialize panic notifier chain */ | 152 | /* initialize panic notifier chain */ |
| 153 | notifier_chain_register(&panic_notifier_list, &pdc_chassis_panic_block); | 153 | atomic_notifier_chain_register(&panic_notifier_list, |
| 154 | &pdc_chassis_panic_block); | ||
| 154 | 155 | ||
| 155 | /* initialize reboot notifier chain */ | 156 | /* initialize reboot notifier chain */ |
| 156 | register_reboot_notifier(&pdc_chassis_reboot_block); | 157 | register_reboot_notifier(&pdc_chassis_reboot_block); |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 2f3fdad35594..e20c1fae3423 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -579,7 +579,8 @@ void __init setup_arch(char **cmdline_p) | |||
| 579 | panic_timeout = 180; | 579 | panic_timeout = 180; |
| 580 | 580 | ||
| 581 | if (ppc_md.panic) | 581 | if (ppc_md.panic) |
| 582 | notifier_chain_register(&panic_notifier_list, &ppc64_panic_block); | 582 | atomic_notifier_chain_register(&panic_notifier_list, |
| 583 | &ppc64_panic_block); | ||
| 583 | 584 | ||
| 584 | init_mm.start_code = PAGE_OFFSET; | 585 | init_mm.start_code = PAGE_OFFSET; |
| 585 | init_mm.end_code = (unsigned long) _etext; | 586 | init_mm.end_code = (unsigned long) _etext; |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 98660aedeeb7..9763faab6739 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -74,19 +74,19 @@ EXPORT_SYMBOL(__debugger_dabr_match); | |||
| 74 | EXPORT_SYMBOL(__debugger_fault_handler); | 74 | EXPORT_SYMBOL(__debugger_fault_handler); |
| 75 | #endif | 75 | #endif |
| 76 | 76 | ||
| 77 | struct notifier_block *powerpc_die_chain; | 77 | ATOMIC_NOTIFIER_HEAD(powerpc_die_chain); |
| 78 | static DEFINE_SPINLOCK(die_notifier_lock); | ||
| 79 | 78 | ||
| 80 | int register_die_notifier(struct notifier_block *nb) | 79 | int register_die_notifier(struct notifier_block *nb) |
| 81 | { | 80 | { |
| 82 | int err = 0; | 81 | return atomic_notifier_chain_register(&powerpc_die_chain, nb); |
| 83 | unsigned long flags; | 82 | } |
| 83 | EXPORT_SYMBOL(register_die_notifier); | ||
| 84 | 84 | ||
| 85 | spin_lock_irqsave(&die_notifier_lock, flags); | 85 | int unregister_die_notifier(struct notifier_block *nb) |
| 86 | err = notifier_chain_register(&powerpc_die_chain, nb); | 86 | { |
| 87 | spin_unlock_irqrestore(&die_notifier_lock, flags); | 87 | return atomic_notifier_chain_unregister(&powerpc_die_chain, nb); |
| 88 | return err; | ||
| 89 | } | 88 | } |
| 89 | EXPORT_SYMBOL(unregister_die_notifier); | ||
| 90 | 90 | ||
| 91 | /* | 91 | /* |
| 92 | * Trap & Exception support | 92 | * Trap & Exception support |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index badac10d700c..5e435a9c3431 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
| @@ -195,7 +195,7 @@ void show_mem(void) | |||
| 195 | printk("Mem-info:\n"); | 195 | printk("Mem-info:\n"); |
| 196 | show_free_areas(); | 196 | show_free_areas(); |
| 197 | printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); | 197 | printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); |
| 198 | for_each_pgdat(pgdat) { | 198 | for_each_online_pgdat(pgdat) { |
| 199 | unsigned long flags; | 199 | unsigned long flags; |
| 200 | pgdat_resize_lock(pgdat, &flags); | 200 | pgdat_resize_lock(pgdat, &flags); |
| 201 | for (i = 0; i < pgdat->node_spanned_pages; i++) { | 201 | for (i = 0; i < pgdat->node_spanned_pages; i++) { |
| @@ -351,7 +351,7 @@ void __init mem_init(void) | |||
| 351 | max_mapnr = max_pfn; | 351 | max_mapnr = max_pfn; |
| 352 | totalram_pages += free_all_bootmem(); | 352 | totalram_pages += free_all_bootmem(); |
| 353 | #endif | 353 | #endif |
| 354 | for_each_pgdat(pgdat) { | 354 | for_each_online_pgdat(pgdat) { |
| 355 | for (i = 0; i < pgdat->node_spanned_pages; i++) { | 355 | for (i = 0; i < pgdat->node_spanned_pages; i++) { |
| 356 | if (!pfn_valid(pgdat->node_start_pfn + i)) | 356 | if (!pfn_valid(pgdat->node_start_pfn + i)) |
| 357 | continue; | 357 | continue; |
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index b3962c3a0348..5be40aa483fd 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
| @@ -103,7 +103,7 @@ spufs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 103 | 103 | ||
| 104 | static int | 104 | static int |
| 105 | spufs_new_file(struct super_block *sb, struct dentry *dentry, | 105 | spufs_new_file(struct super_block *sb, struct dentry *dentry, |
| 106 | struct file_operations *fops, int mode, | 106 | const struct file_operations *fops, int mode, |
| 107 | struct spu_context *ctx) | 107 | struct spu_context *ctx) |
| 108 | { | 108 | { |
| 109 | static struct inode_operations spufs_file_iops = { | 109 | static struct inode_operations spufs_file_iops = { |
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 12c6f689b1aa..7d7889026936 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c | |||
| @@ -120,33 +120,15 @@ int chrp_set_rtc_time(struct rtc_time *tmarg) | |||
| 120 | void chrp_get_rtc_time(struct rtc_time *tm) | 120 | void chrp_get_rtc_time(struct rtc_time *tm) |
| 121 | { | 121 | { |
| 122 | unsigned int year, mon, day, hour, min, sec; | 122 | unsigned int year, mon, day, hour, min, sec; |
| 123 | int uip, i; | ||
| 124 | 123 | ||
| 125 | /* The Linux interpretation of the CMOS clock register contents: | 124 | do { |
| 126 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
| 127 | * RTC registers show the second which has precisely just started. | ||
| 128 | * Let's hope other operating systems interpret the RTC the same way. | ||
| 129 | */ | ||
| 130 | |||
| 131 | /* Since the UIP flag is set for about 2.2 ms and the clock | ||
| 132 | * is typically written with a precision of 1 jiffy, trying | ||
| 133 | * to obtain a precision better than a few milliseconds is | ||
| 134 | * an illusion. Only consistency is interesting, this also | ||
| 135 | * allows to use the routine for /dev/rtc without a potential | ||
| 136 | * 1 second kernel busy loop triggered by any reader of /dev/rtc. | ||
| 137 | */ | ||
| 138 | |||
| 139 | for ( i = 0; i<1000000; i++) { | ||
| 140 | uip = chrp_cmos_clock_read(RTC_FREQ_SELECT); | ||
| 141 | sec = chrp_cmos_clock_read(RTC_SECONDS); | 125 | sec = chrp_cmos_clock_read(RTC_SECONDS); |
| 142 | min = chrp_cmos_clock_read(RTC_MINUTES); | 126 | min = chrp_cmos_clock_read(RTC_MINUTES); |
| 143 | hour = chrp_cmos_clock_read(RTC_HOURS); | 127 | hour = chrp_cmos_clock_read(RTC_HOURS); |
| 144 | day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH); | 128 | day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH); |
| 145 | mon = chrp_cmos_clock_read(RTC_MONTH); | 129 | mon = chrp_cmos_clock_read(RTC_MONTH); |
| 146 | year = chrp_cmos_clock_read(RTC_YEAR); | 130 | year = chrp_cmos_clock_read(RTC_YEAR); |
| 147 | uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT); | 131 | } while (sec != chrp_cmos_clock_read(RTC_SECONDS)); |
| 148 | if ((uip & RTC_UIP)==0) break; | ||
| 149 | } | ||
| 150 | 132 | ||
| 151 | if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | 133 | if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
| 152 | BCD_TO_BIN(sec); | 134 | BCD_TO_BIN(sec); |
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 5e6981d17379..b9a2b3d4bf33 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c | |||
| @@ -60,34 +60,14 @@ static void maple_clock_write(unsigned long val, int addr) | |||
| 60 | 60 | ||
| 61 | void maple_get_rtc_time(struct rtc_time *tm) | 61 | void maple_get_rtc_time(struct rtc_time *tm) |
| 62 | { | 62 | { |
| 63 | int uip, i; | 63 | do { |
| 64 | |||
| 65 | /* The Linux interpretation of the CMOS clock register contents: | ||
| 66 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
| 67 | * RTC registers show the second which has precisely just started. | ||
| 68 | * Let's hope other operating systems interpret the RTC the same way. | ||
| 69 | */ | ||
| 70 | |||
| 71 | /* Since the UIP flag is set for about 2.2 ms and the clock | ||
| 72 | * is typically written with a precision of 1 jiffy, trying | ||
| 73 | * to obtain a precision better than a few milliseconds is | ||
| 74 | * an illusion. Only consistency is interesting, this also | ||
| 75 | * allows to use the routine for /dev/rtc without a potential | ||
| 76 | * 1 second kernel busy loop triggered by any reader of /dev/rtc. | ||
| 77 | */ | ||
| 78 | |||
| 79 | for (i = 0; i<1000000; i++) { | ||
| 80 | uip = maple_clock_read(RTC_FREQ_SELECT); | ||
| 81 | tm->tm_sec = maple_clock_read(RTC_SECONDS); | 64 | tm->tm_sec = maple_clock_read(RTC_SECONDS); |
| 82 | tm->tm_min = maple_clock_read(RTC_MINUTES); | 65 | tm->tm_min = maple_clock_read(RTC_MINUTES); |
| 83 | tm->tm_hour = maple_clock_read(RTC_HOURS); | 66 | tm->tm_hour = maple_clock_read(RTC_HOURS); |
| 84 | tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH); | 67 | tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH); |
| 85 | tm->tm_mon = maple_clock_read(RTC_MONTH); | 68 | tm->tm_mon = maple_clock_read(RTC_MONTH); |
| 86 | tm->tm_year = maple_clock_read(RTC_YEAR); | 69 | tm->tm_year = maple_clock_read(RTC_YEAR); |
| 87 | uip |= maple_clock_read(RTC_FREQ_SELECT); | 70 | } while (tm->tm_sec != maple_clock_read(RTC_SECONDS)); |
| 88 | if ((uip & RTC_UIP)==0) | ||
| 89 | break; | ||
| 90 | } | ||
| 91 | 71 | ||
| 92 | if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY) | 72 | if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY) |
| 93 | || RTC_ALWAYS_BCD) { | 73 | || RTC_ALWAYS_BCD) { |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 86cfa6ecdcf3..5ad90676567a 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
| @@ -94,16 +94,16 @@ static struct device_node *derive_parent(const char *path) | |||
| 94 | return parent; | 94 | return parent; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | static struct notifier_block *pSeries_reconfig_chain; | 97 | static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); |
| 98 | 98 | ||
| 99 | int pSeries_reconfig_notifier_register(struct notifier_block *nb) | 99 | int pSeries_reconfig_notifier_register(struct notifier_block *nb) |
| 100 | { | 100 | { |
| 101 | return notifier_chain_register(&pSeries_reconfig_chain, nb); | 101 | return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) | 104 | void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) |
| 105 | { | 105 | { |
| 106 | notifier_chain_unregister(&pSeries_reconfig_chain, nb); | 106 | blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | static int pSeries_reconfig_add_node(const char *path, struct property *proplist) | 109 | static int pSeries_reconfig_add_node(const char *path, struct property *proplist) |
| @@ -131,7 +131,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist | |||
| 131 | goto out_err; | 131 | goto out_err; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | err = notifier_call_chain(&pSeries_reconfig_chain, | 134 | err = blocking_notifier_call_chain(&pSeries_reconfig_chain, |
| 135 | PSERIES_RECONFIG_ADD, np); | 135 | PSERIES_RECONFIG_ADD, np); |
| 136 | if (err == NOTIFY_BAD) { | 136 | if (err == NOTIFY_BAD) { |
| 137 | printk(KERN_ERR "Failed to add device node %s\n", path); | 137 | printk(KERN_ERR "Failed to add device node %s\n", path); |
| @@ -171,7 +171,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np) | |||
| 171 | 171 | ||
| 172 | remove_node_proc_entries(np); | 172 | remove_node_proc_entries(np); |
| 173 | 173 | ||
| 174 | notifier_call_chain(&pSeries_reconfig_chain, | 174 | blocking_notifier_call_chain(&pSeries_reconfig_chain, |
| 175 | PSERIES_RECONFIG_REMOVE, np); | 175 | PSERIES_RECONFIG_REMOVE, np); |
| 176 | of_detach_node(np); | 176 | of_detach_node(np); |
| 177 | 177 | ||
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c index 2f5c7650274f..9b84bffdefce 100644 --- a/arch/ppc/kernel/ppc_htab.c +++ b/arch/ppc/kernel/ppc_htab.c | |||
| @@ -52,7 +52,7 @@ static int ppc_htab_open(struct inode *inode, struct file *file) | |||
| 52 | return single_open(file, ppc_htab_show, NULL); | 52 | return single_open(file, ppc_htab_show, NULL); |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | struct file_operations ppc_htab_operations = { | 55 | const struct file_operations ppc_htab_operations = { |
| 56 | .open = ppc_htab_open, | 56 | .open = ppc_htab_open, |
| 57 | .read = seq_read, | 57 | .read = seq_read, |
| 58 | .llseek = seq_lseek, | 58 | .llseek = seq_lseek, |
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c index c8627770af13..51e06ad66168 100644 --- a/arch/ppc/platforms/chrp_time.c +++ b/arch/ppc/platforms/chrp_time.c | |||
| @@ -119,44 +119,28 @@ int chrp_set_rtc_time(unsigned long nowtime) | |||
| 119 | unsigned long chrp_get_rtc_time(void) | 119 | unsigned long chrp_get_rtc_time(void) |
| 120 | { | 120 | { |
| 121 | unsigned int year, mon, day, hour, min, sec; | 121 | unsigned int year, mon, day, hour, min, sec; |
| 122 | int uip, i; | ||
| 123 | 122 | ||
| 124 | /* The Linux interpretation of the CMOS clock register contents: | 123 | do { |
| 125 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
| 126 | * RTC registers show the second which has precisely just started. | ||
| 127 | * Let's hope other operating systems interpret the RTC the same way. | ||
| 128 | */ | ||
| 129 | |||
| 130 | /* Since the UIP flag is set for about 2.2 ms and the clock | ||
| 131 | * is typically written with a precision of 1 jiffy, trying | ||
| 132 | * to obtain a precision better than a few milliseconds is | ||
| 133 | * an illusion. Only consistency is interesting, this also | ||
| 134 | * allows to use the routine for /dev/rtc without a potential | ||
| 135 | * 1 second kernel busy loop triggered by any reader of /dev/rtc. | ||
| 136 | */ | ||
| 137 | |||
| 138 | for ( i = 0; i<1000000; i++) { | ||
| 139 | uip = chrp_cmos_clock_read(RTC_FREQ_SELECT); | ||
| 140 | sec = chrp_cmos_clock_read(RTC_SECONDS); | 124 | sec = chrp_cmos_clock_read(RTC_SECONDS); |
| 141 | min = chrp_cmos_clock_read(RTC_MINUTES); | 125 | min = chrp_cmos_clock_read(RTC_MINUTES); |
| 142 | hour = chrp_cmos_clock_read(RTC_HOURS); | 126 | hour = chrp_cmos_clock_read(RTC_HOURS); |
| 143 | day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH); | 127 | day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH); |
| 144 | mon = chrp_cmos_clock_read(RTC_MONTH); | 128 | mon = chrp_cmos_clock_read(RTC_MONTH); |
| 145 | year = chrp_cmos_clock_read(RTC_YEAR); | 129 | year = chrp_cmos_clock_read(RTC_YEAR); |
| 146 | uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT); | 130 | } while (sec != chrp_cmos_clock_read(RTC_SECONDS)); |
| 147 | if ((uip & RTC_UIP)==0) break; | 131 | |
| 132 | if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) | ||
| 133 | || RTC_ALWAYS_BCD) { | ||
| 134 | BCD_TO_BIN(sec); | ||
| 135 | BCD_TO_BIN(min); | ||
| 136 | BCD_TO_BIN(hour); | ||
| 137 | BCD_TO_BIN(day); | ||
| 138 | BCD_TO_BIN(mon); | ||
| 139 | BCD_TO_BIN(year); | ||
| 148 | } | 140 | } |
| 149 | 141 | ||
| 150 | if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | 142 | year += 1900; |
| 151 | { | 143 | if (year < 1970) |
| 152 | BCD_TO_BIN(sec); | ||
| 153 | BCD_TO_BIN(min); | ||
| 154 | BCD_TO_BIN(hour); | ||
| 155 | BCD_TO_BIN(day); | ||
| 156 | BCD_TO_BIN(mon); | ||
| 157 | BCD_TO_BIN(year); | ||
| 158 | } | ||
| 159 | if ((year += 1900) < 1970) | ||
| 160 | year += 100; | 144 | year += 100; |
| 161 | return mktime(year, mon, day, hour, min, sec); | 145 | return mktime(year, mon, day, hour, min, sec); |
| 162 | } | 146 | } |
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c index a0fc628ffb1e..d95c05d9824d 100644 --- a/arch/ppc/platforms/prep_setup.c +++ b/arch/ppc/platforms/prep_setup.c | |||
| @@ -736,7 +736,7 @@ ibm_statusled_progress(char *s, unsigned short hex) | |||
| 736 | hex = 0xfff; | 736 | hex = 0xfff; |
| 737 | if (!notifier_installed) { | 737 | if (!notifier_installed) { |
| 738 | ++notifier_installed; | 738 | ++notifier_installed; |
| 739 | notifier_chain_register(&panic_notifier_list, | 739 | atomic_notifier_chain_register(&panic_notifier_list, |
| 740 | &ibm_statusled_block); | 740 | &ibm_statusled_block); |
| 741 | } | 741 | } |
| 742 | } | 742 | } |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 99182a415fe7..4a0f5a1551ea 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
| @@ -76,17 +76,17 @@ unsigned long thread_saved_pc(struct task_struct *tsk) | |||
| 76 | /* | 76 | /* |
| 77 | * Need to know about CPUs going idle? | 77 | * Need to know about CPUs going idle? |
| 78 | */ | 78 | */ |
| 79 | static struct notifier_block *idle_chain; | 79 | static ATOMIC_NOTIFIER_HEAD(idle_chain); |
| 80 | 80 | ||
| 81 | int register_idle_notifier(struct notifier_block *nb) | 81 | int register_idle_notifier(struct notifier_block *nb) |
| 82 | { | 82 | { |
| 83 | return notifier_chain_register(&idle_chain, nb); | 83 | return atomic_notifier_chain_register(&idle_chain, nb); |
| 84 | } | 84 | } |
| 85 | EXPORT_SYMBOL(register_idle_notifier); | 85 | EXPORT_SYMBOL(register_idle_notifier); |
| 86 | 86 | ||
| 87 | int unregister_idle_notifier(struct notifier_block *nb) | 87 | int unregister_idle_notifier(struct notifier_block *nb) |
| 88 | { | 88 | { |
| 89 | return notifier_chain_unregister(&idle_chain, nb); | 89 | return atomic_notifier_chain_unregister(&idle_chain, nb); |
| 90 | } | 90 | } |
| 91 | EXPORT_SYMBOL(unregister_idle_notifier); | 91 | EXPORT_SYMBOL(unregister_idle_notifier); |
| 92 | 92 | ||
| @@ -95,7 +95,7 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code) | |||
| 95 | /* disable monitor call class 0 */ | 95 | /* disable monitor call class 0 */ |
| 96 | __ctl_clear_bit(8, 15); | 96 | __ctl_clear_bit(8, 15); |
| 97 | 97 | ||
| 98 | notifier_call_chain(&idle_chain, CPU_NOT_IDLE, | 98 | atomic_notifier_call_chain(&idle_chain, CPU_NOT_IDLE, |
| 99 | (void *)(long) smp_processor_id()); | 99 | (void *)(long) smp_processor_id()); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| @@ -116,7 +116,8 @@ static void default_idle(void) | |||
| 116 | return; | 116 | return; |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | rc = notifier_call_chain(&idle_chain, CPU_IDLE, (void *)(long) cpu); | 119 | rc = atomic_notifier_call_chain(&idle_chain, |
| 120 | CPU_IDLE, (void *)(long) cpu); | ||
| 120 | if (rc != NOTIFY_OK && rc != NOTIFY_DONE) | 121 | if (rc != NOTIFY_OK && rc != NOTIFY_DONE) |
| 121 | BUG(); | 122 | BUG(); |
| 122 | if (rc != NOTIFY_OK) { | 123 | if (rc != NOTIFY_OK) { |
diff --git a/arch/sh/boards/mpc1211/rtc.c b/arch/sh/boards/mpc1211/rtc.c index 4d100f048072..a76c655dceee 100644 --- a/arch/sh/boards/mpc1211/rtc.c +++ b/arch/sh/boards/mpc1211/rtc.c | |||
| @@ -9,36 +9,16 @@ | |||
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
| 11 | #include <linux/time.h> | 11 | #include <linux/time.h> |
| 12 | #include <linux/bcd.h> | ||
| 12 | #include <linux/mc146818rtc.h> | 13 | #include <linux/mc146818rtc.h> |
| 13 | 14 | ||
| 14 | #ifndef BCD_TO_BIN | ||
| 15 | #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) | ||
| 16 | #endif | ||
| 17 | |||
| 18 | #ifndef BIN_TO_BCD | ||
| 19 | #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) | ||
| 20 | #endif | ||
| 21 | |||
| 22 | /* arc/i386/kernel/time.c */ | ||
| 23 | unsigned long get_cmos_time(void) | 15 | unsigned long get_cmos_time(void) |
| 24 | { | 16 | { |
| 25 | unsigned int year, mon, day, hour, min, sec; | 17 | unsigned int year, mon, day, hour, min, sec; |
| 26 | int i; | ||
| 27 | 18 | ||
| 28 | spin_lock(&rtc_lock); | 19 | spin_lock(&rtc_lock); |
| 29 | /* The Linux interpretation of the CMOS clock register contents: | 20 | |
| 30 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | 21 | do { |
| 31 | * RTC registers show the second which has precisely just started. | ||
| 32 | * Let's hope other operating systems interpret the RTC the same way. | ||
| 33 | */ | ||
| 34 | /* read RTC exactly on falling edge of update flag */ | ||
| 35 | for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ | ||
| 36 | if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) | ||
| 37 | break; | ||
| 38 | for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ | ||
| 39 | if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) | ||
| 40 | break; | ||
| 41 | do { /* Isn't this overkill ? UIP above should guarantee consistency */ | ||
| 42 | sec = CMOS_READ(RTC_SECONDS); | 22 | sec = CMOS_READ(RTC_SECONDS); |
| 43 | min = CMOS_READ(RTC_MINUTES); | 23 | min = CMOS_READ(RTC_MINUTES); |
| 44 | hour = CMOS_READ(RTC_HOURS); | 24 | hour = CMOS_READ(RTC_HOURS); |
| @@ -46,18 +26,22 @@ unsigned long get_cmos_time(void) | |||
| 46 | mon = CMOS_READ(RTC_MONTH); | 26 | mon = CMOS_READ(RTC_MONTH); |
| 47 | year = CMOS_READ(RTC_YEAR); | 27 | year = CMOS_READ(RTC_YEAR); |
| 48 | } while (sec != CMOS_READ(RTC_SECONDS)); | 28 | } while (sec != CMOS_READ(RTC_SECONDS)); |
| 49 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | 29 | |
| 50 | { | 30 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
| 51 | BCD_TO_BIN(sec); | 31 | BCD_TO_BIN(sec); |
| 52 | BCD_TO_BIN(min); | 32 | BCD_TO_BIN(min); |
| 53 | BCD_TO_BIN(hour); | 33 | BCD_TO_BIN(hour); |
| 54 | BCD_TO_BIN(day); | 34 | BCD_TO_BIN(day); |
| 55 | BCD_TO_BIN(mon); | 35 | BCD_TO_BIN(mon); |
| 56 | BCD_TO_BIN(year); | 36 | BCD_TO_BIN(year); |
| 57 | } | 37 | } |
| 38 | |||
| 58 | spin_unlock(&rtc_lock); | 39 | spin_unlock(&rtc_lock); |
| 59 | if ((year += 1900) < 1970) | 40 | |
| 41 | year += 1900; | ||
| 42 | if (year < 1970) | ||
| 60 | year += 100; | 43 | year += 100; |
| 44 | |||
| 61 | return mktime(year, mon, day, hour, min, sec); | 45 | return mktime(year, mon, day, hour, min, sec); |
| 62 | } | 46 | } |
| 63 | 47 | ||
diff --git a/arch/sh/boards/sh03/rtc.c b/arch/sh/boards/sh03/rtc.c index cbeca7037ba5..d609863cfe53 100644 --- a/arch/sh/boards/sh03/rtc.c +++ b/arch/sh/boards/sh03/rtc.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
| 11 | #include <linux/time.h> | 11 | #include <linux/time.h> |
| 12 | #include <linux/bcd.h> | ||
| 12 | #include <asm/io.h> | 13 | #include <asm/io.h> |
| 13 | #include <linux/rtc.h> | 14 | #include <linux/rtc.h> |
| 14 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
| @@ -33,14 +34,6 @@ | |||
| 33 | #define RTC_BUSY 1 | 34 | #define RTC_BUSY 1 |
| 34 | #define RTC_STOP 2 | 35 | #define RTC_STOP 2 |
| 35 | 36 | ||
| 36 | #ifndef BCD_TO_BIN | ||
| 37 | #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) | ||
| 38 | #endif | ||
| 39 | |||
| 40 | #ifndef BIN_TO_BCD | ||
| 41 | #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) | ||
| 42 | #endif | ||
| 43 | |||
| 44 | extern void (*rtc_get_time)(struct timespec *); | 37 | extern void (*rtc_get_time)(struct timespec *); |
| 45 | extern int (*rtc_set_time)(const time_t); | 38 | extern int (*rtc_set_time)(const time_t); |
| 46 | extern spinlock_t rtc_lock; | 39 | extern spinlock_t rtc_lock; |
| @@ -48,13 +41,9 @@ extern spinlock_t rtc_lock; | |||
| 48 | unsigned long get_cmos_time(void) | 41 | unsigned long get_cmos_time(void) |
| 49 | { | 42 | { |
| 50 | unsigned int year, mon, day, hour, min, sec; | 43 | unsigned int year, mon, day, hour, min, sec; |
| 51 | int i; | ||
| 52 | 44 | ||
| 53 | spin_lock(&rtc_lock); | 45 | spin_lock(&rtc_lock); |
| 54 | again: | 46 | again: |
| 55 | for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ | ||
| 56 | if (!(ctrl_inb(RTC_CTL) & RTC_BUSY)) | ||
| 57 | break; | ||
| 58 | do { | 47 | do { |
| 59 | sec = (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10; | 48 | sec = (ctrl_inb(RTC_SEC1) & 0xf) + (ctrl_inb(RTC_SEC10) & 0x7) * 10; |
| 60 | min = (ctrl_inb(RTC_MIN1) & 0xf) + (ctrl_inb(RTC_MIN10) & 0xf) * 10; | 49 | min = (ctrl_inb(RTC_MIN1) & 0xf) + (ctrl_inb(RTC_MIN10) & 0xf) * 10; |
diff --git a/arch/sh/kernel/cpu/rtc.c b/arch/sh/kernel/cpu/rtc.c index f8361f5e788b..4304cf75cfa2 100644 --- a/arch/sh/kernel/cpu/rtc.c +++ b/arch/sh/kernel/cpu/rtc.c | |||
| @@ -9,18 +9,10 @@ | |||
| 9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| 10 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
| 11 | #include <linux/time.h> | 11 | #include <linux/time.h> |
| 12 | 12 | #include <linux/bcd.h> | |
| 13 | #include <asm/io.h> | 13 | #include <asm/io.h> |
| 14 | #include <asm/rtc.h> | 14 | #include <asm/rtc.h> |
| 15 | 15 | ||
| 16 | #ifndef BCD_TO_BIN | ||
| 17 | #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) | ||
| 18 | #endif | ||
| 19 | |||
| 20 | #ifndef BIN_TO_BCD | ||
| 21 | #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) | ||
| 22 | #endif | ||
| 23 | |||
| 24 | void sh_rtc_gettimeofday(struct timespec *ts) | 16 | void sh_rtc_gettimeofday(struct timespec *ts) |
| 25 | { | 17 | { |
| 26 | unsigned int sec128, sec, sec2, min, hr, wk, day, mon, yr, yr100, cf_bit; | 18 | unsigned int sec128, sec, sec2, min, hr, wk, day, mon, yr, yr100, cf_bit; |
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index c0e79843f580..7ee4ca203616 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/root_dev.h> | 20 | #include <linux/root_dev.h> |
| 21 | #include <linux/utsname.h> | 21 | #include <linux/utsname.h> |
| 22 | #include <linux/cpu.h> | 22 | #include <linux/cpu.h> |
| 23 | #include <linux/pfn.h> | ||
| 23 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
| 24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
| 25 | #include <asm/sections.h> | 26 | #include <asm/sections.h> |
| @@ -275,10 +276,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 275 | 276 | ||
| 276 | sh_mv_setup(cmdline_p); | 277 | sh_mv_setup(cmdline_p); |
| 277 | 278 | ||
| 278 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | ||
| 279 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
| 280 | #define PFN_PHYS(x) ((x) << PAGE_SHIFT) | ||
| 281 | |||
| 282 | /* | 279 | /* |
| 283 | * Find the highest page frame number we have available | 280 | * Find the highest page frame number we have available |
| 284 | */ | 281 | */ |
diff --git a/arch/sh64/kernel/setup.c b/arch/sh64/kernel/setup.c index c7a7b816a30f..d2711c9c9d13 100644 --- a/arch/sh64/kernel/setup.c +++ b/arch/sh64/kernel/setup.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | #include <linux/root_dev.h> | 48 | #include <linux/root_dev.h> |
| 49 | #include <linux/cpu.h> | 49 | #include <linux/cpu.h> |
| 50 | #include <linux/initrd.h> | 50 | #include <linux/initrd.h> |
| 51 | #include <linux/pfn.h> | ||
| 51 | #include <asm/processor.h> | 52 | #include <asm/processor.h> |
| 52 | #include <asm/page.h> | 53 | #include <asm/page.h> |
| 53 | #include <asm/pgtable.h> | 54 | #include <asm/pgtable.h> |
diff --git a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c index 0773c9f389f3..6b8f4d22abc6 100644 --- a/arch/sh64/kernel/time.c +++ b/arch/sh64/kernel/time.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/profile.h> | 30 | #include <linux/profile.h> |
| 31 | #include <linux/smp.h> | 31 | #include <linux/smp.h> |
| 32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
| 33 | #include <linux/bcd.h> | ||
| 33 | 34 | ||
| 34 | #include <asm/registers.h> /* required by inline __asm__ stmt. */ | 35 | #include <asm/registers.h> /* required by inline __asm__ stmt. */ |
| 35 | 36 | ||
| @@ -105,14 +106,6 @@ | |||
| 105 | #define RCR1 rtc_base+0x38 | 106 | #define RCR1 rtc_base+0x38 |
| 106 | #define RCR2 rtc_base+0x3c | 107 | #define RCR2 rtc_base+0x3c |
| 107 | 108 | ||
| 108 | #ifndef BCD_TO_BIN | ||
| 109 | #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) | ||
| 110 | #endif | ||
| 111 | |||
| 112 | #ifndef BIN_TO_BCD | ||
| 113 | #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) | ||
| 114 | #endif | ||
| 115 | |||
| 116 | #define TICK_SIZE (tick_nsec / 1000) | 109 | #define TICK_SIZE (tick_nsec / 1000) |
| 117 | 110 | ||
| 118 | extern unsigned long wall_jiffies; | 111 | extern unsigned long wall_jiffies; |
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 7d61f1bfd3d3..e55b5c6ece02 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
| @@ -641,23 +641,8 @@ static void __init set_system_time(void) | |||
| 641 | mon = MSTK_REG_MONTH(mregs); | 641 | mon = MSTK_REG_MONTH(mregs); |
| 642 | year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); | 642 | year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); |
| 643 | } else { | 643 | } else { |
| 644 | int i; | ||
| 645 | |||
| 646 | /* Dallas 12887 RTC chip. */ | 644 | /* Dallas 12887 RTC chip. */ |
| 647 | 645 | ||
| 648 | /* Stolen from arch/i386/kernel/time.c, see there for | ||
| 649 | * credits and descriptive comments. | ||
| 650 | */ | ||
| 651 | for (i = 0; i < 1000000; i++) { | ||
| 652 | if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) | ||
| 653 | break; | ||
| 654 | udelay(10); | ||
| 655 | } | ||
| 656 | for (i = 0; i < 1000000; i++) { | ||
| 657 | if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) | ||
| 658 | break; | ||
| 659 | udelay(10); | ||
| 660 | } | ||
| 661 | do { | 646 | do { |
| 662 | sec = CMOS_READ(RTC_SECONDS); | 647 | sec = CMOS_READ(RTC_SECONDS); |
| 663 | min = CMOS_READ(RTC_MINUTES); | 648 | min = CMOS_READ(RTC_MINUTES); |
| @@ -666,6 +651,7 @@ static void __init set_system_time(void) | |||
| 666 | mon = CMOS_READ(RTC_MONTH); | 651 | mon = CMOS_READ(RTC_MONTH); |
| 667 | year = CMOS_READ(RTC_YEAR); | 652 | year = CMOS_READ(RTC_YEAR); |
| 668 | } while (sec != CMOS_READ(RTC_SECONDS)); | 653 | } while (sec != CMOS_READ(RTC_SECONDS)); |
| 654 | |||
| 669 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | 655 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
| 670 | BCD_TO_BIN(sec); | 656 | BCD_TO_BIN(sec); |
| 671 | BCD_TO_BIN(min); | 657 | BCD_TO_BIN(min); |
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index df612e4f75f9..ff090bb9734b 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c | |||
| @@ -43,18 +43,19 @@ | |||
| 43 | #include <linux/kmod.h> | 43 | #include <linux/kmod.h> |
| 44 | #endif | 44 | #endif |
| 45 | 45 | ||
| 46 | struct notifier_block *sparc64die_chain; | 46 | ATOMIC_NOTIFIER_HEAD(sparc64die_chain); |
| 47 | static DEFINE_SPINLOCK(die_notifier_lock); | ||
| 48 | 47 | ||
| 49 | int register_die_notifier(struct notifier_block *nb) | 48 | int register_die_notifier(struct notifier_block *nb) |
| 50 | { | 49 | { |
| 51 | int err = 0; | 50 | return atomic_notifier_chain_register(&sparc64die_chain, nb); |
| 52 | unsigned long flags; | ||
| 53 | spin_lock_irqsave(&die_notifier_lock, flags); | ||
| 54 | err = notifier_chain_register(&sparc64die_chain, nb); | ||
| 55 | spin_unlock_irqrestore(&die_notifier_lock, flags); | ||
| 56 | return err; | ||
| 57 | } | 51 | } |
| 52 | EXPORT_SYMBOL(register_die_notifier); | ||
| 53 | |||
| 54 | int unregister_die_notifier(struct notifier_block *nb) | ||
| 55 | { | ||
| 56 | return atomic_notifier_chain_unregister(&sparc64die_chain, nb); | ||
| 57 | } | ||
| 58 | EXPORT_SYMBOL(unregister_die_notifier); | ||
| 58 | 59 | ||
| 59 | /* When an irrecoverable trap occurs at tl > 0, the trap entry | 60 | /* When an irrecoverable trap occurs at tl > 0, the trap entry |
| 60 | * code logs the trap state registers at every level in the trap | 61 | * code logs the trap state registers at every level in the trap |
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index d21ff3230c02..0db2f7d9fab5 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c | |||
| @@ -413,12 +413,12 @@ good_area: | |||
| 413 | #ifdef CONFIG_HUGETLB_PAGE | 413 | #ifdef CONFIG_HUGETLB_PAGE |
| 414 | mm_rss -= (mm->context.huge_pte_count * (HPAGE_SIZE / PAGE_SIZE)); | 414 | mm_rss -= (mm->context.huge_pte_count * (HPAGE_SIZE / PAGE_SIZE)); |
| 415 | #endif | 415 | #endif |
| 416 | if (unlikely(mm_rss >= | 416 | if (unlikely(mm_rss > |
| 417 | mm->context.tsb_block[MM_TSB_BASE].tsb_rss_limit)) | 417 | mm->context.tsb_block[MM_TSB_BASE].tsb_rss_limit)) |
| 418 | tsb_grow(mm, MM_TSB_BASE, mm_rss); | 418 | tsb_grow(mm, MM_TSB_BASE, mm_rss); |
| 419 | #ifdef CONFIG_HUGETLB_PAGE | 419 | #ifdef CONFIG_HUGETLB_PAGE |
| 420 | mm_rss = mm->context.huge_pte_count; | 420 | mm_rss = mm->context.huge_pte_count; |
| 421 | if (unlikely(mm_rss >= | 421 | if (unlikely(mm_rss > |
| 422 | mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit)) | 422 | mm->context.tsb_block[MM_TSB_HUGE].tsb_rss_limit)) |
| 423 | tsb_grow(mm, MM_TSB_HUGE, mm_rss); | 423 | tsb_grow(mm, MM_TSB_HUGE, mm_rss); |
| 424 | #endif | 424 | #endif |
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index 54388d10bcf9..1488816588ea 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
| @@ -762,7 +762,8 @@ static struct notifier_block panic_exit_notifier = { | |||
| 762 | 762 | ||
| 763 | static int add_notifier(void) | 763 | static int add_notifier(void) |
| 764 | { | 764 | { |
| 765 | notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); | 765 | atomic_notifier_chain_register(&panic_notifier_list, |
| 766 | &panic_exit_notifier); | ||
| 766 | return(0); | 767 | return(0); |
| 767 | } | 768 | } |
| 768 | 769 | ||
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index fa617e0719ab..0336575d2448 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) |
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| @@ -71,7 +71,7 @@ struct io_thread_req { | |||
| 71 | int error; | 71 | int error; |
| 72 | }; | 72 | }; |
| 73 | 73 | ||
| 74 | extern int open_ubd_file(char *file, struct openflags *openflags, | 74 | extern int open_ubd_file(char *file, struct openflags *openflags, int shared, |
| 75 | char **backing_file_out, int *bitmap_offset_out, | 75 | char **backing_file_out, int *bitmap_offset_out, |
| 76 | unsigned long *bitmap_len_out, int *data_offset_out, | 76 | unsigned long *bitmap_len_out, int *data_offset_out, |
| 77 | int *create_cow_out); | 77 | int *create_cow_out); |
| @@ -137,7 +137,7 @@ static int fake_major = MAJOR_NR; | |||
| 137 | 137 | ||
| 138 | static struct gendisk *ubd_gendisk[MAX_DEV]; | 138 | static struct gendisk *ubd_gendisk[MAX_DEV]; |
| 139 | static struct gendisk *fake_gendisk[MAX_DEV]; | 139 | static struct gendisk *fake_gendisk[MAX_DEV]; |
| 140 | 140 | ||
| 141 | #ifdef CONFIG_BLK_DEV_UBD_SYNC | 141 | #ifdef CONFIG_BLK_DEV_UBD_SYNC |
| 142 | #define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 1, .c = 0, \ | 142 | #define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 1, .c = 0, \ |
| 143 | .cl = 1 }) | 143 | .cl = 1 }) |
| @@ -168,6 +168,7 @@ struct ubd { | |||
| 168 | __u64 size; | 168 | __u64 size; |
| 169 | struct openflags boot_openflags; | 169 | struct openflags boot_openflags; |
| 170 | struct openflags openflags; | 170 | struct openflags openflags; |
| 171 | int shared; | ||
| 171 | int no_cow; | 172 | int no_cow; |
| 172 | struct cow cow; | 173 | struct cow cow; |
| 173 | struct platform_device pdev; | 174 | struct platform_device pdev; |
| @@ -189,6 +190,7 @@ struct ubd { | |||
| 189 | .boot_openflags = OPEN_FLAGS, \ | 190 | .boot_openflags = OPEN_FLAGS, \ |
| 190 | .openflags = OPEN_FLAGS, \ | 191 | .openflags = OPEN_FLAGS, \ |
| 191 | .no_cow = 0, \ | 192 | .no_cow = 0, \ |
| 193 | .shared = 0, \ | ||
| 192 | .cow = DEFAULT_COW, \ | 194 | .cow = DEFAULT_COW, \ |
| 193 | } | 195 | } |
| 194 | 196 | ||
| @@ -305,7 +307,7 @@ static int ubd_setup_common(char *str, int *index_out) | |||
| 305 | } | 307 | } |
| 306 | major = simple_strtoul(str, &end, 0); | 308 | major = simple_strtoul(str, &end, 0); |
| 307 | if((*end != '\0') || (end == str)){ | 309 | if((*end != '\0') || (end == str)){ |
| 308 | printk(KERN_ERR | 310 | printk(KERN_ERR |
| 309 | "ubd_setup : didn't parse major number\n"); | 311 | "ubd_setup : didn't parse major number\n"); |
| 310 | return(1); | 312 | return(1); |
| 311 | } | 313 | } |
| @@ -316,7 +318,7 @@ static int ubd_setup_common(char *str, int *index_out) | |||
| 316 | printk(KERN_ERR "Can't assign a fake major twice\n"); | 318 | printk(KERN_ERR "Can't assign a fake major twice\n"); |
| 317 | goto out1; | 319 | goto out1; |
| 318 | } | 320 | } |
| 319 | 321 | ||
| 320 | fake_major = major; | 322 | fake_major = major; |
| 321 | 323 | ||
| 322 | printk(KERN_INFO "Setting extra ubd major number to %d\n", | 324 | printk(KERN_INFO "Setting extra ubd major number to %d\n", |
| @@ -351,7 +353,7 @@ static int ubd_setup_common(char *str, int *index_out) | |||
| 351 | if (index_out) | 353 | if (index_out) |
| 352 | *index_out = n; | 354 | *index_out = n; |
| 353 | 355 | ||
| 354 | for (i = 0; i < 4; i++) { | 356 | for (i = 0; i < sizeof("rscd="); i++) { |
| 355 | switch (*str) { | 357 | switch (*str) { |
| 356 | case 'r': | 358 | case 'r': |
| 357 | flags.w = 0; | 359 | flags.w = 0; |
| @@ -362,11 +364,14 @@ static int ubd_setup_common(char *str, int *index_out) | |||
| 362 | case 'd': | 364 | case 'd': |
| 363 | dev->no_cow = 1; | 365 | dev->no_cow = 1; |
| 364 | break; | 366 | break; |
| 367 | case 'c': | ||
| 368 | dev->shared = 1; | ||
| 369 | break; | ||
| 365 | case '=': | 370 | case '=': |
| 366 | str++; | 371 | str++; |
| 367 | goto break_loop; | 372 | goto break_loop; |
| 368 | default: | 373 | default: |
| 369 | printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r,s or d)\n"); | 374 | printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r, s, c, or d)\n"); |
| 370 | goto out; | 375 | goto out; |
| 371 | } | 376 | } |
| 372 | str++; | 377 | str++; |
| @@ -515,7 +520,7 @@ static void ubd_handler(void) | |||
| 515 | spin_unlock(&ubd_io_lock); | 520 | spin_unlock(&ubd_io_lock); |
| 516 | return; | 521 | return; |
| 517 | } | 522 | } |
| 518 | 523 | ||
| 519 | ubd_finish(rq, req.error); | 524 | ubd_finish(rq, req.error); |
| 520 | reactivate_fd(thread_fd, UBD_IRQ); | 525 | reactivate_fd(thread_fd, UBD_IRQ); |
| 521 | do_ubd_request(ubd_queue); | 526 | do_ubd_request(ubd_queue); |
| @@ -532,7 +537,7 @@ static int io_pid = -1; | |||
| 532 | 537 | ||
| 533 | void kill_io_thread(void) | 538 | void kill_io_thread(void) |
| 534 | { | 539 | { |
| 535 | if(io_pid != -1) | 540 | if(io_pid != -1) |
| 536 | os_kill_process(io_pid, 1); | 541 | os_kill_process(io_pid, 1); |
| 537 | } | 542 | } |
| 538 | 543 | ||
| @@ -567,14 +572,15 @@ static int ubd_open_dev(struct ubd *dev) | |||
| 567 | create_cow = 0; | 572 | create_cow = 0; |
| 568 | create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; | 573 | create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; |
| 569 | back_ptr = dev->no_cow ? NULL : &dev->cow.file; | 574 | back_ptr = dev->no_cow ? NULL : &dev->cow.file; |
| 570 | dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr, | 575 | dev->fd = open_ubd_file(dev->file, &dev->openflags, dev->shared, |
| 571 | &dev->cow.bitmap_offset, &dev->cow.bitmap_len, | 576 | back_ptr, &dev->cow.bitmap_offset, |
| 572 | &dev->cow.data_offset, create_ptr); | 577 | &dev->cow.bitmap_len, &dev->cow.data_offset, |
| 578 | create_ptr); | ||
| 573 | 579 | ||
| 574 | if((dev->fd == -ENOENT) && create_cow){ | 580 | if((dev->fd == -ENOENT) && create_cow){ |
| 575 | dev->fd = create_cow_file(dev->file, dev->cow.file, | 581 | dev->fd = create_cow_file(dev->file, dev->cow.file, |
| 576 | dev->openflags, 1 << 9, PAGE_SIZE, | 582 | dev->openflags, 1 << 9, PAGE_SIZE, |
| 577 | &dev->cow.bitmap_offset, | 583 | &dev->cow.bitmap_offset, |
| 578 | &dev->cow.bitmap_len, | 584 | &dev->cow.bitmap_len, |
| 579 | &dev->cow.data_offset); | 585 | &dev->cow.data_offset); |
| 580 | if(dev->fd >= 0){ | 586 | if(dev->fd >= 0){ |
| @@ -598,16 +604,16 @@ static int ubd_open_dev(struct ubd *dev) | |||
| 598 | } | 604 | } |
| 599 | flush_tlb_kernel_vm(); | 605 | flush_tlb_kernel_vm(); |
| 600 | 606 | ||
| 601 | err = read_cow_bitmap(dev->fd, dev->cow.bitmap, | 607 | err = read_cow_bitmap(dev->fd, dev->cow.bitmap, |
| 602 | dev->cow.bitmap_offset, | 608 | dev->cow.bitmap_offset, |
| 603 | dev->cow.bitmap_len); | 609 | dev->cow.bitmap_len); |
| 604 | if(err < 0) | 610 | if(err < 0) |
| 605 | goto error; | 611 | goto error; |
| 606 | 612 | ||
| 607 | flags = dev->openflags; | 613 | flags = dev->openflags; |
| 608 | flags.w = 0; | 614 | flags.w = 0; |
| 609 | err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL, | 615 | err = open_ubd_file(dev->cow.file, &flags, dev->shared, NULL, |
| 610 | NULL, NULL); | 616 | NULL, NULL, NULL, NULL); |
| 611 | if(err < 0) goto error; | 617 | if(err < 0) goto error; |
| 612 | dev->cow.fd = err; | 618 | dev->cow.fd = err; |
| 613 | } | 619 | } |
| @@ -685,11 +691,11 @@ static int ubd_add(int n) | |||
| 685 | dev->size = ROUND_BLOCK(dev->size); | 691 | dev->size = ROUND_BLOCK(dev->size); |
| 686 | 692 | ||
| 687 | err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); | 693 | err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); |
| 688 | if(err) | 694 | if(err) |
| 689 | goto out_close; | 695 | goto out_close; |
| 690 | 696 | ||
| 691 | if(fake_major != MAJOR_NR) | 697 | if(fake_major != MAJOR_NR) |
| 692 | ubd_new_disk(fake_major, dev->size, n, | 698 | ubd_new_disk(fake_major, dev->size, n, |
| 693 | &fake_gendisk[n]); | 699 | &fake_gendisk[n]); |
| 694 | 700 | ||
| 695 | /* perhaps this should also be under the "if (fake_major)" above */ | 701 | /* perhaps this should also be under the "if (fake_major)" above */ |
| @@ -854,7 +860,7 @@ int ubd_init(void) | |||
| 854 | return -1; | 860 | return -1; |
| 855 | } | 861 | } |
| 856 | platform_driver_register(&ubd_driver); | 862 | platform_driver_register(&ubd_driver); |
| 857 | for (i = 0; i < MAX_DEV; i++) | 863 | for (i = 0; i < MAX_DEV; i++) |
| 858 | ubd_add(i); | 864 | ubd_add(i); |
| 859 | return 0; | 865 | return 0; |
| 860 | } | 866 | } |
| @@ -872,16 +878,16 @@ int ubd_driver_init(void){ | |||
| 872 | * enough. So use anyway the io thread. */ | 878 | * enough. So use anyway the io thread. */ |
| 873 | } | 879 | } |
| 874 | stack = alloc_stack(0, 0); | 880 | stack = alloc_stack(0, 0); |
| 875 | io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), | 881 | io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), |
| 876 | &thread_fd); | 882 | &thread_fd); |
| 877 | if(io_pid < 0){ | 883 | if(io_pid < 0){ |
| 878 | printk(KERN_ERR | 884 | printk(KERN_ERR |
| 879 | "ubd : Failed to start I/O thread (errno = %d) - " | 885 | "ubd : Failed to start I/O thread (errno = %d) - " |
| 880 | "falling back to synchronous I/O\n", -io_pid); | 886 | "falling back to synchronous I/O\n", -io_pid); |
| 881 | io_pid = -1; | 887 | io_pid = -1; |
| 882 | return(0); | 888 | return(0); |
| 883 | } | 889 | } |
| 884 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, | 890 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, |
| 885 | SA_INTERRUPT, "ubd", ubd_dev); | 891 | SA_INTERRUPT, "ubd", ubd_dev); |
| 886 | if(err != 0) | 892 | if(err != 0) |
| 887 | printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); | 893 | printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); |
| @@ -978,7 +984,7 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, | |||
| 978 | if(req->op == UBD_READ) { | 984 | if(req->op == UBD_READ) { |
| 979 | for(i = 0; i < req->length >> 9; i++){ | 985 | for(i = 0; i < req->length >> 9; i++){ |
| 980 | if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) | 986 | if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) |
| 981 | ubd_set_bit(i, (unsigned char *) | 987 | ubd_set_bit(i, (unsigned char *) |
| 982 | &req->sector_mask); | 988 | &req->sector_mask); |
| 983 | } | 989 | } |
| 984 | } | 990 | } |
| @@ -999,7 +1005,7 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) | |||
| 999 | 1005 | ||
| 1000 | /* This should be impossible now */ | 1006 | /* This should be impossible now */ |
| 1001 | if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ | 1007 | if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ |
| 1002 | printk("Write attempted on readonly ubd device %s\n", | 1008 | printk("Write attempted on readonly ubd device %s\n", |
| 1003 | disk->disk_name); | 1009 | disk->disk_name); |
| 1004 | end_request(req, 0); | 1010 | end_request(req, 0); |
| 1005 | return(1); | 1011 | return(1); |
| @@ -1182,7 +1188,7 @@ int read_cow_bitmap(int fd, void *buf, int offset, int len) | |||
| 1182 | return(0); | 1188 | return(0); |
| 1183 | } | 1189 | } |
| 1184 | 1190 | ||
| 1185 | int open_ubd_file(char *file, struct openflags *openflags, | 1191 | int open_ubd_file(char *file, struct openflags *openflags, int shared, |
| 1186 | char **backing_file_out, int *bitmap_offset_out, | 1192 | char **backing_file_out, int *bitmap_offset_out, |
| 1187 | unsigned long *bitmap_len_out, int *data_offset_out, | 1193 | unsigned long *bitmap_len_out, int *data_offset_out, |
| 1188 | int *create_cow_out) | 1194 | int *create_cow_out) |
| @@ -1206,10 +1212,14 @@ int open_ubd_file(char *file, struct openflags *openflags, | |||
| 1206 | return fd; | 1212 | return fd; |
| 1207 | } | 1213 | } |
| 1208 | 1214 | ||
| 1209 | err = os_lock_file(fd, openflags->w); | 1215 | if(shared) |
| 1210 | if(err < 0){ | 1216 | printk("Not locking \"%s\" on the host\n", file); |
| 1211 | printk("Failed to lock '%s', err = %d\n", file, -err); | 1217 | else { |
| 1212 | goto out_close; | 1218 | err = os_lock_file(fd, openflags->w); |
| 1219 | if(err < 0){ | ||
| 1220 | printk("Failed to lock '%s', err = %d\n", file, -err); | ||
| 1221 | goto out_close; | ||
| 1222 | } | ||
| 1213 | } | 1223 | } |
| 1214 | 1224 | ||
| 1215 | /* Succesful return case! */ | 1225 | /* Succesful return case! */ |
| @@ -1260,7 +1270,7 @@ int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, | |||
| 1260 | int err, fd; | 1270 | int err, fd; |
| 1261 | 1271 | ||
| 1262 | flags.c = 1; | 1272 | flags.c = 1; |
| 1263 | fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL); | 1273 | fd = open_ubd_file(cow_file, &flags, 0, NULL, NULL, NULL, NULL, NULL); |
| 1264 | if(fd < 0){ | 1274 | if(fd < 0){ |
| 1265 | err = fd; | 1275 | err = fd; |
| 1266 | printk("Open of COW file '%s' failed, errno = %d\n", cow_file, | 1276 | printk("Open of COW file '%s' failed, errno = %d\n", cow_file, |
diff --git a/arch/um/include/irq_user.h b/arch/um/include/irq_user.h index b61deb8b362a..69a93c804f0e 100644 --- a/arch/um/include/irq_user.h +++ b/arch/um/include/irq_user.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) |
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| @@ -6,6 +6,17 @@ | |||
| 6 | #ifndef __IRQ_USER_H__ | 6 | #ifndef __IRQ_USER_H__ |
| 7 | #define __IRQ_USER_H__ | 7 | #define __IRQ_USER_H__ |
| 8 | 8 | ||
| 9 | struct irq_fd { | ||
| 10 | struct irq_fd *next; | ||
| 11 | void *id; | ||
| 12 | int fd; | ||
| 13 | int type; | ||
| 14 | int irq; | ||
| 15 | int pid; | ||
| 16 | int events; | ||
| 17 | int current_events; | ||
| 18 | }; | ||
| 19 | |||
| 9 | enum { IRQ_READ, IRQ_WRITE }; | 20 | enum { IRQ_READ, IRQ_WRITE }; |
| 10 | 21 | ||
| 11 | extern void sigio_handler(int sig, union uml_pt_regs *regs); | 22 | extern void sigio_handler(int sig, union uml_pt_regs *regs); |
| @@ -16,8 +27,6 @@ extern void reactivate_fd(int fd, int irqnum); | |||
| 16 | extern void deactivate_fd(int fd, int irqnum); | 27 | extern void deactivate_fd(int fd, int irqnum); |
| 17 | extern int deactivate_all_fds(void); | 28 | extern int deactivate_all_fds(void); |
| 18 | extern void forward_interrupts(int pid); | 29 | extern void forward_interrupts(int pid); |
| 19 | extern void init_irq_signals(int on_sigstack); | ||
| 20 | extern void forward_ipi(int fd, int pid); | ||
| 21 | extern int activate_ipi(int fd, int pid); | 30 | extern int activate_ipi(int fd, int pid); |
| 22 | extern unsigned long irq_lock(void); | 31 | extern unsigned long irq_lock(void); |
| 23 | extern void irq_unlock(unsigned long flags); | 32 | extern void irq_unlock(unsigned long flags); |
diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h index 7d223beccbc0..4ce3fc650e57 100644 --- a/arch/um/include/kern.h +++ b/arch/um/include/kern.h | |||
| @@ -29,7 +29,7 @@ extern int getuid(void); | |||
| 29 | extern int getgid(void); | 29 | extern int getgid(void); |
| 30 | extern int pause(void); | 30 | extern int pause(void); |
| 31 | extern int write(int, const void *, int); | 31 | extern int write(int, const void *, int); |
| 32 | extern int exit(int); | 32 | extern void exit(int); |
| 33 | extern int close(int); | 33 | extern int close(int); |
| 34 | extern int read(unsigned int, char *, int); | 34 | extern int read(unsigned int, char *, int); |
| 35 | extern int pipe(int *); | 35 | extern int pipe(int *); |
diff --git a/arch/um/include/misc_constants.h b/arch/um/include/misc_constants.h new file mode 100644 index 000000000000..989bc08de36e --- /dev/null +++ b/arch/um/include/misc_constants.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | #ifndef __MISC_CONSTANT_H_ | ||
| 2 | #define __MISC_CONSTANT_H_ | ||
| 3 | |||
| 4 | #include <user_constants.h> | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 2a1c64d8d0bf..d3d1bc6074ef 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "sysdep/ptrace.h" | 12 | #include "sysdep/ptrace.h" |
| 13 | #include "kern_util.h" | 13 | #include "kern_util.h" |
| 14 | #include "skas/mm_id.h" | 14 | #include "skas/mm_id.h" |
| 15 | #include "irq_user.h" | ||
| 15 | 16 | ||
| 16 | #define OS_TYPE_FILE 1 | 17 | #define OS_TYPE_FILE 1 |
| 17 | #define OS_TYPE_DIR 2 | 18 | #define OS_TYPE_DIR 2 |
| @@ -121,6 +122,7 @@ static inline struct openflags of_cloexec(struct openflags flags) | |||
| 121 | return(flags); | 122 | return(flags); |
| 122 | } | 123 | } |
| 123 | 124 | ||
| 125 | /* file.c */ | ||
| 124 | extern int os_stat_file(const char *file_name, struct uml_stat *buf); | 126 | extern int os_stat_file(const char *file_name, struct uml_stat *buf); |
| 125 | extern int os_stat_fd(const int fd, struct uml_stat *buf); | 127 | extern int os_stat_fd(const int fd, struct uml_stat *buf); |
| 126 | extern int os_access(const char *file, int mode); | 128 | extern int os_access(const char *file, int mode); |
| @@ -156,10 +158,20 @@ extern int os_connect_socket(char *name); | |||
| 156 | extern int os_file_type(char *file); | 158 | extern int os_file_type(char *file); |
| 157 | extern int os_file_mode(char *file, struct openflags *mode_out); | 159 | extern int os_file_mode(char *file, struct openflags *mode_out); |
| 158 | extern int os_lock_file(int fd, int excl); | 160 | extern int os_lock_file(int fd, int excl); |
| 161 | extern void os_flush_stdout(void); | ||
| 162 | extern int os_stat_filesystem(char *path, long *bsize_out, | ||
| 163 | long long *blocks_out, long long *bfree_out, | ||
| 164 | long long *bavail_out, long long *files_out, | ||
| 165 | long long *ffree_out, void *fsid_out, | ||
| 166 | int fsid_size, long *namelen_out, | ||
| 167 | long *spare_out); | ||
| 168 | extern int os_change_dir(char *dir); | ||
| 169 | extern int os_fchange_dir(int fd); | ||
| 159 | 170 | ||
| 160 | /* start_up.c */ | 171 | /* start_up.c */ |
| 161 | extern void os_early_checks(void); | 172 | extern void os_early_checks(void); |
| 162 | extern int can_do_skas(void); | 173 | extern int can_do_skas(void); |
| 174 | extern void os_check_bugs(void); | ||
| 163 | 175 | ||
| 164 | /* Make sure they are clear when running in TT mode. Required by | 176 | /* Make sure they are clear when running in TT mode. Required by |
| 165 | * SEGV_MAYBE_FIXABLE */ | 177 | * SEGV_MAYBE_FIXABLE */ |
| @@ -198,6 +210,8 @@ extern void os_flush_stdout(void); | |||
| 198 | /* tt.c | 210 | /* tt.c |
| 199 | * for tt mode only (will be deleted in future...) | 211 | * for tt mode only (will be deleted in future...) |
| 200 | */ | 212 | */ |
| 213 | extern void forward_ipi(int fd, int pid); | ||
| 214 | extern void kill_child_dead(int pid); | ||
| 201 | extern void stop(void); | 215 | extern void stop(void); |
| 202 | extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); | 216 | extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); |
| 203 | extern int protect_memory(unsigned long addr, unsigned long len, | 217 | extern int protect_memory(unsigned long addr, unsigned long len, |
| @@ -294,4 +308,26 @@ extern void initial_thread_cb_skas(void (*proc)(void *), | |||
| 294 | extern void halt_skas(void); | 308 | extern void halt_skas(void); |
| 295 | extern void reboot_skas(void); | 309 | extern void reboot_skas(void); |
| 296 | 310 | ||
| 311 | /* irq.c */ | ||
| 312 | extern int os_waiting_for_events(struct irq_fd *active_fds); | ||
| 313 | extern int os_isatty(int fd); | ||
| 314 | extern int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds); | ||
| 315 | extern void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg, | ||
| 316 | struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2); | ||
| 317 | extern void os_free_irq_later(struct irq_fd *active_fds, | ||
| 318 | int irq, void *dev_id); | ||
| 319 | extern int os_get_pollfd(int i); | ||
| 320 | extern void os_set_pollfd(int i, int fd); | ||
| 321 | extern void os_set_ioignore(void); | ||
| 322 | extern void init_irq_signals(int on_sigstack); | ||
| 323 | |||
| 324 | /* sigio.c */ | ||
| 325 | extern void write_sigio_workaround(void); | ||
| 326 | extern int add_sigio_fd(int fd, int read); | ||
| 327 | extern int ignore_sigio_fd(int fd); | ||
| 328 | |||
| 329 | /* skas/trap */ | ||
| 330 | extern void sig_handler_common_skas(int sig, void *sc_ptr); | ||
| 331 | extern void user_signal(int sig, union uml_pt_regs *regs, int pid); | ||
| 332 | |||
| 297 | #endif | 333 | #endif |
diff --git a/arch/um/include/sigio.h b/arch/um/include/sigio.h index 37d76e29a147..fe99ea163c2e 100644 --- a/arch/um/include/sigio.h +++ b/arch/um/include/sigio.h | |||
| @@ -8,9 +8,6 @@ | |||
| 8 | 8 | ||
| 9 | extern int write_sigio_irq(int fd); | 9 | extern int write_sigio_irq(int fd); |
| 10 | extern int register_sigio_fd(int fd); | 10 | extern int register_sigio_fd(int fd); |
| 11 | extern int read_sigio_fd(int fd); | ||
| 12 | extern int add_sigio_fd(int fd, int read); | ||
| 13 | extern int ignore_sigio_fd(int fd); | ||
| 14 | extern void sigio_lock(void); | 11 | extern void sigio_lock(void); |
| 15 | extern void sigio_unlock(void); | 12 | extern void sigio_unlock(void); |
| 16 | 13 | ||
diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h index 260065cfeef1..8bc6916bbbb1 100644 --- a/arch/um/include/skas/mode-skas.h +++ b/arch/um/include/skas/mode-skas.h | |||
| @@ -13,7 +13,6 @@ extern unsigned long exec_fp_regs[]; | |||
| 13 | extern unsigned long exec_fpx_regs[]; | 13 | extern unsigned long exec_fpx_regs[]; |
| 14 | extern int have_fpx_regs; | 14 | extern int have_fpx_regs; |
| 15 | 15 | ||
| 16 | extern void sig_handler_common_skas(int sig, void *sc_ptr); | ||
| 17 | extern void kill_off_processes_skas(void); | 16 | extern void kill_off_processes_skas(void); |
| 18 | 17 | ||
| 19 | #endif | 18 | #endif |
diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h index 86357282d681..853b26f148c5 100644 --- a/arch/um/include/skas/skas.h +++ b/arch/um/include/skas/skas.h | |||
| @@ -17,7 +17,6 @@ extern int user_thread(unsigned long stack, int flags); | |||
| 17 | extern void new_thread_proc(void *stack, void (*handler)(int sig)); | 17 | extern void new_thread_proc(void *stack, void (*handler)(int sig)); |
| 18 | extern void new_thread_handler(int sig); | 18 | extern void new_thread_handler(int sig); |
| 19 | extern void handle_syscall(union uml_pt_regs *regs); | 19 | extern void handle_syscall(union uml_pt_regs *regs); |
| 20 | extern void user_signal(int sig, union uml_pt_regs *regs, int pid); | ||
| 21 | extern int new_mm(unsigned long stack); | 20 | extern int new_mm(unsigned long stack); |
| 22 | extern void get_skas_faultinfo(int pid, struct faultinfo * fi); | 21 | extern void get_skas_faultinfo(int pid, struct faultinfo * fi); |
| 23 | extern long execute_syscall_skas(void *r); | 22 | extern long execute_syscall_skas(void *r); |
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h index a6f1f176cf84..992a7e1e0fca 100644 --- a/arch/um/include/user_util.h +++ b/arch/um/include/user_util.h | |||
| @@ -58,7 +58,6 @@ extern int attach(int pid); | |||
| 58 | extern void kill_child_dead(int pid); | 58 | extern void kill_child_dead(int pid); |
| 59 | extern int cont(int pid); | 59 | extern int cont(int pid); |
| 60 | extern void check_sigio(void); | 60 | extern void check_sigio(void); |
| 61 | extern void write_sigio_workaround(void); | ||
| 62 | extern void arch_check_bugs(void); | 61 | extern void arch_check_bugs(void); |
| 63 | extern int cpu_feature(char *what, char *buf, int len); | 62 | extern int cpu_feature(char *what, char *buf, int len); |
| 64 | extern int arch_handle_signal(int sig, union uml_pt_regs *regs); | 63 | extern int arch_handle_signal(int sig, union uml_pt_regs *regs); |
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 693018ba80f1..fe08971b64cf 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile | |||
| @@ -7,23 +7,20 @@ extra-y := vmlinux.lds | |||
| 7 | clean-files := | 7 | clean-files := |
| 8 | 8 | ||
| 9 | obj-y = config.o exec_kern.o exitcode.o \ | 9 | obj-y = config.o exec_kern.o exitcode.o \ |
| 10 | init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ | 10 | init_task.o irq.o ksyms.o mem.o physmem.o \ |
| 11 | process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ | 11 | process_kern.o ptrace.o reboot.o resource.o sigio_kern.o \ |
| 12 | signal_kern.o smp.o syscall_kern.o sysrq.o \ | 12 | signal_kern.o smp.o syscall_kern.o sysrq.o \ |
| 13 | time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o | 13 | time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o |
| 14 | 14 | ||
| 15 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o | 15 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o |
| 16 | obj-$(CONFIG_GPROF) += gprof_syms.o | 16 | obj-$(CONFIG_GPROF) += gprof_syms.o |
| 17 | obj-$(CONFIG_GCOV) += gmon_syms.o | 17 | obj-$(CONFIG_GCOV) += gmon_syms.o |
| 18 | obj-$(CONFIG_TTY_LOG) += tty_log.o | ||
| 19 | obj-$(CONFIG_SYSCALL_DEBUG) += syscall.o | 18 | obj-$(CONFIG_SYSCALL_DEBUG) += syscall.o |
| 20 | 19 | ||
| 21 | obj-$(CONFIG_MODE_TT) += tt/ | 20 | obj-$(CONFIG_MODE_TT) += tt/ |
| 22 | obj-$(CONFIG_MODE_SKAS) += skas/ | 21 | obj-$(CONFIG_MODE_SKAS) += skas/ |
| 23 | 22 | ||
| 24 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o | 23 | USER_OBJS := config.o |
| 25 | |||
| 26 | USER_OBJS := $(user-objs-y) config.o tty_log.o | ||
| 27 | 24 | ||
| 28 | include arch/um/scripts/Makefile.rules | 25 | include arch/um/scripts/Makefile.rules |
| 29 | 26 | ||
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index c264e1c05ab3..1ca84319317d 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c | |||
| @@ -30,8 +30,6 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) | |||
| 30 | CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); | 30 | CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | extern void log_exec(char **argv, void *tty); | ||
| 34 | |||
| 35 | static long execve1(char *file, char __user * __user *argv, | 33 | static long execve1(char *file, char __user * __user *argv, |
| 36 | char __user *__user *env) | 34 | char __user *__user *env) |
| 37 | { | 35 | { |
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index bbf94bf2921e..c39ea3abeda4 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c | |||
| @@ -31,6 +31,8 @@ | |||
| 31 | #include "irq_user.h" | 31 | #include "irq_user.h" |
| 32 | #include "irq_kern.h" | 32 | #include "irq_kern.h" |
| 33 | #include "os.h" | 33 | #include "os.h" |
| 34 | #include "sigio.h" | ||
| 35 | #include "misc_constants.h" | ||
| 34 | 36 | ||
| 35 | /* | 37 | /* |
| 36 | * Generic, controller-independent functions: | 38 | * Generic, controller-independent functions: |
| @@ -77,6 +79,298 @@ skip: | |||
| 77 | return 0; | 79 | return 0; |
| 78 | } | 80 | } |
| 79 | 81 | ||
| 82 | struct irq_fd *active_fds = NULL; | ||
| 83 | static struct irq_fd **last_irq_ptr = &active_fds; | ||
| 84 | |||
| 85 | extern void free_irqs(void); | ||
| 86 | |||
| 87 | void sigio_handler(int sig, union uml_pt_regs *regs) | ||
| 88 | { | ||
| 89 | struct irq_fd *irq_fd; | ||
| 90 | int n; | ||
| 91 | |||
| 92 | if(smp_sigio_handler()) return; | ||
| 93 | while(1){ | ||
| 94 | n = os_waiting_for_events(active_fds); | ||
| 95 | if (n <= 0) { | ||
| 96 | if(n == -EINTR) continue; | ||
| 97 | else break; | ||
| 98 | } | ||
| 99 | |||
| 100 | for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ | ||
| 101 | if(irq_fd->current_events != 0){ | ||
| 102 | irq_fd->current_events = 0; | ||
| 103 | do_IRQ(irq_fd->irq, regs); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | free_irqs(); | ||
| 109 | } | ||
| 110 | |||
| 111 | static void maybe_sigio_broken(int fd, int type) | ||
| 112 | { | ||
| 113 | if(os_isatty(fd)){ | ||
| 114 | if((type == IRQ_WRITE) && !pty_output_sigio){ | ||
| 115 | write_sigio_workaround(); | ||
| 116 | add_sigio_fd(fd, 0); | ||
| 117 | } | ||
| 118 | else if((type == IRQ_READ) && !pty_close_sigio){ | ||
| 119 | write_sigio_workaround(); | ||
| 120 | add_sigio_fd(fd, 1); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | |||
| 126 | int activate_fd(int irq, int fd, int type, void *dev_id) | ||
| 127 | { | ||
| 128 | struct pollfd *tmp_pfd; | ||
| 129 | struct irq_fd *new_fd, *irq_fd; | ||
| 130 | unsigned long flags; | ||
| 131 | int pid, events, err, n; | ||
| 132 | |||
| 133 | pid = os_getpid(); | ||
| 134 | err = os_set_fd_async(fd, pid); | ||
| 135 | if(err < 0) | ||
| 136 | goto out; | ||
| 137 | |||
| 138 | new_fd = um_kmalloc(sizeof(*new_fd)); | ||
| 139 | err = -ENOMEM; | ||
| 140 | if(new_fd == NULL) | ||
| 141 | goto out; | ||
| 142 | |||
| 143 | if(type == IRQ_READ) events = UM_POLLIN | UM_POLLPRI; | ||
| 144 | else events = UM_POLLOUT; | ||
| 145 | *new_fd = ((struct irq_fd) { .next = NULL, | ||
| 146 | .id = dev_id, | ||
| 147 | .fd = fd, | ||
| 148 | .type = type, | ||
| 149 | .irq = irq, | ||
| 150 | .pid = pid, | ||
| 151 | .events = events, | ||
| 152 | .current_events = 0 } ); | ||
| 153 | |||
| 154 | /* Critical section - locked by a spinlock because this stuff can | ||
| 155 | * be changed from interrupt handlers. The stuff above is done | ||
| 156 | * outside the lock because it allocates memory. | ||
| 157 | */ | ||
| 158 | |||
| 159 | /* Actually, it only looks like it can be called from interrupt | ||
| 160 | * context. The culprit is reactivate_fd, which calls | ||
| 161 | * maybe_sigio_broken, which calls write_sigio_workaround, | ||
| 162 | * which calls activate_fd. However, write_sigio_workaround should | ||
| 163 | * only be called once, at boot time. That would make it clear that | ||
| 164 | * this is called only from process context, and can be locked with | ||
| 165 | * a semaphore. | ||
| 166 | */ | ||
| 167 | flags = irq_lock(); | ||
| 168 | for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ | ||
| 169 | if((irq_fd->fd == fd) && (irq_fd->type == type)){ | ||
| 170 | printk("Registering fd %d twice\n", fd); | ||
| 171 | printk("Irqs : %d, %d\n", irq_fd->irq, irq); | ||
| 172 | printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id); | ||
| 173 | goto out_unlock; | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | /*-------------*/ | ||
| 178 | if(type == IRQ_WRITE) | ||
| 179 | fd = -1; | ||
| 180 | |||
| 181 | tmp_pfd = NULL; | ||
| 182 | n = 0; | ||
| 183 | |||
| 184 | while(1){ | ||
| 185 | n = os_create_pollfd(fd, events, tmp_pfd, n); | ||
| 186 | if (n == 0) | ||
| 187 | break; | ||
| 188 | |||
| 189 | /* n > 0 | ||
| 190 | * It means we couldn't put new pollfd to current pollfds | ||
| 191 | * and tmp_fds is NULL or too small for new pollfds array. | ||
| 192 | * Needed size is equal to n as minimum. | ||
| 193 | * | ||
| 194 | * Here we have to drop the lock in order to call | ||
| 195 | * kmalloc, which might sleep. | ||
| 196 | * If something else came in and changed the pollfds array | ||
| 197 | * so we will not be able to put new pollfd struct to pollfds | ||
| 198 | * then we free the buffer tmp_fds and try again. | ||
| 199 | */ | ||
| 200 | irq_unlock(flags); | ||
| 201 | if (tmp_pfd != NULL) { | ||
| 202 | kfree(tmp_pfd); | ||
| 203 | tmp_pfd = NULL; | ||
| 204 | } | ||
| 205 | |||
| 206 | tmp_pfd = um_kmalloc(n); | ||
| 207 | if (tmp_pfd == NULL) | ||
| 208 | goto out_kfree; | ||
| 209 | |||
| 210 | flags = irq_lock(); | ||
| 211 | } | ||
| 212 | /*-------------*/ | ||
| 213 | |||
| 214 | *last_irq_ptr = new_fd; | ||
| 215 | last_irq_ptr = &new_fd->next; | ||
| 216 | |||
| 217 | irq_unlock(flags); | ||
| 218 | |||
| 219 | /* This calls activate_fd, so it has to be outside the critical | ||
| 220 | * section. | ||
| 221 | */ | ||
| 222 | maybe_sigio_broken(fd, type); | ||
| 223 | |||
| 224 | return(0); | ||
| 225 | |||
| 226 | out_unlock: | ||
| 227 | irq_unlock(flags); | ||
| 228 | out_kfree: | ||
| 229 | kfree(new_fd); | ||
| 230 | out: | ||
| 231 | return(err); | ||
| 232 | } | ||
| 233 | |||
| 234 | static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) | ||
| 235 | { | ||
| 236 | unsigned long flags; | ||
| 237 | |||
| 238 | flags = irq_lock(); | ||
| 239 | os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr); | ||
| 240 | irq_unlock(flags); | ||
| 241 | } | ||
| 242 | |||
| 243 | struct irq_and_dev { | ||
| 244 | int irq; | ||
| 245 | void *dev; | ||
| 246 | }; | ||
| 247 | |||
| 248 | static int same_irq_and_dev(struct irq_fd *irq, void *d) | ||
| 249 | { | ||
| 250 | struct irq_and_dev *data = d; | ||
| 251 | |||
| 252 | return((irq->irq == data->irq) && (irq->id == data->dev)); | ||
| 253 | } | ||
| 254 | |||
| 255 | void free_irq_by_irq_and_dev(unsigned int irq, void *dev) | ||
| 256 | { | ||
| 257 | struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq, | ||
| 258 | .dev = dev }); | ||
| 259 | |||
| 260 | free_irq_by_cb(same_irq_and_dev, &data); | ||
| 261 | } | ||
| 262 | |||
| 263 | static int same_fd(struct irq_fd *irq, void *fd) | ||
| 264 | { | ||
| 265 | return(irq->fd == *((int *) fd)); | ||
| 266 | } | ||
| 267 | |||
| 268 | void free_irq_by_fd(int fd) | ||
| 269 | { | ||
| 270 | free_irq_by_cb(same_fd, &fd); | ||
| 271 | } | ||
| 272 | |||
| 273 | static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) | ||
| 274 | { | ||
| 275 | struct irq_fd *irq; | ||
| 276 | int i = 0; | ||
| 277 | int fdi; | ||
| 278 | |||
| 279 | for(irq=active_fds; irq != NULL; irq = irq->next){ | ||
| 280 | if((irq->fd == fd) && (irq->irq == irqnum)) break; | ||
| 281 | i++; | ||
| 282 | } | ||
| 283 | if(irq == NULL){ | ||
| 284 | printk("find_irq_by_fd doesn't have descriptor %d\n", fd); | ||
| 285 | goto out; | ||
| 286 | } | ||
| 287 | fdi = os_get_pollfd(i); | ||
| 288 | if((fdi != -1) && (fdi != fd)){ | ||
| 289 | printk("find_irq_by_fd - mismatch between active_fds and " | ||
| 290 | "pollfds, fd %d vs %d, need %d\n", irq->fd, | ||
| 291 | fdi, fd); | ||
| 292 | irq = NULL; | ||
| 293 | goto out; | ||
| 294 | } | ||
| 295 | *index_out = i; | ||
| 296 | out: | ||
| 297 | return(irq); | ||
| 298 | } | ||
| 299 | |||
| 300 | void reactivate_fd(int fd, int irqnum) | ||
| 301 | { | ||
| 302 | struct irq_fd *irq; | ||
| 303 | unsigned long flags; | ||
| 304 | int i; | ||
| 305 | |||
| 306 | flags = irq_lock(); | ||
| 307 | irq = find_irq_by_fd(fd, irqnum, &i); | ||
| 308 | if(irq == NULL){ | ||
| 309 | irq_unlock(flags); | ||
| 310 | return; | ||
| 311 | } | ||
| 312 | os_set_pollfd(i, irq->fd); | ||
| 313 | irq_unlock(flags); | ||
| 314 | |||
| 315 | /* This calls activate_fd, so it has to be outside the critical | ||
| 316 | * section. | ||
| 317 | */ | ||
| 318 | maybe_sigio_broken(fd, irq->type); | ||
| 319 | } | ||
| 320 | |||
| 321 | void deactivate_fd(int fd, int irqnum) | ||
| 322 | { | ||
| 323 | struct irq_fd *irq; | ||
| 324 | unsigned long flags; | ||
| 325 | int i; | ||
| 326 | |||
| 327 | flags = irq_lock(); | ||
| 328 | irq = find_irq_by_fd(fd, irqnum, &i); | ||
| 329 | if(irq == NULL) | ||
| 330 | goto out; | ||
| 331 | os_set_pollfd(i, -1); | ||
| 332 | out: | ||
| 333 | irq_unlock(flags); | ||
| 334 | } | ||
| 335 | |||
| 336 | int deactivate_all_fds(void) | ||
| 337 | { | ||
| 338 | struct irq_fd *irq; | ||
| 339 | int err; | ||
| 340 | |||
| 341 | for(irq=active_fds;irq != NULL;irq = irq->next){ | ||
| 342 | err = os_clear_fd_async(irq->fd); | ||
| 343 | if(err) | ||
| 344 | return(err); | ||
| 345 | } | ||
| 346 | /* If there is a signal already queued, after unblocking ignore it */ | ||
| 347 | os_set_ioignore(); | ||
| 348 | |||
| 349 | return(0); | ||
| 350 | } | ||
| 351 | |||
| 352 | void forward_interrupts(int pid) | ||
| 353 | { | ||
| 354 | struct irq_fd *irq; | ||
| 355 | unsigned long flags; | ||
| 356 | int err; | ||
| 357 | |||
| 358 | flags = irq_lock(); | ||
| 359 | for(irq=active_fds;irq != NULL;irq = irq->next){ | ||
| 360 | err = os_set_owner(irq->fd, pid); | ||
| 361 | if(err < 0){ | ||
| 362 | /* XXX Just remove the irq rather than | ||
| 363 | * print out an infinite stream of these | ||
| 364 | */ | ||
| 365 | printk("Failed to forward %d to pid %d, err = %d\n", | ||
| 366 | irq->fd, pid, -err); | ||
| 367 | } | ||
| 368 | |||
| 369 | irq->pid = pid; | ||
| 370 | } | ||
| 371 | irq_unlock(flags); | ||
| 372 | } | ||
| 373 | |||
| 80 | /* | 374 | /* |
| 81 | * do_IRQ handles all normal device IRQ's (the special | 375 | * do_IRQ handles all normal device IRQ's (the special |
| 82 | * SMP cross-CPU interrupts have their own specific | 376 | * SMP cross-CPU interrupts have their own specific |
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c deleted file mode 100644 index 0e32f5f4a887..000000000000 --- a/arch/um/kernel/irq_user.c +++ /dev/null | |||
| @@ -1,412 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <stdlib.h> | ||
| 7 | #include <unistd.h> | ||
| 8 | #include <errno.h> | ||
| 9 | #include <signal.h> | ||
| 10 | #include <string.h> | ||
| 11 | #include <sys/poll.h> | ||
| 12 | #include <sys/types.h> | ||
| 13 | #include <sys/time.h> | ||
| 14 | #include "user_util.h" | ||
| 15 | #include "kern_util.h" | ||
| 16 | #include "user.h" | ||
| 17 | #include "process.h" | ||
| 18 | #include "sigio.h" | ||
| 19 | #include "irq_user.h" | ||
| 20 | #include "os.h" | ||
| 21 | |||
| 22 | struct irq_fd { | ||
| 23 | struct irq_fd *next; | ||
| 24 | void *id; | ||
| 25 | int fd; | ||
| 26 | int type; | ||
| 27 | int irq; | ||
| 28 | int pid; | ||
| 29 | int events; | ||
| 30 | int current_events; | ||
| 31 | }; | ||
| 32 | |||
| 33 | static struct irq_fd *active_fds = NULL; | ||
| 34 | static struct irq_fd **last_irq_ptr = &active_fds; | ||
| 35 | |||
| 36 | static struct pollfd *pollfds = NULL; | ||
| 37 | static int pollfds_num = 0; | ||
| 38 | static int pollfds_size = 0; | ||
| 39 | |||
| 40 | extern int io_count, intr_count; | ||
| 41 | |||
| 42 | extern void free_irqs(void); | ||
| 43 | |||
| 44 | void sigio_handler(int sig, union uml_pt_regs *regs) | ||
| 45 | { | ||
| 46 | struct irq_fd *irq_fd; | ||
| 47 | int i, n; | ||
| 48 | |||
| 49 | if(smp_sigio_handler()) return; | ||
| 50 | while(1){ | ||
| 51 | n = poll(pollfds, pollfds_num, 0); | ||
| 52 | if(n < 0){ | ||
| 53 | if(errno == EINTR) continue; | ||
| 54 | printk("sigio_handler : poll returned %d, " | ||
| 55 | "errno = %d\n", n, errno); | ||
| 56 | break; | ||
| 57 | } | ||
| 58 | if(n == 0) break; | ||
| 59 | |||
| 60 | irq_fd = active_fds; | ||
| 61 | for(i = 0; i < pollfds_num; i++){ | ||
| 62 | if(pollfds[i].revents != 0){ | ||
| 63 | irq_fd->current_events = pollfds[i].revents; | ||
| 64 | pollfds[i].fd = -1; | ||
| 65 | } | ||
| 66 | irq_fd = irq_fd->next; | ||
| 67 | } | ||
| 68 | |||
| 69 | for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ | ||
| 70 | if(irq_fd->current_events != 0){ | ||
| 71 | irq_fd->current_events = 0; | ||
| 72 | do_IRQ(irq_fd->irq, regs); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | free_irqs(); | ||
| 78 | } | ||
| 79 | |||
| 80 | int activate_ipi(int fd, int pid) | ||
| 81 | { | ||
| 82 | return(os_set_fd_async(fd, pid)); | ||
| 83 | } | ||
| 84 | |||
| 85 | static void maybe_sigio_broken(int fd, int type) | ||
| 86 | { | ||
| 87 | if(isatty(fd)){ | ||
| 88 | if((type == IRQ_WRITE) && !pty_output_sigio){ | ||
| 89 | write_sigio_workaround(); | ||
| 90 | add_sigio_fd(fd, 0); | ||
| 91 | } | ||
| 92 | else if((type == IRQ_READ) && !pty_close_sigio){ | ||
| 93 | write_sigio_workaround(); | ||
| 94 | add_sigio_fd(fd, 1); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | int activate_fd(int irq, int fd, int type, void *dev_id) | ||
| 100 | { | ||
| 101 | struct pollfd *tmp_pfd; | ||
| 102 | struct irq_fd *new_fd, *irq_fd; | ||
| 103 | unsigned long flags; | ||
| 104 | int pid, events, err, n, size; | ||
| 105 | |||
| 106 | pid = os_getpid(); | ||
| 107 | err = os_set_fd_async(fd, pid); | ||
| 108 | if(err < 0) | ||
| 109 | goto out; | ||
| 110 | |||
| 111 | new_fd = um_kmalloc(sizeof(*new_fd)); | ||
| 112 | err = -ENOMEM; | ||
| 113 | if(new_fd == NULL) | ||
| 114 | goto out; | ||
| 115 | |||
| 116 | if(type == IRQ_READ) events = POLLIN | POLLPRI; | ||
| 117 | else events = POLLOUT; | ||
| 118 | *new_fd = ((struct irq_fd) { .next = NULL, | ||
| 119 | .id = dev_id, | ||
| 120 | .fd = fd, | ||
| 121 | .type = type, | ||
| 122 | .irq = irq, | ||
| 123 | .pid = pid, | ||
| 124 | .events = events, | ||
| 125 | .current_events = 0 } ); | ||
| 126 | |||
| 127 | /* Critical section - locked by a spinlock because this stuff can | ||
| 128 | * be changed from interrupt handlers. The stuff above is done | ||
| 129 | * outside the lock because it allocates memory. | ||
| 130 | */ | ||
| 131 | |||
| 132 | /* Actually, it only looks like it can be called from interrupt | ||
| 133 | * context. The culprit is reactivate_fd, which calls | ||
| 134 | * maybe_sigio_broken, which calls write_sigio_workaround, | ||
| 135 | * which calls activate_fd. However, write_sigio_workaround should | ||
| 136 | * only be called once, at boot time. That would make it clear that | ||
| 137 | * this is called only from process context, and can be locked with | ||
| 138 | * a semaphore. | ||
| 139 | */ | ||
| 140 | flags = irq_lock(); | ||
| 141 | for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ | ||
| 142 | if((irq_fd->fd == fd) && (irq_fd->type == type)){ | ||
| 143 | printk("Registering fd %d twice\n", fd); | ||
| 144 | printk("Irqs : %d, %d\n", irq_fd->irq, irq); | ||
| 145 | printk("Ids : 0x%x, 0x%x\n", irq_fd->id, dev_id); | ||
| 146 | goto out_unlock; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | n = pollfds_num; | ||
| 151 | if(n == pollfds_size){ | ||
| 152 | while(1){ | ||
| 153 | /* Here we have to drop the lock in order to call | ||
| 154 | * kmalloc, which might sleep. If something else | ||
| 155 | * came in and changed the pollfds array, we free | ||
| 156 | * the buffer and try again. | ||
| 157 | */ | ||
| 158 | irq_unlock(flags); | ||
| 159 | size = (pollfds_num + 1) * sizeof(pollfds[0]); | ||
| 160 | tmp_pfd = um_kmalloc(size); | ||
| 161 | flags = irq_lock(); | ||
| 162 | if(tmp_pfd == NULL) | ||
| 163 | goto out_unlock; | ||
| 164 | if(n == pollfds_size) | ||
| 165 | break; | ||
| 166 | kfree(tmp_pfd); | ||
| 167 | } | ||
| 168 | if(pollfds != NULL){ | ||
| 169 | memcpy(tmp_pfd, pollfds, | ||
| 170 | sizeof(pollfds[0]) * pollfds_size); | ||
| 171 | kfree(pollfds); | ||
| 172 | } | ||
| 173 | pollfds = tmp_pfd; | ||
| 174 | pollfds_size++; | ||
| 175 | } | ||
| 176 | |||
| 177 | if(type == IRQ_WRITE) | ||
| 178 | fd = -1; | ||
| 179 | |||
| 180 | pollfds[pollfds_num] = ((struct pollfd) { .fd = fd, | ||
| 181 | .events = events, | ||
| 182 | .revents = 0 }); | ||
| 183 | pollfds_num++; | ||
| 184 | |||
| 185 | *last_irq_ptr = new_fd; | ||
| 186 | last_irq_ptr = &new_fd->next; | ||
| 187 | |||
| 188 | irq_unlock(flags); | ||
| 189 | |||
| 190 | /* This calls activate_fd, so it has to be outside the critical | ||
| 191 | * section. | ||
| 192 | */ | ||
| 193 | maybe_sigio_broken(fd, type); | ||
| 194 | |||
| 195 | return(0); | ||
| 196 | |||
| 197 | out_unlock: | ||
| 198 | irq_unlock(flags); | ||
| 199 | kfree(new_fd); | ||
| 200 | out: | ||
| 201 | return(err); | ||
| 202 | } | ||
| 203 | |||
| 204 | static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) | ||
| 205 | { | ||
| 206 | struct irq_fd **prev; | ||
| 207 | unsigned long flags; | ||
| 208 | int i = 0; | ||
| 209 | |||
| 210 | flags = irq_lock(); | ||
| 211 | prev = &active_fds; | ||
| 212 | while(*prev != NULL){ | ||
| 213 | if((*test)(*prev, arg)){ | ||
| 214 | struct irq_fd *old_fd = *prev; | ||
| 215 | if((pollfds[i].fd != -1) && | ||
| 216 | (pollfds[i].fd != (*prev)->fd)){ | ||
| 217 | printk("free_irq_by_cb - mismatch between " | ||
| 218 | "active_fds and pollfds, fd %d vs %d\n", | ||
| 219 | (*prev)->fd, pollfds[i].fd); | ||
| 220 | goto out; | ||
| 221 | } | ||
| 222 | |||
| 223 | pollfds_num--; | ||
| 224 | |||
| 225 | /* This moves the *whole* array after pollfds[i] (though | ||
| 226 | * it doesn't spot as such)! */ | ||
| 227 | |||
| 228 | memmove(&pollfds[i], &pollfds[i + 1], | ||
| 229 | (pollfds_num - i) * sizeof(pollfds[0])); | ||
| 230 | |||
| 231 | if(last_irq_ptr == &old_fd->next) | ||
| 232 | last_irq_ptr = prev; | ||
| 233 | *prev = (*prev)->next; | ||
| 234 | if(old_fd->type == IRQ_WRITE) | ||
| 235 | ignore_sigio_fd(old_fd->fd); | ||
| 236 | kfree(old_fd); | ||
| 237 | continue; | ||
| 238 | } | ||
| 239 | prev = &(*prev)->next; | ||
| 240 | i++; | ||
| 241 | } | ||
| 242 | out: | ||
| 243 | irq_unlock(flags); | ||
| 244 | } | ||
| 245 | |||
| 246 | struct irq_and_dev { | ||
| 247 | int irq; | ||
| 248 | void *dev; | ||
| 249 | }; | ||
| 250 | |||
| 251 | static int same_irq_and_dev(struct irq_fd *irq, void *d) | ||
| 252 | { | ||
| 253 | struct irq_and_dev *data = d; | ||
| 254 | |||
| 255 | return((irq->irq == data->irq) && (irq->id == data->dev)); | ||
| 256 | } | ||
| 257 | |||
| 258 | void free_irq_by_irq_and_dev(unsigned int irq, void *dev) | ||
| 259 | { | ||
| 260 | struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq, | ||
| 261 | .dev = dev }); | ||
| 262 | |||
| 263 | free_irq_by_cb(same_irq_and_dev, &data); | ||
| 264 | } | ||
| 265 | |||
| 266 | static int same_fd(struct irq_fd *irq, void *fd) | ||
| 267 | { | ||
| 268 | return(irq->fd == *((int *) fd)); | ||
| 269 | } | ||
| 270 | |||
| 271 | void free_irq_by_fd(int fd) | ||
| 272 | { | ||
| 273 | free_irq_by_cb(same_fd, &fd); | ||
| 274 | } | ||
| 275 | |||
| 276 | static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) | ||
| 277 | { | ||
| 278 | struct irq_fd *irq; | ||
| 279 | int i = 0; | ||
| 280 | |||
| 281 | for(irq=active_fds; irq != NULL; irq = irq->next){ | ||
| 282 | if((irq->fd == fd) && (irq->irq == irqnum)) break; | ||
| 283 | i++; | ||
| 284 | } | ||
| 285 | if(irq == NULL){ | ||
| 286 | printk("find_irq_by_fd doesn't have descriptor %d\n", fd); | ||
| 287 | goto out; | ||
| 288 | } | ||
| 289 | if((pollfds[i].fd != -1) && (pollfds[i].fd != fd)){ | ||
| 290 | printk("find_irq_by_fd - mismatch between active_fds and " | ||
| 291 | "pollfds, fd %d vs %d, need %d\n", irq->fd, | ||
| 292 | pollfds[i].fd, fd); | ||
| 293 | irq = NULL; | ||
| 294 | goto out; | ||
| 295 | } | ||
| 296 | *index_out = i; | ||
| 297 | out: | ||
| 298 | return(irq); | ||
| 299 | } | ||
| 300 | |||
| 301 | void reactivate_fd(int fd, int irqnum) | ||
| 302 | { | ||
| 303 | struct irq_fd *irq; | ||
| 304 | unsigned long flags; | ||
| 305 | int i; | ||
| 306 | |||
| 307 | flags = irq_lock(); | ||
| 308 | irq = find_irq_by_fd(fd, irqnum, &i); | ||
| 309 | if(irq == NULL){ | ||
| 310 | irq_unlock(flags); | ||
| 311 | return; | ||
| 312 | } | ||
| 313 | |||
| 314 | pollfds[i].fd = irq->fd; | ||
| 315 | |||
| 316 | irq_unlock(flags); | ||
| 317 | |||
| 318 | /* This calls activate_fd, so it has to be outside the critical | ||
| 319 | * section. | ||
| 320 | */ | ||
| 321 | maybe_sigio_broken(fd, irq->type); | ||
| 322 | } | ||
| 323 | |||
| 324 | void deactivate_fd(int fd, int irqnum) | ||
| 325 | { | ||
| 326 | struct irq_fd *irq; | ||
| 327 | unsigned long flags; | ||
| 328 | int i; | ||
| 329 | |||
| 330 | flags = irq_lock(); | ||
| 331 | irq = find_irq_by_fd(fd, irqnum, &i); | ||
| 332 | if(irq == NULL) | ||
| 333 | goto out; | ||
| 334 | pollfds[i].fd = -1; | ||
| 335 | out: | ||
| 336 | irq_unlock(flags); | ||
| 337 | } | ||
| 338 | |||
| 339 | int deactivate_all_fds(void) | ||
| 340 | { | ||
| 341 | struct irq_fd *irq; | ||
| 342 | int err; | ||
| 343 | |||
| 344 | for(irq=active_fds;irq != NULL;irq = irq->next){ | ||
| 345 | err = os_clear_fd_async(irq->fd); | ||
| 346 | if(err) | ||
| 347 | return(err); | ||
| 348 | } | ||
| 349 | /* If there is a signal already queued, after unblocking ignore it */ | ||
| 350 | set_handler(SIGIO, SIG_IGN, 0, -1); | ||
| 351 | |||
| 352 | return(0); | ||
| 353 | } | ||
| 354 | |||
| 355 | void forward_ipi(int fd, int pid) | ||
| 356 | { | ||
| 357 | int err; | ||
| 358 | |||
| 359 | err = os_set_owner(fd, pid); | ||
| 360 | if(err < 0) | ||
| 361 | printk("forward_ipi: set_owner failed, fd = %d, me = %d, " | ||
| 362 | "target = %d, err = %d\n", fd, os_getpid(), pid, -err); | ||
| 363 | } | ||
| 364 | |||
| 365 | void forward_interrupts(int pid) | ||
| 366 | { | ||
| 367 | struct irq_fd *irq; | ||
| 368 | unsigned long flags; | ||
| 369 | int err; | ||
| 370 | |||
| 371 | flags = irq_lock(); | ||
| 372 | for(irq=active_fds;irq != NULL;irq = irq->next){ | ||
| 373 | err = os_set_owner(irq->fd, pid); | ||
| 374 | if(err < 0){ | ||
| 375 | /* XXX Just remove the irq rather than | ||
| 376 | * print out an infinite stream of these | ||
| 377 | */ | ||
| 378 | printk("Failed to forward %d to pid %d, err = %d\n", | ||
| 379 | irq->fd, pid, -err); | ||
| 380 | } | ||
| 381 | |||
| 382 | irq->pid = pid; | ||
| 383 | } | ||
| 384 | irq_unlock(flags); | ||
| 385 | } | ||
| 386 | |||
| 387 | void init_irq_signals(int on_sigstack) | ||
| 388 | { | ||
| 389 | __sighandler_t h; | ||
| 390 | int flags; | ||
| 391 | |||
| 392 | flags = on_sigstack ? SA_ONSTACK : 0; | ||
| 393 | if(timer_irq_inited) h = (__sighandler_t) alarm_handler; | ||
| 394 | else h = boot_timer_handler; | ||
| 395 | |||
| 396 | set_handler(SIGVTALRM, h, flags | SA_RESTART, | ||
| 397 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); | ||
| 398 | set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, | ||
| 399 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | ||
| 400 | signal(SIGWINCH, SIG_IGN); | ||
| 401 | } | ||
| 402 | |||
| 403 | /* | ||
| 404 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
| 405 | * Emacs will notice this stuff at the end of the file and automatically | ||
| 406 | * adjust the settings for this buffer only. This must remain at the end | ||
| 407 | * of the file. | ||
| 408 | * --------------------------------------------------------------------------- | ||
| 409 | * Local variables: | ||
| 410 | * c-file-style: "linux" | ||
| 411 | * End: | ||
| 412 | */ | ||
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 0e65340eee33..0500800df1c1 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "linux/vmalloc.h" | 9 | #include "linux/vmalloc.h" |
| 10 | #include "linux/bootmem.h" | 10 | #include "linux/bootmem.h" |
| 11 | #include "linux/module.h" | 11 | #include "linux/module.h" |
| 12 | #include "linux/pfn.h" | ||
| 12 | #include "asm/types.h" | 13 | #include "asm/types.h" |
| 13 | #include "asm/pgtable.h" | 14 | #include "asm/pgtable.h" |
| 14 | #include "kern_util.h" | 15 | #include "kern_util.h" |
| @@ -316,8 +317,6 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len, | |||
| 316 | } | 317 | } |
| 317 | } | 318 | } |
| 318 | 319 | ||
| 319 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | ||
| 320 | |||
| 321 | extern int __syscall_stub_start, __binary_start; | 320 | extern int __syscall_stub_start, __binary_start; |
| 322 | 321 | ||
| 323 | void setup_physmem(unsigned long start, unsigned long reserve_end, | 322 | void setup_physmem(unsigned long start, unsigned long reserve_end, |
diff --git a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio_kern.c index 229988463c4c..1c1300fb1e95 100644 --- a/arch/um/kernel/sigio_kern.c +++ b/arch/um/kernel/sigio_kern.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) |
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| @@ -12,13 +12,16 @@ | |||
| 12 | #include "sigio.h" | 12 | #include "sigio.h" |
| 13 | #include "irq_user.h" | 13 | #include "irq_user.h" |
| 14 | #include "irq_kern.h" | 14 | #include "irq_kern.h" |
| 15 | #include "os.h" | ||
| 15 | 16 | ||
| 16 | /* Protected by sigio_lock() called from write_sigio_workaround */ | 17 | /* Protected by sigio_lock() called from write_sigio_workaround */ |
| 17 | static int sigio_irq_fd = -1; | 18 | static int sigio_irq_fd = -1; |
| 18 | 19 | ||
| 19 | static irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused) | 20 | static irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused) |
| 20 | { | 21 | { |
| 21 | read_sigio_fd(sigio_irq_fd); | 22 | char c; |
| 23 | |||
| 24 | os_read_file(sigio_irq_fd, &c, sizeof(c)); | ||
| 22 | reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); | 25 | reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); |
| 23 | return(IRQ_HANDLED); | 26 | return(IRQ_HANDLED); |
| 24 | } | 27 | } |
| @@ -51,6 +54,9 @@ void sigio_unlock(void) | |||
| 51 | spin_unlock(&sigio_spinlock); | 54 | spin_unlock(&sigio_spinlock); |
| 52 | } | 55 | } |
| 53 | 56 | ||
| 57 | extern void sigio_cleanup(void); | ||
| 58 | __uml_exitcall(sigio_cleanup); | ||
| 59 | |||
| 54 | /* | 60 | /* |
| 55 | * Overrides for Emacs so that we follow Linus's tabbing style. | 61 | * Overrides for Emacs so that we follow Linus's tabbing style. |
| 56 | * Emacs will notice this stuff at the end of the file and automatically | 62 | * Emacs will notice this stuff at the end of the file and automatically |
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index 72113b0a96e7..c8d8d0ac1a7f 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) |
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| @@ -77,9 +77,9 @@ static int idle_proc(void *cpup) | |||
| 77 | if(err < 0) | 77 | if(err < 0) |
| 78 | panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); | 78 | panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); |
| 79 | 79 | ||
| 80 | activate_ipi(cpu_data[cpu].ipi_pipe[0], | 80 | os_set_fd_async(cpu_data[cpu].ipi_pipe[0], |
| 81 | current->thread.mode.tt.extern_pid); | 81 | current->thread.mode.tt.extern_pid); |
| 82 | 82 | ||
| 83 | wmb(); | 83 | wmb(); |
| 84 | if (cpu_test_and_set(cpu, cpu_callin_map)) { | 84 | if (cpu_test_and_set(cpu, cpu_callin_map)) { |
| 85 | printk("huh, CPU#%d already present??\n", cpu); | 85 | printk("huh, CPU#%d already present??\n", cpu); |
| @@ -106,7 +106,7 @@ static struct task_struct *idle_thread(int cpu) | |||
| 106 | panic("copy_process failed in idle_thread, error = %ld", | 106 | panic("copy_process failed in idle_thread, error = %ld", |
| 107 | PTR_ERR(new_task)); | 107 | PTR_ERR(new_task)); |
| 108 | 108 | ||
| 109 | cpu_tasks[cpu] = ((struct cpu_task) | 109 | cpu_tasks[cpu] = ((struct cpu_task) |
| 110 | { .pid = new_task->thread.mode.tt.extern_pid, | 110 | { .pid = new_task->thread.mode.tt.extern_pid, |
| 111 | .task = new_task } ); | 111 | .task = new_task } ); |
| 112 | idle_threads[cpu] = new_task; | 112 | idle_threads[cpu] = new_task; |
| @@ -134,12 +134,12 @@ void smp_prepare_cpus(unsigned int maxcpus) | |||
| 134 | if(err < 0) | 134 | if(err < 0) |
| 135 | panic("CPU#0 failed to create IPI pipe, errno = %d", -err); | 135 | panic("CPU#0 failed to create IPI pipe, errno = %d", -err); |
| 136 | 136 | ||
| 137 | activate_ipi(cpu_data[me].ipi_pipe[0], | 137 | os_set_fd_async(cpu_data[me].ipi_pipe[0], |
| 138 | current->thread.mode.tt.extern_pid); | 138 | current->thread.mode.tt.extern_pid); |
| 139 | 139 | ||
| 140 | for(cpu = 1; cpu < ncpus; cpu++){ | 140 | for(cpu = 1; cpu < ncpus; cpu++){ |
| 141 | printk("Booting processor %d...\n", cpu); | 141 | printk("Booting processor %d...\n", cpu); |
| 142 | 142 | ||
| 143 | idle = idle_thread(cpu); | 143 | idle = idle_thread(cpu); |
| 144 | 144 | ||
| 145 | init_idle(idle, cpu); | 145 | init_idle(idle, cpu); |
| @@ -223,7 +223,7 @@ void smp_call_function_slave(int cpu) | |||
| 223 | atomic_inc(&scf_finished); | 223 | atomic_inc(&scf_finished); |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, | 226 | int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, |
| 227 | int wait) | 227 | int wait) |
| 228 | { | 228 | { |
| 229 | int cpus = num_online_cpus() - 1; | 229 | int cpus = num_online_cpus() - 1; |
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 80c9c18aae94..7d51dd7201c3 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c | |||
| @@ -421,7 +421,7 @@ int linux_main(int argc, char **argv) | |||
| 421 | #ifndef CONFIG_HIGHMEM | 421 | #ifndef CONFIG_HIGHMEM |
| 422 | highmem = 0; | 422 | highmem = 0; |
| 423 | printf("CONFIG_HIGHMEM not enabled - physical memory shrunk " | 423 | printf("CONFIG_HIGHMEM not enabled - physical memory shrunk " |
| 424 | "to %lu bytes\n", physmem_size); | 424 | "to %Lu bytes\n", physmem_size); |
| 425 | #endif | 425 | #endif |
| 426 | } | 426 | } |
| 427 | 427 | ||
| @@ -433,8 +433,8 @@ int linux_main(int argc, char **argv) | |||
| 433 | 433 | ||
| 434 | setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); | 434 | setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); |
| 435 | if(init_maps(physmem_size, iomem_size, highmem)){ | 435 | if(init_maps(physmem_size, iomem_size, highmem)){ |
| 436 | printf("Failed to allocate mem_map for %lu bytes of physical " | 436 | printf("Failed to allocate mem_map for %Lu bytes of physical " |
| 437 | "memory and %lu bytes of highmem\n", physmem_size, | 437 | "memory and %Lu bytes of highmem\n", physmem_size, |
| 438 | highmem); | 438 | highmem); |
| 439 | exit(1); | 439 | exit(1); |
| 440 | } | 440 | } |
| @@ -477,7 +477,8 @@ static struct notifier_block panic_exit_notifier = { | |||
| 477 | 477 | ||
| 478 | void __init setup_arch(char **cmdline_p) | 478 | void __init setup_arch(char **cmdline_p) |
| 479 | { | 479 | { |
| 480 | notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); | 480 | atomic_notifier_chain_register(&panic_notifier_list, |
| 481 | &panic_exit_notifier); | ||
| 481 | paging_init(); | 482 | paging_init(); |
| 482 | strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); | 483 | strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); |
| 483 | *cmdline_p = command_line; | 484 | *cmdline_p = command_line; |
| @@ -487,8 +488,7 @@ void __init setup_arch(char **cmdline_p) | |||
| 487 | void __init check_bugs(void) | 488 | void __init check_bugs(void) |
| 488 | { | 489 | { |
| 489 | arch_check_bugs(); | 490 | arch_check_bugs(); |
| 490 | check_sigio(); | 491 | os_check_bugs(); |
| 491 | check_devanon(); | ||
| 492 | } | 492 | } |
| 493 | 493 | ||
| 494 | void apply_alternatives(struct alt_instr *start, struct alt_instr *end) | 494 | void apply_alternatives(struct alt_instr *start, struct alt_instr *end) |
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 08a4e628b24c..1659386b42bb 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile | |||
| @@ -3,14 +3,17 @@ | |||
| 3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ | 6 | obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \ |
| 7 | start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o user_syms.o \ | 7 | signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o \ |
| 8 | util.o drivers/ sys-$(SUBARCH)/ | 8 | user_syms.o util.o drivers/ sys-$(SUBARCH)/ |
| 9 | 9 | ||
| 10 | obj-$(CONFIG_MODE_SKAS) += skas/ | 10 | obj-$(CONFIG_MODE_SKAS) += skas/ |
| 11 | obj-$(CONFIG_TTY_LOG) += tty_log.o | ||
| 12 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o | ||
| 11 | 13 | ||
| 12 | USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ | 14 | USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \ |
| 13 | start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o util.o | 15 | process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o \ |
| 16 | uaccess.o umid.o util.o | ||
| 14 | 17 | ||
| 15 | elf_aux.o: $(ARCH_DIR)/kernel-offsets.h | 18 | elf_aux.o: $(ARCH_DIR)/kernel-offsets.h |
| 16 | CFLAGS_elf_aux.o += -I$(objtree)/arch/um | 19 | CFLAGS_elf_aux.o += -I$(objtree)/arch/um |
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c new file mode 100644 index 000000000000..e599be423da1 --- /dev/null +++ b/arch/um/os-Linux/irq.c | |||
| @@ -0,0 +1,162 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
| 3 | * Licensed under the GPL | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <stdlib.h> | ||
| 7 | #include <unistd.h> | ||
| 8 | #include <errno.h> | ||
| 9 | #include <signal.h> | ||
| 10 | #include <string.h> | ||
| 11 | #include <sys/poll.h> | ||
| 12 | #include <sys/types.h> | ||
| 13 | #include <sys/time.h> | ||
| 14 | #include "user_util.h" | ||
| 15 | #include "kern_util.h" | ||
| 16 | #include "user.h" | ||
| 17 | #include "process.h" | ||
| 18 | #include "sigio.h" | ||
| 19 | #include "irq_user.h" | ||
| 20 | #include "os.h" | ||
| 21 | |||
| 22 | static struct pollfd *pollfds = NULL; | ||
| 23 | static int pollfds_num = 0; | ||
| 24 | static int pollfds_size = 0; | ||
| 25 | |||
| 26 | int os_waiting_for_events(struct irq_fd *active_fds) | ||
| 27 | { | ||
| 28 | struct irq_fd *irq_fd; | ||
| 29 | int i, n, err; | ||
| 30 | |||
| 31 | n = poll(pollfds, pollfds_num, 0); | ||
| 32 | if(n < 0){ | ||
| 33 | err = -errno; | ||
| 34 | if(errno != EINTR) | ||
| 35 | printk("sigio_handler: os_waiting_for_events:" | ||
| 36 | " poll returned %d, errno = %d\n", n, errno); | ||
| 37 | return err; | ||
| 38 | } | ||
| 39 | |||
| 40 | if(n == 0) | ||
| 41 | return 0; | ||
| 42 | |||
| 43 | irq_fd = active_fds; | ||
| 44 | |||
| 45 | for(i = 0; i < pollfds_num; i++){ | ||
| 46 | if(pollfds[i].revents != 0){ | ||
| 47 | irq_fd->current_events = pollfds[i].revents; | ||
| 48 | pollfds[i].fd = -1; | ||
| 49 | } | ||
| 50 | irq_fd = irq_fd->next; | ||
| 51 | } | ||
| 52 | return n; | ||
| 53 | } | ||
| 54 | |||
| 55 | int os_isatty(int fd) | ||
| 56 | { | ||
| 57 | return(isatty(fd)); | ||
| 58 | } | ||
| 59 | |||
| 60 | int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds) | ||
| 61 | { | ||
| 62 | if (pollfds_num == pollfds_size) { | ||
| 63 | if (size_tmpfds <= pollfds_size * sizeof(pollfds[0])) { | ||
| 64 | /* return min size needed for new pollfds area */ | ||
| 65 | return((pollfds_size + 1) * sizeof(pollfds[0])); | ||
| 66 | } | ||
| 67 | |||
| 68 | if(pollfds != NULL){ | ||
| 69 | memcpy(tmp_pfd, pollfds, | ||
| 70 | sizeof(pollfds[0]) * pollfds_size); | ||
| 71 | /* remove old pollfds */ | ||
| 72 | kfree(pollfds); | ||
| 73 | } | ||
| 74 | pollfds = tmp_pfd; | ||
| 75 | pollfds_size++; | ||
| 76 | } else { | ||
| 77 | /* remove not used tmp_pfd */ | ||
| 78 | if (tmp_pfd != NULL) | ||
| 79 | kfree(tmp_pfd); | ||
| 80 | } | ||
| 81 | |||
| 82 | pollfds[pollfds_num] = ((struct pollfd) { .fd = fd, | ||
| 83 | .events = events, | ||
| 84 | .revents = 0 }); | ||
| 85 | pollfds_num++; | ||
| 86 | |||
| 87 | return(0); | ||
| 88 | } | ||
| 89 | |||
| 90 | void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg, | ||
| 91 | struct irq_fd *active_fds, struct irq_fd ***last_irq_ptr2) | ||
| 92 | { | ||
| 93 | struct irq_fd **prev; | ||
| 94 | int i = 0; | ||
| 95 | |||
| 96 | prev = &active_fds; | ||
| 97 | while(*prev != NULL){ | ||
| 98 | if((*test)(*prev, arg)){ | ||
| 99 | struct irq_fd *old_fd = *prev; | ||
| 100 | if((pollfds[i].fd != -1) && | ||
| 101 | (pollfds[i].fd != (*prev)->fd)){ | ||
| 102 | printk("os_free_irq_by_cb - mismatch between " | ||
| 103 | "active_fds and pollfds, fd %d vs %d\n", | ||
| 104 | (*prev)->fd, pollfds[i].fd); | ||
| 105 | goto out; | ||
| 106 | } | ||
| 107 | |||
| 108 | pollfds_num--; | ||
| 109 | |||
| 110 | /* This moves the *whole* array after pollfds[i] | ||
| 111 | * (though it doesn't spot as such)! | ||
| 112 | */ | ||
| 113 | |||
| 114 | memmove(&pollfds[i], &pollfds[i + 1], | ||
| 115 | (pollfds_num - i) * sizeof(pollfds[0])); | ||
| 116 | if(*last_irq_ptr2 == &old_fd->next) | ||
| 117 | *last_irq_ptr2 = prev; | ||
| 118 | |||
| 119 | *prev = (*prev)->next; | ||
| 120 | if(old_fd->type == IRQ_WRITE) | ||
| 121 | ignore_sigio_fd(old_fd->fd); | ||
| 122 | kfree(old_fd); | ||
| 123 | continue; | ||
| 124 | } | ||
| 125 | prev = &(*prev)->next; | ||
| 126 | i++; | ||
| 127 | } | ||
| 128 | out: | ||
| 129 | return; | ||
| 130 | } | ||
| 131 | |||
| 132 | |||
| 133 | int os_get_pollfd(int i) | ||
| 134 | { | ||
| 135 | return(pollfds[i].fd); | ||
| 136 | } | ||
| 137 | |||
| 138 | void os_set_pollfd(int i, int fd) | ||
| 139 | { | ||
| 140 | pollfds[i].fd = fd; | ||
| 141 | } | ||
| 142 | |||
| 143 | void os_set_ioignore(void) | ||
| 144 | { | ||
| 145 | set_handler(SIGIO, SIG_IGN, 0, -1); | ||
| 146 | } | ||
| 147 | |||
| 148 | void init_irq_signals(int on_sigstack) | ||
| 149 | { | ||
| 150 | __sighandler_t h; | ||
| 151 | int flags; | ||
| 152 | |||
| 153 | flags = on_sigstack ? SA_ONSTACK : 0; | ||
| 154 | if(timer_irq_inited) h = (__sighandler_t) alarm_handler; | ||
| 155 | else h = boot_timer_handler; | ||
| 156 | |||
| 157 | set_handler(SIGVTALRM, h, flags | SA_RESTART, | ||
| 158 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1); | ||
| 159 | set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART, | ||
| 160 | SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); | ||
| 161 | signal(SIGWINCH, SIG_IGN); | ||
| 162 | } | ||
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/os-Linux/sigio.c index f7b18e157d35..9ba942947146 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/os-Linux/sigio.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) |
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| @@ -20,128 +20,7 @@ | |||
| 20 | #include "sigio.h" | 20 | #include "sigio.h" |
| 21 | #include "os.h" | 21 | #include "os.h" |
| 22 | 22 | ||
| 23 | /* Changed during early boot */ | 23 | /* Protected by sigio_lock(), also used by sigio_cleanup, which is an |
| 24 | int pty_output_sigio = 0; | ||
| 25 | int pty_close_sigio = 0; | ||
| 26 | |||
| 27 | /* Used as a flag during SIGIO testing early in boot */ | ||
| 28 | static volatile int got_sigio = 0; | ||
| 29 | |||
| 30 | void __init handler(int sig) | ||
| 31 | { | ||
| 32 | got_sigio = 1; | ||
| 33 | } | ||
| 34 | |||
| 35 | struct openpty_arg { | ||
| 36 | int master; | ||
| 37 | int slave; | ||
| 38 | int err; | ||
| 39 | }; | ||
| 40 | |||
| 41 | static void openpty_cb(void *arg) | ||
| 42 | { | ||
| 43 | struct openpty_arg *info = arg; | ||
| 44 | |||
| 45 | info->err = 0; | ||
| 46 | if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) | ||
| 47 | info->err = -errno; | ||
| 48 | } | ||
| 49 | |||
| 50 | void __init check_one_sigio(void (*proc)(int, int)) | ||
| 51 | { | ||
| 52 | struct sigaction old, new; | ||
| 53 | struct openpty_arg pty = { .master = -1, .slave = -1 }; | ||
| 54 | int master, slave, err; | ||
| 55 | |||
| 56 | initial_thread_cb(openpty_cb, &pty); | ||
| 57 | if(pty.err){ | ||
| 58 | printk("openpty failed, errno = %d\n", -pty.err); | ||
| 59 | return; | ||
| 60 | } | ||
| 61 | |||
| 62 | master = pty.master; | ||
| 63 | slave = pty.slave; | ||
| 64 | |||
| 65 | if((master == -1) || (slave == -1)){ | ||
| 66 | printk("openpty failed to allocate a pty\n"); | ||
| 67 | return; | ||
| 68 | } | ||
| 69 | |||
| 70 | /* Not now, but complain so we now where we failed. */ | ||
| 71 | err = raw(master); | ||
| 72 | if (err < 0) | ||
| 73 | panic("check_sigio : __raw failed, errno = %d\n", -err); | ||
| 74 | |||
| 75 | err = os_sigio_async(master, slave); | ||
| 76 | if(err < 0) | ||
| 77 | panic("tty_fds : sigio_async failed, err = %d\n", -err); | ||
| 78 | |||
| 79 | if(sigaction(SIGIO, NULL, &old) < 0) | ||
| 80 | panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); | ||
| 81 | new = old; | ||
| 82 | new.sa_handler = handler; | ||
| 83 | if(sigaction(SIGIO, &new, NULL) < 0) | ||
| 84 | panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); | ||
| 85 | |||
| 86 | got_sigio = 0; | ||
| 87 | (*proc)(master, slave); | ||
| 88 | |||
| 89 | os_close_file(master); | ||
| 90 | os_close_file(slave); | ||
| 91 | |||
| 92 | if(sigaction(SIGIO, &old, NULL) < 0) | ||
| 93 | panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); | ||
| 94 | } | ||
| 95 | |||
| 96 | static void tty_output(int master, int slave) | ||
| 97 | { | ||
| 98 | int n; | ||
| 99 | char buf[512]; | ||
| 100 | |||
| 101 | printk("Checking that host ptys support output SIGIO..."); | ||
| 102 | |||
| 103 | memset(buf, 0, sizeof(buf)); | ||
| 104 | |||
| 105 | while(os_write_file(master, buf, sizeof(buf)) > 0) ; | ||
| 106 | if(errno != EAGAIN) | ||
| 107 | panic("check_sigio : write failed, errno = %d\n", errno); | ||
| 108 | while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; | ||
| 109 | |||
| 110 | if (got_sigio) { | ||
| 111 | printk("Yes\n"); | ||
| 112 | pty_output_sigio = 1; | ||
| 113 | } else if (n == -EAGAIN) { | ||
| 114 | printk("No, enabling workaround\n"); | ||
| 115 | } else { | ||
| 116 | panic("check_sigio : read failed, err = %d\n", n); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | static void tty_close(int master, int slave) | ||
| 121 | { | ||
| 122 | printk("Checking that host ptys support SIGIO on close..."); | ||
| 123 | |||
| 124 | os_close_file(slave); | ||
| 125 | if(got_sigio){ | ||
| 126 | printk("Yes\n"); | ||
| 127 | pty_close_sigio = 1; | ||
| 128 | } | ||
| 129 | else printk("No, enabling workaround\n"); | ||
| 130 | } | ||
| 131 | |||
| 132 | void __init check_sigio(void) | ||
| 133 | { | ||
| 134 | if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && | ||
| 135 | (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ | ||
| 136 | printk("No pseudo-terminals available - skipping pty SIGIO " | ||
| 137 | "check\n"); | ||
| 138 | return; | ||
| 139 | } | ||
| 140 | check_one_sigio(tty_output); | ||
| 141 | check_one_sigio(tty_close); | ||
| 142 | } | ||
| 143 | |||
| 144 | /* Protected by sigio_lock(), also used by sigio_cleanup, which is an | ||
| 145 | * exitcall. | 24 | * exitcall. |
| 146 | */ | 25 | */ |
| 147 | static int write_sigio_pid = -1; | 26 | static int write_sigio_pid = -1; |
| @@ -150,8 +29,10 @@ static int write_sigio_pid = -1; | |||
| 150 | * the descriptors closed after it is killed. So, it can't see them change. | 29 | * the descriptors closed after it is killed. So, it can't see them change. |
| 151 | * On the UML side, they are changed under the sigio_lock. | 30 | * On the UML side, they are changed under the sigio_lock. |
| 152 | */ | 31 | */ |
| 153 | static int write_sigio_fds[2] = { -1, -1 }; | 32 | #define SIGIO_FDS_INIT {-1, -1} |
| 154 | static int sigio_private[2] = { -1, -1 }; | 33 | |
| 34 | static int write_sigio_fds[2] = SIGIO_FDS_INIT; | ||
| 35 | static int sigio_private[2] = SIGIO_FDS_INIT; | ||
| 155 | 36 | ||
| 156 | struct pollfds { | 37 | struct pollfds { |
| 157 | struct pollfd *poll; | 38 | struct pollfd *poll; |
| @@ -264,13 +145,13 @@ static void update_thread(void) | |||
| 264 | return; | 145 | return; |
| 265 | fail: | 146 | fail: |
| 266 | /* Critical section start */ | 147 | /* Critical section start */ |
| 267 | if(write_sigio_pid != -1) | 148 | if(write_sigio_pid != -1) |
| 268 | os_kill_process(write_sigio_pid, 1); | 149 | os_kill_process(write_sigio_pid, 1); |
| 269 | write_sigio_pid = -1; | 150 | write_sigio_pid = -1; |
| 270 | os_close_file(sigio_private[0]); | 151 | close(sigio_private[0]); |
| 271 | os_close_file(sigio_private[1]); | 152 | close(sigio_private[1]); |
| 272 | os_close_file(write_sigio_fds[0]); | 153 | close(write_sigio_fds[0]); |
| 273 | os_close_file(write_sigio_fds[1]); | 154 | close(write_sigio_fds[1]); |
| 274 | /* Critical section end */ | 155 | /* Critical section end */ |
| 275 | set_signals(flags); | 156 | set_signals(flags); |
| 276 | } | 157 | } |
| @@ -281,13 +162,13 @@ int add_sigio_fd(int fd, int read) | |||
| 281 | 162 | ||
| 282 | sigio_lock(); | 163 | sigio_lock(); |
| 283 | for(i = 0; i < current_poll.used; i++){ | 164 | for(i = 0; i < current_poll.used; i++){ |
| 284 | if(current_poll.poll[i].fd == fd) | 165 | if(current_poll.poll[i].fd == fd) |
| 285 | goto out; | 166 | goto out; |
| 286 | } | 167 | } |
| 287 | 168 | ||
| 288 | n = current_poll.used + 1; | 169 | n = current_poll.used + 1; |
| 289 | err = need_poll(n); | 170 | err = need_poll(n); |
| 290 | if(err) | 171 | if(err) |
| 291 | goto out; | 172 | goto out; |
| 292 | 173 | ||
| 293 | for(i = 0; i < current_poll.used; i++) | 174 | for(i = 0; i < current_poll.used; i++) |
| @@ -316,7 +197,7 @@ int ignore_sigio_fd(int fd) | |||
| 316 | } | 197 | } |
| 317 | if(i == current_poll.used) | 198 | if(i == current_poll.used) |
| 318 | goto out; | 199 | goto out; |
| 319 | 200 | ||
| 320 | err = need_poll(current_poll.used - 1); | 201 | err = need_poll(current_poll.used - 1); |
| 321 | if(err) | 202 | if(err) |
| 322 | goto out; | 203 | goto out; |
| @@ -337,7 +218,7 @@ int ignore_sigio_fd(int fd) | |||
| 337 | return(err); | 218 | return(err); |
| 338 | } | 219 | } |
| 339 | 220 | ||
| 340 | static struct pollfd* setup_initial_poll(int fd) | 221 | static struct pollfd *setup_initial_poll(int fd) |
| 341 | { | 222 | { |
| 342 | struct pollfd *p; | 223 | struct pollfd *p; |
| 343 | 224 | ||
| @@ -377,7 +258,7 @@ void write_sigio_workaround(void) | |||
| 377 | } | 258 | } |
| 378 | err = os_pipe(l_sigio_private, 1, 1); | 259 | err = os_pipe(l_sigio_private, 1, 1); |
| 379 | if(err < 0){ | 260 | if(err < 0){ |
| 380 | printk("write_sigio_workaround - os_pipe 1 failed, " | 261 | printk("write_sigio_workaround - os_pipe 2 failed, " |
| 381 | "err = %d\n", -err); | 262 | "err = %d\n", -err); |
| 382 | goto out_close1; | 263 | goto out_close1; |
| 383 | } | 264 | } |
| @@ -391,76 +272,52 @@ void write_sigio_workaround(void) | |||
| 391 | /* Did we race? Don't try to optimize this, please, it's not so likely | 272 | /* Did we race? Don't try to optimize this, please, it's not so likely |
| 392 | * to happen, and no more than once at the boot. */ | 273 | * to happen, and no more than once at the boot. */ |
| 393 | if(write_sigio_pid != -1) | 274 | if(write_sigio_pid != -1) |
| 394 | goto out_unlock; | 275 | goto out_free; |
| 395 | 276 | ||
| 396 | write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, | 277 | current_poll = ((struct pollfds) { .poll = p, |
| 397 | CLONE_FILES | CLONE_VM, &stack, 0); | 278 | .used = 1, |
| 398 | 279 | .size = 1 }); | |
| 399 | if (write_sigio_pid < 0) | ||
| 400 | goto out_clear; | ||
| 401 | 280 | ||
| 402 | if (write_sigio_irq(l_write_sigio_fds[0])) | 281 | if (write_sigio_irq(l_write_sigio_fds[0])) |
| 403 | goto out_kill; | 282 | goto out_clear_poll; |
| 404 | 283 | ||
| 405 | /* Success, finally. */ | ||
| 406 | memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds)); | 284 | memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds)); |
| 407 | memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private)); | 285 | memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private)); |
| 408 | 286 | ||
| 409 | current_poll = ((struct pollfds) { .poll = p, | 287 | write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, |
| 410 | .used = 1, | 288 | CLONE_FILES | CLONE_VM, &stack, 0); |
| 411 | .size = 1 }); | ||
| 412 | 289 | ||
| 413 | sigio_unlock(); | 290 | if (write_sigio_pid < 0) |
| 414 | return; | 291 | goto out_clear; |
| 415 | 292 | ||
| 416 | out_kill: | ||
| 417 | l_write_sigio_pid = write_sigio_pid; | ||
| 418 | write_sigio_pid = -1; | ||
| 419 | sigio_unlock(); | 293 | sigio_unlock(); |
| 420 | /* Going to call waitpid, avoid holding the lock. */ | 294 | return; |
| 421 | os_kill_process(l_write_sigio_pid, 1); | ||
| 422 | goto out_free; | ||
| 423 | 295 | ||
| 424 | out_clear: | 296 | out_clear: |
| 425 | write_sigio_pid = -1; | 297 | write_sigio_pid = -1; |
| 426 | out_unlock: | 298 | write_sigio_fds[0] = -1; |
| 427 | sigio_unlock(); | 299 | write_sigio_fds[1] = -1; |
| 428 | out_free: | 300 | sigio_private[0] = -1; |
| 301 | sigio_private[1] = -1; | ||
| 302 | out_clear_poll: | ||
| 303 | current_poll = ((struct pollfds) { .poll = NULL, | ||
| 304 | .size = 0, | ||
| 305 | .used = 0 }); | ||
| 306 | out_free: | ||
| 429 | kfree(p); | 307 | kfree(p); |
| 430 | out_close2: | 308 | sigio_unlock(); |
| 431 | os_close_file(l_sigio_private[0]); | 309 | out_close2: |
| 432 | os_close_file(l_sigio_private[1]); | 310 | close(l_sigio_private[0]); |
| 433 | out_close1: | 311 | close(l_sigio_private[1]); |
| 434 | os_close_file(l_write_sigio_fds[0]); | 312 | out_close1: |
| 435 | os_close_file(l_write_sigio_fds[1]); | 313 | close(l_write_sigio_fds[0]); |
| 436 | return; | 314 | close(l_write_sigio_fds[1]); |
| 437 | } | ||
| 438 | |||
| 439 | int read_sigio_fd(int fd) | ||
| 440 | { | ||
| 441 | int n; | ||
| 442 | char c; | ||
| 443 | |||
| 444 | n = os_read_file(fd, &c, sizeof(c)); | ||
| 445 | if(n != sizeof(c)){ | ||
| 446 | if(n < 0) { | ||
| 447 | printk("read_sigio_fd - read failed, err = %d\n", -n); | ||
| 448 | return(n); | ||
| 449 | } | ||
| 450 | else { | ||
| 451 | printk("read_sigio_fd - short read, bytes = %d\n", n); | ||
| 452 | return(-EIO); | ||
| 453 | } | ||
| 454 | } | ||
| 455 | return(n); | ||
| 456 | } | 315 | } |
| 457 | 316 | ||
| 458 | static void sigio_cleanup(void) | 317 | void sigio_cleanup(void) |
| 459 | { | 318 | { |
| 460 | if (write_sigio_pid != -1) { | 319 | if(write_sigio_pid != -1){ |
| 461 | os_kill_process(write_sigio_pid, 1); | 320 | os_kill_process(write_sigio_pid, 1); |
| 462 | write_sigio_pid = -1; | 321 | write_sigio_pid = -1; |
| 463 | } | 322 | } |
| 464 | } | 323 | } |
| 465 | |||
| 466 | __uml_exitcall(sigio_cleanup); | ||
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 829d6b0d8b02..32753131f8d8 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <pty.h> | ||
| 6 | #include <stdio.h> | 7 | #include <stdio.h> |
| 7 | #include <stddef.h> | 8 | #include <stddef.h> |
| 8 | #include <stdarg.h> | 9 | #include <stdarg.h> |
| @@ -539,3 +540,130 @@ int __init parse_iomem(char *str, int *add) | |||
| 539 | return(1); | 540 | return(1); |
| 540 | } | 541 | } |
| 541 | 542 | ||
| 543 | |||
| 544 | /* Changed during early boot */ | ||
| 545 | int pty_output_sigio = 0; | ||
| 546 | int pty_close_sigio = 0; | ||
| 547 | |||
| 548 | /* Used as a flag during SIGIO testing early in boot */ | ||
| 549 | static volatile int got_sigio = 0; | ||
| 550 | |||
| 551 | static void __init handler(int sig) | ||
| 552 | { | ||
| 553 | got_sigio = 1; | ||
| 554 | } | ||
| 555 | |||
| 556 | struct openpty_arg { | ||
| 557 | int master; | ||
| 558 | int slave; | ||
| 559 | int err; | ||
| 560 | }; | ||
| 561 | |||
| 562 | static void openpty_cb(void *arg) | ||
| 563 | { | ||
| 564 | struct openpty_arg *info = arg; | ||
| 565 | |||
| 566 | info->err = 0; | ||
| 567 | if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) | ||
| 568 | info->err = -errno; | ||
| 569 | } | ||
| 570 | |||
| 571 | static void __init check_one_sigio(void (*proc)(int, int)) | ||
| 572 | { | ||
| 573 | struct sigaction old, new; | ||
| 574 | struct openpty_arg pty = { .master = -1, .slave = -1 }; | ||
| 575 | int master, slave, err; | ||
| 576 | |||
| 577 | initial_thread_cb(openpty_cb, &pty); | ||
| 578 | if(pty.err){ | ||
| 579 | printk("openpty failed, errno = %d\n", -pty.err); | ||
| 580 | return; | ||
| 581 | } | ||
| 582 | |||
| 583 | master = pty.master; | ||
| 584 | slave = pty.slave; | ||
| 585 | |||
| 586 | if((master == -1) || (slave == -1)){ | ||
| 587 | printk("openpty failed to allocate a pty\n"); | ||
| 588 | return; | ||
| 589 | } | ||
| 590 | |||
| 591 | /* Not now, but complain so we now where we failed. */ | ||
| 592 | err = raw(master); | ||
| 593 | if (err < 0) | ||
| 594 | panic("check_sigio : __raw failed, errno = %d\n", -err); | ||
| 595 | |||
| 596 | err = os_sigio_async(master, slave); | ||
| 597 | if(err < 0) | ||
| 598 | panic("tty_fds : sigio_async failed, err = %d\n", -err); | ||
| 599 | |||
| 600 | if(sigaction(SIGIO, NULL, &old) < 0) | ||
| 601 | panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); | ||
| 602 | new = old; | ||
| 603 | new.sa_handler = handler; | ||
| 604 | if(sigaction(SIGIO, &new, NULL) < 0) | ||
| 605 | panic("check_sigio : sigaction 2 failed, errno = %d\n", errno); | ||
| 606 | |||
| 607 | got_sigio = 0; | ||
| 608 | (*proc)(master, slave); | ||
| 609 | |||
| 610 | close(master); | ||
| 611 | close(slave); | ||
| 612 | |||
| 613 | if(sigaction(SIGIO, &old, NULL) < 0) | ||
| 614 | panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); | ||
| 615 | } | ||
| 616 | |||
| 617 | static void tty_output(int master, int slave) | ||
| 618 | { | ||
| 619 | int n; | ||
| 620 | char buf[512]; | ||
| 621 | |||
| 622 | printk("Checking that host ptys support output SIGIO..."); | ||
| 623 | |||
| 624 | memset(buf, 0, sizeof(buf)); | ||
| 625 | |||
| 626 | while(os_write_file(master, buf, sizeof(buf)) > 0) ; | ||
| 627 | if(errno != EAGAIN) | ||
| 628 | panic("check_sigio : write failed, errno = %d\n", errno); | ||
| 629 | while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; | ||
| 630 | |||
| 631 | if(got_sigio){ | ||
| 632 | printk("Yes\n"); | ||
| 633 | pty_output_sigio = 1; | ||
| 634 | } | ||
| 635 | else if(n == -EAGAIN) printk("No, enabling workaround\n"); | ||
| 636 | else panic("check_sigio : read failed, err = %d\n", n); | ||
| 637 | } | ||
| 638 | |||
| 639 | static void tty_close(int master, int slave) | ||
| 640 | { | ||
| 641 | printk("Checking that host ptys support SIGIO on close..."); | ||
| 642 | |||
| 643 | close(slave); | ||
| 644 | if(got_sigio){ | ||
| 645 | printk("Yes\n"); | ||
| 646 | pty_close_sigio = 1; | ||
| 647 | } | ||
| 648 | else printk("No, enabling workaround\n"); | ||
| 649 | } | ||
| 650 | |||
| 651 | void __init check_sigio(void) | ||
| 652 | { | ||
| 653 | if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && | ||
| 654 | (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ | ||
| 655 | printk("No pseudo-terminals available - skipping pty SIGIO " | ||
| 656 | "check\n"); | ||
| 657 | return; | ||
| 658 | } | ||
| 659 | check_one_sigio(tty_output); | ||
| 660 | check_one_sigio(tty_close); | ||
| 661 | } | ||
| 662 | |||
| 663 | void os_check_bugs(void) | ||
| 664 | { | ||
| 665 | check_ptrace(); | ||
| 666 | check_sigio(); | ||
| 667 | check_devanon(); | ||
| 668 | } | ||
| 669 | |||
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c index 919d19f11537..5461a065bbb9 100644 --- a/arch/um/os-Linux/tt.c +++ b/arch/um/os-Linux/tt.c | |||
| @@ -110,6 +110,16 @@ int wait_for_stop(int pid, int sig, int cont_type, void *relay) | |||
| 110 | } | 110 | } |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | void forward_ipi(int fd, int pid) | ||
| 114 | { | ||
| 115 | int err; | ||
| 116 | |||
| 117 | err = os_set_owner(fd, pid); | ||
| 118 | if(err < 0) | ||
| 119 | printk("forward_ipi: set_owner failed, fd = %d, me = %d, " | ||
| 120 | "target = %d, err = %d\n", fd, os_getpid(), pid, -err); | ||
| 121 | } | ||
| 122 | |||
| 113 | /* | 123 | /* |
| 114 | *------------------------- | 124 | *------------------------- |
| 115 | * only for tt mode (will be deleted in future...) | 125 | * only for tt mode (will be deleted in future...) |
diff --git a/arch/um/kernel/tty_log.c b/arch/um/os-Linux/tty_log.c index 9ada656f68ce..c6ba56c1560f 100644 --- a/arch/um/kernel/tty_log.c +++ b/arch/um/os-Linux/tty_log.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and | 2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and |
| 3 | * geoffrey hing <ghing@net.ohio-state.edu> | 3 | * geoffrey hing <ghing@net.ohio-state.edu> |
| 4 | * Licensed under the GPL | 4 | * Licensed under the GPL |
| 5 | */ | 5 | */ |
| @@ -58,7 +58,7 @@ int open_tty_log(void *tty, void *current_tty) | |||
| 58 | return(tty_log_fd); | 58 | return(tty_log_fd); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, | 61 | sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, |
| 62 | (unsigned int) tv.tv_usec); | 62 | (unsigned int) tv.tv_usec); |
| 63 | 63 | ||
| 64 | fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))), | 64 | fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))), |
| @@ -216,15 +216,3 @@ __uml_setup("tty_log_fd=", set_tty_log_fd, | |||
| 216 | " tty data will be written. Preconfigure the descriptor with something\n" | 216 | " tty data will be written. Preconfigure the descriptor with something\n" |
| 217 | " like '10>tty_log tty_log_fd=10'.\n\n" | 217 | " like '10>tty_log tty_log_fd=10'.\n\n" |
| 218 | ); | 218 | ); |
| 219 | |||
| 220 | |||
| 221 | /* | ||
| 222 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
| 223 | * Emacs will notice this stuff at the end of the file and automatically | ||
| 224 | * adjust the settings for this buffer only. This must remain at the end | ||
| 225 | * of the file. | ||
| 226 | * --------------------------------------------------------------------------- | ||
| 227 | * Local variables: | ||
| 228 | * c-file-style: "linux" | ||
| 229 | * End: | ||
| 230 | */ | ||
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c index ecf107ae5ac8..198e59163288 100644 --- a/arch/um/os-Linux/umid.c +++ b/arch/um/os-Linux/umid.c | |||
| @@ -143,8 +143,10 @@ static int not_dead_yet(char *dir) | |||
| 143 | goto out_close; | 143 | goto out_close; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | if((kill(p, 0) == 0) || (errno != ESRCH)) | 146 | if((kill(p, 0) == 0) || (errno != ESRCH)){ |
| 147 | printk("umid \"%s\" is already in use by pid %d\n", umid, p); | ||
| 147 | return 1; | 148 | return 1; |
| 149 | } | ||
| 148 | 150 | ||
| 149 | err = actually_do_remove(dir); | 151 | err = actually_do_remove(dir); |
| 150 | if(err) | 152 | if(err) |
| @@ -234,33 +236,44 @@ int __init make_umid(void) | |||
| 234 | err = mkdir(tmp, 0777); | 236 | err = mkdir(tmp, 0777); |
| 235 | if(err < 0){ | 237 | if(err < 0){ |
| 236 | err = -errno; | 238 | err = -errno; |
| 237 | if(errno != EEXIST) | 239 | if(err != -EEXIST) |
| 238 | goto err; | 240 | goto err; |
| 239 | 241 | ||
| 240 | if(not_dead_yet(tmp) < 0) | 242 | /* 1 -> this umid is already in use |
| 243 | * < 0 -> we couldn't remove the umid directory | ||
| 244 | * In either case, we can't use this umid, so return -EEXIST. | ||
| 245 | */ | ||
| 246 | if(not_dead_yet(tmp) != 0) | ||
| 241 | goto err; | 247 | goto err; |
| 242 | 248 | ||
| 243 | err = mkdir(tmp, 0777); | 249 | err = mkdir(tmp, 0777); |
| 244 | } | 250 | } |
| 245 | if(err < 0){ | 251 | if(err){ |
| 246 | printk("Failed to create '%s' - err = %d\n", umid, err); | 252 | err = -errno; |
| 247 | goto err_rmdir; | 253 | printk("Failed to create '%s' - err = %d\n", umid, -errno); |
| 254 | goto err; | ||
| 248 | } | 255 | } |
| 249 | 256 | ||
| 250 | umid_setup = 1; | 257 | umid_setup = 1; |
| 251 | 258 | ||
| 252 | create_pid_file(); | 259 | create_pid_file(); |
| 253 | 260 | ||
| 254 | return 0; | 261 | err = 0; |
| 255 | |||
| 256 | err_rmdir: | ||
| 257 | rmdir(tmp); | ||
| 258 | err: | 262 | err: |
| 259 | return err; | 263 | return err; |
| 260 | } | 264 | } |
| 261 | 265 | ||
| 262 | static int __init make_umid_init(void) | 266 | static int __init make_umid_init(void) |
| 263 | { | 267 | { |
| 268 | if(!make_umid()) | ||
| 269 | return 0; | ||
| 270 | |||
| 271 | /* If initializing with the given umid failed, then try again with | ||
| 272 | * a random one. | ||
| 273 | */ | ||
| 274 | printk("Failed to initialize umid \"%s\", trying with a random umid\n", | ||
| 275 | umid); | ||
| 276 | *umid = '\0'; | ||
| 264 | make_umid(); | 277 | make_umid(); |
| 265 | 278 | ||
| 266 | return 0; | 279 | return 0; |
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index e839ce65ad28..8032a105949a 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <linux/config.h> | 6 | #include <linux/config.h> |
| 7 | #include <linux/compiler.h> | 7 | #include <linux/compiler.h> |
| 8 | #include "linux/sched.h" | 8 | #include "linux/sched.h" |
| 9 | #include "linux/mm.h" | ||
| 9 | #include "asm/elf.h" | 10 | #include "asm/elf.h" |
| 10 | #include "asm/ptrace.h" | 11 | #include "asm/ptrace.h" |
| 11 | #include "asm/uaccess.h" | 12 | #include "asm/uaccess.h" |
| @@ -26,9 +27,17 @@ int is_syscall(unsigned long addr) | |||
| 26 | 27 | ||
| 27 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); | 28 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); |
| 28 | if(n){ | 29 | if(n){ |
| 29 | printk("is_syscall : failed to read instruction from 0x%lx\n", | 30 | /* access_process_vm() grants access to vsyscall and stub, |
| 30 | addr); | 31 | * while copy_from_user doesn't. Maybe access_process_vm is |
| 31 | return(0); | 32 | * slow, but that doesn't matter, since it will be called only |
| 33 | * in case of singlestepping, if copy_from_user failed. | ||
| 34 | */ | ||
| 35 | n = access_process_vm(current, addr, &instr, sizeof(instr), 0); | ||
| 36 | if(n != sizeof(instr)) { | ||
| 37 | printk("is_syscall : failed to read instruction from " | ||
| 38 | "0x%lx\n", addr); | ||
| 39 | return(1); | ||
| 40 | } | ||
| 32 | } | 41 | } |
| 33 | /* int 0x80 or sysenter */ | 42 | /* int 0x80 or sysenter */ |
| 34 | return((instr == 0x80cd) || (instr == 0x340f)); | 43 | return((instr == 0x80cd) || (instr == 0x340f)); |
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c index 7cd1a82dc8c2..33a40f5ef0d2 100644 --- a/arch/um/sys-i386/signal.c +++ b/arch/um/sys-i386/signal.c | |||
| @@ -58,7 +58,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs, | |||
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, | 60 | int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, |
| 61 | struct pt_regs *regs) | 61 | struct pt_regs *regs, unsigned long sp) |
| 62 | { | 62 | { |
| 63 | struct sigcontext sc; | 63 | struct sigcontext sc; |
| 64 | unsigned long fpregs[HOST_FP_SIZE]; | 64 | unsigned long fpregs[HOST_FP_SIZE]; |
| @@ -72,7 +72,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, | |||
| 72 | sc.edi = REGS_EDI(regs->regs.skas.regs); | 72 | sc.edi = REGS_EDI(regs->regs.skas.regs); |
| 73 | sc.esi = REGS_ESI(regs->regs.skas.regs); | 73 | sc.esi = REGS_ESI(regs->regs.skas.regs); |
| 74 | sc.ebp = REGS_EBP(regs->regs.skas.regs); | 74 | sc.ebp = REGS_EBP(regs->regs.skas.regs); |
| 75 | sc.esp = REGS_SP(regs->regs.skas.regs); | 75 | sc.esp = sp; |
| 76 | sc.ebx = REGS_EBX(regs->regs.skas.regs); | 76 | sc.ebx = REGS_EBX(regs->regs.skas.regs); |
| 77 | sc.edx = REGS_EDX(regs->regs.skas.regs); | 77 | sc.edx = REGS_EDX(regs->regs.skas.regs); |
| 78 | sc.ecx = REGS_ECX(regs->regs.skas.regs); | 78 | sc.ecx = REGS_ECX(regs->regs.skas.regs); |
| @@ -132,7 +132,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, | |||
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, | 134 | int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, |
| 135 | struct sigcontext *from, int fpsize) | 135 | struct sigcontext *from, int fpsize, unsigned long sp) |
| 136 | { | 136 | { |
| 137 | struct _fpstate *to_fp, *from_fp; | 137 | struct _fpstate *to_fp, *from_fp; |
| 138 | int err; | 138 | int err; |
| @@ -140,11 +140,18 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, | |||
| 140 | to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); | 140 | to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); |
| 141 | from_fp = from->fpstate; | 141 | from_fp = from->fpstate; |
| 142 | err = copy_to_user(to, from, sizeof(*to)); | 142 | err = copy_to_user(to, from, sizeof(*to)); |
| 143 | |||
| 144 | /* The SP in the sigcontext is the updated one for the signal | ||
| 145 | * delivery. The sp passed in is the original, and this needs | ||
| 146 | * to be restored, so we stick it in separately. | ||
| 147 | */ | ||
| 148 | err |= copy_to_user(&SC_SP(to), sp, sizeof(sp)); | ||
| 149 | |||
| 143 | if(from_fp != NULL){ | 150 | if(from_fp != NULL){ |
| 144 | err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); | 151 | err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); |
| 145 | err |= copy_to_user(to_fp, from_fp, fpsize); | 152 | err |= copy_to_user(to_fp, from_fp, fpsize); |
| 146 | } | 153 | } |
| 147 | return(err); | 154 | return err; |
| 148 | } | 155 | } |
| 149 | #endif | 156 | #endif |
| 150 | 157 | ||
| @@ -159,11 +166,11 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from) | |||
| 159 | } | 166 | } |
| 160 | 167 | ||
| 161 | static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, | 168 | static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, |
| 162 | struct pt_regs *from) | 169 | struct pt_regs *from, unsigned long sp) |
| 163 | { | 170 | { |
| 164 | return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), | 171 | return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), |
| 165 | sizeof(*fp)), | 172 | sizeof(*fp), sp), |
| 166 | copy_sc_to_user_skas(to, fp, from))); | 173 | copy_sc_to_user_skas(to, fp, from, sp))); |
| 167 | } | 174 | } |
| 168 | 175 | ||
| 169 | static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp, | 176 | static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp, |
| @@ -174,7 +181,7 @@ static int copy_ucontext_to_user(struct ucontext *uc, struct _fpstate *fp, | |||
| 174 | err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); | 181 | err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); |
| 175 | err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); | 182 | err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); |
| 176 | err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); | 183 | err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); |
| 177 | err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs); | 184 | err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, sp); |
| 178 | err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); | 185 | err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); |
| 179 | return(err); | 186 | return(err); |
| 180 | } | 187 | } |
| @@ -207,6 +214,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
| 207 | { | 214 | { |
| 208 | struct sigframe __user *frame; | 215 | struct sigframe __user *frame; |
| 209 | void *restorer; | 216 | void *restorer; |
| 217 | unsigned long save_sp = PT_REGS_SP(regs); | ||
| 210 | int err = 0; | 218 | int err = 0; |
| 211 | 219 | ||
| 212 | stack_top &= -8UL; | 220 | stack_top &= -8UL; |
| @@ -218,9 +226,19 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
| 218 | if(ka->sa.sa_flags & SA_RESTORER) | 226 | if(ka->sa.sa_flags & SA_RESTORER) |
| 219 | restorer = ka->sa.sa_restorer; | 227 | restorer = ka->sa.sa_restorer; |
| 220 | 228 | ||
| 229 | /* Update SP now because the page fault handler refuses to extend | ||
| 230 | * the stack if the faulting address is too far below the current | ||
| 231 | * SP, which frame now certainly is. If there's an error, the original | ||
| 232 | * value is restored on the way out. | ||
| 233 | * When writing the sigcontext to the stack, we have to write the | ||
| 234 | * original value, so that's passed to copy_sc_to_user, which does | ||
| 235 | * the right thing with it. | ||
| 236 | */ | ||
| 237 | PT_REGS_SP(regs) = (unsigned long) frame; | ||
| 238 | |||
| 221 | err |= __put_user(restorer, &frame->pretcode); | 239 | err |= __put_user(restorer, &frame->pretcode); |
| 222 | err |= __put_user(sig, &frame->sig); | 240 | err |= __put_user(sig, &frame->sig); |
| 223 | err |= copy_sc_to_user(&frame->sc, NULL, regs); | 241 | err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp); |
| 224 | err |= __put_user(mask->sig[0], &frame->sc.oldmask); | 242 | err |= __put_user(mask->sig[0], &frame->sc.oldmask); |
| 225 | if (_NSIG_WORDS > 1) | 243 | if (_NSIG_WORDS > 1) |
| 226 | err |= __copy_to_user(&frame->extramask, &mask->sig[1], | 244 | err |= __copy_to_user(&frame->extramask, &mask->sig[1], |
| @@ -238,7 +256,7 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
| 238 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); | 256 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); |
| 239 | 257 | ||
| 240 | if(err) | 258 | if(err) |
| 241 | return(err); | 259 | goto err; |
| 242 | 260 | ||
| 243 | PT_REGS_SP(regs) = (unsigned long) frame; | 261 | PT_REGS_SP(regs) = (unsigned long) frame; |
| 244 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; | 262 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; |
| @@ -248,7 +266,11 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, | |||
| 248 | 266 | ||
| 249 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) | 267 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) |
| 250 | ptrace_notify(SIGTRAP); | 268 | ptrace_notify(SIGTRAP); |
| 251 | return(0); | 269 | return 0; |
| 270 | |||
| 271 | err: | ||
| 272 | PT_REGS_SP(regs) = save_sp; | ||
| 273 | return err; | ||
| 252 | } | 274 | } |
| 253 | 275 | ||
| 254 | int setup_signal_stack_si(unsigned long stack_top, int sig, | 276 | int setup_signal_stack_si(unsigned long stack_top, int sig, |
| @@ -257,6 +279,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
| 257 | { | 279 | { |
| 258 | struct rt_sigframe __user *frame; | 280 | struct rt_sigframe __user *frame; |
| 259 | void *restorer; | 281 | void *restorer; |
| 282 | unsigned long save_sp = PT_REGS_SP(regs); | ||
| 260 | int err = 0; | 283 | int err = 0; |
| 261 | 284 | ||
| 262 | stack_top &= -8UL; | 285 | stack_top &= -8UL; |
| @@ -268,13 +291,16 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
| 268 | if(ka->sa.sa_flags & SA_RESTORER) | 291 | if(ka->sa.sa_flags & SA_RESTORER) |
| 269 | restorer = ka->sa.sa_restorer; | 292 | restorer = ka->sa.sa_restorer; |
| 270 | 293 | ||
| 294 | /* See comment above about why this is here */ | ||
| 295 | PT_REGS_SP(regs) = (unsigned long) frame; | ||
| 296 | |||
| 271 | err |= __put_user(restorer, &frame->pretcode); | 297 | err |= __put_user(restorer, &frame->pretcode); |
| 272 | err |= __put_user(sig, &frame->sig); | 298 | err |= __put_user(sig, &frame->sig); |
| 273 | err |= __put_user(&frame->info, &frame->pinfo); | 299 | err |= __put_user(&frame->info, &frame->pinfo); |
| 274 | err |= __put_user(&frame->uc, &frame->puc); | 300 | err |= __put_user(&frame->uc, &frame->puc); |
| 275 | err |= copy_siginfo_to_user(&frame->info, info); | 301 | err |= copy_siginfo_to_user(&frame->info, info); |
| 276 | err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask, | 302 | err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask, |
| 277 | PT_REGS_SP(regs)); | 303 | save_sp); |
| 278 | 304 | ||
| 279 | /* | 305 | /* |
| 280 | * This is movl $,%eax ; int $0x80 | 306 | * This is movl $,%eax ; int $0x80 |
| @@ -288,9 +314,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
| 288 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); | 314 | err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); |
| 289 | 315 | ||
| 290 | if(err) | 316 | if(err) |
| 291 | return(err); | 317 | goto err; |
| 292 | 318 | ||
| 293 | PT_REGS_SP(regs) = (unsigned long) frame; | ||
| 294 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; | 319 | PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; |
| 295 | PT_REGS_EAX(regs) = (unsigned long) sig; | 320 | PT_REGS_EAX(regs) = (unsigned long) sig; |
| 296 | PT_REGS_EDX(regs) = (unsigned long) &frame->info; | 321 | PT_REGS_EDX(regs) = (unsigned long) &frame->info; |
| @@ -298,7 +323,11 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
| 298 | 323 | ||
| 299 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) | 324 | if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) |
| 300 | ptrace_notify(SIGTRAP); | 325 | ptrace_notify(SIGTRAP); |
| 301 | return(0); | 326 | return 0; |
| 327 | |||
| 328 | err: | ||
| 329 | PT_REGS_SP(regs) = save_sp; | ||
| 330 | return err; | ||
| 302 | } | 331 | } |
| 303 | 332 | ||
| 304 | long sys_sigreturn(struct pt_regs regs) | 333 | long sys_sigreturn(struct pt_regs regs) |
diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c index 26b68675053d..6f4ef2b7fa4a 100644 --- a/arch/um/sys-i386/user-offsets.c +++ b/arch/um/sys-i386/user-offsets.c | |||
| @@ -3,12 +3,13 @@ | |||
| 3 | #include <asm/ptrace.h> | 3 | #include <asm/ptrace.h> |
| 4 | #include <asm/user.h> | 4 | #include <asm/user.h> |
| 5 | #include <linux/stddef.h> | 5 | #include <linux/stddef.h> |
| 6 | #include <sys/poll.h> | ||
| 6 | 7 | ||
| 7 | #define DEFINE(sym, val) \ | 8 | #define DEFINE(sym, val) \ |
| 8 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | 9 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) |
| 9 | 10 | ||
| 10 | #define DEFINE_LONGS(sym, val) \ | 11 | #define DEFINE_LONGS(sym, val) \ |
| 11 | asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long))) | 12 | asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long))) |
| 12 | 13 | ||
| 13 | #define OFFSET(sym, str, mem) \ | 14 | #define OFFSET(sym, str, mem) \ |
| 14 | DEFINE(sym, offsetof(struct str, mem)); | 15 | DEFINE(sym, offsetof(struct str, mem)); |
| @@ -67,4 +68,9 @@ void foo(void) | |||
| 67 | DEFINE(HOST_ES, ES); | 68 | DEFINE(HOST_ES, ES); |
| 68 | DEFINE(HOST_GS, GS); | 69 | DEFINE(HOST_GS, GS); |
| 69 | DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct)); | 70 | DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct)); |
| 71 | |||
| 72 | /* XXX Duplicated between i386 and x86_64 */ | ||
| 73 | DEFINE(UM_POLLIN, POLLIN); | ||
| 74 | DEFINE(UM_POLLPRI, POLLPRI); | ||
| 75 | DEFINE(UM_POLLOUT, POLLOUT); | ||
| 70 | } | 76 | } |
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c index 74eee5c7c6dd..147bbf05cbc2 100644 --- a/arch/um/sys-x86_64/ptrace.c +++ b/arch/um/sys-x86_64/ptrace.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <asm/ptrace.h> | 8 | #include <asm/ptrace.h> |
| 9 | #include <linux/sched.h> | 9 | #include <linux/sched.h> |
| 10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
| 11 | #include <linux/mm.h> | ||
| 11 | #include <asm/uaccess.h> | 12 | #include <asm/uaccess.h> |
| 12 | #include <asm/elf.h> | 13 | #include <asm/elf.h> |
| 13 | 14 | ||
| @@ -136,9 +137,28 @@ void arch_switch(void) | |||
| 136 | */ | 137 | */ |
| 137 | } | 138 | } |
| 138 | 139 | ||
| 140 | /* XXX Mostly copied from sys-i386 */ | ||
| 139 | int is_syscall(unsigned long addr) | 141 | int is_syscall(unsigned long addr) |
| 140 | { | 142 | { |
| 141 | panic("is_syscall"); | 143 | unsigned short instr; |
| 144 | int n; | ||
| 145 | |||
| 146 | n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); | ||
| 147 | if(n){ | ||
| 148 | /* access_process_vm() grants access to vsyscall and stub, | ||
| 149 | * while copy_from_user doesn't. Maybe access_process_vm is | ||
| 150 | * slow, but that doesn't matter, since it will be called only | ||
| 151 | * in case of singlestepping, if copy_from_user failed. | ||
| 152 | */ | ||
| 153 | n = access_process_vm(current, addr, &instr, sizeof(instr), 0); | ||
| 154 | if(n != sizeof(instr)) { | ||
| 155 | printk("is_syscall : failed to read instruction from " | ||
| 156 | "0x%lx\n", addr); | ||
| 157 | return(1); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | /* sysenter */ | ||
| 161 | return(instr == 0x050f); | ||
| 142 | } | 162 | } |
| 143 | 163 | ||
| 144 | int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) | 164 | int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu ) |
diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c index fe1d065332b1..e75c4e1838b0 100644 --- a/arch/um/sys-x86_64/signal.c +++ b/arch/um/sys-x86_64/signal.c | |||
| @@ -55,7 +55,8 @@ static int copy_sc_from_user_skas(struct pt_regs *regs, | |||
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, | 57 | int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, |
| 58 | struct pt_regs *regs, unsigned long mask) | 58 | struct pt_regs *regs, unsigned long mask, |
| 59 | unsigned long sp) | ||
| 59 | { | 60 | { |
| 60 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; | 61 | struct faultinfo * fi = ¤t->thread.arch.faultinfo; |
| 61 | int err = 0; | 62 | int err = 0; |
| @@ -70,7 +71,11 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, | |||
| 70 | err |= PUTREG(regs, RDI, to, rdi); | 71 | err |= PUTREG(regs, RDI, to, rdi); |
| 71 | err |= PUTREG(regs, RSI, to, rsi); | 72 | err |= PUTREG(regs, RSI, to, rsi); |
| 72 | err |= PUTREG(regs, RBP, to, rbp); | 73 | err |= PUTREG(regs, RBP, to, rbp); |
| 73 | err |= PUTREG(regs, RSP, to, rsp); | 74 | /* Must use orignal RSP, which is passed in, rather than what's in |
| 75 | * the pt_regs, because that's already been updated to point at the | ||
| 76 | * signal frame. | ||
| 77 | */ | ||
| 78 | err |= __put_user(sp, &to->rsp); | ||
| 74 | err |= PUTREG(regs, RBX, to, rbx); | 79 | err |= PUTREG(regs, RBX, to, rbx); |
| 75 | err |= PUTREG(regs, RDX, to, rdx); | 80 | err |= PUTREG(regs, RDX, to, rdx); |
| 76 | err |= PUTREG(regs, RCX, to, rcx); | 81 | err |= PUTREG(regs, RCX, to, rcx); |
| @@ -102,7 +107,7 @@ int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate *to_fp, | |||
| 102 | 107 | ||
| 103 | #ifdef CONFIG_MODE_TT | 108 | #ifdef CONFIG_MODE_TT |
| 104 | int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, | 109 | int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, |
| 105 | int fpsize) | 110 | int fpsize) |
| 106 | { | 111 | { |
| 107 | struct _fpstate *to_fp, *from_fp; | 112 | struct _fpstate *to_fp, *from_fp; |
| 108 | unsigned long sigs; | 113 | unsigned long sigs; |
| @@ -120,7 +125,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from, | |||
| 120 | } | 125 | } |
| 121 | 126 | ||
| 122 | int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, | 127 | int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, |
| 123 | struct sigcontext *from, int fpsize) | 128 | struct sigcontext *from, int fpsize, unsigned long sp) |
| 124 | { | 129 | { |
| 125 | struct _fpstate *to_fp, *from_fp; | 130 | struct _fpstate *to_fp, *from_fp; |
| 126 | int err; | 131 | int err; |
| @@ -128,11 +133,17 @@ int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate *fp, | |||
| 128 | to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); | 133 | to_fp = (fp ? fp : (struct _fpstate *) (to + 1)); |
| 129 | from_fp = from->fpstate; | 134 | from_fp = from->fpstate; |
| 130 | err = copy_to_user(to, from, sizeof(*to)); | 135 | err = copy_to_user(to, from, sizeof(*to)); |
| 136 | /* The SP in the sigcontext is the updated one for the signal | ||
| 137 | * delivery. The sp passed in is the original, and this needs | ||
| 138 | * to be restored, so we stick it in separately. | ||
| 139 | */ | ||
| 140 | err |= copy_to_user(&SC_SP(to), sp, sizeof(sp)); | ||
| 141 | |||
| 131 | if(from_fp != NULL){ | 142 | if(from_fp != NULL){ |
| 132 | err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); | 143 | err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate)); |
| 133 | err |= copy_to_user(to_fp, from_fp, fpsize); | 144 | err |= copy_to_user(to_fp, from_fp, fpsize); |
| 134 | } | 145 | } |
| 135 | return(err); | 146 | return err; |
| 136 | } | 147 | } |
| 137 | 148 | ||
| 138 | #endif | 149 | #endif |
| @@ -148,11 +159,12 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from) | |||
| 148 | } | 159 | } |
| 149 | 160 | ||
| 150 | static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, | 161 | static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, |
| 151 | struct pt_regs *from, unsigned long mask) | 162 | struct pt_regs *from, unsigned long mask, |
| 163 | unsigned long sp) | ||
| 152 | { | 164 | { |
| 153 | return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), | 165 | return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), |
| 154 | sizeof(*fp)), | 166 | sizeof(*fp), sp), |
| 155 | copy_sc_to_user_skas(to, fp, from, mask))); | 167 | copy_sc_to_user_skas(to, fp, from, mask, sp))); |
| 156 | } | 168 | } |
| 157 | 169 | ||
| 158 | struct rt_sigframe | 170 | struct rt_sigframe |
| @@ -170,6 +182,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
| 170 | { | 182 | { |
| 171 | struct rt_sigframe __user *frame; | 183 | struct rt_sigframe __user *frame; |
| 172 | struct _fpstate __user *fp = NULL; | 184 | struct _fpstate __user *fp = NULL; |
| 185 | unsigned long save_sp = PT_REGS_RSP(regs); | ||
| 173 | int err = 0; | 186 | int err = 0; |
| 174 | struct task_struct *me = current; | 187 | struct task_struct *me = current; |
| 175 | 188 | ||
| @@ -193,14 +206,25 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
| 193 | goto out; | 206 | goto out; |
| 194 | } | 207 | } |
| 195 | 208 | ||
| 209 | /* Update SP now because the page fault handler refuses to extend | ||
| 210 | * the stack if the faulting address is too far below the current | ||
| 211 | * SP, which frame now certainly is. If there's an error, the original | ||
| 212 | * value is restored on the way out. | ||
| 213 | * When writing the sigcontext to the stack, we have to write the | ||
| 214 | * original value, so that's passed to copy_sc_to_user, which does | ||
| 215 | * the right thing with it. | ||
| 216 | */ | ||
| 217 | PT_REGS_RSP(regs) = (unsigned long) frame; | ||
| 218 | |||
| 196 | /* Create the ucontext. */ | 219 | /* Create the ucontext. */ |
| 197 | err |= __put_user(0, &frame->uc.uc_flags); | 220 | err |= __put_user(0, &frame->uc.uc_flags); |
| 198 | err |= __put_user(0, &frame->uc.uc_link); | 221 | err |= __put_user(0, &frame->uc.uc_link); |
| 199 | err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | 222 | err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); |
| 200 | err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)), | 223 | err |= __put_user(sas_ss_flags(save_sp), |
| 201 | &frame->uc.uc_stack.ss_flags); | 224 | &frame->uc.uc_stack.ss_flags); |
| 202 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); | 225 | err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); |
| 203 | err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); | 226 | err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0], |
| 227 | save_sp); | ||
| 204 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); | 228 | err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); |
| 205 | if (sizeof(*set) == 16) { | 229 | if (sizeof(*set) == 16) { |
| 206 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); | 230 | __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); |
| @@ -217,10 +241,10 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
| 217 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); | 241 | err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); |
| 218 | else | 242 | else |
| 219 | /* could use a vstub here */ | 243 | /* could use a vstub here */ |
| 220 | goto out; | 244 | goto restore_sp; |
| 221 | 245 | ||
| 222 | if (err) | 246 | if (err) |
| 223 | goto out; | 247 | goto restore_sp; |
| 224 | 248 | ||
| 225 | /* Set up registers for signal handler */ | 249 | /* Set up registers for signal handler */ |
| 226 | { | 250 | { |
| @@ -238,10 +262,12 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
| 238 | PT_REGS_RSI(regs) = (unsigned long) &frame->info; | 262 | PT_REGS_RSI(regs) = (unsigned long) &frame->info; |
| 239 | PT_REGS_RDX(regs) = (unsigned long) &frame->uc; | 263 | PT_REGS_RDX(regs) = (unsigned long) &frame->uc; |
| 240 | PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; | 264 | PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; |
| 241 | |||
| 242 | PT_REGS_RSP(regs) = (unsigned long) frame; | ||
| 243 | out: | 265 | out: |
| 244 | return(err); | 266 | return err; |
| 267 | |||
| 268 | restore_sp: | ||
| 269 | PT_REGS_RSP(regs) = save_sp; | ||
| 270 | return err; | ||
| 245 | } | 271 | } |
| 246 | 272 | ||
| 247 | long sys_rt_sigreturn(struct pt_regs *regs) | 273 | long sys_rt_sigreturn(struct pt_regs *regs) |
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c index 7bd54a921cf7..899cebb57c3f 100644 --- a/arch/um/sys-x86_64/user-offsets.c +++ b/arch/um/sys-x86_64/user-offsets.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #include <stdio.h> | 1 | #include <stdio.h> |
| 2 | #include <stddef.h> | 2 | #include <stddef.h> |
| 3 | #include <signal.h> | 3 | #include <signal.h> |
| 4 | #include <sys/poll.h> | ||
| 4 | #define __FRAME_OFFSETS | 5 | #define __FRAME_OFFSETS |
| 5 | #include <asm/ptrace.h> | 6 | #include <asm/ptrace.h> |
| 6 | #include <asm/types.h> | 7 | #include <asm/types.h> |
| @@ -88,4 +89,9 @@ void foo(void) | |||
| 88 | DEFINE_LONGS(HOST_IP, RIP); | 89 | DEFINE_LONGS(HOST_IP, RIP); |
| 89 | DEFINE_LONGS(HOST_SP, RSP); | 90 | DEFINE_LONGS(HOST_SP, RSP); |
| 90 | DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct)); | 91 | DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct)); |
| 92 | |||
| 93 | /* XXX Duplicated between i386 and x86_64 */ | ||
| 94 | DEFINE(UM_POLLIN, POLLIN); | ||
| 95 | DEFINE(UM_POLLPRI, POLLPRI); | ||
| 96 | DEFINE(UM_POLLOUT, POLLOUT); | ||
| 91 | } | 97 | } |
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 45efe0ca88f8..4310b4a311a5 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
| @@ -250,6 +250,15 @@ config SCHED_SMT | |||
| 250 | cost of slightly increased overhead in some places. If unsure say | 250 | cost of slightly increased overhead in some places. If unsure say |
| 251 | N here. | 251 | N here. |
| 252 | 252 | ||
| 253 | config SCHED_MC | ||
| 254 | bool "Multi-core scheduler support" | ||
| 255 | depends on SMP | ||
| 256 | default y | ||
| 257 | help | ||
| 258 | Multi-core scheduler support improves the CPU scheduler's decision | ||
| 259 | making when dealing with multi-core CPU chips at a cost of slightly | ||
| 260 | increased overhead in some places. If unsure say N here. | ||
| 261 | |||
| 253 | source "kernel/Kconfig.preempt" | 262 | source "kernel/Kconfig.preempt" |
| 254 | 263 | ||
| 255 | config NUMA | 264 | config NUMA |
| @@ -325,6 +334,10 @@ config HAVE_ARCH_EARLY_PFN_TO_NID | |||
| 325 | def_bool y | 334 | def_bool y |
| 326 | depends on NUMA | 335 | depends on NUMA |
| 327 | 336 | ||
| 337 | config OUT_OF_LINE_PFN_TO_PAGE | ||
| 338 | def_bool y | ||
| 339 | depends on DISCONTIGMEM | ||
| 340 | |||
| 328 | config NR_CPUS | 341 | config NR_CPUS |
| 329 | int "Maximum number of CPUs (2-256)" | 342 | int "Maximum number of CPUs (2-256)" |
| 330 | range 2 255 | 343 | range 2 255 |
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 7549a4389fbf..35b2faccdc6c 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S | |||
| @@ -688,6 +688,8 @@ ia32_sys_call_table: | |||
| 688 | .quad sys_ni_syscall /* pselect6 for now */ | 688 | .quad sys_ni_syscall /* pselect6 for now */ |
| 689 | .quad sys_ni_syscall /* ppoll for now */ | 689 | .quad sys_ni_syscall /* ppoll for now */ |
| 690 | .quad sys_unshare /* 310 */ | 690 | .quad sys_unshare /* 310 */ |
| 691 | .quad compat_sys_set_robust_list | ||
| 692 | .quad compat_sys_get_robust_list | ||
| 691 | ia32_syscall_end: | 693 | ia32_syscall_end: |
| 692 | .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8 | 694 | .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8 |
| 693 | .quad ni_syscall | 695 | .quad ni_syscall |
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 0370720515f1..70dd8e5c6889 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
| @@ -66,24 +66,17 @@ EXPORT_SYMBOL(boot_option_idle_override); | |||
| 66 | void (*pm_idle)(void); | 66 | void (*pm_idle)(void); |
| 67 | static DEFINE_PER_CPU(unsigned int, cpu_idle_state); | 67 | static DEFINE_PER_CPU(unsigned int, cpu_idle_state); |
| 68 | 68 | ||
| 69 | static struct notifier_block *idle_notifier; | 69 | static ATOMIC_NOTIFIER_HEAD(idle_notifier); |
| 70 | static DEFINE_SPINLOCK(idle_notifier_lock); | ||
| 71 | 70 | ||
| 72 | void idle_notifier_register(struct notifier_block *n) | 71 | void idle_notifier_register(struct notifier_block *n) |
| 73 | { | 72 | { |
| 74 | unsigned long flags; | 73 | atomic_notifier_chain_register(&idle_notifier, n); |
| 75 | spin_lock_irqsave(&idle_notifier_lock, flags); | ||
| 76 | notifier_chain_register(&idle_notifier, n); | ||
| 77 | spin_unlock_irqrestore(&idle_notifier_lock, flags); | ||
| 78 | } | 74 | } |
| 79 | EXPORT_SYMBOL_GPL(idle_notifier_register); | 75 | EXPORT_SYMBOL_GPL(idle_notifier_register); |
| 80 | 76 | ||
| 81 | void idle_notifier_unregister(struct notifier_block *n) | 77 | void idle_notifier_unregister(struct notifier_block *n) |
| 82 | { | 78 | { |
| 83 | unsigned long flags; | 79 | atomic_notifier_chain_unregister(&idle_notifier, n); |
| 84 | spin_lock_irqsave(&idle_notifier_lock, flags); | ||
| 85 | notifier_chain_unregister(&idle_notifier, n); | ||
| 86 | spin_unlock_irqrestore(&idle_notifier_lock, flags); | ||
| 87 | } | 80 | } |
| 88 | EXPORT_SYMBOL(idle_notifier_unregister); | 81 | EXPORT_SYMBOL(idle_notifier_unregister); |
| 89 | 82 | ||
| @@ -93,13 +86,13 @@ static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE; | |||
| 93 | void enter_idle(void) | 86 | void enter_idle(void) |
| 94 | { | 87 | { |
| 95 | __get_cpu_var(idle_state) = CPU_IDLE; | 88 | __get_cpu_var(idle_state) = CPU_IDLE; |
| 96 | notifier_call_chain(&idle_notifier, IDLE_START, NULL); | 89 | atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL); |
| 97 | } | 90 | } |
| 98 | 91 | ||
| 99 | static void __exit_idle(void) | 92 | static void __exit_idle(void) |
| 100 | { | 93 | { |
| 101 | __get_cpu_var(idle_state) = CPU_NOT_IDLE; | 94 | __get_cpu_var(idle_state) = CPU_NOT_IDLE; |
| 102 | notifier_call_chain(&idle_notifier, IDLE_END, NULL); | 95 | atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL); |
| 103 | } | 96 | } |
| 104 | 97 | ||
| 105 | /* Called from interrupts to signify idle end */ | 98 | /* Called from interrupts to signify idle end */ |
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index a57eec8311a7..d1f3e9272c05 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c | |||
| @@ -962,7 +962,6 @@ static void __cpuinit detect_ht(struct cpuinfo_x86 *c) | |||
| 962 | 962 | ||
| 963 | cpuid(1, &eax, &ebx, &ecx, &edx); | 963 | cpuid(1, &eax, &ebx, &ecx, &edx); |
| 964 | 964 | ||
| 965 | c->apicid = phys_pkg_id(0); | ||
| 966 | 965 | ||
| 967 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) | 966 | if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) |
| 968 | return; | 967 | return; |
| @@ -1171,6 +1170,8 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c) | |||
| 1171 | c->x86_capability[2] = cpuid_edx(0x80860001); | 1170 | c->x86_capability[2] = cpuid_edx(0x80860001); |
| 1172 | } | 1171 | } |
| 1173 | 1172 | ||
| 1173 | c->apicid = phys_pkg_id(0); | ||
| 1174 | |||
| 1174 | /* | 1175 | /* |
| 1175 | * Vendor-specific initialization. In this section we | 1176 | * Vendor-specific initialization. In this section we |
| 1176 | * canonicalize the feature flags, meaning if there are | 1177 | * canonicalize the feature flags, meaning if there are |
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c index 66e98659d077..ea48fa638070 100644 --- a/arch/x86_64/kernel/smpboot.c +++ b/arch/x86_64/kernel/smpboot.c | |||
| @@ -68,6 +68,9 @@ u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; | |||
| 68 | /* core ID of each logical CPU */ | 68 | /* core ID of each logical CPU */ |
| 69 | u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; | 69 | u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID }; |
| 70 | 70 | ||
| 71 | /* Last level cache ID of each logical CPU */ | ||
| 72 | u8 cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID}; | ||
| 73 | |||
| 71 | /* Bitmask of currently online CPUs */ | 74 | /* Bitmask of currently online CPUs */ |
| 72 | cpumask_t cpu_online_map __read_mostly; | 75 | cpumask_t cpu_online_map __read_mostly; |
| 73 | 76 | ||
| @@ -445,6 +448,18 @@ void __cpuinit smp_callin(void) | |||
| 445 | cpu_set(cpuid, cpu_callin_map); | 448 | cpu_set(cpuid, cpu_callin_map); |
| 446 | } | 449 | } |
| 447 | 450 | ||
| 451 | /* maps the cpu to the sched domain representing multi-core */ | ||
| 452 | cpumask_t cpu_coregroup_map(int cpu) | ||
| 453 | { | ||
| 454 | struct cpuinfo_x86 *c = cpu_data + cpu; | ||
| 455 | /* | ||
| 456 | * For perf, we return last level cache shared map. | ||
| 457 | * TBD: when power saving sched policy is added, we will return | ||
| 458 | * cpu_core_map when power saving policy is enabled | ||
| 459 | */ | ||
| 460 | return c->llc_shared_map; | ||
| 461 | } | ||
| 462 | |||
| 448 | /* representing cpus for which sibling maps can be computed */ | 463 | /* representing cpus for which sibling maps can be computed */ |
| 449 | static cpumask_t cpu_sibling_setup_map; | 464 | static cpumask_t cpu_sibling_setup_map; |
| 450 | 465 | ||
| @@ -463,12 +478,16 @@ static inline void set_cpu_sibling_map(int cpu) | |||
| 463 | cpu_set(cpu, cpu_sibling_map[i]); | 478 | cpu_set(cpu, cpu_sibling_map[i]); |
| 464 | cpu_set(i, cpu_core_map[cpu]); | 479 | cpu_set(i, cpu_core_map[cpu]); |
| 465 | cpu_set(cpu, cpu_core_map[i]); | 480 | cpu_set(cpu, cpu_core_map[i]); |
| 481 | cpu_set(i, c[cpu].llc_shared_map); | ||
| 482 | cpu_set(cpu, c[i].llc_shared_map); | ||
| 466 | } | 483 | } |
| 467 | } | 484 | } |
| 468 | } else { | 485 | } else { |
| 469 | cpu_set(cpu, cpu_sibling_map[cpu]); | 486 | cpu_set(cpu, cpu_sibling_map[cpu]); |
| 470 | } | 487 | } |
| 471 | 488 | ||
| 489 | cpu_set(cpu, c[cpu].llc_shared_map); | ||
| 490 | |||
| 472 | if (current_cpu_data.x86_max_cores == 1) { | 491 | if (current_cpu_data.x86_max_cores == 1) { |
| 473 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; | 492 | cpu_core_map[cpu] = cpu_sibling_map[cpu]; |
| 474 | c[cpu].booted_cores = 1; | 493 | c[cpu].booted_cores = 1; |
| @@ -476,6 +495,11 @@ static inline void set_cpu_sibling_map(int cpu) | |||
| 476 | } | 495 | } |
| 477 | 496 | ||
| 478 | for_each_cpu_mask(i, cpu_sibling_setup_map) { | 497 | for_each_cpu_mask(i, cpu_sibling_setup_map) { |
| 498 | if (cpu_llc_id[cpu] != BAD_APICID && | ||
| 499 | cpu_llc_id[cpu] == cpu_llc_id[i]) { | ||
| 500 | cpu_set(i, c[cpu].llc_shared_map); | ||
| 501 | cpu_set(cpu, c[i].llc_shared_map); | ||
| 502 | } | ||
| 479 | if (phys_proc_id[cpu] == phys_proc_id[i]) { | 503 | if (phys_proc_id[cpu] == phys_proc_id[i]) { |
| 480 | cpu_set(i, cpu_core_map[cpu]); | 504 | cpu_set(i, cpu_core_map[cpu]); |
| 481 | cpu_set(cpu, cpu_core_map[i]); | 505 | cpu_set(cpu, cpu_core_map[i]); |
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c index 7f58fa682491..473b514b66e4 100644 --- a/arch/x86_64/kernel/time.c +++ b/arch/x86_64/kernel/time.c | |||
| @@ -504,42 +504,25 @@ unsigned long long sched_clock(void) | |||
| 504 | 504 | ||
| 505 | static unsigned long get_cmos_time(void) | 505 | static unsigned long get_cmos_time(void) |
| 506 | { | 506 | { |
| 507 | unsigned int timeout = 1000000, year, mon, day, hour, min, sec; | 507 | unsigned int year, mon, day, hour, min, sec; |
| 508 | unsigned char uip = 0, this = 0; | ||
| 509 | unsigned long flags; | 508 | unsigned long flags; |
| 510 | unsigned extyear = 0; | 509 | unsigned extyear = 0; |
| 511 | 510 | ||
| 512 | /* | ||
| 513 | * The Linux interpretation of the CMOS clock register contents: When the | ||
| 514 | * Update-In-Progress (UIP) flag goes from 1 to 0, the RTC registers show the | ||
| 515 | * second which has precisely just started. Waiting for this can take up to 1 | ||
| 516 | * second, we timeout approximately after 2.4 seconds on a machine with | ||
| 517 | * standard 8.3 MHz ISA bus. | ||
| 518 | */ | ||
| 519 | |||
| 520 | spin_lock_irqsave(&rtc_lock, flags); | 511 | spin_lock_irqsave(&rtc_lock, flags); |
| 521 | 512 | ||
| 522 | while (timeout && (!uip || this)) { | 513 | do { |
| 523 | uip |= this; | 514 | sec = CMOS_READ(RTC_SECONDS); |
| 524 | this = CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP; | 515 | min = CMOS_READ(RTC_MINUTES); |
| 525 | timeout--; | 516 | hour = CMOS_READ(RTC_HOURS); |
| 526 | } | 517 | day = CMOS_READ(RTC_DAY_OF_MONTH); |
| 527 | 518 | mon = CMOS_READ(RTC_MONTH); | |
| 528 | /* | 519 | year = CMOS_READ(RTC_YEAR); |
| 529 | * Here we are safe to assume the registers won't change for a whole | ||
| 530 | * second, so we just go ahead and read them. | ||
| 531 | */ | ||
| 532 | sec = CMOS_READ(RTC_SECONDS); | ||
| 533 | min = CMOS_READ(RTC_MINUTES); | ||
| 534 | hour = CMOS_READ(RTC_HOURS); | ||
| 535 | day = CMOS_READ(RTC_DAY_OF_MONTH); | ||
| 536 | mon = CMOS_READ(RTC_MONTH); | ||
| 537 | year = CMOS_READ(RTC_YEAR); | ||
| 538 | |||
| 539 | #ifdef CONFIG_ACPI | 520 | #ifdef CONFIG_ACPI |
| 540 | if (acpi_fadt.revision >= FADT2_REVISION_ID && acpi_fadt.century) | 521 | if (acpi_fadt.revision >= FADT2_REVISION_ID && |
| 541 | extyear = CMOS_READ(acpi_fadt.century); | 522 | acpi_fadt.century) |
| 523 | extyear = CMOS_READ(acpi_fadt.century); | ||
| 542 | #endif | 524 | #endif |
| 525 | } while (sec != CMOS_READ(RTC_SECONDS)); | ||
| 543 | 526 | ||
| 544 | spin_unlock_irqrestore(&rtc_lock, flags); | 527 | spin_unlock_irqrestore(&rtc_lock, flags); |
| 545 | 528 | ||
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 7b148309c529..edaa9fe654dc 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c | |||
| @@ -69,20 +69,20 @@ asmlinkage void alignment_check(void); | |||
| 69 | asmlinkage void machine_check(void); | 69 | asmlinkage void machine_check(void); |
| 70 | asmlinkage void spurious_interrupt_bug(void); | 70 | asmlinkage void spurious_interrupt_bug(void); |
| 71 | 71 | ||
| 72 | struct notifier_block *die_chain; | 72 | ATOMIC_NOTIFIER_HEAD(die_chain); |
| 73 | static DEFINE_SPINLOCK(die_notifier_lock); | ||
| 74 | 73 | ||
| 75 | int register_die_notifier(struct notifier_block *nb) | 74 | int register_die_notifier(struct notifier_block *nb) |
| 76 | { | 75 | { |
| 77 | int err = 0; | ||
| 78 | unsigned long flags; | ||
| 79 | |||
| 80 | vmalloc_sync_all(); | 76 | vmalloc_sync_all(); |
| 81 | spin_lock_irqsave(&die_notifier_lock, flags); | 77 | return atomic_notifier_chain_register(&die_chain, nb); |
| 82 | err = notifier_chain_register(&die_chain, nb); | 78 | } |
| 83 | spin_unlock_irqrestore(&die_notifier_lock, flags); | 79 | EXPORT_SYMBOL(register_die_notifier); |
| 84 | return err; | 80 | |
| 81 | int unregister_die_notifier(struct notifier_block *nb) | ||
| 82 | { | ||
| 83 | return atomic_notifier_chain_unregister(&die_chain, nb); | ||
| 85 | } | 84 | } |
| 85 | EXPORT_SYMBOL(unregister_die_notifier); | ||
| 86 | 86 | ||
| 87 | static inline void conditional_sti(struct pt_regs *regs) | 87 | static inline void conditional_sti(struct pt_regs *regs) |
| 88 | { | 88 | { |
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index b04415625442..e5f7f1c34462 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c | |||
| @@ -72,7 +72,7 @@ void show_mem(void) | |||
| 72 | show_free_areas(); | 72 | show_free_areas(); |
| 73 | printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); | 73 | printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); |
| 74 | 74 | ||
| 75 | for_each_pgdat(pgdat) { | 75 | for_each_online_pgdat(pgdat) { |
| 76 | for (i = 0; i < pgdat->node_spanned_pages; ++i) { | 76 | for (i = 0; i < pgdat->node_spanned_pages; ++i) { |
| 77 | page = pfn_to_page(pgdat->node_start_pfn + i); | 77 | page = pfn_to_page(pgdat->node_start_pfn + i); |
| 78 | total++; | 78 | total++; |
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 63c72641b737..4be82d6e2b48 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c | |||
| @@ -377,21 +377,6 @@ EXPORT_SYMBOL(node_data); | |||
| 377 | * Should do that. | 377 | * Should do that. |
| 378 | */ | 378 | */ |
| 379 | 379 | ||
| 380 | /* Requires pfn_valid(pfn) to be true */ | ||
| 381 | struct page *pfn_to_page(unsigned long pfn) | ||
| 382 | { | ||
| 383 | int nid = phys_to_nid(((unsigned long)(pfn)) << PAGE_SHIFT); | ||
| 384 | return (pfn - node_start_pfn(nid)) + NODE_DATA(nid)->node_mem_map; | ||
| 385 | } | ||
| 386 | EXPORT_SYMBOL(pfn_to_page); | ||
| 387 | |||
| 388 | unsigned long page_to_pfn(struct page *page) | ||
| 389 | { | ||
| 390 | return (long)(((page) - page_zone(page)->zone_mem_map) + | ||
| 391 | page_zone(page)->zone_start_pfn); | ||
| 392 | } | ||
| 393 | EXPORT_SYMBOL(page_to_pfn); | ||
| 394 | |||
| 395 | int pfn_valid(unsigned long pfn) | 380 | int pfn_valid(unsigned long pfn) |
| 396 | { | 381 | { |
| 397 | unsigned nid; | 382 | unsigned nid; |
diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platform-iss/setup.c index 2e6dcbf0cc04..23790a5610e2 100644 --- a/arch/xtensa/platform-iss/setup.c +++ b/arch/xtensa/platform-iss/setup.c | |||
| @@ -108,5 +108,5 @@ static struct notifier_block iss_panic_block = { | |||
| 108 | 108 | ||
| 109 | void __init platform_setup(char **p_cmdline) | 109 | void __init platform_setup(char **p_cmdline) |
| 110 | { | 110 | { |
| 111 | notifier_chain_register(&panic_notifier_list, &iss_panic_block); | 111 | atomic_notifier_chain_register(&panic_notifier_list, &iss_panic_block); |
| 112 | } | 112 | } |
diff --git a/block/Kconfig b/block/Kconfig index 43ca070dc0f8..5536839886ff 100644 --- a/block/Kconfig +++ b/block/Kconfig | |||
| @@ -13,6 +13,7 @@ config LBD | |||
| 13 | 13 | ||
| 14 | config BLK_DEV_IO_TRACE | 14 | config BLK_DEV_IO_TRACE |
| 15 | bool "Support for tracing block io actions" | 15 | bool "Support for tracing block io actions" |
| 16 | depends on SYSFS | ||
| 16 | select RELAY | 17 | select RELAY |
| 17 | select DEBUG_FS | 18 | select DEBUG_FS |
| 18 | help | 19 | help |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index bde40a6ae665..67d446de0227 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -26,18 +26,12 @@ static const int cfq_back_penalty = 2; /* penalty of a backwards seek */ | |||
| 26 | static const int cfq_slice_sync = HZ / 10; | 26 | static const int cfq_slice_sync = HZ / 10; |
| 27 | static int cfq_slice_async = HZ / 25; | 27 | static int cfq_slice_async = HZ / 25; |
| 28 | static const int cfq_slice_async_rq = 2; | 28 | static const int cfq_slice_async_rq = 2; |
| 29 | static int cfq_slice_idle = HZ / 100; | 29 | static int cfq_slice_idle = HZ / 70; |
| 30 | 30 | ||
| 31 | #define CFQ_IDLE_GRACE (HZ / 10) | 31 | #define CFQ_IDLE_GRACE (HZ / 10) |
| 32 | #define CFQ_SLICE_SCALE (5) | 32 | #define CFQ_SLICE_SCALE (5) |
| 33 | 33 | ||
| 34 | #define CFQ_KEY_ASYNC (0) | 34 | #define CFQ_KEY_ASYNC (0) |
| 35 | #define CFQ_KEY_ANY (0xffff) | ||
| 36 | |||
| 37 | /* | ||
| 38 | * disable queueing at the driver/hardware level | ||
| 39 | */ | ||
| 40 | static const int cfq_max_depth = 2; | ||
| 41 | 35 | ||
| 42 | static DEFINE_RWLOCK(cfq_exit_lock); | 36 | static DEFINE_RWLOCK(cfq_exit_lock); |
| 43 | 37 | ||
| @@ -102,6 +96,8 @@ static struct completion *ioc_gone; | |||
| 102 | #define cfq_cfqq_sync(cfqq) \ | 96 | #define cfq_cfqq_sync(cfqq) \ |
| 103 | (cfq_cfqq_class_sync(cfqq) || (cfqq)->on_dispatch[SYNC]) | 97 | (cfq_cfqq_class_sync(cfqq) || (cfqq)->on_dispatch[SYNC]) |
| 104 | 98 | ||
| 99 | #define sample_valid(samples) ((samples) > 80) | ||
| 100 | |||
| 105 | /* | 101 | /* |
| 106 | * Per block device queue structure | 102 | * Per block device queue structure |
| 107 | */ | 103 | */ |
| @@ -170,7 +166,6 @@ struct cfq_data { | |||
| 170 | unsigned int cfq_slice[2]; | 166 | unsigned int cfq_slice[2]; |
| 171 | unsigned int cfq_slice_async_rq; | 167 | unsigned int cfq_slice_async_rq; |
| 172 | unsigned int cfq_slice_idle; | 168 | unsigned int cfq_slice_idle; |
| 173 | unsigned int cfq_max_depth; | ||
| 174 | 169 | ||
| 175 | struct list_head cic_list; | 170 | struct list_head cic_list; |
| 176 | }; | 171 | }; |
| @@ -343,17 +338,27 @@ static int cfq_queue_empty(request_queue_t *q) | |||
| 343 | return !cfqd->busy_queues; | 338 | return !cfqd->busy_queues; |
| 344 | } | 339 | } |
| 345 | 340 | ||
| 341 | static inline pid_t cfq_queue_pid(struct task_struct *task, int rw) | ||
| 342 | { | ||
| 343 | if (rw == READ || process_sync(task)) | ||
| 344 | return task->pid; | ||
| 345 | |||
| 346 | return CFQ_KEY_ASYNC; | ||
| 347 | } | ||
| 348 | |||
| 346 | /* | 349 | /* |
| 347 | * Lifted from AS - choose which of crq1 and crq2 that is best served now. | 350 | * Lifted from AS - choose which of crq1 and crq2 that is best served now. |
| 348 | * We choose the request that is closest to the head right now. Distance | 351 | * We choose the request that is closest to the head right now. Distance |
| 349 | * behind the head are penalized and only allowed to a certain extent. | 352 | * behind the head is penalized and only allowed to a certain extent. |
| 350 | */ | 353 | */ |
| 351 | static struct cfq_rq * | 354 | static struct cfq_rq * |
| 352 | cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) | 355 | cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) |
| 353 | { | 356 | { |
| 354 | sector_t last, s1, s2, d1 = 0, d2 = 0; | 357 | sector_t last, s1, s2, d1 = 0, d2 = 0; |
| 355 | int r1_wrap = 0, r2_wrap = 0; /* requests are behind the disk head */ | ||
| 356 | unsigned long back_max; | 358 | unsigned long back_max; |
| 359 | #define CFQ_RQ1_WRAP 0x01 /* request 1 wraps */ | ||
| 360 | #define CFQ_RQ2_WRAP 0x02 /* request 2 wraps */ | ||
| 361 | unsigned wrap = 0; /* bit mask: requests behind the disk head? */ | ||
| 357 | 362 | ||
| 358 | if (crq1 == NULL || crq1 == crq2) | 363 | if (crq1 == NULL || crq1 == crq2) |
| 359 | return crq2; | 364 | return crq2; |
| @@ -385,35 +390,47 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2) | |||
| 385 | else if (s1 + back_max >= last) | 390 | else if (s1 + back_max >= last) |
| 386 | d1 = (last - s1) * cfqd->cfq_back_penalty; | 391 | d1 = (last - s1) * cfqd->cfq_back_penalty; |
| 387 | else | 392 | else |
| 388 | r1_wrap = 1; | 393 | wrap |= CFQ_RQ1_WRAP; |
| 389 | 394 | ||
| 390 | if (s2 >= last) | 395 | if (s2 >= last) |
| 391 | d2 = s2 - last; | 396 | d2 = s2 - last; |
| 392 | else if (s2 + back_max >= last) | 397 | else if (s2 + back_max >= last) |
| 393 | d2 = (last - s2) * cfqd->cfq_back_penalty; | 398 | d2 = (last - s2) * cfqd->cfq_back_penalty; |
| 394 | else | 399 | else |
| 395 | r2_wrap = 1; | 400 | wrap |= CFQ_RQ2_WRAP; |
| 396 | 401 | ||
| 397 | /* Found required data */ | 402 | /* Found required data */ |
| 398 | if (!r1_wrap && r2_wrap) | 403 | |
| 399 | return crq1; | 404 | /* |
| 400 | else if (!r2_wrap && r1_wrap) | 405 | * By doing switch() on the bit mask "wrap" we avoid having to |
| 401 | return crq2; | 406 | * check two variables for all permutations: --> faster! |
| 402 | else if (r1_wrap && r2_wrap) { | 407 | */ |
| 403 | /* both behind the head */ | 408 | switch (wrap) { |
| 404 | if (s1 <= s2) | 409 | case 0: /* common case for CFQ: crq1 and crq2 not wrapped */ |
| 410 | if (d1 < d2) | ||
| 405 | return crq1; | 411 | return crq1; |
| 406 | else | 412 | else if (d2 < d1) |
| 407 | return crq2; | 413 | return crq2; |
| 408 | } | 414 | else { |
| 415 | if (s1 >= s2) | ||
| 416 | return crq1; | ||
| 417 | else | ||
| 418 | return crq2; | ||
| 419 | } | ||
| 409 | 420 | ||
| 410 | /* Both requests in front of the head */ | 421 | case CFQ_RQ2_WRAP: |
| 411 | if (d1 < d2) | ||
| 412 | return crq1; | 422 | return crq1; |
| 413 | else if (d2 < d1) | 423 | case CFQ_RQ1_WRAP: |
| 414 | return crq2; | 424 | return crq2; |
| 415 | else { | 425 | case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both crqs wrapped */ |
| 416 | if (s1 >= s2) | 426 | default: |
| 427 | /* | ||
| 428 | * Since both rqs are wrapped, | ||
| 429 | * start with the one that's further behind head | ||
| 430 | * (--> only *one* back seek required), | ||
| 431 | * since back seek takes more time than forward. | ||
| 432 | */ | ||
| 433 | if (s1 <= s2) | ||
| 417 | return crq1; | 434 | return crq1; |
| 418 | else | 435 | else |
| 419 | return crq2; | 436 | return crq2; |
| @@ -612,15 +629,20 @@ cfq_reposition_crq_rb(struct cfq_queue *cfqq, struct cfq_rq *crq) | |||
| 612 | cfq_add_crq_rb(crq); | 629 | cfq_add_crq_rb(crq); |
| 613 | } | 630 | } |
| 614 | 631 | ||
| 615 | static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector) | 632 | static struct request * |
| 616 | 633 | cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio) | |
| 617 | { | 634 | { |
| 618 | struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY); | 635 | struct task_struct *tsk = current; |
| 636 | pid_t key = cfq_queue_pid(tsk, bio_data_dir(bio)); | ||
| 637 | struct cfq_queue *cfqq; | ||
| 619 | struct rb_node *n; | 638 | struct rb_node *n; |
| 639 | sector_t sector; | ||
| 620 | 640 | ||
| 641 | cfqq = cfq_find_cfq_hash(cfqd, key, tsk->ioprio); | ||
| 621 | if (!cfqq) | 642 | if (!cfqq) |
| 622 | goto out; | 643 | goto out; |
| 623 | 644 | ||
| 645 | sector = bio->bi_sector + bio_sectors(bio); | ||
| 624 | n = cfqq->sort_list.rb_node; | 646 | n = cfqq->sort_list.rb_node; |
| 625 | while (n) { | 647 | while (n) { |
| 626 | struct cfq_rq *crq = rb_entry_crq(n); | 648 | struct cfq_rq *crq = rb_entry_crq(n); |
| @@ -674,7 +696,7 @@ cfq_merge(request_queue_t *q, struct request **req, struct bio *bio) | |||
| 674 | goto out; | 696 | goto out; |
| 675 | } | 697 | } |
| 676 | 698 | ||
| 677 | __rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio)); | 699 | __rq = cfq_find_rq_fmerge(cfqd, bio); |
| 678 | if (__rq && elv_rq_merge_ok(__rq, bio)) { | 700 | if (__rq && elv_rq_merge_ok(__rq, bio)) { |
| 679 | ret = ELEVATOR_FRONT_MERGE; | 701 | ret = ELEVATOR_FRONT_MERGE; |
| 680 | goto out; | 702 | goto out; |
| @@ -877,6 +899,7 @@ static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd) | |||
| 877 | static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) | 899 | static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
| 878 | 900 | ||
| 879 | { | 901 | { |
| 902 | struct cfq_io_context *cic; | ||
| 880 | unsigned long sl; | 903 | unsigned long sl; |
| 881 | 904 | ||
| 882 | WARN_ON(!RB_EMPTY(&cfqq->sort_list)); | 905 | WARN_ON(!RB_EMPTY(&cfqq->sort_list)); |
| @@ -892,13 +915,23 @@ static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
| 892 | /* | 915 | /* |
| 893 | * task has exited, don't wait | 916 | * task has exited, don't wait |
| 894 | */ | 917 | */ |
| 895 | if (cfqd->active_cic && !cfqd->active_cic->ioc->task) | 918 | cic = cfqd->active_cic; |
| 919 | if (!cic || !cic->ioc->task) | ||
| 896 | return 0; | 920 | return 0; |
| 897 | 921 | ||
| 898 | cfq_mark_cfqq_must_dispatch(cfqq); | 922 | cfq_mark_cfqq_must_dispatch(cfqq); |
| 899 | cfq_mark_cfqq_wait_request(cfqq); | 923 | cfq_mark_cfqq_wait_request(cfqq); |
| 900 | 924 | ||
| 901 | sl = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle); | 925 | sl = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle); |
| 926 | |||
| 927 | /* | ||
| 928 | * we don't want to idle for seeks, but we do want to allow | ||
| 929 | * fair distribution of slice time for a process doing back-to-back | ||
| 930 | * seeks. so allow a little bit of time for him to submit a new rq | ||
| 931 | */ | ||
| 932 | if (sample_valid(cic->seek_samples) && cic->seek_mean > 131072) | ||
| 933 | sl = 2; | ||
| 934 | |||
| 902 | mod_timer(&cfqd->idle_slice_timer, jiffies + sl); | 935 | mod_timer(&cfqd->idle_slice_timer, jiffies + sl); |
| 903 | return 1; | 936 | return 1; |
| 904 | } | 937 | } |
| @@ -1115,13 +1148,6 @@ cfq_dispatch_requests(request_queue_t *q, int force) | |||
| 1115 | if (cfqq) { | 1148 | if (cfqq) { |
| 1116 | int max_dispatch; | 1149 | int max_dispatch; |
| 1117 | 1150 | ||
| 1118 | /* | ||
| 1119 | * if idle window is disabled, allow queue buildup | ||
| 1120 | */ | ||
| 1121 | if (!cfq_cfqq_idle_window(cfqq) && | ||
| 1122 | cfqd->rq_in_driver >= cfqd->cfq_max_depth) | ||
| 1123 | return 0; | ||
| 1124 | |||
| 1125 | cfq_clear_cfqq_must_dispatch(cfqq); | 1151 | cfq_clear_cfqq_must_dispatch(cfqq); |
| 1126 | cfq_clear_cfqq_wait_request(cfqq); | 1152 | cfq_clear_cfqq_wait_request(cfqq); |
| 1127 | del_timer(&cfqd->idle_slice_timer); | 1153 | del_timer(&cfqd->idle_slice_timer); |
| @@ -1171,13 +1197,13 @@ __cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio, | |||
| 1171 | const int hashval) | 1197 | const int hashval) |
| 1172 | { | 1198 | { |
| 1173 | struct hlist_head *hash_list = &cfqd->cfq_hash[hashval]; | 1199 | struct hlist_head *hash_list = &cfqd->cfq_hash[hashval]; |
| 1174 | struct hlist_node *entry, *next; | 1200 | struct hlist_node *entry; |
| 1201 | struct cfq_queue *__cfqq; | ||
| 1175 | 1202 | ||
| 1176 | hlist_for_each_safe(entry, next, hash_list) { | 1203 | hlist_for_each_entry(__cfqq, entry, hash_list, cfq_hash) { |
| 1177 | struct cfq_queue *__cfqq = list_entry_qhash(entry); | ||
| 1178 | const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->org_ioprio_class, __cfqq->org_ioprio); | 1204 | const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->org_ioprio_class, __cfqq->org_ioprio); |
| 1179 | 1205 | ||
| 1180 | if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY)) | 1206 | if (__cfqq->key == key && (__p == prio || !prio)) |
| 1181 | return __cfqq; | 1207 | return __cfqq; |
| 1182 | } | 1208 | } |
| 1183 | 1209 | ||
| @@ -1190,19 +1216,19 @@ cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned short prio) | |||
| 1190 | return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT)); | 1216 | return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT)); |
| 1191 | } | 1217 | } |
| 1192 | 1218 | ||
| 1193 | static void cfq_free_io_context(struct cfq_io_context *cic) | 1219 | static void cfq_free_io_context(struct io_context *ioc) |
| 1194 | { | 1220 | { |
| 1195 | struct cfq_io_context *__cic; | 1221 | struct cfq_io_context *__cic; |
| 1196 | struct list_head *entry, *next; | 1222 | struct rb_node *n; |
| 1197 | int freed = 1; | 1223 | int freed = 0; |
| 1198 | 1224 | ||
| 1199 | list_for_each_safe(entry, next, &cic->list) { | 1225 | while ((n = rb_first(&ioc->cic_root)) != NULL) { |
| 1200 | __cic = list_entry(entry, struct cfq_io_context, list); | 1226 | __cic = rb_entry(n, struct cfq_io_context, rb_node); |
| 1227 | rb_erase(&__cic->rb_node, &ioc->cic_root); | ||
| 1201 | kmem_cache_free(cfq_ioc_pool, __cic); | 1228 | kmem_cache_free(cfq_ioc_pool, __cic); |
| 1202 | freed++; | 1229 | freed++; |
| 1203 | } | 1230 | } |
| 1204 | 1231 | ||
| 1205 | kmem_cache_free(cfq_ioc_pool, cic); | ||
| 1206 | if (atomic_sub_and_test(freed, &ioc_count) && ioc_gone) | 1232 | if (atomic_sub_and_test(freed, &ioc_count) && ioc_gone) |
| 1207 | complete(ioc_gone); | 1233 | complete(ioc_gone); |
| 1208 | } | 1234 | } |
| @@ -1210,8 +1236,7 @@ static void cfq_free_io_context(struct cfq_io_context *cic) | |||
| 1210 | static void cfq_trim(struct io_context *ioc) | 1236 | static void cfq_trim(struct io_context *ioc) |
| 1211 | { | 1237 | { |
| 1212 | ioc->set_ioprio = NULL; | 1238 | ioc->set_ioprio = NULL; |
| 1213 | if (ioc->cic) | 1239 | cfq_free_io_context(ioc); |
| 1214 | cfq_free_io_context(ioc->cic); | ||
| 1215 | } | 1240 | } |
| 1216 | 1241 | ||
| 1217 | /* | 1242 | /* |
| @@ -1250,26 +1275,26 @@ static void cfq_exit_single_io_context(struct cfq_io_context *cic) | |||
| 1250 | spin_unlock(q->queue_lock); | 1275 | spin_unlock(q->queue_lock); |
| 1251 | } | 1276 | } |
| 1252 | 1277 | ||
| 1253 | static void cfq_exit_io_context(struct cfq_io_context *cic) | 1278 | static void cfq_exit_io_context(struct io_context *ioc) |
| 1254 | { | 1279 | { |
| 1255 | struct cfq_io_context *__cic; | 1280 | struct cfq_io_context *__cic; |
| 1256 | struct list_head *entry; | ||
| 1257 | unsigned long flags; | 1281 | unsigned long flags; |
| 1258 | 1282 | struct rb_node *n; | |
| 1259 | local_irq_save(flags); | ||
| 1260 | 1283 | ||
| 1261 | /* | 1284 | /* |
| 1262 | * put the reference this task is holding to the various queues | 1285 | * put the reference this task is holding to the various queues |
| 1263 | */ | 1286 | */ |
| 1264 | read_lock(&cfq_exit_lock); | 1287 | read_lock_irqsave(&cfq_exit_lock, flags); |
| 1265 | list_for_each(entry, &cic->list) { | 1288 | |
| 1266 | __cic = list_entry(entry, struct cfq_io_context, list); | 1289 | n = rb_first(&ioc->cic_root); |
| 1290 | while (n != NULL) { | ||
| 1291 | __cic = rb_entry(n, struct cfq_io_context, rb_node); | ||
| 1292 | |||
| 1267 | cfq_exit_single_io_context(__cic); | 1293 | cfq_exit_single_io_context(__cic); |
| 1294 | n = rb_next(n); | ||
| 1268 | } | 1295 | } |
| 1269 | 1296 | ||
| 1270 | cfq_exit_single_io_context(cic); | 1297 | read_unlock_irqrestore(&cfq_exit_lock, flags); |
| 1271 | read_unlock(&cfq_exit_lock); | ||
| 1272 | local_irq_restore(flags); | ||
| 1273 | } | 1298 | } |
| 1274 | 1299 | ||
| 1275 | static struct cfq_io_context * | 1300 | static struct cfq_io_context * |
| @@ -1278,10 +1303,10 @@ cfq_alloc_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) | |||
| 1278 | struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask); | 1303 | struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask); |
| 1279 | 1304 | ||
| 1280 | if (cic) { | 1305 | if (cic) { |
| 1281 | INIT_LIST_HEAD(&cic->list); | 1306 | RB_CLEAR(&cic->rb_node); |
| 1307 | cic->key = NULL; | ||
| 1282 | cic->cfqq[ASYNC] = NULL; | 1308 | cic->cfqq[ASYNC] = NULL; |
| 1283 | cic->cfqq[SYNC] = NULL; | 1309 | cic->cfqq[SYNC] = NULL; |
| 1284 | cic->key = NULL; | ||
| 1285 | cic->last_end_request = jiffies; | 1310 | cic->last_end_request = jiffies; |
| 1286 | cic->ttime_total = 0; | 1311 | cic->ttime_total = 0; |
| 1287 | cic->ttime_samples = 0; | 1312 | cic->ttime_samples = 0; |
| @@ -1373,15 +1398,17 @@ static inline void changed_ioprio(struct cfq_io_context *cic) | |||
| 1373 | static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio) | 1398 | static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio) |
| 1374 | { | 1399 | { |
| 1375 | struct cfq_io_context *cic; | 1400 | struct cfq_io_context *cic; |
| 1401 | struct rb_node *n; | ||
| 1376 | 1402 | ||
| 1377 | write_lock(&cfq_exit_lock); | 1403 | write_lock(&cfq_exit_lock); |
| 1378 | 1404 | ||
| 1379 | cic = ioc->cic; | 1405 | n = rb_first(&ioc->cic_root); |
| 1380 | 1406 | while (n != NULL) { | |
| 1381 | changed_ioprio(cic); | 1407 | cic = rb_entry(n, struct cfq_io_context, rb_node); |
| 1382 | 1408 | ||
| 1383 | list_for_each_entry(cic, &cic->list, list) | ||
| 1384 | changed_ioprio(cic); | 1409 | changed_ioprio(cic); |
| 1410 | n = rb_next(n); | ||
| 1411 | } | ||
| 1385 | 1412 | ||
| 1386 | write_unlock(&cfq_exit_lock); | 1413 | write_unlock(&cfq_exit_lock); |
| 1387 | 1414 | ||
| @@ -1445,14 +1472,67 @@ out: | |||
| 1445 | return cfqq; | 1472 | return cfqq; |
| 1446 | } | 1473 | } |
| 1447 | 1474 | ||
| 1475 | static struct cfq_io_context * | ||
| 1476 | cfq_cic_rb_lookup(struct cfq_data *cfqd, struct io_context *ioc) | ||
| 1477 | { | ||
| 1478 | struct rb_node *n = ioc->cic_root.rb_node; | ||
| 1479 | struct cfq_io_context *cic; | ||
| 1480 | void *key = cfqd; | ||
| 1481 | |||
| 1482 | while (n) { | ||
| 1483 | cic = rb_entry(n, struct cfq_io_context, rb_node); | ||
| 1484 | |||
| 1485 | if (key < cic->key) | ||
| 1486 | n = n->rb_left; | ||
| 1487 | else if (key > cic->key) | ||
| 1488 | n = n->rb_right; | ||
| 1489 | else | ||
| 1490 | return cic; | ||
| 1491 | } | ||
| 1492 | |||
| 1493 | return NULL; | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | static inline void | ||
| 1497 | cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc, | ||
| 1498 | struct cfq_io_context *cic) | ||
| 1499 | { | ||
| 1500 | struct rb_node **p = &ioc->cic_root.rb_node; | ||
| 1501 | struct rb_node *parent = NULL; | ||
| 1502 | struct cfq_io_context *__cic; | ||
| 1503 | |||
| 1504 | read_lock(&cfq_exit_lock); | ||
| 1505 | |||
| 1506 | cic->ioc = ioc; | ||
| 1507 | cic->key = cfqd; | ||
| 1508 | |||
| 1509 | ioc->set_ioprio = cfq_ioc_set_ioprio; | ||
| 1510 | |||
| 1511 | while (*p) { | ||
| 1512 | parent = *p; | ||
| 1513 | __cic = rb_entry(parent, struct cfq_io_context, rb_node); | ||
| 1514 | |||
| 1515 | if (cic->key < __cic->key) | ||
| 1516 | p = &(*p)->rb_left; | ||
| 1517 | else if (cic->key > __cic->key) | ||
| 1518 | p = &(*p)->rb_right; | ||
| 1519 | else | ||
| 1520 | BUG(); | ||
| 1521 | } | ||
| 1522 | |||
| 1523 | rb_link_node(&cic->rb_node, parent, p); | ||
| 1524 | rb_insert_color(&cic->rb_node, &ioc->cic_root); | ||
| 1525 | list_add(&cic->queue_list, &cfqd->cic_list); | ||
| 1526 | read_unlock(&cfq_exit_lock); | ||
| 1527 | } | ||
| 1528 | |||
| 1448 | /* | 1529 | /* |
| 1449 | * Setup general io context and cfq io context. There can be several cfq | 1530 | * Setup general io context and cfq io context. There can be several cfq |
| 1450 | * io contexts per general io context, if this process is doing io to more | 1531 | * io contexts per general io context, if this process is doing io to more |
| 1451 | * than one device managed by cfq. Note that caller is holding a reference to | 1532 | * than one device managed by cfq. |
| 1452 | * cfqq, so we don't need to worry about it disappearing | ||
| 1453 | */ | 1533 | */ |
| 1454 | static struct cfq_io_context * | 1534 | static struct cfq_io_context * |
| 1455 | cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask) | 1535 | cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask) |
| 1456 | { | 1536 | { |
| 1457 | struct io_context *ioc = NULL; | 1537 | struct io_context *ioc = NULL; |
| 1458 | struct cfq_io_context *cic; | 1538 | struct cfq_io_context *cic; |
| @@ -1463,88 +1543,15 @@ cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, gfp_t gfp_mask) | |||
| 1463 | if (!ioc) | 1543 | if (!ioc) |
| 1464 | return NULL; | 1544 | return NULL; |
| 1465 | 1545 | ||
| 1466 | restart: | 1546 | cic = cfq_cic_rb_lookup(cfqd, ioc); |
| 1467 | if ((cic = ioc->cic) == NULL) { | 1547 | if (cic) |
| 1468 | cic = cfq_alloc_io_context(cfqd, gfp_mask); | 1548 | goto out; |
| 1469 | |||
| 1470 | if (cic == NULL) | ||
| 1471 | goto err; | ||
| 1472 | |||
| 1473 | /* | ||
| 1474 | * manually increment generic io_context usage count, it | ||
| 1475 | * cannot go away since we are already holding one ref to it | ||
| 1476 | */ | ||
| 1477 | cic->ioc = ioc; | ||
| 1478 | cic->key = cfqd; | ||
| 1479 | read_lock(&cfq_exit_lock); | ||
| 1480 | ioc->set_ioprio = cfq_ioc_set_ioprio; | ||
| 1481 | ioc->cic = cic; | ||
| 1482 | list_add(&cic->queue_list, &cfqd->cic_list); | ||
| 1483 | read_unlock(&cfq_exit_lock); | ||
| 1484 | } else { | ||
| 1485 | struct cfq_io_context *__cic; | ||
| 1486 | |||
| 1487 | /* | ||
| 1488 | * the first cic on the list is actually the head itself | ||
| 1489 | */ | ||
| 1490 | if (cic->key == cfqd) | ||
| 1491 | goto out; | ||
| 1492 | |||
| 1493 | if (unlikely(!cic->key)) { | ||
| 1494 | read_lock(&cfq_exit_lock); | ||
| 1495 | if (list_empty(&cic->list)) | ||
| 1496 | ioc->cic = NULL; | ||
| 1497 | else | ||
| 1498 | ioc->cic = list_entry(cic->list.next, | ||
| 1499 | struct cfq_io_context, | ||
| 1500 | list); | ||
| 1501 | read_unlock(&cfq_exit_lock); | ||
| 1502 | kmem_cache_free(cfq_ioc_pool, cic); | ||
| 1503 | atomic_dec(&ioc_count); | ||
| 1504 | goto restart; | ||
| 1505 | } | ||
| 1506 | |||
| 1507 | /* | ||
| 1508 | * cic exists, check if we already are there. linear search | ||
| 1509 | * should be ok here, the list will usually not be more than | ||
| 1510 | * 1 or a few entries long | ||
| 1511 | */ | ||
| 1512 | list_for_each_entry(__cic, &cic->list, list) { | ||
| 1513 | /* | ||
| 1514 | * this process is already holding a reference to | ||
| 1515 | * this queue, so no need to get one more | ||
| 1516 | */ | ||
| 1517 | if (__cic->key == cfqd) { | ||
| 1518 | cic = __cic; | ||
| 1519 | goto out; | ||
| 1520 | } | ||
| 1521 | if (unlikely(!__cic->key)) { | ||
| 1522 | read_lock(&cfq_exit_lock); | ||
| 1523 | list_del(&__cic->list); | ||
| 1524 | read_unlock(&cfq_exit_lock); | ||
| 1525 | kmem_cache_free(cfq_ioc_pool, __cic); | ||
| 1526 | atomic_dec(&ioc_count); | ||
| 1527 | goto restart; | ||
| 1528 | } | ||
| 1529 | } | ||
| 1530 | 1549 | ||
| 1531 | /* | 1550 | cic = cfq_alloc_io_context(cfqd, gfp_mask); |
| 1532 | * nope, process doesn't have a cic assoicated with this | 1551 | if (cic == NULL) |
| 1533 | * cfqq yet. get a new one and add to list | 1552 | goto err; |
| 1534 | */ | ||
| 1535 | __cic = cfq_alloc_io_context(cfqd, gfp_mask); | ||
| 1536 | if (__cic == NULL) | ||
| 1537 | goto err; | ||
| 1538 | |||
| 1539 | __cic->ioc = ioc; | ||
| 1540 | __cic->key = cfqd; | ||
| 1541 | read_lock(&cfq_exit_lock); | ||
| 1542 | list_add(&__cic->list, &cic->list); | ||
| 1543 | list_add(&__cic->queue_list, &cfqd->cic_list); | ||
| 1544 | read_unlock(&cfq_exit_lock); | ||
| 1545 | cic = __cic; | ||
| 1546 | } | ||
| 1547 | 1553 | ||
| 1554 | cfq_cic_link(cfqd, ioc, cic); | ||
| 1548 | out: | 1555 | out: |
| 1549 | return cic; | 1556 | return cic; |
| 1550 | err: | 1557 | err: |
| @@ -1577,7 +1584,33 @@ cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic) | |||
| 1577 | cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples; | 1584 | cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples; |
| 1578 | } | 1585 | } |
| 1579 | 1586 | ||
| 1580 | #define sample_valid(samples) ((samples) > 80) | 1587 | static void |
| 1588 | cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic, | ||
| 1589 | struct cfq_rq *crq) | ||
| 1590 | { | ||
| 1591 | sector_t sdist; | ||
| 1592 | u64 total; | ||
| 1593 | |||
| 1594 | if (cic->last_request_pos < crq->request->sector) | ||
| 1595 | sdist = crq->request->sector - cic->last_request_pos; | ||
| 1596 | else | ||
| 1597 | sdist = cic->last_request_pos - crq->request->sector; | ||
| 1598 | |||
| 1599 | /* | ||
| 1600 | * Don't allow the seek distance to get too large from the | ||
| 1601 | * odd fragment, pagein, etc | ||
| 1602 | */ | ||
| 1603 | if (cic->seek_samples <= 60) /* second&third seek */ | ||
| 1604 | sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*1024); | ||
| 1605 | else | ||
| 1606 | sdist = min(sdist, (cic->seek_mean * 4) + 2*1024*64); | ||
| 1607 | |||
| 1608 | cic->seek_samples = (7*cic->seek_samples + 256) / 8; | ||
| 1609 | cic->seek_total = (7*cic->seek_total + (u64)256*sdist) / 8; | ||
| 1610 | total = cic->seek_total + (cic->seek_samples/2); | ||
| 1611 | do_div(total, cic->seek_samples); | ||
| 1612 | cic->seek_mean = (sector_t)total; | ||
| 1613 | } | ||
| 1581 | 1614 | ||
| 1582 | /* | 1615 | /* |
| 1583 | * Disable idle window if the process thinks too long or seeks so much that | 1616 | * Disable idle window if the process thinks too long or seeks so much that |
| @@ -1690,9 +1723,11 @@ cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
| 1690 | cic = crq->io_context; | 1723 | cic = crq->io_context; |
| 1691 | 1724 | ||
| 1692 | cfq_update_io_thinktime(cfqd, cic); | 1725 | cfq_update_io_thinktime(cfqd, cic); |
| 1726 | cfq_update_io_seektime(cfqd, cic, crq); | ||
| 1693 | cfq_update_idle_window(cfqd, cfqq, cic); | 1727 | cfq_update_idle_window(cfqd, cfqq, cic); |
| 1694 | 1728 | ||
| 1695 | cic->last_queue = jiffies; | 1729 | cic->last_queue = jiffies; |
| 1730 | cic->last_request_pos = crq->request->sector + crq->request->nr_sectors; | ||
| 1696 | 1731 | ||
| 1697 | if (cfqq == cfqd->active_queue) { | 1732 | if (cfqq == cfqd->active_queue) { |
| 1698 | /* | 1733 | /* |
| @@ -1825,14 +1860,6 @@ static void cfq_prio_boost(struct cfq_queue *cfqq) | |||
| 1825 | cfq_resort_rr_list(cfqq, 0); | 1860 | cfq_resort_rr_list(cfqq, 0); |
| 1826 | } | 1861 | } |
| 1827 | 1862 | ||
| 1828 | static inline pid_t cfq_queue_pid(struct task_struct *task, int rw) | ||
| 1829 | { | ||
| 1830 | if (rw == READ || process_sync(task)) | ||
| 1831 | return task->pid; | ||
| 1832 | |||
| 1833 | return CFQ_KEY_ASYNC; | ||
| 1834 | } | ||
| 1835 | |||
| 1836 | static inline int | 1863 | static inline int |
| 1837 | __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, | 1864 | __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq, |
| 1838 | struct task_struct *task, int rw) | 1865 | struct task_struct *task, int rw) |
| @@ -1965,7 +1992,7 @@ cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio, | |||
| 1965 | 1992 | ||
| 1966 | might_sleep_if(gfp_mask & __GFP_WAIT); | 1993 | might_sleep_if(gfp_mask & __GFP_WAIT); |
| 1967 | 1994 | ||
| 1968 | cic = cfq_get_io_context(cfqd, key, gfp_mask); | 1995 | cic = cfq_get_io_context(cfqd, gfp_mask); |
| 1969 | 1996 | ||
| 1970 | spin_lock_irqsave(q->queue_lock, flags); | 1997 | spin_lock_irqsave(q->queue_lock, flags); |
| 1971 | 1998 | ||
| @@ -2133,11 +2160,14 @@ static void cfq_exit_queue(elevator_t *e) | |||
| 2133 | request_queue_t *q = cfqd->queue; | 2160 | request_queue_t *q = cfqd->queue; |
| 2134 | 2161 | ||
| 2135 | cfq_shutdown_timer_wq(cfqd); | 2162 | cfq_shutdown_timer_wq(cfqd); |
| 2163 | |||
| 2136 | write_lock(&cfq_exit_lock); | 2164 | write_lock(&cfq_exit_lock); |
| 2137 | spin_lock_irq(q->queue_lock); | 2165 | spin_lock_irq(q->queue_lock); |
| 2166 | |||
| 2138 | if (cfqd->active_queue) | 2167 | if (cfqd->active_queue) |
| 2139 | __cfq_slice_expired(cfqd, cfqd->active_queue, 0); | 2168 | __cfq_slice_expired(cfqd, cfqd->active_queue, 0); |
| 2140 | while(!list_empty(&cfqd->cic_list)) { | 2169 | |
| 2170 | while (!list_empty(&cfqd->cic_list)) { | ||
| 2141 | struct cfq_io_context *cic = list_entry(cfqd->cic_list.next, | 2171 | struct cfq_io_context *cic = list_entry(cfqd->cic_list.next, |
| 2142 | struct cfq_io_context, | 2172 | struct cfq_io_context, |
| 2143 | queue_list); | 2173 | queue_list); |
| @@ -2152,6 +2182,7 @@ static void cfq_exit_queue(elevator_t *e) | |||
| 2152 | cic->key = NULL; | 2182 | cic->key = NULL; |
| 2153 | list_del_init(&cic->queue_list); | 2183 | list_del_init(&cic->queue_list); |
| 2154 | } | 2184 | } |
| 2185 | |||
| 2155 | spin_unlock_irq(q->queue_lock); | 2186 | spin_unlock_irq(q->queue_lock); |
| 2156 | write_unlock(&cfq_exit_lock); | 2187 | write_unlock(&cfq_exit_lock); |
| 2157 | 2188 | ||
| @@ -2227,7 +2258,6 @@ static int cfq_init_queue(request_queue_t *q, elevator_t *e) | |||
| 2227 | cfqd->cfq_slice[1] = cfq_slice_sync; | 2258 | cfqd->cfq_slice[1] = cfq_slice_sync; |
| 2228 | cfqd->cfq_slice_async_rq = cfq_slice_async_rq; | 2259 | cfqd->cfq_slice_async_rq = cfq_slice_async_rq; |
| 2229 | cfqd->cfq_slice_idle = cfq_slice_idle; | 2260 | cfqd->cfq_slice_idle = cfq_slice_idle; |
| 2230 | cfqd->cfq_max_depth = cfq_max_depth; | ||
| 2231 | 2261 | ||
| 2232 | return 0; | 2262 | return 0; |
| 2233 | out_crqpool: | 2263 | out_crqpool: |
| @@ -2310,7 +2340,6 @@ SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1); | |||
| 2310 | SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); | 2340 | SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1); |
| 2311 | SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); | 2341 | SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1); |
| 2312 | SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); | 2342 | SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0); |
| 2313 | SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0); | ||
| 2314 | #undef SHOW_FUNCTION | 2343 | #undef SHOW_FUNCTION |
| 2315 | 2344 | ||
| 2316 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ | 2345 | #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ |
| @@ -2339,7 +2368,6 @@ STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1); | |||
| 2339 | STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1); | 2368 | STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1); |
| 2340 | STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); | 2369 | STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1); |
| 2341 | STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0); | 2370 | STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0); |
| 2342 | STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0); | ||
| 2343 | #undef STORE_FUNCTION | 2371 | #undef STORE_FUNCTION |
| 2344 | 2372 | ||
| 2345 | #define CFQ_ATTR(name) \ | 2373 | #define CFQ_ATTR(name) \ |
| @@ -2356,7 +2384,6 @@ static struct elv_fs_entry cfq_attrs[] = { | |||
| 2356 | CFQ_ATTR(slice_async), | 2384 | CFQ_ATTR(slice_async), |
| 2357 | CFQ_ATTR(slice_async_rq), | 2385 | CFQ_ATTR(slice_async_rq), |
| 2358 | CFQ_ATTR(slice_idle), | 2386 | CFQ_ATTR(slice_idle), |
| 2359 | CFQ_ATTR(max_depth), | ||
| 2360 | __ATTR_NULL | 2387 | __ATTR_NULL |
| 2361 | }; | 2388 | }; |
| 2362 | 2389 | ||
diff --git a/block/genhd.c b/block/genhd.c index 64510fd88621..db4c60c802d6 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
| @@ -454,8 +454,8 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page) | |||
| 454 | disk_round_stats(disk); | 454 | disk_round_stats(disk); |
| 455 | preempt_enable(); | 455 | preempt_enable(); |
| 456 | return sprintf(page, | 456 | return sprintf(page, |
| 457 | "%8u %8u %8llu %8u " | 457 | "%8lu %8lu %8llu %8u " |
| 458 | "%8u %8u %8llu %8u " | 458 | "%8lu %8lu %8llu %8u " |
| 459 | "%8u %8u %8u" | 459 | "%8u %8u %8u" |
| 460 | "\n", | 460 | "\n", |
| 461 | disk_stat_read(disk, ios[READ]), | 461 | disk_stat_read(disk, ios[READ]), |
| @@ -649,7 +649,7 @@ static int diskstats_show(struct seq_file *s, void *v) | |||
| 649 | preempt_disable(); | 649 | preempt_disable(); |
| 650 | disk_round_stats(gp); | 650 | disk_round_stats(gp); |
| 651 | preempt_enable(); | 651 | preempt_enable(); |
| 652 | seq_printf(s, "%4d %4d %s %u %u %llu %u %u %u %llu %u %u %u %u\n", | 652 | seq_printf(s, "%4d %4d %s %lu %lu %llu %u %lu %lu %llu %u %u %u %u\n", |
| 653 | gp->major, n + gp->first_minor, disk_name(gp, n, buf), | 653 | gp->major, n + gp->first_minor, disk_name(gp, n, buf), |
| 654 | disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), | 654 | disk_stat_read(gp, ios[0]), disk_stat_read(gp, merges[0]), |
| 655 | (unsigned long long)disk_stat_read(gp, sectors[0]), | 655 | (unsigned long long)disk_stat_read(gp, sectors[0]), |
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 062067fa7ead..5b26af8597f3 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c | |||
| @@ -785,6 +785,8 @@ void blk_queue_stack_limits(request_queue_t *t, request_queue_t *b) | |||
| 785 | t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments); | 785 | t->max_hw_segments = min(t->max_hw_segments,b->max_hw_segments); |
| 786 | t->max_segment_size = min(t->max_segment_size,b->max_segment_size); | 786 | t->max_segment_size = min(t->max_segment_size,b->max_segment_size); |
| 787 | t->hardsect_size = max(t->hardsect_size,b->hardsect_size); | 787 | t->hardsect_size = max(t->hardsect_size,b->hardsect_size); |
| 788 | if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) | ||
| 789 | clear_bit(QUEUE_FLAG_CLUSTER, &t->queue_flags); | ||
| 788 | } | 790 | } |
| 789 | 791 | ||
| 790 | EXPORT_SYMBOL(blk_queue_stack_limits); | 792 | EXPORT_SYMBOL(blk_queue_stack_limits); |
| @@ -906,17 +908,15 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth) | |||
| 906 | __FUNCTION__, depth); | 908 | __FUNCTION__, depth); |
| 907 | } | 909 | } |
| 908 | 910 | ||
| 909 | tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC); | 911 | tag_index = kzalloc(depth * sizeof(struct request *), GFP_ATOMIC); |
| 910 | if (!tag_index) | 912 | if (!tag_index) |
| 911 | goto fail; | 913 | goto fail; |
| 912 | 914 | ||
| 913 | nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG; | 915 | nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG; |
| 914 | tag_map = kmalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC); | 916 | tag_map = kzalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC); |
| 915 | if (!tag_map) | 917 | if (!tag_map) |
| 916 | goto fail; | 918 | goto fail; |
| 917 | 919 | ||
| 918 | memset(tag_index, 0, depth * sizeof(struct request *)); | ||
| 919 | memset(tag_map, 0, nr_ulongs * sizeof(unsigned long)); | ||
| 920 | tags->real_max_depth = depth; | 920 | tags->real_max_depth = depth; |
| 921 | tags->max_depth = depth; | 921 | tags->max_depth = depth; |
| 922 | tags->tag_index = tag_index; | 922 | tags->tag_index = tag_index; |
| @@ -2479,10 +2479,12 @@ void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk, | |||
| 2479 | rq->rq_disk = bd_disk; | 2479 | rq->rq_disk = bd_disk; |
| 2480 | rq->flags |= REQ_NOMERGE; | 2480 | rq->flags |= REQ_NOMERGE; |
| 2481 | rq->end_io = done; | 2481 | rq->end_io = done; |
| 2482 | elv_add_request(q, rq, where, 1); | 2482 | WARN_ON(irqs_disabled()); |
| 2483 | generic_unplug_device(q); | 2483 | spin_lock_irq(q->queue_lock); |
| 2484 | __elv_add_request(q, rq, where, 1); | ||
| 2485 | __generic_unplug_device(q); | ||
| 2486 | spin_unlock_irq(q->queue_lock); | ||
| 2484 | } | 2487 | } |
| 2485 | |||
| 2486 | EXPORT_SYMBOL_GPL(blk_execute_rq_nowait); | 2488 | EXPORT_SYMBOL_GPL(blk_execute_rq_nowait); |
| 2487 | 2489 | ||
| 2488 | /** | 2490 | /** |
| @@ -3512,7 +3514,7 @@ int __init blk_dev_init(void) | |||
| 3512 | iocontext_cachep = kmem_cache_create("blkdev_ioc", | 3514 | iocontext_cachep = kmem_cache_create("blkdev_ioc", |
| 3513 | sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL); | 3515 | sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL); |
| 3514 | 3516 | ||
| 3515 | for_each_cpu(i) | 3517 | for_each_possible_cpu(i) |
| 3516 | INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i)); | 3518 | INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i)); |
| 3517 | 3519 | ||
| 3518 | open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL); | 3520 | open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL); |
| @@ -3537,11 +3539,17 @@ void put_io_context(struct io_context *ioc) | |||
| 3537 | BUG_ON(atomic_read(&ioc->refcount) == 0); | 3539 | BUG_ON(atomic_read(&ioc->refcount) == 0); |
| 3538 | 3540 | ||
| 3539 | if (atomic_dec_and_test(&ioc->refcount)) { | 3541 | if (atomic_dec_and_test(&ioc->refcount)) { |
| 3542 | struct cfq_io_context *cic; | ||
| 3543 | |||
| 3540 | rcu_read_lock(); | 3544 | rcu_read_lock(); |
| 3541 | if (ioc->aic && ioc->aic->dtor) | 3545 | if (ioc->aic && ioc->aic->dtor) |
| 3542 | ioc->aic->dtor(ioc->aic); | 3546 | ioc->aic->dtor(ioc->aic); |
| 3543 | if (ioc->cic && ioc->cic->dtor) | 3547 | if (ioc->cic_root.rb_node != NULL) { |
| 3544 | ioc->cic->dtor(ioc->cic); | 3548 | struct rb_node *n = rb_first(&ioc->cic_root); |
| 3549 | |||
| 3550 | cic = rb_entry(n, struct cfq_io_context, rb_node); | ||
| 3551 | cic->dtor(ioc); | ||
| 3552 | } | ||
| 3545 | rcu_read_unlock(); | 3553 | rcu_read_unlock(); |
| 3546 | 3554 | ||
| 3547 | kmem_cache_free(iocontext_cachep, ioc); | 3555 | kmem_cache_free(iocontext_cachep, ioc); |
| @@ -3554,6 +3562,7 @@ void exit_io_context(void) | |||
| 3554 | { | 3562 | { |
| 3555 | unsigned long flags; | 3563 | unsigned long flags; |
| 3556 | struct io_context *ioc; | 3564 | struct io_context *ioc; |
| 3565 | struct cfq_io_context *cic; | ||
| 3557 | 3566 | ||
| 3558 | local_irq_save(flags); | 3567 | local_irq_save(flags); |
| 3559 | task_lock(current); | 3568 | task_lock(current); |
| @@ -3565,9 +3574,11 @@ void exit_io_context(void) | |||
| 3565 | 3574 | ||
| 3566 | if (ioc->aic && ioc->aic->exit) | 3575 | if (ioc->aic && ioc->aic->exit) |
| 3567 | ioc->aic->exit(ioc->aic); | 3576 | ioc->aic->exit(ioc->aic); |
| 3568 | if (ioc->cic && ioc->cic->exit) | 3577 | if (ioc->cic_root.rb_node != NULL) { |
| 3569 | ioc->cic->exit(ioc->cic); | 3578 | cic = rb_entry(rb_first(&ioc->cic_root), struct cfq_io_context, rb_node); |
| 3570 | 3579 | cic->exit(ioc); | |
| 3580 | } | ||
| 3581 | |||
| 3571 | put_io_context(ioc); | 3582 | put_io_context(ioc); |
| 3572 | } | 3583 | } |
| 3573 | 3584 | ||
| @@ -3596,7 +3607,7 @@ struct io_context *current_io_context(gfp_t gfp_flags) | |||
| 3596 | ret->last_waited = jiffies; /* doesn't matter... */ | 3607 | ret->last_waited = jiffies; /* doesn't matter... */ |
| 3597 | ret->nr_batch_requests = 0; /* because this is 0 */ | 3608 | ret->nr_batch_requests = 0; /* because this is 0 */ |
| 3598 | ret->aic = NULL; | 3609 | ret->aic = NULL; |
| 3599 | ret->cic = NULL; | 3610 | ret->cic_root.rb_node = NULL; |
| 3600 | tsk->io_context = ret; | 3611 | tsk->io_context = ret; |
| 3601 | } | 3612 | } |
| 3602 | 3613 | ||
diff --git a/drivers/Kconfig b/drivers/Kconfig index bddf431bbb72..9f5c0da57c90 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
| @@ -70,4 +70,6 @@ source "drivers/sn/Kconfig" | |||
| 70 | 70 | ||
| 71 | source "drivers/edac/Kconfig" | 71 | source "drivers/edac/Kconfig" |
| 72 | 72 | ||
| 73 | source "drivers/rtc/Kconfig" | ||
| 74 | |||
| 73 | endmenu | 75 | endmenu |
diff --git a/drivers/Makefile b/drivers/Makefile index 5c69b86db624..424955274e60 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
| @@ -56,6 +56,7 @@ obj-$(CONFIG_USB_GADGET) += usb/gadget/ | |||
| 56 | obj-$(CONFIG_GAMEPORT) += input/gameport/ | 56 | obj-$(CONFIG_GAMEPORT) += input/gameport/ |
| 57 | obj-$(CONFIG_INPUT) += input/ | 57 | obj-$(CONFIG_INPUT) += input/ |
| 58 | obj-$(CONFIG_I2O) += message/ | 58 | obj-$(CONFIG_I2O) += message/ |
| 59 | obj-$(CONFIG_RTC_LIB) += rtc/ | ||
| 59 | obj-$(CONFIG_I2C) += i2c/ | 60 | obj-$(CONFIG_I2C) += i2c/ |
| 60 | obj-$(CONFIG_W1) += w1/ | 61 | obj-$(CONFIG_W1) += w1/ |
| 61 | obj-$(CONFIG_HWMON) += hwmon/ | 62 | obj-$(CONFIG_HWMON) += hwmon/ |
diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 69f4c7ce9a63..cac09e353be8 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c | |||
| @@ -1972,7 +1972,7 @@ static int __devinit lanai_pci_start(struct lanai_dev *lanai) | |||
| 1972 | "(itf %d): No suitable DMA available.\n", lanai->number); | 1972 | "(itf %d): No suitable DMA available.\n", lanai->number); |
| 1973 | return -EBUSY; | 1973 | return -EBUSY; |
| 1974 | } | 1974 | } |
| 1975 | if (pci_set_consistent_dma_mask(pci, 0xFFFFFFFF) != 0) { | 1975 | if (pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) != 0) { |
| 1976 | printk(KERN_WARNING DEV_LABEL | 1976 | printk(KERN_WARNING DEV_LABEL |
| 1977 | "(itf %d): No suitable DMA available.\n", lanai->number); | 1977 | "(itf %d): No suitable DMA available.\n", lanai->number); |
| 1978 | return -EBUSY; | 1978 | return -EBUSY; |
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 105a0d61eb1f..dd547af4681a 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
| @@ -47,16 +47,16 @@ static struct kset_uevent_ops memory_uevent_ops = { | |||
| 47 | .uevent = memory_uevent, | 47 | .uevent = memory_uevent, |
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| 50 | static struct notifier_block *memory_chain; | 50 | static BLOCKING_NOTIFIER_HEAD(memory_chain); |
| 51 | 51 | ||
| 52 | int register_memory_notifier(struct notifier_block *nb) | 52 | int register_memory_notifier(struct notifier_block *nb) |
| 53 | { | 53 | { |
| 54 | return notifier_chain_register(&memory_chain, nb); | 54 | return blocking_notifier_chain_register(&memory_chain, nb); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | void unregister_memory_notifier(struct notifier_block *nb) | 57 | void unregister_memory_notifier(struct notifier_block *nb) |
| 58 | { | 58 | { |
| 59 | notifier_chain_unregister(&memory_chain, nb); | 59 | blocking_notifier_chain_unregister(&memory_chain, nb); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | /* | 62 | /* |
| @@ -140,7 +140,7 @@ static ssize_t show_mem_state(struct sys_device *dev, char *buf) | |||
| 140 | 140 | ||
| 141 | static inline int memory_notify(unsigned long val, void *v) | 141 | static inline int memory_notify(unsigned long val, void *v) |
| 142 | { | 142 | { |
| 143 | return notifier_call_chain(&memory_chain, val, v); | 143 | return blocking_notifier_call_chain(&memory_chain, val, v); |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | /* | 146 | /* |
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 9bdea2a5cf0e..45bcda544880 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/timer.h> | 41 | #include <linux/timer.h> |
| 42 | #include <linux/pci.h> | 42 | #include <linux/pci.h> |
| 43 | #include <linux/init.h> | 43 | #include <linux/init.h> |
| 44 | #include <linux/jiffies.h> | ||
| 44 | #include <linux/random.h> | 45 | #include <linux/random.h> |
| 45 | #include <asm/io.h> | 46 | #include <asm/io.h> |
| 46 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
| @@ -311,11 +312,10 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller) | |||
| 311 | CommandsRemaining = CommandAllocationGroupSize; | 312 | CommandsRemaining = CommandAllocationGroupSize; |
| 312 | CommandGroupByteCount = | 313 | CommandGroupByteCount = |
| 313 | CommandsRemaining * CommandAllocationLength; | 314 | CommandsRemaining * CommandAllocationLength; |
| 314 | AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC); | 315 | AllocationPointer = kzalloc(CommandGroupByteCount, GFP_ATOMIC); |
| 315 | if (AllocationPointer == NULL) | 316 | if (AllocationPointer == NULL) |
| 316 | return DAC960_Failure(Controller, | 317 | return DAC960_Failure(Controller, |
| 317 | "AUXILIARY STRUCTURE CREATION"); | 318 | "AUXILIARY STRUCTURE CREATION"); |
| 318 | memset(AllocationPointer, 0, CommandGroupByteCount); | ||
| 319 | } | 319 | } |
| 320 | Command = (DAC960_Command_T *) AllocationPointer; | 320 | Command = (DAC960_Command_T *) AllocationPointer; |
| 321 | AllocationPointer += CommandAllocationLength; | 321 | AllocationPointer += CommandAllocationLength; |
| @@ -2709,14 +2709,12 @@ DAC960_DetectController(struct pci_dev *PCI_Device, | |||
| 2709 | void __iomem *BaseAddress; | 2709 | void __iomem *BaseAddress; |
| 2710 | int i; | 2710 | int i; |
| 2711 | 2711 | ||
| 2712 | Controller = (DAC960_Controller_T *) | 2712 | Controller = kzalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); |
| 2713 | kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); | ||
| 2714 | if (Controller == NULL) { | 2713 | if (Controller == NULL) { |
| 2715 | DAC960_Error("Unable to allocate Controller structure for " | 2714 | DAC960_Error("Unable to allocate Controller structure for " |
| 2716 | "Controller at\n", NULL); | 2715 | "Controller at\n", NULL); |
| 2717 | return NULL; | 2716 | return NULL; |
| 2718 | } | 2717 | } |
| 2719 | memset(Controller, 0, sizeof(DAC960_Controller_T)); | ||
| 2720 | Controller->ControllerNumber = DAC960_ControllerCount; | 2718 | Controller->ControllerNumber = DAC960_ControllerCount; |
| 2721 | DAC960_Controllers[DAC960_ControllerCount++] = Controller; | 2719 | DAC960_Controllers[DAC960_ControllerCount++] = Controller; |
| 2722 | Controller->Bus = PCI_Device->bus->number; | 2720 | Controller->Bus = PCI_Device->bus->number; |
| @@ -3657,8 +3655,8 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command) | |||
| 3657 | (NewEnquiry->EventLogSequenceNumber != | 3655 | (NewEnquiry->EventLogSequenceNumber != |
| 3658 | OldEnquiry->EventLogSequenceNumber) || | 3656 | OldEnquiry->EventLogSequenceNumber) || |
| 3659 | Controller->MonitoringTimerCount == 0 || | 3657 | Controller->MonitoringTimerCount == 0 || |
| 3660 | (jiffies - Controller->SecondaryMonitoringTime | 3658 | time_after_eq(jiffies, Controller->SecondaryMonitoringTime |
| 3661 | >= DAC960_SecondaryMonitoringInterval)) | 3659 | + DAC960_SecondaryMonitoringInterval)) |
| 3662 | { | 3660 | { |
| 3663 | Controller->V1.NeedLogicalDriveInformation = true; | 3661 | Controller->V1.NeedLogicalDriveInformation = true; |
| 3664 | Controller->V1.NewEventLogSequenceNumber = | 3662 | Controller->V1.NewEventLogSequenceNumber = |
| @@ -5643,8 +5641,8 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData) | |||
| 5643 | unsigned int StatusChangeCounter = | 5641 | unsigned int StatusChangeCounter = |
| 5644 | Controller->V2.HealthStatusBuffer->StatusChangeCounter; | 5642 | Controller->V2.HealthStatusBuffer->StatusChangeCounter; |
| 5645 | boolean ForceMonitoringCommand = false; | 5643 | boolean ForceMonitoringCommand = false; |
| 5646 | if (jiffies - Controller->SecondaryMonitoringTime | 5644 | if (time_after(jiffies, Controller->SecondaryMonitoringTime |
| 5647 | > DAC960_SecondaryMonitoringInterval) | 5645 | + DAC960_SecondaryMonitoringInterval)) |
| 5648 | { | 5646 | { |
| 5649 | int LogicalDriveNumber; | 5647 | int LogicalDriveNumber; |
| 5650 | for (LogicalDriveNumber = 0; | 5648 | for (LogicalDriveNumber = 0; |
| @@ -5672,8 +5670,8 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData) | |||
| 5672 | ControllerInfo->ConsistencyChecksActive + | 5670 | ControllerInfo->ConsistencyChecksActive + |
| 5673 | ControllerInfo->RebuildsActive + | 5671 | ControllerInfo->RebuildsActive + |
| 5674 | ControllerInfo->OnlineExpansionsActive == 0 || | 5672 | ControllerInfo->OnlineExpansionsActive == 0 || |
| 5675 | jiffies - Controller->PrimaryMonitoringTime | 5673 | time_before(jiffies, Controller->PrimaryMonitoringTime |
| 5676 | < DAC960_MonitoringTimerInterval) && | 5674 | + DAC960_MonitoringTimerInterval)) && |
| 5677 | !ForceMonitoringCommand) | 5675 | !ForceMonitoringCommand) |
| 5678 | { | 5676 | { |
| 5679 | Controller->MonitoringTimer.expires = | 5677 | Controller->MonitoringTimer.expires = |
| @@ -5810,8 +5808,8 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, | |||
| 5810 | Controller->ProgressBufferLength = Length; | 5808 | Controller->ProgressBufferLength = Length; |
| 5811 | if (Controller->EphemeralProgressMessage) | 5809 | if (Controller->EphemeralProgressMessage) |
| 5812 | { | 5810 | { |
| 5813 | if (jiffies - Controller->LastProgressReportTime | 5811 | if (time_after_eq(jiffies, Controller->LastProgressReportTime |
| 5814 | >= DAC960_ProgressReportingInterval) | 5812 | + DAC960_ProgressReportingInterval)) |
| 5815 | { | 5813 | { |
| 5816 | printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel], | 5814 | printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel], |
| 5817 | Controller->ControllerNumber, Buffer); | 5815 | Controller->ControllerNumber, Buffer); |
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 875ae7699025..ae0949b3394f 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
| @@ -383,8 +383,9 @@ config BLK_DEV_RAM | |||
| 383 | thus say N here. | 383 | thus say N here. |
| 384 | 384 | ||
| 385 | config BLK_DEV_RAM_COUNT | 385 | config BLK_DEV_RAM_COUNT |
| 386 | int "Default number of RAM disks" if BLK_DEV_RAM | 386 | int "Default number of RAM disks" |
| 387 | default "16" | 387 | default "16" |
| 388 | depends on BLK_DEV_RAM | ||
| 388 | help | 389 | help |
| 389 | The default value is 16 RAM disks. Change this if you know what | 390 | The default value is 16 RAM disks. Change this if you know what |
| 390 | are doing. If you boot from a filesystem that needs to be extracted | 391 | are doing. If you boot from a filesystem that needs to be extracted |
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c index a5c1c8e871ec..4cb9c1336287 100644 --- a/drivers/block/acsi_slm.c +++ b/drivers/block/acsi_slm.c | |||
| @@ -369,8 +369,6 @@ static ssize_t slm_read( struct file *file, char *buf, size_t count, | |||
| 369 | int length; | 369 | int length; |
| 370 | int end; | 370 | int end; |
| 371 | 371 | ||
| 372 | if (count < 0) | ||
| 373 | return( -EINVAL ); | ||
| 374 | if (!(page = __get_free_page( GFP_KERNEL ))) | 372 | if (!(page = __get_free_page( GFP_KERNEL ))) |
| 375 | return( -ENOMEM ); | 373 | return( -ENOMEM ); |
| 376 | 374 | ||
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 71ec9e664383..1b0fd31c57c3 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -996,13 +996,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, | |||
| 996 | status = -EINVAL; | 996 | status = -EINVAL; |
| 997 | goto cleanup1; | 997 | goto cleanup1; |
| 998 | } | 998 | } |
| 999 | buff = (unsigned char **) kmalloc(MAXSGENTRIES * | 999 | buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL); |
| 1000 | sizeof(char *), GFP_KERNEL); | ||
| 1001 | if (!buff) { | 1000 | if (!buff) { |
| 1002 | status = -ENOMEM; | 1001 | status = -ENOMEM; |
| 1003 | goto cleanup1; | 1002 | goto cleanup1; |
| 1004 | } | 1003 | } |
| 1005 | memset(buff, 0, MAXSGENTRIES); | ||
| 1006 | buff_size = (int *) kmalloc(MAXSGENTRIES * sizeof(int), | 1004 | buff_size = (int *) kmalloc(MAXSGENTRIES * sizeof(int), |
| 1007 | GFP_KERNEL); | 1005 | GFP_KERNEL); |
| 1008 | if (!buff_size) { | 1006 | if (!buff_size) { |
| @@ -2729,9 +2727,9 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *c, struct pci_dev *pdev, | |||
| 2729 | return; | 2727 | return; |
| 2730 | } | 2728 | } |
| 2731 | } | 2729 | } |
| 2730 | default_int_mode: | ||
| 2732 | #endif /* CONFIG_PCI_MSI */ | 2731 | #endif /* CONFIG_PCI_MSI */ |
| 2733 | /* if we get here we're going to use the default interrupt mode */ | 2732 | /* if we get here we're going to use the default interrupt mode */ |
| 2734 | default_int_mode: | ||
| 2735 | c->intr[SIMPLE_MODE_INT] = pdev->irq; | 2733 | c->intr[SIMPLE_MODE_INT] = pdev->irq; |
| 2736 | return; | 2734 | return; |
| 2737 | } | 2735 | } |
| @@ -2940,13 +2938,12 @@ static void cciss_getgeometry(int cntl_num) | |||
| 2940 | int block_size; | 2938 | int block_size; |
| 2941 | int total_size; | 2939 | int total_size; |
| 2942 | 2940 | ||
| 2943 | ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL); | 2941 | ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); |
| 2944 | if (ld_buff == NULL) | 2942 | if (ld_buff == NULL) |
| 2945 | { | 2943 | { |
| 2946 | printk(KERN_ERR "cciss: out of memory\n"); | 2944 | printk(KERN_ERR "cciss: out of memory\n"); |
| 2947 | return; | 2945 | return; |
| 2948 | } | 2946 | } |
| 2949 | memset(ld_buff, 0, sizeof(ReportLunData_struct)); | ||
| 2950 | size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); | 2947 | size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); |
| 2951 | if (size_buff == NULL) | 2948 | if (size_buff == NULL) |
| 2952 | { | 2949 | { |
| @@ -3060,10 +3057,9 @@ static int alloc_cciss_hba(void) | |||
| 3060 | for(i=0; i< MAX_CTLR; i++) { | 3057 | for(i=0; i< MAX_CTLR; i++) { |
| 3061 | if (!hba[i]) { | 3058 | if (!hba[i]) { |
| 3062 | ctlr_info_t *p; | 3059 | ctlr_info_t *p; |
| 3063 | p = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL); | 3060 | p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL); |
| 3064 | if (!p) | 3061 | if (!p) |
| 3065 | goto Enomem; | 3062 | goto Enomem; |
| 3066 | memset(p, 0, sizeof(ctlr_info_t)); | ||
| 3067 | for (n = 0; n < NWD; n++) | 3063 | for (n = 0; n < NWD; n++) |
| 3068 | p->gendisk[n] = disk[n]; | 3064 | p->gendisk[n] = disk[n]; |
| 3069 | hba[i] = p; | 3065 | hba[i] = p; |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 0e66e904bd8c..597c007fe81b 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
| @@ -1027,12 +1027,11 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) | |||
| 1027 | int i; | 1027 | int i; |
| 1028 | 1028 | ||
| 1029 | c = (ctlr_info_t *) hba[cntl_num]; | 1029 | c = (ctlr_info_t *) hba[cntl_num]; |
| 1030 | ld_buff = kmalloc(reportlunsize, GFP_KERNEL); | 1030 | ld_buff = kzalloc(reportlunsize, GFP_KERNEL); |
| 1031 | if (ld_buff == NULL) { | 1031 | if (ld_buff == NULL) { |
| 1032 | printk(KERN_ERR "cciss: out of memory\n"); | 1032 | printk(KERN_ERR "cciss: out of memory\n"); |
| 1033 | return; | 1033 | return; |
| 1034 | } | 1034 | } |
| 1035 | memset(ld_buff, 0, reportlunsize); | ||
| 1036 | inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); | 1035 | inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); |
| 1037 | if (inq_buff == NULL) { | 1036 | if (inq_buff == NULL) { |
| 1038 | printk(KERN_ERR "cciss: out of memory\n"); | 1037 | printk(KERN_ERR "cciss: out of memory\n"); |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index d3ad9081697e..bedb689b051f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
| @@ -170,6 +170,7 @@ static int print_unex = 1; | |||
| 170 | #include <linux/mm.h> | 170 | #include <linux/mm.h> |
| 171 | #include <linux/bio.h> | 171 | #include <linux/bio.h> |
| 172 | #include <linux/string.h> | 172 | #include <linux/string.h> |
| 173 | #include <linux/jiffies.h> | ||
| 173 | #include <linux/fcntl.h> | 174 | #include <linux/fcntl.h> |
| 174 | #include <linux/delay.h> | 175 | #include <linux/delay.h> |
| 175 | #include <linux/mc146818rtc.h> /* CMOS defines */ | 176 | #include <linux/mc146818rtc.h> /* CMOS defines */ |
| @@ -747,7 +748,7 @@ static int disk_change(int drive) | |||
| 747 | { | 748 | { |
| 748 | int fdc = FDC(drive); | 749 | int fdc = FDC(drive); |
| 749 | #ifdef FLOPPY_SANITY_CHECK | 750 | #ifdef FLOPPY_SANITY_CHECK |
| 750 | if (jiffies - UDRS->select_date < UDP->select_delay) | 751 | if (time_before(jiffies, UDRS->select_date + UDP->select_delay)) |
| 751 | DPRINT("WARNING disk change called early\n"); | 752 | DPRINT("WARNING disk change called early\n"); |
| 752 | if (!(FDCS->dor & (0x10 << UNIT(drive))) || | 753 | if (!(FDCS->dor & (0x10 << UNIT(drive))) || |
| 753 | (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) { | 754 | (FDCS->dor & 3) != UNIT(drive) || fdc != FDC(drive)) { |
| @@ -1075,7 +1076,7 @@ static int fd_wait_for_completion(unsigned long delay, timeout_fn function) | |||
| 1075 | return 1; | 1076 | return 1; |
| 1076 | } | 1077 | } |
| 1077 | 1078 | ||
| 1078 | if ((signed)(jiffies - delay) < 0) { | 1079 | if (time_before(jiffies, delay)) { |
| 1079 | del_timer(&fd_timer); | 1080 | del_timer(&fd_timer); |
| 1080 | fd_timer.function = function; | 1081 | fd_timer.function = function; |
| 1081 | fd_timer.expires = delay; | 1082 | fd_timer.expires = delay; |
| @@ -1535,7 +1536,7 @@ static void setup_rw_floppy(void) | |||
| 1535 | * again just before spinup completion. Beware that | 1536 | * again just before spinup completion. Beware that |
| 1536 | * after scandrives, we must again wait for selection. | 1537 | * after scandrives, we must again wait for selection. |
| 1537 | */ | 1538 | */ |
| 1538 | if ((signed)(ready_date - jiffies) > DP->select_delay) { | 1539 | if (time_after(ready_date, jiffies + DP->select_delay)) { |
| 1539 | ready_date -= DP->select_delay; | 1540 | ready_date -= DP->select_delay; |
| 1540 | function = (timeout_fn) floppy_start; | 1541 | function = (timeout_fn) floppy_start; |
| 1541 | } else | 1542 | } else |
| @@ -3823,7 +3824,7 @@ static int check_floppy_change(struct gendisk *disk) | |||
| 3823 | if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY)) | 3824 | if (UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY)) |
| 3824 | return 1; | 3825 | return 1; |
| 3825 | 3826 | ||
| 3826 | if (UDP->checkfreq < (int)(jiffies - UDRS->last_checked)) { | 3827 | if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) { |
| 3827 | if (floppy_grab_irq_and_dma()) { | 3828 | if (floppy_grab_irq_and_dma()) { |
| 3828 | return 1; | 3829 | return 1; |
| 3829 | } | 3830 | } |
diff --git a/drivers/block/paride/bpck6.c b/drivers/block/paride/bpck6.c index 08d858ad64db..41a237c5957d 100644 --- a/drivers/block/paride/bpck6.c +++ b/drivers/block/paride/bpck6.c | |||
| @@ -224,10 +224,9 @@ static void bpck6_log_adapter( PIA *pi, char * scratch, int verbose ) | |||
| 224 | 224 | ||
| 225 | static int bpck6_init_proto(PIA *pi) | 225 | static int bpck6_init_proto(PIA *pi) |
| 226 | { | 226 | { |
| 227 | Interface *p = kmalloc(sizeof(Interface), GFP_KERNEL); | 227 | Interface *p = kzalloc(sizeof(Interface), GFP_KERNEL); |
| 228 | 228 | ||
| 229 | if (p) { | 229 | if (p) { |
| 230 | memset(p, 0, sizeof(Interface)); | ||
| 231 | pi->private = (unsigned long)p; | 230 | pi->private = (unsigned long)p; |
| 232 | return 0; | 231 | return 0; |
| 233 | } | 232 | } |
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 62d2464c12f2..2403721f9db1 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c | |||
| @@ -151,6 +151,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV}; | |||
| 151 | #include <linux/cdrom.h> /* for the eject ioctl */ | 151 | #include <linux/cdrom.h> /* for the eject ioctl */ |
| 152 | #include <linux/blkdev.h> | 152 | #include <linux/blkdev.h> |
| 153 | #include <linux/blkpg.h> | 153 | #include <linux/blkpg.h> |
| 154 | #include <linux/kernel.h> | ||
| 154 | #include <asm/uaccess.h> | 155 | #include <asm/uaccess.h> |
| 155 | #include <linux/sched.h> | 156 | #include <linux/sched.h> |
| 156 | #include <linux/workqueue.h> | 157 | #include <linux/workqueue.h> |
| @@ -275,7 +276,7 @@ static void pd_print_error(struct pd_unit *disk, char *msg, int status) | |||
| 275 | int i; | 276 | int i; |
| 276 | 277 | ||
| 277 | printk("%s: %s: status = 0x%x =", disk->name, msg, status); | 278 | printk("%s: %s: status = 0x%x =", disk->name, msg, status); |
| 278 | for (i = 0; i < 18; i++) | 279 | for (i = 0; i < ARRAY_SIZE(pd_errs); i++) |
| 279 | if (status & (1 << i)) | 280 | if (status & (1 << i)) |
| 280 | printk(" %s", pd_errs[i]); | 281 | printk(" %s", pd_errs[i]); |
| 281 | printk("\n"); | 282 | printk("\n"); |
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index 6f5df0fad703..79b868254032 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c | |||
| @@ -643,7 +643,8 @@ static ssize_t pg_read(struct file *filp, char __user *buf, size_t count, loff_t | |||
| 643 | 643 | ||
| 644 | static int __init pg_init(void) | 644 | static int __init pg_init(void) |
| 645 | { | 645 | { |
| 646 | int unit, err = 0; | 646 | int unit; |
| 647 | int err; | ||
| 647 | 648 | ||
| 648 | if (disable){ | 649 | if (disable){ |
| 649 | err = -1; | 650 | err = -1; |
| @@ -657,16 +658,17 @@ static int __init pg_init(void) | |||
| 657 | goto out; | 658 | goto out; |
| 658 | } | 659 | } |
| 659 | 660 | ||
| 660 | if (register_chrdev(major, name, &pg_fops)) { | 661 | err = register_chrdev(major, name, &pg_fops); |
| 662 | if (err < 0) { | ||
| 661 | printk("pg_init: unable to get major number %d\n", major); | 663 | printk("pg_init: unable to get major number %d\n", major); |
| 662 | for (unit = 0; unit < PG_UNITS; unit++) { | 664 | for (unit = 0; unit < PG_UNITS; unit++) { |
| 663 | struct pg *dev = &devices[unit]; | 665 | struct pg *dev = &devices[unit]; |
| 664 | if (dev->present) | 666 | if (dev->present) |
| 665 | pi_release(dev->pi); | 667 | pi_release(dev->pi); |
| 666 | } | 668 | } |
| 667 | err = -1; | ||
| 668 | goto out; | 669 | goto out; |
| 669 | } | 670 | } |
| 671 | major = err; /* In case the user specified `major=0' (dynamic) */ | ||
| 670 | pg_class = class_create(THIS_MODULE, "pg"); | 672 | pg_class = class_create(THIS_MODULE, "pg"); |
| 671 | if (IS_ERR(pg_class)) { | 673 | if (IS_ERR(pg_class)) { |
| 672 | err = PTR_ERR(pg_class); | 674 | err = PTR_ERR(pg_class); |
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index 715ae5dc88fb..d2013d362403 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c | |||
| @@ -943,7 +943,8 @@ static ssize_t pt_write(struct file *filp, const char __user *buf, size_t count, | |||
| 943 | 943 | ||
| 944 | static int __init pt_init(void) | 944 | static int __init pt_init(void) |
| 945 | { | 945 | { |
| 946 | int unit, err = 0; | 946 | int unit; |
| 947 | int err; | ||
| 947 | 948 | ||
| 948 | if (disable) { | 949 | if (disable) { |
| 949 | err = -1; | 950 | err = -1; |
| @@ -955,14 +956,15 @@ static int __init pt_init(void) | |||
| 955 | goto out; | 956 | goto out; |
| 956 | } | 957 | } |
| 957 | 958 | ||
| 958 | if (register_chrdev(major, name, &pt_fops)) { | 959 | err = register_chrdev(major, name, &pt_fops); |
| 960 | if (err < 0) { | ||
| 959 | printk("pt_init: unable to get major number %d\n", major); | 961 | printk("pt_init: unable to get major number %d\n", major); |
| 960 | for (unit = 0; unit < PT_UNITS; unit++) | 962 | for (unit = 0; unit < PT_UNITS; unit++) |
| 961 | if (pt[unit].present) | 963 | if (pt[unit].present) |
| 962 | pi_release(pt[unit].pi); | 964 | pi_release(pt[unit].pi); |
| 963 | err = -1; | ||
| 964 | goto out; | 965 | goto out; |
| 965 | } | 966 | } |
| 967 | major = err; | ||
| 966 | pt_class = class_create(THIS_MODULE, "pt"); | 968 | pt_class = class_create(THIS_MODULE, "pt"); |
| 967 | if (IS_ERR(pt_class)) { | 969 | if (IS_ERR(pt_class)) { |
| 968 | err = PTR_ERR(pt_class); | 970 | err = PTR_ERR(pt_class); |
diff --git a/drivers/block/umem.c b/drivers/block/umem.c index c16e66b9c7a7..f7d4c65a7b8c 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | #include <linux/timer.h> | 50 | #include <linux/timer.h> |
| 51 | #include <linux/pci.h> | 51 | #include <linux/pci.h> |
| 52 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
| 53 | #include <linux/dma-mapping.h> | ||
| 53 | 54 | ||
| 54 | #include <linux/fcntl.h> /* O_ACCMODE */ | 55 | #include <linux/fcntl.h> /* O_ACCMODE */ |
| 55 | #include <linux/hdreg.h> /* HDIO_GETGEO */ | 56 | #include <linux/hdreg.h> /* HDIO_GETGEO */ |
| @@ -881,8 +882,8 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
| 881 | printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n", | 882 | printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n", |
| 882 | card->card_number, dev->bus->number, dev->devfn); | 883 | card->card_number, dev->bus->number, dev->devfn); |
| 883 | 884 | ||
| 884 | if (pci_set_dma_mask(dev, 0xffffffffffffffffLL) && | 885 | if (pci_set_dma_mask(dev, DMA_64BIT_MASK) && |
| 885 | pci_set_dma_mask(dev, 0xffffffffLL)) { | 886 | pci_set_dma_mask(dev, DMA_32BIT_MASK)) { |
| 886 | printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards); | 887 | printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards); |
| 887 | return -ENOMEM; | 888 | return -ENOMEM; |
| 888 | } | 889 | } |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index facc3f1d9e37..73d30bf01582 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
| @@ -696,7 +696,7 @@ config NVRAM | |||
| 696 | 696 | ||
| 697 | config RTC | 697 | config RTC |
| 698 | tristate "Enhanced Real Time Clock Support" | 698 | tristate "Enhanced Real Time Clock Support" |
| 699 | depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV | 699 | depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM |
| 700 | ---help--- | 700 | ---help--- |
| 701 | If you say Y here and create a character special file /dev/rtc with | 701 | If you say Y here and create a character special file /dev/rtc with |
| 702 | major number 10 and minor number 135 using mknod ("man mknod"), you | 702 | major number 10 and minor number 135 using mknod ("man mknod"), you |
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 70b8ed9cd172..4c67135c12d8 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/gfp.h> | 11 | #include <linux/gfp.h> |
| 12 | #include <linux/page-flags.h> | 12 | #include <linux/page-flags.h> |
| 13 | #include <linux/mm.h> | 13 | #include <linux/mm.h> |
| 14 | #include <linux/jiffies.h> | ||
| 14 | #include "agp.h" | 15 | #include "agp.h" |
| 15 | 16 | ||
| 16 | /* NVIDIA registers */ | 17 | /* NVIDIA registers */ |
| @@ -256,7 +257,7 @@ static void nvidia_tlbflush(struct agp_memory *mem) | |||
| 256 | do { | 257 | do { |
| 257 | pci_read_config_dword(nvidia_private.dev_1, | 258 | pci_read_config_dword(nvidia_private.dev_1, |
| 258 | NVIDIA_1_WBC, &wbc_reg); | 259 | NVIDIA_1_WBC, &wbc_reg); |
| 259 | if ((signed)(end - jiffies) <= 0) { | 260 | if (time_before_eq(end, jiffies)) { |
| 260 | printk(KERN_ERR PFX | 261 | printk(KERN_ERR PFX |
| 261 | "TLB flush took more than 3 seconds.\n"); | 262 | "TLB flush took more than 3 seconds.\n"); |
| 262 | } | 263 | } |
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 641f7633878c..b7f7951c4587 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c | |||
| @@ -175,7 +175,7 @@ int drm_stub_open(struct inode *inode, struct file *filp) | |||
| 175 | drm_device_t *dev = NULL; | 175 | drm_device_t *dev = NULL; |
| 176 | int minor = iminor(inode); | 176 | int minor = iminor(inode); |
| 177 | int err = -ENODEV; | 177 | int err = -ENODEV; |
| 178 | struct file_operations *old_fops; | 178 | const struct file_operations *old_fops; |
| 179 | 179 | ||
| 180 | DRM_DEBUG("\n"); | 180 | DRM_DEBUG("\n"); |
| 181 | 181 | ||
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index ae0aa6d7e0bb..c658dde3633b 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c | |||
| @@ -126,7 +126,7 @@ static int i810_map_buffer(drm_buf_t * buf, struct file *filp) | |||
| 126 | drm_device_t *dev = priv->head->dev; | 126 | drm_device_t *dev = priv->head->dev; |
| 127 | drm_i810_buf_priv_t *buf_priv = buf->dev_private; | 127 | drm_i810_buf_priv_t *buf_priv = buf->dev_private; |
| 128 | drm_i810_private_t *dev_priv = dev->dev_private; | 128 | drm_i810_private_t *dev_priv = dev->dev_private; |
| 129 | struct file_operations *old_fops; | 129 | const struct file_operations *old_fops; |
| 130 | int retcode = 0; | 130 | int retcode = 0; |
| 131 | 131 | ||
| 132 | if (buf_priv->currently_mapped == I810_BUF_MAPPED) | 132 | if (buf_priv->currently_mapped == I810_BUF_MAPPED) |
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index 163f2cbfe60d..b0f815d8cea8 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c | |||
| @@ -128,7 +128,7 @@ static int i830_map_buffer(drm_buf_t * buf, struct file *filp) | |||
| 128 | drm_device_t *dev = priv->head->dev; | 128 | drm_device_t *dev = priv->head->dev; |
| 129 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; | 129 | drm_i830_buf_priv_t *buf_priv = buf->dev_private; |
| 130 | drm_i830_private_t *dev_priv = dev->dev_private; | 130 | drm_i830_private_t *dev_priv = dev->dev_private; |
| 131 | struct file_operations *old_fops; | 131 | const struct file_operations *old_fops; |
| 132 | unsigned long virtual; | 132 | unsigned long virtual; |
| 133 | int retcode = 0; | 133 | int retcode = 0; |
| 134 | 134 | ||
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index b8fb87c6c29f..40eb005b9d77 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
| @@ -3744,7 +3744,7 @@ static int ipmi_init_msghandler(void) | |||
| 3744 | ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES; | 3744 | ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES; |
| 3745 | add_timer(&ipmi_timer); | 3745 | add_timer(&ipmi_timer); |
| 3746 | 3746 | ||
| 3747 | notifier_chain_register(&panic_notifier_list, &panic_block); | 3747 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); |
| 3748 | 3748 | ||
| 3749 | initialized = 1; | 3749 | initialized = 1; |
| 3750 | 3750 | ||
| @@ -3764,7 +3764,7 @@ static __exit void cleanup_ipmi(void) | |||
| 3764 | if (!initialized) | 3764 | if (!initialized) |
| 3765 | return; | 3765 | return; |
| 3766 | 3766 | ||
| 3767 | notifier_chain_unregister(&panic_notifier_list, &panic_block); | 3767 | atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block); |
| 3768 | 3768 | ||
| 3769 | /* This can't be called if any interfaces exist, so no worry about | 3769 | /* This can't be called if any interfaces exist, so no worry about |
| 3770 | shutting down the interfaces. */ | 3770 | shutting down the interfaces. */ |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 12f858dc9994..35fbd4d8ed4b 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
| @@ -237,10 +237,10 @@ struct smi_info | |||
| 237 | 237 | ||
| 238 | static int try_smi_init(struct smi_info *smi); | 238 | static int try_smi_init(struct smi_info *smi); |
| 239 | 239 | ||
| 240 | static struct notifier_block *xaction_notifier_list; | 240 | static ATOMIC_NOTIFIER_HEAD(xaction_notifier_list); |
| 241 | static int register_xaction_notifier(struct notifier_block * nb) | 241 | static int register_xaction_notifier(struct notifier_block * nb) |
| 242 | { | 242 | { |
| 243 | return notifier_chain_register(&xaction_notifier_list, nb); | 243 | return atomic_notifier_chain_register(&xaction_notifier_list, nb); |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | static void si_restart_short_timer(struct smi_info *smi_info); | 246 | static void si_restart_short_timer(struct smi_info *smi_info); |
| @@ -302,7 +302,8 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) | |||
| 302 | do_gettimeofday(&t); | 302 | do_gettimeofday(&t); |
| 303 | printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec); | 303 | printk("**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec); |
| 304 | #endif | 304 | #endif |
| 305 | err = notifier_call_chain(&xaction_notifier_list, 0, smi_info); | 305 | err = atomic_notifier_call_chain(&xaction_notifier_list, |
| 306 | 0, smi_info); | ||
| 306 | if (err & NOTIFY_STOP_MASK) { | 307 | if (err & NOTIFY_STOP_MASK) { |
| 307 | rv = SI_SM_CALL_WITHOUT_DELAY; | 308 | rv = SI_SM_CALL_WITHOUT_DELAY; |
| 308 | goto out; | 309 | goto out; |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 616539310d9a..7ece9f3c8f70 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
| @@ -1158,7 +1158,8 @@ static int __init ipmi_wdog_init(void) | |||
| 1158 | } | 1158 | } |
| 1159 | 1159 | ||
| 1160 | register_reboot_notifier(&wdog_reboot_notifier); | 1160 | register_reboot_notifier(&wdog_reboot_notifier); |
| 1161 | notifier_chain_register(&panic_notifier_list, &wdog_panic_notifier); | 1161 | atomic_notifier_chain_register(&panic_notifier_list, |
| 1162 | &wdog_panic_notifier); | ||
| 1162 | 1163 | ||
| 1163 | printk(KERN_INFO PFX "driver initialized\n"); | 1164 | printk(KERN_INFO PFX "driver initialized\n"); |
| 1164 | 1165 | ||
| @@ -1176,7 +1177,8 @@ static __exit void ipmi_unregister_watchdog(void) | |||
| 1176 | release_nmi(&ipmi_nmi_handler); | 1177 | release_nmi(&ipmi_nmi_handler); |
| 1177 | #endif | 1178 | #endif |
| 1178 | 1179 | ||
| 1179 | notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier); | 1180 | atomic_notifier_chain_unregister(&panic_notifier_list, |
| 1181 | &wdog_panic_notifier); | ||
| 1180 | unregister_reboot_notifier(&wdog_reboot_notifier); | 1182 | unregister_reboot_notifier(&wdog_reboot_notifier); |
| 1181 | 1183 | ||
| 1182 | if (! watchdog_user) | 1184 | if (! watchdog_user) |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 5245ba1649ed..66719f9d294c 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
| @@ -899,7 +899,7 @@ static const struct { | |||
| 899 | unsigned int minor; | 899 | unsigned int minor; |
| 900 | char *name; | 900 | char *name; |
| 901 | umode_t mode; | 901 | umode_t mode; |
| 902 | struct file_operations *fops; | 902 | const struct file_operations *fops; |
| 903 | } devlist[] = { /* list of minor devices */ | 903 | } devlist[] = { /* list of minor devices */ |
| 904 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, | 904 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, |
| 905 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, | 905 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 3e4c0414a01a..96eb2a709e21 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
| @@ -129,7 +129,7 @@ static int misc_open(struct inode * inode, struct file * file) | |||
| 129 | int minor = iminor(inode); | 129 | int minor = iminor(inode); |
| 130 | struct miscdevice *c; | 130 | struct miscdevice *c; |
| 131 | int err = -ENODEV; | 131 | int err = -ENODEV; |
| 132 | struct file_operations *old_fops, *new_fops = NULL; | 132 | const struct file_operations *old_fops, *new_fops = NULL; |
| 133 | 133 | ||
| 134 | down(&misc_sem); | 134 | down(&misc_sem); |
| 135 | 135 | ||
diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h index e7fd0b08e0b7..7e188a4d602a 100644 --- a/drivers/char/mxser.h +++ b/drivers/char/mxser.h | |||
| @@ -118,7 +118,7 @@ | |||
| 118 | 118 | ||
| 119 | // enable CTS interrupt | 119 | // enable CTS interrupt |
| 120 | #define MOXA_MUST_IER_ECTSI 0x80 | 120 | #define MOXA_MUST_IER_ECTSI 0x80 |
| 121 | // eanble RTS interrupt | 121 | // enable RTS interrupt |
| 122 | #define MOXA_MUST_IER_ERTSI 0x40 | 122 | #define MOXA_MUST_IER_ERTSI 0x40 |
| 123 | // enable Xon/Xoff interrupt | 123 | // enable Xon/Xoff interrupt |
| 124 | #define MOXA_MUST_IER_XINT 0x20 | 124 | #define MOXA_MUST_IER_XINT 0x20 |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index d68be61f0a49..fee2aca3f6a5 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
| @@ -941,17 +941,6 @@ static void* mgsl_get_text_ptr(void) | |||
| 941 | return mgsl_get_text_ptr; | 941 | return mgsl_get_text_ptr; |
| 942 | } | 942 | } |
| 943 | 943 | ||
| 944 | /* | ||
| 945 | * tmp_buf is used as a temporary buffer by mgsl_write. We need to | ||
| 946 | * lock it in case the COPY_FROM_USER blocks while swapping in a page, | ||
| 947 | * and some other program tries to do a serial write at the same time. | ||
| 948 | * Since the lock will only come under contention when the system is | ||
| 949 | * swapping and available memory is low, it makes sense to share one | ||
| 950 | * buffer across all the serial ioports, since it significantly saves | ||
| 951 | * memory if large numbers of serial ports are open. | ||
| 952 | */ | ||
| 953 | static unsigned char *tmp_buf; | ||
| 954 | |||
| 955 | static inline int mgsl_paranoia_check(struct mgsl_struct *info, | 944 | static inline int mgsl_paranoia_check(struct mgsl_struct *info, |
| 956 | char *name, const char *routine) | 945 | char *name, const char *routine) |
| 957 | { | 946 | { |
| @@ -2150,7 +2139,7 @@ static int mgsl_write(struct tty_struct * tty, | |||
| 2150 | if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) | 2139 | if (mgsl_paranoia_check(info, tty->name, "mgsl_write")) |
| 2151 | goto cleanup; | 2140 | goto cleanup; |
| 2152 | 2141 | ||
| 2153 | if (!tty || !info->xmit_buf || !tmp_buf) | 2142 | if (!tty || !info->xmit_buf) |
| 2154 | goto cleanup; | 2143 | goto cleanup; |
| 2155 | 2144 | ||
| 2156 | if ( info->params.mode == MGSL_MODE_HDLC || | 2145 | if ( info->params.mode == MGSL_MODE_HDLC || |
| @@ -3438,7 +3427,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) | |||
| 3438 | { | 3427 | { |
| 3439 | struct mgsl_struct *info; | 3428 | struct mgsl_struct *info; |
| 3440 | int retval, line; | 3429 | int retval, line; |
| 3441 | unsigned long page; | ||
| 3442 | unsigned long flags; | 3430 | unsigned long flags; |
| 3443 | 3431 | ||
| 3444 | /* verify range of specified line number */ | 3432 | /* verify range of specified line number */ |
| @@ -3472,18 +3460,6 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) | |||
| 3472 | goto cleanup; | 3460 | goto cleanup; |
| 3473 | } | 3461 | } |
| 3474 | 3462 | ||
| 3475 | if (!tmp_buf) { | ||
| 3476 | page = get_zeroed_page(GFP_KERNEL); | ||
| 3477 | if (!page) { | ||
| 3478 | retval = -ENOMEM; | ||
| 3479 | goto cleanup; | ||
| 3480 | } | ||
| 3481 | if (tmp_buf) | ||
| 3482 | free_page(page); | ||
| 3483 | else | ||
| 3484 | tmp_buf = (unsigned char *) page; | ||
| 3485 | } | ||
| 3486 | |||
| 3487 | info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 3463 | info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
| 3488 | 3464 | ||
| 3489 | spin_lock_irqsave(&info->netlock, flags); | 3465 | spin_lock_irqsave(&info->netlock, flags); |
| @@ -4502,11 +4478,6 @@ static void synclink_cleanup(void) | |||
| 4502 | kfree(tmp); | 4478 | kfree(tmp); |
| 4503 | } | 4479 | } |
| 4504 | 4480 | ||
| 4505 | if (tmp_buf) { | ||
| 4506 | free_page((unsigned long) tmp_buf); | ||
| 4507 | tmp_buf = NULL; | ||
| 4508 | } | ||
| 4509 | |||
| 4510 | if (pci_registered) | 4481 | if (pci_registered) |
| 4511 | pci_unregister_driver(&synclink_pci_driver); | 4482 | pci_unregister_driver(&synclink_pci_driver); |
| 4512 | } | 4483 | } |
| @@ -6025,7 +5996,7 @@ static void usc_set_async_mode( struct mgsl_struct *info ) | |||
| 6025 | * <15..8> ? RxFIFO IRQ Request Level | 5996 | * <15..8> ? RxFIFO IRQ Request Level |
| 6026 | * | 5997 | * |
| 6027 | * Note: For async mode the receive FIFO level must be set | 5998 | * Note: For async mode the receive FIFO level must be set |
| 6028 | * to 0 to aviod the situation where the FIFO contains fewer bytes | 5999 | * to 0 to avoid the situation where the FIFO contains fewer bytes |
| 6029 | * than the trigger level and no more data is expected. | 6000 | * than the trigger level and no more data is expected. |
| 6030 | * | 6001 | * |
| 6031 | * <7> 0 Exited Hunt IA (Interrupt Arm) | 6002 | * <7> 0 Exited Hunt IA (Interrupt Arm) |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 738ec2f4e563..b4d1f4eea435 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: synclink_gt.c,v 4.22 2006/01/09 20:16:06 paulkf Exp $ | 2 | * $Id: synclink_gt.c,v 4.25 2006/02/06 21:20:33 paulkf Exp $ |
| 3 | * | 3 | * |
| 4 | * Device driver for Microgate SyncLink GT serial adapters. | 4 | * Device driver for Microgate SyncLink GT serial adapters. |
| 5 | * | 5 | * |
| @@ -92,7 +92,7 @@ | |||
| 92 | * module identification | 92 | * module identification |
| 93 | */ | 93 | */ |
| 94 | static char *driver_name = "SyncLink GT"; | 94 | static char *driver_name = "SyncLink GT"; |
| 95 | static char *driver_version = "$Revision: 4.22 $"; | 95 | static char *driver_version = "$Revision: 4.25 $"; |
| 96 | static char *tty_driver_name = "synclink_gt"; | 96 | static char *tty_driver_name = "synclink_gt"; |
| 97 | static char *tty_dev_prefix = "ttySLG"; | 97 | static char *tty_dev_prefix = "ttySLG"; |
| 98 | MODULE_LICENSE("GPL"); | 98 | MODULE_LICENSE("GPL"); |
| @@ -188,6 +188,20 @@ static void hdlcdev_exit(struct slgt_info *info); | |||
| 188 | #define SLGT_REG_SIZE 256 | 188 | #define SLGT_REG_SIZE 256 |
| 189 | 189 | ||
| 190 | /* | 190 | /* |
| 191 | * conditional wait facility | ||
| 192 | */ | ||
| 193 | struct cond_wait { | ||
| 194 | struct cond_wait *next; | ||
| 195 | wait_queue_head_t q; | ||
| 196 | wait_queue_t wait; | ||
| 197 | unsigned int data; | ||
| 198 | }; | ||
| 199 | static void init_cond_wait(struct cond_wait *w, unsigned int data); | ||
| 200 | static void add_cond_wait(struct cond_wait **head, struct cond_wait *w); | ||
| 201 | static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w); | ||
| 202 | static void flush_cond_wait(struct cond_wait **head); | ||
| 203 | |||
| 204 | /* | ||
| 191 | * DMA buffer descriptor and access macros | 205 | * DMA buffer descriptor and access macros |
| 192 | */ | 206 | */ |
| 193 | struct slgt_desc | 207 | struct slgt_desc |
| @@ -269,6 +283,9 @@ struct slgt_info { | |||
| 269 | struct timer_list tx_timer; | 283 | struct timer_list tx_timer; |
| 270 | struct timer_list rx_timer; | 284 | struct timer_list rx_timer; |
| 271 | 285 | ||
| 286 | unsigned int gpio_present; | ||
| 287 | struct cond_wait *gpio_wait_q; | ||
| 288 | |||
| 272 | spinlock_t lock; /* spinlock for synchronizing with ISR */ | 289 | spinlock_t lock; /* spinlock for synchronizing with ISR */ |
| 273 | 290 | ||
| 274 | struct work_struct task; | 291 | struct work_struct task; |
| @@ -379,6 +396,11 @@ static MGSL_PARAMS default_params = { | |||
| 379 | #define MASK_OVERRUN BIT4 | 396 | #define MASK_OVERRUN BIT4 |
| 380 | 397 | ||
| 381 | #define GSR 0x00 /* global status */ | 398 | #define GSR 0x00 /* global status */ |
| 399 | #define JCR 0x04 /* JTAG control */ | ||
| 400 | #define IODR 0x08 /* GPIO direction */ | ||
| 401 | #define IOER 0x0c /* GPIO interrupt enable */ | ||
| 402 | #define IOVR 0x10 /* GPIO value */ | ||
| 403 | #define IOSR 0x14 /* GPIO interrupt status */ | ||
| 382 | #define TDR 0x80 /* tx data */ | 404 | #define TDR 0x80 /* tx data */ |
| 383 | #define RDR 0x80 /* rx data */ | 405 | #define RDR 0x80 /* rx data */ |
| 384 | #define TCR 0x82 /* tx control */ | 406 | #define TCR 0x82 /* tx control */ |
| @@ -503,6 +525,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
| 503 | static void set_break(struct tty_struct *tty, int break_state); | 525 | static void set_break(struct tty_struct *tty, int break_state); |
| 504 | static int get_interface(struct slgt_info *info, int __user *if_mode); | 526 | static int get_interface(struct slgt_info *info, int __user *if_mode); |
| 505 | static int set_interface(struct slgt_info *info, int if_mode); | 527 | static int set_interface(struct slgt_info *info, int if_mode); |
| 528 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | ||
| 529 | static int get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | ||
| 530 | static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | ||
| 506 | 531 | ||
| 507 | /* | 532 | /* |
| 508 | * driver functions | 533 | * driver functions |
| @@ -1112,6 +1137,12 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
| 1112 | return get_interface(info, argp); | 1137 | return get_interface(info, argp); |
| 1113 | case MGSL_IOCSIF: | 1138 | case MGSL_IOCSIF: |
| 1114 | return set_interface(info,(int)arg); | 1139 | return set_interface(info,(int)arg); |
| 1140 | case MGSL_IOCSGPIO: | ||
| 1141 | return set_gpio(info, argp); | ||
| 1142 | case MGSL_IOCGGPIO: | ||
| 1143 | return get_gpio(info, argp); | ||
| 1144 | case MGSL_IOCWAITGPIO: | ||
| 1145 | return wait_gpio(info, argp); | ||
| 1115 | case TIOCGICOUNT: | 1146 | case TIOCGICOUNT: |
| 1116 | spin_lock_irqsave(&info->lock,flags); | 1147 | spin_lock_irqsave(&info->lock,flags); |
| 1117 | cnow = info->icount; | 1148 | cnow = info->icount; |
| @@ -1762,10 +1793,6 @@ static void rx_async(struct slgt_info *info) | |||
| 1762 | DBGDATA(info, p, count, "rx"); | 1793 | DBGDATA(info, p, count, "rx"); |
| 1763 | 1794 | ||
| 1764 | for(i=0 ; i < count; i+=2, p+=2) { | 1795 | for(i=0 ; i < count; i+=2, p+=2) { |
| 1765 | if (tty && chars) { | ||
| 1766 | tty_flip_buffer_push(tty); | ||
| 1767 | chars = 0; | ||
| 1768 | } | ||
| 1769 | ch = *p; | 1796 | ch = *p; |
| 1770 | icount->rx++; | 1797 | icount->rx++; |
| 1771 | 1798 | ||
| @@ -2158,6 +2185,24 @@ static void isr_txeom(struct slgt_info *info, unsigned short status) | |||
| 2158 | } | 2185 | } |
| 2159 | } | 2186 | } |
| 2160 | 2187 | ||
| 2188 | static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int state) | ||
| 2189 | { | ||
| 2190 | struct cond_wait *w, *prev; | ||
| 2191 | |||
| 2192 | /* wake processes waiting for specific transitions */ | ||
| 2193 | for (w = info->gpio_wait_q, prev = NULL ; w != NULL ; w = w->next) { | ||
| 2194 | if (w->data & changed) { | ||
| 2195 | w->data = state; | ||
| 2196 | wake_up_interruptible(&w->q); | ||
| 2197 | if (prev != NULL) | ||
| 2198 | prev->next = w->next; | ||
| 2199 | else | ||
| 2200 | info->gpio_wait_q = w->next; | ||
| 2201 | } else | ||
| 2202 | prev = w; | ||
| 2203 | } | ||
| 2204 | } | ||
| 2205 | |||
| 2161 | /* interrupt service routine | 2206 | /* interrupt service routine |
| 2162 | * | 2207 | * |
| 2163 | * irq interrupt number | 2208 | * irq interrupt number |
| @@ -2193,6 +2238,22 @@ static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
| 2193 | } | 2238 | } |
| 2194 | } | 2239 | } |
| 2195 | 2240 | ||
| 2241 | if (info->gpio_present) { | ||
| 2242 | unsigned int state; | ||
| 2243 | unsigned int changed; | ||
| 2244 | while ((changed = rd_reg32(info, IOSR)) != 0) { | ||
| 2245 | DBGISR(("%s iosr=%08x\n", info->device_name, changed)); | ||
| 2246 | /* read latched state of GPIO signals */ | ||
| 2247 | state = rd_reg32(info, IOVR); | ||
| 2248 | /* clear pending GPIO interrupt bits */ | ||
| 2249 | wr_reg32(info, IOSR, changed); | ||
| 2250 | for (i=0 ; i < info->port_count ; i++) { | ||
| 2251 | if (info->port_array[i] != NULL) | ||
| 2252 | isr_gpio(info->port_array[i], changed, state); | ||
| 2253 | } | ||
| 2254 | } | ||
| 2255 | } | ||
| 2256 | |||
| 2196 | for(i=0; i < info->port_count ; i++) { | 2257 | for(i=0; i < info->port_count ; i++) { |
| 2197 | struct slgt_info *port = info->port_array[i]; | 2258 | struct slgt_info *port = info->port_array[i]; |
| 2198 | 2259 | ||
| @@ -2276,6 +2337,8 @@ static void shutdown(struct slgt_info *info) | |||
| 2276 | set_signals(info); | 2337 | set_signals(info); |
| 2277 | } | 2338 | } |
| 2278 | 2339 | ||
| 2340 | flush_cond_wait(&info->gpio_wait_q); | ||
| 2341 | |||
| 2279 | spin_unlock_irqrestore(&info->lock,flags); | 2342 | spin_unlock_irqrestore(&info->lock,flags); |
| 2280 | 2343 | ||
| 2281 | if (info->tty) | 2344 | if (info->tty) |
| @@ -2650,6 +2713,175 @@ static int set_interface(struct slgt_info *info, int if_mode) | |||
| 2650 | return 0; | 2713 | return 0; |
| 2651 | } | 2714 | } |
| 2652 | 2715 | ||
| 2716 | /* | ||
| 2717 | * set general purpose IO pin state and direction | ||
| 2718 | * | ||
| 2719 | * user_gpio fields: | ||
| 2720 | * state each bit indicates a pin state | ||
| 2721 | * smask set bit indicates pin state to set | ||
| 2722 | * dir each bit indicates a pin direction (0=input, 1=output) | ||
| 2723 | * dmask set bit indicates pin direction to set | ||
| 2724 | */ | ||
| 2725 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | ||
| 2726 | { | ||
| 2727 | unsigned long flags; | ||
| 2728 | struct gpio_desc gpio; | ||
| 2729 | __u32 data; | ||
| 2730 | |||
| 2731 | if (!info->gpio_present) | ||
| 2732 | return -EINVAL; | ||
| 2733 | if (copy_from_user(&gpio, user_gpio, sizeof(gpio))) | ||
| 2734 | return -EFAULT; | ||
| 2735 | DBGINFO(("%s set_gpio state=%08x smask=%08x dir=%08x dmask=%08x\n", | ||
| 2736 | info->device_name, gpio.state, gpio.smask, | ||
| 2737 | gpio.dir, gpio.dmask)); | ||
| 2738 | |||
| 2739 | spin_lock_irqsave(&info->lock,flags); | ||
| 2740 | if (gpio.dmask) { | ||
| 2741 | data = rd_reg32(info, IODR); | ||
| 2742 | data |= gpio.dmask & gpio.dir; | ||
| 2743 | data &= ~(gpio.dmask & ~gpio.dir); | ||
| 2744 | wr_reg32(info, IODR, data); | ||
| 2745 | } | ||
| 2746 | if (gpio.smask) { | ||
| 2747 | data = rd_reg32(info, IOVR); | ||
| 2748 | data |= gpio.smask & gpio.state; | ||
| 2749 | data &= ~(gpio.smask & ~gpio.state); | ||
| 2750 | wr_reg32(info, IOVR, data); | ||
| 2751 | } | ||
| 2752 | spin_unlock_irqrestore(&info->lock,flags); | ||
| 2753 | |||
| 2754 | return 0; | ||
| 2755 | } | ||
| 2756 | |||
| 2757 | /* | ||
| 2758 | * get general purpose IO pin state and direction | ||
| 2759 | */ | ||
| 2760 | static int get_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | ||
| 2761 | { | ||
| 2762 | struct gpio_desc gpio; | ||
| 2763 | if (!info->gpio_present) | ||
| 2764 | return -EINVAL; | ||
| 2765 | gpio.state = rd_reg32(info, IOVR); | ||
| 2766 | gpio.smask = 0xffffffff; | ||
| 2767 | gpio.dir = rd_reg32(info, IODR); | ||
| 2768 | gpio.dmask = 0xffffffff; | ||
| 2769 | if (copy_to_user(user_gpio, &gpio, sizeof(gpio))) | ||
| 2770 | return -EFAULT; | ||
| 2771 | DBGINFO(("%s get_gpio state=%08x dir=%08x\n", | ||
| 2772 | info->device_name, gpio.state, gpio.dir)); | ||
| 2773 | return 0; | ||
| 2774 | } | ||
| 2775 | |||
| 2776 | /* | ||
| 2777 | * conditional wait facility | ||
| 2778 | */ | ||
| 2779 | static void init_cond_wait(struct cond_wait *w, unsigned int data) | ||
| 2780 | { | ||
| 2781 | init_waitqueue_head(&w->q); | ||
| 2782 | init_waitqueue_entry(&w->wait, current); | ||
| 2783 | w->data = data; | ||
| 2784 | } | ||
| 2785 | |||
| 2786 | static void add_cond_wait(struct cond_wait **head, struct cond_wait *w) | ||
| 2787 | { | ||
| 2788 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 2789 | add_wait_queue(&w->q, &w->wait); | ||
| 2790 | w->next = *head; | ||
| 2791 | *head = w; | ||
| 2792 | } | ||
| 2793 | |||
| 2794 | static void remove_cond_wait(struct cond_wait **head, struct cond_wait *cw) | ||
| 2795 | { | ||
| 2796 | struct cond_wait *w, *prev; | ||
| 2797 | remove_wait_queue(&cw->q, &cw->wait); | ||
| 2798 | set_current_state(TASK_RUNNING); | ||
| 2799 | for (w = *head, prev = NULL ; w != NULL ; prev = w, w = w->next) { | ||
| 2800 | if (w == cw) { | ||
| 2801 | if (prev != NULL) | ||
| 2802 | prev->next = w->next; | ||
| 2803 | else | ||
| 2804 | *head = w->next; | ||
| 2805 | break; | ||
| 2806 | } | ||
| 2807 | } | ||
| 2808 | } | ||
| 2809 | |||
| 2810 | static void flush_cond_wait(struct cond_wait **head) | ||
| 2811 | { | ||
| 2812 | while (*head != NULL) { | ||
| 2813 | wake_up_interruptible(&(*head)->q); | ||
| 2814 | *head = (*head)->next; | ||
| 2815 | } | ||
| 2816 | } | ||
| 2817 | |||
| 2818 | /* | ||
| 2819 | * wait for general purpose I/O pin(s) to enter specified state | ||
| 2820 | * | ||
| 2821 | * user_gpio fields: | ||
| 2822 | * state - bit indicates target pin state | ||
| 2823 | * smask - set bit indicates watched pin | ||
| 2824 | * | ||
| 2825 | * The wait ends when at least one watched pin enters the specified | ||
| 2826 | * state. When 0 (no error) is returned, user_gpio->state is set to the | ||
| 2827 | * state of all GPIO pins when the wait ends. | ||
| 2828 | * | ||
| 2829 | * Note: Each pin may be a dedicated input, dedicated output, or | ||
| 2830 | * configurable input/output. The number and configuration of pins | ||
| 2831 | * varies with the specific adapter model. Only input pins (dedicated | ||
| 2832 | * or configured) can be monitored with this function. | ||
| 2833 | */ | ||
| 2834 | static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio) | ||
| 2835 | { | ||
| 2836 | unsigned long flags; | ||
| 2837 | int rc = 0; | ||
| 2838 | struct gpio_desc gpio; | ||
| 2839 | struct cond_wait wait; | ||
| 2840 | u32 state; | ||
| 2841 | |||
| 2842 | if (!info->gpio_present) | ||
| 2843 | return -EINVAL; | ||
| 2844 | if (copy_from_user(&gpio, user_gpio, sizeof(gpio))) | ||
| 2845 | return -EFAULT; | ||
| 2846 | DBGINFO(("%s wait_gpio() state=%08x smask=%08x\n", | ||
| 2847 | info->device_name, gpio.state, gpio.smask)); | ||
| 2848 | /* ignore output pins identified by set IODR bit */ | ||
| 2849 | if ((gpio.smask &= ~rd_reg32(info, IODR)) == 0) | ||
| 2850 | return -EINVAL; | ||
| 2851 | init_cond_wait(&wait, gpio.smask); | ||
| 2852 | |||
| 2853 | spin_lock_irqsave(&info->lock, flags); | ||
| 2854 | /* enable interrupts for watched pins */ | ||
| 2855 | wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask); | ||
| 2856 | /* get current pin states */ | ||
| 2857 | state = rd_reg32(info, IOVR); | ||
| 2858 | |||
| 2859 | if (gpio.smask & ~(state ^ gpio.state)) { | ||
| 2860 | /* already in target state */ | ||
| 2861 | gpio.state = state; | ||
| 2862 | } else { | ||
| 2863 | /* wait for target state */ | ||
| 2864 | add_cond_wait(&info->gpio_wait_q, &wait); | ||
| 2865 | spin_unlock_irqrestore(&info->lock, flags); | ||
| 2866 | schedule(); | ||
| 2867 | if (signal_pending(current)) | ||
| 2868 | rc = -ERESTARTSYS; | ||
| 2869 | else | ||
| 2870 | gpio.state = wait.data; | ||
| 2871 | spin_lock_irqsave(&info->lock, flags); | ||
| 2872 | remove_cond_wait(&info->gpio_wait_q, &wait); | ||
| 2873 | } | ||
| 2874 | |||
| 2875 | /* disable all GPIO interrupts if no waiting processes */ | ||
| 2876 | if (info->gpio_wait_q == NULL) | ||
| 2877 | wr_reg32(info, IOER, 0); | ||
| 2878 | spin_unlock_irqrestore(&info->lock,flags); | ||
| 2879 | |||
| 2880 | if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio))) | ||
| 2881 | rc = -EFAULT; | ||
| 2882 | return rc; | ||
| 2883 | } | ||
| 2884 | |||
| 2653 | static int modem_input_wait(struct slgt_info *info,int arg) | 2885 | static int modem_input_wait(struct slgt_info *info,int arg) |
| 2654 | { | 2886 | { |
| 2655 | unsigned long flags; | 2887 | unsigned long flags; |
| @@ -3166,8 +3398,10 @@ static void device_init(int adapter_num, struct pci_dev *pdev) | |||
| 3166 | } else { | 3398 | } else { |
| 3167 | port_array[0]->irq_requested = 1; | 3399 | port_array[0]->irq_requested = 1; |
| 3168 | adapter_test(port_array[0]); | 3400 | adapter_test(port_array[0]); |
| 3169 | for (i=1 ; i < port_count ; i++) | 3401 | for (i=1 ; i < port_count ; i++) { |
| 3170 | port_array[i]->init_error = port_array[0]->init_error; | 3402 | port_array[i]->init_error = port_array[0]->init_error; |
| 3403 | port_array[i]->gpio_present = port_array[0]->gpio_present; | ||
| 3404 | } | ||
| 3171 | } | 3405 | } |
| 3172 | } | 3406 | } |
| 3173 | } | 3407 | } |
| @@ -4301,7 +4535,7 @@ static int register_test(struct slgt_info *info) | |||
| 4301 | break; | 4535 | break; |
| 4302 | } | 4536 | } |
| 4303 | } | 4537 | } |
| 4304 | 4538 | info->gpio_present = (rd_reg32(info, JCR) & BIT5) ? 1 : 0; | |
| 4305 | info->init_error = rc ? 0 : DiagStatus_AddressFailure; | 4539 | info->init_error = rc ? 0 : DiagStatus_AddressFailure; |
| 4306 | return rc; | 4540 | return rc; |
| 4307 | } | 4541 | } |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index aed80e6aec6d..9b6ae7dc8b8a 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -52,9 +52,8 @@ static void handle_update(void *data); | |||
| 52 | * changes to devices when the CPU clock speed changes. | 52 | * changes to devices when the CPU clock speed changes. |
| 53 | * The mutex locks both lists. | 53 | * The mutex locks both lists. |
| 54 | */ | 54 | */ |
| 55 | static struct notifier_block *cpufreq_policy_notifier_list; | 55 | static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list); |
| 56 | static struct notifier_block *cpufreq_transition_notifier_list; | 56 | static BLOCKING_NOTIFIER_HEAD(cpufreq_transition_notifier_list); |
| 57 | static DECLARE_RWSEM (cpufreq_notifier_rwsem); | ||
| 58 | 57 | ||
| 59 | 58 | ||
| 60 | static LIST_HEAD(cpufreq_governor_list); | 59 | static LIST_HEAD(cpufreq_governor_list); |
| @@ -247,8 +246,6 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) | |||
| 247 | dprintk("notification %u of frequency transition to %u kHz\n", | 246 | dprintk("notification %u of frequency transition to %u kHz\n", |
| 248 | state, freqs->new); | 247 | state, freqs->new); |
| 249 | 248 | ||
| 250 | down_read(&cpufreq_notifier_rwsem); | ||
| 251 | |||
| 252 | policy = cpufreq_cpu_data[freqs->cpu]; | 249 | policy = cpufreq_cpu_data[freqs->cpu]; |
| 253 | switch (state) { | 250 | switch (state) { |
| 254 | 251 | ||
| @@ -266,20 +263,19 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state) | |||
| 266 | freqs->old = policy->cur; | 263 | freqs->old = policy->cur; |
| 267 | } | 264 | } |
| 268 | } | 265 | } |
| 269 | notifier_call_chain(&cpufreq_transition_notifier_list, | 266 | blocking_notifier_call_chain(&cpufreq_transition_notifier_list, |
| 270 | CPUFREQ_PRECHANGE, freqs); | 267 | CPUFREQ_PRECHANGE, freqs); |
| 271 | adjust_jiffies(CPUFREQ_PRECHANGE, freqs); | 268 | adjust_jiffies(CPUFREQ_PRECHANGE, freqs); |
| 272 | break; | 269 | break; |
| 273 | 270 | ||
| 274 | case CPUFREQ_POSTCHANGE: | 271 | case CPUFREQ_POSTCHANGE: |
| 275 | adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); | 272 | adjust_jiffies(CPUFREQ_POSTCHANGE, freqs); |
| 276 | notifier_call_chain(&cpufreq_transition_notifier_list, | 273 | blocking_notifier_call_chain(&cpufreq_transition_notifier_list, |
| 277 | CPUFREQ_POSTCHANGE, freqs); | 274 | CPUFREQ_POSTCHANGE, freqs); |
| 278 | if (likely(policy) && likely(policy->cpu == freqs->cpu)) | 275 | if (likely(policy) && likely(policy->cpu == freqs->cpu)) |
| 279 | policy->cur = freqs->new; | 276 | policy->cur = freqs->new; |
| 280 | break; | 277 | break; |
| 281 | } | 278 | } |
| 282 | up_read(&cpufreq_notifier_rwsem); | ||
| 283 | } | 279 | } |
| 284 | EXPORT_SYMBOL_GPL(cpufreq_notify_transition); | 280 | EXPORT_SYMBOL_GPL(cpufreq_notify_transition); |
| 285 | 281 | ||
| @@ -1007,7 +1003,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) | |||
| 1007 | freqs.old = cpu_policy->cur; | 1003 | freqs.old = cpu_policy->cur; |
| 1008 | freqs.new = cur_freq; | 1004 | freqs.new = cur_freq; |
| 1009 | 1005 | ||
| 1010 | notifier_call_chain(&cpufreq_transition_notifier_list, | 1006 | blocking_notifier_call_chain(&cpufreq_transition_notifier_list, |
| 1011 | CPUFREQ_SUSPENDCHANGE, &freqs); | 1007 | CPUFREQ_SUSPENDCHANGE, &freqs); |
| 1012 | adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs); | 1008 | adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs); |
| 1013 | 1009 | ||
| @@ -1088,7 +1084,8 @@ static int cpufreq_resume(struct sys_device * sysdev) | |||
| 1088 | freqs.old = cpu_policy->cur; | 1084 | freqs.old = cpu_policy->cur; |
| 1089 | freqs.new = cur_freq; | 1085 | freqs.new = cur_freq; |
| 1090 | 1086 | ||
| 1091 | notifier_call_chain(&cpufreq_transition_notifier_list, | 1087 | blocking_notifier_call_chain( |
| 1088 | &cpufreq_transition_notifier_list, | ||
| 1092 | CPUFREQ_RESUMECHANGE, &freqs); | 1089 | CPUFREQ_RESUMECHANGE, &freqs); |
| 1093 | adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); | 1090 | adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); |
| 1094 | 1091 | ||
| @@ -1125,24 +1122,24 @@ static struct sysdev_driver cpufreq_sysdev_driver = { | |||
| 1125 | * changes in cpufreq policy. | 1122 | * changes in cpufreq policy. |
| 1126 | * | 1123 | * |
| 1127 | * This function may sleep, and has the same return conditions as | 1124 | * This function may sleep, and has the same return conditions as |
| 1128 | * notifier_chain_register. | 1125 | * blocking_notifier_chain_register. |
| 1129 | */ | 1126 | */ |
| 1130 | int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) | 1127 | int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) |
| 1131 | { | 1128 | { |
| 1132 | int ret; | 1129 | int ret; |
| 1133 | 1130 | ||
| 1134 | down_write(&cpufreq_notifier_rwsem); | ||
| 1135 | switch (list) { | 1131 | switch (list) { |
| 1136 | case CPUFREQ_TRANSITION_NOTIFIER: | 1132 | case CPUFREQ_TRANSITION_NOTIFIER: |
| 1137 | ret = notifier_chain_register(&cpufreq_transition_notifier_list, nb); | 1133 | ret = blocking_notifier_chain_register( |
| 1134 | &cpufreq_transition_notifier_list, nb); | ||
| 1138 | break; | 1135 | break; |
| 1139 | case CPUFREQ_POLICY_NOTIFIER: | 1136 | case CPUFREQ_POLICY_NOTIFIER: |
| 1140 | ret = notifier_chain_register(&cpufreq_policy_notifier_list, nb); | 1137 | ret = blocking_notifier_chain_register( |
| 1138 | &cpufreq_policy_notifier_list, nb); | ||
| 1141 | break; | 1139 | break; |
| 1142 | default: | 1140 | default: |
| 1143 | ret = -EINVAL; | 1141 | ret = -EINVAL; |
| 1144 | } | 1142 | } |
| 1145 | up_write(&cpufreq_notifier_rwsem); | ||
| 1146 | 1143 | ||
| 1147 | return ret; | 1144 | return ret; |
| 1148 | } | 1145 | } |
| @@ -1157,24 +1154,24 @@ EXPORT_SYMBOL(cpufreq_register_notifier); | |||
| 1157 | * Remove a driver from the CPU frequency notifier list. | 1154 | * Remove a driver from the CPU frequency notifier list. |
| 1158 | * | 1155 | * |
| 1159 | * This function may sleep, and has the same return conditions as | 1156 | * This function may sleep, and has the same return conditions as |
| 1160 | * notifier_chain_unregister. | 1157 | * blocking_notifier_chain_unregister. |
| 1161 | */ | 1158 | */ |
| 1162 | int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) | 1159 | int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list) |
| 1163 | { | 1160 | { |
| 1164 | int ret; | 1161 | int ret; |
| 1165 | 1162 | ||
| 1166 | down_write(&cpufreq_notifier_rwsem); | ||
| 1167 | switch (list) { | 1163 | switch (list) { |
| 1168 | case CPUFREQ_TRANSITION_NOTIFIER: | 1164 | case CPUFREQ_TRANSITION_NOTIFIER: |
| 1169 | ret = notifier_chain_unregister(&cpufreq_transition_notifier_list, nb); | 1165 | ret = blocking_notifier_chain_unregister( |
| 1166 | &cpufreq_transition_notifier_list, nb); | ||
| 1170 | break; | 1167 | break; |
| 1171 | case CPUFREQ_POLICY_NOTIFIER: | 1168 | case CPUFREQ_POLICY_NOTIFIER: |
| 1172 | ret = notifier_chain_unregister(&cpufreq_policy_notifier_list, nb); | 1169 | ret = blocking_notifier_chain_unregister( |
| 1170 | &cpufreq_policy_notifier_list, nb); | ||
| 1173 | break; | 1171 | break; |
| 1174 | default: | 1172 | default: |
| 1175 | ret = -EINVAL; | 1173 | ret = -EINVAL; |
| 1176 | } | 1174 | } |
| 1177 | up_write(&cpufreq_notifier_rwsem); | ||
| 1178 | 1175 | ||
| 1179 | return ret; | 1176 | return ret; |
| 1180 | } | 1177 | } |
| @@ -1346,29 +1343,23 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli | |||
| 1346 | if (ret) | 1343 | if (ret) |
| 1347 | goto error_out; | 1344 | goto error_out; |
| 1348 | 1345 | ||
| 1349 | down_read(&cpufreq_notifier_rwsem); | ||
| 1350 | |||
| 1351 | /* adjust if necessary - all reasons */ | 1346 | /* adjust if necessary - all reasons */ |
| 1352 | notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_ADJUST, | 1347 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
| 1353 | policy); | 1348 | CPUFREQ_ADJUST, policy); |
| 1354 | 1349 | ||
| 1355 | /* adjust if necessary - hardware incompatibility*/ | 1350 | /* adjust if necessary - hardware incompatibility*/ |
| 1356 | notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_INCOMPATIBLE, | 1351 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
| 1357 | policy); | 1352 | CPUFREQ_INCOMPATIBLE, policy); |
| 1358 | 1353 | ||
| 1359 | /* verify the cpu speed can be set within this limit, | 1354 | /* verify the cpu speed can be set within this limit, |
| 1360 | which might be different to the first one */ | 1355 | which might be different to the first one */ |
| 1361 | ret = cpufreq_driver->verify(policy); | 1356 | ret = cpufreq_driver->verify(policy); |
| 1362 | if (ret) { | 1357 | if (ret) |
| 1363 | up_read(&cpufreq_notifier_rwsem); | ||
| 1364 | goto error_out; | 1358 | goto error_out; |
| 1365 | } | ||
| 1366 | 1359 | ||
| 1367 | /* notification of the new policy */ | 1360 | /* notification of the new policy */ |
| 1368 | notifier_call_chain(&cpufreq_policy_notifier_list, CPUFREQ_NOTIFY, | 1361 | blocking_notifier_call_chain(&cpufreq_policy_notifier_list, |
| 1369 | policy); | 1362 | CPUFREQ_NOTIFY, policy); |
| 1370 | |||
| 1371 | up_read(&cpufreq_notifier_rwsem); | ||
| 1372 | 1363 | ||
| 1373 | data->min = policy->min; | 1364 | data->min = policy->min; |
| 1374 | data->max = policy->max; | 1365 | data->max = policy->max; |
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index ac38766b2583..037f6bf4543c 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c | |||
| @@ -35,12 +35,7 @@ | |||
| 35 | */ | 35 | */ |
| 36 | 36 | ||
| 37 | #define DEF_FREQUENCY_UP_THRESHOLD (80) | 37 | #define DEF_FREQUENCY_UP_THRESHOLD (80) |
| 38 | #define MIN_FREQUENCY_UP_THRESHOLD (0) | ||
| 39 | #define MAX_FREQUENCY_UP_THRESHOLD (100) | ||
| 40 | |||
| 41 | #define DEF_FREQUENCY_DOWN_THRESHOLD (20) | 38 | #define DEF_FREQUENCY_DOWN_THRESHOLD (20) |
| 42 | #define MIN_FREQUENCY_DOWN_THRESHOLD (0) | ||
| 43 | #define MAX_FREQUENCY_DOWN_THRESHOLD (100) | ||
| 44 | 39 | ||
| 45 | /* | 40 | /* |
| 46 | * The polling frequency of this governor depends on the capability of | 41 | * The polling frequency of this governor depends on the capability of |
| @@ -53,10 +48,14 @@ | |||
| 53 | * All times here are in uS. | 48 | * All times here are in uS. |
| 54 | */ | 49 | */ |
| 55 | static unsigned int def_sampling_rate; | 50 | static unsigned int def_sampling_rate; |
| 56 | #define MIN_SAMPLING_RATE (def_sampling_rate / 2) | 51 | #define MIN_SAMPLING_RATE_RATIO (2) |
| 52 | /* for correct statistics, we need at least 10 ticks between each measure */ | ||
| 53 | #define MIN_STAT_SAMPLING_RATE (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) | ||
| 54 | #define MIN_SAMPLING_RATE (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) | ||
| 57 | #define MAX_SAMPLING_RATE (500 * def_sampling_rate) | 55 | #define MAX_SAMPLING_RATE (500 * def_sampling_rate) |
| 58 | #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (100000) | 56 | #define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) |
| 59 | #define DEF_SAMPLING_DOWN_FACTOR (5) | 57 | #define DEF_SAMPLING_DOWN_FACTOR (1) |
| 58 | #define MAX_SAMPLING_DOWN_FACTOR (10) | ||
| 60 | #define TRANSITION_LATENCY_LIMIT (10 * 1000) | 59 | #define TRANSITION_LATENCY_LIMIT (10 * 1000) |
| 61 | 60 | ||
| 62 | static void do_dbs_timer(void *data); | 61 | static void do_dbs_timer(void *data); |
| @@ -66,6 +65,8 @@ struct cpu_dbs_info_s { | |||
| 66 | unsigned int prev_cpu_idle_up; | 65 | unsigned int prev_cpu_idle_up; |
| 67 | unsigned int prev_cpu_idle_down; | 66 | unsigned int prev_cpu_idle_down; |
| 68 | unsigned int enable; | 67 | unsigned int enable; |
| 68 | unsigned int down_skip; | ||
| 69 | unsigned int requested_freq; | ||
| 69 | }; | 70 | }; |
| 70 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); | 71 | static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); |
| 71 | 72 | ||
| @@ -87,6 +88,8 @@ static struct dbs_tuners dbs_tuners_ins = { | |||
| 87 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, | 88 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, |
| 88 | .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, | 89 | .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, |
| 89 | .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, | 90 | .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, |
| 91 | .ignore_nice = 0, | ||
| 92 | .freq_step = 5, | ||
| 90 | }; | 93 | }; |
| 91 | 94 | ||
| 92 | static inline unsigned int get_cpu_idle_time(unsigned int cpu) | 95 | static inline unsigned int get_cpu_idle_time(unsigned int cpu) |
| @@ -136,7 +139,7 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, | |||
| 136 | unsigned int input; | 139 | unsigned int input; |
| 137 | int ret; | 140 | int ret; |
| 138 | ret = sscanf (buf, "%u", &input); | 141 | ret = sscanf (buf, "%u", &input); |
| 139 | if (ret != 1 ) | 142 | if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) |
| 140 | return -EINVAL; | 143 | return -EINVAL; |
| 141 | 144 | ||
| 142 | mutex_lock(&dbs_mutex); | 145 | mutex_lock(&dbs_mutex); |
| @@ -173,8 +176,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, | |||
| 173 | ret = sscanf (buf, "%u", &input); | 176 | ret = sscanf (buf, "%u", &input); |
| 174 | 177 | ||
| 175 | mutex_lock(&dbs_mutex); | 178 | mutex_lock(&dbs_mutex); |
| 176 | if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || | 179 | if (ret != 1 || input > 100 || input < 0 || |
| 177 | input < MIN_FREQUENCY_UP_THRESHOLD || | ||
| 178 | input <= dbs_tuners_ins.down_threshold) { | 180 | input <= dbs_tuners_ins.down_threshold) { |
| 179 | mutex_unlock(&dbs_mutex); | 181 | mutex_unlock(&dbs_mutex); |
| 180 | return -EINVAL; | 182 | return -EINVAL; |
| @@ -194,8 +196,7 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused, | |||
| 194 | ret = sscanf (buf, "%u", &input); | 196 | ret = sscanf (buf, "%u", &input); |
| 195 | 197 | ||
| 196 | mutex_lock(&dbs_mutex); | 198 | mutex_lock(&dbs_mutex); |
| 197 | if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD || | 199 | if (ret != 1 || input > 100 || input < 0 || |
| 198 | input < MIN_FREQUENCY_DOWN_THRESHOLD || | ||
| 199 | input >= dbs_tuners_ins.up_threshold) { | 200 | input >= dbs_tuners_ins.up_threshold) { |
| 200 | mutex_unlock(&dbs_mutex); | 201 | mutex_unlock(&dbs_mutex); |
| 201 | return -EINVAL; | 202 | return -EINVAL; |
| @@ -297,31 +298,17 @@ static struct attribute_group dbs_attr_group = { | |||
| 297 | static void dbs_check_cpu(int cpu) | 298 | static void dbs_check_cpu(int cpu) |
| 298 | { | 299 | { |
| 299 | unsigned int idle_ticks, up_idle_ticks, down_idle_ticks; | 300 | unsigned int idle_ticks, up_idle_ticks, down_idle_ticks; |
| 301 | unsigned int tmp_idle_ticks, total_idle_ticks; | ||
| 300 | unsigned int freq_step; | 302 | unsigned int freq_step; |
| 301 | unsigned int freq_down_sampling_rate; | 303 | unsigned int freq_down_sampling_rate; |
| 302 | static int down_skip[NR_CPUS]; | 304 | struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info, cpu); |
| 303 | static int requested_freq[NR_CPUS]; | ||
| 304 | static unsigned short init_flag = 0; | ||
| 305 | struct cpu_dbs_info_s *this_dbs_info; | ||
| 306 | struct cpu_dbs_info_s *dbs_info; | ||
| 307 | |||
| 308 | struct cpufreq_policy *policy; | 305 | struct cpufreq_policy *policy; |
| 309 | unsigned int j; | ||
| 310 | 306 | ||
| 311 | this_dbs_info = &per_cpu(cpu_dbs_info, cpu); | ||
| 312 | if (!this_dbs_info->enable) | 307 | if (!this_dbs_info->enable) |
| 313 | return; | 308 | return; |
| 314 | 309 | ||
| 315 | policy = this_dbs_info->cur_policy; | 310 | policy = this_dbs_info->cur_policy; |
| 316 | 311 | ||
| 317 | if ( init_flag == 0 ) { | ||
| 318 | for_each_online_cpu(j) { | ||
| 319 | dbs_info = &per_cpu(cpu_dbs_info, j); | ||
| 320 | requested_freq[j] = dbs_info->cur_policy->cur; | ||
| 321 | } | ||
| 322 | init_flag = 1; | ||
| 323 | } | ||
| 324 | |||
| 325 | /* | 312 | /* |
| 326 | * The default safe range is 20% to 80% | 313 | * The default safe range is 20% to 80% |
| 327 | * Every sampling_rate, we check | 314 | * Every sampling_rate, we check |
| @@ -337,39 +324,29 @@ static void dbs_check_cpu(int cpu) | |||
| 337 | */ | 324 | */ |
| 338 | 325 | ||
| 339 | /* Check for frequency increase */ | 326 | /* Check for frequency increase */ |
| 340 | |||
| 341 | idle_ticks = UINT_MAX; | 327 | idle_ticks = UINT_MAX; |
| 342 | for_each_cpu_mask(j, policy->cpus) { | ||
| 343 | unsigned int tmp_idle_ticks, total_idle_ticks; | ||
| 344 | struct cpu_dbs_info_s *j_dbs_info; | ||
| 345 | 328 | ||
| 346 | j_dbs_info = &per_cpu(cpu_dbs_info, j); | 329 | /* Check for frequency increase */ |
| 347 | /* Check for frequency increase */ | 330 | total_idle_ticks = get_cpu_idle_time(cpu); |
| 348 | total_idle_ticks = get_cpu_idle_time(j); | 331 | tmp_idle_ticks = total_idle_ticks - |
| 349 | tmp_idle_ticks = total_idle_ticks - | 332 | this_dbs_info->prev_cpu_idle_up; |
| 350 | j_dbs_info->prev_cpu_idle_up; | 333 | this_dbs_info->prev_cpu_idle_up = total_idle_ticks; |
| 351 | j_dbs_info->prev_cpu_idle_up = total_idle_ticks; | 334 | |
| 352 | 335 | if (tmp_idle_ticks < idle_ticks) | |
| 353 | if (tmp_idle_ticks < idle_ticks) | 336 | idle_ticks = tmp_idle_ticks; |
| 354 | idle_ticks = tmp_idle_ticks; | ||
| 355 | } | ||
| 356 | 337 | ||
| 357 | /* Scale idle ticks by 100 and compare with up and down ticks */ | 338 | /* Scale idle ticks by 100 and compare with up and down ticks */ |
| 358 | idle_ticks *= 100; | 339 | idle_ticks *= 100; |
| 359 | up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) * | 340 | up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) * |
| 360 | usecs_to_jiffies(dbs_tuners_ins.sampling_rate); | 341 | usecs_to_jiffies(dbs_tuners_ins.sampling_rate); |
| 361 | 342 | ||
| 362 | if (idle_ticks < up_idle_ticks) { | 343 | if (idle_ticks < up_idle_ticks) { |
| 363 | down_skip[cpu] = 0; | 344 | this_dbs_info->down_skip = 0; |
| 364 | for_each_cpu_mask(j, policy->cpus) { | 345 | this_dbs_info->prev_cpu_idle_down = |
| 365 | struct cpu_dbs_info_s *j_dbs_info; | 346 | this_dbs_info->prev_cpu_idle_up; |
| 366 | 347 | ||
| 367 | j_dbs_info = &per_cpu(cpu_dbs_info, j); | ||
| 368 | j_dbs_info->prev_cpu_idle_down = | ||
| 369 | j_dbs_info->prev_cpu_idle_up; | ||
| 370 | } | ||
| 371 | /* if we are already at full speed then break out early */ | 348 | /* if we are already at full speed then break out early */ |
| 372 | if (requested_freq[cpu] == policy->max) | 349 | if (this_dbs_info->requested_freq == policy->max) |
| 373 | return; | 350 | return; |
| 374 | 351 | ||
| 375 | freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100; | 352 | freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100; |
| @@ -378,49 +355,45 @@ static void dbs_check_cpu(int cpu) | |||
| 378 | if (unlikely(freq_step == 0)) | 355 | if (unlikely(freq_step == 0)) |
| 379 | freq_step = 5; | 356 | freq_step = 5; |
| 380 | 357 | ||
| 381 | requested_freq[cpu] += freq_step; | 358 | this_dbs_info->requested_freq += freq_step; |
| 382 | if (requested_freq[cpu] > policy->max) | 359 | if (this_dbs_info->requested_freq > policy->max) |
| 383 | requested_freq[cpu] = policy->max; | 360 | this_dbs_info->requested_freq = policy->max; |
| 384 | 361 | ||
| 385 | __cpufreq_driver_target(policy, requested_freq[cpu], | 362 | __cpufreq_driver_target(policy, this_dbs_info->requested_freq, |
| 386 | CPUFREQ_RELATION_H); | 363 | CPUFREQ_RELATION_H); |
| 387 | return; | 364 | return; |
| 388 | } | 365 | } |
| 389 | 366 | ||
| 390 | /* Check for frequency decrease */ | 367 | /* Check for frequency decrease */ |
| 391 | down_skip[cpu]++; | 368 | this_dbs_info->down_skip++; |
| 392 | if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor) | 369 | if (this_dbs_info->down_skip < dbs_tuners_ins.sampling_down_factor) |
| 393 | return; | 370 | return; |
| 394 | 371 | ||
| 395 | idle_ticks = UINT_MAX; | 372 | /* Check for frequency decrease */ |
| 396 | for_each_cpu_mask(j, policy->cpus) { | 373 | total_idle_ticks = this_dbs_info->prev_cpu_idle_up; |
| 397 | unsigned int tmp_idle_ticks, total_idle_ticks; | 374 | tmp_idle_ticks = total_idle_ticks - |
| 398 | struct cpu_dbs_info_s *j_dbs_info; | 375 | this_dbs_info->prev_cpu_idle_down; |
| 376 | this_dbs_info->prev_cpu_idle_down = total_idle_ticks; | ||
| 399 | 377 | ||
| 400 | j_dbs_info = &per_cpu(cpu_dbs_info, j); | 378 | if (tmp_idle_ticks < idle_ticks) |
| 401 | total_idle_ticks = j_dbs_info->prev_cpu_idle_up; | 379 | idle_ticks = tmp_idle_ticks; |
| 402 | tmp_idle_ticks = total_idle_ticks - | ||
| 403 | j_dbs_info->prev_cpu_idle_down; | ||
| 404 | j_dbs_info->prev_cpu_idle_down = total_idle_ticks; | ||
| 405 | |||
| 406 | if (tmp_idle_ticks < idle_ticks) | ||
| 407 | idle_ticks = tmp_idle_ticks; | ||
| 408 | } | ||
| 409 | 380 | ||
| 410 | /* Scale idle ticks by 100 and compare with up and down ticks */ | 381 | /* Scale idle ticks by 100 and compare with up and down ticks */ |
| 411 | idle_ticks *= 100; | 382 | idle_ticks *= 100; |
| 412 | down_skip[cpu] = 0; | 383 | this_dbs_info->down_skip = 0; |
| 413 | 384 | ||
| 414 | freq_down_sampling_rate = dbs_tuners_ins.sampling_rate * | 385 | freq_down_sampling_rate = dbs_tuners_ins.sampling_rate * |
| 415 | dbs_tuners_ins.sampling_down_factor; | 386 | dbs_tuners_ins.sampling_down_factor; |
| 416 | down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) * | 387 | down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) * |
| 417 | usecs_to_jiffies(freq_down_sampling_rate); | 388 | usecs_to_jiffies(freq_down_sampling_rate); |
| 418 | 389 | ||
| 419 | if (idle_ticks > down_idle_ticks) { | 390 | if (idle_ticks > down_idle_ticks) { |
| 420 | /* if we are already at the lowest speed then break out early | 391 | /* |
| 392 | * if we are already at the lowest speed then break out early | ||
| 421 | * or if we 'cannot' reduce the speed as the user might want | 393 | * or if we 'cannot' reduce the speed as the user might want |
| 422 | * freq_step to be zero */ | 394 | * freq_step to be zero |
| 423 | if (requested_freq[cpu] == policy->min | 395 | */ |
| 396 | if (this_dbs_info->requested_freq == policy->min | ||
| 424 | || dbs_tuners_ins.freq_step == 0) | 397 | || dbs_tuners_ins.freq_step == 0) |
| 425 | return; | 398 | return; |
| 426 | 399 | ||
| @@ -430,13 +403,12 @@ static void dbs_check_cpu(int cpu) | |||
| 430 | if (unlikely(freq_step == 0)) | 403 | if (unlikely(freq_step == 0)) |
| 431 | freq_step = 5; | 404 | freq_step = 5; |
| 432 | 405 | ||
| 433 | requested_freq[cpu] -= freq_step; | 406 | this_dbs_info->requested_freq -= freq_step; |
| 434 | if (requested_freq[cpu] < policy->min) | 407 | if (this_dbs_info->requested_freq < policy->min) |
| 435 | requested_freq[cpu] = policy->min; | 408 | this_dbs_info->requested_freq = policy->min; |
| 436 | 409 | ||
| 437 | __cpufreq_driver_target(policy, | 410 | __cpufreq_driver_target(policy, this_dbs_info->requested_freq, |
| 438 | requested_freq[cpu], | 411 | CPUFREQ_RELATION_H); |
| 439 | CPUFREQ_RELATION_H); | ||
| 440 | return; | 412 | return; |
| 441 | } | 413 | } |
| 442 | } | 414 | } |
| @@ -493,11 +465,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 493 | j_dbs_info = &per_cpu(cpu_dbs_info, j); | 465 | j_dbs_info = &per_cpu(cpu_dbs_info, j); |
| 494 | j_dbs_info->cur_policy = policy; | 466 | j_dbs_info->cur_policy = policy; |
| 495 | 467 | ||
| 496 | j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j); | 468 | j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(cpu); |
| 497 | j_dbs_info->prev_cpu_idle_down | 469 | j_dbs_info->prev_cpu_idle_down |
| 498 | = j_dbs_info->prev_cpu_idle_up; | 470 | = j_dbs_info->prev_cpu_idle_up; |
| 499 | } | 471 | } |
| 500 | this_dbs_info->enable = 1; | 472 | this_dbs_info->enable = 1; |
| 473 | this_dbs_info->down_skip = 0; | ||
| 474 | this_dbs_info->requested_freq = policy->cur; | ||
| 501 | sysfs_create_group(&policy->kobj, &dbs_attr_group); | 475 | sysfs_create_group(&policy->kobj, &dbs_attr_group); |
| 502 | dbs_enable++; | 476 | dbs_enable++; |
| 503 | /* | 477 | /* |
| @@ -507,16 +481,17 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 507 | if (dbs_enable == 1) { | 481 | if (dbs_enable == 1) { |
| 508 | unsigned int latency; | 482 | unsigned int latency; |
| 509 | /* policy latency is in nS. Convert it to uS first */ | 483 | /* policy latency is in nS. Convert it to uS first */ |
| 484 | latency = policy->cpuinfo.transition_latency / 1000; | ||
| 485 | if (latency == 0) | ||
| 486 | latency = 1; | ||
| 510 | 487 | ||
| 511 | latency = policy->cpuinfo.transition_latency; | 488 | def_sampling_rate = 10 * latency * |
| 512 | if (latency < 1000) | ||
| 513 | latency = 1000; | ||
| 514 | |||
| 515 | def_sampling_rate = (latency / 1000) * | ||
| 516 | DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; | 489 | DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; |
| 490 | |||
| 491 | if (def_sampling_rate < MIN_STAT_SAMPLING_RATE) | ||
| 492 | def_sampling_rate = MIN_STAT_SAMPLING_RATE; | ||
| 493 | |||
| 517 | dbs_tuners_ins.sampling_rate = def_sampling_rate; | 494 | dbs_tuners_ins.sampling_rate = def_sampling_rate; |
| 518 | dbs_tuners_ins.ignore_nice = 0; | ||
| 519 | dbs_tuners_ins.freq_step = 5; | ||
| 520 | 495 | ||
| 521 | dbs_timer_init(); | 496 | dbs_timer_init(); |
| 522 | } | 497 | } |
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 69aa1db8336c..956d121cb161 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
| @@ -84,6 +84,7 @@ struct dbs_tuners { | |||
| 84 | static struct dbs_tuners dbs_tuners_ins = { | 84 | static struct dbs_tuners dbs_tuners_ins = { |
| 85 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, | 85 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, |
| 86 | .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, | 86 | .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, |
| 87 | .ignore_nice = 0, | ||
| 87 | }; | 88 | }; |
| 88 | 89 | ||
| 89 | static inline unsigned int get_cpu_idle_time(unsigned int cpu) | 90 | static inline unsigned int get_cpu_idle_time(unsigned int cpu) |
| @@ -350,6 +351,9 @@ static void dbs_check_cpu(int cpu) | |||
| 350 | freq_next = (freq_next * policy->cur) / | 351 | freq_next = (freq_next * policy->cur) / |
| 351 | (dbs_tuners_ins.up_threshold - 10); | 352 | (dbs_tuners_ins.up_threshold - 10); |
| 352 | 353 | ||
| 354 | if (freq_next < policy->min) | ||
| 355 | freq_next = policy->min; | ||
| 356 | |||
| 353 | if (freq_next <= ((policy->cur * 95) / 100)) | 357 | if (freq_next <= ((policy->cur * 95) / 100)) |
| 354 | __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); | 358 | __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); |
| 355 | } | 359 | } |
| @@ -395,8 +399,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 395 | return -EINVAL; | 399 | return -EINVAL; |
| 396 | 400 | ||
| 397 | if (policy->cpuinfo.transition_latency > | 401 | if (policy->cpuinfo.transition_latency > |
| 398 | (TRANSITION_LATENCY_LIMIT * 1000)) | 402 | (TRANSITION_LATENCY_LIMIT * 1000)) { |
| 403 | printk(KERN_WARNING "ondemand governor failed to load " | ||
| 404 | "due to too long transition latency\n"); | ||
| 399 | return -EINVAL; | 405 | return -EINVAL; |
| 406 | } | ||
| 400 | if (this_dbs_info->enable) /* Already enabled */ | 407 | if (this_dbs_info->enable) /* Already enabled */ |
| 401 | break; | 408 | break; |
| 402 | 409 | ||
| @@ -431,8 +438,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 431 | def_sampling_rate = MIN_STAT_SAMPLING_RATE; | 438 | def_sampling_rate = MIN_STAT_SAMPLING_RATE; |
| 432 | 439 | ||
| 433 | dbs_tuners_ins.sampling_rate = def_sampling_rate; | 440 | dbs_tuners_ins.sampling_rate = def_sampling_rate; |
| 434 | dbs_tuners_ins.ignore_nice = 0; | ||
| 435 | |||
| 436 | dbs_timer_init(); | 441 | dbs_timer_init(); |
| 437 | } | 442 | } |
| 438 | 443 | ||
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 905f58ba8e16..ea06e3a4dc35 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
| @@ -2044,7 +2044,7 @@ static int __init edac_mc_init(void) | |||
| 2044 | */ | 2044 | */ |
| 2045 | clear_pci_parity_errors(); | 2045 | clear_pci_parity_errors(); |
| 2046 | 2046 | ||
| 2047 | /* Create the MC sysfs entires */ | 2047 | /* Create the MC sysfs entries */ |
| 2048 | if (edac_sysfs_memctrl_setup()) { | 2048 | if (edac_sysfs_memctrl_setup()) { |
| 2049 | edac_printk(KERN_ERR, EDAC_MC, | 2049 | edac_printk(KERN_ERR, EDAC_MC, |
| 2050 | "Error initializing sysfs code\n"); | 2050 | "Error initializing sysfs code\n"); |
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index d6543fc4a923..339f405ff708 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c | |||
| @@ -484,26 +484,15 @@ static void dcdbas_host_control(void) | |||
| 484 | static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code, | 484 | static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code, |
| 485 | void *unused) | 485 | void *unused) |
| 486 | { | 486 | { |
| 487 | static unsigned int notify_cnt = 0; | ||
| 488 | |||
| 489 | switch (code) { | 487 | switch (code) { |
| 490 | case SYS_DOWN: | 488 | case SYS_DOWN: |
| 491 | case SYS_HALT: | 489 | case SYS_HALT: |
| 492 | case SYS_POWER_OFF: | 490 | case SYS_POWER_OFF: |
| 493 | if (host_control_on_shutdown) { | 491 | if (host_control_on_shutdown) { |
| 494 | /* firmware is going to perform host control action */ | 492 | /* firmware is going to perform host control action */ |
| 495 | if (++notify_cnt == 2) { | 493 | printk(KERN_WARNING "Please wait for shutdown " |
| 496 | printk(KERN_WARNING | 494 | "action to complete...\n"); |
| 497 | "Please wait for shutdown " | 495 | dcdbas_host_control(); |
| 498 | "action to complete...\n"); | ||
| 499 | dcdbas_host_control(); | ||
| 500 | } | ||
| 501 | /* | ||
| 502 | * register again and initiate the host control | ||
| 503 | * action on the second notification to allow | ||
| 504 | * everyone that registered to be notified | ||
| 505 | */ | ||
| 506 | register_reboot_notifier(nb); | ||
| 507 | } | 496 | } |
| 508 | break; | 497 | break; |
| 509 | } | 498 | } |
| @@ -514,7 +503,7 @@ static int dcdbas_reboot_notify(struct notifier_block *nb, unsigned long code, | |||
| 514 | static struct notifier_block dcdbas_reboot_nb = { | 503 | static struct notifier_block dcdbas_reboot_nb = { |
| 515 | .notifier_call = dcdbas_reboot_notify, | 504 | .notifier_call = dcdbas_reboot_notify, |
| 516 | .next = NULL, | 505 | .next = NULL, |
| 517 | .priority = 0 | 506 | .priority = INT_MIN |
| 518 | }; | 507 | }; |
| 519 | 508 | ||
| 520 | static DCDBAS_BIN_ATTR_RW(smi_data); | 509 | static DCDBAS_BIN_ATTR_RW(smi_data); |
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index f9fae28f5612..7aa5c38f0855 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig | |||
| @@ -65,15 +65,6 @@ config SENSORS_PCF8591 | |||
| 65 | This driver can also be built as a module. If so, the module | 65 | This driver can also be built as a module. If so, the module |
| 66 | will be called pcf8591. | 66 | will be called pcf8591. |
| 67 | 67 | ||
| 68 | config SENSORS_RTC8564 | ||
| 69 | tristate "Epson 8564 RTC chip" | ||
| 70 | depends on I2C && EXPERIMENTAL | ||
| 71 | help | ||
| 72 | If you say yes here you get support for the Epson 8564 RTC chip. | ||
| 73 | |||
| 74 | This driver can also be built as a module. If so, the module | ||
| 75 | will be called i2c-rtc8564. | ||
| 76 | |||
| 77 | config ISP1301_OMAP | 68 | config ISP1301_OMAP |
| 78 | tristate "Philips ISP1301 with OMAP OTG" | 69 | tristate "Philips ISP1301 with OMAP OTG" |
| 79 | depends on I2C && ARCH_OMAP_OTG | 70 | depends on I2C && ARCH_OMAP_OTG |
| @@ -126,13 +117,4 @@ config SENSORS_MAX6875 | |||
| 126 | This driver can also be built as a module. If so, the module | 117 | This driver can also be built as a module. If so, the module |
| 127 | will be called max6875. | 118 | will be called max6875. |
| 128 | 119 | ||
| 129 | config RTC_X1205_I2C | ||
| 130 | tristate "Xicor X1205 RTC chip" | ||
| 131 | depends on I2C && EXPERIMENTAL | ||
| 132 | help | ||
| 133 | If you say yes here you get support for the Xicor X1205 RTC chip. | ||
| 134 | |||
| 135 | This driver can also be built as a module. If so, the module | ||
| 136 | will be called x1205. | ||
| 137 | |||
| 138 | endmenu | 120 | endmenu |
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index 46178b57b1f1..779868ef2e26 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile | |||
| @@ -10,10 +10,8 @@ obj-$(CONFIG_SENSORS_M41T00) += m41t00.o | |||
| 10 | obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o | 10 | obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o |
| 11 | obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o | 11 | obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o |
| 12 | obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o | 12 | obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o |
| 13 | obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o | ||
| 14 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o | 13 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o |
| 15 | obj-$(CONFIG_TPS65010) += tps65010.o | 14 | obj-$(CONFIG_TPS65010) += tps65010.o |
| 16 | obj-$(CONFIG_RTC_X1205_I2C) += x1205.o | ||
| 17 | 15 | ||
| 18 | ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) | 16 | ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) |
| 19 | EXTRA_CFLAGS += -DDEBUG | 17 | EXTRA_CFLAGS += -DDEBUG |
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c deleted file mode 100644 index 0d8699b3f488..000000000000 --- a/drivers/i2c/chips/rtc8564.c +++ /dev/null | |||
| @@ -1,385 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/i2c/chips/rtc8564.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002-2004 Stefan Eletzhofer | ||
| 5 | * | ||
| 6 | * based on linux/drivers/acron/char/pcf8583.c | ||
| 7 | * Copyright (C) 2000 Russell King | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | * Driver for system3's EPSON RTC 8564 chip | ||
| 14 | */ | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/bcd.h> | ||
| 18 | #include <linux/i2c.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/string.h> | ||
| 21 | #include <linux/rtc.h> /* get the user-level API */ | ||
| 22 | #include <linux/init.h> | ||
| 23 | |||
| 24 | #include "rtc8564.h" | ||
| 25 | |||
| 26 | #ifdef DEBUG | ||
| 27 | # define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0); | ||
| 28 | #else | ||
| 29 | # define _DBG(x, fmt, args...) do { } while(0); | ||
| 30 | #endif | ||
| 31 | |||
| 32 | #define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, " \ | ||
| 33 | "mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \ | ||
| 34 | (rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \ | ||
| 35 | (rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl); | ||
| 36 | |||
| 37 | struct rtc8564_data { | ||
| 38 | struct i2c_client client; | ||
| 39 | u16 ctrl; | ||
| 40 | }; | ||
| 41 | |||
| 42 | static inline u8 _rtc8564_ctrl1(struct i2c_client *client) | ||
| 43 | { | ||
| 44 | struct rtc8564_data *data = i2c_get_clientdata(client); | ||
| 45 | return data->ctrl & 0xff; | ||
| 46 | } | ||
| 47 | static inline u8 _rtc8564_ctrl2(struct i2c_client *client) | ||
| 48 | { | ||
| 49 | struct rtc8564_data *data = i2c_get_clientdata(client); | ||
| 50 | return (data->ctrl & 0xff00) >> 8; | ||
| 51 | } | ||
| 52 | |||
| 53 | #define CTRL1(c) _rtc8564_ctrl1(c) | ||
| 54 | #define CTRL2(c) _rtc8564_ctrl2(c) | ||
| 55 | |||
| 56 | static int debug; | ||
| 57 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
| 58 | |||
| 59 | static struct i2c_driver rtc8564_driver; | ||
| 60 | |||
| 61 | static unsigned short ignore[] = { I2C_CLIENT_END }; | ||
| 62 | static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END }; | ||
| 63 | |||
| 64 | static struct i2c_client_address_data addr_data = { | ||
| 65 | .normal_i2c = normal_addr, | ||
| 66 | .probe = ignore, | ||
| 67 | .ignore = ignore, | ||
| 68 | }; | ||
| 69 | |||
| 70 | static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem); | ||
| 71 | static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem); | ||
| 72 | |||
| 73 | static int rtc8564_read(struct i2c_client *client, unsigned char adr, | ||
| 74 | unsigned char *buf, unsigned char len) | ||
| 75 | { | ||
| 76 | int ret = -EIO; | ||
| 77 | unsigned char addr[1] = { adr }; | ||
| 78 | struct i2c_msg msgs[2] = { | ||
| 79 | {client->addr, 0, 1, addr}, | ||
| 80 | {client->addr, I2C_M_RD, len, buf} | ||
| 81 | }; | ||
| 82 | |||
| 83 | _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len); | ||
| 84 | |||
| 85 | if (!buf) { | ||
| 86 | ret = -EINVAL; | ||
| 87 | goto done; | ||
| 88 | } | ||
| 89 | |||
| 90 | ret = i2c_transfer(client->adapter, msgs, 2); | ||
| 91 | if (ret == 2) { | ||
| 92 | ret = 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | done: | ||
| 96 | return ret; | ||
| 97 | } | ||
| 98 | |||
| 99 | static int rtc8564_write(struct i2c_client *client, unsigned char adr, | ||
| 100 | unsigned char *data, unsigned char len) | ||
| 101 | { | ||
| 102 | int ret = 0; | ||
| 103 | unsigned char _data[16]; | ||
| 104 | struct i2c_msg wr; | ||
| 105 | int i; | ||
| 106 | |||
| 107 | if (!data || len > 15) { | ||
| 108 | ret = -EINVAL; | ||
| 109 | goto done; | ||
| 110 | } | ||
| 111 | |||
| 112 | _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len); | ||
| 113 | |||
| 114 | _data[0] = adr; | ||
| 115 | for (i = 0; i < len; i++) { | ||
| 116 | _data[i + 1] = data[i]; | ||
| 117 | _DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]); | ||
| 118 | } | ||
| 119 | |||
| 120 | wr.addr = client->addr; | ||
| 121 | wr.flags = 0; | ||
| 122 | wr.len = len + 1; | ||
| 123 | wr.buf = _data; | ||
| 124 | |||
| 125 | ret = i2c_transfer(client->adapter, &wr, 1); | ||
| 126 | if (ret == 1) { | ||
| 127 | ret = 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | done: | ||
| 131 | return ret; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind) | ||
| 135 | { | ||
| 136 | int ret; | ||
| 137 | struct i2c_client *new_client; | ||
| 138 | struct rtc8564_data *d; | ||
| 139 | unsigned char data[10]; | ||
| 140 | unsigned char ad[1] = { 0 }; | ||
| 141 | struct i2c_msg ctrl_wr[1] = { | ||
| 142 | {addr, 0, 2, data} | ||
| 143 | }; | ||
| 144 | struct i2c_msg ctrl_rd[2] = { | ||
| 145 | {addr, 0, 1, ad}, | ||
| 146 | {addr, I2C_M_RD, 2, data} | ||
| 147 | }; | ||
| 148 | |||
| 149 | d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL); | ||
| 150 | if (!d) { | ||
| 151 | ret = -ENOMEM; | ||
| 152 | goto done; | ||
| 153 | } | ||
| 154 | new_client = &d->client; | ||
| 155 | |||
| 156 | strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE); | ||
| 157 | i2c_set_clientdata(new_client, d); | ||
| 158 | new_client->addr = addr; | ||
| 159 | new_client->adapter = adap; | ||
| 160 | new_client->driver = &rtc8564_driver; | ||
| 161 | |||
| 162 | _DBG(1, "client=%p", new_client); | ||
| 163 | |||
| 164 | /* init ctrl1 reg */ | ||
| 165 | data[0] = 0; | ||
| 166 | data[1] = 0; | ||
| 167 | ret = i2c_transfer(new_client->adapter, ctrl_wr, 1); | ||
| 168 | if (ret != 1) { | ||
| 169 | printk(KERN_INFO "rtc8564: cant init ctrl1\n"); | ||
| 170 | ret = -ENODEV; | ||
| 171 | goto done; | ||
| 172 | } | ||
| 173 | |||
| 174 | /* read back ctrl1 and ctrl2 */ | ||
| 175 | ret = i2c_transfer(new_client->adapter, ctrl_rd, 2); | ||
| 176 | if (ret != 2) { | ||
| 177 | printk(KERN_INFO "rtc8564: cant read ctrl\n"); | ||
| 178 | ret = -ENODEV; | ||
| 179 | goto done; | ||
| 180 | } | ||
| 181 | |||
| 182 | d->ctrl = data[0] | (data[1] << 8); | ||
| 183 | |||
| 184 | _DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x", | ||
| 185 | data[0], data[1]); | ||
| 186 | |||
| 187 | ret = i2c_attach_client(new_client); | ||
| 188 | done: | ||
| 189 | if (ret) { | ||
| 190 | kfree(d); | ||
| 191 | } | ||
| 192 | return ret; | ||
| 193 | } | ||
| 194 | |||
| 195 | static int rtc8564_probe(struct i2c_adapter *adap) | ||
| 196 | { | ||
| 197 | return i2c_probe(adap, &addr_data, rtc8564_attach); | ||
| 198 | } | ||
| 199 | |||
| 200 | static int rtc8564_detach(struct i2c_client *client) | ||
| 201 | { | ||
| 202 | i2c_detach_client(client); | ||
| 203 | kfree(i2c_get_clientdata(client)); | ||
| 204 | return 0; | ||
| 205 | } | ||
| 206 | |||
| 207 | static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt) | ||
| 208 | { | ||
| 209 | int ret = -EIO; | ||
| 210 | unsigned char buf[15]; | ||
| 211 | |||
| 212 | _DBG(1, "client=%p, dt=%p", client, dt); | ||
| 213 | |||
| 214 | if (!dt) | ||
| 215 | return -EINVAL; | ||
| 216 | |||
| 217 | memset(buf, 0, sizeof(buf)); | ||
| 218 | |||
| 219 | ret = rtc8564_read(client, 0, buf, 15); | ||
| 220 | if (ret) | ||
| 221 | return ret; | ||
| 222 | |||
| 223 | /* century stored in minute alarm reg */ | ||
| 224 | dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]); | ||
| 225 | dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f); | ||
| 226 | dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f); | ||
| 227 | dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7); | ||
| 228 | dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f); | ||
| 229 | |||
| 230 | dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f); | ||
| 231 | dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80; | ||
| 232 | dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f); | ||
| 233 | dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f); | ||
| 234 | |||
| 235 | _DBGRTCTM(2, *dt); | ||
| 236 | |||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | static int | ||
| 241 | rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo) | ||
| 242 | { | ||
| 243 | int ret, len = 5; | ||
| 244 | unsigned char buf[15]; | ||
| 245 | |||
| 246 | _DBG(1, "client=%p, dt=%p", client, dt); | ||
| 247 | |||
| 248 | if (!dt) | ||
| 249 | return -EINVAL; | ||
| 250 | |||
| 251 | _DBGRTCTM(2, *dt); | ||
| 252 | |||
| 253 | buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP; | ||
| 254 | buf[RTC8564_REG_CTRL2] = CTRL2(client); | ||
| 255 | buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs); | ||
| 256 | buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins); | ||
| 257 | buf[RTC8564_REG_HR] = BIN2BCD(dt->hours); | ||
| 258 | |||
| 259 | if (datetoo) { | ||
| 260 | len += 5; | ||
| 261 | buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday); | ||
| 262 | buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday); | ||
| 263 | buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f; | ||
| 264 | /* century stored in minute alarm reg */ | ||
| 265 | buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100); | ||
| 266 | buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100); | ||
| 267 | } | ||
| 268 | |||
| 269 | ret = rtc8564_write(client, 0, buf, len); | ||
| 270 | if (ret) { | ||
| 271 | _DBG(1, "error writing data! %d", ret); | ||
| 272 | } | ||
| 273 | |||
| 274 | buf[RTC8564_REG_CTRL1] = CTRL1(client); | ||
| 275 | ret = rtc8564_write(client, 0, buf, 1); | ||
| 276 | if (ret) { | ||
| 277 | _DBG(1, "error writing data! %d", ret); | ||
| 278 | } | ||
| 279 | |||
| 280 | return ret; | ||
| 281 | } | ||
| 282 | |||
| 283 | static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl) | ||
| 284 | { | ||
| 285 | struct rtc8564_data *data = i2c_get_clientdata(client); | ||
| 286 | |||
| 287 | if (!ctrl) | ||
| 288 | return -1; | ||
| 289 | |||
| 290 | *ctrl = data->ctrl; | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl) | ||
| 295 | { | ||
| 296 | struct rtc8564_data *data = i2c_get_clientdata(client); | ||
| 297 | unsigned char buf[2]; | ||
| 298 | |||
| 299 | if (!ctrl) | ||
| 300 | return -1; | ||
| 301 | |||
| 302 | buf[0] = *ctrl & 0xff; | ||
| 303 | buf[1] = (*ctrl & 0xff00) >> 8; | ||
| 304 | data->ctrl = *ctrl; | ||
| 305 | |||
| 306 | return rtc8564_write(client, 0, buf, 2); | ||
| 307 | } | ||
| 308 | |||
| 309 | static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem) | ||
| 310 | { | ||
| 311 | |||
| 312 | if (!mem) | ||
| 313 | return -EINVAL; | ||
| 314 | |||
| 315 | return rtc8564_read(client, mem->loc, mem->data, mem->nr); | ||
| 316 | } | ||
| 317 | |||
| 318 | static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem) | ||
| 319 | { | ||
| 320 | |||
| 321 | if (!mem) | ||
| 322 | return -EINVAL; | ||
| 323 | |||
| 324 | return rtc8564_write(client, mem->loc, mem->data, mem->nr); | ||
| 325 | } | ||
| 326 | |||
| 327 | static int | ||
| 328 | rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg) | ||
| 329 | { | ||
| 330 | |||
| 331 | _DBG(1, "cmd=%d", cmd); | ||
| 332 | |||
| 333 | switch (cmd) { | ||
| 334 | case RTC_GETDATETIME: | ||
| 335 | return rtc8564_get_datetime(client, arg); | ||
| 336 | |||
| 337 | case RTC_SETTIME: | ||
| 338 | return rtc8564_set_datetime(client, arg, 0); | ||
| 339 | |||
| 340 | case RTC_SETDATETIME: | ||
| 341 | return rtc8564_set_datetime(client, arg, 1); | ||
| 342 | |||
| 343 | case RTC_GETCTRL: | ||
| 344 | return rtc8564_get_ctrl(client, arg); | ||
| 345 | |||
| 346 | case RTC_SETCTRL: | ||
| 347 | return rtc8564_set_ctrl(client, arg); | ||
| 348 | |||
| 349 | case MEM_READ: | ||
| 350 | return rtc8564_read_mem(client, arg); | ||
| 351 | |||
| 352 | case MEM_WRITE: | ||
| 353 | return rtc8564_write_mem(client, arg); | ||
| 354 | |||
| 355 | default: | ||
| 356 | return -EINVAL; | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 360 | static struct i2c_driver rtc8564_driver = { | ||
| 361 | .driver = { | ||
| 362 | .name = "RTC8564", | ||
| 363 | }, | ||
| 364 | .id = I2C_DRIVERID_RTC8564, | ||
| 365 | .attach_adapter = rtc8564_probe, | ||
| 366 | .detach_client = rtc8564_detach, | ||
| 367 | .command = rtc8564_command | ||
| 368 | }; | ||
| 369 | |||
| 370 | static __init int rtc8564_init(void) | ||
| 371 | { | ||
| 372 | return i2c_add_driver(&rtc8564_driver); | ||
| 373 | } | ||
| 374 | |||
| 375 | static __exit void rtc8564_exit(void) | ||
| 376 | { | ||
| 377 | i2c_del_driver(&rtc8564_driver); | ||
| 378 | } | ||
| 379 | |||
| 380 | MODULE_AUTHOR("Stefan Eletzhofer <Stefan.Eletzhofer@eletztrick.de>"); | ||
| 381 | MODULE_DESCRIPTION("EPSON RTC8564 Driver"); | ||
| 382 | MODULE_LICENSE("GPL"); | ||
| 383 | |||
| 384 | module_init(rtc8564_init); | ||
| 385 | module_exit(rtc8564_exit); | ||
diff --git a/drivers/i2c/chips/rtc8564.h b/drivers/i2c/chips/rtc8564.h deleted file mode 100644 index e5342d10b8fa..000000000000 --- a/drivers/i2c/chips/rtc8564.h +++ /dev/null | |||
| @@ -1,78 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/i2c/chips/rtc8564.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002-2004 Stefan Eletzhofer | ||
| 5 | * | ||
| 6 | * based on linux/drivers/acron/char/pcf8583.h | ||
| 7 | * Copyright (C) 2000 Russell King | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | struct rtc_tm { | ||
| 14 | unsigned char secs; | ||
| 15 | unsigned char mins; | ||
| 16 | unsigned char hours; | ||
| 17 | unsigned char mday; | ||
| 18 | unsigned char mon; | ||
| 19 | unsigned short year; /* xxxx 4 digits :) */ | ||
| 20 | unsigned char wday; | ||
| 21 | unsigned char vl; | ||
| 22 | }; | ||
| 23 | |||
| 24 | struct mem { | ||
| 25 | unsigned int loc; | ||
| 26 | unsigned int nr; | ||
| 27 | unsigned char *data; | ||
| 28 | }; | ||
| 29 | |||
| 30 | #define RTC_GETDATETIME 0 | ||
| 31 | #define RTC_SETTIME 1 | ||
| 32 | #define RTC_SETDATETIME 2 | ||
| 33 | #define RTC_GETCTRL 3 | ||
| 34 | #define RTC_SETCTRL 4 | ||
| 35 | #define MEM_READ 5 | ||
| 36 | #define MEM_WRITE 6 | ||
| 37 | |||
| 38 | #define RTC8564_REG_CTRL1 0x0 /* T 0 S 0 | T 0 0 0 */ | ||
| 39 | #define RTC8564_REG_CTRL2 0x1 /* 0 0 0 TI/TP | AF TF AIE TIE */ | ||
| 40 | #define RTC8564_REG_SEC 0x2 /* VL 4 2 1 | 8 4 2 1 */ | ||
| 41 | #define RTC8564_REG_MIN 0x3 /* x 4 2 1 | 8 4 2 1 */ | ||
| 42 | #define RTC8564_REG_HR 0x4 /* x x 2 1 | 8 4 2 1 */ | ||
| 43 | #define RTC8564_REG_DAY 0x5 /* x x 2 1 | 8 4 2 1 */ | ||
| 44 | #define RTC8564_REG_WDAY 0x6 /* x x x x | x 4 2 1 */ | ||
| 45 | #define RTC8564_REG_MON_CENT 0x7 /* C x x 1 | 8 4 2 1 */ | ||
| 46 | #define RTC8564_REG_YEAR 0x8 /* 8 4 2 1 | 8 4 2 1 */ | ||
| 47 | #define RTC8564_REG_AL_MIN 0x9 /* AE 4 2 1 | 8 4 2 1 */ | ||
| 48 | #define RTC8564_REG_AL_HR 0xa /* AE 4 2 1 | 8 4 2 1 */ | ||
| 49 | #define RTC8564_REG_AL_DAY 0xb /* AE x 2 1 | 8 4 2 1 */ | ||
| 50 | #define RTC8564_REG_AL_WDAY 0xc /* AE x x x | x 4 2 1 */ | ||
| 51 | #define RTC8564_REG_CLKOUT 0xd /* FE x x x | x x FD1 FD0 */ | ||
| 52 | #define RTC8564_REG_TCTL 0xe /* TE x x x | x x FD1 FD0 */ | ||
| 53 | #define RTC8564_REG_TIMER 0xf /* 8 bit binary */ | ||
| 54 | |||
| 55 | /* Control reg */ | ||
| 56 | #define RTC8564_CTRL1_TEST1 (1<<3) | ||
| 57 | #define RTC8564_CTRL1_STOP (1<<5) | ||
| 58 | #define RTC8564_CTRL1_TEST2 (1<<7) | ||
| 59 | |||
| 60 | #define RTC8564_CTRL2_TIE (1<<0) | ||
| 61 | #define RTC8564_CTRL2_AIE (1<<1) | ||
| 62 | #define RTC8564_CTRL2_TF (1<<2) | ||
| 63 | #define RTC8564_CTRL2_AF (1<<3) | ||
| 64 | #define RTC8564_CTRL2_TI_TP (1<<4) | ||
| 65 | |||
| 66 | /* CLKOUT frequencies */ | ||
| 67 | #define RTC8564_FD_32768HZ (0x0) | ||
| 68 | #define RTC8564_FD_1024HZ (0x1) | ||
| 69 | #define RTC8564_FD_32 (0x2) | ||
| 70 | #define RTC8564_FD_1HZ (0x3) | ||
| 71 | |||
| 72 | /* Timer CTRL */ | ||
| 73 | #define RTC8564_TD_4096HZ (0x0) | ||
| 74 | #define RTC8564_TD_64HZ (0x1) | ||
| 75 | #define RTC8564_TD_1HZ (0x2) | ||
| 76 | #define RTC8564_TD_1_60HZ (0x3) | ||
| 77 | |||
| 78 | #define I2C_DRIVERID_RTC8564 0xf000 | ||
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index c7671e188017..b4a41d6d0714 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
| @@ -2143,6 +2143,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, | |||
| 2143 | req.cmd[0] = GPCMD_READ_CDVD_CAPACITY; | 2143 | req.cmd[0] = GPCMD_READ_CDVD_CAPACITY; |
| 2144 | req.data = (char *)&capbuf; | 2144 | req.data = (char *)&capbuf; |
| 2145 | req.data_len = sizeof(capbuf); | 2145 | req.data_len = sizeof(capbuf); |
| 2146 | req.flags |= REQ_QUIET; | ||
| 2146 | 2147 | ||
| 2147 | stat = cdrom_queue_packet_command(drive, &req); | 2148 | stat = cdrom_queue_packet_command(drive, &req); |
| 2148 | if (stat == 0) { | 2149 | if (stat == 0) { |
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index ebc59064b475..f04791a58df0 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
| @@ -433,6 +433,7 @@ | |||
| 433 | #include <linux/timer.h> | 433 | #include <linux/timer.h> |
| 434 | #include <linux/mm.h> | 434 | #include <linux/mm.h> |
| 435 | #include <linux/interrupt.h> | 435 | #include <linux/interrupt.h> |
| 436 | #include <linux/jiffies.h> | ||
| 436 | #include <linux/major.h> | 437 | #include <linux/major.h> |
| 437 | #include <linux/devfs_fs_kernel.h> | 438 | #include <linux/devfs_fs_kernel.h> |
| 438 | #include <linux/errno.h> | 439 | #include <linux/errno.h> |
| @@ -2336,7 +2337,7 @@ static ide_startstop_t idetape_rw_callback (ide_drive_t *drive) | |||
| 2336 | } | 2337 | } |
| 2337 | if (time_after(jiffies, tape->insert_time)) | 2338 | if (time_after(jiffies, tape->insert_time)) |
| 2338 | tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); | 2339 | tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); |
| 2339 | if (jiffies - tape->avg_time >= HZ) { | 2340 | if (time_after_eq(jiffies, tape->avg_time + HZ)) { |
| 2340 | tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024; | 2341 | tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024; |
| 2341 | tape->avg_size = 0; | 2342 | tape->avg_size = 0; |
| 2342 | tape->avg_time = jiffies; | 2343 | tape->avg_time = jiffies; |
| @@ -2497,7 +2498,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
| 2497 | } else { | 2498 | } else { |
| 2498 | return ide_do_reset(drive); | 2499 | return ide_do_reset(drive); |
| 2499 | } | 2500 | } |
| 2500 | } else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD) | 2501 | } else if (time_after(jiffies, tape->dsc_polling_start + IDETAPE_DSC_MA_THRESHOLD)) |
| 2501 | tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW; | 2502 | tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW; |
| 2502 | idetape_postpone_request(drive); | 2503 | idetape_postpone_request(drive); |
| 2503 | return ide_stopped; | 2504 | return ide_stopped; |
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 21965e5ef25e..b22ee5462318 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c | |||
| @@ -347,10 +347,8 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch | |||
| 347 | break; | 347 | break; |
| 348 | 348 | ||
| 349 | case AMD_UDMA_66: | 349 | case AMD_UDMA_66: |
| 350 | pci_read_config_dword(dev, AMD_UDMA_TIMING, &u); | 350 | /* no host side cable detection */ |
| 351 | for (i = 24; i >= 0; i -= 8) | 351 | amd_80w = 0x03; |
| 352 | if ((u >> i) & 4) | ||
| 353 | amd_80w |= (1 << (1 - (i >> 4))); | ||
| 354 | break; | 352 | break; |
| 355 | } | 353 | } |
| 356 | 354 | ||
| @@ -386,8 +384,6 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch | |||
| 386 | if (amd_clock < 20000 || amd_clock > 50000) { | 384 | if (amd_clock < 20000 || amd_clock > 50000) { |
| 387 | printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", | 385 | printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", |
| 388 | amd_chipset->name, amd_clock); | 386 | amd_chipset->name, amd_clock); |
| 389 | printk(KERN_WARNING "%s: Use ide0=ata66 if you want to assume 80-wire cable\n", | ||
| 390 | amd_chipset->name); | ||
| 391 | amd_clock = 33333; | 387 | amd_clock = 33333; |
| 392 | } | 388 | } |
| 393 | 389 | ||
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 6e3ab0c38c4d..f82e82109728 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c | |||
| @@ -41,14 +41,15 @@ | |||
| 41 | 41 | ||
| 42 | static int ide_generic_all; /* Set to claim all devices */ | 42 | static int ide_generic_all; /* Set to claim all devices */ |
| 43 | 43 | ||
| 44 | #ifndef MODULE | ||
| 44 | static int __init ide_generic_all_on(char *unused) | 45 | static int __init ide_generic_all_on(char *unused) |
| 45 | { | 46 | { |
| 46 | ide_generic_all = 1; | 47 | ide_generic_all = 1; |
| 47 | printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n"); | 48 | printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n"); |
| 48 | return 1; | 49 | return 1; |
| 49 | } | 50 | } |
| 50 | |||
| 51 | __setup("all-generic-ide", ide_generic_all_on); | 51 | __setup("all-generic-ide", ide_generic_all_on); |
| 52 | #endif | ||
| 52 | 53 | ||
| 53 | static void __devinit init_hwif_generic (ide_hwif_t *hwif) | 54 | static void __devinit init_hwif_generic (ide_hwif_t *hwif) |
| 54 | { | 55 | { |
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 75a2253a3e68..8e9d87701ce2 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c | |||
| @@ -112,6 +112,7 @@ static const struct { | |||
| 112 | 112 | ||
| 113 | { "SiS5596", PCI_DEVICE_ID_SI_5596, ATA_16 }, | 113 | { "SiS5596", PCI_DEVICE_ID_SI_5596, ATA_16 }, |
| 114 | { "SiS5571", PCI_DEVICE_ID_SI_5571, ATA_16 }, | 114 | { "SiS5571", PCI_DEVICE_ID_SI_5571, ATA_16 }, |
| 115 | { "SiS5517", PCI_DEVICE_ID_SI_5517, ATA_16 }, | ||
| 115 | { "SiS551x", PCI_DEVICE_ID_SI_5511, ATA_16 }, | 116 | { "SiS551x", PCI_DEVICE_ID_SI_5511, ATA_16 }, |
| 116 | }; | 117 | }; |
| 117 | 118 | ||
| @@ -524,6 +525,7 @@ static void config_art_rwp_pio (ide_drive_t *drive, u8 pio) | |||
| 524 | case 3: test1 = 0x30|0x03; break; | 525 | case 3: test1 = 0x30|0x03; break; |
| 525 | case 2: test1 = 0x40|0x04; break; | 526 | case 2: test1 = 0x40|0x04; break; |
| 526 | case 1: test1 = 0x60|0x07; break; | 527 | case 1: test1 = 0x60|0x07; break; |
| 528 | case 0: test1 = 0x00; break; | ||
| 527 | default: break; | 529 | default: break; |
| 528 | } | 530 | } |
| 529 | pci_write_config_byte(dev, drive_pci, test1); | 531 | pci_write_config_byte(dev, drive_pci, test1); |
diff --git a/drivers/input/input.c b/drivers/input/input.c index 4fe3da3c667a..f8af0945964e 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -923,7 +923,7 @@ void input_unregister_handler(struct input_handler *handler) | |||
| 923 | static int input_open_file(struct inode *inode, struct file *file) | 923 | static int input_open_file(struct inode *inode, struct file *file) |
| 924 | { | 924 | { |
| 925 | struct input_handler *handler = input_table[iminor(inode) >> 5]; | 925 | struct input_handler *handler = input_table[iminor(inode) >> 5]; |
| 926 | struct file_operations *old_fops, *new_fops = NULL; | 926 | const struct file_operations *old_fops, *new_fops = NULL; |
| 927 | int err; | 927 | int err; |
| 928 | 928 | ||
| 929 | /* No load-on-demand here? */ | 929 | /* No load-on-demand here? */ |
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 623adbb0d13a..9b493f0becc4 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c | |||
| @@ -1485,6 +1485,7 @@ static int __init capi_init(void) | |||
| 1485 | { | 1485 | { |
| 1486 | char *p; | 1486 | char *p; |
| 1487 | char *compileinfo; | 1487 | char *compileinfo; |
| 1488 | int major_ret; | ||
| 1488 | 1489 | ||
| 1489 | if ((p = strchr(revision, ':')) != 0 && p[1]) { | 1490 | if ((p = strchr(revision, ':')) != 0 && p[1]) { |
| 1490 | strlcpy(rev, p + 2, sizeof(rev)); | 1491 | strlcpy(rev, p + 2, sizeof(rev)); |
| @@ -1493,11 +1494,12 @@ static int __init capi_init(void) | |||
| 1493 | } else | 1494 | } else |
| 1494 | strcpy(rev, "1.0"); | 1495 | strcpy(rev, "1.0"); |
| 1495 | 1496 | ||
| 1496 | if (register_chrdev(capi_major, "capi20", &capi_fops)) { | 1497 | major_ret = register_chrdev(capi_major, "capi20", &capi_fops); |
| 1498 | if (major_ret < 0) { | ||
| 1497 | printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); | 1499 | printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); |
| 1498 | return -EIO; | 1500 | return major_ret; |
| 1499 | } | 1501 | } |
| 1500 | 1502 | capi_major = major_ret; | |
| 1501 | capi_class = class_create(THIS_MODULE, "capi"); | 1503 | capi_class = class_create(THIS_MODULE, "capi"); |
| 1502 | if (IS_ERR(capi_class)) { | 1504 | if (IS_ERR(capi_class)) { |
| 1503 | unregister_chrdev(capi_major, "capi20"); | 1505 | unregister_chrdev(capi_major, "capi20"); |
diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index 2cc8b27e4c3b..ca9dc00a45c4 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c | |||
| @@ -233,7 +233,7 @@ static struct file_operations proc_applstats_ops = { | |||
| 233 | }; | 233 | }; |
| 234 | 234 | ||
| 235 | static void | 235 | static void |
| 236 | create_seq_entry(char *name, mode_t mode, struct file_operations *f) | 236 | create_seq_entry(char *name, mode_t mode, const struct file_operations *f) |
| 237 | { | 237 | { |
| 238 | struct proc_dir_entry *entry; | 238 | struct proc_dir_entry *entry; |
| 239 | entry = create_proc_entry(name, mode, NULL); | 239 | entry = create_proc_entry(name, mode, NULL); |
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index d2ead1776c16..34fcabac5fdb 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c | |||
| @@ -80,7 +80,7 @@ static struct adb_driver *adb_driver_list[] = { | |||
| 80 | static struct class *adb_dev_class; | 80 | static struct class *adb_dev_class; |
| 81 | 81 | ||
| 82 | struct adb_driver *adb_controller; | 82 | struct adb_driver *adb_controller; |
| 83 | struct notifier_block *adb_client_list = NULL; | 83 | BLOCKING_NOTIFIER_HEAD(adb_client_list); |
| 84 | static int adb_got_sleep; | 84 | static int adb_got_sleep; |
| 85 | static int adb_inited; | 85 | static int adb_inited; |
| 86 | static pid_t adb_probe_task_pid; | 86 | static pid_t adb_probe_task_pid; |
| @@ -354,7 +354,8 @@ adb_notify_sleep(struct pmu_sleep_notifier *self, int when) | |||
| 354 | /* Stop autopoll */ | 354 | /* Stop autopoll */ |
| 355 | if (adb_controller->autopoll) | 355 | if (adb_controller->autopoll) |
| 356 | adb_controller->autopoll(0); | 356 | adb_controller->autopoll(0); |
| 357 | ret = notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL); | 357 | ret = blocking_notifier_call_chain(&adb_client_list, |
| 358 | ADB_MSG_POWERDOWN, NULL); | ||
| 358 | if (ret & NOTIFY_STOP_MASK) { | 359 | if (ret & NOTIFY_STOP_MASK) { |
| 359 | up(&adb_probe_mutex); | 360 | up(&adb_probe_mutex); |
| 360 | return PBOOK_SLEEP_REFUSE; | 361 | return PBOOK_SLEEP_REFUSE; |
| @@ -391,7 +392,8 @@ do_adb_reset_bus(void) | |||
| 391 | if (adb_controller->autopoll) | 392 | if (adb_controller->autopoll) |
| 392 | adb_controller->autopoll(0); | 393 | adb_controller->autopoll(0); |
| 393 | 394 | ||
| 394 | nret = notifier_call_chain(&adb_client_list, ADB_MSG_PRE_RESET, NULL); | 395 | nret = blocking_notifier_call_chain(&adb_client_list, |
| 396 | ADB_MSG_PRE_RESET, NULL); | ||
| 395 | if (nret & NOTIFY_STOP_MASK) { | 397 | if (nret & NOTIFY_STOP_MASK) { |
| 396 | if (adb_controller->autopoll) | 398 | if (adb_controller->autopoll) |
| 397 | adb_controller->autopoll(autopoll_devs); | 399 | adb_controller->autopoll(autopoll_devs); |
| @@ -426,7 +428,8 @@ do_adb_reset_bus(void) | |||
| 426 | } | 428 | } |
| 427 | up(&adb_handler_sem); | 429 | up(&adb_handler_sem); |
| 428 | 430 | ||
| 429 | nret = notifier_call_chain(&adb_client_list, ADB_MSG_POST_RESET, NULL); | 431 | nret = blocking_notifier_call_chain(&adb_client_list, |
| 432 | ADB_MSG_POST_RESET, NULL); | ||
| 430 | if (nret & NOTIFY_STOP_MASK) | 433 | if (nret & NOTIFY_STOP_MASK) |
| 431 | return -EBUSY; | 434 | return -EBUSY; |
| 432 | 435 | ||
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index c0b46bceb5df..f5779a73184d 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c | |||
| @@ -1214,7 +1214,8 @@ static int __init adbhid_init(void) | |||
| 1214 | 1214 | ||
| 1215 | adbhid_probe(); | 1215 | adbhid_probe(); |
| 1216 | 1216 | ||
| 1217 | notifier_chain_register(&adb_client_list, &adbhid_adb_notifier); | 1217 | blocking_notifier_chain_register(&adb_client_list, |
| 1218 | &adbhid_adb_notifier); | ||
| 1218 | 1219 | ||
| 1219 | return 0; | 1220 | return 0; |
| 1220 | } | 1221 | } |
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 4f5f3abc9cb3..0b5ff553e39a 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
| @@ -187,7 +187,7 @@ extern int disable_kernel_backlight; | |||
| 187 | 187 | ||
| 188 | int __fake_sleep; | 188 | int __fake_sleep; |
| 189 | int asleep; | 189 | int asleep; |
| 190 | struct notifier_block *sleep_notifier_list; | 190 | BLOCKING_NOTIFIER_HEAD(sleep_notifier_list); |
| 191 | 191 | ||
| 192 | #ifdef CONFIG_ADB | 192 | #ifdef CONFIG_ADB |
| 193 | static int adb_dev_map = 0; | 193 | static int adb_dev_map = 0; |
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c index f08e52f2107b..35b70323e7e3 100644 --- a/drivers/macintosh/via-pmu68k.c +++ b/drivers/macintosh/via-pmu68k.c | |||
| @@ -102,7 +102,7 @@ static int pmu_kind = PMU_UNKNOWN; | |||
| 102 | static int pmu_fully_inited = 0; | 102 | static int pmu_fully_inited = 0; |
| 103 | 103 | ||
| 104 | int asleep; | 104 | int asleep; |
| 105 | struct notifier_block *sleep_notifier_list; | 105 | BLOCKING_NOTIFIER_HEAD(sleep_notifier_list); |
| 106 | 106 | ||
| 107 | static int pmu_probe(void); | 107 | static int pmu_probe(void); |
| 108 | static int pmu_init(void); | 108 | static int pmu_init(void); |
| @@ -913,7 +913,8 @@ int powerbook_sleep(void) | |||
| 913 | struct adb_request sleep_req; | 913 | struct adb_request sleep_req; |
| 914 | 914 | ||
| 915 | /* Notify device drivers */ | 915 | /* Notify device drivers */ |
| 916 | ret = notifier_call_chain(&sleep_notifier_list, PBOOK_SLEEP, NULL); | 916 | ret = blocking_notifier_call_chain(&sleep_notifier_list, |
| 917 | PBOOK_SLEEP, NULL); | ||
| 917 | if (ret & NOTIFY_STOP_MASK) | 918 | if (ret & NOTIFY_STOP_MASK) |
| 918 | return -EBUSY; | 919 | return -EBUSY; |
| 919 | 920 | ||
| @@ -984,7 +985,7 @@ int powerbook_sleep(void) | |||
| 984 | enable_irq(i); | 985 | enable_irq(i); |
| 985 | 986 | ||
| 986 | /* Notify drivers */ | 987 | /* Notify drivers */ |
| 987 | notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL); | 988 | blocking_notifier_call_chain(&sleep_notifier_list, PBOOK_WAKE, NULL); |
| 988 | 989 | ||
| 989 | /* reenable ADB autopoll */ | 990 | /* reenable ADB autopoll */ |
| 990 | pmu_adb_autopoll(adb_dev_map); | 991 | pmu_adb_autopoll(adb_dev_map); |
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 6c0ba04bc57a..ab3faa702d58 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | static LIST_HEAD(wf_controls); | 52 | static LIST_HEAD(wf_controls); |
| 53 | static LIST_HEAD(wf_sensors); | 53 | static LIST_HEAD(wf_sensors); |
| 54 | static DEFINE_MUTEX(wf_lock); | 54 | static DEFINE_MUTEX(wf_lock); |
| 55 | static struct notifier_block *wf_client_list; | 55 | static BLOCKING_NOTIFIER_HEAD(wf_client_list); |
| 56 | static int wf_client_count; | 56 | static int wf_client_count; |
| 57 | static unsigned int wf_overtemp; | 57 | static unsigned int wf_overtemp; |
| 58 | static unsigned int wf_overtemp_counter; | 58 | static unsigned int wf_overtemp_counter; |
| @@ -68,7 +68,7 @@ static struct platform_device wf_platform_device = { | |||
| 68 | 68 | ||
| 69 | static inline void wf_notify(int event, void *param) | 69 | static inline void wf_notify(int event, void *param) |
| 70 | { | 70 | { |
| 71 | notifier_call_chain(&wf_client_list, event, param); | 71 | blocking_notifier_call_chain(&wf_client_list, event, param); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | int wf_critical_overtemp(void) | 74 | int wf_critical_overtemp(void) |
| @@ -398,7 +398,7 @@ int wf_register_client(struct notifier_block *nb) | |||
| 398 | struct wf_sensor *sr; | 398 | struct wf_sensor *sr; |
| 399 | 399 | ||
| 400 | mutex_lock(&wf_lock); | 400 | mutex_lock(&wf_lock); |
| 401 | rc = notifier_chain_register(&wf_client_list, nb); | 401 | rc = blocking_notifier_chain_register(&wf_client_list, nb); |
| 402 | if (rc != 0) | 402 | if (rc != 0) |
| 403 | goto bail; | 403 | goto bail; |
| 404 | wf_client_count++; | 404 | wf_client_count++; |
| @@ -417,7 +417,7 @@ EXPORT_SYMBOL_GPL(wf_register_client); | |||
| 417 | int wf_unregister_client(struct notifier_block *nb) | 417 | int wf_unregister_client(struct notifier_block *nb) |
| 418 | { | 418 | { |
| 419 | mutex_lock(&wf_lock); | 419 | mutex_lock(&wf_lock); |
| 420 | notifier_chain_unregister(&wf_client_list, nb); | 420 | blocking_notifier_chain_unregister(&wf_client_list, nb); |
| 421 | wf_client_count++; | 421 | wf_client_count++; |
| 422 | if (wf_client_count == 0) | 422 | if (wf_client_count == 0) |
| 423 | wf_stop_thread(); | 423 | wf_stop_thread(); |
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index ac43f98062fd..fd2aae150ccc 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig | |||
| @@ -127,6 +127,32 @@ config MD_RAID5 | |||
| 127 | 127 | ||
| 128 | If unsure, say Y. | 128 | If unsure, say Y. |
| 129 | 129 | ||
| 130 | config MD_RAID5_RESHAPE | ||
| 131 | bool "Support adding drives to a raid-5 array (experimental)" | ||
| 132 | depends on MD_RAID5 && EXPERIMENTAL | ||
| 133 | ---help--- | ||
| 134 | A RAID-5 set can be expanded by adding extra drives. This | ||
| 135 | requires "restriping" the array which means (almost) every | ||
| 136 | block must be written to a different place. | ||
| 137 | |||
| 138 | This option allows such restriping to be done while the array | ||
| 139 | is online. However it is still EXPERIMENTAL code. It should | ||
| 140 | work, but please be sure that you have backups. | ||
| 141 | |||
| 142 | You will need a version of mdadm newer than 2.3.1. During the | ||
| 143 | early stage of reshape there is a critical section where live data | ||
| 144 | is being over-written. A crash during this time needs extra care | ||
| 145 | for recovery. The newer mdadm takes a copy of the data in the | ||
| 146 | critical section and will restore it, if necessary, after a crash. | ||
| 147 | |||
| 148 | The mdadm usage is e.g. | ||
| 149 | mdadm --grow /dev/md1 --raid-disks=6 | ||
| 150 | to grow '/dev/md1' to having 6 disks. | ||
| 151 | |||
| 152 | Note: The array can only be expanded, not contracted. | ||
| 153 | There should be enough spares already present to make the new | ||
| 154 | array workable. | ||
| 155 | |||
| 130 | config MD_RAID6 | 156 | config MD_RAID6 |
| 131 | tristate "RAID-6 mode" | 157 | tristate "RAID-6 mode" |
| 132 | depends on BLK_DEV_MD | 158 | depends on BLK_DEV_MD |
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 259e86f26549..61a590bb6241 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
| @@ -518,6 +518,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 518 | char *ivopts; | 518 | char *ivopts; |
| 519 | unsigned int crypto_flags; | 519 | unsigned int crypto_flags; |
| 520 | unsigned int key_size; | 520 | unsigned int key_size; |
| 521 | unsigned long long tmpll; | ||
| 521 | 522 | ||
| 522 | if (argc != 5) { | 523 | if (argc != 5) { |
| 523 | ti->error = PFX "Not enough arguments"; | 524 | ti->error = PFX "Not enough arguments"; |
| @@ -633,15 +634,17 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 633 | goto bad5; | 634 | goto bad5; |
| 634 | } | 635 | } |
| 635 | 636 | ||
| 636 | if (sscanf(argv[2], SECTOR_FORMAT, &cc->iv_offset) != 1) { | 637 | if (sscanf(argv[2], "%llu", &tmpll) != 1) { |
| 637 | ti->error = PFX "Invalid iv_offset sector"; | 638 | ti->error = PFX "Invalid iv_offset sector"; |
| 638 | goto bad5; | 639 | goto bad5; |
| 639 | } | 640 | } |
| 641 | cc->iv_offset = tmpll; | ||
| 640 | 642 | ||
| 641 | if (sscanf(argv[4], SECTOR_FORMAT, &cc->start) != 1) { | 643 | if (sscanf(argv[4], "%llu", &tmpll) != 1) { |
| 642 | ti->error = PFX "Invalid device sector"; | 644 | ti->error = PFX "Invalid device sector"; |
| 643 | goto bad5; | 645 | goto bad5; |
| 644 | } | 646 | } |
| 647 | cc->start = tmpll; | ||
| 645 | 648 | ||
| 646 | if (dm_get_device(ti, argv[3], cc->start, ti->len, | 649 | if (dm_get_device(ti, argv[3], cc->start, ti->len, |
| 647 | dm_table_get_mode(ti->table), &cc->dev)) { | 650 | dm_table_get_mode(ti->table), &cc->dev)) { |
| @@ -885,8 +888,8 @@ static int crypt_status(struct dm_target *ti, status_type_t type, | |||
| 885 | result[sz++] = '-'; | 888 | result[sz++] = '-'; |
| 886 | } | 889 | } |
| 887 | 890 | ||
| 888 | DMEMIT(" " SECTOR_FORMAT " %s " SECTOR_FORMAT, | 891 | DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset, |
| 889 | cc->iv_offset, cc->dev->name, cc->start); | 892 | cc->dev->name, (unsigned long long)cc->start); |
| 890 | break; | 893 | break; |
| 891 | } | 894 | } |
| 892 | return 0; | 895 | return 0; |
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 442e2be6052e..8edd6435414d 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/devfs_fs_kernel.h> | 16 | #include <linux/devfs_fs_kernel.h> |
| 17 | #include <linux/dm-ioctl.h> | 17 | #include <linux/dm-ioctl.h> |
| 18 | #include <linux/hdreg.h> | ||
| 18 | 19 | ||
| 19 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
| 20 | 21 | ||
| @@ -244,9 +245,9 @@ static void __hash_remove(struct hash_cell *hc) | |||
| 244 | dm_table_put(table); | 245 | dm_table_put(table); |
| 245 | } | 246 | } |
| 246 | 247 | ||
| 247 | dm_put(hc->md); | ||
| 248 | if (hc->new_map) | 248 | if (hc->new_map) |
| 249 | dm_table_put(hc->new_map); | 249 | dm_table_put(hc->new_map); |
| 250 | dm_put(hc->md); | ||
| 250 | free_cell(hc); | 251 | free_cell(hc); |
| 251 | } | 252 | } |
| 252 | 253 | ||
| @@ -600,12 +601,22 @@ static int dev_create(struct dm_ioctl *param, size_t param_size) | |||
| 600 | */ | 601 | */ |
| 601 | static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) | 602 | static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) |
| 602 | { | 603 | { |
| 604 | struct mapped_device *md; | ||
| 605 | void *mdptr = NULL; | ||
| 606 | |||
| 603 | if (*param->uuid) | 607 | if (*param->uuid) |
| 604 | return __get_uuid_cell(param->uuid); | 608 | return __get_uuid_cell(param->uuid); |
| 605 | else if (*param->name) | 609 | |
| 610 | if (*param->name) | ||
| 606 | return __get_name_cell(param->name); | 611 | return __get_name_cell(param->name); |
| 607 | else | 612 | |
| 608 | return dm_get_mdptr(huge_decode_dev(param->dev)); | 613 | md = dm_get_md(huge_decode_dev(param->dev)); |
| 614 | if (md) { | ||
| 615 | mdptr = dm_get_mdptr(md); | ||
| 616 | dm_put(md); | ||
| 617 | } | ||
| 618 | |||
| 619 | return mdptr; | ||
| 609 | } | 620 | } |
| 610 | 621 | ||
| 611 | static struct mapped_device *find_device(struct dm_ioctl *param) | 622 | static struct mapped_device *find_device(struct dm_ioctl *param) |
| @@ -690,6 +701,54 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) | |||
| 690 | return dm_hash_rename(param->name, new_name); | 701 | return dm_hash_rename(param->name, new_name); |
| 691 | } | 702 | } |
| 692 | 703 | ||
| 704 | static int dev_set_geometry(struct dm_ioctl *param, size_t param_size) | ||
| 705 | { | ||
| 706 | int r = -EINVAL, x; | ||
| 707 | struct mapped_device *md; | ||
| 708 | struct hd_geometry geometry; | ||
| 709 | unsigned long indata[4]; | ||
| 710 | char *geostr = (char *) param + param->data_start; | ||
| 711 | |||
| 712 | md = find_device(param); | ||
| 713 | if (!md) | ||
| 714 | return -ENXIO; | ||
| 715 | |||
| 716 | if (geostr < (char *) (param + 1) || | ||
| 717 | invalid_str(geostr, (void *) param + param_size)) { | ||
| 718 | DMWARN("Invalid geometry supplied."); | ||
| 719 | goto out; | ||
| 720 | } | ||
| 721 | |||
| 722 | x = sscanf(geostr, "%lu %lu %lu %lu", indata, | ||
| 723 | indata + 1, indata + 2, indata + 3); | ||
| 724 | |||
| 725 | if (x != 4) { | ||
| 726 | DMWARN("Unable to interpret geometry settings."); | ||
| 727 | goto out; | ||
| 728 | } | ||
| 729 | |||
| 730 | if (indata[0] > 65535 || indata[1] > 255 || | ||
| 731 | indata[2] > 255 || indata[3] > ULONG_MAX) { | ||
| 732 | DMWARN("Geometry exceeds range limits."); | ||
| 733 | goto out; | ||
| 734 | } | ||
| 735 | |||
| 736 | geometry.cylinders = indata[0]; | ||
| 737 | geometry.heads = indata[1]; | ||
| 738 | geometry.sectors = indata[2]; | ||
| 739 | geometry.start = indata[3]; | ||
| 740 | |||
| 741 | r = dm_set_geometry(md, &geometry); | ||
| 742 | if (!r) | ||
| 743 | r = __dev_status(md, param); | ||
| 744 | |||
| 745 | param->data_size = 0; | ||
| 746 | |||
| 747 | out: | ||
| 748 | dm_put(md); | ||
| 749 | return r; | ||
| 750 | } | ||
| 751 | |||
| 693 | static int do_suspend(struct dm_ioctl *param) | 752 | static int do_suspend(struct dm_ioctl *param) |
| 694 | { | 753 | { |
| 695 | int r = 0; | 754 | int r = 0; |
| @@ -975,33 +1034,43 @@ static int table_load(struct dm_ioctl *param, size_t param_size) | |||
| 975 | int r; | 1034 | int r; |
| 976 | struct hash_cell *hc; | 1035 | struct hash_cell *hc; |
| 977 | struct dm_table *t; | 1036 | struct dm_table *t; |
| 1037 | struct mapped_device *md; | ||
| 978 | 1038 | ||
| 979 | r = dm_table_create(&t, get_mode(param), param->target_count); | 1039 | md = find_device(param); |
| 1040 | if (!md) | ||
| 1041 | return -ENXIO; | ||
| 1042 | |||
| 1043 | r = dm_table_create(&t, get_mode(param), param->target_count, md); | ||
| 980 | if (r) | 1044 | if (r) |
| 981 | return r; | 1045 | goto out; |
| 982 | 1046 | ||
| 983 | r = populate_table(t, param, param_size); | 1047 | r = populate_table(t, param, param_size); |
| 984 | if (r) { | 1048 | if (r) { |
| 985 | dm_table_put(t); | 1049 | dm_table_put(t); |
| 986 | return r; | 1050 | goto out; |
| 987 | } | 1051 | } |
| 988 | 1052 | ||
| 989 | down_write(&_hash_lock); | 1053 | down_write(&_hash_lock); |
| 990 | hc = __find_device_hash_cell(param); | 1054 | hc = dm_get_mdptr(md); |
| 991 | if (!hc) { | 1055 | if (!hc || hc->md != md) { |
| 992 | DMWARN("device doesn't appear to be in the dev hash table."); | 1056 | DMWARN("device has been removed from the dev hash table."); |
| 993 | up_write(&_hash_lock); | ||
| 994 | dm_table_put(t); | 1057 | dm_table_put(t); |
| 995 | return -ENXIO; | 1058 | up_write(&_hash_lock); |
| 1059 | r = -ENXIO; | ||
| 1060 | goto out; | ||
| 996 | } | 1061 | } |
| 997 | 1062 | ||
| 998 | if (hc->new_map) | 1063 | if (hc->new_map) |
| 999 | dm_table_put(hc->new_map); | 1064 | dm_table_put(hc->new_map); |
| 1000 | hc->new_map = t; | 1065 | hc->new_map = t; |
| 1066 | up_write(&_hash_lock); | ||
| 1067 | |||
| 1001 | param->flags |= DM_INACTIVE_PRESENT_FLAG; | 1068 | param->flags |= DM_INACTIVE_PRESENT_FLAG; |
| 1069 | r = __dev_status(md, param); | ||
| 1070 | |||
| 1071 | out: | ||
| 1072 | dm_put(md); | ||
| 1002 | 1073 | ||
| 1003 | r = __dev_status(hc->md, param); | ||
| 1004 | up_write(&_hash_lock); | ||
| 1005 | return r; | 1074 | return r; |
| 1006 | } | 1075 | } |
| 1007 | 1076 | ||
| @@ -1214,7 +1283,8 @@ static ioctl_fn lookup_ioctl(unsigned int cmd) | |||
| 1214 | 1283 | ||
| 1215 | {DM_LIST_VERSIONS_CMD, list_versions}, | 1284 | {DM_LIST_VERSIONS_CMD, list_versions}, |
| 1216 | 1285 | ||
| 1217 | {DM_TARGET_MSG_CMD, target_message} | 1286 | {DM_TARGET_MSG_CMD, target_message}, |
| 1287 | {DM_DEV_SET_GEOMETRY_CMD, dev_set_geometry} | ||
| 1218 | }; | 1288 | }; |
| 1219 | 1289 | ||
| 1220 | return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; | 1290 | return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; |
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 6a2cd5dc8a63..daf586c0898d 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c | |||
| @@ -26,6 +26,7 @@ struct linear_c { | |||
| 26 | static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) | 26 | static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) |
| 27 | { | 27 | { |
| 28 | struct linear_c *lc; | 28 | struct linear_c *lc; |
| 29 | unsigned long long tmp; | ||
| 29 | 30 | ||
| 30 | if (argc != 2) { | 31 | if (argc != 2) { |
| 31 | ti->error = "dm-linear: Invalid argument count"; | 32 | ti->error = "dm-linear: Invalid argument count"; |
| @@ -38,10 +39,11 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 38 | return -ENOMEM; | 39 | return -ENOMEM; |
| 39 | } | 40 | } |
| 40 | 41 | ||
| 41 | if (sscanf(argv[1], SECTOR_FORMAT, &lc->start) != 1) { | 42 | if (sscanf(argv[1], "%llu", &tmp) != 1) { |
| 42 | ti->error = "dm-linear: Invalid device sector"; | 43 | ti->error = "dm-linear: Invalid device sector"; |
| 43 | goto bad; | 44 | goto bad; |
| 44 | } | 45 | } |
| 46 | lc->start = tmp; | ||
| 45 | 47 | ||
| 46 | if (dm_get_device(ti, argv[0], lc->start, ti->len, | 48 | if (dm_get_device(ti, argv[0], lc->start, ti->len, |
| 47 | dm_table_get_mode(ti->table), &lc->dev)) { | 49 | dm_table_get_mode(ti->table), &lc->dev)) { |
| @@ -87,8 +89,8 @@ static int linear_status(struct dm_target *ti, status_type_t type, | |||
| 87 | break; | 89 | break; |
| 88 | 90 | ||
| 89 | case STATUSTYPE_TABLE: | 91 | case STATUSTYPE_TABLE: |
| 90 | snprintf(result, maxlen, "%s " SECTOR_FORMAT, lc->dev->name, | 92 | snprintf(result, maxlen, "%s %llu", lc->dev->name, |
| 91 | lc->start); | 93 | (unsigned long long)lc->start); |
| 92 | break; | 94 | break; |
| 93 | } | 95 | } |
| 94 | return 0; | 96 | return 0; |
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 4e90f231fbfb..d12cf3e5e076 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
| @@ -402,9 +402,21 @@ static void rh_dec(struct region_hash *rh, region_t region) | |||
| 402 | 402 | ||
| 403 | spin_lock_irqsave(&rh->region_lock, flags); | 403 | spin_lock_irqsave(&rh->region_lock, flags); |
| 404 | if (atomic_dec_and_test(®->pending)) { | 404 | if (atomic_dec_and_test(®->pending)) { |
| 405 | /* | ||
| 406 | * There is no pending I/O for this region. | ||
| 407 | * We can move the region to corresponding list for next action. | ||
| 408 | * At this point, the region is not yet connected to any list. | ||
| 409 | * | ||
| 410 | * If the state is RH_NOSYNC, the region should be kept off | ||
| 411 | * from clean list. | ||
| 412 | * The hash entry for RH_NOSYNC will remain in memory | ||
| 413 | * until the region is recovered or the map is reloaded. | ||
| 414 | */ | ||
| 415 | |||
| 416 | /* do nothing for RH_NOSYNC */ | ||
| 405 | if (reg->state == RH_RECOVERING) { | 417 | if (reg->state == RH_RECOVERING) { |
| 406 | list_add_tail(®->list, &rh->quiesced_regions); | 418 | list_add_tail(®->list, &rh->quiesced_regions); |
| 407 | } else { | 419 | } else if (reg->state == RH_DIRTY) { |
| 408 | reg->state = RH_CLEAN; | 420 | reg->state = RH_CLEAN; |
| 409 | list_add(®->list, &rh->clean_regions); | 421 | list_add(®->list, &rh->clean_regions); |
| 410 | } | 422 | } |
| @@ -922,9 +934,9 @@ static inline int _check_region_size(struct dm_target *ti, uint32_t size) | |||
| 922 | static int get_mirror(struct mirror_set *ms, struct dm_target *ti, | 934 | static int get_mirror(struct mirror_set *ms, struct dm_target *ti, |
| 923 | unsigned int mirror, char **argv) | 935 | unsigned int mirror, char **argv) |
| 924 | { | 936 | { |
| 925 | sector_t offset; | 937 | unsigned long long offset; |
| 926 | 938 | ||
| 927 | if (sscanf(argv[1], SECTOR_FORMAT, &offset) != 1) { | 939 | if (sscanf(argv[1], "%llu", &offset) != 1) { |
| 928 | ti->error = "dm-mirror: Invalid offset"; | 940 | ti->error = "dm-mirror: Invalid offset"; |
| 929 | return -EINVAL; | 941 | return -EINVAL; |
| 930 | } | 942 | } |
| @@ -1191,16 +1203,17 @@ static int mirror_status(struct dm_target *ti, status_type_t type, | |||
| 1191 | for (m = 0; m < ms->nr_mirrors; m++) | 1203 | for (m = 0; m < ms->nr_mirrors; m++) |
| 1192 | DMEMIT("%s ", ms->mirror[m].dev->name); | 1204 | DMEMIT("%s ", ms->mirror[m].dev->name); |
| 1193 | 1205 | ||
| 1194 | DMEMIT(SECTOR_FORMAT "/" SECTOR_FORMAT, | 1206 | DMEMIT("%llu/%llu", |
| 1195 | ms->rh.log->type->get_sync_count(ms->rh.log), | 1207 | (unsigned long long)ms->rh.log->type-> |
| 1196 | ms->nr_regions); | 1208 | get_sync_count(ms->rh.log), |
| 1209 | (unsigned long long)ms->nr_regions); | ||
| 1197 | break; | 1210 | break; |
| 1198 | 1211 | ||
| 1199 | case STATUSTYPE_TABLE: | 1212 | case STATUSTYPE_TABLE: |
| 1200 | DMEMIT("%d ", ms->nr_mirrors); | 1213 | DMEMIT("%d ", ms->nr_mirrors); |
| 1201 | for (m = 0; m < ms->nr_mirrors; m++) | 1214 | for (m = 0; m < ms->nr_mirrors; m++) |
| 1202 | DMEMIT("%s " SECTOR_FORMAT " ", | 1215 | DMEMIT("%s %llu ", ms->mirror[m].dev->name, |
| 1203 | ms->mirror[m].dev->name, ms->mirror[m].offset); | 1216 | (unsigned long long)ms->mirror[m].offset); |
| 1204 | } | 1217 | } |
| 1205 | 1218 | ||
| 1206 | return 0; | 1219 | return 0; |
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 7401540086df..08312b46463a 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
| @@ -49,11 +49,26 @@ struct pending_exception { | |||
| 49 | struct bio_list snapshot_bios; | 49 | struct bio_list snapshot_bios; |
| 50 | 50 | ||
| 51 | /* | 51 | /* |
| 52 | * Other pending_exceptions that are processing this | 52 | * Short-term queue of pending exceptions prior to submission. |
| 53 | * chunk. When this list is empty, we know we can | ||
| 54 | * complete the origins. | ||
| 55 | */ | 53 | */ |
| 56 | struct list_head siblings; | 54 | struct list_head list; |
| 55 | |||
| 56 | /* | ||
| 57 | * The primary pending_exception is the one that holds | ||
| 58 | * the sibling_count and the list of origin_bios for a | ||
| 59 | * group of pending_exceptions. It is always last to get freed. | ||
| 60 | * These fields get set up when writing to the origin. | ||
| 61 | */ | ||
| 62 | struct pending_exception *primary_pe; | ||
| 63 | |||
| 64 | /* | ||
| 65 | * Number of pending_exceptions processing this chunk. | ||
| 66 | * When this drops to zero we must complete the origin bios. | ||
| 67 | * If incrementing or decrementing this, hold pe->snap->lock for | ||
| 68 | * the sibling concerned and not pe->primary_pe->snap->lock unless | ||
| 69 | * they are the same. | ||
| 70 | */ | ||
| 71 | atomic_t sibling_count; | ||
| 57 | 72 | ||
| 58 | /* Pointer back to snapshot context */ | 73 | /* Pointer back to snapshot context */ |
| 59 | struct dm_snapshot *snap; | 74 | struct dm_snapshot *snap; |
| @@ -377,6 +392,8 @@ static void read_snapshot_metadata(struct dm_snapshot *s) | |||
| 377 | down_write(&s->lock); | 392 | down_write(&s->lock); |
| 378 | s->valid = 0; | 393 | s->valid = 0; |
| 379 | up_write(&s->lock); | 394 | up_write(&s->lock); |
| 395 | |||
| 396 | dm_table_event(s->table); | ||
| 380 | } | 397 | } |
| 381 | } | 398 | } |
| 382 | 399 | ||
| @@ -542,8 +559,12 @@ static void snapshot_dtr(struct dm_target *ti) | |||
| 542 | { | 559 | { |
| 543 | struct dm_snapshot *s = (struct dm_snapshot *) ti->private; | 560 | struct dm_snapshot *s = (struct dm_snapshot *) ti->private; |
| 544 | 561 | ||
| 562 | /* Prevent further origin writes from using this snapshot. */ | ||
| 563 | /* After this returns there can be no new kcopyd jobs. */ | ||
| 545 | unregister_snapshot(s); | 564 | unregister_snapshot(s); |
| 546 | 565 | ||
| 566 | kcopyd_client_destroy(s->kcopyd_client); | ||
| 567 | |||
| 547 | exit_exception_table(&s->pending, pending_cache); | 568 | exit_exception_table(&s->pending, pending_cache); |
| 548 | exit_exception_table(&s->complete, exception_cache); | 569 | exit_exception_table(&s->complete, exception_cache); |
| 549 | 570 | ||
| @@ -552,7 +573,7 @@ static void snapshot_dtr(struct dm_target *ti) | |||
| 552 | 573 | ||
| 553 | dm_put_device(ti, s->origin); | 574 | dm_put_device(ti, s->origin); |
| 554 | dm_put_device(ti, s->cow); | 575 | dm_put_device(ti, s->cow); |
| 555 | kcopyd_client_destroy(s->kcopyd_client); | 576 | |
| 556 | kfree(s); | 577 | kfree(s); |
| 557 | } | 578 | } |
| 558 | 579 | ||
| @@ -586,78 +607,117 @@ static void error_bios(struct bio *bio) | |||
| 586 | } | 607 | } |
| 587 | } | 608 | } |
| 588 | 609 | ||
| 610 | static inline void error_snapshot_bios(struct pending_exception *pe) | ||
| 611 | { | ||
| 612 | error_bios(bio_list_get(&pe->snapshot_bios)); | ||
| 613 | } | ||
| 614 | |||
| 589 | static struct bio *__flush_bios(struct pending_exception *pe) | 615 | static struct bio *__flush_bios(struct pending_exception *pe) |
| 590 | { | 616 | { |
| 591 | struct pending_exception *sibling; | 617 | /* |
| 618 | * If this pe is involved in a write to the origin and | ||
| 619 | * it is the last sibling to complete then release | ||
| 620 | * the bios for the original write to the origin. | ||
| 621 | */ | ||
| 622 | |||
| 623 | if (pe->primary_pe && | ||
| 624 | atomic_dec_and_test(&pe->primary_pe->sibling_count)) | ||
| 625 | return bio_list_get(&pe->primary_pe->origin_bios); | ||
| 626 | |||
| 627 | return NULL; | ||
| 628 | } | ||
| 629 | |||
| 630 | static void __invalidate_snapshot(struct dm_snapshot *s, | ||
| 631 | struct pending_exception *pe, int err) | ||
| 632 | { | ||
| 633 | if (!s->valid) | ||
| 634 | return; | ||
| 592 | 635 | ||
| 593 | if (list_empty(&pe->siblings)) | 636 | if (err == -EIO) |
| 594 | return bio_list_get(&pe->origin_bios); | 637 | DMERR("Invalidating snapshot: Error reading/writing."); |
| 638 | else if (err == -ENOMEM) | ||
| 639 | DMERR("Invalidating snapshot: Unable to allocate exception."); | ||
| 595 | 640 | ||
| 596 | sibling = list_entry(pe->siblings.next, | 641 | if (pe) |
| 597 | struct pending_exception, siblings); | 642 | remove_exception(&pe->e); |
| 598 | 643 | ||
| 599 | list_del(&pe->siblings); | 644 | if (s->store.drop_snapshot) |
| 645 | s->store.drop_snapshot(&s->store); | ||
| 600 | 646 | ||
| 601 | /* This is fine as long as kcopyd is single-threaded. If kcopyd | 647 | s->valid = 0; |
| 602 | * becomes multi-threaded, we'll need some locking here. | ||
| 603 | */ | ||
| 604 | bio_list_merge(&sibling->origin_bios, &pe->origin_bios); | ||
| 605 | 648 | ||
| 606 | return NULL; | 649 | dm_table_event(s->table); |
| 607 | } | 650 | } |
| 608 | 651 | ||
| 609 | static void pending_complete(struct pending_exception *pe, int success) | 652 | static void pending_complete(struct pending_exception *pe, int success) |
| 610 | { | 653 | { |
| 611 | struct exception *e; | 654 | struct exception *e; |
| 655 | struct pending_exception *primary_pe; | ||
| 612 | struct dm_snapshot *s = pe->snap; | 656 | struct dm_snapshot *s = pe->snap; |
| 613 | struct bio *flush = NULL; | 657 | struct bio *flush = NULL; |
| 614 | 658 | ||
| 615 | if (success) { | 659 | if (!success) { |
| 616 | e = alloc_exception(); | 660 | /* Read/write error - snapshot is unusable */ |
| 617 | if (!e) { | ||
| 618 | DMWARN("Unable to allocate exception."); | ||
| 619 | down_write(&s->lock); | ||
| 620 | s->store.drop_snapshot(&s->store); | ||
| 621 | s->valid = 0; | ||
| 622 | flush = __flush_bios(pe); | ||
| 623 | up_write(&s->lock); | ||
| 624 | |||
| 625 | error_bios(bio_list_get(&pe->snapshot_bios)); | ||
| 626 | goto out; | ||
| 627 | } | ||
| 628 | *e = pe->e; | ||
| 629 | |||
| 630 | /* | ||
| 631 | * Add a proper exception, and remove the | ||
| 632 | * in-flight exception from the list. | ||
| 633 | */ | ||
| 634 | down_write(&s->lock); | 661 | down_write(&s->lock); |
| 635 | insert_exception(&s->complete, e); | 662 | __invalidate_snapshot(s, pe, -EIO); |
| 636 | remove_exception(&pe->e); | ||
| 637 | flush = __flush_bios(pe); | 663 | flush = __flush_bios(pe); |
| 638 | |||
| 639 | /* Submit any pending write bios */ | ||
| 640 | up_write(&s->lock); | 664 | up_write(&s->lock); |
| 641 | 665 | ||
| 642 | flush_bios(bio_list_get(&pe->snapshot_bios)); | 666 | error_snapshot_bios(pe); |
| 643 | } else { | 667 | goto out; |
| 644 | /* Read/write error - snapshot is unusable */ | 668 | } |
| 669 | |||
| 670 | e = alloc_exception(); | ||
| 671 | if (!e) { | ||
| 645 | down_write(&s->lock); | 672 | down_write(&s->lock); |
| 646 | if (s->valid) | 673 | __invalidate_snapshot(s, pe, -ENOMEM); |
| 647 | DMERR("Error reading/writing snapshot"); | ||
| 648 | s->store.drop_snapshot(&s->store); | ||
| 649 | s->valid = 0; | ||
| 650 | remove_exception(&pe->e); | ||
| 651 | flush = __flush_bios(pe); | 674 | flush = __flush_bios(pe); |
| 652 | up_write(&s->lock); | 675 | up_write(&s->lock); |
| 653 | 676 | ||
| 654 | error_bios(bio_list_get(&pe->snapshot_bios)); | 677 | error_snapshot_bios(pe); |
| 678 | goto out; | ||
| 679 | } | ||
| 680 | *e = pe->e; | ||
| 655 | 681 | ||
| 656 | dm_table_event(s->table); | 682 | /* |
| 683 | * Add a proper exception, and remove the | ||
| 684 | * in-flight exception from the list. | ||
| 685 | */ | ||
| 686 | down_write(&s->lock); | ||
| 687 | if (!s->valid) { | ||
| 688 | flush = __flush_bios(pe); | ||
| 689 | up_write(&s->lock); | ||
| 690 | |||
| 691 | free_exception(e); | ||
| 692 | |||
| 693 | error_snapshot_bios(pe); | ||
| 694 | goto out; | ||
| 657 | } | 695 | } |
| 658 | 696 | ||
| 697 | insert_exception(&s->complete, e); | ||
| 698 | remove_exception(&pe->e); | ||
| 699 | flush = __flush_bios(pe); | ||
| 700 | |||
| 701 | up_write(&s->lock); | ||
| 702 | |||
| 703 | /* Submit any pending write bios */ | ||
| 704 | flush_bios(bio_list_get(&pe->snapshot_bios)); | ||
| 705 | |||
| 659 | out: | 706 | out: |
| 660 | free_pending_exception(pe); | 707 | primary_pe = pe->primary_pe; |
| 708 | |||
| 709 | /* | ||
| 710 | * Free the pe if it's not linked to an origin write or if | ||
| 711 | * it's not itself a primary pe. | ||
| 712 | */ | ||
| 713 | if (!primary_pe || primary_pe != pe) | ||
| 714 | free_pending_exception(pe); | ||
| 715 | |||
| 716 | /* | ||
| 717 | * Free the primary pe if nothing references it. | ||
| 718 | */ | ||
| 719 | if (primary_pe && !atomic_read(&primary_pe->sibling_count)) | ||
| 720 | free_pending_exception(primary_pe); | ||
| 661 | 721 | ||
| 662 | if (flush) | 722 | if (flush) |
| 663 | flush_bios(flush); | 723 | flush_bios(flush); |
| @@ -734,38 +794,45 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio) | |||
| 734 | if (e) { | 794 | if (e) { |
| 735 | /* cast the exception to a pending exception */ | 795 | /* cast the exception to a pending exception */ |
| 736 | pe = container_of(e, struct pending_exception, e); | 796 | pe = container_of(e, struct pending_exception, e); |
| 797 | goto out; | ||
| 798 | } | ||
| 737 | 799 | ||
| 738 | } else { | 800 | /* |
| 739 | /* | 801 | * Create a new pending exception, we don't want |
| 740 | * Create a new pending exception, we don't want | 802 | * to hold the lock while we do this. |
| 741 | * to hold the lock while we do this. | 803 | */ |
| 742 | */ | 804 | up_write(&s->lock); |
| 743 | up_write(&s->lock); | 805 | pe = alloc_pending_exception(); |
| 744 | pe = alloc_pending_exception(); | 806 | down_write(&s->lock); |
| 745 | down_write(&s->lock); | ||
| 746 | 807 | ||
| 747 | e = lookup_exception(&s->pending, chunk); | 808 | if (!s->valid) { |
| 748 | if (e) { | 809 | free_pending_exception(pe); |
| 749 | free_pending_exception(pe); | 810 | return NULL; |
| 750 | pe = container_of(e, struct pending_exception, e); | 811 | } |
| 751 | } else { | ||
| 752 | pe->e.old_chunk = chunk; | ||
| 753 | bio_list_init(&pe->origin_bios); | ||
| 754 | bio_list_init(&pe->snapshot_bios); | ||
| 755 | INIT_LIST_HEAD(&pe->siblings); | ||
| 756 | pe->snap = s; | ||
| 757 | pe->started = 0; | ||
| 758 | |||
| 759 | if (s->store.prepare_exception(&s->store, &pe->e)) { | ||
| 760 | free_pending_exception(pe); | ||
| 761 | s->valid = 0; | ||
| 762 | return NULL; | ||
| 763 | } | ||
| 764 | 812 | ||
| 765 | insert_exception(&s->pending, &pe->e); | 813 | e = lookup_exception(&s->pending, chunk); |
| 766 | } | 814 | if (e) { |
| 815 | free_pending_exception(pe); | ||
| 816 | pe = container_of(e, struct pending_exception, e); | ||
| 817 | goto out; | ||
| 818 | } | ||
| 819 | |||
| 820 | pe->e.old_chunk = chunk; | ||
| 821 | bio_list_init(&pe->origin_bios); | ||
| 822 | bio_list_init(&pe->snapshot_bios); | ||
| 823 | pe->primary_pe = NULL; | ||
| 824 | atomic_set(&pe->sibling_count, 1); | ||
| 825 | pe->snap = s; | ||
| 826 | pe->started = 0; | ||
| 827 | |||
| 828 | if (s->store.prepare_exception(&s->store, &pe->e)) { | ||
| 829 | free_pending_exception(pe); | ||
| 830 | return NULL; | ||
| 767 | } | 831 | } |
| 768 | 832 | ||
| 833 | insert_exception(&s->pending, &pe->e); | ||
| 834 | |||
| 835 | out: | ||
| 769 | return pe; | 836 | return pe; |
| 770 | } | 837 | } |
| 771 | 838 | ||
| @@ -782,13 +849,15 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
| 782 | { | 849 | { |
| 783 | struct exception *e; | 850 | struct exception *e; |
| 784 | struct dm_snapshot *s = (struct dm_snapshot *) ti->private; | 851 | struct dm_snapshot *s = (struct dm_snapshot *) ti->private; |
| 852 | int copy_needed = 0; | ||
| 785 | int r = 1; | 853 | int r = 1; |
| 786 | chunk_t chunk; | 854 | chunk_t chunk; |
| 787 | struct pending_exception *pe; | 855 | struct pending_exception *pe = NULL; |
| 788 | 856 | ||
| 789 | chunk = sector_to_chunk(s, bio->bi_sector); | 857 | chunk = sector_to_chunk(s, bio->bi_sector); |
| 790 | 858 | ||
| 791 | /* Full snapshots are not usable */ | 859 | /* Full snapshots are not usable */ |
| 860 | /* To get here the table must be live so s->active is always set. */ | ||
| 792 | if (!s->valid) | 861 | if (!s->valid) |
| 793 | return -EIO; | 862 | return -EIO; |
| 794 | 863 | ||
| @@ -806,36 +875,41 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
| 806 | * to copy an exception */ | 875 | * to copy an exception */ |
| 807 | down_write(&s->lock); | 876 | down_write(&s->lock); |
| 808 | 877 | ||
| 878 | if (!s->valid) { | ||
| 879 | r = -EIO; | ||
| 880 | goto out_unlock; | ||
| 881 | } | ||
| 882 | |||
| 809 | /* If the block is already remapped - use that, else remap it */ | 883 | /* If the block is already remapped - use that, else remap it */ |
| 810 | e = lookup_exception(&s->complete, chunk); | 884 | e = lookup_exception(&s->complete, chunk); |
| 811 | if (e) { | 885 | if (e) { |
| 812 | remap_exception(s, e, bio); | 886 | remap_exception(s, e, bio); |
| 813 | up_write(&s->lock); | 887 | goto out_unlock; |
| 814 | 888 | } | |
| 815 | } else { | 889 | |
| 816 | pe = __find_pending_exception(s, bio); | 890 | pe = __find_pending_exception(s, bio); |
| 817 | 891 | if (!pe) { | |
| 818 | if (!pe) { | 892 | __invalidate_snapshot(s, pe, -ENOMEM); |
| 819 | if (s->store.drop_snapshot) | 893 | r = -EIO; |
| 820 | s->store.drop_snapshot(&s->store); | 894 | goto out_unlock; |
| 821 | s->valid = 0; | 895 | } |
| 822 | r = -EIO; | 896 | |
| 823 | up_write(&s->lock); | 897 | remap_exception(s, &pe->e, bio); |
| 824 | } else { | 898 | bio_list_add(&pe->snapshot_bios, bio); |
| 825 | remap_exception(s, &pe->e, bio); | 899 | |
| 826 | bio_list_add(&pe->snapshot_bios, bio); | 900 | if (!pe->started) { |
| 827 | 901 | /* this is protected by snap->lock */ | |
| 828 | if (!pe->started) { | 902 | pe->started = 1; |
| 829 | /* this is protected by snap->lock */ | 903 | copy_needed = 1; |
| 830 | pe->started = 1; | ||
| 831 | up_write(&s->lock); | ||
| 832 | start_copy(pe); | ||
| 833 | } else | ||
| 834 | up_write(&s->lock); | ||
| 835 | r = 0; | ||
| 836 | } | ||
| 837 | } | 904 | } |
| 838 | 905 | ||
| 906 | r = 0; | ||
| 907 | |||
| 908 | out_unlock: | ||
| 909 | up_write(&s->lock); | ||
| 910 | |||
| 911 | if (copy_needed) | ||
| 912 | start_copy(pe); | ||
| 839 | } else { | 913 | } else { |
| 840 | /* | 914 | /* |
| 841 | * FIXME: this read path scares me because we | 915 | * FIXME: this read path scares me because we |
| @@ -847,6 +921,11 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio, | |||
| 847 | /* Do reads */ | 921 | /* Do reads */ |
| 848 | down_read(&s->lock); | 922 | down_read(&s->lock); |
| 849 | 923 | ||
| 924 | if (!s->valid) { | ||
| 925 | up_read(&s->lock); | ||
| 926 | return -EIO; | ||
| 927 | } | ||
| 928 | |||
| 850 | /* See if it it has been remapped */ | 929 | /* See if it it has been remapped */ |
| 851 | e = lookup_exception(&s->complete, chunk); | 930 | e = lookup_exception(&s->complete, chunk); |
| 852 | if (e) | 931 | if (e) |
| @@ -884,9 +963,9 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, | |||
| 884 | snap->store.fraction_full(&snap->store, | 963 | snap->store.fraction_full(&snap->store, |
| 885 | &numerator, | 964 | &numerator, |
| 886 | &denominator); | 965 | &denominator); |
| 887 | snprintf(result, maxlen, | 966 | snprintf(result, maxlen, "%llu/%llu", |
| 888 | SECTOR_FORMAT "/" SECTOR_FORMAT, | 967 | (unsigned long long)numerator, |
| 889 | numerator, denominator); | 968 | (unsigned long long)denominator); |
| 890 | } | 969 | } |
| 891 | else | 970 | else |
| 892 | snprintf(result, maxlen, "Unknown"); | 971 | snprintf(result, maxlen, "Unknown"); |
| @@ -899,9 +978,10 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, | |||
| 899 | * to make private copies if the output is to | 978 | * to make private copies if the output is to |
| 900 | * make sense. | 979 | * make sense. |
| 901 | */ | 980 | */ |
| 902 | snprintf(result, maxlen, "%s %s %c " SECTOR_FORMAT, | 981 | snprintf(result, maxlen, "%s %s %c %llu", |
| 903 | snap->origin->name, snap->cow->name, | 982 | snap->origin->name, snap->cow->name, |
| 904 | snap->type, snap->chunk_size); | 983 | snap->type, |
| 984 | (unsigned long long)snap->chunk_size); | ||
| 905 | break; | 985 | break; |
| 906 | } | 986 | } |
| 907 | 987 | ||
| @@ -911,40 +991,27 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, | |||
| 911 | /*----------------------------------------------------------------- | 991 | /*----------------------------------------------------------------- |
| 912 | * Origin methods | 992 | * Origin methods |
| 913 | *---------------------------------------------------------------*/ | 993 | *---------------------------------------------------------------*/ |
| 914 | static void list_merge(struct list_head *l1, struct list_head *l2) | ||
| 915 | { | ||
| 916 | struct list_head *l1_n, *l2_p; | ||
| 917 | |||
| 918 | l1_n = l1->next; | ||
| 919 | l2_p = l2->prev; | ||
| 920 | |||
| 921 | l1->next = l2; | ||
| 922 | l2->prev = l1; | ||
| 923 | |||
| 924 | l2_p->next = l1_n; | ||
| 925 | l1_n->prev = l2_p; | ||
| 926 | } | ||
| 927 | |||
| 928 | static int __origin_write(struct list_head *snapshots, struct bio *bio) | 994 | static int __origin_write(struct list_head *snapshots, struct bio *bio) |
| 929 | { | 995 | { |
| 930 | int r = 1, first = 1; | 996 | int r = 1, first = 0; |
| 931 | struct dm_snapshot *snap; | 997 | struct dm_snapshot *snap; |
| 932 | struct exception *e; | 998 | struct exception *e; |
| 933 | struct pending_exception *pe, *last = NULL; | 999 | struct pending_exception *pe, *next_pe, *primary_pe = NULL; |
| 934 | chunk_t chunk; | 1000 | chunk_t chunk; |
| 1001 | LIST_HEAD(pe_queue); | ||
| 935 | 1002 | ||
| 936 | /* Do all the snapshots on this origin */ | 1003 | /* Do all the snapshots on this origin */ |
| 937 | list_for_each_entry (snap, snapshots, list) { | 1004 | list_for_each_entry (snap, snapshots, list) { |
| 938 | 1005 | ||
| 1006 | down_write(&snap->lock); | ||
| 1007 | |||
| 939 | /* Only deal with valid and active snapshots */ | 1008 | /* Only deal with valid and active snapshots */ |
| 940 | if (!snap->valid || !snap->active) | 1009 | if (!snap->valid || !snap->active) |
| 941 | continue; | 1010 | goto next_snapshot; |
| 942 | 1011 | ||
| 943 | /* Nothing to do if writing beyond end of snapshot */ | 1012 | /* Nothing to do if writing beyond end of snapshot */ |
| 944 | if (bio->bi_sector >= dm_table_get_size(snap->table)) | 1013 | if (bio->bi_sector >= dm_table_get_size(snap->table)) |
| 945 | continue; | 1014 | goto next_snapshot; |
| 946 | |||
| 947 | down_write(&snap->lock); | ||
| 948 | 1015 | ||
| 949 | /* | 1016 | /* |
| 950 | * Remember, different snapshots can have | 1017 | * Remember, different snapshots can have |
| @@ -956,49 +1023,75 @@ static int __origin_write(struct list_head *snapshots, struct bio *bio) | |||
| 956 | * Check exception table to see if block | 1023 | * Check exception table to see if block |
| 957 | * is already remapped in this snapshot | 1024 | * is already remapped in this snapshot |
| 958 | * and trigger an exception if not. | 1025 | * and trigger an exception if not. |
| 1026 | * | ||
| 1027 | * sibling_count is initialised to 1 so pending_complete() | ||
| 1028 | * won't destroy the primary_pe while we're inside this loop. | ||
| 959 | */ | 1029 | */ |
| 960 | e = lookup_exception(&snap->complete, chunk); | 1030 | e = lookup_exception(&snap->complete, chunk); |
| 961 | if (!e) { | 1031 | if (e) |
| 962 | pe = __find_pending_exception(snap, bio); | 1032 | goto next_snapshot; |
| 963 | if (!pe) { | 1033 | |
| 964 | snap->store.drop_snapshot(&snap->store); | 1034 | pe = __find_pending_exception(snap, bio); |
| 965 | snap->valid = 0; | 1035 | if (!pe) { |
| 966 | 1036 | __invalidate_snapshot(snap, pe, ENOMEM); | |
| 967 | } else { | 1037 | goto next_snapshot; |
| 968 | if (last) | 1038 | } |
| 969 | list_merge(&pe->siblings, | 1039 | |
| 970 | &last->siblings); | 1040 | if (!primary_pe) { |
| 971 | 1041 | /* | |
| 972 | last = pe; | 1042 | * Either every pe here has same |
| 973 | r = 0; | 1043 | * primary_pe or none has one yet. |
| 1044 | */ | ||
| 1045 | if (pe->primary_pe) | ||
| 1046 | primary_pe = pe->primary_pe; | ||
| 1047 | else { | ||
| 1048 | primary_pe = pe; | ||
| 1049 | first = 1; | ||
| 974 | } | 1050 | } |
| 1051 | |||
| 1052 | bio_list_add(&primary_pe->origin_bios, bio); | ||
| 1053 | |||
| 1054 | r = 0; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | if (!pe->primary_pe) { | ||
| 1058 | atomic_inc(&primary_pe->sibling_count); | ||
| 1059 | pe->primary_pe = primary_pe; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | if (!pe->started) { | ||
| 1063 | pe->started = 1; | ||
| 1064 | list_add_tail(&pe->list, &pe_queue); | ||
| 975 | } | 1065 | } |
| 976 | 1066 | ||
| 1067 | next_snapshot: | ||
| 977 | up_write(&snap->lock); | 1068 | up_write(&snap->lock); |
| 978 | } | 1069 | } |
| 979 | 1070 | ||
| 1071 | if (!primary_pe) | ||
| 1072 | goto out; | ||
| 1073 | |||
| 980 | /* | 1074 | /* |
| 981 | * Now that we have a complete pe list we can start the copying. | 1075 | * If this is the first time we're processing this chunk and |
| 1076 | * sibling_count is now 1 it means all the pending exceptions | ||
| 1077 | * got completed while we were in the loop above, so it falls to | ||
| 1078 | * us here to remove the primary_pe and submit any origin_bios. | ||
| 982 | */ | 1079 | */ |
| 983 | if (last) { | 1080 | |
| 984 | pe = last; | 1081 | if (first && atomic_dec_and_test(&primary_pe->sibling_count)) { |
| 985 | do { | 1082 | flush_bios(bio_list_get(&primary_pe->origin_bios)); |
| 986 | down_write(&pe->snap->lock); | 1083 | free_pending_exception(primary_pe); |
| 987 | if (first) | 1084 | /* If we got here, pe_queue is necessarily empty. */ |
| 988 | bio_list_add(&pe->origin_bios, bio); | 1085 | goto out; |
| 989 | if (!pe->started) { | ||
| 990 | pe->started = 1; | ||
| 991 | up_write(&pe->snap->lock); | ||
| 992 | start_copy(pe); | ||
| 993 | } else | ||
| 994 | up_write(&pe->snap->lock); | ||
| 995 | first = 0; | ||
| 996 | pe = list_entry(pe->siblings.next, | ||
| 997 | struct pending_exception, siblings); | ||
| 998 | |||
| 999 | } while (pe != last); | ||
| 1000 | } | 1086 | } |
| 1001 | 1087 | ||
| 1088 | /* | ||
| 1089 | * Now that we have a complete pe list we can start the copying. | ||
| 1090 | */ | ||
| 1091 | list_for_each_entry_safe(pe, next_pe, &pe_queue, list) | ||
| 1092 | start_copy(pe); | ||
| 1093 | |||
| 1094 | out: | ||
| 1002 | return r; | 1095 | return r; |
| 1003 | } | 1096 | } |
| 1004 | 1097 | ||
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 697aacafb02a..08328a8f5a3c 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c | |||
| @@ -49,9 +49,9 @@ static inline struct stripe_c *alloc_context(unsigned int stripes) | |||
| 49 | static int get_stripe(struct dm_target *ti, struct stripe_c *sc, | 49 | static int get_stripe(struct dm_target *ti, struct stripe_c *sc, |
| 50 | unsigned int stripe, char **argv) | 50 | unsigned int stripe, char **argv) |
| 51 | { | 51 | { |
| 52 | sector_t start; | 52 | unsigned long long start; |
| 53 | 53 | ||
| 54 | if (sscanf(argv[1], SECTOR_FORMAT, &start) != 1) | 54 | if (sscanf(argv[1], "%llu", &start) != 1) |
| 55 | return -EINVAL; | 55 | return -EINVAL; |
| 56 | 56 | ||
| 57 | if (dm_get_device(ti, argv[0], start, sc->stripe_width, | 57 | if (dm_get_device(ti, argv[0], start, sc->stripe_width, |
| @@ -103,7 +103,7 @@ static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 103 | return -EINVAL; | 103 | return -EINVAL; |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | if (((uint32_t)ti->len) & (chunk_size - 1)) { | 106 | if (ti->len & (chunk_size - 1)) { |
| 107 | ti->error = "dm-stripe: Target length not divisible by " | 107 | ti->error = "dm-stripe: Target length not divisible by " |
| 108 | "chunk size"; | 108 | "chunk size"; |
| 109 | return -EINVAL; | 109 | return -EINVAL; |
| @@ -201,10 +201,11 @@ static int stripe_status(struct dm_target *ti, | |||
| 201 | break; | 201 | break; |
| 202 | 202 | ||
| 203 | case STATUSTYPE_TABLE: | 203 | case STATUSTYPE_TABLE: |
| 204 | DMEMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1); | 204 | DMEMIT("%d %llu", sc->stripes, |
| 205 | (unsigned long long)sc->chunk_mask + 1); | ||
| 205 | for (i = 0; i < sc->stripes; i++) | 206 | for (i = 0; i < sc->stripes; i++) |
| 206 | DMEMIT(" %s " SECTOR_FORMAT, sc->stripe[i].dev->name, | 207 | DMEMIT(" %s %llu", sc->stripe[i].dev->name, |
| 207 | sc->stripe[i].physical_start); | 208 | (unsigned long long)sc->stripe[i].physical_start); |
| 208 | break; | 209 | break; |
| 209 | } | 210 | } |
| 210 | return 0; | 211 | return 0; |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 907b08ddb783..8f56a54cf0ce 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/ctype.h> | 14 | #include <linux/ctype.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
| 17 | #include <linux/mutex.h> | ||
| 17 | #include <asm/atomic.h> | 18 | #include <asm/atomic.h> |
| 18 | 19 | ||
| 19 | #define MAX_DEPTH 16 | 20 | #define MAX_DEPTH 16 |
| @@ -22,6 +23,7 @@ | |||
| 22 | #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1) | 23 | #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1) |
| 23 | 24 | ||
| 24 | struct dm_table { | 25 | struct dm_table { |
| 26 | struct mapped_device *md; | ||
| 25 | atomic_t holders; | 27 | atomic_t holders; |
| 26 | 28 | ||
| 27 | /* btree table */ | 29 | /* btree table */ |
| @@ -97,6 +99,8 @@ static void combine_restrictions_low(struct io_restrictions *lhs, | |||
| 97 | 99 | ||
| 98 | lhs->seg_boundary_mask = | 100 | lhs->seg_boundary_mask = |
| 99 | min_not_zero(lhs->seg_boundary_mask, rhs->seg_boundary_mask); | 101 | min_not_zero(lhs->seg_boundary_mask, rhs->seg_boundary_mask); |
| 102 | |||
| 103 | lhs->no_cluster |= rhs->no_cluster; | ||
| 100 | } | 104 | } |
| 101 | 105 | ||
| 102 | /* | 106 | /* |
| @@ -204,7 +208,8 @@ static int alloc_targets(struct dm_table *t, unsigned int num) | |||
| 204 | return 0; | 208 | return 0; |
| 205 | } | 209 | } |
| 206 | 210 | ||
| 207 | int dm_table_create(struct dm_table **result, int mode, unsigned num_targets) | 211 | int dm_table_create(struct dm_table **result, int mode, |
| 212 | unsigned num_targets, struct mapped_device *md) | ||
| 208 | { | 213 | { |
| 209 | struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL); | 214 | struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL); |
| 210 | 215 | ||
| @@ -227,6 +232,7 @@ int dm_table_create(struct dm_table **result, int mode, unsigned num_targets) | |||
| 227 | } | 232 | } |
| 228 | 233 | ||
| 229 | t->mode = mode; | 234 | t->mode = mode; |
| 235 | t->md = md; | ||
| 230 | *result = t; | 236 | *result = t; |
| 231 | return 0; | 237 | return 0; |
| 232 | } | 238 | } |
| @@ -345,7 +351,7 @@ static struct dm_dev *find_device(struct list_head *l, dev_t dev) | |||
| 345 | /* | 351 | /* |
| 346 | * Open a device so we can use it as a map destination. | 352 | * Open a device so we can use it as a map destination. |
| 347 | */ | 353 | */ |
| 348 | static int open_dev(struct dm_dev *d, dev_t dev) | 354 | static int open_dev(struct dm_dev *d, dev_t dev, struct mapped_device *md) |
| 349 | { | 355 | { |
| 350 | static char *_claim_ptr = "I belong to device-mapper"; | 356 | static char *_claim_ptr = "I belong to device-mapper"; |
| 351 | struct block_device *bdev; | 357 | struct block_device *bdev; |
| @@ -357,7 +363,7 @@ static int open_dev(struct dm_dev *d, dev_t dev) | |||
| 357 | bdev = open_by_devnum(dev, d->mode); | 363 | bdev = open_by_devnum(dev, d->mode); |
| 358 | if (IS_ERR(bdev)) | 364 | if (IS_ERR(bdev)) |
| 359 | return PTR_ERR(bdev); | 365 | return PTR_ERR(bdev); |
| 360 | r = bd_claim(bdev, _claim_ptr); | 366 | r = bd_claim_by_disk(bdev, _claim_ptr, dm_disk(md)); |
| 361 | if (r) | 367 | if (r) |
| 362 | blkdev_put(bdev); | 368 | blkdev_put(bdev); |
| 363 | else | 369 | else |
| @@ -368,12 +374,12 @@ static int open_dev(struct dm_dev *d, dev_t dev) | |||
| 368 | /* | 374 | /* |
| 369 | * Close a device that we've been using. | 375 | * Close a device that we've been using. |
| 370 | */ | 376 | */ |
| 371 | static void close_dev(struct dm_dev *d) | 377 | static void close_dev(struct dm_dev *d, struct mapped_device *md) |
| 372 | { | 378 | { |
| 373 | if (!d->bdev) | 379 | if (!d->bdev) |
| 374 | return; | 380 | return; |
| 375 | 381 | ||
| 376 | bd_release(d->bdev); | 382 | bd_release_from_disk(d->bdev, dm_disk(md)); |
| 377 | blkdev_put(d->bdev); | 383 | blkdev_put(d->bdev); |
| 378 | d->bdev = NULL; | 384 | d->bdev = NULL; |
| 379 | } | 385 | } |
| @@ -394,7 +400,7 @@ static int check_device_area(struct dm_dev *dd, sector_t start, sector_t len) | |||
| 394 | * careful to leave things as they were if we fail to reopen the | 400 | * careful to leave things as they were if we fail to reopen the |
| 395 | * device. | 401 | * device. |
| 396 | */ | 402 | */ |
| 397 | static int upgrade_mode(struct dm_dev *dd, int new_mode) | 403 | static int upgrade_mode(struct dm_dev *dd, int new_mode, struct mapped_device *md) |
| 398 | { | 404 | { |
| 399 | int r; | 405 | int r; |
| 400 | struct dm_dev dd_copy; | 406 | struct dm_dev dd_copy; |
| @@ -404,9 +410,9 @@ static int upgrade_mode(struct dm_dev *dd, int new_mode) | |||
| 404 | 410 | ||
| 405 | dd->mode |= new_mode; | 411 | dd->mode |= new_mode; |
| 406 | dd->bdev = NULL; | 412 | dd->bdev = NULL; |
| 407 | r = open_dev(dd, dev); | 413 | r = open_dev(dd, dev, md); |
| 408 | if (!r) | 414 | if (!r) |
| 409 | close_dev(&dd_copy); | 415 | close_dev(&dd_copy, md); |
| 410 | else | 416 | else |
| 411 | *dd = dd_copy; | 417 | *dd = dd_copy; |
| 412 | 418 | ||
| @@ -448,7 +454,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, | |||
| 448 | dd->mode = mode; | 454 | dd->mode = mode; |
| 449 | dd->bdev = NULL; | 455 | dd->bdev = NULL; |
| 450 | 456 | ||
| 451 | if ((r = open_dev(dd, dev))) { | 457 | if ((r = open_dev(dd, dev, t->md))) { |
| 452 | kfree(dd); | 458 | kfree(dd); |
| 453 | return r; | 459 | return r; |
| 454 | } | 460 | } |
| @@ -459,7 +465,7 @@ static int __table_get_device(struct dm_table *t, struct dm_target *ti, | |||
| 459 | list_add(&dd->list, &t->devices); | 465 | list_add(&dd->list, &t->devices); |
| 460 | 466 | ||
| 461 | } else if (dd->mode != (mode | dd->mode)) { | 467 | } else if (dd->mode != (mode | dd->mode)) { |
| 462 | r = upgrade_mode(dd, mode); | 468 | r = upgrade_mode(dd, mode, t->md); |
| 463 | if (r) | 469 | if (r) |
| 464 | return r; | 470 | return r; |
| 465 | } | 471 | } |
| @@ -523,6 +529,8 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start, | |||
| 523 | rs->seg_boundary_mask = | 529 | rs->seg_boundary_mask = |
| 524 | min_not_zero(rs->seg_boundary_mask, | 530 | min_not_zero(rs->seg_boundary_mask, |
| 525 | q->seg_boundary_mask); | 531 | q->seg_boundary_mask); |
| 532 | |||
| 533 | rs->no_cluster |= !test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); | ||
| 526 | } | 534 | } |
| 527 | 535 | ||
| 528 | return r; | 536 | return r; |
| @@ -534,7 +542,7 @@ int dm_get_device(struct dm_target *ti, const char *path, sector_t start, | |||
| 534 | void dm_put_device(struct dm_target *ti, struct dm_dev *dd) | 542 | void dm_put_device(struct dm_target *ti, struct dm_dev *dd) |
| 535 | { | 543 | { |
| 536 | if (atomic_dec_and_test(&dd->count)) { | 544 | if (atomic_dec_and_test(&dd->count)) { |
| 537 | close_dev(dd); | 545 | close_dev(dd, ti->table->md); |
| 538 | list_del(&dd->list); | 546 | list_del(&dd->list); |
| 539 | kfree(dd); | 547 | kfree(dd); |
| 540 | } | 548 | } |
| @@ -763,14 +771,14 @@ int dm_table_complete(struct dm_table *t) | |||
| 763 | return r; | 771 | return r; |
| 764 | } | 772 | } |
| 765 | 773 | ||
| 766 | static DECLARE_MUTEX(_event_lock); | 774 | static DEFINE_MUTEX(_event_lock); |
| 767 | void dm_table_event_callback(struct dm_table *t, | 775 | void dm_table_event_callback(struct dm_table *t, |
| 768 | void (*fn)(void *), void *context) | 776 | void (*fn)(void *), void *context) |
| 769 | { | 777 | { |
| 770 | down(&_event_lock); | 778 | mutex_lock(&_event_lock); |
| 771 | t->event_fn = fn; | 779 | t->event_fn = fn; |
| 772 | t->event_context = context; | 780 | t->event_context = context; |
| 773 | up(&_event_lock); | 781 | mutex_unlock(&_event_lock); |
| 774 | } | 782 | } |
| 775 | 783 | ||
| 776 | void dm_table_event(struct dm_table *t) | 784 | void dm_table_event(struct dm_table *t) |
| @@ -781,10 +789,10 @@ void dm_table_event(struct dm_table *t) | |||
| 781 | */ | 789 | */ |
| 782 | BUG_ON(in_interrupt()); | 790 | BUG_ON(in_interrupt()); |
| 783 | 791 | ||
| 784 | down(&_event_lock); | 792 | mutex_lock(&_event_lock); |
| 785 | if (t->event_fn) | 793 | if (t->event_fn) |
| 786 | t->event_fn(t->event_context); | 794 | t->event_fn(t->event_context); |
| 787 | up(&_event_lock); | 795 | mutex_unlock(&_event_lock); |
| 788 | } | 796 | } |
| 789 | 797 | ||
| 790 | sector_t dm_table_get_size(struct dm_table *t) | 798 | sector_t dm_table_get_size(struct dm_table *t) |
| @@ -832,6 +840,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q) | |||
| 832 | q->hardsect_size = t->limits.hardsect_size; | 840 | q->hardsect_size = t->limits.hardsect_size; |
| 833 | q->max_segment_size = t->limits.max_segment_size; | 841 | q->max_segment_size = t->limits.max_segment_size; |
| 834 | q->seg_boundary_mask = t->limits.seg_boundary_mask; | 842 | q->seg_boundary_mask = t->limits.seg_boundary_mask; |
| 843 | if (t->limits.no_cluster) | ||
| 844 | q->queue_flags &= ~(1 << QUEUE_FLAG_CLUSTER); | ||
| 845 | else | ||
| 846 | q->queue_flags |= (1 << QUEUE_FLAG_CLUSTER); | ||
| 847 | |||
| 835 | } | 848 | } |
| 836 | 849 | ||
| 837 | unsigned int dm_table_get_num_targets(struct dm_table *t) | 850 | unsigned int dm_table_get_num_targets(struct dm_table *t) |
| @@ -943,12 +956,20 @@ int dm_table_flush_all(struct dm_table *t) | |||
| 943 | return ret; | 956 | return ret; |
| 944 | } | 957 | } |
| 945 | 958 | ||
| 959 | struct mapped_device *dm_table_get_md(struct dm_table *t) | ||
| 960 | { | ||
| 961 | dm_get(t->md); | ||
| 962 | |||
| 963 | return t->md; | ||
| 964 | } | ||
| 965 | |||
| 946 | EXPORT_SYMBOL(dm_vcalloc); | 966 | EXPORT_SYMBOL(dm_vcalloc); |
| 947 | EXPORT_SYMBOL(dm_get_device); | 967 | EXPORT_SYMBOL(dm_get_device); |
| 948 | EXPORT_SYMBOL(dm_put_device); | 968 | EXPORT_SYMBOL(dm_put_device); |
| 949 | EXPORT_SYMBOL(dm_table_event); | 969 | EXPORT_SYMBOL(dm_table_event); |
| 950 | EXPORT_SYMBOL(dm_table_get_size); | 970 | EXPORT_SYMBOL(dm_table_get_size); |
| 951 | EXPORT_SYMBOL(dm_table_get_mode); | 971 | EXPORT_SYMBOL(dm_table_get_mode); |
| 972 | EXPORT_SYMBOL(dm_table_get_md); | ||
| 952 | EXPORT_SYMBOL(dm_table_put); | 973 | EXPORT_SYMBOL(dm_table_put); |
| 953 | EXPORT_SYMBOL(dm_table_get); | 974 | EXPORT_SYMBOL(dm_table_get); |
| 954 | EXPORT_SYMBOL(dm_table_unplug_all); | 975 | EXPORT_SYMBOL(dm_table_unplug_all); |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index a64798ef481e..4d710b7a133b 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
| 13 | #include <linux/mutex.h> | ||
| 13 | #include <linux/moduleparam.h> | 14 | #include <linux/moduleparam.h> |
| 14 | #include <linux/blkpg.h> | 15 | #include <linux/blkpg.h> |
| 15 | #include <linux/bio.h> | 16 | #include <linux/bio.h> |
| @@ -17,6 +18,7 @@ | |||
| 17 | #include <linux/mempool.h> | 18 | #include <linux/mempool.h> |
| 18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 19 | #include <linux/idr.h> | 20 | #include <linux/idr.h> |
| 21 | #include <linux/hdreg.h> | ||
| 20 | #include <linux/blktrace_api.h> | 22 | #include <linux/blktrace_api.h> |
| 21 | 23 | ||
| 22 | static const char *_name = DM_NAME; | 24 | static const char *_name = DM_NAME; |
| @@ -69,6 +71,7 @@ struct mapped_device { | |||
| 69 | 71 | ||
| 70 | request_queue_t *queue; | 72 | request_queue_t *queue; |
| 71 | struct gendisk *disk; | 73 | struct gendisk *disk; |
| 74 | char name[16]; | ||
| 72 | 75 | ||
| 73 | void *interface_ptr; | 76 | void *interface_ptr; |
| 74 | 77 | ||
| @@ -101,6 +104,9 @@ struct mapped_device { | |||
| 101 | */ | 104 | */ |
| 102 | struct super_block *frozen_sb; | 105 | struct super_block *frozen_sb; |
| 103 | struct block_device *suspended_bdev; | 106 | struct block_device *suspended_bdev; |
| 107 | |||
| 108 | /* forced geometry settings */ | ||
| 109 | struct hd_geometry geometry; | ||
| 104 | }; | 110 | }; |
| 105 | 111 | ||
| 106 | #define MIN_IOS 256 | 112 | #define MIN_IOS 256 |
| @@ -226,6 +232,13 @@ static int dm_blk_close(struct inode *inode, struct file *file) | |||
| 226 | return 0; | 232 | return 0; |
| 227 | } | 233 | } |
| 228 | 234 | ||
| 235 | static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
| 236 | { | ||
| 237 | struct mapped_device *md = bdev->bd_disk->private_data; | ||
| 238 | |||
| 239 | return dm_get_geometry(md, geo); | ||
| 240 | } | ||
| 241 | |||
| 229 | static inline struct dm_io *alloc_io(struct mapped_device *md) | 242 | static inline struct dm_io *alloc_io(struct mapped_device *md) |
| 230 | { | 243 | { |
| 231 | return mempool_alloc(md->io_pool, GFP_NOIO); | 244 | return mempool_alloc(md->io_pool, GFP_NOIO); |
| @@ -312,6 +325,33 @@ struct dm_table *dm_get_table(struct mapped_device *md) | |||
| 312 | return t; | 325 | return t; |
| 313 | } | 326 | } |
| 314 | 327 | ||
| 328 | /* | ||
| 329 | * Get the geometry associated with a dm device | ||
| 330 | */ | ||
| 331 | int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo) | ||
| 332 | { | ||
| 333 | *geo = md->geometry; | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | /* | ||
| 339 | * Set the geometry of a device. | ||
| 340 | */ | ||
| 341 | int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo) | ||
| 342 | { | ||
| 343 | sector_t sz = (sector_t)geo->cylinders * geo->heads * geo->sectors; | ||
| 344 | |||
| 345 | if (geo->start > sz) { | ||
| 346 | DMWARN("Start sector is beyond the geometry limits."); | ||
| 347 | return -EINVAL; | ||
| 348 | } | ||
| 349 | |||
| 350 | md->geometry = *geo; | ||
| 351 | |||
| 352 | return 0; | ||
| 353 | } | ||
| 354 | |||
| 315 | /*----------------------------------------------------------------- | 355 | /*----------------------------------------------------------------- |
| 316 | * CRUD START: | 356 | * CRUD START: |
| 317 | * A more elegant soln is in the works that uses the queue | 357 | * A more elegant soln is in the works that uses the queue |
| @@ -704,14 +744,14 @@ static int dm_any_congested(void *congested_data, int bdi_bits) | |||
| 704 | /*----------------------------------------------------------------- | 744 | /*----------------------------------------------------------------- |
| 705 | * An IDR is used to keep track of allocated minor numbers. | 745 | * An IDR is used to keep track of allocated minor numbers. |
| 706 | *---------------------------------------------------------------*/ | 746 | *---------------------------------------------------------------*/ |
| 707 | static DECLARE_MUTEX(_minor_lock); | 747 | static DEFINE_MUTEX(_minor_lock); |
| 708 | static DEFINE_IDR(_minor_idr); | 748 | static DEFINE_IDR(_minor_idr); |
| 709 | 749 | ||
| 710 | static void free_minor(unsigned int minor) | 750 | static void free_minor(unsigned int minor) |
| 711 | { | 751 | { |
| 712 | down(&_minor_lock); | 752 | mutex_lock(&_minor_lock); |
| 713 | idr_remove(&_minor_idr, minor); | 753 | idr_remove(&_minor_idr, minor); |
| 714 | up(&_minor_lock); | 754 | mutex_unlock(&_minor_lock); |
| 715 | } | 755 | } |
| 716 | 756 | ||
| 717 | /* | 757 | /* |
| @@ -724,7 +764,7 @@ static int specific_minor(struct mapped_device *md, unsigned int minor) | |||
| 724 | if (minor >= (1 << MINORBITS)) | 764 | if (minor >= (1 << MINORBITS)) |
| 725 | return -EINVAL; | 765 | return -EINVAL; |
| 726 | 766 | ||
| 727 | down(&_minor_lock); | 767 | mutex_lock(&_minor_lock); |
| 728 | 768 | ||
| 729 | if (idr_find(&_minor_idr, minor)) { | 769 | if (idr_find(&_minor_idr, minor)) { |
| 730 | r = -EBUSY; | 770 | r = -EBUSY; |
| @@ -749,7 +789,7 @@ static int specific_minor(struct mapped_device *md, unsigned int minor) | |||
| 749 | } | 789 | } |
| 750 | 790 | ||
| 751 | out: | 791 | out: |
| 752 | up(&_minor_lock); | 792 | mutex_unlock(&_minor_lock); |
| 753 | return r; | 793 | return r; |
| 754 | } | 794 | } |
| 755 | 795 | ||
| @@ -758,7 +798,7 @@ static int next_free_minor(struct mapped_device *md, unsigned int *minor) | |||
| 758 | int r; | 798 | int r; |
| 759 | unsigned int m; | 799 | unsigned int m; |
| 760 | 800 | ||
| 761 | down(&_minor_lock); | 801 | mutex_lock(&_minor_lock); |
| 762 | 802 | ||
| 763 | r = idr_pre_get(&_minor_idr, GFP_KERNEL); | 803 | r = idr_pre_get(&_minor_idr, GFP_KERNEL); |
| 764 | if (!r) { | 804 | if (!r) { |
| @@ -780,7 +820,7 @@ static int next_free_minor(struct mapped_device *md, unsigned int *minor) | |||
| 780 | *minor = m; | 820 | *minor = m; |
| 781 | 821 | ||
| 782 | out: | 822 | out: |
| 783 | up(&_minor_lock); | 823 | mutex_unlock(&_minor_lock); |
| 784 | return r; | 824 | return r; |
| 785 | } | 825 | } |
| 786 | 826 | ||
| @@ -842,6 +882,7 @@ static struct mapped_device *alloc_dev(unsigned int minor, int persistent) | |||
| 842 | md->disk->private_data = md; | 882 | md->disk->private_data = md; |
| 843 | sprintf(md->disk->disk_name, "dm-%d", minor); | 883 | sprintf(md->disk->disk_name, "dm-%d", minor); |
| 844 | add_disk(md->disk); | 884 | add_disk(md->disk); |
| 885 | format_dev_t(md->name, MKDEV(_major, minor)); | ||
| 845 | 886 | ||
| 846 | atomic_set(&md->pending, 0); | 887 | atomic_set(&md->pending, 0); |
| 847 | init_waitqueue_head(&md->wait); | 888 | init_waitqueue_head(&md->wait); |
| @@ -904,6 +945,13 @@ static int __bind(struct mapped_device *md, struct dm_table *t) | |||
| 904 | sector_t size; | 945 | sector_t size; |
| 905 | 946 | ||
| 906 | size = dm_table_get_size(t); | 947 | size = dm_table_get_size(t); |
| 948 | |||
| 949 | /* | ||
| 950 | * Wipe any geometry if the size of the table changed. | ||
| 951 | */ | ||
| 952 | if (size != get_capacity(md->disk)) | ||
| 953 | memset(&md->geometry, 0, sizeof(md->geometry)); | ||
| 954 | |||
| 907 | __set_size(md, size); | 955 | __set_size(md, size); |
| 908 | if (size == 0) | 956 | if (size == 0) |
| 909 | return 0; | 957 | return 0; |
| @@ -967,13 +1015,13 @@ static struct mapped_device *dm_find_md(dev_t dev) | |||
| 967 | if (MAJOR(dev) != _major || minor >= (1 << MINORBITS)) | 1015 | if (MAJOR(dev) != _major || minor >= (1 << MINORBITS)) |
| 968 | return NULL; | 1016 | return NULL; |
| 969 | 1017 | ||
| 970 | down(&_minor_lock); | 1018 | mutex_lock(&_minor_lock); |
| 971 | 1019 | ||
| 972 | md = idr_find(&_minor_idr, minor); | 1020 | md = idr_find(&_minor_idr, minor); |
| 973 | if (!md || (dm_disk(md)->first_minor != minor)) | 1021 | if (!md || (dm_disk(md)->first_minor != minor)) |
| 974 | md = NULL; | 1022 | md = NULL; |
| 975 | 1023 | ||
| 976 | up(&_minor_lock); | 1024 | mutex_unlock(&_minor_lock); |
| 977 | 1025 | ||
| 978 | return md; | 1026 | return md; |
| 979 | } | 1027 | } |
| @@ -988,15 +1036,9 @@ struct mapped_device *dm_get_md(dev_t dev) | |||
| 988 | return md; | 1036 | return md; |
| 989 | } | 1037 | } |
| 990 | 1038 | ||
| 991 | void *dm_get_mdptr(dev_t dev) | 1039 | void *dm_get_mdptr(struct mapped_device *md) |
| 992 | { | 1040 | { |
| 993 | struct mapped_device *md; | 1041 | return md->interface_ptr; |
| 994 | void *mdptr = NULL; | ||
| 995 | |||
| 996 | md = dm_find_md(dev); | ||
| 997 | if (md) | ||
| 998 | mdptr = md->interface_ptr; | ||
| 999 | return mdptr; | ||
| 1000 | } | 1042 | } |
| 1001 | 1043 | ||
| 1002 | void dm_set_mdptr(struct mapped_device *md, void *ptr) | 1044 | void dm_set_mdptr(struct mapped_device *md, void *ptr) |
| @@ -1011,18 +1053,18 @@ void dm_get(struct mapped_device *md) | |||
| 1011 | 1053 | ||
| 1012 | void dm_put(struct mapped_device *md) | 1054 | void dm_put(struct mapped_device *md) |
| 1013 | { | 1055 | { |
| 1014 | struct dm_table *map = dm_get_table(md); | 1056 | struct dm_table *map; |
| 1015 | 1057 | ||
| 1016 | if (atomic_dec_and_test(&md->holders)) { | 1058 | if (atomic_dec_and_test(&md->holders)) { |
| 1059 | map = dm_get_table(md); | ||
| 1017 | if (!dm_suspended(md)) { | 1060 | if (!dm_suspended(md)) { |
| 1018 | dm_table_presuspend_targets(map); | 1061 | dm_table_presuspend_targets(map); |
| 1019 | dm_table_postsuspend_targets(map); | 1062 | dm_table_postsuspend_targets(map); |
| 1020 | } | 1063 | } |
| 1021 | __unbind(md); | 1064 | __unbind(md); |
| 1065 | dm_table_put(map); | ||
| 1022 | free_dev(md); | 1066 | free_dev(md); |
| 1023 | } | 1067 | } |
| 1024 | |||
| 1025 | dm_table_put(map); | ||
| 1026 | } | 1068 | } |
| 1027 | 1069 | ||
| 1028 | /* | 1070 | /* |
| @@ -1107,6 +1149,7 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) | |||
| 1107 | { | 1149 | { |
| 1108 | struct dm_table *map = NULL; | 1150 | struct dm_table *map = NULL; |
| 1109 | DECLARE_WAITQUEUE(wait, current); | 1151 | DECLARE_WAITQUEUE(wait, current); |
| 1152 | struct bio *def; | ||
| 1110 | int r = -EINVAL; | 1153 | int r = -EINVAL; |
| 1111 | 1154 | ||
| 1112 | down(&md->suspend_lock); | 1155 | down(&md->suspend_lock); |
| @@ -1166,9 +1209,11 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) | |||
| 1166 | /* were we interrupted ? */ | 1209 | /* were we interrupted ? */ |
| 1167 | r = -EINTR; | 1210 | r = -EINTR; |
| 1168 | if (atomic_read(&md->pending)) { | 1211 | if (atomic_read(&md->pending)) { |
| 1212 | clear_bit(DMF_BLOCK_IO, &md->flags); | ||
| 1213 | def = bio_list_get(&md->deferred); | ||
| 1214 | __flush_deferred_io(md, def); | ||
| 1169 | up_write(&md->io_lock); | 1215 | up_write(&md->io_lock); |
| 1170 | unlock_fs(md); | 1216 | unlock_fs(md); |
| 1171 | clear_bit(DMF_BLOCK_IO, &md->flags); | ||
| 1172 | goto out; | 1217 | goto out; |
| 1173 | } | 1218 | } |
| 1174 | up_write(&md->io_lock); | 1219 | up_write(&md->io_lock); |
| @@ -1262,6 +1307,7 @@ int dm_suspended(struct mapped_device *md) | |||
| 1262 | static struct block_device_operations dm_blk_dops = { | 1307 | static struct block_device_operations dm_blk_dops = { |
| 1263 | .open = dm_blk_open, | 1308 | .open = dm_blk_open, |
| 1264 | .release = dm_blk_close, | 1309 | .release = dm_blk_close, |
| 1310 | .getgeo = dm_blk_getgeo, | ||
| 1265 | .owner = THIS_MODULE | 1311 | .owner = THIS_MODULE |
| 1266 | }; | 1312 | }; |
| 1267 | 1313 | ||
diff --git a/drivers/md/dm.h b/drivers/md/dm.h index 4eaf075da217..fd90bc8f9e45 100644 --- a/drivers/md/dm.h +++ b/drivers/md/dm.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/device-mapper.h> | 14 | #include <linux/device-mapper.h> |
| 15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
| 16 | #include <linux/blkdev.h> | 16 | #include <linux/blkdev.h> |
| 17 | #include <linux/hdreg.h> | ||
| 17 | 18 | ||
| 18 | #define DM_NAME "device-mapper" | 19 | #define DM_NAME "device-mapper" |
| 19 | #define DMWARN(f, x...) printk(KERN_WARNING DM_NAME ": " f "\n" , ## x) | 20 | #define DMWARN(f, x...) printk(KERN_WARNING DM_NAME ": " f "\n" , ## x) |
| @@ -23,16 +24,6 @@ | |||
| 23 | #define DMEMIT(x...) sz += ((sz >= maxlen) ? \ | 24 | #define DMEMIT(x...) sz += ((sz >= maxlen) ? \ |
| 24 | 0 : scnprintf(result + sz, maxlen - sz, x)) | 25 | 0 : scnprintf(result + sz, maxlen - sz, x)) |
| 25 | 26 | ||
| 26 | /* | ||
| 27 | * FIXME: I think this should be with the definition of sector_t | ||
| 28 | * in types.h. | ||
| 29 | */ | ||
| 30 | #ifdef CONFIG_LBD | ||
| 31 | #define SECTOR_FORMAT "%llu" | ||
| 32 | #else | ||
| 33 | #define SECTOR_FORMAT "%lu" | ||
| 34 | #endif | ||
| 35 | |||
| 36 | #define SECTOR_SHIFT 9 | 27 | #define SECTOR_SHIFT 9 |
| 37 | 28 | ||
| 38 | /* | 29 | /* |
| @@ -57,7 +48,7 @@ struct mapped_device; | |||
| 57 | int dm_create(struct mapped_device **md); | 48 | int dm_create(struct mapped_device **md); |
| 58 | int dm_create_with_minor(unsigned int minor, struct mapped_device **md); | 49 | int dm_create_with_minor(unsigned int minor, struct mapped_device **md); |
| 59 | void dm_set_mdptr(struct mapped_device *md, void *ptr); | 50 | void dm_set_mdptr(struct mapped_device *md, void *ptr); |
| 60 | void *dm_get_mdptr(dev_t dev); | 51 | void *dm_get_mdptr(struct mapped_device *md); |
| 61 | struct mapped_device *dm_get_md(dev_t dev); | 52 | struct mapped_device *dm_get_md(dev_t dev); |
| 62 | 53 | ||
| 63 | /* | 54 | /* |
| @@ -95,11 +86,18 @@ int dm_wait_event(struct mapped_device *md, int event_nr); | |||
| 95 | struct gendisk *dm_disk(struct mapped_device *md); | 86 | struct gendisk *dm_disk(struct mapped_device *md); |
| 96 | int dm_suspended(struct mapped_device *md); | 87 | int dm_suspended(struct mapped_device *md); |
| 97 | 88 | ||
| 89 | /* | ||
| 90 | * Geometry functions. | ||
| 91 | */ | ||
| 92 | int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo); | ||
| 93 | int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo); | ||
| 94 | |||
| 98 | /*----------------------------------------------------------------- | 95 | /*----------------------------------------------------------------- |
| 99 | * Functions for manipulating a table. Tables are also reference | 96 | * Functions for manipulating a table. Tables are also reference |
| 100 | * counted. | 97 | * counted. |
| 101 | *---------------------------------------------------------------*/ | 98 | *---------------------------------------------------------------*/ |
| 102 | int dm_table_create(struct dm_table **result, int mode, unsigned num_targets); | 99 | int dm_table_create(struct dm_table **result, int mode, |
| 100 | unsigned num_targets, struct mapped_device *md); | ||
| 103 | 101 | ||
| 104 | void dm_table_get(struct dm_table *t); | 102 | void dm_table_get(struct dm_table *t); |
| 105 | void dm_table_put(struct dm_table *t); | 103 | void dm_table_put(struct dm_table *t); |
| @@ -117,6 +115,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q); | |||
| 117 | unsigned int dm_table_get_num_targets(struct dm_table *t); | 115 | unsigned int dm_table_get_num_targets(struct dm_table *t); |
| 118 | struct list_head *dm_table_get_devices(struct dm_table *t); | 116 | struct list_head *dm_table_get_devices(struct dm_table *t); |
| 119 | int dm_table_get_mode(struct dm_table *t); | 117 | int dm_table_get_mode(struct dm_table *t); |
| 118 | struct mapped_device *dm_table_get_md(struct dm_table *t); | ||
| 120 | void dm_table_presuspend_targets(struct dm_table *t); | 119 | void dm_table_presuspend_targets(struct dm_table *t); |
| 121 | void dm_table_postsuspend_targets(struct dm_table *t); | 120 | void dm_table_postsuspend_targets(struct dm_table *t); |
| 122 | void dm_table_resume_targets(struct dm_table *t); | 121 | void dm_table_resume_targets(struct dm_table *t); |
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c index 9dcb2c8a3853..72480a48d88b 100644 --- a/drivers/md/kcopyd.c +++ b/drivers/md/kcopyd.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/vmalloc.h> | 23 | #include <linux/vmalloc.h> |
| 24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
| 25 | #include <linux/mutex.h> | ||
| 25 | 26 | ||
| 26 | #include "kcopyd.h" | 27 | #include "kcopyd.h" |
| 27 | 28 | ||
| @@ -44,6 +45,9 @@ struct kcopyd_client { | |||
| 44 | struct page_list *pages; | 45 | struct page_list *pages; |
| 45 | unsigned int nr_pages; | 46 | unsigned int nr_pages; |
| 46 | unsigned int nr_free_pages; | 47 | unsigned int nr_free_pages; |
| 48 | |||
| 49 | wait_queue_head_t destroyq; | ||
| 50 | atomic_t nr_jobs; | ||
| 47 | }; | 51 | }; |
| 48 | 52 | ||
| 49 | static struct page_list *alloc_pl(void) | 53 | static struct page_list *alloc_pl(void) |
| @@ -292,10 +296,15 @@ static int run_complete_job(struct kcopyd_job *job) | |||
| 292 | int read_err = job->read_err; | 296 | int read_err = job->read_err; |
| 293 | unsigned int write_err = job->write_err; | 297 | unsigned int write_err = job->write_err; |
| 294 | kcopyd_notify_fn fn = job->fn; | 298 | kcopyd_notify_fn fn = job->fn; |
| 299 | struct kcopyd_client *kc = job->kc; | ||
| 295 | 300 | ||
| 296 | kcopyd_put_pages(job->kc, job->pages); | 301 | kcopyd_put_pages(kc, job->pages); |
| 297 | mempool_free(job, _job_pool); | 302 | mempool_free(job, _job_pool); |
| 298 | fn(read_err, write_err, context); | 303 | fn(read_err, write_err, context); |
| 304 | |||
| 305 | if (atomic_dec_and_test(&kc->nr_jobs)) | ||
| 306 | wake_up(&kc->destroyq); | ||
| 307 | |||
| 299 | return 0; | 308 | return 0; |
| 300 | } | 309 | } |
| 301 | 310 | ||
| @@ -430,6 +439,7 @@ static void do_work(void *ignored) | |||
| 430 | */ | 439 | */ |
| 431 | static void dispatch_job(struct kcopyd_job *job) | 440 | static void dispatch_job(struct kcopyd_job *job) |
| 432 | { | 441 | { |
| 442 | atomic_inc(&job->kc->nr_jobs); | ||
| 433 | push(&_pages_jobs, job); | 443 | push(&_pages_jobs, job); |
| 434 | wake(); | 444 | wake(); |
| 435 | } | 445 | } |
| @@ -572,21 +582,21 @@ int kcopyd_cancel(struct kcopyd_job *job, int block) | |||
| 572 | /*----------------------------------------------------------------- | 582 | /*----------------------------------------------------------------- |
| 573 | * Unit setup | 583 | * Unit setup |
| 574 | *---------------------------------------------------------------*/ | 584 | *---------------------------------------------------------------*/ |
| 575 | static DECLARE_MUTEX(_client_lock); | 585 | static DEFINE_MUTEX(_client_lock); |
| 576 | static LIST_HEAD(_clients); | 586 | static LIST_HEAD(_clients); |
| 577 | 587 | ||
| 578 | static void client_add(struct kcopyd_client *kc) | 588 | static void client_add(struct kcopyd_client *kc) |
| 579 | { | 589 | { |
| 580 | down(&_client_lock); | 590 | mutex_lock(&_client_lock); |
| 581 | list_add(&kc->list, &_clients); | 591 | list_add(&kc->list, &_clients); |
| 582 | up(&_client_lock); | 592 | mutex_unlock(&_client_lock); |
| 583 | } | 593 | } |
| 584 | 594 | ||
| 585 | static void client_del(struct kcopyd_client *kc) | 595 | static void client_del(struct kcopyd_client *kc) |
| 586 | { | 596 | { |
| 587 | down(&_client_lock); | 597 | mutex_lock(&_client_lock); |
| 588 | list_del(&kc->list); | 598 | list_del(&kc->list); |
| 589 | up(&_client_lock); | 599 | mutex_unlock(&_client_lock); |
| 590 | } | 600 | } |
| 591 | 601 | ||
| 592 | static DEFINE_MUTEX(kcopyd_init_lock); | 602 | static DEFINE_MUTEX(kcopyd_init_lock); |
| @@ -669,6 +679,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result) | |||
| 669 | return r; | 679 | return r; |
| 670 | } | 680 | } |
| 671 | 681 | ||
| 682 | init_waitqueue_head(&kc->destroyq); | ||
| 683 | atomic_set(&kc->nr_jobs, 0); | ||
| 684 | |||
| 672 | client_add(kc); | 685 | client_add(kc); |
| 673 | *result = kc; | 686 | *result = kc; |
| 674 | return 0; | 687 | return 0; |
| @@ -676,6 +689,9 @@ int kcopyd_client_create(unsigned int nr_pages, struct kcopyd_client **result) | |||
| 676 | 689 | ||
| 677 | void kcopyd_client_destroy(struct kcopyd_client *kc) | 690 | void kcopyd_client_destroy(struct kcopyd_client *kc) |
| 678 | { | 691 | { |
| 692 | /* Wait for completion of all jobs submitted by this client. */ | ||
| 693 | wait_event(kc->destroyq, !atomic_read(&kc->nr_jobs)); | ||
| 694 | |||
| 679 | dm_io_put(kc->nr_pages); | 695 | dm_io_put(kc->nr_pages); |
| 680 | client_free_pages(kc); | 696 | client_free_pages(kc); |
| 681 | client_del(kc); | 697 | client_del(kc); |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 5ed2228745cb..039e071c1007 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | #include <linux/buffer_head.h> /* for invalidate_bdev */ | 43 | #include <linux/buffer_head.h> /* for invalidate_bdev */ |
| 44 | #include <linux/suspend.h> | 44 | #include <linux/suspend.h> |
| 45 | #include <linux/poll.h> | 45 | #include <linux/poll.h> |
| 46 | #include <linux/mutex.h> | ||
| 46 | 47 | ||
| 47 | #include <linux/init.h> | 48 | #include <linux/init.h> |
| 48 | 49 | ||
| @@ -158,11 +159,12 @@ static int start_readonly; | |||
| 158 | */ | 159 | */ |
| 159 | static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters); | 160 | static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters); |
| 160 | static atomic_t md_event_count; | 161 | static atomic_t md_event_count; |
| 161 | static void md_new_event(mddev_t *mddev) | 162 | void md_new_event(mddev_t *mddev) |
| 162 | { | 163 | { |
| 163 | atomic_inc(&md_event_count); | 164 | atomic_inc(&md_event_count); |
| 164 | wake_up(&md_event_waiters); | 165 | wake_up(&md_event_waiters); |
| 165 | } | 166 | } |
| 167 | EXPORT_SYMBOL_GPL(md_new_event); | ||
| 166 | 168 | ||
| 167 | /* | 169 | /* |
| 168 | * Enables to iterate over all existing md arrays | 170 | * Enables to iterate over all existing md arrays |
| @@ -253,7 +255,7 @@ static mddev_t * mddev_find(dev_t unit) | |||
| 253 | else | 255 | else |
| 254 | new->md_minor = MINOR(unit) >> MdpMinorShift; | 256 | new->md_minor = MINOR(unit) >> MdpMinorShift; |
| 255 | 257 | ||
| 256 | init_MUTEX(&new->reconfig_sem); | 258 | mutex_init(&new->reconfig_mutex); |
| 257 | INIT_LIST_HEAD(&new->disks); | 259 | INIT_LIST_HEAD(&new->disks); |
| 258 | INIT_LIST_HEAD(&new->all_mddevs); | 260 | INIT_LIST_HEAD(&new->all_mddevs); |
| 259 | init_timer(&new->safemode_timer); | 261 | init_timer(&new->safemode_timer); |
| @@ -266,6 +268,7 @@ static mddev_t * mddev_find(dev_t unit) | |||
| 266 | kfree(new); | 268 | kfree(new); |
| 267 | return NULL; | 269 | return NULL; |
| 268 | } | 270 | } |
| 271 | set_bit(QUEUE_FLAG_CLUSTER, &new->queue->queue_flags); | ||
| 269 | 272 | ||
| 270 | blk_queue_make_request(new->queue, md_fail_request); | 273 | blk_queue_make_request(new->queue, md_fail_request); |
| 271 | 274 | ||
| @@ -274,22 +277,22 @@ static mddev_t * mddev_find(dev_t unit) | |||
| 274 | 277 | ||
| 275 | static inline int mddev_lock(mddev_t * mddev) | 278 | static inline int mddev_lock(mddev_t * mddev) |
| 276 | { | 279 | { |
| 277 | return down_interruptible(&mddev->reconfig_sem); | 280 | return mutex_lock_interruptible(&mddev->reconfig_mutex); |
| 278 | } | 281 | } |
| 279 | 282 | ||
| 280 | static inline void mddev_lock_uninterruptible(mddev_t * mddev) | 283 | static inline void mddev_lock_uninterruptible(mddev_t * mddev) |
| 281 | { | 284 | { |
| 282 | down(&mddev->reconfig_sem); | 285 | mutex_lock(&mddev->reconfig_mutex); |
| 283 | } | 286 | } |
| 284 | 287 | ||
| 285 | static inline int mddev_trylock(mddev_t * mddev) | 288 | static inline int mddev_trylock(mddev_t * mddev) |
| 286 | { | 289 | { |
| 287 | return down_trylock(&mddev->reconfig_sem); | 290 | return mutex_trylock(&mddev->reconfig_mutex); |
| 288 | } | 291 | } |
| 289 | 292 | ||
| 290 | static inline void mddev_unlock(mddev_t * mddev) | 293 | static inline void mddev_unlock(mddev_t * mddev) |
| 291 | { | 294 | { |
| 292 | up(&mddev->reconfig_sem); | 295 | mutex_unlock(&mddev->reconfig_mutex); |
| 293 | 296 | ||
| 294 | md_wakeup_thread(mddev->thread); | 297 | md_wakeup_thread(mddev->thread); |
| 295 | } | 298 | } |
| @@ -660,7 +663,8 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version | |||
| 660 | } | 663 | } |
| 661 | 664 | ||
| 662 | if (sb->major_version != 0 || | 665 | if (sb->major_version != 0 || |
| 663 | sb->minor_version != 90) { | 666 | sb->minor_version < 90 || |
| 667 | sb->minor_version > 91) { | ||
| 664 | printk(KERN_WARNING "Bad version number %d.%d on %s\n", | 668 | printk(KERN_WARNING "Bad version number %d.%d on %s\n", |
| 665 | sb->major_version, sb->minor_version, | 669 | sb->major_version, sb->minor_version, |
| 666 | b); | 670 | b); |
| @@ -745,6 +749,20 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 745 | mddev->bitmap_offset = 0; | 749 | mddev->bitmap_offset = 0; |
| 746 | mddev->default_bitmap_offset = MD_SB_BYTES >> 9; | 750 | mddev->default_bitmap_offset = MD_SB_BYTES >> 9; |
| 747 | 751 | ||
| 752 | if (mddev->minor_version >= 91) { | ||
| 753 | mddev->reshape_position = sb->reshape_position; | ||
| 754 | mddev->delta_disks = sb->delta_disks; | ||
| 755 | mddev->new_level = sb->new_level; | ||
| 756 | mddev->new_layout = sb->new_layout; | ||
| 757 | mddev->new_chunk = sb->new_chunk; | ||
| 758 | } else { | ||
| 759 | mddev->reshape_position = MaxSector; | ||
| 760 | mddev->delta_disks = 0; | ||
| 761 | mddev->new_level = mddev->level; | ||
| 762 | mddev->new_layout = mddev->layout; | ||
| 763 | mddev->new_chunk = mddev->chunk_size; | ||
| 764 | } | ||
| 765 | |||
| 748 | if (sb->state & (1<<MD_SB_CLEAN)) | 766 | if (sb->state & (1<<MD_SB_CLEAN)) |
| 749 | mddev->recovery_cp = MaxSector; | 767 | mddev->recovery_cp = MaxSector; |
| 750 | else { | 768 | else { |
| @@ -764,7 +782,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 764 | 782 | ||
| 765 | if (sb->state & (1<<MD_SB_BITMAP_PRESENT) && | 783 | if (sb->state & (1<<MD_SB_BITMAP_PRESENT) && |
| 766 | mddev->bitmap_file == NULL) { | 784 | mddev->bitmap_file == NULL) { |
| 767 | if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6 | 785 | if (mddev->level != 1 && mddev->level != 4 |
| 786 | && mddev->level != 5 && mddev->level != 6 | ||
| 768 | && mddev->level != 10) { | 787 | && mddev->level != 10) { |
| 769 | /* FIXME use a better test */ | 788 | /* FIXME use a better test */ |
| 770 | printk(KERN_WARNING "md: bitmaps not supported for this level.\n"); | 789 | printk(KERN_WARNING "md: bitmaps not supported for this level.\n"); |
| @@ -838,7 +857,6 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 838 | 857 | ||
| 839 | sb->md_magic = MD_SB_MAGIC; | 858 | sb->md_magic = MD_SB_MAGIC; |
| 840 | sb->major_version = mddev->major_version; | 859 | sb->major_version = mddev->major_version; |
| 841 | sb->minor_version = mddev->minor_version; | ||
| 842 | sb->patch_version = mddev->patch_version; | 860 | sb->patch_version = mddev->patch_version; |
| 843 | sb->gvalid_words = 0; /* ignored */ | 861 | sb->gvalid_words = 0; /* ignored */ |
| 844 | memcpy(&sb->set_uuid0, mddev->uuid+0, 4); | 862 | memcpy(&sb->set_uuid0, mddev->uuid+0, 4); |
| @@ -857,6 +875,17 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 857 | sb->events_hi = (mddev->events>>32); | 875 | sb->events_hi = (mddev->events>>32); |
| 858 | sb->events_lo = (u32)mddev->events; | 876 | sb->events_lo = (u32)mddev->events; |
| 859 | 877 | ||
| 878 | if (mddev->reshape_position == MaxSector) | ||
| 879 | sb->minor_version = 90; | ||
| 880 | else { | ||
| 881 | sb->minor_version = 91; | ||
| 882 | sb->reshape_position = mddev->reshape_position; | ||
| 883 | sb->new_level = mddev->new_level; | ||
| 884 | sb->delta_disks = mddev->delta_disks; | ||
| 885 | sb->new_layout = mddev->new_layout; | ||
| 886 | sb->new_chunk = mddev->new_chunk; | ||
| 887 | } | ||
| 888 | mddev->minor_version = sb->minor_version; | ||
| 860 | if (mddev->in_sync) | 889 | if (mddev->in_sync) |
| 861 | { | 890 | { |
| 862 | sb->recovery_cp = mddev->recovery_cp; | 891 | sb->recovery_cp = mddev->recovery_cp; |
| @@ -893,10 +922,9 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 893 | d->raid_disk = rdev2->raid_disk; | 922 | d->raid_disk = rdev2->raid_disk; |
| 894 | else | 923 | else |
| 895 | d->raid_disk = rdev2->desc_nr; /* compatibility */ | 924 | d->raid_disk = rdev2->desc_nr; /* compatibility */ |
| 896 | if (test_bit(Faulty, &rdev2->flags)) { | 925 | if (test_bit(Faulty, &rdev2->flags)) |
| 897 | d->state = (1<<MD_DISK_FAULTY); | 926 | d->state = (1<<MD_DISK_FAULTY); |
| 898 | failed++; | 927 | else if (test_bit(In_sync, &rdev2->flags)) { |
| 899 | } else if (test_bit(In_sync, &rdev2->flags)) { | ||
| 900 | d->state = (1<<MD_DISK_ACTIVE); | 928 | d->state = (1<<MD_DISK_ACTIVE); |
| 901 | d->state |= (1<<MD_DISK_SYNC); | 929 | d->state |= (1<<MD_DISK_SYNC); |
| 902 | active++; | 930 | active++; |
| @@ -1102,6 +1130,20 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 1102 | } | 1130 | } |
| 1103 | mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset); | 1131 | mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset); |
| 1104 | } | 1132 | } |
| 1133 | if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) { | ||
| 1134 | mddev->reshape_position = le64_to_cpu(sb->reshape_position); | ||
| 1135 | mddev->delta_disks = le32_to_cpu(sb->delta_disks); | ||
| 1136 | mddev->new_level = le32_to_cpu(sb->new_level); | ||
| 1137 | mddev->new_layout = le32_to_cpu(sb->new_layout); | ||
| 1138 | mddev->new_chunk = le32_to_cpu(sb->new_chunk)<<9; | ||
| 1139 | } else { | ||
| 1140 | mddev->reshape_position = MaxSector; | ||
| 1141 | mddev->delta_disks = 0; | ||
| 1142 | mddev->new_level = mddev->level; | ||
| 1143 | mddev->new_layout = mddev->layout; | ||
| 1144 | mddev->new_chunk = mddev->chunk_size; | ||
| 1145 | } | ||
| 1146 | |||
| 1105 | } else if (mddev->pers == NULL) { | 1147 | } else if (mddev->pers == NULL) { |
| 1106 | /* Insist of good event counter while assembling */ | 1148 | /* Insist of good event counter while assembling */ |
| 1107 | __u64 ev1 = le64_to_cpu(sb->events); | 1149 | __u64 ev1 = le64_to_cpu(sb->events); |
| @@ -1173,6 +1215,14 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 1173 | sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset); | 1215 | sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset); |
| 1174 | sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); | 1216 | sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); |
| 1175 | } | 1217 | } |
| 1218 | if (mddev->reshape_position != MaxSector) { | ||
| 1219 | sb->feature_map |= cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE); | ||
| 1220 | sb->reshape_position = cpu_to_le64(mddev->reshape_position); | ||
| 1221 | sb->new_layout = cpu_to_le32(mddev->new_layout); | ||
| 1222 | sb->delta_disks = cpu_to_le32(mddev->delta_disks); | ||
| 1223 | sb->new_level = cpu_to_le32(mddev->new_level); | ||
| 1224 | sb->new_chunk = cpu_to_le32(mddev->new_chunk>>9); | ||
| 1225 | } | ||
| 1176 | 1226 | ||
| 1177 | max_dev = 0; | 1227 | max_dev = 0; |
| 1178 | ITERATE_RDEV(mddev,rdev2,tmp) | 1228 | ITERATE_RDEV(mddev,rdev2,tmp) |
| @@ -1301,6 +1351,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
| 1301 | else | 1351 | else |
| 1302 | ko = &rdev->bdev->bd_disk->kobj; | 1352 | ko = &rdev->bdev->bd_disk->kobj; |
| 1303 | sysfs_create_link(&rdev->kobj, ko, "block"); | 1353 | sysfs_create_link(&rdev->kobj, ko, "block"); |
| 1354 | bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk); | ||
| 1304 | return 0; | 1355 | return 0; |
| 1305 | } | 1356 | } |
| 1306 | 1357 | ||
| @@ -1311,6 +1362,7 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) | |||
| 1311 | MD_BUG(); | 1362 | MD_BUG(); |
| 1312 | return; | 1363 | return; |
| 1313 | } | 1364 | } |
| 1365 | bd_release_from_disk(rdev->bdev, rdev->mddev->gendisk); | ||
| 1314 | list_del_init(&rdev->same_set); | 1366 | list_del_init(&rdev->same_set); |
| 1315 | printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); | 1367 | printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); |
| 1316 | rdev->mddev = NULL; | 1368 | rdev->mddev = NULL; |
| @@ -1493,7 +1545,7 @@ static void sync_sbs(mddev_t * mddev) | |||
| 1493 | } | 1545 | } |
| 1494 | } | 1546 | } |
| 1495 | 1547 | ||
| 1496 | static void md_update_sb(mddev_t * mddev) | 1548 | void md_update_sb(mddev_t * mddev) |
| 1497 | { | 1549 | { |
| 1498 | int err; | 1550 | int err; |
| 1499 | struct list_head *tmp; | 1551 | struct list_head *tmp; |
| @@ -1570,6 +1622,7 @@ repeat: | |||
| 1570 | wake_up(&mddev->sb_wait); | 1622 | wake_up(&mddev->sb_wait); |
| 1571 | 1623 | ||
| 1572 | } | 1624 | } |
| 1625 | EXPORT_SYMBOL_GPL(md_update_sb); | ||
| 1573 | 1626 | ||
| 1574 | /* words written to sysfs files may, or my not, be \n terminated. | 1627 | /* words written to sysfs files may, or my not, be \n terminated. |
| 1575 | * We want to accept with case. For this we use cmd_match. | 1628 | * We want to accept with case. For this we use cmd_match. |
| @@ -2162,7 +2215,9 @@ action_show(mddev_t *mddev, char *page) | |||
| 2162 | char *type = "idle"; | 2215 | char *type = "idle"; |
| 2163 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || | 2216 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || |
| 2164 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) { | 2217 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) { |
| 2165 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { | 2218 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) |
| 2219 | type = "reshape"; | ||
| 2220 | else if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { | ||
| 2166 | if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) | 2221 | if (!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) |
| 2167 | type = "resync"; | 2222 | type = "resync"; |
| 2168 | else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) | 2223 | else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) |
| @@ -2193,7 +2248,14 @@ action_store(mddev_t *mddev, const char *page, size_t len) | |||
| 2193 | return -EBUSY; | 2248 | return -EBUSY; |
| 2194 | else if (cmd_match(page, "resync") || cmd_match(page, "recover")) | 2249 | else if (cmd_match(page, "resync") || cmd_match(page, "recover")) |
| 2195 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | 2250 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
| 2196 | else { | 2251 | else if (cmd_match(page, "reshape")) { |
| 2252 | int err; | ||
| 2253 | if (mddev->pers->start_reshape == NULL) | ||
| 2254 | return -EINVAL; | ||
| 2255 | err = mddev->pers->start_reshape(mddev); | ||
| 2256 | if (err) | ||
| 2257 | return err; | ||
| 2258 | } else { | ||
| 2197 | if (cmd_match(page, "check")) | 2259 | if (cmd_match(page, "check")) |
| 2198 | set_bit(MD_RECOVERY_CHECK, &mddev->recovery); | 2260 | set_bit(MD_RECOVERY_CHECK, &mddev->recovery); |
| 2199 | else if (cmd_match(page, "repair")) | 2261 | else if (cmd_match(page, "repair")) |
| @@ -2304,6 +2366,63 @@ sync_completed_show(mddev_t *mddev, char *page) | |||
| 2304 | static struct md_sysfs_entry | 2366 | static struct md_sysfs_entry |
| 2305 | md_sync_completed = __ATTR_RO(sync_completed); | 2367 | md_sync_completed = __ATTR_RO(sync_completed); |
| 2306 | 2368 | ||
| 2369 | static ssize_t | ||
| 2370 | suspend_lo_show(mddev_t *mddev, char *page) | ||
| 2371 | { | ||
| 2372 | return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo); | ||
| 2373 | } | ||
| 2374 | |||
| 2375 | static ssize_t | ||
| 2376 | suspend_lo_store(mddev_t *mddev, const char *buf, size_t len) | ||
| 2377 | { | ||
| 2378 | char *e; | ||
| 2379 | unsigned long long new = simple_strtoull(buf, &e, 10); | ||
| 2380 | |||
| 2381 | if (mddev->pers->quiesce == NULL) | ||
| 2382 | return -EINVAL; | ||
| 2383 | if (buf == e || (*e && *e != '\n')) | ||
| 2384 | return -EINVAL; | ||
| 2385 | if (new >= mddev->suspend_hi || | ||
| 2386 | (new > mddev->suspend_lo && new < mddev->suspend_hi)) { | ||
| 2387 | mddev->suspend_lo = new; | ||
| 2388 | mddev->pers->quiesce(mddev, 2); | ||
| 2389 | return len; | ||
| 2390 | } else | ||
| 2391 | return -EINVAL; | ||
| 2392 | } | ||
| 2393 | static struct md_sysfs_entry md_suspend_lo = | ||
| 2394 | __ATTR(suspend_lo, S_IRUGO|S_IWUSR, suspend_lo_show, suspend_lo_store); | ||
| 2395 | |||
| 2396 | |||
| 2397 | static ssize_t | ||
| 2398 | suspend_hi_show(mddev_t *mddev, char *page) | ||
| 2399 | { | ||
| 2400 | return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_hi); | ||
| 2401 | } | ||
| 2402 | |||
| 2403 | static ssize_t | ||
| 2404 | suspend_hi_store(mddev_t *mddev, const char *buf, size_t len) | ||
| 2405 | { | ||
| 2406 | char *e; | ||
| 2407 | unsigned long long new = simple_strtoull(buf, &e, 10); | ||
| 2408 | |||
| 2409 | if (mddev->pers->quiesce == NULL) | ||
| 2410 | return -EINVAL; | ||
| 2411 | if (buf == e || (*e && *e != '\n')) | ||
| 2412 | return -EINVAL; | ||
| 2413 | if ((new <= mddev->suspend_lo && mddev->suspend_lo >= mddev->suspend_hi) || | ||
| 2414 | (new > mddev->suspend_lo && new > mddev->suspend_hi)) { | ||
| 2415 | mddev->suspend_hi = new; | ||
| 2416 | mddev->pers->quiesce(mddev, 1); | ||
| 2417 | mddev->pers->quiesce(mddev, 0); | ||
| 2418 | return len; | ||
| 2419 | } else | ||
| 2420 | return -EINVAL; | ||
| 2421 | } | ||
| 2422 | static struct md_sysfs_entry md_suspend_hi = | ||
| 2423 | __ATTR(suspend_hi, S_IRUGO|S_IWUSR, suspend_hi_show, suspend_hi_store); | ||
| 2424 | |||
| 2425 | |||
| 2307 | static struct attribute *md_default_attrs[] = { | 2426 | static struct attribute *md_default_attrs[] = { |
| 2308 | &md_level.attr, | 2427 | &md_level.attr, |
| 2309 | &md_raid_disks.attr, | 2428 | &md_raid_disks.attr, |
| @@ -2321,6 +2440,8 @@ static struct attribute *md_redundancy_attrs[] = { | |||
| 2321 | &md_sync_max.attr, | 2440 | &md_sync_max.attr, |
| 2322 | &md_sync_speed.attr, | 2441 | &md_sync_speed.attr, |
| 2323 | &md_sync_completed.attr, | 2442 | &md_sync_completed.attr, |
| 2443 | &md_suspend_lo.attr, | ||
| 2444 | &md_suspend_hi.attr, | ||
| 2324 | NULL, | 2445 | NULL, |
| 2325 | }; | 2446 | }; |
| 2326 | static struct attribute_group md_redundancy_group = { | 2447 | static struct attribute_group md_redundancy_group = { |
| @@ -2380,7 +2501,7 @@ int mdp_major = 0; | |||
| 2380 | 2501 | ||
| 2381 | static struct kobject *md_probe(dev_t dev, int *part, void *data) | 2502 | static struct kobject *md_probe(dev_t dev, int *part, void *data) |
| 2382 | { | 2503 | { |
| 2383 | static DECLARE_MUTEX(disks_sem); | 2504 | static DEFINE_MUTEX(disks_mutex); |
| 2384 | mddev_t *mddev = mddev_find(dev); | 2505 | mddev_t *mddev = mddev_find(dev); |
| 2385 | struct gendisk *disk; | 2506 | struct gendisk *disk; |
| 2386 | int partitioned = (MAJOR(dev) != MD_MAJOR); | 2507 | int partitioned = (MAJOR(dev) != MD_MAJOR); |
| @@ -2390,15 +2511,15 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) | |||
| 2390 | if (!mddev) | 2511 | if (!mddev) |
| 2391 | return NULL; | 2512 | return NULL; |
| 2392 | 2513 | ||
| 2393 | down(&disks_sem); | 2514 | mutex_lock(&disks_mutex); |
| 2394 | if (mddev->gendisk) { | 2515 | if (mddev->gendisk) { |
| 2395 | up(&disks_sem); | 2516 | mutex_unlock(&disks_mutex); |
| 2396 | mddev_put(mddev); | 2517 | mddev_put(mddev); |
| 2397 | return NULL; | 2518 | return NULL; |
| 2398 | } | 2519 | } |
| 2399 | disk = alloc_disk(1 << shift); | 2520 | disk = alloc_disk(1 << shift); |
| 2400 | if (!disk) { | 2521 | if (!disk) { |
| 2401 | up(&disks_sem); | 2522 | mutex_unlock(&disks_mutex); |
| 2402 | mddev_put(mddev); | 2523 | mddev_put(mddev); |
| 2403 | return NULL; | 2524 | return NULL; |
| 2404 | } | 2525 | } |
| @@ -2416,7 +2537,7 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) | |||
| 2416 | disk->queue = mddev->queue; | 2537 | disk->queue = mddev->queue; |
| 2417 | add_disk(disk); | 2538 | add_disk(disk); |
| 2418 | mddev->gendisk = disk; | 2539 | mddev->gendisk = disk; |
| 2419 | up(&disks_sem); | 2540 | mutex_unlock(&disks_mutex); |
| 2420 | mddev->kobj.parent = &disk->kobj; | 2541 | mddev->kobj.parent = &disk->kobj; |
| 2421 | mddev->kobj.k_name = NULL; | 2542 | mddev->kobj.k_name = NULL; |
| 2422 | snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md"); | 2543 | snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md"); |
| @@ -2539,6 +2660,14 @@ static int do_md_run(mddev_t * mddev) | |||
| 2539 | mddev->level = pers->level; | 2660 | mddev->level = pers->level; |
| 2540 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); | 2661 | strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); |
| 2541 | 2662 | ||
| 2663 | if (mddev->reshape_position != MaxSector && | ||
| 2664 | pers->start_reshape == NULL) { | ||
| 2665 | /* This personality cannot handle reshaping... */ | ||
| 2666 | mddev->pers = NULL; | ||
| 2667 | module_put(pers->owner); | ||
| 2668 | return -EINVAL; | ||
| 2669 | } | ||
| 2670 | |||
| 2542 | mddev->recovery = 0; | 2671 | mddev->recovery = 0; |
| 2543 | mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ | 2672 | mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ |
| 2544 | mddev->barriers_work = 1; | 2673 | mddev->barriers_work = 1; |
| @@ -2772,7 +2901,6 @@ static void autorun_array(mddev_t *mddev) | |||
| 2772 | */ | 2901 | */ |
| 2773 | static void autorun_devices(int part) | 2902 | static void autorun_devices(int part) |
| 2774 | { | 2903 | { |
| 2775 | struct list_head candidates; | ||
| 2776 | struct list_head *tmp; | 2904 | struct list_head *tmp; |
| 2777 | mdk_rdev_t *rdev0, *rdev; | 2905 | mdk_rdev_t *rdev0, *rdev; |
| 2778 | mddev_t *mddev; | 2906 | mddev_t *mddev; |
| @@ -2781,6 +2909,7 @@ static void autorun_devices(int part) | |||
| 2781 | printk(KERN_INFO "md: autorun ...\n"); | 2909 | printk(KERN_INFO "md: autorun ...\n"); |
| 2782 | while (!list_empty(&pending_raid_disks)) { | 2910 | while (!list_empty(&pending_raid_disks)) { |
| 2783 | dev_t dev; | 2911 | dev_t dev; |
| 2912 | LIST_HEAD(candidates); | ||
| 2784 | rdev0 = list_entry(pending_raid_disks.next, | 2913 | rdev0 = list_entry(pending_raid_disks.next, |
| 2785 | mdk_rdev_t, same_set); | 2914 | mdk_rdev_t, same_set); |
| 2786 | 2915 | ||
| @@ -3427,11 +3556,18 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) | |||
| 3427 | mddev->default_bitmap_offset = MD_SB_BYTES >> 9; | 3556 | mddev->default_bitmap_offset = MD_SB_BYTES >> 9; |
| 3428 | mddev->bitmap_offset = 0; | 3557 | mddev->bitmap_offset = 0; |
| 3429 | 3558 | ||
| 3559 | mddev->reshape_position = MaxSector; | ||
| 3560 | |||
| 3430 | /* | 3561 | /* |
| 3431 | * Generate a 128 bit UUID | 3562 | * Generate a 128 bit UUID |
| 3432 | */ | 3563 | */ |
| 3433 | get_random_bytes(mddev->uuid, 16); | 3564 | get_random_bytes(mddev->uuid, 16); |
| 3434 | 3565 | ||
| 3566 | mddev->new_level = mddev->level; | ||
| 3567 | mddev->new_chunk = mddev->chunk_size; | ||
| 3568 | mddev->new_layout = mddev->layout; | ||
| 3569 | mddev->delta_disks = 0; | ||
| 3570 | |||
| 3435 | return 0; | 3571 | return 0; |
| 3436 | } | 3572 | } |
| 3437 | 3573 | ||
| @@ -3440,6 +3576,7 @@ static int update_size(mddev_t *mddev, unsigned long size) | |||
| 3440 | mdk_rdev_t * rdev; | 3576 | mdk_rdev_t * rdev; |
| 3441 | int rv; | 3577 | int rv; |
| 3442 | struct list_head *tmp; | 3578 | struct list_head *tmp; |
| 3579 | int fit = (size == 0); | ||
| 3443 | 3580 | ||
| 3444 | if (mddev->pers->resize == NULL) | 3581 | if (mddev->pers->resize == NULL) |
| 3445 | return -EINVAL; | 3582 | return -EINVAL; |
| @@ -3457,7 +3594,6 @@ static int update_size(mddev_t *mddev, unsigned long size) | |||
| 3457 | return -EBUSY; | 3594 | return -EBUSY; |
| 3458 | ITERATE_RDEV(mddev,rdev,tmp) { | 3595 | ITERATE_RDEV(mddev,rdev,tmp) { |
| 3459 | sector_t avail; | 3596 | sector_t avail; |
| 3460 | int fit = (size == 0); | ||
| 3461 | if (rdev->sb_offset > rdev->data_offset) | 3597 | if (rdev->sb_offset > rdev->data_offset) |
| 3462 | avail = (rdev->sb_offset*2) - rdev->data_offset; | 3598 | avail = (rdev->sb_offset*2) - rdev->data_offset; |
| 3463 | else | 3599 | else |
| @@ -3487,14 +3623,16 @@ static int update_raid_disks(mddev_t *mddev, int raid_disks) | |||
| 3487 | { | 3623 | { |
| 3488 | int rv; | 3624 | int rv; |
| 3489 | /* change the number of raid disks */ | 3625 | /* change the number of raid disks */ |
| 3490 | if (mddev->pers->reshape == NULL) | 3626 | if (mddev->pers->check_reshape == NULL) |
| 3491 | return -EINVAL; | 3627 | return -EINVAL; |
| 3492 | if (raid_disks <= 0 || | 3628 | if (raid_disks <= 0 || |
| 3493 | raid_disks >= mddev->max_disks) | 3629 | raid_disks >= mddev->max_disks) |
| 3494 | return -EINVAL; | 3630 | return -EINVAL; |
| 3495 | if (mddev->sync_thread) | 3631 | if (mddev->sync_thread || mddev->reshape_position != MaxSector) |
| 3496 | return -EBUSY; | 3632 | return -EBUSY; |
| 3497 | rv = mddev->pers->reshape(mddev, raid_disks); | 3633 | mddev->delta_disks = raid_disks - mddev->raid_disks; |
| 3634 | |||
| 3635 | rv = mddev->pers->check_reshape(mddev); | ||
| 3498 | return rv; | 3636 | return rv; |
| 3499 | } | 3637 | } |
| 3500 | 3638 | ||
| @@ -4041,7 +4179,10 @@ static void status_unused(struct seq_file *seq) | |||
| 4041 | 4179 | ||
| 4042 | static void status_resync(struct seq_file *seq, mddev_t * mddev) | 4180 | static void status_resync(struct seq_file *seq, mddev_t * mddev) |
| 4043 | { | 4181 | { |
| 4044 | unsigned long max_blocks, resync, res, dt, db, rt; | 4182 | sector_t max_blocks, resync, res; |
| 4183 | unsigned long dt, db, rt; | ||
| 4184 | int scale; | ||
| 4185 | unsigned int per_milli; | ||
| 4045 | 4186 | ||
| 4046 | resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2; | 4187 | resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2; |
| 4047 | 4188 | ||
| @@ -4057,9 +4198,22 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev) | |||
| 4057 | MD_BUG(); | 4198 | MD_BUG(); |
| 4058 | return; | 4199 | return; |
| 4059 | } | 4200 | } |
| 4060 | res = (resync/1024)*1000/(max_blocks/1024 + 1); | 4201 | /* Pick 'scale' such that (resync>>scale)*1000 will fit |
| 4202 | * in a sector_t, and (max_blocks>>scale) will fit in a | ||
| 4203 | * u32, as those are the requirements for sector_div. | ||
| 4204 | * Thus 'scale' must be at least 10 | ||
| 4205 | */ | ||
| 4206 | scale = 10; | ||
| 4207 | if (sizeof(sector_t) > sizeof(unsigned long)) { | ||
| 4208 | while ( max_blocks/2 > (1ULL<<(scale+32))) | ||
| 4209 | scale++; | ||
| 4210 | } | ||
| 4211 | res = (resync>>scale)*1000; | ||
| 4212 | sector_div(res, (u32)((max_blocks>>scale)+1)); | ||
| 4213 | |||
| 4214 | per_milli = res; | ||
| 4061 | { | 4215 | { |
| 4062 | int i, x = res/50, y = 20-x; | 4216 | int i, x = per_milli/50, y = 20-x; |
| 4063 | seq_printf(seq, "["); | 4217 | seq_printf(seq, "["); |
| 4064 | for (i = 0; i < x; i++) | 4218 | for (i = 0; i < x; i++) |
| 4065 | seq_printf(seq, "="); | 4219 | seq_printf(seq, "="); |
| @@ -4068,10 +4222,14 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev) | |||
| 4068 | seq_printf(seq, "."); | 4222 | seq_printf(seq, "."); |
| 4069 | seq_printf(seq, "] "); | 4223 | seq_printf(seq, "] "); |
| 4070 | } | 4224 | } |
| 4071 | seq_printf(seq, " %s =%3lu.%lu%% (%lu/%lu)", | 4225 | seq_printf(seq, " %s =%3u.%u%% (%llu/%llu)", |
| 4226 | (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)? | ||
| 4227 | "reshape" : | ||
| 4072 | (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ? | 4228 | (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ? |
| 4073 | "resync" : "recovery"), | 4229 | "resync" : "recovery")), |
| 4074 | res/10, res % 10, resync, max_blocks); | 4230 | per_milli/10, per_milli % 10, |
| 4231 | (unsigned long long) resync, | ||
| 4232 | (unsigned long long) max_blocks); | ||
| 4075 | 4233 | ||
| 4076 | /* | 4234 | /* |
| 4077 | * We do not want to overflow, so the order of operands and | 4235 | * We do not want to overflow, so the order of operands and |
| @@ -4085,7 +4243,7 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev) | |||
| 4085 | dt = ((jiffies - mddev->resync_mark) / HZ); | 4243 | dt = ((jiffies - mddev->resync_mark) / HZ); |
| 4086 | if (!dt) dt++; | 4244 | if (!dt) dt++; |
| 4087 | db = resync - (mddev->resync_mark_cnt/2); | 4245 | db = resync - (mddev->resync_mark_cnt/2); |
| 4088 | rt = (dt * ((max_blocks-resync) / (db/100+1)))/100; | 4246 | rt = (dt * ((unsigned long)(max_blocks-resync) / (db/100+1)))/100; |
| 4089 | 4247 | ||
| 4090 | seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6); | 4248 | seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6); |
| 4091 | 4249 | ||
| @@ -4442,7 +4600,7 @@ static DECLARE_WAIT_QUEUE_HEAD(resync_wait); | |||
| 4442 | 4600 | ||
| 4443 | #define SYNC_MARKS 10 | 4601 | #define SYNC_MARKS 10 |
| 4444 | #define SYNC_MARK_STEP (3*HZ) | 4602 | #define SYNC_MARK_STEP (3*HZ) |
| 4445 | static void md_do_sync(mddev_t *mddev) | 4603 | void md_do_sync(mddev_t *mddev) |
| 4446 | { | 4604 | { |
| 4447 | mddev_t *mddev2; | 4605 | mddev_t *mddev2; |
| 4448 | unsigned int currspeed = 0, | 4606 | unsigned int currspeed = 0, |
| @@ -4522,7 +4680,9 @@ static void md_do_sync(mddev_t *mddev) | |||
| 4522 | */ | 4680 | */ |
| 4523 | max_sectors = mddev->resync_max_sectors; | 4681 | max_sectors = mddev->resync_max_sectors; |
| 4524 | mddev->resync_mismatches = 0; | 4682 | mddev->resync_mismatches = 0; |
| 4525 | } else | 4683 | } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) |
| 4684 | max_sectors = mddev->size << 1; | ||
| 4685 | else | ||
| 4526 | /* recovery follows the physical size of devices */ | 4686 | /* recovery follows the physical size of devices */ |
| 4527 | max_sectors = mddev->size << 1; | 4687 | max_sectors = mddev->size << 1; |
| 4528 | 4688 | ||
| @@ -4658,6 +4818,8 @@ static void md_do_sync(mddev_t *mddev) | |||
| 4658 | mddev->pers->sync_request(mddev, max_sectors, &skipped, 1); | 4818 | mddev->pers->sync_request(mddev, max_sectors, &skipped, 1); |
| 4659 | 4819 | ||
| 4660 | if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && | 4820 | if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && |
| 4821 | test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && | ||
| 4822 | !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && | ||
| 4661 | mddev->curr_resync > 2 && | 4823 | mddev->curr_resync > 2 && |
| 4662 | mddev->curr_resync >= mddev->recovery_cp) { | 4824 | mddev->curr_resync >= mddev->recovery_cp) { |
| 4663 | if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { | 4825 | if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { |
| @@ -4675,6 +4837,7 @@ static void md_do_sync(mddev_t *mddev) | |||
| 4675 | set_bit(MD_RECOVERY_DONE, &mddev->recovery); | 4837 | set_bit(MD_RECOVERY_DONE, &mddev->recovery); |
| 4676 | md_wakeup_thread(mddev->thread); | 4838 | md_wakeup_thread(mddev->thread); |
| 4677 | } | 4839 | } |
| 4840 | EXPORT_SYMBOL_GPL(md_do_sync); | ||
| 4678 | 4841 | ||
| 4679 | 4842 | ||
| 4680 | /* | 4843 | /* |
| @@ -4730,7 +4893,7 @@ void md_check_recovery(mddev_t *mddev) | |||
| 4730 | )) | 4893 | )) |
| 4731 | return; | 4894 | return; |
| 4732 | 4895 | ||
| 4733 | if (mddev_trylock(mddev)==0) { | 4896 | if (mddev_trylock(mddev)) { |
| 4734 | int spares =0; | 4897 | int spares =0; |
| 4735 | 4898 | ||
| 4736 | spin_lock_irq(&mddev->write_lock); | 4899 | spin_lock_irq(&mddev->write_lock); |
| @@ -4866,7 +5029,7 @@ static int md_notify_reboot(struct notifier_block *this, | |||
| 4866 | printk(KERN_INFO "md: stopping all md devices.\n"); | 5029 | printk(KERN_INFO "md: stopping all md devices.\n"); |
| 4867 | 5030 | ||
| 4868 | ITERATE_MDDEV(mddev,tmp) | 5031 | ITERATE_MDDEV(mddev,tmp) |
| 4869 | if (mddev_trylock(mddev)==0) | 5032 | if (mddev_trylock(mddev)) |
| 4870 | do_md_stop (mddev, 1); | 5033 | do_md_stop (mddev, 1); |
| 4871 | /* | 5034 | /* |
| 4872 | * certain more exotic SCSI devices are known to be | 5035 | * certain more exotic SCSI devices are known to be |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 5d88329e3c7a..3cb0872a845d 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -1402,6 +1402,9 @@ static void raid1d(mddev_t *mddev) | |||
| 1402 | clear_bit(R1BIO_BarrierRetry, &r1_bio->state); | 1402 | clear_bit(R1BIO_BarrierRetry, &r1_bio->state); |
| 1403 | clear_bit(R1BIO_Barrier, &r1_bio->state); | 1403 | clear_bit(R1BIO_Barrier, &r1_bio->state); |
| 1404 | for (i=0; i < conf->raid_disks; i++) | 1404 | for (i=0; i < conf->raid_disks; i++) |
| 1405 | if (r1_bio->bios[i]) | ||
| 1406 | atomic_inc(&r1_bio->remaining); | ||
| 1407 | for (i=0; i < conf->raid_disks; i++) | ||
| 1405 | if (r1_bio->bios[i]) { | 1408 | if (r1_bio->bios[i]) { |
| 1406 | struct bio_vec *bvec; | 1409 | struct bio_vec *bvec; |
| 1407 | int j; | 1410 | int j; |
| @@ -1789,6 +1792,11 @@ static int run(mddev_t *mddev) | |||
| 1789 | mdname(mddev), mddev->level); | 1792 | mdname(mddev), mddev->level); |
| 1790 | goto out; | 1793 | goto out; |
| 1791 | } | 1794 | } |
| 1795 | if (mddev->reshape_position != MaxSector) { | ||
| 1796 | printk("raid1: %s: reshape_position set but not supported\n", | ||
| 1797 | mdname(mddev)); | ||
| 1798 | goto out; | ||
| 1799 | } | ||
| 1792 | /* | 1800 | /* |
| 1793 | * copy the already verified devices into our private RAID1 | 1801 | * copy the already verified devices into our private RAID1 |
| 1794 | * bookkeeping area. [whatever we allocate in run(), | 1802 | * bookkeeping area. [whatever we allocate in run(), |
| @@ -1971,7 +1979,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors) | |||
| 1971 | return 0; | 1979 | return 0; |
| 1972 | } | 1980 | } |
| 1973 | 1981 | ||
| 1974 | static int raid1_reshape(mddev_t *mddev, int raid_disks) | 1982 | static int raid1_reshape(mddev_t *mddev) |
| 1975 | { | 1983 | { |
| 1976 | /* We need to: | 1984 | /* We need to: |
| 1977 | * 1/ resize the r1bio_pool | 1985 | * 1/ resize the r1bio_pool |
| @@ -1988,10 +1996,22 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) | |||
| 1988 | struct pool_info *newpoolinfo; | 1996 | struct pool_info *newpoolinfo; |
| 1989 | mirror_info_t *newmirrors; | 1997 | mirror_info_t *newmirrors; |
| 1990 | conf_t *conf = mddev_to_conf(mddev); | 1998 | conf_t *conf = mddev_to_conf(mddev); |
| 1991 | int cnt; | 1999 | int cnt, raid_disks; |
| 1992 | 2000 | ||
| 1993 | int d, d2; | 2001 | int d, d2; |
| 1994 | 2002 | ||
| 2003 | /* Cannot change chunk_size, layout, or level */ | ||
| 2004 | if (mddev->chunk_size != mddev->new_chunk || | ||
| 2005 | mddev->layout != mddev->new_layout || | ||
| 2006 | mddev->level != mddev->new_level) { | ||
| 2007 | mddev->new_chunk = mddev->chunk_size; | ||
| 2008 | mddev->new_layout = mddev->layout; | ||
| 2009 | mddev->new_level = mddev->level; | ||
| 2010 | return -EINVAL; | ||
| 2011 | } | ||
| 2012 | |||
| 2013 | raid_disks = mddev->raid_disks + mddev->delta_disks; | ||
| 2014 | |||
| 1995 | if (raid_disks < conf->raid_disks) { | 2015 | if (raid_disks < conf->raid_disks) { |
| 1996 | cnt=0; | 2016 | cnt=0; |
| 1997 | for (d= 0; d < conf->raid_disks; d++) | 2017 | for (d= 0; d < conf->raid_disks; d++) |
| @@ -2038,6 +2058,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) | |||
| 2038 | 2058 | ||
| 2039 | mddev->degraded += (raid_disks - conf->raid_disks); | 2059 | mddev->degraded += (raid_disks - conf->raid_disks); |
| 2040 | conf->raid_disks = mddev->raid_disks = raid_disks; | 2060 | conf->raid_disks = mddev->raid_disks = raid_disks; |
| 2061 | mddev->delta_disks = 0; | ||
| 2041 | 2062 | ||
| 2042 | conf->last_used = 0; /* just make sure it is in-range */ | 2063 | conf->last_used = 0; /* just make sure it is in-range */ |
| 2043 | lower_barrier(conf); | 2064 | lower_barrier(conf); |
| @@ -2079,7 +2100,7 @@ static struct mdk_personality raid1_personality = | |||
| 2079 | .spare_active = raid1_spare_active, | 2100 | .spare_active = raid1_spare_active, |
| 2080 | .sync_request = sync_request, | 2101 | .sync_request = sync_request, |
| 2081 | .resize = raid1_resize, | 2102 | .resize = raid1_resize, |
| 2082 | .reshape = raid1_reshape, | 2103 | .check_reshape = raid1_reshape, |
| 2083 | .quiesce = raid1_quiesce, | 2104 | .quiesce = raid1_quiesce, |
| 2084 | }; | 2105 | }; |
| 2085 | 2106 | ||
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2dba305daf3c..dae740adaf65 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/raid/raid5.h> | 22 | #include <linux/raid/raid5.h> |
| 23 | #include <linux/highmem.h> | 23 | #include <linux/highmem.h> |
| 24 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
| 25 | #include <linux/kthread.h> | ||
| 25 | #include <asm/atomic.h> | 26 | #include <asm/atomic.h> |
| 26 | 27 | ||
| 27 | #include <linux/raid/bitmap.h> | 28 | #include <linux/raid/bitmap.h> |
| @@ -93,11 +94,11 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh) | |||
| 93 | if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) | 94 | if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) |
| 94 | md_wakeup_thread(conf->mddev->thread); | 95 | md_wakeup_thread(conf->mddev->thread); |
| 95 | } | 96 | } |
| 96 | list_add_tail(&sh->lru, &conf->inactive_list); | ||
| 97 | atomic_dec(&conf->active_stripes); | 97 | atomic_dec(&conf->active_stripes); |
| 98 | if (!conf->inactive_blocked || | 98 | if (!test_bit(STRIPE_EXPANDING, &sh->state)) { |
| 99 | atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4)) | 99 | list_add_tail(&sh->lru, &conf->inactive_list); |
| 100 | wake_up(&conf->wait_for_stripe); | 100 | wake_up(&conf->wait_for_stripe); |
| 101 | } | ||
| 101 | } | 102 | } |
| 102 | } | 103 | } |
| 103 | } | 104 | } |
| @@ -178,10 +179,10 @@ static int grow_buffers(struct stripe_head *sh, int num) | |||
| 178 | 179 | ||
| 179 | static void raid5_build_block (struct stripe_head *sh, int i); | 180 | static void raid5_build_block (struct stripe_head *sh, int i); |
| 180 | 181 | ||
| 181 | static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) | 182 | static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int disks) |
| 182 | { | 183 | { |
| 183 | raid5_conf_t *conf = sh->raid_conf; | 184 | raid5_conf_t *conf = sh->raid_conf; |
| 184 | int disks = conf->raid_disks, i; | 185 | int i; |
| 185 | 186 | ||
| 186 | if (atomic_read(&sh->count) != 0) | 187 | if (atomic_read(&sh->count) != 0) |
| 187 | BUG(); | 188 | BUG(); |
| @@ -198,7 +199,9 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) | |||
| 198 | sh->pd_idx = pd_idx; | 199 | sh->pd_idx = pd_idx; |
| 199 | sh->state = 0; | 200 | sh->state = 0; |
| 200 | 201 | ||
| 201 | for (i=disks; i--; ) { | 202 | sh->disks = disks; |
| 203 | |||
| 204 | for (i = sh->disks; i--; ) { | ||
| 202 | struct r5dev *dev = &sh->dev[i]; | 205 | struct r5dev *dev = &sh->dev[i]; |
| 203 | 206 | ||
| 204 | if (dev->toread || dev->towrite || dev->written || | 207 | if (dev->toread || dev->towrite || dev->written || |
| @@ -215,7 +218,7 @@ static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx) | |||
| 215 | insert_hash(conf, sh); | 218 | insert_hash(conf, sh); |
| 216 | } | 219 | } |
| 217 | 220 | ||
| 218 | static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) | 221 | static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector, int disks) |
| 219 | { | 222 | { |
| 220 | struct stripe_head *sh; | 223 | struct stripe_head *sh; |
| 221 | struct hlist_node *hn; | 224 | struct hlist_node *hn; |
| @@ -223,7 +226,7 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) | |||
| 223 | CHECK_DEVLOCK(); | 226 | CHECK_DEVLOCK(); |
| 224 | PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); | 227 | PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); |
| 225 | hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash) | 228 | hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash) |
| 226 | if (sh->sector == sector) | 229 | if (sh->sector == sector && sh->disks == disks) |
| 227 | return sh; | 230 | return sh; |
| 228 | PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); | 231 | PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); |
| 229 | return NULL; | 232 | return NULL; |
| @@ -232,8 +235,8 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) | |||
| 232 | static void unplug_slaves(mddev_t *mddev); | 235 | static void unplug_slaves(mddev_t *mddev); |
| 233 | static void raid5_unplug_device(request_queue_t *q); | 236 | static void raid5_unplug_device(request_queue_t *q); |
| 234 | 237 | ||
| 235 | static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector, | 238 | static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector, int disks, |
| 236 | int pd_idx, int noblock) | 239 | int pd_idx, int noblock) |
| 237 | { | 240 | { |
| 238 | struct stripe_head *sh; | 241 | struct stripe_head *sh; |
| 239 | 242 | ||
| @@ -245,7 +248,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector | |||
| 245 | wait_event_lock_irq(conf->wait_for_stripe, | 248 | wait_event_lock_irq(conf->wait_for_stripe, |
| 246 | conf->quiesce == 0, | 249 | conf->quiesce == 0, |
| 247 | conf->device_lock, /* nothing */); | 250 | conf->device_lock, /* nothing */); |
| 248 | sh = __find_stripe(conf, sector); | 251 | sh = __find_stripe(conf, sector, disks); |
| 249 | if (!sh) { | 252 | if (!sh) { |
| 250 | if (!conf->inactive_blocked) | 253 | if (!conf->inactive_blocked) |
| 251 | sh = get_free_stripe(conf); | 254 | sh = get_free_stripe(conf); |
| @@ -259,11 +262,11 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector | |||
| 259 | < (conf->max_nr_stripes *3/4) | 262 | < (conf->max_nr_stripes *3/4) |
| 260 | || !conf->inactive_blocked), | 263 | || !conf->inactive_blocked), |
| 261 | conf->device_lock, | 264 | conf->device_lock, |
| 262 | unplug_slaves(conf->mddev); | 265 | unplug_slaves(conf->mddev) |
| 263 | ); | 266 | ); |
| 264 | conf->inactive_blocked = 0; | 267 | conf->inactive_blocked = 0; |
| 265 | } else | 268 | } else |
| 266 | init_stripe(sh, sector, pd_idx); | 269 | init_stripe(sh, sector, pd_idx, disks); |
| 267 | } else { | 270 | } else { |
| 268 | if (atomic_read(&sh->count)) { | 271 | if (atomic_read(&sh->count)) { |
| 269 | if (!list_empty(&sh->lru)) | 272 | if (!list_empty(&sh->lru)) |
| @@ -271,9 +274,8 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector | |||
| 271 | } else { | 274 | } else { |
| 272 | if (!test_bit(STRIPE_HANDLE, &sh->state)) | 275 | if (!test_bit(STRIPE_HANDLE, &sh->state)) |
| 273 | atomic_inc(&conf->active_stripes); | 276 | atomic_inc(&conf->active_stripes); |
| 274 | if (list_empty(&sh->lru)) | 277 | if (!list_empty(&sh->lru)) |
| 275 | BUG(); | 278 | list_del_init(&sh->lru); |
| 276 | list_del_init(&sh->lru); | ||
| 277 | } | 279 | } |
| 278 | } | 280 | } |
| 279 | } while (sh == NULL); | 281 | } while (sh == NULL); |
| @@ -300,6 +302,7 @@ static int grow_one_stripe(raid5_conf_t *conf) | |||
| 300 | kmem_cache_free(conf->slab_cache, sh); | 302 | kmem_cache_free(conf->slab_cache, sh); |
| 301 | return 0; | 303 | return 0; |
| 302 | } | 304 | } |
| 305 | sh->disks = conf->raid_disks; | ||
| 303 | /* we just created an active stripe so... */ | 306 | /* we just created an active stripe so... */ |
| 304 | atomic_set(&sh->count, 1); | 307 | atomic_set(&sh->count, 1); |
| 305 | atomic_inc(&conf->active_stripes); | 308 | atomic_inc(&conf->active_stripes); |
| @@ -313,14 +316,16 @@ static int grow_stripes(raid5_conf_t *conf, int num) | |||
| 313 | kmem_cache_t *sc; | 316 | kmem_cache_t *sc; |
| 314 | int devs = conf->raid_disks; | 317 | int devs = conf->raid_disks; |
| 315 | 318 | ||
| 316 | sprintf(conf->cache_name, "raid5/%s", mdname(conf->mddev)); | 319 | sprintf(conf->cache_name[0], "raid5/%s", mdname(conf->mddev)); |
| 317 | 320 | sprintf(conf->cache_name[1], "raid5/%s-alt", mdname(conf->mddev)); | |
| 318 | sc = kmem_cache_create(conf->cache_name, | 321 | conf->active_name = 0; |
| 322 | sc = kmem_cache_create(conf->cache_name[conf->active_name], | ||
| 319 | sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), | 323 | sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), |
| 320 | 0, 0, NULL, NULL); | 324 | 0, 0, NULL, NULL); |
| 321 | if (!sc) | 325 | if (!sc) |
| 322 | return 1; | 326 | return 1; |
| 323 | conf->slab_cache = sc; | 327 | conf->slab_cache = sc; |
| 328 | conf->pool_size = devs; | ||
| 324 | while (num--) { | 329 | while (num--) { |
| 325 | if (!grow_one_stripe(conf)) | 330 | if (!grow_one_stripe(conf)) |
| 326 | return 1; | 331 | return 1; |
| @@ -328,6 +333,129 @@ static int grow_stripes(raid5_conf_t *conf, int num) | |||
| 328 | return 0; | 333 | return 0; |
| 329 | } | 334 | } |
| 330 | 335 | ||
| 336 | #ifdef CONFIG_MD_RAID5_RESHAPE | ||
| 337 | static int resize_stripes(raid5_conf_t *conf, int newsize) | ||
| 338 | { | ||
| 339 | /* Make all the stripes able to hold 'newsize' devices. | ||
| 340 | * New slots in each stripe get 'page' set to a new page. | ||
| 341 | * | ||
| 342 | * This happens in stages: | ||
| 343 | * 1/ create a new kmem_cache and allocate the required number of | ||
| 344 | * stripe_heads. | ||
| 345 | * 2/ gather all the old stripe_heads and tranfer the pages across | ||
| 346 | * to the new stripe_heads. This will have the side effect of | ||
| 347 | * freezing the array as once all stripe_heads have been collected, | ||
| 348 | * no IO will be possible. Old stripe heads are freed once their | ||
| 349 | * pages have been transferred over, and the old kmem_cache is | ||
| 350 | * freed when all stripes are done. | ||
| 351 | * 3/ reallocate conf->disks to be suitable bigger. If this fails, | ||
| 352 | * we simple return a failre status - no need to clean anything up. | ||
| 353 | * 4/ allocate new pages for the new slots in the new stripe_heads. | ||
| 354 | * If this fails, we don't bother trying the shrink the | ||
| 355 | * stripe_heads down again, we just leave them as they are. | ||
| 356 | * As each stripe_head is processed the new one is released into | ||
| 357 | * active service. | ||
| 358 | * | ||
| 359 | * Once step2 is started, we cannot afford to wait for a write, | ||
| 360 | * so we use GFP_NOIO allocations. | ||
| 361 | */ | ||
| 362 | struct stripe_head *osh, *nsh; | ||
| 363 | LIST_HEAD(newstripes); | ||
| 364 | struct disk_info *ndisks; | ||
| 365 | int err = 0; | ||
| 366 | kmem_cache_t *sc; | ||
| 367 | int i; | ||
| 368 | |||
| 369 | if (newsize <= conf->pool_size) | ||
| 370 | return 0; /* never bother to shrink */ | ||
| 371 | |||
| 372 | /* Step 1 */ | ||
| 373 | sc = kmem_cache_create(conf->cache_name[1-conf->active_name], | ||
| 374 | sizeof(struct stripe_head)+(newsize-1)*sizeof(struct r5dev), | ||
| 375 | 0, 0, NULL, NULL); | ||
| 376 | if (!sc) | ||
| 377 | return -ENOMEM; | ||
| 378 | |||
| 379 | for (i = conf->max_nr_stripes; i; i--) { | ||
| 380 | nsh = kmem_cache_alloc(sc, GFP_KERNEL); | ||
| 381 | if (!nsh) | ||
| 382 | break; | ||
| 383 | |||
| 384 | memset(nsh, 0, sizeof(*nsh) + (newsize-1)*sizeof(struct r5dev)); | ||
| 385 | |||
| 386 | nsh->raid_conf = conf; | ||
| 387 | spin_lock_init(&nsh->lock); | ||
| 388 | |||
| 389 | list_add(&nsh->lru, &newstripes); | ||
| 390 | } | ||
| 391 | if (i) { | ||
| 392 | /* didn't get enough, give up */ | ||
| 393 | while (!list_empty(&newstripes)) { | ||
| 394 | nsh = list_entry(newstripes.next, struct stripe_head, lru); | ||
| 395 | list_del(&nsh->lru); | ||
| 396 | kmem_cache_free(sc, nsh); | ||
| 397 | } | ||
| 398 | kmem_cache_destroy(sc); | ||
| 399 | return -ENOMEM; | ||
| 400 | } | ||
| 401 | /* Step 2 - Must use GFP_NOIO now. | ||
| 402 | * OK, we have enough stripes, start collecting inactive | ||
| 403 | * stripes and copying them over | ||
| 404 | */ | ||
| 405 | list_for_each_entry(nsh, &newstripes, lru) { | ||
| 406 | spin_lock_irq(&conf->device_lock); | ||
| 407 | wait_event_lock_irq(conf->wait_for_stripe, | ||
| 408 | !list_empty(&conf->inactive_list), | ||
| 409 | conf->device_lock, | ||
| 410 | unplug_slaves(conf->mddev) | ||
| 411 | ); | ||
| 412 | osh = get_free_stripe(conf); | ||
| 413 | spin_unlock_irq(&conf->device_lock); | ||
| 414 | atomic_set(&nsh->count, 1); | ||
| 415 | for(i=0; i<conf->pool_size; i++) | ||
| 416 | nsh->dev[i].page = osh->dev[i].page; | ||
| 417 | for( ; i<newsize; i++) | ||
| 418 | nsh->dev[i].page = NULL; | ||
| 419 | kmem_cache_free(conf->slab_cache, osh); | ||
| 420 | } | ||
| 421 | kmem_cache_destroy(conf->slab_cache); | ||
| 422 | |||
| 423 | /* Step 3. | ||
| 424 | * At this point, we are holding all the stripes so the array | ||
| 425 | * is completely stalled, so now is a good time to resize | ||
| 426 | * conf->disks. | ||
| 427 | */ | ||
| 428 | ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO); | ||
| 429 | if (ndisks) { | ||
| 430 | for (i=0; i<conf->raid_disks; i++) | ||
| 431 | ndisks[i] = conf->disks[i]; | ||
| 432 | kfree(conf->disks); | ||
| 433 | conf->disks = ndisks; | ||
| 434 | } else | ||
| 435 | err = -ENOMEM; | ||
| 436 | |||
| 437 | /* Step 4, return new stripes to service */ | ||
| 438 | while(!list_empty(&newstripes)) { | ||
| 439 | nsh = list_entry(newstripes.next, struct stripe_head, lru); | ||
| 440 | list_del_init(&nsh->lru); | ||
| 441 | for (i=conf->raid_disks; i < newsize; i++) | ||
| 442 | if (nsh->dev[i].page == NULL) { | ||
| 443 | struct page *p = alloc_page(GFP_NOIO); | ||
| 444 | nsh->dev[i].page = p; | ||
| 445 | if (!p) | ||
| 446 | err = -ENOMEM; | ||
| 447 | } | ||
| 448 | release_stripe(nsh); | ||
| 449 | } | ||
| 450 | /* critical section pass, GFP_NOIO no longer needed */ | ||
| 451 | |||
| 452 | conf->slab_cache = sc; | ||
| 453 | conf->active_name = 1-conf->active_name; | ||
| 454 | conf->pool_size = newsize; | ||
| 455 | return err; | ||
| 456 | } | ||
| 457 | #endif | ||
| 458 | |||
| 331 | static int drop_one_stripe(raid5_conf_t *conf) | 459 | static int drop_one_stripe(raid5_conf_t *conf) |
| 332 | { | 460 | { |
| 333 | struct stripe_head *sh; | 461 | struct stripe_head *sh; |
| @@ -339,7 +467,7 @@ static int drop_one_stripe(raid5_conf_t *conf) | |||
| 339 | return 0; | 467 | return 0; |
| 340 | if (atomic_read(&sh->count)) | 468 | if (atomic_read(&sh->count)) |
| 341 | BUG(); | 469 | BUG(); |
| 342 | shrink_buffers(sh, conf->raid_disks); | 470 | shrink_buffers(sh, conf->pool_size); |
| 343 | kmem_cache_free(conf->slab_cache, sh); | 471 | kmem_cache_free(conf->slab_cache, sh); |
| 344 | atomic_dec(&conf->active_stripes); | 472 | atomic_dec(&conf->active_stripes); |
| 345 | return 1; | 473 | return 1; |
| @@ -360,7 +488,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, | |||
| 360 | { | 488 | { |
| 361 | struct stripe_head *sh = bi->bi_private; | 489 | struct stripe_head *sh = bi->bi_private; |
| 362 | raid5_conf_t *conf = sh->raid_conf; | 490 | raid5_conf_t *conf = sh->raid_conf; |
| 363 | int disks = conf->raid_disks, i; | 491 | int disks = sh->disks, i; |
| 364 | int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); | 492 | int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); |
| 365 | 493 | ||
| 366 | if (bi->bi_size) | 494 | if (bi->bi_size) |
| @@ -458,7 +586,7 @@ static int raid5_end_write_request (struct bio *bi, unsigned int bytes_done, | |||
| 458 | { | 586 | { |
| 459 | struct stripe_head *sh = bi->bi_private; | 587 | struct stripe_head *sh = bi->bi_private; |
| 460 | raid5_conf_t *conf = sh->raid_conf; | 588 | raid5_conf_t *conf = sh->raid_conf; |
| 461 | int disks = conf->raid_disks, i; | 589 | int disks = sh->disks, i; |
| 462 | unsigned long flags; | 590 | unsigned long flags; |
| 463 | int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); | 591 | int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags); |
| 464 | 592 | ||
| @@ -612,7 +740,7 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks, | |||
| 612 | static sector_t compute_blocknr(struct stripe_head *sh, int i) | 740 | static sector_t compute_blocknr(struct stripe_head *sh, int i) |
| 613 | { | 741 | { |
| 614 | raid5_conf_t *conf = sh->raid_conf; | 742 | raid5_conf_t *conf = sh->raid_conf; |
| 615 | int raid_disks = conf->raid_disks, data_disks = raid_disks - 1; | 743 | int raid_disks = sh->disks, data_disks = raid_disks - 1; |
| 616 | sector_t new_sector = sh->sector, check; | 744 | sector_t new_sector = sh->sector, check; |
| 617 | int sectors_per_chunk = conf->chunk_size >> 9; | 745 | int sectors_per_chunk = conf->chunk_size >> 9; |
| 618 | sector_t stripe; | 746 | sector_t stripe; |
| @@ -713,8 +841,7 @@ static void copy_data(int frombio, struct bio *bio, | |||
| 713 | 841 | ||
| 714 | static void compute_block(struct stripe_head *sh, int dd_idx) | 842 | static void compute_block(struct stripe_head *sh, int dd_idx) |
| 715 | { | 843 | { |
| 716 | raid5_conf_t *conf = sh->raid_conf; | 844 | int i, count, disks = sh->disks; |
| 717 | int i, count, disks = conf->raid_disks; | ||
| 718 | void *ptr[MAX_XOR_BLOCKS], *p; | 845 | void *ptr[MAX_XOR_BLOCKS], *p; |
| 719 | 846 | ||
| 720 | PRINTK("compute_block, stripe %llu, idx %d\n", | 847 | PRINTK("compute_block, stripe %llu, idx %d\n", |
| @@ -744,7 +871,7 @@ static void compute_block(struct stripe_head *sh, int dd_idx) | |||
| 744 | static void compute_parity(struct stripe_head *sh, int method) | 871 | static void compute_parity(struct stripe_head *sh, int method) |
| 745 | { | 872 | { |
| 746 | raid5_conf_t *conf = sh->raid_conf; | 873 | raid5_conf_t *conf = sh->raid_conf; |
| 747 | int i, pd_idx = sh->pd_idx, disks = conf->raid_disks, count; | 874 | int i, pd_idx = sh->pd_idx, disks = sh->disks, count; |
| 748 | void *ptr[MAX_XOR_BLOCKS]; | 875 | void *ptr[MAX_XOR_BLOCKS]; |
| 749 | struct bio *chosen; | 876 | struct bio *chosen; |
| 750 | 877 | ||
| @@ -910,6 +1037,20 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in | |||
| 910 | return 0; | 1037 | return 0; |
| 911 | } | 1038 | } |
| 912 | 1039 | ||
| 1040 | static void end_reshape(raid5_conf_t *conf); | ||
| 1041 | |||
| 1042 | static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks) | ||
| 1043 | { | ||
| 1044 | int sectors_per_chunk = conf->chunk_size >> 9; | ||
| 1045 | sector_t x = stripe; | ||
| 1046 | int pd_idx, dd_idx; | ||
| 1047 | int chunk_offset = sector_div(x, sectors_per_chunk); | ||
| 1048 | stripe = x; | ||
| 1049 | raid5_compute_sector(stripe*(disks-1)*sectors_per_chunk | ||
| 1050 | + chunk_offset, disks, disks-1, &dd_idx, &pd_idx, conf); | ||
| 1051 | return pd_idx; | ||
| 1052 | } | ||
| 1053 | |||
| 913 | 1054 | ||
| 914 | /* | 1055 | /* |
| 915 | * handle_stripe - do things to a stripe. | 1056 | * handle_stripe - do things to a stripe. |
| @@ -932,11 +1073,11 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in | |||
| 932 | static void handle_stripe(struct stripe_head *sh) | 1073 | static void handle_stripe(struct stripe_head *sh) |
| 933 | { | 1074 | { |
| 934 | raid5_conf_t *conf = sh->raid_conf; | 1075 | raid5_conf_t *conf = sh->raid_conf; |
| 935 | int disks = conf->raid_disks; | 1076 | int disks = sh->disks; |
| 936 | struct bio *return_bi= NULL; | 1077 | struct bio *return_bi= NULL; |
| 937 | struct bio *bi; | 1078 | struct bio *bi; |
| 938 | int i; | 1079 | int i; |
| 939 | int syncing; | 1080 | int syncing, expanding, expanded; |
| 940 | int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0; | 1081 | int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0; |
| 941 | int non_overwrite = 0; | 1082 | int non_overwrite = 0; |
| 942 | int failed_num=0; | 1083 | int failed_num=0; |
| @@ -951,6 +1092,8 @@ static void handle_stripe(struct stripe_head *sh) | |||
| 951 | clear_bit(STRIPE_DELAYED, &sh->state); | 1092 | clear_bit(STRIPE_DELAYED, &sh->state); |
| 952 | 1093 | ||
| 953 | syncing = test_bit(STRIPE_SYNCING, &sh->state); | 1094 | syncing = test_bit(STRIPE_SYNCING, &sh->state); |
| 1095 | expanding = test_bit(STRIPE_EXPAND_SOURCE, &sh->state); | ||
| 1096 | expanded = test_bit(STRIPE_EXPAND_READY, &sh->state); | ||
| 954 | /* Now to look around and see what can be done */ | 1097 | /* Now to look around and see what can be done */ |
| 955 | 1098 | ||
| 956 | rcu_read_lock(); | 1099 | rcu_read_lock(); |
| @@ -1143,13 +1286,14 @@ static void handle_stripe(struct stripe_head *sh) | |||
| 1143 | * parity, or to satisfy requests | 1286 | * parity, or to satisfy requests |
| 1144 | * or to load a block that is being partially written. | 1287 | * or to load a block that is being partially written. |
| 1145 | */ | 1288 | */ |
| 1146 | if (to_read || non_overwrite || (syncing && (uptodate < disks))) { | 1289 | if (to_read || non_overwrite || (syncing && (uptodate < disks)) || expanding) { |
| 1147 | for (i=disks; i--;) { | 1290 | for (i=disks; i--;) { |
| 1148 | dev = &sh->dev[i]; | 1291 | dev = &sh->dev[i]; |
| 1149 | if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) && | 1292 | if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) && |
| 1150 | (dev->toread || | 1293 | (dev->toread || |
| 1151 | (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) || | 1294 | (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) || |
| 1152 | syncing || | 1295 | syncing || |
| 1296 | expanding || | ||
| 1153 | (failed && (sh->dev[failed_num].toread || | 1297 | (failed && (sh->dev[failed_num].toread || |
| 1154 | (sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num].flags)))) | 1298 | (sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num].flags)))) |
| 1155 | ) | 1299 | ) |
| @@ -1339,13 +1483,77 @@ static void handle_stripe(struct stripe_head *sh) | |||
| 1339 | set_bit(R5_Wantwrite, &dev->flags); | 1483 | set_bit(R5_Wantwrite, &dev->flags); |
| 1340 | set_bit(R5_ReWrite, &dev->flags); | 1484 | set_bit(R5_ReWrite, &dev->flags); |
| 1341 | set_bit(R5_LOCKED, &dev->flags); | 1485 | set_bit(R5_LOCKED, &dev->flags); |
| 1486 | locked++; | ||
| 1342 | } else { | 1487 | } else { |
| 1343 | /* let's read it back */ | 1488 | /* let's read it back */ |
| 1344 | set_bit(R5_Wantread, &dev->flags); | 1489 | set_bit(R5_Wantread, &dev->flags); |
| 1345 | set_bit(R5_LOCKED, &dev->flags); | 1490 | set_bit(R5_LOCKED, &dev->flags); |
| 1491 | locked++; | ||
| 1346 | } | 1492 | } |
| 1347 | } | 1493 | } |
| 1348 | 1494 | ||
| 1495 | if (expanded && test_bit(STRIPE_EXPANDING, &sh->state)) { | ||
| 1496 | /* Need to write out all blocks after computing parity */ | ||
| 1497 | sh->disks = conf->raid_disks; | ||
| 1498 | sh->pd_idx = stripe_to_pdidx(sh->sector, conf, conf->raid_disks); | ||
| 1499 | compute_parity(sh, RECONSTRUCT_WRITE); | ||
| 1500 | for (i= conf->raid_disks; i--;) { | ||
| 1501 | set_bit(R5_LOCKED, &sh->dev[i].flags); | ||
| 1502 | locked++; | ||
| 1503 | set_bit(R5_Wantwrite, &sh->dev[i].flags); | ||
| 1504 | } | ||
| 1505 | clear_bit(STRIPE_EXPANDING, &sh->state); | ||
| 1506 | } else if (expanded) { | ||
| 1507 | clear_bit(STRIPE_EXPAND_READY, &sh->state); | ||
| 1508 | atomic_dec(&conf->reshape_stripes); | ||
| 1509 | wake_up(&conf->wait_for_overlap); | ||
| 1510 | md_done_sync(conf->mddev, STRIPE_SECTORS, 1); | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | if (expanding && locked == 0) { | ||
| 1514 | /* We have read all the blocks in this stripe and now we need to | ||
| 1515 | * copy some of them into a target stripe for expand. | ||
| 1516 | */ | ||
| 1517 | clear_bit(STRIPE_EXPAND_SOURCE, &sh->state); | ||
| 1518 | for (i=0; i< sh->disks; i++) | ||
| 1519 | if (i != sh->pd_idx) { | ||
| 1520 | int dd_idx, pd_idx, j; | ||
| 1521 | struct stripe_head *sh2; | ||
| 1522 | |||
| 1523 | sector_t bn = compute_blocknr(sh, i); | ||
| 1524 | sector_t s = raid5_compute_sector(bn, conf->raid_disks, | ||
| 1525 | conf->raid_disks-1, | ||
| 1526 | &dd_idx, &pd_idx, conf); | ||
| 1527 | sh2 = get_active_stripe(conf, s, conf->raid_disks, pd_idx, 1); | ||
| 1528 | if (sh2 == NULL) | ||
| 1529 | /* so far only the early blocks of this stripe | ||
| 1530 | * have been requested. When later blocks | ||
| 1531 | * get requested, we will try again | ||
| 1532 | */ | ||
| 1533 | continue; | ||
| 1534 | if(!test_bit(STRIPE_EXPANDING, &sh2->state) || | ||
| 1535 | test_bit(R5_Expanded, &sh2->dev[dd_idx].flags)) { | ||
| 1536 | /* must have already done this block */ | ||
| 1537 | release_stripe(sh2); | ||
| 1538 | continue; | ||
| 1539 | } | ||
| 1540 | memcpy(page_address(sh2->dev[dd_idx].page), | ||
| 1541 | page_address(sh->dev[i].page), | ||
| 1542 | STRIPE_SIZE); | ||
| 1543 | set_bit(R5_Expanded, &sh2->dev[dd_idx].flags); | ||
| 1544 | set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags); | ||
| 1545 | for (j=0; j<conf->raid_disks; j++) | ||
| 1546 | if (j != sh2->pd_idx && | ||
| 1547 | !test_bit(R5_Expanded, &sh2->dev[j].flags)) | ||
| 1548 | break; | ||
| 1549 | if (j == conf->raid_disks) { | ||
| 1550 | set_bit(STRIPE_EXPAND_READY, &sh2->state); | ||
| 1551 | set_bit(STRIPE_HANDLE, &sh2->state); | ||
| 1552 | } | ||
| 1553 | release_stripe(sh2); | ||
| 1554 | } | ||
| 1555 | } | ||
| 1556 | |||
| 1349 | spin_unlock(&sh->lock); | 1557 | spin_unlock(&sh->lock); |
| 1350 | 1558 | ||
| 1351 | while ((bi=return_bi)) { | 1559 | while ((bi=return_bi)) { |
| @@ -1384,7 +1592,7 @@ static void handle_stripe(struct stripe_head *sh) | |||
| 1384 | rcu_read_unlock(); | 1592 | rcu_read_unlock(); |
| 1385 | 1593 | ||
| 1386 | if (rdev) { | 1594 | if (rdev) { |
| 1387 | if (syncing) | 1595 | if (syncing || expanding || expanded) |
| 1388 | md_sync_acct(rdev->bdev, STRIPE_SECTORS); | 1596 | md_sync_acct(rdev->bdev, STRIPE_SECTORS); |
| 1389 | 1597 | ||
| 1390 | bi->bi_bdev = rdev->bdev; | 1598 | bi->bi_bdev = rdev->bdev; |
| @@ -1526,17 +1734,16 @@ static inline void raid5_plug_device(raid5_conf_t *conf) | |||
| 1526 | spin_unlock_irq(&conf->device_lock); | 1734 | spin_unlock_irq(&conf->device_lock); |
| 1527 | } | 1735 | } |
| 1528 | 1736 | ||
| 1529 | static int make_request (request_queue_t *q, struct bio * bi) | 1737 | static int make_request(request_queue_t *q, struct bio * bi) |
| 1530 | { | 1738 | { |
| 1531 | mddev_t *mddev = q->queuedata; | 1739 | mddev_t *mddev = q->queuedata; |
| 1532 | raid5_conf_t *conf = mddev_to_conf(mddev); | 1740 | raid5_conf_t *conf = mddev_to_conf(mddev); |
| 1533 | const unsigned int raid_disks = conf->raid_disks; | ||
| 1534 | const unsigned int data_disks = raid_disks - 1; | ||
| 1535 | unsigned int dd_idx, pd_idx; | 1741 | unsigned int dd_idx, pd_idx; |
| 1536 | sector_t new_sector; | 1742 | sector_t new_sector; |
| 1537 | sector_t logical_sector, last_sector; | 1743 | sector_t logical_sector, last_sector; |
| 1538 | struct stripe_head *sh; | 1744 | struct stripe_head *sh; |
| 1539 | const int rw = bio_data_dir(bi); | 1745 | const int rw = bio_data_dir(bi); |
| 1746 | int remaining; | ||
| 1540 | 1747 | ||
| 1541 | if (unlikely(bio_barrier(bi))) { | 1748 | if (unlikely(bio_barrier(bi))) { |
| 1542 | bio_endio(bi, bi->bi_size, -EOPNOTSUPP); | 1749 | bio_endio(bi, bi->bi_size, -EOPNOTSUPP); |
| @@ -1555,20 +1762,77 @@ static int make_request (request_queue_t *q, struct bio * bi) | |||
| 1555 | 1762 | ||
| 1556 | for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { | 1763 | for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) { |
| 1557 | DEFINE_WAIT(w); | 1764 | DEFINE_WAIT(w); |
| 1558 | 1765 | int disks; | |
| 1559 | new_sector = raid5_compute_sector(logical_sector, | ||
| 1560 | raid_disks, data_disks, &dd_idx, &pd_idx, conf); | ||
| 1561 | 1766 | ||
| 1767 | retry: | ||
| 1768 | prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); | ||
| 1769 | if (likely(conf->expand_progress == MaxSector)) | ||
| 1770 | disks = conf->raid_disks; | ||
| 1771 | else { | ||
| 1772 | /* spinlock is needed as expand_progress may be | ||
| 1773 | * 64bit on a 32bit platform, and so it might be | ||
| 1774 | * possible to see a half-updated value | ||
| 1775 | * Ofcourse expand_progress could change after | ||
| 1776 | * the lock is dropped, so once we get a reference | ||
| 1777 | * to the stripe that we think it is, we will have | ||
| 1778 | * to check again. | ||
| 1779 | */ | ||
| 1780 | spin_lock_irq(&conf->device_lock); | ||
| 1781 | disks = conf->raid_disks; | ||
| 1782 | if (logical_sector >= conf->expand_progress) | ||
| 1783 | disks = conf->previous_raid_disks; | ||
| 1784 | else { | ||
| 1785 | if (logical_sector >= conf->expand_lo) { | ||
| 1786 | spin_unlock_irq(&conf->device_lock); | ||
| 1787 | schedule(); | ||
| 1788 | goto retry; | ||
| 1789 | } | ||
| 1790 | } | ||
| 1791 | spin_unlock_irq(&conf->device_lock); | ||
| 1792 | } | ||
| 1793 | new_sector = raid5_compute_sector(logical_sector, disks, disks - 1, | ||
| 1794 | &dd_idx, &pd_idx, conf); | ||
| 1562 | PRINTK("raid5: make_request, sector %llu logical %llu\n", | 1795 | PRINTK("raid5: make_request, sector %llu logical %llu\n", |
| 1563 | (unsigned long long)new_sector, | 1796 | (unsigned long long)new_sector, |
| 1564 | (unsigned long long)logical_sector); | 1797 | (unsigned long long)logical_sector); |
| 1565 | 1798 | ||
| 1566 | retry: | 1799 | sh = get_active_stripe(conf, new_sector, disks, pd_idx, (bi->bi_rw&RWA_MASK)); |
| 1567 | prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE); | ||
| 1568 | sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK)); | ||
| 1569 | if (sh) { | 1800 | if (sh) { |
| 1570 | if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) { | 1801 | if (unlikely(conf->expand_progress != MaxSector)) { |
| 1571 | /* Add failed due to overlap. Flush everything | 1802 | /* expansion might have moved on while waiting for a |
| 1803 | * stripe, so we must do the range check again. | ||
| 1804 | * Expansion could still move past after this | ||
| 1805 | * test, but as we are holding a reference to | ||
| 1806 | * 'sh', we know that if that happens, | ||
| 1807 | * STRIPE_EXPANDING will get set and the expansion | ||
| 1808 | * won't proceed until we finish with the stripe. | ||
| 1809 | */ | ||
| 1810 | int must_retry = 0; | ||
| 1811 | spin_lock_irq(&conf->device_lock); | ||
| 1812 | if (logical_sector < conf->expand_progress && | ||
| 1813 | disks == conf->previous_raid_disks) | ||
| 1814 | /* mismatch, need to try again */ | ||
| 1815 | must_retry = 1; | ||
| 1816 | spin_unlock_irq(&conf->device_lock); | ||
| 1817 | if (must_retry) { | ||
| 1818 | release_stripe(sh); | ||
| 1819 | goto retry; | ||
| 1820 | } | ||
| 1821 | } | ||
| 1822 | /* FIXME what if we get a false positive because these | ||
| 1823 | * are being updated. | ||
| 1824 | */ | ||
| 1825 | if (logical_sector >= mddev->suspend_lo && | ||
| 1826 | logical_sector < mddev->suspend_hi) { | ||
| 1827 | release_stripe(sh); | ||
| 1828 | schedule(); | ||
| 1829 | goto retry; | ||
| 1830 | } | ||
| 1831 | |||
| 1832 | if (test_bit(STRIPE_EXPANDING, &sh->state) || | ||
| 1833 | !add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) { | ||
| 1834 | /* Stripe is busy expanding or | ||
| 1835 | * add failed due to overlap. Flush everything | ||
| 1572 | * and wait a while | 1836 | * and wait a while |
| 1573 | */ | 1837 | */ |
| 1574 | raid5_unplug_device(mddev->queue); | 1838 | raid5_unplug_device(mddev->queue); |
| @@ -1580,7 +1844,6 @@ static int make_request (request_queue_t *q, struct bio * bi) | |||
| 1580 | raid5_plug_device(conf); | 1844 | raid5_plug_device(conf); |
| 1581 | handle_stripe(sh); | 1845 | handle_stripe(sh); |
| 1582 | release_stripe(sh); | 1846 | release_stripe(sh); |
| 1583 | |||
| 1584 | } else { | 1847 | } else { |
| 1585 | /* cannot get stripe for read-ahead, just give-up */ | 1848 | /* cannot get stripe for read-ahead, just give-up */ |
| 1586 | clear_bit(BIO_UPTODATE, &bi->bi_flags); | 1849 | clear_bit(BIO_UPTODATE, &bi->bi_flags); |
| @@ -1590,7 +1853,9 @@ static int make_request (request_queue_t *q, struct bio * bi) | |||
| 1590 | 1853 | ||
| 1591 | } | 1854 | } |
| 1592 | spin_lock_irq(&conf->device_lock); | 1855 | spin_lock_irq(&conf->device_lock); |
| 1593 | if (--bi->bi_phys_segments == 0) { | 1856 | remaining = --bi->bi_phys_segments; |
| 1857 | spin_unlock_irq(&conf->device_lock); | ||
| 1858 | if (remaining == 0) { | ||
| 1594 | int bytes = bi->bi_size; | 1859 | int bytes = bi->bi_size; |
| 1595 | 1860 | ||
| 1596 | if ( bio_data_dir(bi) == WRITE ) | 1861 | if ( bio_data_dir(bi) == WRITE ) |
| @@ -1598,7 +1863,6 @@ static int make_request (request_queue_t *q, struct bio * bi) | |||
| 1598 | bi->bi_size = 0; | 1863 | bi->bi_size = 0; |
| 1599 | bi->bi_end_io(bi, bytes, 0); | 1864 | bi->bi_end_io(bi, bytes, 0); |
| 1600 | } | 1865 | } |
| 1601 | spin_unlock_irq(&conf->device_lock); | ||
| 1602 | return 0; | 1866 | return 0; |
| 1603 | } | 1867 | } |
| 1604 | 1868 | ||
| @@ -1607,12 +1871,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
| 1607 | { | 1871 | { |
| 1608 | raid5_conf_t *conf = (raid5_conf_t *) mddev->private; | 1872 | raid5_conf_t *conf = (raid5_conf_t *) mddev->private; |
| 1609 | struct stripe_head *sh; | 1873 | struct stripe_head *sh; |
| 1610 | int sectors_per_chunk = conf->chunk_size >> 9; | 1874 | int pd_idx; |
| 1611 | sector_t x; | 1875 | sector_t first_sector, last_sector; |
| 1612 | unsigned long stripe; | ||
| 1613 | int chunk_offset; | ||
| 1614 | int dd_idx, pd_idx; | ||
| 1615 | sector_t first_sector; | ||
| 1616 | int raid_disks = conf->raid_disks; | 1876 | int raid_disks = conf->raid_disks; |
| 1617 | int data_disks = raid_disks-1; | 1877 | int data_disks = raid_disks-1; |
| 1618 | sector_t max_sector = mddev->size << 1; | 1878 | sector_t max_sector = mddev->size << 1; |
| @@ -1621,6 +1881,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
| 1621 | if (sector_nr >= max_sector) { | 1881 | if (sector_nr >= max_sector) { |
| 1622 | /* just being told to finish up .. nothing much to do */ | 1882 | /* just being told to finish up .. nothing much to do */ |
| 1623 | unplug_slaves(mddev); | 1883 | unplug_slaves(mddev); |
| 1884 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) { | ||
| 1885 | end_reshape(conf); | ||
| 1886 | return 0; | ||
| 1887 | } | ||
| 1624 | 1888 | ||
| 1625 | if (mddev->curr_resync < max_sector) /* aborted */ | 1889 | if (mddev->curr_resync < max_sector) /* aborted */ |
| 1626 | bitmap_end_sync(mddev->bitmap, mddev->curr_resync, | 1890 | bitmap_end_sync(mddev->bitmap, mddev->curr_resync, |
| @@ -1631,6 +1895,123 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
| 1631 | 1895 | ||
| 1632 | return 0; | 1896 | return 0; |
| 1633 | } | 1897 | } |
| 1898 | |||
| 1899 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) { | ||
| 1900 | /* reshaping is quite different to recovery/resync so it is | ||
| 1901 | * handled quite separately ... here. | ||
| 1902 | * | ||
| 1903 | * On each call to sync_request, we gather one chunk worth of | ||
| 1904 | * destination stripes and flag them as expanding. | ||
| 1905 | * Then we find all the source stripes and request reads. | ||
| 1906 | * As the reads complete, handle_stripe will copy the data | ||
| 1907 | * into the destination stripe and release that stripe. | ||
| 1908 | */ | ||
| 1909 | int i; | ||
| 1910 | int dd_idx; | ||
| 1911 | sector_t writepos, safepos, gap; | ||
| 1912 | |||
| 1913 | if (sector_nr == 0 && | ||
| 1914 | conf->expand_progress != 0) { | ||
| 1915 | /* restarting in the middle, skip the initial sectors */ | ||
| 1916 | sector_nr = conf->expand_progress; | ||
| 1917 | sector_div(sector_nr, conf->raid_disks-1); | ||
| 1918 | *skipped = 1; | ||
| 1919 | return sector_nr; | ||
| 1920 | } | ||
| 1921 | |||
| 1922 | /* we update the metadata when there is more than 3Meg | ||
| 1923 | * in the block range (that is rather arbitrary, should | ||
| 1924 | * probably be time based) or when the data about to be | ||
| 1925 | * copied would over-write the source of the data at | ||
| 1926 | * the front of the range. | ||
| 1927 | * i.e. one new_stripe forward from expand_progress new_maps | ||
| 1928 | * to after where expand_lo old_maps to | ||
| 1929 | */ | ||
| 1930 | writepos = conf->expand_progress + | ||
| 1931 | conf->chunk_size/512*(conf->raid_disks-1); | ||
| 1932 | sector_div(writepos, conf->raid_disks-1); | ||
| 1933 | safepos = conf->expand_lo; | ||
| 1934 | sector_div(safepos, conf->previous_raid_disks-1); | ||
| 1935 | gap = conf->expand_progress - conf->expand_lo; | ||
| 1936 | |||
| 1937 | if (writepos >= safepos || | ||
| 1938 | gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) { | ||
| 1939 | /* Cannot proceed until we've updated the superblock... */ | ||
| 1940 | wait_event(conf->wait_for_overlap, | ||
| 1941 | atomic_read(&conf->reshape_stripes)==0); | ||
| 1942 | mddev->reshape_position = conf->expand_progress; | ||
| 1943 | mddev->sb_dirty = 1; | ||
| 1944 | md_wakeup_thread(mddev->thread); | ||
| 1945 | wait_event(mddev->sb_wait, mddev->sb_dirty == 0 || | ||
| 1946 | kthread_should_stop()); | ||
| 1947 | spin_lock_irq(&conf->device_lock); | ||
| 1948 | conf->expand_lo = mddev->reshape_position; | ||
| 1949 | spin_unlock_irq(&conf->device_lock); | ||
| 1950 | wake_up(&conf->wait_for_overlap); | ||
| 1951 | } | ||
| 1952 | |||
| 1953 | for (i=0; i < conf->chunk_size/512; i+= STRIPE_SECTORS) { | ||
| 1954 | int j; | ||
| 1955 | int skipped = 0; | ||
| 1956 | pd_idx = stripe_to_pdidx(sector_nr+i, conf, conf->raid_disks); | ||
| 1957 | sh = get_active_stripe(conf, sector_nr+i, | ||
| 1958 | conf->raid_disks, pd_idx, 0); | ||
| 1959 | set_bit(STRIPE_EXPANDING, &sh->state); | ||
| 1960 | atomic_inc(&conf->reshape_stripes); | ||
| 1961 | /* If any of this stripe is beyond the end of the old | ||
| 1962 | * array, then we need to zero those blocks | ||
| 1963 | */ | ||
| 1964 | for (j=sh->disks; j--;) { | ||
| 1965 | sector_t s; | ||
| 1966 | if (j == sh->pd_idx) | ||
| 1967 | continue; | ||
| 1968 | s = compute_blocknr(sh, j); | ||
| 1969 | if (s < (mddev->array_size<<1)) { | ||
| 1970 | skipped = 1; | ||
| 1971 | continue; | ||
| 1972 | } | ||
| 1973 | memset(page_address(sh->dev[j].page), 0, STRIPE_SIZE); | ||
| 1974 | set_bit(R5_Expanded, &sh->dev[j].flags); | ||
| 1975 | set_bit(R5_UPTODATE, &sh->dev[j].flags); | ||
| 1976 | } | ||
| 1977 | if (!skipped) { | ||
| 1978 | set_bit(STRIPE_EXPAND_READY, &sh->state); | ||
| 1979 | set_bit(STRIPE_HANDLE, &sh->state); | ||
| 1980 | } | ||
| 1981 | release_stripe(sh); | ||
| 1982 | } | ||
| 1983 | spin_lock_irq(&conf->device_lock); | ||
| 1984 | conf->expand_progress = (sector_nr + i)*(conf->raid_disks-1); | ||
| 1985 | spin_unlock_irq(&conf->device_lock); | ||
| 1986 | /* Ok, those stripe are ready. We can start scheduling | ||
| 1987 | * reads on the source stripes. | ||
| 1988 | * The source stripes are determined by mapping the first and last | ||
| 1989 | * block on the destination stripes. | ||
| 1990 | */ | ||
| 1991 | raid_disks = conf->previous_raid_disks; | ||
| 1992 | data_disks = raid_disks - 1; | ||
| 1993 | first_sector = | ||
| 1994 | raid5_compute_sector(sector_nr*(conf->raid_disks-1), | ||
| 1995 | raid_disks, data_disks, | ||
| 1996 | &dd_idx, &pd_idx, conf); | ||
| 1997 | last_sector = | ||
| 1998 | raid5_compute_sector((sector_nr+conf->chunk_size/512) | ||
| 1999 | *(conf->raid_disks-1) -1, | ||
| 2000 | raid_disks, data_disks, | ||
| 2001 | &dd_idx, &pd_idx, conf); | ||
| 2002 | if (last_sector >= (mddev->size<<1)) | ||
| 2003 | last_sector = (mddev->size<<1)-1; | ||
| 2004 | while (first_sector <= last_sector) { | ||
| 2005 | pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks); | ||
| 2006 | sh = get_active_stripe(conf, first_sector, | ||
| 2007 | conf->previous_raid_disks, pd_idx, 0); | ||
| 2008 | set_bit(STRIPE_EXPAND_SOURCE, &sh->state); | ||
| 2009 | set_bit(STRIPE_HANDLE, &sh->state); | ||
| 2010 | release_stripe(sh); | ||
| 2011 | first_sector += STRIPE_SECTORS; | ||
| 2012 | } | ||
| 2013 | return conf->chunk_size>>9; | ||
| 2014 | } | ||
| 1634 | /* if there is 1 or more failed drives and we are trying | 2015 | /* if there is 1 or more failed drives and we are trying |
| 1635 | * to resync, then assert that we are finished, because there is | 2016 | * to resync, then assert that we are finished, because there is |
| 1636 | * nothing we can do. | 2017 | * nothing we can do. |
| @@ -1649,16 +2030,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
| 1649 | return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */ | 2030 | return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */ |
| 1650 | } | 2031 | } |
| 1651 | 2032 | ||
| 1652 | x = sector_nr; | 2033 | pd_idx = stripe_to_pdidx(sector_nr, conf, raid_disks); |
| 1653 | chunk_offset = sector_div(x, sectors_per_chunk); | 2034 | sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1); |
| 1654 | stripe = x; | ||
| 1655 | BUG_ON(x != stripe); | ||
| 1656 | |||
| 1657 | first_sector = raid5_compute_sector((sector_t)stripe*data_disks*sectors_per_chunk | ||
| 1658 | + chunk_offset, raid_disks, data_disks, &dd_idx, &pd_idx, conf); | ||
| 1659 | sh = get_active_stripe(conf, sector_nr, pd_idx, 1); | ||
| 1660 | if (sh == NULL) { | 2035 | if (sh == NULL) { |
| 1661 | sh = get_active_stripe(conf, sector_nr, pd_idx, 0); | 2036 | sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 0); |
| 1662 | /* make sure we don't swamp the stripe cache if someone else | 2037 | /* make sure we don't swamp the stripe cache if someone else |
| 1663 | * is trying to get access | 2038 | * is trying to get access |
| 1664 | */ | 2039 | */ |
| @@ -1822,11 +2197,64 @@ static int run(mddev_t *mddev) | |||
| 1822 | return -EIO; | 2197 | return -EIO; |
| 1823 | } | 2198 | } |
| 1824 | 2199 | ||
| 1825 | mddev->private = kzalloc(sizeof (raid5_conf_t) | 2200 | if (mddev->reshape_position != MaxSector) { |
| 1826 | + mddev->raid_disks * sizeof(struct disk_info), | 2201 | /* Check that we can continue the reshape. |
| 1827 | GFP_KERNEL); | 2202 | * Currently only disks can change, it must |
| 2203 | * increase, and we must be past the point where | ||
| 2204 | * a stripe over-writes itself | ||
| 2205 | */ | ||
| 2206 | sector_t here_new, here_old; | ||
| 2207 | int old_disks; | ||
| 2208 | |||
| 2209 | if (mddev->new_level != mddev->level || | ||
| 2210 | mddev->new_layout != mddev->layout || | ||
| 2211 | mddev->new_chunk != mddev->chunk_size) { | ||
| 2212 | printk(KERN_ERR "raid5: %s: unsupported reshape required - aborting.\n", | ||
| 2213 | mdname(mddev)); | ||
| 2214 | return -EINVAL; | ||
| 2215 | } | ||
| 2216 | if (mddev->delta_disks <= 0) { | ||
| 2217 | printk(KERN_ERR "raid5: %s: unsupported reshape (reduce disks) required - aborting.\n", | ||
| 2218 | mdname(mddev)); | ||
| 2219 | return -EINVAL; | ||
| 2220 | } | ||
| 2221 | old_disks = mddev->raid_disks - mddev->delta_disks; | ||
| 2222 | /* reshape_position must be on a new-stripe boundary, and one | ||
| 2223 | * further up in new geometry must map after here in old geometry. | ||
| 2224 | */ | ||
| 2225 | here_new = mddev->reshape_position; | ||
| 2226 | if (sector_div(here_new, (mddev->chunk_size>>9)*(mddev->raid_disks-1))) { | ||
| 2227 | printk(KERN_ERR "raid5: reshape_position not on a stripe boundary\n"); | ||
| 2228 | return -EINVAL; | ||
| 2229 | } | ||
| 2230 | /* here_new is the stripe we will write to */ | ||
| 2231 | here_old = mddev->reshape_position; | ||
| 2232 | sector_div(here_old, (mddev->chunk_size>>9)*(old_disks-1)); | ||
| 2233 | /* here_old is the first stripe that we might need to read from */ | ||
| 2234 | if (here_new >= here_old) { | ||
| 2235 | /* Reading from the same stripe as writing to - bad */ | ||
| 2236 | printk(KERN_ERR "raid5: reshape_position too early for auto-recovery - aborting.\n"); | ||
| 2237 | return -EINVAL; | ||
| 2238 | } | ||
| 2239 | printk(KERN_INFO "raid5: reshape will continue\n"); | ||
| 2240 | /* OK, we should be able to continue; */ | ||
| 2241 | } | ||
| 2242 | |||
| 2243 | |||
| 2244 | mddev->private = kzalloc(sizeof (raid5_conf_t), GFP_KERNEL); | ||
| 1828 | if ((conf = mddev->private) == NULL) | 2245 | if ((conf = mddev->private) == NULL) |
| 1829 | goto abort; | 2246 | goto abort; |
| 2247 | if (mddev->reshape_position == MaxSector) { | ||
| 2248 | conf->previous_raid_disks = conf->raid_disks = mddev->raid_disks; | ||
| 2249 | } else { | ||
| 2250 | conf->raid_disks = mddev->raid_disks; | ||
| 2251 | conf->previous_raid_disks = mddev->raid_disks - mddev->delta_disks; | ||
| 2252 | } | ||
| 2253 | |||
| 2254 | conf->disks = kzalloc(conf->raid_disks * sizeof(struct disk_info), | ||
| 2255 | GFP_KERNEL); | ||
| 2256 | if (!conf->disks) | ||
| 2257 | goto abort; | ||
| 1830 | 2258 | ||
| 1831 | conf->mddev = mddev; | 2259 | conf->mddev = mddev; |
| 1832 | 2260 | ||
| @@ -1847,7 +2275,7 @@ static int run(mddev_t *mddev) | |||
| 1847 | 2275 | ||
| 1848 | ITERATE_RDEV(mddev,rdev,tmp) { | 2276 | ITERATE_RDEV(mddev,rdev,tmp) { |
| 1849 | raid_disk = rdev->raid_disk; | 2277 | raid_disk = rdev->raid_disk; |
| 1850 | if (raid_disk >= mddev->raid_disks | 2278 | if (raid_disk >= conf->raid_disks |
| 1851 | || raid_disk < 0) | 2279 | || raid_disk < 0) |
| 1852 | continue; | 2280 | continue; |
| 1853 | disk = conf->disks + raid_disk; | 2281 | disk = conf->disks + raid_disk; |
| @@ -1863,7 +2291,6 @@ static int run(mddev_t *mddev) | |||
| 1863 | } | 2291 | } |
| 1864 | } | 2292 | } |
| 1865 | 2293 | ||
| 1866 | conf->raid_disks = mddev->raid_disks; | ||
| 1867 | /* | 2294 | /* |
| 1868 | * 0 for a fully functional array, 1 for a degraded array. | 2295 | * 0 for a fully functional array, 1 for a degraded array. |
| 1869 | */ | 2296 | */ |
| @@ -1873,6 +2300,7 @@ static int run(mddev_t *mddev) | |||
| 1873 | conf->level = mddev->level; | 2300 | conf->level = mddev->level; |
| 1874 | conf->algorithm = mddev->layout; | 2301 | conf->algorithm = mddev->layout; |
| 1875 | conf->max_nr_stripes = NR_STRIPES; | 2302 | conf->max_nr_stripes = NR_STRIPES; |
| 2303 | conf->expand_progress = mddev->reshape_position; | ||
| 1876 | 2304 | ||
| 1877 | /* device size must be a multiple of chunk size */ | 2305 | /* device size must be a multiple of chunk size */ |
| 1878 | mddev->size &= ~(mddev->chunk_size/1024 -1); | 2306 | mddev->size &= ~(mddev->chunk_size/1024 -1); |
| @@ -1945,6 +2373,21 @@ static int run(mddev_t *mddev) | |||
| 1945 | 2373 | ||
| 1946 | print_raid5_conf(conf); | 2374 | print_raid5_conf(conf); |
| 1947 | 2375 | ||
| 2376 | if (conf->expand_progress != MaxSector) { | ||
| 2377 | printk("...ok start reshape thread\n"); | ||
| 2378 | conf->expand_lo = conf->expand_progress; | ||
| 2379 | atomic_set(&conf->reshape_stripes, 0); | ||
| 2380 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); | ||
| 2381 | clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); | ||
| 2382 | set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); | ||
| 2383 | set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); | ||
| 2384 | mddev->sync_thread = md_register_thread(md_do_sync, mddev, | ||
| 2385 | "%s_reshape"); | ||
| 2386 | /* FIXME if md_register_thread fails?? */ | ||
| 2387 | md_wakeup_thread(mddev->sync_thread); | ||
| 2388 | |||
| 2389 | } | ||
| 2390 | |||
| 1948 | /* read-ahead size must cover two whole stripes, which is | 2391 | /* read-ahead size must cover two whole stripes, which is |
| 1949 | * 2 * (n-1) * chunksize where 'n' is the number of raid devices | 2392 | * 2 * (n-1) * chunksize where 'n' is the number of raid devices |
| 1950 | */ | 2393 | */ |
| @@ -1960,12 +2403,13 @@ static int run(mddev_t *mddev) | |||
| 1960 | 2403 | ||
| 1961 | mddev->queue->unplug_fn = raid5_unplug_device; | 2404 | mddev->queue->unplug_fn = raid5_unplug_device; |
| 1962 | mddev->queue->issue_flush_fn = raid5_issue_flush; | 2405 | mddev->queue->issue_flush_fn = raid5_issue_flush; |
| 2406 | mddev->array_size = mddev->size * (conf->previous_raid_disks - 1); | ||
| 1963 | 2407 | ||
| 1964 | mddev->array_size = mddev->size * (mddev->raid_disks - 1); | ||
| 1965 | return 0; | 2408 | return 0; |
| 1966 | abort: | 2409 | abort: |
| 1967 | if (conf) { | 2410 | if (conf) { |
| 1968 | print_raid5_conf(conf); | 2411 | print_raid5_conf(conf); |
| 2412 | kfree(conf->disks); | ||
| 1969 | kfree(conf->stripe_hashtbl); | 2413 | kfree(conf->stripe_hashtbl); |
| 1970 | kfree(conf); | 2414 | kfree(conf); |
| 1971 | } | 2415 | } |
| @@ -1986,6 +2430,7 @@ static int stop(mddev_t *mddev) | |||
| 1986 | kfree(conf->stripe_hashtbl); | 2430 | kfree(conf->stripe_hashtbl); |
| 1987 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 2431 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
| 1988 | sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); | 2432 | sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); |
| 2433 | kfree(conf->disks); | ||
| 1989 | kfree(conf); | 2434 | kfree(conf); |
| 1990 | mddev->private = NULL; | 2435 | mddev->private = NULL; |
| 1991 | return 0; | 2436 | return 0; |
| @@ -2001,7 +2446,7 @@ static void print_sh (struct stripe_head *sh) | |||
| 2001 | printk("sh %llu, count %d.\n", | 2446 | printk("sh %llu, count %d.\n", |
| 2002 | (unsigned long long)sh->sector, atomic_read(&sh->count)); | 2447 | (unsigned long long)sh->sector, atomic_read(&sh->count)); |
| 2003 | printk("sh %llu, ", (unsigned long long)sh->sector); | 2448 | printk("sh %llu, ", (unsigned long long)sh->sector); |
| 2004 | for (i = 0; i < sh->raid_conf->raid_disks; i++) { | 2449 | for (i = 0; i < sh->disks; i++) { |
| 2005 | printk("(cache%d: %p %ld) ", | 2450 | printk("(cache%d: %p %ld) ", |
| 2006 | i, sh->dev[i].page, sh->dev[i].flags); | 2451 | i, sh->dev[i].page, sh->dev[i].flags); |
| 2007 | } | 2452 | } |
| @@ -2132,7 +2577,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 2132 | /* | 2577 | /* |
| 2133 | * find the disk ... | 2578 | * find the disk ... |
| 2134 | */ | 2579 | */ |
| 2135 | for (disk=0; disk < mddev->raid_disks; disk++) | 2580 | for (disk=0; disk < conf->raid_disks; disk++) |
| 2136 | if ((p=conf->disks + disk)->rdev == NULL) { | 2581 | if ((p=conf->disks + disk)->rdev == NULL) { |
| 2137 | clear_bit(In_sync, &rdev->flags); | 2582 | clear_bit(In_sync, &rdev->flags); |
| 2138 | rdev->raid_disk = disk; | 2583 | rdev->raid_disk = disk; |
| @@ -2168,11 +2613,146 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors) | |||
| 2168 | return 0; | 2613 | return 0; |
| 2169 | } | 2614 | } |
| 2170 | 2615 | ||
| 2616 | #ifdef CONFIG_MD_RAID5_RESHAPE | ||
| 2617 | static int raid5_check_reshape(mddev_t *mddev) | ||
| 2618 | { | ||
| 2619 | raid5_conf_t *conf = mddev_to_conf(mddev); | ||
| 2620 | int err; | ||
| 2621 | |||
| 2622 | if (mddev->delta_disks < 0 || | ||
| 2623 | mddev->new_level != mddev->level) | ||
| 2624 | return -EINVAL; /* Cannot shrink array or change level yet */ | ||
| 2625 | if (mddev->delta_disks == 0) | ||
| 2626 | return 0; /* nothing to do */ | ||
| 2627 | |||
| 2628 | /* Can only proceed if there are plenty of stripe_heads. | ||
| 2629 | * We need a minimum of one full stripe,, and for sensible progress | ||
| 2630 | * it is best to have about 4 times that. | ||
| 2631 | * If we require 4 times, then the default 256 4K stripe_heads will | ||
| 2632 | * allow for chunk sizes up to 256K, which is probably OK. | ||
| 2633 | * If the chunk size is greater, user-space should request more | ||
| 2634 | * stripe_heads first. | ||
| 2635 | */ | ||
| 2636 | if ((mddev->chunk_size / STRIPE_SIZE) * 4 > conf->max_nr_stripes || | ||
| 2637 | (mddev->new_chunk / STRIPE_SIZE) * 4 > conf->max_nr_stripes) { | ||
| 2638 | printk(KERN_WARNING "raid5: reshape: not enough stripes. Needed %lu\n", | ||
| 2639 | (mddev->chunk_size / STRIPE_SIZE)*4); | ||
| 2640 | return -ENOSPC; | ||
| 2641 | } | ||
| 2642 | |||
| 2643 | err = resize_stripes(conf, conf->raid_disks + mddev->delta_disks); | ||
| 2644 | if (err) | ||
| 2645 | return err; | ||
| 2646 | |||
| 2647 | /* looks like we might be able to manage this */ | ||
| 2648 | return 0; | ||
| 2649 | } | ||
| 2650 | |||
| 2651 | static int raid5_start_reshape(mddev_t *mddev) | ||
| 2652 | { | ||
| 2653 | raid5_conf_t *conf = mddev_to_conf(mddev); | ||
| 2654 | mdk_rdev_t *rdev; | ||
| 2655 | struct list_head *rtmp; | ||
| 2656 | int spares = 0; | ||
| 2657 | int added_devices = 0; | ||
| 2658 | |||
| 2659 | if (mddev->degraded || | ||
| 2660 | test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) | ||
| 2661 | return -EBUSY; | ||
| 2662 | |||
| 2663 | ITERATE_RDEV(mddev, rdev, rtmp) | ||
| 2664 | if (rdev->raid_disk < 0 && | ||
| 2665 | !test_bit(Faulty, &rdev->flags)) | ||
| 2666 | spares++; | ||
| 2667 | |||
| 2668 | if (spares < mddev->delta_disks-1) | ||
| 2669 | /* Not enough devices even to make a degraded array | ||
| 2670 | * of that size | ||
| 2671 | */ | ||
| 2672 | return -EINVAL; | ||
| 2673 | |||
| 2674 | atomic_set(&conf->reshape_stripes, 0); | ||
| 2675 | spin_lock_irq(&conf->device_lock); | ||
| 2676 | conf->previous_raid_disks = conf->raid_disks; | ||
| 2677 | conf->raid_disks += mddev->delta_disks; | ||
| 2678 | conf->expand_progress = 0; | ||
| 2679 | conf->expand_lo = 0; | ||
| 2680 | spin_unlock_irq(&conf->device_lock); | ||
| 2681 | |||
| 2682 | /* Add some new drives, as many as will fit. | ||
| 2683 | * We know there are enough to make the newly sized array work. | ||
| 2684 | */ | ||
| 2685 | ITERATE_RDEV(mddev, rdev, rtmp) | ||
| 2686 | if (rdev->raid_disk < 0 && | ||
| 2687 | !test_bit(Faulty, &rdev->flags)) { | ||
| 2688 | if (raid5_add_disk(mddev, rdev)) { | ||
| 2689 | char nm[20]; | ||
| 2690 | set_bit(In_sync, &rdev->flags); | ||
| 2691 | conf->working_disks++; | ||
| 2692 | added_devices++; | ||
| 2693 | sprintf(nm, "rd%d", rdev->raid_disk); | ||
| 2694 | sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); | ||
| 2695 | } else | ||
| 2696 | break; | ||
| 2697 | } | ||
| 2698 | |||
| 2699 | mddev->degraded = (conf->raid_disks - conf->previous_raid_disks) - added_devices; | ||
| 2700 | mddev->raid_disks = conf->raid_disks; | ||
| 2701 | mddev->reshape_position = 0; | ||
| 2702 | mddev->sb_dirty = 1; | ||
| 2703 | |||
| 2704 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); | ||
| 2705 | clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); | ||
| 2706 | set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); | ||
| 2707 | set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); | ||
| 2708 | mddev->sync_thread = md_register_thread(md_do_sync, mddev, | ||
| 2709 | "%s_reshape"); | ||
| 2710 | if (!mddev->sync_thread) { | ||
| 2711 | mddev->recovery = 0; | ||
| 2712 | spin_lock_irq(&conf->device_lock); | ||
| 2713 | mddev->raid_disks = conf->raid_disks = conf->previous_raid_disks; | ||
| 2714 | conf->expand_progress = MaxSector; | ||
| 2715 | spin_unlock_irq(&conf->device_lock); | ||
| 2716 | return -EAGAIN; | ||
| 2717 | } | ||
| 2718 | md_wakeup_thread(mddev->sync_thread); | ||
| 2719 | md_new_event(mddev); | ||
| 2720 | return 0; | ||
| 2721 | } | ||
| 2722 | #endif | ||
| 2723 | |||
| 2724 | static void end_reshape(raid5_conf_t *conf) | ||
| 2725 | { | ||
| 2726 | struct block_device *bdev; | ||
| 2727 | |||
| 2728 | if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { | ||
| 2729 | conf->mddev->array_size = conf->mddev->size * (conf->raid_disks-1); | ||
| 2730 | set_capacity(conf->mddev->gendisk, conf->mddev->array_size << 1); | ||
| 2731 | conf->mddev->changed = 1; | ||
| 2732 | |||
| 2733 | bdev = bdget_disk(conf->mddev->gendisk, 0); | ||
| 2734 | if (bdev) { | ||
| 2735 | mutex_lock(&bdev->bd_inode->i_mutex); | ||
| 2736 | i_size_write(bdev->bd_inode, conf->mddev->array_size << 10); | ||
| 2737 | mutex_unlock(&bdev->bd_inode->i_mutex); | ||
| 2738 | bdput(bdev); | ||
| 2739 | } | ||
| 2740 | spin_lock_irq(&conf->device_lock); | ||
| 2741 | conf->expand_progress = MaxSector; | ||
| 2742 | spin_unlock_irq(&conf->device_lock); | ||
| 2743 | conf->mddev->reshape_position = MaxSector; | ||
| 2744 | } | ||
| 2745 | } | ||
| 2746 | |||
| 2171 | static void raid5_quiesce(mddev_t *mddev, int state) | 2747 | static void raid5_quiesce(mddev_t *mddev, int state) |
| 2172 | { | 2748 | { |
| 2173 | raid5_conf_t *conf = mddev_to_conf(mddev); | 2749 | raid5_conf_t *conf = mddev_to_conf(mddev); |
| 2174 | 2750 | ||
| 2175 | switch(state) { | 2751 | switch(state) { |
| 2752 | case 2: /* resume for a suspend */ | ||
| 2753 | wake_up(&conf->wait_for_overlap); | ||
| 2754 | break; | ||
| 2755 | |||
| 2176 | case 1: /* stop all writes */ | 2756 | case 1: /* stop all writes */ |
| 2177 | spin_lock_irq(&conf->device_lock); | 2757 | spin_lock_irq(&conf->device_lock); |
| 2178 | conf->quiesce = 1; | 2758 | conf->quiesce = 1; |
| @@ -2186,6 +2766,7 @@ static void raid5_quiesce(mddev_t *mddev, int state) | |||
| 2186 | spin_lock_irq(&conf->device_lock); | 2766 | spin_lock_irq(&conf->device_lock); |
| 2187 | conf->quiesce = 0; | 2767 | conf->quiesce = 0; |
| 2188 | wake_up(&conf->wait_for_stripe); | 2768 | wake_up(&conf->wait_for_stripe); |
| 2769 | wake_up(&conf->wait_for_overlap); | ||
| 2189 | spin_unlock_irq(&conf->device_lock); | 2770 | spin_unlock_irq(&conf->device_lock); |
| 2190 | break; | 2771 | break; |
| 2191 | } | 2772 | } |
| @@ -2206,6 +2787,10 @@ static struct mdk_personality raid5_personality = | |||
| 2206 | .spare_active = raid5_spare_active, | 2787 | .spare_active = raid5_spare_active, |
| 2207 | .sync_request = sync_request, | 2788 | .sync_request = sync_request, |
| 2208 | .resize = raid5_resize, | 2789 | .resize = raid5_resize, |
| 2790 | #ifdef CONFIG_MD_RAID5_RESHAPE | ||
| 2791 | .check_reshape = raid5_check_reshape, | ||
| 2792 | .start_reshape = raid5_start_reshape, | ||
| 2793 | #endif | ||
| 2209 | .quiesce = raid5_quiesce, | 2794 | .quiesce = raid5_quiesce, |
| 2210 | }; | 2795 | }; |
| 2211 | 2796 | ||
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index cd477ebf2ee4..6df4930fddec 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c | |||
| @@ -331,9 +331,9 @@ static int grow_stripes(raid6_conf_t *conf, int num) | |||
| 331 | kmem_cache_t *sc; | 331 | kmem_cache_t *sc; |
| 332 | int devs = conf->raid_disks; | 332 | int devs = conf->raid_disks; |
| 333 | 333 | ||
| 334 | sprintf(conf->cache_name, "raid6/%s", mdname(conf->mddev)); | 334 | sprintf(conf->cache_name[0], "raid6/%s", mdname(conf->mddev)); |
| 335 | 335 | ||
| 336 | sc = kmem_cache_create(conf->cache_name, | 336 | sc = kmem_cache_create(conf->cache_name[0], |
| 337 | sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), | 337 | sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev), |
| 338 | 0, 0, NULL, NULL); | 338 | 0, 0, NULL, NULL); |
| 339 | if (!sc) | 339 | if (!sc) |
| @@ -2006,11 +2006,14 @@ static int run(mddev_t *mddev) | |||
| 2006 | return -EIO; | 2006 | return -EIO; |
| 2007 | } | 2007 | } |
| 2008 | 2008 | ||
| 2009 | mddev->private = kzalloc(sizeof (raid6_conf_t) | 2009 | mddev->private = kzalloc(sizeof (raid6_conf_t), GFP_KERNEL); |
| 2010 | + mddev->raid_disks * sizeof(struct disk_info), | ||
| 2011 | GFP_KERNEL); | ||
| 2012 | if ((conf = mddev->private) == NULL) | 2010 | if ((conf = mddev->private) == NULL) |
| 2013 | goto abort; | 2011 | goto abort; |
| 2012 | conf->disks = kzalloc(mddev->raid_disks * sizeof(struct disk_info), | ||
| 2013 | GFP_KERNEL); | ||
| 2014 | if (!conf->disks) | ||
| 2015 | goto abort; | ||
| 2016 | |||
| 2014 | conf->mddev = mddev; | 2017 | conf->mddev = mddev; |
| 2015 | 2018 | ||
| 2016 | if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL) | 2019 | if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL) |
| @@ -2158,6 +2161,7 @@ abort: | |||
| 2158 | print_raid6_conf(conf); | 2161 | print_raid6_conf(conf); |
| 2159 | safe_put_page(conf->spare_page); | 2162 | safe_put_page(conf->spare_page); |
| 2160 | kfree(conf->stripe_hashtbl); | 2163 | kfree(conf->stripe_hashtbl); |
| 2164 | kfree(conf->disks); | ||
| 2161 | kfree(conf); | 2165 | kfree(conf); |
| 2162 | } | 2166 | } |
| 2163 | mddev->private = NULL; | 2167 | mddev->private = NULL; |
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 54f8b95717b0..96fe0ecae250 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c | |||
| @@ -86,7 +86,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) | |||
| 86 | 86 | ||
| 87 | if (dvbdev && dvbdev->fops) { | 87 | if (dvbdev && dvbdev->fops) { |
| 88 | int err = 0; | 88 | int err = 0; |
| 89 | struct file_operations *old_fops; | 89 | const struct file_operations *old_fops; |
| 90 | 90 | ||
| 91 | file->private_data = dvbdev; | 91 | file->private_data = dvbdev; |
| 92 | old_fops = file->f_op; | 92 | old_fops = file->f_op; |
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 75e3d41382f2..5f87dd5f1d0b 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
| @@ -97,7 +97,7 @@ static int video_open(struct inode *inode, struct file *file) | |||
| 97 | unsigned int minor = iminor(inode); | 97 | unsigned int minor = iminor(inode); |
| 98 | int err = 0; | 98 | int err = 0; |
| 99 | struct video_device *vfl; | 99 | struct video_device *vfl; |
| 100 | struct file_operations *old_fops; | 100 | const struct file_operations *old_fops; |
| 101 | 101 | ||
| 102 | if(minor>=VIDEO_NUM_DEVICES) | 102 | if(minor>=VIDEO_NUM_DEVICES) |
| 103 | return -ENODEV; | 103 | return -ENODEV; |
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index 2a0c42b8cda5..3d2e76eea93e 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c | |||
| @@ -56,7 +56,7 @@ | |||
| 56 | typedef struct _i2o_proc_entry_t { | 56 | typedef struct _i2o_proc_entry_t { |
| 57 | char *name; /* entry name */ | 57 | char *name; /* entry name */ |
| 58 | mode_t mode; /* mode */ | 58 | mode_t mode; /* mode */ |
| 59 | struct file_operations *fops; /* open function */ | 59 | const struct file_operations *fops; /* open function */ |
| 60 | } i2o_proc_entry; | 60 | } i2o_proc_entry; |
| 61 | 61 | ||
| 62 | /* global I2O /proc/i2o entry */ | 62 | /* global I2O /proc/i2o entry */ |
diff --git a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c index f295401fac21..7fd7a43e38de 100644 --- a/drivers/misc/ibmasm/heartbeat.c +++ b/drivers/misc/ibmasm/heartbeat.c | |||
| @@ -52,12 +52,13 @@ static struct notifier_block panic_notifier = { panic_happened, NULL, 1 }; | |||
| 52 | 52 | ||
| 53 | void ibmasm_register_panic_notifier(void) | 53 | void ibmasm_register_panic_notifier(void) |
| 54 | { | 54 | { |
| 55 | notifier_chain_register(&panic_notifier_list, &panic_notifier); | 55 | atomic_notifier_chain_register(&panic_notifier_list, &panic_notifier); |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | void ibmasm_unregister_panic_notifier(void) | 58 | void ibmasm_unregister_panic_notifier(void) |
| 59 | { | 59 | { |
| 60 | notifier_chain_unregister(&panic_notifier_list, &panic_notifier); | 60 | atomic_notifier_chain_unregister(&panic_notifier_list, |
| 61 | &panic_notifier); | ||
| 61 | } | 62 | } |
| 62 | 63 | ||
| 63 | 64 | ||
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index 5c550fcac2c4..26a230b6ff80 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c | |||
| @@ -101,7 +101,7 @@ static struct super_operations ibmasmfs_s_ops = { | |||
| 101 | .drop_inode = generic_delete_inode, | 101 | .drop_inode = generic_delete_inode, |
| 102 | }; | 102 | }; |
| 103 | 103 | ||
| 104 | static struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations; | 104 | static const struct file_operations *ibmasmfs_dir_ops = &simple_dir_operations; |
| 105 | 105 | ||
| 106 | static struct file_system_type ibmasmfs_type = { | 106 | static struct file_system_type ibmasmfs_type = { |
| 107 | .owner = THIS_MODULE, | 107 | .owner = THIS_MODULE, |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2d0ac169a86c..f13a539dc169 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
| @@ -3159,7 +3159,7 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave | |||
| 3159 | * bond_netdev_event: handle netdev notifier chain events. | 3159 | * bond_netdev_event: handle netdev notifier chain events. |
| 3160 | * | 3160 | * |
| 3161 | * This function receives events for the netdev chain. The caller (an | 3161 | * This function receives events for the netdev chain. The caller (an |
| 3162 | * ioctl handler calling notifier_call_chain) holds the necessary | 3162 | * ioctl handler calling blocking_notifier_call_chain) holds the necessary |
| 3163 | * locks for us to safely manipulate the slave devices (RTNL lock, | 3163 | * locks for us to safely manipulate the slave devices (RTNL lock, |
| 3164 | * dev_probe_lock). | 3164 | * dev_probe_lock). |
| 3165 | */ | 3165 | */ |
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index e7fc28b07e5a..7627a75f4f7c 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
| @@ -134,6 +134,7 @@ | |||
| 134 | #include <linux/random.h> | 134 | #include <linux/random.h> |
| 135 | #include <linux/init.h> | 135 | #include <linux/init.h> |
| 136 | #include <linux/if_vlan.h> | 136 | #include <linux/if_vlan.h> |
| 137 | #include <linux/dma-mapping.h> | ||
| 137 | 138 | ||
| 138 | #include <asm/irq.h> | 139 | #include <asm/irq.h> |
| 139 | #include <asm/io.h> | 140 | #include <asm/io.h> |
| @@ -2932,7 +2933,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
| 2932 | if (id->driver_data & DEV_HAS_HIGH_DMA) { | 2933 | if (id->driver_data & DEV_HAS_HIGH_DMA) { |
| 2933 | /* packet format 3: supports 40-bit addressing */ | 2934 | /* packet format 3: supports 40-bit addressing */ |
| 2934 | np->desc_ver = DESC_VER_3; | 2935 | np->desc_ver = DESC_VER_3; |
| 2935 | if (pci_set_dma_mask(pci_dev, 0x0000007fffffffffULL)) { | 2936 | if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) { |
| 2936 | printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", | 2937 | printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", |
| 2937 | pci_name(pci_dev)); | 2938 | pci_name(pci_dev)); |
| 2938 | } else { | 2939 | } else { |
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index 9b8295ee06ef..ae71ed57c12d 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include <linux/ip.h> | 44 | #include <linux/ip.h> |
| 45 | #include <linux/tcp.h> | 45 | #include <linux/tcp.h> |
| 46 | #include <linux/udp.h> | 46 | #include <linux/udp.h> |
| 47 | #include <linux/dma-mapping.h> | ||
| 47 | 48 | ||
| 48 | #ifdef CONFIG_SERIAL_8250 | 49 | #ifdef CONFIG_SERIAL_8250 |
| 49 | #include <linux/serial_core.h> | 50 | #include <linux/serial_core.h> |
| @@ -1195,17 +1196,17 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1195 | int err, pci_using_dac; | 1196 | int err, pci_using_dac; |
| 1196 | 1197 | ||
| 1197 | /* Configure DMA attributes. */ | 1198 | /* Configure DMA attributes. */ |
| 1198 | err = pci_set_dma_mask(pdev, 0xffffffffffffffffULL); | 1199 | err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); |
| 1199 | if (!err) { | 1200 | if (!err) { |
| 1200 | pci_using_dac = 1; | 1201 | pci_using_dac = 1; |
| 1201 | err = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); | 1202 | err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); |
| 1202 | if (err < 0) { | 1203 | if (err < 0) { |
| 1203 | printk(KERN_ERR "%s: Unable to obtain 64 bit DMA " | 1204 | printk(KERN_ERR "%s: Unable to obtain 64 bit DMA " |
| 1204 | "for consistent allocations\n", pci_name(pdev)); | 1205 | "for consistent allocations\n", pci_name(pdev)); |
| 1205 | goto out; | 1206 | goto out; |
| 1206 | } | 1207 | } |
| 1207 | } else { | 1208 | } else { |
| 1208 | err = pci_set_dma_mask(pdev, 0xffffffffULL); | 1209 | err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); |
| 1209 | if (err) { | 1210 | if (err) { |
| 1210 | printk(KERN_ERR "%s: No usable DMA configuration, " | 1211 | printk(KERN_ERR "%s: No usable DMA configuration, " |
| 1211 | "aborting.\n", pci_name(pdev)); | 1212 | "aborting.\n", pci_name(pdev)); |
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index 83141a3ff546..cc7ff8f00e42 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c | |||
| @@ -207,7 +207,7 @@ static int __init nsc_ircc_init(void) | |||
| 207 | /* Register with PnP subsystem to detect disable ports */ | 207 | /* Register with PnP subsystem to detect disable ports */ |
| 208 | ret = pnp_register_driver(&nsc_ircc_pnp_driver); | 208 | ret = pnp_register_driver(&nsc_ircc_pnp_driver); |
| 209 | 209 | ||
| 210 | if (ret >= 0) | 210 | if (!ret) |
| 211 | pnp_registered = 1; | 211 | pnp_registered = 1; |
| 212 | 212 | ||
| 213 | ret = -ENODEV; | 213 | ret = -ENODEV; |
| @@ -812,7 +812,7 @@ static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info) | |||
| 812 | int cfg_base = info->cfg_base; | 812 | int cfg_base = info->cfg_base; |
| 813 | int enabled; | 813 | int enabled; |
| 814 | 814 | ||
| 815 | /* User is shure about his config... accept it. */ | 815 | /* User is sure about his config... accept it. */ |
| 816 | IRDA_DEBUG(2, "%s(): nsc_ircc_init_39x (user settings): " | 816 | IRDA_DEBUG(2, "%s(): nsc_ircc_init_39x (user settings): " |
| 817 | "io=0x%04x, irq=%d, dma=%d\n", | 817 | "io=0x%04x, irq=%d, dma=%d\n", |
| 818 | __FUNCTION__, info->fir_base, info->irq, info->dma); | 818 | __FUNCTION__, info->fir_base, info->irq, info->dma); |
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 0c13795dca38..b79d6e8d3045 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c | |||
| @@ -172,7 +172,7 @@ static struct net_device_stats *get_stats(struct net_device *dev) | |||
| 172 | 172 | ||
| 173 | memset(stats, 0, sizeof(struct net_device_stats)); | 173 | memset(stats, 0, sizeof(struct net_device_stats)); |
| 174 | 174 | ||
| 175 | for_each_cpu(i) { | 175 | for_each_possible_cpu(i) { |
| 176 | struct net_device_stats *lb_stats; | 176 | struct net_device_stats *lb_stats; |
| 177 | 177 | ||
| 178 | lb_stats = &per_cpu(loopback_stats, i); | 178 | lb_stats = &per_cpu(loopback_stats, i); |
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 0fede50abd3e..8e9b1a537dee 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c | |||
| @@ -1828,10 +1828,10 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ | |||
| 1828 | int using_dac = 0; | 1828 | int using_dac = 0; |
| 1829 | 1829 | ||
| 1830 | /* See if we can set the dma mask early on; failure is fatal. */ | 1830 | /* See if we can set the dma mask early on; failure is fatal. */ |
| 1831 | if (sizeof(dma_addr_t) == 8 && | 1831 | if (sizeof(dma_addr_t) == 8 && |
| 1832 | !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) { | 1832 | !pci_set_dma_mask(pci_dev, DMA_64BIT_MASK)) { |
| 1833 | using_dac = 1; | 1833 | using_dac = 1; |
| 1834 | } else if (!pci_set_dma_mask(pci_dev, 0xffffffff)) { | 1834 | } else if (!pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) { |
| 1835 | using_dac = 0; | 1835 | using_dac = 0; |
| 1836 | } else { | 1836 | } else { |
| 1837 | printk(KERN_WARNING "ns83820.c: pci_set_dma_mask failed!\n"); | 1837 | printk(KERN_WARNING "ns83820.c: pci_set_dma_mask failed!\n"); |
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c index 8429ceb01389..b82191d2bee1 100644 --- a/drivers/net/sis900.c +++ b/drivers/net/sis900.c | |||
| @@ -2283,7 +2283,7 @@ static void set_rx_mode(struct net_device *net_dev) | |||
| 2283 | int i, table_entries; | 2283 | int i, table_entries; |
| 2284 | u32 rx_mode; | 2284 | u32 rx_mode; |
| 2285 | 2285 | ||
| 2286 | /* 635 Hash Table entires = 256(2^16) */ | 2286 | /* 635 Hash Table entries = 256(2^16) */ |
| 2287 | if((sis_priv->chipset_rev >= SIS635A_900_REV) || | 2287 | if((sis_priv->chipset_rev >= SIS635A_900_REV) || |
| 2288 | (sis_priv->chipset_rev == SIS900B_900_REV)) | 2288 | (sis_priv->chipset_rev == SIS900B_900_REV)) |
| 2289 | table_entries = 16; | 2289 | table_entries = 16; |
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index ee48bfd67349..d1a86a080a65 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c | |||
| @@ -513,7 +513,7 @@ struct mii_phy { | |||
| 513 | u_char *rst; /* Start of reset sequence in SROM */ | 513 | u_char *rst; /* Start of reset sequence in SROM */ |
| 514 | u_int mc; /* Media Capabilities */ | 514 | u_int mc; /* Media Capabilities */ |
| 515 | u_int ana; /* NWay Advertisement */ | 515 | u_int ana; /* NWay Advertisement */ |
| 516 | u_int fdx; /* Full DupleX capabilites for each media */ | 516 | u_int fdx; /* Full DupleX capabilities for each media */ |
| 517 | u_int ttm; /* Transmit Threshold Mode for each media */ | 517 | u_int ttm; /* Transmit Threshold Mode for each media */ |
| 518 | u_int mci; /* 21142 MII Connector Interrupt info */ | 518 | u_int mci; /* 21142 MII Connector Interrupt info */ |
| 519 | }; | 519 | }; |
diff --git a/drivers/net/tulip/pnic2.c b/drivers/net/tulip/pnic2.c index 55f4a9a631bc..ab985023fcca 100644 --- a/drivers/net/tulip/pnic2.c +++ b/drivers/net/tulip/pnic2.c | |||
| @@ -199,7 +199,7 @@ void pnic2_lnk_change(struct net_device *dev, int csr5) | |||
| 199 | /* negotiation ended successfully */ | 199 | /* negotiation ended successfully */ |
| 200 | 200 | ||
| 201 | /* get the link partners reply and mask out all but | 201 | /* get the link partners reply and mask out all but |
| 202 | * bits 24-21 which show the partners capabilites | 202 | * bits 24-21 which show the partners capabilities |
| 203 | * and match those to what we advertised | 203 | * and match those to what we advertised |
| 204 | * | 204 | * |
| 205 | * then begin to interpret the results of the negotiation. | 205 | * then begin to interpret the results of the negotiation. |
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index cde35dd87906..c1ce87a5f8d3 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c | |||
| @@ -208,7 +208,7 @@ static const struct typhoon_card_info typhoon_card_info[] __devinitdata = { | |||
| 208 | }; | 208 | }; |
| 209 | 209 | ||
| 210 | /* Notes on the new subsystem numbering scheme: | 210 | /* Notes on the new subsystem numbering scheme: |
| 211 | * bits 0-1 indicate crypto capabilites: (0) variable, (1) DES, or (2) 3DES | 211 | * bits 0-1 indicate crypto capabilities: (0) variable, (1) DES, or (2) 3DES |
| 212 | * bit 4 indicates if this card has secured firmware (we don't support it) | 212 | * bit 4 indicates if this card has secured firmware (we don't support it) |
| 213 | * bit 8 indicates if this is a (0) copper or (1) fiber card | 213 | * bit 8 indicates if this is a (0) copper or (1) fiber card |
| 214 | * bits 12-16 indicate card type: (0) client and (1) server | 214 | * bits 12-16 indicate card type: (0) client and (1) server |
| @@ -788,7 +788,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) | |||
| 788 | /* we have two rings to choose from, but we only use txLo for now | 788 | /* we have two rings to choose from, but we only use txLo for now |
| 789 | * If we start using the Hi ring as well, we'll need to update | 789 | * If we start using the Hi ring as well, we'll need to update |
| 790 | * typhoon_stop_runtime(), typhoon_interrupt(), typhoon_num_free_tx(), | 790 | * typhoon_stop_runtime(), typhoon_interrupt(), typhoon_num_free_tx(), |
| 791 | * and TXHI_ENTIRES to match, as well as update the TSO code below | 791 | * and TXHI_ENTRIES to match, as well as update the TSO code below |
| 792 | * to get the right DMA address | 792 | * to get the right DMA address |
| 793 | */ | 793 | */ |
| 794 | txRing = &tp->txLoRing; | 794 | txRing = &tp->txLoRing; |
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 9d3b51c3ef54..29a756dd979b 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c | |||
| @@ -577,8 +577,8 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev, | |||
| 577 | We set both dma_mask and consistent_dma_mask to 28 bits | 577 | We set both dma_mask and consistent_dma_mask to 28 bits |
| 578 | and pray pci_alloc_consistent() will use this info. It should | 578 | and pray pci_alloc_consistent() will use this info. It should |
| 579 | work on most platforms */ | 579 | work on most platforms */ |
| 580 | if (pci_set_consistent_dma_mask(pdev, 0x0FFFFFFF) || | 580 | if (pci_set_consistent_dma_mask(pdev, DMA_28BIT_MASK) || |
| 581 | pci_set_dma_mask(pdev, 0x0FFFFFFF)) { | 581 | pci_set_dma_mask(pdev, DMA_28BIT_MASK)) { |
| 582 | printk(KERN_ERR "wanXL: No usable DMA configuration\n"); | 582 | printk(KERN_ERR "wanXL: No usable DMA configuration\n"); |
| 583 | return -EIO; | 583 | return -EIO; |
| 584 | } | 584 | } |
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 6fd0bf736830..8dfdfbd5966c 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
| @@ -3858,7 +3858,7 @@ static int orinoco_ioctl_setscan(struct net_device *dev, | |||
| 3858 | unsigned long flags; | 3858 | unsigned long flags; |
| 3859 | 3859 | ||
| 3860 | /* Note : you may have realised that, as this is a SET operation, | 3860 | /* Note : you may have realised that, as this is a SET operation, |
| 3861 | * this is priviledged and therefore a normal user can't | 3861 | * this is privileged and therefore a normal user can't |
| 3862 | * perform scanning. | 3862 | * perform scanning. |
| 3863 | * This is not an error, while the device perform scanning, | 3863 | * This is not an error, while the device perform scanning, |
| 3864 | * traffic doesn't flow, so it's a perfect DoS... | 3864 | * traffic doesn't flow, so it's a perfect DoS... |
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index e5bb9f5ae429..989599ad33ef 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c | |||
| @@ -747,7 +747,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info, | |||
| 747 | 747 | ||
| 748 | if (essid->length) { | 748 | if (essid->length) { |
| 749 | dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */ | 749 | dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */ |
| 750 | /* if it is to big, trunk it */ | 750 | /* if it is too big, trunk it */ |
| 751 | dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length); | 751 | dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length); |
| 752 | } else { | 752 | } else { |
| 753 | dwrq->flags = 0; | 753 | dwrq->flags = 0; |
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index b41d666fea3c..bfa0cc319a09 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
| 23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 24 | #include <linux/init.h> /* For __init, __exit */ | 24 | #include <linux/init.h> /* For __init, __exit */ |
| 25 | #include <linux/dma-mapping.h> | ||
| 25 | 26 | ||
| 26 | #include "prismcompat.h" | 27 | #include "prismcompat.h" |
| 27 | #include "islpci_dev.h" | 28 | #include "islpci_dev.h" |
| @@ -124,7 +125,7 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 124 | } | 125 | } |
| 125 | 126 | ||
| 126 | /* enable PCI DMA */ | 127 | /* enable PCI DMA */ |
| 127 | if (pci_set_dma_mask(pdev, 0xffffffff)) { | 128 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { |
| 128 | printk(KERN_ERR "%s: 32-bit PCI DMA not supported", DRV_NAME); | 129 | printk(KERN_ERR "%s: 32-bit PCI DMA not supported", DRV_NAME); |
| 129 | goto do_pci_disable_device; | 130 | goto do_pci_disable_device; |
| 130 | } | 131 | } |
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 330d3869b41e..fc4bc9b94c74 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c | |||
| @@ -217,11 +217,10 @@ static void oprofile_end_trace(struct oprofile_cpu_buffer * cpu_buf) | |||
| 217 | cpu_buf->tracing = 0; | 217 | cpu_buf->tracing = 0; |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) | 220 | void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, |
| 221 | unsigned long event, int is_kernel) | ||
| 221 | { | 222 | { |
| 222 | struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()]; | 223 | struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()]; |
| 223 | unsigned long pc = profile_pc(regs); | ||
| 224 | int is_kernel = !user_mode(regs); | ||
| 225 | 224 | ||
| 226 | if (!backtrace_depth) { | 225 | if (!backtrace_depth) { |
| 227 | log_sample(cpu_buf, pc, is_kernel, event); | 226 | log_sample(cpu_buf, pc, is_kernel, event); |
| @@ -238,6 +237,14 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) | |||
| 238 | oprofile_end_trace(cpu_buf); | 237 | oprofile_end_trace(cpu_buf); |
| 239 | } | 238 | } |
| 240 | 239 | ||
| 240 | void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) | ||
| 241 | { | ||
| 242 | int is_kernel = !user_mode(regs); | ||
| 243 | unsigned long pc = profile_pc(regs); | ||
| 244 | |||
| 245 | oprofile_add_ext_sample(pc, regs, event, is_kernel); | ||
| 246 | } | ||
| 247 | |||
| 241 | void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) | 248 | void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) |
| 242 | { | 249 | { |
| 243 | struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()]; | 250 | struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()]; |
diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c index e94b1e4a2a84..f0acb661c253 100644 --- a/drivers/oprofile/oprofile_stats.c +++ b/drivers/oprofile/oprofile_stats.c | |||
| @@ -22,7 +22,7 @@ void oprofile_reset_stats(void) | |||
| 22 | struct oprofile_cpu_buffer * cpu_buf; | 22 | struct oprofile_cpu_buffer * cpu_buf; |
| 23 | int i; | 23 | int i; |
| 24 | 24 | ||
| 25 | for_each_cpu(i) { | 25 | for_each_possible_cpu(i) { |
| 26 | cpu_buf = &cpu_buffer[i]; | 26 | cpu_buf = &cpu_buffer[i]; |
| 27 | cpu_buf->sample_received = 0; | 27 | cpu_buf->sample_received = 0; |
| 28 | cpu_buf->sample_lost_overflow = 0; | 28 | cpu_buf->sample_lost_overflow = 0; |
| @@ -46,7 +46,7 @@ void oprofile_create_stats_files(struct super_block * sb, struct dentry * root) | |||
| 46 | if (!dir) | 46 | if (!dir) |
| 47 | return; | 47 | return; |
| 48 | 48 | ||
| 49 | for_each_cpu(i) { | 49 | for_each_possible_cpu(i) { |
| 50 | cpu_buf = &cpu_buffer[i]; | 50 | cpu_buf = &cpu_buffer[i]; |
| 51 | snprintf(buf, 10, "cpu%d", i); | 51 | snprintf(buf, 10, "cpu%d", i); |
| 52 | cpudir = oprofilefs_mkdir(sb, dir, buf); | 52 | cpudir = oprofilefs_mkdir(sb, dir, buf); |
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index d6bae699749a..b62da9b0cbf0 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c | |||
| @@ -130,7 +130,7 @@ static struct file_operations ulong_ro_fops = { | |||
| 130 | 130 | ||
| 131 | 131 | ||
| 132 | static struct dentry * __oprofilefs_create_file(struct super_block * sb, | 132 | static struct dentry * __oprofilefs_create_file(struct super_block * sb, |
| 133 | struct dentry * root, char const * name, struct file_operations * fops, | 133 | struct dentry * root, char const * name, const struct file_operations * fops, |
| 134 | int perm) | 134 | int perm) |
| 135 | { | 135 | { |
| 136 | struct dentry * dentry; | 136 | struct dentry * dentry; |
| @@ -203,7 +203,7 @@ int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root, | |||
| 203 | 203 | ||
| 204 | 204 | ||
| 205 | int oprofilefs_create_file(struct super_block * sb, struct dentry * root, | 205 | int oprofilefs_create_file(struct super_block * sb, struct dentry * root, |
| 206 | char const * name, struct file_operations * fops) | 206 | char const * name, const struct file_operations * fops) |
| 207 | { | 207 | { |
| 208 | if (!__oprofilefs_create_file(sb, root, name, fops, 0644)) | 208 | if (!__oprofilefs_create_file(sb, root, name, fops, 0644)) |
| 209 | return -EFAULT; | 209 | return -EFAULT; |
| @@ -212,7 +212,7 @@ int oprofilefs_create_file(struct super_block * sb, struct dentry * root, | |||
| 212 | 212 | ||
| 213 | 213 | ||
| 214 | int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root, | 214 | int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root, |
| 215 | char const * name, struct file_operations * fops, int perm) | 215 | char const * name, const struct file_operations * fops, int perm) |
| 216 | { | 216 | { |
| 217 | if (!__oprofilefs_create_file(sb, root, name, fops, perm)) | 217 | if (!__oprofilefs_create_file(sb, root, name, fops, perm)) |
| 218 | return -EFAULT; | 218 | return -EFAULT; |
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 3627a2d7f79f..298f2ddb2c17 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c | |||
| @@ -499,11 +499,16 @@ static int led_halt(struct notifier_block *, unsigned long, void *); | |||
| 499 | static struct notifier_block led_notifier = { | 499 | static struct notifier_block led_notifier = { |
| 500 | .notifier_call = led_halt, | 500 | .notifier_call = led_halt, |
| 501 | }; | 501 | }; |
| 502 | static int notifier_disabled = 0; | ||
| 502 | 503 | ||
| 503 | static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) | 504 | static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) |
| 504 | { | 505 | { |
| 505 | char *txt; | 506 | char *txt; |
| 506 | 507 | ||
| 508 | if (notifier_disabled) | ||
| 509 | return NOTIFY_OK; | ||
| 510 | |||
| 511 | notifier_disabled = 1; | ||
| 507 | switch (event) { | 512 | switch (event) { |
| 508 | case SYS_RESTART: txt = "SYSTEM RESTART"; | 513 | case SYS_RESTART: txt = "SYSTEM RESTART"; |
| 509 | break; | 514 | break; |
| @@ -527,7 +532,6 @@ static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) | |||
| 527 | if (led_func_ptr) | 532 | if (led_func_ptr) |
| 528 | led_func_ptr(0xff); /* turn all LEDs ON */ | 533 | led_func_ptr(0xff); /* turn all LEDs ON */ |
| 529 | 534 | ||
| 530 | unregister_reboot_notifier(&led_notifier); | ||
| 531 | return NOTIFY_OK; | 535 | return NOTIFY_OK; |
| 532 | } | 536 | } |
| 533 | 537 | ||
| @@ -758,6 +762,12 @@ not_found: | |||
| 758 | return 1; | 762 | return 1; |
| 759 | } | 763 | } |
| 760 | 764 | ||
| 765 | static void __exit led_exit(void) | ||
| 766 | { | ||
| 767 | unregister_reboot_notifier(&led_notifier); | ||
| 768 | return; | ||
| 769 | } | ||
| 770 | |||
| 761 | #ifdef CONFIG_PROC_FS | 771 | #ifdef CONFIG_PROC_FS |
| 762 | module_init(led_create_procfs) | 772 | module_init(led_create_procfs) |
| 763 | #endif | 773 | #endif |
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c index 54b2b7f20b96..0bcab83b4080 100644 --- a/drivers/parisc/power.c +++ b/drivers/parisc/power.c | |||
| @@ -251,7 +251,8 @@ static int __init power_init(void) | |||
| 251 | } | 251 | } |
| 252 | 252 | ||
| 253 | /* Register a call for panic conditions. */ | 253 | /* Register a call for panic conditions. */ |
| 254 | notifier_chain_register(&panic_notifier_list, &parisc_panic_block); | 254 | atomic_notifier_chain_register(&panic_notifier_list, |
| 255 | &parisc_panic_block); | ||
| 255 | 256 | ||
| 256 | tasklet_enable(&power_tasklet); | 257 | tasklet_enable(&power_tasklet); |
| 257 | 258 | ||
| @@ -264,7 +265,8 @@ static void __exit power_exit(void) | |||
| 264 | return; | 265 | return; |
| 265 | 266 | ||
| 266 | tasklet_disable(&power_tasklet); | 267 | tasklet_disable(&power_tasklet); |
| 267 | notifier_chain_unregister(&panic_notifier_list, &parisc_panic_block); | 268 | atomic_notifier_chain_unregister(&panic_notifier_list, |
| 269 | &parisc_panic_block); | ||
| 268 | power_tasklet.func = NULL; | 270 | power_tasklet.func = NULL; |
| 269 | pdc_soft_power_button(0); | 271 | pdc_soft_power_button(0); |
| 270 | } | 272 | } |
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 9302b8fd7461..d5890027f8af 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
| @@ -3126,9 +3126,9 @@ parport_pc_find_isa_ports (int autoirq, int autodma) | |||
| 3126 | * autoirq is PARPORT_IRQ_NONE, PARPORT_IRQ_AUTO, or PARPORT_IRQ_PROBEONLY | 3126 | * autoirq is PARPORT_IRQ_NONE, PARPORT_IRQ_AUTO, or PARPORT_IRQ_PROBEONLY |
| 3127 | * autodma is PARPORT_DMA_NONE or PARPORT_DMA_AUTO | 3127 | * autodma is PARPORT_DMA_NONE or PARPORT_DMA_AUTO |
| 3128 | */ | 3128 | */ |
| 3129 | static int __init parport_pc_find_ports (int autoirq, int autodma) | 3129 | static void __init parport_pc_find_ports (int autoirq, int autodma) |
| 3130 | { | 3130 | { |
| 3131 | int count = 0, r; | 3131 | int count = 0, err; |
| 3132 | 3132 | ||
| 3133 | #ifdef CONFIG_PARPORT_PC_SUPERIO | 3133 | #ifdef CONFIG_PARPORT_PC_SUPERIO |
| 3134 | detect_and_report_winbond (); | 3134 | detect_and_report_winbond (); |
| @@ -3140,23 +3140,17 @@ static int __init parport_pc_find_ports (int autoirq, int autodma) | |||
| 3140 | 3140 | ||
| 3141 | /* PnP ports, skip detection if SuperIO already found them */ | 3141 | /* PnP ports, skip detection if SuperIO already found them */ |
| 3142 | if (!count) { | 3142 | if (!count) { |
| 3143 | r = pnp_register_driver (&parport_pc_pnp_driver); | 3143 | err = pnp_register_driver (&parport_pc_pnp_driver); |
| 3144 | if (r >= 0) { | 3144 | if (!err) |
| 3145 | pnp_registered_parport = 1; | 3145 | pnp_registered_parport = 1; |
| 3146 | count += r; | ||
| 3147 | } | ||
| 3148 | } | 3146 | } |
| 3149 | 3147 | ||
| 3150 | /* ISA ports and whatever (see asm/parport.h). */ | 3148 | /* ISA ports and whatever (see asm/parport.h). */ |
| 3151 | count += parport_pc_find_nonpci_ports (autoirq, autodma); | 3149 | parport_pc_find_nonpci_ports (autoirq, autodma); |
| 3152 | |||
| 3153 | r = pci_register_driver (&parport_pc_pci_driver); | ||
| 3154 | if (r) | ||
| 3155 | return r; | ||
| 3156 | pci_registered_parport = 1; | ||
| 3157 | count += 1; | ||
| 3158 | 3150 | ||
| 3159 | return count; | 3151 | err = pci_register_driver (&parport_pc_pci_driver); |
| 3152 | if (!err) | ||
| 3153 | pci_registered_parport = 1; | ||
| 3160 | } | 3154 | } |
| 3161 | 3155 | ||
| 3162 | /* | 3156 | /* |
| @@ -3381,8 +3375,6 @@ __setup("parport_init_mode=",parport_init_mode_setup); | |||
| 3381 | 3375 | ||
| 3382 | static int __init parport_pc_init(void) | 3376 | static int __init parport_pc_init(void) |
| 3383 | { | 3377 | { |
| 3384 | int count = 0; | ||
| 3385 | |||
| 3386 | if (parse_parport_params()) | 3378 | if (parse_parport_params()) |
| 3387 | return -EINVAL; | 3379 | return -EINVAL; |
| 3388 | 3380 | ||
| @@ -3395,12 +3387,11 @@ static int __init parport_pc_init(void) | |||
| 3395 | break; | 3387 | break; |
| 3396 | if ((io_hi[i]) == PARPORT_IOHI_AUTO) | 3388 | if ((io_hi[i]) == PARPORT_IOHI_AUTO) |
| 3397 | io_hi[i] = 0x400 + io[i]; | 3389 | io_hi[i] = 0x400 + io[i]; |
| 3398 | if (parport_pc_probe_port(io[i], io_hi[i], | 3390 | parport_pc_probe_port(io[i], io_hi[i], |
| 3399 | irqval[i], dmaval[i], NULL)) | 3391 | irqval[i], dmaval[i], NULL); |
| 3400 | count++; | ||
| 3401 | } | 3392 | } |
| 3402 | } else | 3393 | } else |
| 3403 | count += parport_pc_find_ports (irqval[0], dmaval[0]); | 3394 | parport_pc_find_ports (irqval[0], dmaval[0]); |
| 3404 | 3395 | ||
| 3405 | return 0; | 3396 | return 0; |
| 3406 | } | 3397 | } |
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index b68eef251614..bb19c64073c6 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c | |||
| @@ -47,7 +47,7 @@ static void card_remove(struct pnp_dev * dev) | |||
| 47 | { | 47 | { |
| 48 | dev->card_link = NULL; | 48 | dev->card_link = NULL; |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | static void card_remove_first(struct pnp_dev * dev) | 51 | static void card_remove_first(struct pnp_dev * dev) |
| 52 | { | 52 | { |
| 53 | struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver); | 53 | struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver); |
| @@ -361,7 +361,7 @@ static int card_resume(struct pnp_dev *dev) | |||
| 361 | 361 | ||
| 362 | int pnp_register_card_driver(struct pnp_card_driver * drv) | 362 | int pnp_register_card_driver(struct pnp_card_driver * drv) |
| 363 | { | 363 | { |
| 364 | int count; | 364 | int error; |
| 365 | struct list_head *pos, *temp; | 365 | struct list_head *pos, *temp; |
| 366 | 366 | ||
| 367 | drv->link.name = drv->name; | 367 | drv->link.name = drv->name; |
| @@ -372,21 +372,19 @@ int pnp_register_card_driver(struct pnp_card_driver * drv) | |||
| 372 | drv->link.suspend = drv->suspend ? card_suspend : NULL; | 372 | drv->link.suspend = drv->suspend ? card_suspend : NULL; |
| 373 | drv->link.resume = drv->resume ? card_resume : NULL; | 373 | drv->link.resume = drv->resume ? card_resume : NULL; |
| 374 | 374 | ||
| 375 | count = pnp_register_driver(&drv->link); | 375 | error = pnp_register_driver(&drv->link); |
| 376 | if (count < 0) | 376 | if (error < 0) |
| 377 | return count; | 377 | return error; |
| 378 | 378 | ||
| 379 | spin_lock(&pnp_lock); | 379 | spin_lock(&pnp_lock); |
| 380 | list_add_tail(&drv->global_list, &pnp_card_drivers); | 380 | list_add_tail(&drv->global_list, &pnp_card_drivers); |
| 381 | spin_unlock(&pnp_lock); | 381 | spin_unlock(&pnp_lock); |
| 382 | 382 | ||
| 383 | count = 0; | ||
| 384 | |||
| 385 | list_for_each_safe(pos,temp,&pnp_cards){ | 383 | list_for_each_safe(pos,temp,&pnp_cards){ |
| 386 | struct pnp_card *card = list_entry(pos, struct pnp_card, global_list); | 384 | struct pnp_card *card = list_entry(pos, struct pnp_card, global_list); |
| 387 | count += card_probe(card,drv); | 385 | card_probe(card,drv); |
| 388 | } | 386 | } |
| 389 | return count; | 387 | return 0; |
| 390 | } | 388 | } |
| 391 | 389 | ||
| 392 | /** | 390 | /** |
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 7cafacdd12b0..e54c15383193 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c | |||
| @@ -201,31 +201,14 @@ struct bus_type pnp_bus_type = { | |||
| 201 | .resume = pnp_bus_resume, | 201 | .resume = pnp_bus_resume, |
| 202 | }; | 202 | }; |
| 203 | 203 | ||
| 204 | |||
| 205 | static int count_devices(struct device * dev, void * c) | ||
| 206 | { | ||
| 207 | int * count = c; | ||
| 208 | (*count)++; | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | int pnp_register_driver(struct pnp_driver *drv) | 204 | int pnp_register_driver(struct pnp_driver *drv) |
| 213 | { | 205 | { |
| 214 | int count; | ||
| 215 | |||
| 216 | pnp_dbg("the driver '%s' has been registered", drv->name); | 206 | pnp_dbg("the driver '%s' has been registered", drv->name); |
| 217 | 207 | ||
| 218 | drv->driver.name = drv->name; | 208 | drv->driver.name = drv->name; |
| 219 | drv->driver.bus = &pnp_bus_type; | 209 | drv->driver.bus = &pnp_bus_type; |
| 220 | 210 | ||
| 221 | count = driver_register(&drv->driver); | 211 | return driver_register(&drv->driver); |
| 222 | |||
| 223 | /* get the number of initial matches */ | ||
| 224 | if (count >= 0){ | ||
| 225 | count = 0; | ||
| 226 | driver_for_each_device(&drv->driver, NULL, &count, count_devices); | ||
| 227 | } | ||
| 228 | return count; | ||
| 229 | } | 212 | } |
| 230 | 213 | ||
| 231 | void pnp_unregister_driver(struct pnp_driver *drv) | 214 | void pnp_unregister_driver(struct pnp_driver *drv) |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig new file mode 100644 index 000000000000..929dd8090578 --- /dev/null +++ b/drivers/rtc/Kconfig | |||
| @@ -0,0 +1,165 @@ | |||
| 1 | \# | ||
| 2 | # RTC class/drivers configuration | ||
| 3 | # | ||
| 4 | |||
| 5 | menu "Real Time Clock" | ||
| 6 | |||
| 7 | config RTC_LIB | ||
| 8 | tristate | ||
| 9 | |||
| 10 | config RTC_CLASS | ||
| 11 | tristate "RTC class" | ||
| 12 | depends on EXPERIMENTAL | ||
| 13 | default n | ||
| 14 | select RTC_LIB | ||
| 15 | help | ||
| 16 | Generic RTC class support. If you say yes here, you will | ||
| 17 | be allowed to plug one or more RTCs to your system. You will | ||
| 18 | probably want to enable one of more of the interfaces below. | ||
| 19 | |||
| 20 | This driver can also be built as a module. If so, the module | ||
| 21 | will be called rtc-class. | ||
| 22 | |||
| 23 | config RTC_HCTOSYS | ||
| 24 | bool "Set system time from RTC on startup" | ||
| 25 | depends on RTC_CLASS = y | ||
| 26 | default y | ||
| 27 | help | ||
| 28 | If you say yes here, the system time will be set using | ||
| 29 | the value read from the specified RTC device. This is useful | ||
| 30 | in order to avoid unnecessary fschk runs. | ||
| 31 | |||
| 32 | config RTC_HCTOSYS_DEVICE | ||
| 33 | string "The RTC to read the time from" | ||
| 34 | depends on RTC_HCTOSYS = y | ||
| 35 | default "rtc0" | ||
| 36 | help | ||
| 37 | The RTC device that will be used as the source for | ||
| 38 | the system time, usually rtc0. | ||
| 39 | |||
| 40 | comment "RTC interfaces" | ||
| 41 | depends on RTC_CLASS | ||
| 42 | |||
| 43 | config RTC_INTF_SYSFS | ||
| 44 | tristate "sysfs" | ||
| 45 | depends on RTC_CLASS && SYSFS | ||
| 46 | default RTC_CLASS | ||
| 47 | help | ||
| 48 | Say yes here if you want to use your RTC using the sysfs | ||
| 49 | interface, /sys/class/rtc/rtcX . | ||
| 50 | |||
| 51 | This driver can also be built as a module. If so, the module | ||
| 52 | will be called rtc-sysfs. | ||
| 53 | |||
| 54 | config RTC_INTF_PROC | ||
| 55 | tristate "proc" | ||
| 56 | depends on RTC_CLASS && PROC_FS | ||
| 57 | default RTC_CLASS | ||
| 58 | help | ||
| 59 | Say yes here if you want to use your RTC using the proc | ||
| 60 | interface, /proc/driver/rtc . | ||
| 61 | |||
| 62 | This driver can also be built as a module. If so, the module | ||
| 63 | will be called rtc-proc. | ||
| 64 | |||
| 65 | config RTC_INTF_DEV | ||
| 66 | tristate "dev" | ||
| 67 | depends on RTC_CLASS | ||
| 68 | default RTC_CLASS | ||
| 69 | help | ||
| 70 | Say yes here if you want to use your RTC using the dev | ||
| 71 | interface, /dev/rtc . | ||
| 72 | |||
| 73 | This driver can also be built as a module. If so, the module | ||
| 74 | will be called rtc-dev. | ||
| 75 | |||
| 76 | comment "RTC drivers" | ||
| 77 | depends on RTC_CLASS | ||
| 78 | |||
| 79 | config RTC_DRV_X1205 | ||
| 80 | tristate "Xicor/Intersil X1205" | ||
| 81 | depends on RTC_CLASS && I2C | ||
| 82 | help | ||
| 83 | If you say yes here you get support for the | ||
| 84 | Xicor/Intersil X1205 RTC chip. | ||
| 85 | |||
| 86 | This driver can also be built as a module. If so, the module | ||
| 87 | will be called rtc-x1205. | ||
| 88 | |||
| 89 | config RTC_DRV_DS1672 | ||
| 90 | tristate "Dallas/Maxim DS1672" | ||
| 91 | depends on RTC_CLASS && I2C | ||
| 92 | help | ||
| 93 | If you say yes here you get support for the | ||
| 94 | Dallas/Maxim DS1672 timekeeping chip. | ||
| 95 | |||
| 96 | This driver can also be built as a module. If so, the module | ||
| 97 | will be called rtc-ds1672. | ||
| 98 | |||
| 99 | config RTC_DRV_PCF8563 | ||
| 100 | tristate "Philips PCF8563/Epson RTC8564" | ||
| 101 | depends on RTC_CLASS && I2C | ||
| 102 | help | ||
| 103 | If you say yes here you get support for the | ||
| 104 | Philips PCF8563 RTC chip. The Epson RTC8564 | ||
| 105 | should work as well. | ||
| 106 | |||
| 107 | This driver can also be built as a module. If so, the module | ||
| 108 | will be called rtc-pcf8563. | ||
| 109 | |||
| 110 | config RTC_DRV_RS5C372 | ||
| 111 | tristate "Ricoh RS5C372A/B" | ||
| 112 | depends on RTC_CLASS && I2C | ||
| 113 | help | ||
| 114 | If you say yes here you get support for the | ||
| 115 | Ricoh RS5C372A and RS5C372B RTC chips. | ||
| 116 | |||
| 117 | This driver can also be built as a module. If so, the module | ||
| 118 | will be called rtc-rs5c372. | ||
| 119 | |||
| 120 | config RTC_DRV_M48T86 | ||
| 121 | tristate "ST M48T86/Dallas DS12887" | ||
| 122 | depends on RTC_CLASS | ||
| 123 | help | ||
| 124 | If you say Y here you will get support for the | ||
| 125 | ST M48T86 and Dallas DS12887 RTC chips. | ||
| 126 | |||
| 127 | This driver can also be built as a module. If so, the module | ||
| 128 | will be called rtc-m48t86. | ||
| 129 | |||
| 130 | config RTC_DRV_EP93XX | ||
| 131 | tristate "Cirrus Logic EP93XX" | ||
| 132 | depends on RTC_CLASS && ARCH_EP93XX | ||
| 133 | help | ||
| 134 | If you say yes here you get support for the | ||
| 135 | RTC embedded in the Cirrus Logic EP93XX processors. | ||
| 136 | |||
| 137 | This driver can also be built as a module. If so, the module | ||
| 138 | will be called rtc-ep93xx. | ||
| 139 | |||
| 140 | config RTC_DRV_SA1100 | ||
| 141 | tristate "SA11x0/PXA2xx" | ||
| 142 | depends on RTC_CLASS && (ARCH_SA1100 || ARCH_PXA) | ||
| 143 | help | ||
| 144 | If you say Y here you will get access to the real time clock | ||
| 145 | built into your SA11x0 or PXA2xx CPU. | ||
| 146 | |||
| 147 | To compile this driver as a module, choose M here: the | ||
| 148 | module will be called rtc-sa1100. | ||
| 149 | |||
| 150 | config RTC_DRV_TEST | ||
| 151 | tristate "Test driver/device" | ||
| 152 | depends on RTC_CLASS | ||
| 153 | help | ||
| 154 | If you say yes here you get support for the | ||
| 155 | RTC test driver. It's a software RTC which can be | ||
| 156 | used to test the RTC subsystem APIs. It gets | ||
| 157 | the time from the system clock. | ||
| 158 | You want this driver only if you are doing development | ||
| 159 | on the RTC subsystem. Please read the source code | ||
| 160 | for further details. | ||
| 161 | |||
| 162 | This driver can also be built as a module. If so, the module | ||
| 163 | will be called rtc-test. | ||
| 164 | |||
| 165 | endmenu | ||
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile new file mode 100644 index 000000000000..8d4c7fe88d58 --- /dev/null +++ b/drivers/rtc/Makefile | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | # | ||
| 2 | # Makefile for RTC class/drivers. | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_RTC_LIB) += rtc-lib.o | ||
| 6 | obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o | ||
| 7 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o | ||
| 8 | rtc-core-y := class.o interface.o | ||
| 9 | |||
| 10 | obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | ||
| 11 | obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o | ||
| 12 | obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o | ||
| 13 | |||
| 14 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | ||
| 15 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | ||
| 16 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | ||
| 17 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | ||
| 18 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | ||
| 19 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | ||
| 20 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | ||
| 21 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o | ||
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c new file mode 100644 index 000000000000..8533936d50d8 --- /dev/null +++ b/drivers/rtc/class.c | |||
| @@ -0,0 +1,145 @@ | |||
| 1 | /* | ||
| 2 | * RTC subsystem, base class | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Tower Technologies | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * class skeleton from drivers/hwmon/hwmon.c | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/rtc.h> | ||
| 16 | #include <linux/kdev_t.h> | ||
| 17 | #include <linux/idr.h> | ||
| 18 | |||
| 19 | static DEFINE_IDR(rtc_idr); | ||
| 20 | static DEFINE_MUTEX(idr_lock); | ||
| 21 | struct class *rtc_class; | ||
| 22 | |||
| 23 | static void rtc_device_release(struct class_device *class_dev) | ||
| 24 | { | ||
| 25 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 26 | mutex_lock(&idr_lock); | ||
| 27 | idr_remove(&rtc_idr, rtc->id); | ||
| 28 | mutex_unlock(&idr_lock); | ||
| 29 | kfree(rtc); | ||
| 30 | } | ||
| 31 | |||
| 32 | /** | ||
| 33 | * rtc_device_register - register w/ RTC class | ||
| 34 | * @dev: the device to register | ||
| 35 | * | ||
| 36 | * rtc_device_unregister() must be called when the class device is no | ||
| 37 | * longer needed. | ||
| 38 | * | ||
| 39 | * Returns the pointer to the new struct class device. | ||
| 40 | */ | ||
| 41 | struct rtc_device *rtc_device_register(const char *name, struct device *dev, | ||
| 42 | struct rtc_class_ops *ops, | ||
| 43 | struct module *owner) | ||
| 44 | { | ||
| 45 | struct rtc_device *rtc; | ||
| 46 | int id, err; | ||
| 47 | |||
| 48 | if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) { | ||
| 49 | err = -ENOMEM; | ||
| 50 | goto exit; | ||
| 51 | } | ||
| 52 | |||
| 53 | |||
| 54 | mutex_lock(&idr_lock); | ||
| 55 | err = idr_get_new(&rtc_idr, NULL, &id); | ||
| 56 | mutex_unlock(&idr_lock); | ||
| 57 | |||
| 58 | if (err < 0) | ||
| 59 | goto exit; | ||
| 60 | |||
| 61 | id = id & MAX_ID_MASK; | ||
| 62 | |||
| 63 | rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL); | ||
| 64 | if (rtc == NULL) { | ||
| 65 | err = -ENOMEM; | ||
| 66 | goto exit_idr; | ||
| 67 | } | ||
| 68 | |||
| 69 | rtc->id = id; | ||
| 70 | rtc->ops = ops; | ||
| 71 | rtc->owner = owner; | ||
| 72 | rtc->class_dev.dev = dev; | ||
| 73 | rtc->class_dev.class = rtc_class; | ||
| 74 | rtc->class_dev.release = rtc_device_release; | ||
| 75 | |||
| 76 | mutex_init(&rtc->ops_lock); | ||
| 77 | spin_lock_init(&rtc->irq_lock); | ||
| 78 | spin_lock_init(&rtc->irq_task_lock); | ||
| 79 | |||
| 80 | strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE); | ||
| 81 | snprintf(rtc->class_dev.class_id, BUS_ID_SIZE, "rtc%d", id); | ||
| 82 | |||
| 83 | err = class_device_register(&rtc->class_dev); | ||
| 84 | if (err) | ||
| 85 | goto exit_kfree; | ||
| 86 | |||
| 87 | dev_info(dev, "rtc core: registered %s as %s\n", | ||
| 88 | rtc->name, rtc->class_dev.class_id); | ||
| 89 | |||
| 90 | return rtc; | ||
| 91 | |||
| 92 | exit_kfree: | ||
| 93 | kfree(rtc); | ||
| 94 | |||
| 95 | exit_idr: | ||
| 96 | idr_remove(&rtc_idr, id); | ||
| 97 | |||
| 98 | exit: | ||
| 99 | return ERR_PTR(err); | ||
| 100 | } | ||
| 101 | EXPORT_SYMBOL_GPL(rtc_device_register); | ||
| 102 | |||
| 103 | |||
| 104 | /** | ||
| 105 | * rtc_device_unregister - removes the previously registered RTC class device | ||
| 106 | * | ||
| 107 | * @rtc: the RTC class device to destroy | ||
| 108 | */ | ||
| 109 | void rtc_device_unregister(struct rtc_device *rtc) | ||
| 110 | { | ||
| 111 | mutex_lock(&rtc->ops_lock); | ||
| 112 | rtc->ops = NULL; | ||
| 113 | mutex_unlock(&rtc->ops_lock); | ||
| 114 | class_device_unregister(&rtc->class_dev); | ||
| 115 | } | ||
| 116 | EXPORT_SYMBOL_GPL(rtc_device_unregister); | ||
| 117 | |||
| 118 | int rtc_interface_register(struct class_interface *intf) | ||
| 119 | { | ||
| 120 | intf->class = rtc_class; | ||
| 121 | return class_interface_register(intf); | ||
| 122 | } | ||
| 123 | EXPORT_SYMBOL_GPL(rtc_interface_register); | ||
| 124 | |||
| 125 | static int __init rtc_init(void) | ||
| 126 | { | ||
| 127 | rtc_class = class_create(THIS_MODULE, "rtc"); | ||
| 128 | if (IS_ERR(rtc_class)) { | ||
| 129 | printk(KERN_ERR "%s: couldn't create class\n", __FILE__); | ||
| 130 | return PTR_ERR(rtc_class); | ||
| 131 | } | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | static void __exit rtc_exit(void) | ||
| 136 | { | ||
| 137 | class_destroy(rtc_class); | ||
| 138 | } | ||
| 139 | |||
| 140 | module_init(rtc_init); | ||
| 141 | module_exit(rtc_exit); | ||
| 142 | |||
| 143 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towerteh.it>"); | ||
| 144 | MODULE_DESCRIPTION("RTC class support"); | ||
| 145 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c new file mode 100644 index 000000000000..d02fe9a0001f --- /dev/null +++ b/drivers/rtc/hctosys.c | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | /* | ||
| 2 | * RTC subsystem, initialize system time on startup | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Tower Technologies | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/rtc.h> | ||
| 13 | |||
| 14 | /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary | ||
| 15 | * whether it stores the most close value or the value with partial | ||
| 16 | * seconds truncated. However, it is important that we use it to store | ||
| 17 | * the truncated value. This is because otherwise it is necessary, | ||
| 18 | * in an rtc sync function, to read both xtime.tv_sec and | ||
| 19 | * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read | ||
| 20 | * of >32bits is not possible. So storing the most close value would | ||
| 21 | * slow down the sync API. So here we have the truncated value and | ||
| 22 | * the best guess is to add 0.5s. | ||
| 23 | */ | ||
| 24 | |||
| 25 | static int __init rtc_hctosys(void) | ||
| 26 | { | ||
| 27 | int err; | ||
| 28 | struct rtc_time tm; | ||
| 29 | struct class_device *class_dev = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); | ||
| 30 | |||
| 31 | if (class_dev == NULL) { | ||
| 32 | printk("%s: unable to open rtc device (%s)\n", | ||
| 33 | __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); | ||
| 34 | return -ENODEV; | ||
| 35 | } | ||
| 36 | |||
| 37 | err = rtc_read_time(class_dev, &tm); | ||
| 38 | if (err == 0) { | ||
| 39 | err = rtc_valid_tm(&tm); | ||
| 40 | if (err == 0) { | ||
| 41 | struct timespec tv; | ||
| 42 | |||
| 43 | tv.tv_nsec = NSEC_PER_SEC >> 1; | ||
| 44 | |||
| 45 | rtc_tm_to_time(&tm, &tv.tv_sec); | ||
| 46 | |||
| 47 | do_settimeofday(&tv); | ||
| 48 | |||
| 49 | dev_info(class_dev->dev, | ||
| 50 | "setting the system clock to " | ||
| 51 | "%d-%02d-%02d %02d:%02d:%02d (%u)\n", | ||
| 52 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | ||
| 53 | tm.tm_hour, tm.tm_min, tm.tm_sec, | ||
| 54 | (unsigned int) tv.tv_sec); | ||
| 55 | } | ||
| 56 | else | ||
| 57 | dev_err(class_dev->dev, | ||
| 58 | "hctosys: invalid date/time\n"); | ||
| 59 | } | ||
| 60 | else | ||
| 61 | dev_err(class_dev->dev, | ||
| 62 | "hctosys: unable to read the hardware clock\n"); | ||
| 63 | |||
| 64 | rtc_class_close(class_dev); | ||
| 65 | |||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | late_initcall(rtc_hctosys); | ||
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c new file mode 100644 index 000000000000..56e490709b87 --- /dev/null +++ b/drivers/rtc/interface.c | |||
| @@ -0,0 +1,277 @@ | |||
| 1 | /* | ||
| 2 | * RTC subsystem, interface functions | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Tower Technologies | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * based on arch/arm/common/rtctime.c | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/rtc.h> | ||
| 15 | |||
| 16 | int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm) | ||
| 17 | { | ||
| 18 | int err; | ||
| 19 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 20 | |||
| 21 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
| 22 | if (err) | ||
| 23 | return -EBUSY; | ||
| 24 | |||
| 25 | if (!rtc->ops) | ||
| 26 | err = -ENODEV; | ||
| 27 | else if (!rtc->ops->read_time) | ||
| 28 | err = -EINVAL; | ||
| 29 | else { | ||
| 30 | memset(tm, 0, sizeof(struct rtc_time)); | ||
| 31 | err = rtc->ops->read_time(class_dev->dev, tm); | ||
| 32 | } | ||
| 33 | |||
| 34 | mutex_unlock(&rtc->ops_lock); | ||
| 35 | return err; | ||
| 36 | } | ||
| 37 | EXPORT_SYMBOL_GPL(rtc_read_time); | ||
| 38 | |||
| 39 | int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm) | ||
| 40 | { | ||
| 41 | int err; | ||
| 42 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 43 | |||
| 44 | err = rtc_valid_tm(tm); | ||
| 45 | if (err != 0) | ||
| 46 | return err; | ||
| 47 | |||
| 48 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
| 49 | if (err) | ||
| 50 | return -EBUSY; | ||
| 51 | |||
| 52 | if (!rtc->ops) | ||
| 53 | err = -ENODEV; | ||
| 54 | else if (!rtc->ops->set_time) | ||
| 55 | err = -EINVAL; | ||
| 56 | else | ||
| 57 | err = rtc->ops->set_time(class_dev->dev, tm); | ||
| 58 | |||
| 59 | mutex_unlock(&rtc->ops_lock); | ||
| 60 | return err; | ||
| 61 | } | ||
| 62 | EXPORT_SYMBOL_GPL(rtc_set_time); | ||
| 63 | |||
| 64 | int rtc_set_mmss(struct class_device *class_dev, unsigned long secs) | ||
| 65 | { | ||
| 66 | int err; | ||
| 67 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 68 | |||
| 69 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
| 70 | if (err) | ||
| 71 | return -EBUSY; | ||
| 72 | |||
| 73 | if (!rtc->ops) | ||
| 74 | err = -ENODEV; | ||
| 75 | else if (rtc->ops->set_mmss) | ||
| 76 | err = rtc->ops->set_mmss(class_dev->dev, secs); | ||
| 77 | else if (rtc->ops->read_time && rtc->ops->set_time) { | ||
| 78 | struct rtc_time new, old; | ||
| 79 | |||
| 80 | err = rtc->ops->read_time(class_dev->dev, &old); | ||
| 81 | if (err == 0) { | ||
| 82 | rtc_time_to_tm(secs, &new); | ||
| 83 | |||
| 84 | /* | ||
| 85 | * avoid writing when we're going to change the day of | ||
| 86 | * the month. We will retry in the next minute. This | ||
| 87 | * basically means that if the RTC must not drift | ||
| 88 | * by more than 1 minute in 11 minutes. | ||
| 89 | */ | ||
| 90 | if (!((old.tm_hour == 23 && old.tm_min == 59) || | ||
| 91 | (new.tm_hour == 23 && new.tm_min == 59))) | ||
| 92 | err = rtc->ops->set_time(class_dev->dev, &new); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | else | ||
| 96 | err = -EINVAL; | ||
| 97 | |||
| 98 | mutex_unlock(&rtc->ops_lock); | ||
| 99 | |||
| 100 | return err; | ||
| 101 | } | ||
| 102 | EXPORT_SYMBOL_GPL(rtc_set_mmss); | ||
| 103 | |||
| 104 | int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) | ||
| 105 | { | ||
| 106 | int err; | ||
| 107 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 108 | |||
| 109 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
| 110 | if (err) | ||
| 111 | return -EBUSY; | ||
| 112 | |||
| 113 | if (rtc->ops == NULL) | ||
| 114 | err = -ENODEV; | ||
| 115 | else if (!rtc->ops->read_alarm) | ||
| 116 | err = -EINVAL; | ||
| 117 | else { | ||
| 118 | memset(alarm, 0, sizeof(struct rtc_wkalrm)); | ||
| 119 | err = rtc->ops->read_alarm(class_dev->dev, alarm); | ||
| 120 | } | ||
| 121 | |||
| 122 | mutex_unlock(&rtc->ops_lock); | ||
| 123 | return err; | ||
| 124 | } | ||
| 125 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | ||
| 126 | |||
| 127 | int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) | ||
| 128 | { | ||
| 129 | int err; | ||
| 130 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 131 | |||
| 132 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
| 133 | if (err) | ||
| 134 | return -EBUSY; | ||
| 135 | |||
| 136 | if (!rtc->ops) | ||
| 137 | err = -ENODEV; | ||
| 138 | else if (!rtc->ops->set_alarm) | ||
| 139 | err = -EINVAL; | ||
| 140 | else | ||
| 141 | err = rtc->ops->set_alarm(class_dev->dev, alarm); | ||
| 142 | |||
| 143 | mutex_unlock(&rtc->ops_lock); | ||
| 144 | return err; | ||
| 145 | } | ||
| 146 | EXPORT_SYMBOL_GPL(rtc_set_alarm); | ||
| 147 | |||
| 148 | void rtc_update_irq(struct class_device *class_dev, | ||
| 149 | unsigned long num, unsigned long events) | ||
| 150 | { | ||
| 151 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 152 | |||
| 153 | spin_lock(&rtc->irq_lock); | ||
| 154 | rtc->irq_data = (rtc->irq_data + (num << 8)) | events; | ||
| 155 | spin_unlock(&rtc->irq_lock); | ||
| 156 | |||
| 157 | spin_lock(&rtc->irq_task_lock); | ||
| 158 | if (rtc->irq_task) | ||
| 159 | rtc->irq_task->func(rtc->irq_task->private_data); | ||
| 160 | spin_unlock(&rtc->irq_task_lock); | ||
| 161 | |||
| 162 | wake_up_interruptible(&rtc->irq_queue); | ||
| 163 | kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); | ||
| 164 | } | ||
| 165 | EXPORT_SYMBOL_GPL(rtc_update_irq); | ||
| 166 | |||
| 167 | struct class_device *rtc_class_open(char *name) | ||
| 168 | { | ||
| 169 | struct class_device *class_dev = NULL, | ||
| 170 | *class_dev_tmp; | ||
| 171 | |||
| 172 | down(&rtc_class->sem); | ||
| 173 | list_for_each_entry(class_dev_tmp, &rtc_class->children, node) { | ||
| 174 | if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) { | ||
| 175 | class_dev = class_dev_tmp; | ||
| 176 | break; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | if (class_dev) { | ||
| 181 | if (!try_module_get(to_rtc_device(class_dev)->owner)) | ||
| 182 | class_dev = NULL; | ||
| 183 | } | ||
| 184 | up(&rtc_class->sem); | ||
| 185 | |||
| 186 | return class_dev; | ||
| 187 | } | ||
| 188 | EXPORT_SYMBOL_GPL(rtc_class_open); | ||
| 189 | |||
| 190 | void rtc_class_close(struct class_device *class_dev) | ||
| 191 | { | ||
| 192 | module_put(to_rtc_device(class_dev)->owner); | ||
| 193 | } | ||
| 194 | EXPORT_SYMBOL_GPL(rtc_class_close); | ||
| 195 | |||
| 196 | int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task) | ||
| 197 | { | ||
| 198 | int retval = -EBUSY; | ||
| 199 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 200 | |||
| 201 | if (task == NULL || task->func == NULL) | ||
| 202 | return -EINVAL; | ||
| 203 | |||
| 204 | spin_lock(&rtc->irq_task_lock); | ||
| 205 | if (rtc->irq_task == NULL) { | ||
| 206 | rtc->irq_task = task; | ||
| 207 | retval = 0; | ||
| 208 | } | ||
| 209 | spin_unlock(&rtc->irq_task_lock); | ||
| 210 | |||
| 211 | return retval; | ||
| 212 | } | ||
| 213 | EXPORT_SYMBOL_GPL(rtc_irq_register); | ||
| 214 | |||
| 215 | void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task) | ||
| 216 | { | ||
| 217 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 218 | |||
| 219 | spin_lock(&rtc->irq_task_lock); | ||
| 220 | if (rtc->irq_task == task) | ||
| 221 | rtc->irq_task = NULL; | ||
| 222 | spin_unlock(&rtc->irq_task_lock); | ||
| 223 | } | ||
| 224 | EXPORT_SYMBOL_GPL(rtc_irq_unregister); | ||
| 225 | |||
| 226 | int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int enabled) | ||
| 227 | { | ||
| 228 | int err = 0; | ||
| 229 | unsigned long flags; | ||
| 230 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 231 | |||
| 232 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | ||
| 233 | if (rtc->irq_task != task) | ||
| 234 | err = -ENXIO; | ||
| 235 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
| 236 | |||
| 237 | if (err == 0) | ||
| 238 | err = rtc->ops->irq_set_state(class_dev->dev, enabled); | ||
| 239 | |||
| 240 | return err; | ||
| 241 | } | ||
| 242 | EXPORT_SYMBOL_GPL(rtc_irq_set_state); | ||
| 243 | |||
| 244 | int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq) | ||
| 245 | { | ||
| 246 | int err = 0, tmp = 0; | ||
| 247 | unsigned long flags; | ||
| 248 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 249 | |||
| 250 | /* allowed range is 2-8192 */ | ||
| 251 | if (freq < 2 || freq > 8192) | ||
| 252 | return -EINVAL; | ||
| 253 | /* | ||
| 254 | FIXME: this does not belong here, will move where appropriate | ||
| 255 | at a later stage. It cannot hurt right now, trust me :) | ||
| 256 | if ((freq > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE))) | ||
| 257 | return -EACCES; | ||
| 258 | */ | ||
| 259 | /* check if freq is a power of 2 */ | ||
| 260 | while (freq > (1 << tmp)) | ||
| 261 | tmp++; | ||
| 262 | |||
| 263 | if (freq != (1 << tmp)) | ||
| 264 | return -EINVAL; | ||
| 265 | |||
| 266 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | ||
| 267 | if (rtc->irq_task != task) | ||
| 268 | err = -ENXIO; | ||
| 269 | spin_unlock_irqrestore(&rtc->irq_task_lock, flags); | ||
| 270 | |||
| 271 | if (err == 0) { | ||
| 272 | err = rtc->ops->irq_set_freq(class_dev->dev, freq); | ||
| 273 | if (err == 0) | ||
| 274 | rtc->irq_freq = freq; | ||
| 275 | } | ||
| 276 | return err; | ||
| 277 | } | ||
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c new file mode 100644 index 000000000000..b1e3e6179e56 --- /dev/null +++ b/drivers/rtc/rtc-dev.c | |||
| @@ -0,0 +1,382 @@ | |||
| 1 | /* | ||
| 2 | * RTC subsystem, dev interface | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Tower Technologies | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * based on arch/arm/common/rtctime.c | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/rtc.h> | ||
| 16 | |||
| 17 | static struct class *rtc_dev_class; | ||
| 18 | static dev_t rtc_devt; | ||
| 19 | |||
| 20 | #define RTC_DEV_MAX 16 /* 16 RTCs should be enough for everyone... */ | ||
| 21 | |||
| 22 | static int rtc_dev_open(struct inode *inode, struct file *file) | ||
| 23 | { | ||
| 24 | int err; | ||
| 25 | struct rtc_device *rtc = container_of(inode->i_cdev, | ||
| 26 | struct rtc_device, char_dev); | ||
| 27 | struct rtc_class_ops *ops = rtc->ops; | ||
| 28 | |||
| 29 | /* We keep the lock as long as the device is in use | ||
| 30 | * and return immediately if busy | ||
| 31 | */ | ||
| 32 | if (!(mutex_trylock(&rtc->char_lock))) | ||
| 33 | return -EBUSY; | ||
| 34 | |||
| 35 | file->private_data = &rtc->class_dev; | ||
| 36 | |||
| 37 | err = ops->open ? ops->open(rtc->class_dev.dev) : 0; | ||
| 38 | if (err == 0) { | ||
| 39 | spin_lock_irq(&rtc->irq_lock); | ||
| 40 | rtc->irq_data = 0; | ||
| 41 | spin_unlock_irq(&rtc->irq_lock); | ||
| 42 | |||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | /* something has gone wrong, release the lock */ | ||
| 47 | mutex_unlock(&rtc->char_lock); | ||
| 48 | return err; | ||
| 49 | } | ||
| 50 | |||
| 51 | |||
| 52 | static ssize_t | ||
| 53 | rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | ||
| 54 | { | ||
| 55 | struct rtc_device *rtc = to_rtc_device(file->private_data); | ||
| 56 | |||
| 57 | DECLARE_WAITQUEUE(wait, current); | ||
| 58 | unsigned long data; | ||
| 59 | ssize_t ret; | ||
| 60 | |||
| 61 | if (count < sizeof(unsigned long)) | ||
| 62 | return -EINVAL; | ||
| 63 | |||
| 64 | add_wait_queue(&rtc->irq_queue, &wait); | ||
| 65 | do { | ||
| 66 | __set_current_state(TASK_INTERRUPTIBLE); | ||
| 67 | |||
| 68 | spin_lock_irq(&rtc->irq_lock); | ||
| 69 | data = rtc->irq_data; | ||
| 70 | rtc->irq_data = 0; | ||
| 71 | spin_unlock_irq(&rtc->irq_lock); | ||
| 72 | |||
| 73 | if (data != 0) { | ||
| 74 | ret = 0; | ||
| 75 | break; | ||
| 76 | } | ||
| 77 | if (file->f_flags & O_NONBLOCK) { | ||
| 78 | ret = -EAGAIN; | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | if (signal_pending(current)) { | ||
| 82 | ret = -ERESTARTSYS; | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | schedule(); | ||
| 86 | } while (1); | ||
| 87 | set_current_state(TASK_RUNNING); | ||
| 88 | remove_wait_queue(&rtc->irq_queue, &wait); | ||
| 89 | |||
| 90 | if (ret == 0) { | ||
| 91 | /* Check for any data updates */ | ||
| 92 | if (rtc->ops->read_callback) | ||
| 93 | data = rtc->ops->read_callback(rtc->class_dev.dev, data); | ||
| 94 | |||
| 95 | ret = put_user(data, (unsigned long __user *)buf); | ||
| 96 | if (ret == 0) | ||
| 97 | ret = sizeof(unsigned long); | ||
| 98 | } | ||
| 99 | return ret; | ||
| 100 | } | ||
| 101 | |||
| 102 | static unsigned int rtc_dev_poll(struct file *file, poll_table *wait) | ||
| 103 | { | ||
| 104 | struct rtc_device *rtc = to_rtc_device(file->private_data); | ||
| 105 | unsigned long data; | ||
| 106 | |||
| 107 | poll_wait(file, &rtc->irq_queue, wait); | ||
| 108 | |||
| 109 | data = rtc->irq_data; | ||
| 110 | |||
| 111 | return (data != 0) ? (POLLIN | POLLRDNORM) : 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static int rtc_dev_ioctl(struct inode *inode, struct file *file, | ||
| 115 | unsigned int cmd, unsigned long arg) | ||
| 116 | { | ||
| 117 | int err = 0; | ||
| 118 | struct class_device *class_dev = file->private_data; | ||
| 119 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 120 | struct rtc_class_ops *ops = rtc->ops; | ||
| 121 | struct rtc_time tm; | ||
| 122 | struct rtc_wkalrm alarm; | ||
| 123 | void __user *uarg = (void __user *) arg; | ||
| 124 | |||
| 125 | /* avoid conflicting IRQ users */ | ||
| 126 | if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) { | ||
| 127 | spin_lock(&rtc->irq_task_lock); | ||
| 128 | if (rtc->irq_task) | ||
| 129 | err = -EBUSY; | ||
| 130 | spin_unlock(&rtc->irq_task_lock); | ||
| 131 | |||
| 132 | if (err < 0) | ||
| 133 | return err; | ||
| 134 | } | ||
| 135 | |||
| 136 | /* try the driver's ioctl interface */ | ||
| 137 | if (ops->ioctl) { | ||
| 138 | err = ops->ioctl(class_dev->dev, cmd, arg); | ||
| 139 | if (err != -EINVAL) | ||
| 140 | return err; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* if the driver does not provide the ioctl interface | ||
| 144 | * or if that particular ioctl was not implemented | ||
| 145 | * (-EINVAL), we will try to emulate here. | ||
| 146 | */ | ||
| 147 | |||
| 148 | switch (cmd) { | ||
| 149 | case RTC_ALM_READ: | ||
| 150 | err = rtc_read_alarm(class_dev, &alarm); | ||
| 151 | if (err < 0) | ||
| 152 | return err; | ||
| 153 | |||
| 154 | if (copy_to_user(uarg, &alarm.time, sizeof(tm))) | ||
| 155 | return -EFAULT; | ||
| 156 | break; | ||
| 157 | |||
| 158 | case RTC_ALM_SET: | ||
| 159 | if (copy_from_user(&alarm.time, uarg, sizeof(tm))) | ||
| 160 | return -EFAULT; | ||
| 161 | |||
| 162 | alarm.enabled = 0; | ||
| 163 | alarm.pending = 0; | ||
| 164 | alarm.time.tm_mday = -1; | ||
| 165 | alarm.time.tm_mon = -1; | ||
| 166 | alarm.time.tm_year = -1; | ||
| 167 | alarm.time.tm_wday = -1; | ||
| 168 | alarm.time.tm_yday = -1; | ||
| 169 | alarm.time.tm_isdst = -1; | ||
| 170 | err = rtc_set_alarm(class_dev, &alarm); | ||
| 171 | break; | ||
| 172 | |||
| 173 | case RTC_RD_TIME: | ||
| 174 | err = rtc_read_time(class_dev, &tm); | ||
| 175 | if (err < 0) | ||
| 176 | return err; | ||
| 177 | |||
| 178 | if (copy_to_user(uarg, &tm, sizeof(tm))) | ||
| 179 | return -EFAULT; | ||
| 180 | break; | ||
| 181 | |||
| 182 | case RTC_SET_TIME: | ||
| 183 | if (!capable(CAP_SYS_TIME)) | ||
| 184 | return -EACCES; | ||
| 185 | |||
| 186 | if (copy_from_user(&tm, uarg, sizeof(tm))) | ||
| 187 | return -EFAULT; | ||
| 188 | |||
| 189 | err = rtc_set_time(class_dev, &tm); | ||
| 190 | break; | ||
| 191 | #if 0 | ||
| 192 | case RTC_EPOCH_SET: | ||
| 193 | #ifndef rtc_epoch | ||
| 194 | /* | ||
| 195 | * There were no RTC clocks before 1900. | ||
| 196 | */ | ||
| 197 | if (arg < 1900) { | ||
| 198 | err = -EINVAL; | ||
| 199 | break; | ||
| 200 | } | ||
| 201 | if (!capable(CAP_SYS_TIME)) { | ||
| 202 | err = -EACCES; | ||
| 203 | break; | ||
| 204 | } | ||
| 205 | rtc_epoch = arg; | ||
| 206 | err = 0; | ||
| 207 | #endif | ||
| 208 | break; | ||
| 209 | |||
| 210 | case RTC_EPOCH_READ: | ||
| 211 | err = put_user(rtc_epoch, (unsigned long __user *)uarg); | ||
| 212 | break; | ||
| 213 | #endif | ||
| 214 | case RTC_WKALM_SET: | ||
| 215 | if (copy_from_user(&alarm, uarg, sizeof(alarm))) | ||
| 216 | return -EFAULT; | ||
| 217 | |||
| 218 | err = rtc_set_alarm(class_dev, &alarm); | ||
| 219 | break; | ||
| 220 | |||
| 221 | case RTC_WKALM_RD: | ||
| 222 | err = rtc_read_alarm(class_dev, &alarm); | ||
| 223 | if (err < 0) | ||
| 224 | return err; | ||
| 225 | |||
| 226 | if (copy_to_user(uarg, &alarm, sizeof(alarm))) | ||
| 227 | return -EFAULT; | ||
| 228 | break; | ||
| 229 | |||
| 230 | default: | ||
| 231 | err = -EINVAL; | ||
| 232 | break; | ||
| 233 | } | ||
| 234 | |||
| 235 | return err; | ||
| 236 | } | ||
| 237 | |||
| 238 | static int rtc_dev_release(struct inode *inode, struct file *file) | ||
| 239 | { | ||
| 240 | struct rtc_device *rtc = to_rtc_device(file->private_data); | ||
| 241 | |||
| 242 | if (rtc->ops->release) | ||
| 243 | rtc->ops->release(rtc->class_dev.dev); | ||
| 244 | |||
| 245 | mutex_unlock(&rtc->char_lock); | ||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | |||
| 249 | static int rtc_dev_fasync(int fd, struct file *file, int on) | ||
| 250 | { | ||
| 251 | struct rtc_device *rtc = to_rtc_device(file->private_data); | ||
| 252 | return fasync_helper(fd, file, on, &rtc->async_queue); | ||
| 253 | } | ||
| 254 | |||
| 255 | static struct file_operations rtc_dev_fops = { | ||
| 256 | .owner = THIS_MODULE, | ||
| 257 | .llseek = no_llseek, | ||
| 258 | .read = rtc_dev_read, | ||
| 259 | .poll = rtc_dev_poll, | ||
| 260 | .ioctl = rtc_dev_ioctl, | ||
| 261 | .open = rtc_dev_open, | ||
| 262 | .release = rtc_dev_release, | ||
| 263 | .fasync = rtc_dev_fasync, | ||
| 264 | }; | ||
| 265 | |||
| 266 | /* insertion/removal hooks */ | ||
| 267 | |||
| 268 | static int rtc_dev_add_device(struct class_device *class_dev, | ||
| 269 | struct class_interface *class_intf) | ||
| 270 | { | ||
| 271 | int err = 0; | ||
| 272 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 273 | |||
| 274 | if (rtc->id >= RTC_DEV_MAX) { | ||
| 275 | dev_err(class_dev->dev, "too many RTCs\n"); | ||
| 276 | return -EINVAL; | ||
| 277 | } | ||
| 278 | |||
| 279 | mutex_init(&rtc->char_lock); | ||
| 280 | spin_lock_init(&rtc->irq_lock); | ||
| 281 | init_waitqueue_head(&rtc->irq_queue); | ||
| 282 | |||
| 283 | cdev_init(&rtc->char_dev, &rtc_dev_fops); | ||
| 284 | rtc->char_dev.owner = rtc->owner; | ||
| 285 | |||
| 286 | if (cdev_add(&rtc->char_dev, MKDEV(MAJOR(rtc_devt), rtc->id), 1)) { | ||
| 287 | cdev_del(&rtc->char_dev); | ||
| 288 | dev_err(class_dev->dev, | ||
| 289 | "failed to add char device %d:%d\n", | ||
| 290 | MAJOR(rtc_devt), rtc->id); | ||
| 291 | return -ENODEV; | ||
| 292 | } | ||
| 293 | |||
| 294 | rtc->rtc_dev = class_device_create(rtc_dev_class, NULL, | ||
| 295 | MKDEV(MAJOR(rtc_devt), rtc->id), | ||
| 296 | class_dev->dev, "rtc%d", rtc->id); | ||
| 297 | if (IS_ERR(rtc->rtc_dev)) { | ||
| 298 | dev_err(class_dev->dev, "cannot create rtc_dev device\n"); | ||
| 299 | err = PTR_ERR(rtc->rtc_dev); | ||
| 300 | goto err_cdev_del; | ||
| 301 | } | ||
| 302 | |||
| 303 | dev_info(class_dev->dev, "rtc intf: dev (%d:%d)\n", | ||
| 304 | MAJOR(rtc->rtc_dev->devt), | ||
| 305 | MINOR(rtc->rtc_dev->devt)); | ||
| 306 | |||
| 307 | return 0; | ||
| 308 | |||
| 309 | err_cdev_del: | ||
| 310 | |||
| 311 | cdev_del(&rtc->char_dev); | ||
| 312 | return err; | ||
| 313 | } | ||
| 314 | |||
| 315 | static void rtc_dev_remove_device(struct class_device *class_dev, | ||
| 316 | struct class_interface *class_intf) | ||
| 317 | { | ||
| 318 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 319 | |||
| 320 | if (rtc->rtc_dev) { | ||
| 321 | dev_dbg(class_dev->dev, "removing char %d:%d\n", | ||
| 322 | MAJOR(rtc->rtc_dev->devt), | ||
| 323 | MINOR(rtc->rtc_dev->devt)); | ||
| 324 | |||
| 325 | class_device_unregister(rtc->rtc_dev); | ||
| 326 | cdev_del(&rtc->char_dev); | ||
| 327 | } | ||
| 328 | } | ||
| 329 | |||
| 330 | /* interface registration */ | ||
| 331 | |||
| 332 | static struct class_interface rtc_dev_interface = { | ||
| 333 | .add = &rtc_dev_add_device, | ||
| 334 | .remove = &rtc_dev_remove_device, | ||
| 335 | }; | ||
| 336 | |||
| 337 | static int __init rtc_dev_init(void) | ||
| 338 | { | ||
| 339 | int err; | ||
| 340 | |||
| 341 | rtc_dev_class = class_create(THIS_MODULE, "rtc-dev"); | ||
| 342 | if (IS_ERR(rtc_dev_class)) | ||
| 343 | return PTR_ERR(rtc_dev_class); | ||
| 344 | |||
| 345 | err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc"); | ||
| 346 | if (err < 0) { | ||
| 347 | printk(KERN_ERR "%s: failed to allocate char dev region\n", | ||
| 348 | __FILE__); | ||
| 349 | goto err_destroy_class; | ||
| 350 | } | ||
| 351 | |||
| 352 | err = rtc_interface_register(&rtc_dev_interface); | ||
| 353 | if (err < 0) { | ||
| 354 | printk(KERN_ERR "%s: failed to register the interface\n", | ||
| 355 | __FILE__); | ||
| 356 | goto err_unregister_chrdev; | ||
| 357 | } | ||
| 358 | |||
| 359 | return 0; | ||
| 360 | |||
| 361 | err_unregister_chrdev: | ||
| 362 | unregister_chrdev_region(rtc_devt, RTC_DEV_MAX); | ||
| 363 | |||
| 364 | err_destroy_class: | ||
| 365 | class_destroy(rtc_dev_class); | ||
| 366 | |||
| 367 | return err; | ||
| 368 | } | ||
| 369 | |||
| 370 | static void __exit rtc_dev_exit(void) | ||
| 371 | { | ||
| 372 | class_interface_unregister(&rtc_dev_interface); | ||
| 373 | class_destroy(rtc_dev_class); | ||
| 374 | unregister_chrdev_region(rtc_devt, RTC_DEV_MAX); | ||
| 375 | } | ||
| 376 | |||
| 377 | module_init(rtc_dev_init); | ||
| 378 | module_exit(rtc_dev_exit); | ||
| 379 | |||
| 380 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 381 | MODULE_DESCRIPTION("RTC class dev interface"); | ||
| 382 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c new file mode 100644 index 000000000000..358695a416f3 --- /dev/null +++ b/drivers/rtc/rtc-ds1672.c | |||
| @@ -0,0 +1,233 @@ | |||
| 1 | /* | ||
| 2 | * An rtc/i2c driver for the Dallas DS1672 | ||
| 3 | * Copyright 2005 Alessandro Zummo | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/i2c.h> | ||
| 12 | #include <linux/rtc.h> | ||
| 13 | |||
| 14 | #define DRV_VERSION "0.2" | ||
| 15 | |||
| 16 | /* Addresses to scan: none. This chip cannot be detected. */ | ||
| 17 | static unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
| 18 | |||
| 19 | /* Insmod parameters */ | ||
| 20 | I2C_CLIENT_INSMOD; | ||
| 21 | |||
| 22 | /* Registers */ | ||
| 23 | |||
| 24 | #define DS1672_REG_CNT_BASE 0 | ||
| 25 | #define DS1672_REG_CONTROL 4 | ||
| 26 | #define DS1672_REG_TRICKLE 5 | ||
| 27 | |||
| 28 | |||
| 29 | /* Prototypes */ | ||
| 30 | static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind); | ||
| 31 | |||
| 32 | /* | ||
| 33 | * In the routines that deal directly with the ds1672 hardware, we use | ||
| 34 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch | ||
| 35 | * Epoch is initialized as 2000. Time is set to UTC. | ||
| 36 | */ | ||
| 37 | static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 38 | { | ||
| 39 | unsigned long time; | ||
| 40 | unsigned char addr = DS1672_REG_CNT_BASE; | ||
| 41 | unsigned char buf[4]; | ||
| 42 | |||
| 43 | struct i2c_msg msgs[] = { | ||
| 44 | { client->addr, 0, 1, &addr }, /* setup read ptr */ | ||
| 45 | { client->addr, I2C_M_RD, 4, buf }, /* read date */ | ||
| 46 | }; | ||
| 47 | |||
| 48 | /* read date registers */ | ||
| 49 | if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { | ||
| 50 | dev_err(&client->dev, "%s: read error\n", __FUNCTION__); | ||
| 51 | return -EIO; | ||
| 52 | } | ||
| 53 | |||
| 54 | dev_dbg(&client->dev, | ||
| 55 | "%s: raw read data - counters=%02x,%02x,%02x,%02x\n" | ||
| 56 | __FUNCTION__, | ||
| 57 | buf[0], buf[1], buf[2], buf[3]); | ||
| 58 | |||
| 59 | time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; | ||
| 60 | |||
| 61 | rtc_time_to_tm(time, tm); | ||
| 62 | |||
| 63 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | ||
| 64 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 65 | __FUNCTION__, | ||
| 66 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
| 67 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 68 | |||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) | ||
| 73 | { | ||
| 74 | int xfer; | ||
| 75 | unsigned char buf[5]; | ||
| 76 | |||
| 77 | buf[0] = DS1672_REG_CNT_BASE; | ||
| 78 | buf[1] = secs & 0x000000FF; | ||
| 79 | buf[2] = (secs & 0x0000FF00) >> 8; | ||
| 80 | buf[3] = (secs & 0x00FF0000) >> 16; | ||
| 81 | buf[4] = (secs & 0xFF000000) >> 24; | ||
| 82 | |||
| 83 | xfer = i2c_master_send(client, buf, 5); | ||
| 84 | if (xfer != 5) { | ||
| 85 | dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer); | ||
| 86 | return -EIO; | ||
| 87 | } | ||
| 88 | |||
| 89 | return 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | static int ds1672_set_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 93 | { | ||
| 94 | unsigned long secs; | ||
| 95 | |||
| 96 | dev_dbg(&client->dev, | ||
| 97 | "%s: secs=%d, mins=%d, hours=%d, ", | ||
| 98 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 99 | __FUNCTION__, | ||
| 100 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
| 101 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 102 | |||
| 103 | rtc_tm_to_time(tm, &secs); | ||
| 104 | |||
| 105 | return ds1672_set_mmss(client, secs); | ||
| 106 | } | ||
| 107 | |||
| 108 | static int ds1672_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 109 | { | ||
| 110 | return ds1672_get_datetime(to_i2c_client(dev), tm); | ||
| 111 | } | ||
| 112 | |||
| 113 | static int ds1672_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 114 | { | ||
| 115 | return ds1672_set_datetime(to_i2c_client(dev), tm); | ||
| 116 | } | ||
| 117 | |||
| 118 | static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
| 119 | { | ||
| 120 | return ds1672_set_mmss(to_i2c_client(dev), secs); | ||
| 121 | } | ||
| 122 | |||
| 123 | static struct rtc_class_ops ds1672_rtc_ops = { | ||
| 124 | .read_time = ds1672_rtc_read_time, | ||
| 125 | .set_time = ds1672_rtc_set_time, | ||
| 126 | .set_mmss = ds1672_rtc_set_mmss, | ||
| 127 | }; | ||
| 128 | |||
| 129 | static int ds1672_attach(struct i2c_adapter *adapter) | ||
| 130 | { | ||
| 131 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | ||
| 132 | return i2c_probe(adapter, &addr_data, ds1672_probe); | ||
| 133 | } | ||
| 134 | |||
| 135 | static int ds1672_detach(struct i2c_client *client) | ||
| 136 | { | ||
| 137 | int err; | ||
| 138 | struct rtc_device *rtc = i2c_get_clientdata(client); | ||
| 139 | |||
| 140 | dev_dbg(&client->dev, "%s\n", __FUNCTION__); | ||
| 141 | |||
| 142 | if (rtc) | ||
| 143 | rtc_device_unregister(rtc); | ||
| 144 | |||
| 145 | if ((err = i2c_detach_client(client))) | ||
| 146 | return err; | ||
| 147 | |||
| 148 | kfree(client); | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static struct i2c_driver ds1672_driver = { | ||
| 154 | .driver = { | ||
| 155 | .name = "ds1672", | ||
| 156 | }, | ||
| 157 | .id = I2C_DRIVERID_DS1672, | ||
| 158 | .attach_adapter = &ds1672_attach, | ||
| 159 | .detach_client = &ds1672_detach, | ||
| 160 | }; | ||
| 161 | |||
| 162 | static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) | ||
| 163 | { | ||
| 164 | int err = 0; | ||
| 165 | struct i2c_client *client; | ||
| 166 | struct rtc_device *rtc; | ||
| 167 | |||
| 168 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | ||
| 169 | |||
| 170 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | ||
| 171 | err = -ENODEV; | ||
| 172 | goto exit; | ||
| 173 | } | ||
| 174 | |||
| 175 | if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { | ||
| 176 | err = -ENOMEM; | ||
| 177 | goto exit; | ||
| 178 | } | ||
| 179 | |||
| 180 | /* I2C client */ | ||
| 181 | client->addr = address; | ||
| 182 | client->driver = &ds1672_driver; | ||
| 183 | client->adapter = adapter; | ||
| 184 | |||
| 185 | strlcpy(client->name, ds1672_driver.driver.name, I2C_NAME_SIZE); | ||
| 186 | |||
| 187 | /* Inform the i2c layer */ | ||
| 188 | if ((err = i2c_attach_client(client))) | ||
| 189 | goto exit_kfree; | ||
| 190 | |||
| 191 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | ||
| 192 | |||
| 193 | rtc = rtc_device_register(ds1672_driver.driver.name, &client->dev, | ||
| 194 | &ds1672_rtc_ops, THIS_MODULE); | ||
| 195 | |||
| 196 | if (IS_ERR(rtc)) { | ||
| 197 | err = PTR_ERR(rtc); | ||
| 198 | dev_err(&client->dev, | ||
| 199 | "unable to register the class device\n"); | ||
| 200 | goto exit_detach; | ||
| 201 | } | ||
| 202 | |||
| 203 | i2c_set_clientdata(client, rtc); | ||
| 204 | |||
| 205 | return 0; | ||
| 206 | |||
| 207 | exit_detach: | ||
| 208 | i2c_detach_client(client); | ||
| 209 | |||
| 210 | exit_kfree: | ||
| 211 | kfree(client); | ||
| 212 | |||
| 213 | exit: | ||
| 214 | return err; | ||
| 215 | } | ||
| 216 | |||
| 217 | static int __init ds1672_init(void) | ||
| 218 | { | ||
| 219 | return i2c_add_driver(&ds1672_driver); | ||
| 220 | } | ||
| 221 | |||
| 222 | static void __exit ds1672_exit(void) | ||
| 223 | { | ||
| 224 | i2c_del_driver(&ds1672_driver); | ||
| 225 | } | ||
| 226 | |||
| 227 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 228 | MODULE_DESCRIPTION("Dallas/Maxim DS1672 timekeeper driver"); | ||
| 229 | MODULE_LICENSE("GPL"); | ||
| 230 | MODULE_VERSION(DRV_VERSION); | ||
| 231 | |||
| 232 | module_init(ds1672_init); | ||
| 233 | module_exit(ds1672_exit); | ||
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c new file mode 100644 index 000000000000..0dd80ea686a9 --- /dev/null +++ b/drivers/rtc/rtc-ep93xx.c | |||
| @@ -0,0 +1,162 @@ | |||
| 1 | /* | ||
| 2 | * A driver for the RTC embedded in the Cirrus Logic EP93XX processors | ||
| 3 | * Copyright (c) 2006 Tower Technologies | ||
| 4 | * | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/rtc.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <asm/hardware.h> | ||
| 16 | |||
| 17 | #define EP93XX_RTC_REG(x) (EP93XX_RTC_BASE + (x)) | ||
| 18 | #define EP93XX_RTC_DATA EP93XX_RTC_REG(0x0000) | ||
| 19 | #define EP93XX_RTC_LOAD EP93XX_RTC_REG(0x000C) | ||
| 20 | #define EP93XX_RTC_SWCOMP EP93XX_RTC_REG(0x0108) | ||
| 21 | |||
| 22 | #define DRV_VERSION "0.2" | ||
| 23 | |||
| 24 | static int ep93xx_get_swcomp(struct device *dev, unsigned short *preload, | ||
| 25 | unsigned short *delete) | ||
| 26 | { | ||
| 27 | unsigned short comp = __raw_readl(EP93XX_RTC_SWCOMP); | ||
| 28 | |||
| 29 | if (preload) | ||
| 30 | *preload = comp & 0xffff; | ||
| 31 | |||
| 32 | if (delete) | ||
| 33 | *delete = (comp >> 16) & 0x1f; | ||
| 34 | |||
| 35 | return 0; | ||
| 36 | } | ||
| 37 | |||
| 38 | static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 39 | { | ||
| 40 | unsigned long time = __raw_readl(EP93XX_RTC_DATA); | ||
| 41 | |||
| 42 | rtc_time_to_tm(time, tm); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | static int ep93xx_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
| 47 | { | ||
| 48 | __raw_writel(secs + 1, EP93XX_RTC_LOAD); | ||
| 49 | return 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static int ep93xx_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 53 | { | ||
| 54 | int err; | ||
| 55 | unsigned long secs; | ||
| 56 | |||
| 57 | err = rtc_tm_to_time(tm, &secs); | ||
| 58 | if (err != 0) | ||
| 59 | return err; | ||
| 60 | |||
| 61 | return ep93xx_rtc_set_mmss(dev, secs); | ||
| 62 | } | ||
| 63 | |||
| 64 | static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq) | ||
| 65 | { | ||
| 66 | unsigned short preload, delete; | ||
| 67 | |||
| 68 | ep93xx_get_swcomp(dev, &preload, &delete); | ||
| 69 | |||
| 70 | seq_printf(seq, "24hr\t\t: yes\n"); | ||
| 71 | seq_printf(seq, "preload\t\t: %d\n", preload); | ||
| 72 | seq_printf(seq, "delete\t\t: %d\n", delete); | ||
| 73 | |||
| 74 | return 0; | ||
| 75 | } | ||
| 76 | |||
| 77 | static struct rtc_class_ops ep93xx_rtc_ops = { | ||
| 78 | .read_time = ep93xx_rtc_read_time, | ||
| 79 | .set_time = ep93xx_rtc_set_time, | ||
| 80 | .set_mmss = ep93xx_rtc_set_mmss, | ||
| 81 | .proc = ep93xx_rtc_proc, | ||
| 82 | }; | ||
| 83 | |||
| 84 | static ssize_t ep93xx_sysfs_show_comp_preload(struct device *dev, | ||
| 85 | struct device_attribute *attr, char *buf) | ||
| 86 | { | ||
| 87 | unsigned short preload; | ||
| 88 | |||
| 89 | ep93xx_get_swcomp(dev, &preload, NULL); | ||
| 90 | |||
| 91 | return sprintf(buf, "%d\n", preload); | ||
| 92 | } | ||
| 93 | static DEVICE_ATTR(comp_preload, S_IRUGO, ep93xx_sysfs_show_comp_preload, NULL); | ||
| 94 | |||
| 95 | static ssize_t ep93xx_sysfs_show_comp_delete(struct device *dev, | ||
| 96 | struct device_attribute *attr, char *buf) | ||
| 97 | { | ||
| 98 | unsigned short delete; | ||
| 99 | |||
| 100 | ep93xx_get_swcomp(dev, NULL, &delete); | ||
| 101 | |||
| 102 | return sprintf(buf, "%d\n", delete); | ||
| 103 | } | ||
| 104 | static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_sysfs_show_comp_delete, NULL); | ||
| 105 | |||
| 106 | |||
| 107 | static int __devinit ep93xx_rtc_probe(struct platform_device *dev) | ||
| 108 | { | ||
| 109 | struct rtc_device *rtc = rtc_device_register("ep93xx", | ||
| 110 | &dev->dev, &ep93xx_rtc_ops, THIS_MODULE); | ||
| 111 | |||
| 112 | if (IS_ERR(rtc)) { | ||
| 113 | dev_err(&dev->dev, "unable to register\n"); | ||
| 114 | return PTR_ERR(rtc); | ||
| 115 | } | ||
| 116 | |||
| 117 | platform_set_drvdata(dev, rtc); | ||
| 118 | |||
| 119 | device_create_file(&dev->dev, &dev_attr_comp_preload); | ||
| 120 | device_create_file(&dev->dev, &dev_attr_comp_delete); | ||
| 121 | |||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | static int __devexit ep93xx_rtc_remove(struct platform_device *dev) | ||
| 126 | { | ||
| 127 | struct rtc_device *rtc = platform_get_drvdata(dev); | ||
| 128 | |||
| 129 | if (rtc) | ||
| 130 | rtc_device_unregister(rtc); | ||
| 131 | |||
| 132 | platform_set_drvdata(dev, NULL); | ||
| 133 | |||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | static struct platform_driver ep93xx_rtc_platform_driver = { | ||
| 138 | .driver = { | ||
| 139 | .name = "ep93xx-rtc", | ||
| 140 | .owner = THIS_MODULE, | ||
| 141 | }, | ||
| 142 | .probe = ep93xx_rtc_probe, | ||
| 143 | .remove = __devexit_p(ep93xx_rtc_remove), | ||
| 144 | }; | ||
| 145 | |||
| 146 | static int __init ep93xx_rtc_init(void) | ||
| 147 | { | ||
| 148 | return platform_driver_register(&ep93xx_rtc_platform_driver); | ||
| 149 | } | ||
| 150 | |||
| 151 | static void __exit ep93xx_rtc_exit(void) | ||
| 152 | { | ||
| 153 | platform_driver_unregister(&ep93xx_rtc_platform_driver); | ||
| 154 | } | ||
| 155 | |||
| 156 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 157 | MODULE_DESCRIPTION("EP93XX RTC driver"); | ||
| 158 | MODULE_LICENSE("GPL"); | ||
| 159 | MODULE_VERSION(DRV_VERSION); | ||
| 160 | |||
| 161 | module_init(ep93xx_rtc_init); | ||
| 162 | module_exit(ep93xx_rtc_exit); | ||
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c new file mode 100644 index 000000000000..cfedc1d28ee1 --- /dev/null +++ b/drivers/rtc/rtc-lib.c | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | /* | ||
| 2 | * rtc and date/time utility functions | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-06 Tower Technologies | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * based on arch/arm/common/rtctime.c and other bits | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/rtc.h> | ||
| 16 | |||
| 17 | static const unsigned char rtc_days_in_month[] = { | ||
| 18 | 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 | ||
| 19 | }; | ||
| 20 | |||
| 21 | #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) | ||
| 22 | #define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400)) | ||
| 23 | |||
| 24 | int rtc_month_days(unsigned int month, unsigned int year) | ||
| 25 | { | ||
| 26 | return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1); | ||
| 27 | } | ||
| 28 | EXPORT_SYMBOL(rtc_month_days); | ||
| 29 | |||
| 30 | /* | ||
| 31 | * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. | ||
| 32 | */ | ||
| 33 | void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) | ||
| 34 | { | ||
| 35 | register int days, month, year; | ||
| 36 | |||
| 37 | days = time / 86400; | ||
| 38 | time -= days * 86400; | ||
| 39 | |||
| 40 | /* day of the week, 1970-01-01 was a Thursday */ | ||
| 41 | tm->tm_wday = (days + 4) % 7; | ||
| 42 | |||
| 43 | year = 1970 + days / 365; | ||
| 44 | days -= (year - 1970) * 365 | ||
| 45 | + LEAPS_THRU_END_OF(year - 1) | ||
| 46 | - LEAPS_THRU_END_OF(1970 - 1); | ||
| 47 | if (days < 0) { | ||
| 48 | year -= 1; | ||
| 49 | days += 365 + LEAP_YEAR(year); | ||
| 50 | } | ||
| 51 | tm->tm_year = year - 1900; | ||
| 52 | tm->tm_yday = days + 1; | ||
| 53 | |||
| 54 | for (month = 0; month < 11; month++) { | ||
| 55 | int newdays; | ||
| 56 | |||
| 57 | newdays = days - rtc_month_days(month, year); | ||
| 58 | if (newdays < 0) | ||
| 59 | break; | ||
| 60 | days = newdays; | ||
| 61 | } | ||
| 62 | tm->tm_mon = month; | ||
| 63 | tm->tm_mday = days + 1; | ||
| 64 | |||
| 65 | tm->tm_hour = time / 3600; | ||
| 66 | time -= tm->tm_hour * 3600; | ||
| 67 | tm->tm_min = time / 60; | ||
| 68 | tm->tm_sec = time - tm->tm_min * 60; | ||
| 69 | } | ||
| 70 | EXPORT_SYMBOL(rtc_time_to_tm); | ||
| 71 | |||
| 72 | /* | ||
| 73 | * Does the rtc_time represent a valid date/time? | ||
| 74 | */ | ||
| 75 | int rtc_valid_tm(struct rtc_time *tm) | ||
| 76 | { | ||
| 77 | if (tm->tm_year < 70 | ||
| 78 | || tm->tm_mon >= 12 | ||
| 79 | || tm->tm_mday < 1 | ||
| 80 | || tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900) | ||
| 81 | || tm->tm_hour >= 24 | ||
| 82 | || tm->tm_min >= 60 | ||
| 83 | || tm->tm_sec >= 60) | ||
| 84 | return -EINVAL; | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL(rtc_valid_tm); | ||
| 89 | |||
| 90 | /* | ||
| 91 | * Convert Gregorian date to seconds since 01-01-1970 00:00:00. | ||
| 92 | */ | ||
| 93 | int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time) | ||
| 94 | { | ||
| 95 | *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, | ||
| 96 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | EXPORT_SYMBOL(rtc_tm_to_time); | ||
| 100 | |||
| 101 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c new file mode 100644 index 000000000000..db445c872b1b --- /dev/null +++ b/drivers/rtc/rtc-m48t86.c | |||
| @@ -0,0 +1,209 @@ | |||
| 1 | /* | ||
| 2 | * ST M48T86 / Dallas DS12887 RTC driver | ||
| 3 | * Copyright (c) 2006 Tower Technologies | ||
| 4 | * | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * This drivers only supports the clock running in BCD and 24H mode. | ||
| 12 | * If it will be ever adapted to binary and 12H mode, care must be taken | ||
| 13 | * to not introduce bugs. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/rtc.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/m48t86.h> | ||
| 20 | #include <linux/bcd.h> | ||
| 21 | |||
| 22 | #define M48T86_REG_SEC 0x00 | ||
| 23 | #define M48T86_REG_SECALRM 0x01 | ||
| 24 | #define M48T86_REG_MIN 0x02 | ||
| 25 | #define M48T86_REG_MINALRM 0x03 | ||
| 26 | #define M48T86_REG_HOUR 0x04 | ||
| 27 | #define M48T86_REG_HOURALRM 0x05 | ||
| 28 | #define M48T86_REG_DOW 0x06 /* 1 = sunday */ | ||
| 29 | #define M48T86_REG_DOM 0x07 | ||
| 30 | #define M48T86_REG_MONTH 0x08 /* 1 - 12 */ | ||
| 31 | #define M48T86_REG_YEAR 0x09 /* 0 - 99 */ | ||
| 32 | #define M48T86_REG_A 0x0A | ||
| 33 | #define M48T86_REG_B 0x0B | ||
| 34 | #define M48T86_REG_C 0x0C | ||
| 35 | #define M48T86_REG_D 0x0D | ||
| 36 | |||
| 37 | #define M48T86_REG_B_H24 (1 << 1) | ||
| 38 | #define M48T86_REG_B_DM (1 << 2) | ||
| 39 | #define M48T86_REG_B_SET (1 << 7) | ||
| 40 | #define M48T86_REG_D_VRT (1 << 7) | ||
| 41 | |||
| 42 | #define DRV_VERSION "0.1" | ||
| 43 | |||
| 44 | |||
| 45 | static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 46 | { | ||
| 47 | unsigned char reg; | ||
| 48 | struct platform_device *pdev = to_platform_device(dev); | ||
| 49 | struct m48t86_ops *ops = pdev->dev.platform_data; | ||
| 50 | |||
| 51 | reg = ops->readb(M48T86_REG_B); | ||
| 52 | |||
| 53 | if (reg & M48T86_REG_B_DM) { | ||
| 54 | /* data (binary) mode */ | ||
| 55 | tm->tm_sec = ops->readb(M48T86_REG_SEC); | ||
| 56 | tm->tm_min = ops->readb(M48T86_REG_MIN); | ||
| 57 | tm->tm_hour = ops->readb(M48T86_REG_HOUR) & 0x3F; | ||
| 58 | tm->tm_mday = ops->readb(M48T86_REG_DOM); | ||
| 59 | /* tm_mon is 0-11 */ | ||
| 60 | tm->tm_mon = ops->readb(M48T86_REG_MONTH) - 1; | ||
| 61 | tm->tm_year = ops->readb(M48T86_REG_YEAR) + 100; | ||
| 62 | tm->tm_wday = ops->readb(M48T86_REG_DOW); | ||
| 63 | } else { | ||
| 64 | /* bcd mode */ | ||
| 65 | tm->tm_sec = BCD2BIN(ops->readb(M48T86_REG_SEC)); | ||
| 66 | tm->tm_min = BCD2BIN(ops->readb(M48T86_REG_MIN)); | ||
| 67 | tm->tm_hour = BCD2BIN(ops->readb(M48T86_REG_HOUR) & 0x3F); | ||
| 68 | tm->tm_mday = BCD2BIN(ops->readb(M48T86_REG_DOM)); | ||
| 69 | /* tm_mon is 0-11 */ | ||
| 70 | tm->tm_mon = BCD2BIN(ops->readb(M48T86_REG_MONTH)) - 1; | ||
| 71 | tm->tm_year = BCD2BIN(ops->readb(M48T86_REG_YEAR)) + 100; | ||
| 72 | tm->tm_wday = BCD2BIN(ops->readb(M48T86_REG_DOW)); | ||
| 73 | } | ||
| 74 | |||
| 75 | /* correct the hour if the clock is in 12h mode */ | ||
| 76 | if (!(reg & M48T86_REG_B_H24)) | ||
| 77 | if (ops->readb(M48T86_REG_HOUR) & 0x80) | ||
| 78 | tm->tm_hour += 12; | ||
| 79 | |||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | |||
| 83 | static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 84 | { | ||
| 85 | unsigned char reg; | ||
| 86 | struct platform_device *pdev = to_platform_device(dev); | ||
| 87 | struct m48t86_ops *ops = pdev->dev.platform_data; | ||
| 88 | |||
| 89 | reg = ops->readb(M48T86_REG_B); | ||
| 90 | |||
| 91 | /* update flag and 24h mode */ | ||
| 92 | reg |= M48T86_REG_B_SET | M48T86_REG_B_H24; | ||
| 93 | ops->writeb(reg, M48T86_REG_B); | ||
| 94 | |||
| 95 | if (reg & M48T86_REG_B_DM) { | ||
| 96 | /* data (binary) mode */ | ||
| 97 | ops->writeb(tm->tm_sec, M48T86_REG_SEC); | ||
| 98 | ops->writeb(tm->tm_min, M48T86_REG_MIN); | ||
| 99 | ops->writeb(tm->tm_hour, M48T86_REG_HOUR); | ||
| 100 | ops->writeb(tm->tm_mday, M48T86_REG_DOM); | ||
| 101 | ops->writeb(tm->tm_mon + 1, M48T86_REG_MONTH); | ||
| 102 | ops->writeb(tm->tm_year % 100, M48T86_REG_YEAR); | ||
| 103 | ops->writeb(tm->tm_wday, M48T86_REG_DOW); | ||
| 104 | } else { | ||
| 105 | /* bcd mode */ | ||
| 106 | ops->writeb(BIN2BCD(tm->tm_sec), M48T86_REG_SEC); | ||
| 107 | ops->writeb(BIN2BCD(tm->tm_min), M48T86_REG_MIN); | ||
| 108 | ops->writeb(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR); | ||
| 109 | ops->writeb(BIN2BCD(tm->tm_mday), M48T86_REG_DOM); | ||
| 110 | ops->writeb(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH); | ||
| 111 | ops->writeb(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR); | ||
| 112 | ops->writeb(BIN2BCD(tm->tm_wday), M48T86_REG_DOW); | ||
| 113 | } | ||
| 114 | |||
| 115 | /* update ended */ | ||
| 116 | reg &= ~M48T86_REG_B_SET; | ||
| 117 | ops->writeb(reg, M48T86_REG_B); | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq) | ||
| 123 | { | ||
| 124 | unsigned char reg; | ||
| 125 | struct platform_device *pdev = to_platform_device(dev); | ||
| 126 | struct m48t86_ops *ops = pdev->dev.platform_data; | ||
| 127 | |||
| 128 | reg = ops->readb(M48T86_REG_B); | ||
| 129 | |||
| 130 | seq_printf(seq, "24hr\t\t: %s\n", | ||
| 131 | (reg & M48T86_REG_B_H24) ? "yes" : "no"); | ||
| 132 | |||
| 133 | seq_printf(seq, "mode\t\t: %s\n", | ||
| 134 | (reg & M48T86_REG_B_DM) ? "binary" : "bcd"); | ||
| 135 | |||
| 136 | reg = ops->readb(M48T86_REG_D); | ||
| 137 | |||
| 138 | seq_printf(seq, "battery\t\t: %s\n", | ||
| 139 | (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted"); | ||
| 140 | |||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | static struct rtc_class_ops m48t86_rtc_ops = { | ||
| 145 | .read_time = m48t86_rtc_read_time, | ||
| 146 | .set_time = m48t86_rtc_set_time, | ||
| 147 | .proc = m48t86_rtc_proc, | ||
| 148 | }; | ||
| 149 | |||
| 150 | static int __devinit m48t86_rtc_probe(struct platform_device *dev) | ||
| 151 | { | ||
| 152 | unsigned char reg; | ||
| 153 | struct m48t86_ops *ops = dev->dev.platform_data; | ||
| 154 | struct rtc_device *rtc = rtc_device_register("m48t86", | ||
| 155 | &dev->dev, &m48t86_rtc_ops, THIS_MODULE); | ||
| 156 | |||
| 157 | if (IS_ERR(rtc)) { | ||
| 158 | dev_err(&dev->dev, "unable to register\n"); | ||
| 159 | return PTR_ERR(rtc); | ||
| 160 | } | ||
| 161 | |||
| 162 | platform_set_drvdata(dev, rtc); | ||
| 163 | |||
| 164 | /* read battery status */ | ||
| 165 | reg = ops->readb(M48T86_REG_D); | ||
| 166 | dev_info(&dev->dev, "battery %s\n", | ||
| 167 | (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted"); | ||
| 168 | |||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | |||
| 172 | static int __devexit m48t86_rtc_remove(struct platform_device *dev) | ||
| 173 | { | ||
| 174 | struct rtc_device *rtc = platform_get_drvdata(dev); | ||
| 175 | |||
| 176 | if (rtc) | ||
| 177 | rtc_device_unregister(rtc); | ||
| 178 | |||
| 179 | platform_set_drvdata(dev, NULL); | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 184 | static struct platform_driver m48t86_rtc_platform_driver = { | ||
| 185 | .driver = { | ||
| 186 | .name = "rtc-m48t86", | ||
| 187 | .owner = THIS_MODULE, | ||
| 188 | }, | ||
| 189 | .probe = m48t86_rtc_probe, | ||
| 190 | .remove = __devexit_p(m48t86_rtc_remove), | ||
| 191 | }; | ||
| 192 | |||
| 193 | static int __init m48t86_rtc_init(void) | ||
| 194 | { | ||
| 195 | return platform_driver_register(&m48t86_rtc_platform_driver); | ||
| 196 | } | ||
| 197 | |||
| 198 | static void __exit m48t86_rtc_exit(void) | ||
| 199 | { | ||
| 200 | platform_driver_unregister(&m48t86_rtc_platform_driver); | ||
| 201 | } | ||
| 202 | |||
| 203 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 204 | MODULE_DESCRIPTION("M48T86 RTC driver"); | ||
| 205 | MODULE_LICENSE("GPL"); | ||
| 206 | MODULE_VERSION(DRV_VERSION); | ||
| 207 | |||
| 208 | module_init(m48t86_rtc_init); | ||
| 209 | module_exit(m48t86_rtc_exit); | ||
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c new file mode 100644 index 000000000000..d857d45bdbe8 --- /dev/null +++ b/drivers/rtc/rtc-pcf8563.c | |||
| @@ -0,0 +1,353 @@ | |||
| 1 | /* | ||
| 2 | * An I2C driver for the Philips PCF8563 RTC | ||
| 3 | * Copyright 2005-06 Tower Technologies | ||
| 4 | * | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * Maintainers: http://www.nslu2-linux.org/ | ||
| 7 | * | ||
| 8 | * based on the other drivers in this same directory. | ||
| 9 | * | ||
| 10 | * http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License version 2 as | ||
| 14 | * published by the Free Software Foundation. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/i2c.h> | ||
| 18 | #include <linux/bcd.h> | ||
| 19 | #include <linux/rtc.h> | ||
| 20 | |||
| 21 | #define DRV_VERSION "0.4.2" | ||
| 22 | |||
| 23 | /* Addresses to scan: none | ||
| 24 | * This chip cannot be reliably autodetected. An empty eeprom | ||
| 25 | * located at 0x51 will pass the validation routine due to | ||
| 26 | * the way the registers are implemented. | ||
| 27 | */ | ||
| 28 | static unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
| 29 | |||
| 30 | /* Module parameters */ | ||
| 31 | I2C_CLIENT_INSMOD; | ||
| 32 | |||
| 33 | #define PCF8563_REG_ST1 0x00 /* status */ | ||
| 34 | #define PCF8563_REG_ST2 0x01 | ||
| 35 | |||
| 36 | #define PCF8563_REG_SC 0x02 /* datetime */ | ||
| 37 | #define PCF8563_REG_MN 0x03 | ||
| 38 | #define PCF8563_REG_HR 0x04 | ||
| 39 | #define PCF8563_REG_DM 0x05 | ||
| 40 | #define PCF8563_REG_DW 0x06 | ||
| 41 | #define PCF8563_REG_MO 0x07 | ||
| 42 | #define PCF8563_REG_YR 0x08 | ||
| 43 | |||
| 44 | #define PCF8563_REG_AMN 0x09 /* alarm */ | ||
| 45 | #define PCF8563_REG_AHR 0x0A | ||
| 46 | #define PCF8563_REG_ADM 0x0B | ||
| 47 | #define PCF8563_REG_ADW 0x0C | ||
| 48 | |||
| 49 | #define PCF8563_REG_CLKO 0x0D /* clock out */ | ||
| 50 | #define PCF8563_REG_TMRC 0x0E /* timer control */ | ||
| 51 | #define PCF8563_REG_TMR 0x0F /* timer */ | ||
| 52 | |||
| 53 | #define PCF8563_SC_LV 0x80 /* low voltage */ | ||
| 54 | #define PCF8563_MO_C 0x80 /* century */ | ||
| 55 | |||
| 56 | static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind); | ||
| 57 | static int pcf8563_detach(struct i2c_client *client); | ||
| 58 | |||
| 59 | /* | ||
| 60 | * In the routines that deal directly with the pcf8563 hardware, we use | ||
| 61 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. | ||
| 62 | */ | ||
| 63 | static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 64 | { | ||
| 65 | unsigned char buf[13] = { PCF8563_REG_ST1 }; | ||
| 66 | |||
| 67 | struct i2c_msg msgs[] = { | ||
| 68 | { client->addr, 0, 1, buf }, /* setup read ptr */ | ||
| 69 | { client->addr, I2C_M_RD, 13, buf }, /* read status + date */ | ||
| 70 | }; | ||
| 71 | |||
| 72 | /* read registers */ | ||
| 73 | if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { | ||
| 74 | dev_err(&client->dev, "%s: read error\n", __FUNCTION__); | ||
| 75 | return -EIO; | ||
| 76 | } | ||
| 77 | |||
| 78 | if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) | ||
| 79 | dev_info(&client->dev, | ||
| 80 | "low voltage detected, date/time is not reliable.\n"); | ||
| 81 | |||
| 82 | dev_dbg(&client->dev, | ||
| 83 | "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, " | ||
| 84 | "mday=%02x, wday=%02x, mon=%02x, year=%02x\n", | ||
| 85 | __FUNCTION__, | ||
| 86 | buf[0], buf[1], buf[2], buf[3], | ||
| 87 | buf[4], buf[5], buf[6], buf[7], | ||
| 88 | buf[8]); | ||
| 89 | |||
| 90 | |||
| 91 | tm->tm_sec = BCD2BIN(buf[PCF8563_REG_SC] & 0x7F); | ||
| 92 | tm->tm_min = BCD2BIN(buf[PCF8563_REG_MN] & 0x7F); | ||
| 93 | tm->tm_hour = BCD2BIN(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */ | ||
| 94 | tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F); | ||
| 95 | tm->tm_wday = buf[PCF8563_REG_DW] & 0x07; | ||
| 96 | tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ | ||
| 97 | tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]) | ||
| 98 | + (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 100 : 0); | ||
| 99 | |||
| 100 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | ||
| 101 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 102 | __FUNCTION__, | ||
| 103 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
| 104 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 105 | |||
| 106 | /* the clock can give out invalid datetime, but we cannot return | ||
| 107 | * -EINVAL otherwise hwclock will refuse to set the time on bootup. | ||
| 108 | */ | ||
| 109 | if (rtc_valid_tm(tm) < 0) | ||
| 110 | dev_err(&client->dev, "retrieved date/time is not valid.\n"); | ||
| 111 | |||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 116 | { | ||
| 117 | int i, err; | ||
| 118 | unsigned char buf[9]; | ||
| 119 | |||
| 120 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | ||
| 121 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 122 | __FUNCTION__, | ||
| 123 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
| 124 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 125 | |||
| 126 | /* hours, minutes and seconds */ | ||
| 127 | buf[PCF8563_REG_SC] = BIN2BCD(tm->tm_sec); | ||
| 128 | buf[PCF8563_REG_MN] = BIN2BCD(tm->tm_min); | ||
| 129 | buf[PCF8563_REG_HR] = BIN2BCD(tm->tm_hour); | ||
| 130 | |||
| 131 | buf[PCF8563_REG_DM] = BIN2BCD(tm->tm_mday); | ||
| 132 | |||
| 133 | /* month, 1 - 12 */ | ||
| 134 | buf[PCF8563_REG_MO] = BIN2BCD(tm->tm_mon + 1); | ||
| 135 | |||
| 136 | /* year and century */ | ||
| 137 | buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100); | ||
| 138 | if (tm->tm_year / 100) | ||
| 139 | buf[PCF8563_REG_MO] |= PCF8563_MO_C; | ||
| 140 | |||
| 141 | buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; | ||
| 142 | |||
| 143 | /* write register's data */ | ||
| 144 | for (i = 0; i < 7; i++) { | ||
| 145 | unsigned char data[2] = { PCF8563_REG_SC + i, | ||
| 146 | buf[PCF8563_REG_SC + i] }; | ||
| 147 | |||
| 148 | err = i2c_master_send(client, data, sizeof(data)); | ||
| 149 | if (err != sizeof(data)) { | ||
| 150 | dev_err(&client->dev, | ||
| 151 | "%s: err=%d addr=%02x, data=%02x\n", | ||
| 152 | __FUNCTION__, err, data[0], data[1]); | ||
| 153 | return -EIO; | ||
| 154 | } | ||
| 155 | }; | ||
| 156 | |||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | struct pcf8563_limit | ||
| 161 | { | ||
| 162 | unsigned char reg; | ||
| 163 | unsigned char mask; | ||
| 164 | unsigned char min; | ||
| 165 | unsigned char max; | ||
| 166 | }; | ||
| 167 | |||
| 168 | static int pcf8563_validate_client(struct i2c_client *client) | ||
| 169 | { | ||
| 170 | int i; | ||
| 171 | |||
| 172 | static const struct pcf8563_limit pattern[] = { | ||
| 173 | /* register, mask, min, max */ | ||
| 174 | { PCF8563_REG_SC, 0x7F, 0, 59 }, | ||
| 175 | { PCF8563_REG_MN, 0x7F, 0, 59 }, | ||
| 176 | { PCF8563_REG_HR, 0x3F, 0, 23 }, | ||
| 177 | { PCF8563_REG_DM, 0x3F, 0, 31 }, | ||
| 178 | { PCF8563_REG_MO, 0x1F, 0, 12 }, | ||
| 179 | }; | ||
| 180 | |||
| 181 | /* check limits (only registers with bcd values) */ | ||
| 182 | for (i = 0; i < ARRAY_SIZE(pattern); i++) { | ||
| 183 | int xfer; | ||
| 184 | unsigned char value; | ||
| 185 | unsigned char buf = pattern[i].reg; | ||
| 186 | |||
| 187 | struct i2c_msg msgs[] = { | ||
| 188 | { client->addr, 0, 1, &buf }, | ||
| 189 | { client->addr, I2C_M_RD, 1, &buf }, | ||
| 190 | }; | ||
| 191 | |||
| 192 | xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
| 193 | |||
| 194 | if (xfer != ARRAY_SIZE(msgs)) { | ||
| 195 | dev_err(&client->adapter->dev, | ||
| 196 | "%s: could not read register 0x%02X\n", | ||
| 197 | __FUNCTION__, pattern[i].reg); | ||
| 198 | |||
| 199 | return -EIO; | ||
| 200 | } | ||
| 201 | |||
| 202 | value = BCD2BIN(buf & pattern[i].mask); | ||
| 203 | |||
| 204 | if (value > pattern[i].max || | ||
| 205 | value < pattern[i].min) { | ||
| 206 | dev_dbg(&client->adapter->dev, | ||
| 207 | "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, " | ||
| 208 | "max=%d, value=%d, raw=0x%02X\n", | ||
| 209 | __FUNCTION__, i, pattern[i].reg, pattern[i].mask, | ||
| 210 | pattern[i].min, pattern[i].max, | ||
| 211 | value, buf); | ||
| 212 | |||
| 213 | return -ENODEV; | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | return 0; | ||
| 218 | } | ||
| 219 | |||
| 220 | static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 221 | { | ||
| 222 | return pcf8563_get_datetime(to_i2c_client(dev), tm); | ||
| 223 | } | ||
| 224 | |||
| 225 | static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 226 | { | ||
| 227 | return pcf8563_set_datetime(to_i2c_client(dev), tm); | ||
| 228 | } | ||
| 229 | |||
| 230 | static int pcf8563_rtc_proc(struct device *dev, struct seq_file *seq) | ||
| 231 | { | ||
| 232 | seq_printf(seq, "24hr\t\t: yes\n"); | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | static struct rtc_class_ops pcf8563_rtc_ops = { | ||
| 237 | .proc = pcf8563_rtc_proc, | ||
| 238 | .read_time = pcf8563_rtc_read_time, | ||
| 239 | .set_time = pcf8563_rtc_set_time, | ||
| 240 | }; | ||
| 241 | |||
| 242 | static int pcf8563_attach(struct i2c_adapter *adapter) | ||
| 243 | { | ||
| 244 | return i2c_probe(adapter, &addr_data, pcf8563_probe); | ||
| 245 | } | ||
| 246 | |||
| 247 | static struct i2c_driver pcf8563_driver = { | ||
| 248 | .driver = { | ||
| 249 | .name = "pcf8563", | ||
| 250 | }, | ||
| 251 | .id = I2C_DRIVERID_PCF8563, | ||
| 252 | .attach_adapter = &pcf8563_attach, | ||
| 253 | .detach_client = &pcf8563_detach, | ||
| 254 | }; | ||
| 255 | |||
| 256 | static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind) | ||
| 257 | { | ||
| 258 | struct i2c_client *client; | ||
| 259 | struct rtc_device *rtc; | ||
| 260 | |||
| 261 | int err = 0; | ||
| 262 | |||
| 263 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | ||
| 264 | |||
| 265 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | ||
| 266 | err = -ENODEV; | ||
| 267 | goto exit; | ||
| 268 | } | ||
| 269 | |||
| 270 | if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { | ||
| 271 | err = -ENOMEM; | ||
| 272 | goto exit; | ||
| 273 | } | ||
| 274 | |||
| 275 | client->addr = address; | ||
| 276 | client->driver = &pcf8563_driver; | ||
| 277 | client->adapter = adapter; | ||
| 278 | |||
| 279 | strlcpy(client->name, pcf8563_driver.driver.name, I2C_NAME_SIZE); | ||
| 280 | |||
| 281 | /* Verify the chip is really an PCF8563 */ | ||
| 282 | if (kind < 0) { | ||
| 283 | if (pcf8563_validate_client(client) < 0) { | ||
| 284 | err = -ENODEV; | ||
| 285 | goto exit_kfree; | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | /* Inform the i2c layer */ | ||
| 290 | if ((err = i2c_attach_client(client))) | ||
| 291 | goto exit_kfree; | ||
| 292 | |||
| 293 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | ||
| 294 | |||
| 295 | rtc = rtc_device_register(pcf8563_driver.driver.name, &client->dev, | ||
| 296 | &pcf8563_rtc_ops, THIS_MODULE); | ||
| 297 | |||
| 298 | if (IS_ERR(rtc)) { | ||
| 299 | err = PTR_ERR(rtc); | ||
| 300 | dev_err(&client->dev, | ||
| 301 | "unable to register the class device\n"); | ||
| 302 | goto exit_detach; | ||
| 303 | } | ||
| 304 | |||
| 305 | i2c_set_clientdata(client, rtc); | ||
| 306 | |||
| 307 | return 0; | ||
| 308 | |||
| 309 | exit_detach: | ||
| 310 | i2c_detach_client(client); | ||
| 311 | |||
| 312 | exit_kfree: | ||
| 313 | kfree(client); | ||
| 314 | |||
| 315 | exit: | ||
| 316 | return err; | ||
| 317 | } | ||
| 318 | |||
| 319 | static int pcf8563_detach(struct i2c_client *client) | ||
| 320 | { | ||
| 321 | int err; | ||
| 322 | struct rtc_device *rtc = i2c_get_clientdata(client); | ||
| 323 | |||
| 324 | dev_dbg(&client->dev, "%s\n", __FUNCTION__); | ||
| 325 | |||
| 326 | if (rtc) | ||
| 327 | rtc_device_unregister(rtc); | ||
| 328 | |||
| 329 | if ((err = i2c_detach_client(client))) | ||
| 330 | return err; | ||
| 331 | |||
| 332 | kfree(client); | ||
| 333 | |||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | static int __init pcf8563_init(void) | ||
| 338 | { | ||
| 339 | return i2c_add_driver(&pcf8563_driver); | ||
| 340 | } | ||
| 341 | |||
| 342 | static void __exit pcf8563_exit(void) | ||
| 343 | { | ||
| 344 | i2c_del_driver(&pcf8563_driver); | ||
| 345 | } | ||
| 346 | |||
| 347 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 348 | MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver"); | ||
| 349 | MODULE_LICENSE("GPL"); | ||
| 350 | MODULE_VERSION(DRV_VERSION); | ||
| 351 | |||
| 352 | module_init(pcf8563_init); | ||
| 353 | module_exit(pcf8563_exit); | ||
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c new file mode 100644 index 000000000000..90b8a97a0919 --- /dev/null +++ b/drivers/rtc/rtc-proc.c | |||
| @@ -0,0 +1,162 @@ | |||
| 1 | /* | ||
| 2 | * RTC subsystem, proc interface | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-06 Tower Technologies | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * based on arch/arm/common/rtctime.c | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/rtc.h> | ||
| 16 | #include <linux/proc_fs.h> | ||
| 17 | #include <linux/seq_file.h> | ||
| 18 | |||
| 19 | static struct class_device *rtc_dev = NULL; | ||
| 20 | static DEFINE_MUTEX(rtc_lock); | ||
| 21 | |||
| 22 | static int rtc_proc_show(struct seq_file *seq, void *offset) | ||
| 23 | { | ||
| 24 | int err; | ||
| 25 | struct class_device *class_dev = seq->private; | ||
| 26 | struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops; | ||
| 27 | struct rtc_wkalrm alrm; | ||
| 28 | struct rtc_time tm; | ||
| 29 | |||
| 30 | err = rtc_read_time(class_dev, &tm); | ||
| 31 | if (err == 0) { | ||
| 32 | seq_printf(seq, | ||
| 33 | "rtc_time\t: %02d:%02d:%02d\n" | ||
| 34 | "rtc_date\t: %04d-%02d-%02d\n", | ||
| 35 | tm.tm_hour, tm.tm_min, tm.tm_sec, | ||
| 36 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | ||
| 37 | } | ||
| 38 | |||
| 39 | err = rtc_read_alarm(class_dev, &alrm); | ||
| 40 | if (err == 0) { | ||
| 41 | seq_printf(seq, "alrm_time\t: "); | ||
| 42 | if ((unsigned int)alrm.time.tm_hour <= 24) | ||
| 43 | seq_printf(seq, "%02d:", alrm.time.tm_hour); | ||
| 44 | else | ||
| 45 | seq_printf(seq, "**:"); | ||
| 46 | if ((unsigned int)alrm.time.tm_min <= 59) | ||
| 47 | seq_printf(seq, "%02d:", alrm.time.tm_min); | ||
| 48 | else | ||
| 49 | seq_printf(seq, "**:"); | ||
| 50 | if ((unsigned int)alrm.time.tm_sec <= 59) | ||
| 51 | seq_printf(seq, "%02d\n", alrm.time.tm_sec); | ||
| 52 | else | ||
| 53 | seq_printf(seq, "**\n"); | ||
| 54 | |||
| 55 | seq_printf(seq, "alrm_date\t: "); | ||
| 56 | if ((unsigned int)alrm.time.tm_year <= 200) | ||
| 57 | seq_printf(seq, "%04d-", alrm.time.tm_year + 1900); | ||
| 58 | else | ||
| 59 | seq_printf(seq, "****-"); | ||
| 60 | if ((unsigned int)alrm.time.tm_mon <= 11) | ||
| 61 | seq_printf(seq, "%02d-", alrm.time.tm_mon + 1); | ||
| 62 | else | ||
| 63 | seq_printf(seq, "**-"); | ||
| 64 | if ((unsigned int)alrm.time.tm_mday <= 31) | ||
| 65 | seq_printf(seq, "%02d\n", alrm.time.tm_mday); | ||
| 66 | else | ||
| 67 | seq_printf(seq, "**\n"); | ||
| 68 | seq_printf(seq, "alrm_wakeup\t: %s\n", | ||
| 69 | alrm.enabled ? "yes" : "no"); | ||
| 70 | seq_printf(seq, "alrm_pending\t: %s\n", | ||
| 71 | alrm.pending ? "yes" : "no"); | ||
| 72 | } | ||
| 73 | |||
| 74 | if (ops->proc) | ||
| 75 | ops->proc(class_dev->dev, seq); | ||
| 76 | |||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | static int rtc_proc_open(struct inode *inode, struct file *file) | ||
| 81 | { | ||
| 82 | struct class_device *class_dev = PDE(inode)->data; | ||
| 83 | |||
| 84 | if (!try_module_get(THIS_MODULE)) | ||
| 85 | return -ENODEV; | ||
| 86 | |||
| 87 | return single_open(file, rtc_proc_show, class_dev); | ||
| 88 | } | ||
| 89 | |||
| 90 | static int rtc_proc_release(struct inode *inode, struct file *file) | ||
| 91 | { | ||
| 92 | int res = single_release(inode, file); | ||
| 93 | module_put(THIS_MODULE); | ||
| 94 | return res; | ||
| 95 | } | ||
| 96 | |||
| 97 | static struct file_operations rtc_proc_fops = { | ||
| 98 | .open = rtc_proc_open, | ||
| 99 | .read = seq_read, | ||
| 100 | .llseek = seq_lseek, | ||
| 101 | .release = rtc_proc_release, | ||
| 102 | }; | ||
| 103 | |||
| 104 | static int rtc_proc_add_device(struct class_device *class_dev, | ||
| 105 | struct class_interface *class_intf) | ||
| 106 | { | ||
| 107 | mutex_lock(&rtc_lock); | ||
| 108 | if (rtc_dev == NULL) { | ||
| 109 | struct proc_dir_entry *ent; | ||
| 110 | |||
| 111 | rtc_dev = class_dev; | ||
| 112 | |||
| 113 | ent = create_proc_entry("driver/rtc", 0, NULL); | ||
| 114 | if (ent) { | ||
| 115 | struct rtc_device *rtc = to_rtc_device(class_dev); | ||
| 116 | |||
| 117 | ent->proc_fops = &rtc_proc_fops; | ||
| 118 | ent->owner = rtc->owner; | ||
| 119 | ent->data = class_dev; | ||
| 120 | |||
| 121 | dev_info(class_dev->dev, "rtc intf: proc\n"); | ||
| 122 | } | ||
| 123 | else | ||
| 124 | rtc_dev = NULL; | ||
| 125 | } | ||
| 126 | mutex_unlock(&rtc_lock); | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 131 | static void rtc_proc_remove_device(struct class_device *class_dev, | ||
| 132 | struct class_interface *class_intf) | ||
| 133 | { | ||
| 134 | mutex_lock(&rtc_lock); | ||
| 135 | if (rtc_dev == class_dev) { | ||
| 136 | remove_proc_entry("driver/rtc", NULL); | ||
| 137 | rtc_dev = NULL; | ||
| 138 | } | ||
| 139 | mutex_unlock(&rtc_lock); | ||
| 140 | } | ||
| 141 | |||
| 142 | static struct class_interface rtc_proc_interface = { | ||
| 143 | .add = &rtc_proc_add_device, | ||
| 144 | .remove = &rtc_proc_remove_device, | ||
| 145 | }; | ||
| 146 | |||
| 147 | static int __init rtc_proc_init(void) | ||
| 148 | { | ||
| 149 | return rtc_interface_register(&rtc_proc_interface); | ||
| 150 | } | ||
| 151 | |||
| 152 | static void __exit rtc_proc_exit(void) | ||
| 153 | { | ||
| 154 | class_interface_unregister(&rtc_proc_interface); | ||
| 155 | } | ||
| 156 | |||
| 157 | module_init(rtc_proc_init); | ||
| 158 | module_exit(rtc_proc_exit); | ||
| 159 | |||
| 160 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 161 | MODULE_DESCRIPTION("RTC class proc interface"); | ||
| 162 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c new file mode 100644 index 000000000000..396c8681f66c --- /dev/null +++ b/drivers/rtc/rtc-rs5c372.c | |||
| @@ -0,0 +1,294 @@ | |||
| 1 | /* | ||
| 2 | * An I2C driver for the Ricoh RS5C372 RTC | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Pavel Mironchik <pmironchik@optifacio.net> | ||
| 5 | * Copyright (C) 2006 Tower Technologies | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/i2c.h> | ||
| 13 | #include <linux/rtc.h> | ||
| 14 | #include <linux/bcd.h> | ||
| 15 | |||
| 16 | #define DRV_VERSION "0.2" | ||
| 17 | |||
| 18 | /* Addresses to scan */ | ||
| 19 | static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END }; | ||
| 20 | |||
| 21 | /* Insmod parameters */ | ||
| 22 | I2C_CLIENT_INSMOD; | ||
| 23 | |||
| 24 | #define RS5C372_REG_SECS 0 | ||
| 25 | #define RS5C372_REG_MINS 1 | ||
| 26 | #define RS5C372_REG_HOURS 2 | ||
| 27 | #define RS5C372_REG_WDAY 3 | ||
| 28 | #define RS5C372_REG_DAY 4 | ||
| 29 | #define RS5C372_REG_MONTH 5 | ||
| 30 | #define RS5C372_REG_YEAR 6 | ||
| 31 | #define RS5C372_REG_TRIM 7 | ||
| 32 | |||
| 33 | #define RS5C372_TRIM_XSL 0x80 | ||
| 34 | #define RS5C372_TRIM_MASK 0x7F | ||
| 35 | |||
| 36 | #define RS5C372_REG_BASE 0 | ||
| 37 | |||
| 38 | static int rs5c372_attach(struct i2c_adapter *adapter); | ||
| 39 | static int rs5c372_detach(struct i2c_client *client); | ||
| 40 | static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind); | ||
| 41 | |||
| 42 | static struct i2c_driver rs5c372_driver = { | ||
| 43 | .driver = { | ||
| 44 | .name = "rs5c372", | ||
| 45 | }, | ||
| 46 | .attach_adapter = &rs5c372_attach, | ||
| 47 | .detach_client = &rs5c372_detach, | ||
| 48 | }; | ||
| 49 | |||
| 50 | static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 51 | { | ||
| 52 | unsigned char buf[7] = { RS5C372_REG_BASE }; | ||
| 53 | |||
| 54 | /* this implements the 1st reading method, according | ||
| 55 | * to the datasheet. buf[0] is initialized with | ||
| 56 | * address ptr and transmission format register. | ||
| 57 | */ | ||
| 58 | struct i2c_msg msgs[] = { | ||
| 59 | { client->addr, 0, 1, buf }, | ||
| 60 | { client->addr, I2C_M_RD, 7, buf }, | ||
| 61 | }; | ||
| 62 | |||
| 63 | if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { | ||
| 64 | dev_err(&client->dev, "%s: read error\n", __FUNCTION__); | ||
| 65 | return -EIO; | ||
| 66 | } | ||
| 67 | |||
| 68 | tm->tm_sec = BCD2BIN(buf[RS5C372_REG_SECS] & 0x7f); | ||
| 69 | tm->tm_min = BCD2BIN(buf[RS5C372_REG_MINS] & 0x7f); | ||
| 70 | tm->tm_hour = BCD2BIN(buf[RS5C372_REG_HOURS] & 0x3f); | ||
| 71 | tm->tm_wday = BCD2BIN(buf[RS5C372_REG_WDAY] & 0x07); | ||
| 72 | tm->tm_mday = BCD2BIN(buf[RS5C372_REG_DAY] & 0x3f); | ||
| 73 | |||
| 74 | /* tm->tm_mon is zero-based */ | ||
| 75 | tm->tm_mon = BCD2BIN(buf[RS5C372_REG_MONTH] & 0x1f) - 1; | ||
| 76 | |||
| 77 | /* year is 1900 + tm->tm_year */ | ||
| 78 | tm->tm_year = BCD2BIN(buf[RS5C372_REG_YEAR]) + 100; | ||
| 79 | |||
| 80 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | ||
| 81 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 82 | __FUNCTION__, | ||
| 83 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
| 84 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm) | ||
| 90 | { | ||
| 91 | unsigned char buf[8] = { RS5C372_REG_BASE }; | ||
| 92 | |||
| 93 | dev_dbg(&client->dev, | ||
| 94 | "%s: secs=%d, mins=%d, hours=%d ", | ||
| 95 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 96 | __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
| 97 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 98 | |||
| 99 | buf[1] = BIN2BCD(tm->tm_sec); | ||
| 100 | buf[2] = BIN2BCD(tm->tm_min); | ||
| 101 | buf[3] = BIN2BCD(tm->tm_hour); | ||
| 102 | buf[4] = BIN2BCD(tm->tm_wday); | ||
| 103 | buf[5] = BIN2BCD(tm->tm_mday); | ||
| 104 | buf[6] = BIN2BCD(tm->tm_mon + 1); | ||
| 105 | buf[7] = BIN2BCD(tm->tm_year - 100); | ||
| 106 | |||
| 107 | if ((i2c_master_send(client, buf, 8)) != 8) { | ||
| 108 | dev_err(&client->dev, "%s: write error\n", __FUNCTION__); | ||
| 109 | return -EIO; | ||
| 110 | } | ||
| 111 | |||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim) | ||
| 116 | { | ||
| 117 | unsigned char buf = RS5C372_REG_TRIM; | ||
| 118 | |||
| 119 | struct i2c_msg msgs[] = { | ||
| 120 | { client->addr, 0, 1, &buf }, | ||
| 121 | { client->addr, I2C_M_RD, 1, &buf }, | ||
| 122 | }; | ||
| 123 | |||
| 124 | if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { | ||
| 125 | dev_err(&client->dev, "%s: read error\n", __FUNCTION__); | ||
| 126 | return -EIO; | ||
| 127 | } | ||
| 128 | |||
| 129 | dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, trim); | ||
| 130 | |||
| 131 | if (osc) | ||
| 132 | *osc = (buf & RS5C372_TRIM_XSL) ? 32000 : 32768; | ||
| 133 | |||
| 134 | if (trim) | ||
| 135 | *trim = buf & RS5C372_TRIM_MASK; | ||
| 136 | |||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 141 | { | ||
| 142 | return rs5c372_get_datetime(to_i2c_client(dev), tm); | ||
| 143 | } | ||
| 144 | |||
| 145 | static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 146 | { | ||
| 147 | return rs5c372_set_datetime(to_i2c_client(dev), tm); | ||
| 148 | } | ||
| 149 | |||
| 150 | static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq) | ||
| 151 | { | ||
| 152 | int err, osc, trim; | ||
| 153 | |||
| 154 | seq_printf(seq, "24hr\t\t: yes\n"); | ||
| 155 | |||
| 156 | if ((err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim)) == 0) { | ||
| 157 | seq_printf(seq, "%d.%03d KHz\n", osc / 1000, osc % 1000); | ||
| 158 | seq_printf(seq, "trim\t: %d\n", trim); | ||
| 159 | } | ||
| 160 | |||
| 161 | return 0; | ||
| 162 | } | ||
| 163 | |||
| 164 | static struct rtc_class_ops rs5c372_rtc_ops = { | ||
| 165 | .proc = rs5c372_rtc_proc, | ||
| 166 | .read_time = rs5c372_rtc_read_time, | ||
| 167 | .set_time = rs5c372_rtc_set_time, | ||
| 168 | }; | ||
| 169 | |||
| 170 | static ssize_t rs5c372_sysfs_show_trim(struct device *dev, | ||
| 171 | struct device_attribute *attr, char *buf) | ||
| 172 | { | ||
| 173 | int trim; | ||
| 174 | |||
| 175 | if (rs5c372_get_trim(to_i2c_client(dev), NULL, &trim) == 0) | ||
| 176 | return sprintf(buf, "0x%2x\n", trim); | ||
| 177 | |||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | static DEVICE_ATTR(trim, S_IRUGO, rs5c372_sysfs_show_trim, NULL); | ||
| 181 | |||
| 182 | static ssize_t rs5c372_sysfs_show_osc(struct device *dev, | ||
| 183 | struct device_attribute *attr, char *buf) | ||
| 184 | { | ||
| 185 | int osc; | ||
| 186 | |||
| 187 | if (rs5c372_get_trim(to_i2c_client(dev), &osc, NULL) == 0) | ||
| 188 | return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000); | ||
| 189 | |||
| 190 | return 0; | ||
| 191 | } | ||
| 192 | static DEVICE_ATTR(osc, S_IRUGO, rs5c372_sysfs_show_osc, NULL); | ||
| 193 | |||
| 194 | static int rs5c372_attach(struct i2c_adapter *adapter) | ||
| 195 | { | ||
| 196 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | ||
| 197 | return i2c_probe(adapter, &addr_data, rs5c372_probe); | ||
| 198 | } | ||
| 199 | |||
| 200 | static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) | ||
| 201 | { | ||
| 202 | int err = 0; | ||
| 203 | struct i2c_client *client; | ||
| 204 | struct rtc_device *rtc; | ||
| 205 | |||
| 206 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | ||
| 207 | |||
| 208 | if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { | ||
| 209 | err = -ENODEV; | ||
| 210 | goto exit; | ||
| 211 | } | ||
| 212 | |||
| 213 | if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { | ||
| 214 | err = -ENOMEM; | ||
| 215 | goto exit; | ||
| 216 | } | ||
| 217 | |||
| 218 | /* I2C client */ | ||
| 219 | client->addr = address; | ||
| 220 | client->driver = &rs5c372_driver; | ||
| 221 | client->adapter = adapter; | ||
| 222 | |||
| 223 | strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE); | ||
| 224 | |||
| 225 | /* Inform the i2c layer */ | ||
| 226 | if ((err = i2c_attach_client(client))) | ||
| 227 | goto exit_kfree; | ||
| 228 | |||
| 229 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | ||
| 230 | |||
| 231 | rtc = rtc_device_register(rs5c372_driver.driver.name, &client->dev, | ||
| 232 | &rs5c372_rtc_ops, THIS_MODULE); | ||
| 233 | |||
| 234 | if (IS_ERR(rtc)) { | ||
| 235 | err = PTR_ERR(rtc); | ||
| 236 | dev_err(&client->dev, | ||
| 237 | "unable to register the class device\n"); | ||
| 238 | goto exit_detach; | ||
| 239 | } | ||
| 240 | |||
| 241 | i2c_set_clientdata(client, rtc); | ||
| 242 | |||
| 243 | device_create_file(&client->dev, &dev_attr_trim); | ||
| 244 | device_create_file(&client->dev, &dev_attr_osc); | ||
| 245 | |||
| 246 | return 0; | ||
| 247 | |||
| 248 | exit_detach: | ||
| 249 | i2c_detach_client(client); | ||
| 250 | |||
| 251 | exit_kfree: | ||
| 252 | kfree(client); | ||
| 253 | |||
| 254 | exit: | ||
| 255 | return err; | ||
| 256 | } | ||
| 257 | |||
| 258 | static int rs5c372_detach(struct i2c_client *client) | ||
| 259 | { | ||
| 260 | int err; | ||
| 261 | struct rtc_device *rtc = i2c_get_clientdata(client); | ||
| 262 | |||
| 263 | dev_dbg(&client->dev, "%s\n", __FUNCTION__); | ||
| 264 | |||
| 265 | if (rtc) | ||
| 266 | rtc_device_unregister(rtc); | ||
| 267 | |||
| 268 | if ((err = i2c_detach_client(client))) | ||
| 269 | return err; | ||
| 270 | |||
| 271 | kfree(client); | ||
| 272 | |||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | static __init int rs5c372_init(void) | ||
| 277 | { | ||
| 278 | return i2c_add_driver(&rs5c372_driver); | ||
| 279 | } | ||
| 280 | |||
| 281 | static __exit void rs5c372_exit(void) | ||
| 282 | { | ||
| 283 | i2c_del_driver(&rs5c372_driver); | ||
| 284 | } | ||
| 285 | |||
| 286 | module_init(rs5c372_init); | ||
| 287 | module_exit(rs5c372_exit); | ||
| 288 | |||
| 289 | MODULE_AUTHOR( | ||
| 290 | "Pavel Mironchik <pmironchik@optifacio.net>, " | ||
| 291 | "Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 292 | MODULE_DESCRIPTION("Ricoh RS5C372 RTC driver"); | ||
| 293 | MODULE_LICENSE("GPL"); | ||
| 294 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c new file mode 100644 index 000000000000..83b2bb480a16 --- /dev/null +++ b/drivers/rtc/rtc-sa1100.c | |||
| @@ -0,0 +1,388 @@ | |||
| 1 | /* | ||
| 2 | * Real Time Clock interface for StrongARM SA1x00 and XScale PXA2xx | ||
| 3 | * | ||
| 4 | * Copyright (c) 2000 Nils Faerber | ||
| 5 | * | ||
| 6 | * Based on rtc.c by Paul Gortmaker | ||
| 7 | * | ||
| 8 | * Original Driver by Nils Faerber <nils@kernelconcepts.de> | ||
| 9 | * | ||
| 10 | * Modifications from: | ||
| 11 | * CIH <cih@coventive.com> | ||
| 12 | * Nicolas Pitre <nico@cam.org> | ||
| 13 | * Andrew Christian <andrew.christian@hp.com> | ||
| 14 | * | ||
| 15 | * Converted to the RTC subsystem and Driver Model | ||
| 16 | * by Richard Purdie <rpurdie@rpsys.net> | ||
| 17 | * | ||
| 18 | * This program is free software; you can redistribute it and/or | ||
| 19 | * modify it under the terms of the GNU General Public License | ||
| 20 | * as published by the Free Software Foundation; either version | ||
| 21 | * 2 of the License, or (at your option) any later version. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/rtc.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/fs.h> | ||
| 29 | #include <linux/interrupt.h> | ||
| 30 | #include <linux/string.h> | ||
| 31 | #include <linux/pm.h> | ||
| 32 | |||
| 33 | #include <asm/bitops.h> | ||
| 34 | #include <asm/hardware.h> | ||
| 35 | #include <asm/irq.h> | ||
| 36 | #include <asm/rtc.h> | ||
| 37 | |||
| 38 | #ifdef CONFIG_ARCH_PXA | ||
| 39 | #include <asm/arch/pxa-regs.h> | ||
| 40 | #endif | ||
| 41 | |||
| 42 | #define TIMER_FREQ CLOCK_TICK_RATE | ||
| 43 | #define RTC_DEF_DIVIDER 32768 - 1 | ||
| 44 | #define RTC_DEF_TRIM 0 | ||
| 45 | |||
| 46 | static unsigned long rtc_freq = 1024; | ||
| 47 | static struct rtc_time rtc_alarm; | ||
| 48 | static spinlock_t sa1100_rtc_lock = SPIN_LOCK_UNLOCKED; | ||
| 49 | |||
| 50 | static int rtc_update_alarm(struct rtc_time *alrm) | ||
| 51 | { | ||
| 52 | struct rtc_time alarm_tm, now_tm; | ||
| 53 | unsigned long now, time; | ||
| 54 | int ret; | ||
| 55 | |||
| 56 | do { | ||
| 57 | now = RCNR; | ||
| 58 | rtc_time_to_tm(now, &now_tm); | ||
| 59 | rtc_next_alarm_time(&alarm_tm, &now_tm, alrm); | ||
| 60 | ret = rtc_tm_to_time(&alarm_tm, &time); | ||
| 61 | if (ret != 0) | ||
| 62 | break; | ||
| 63 | |||
| 64 | RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL); | ||
| 65 | RTAR = time; | ||
| 66 | } while (now != RCNR); | ||
| 67 | |||
| 68 | return ret; | ||
| 69 | } | ||
| 70 | |||
| 71 | static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id, | ||
| 72 | struct pt_regs *regs) | ||
| 73 | { | ||
| 74 | struct platform_device *pdev = to_platform_device(dev_id); | ||
| 75 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
| 76 | unsigned int rtsr; | ||
| 77 | unsigned long events = 0; | ||
| 78 | |||
| 79 | spin_lock(&sa1100_rtc_lock); | ||
| 80 | |||
| 81 | rtsr = RTSR; | ||
| 82 | /* clear interrupt sources */ | ||
| 83 | RTSR = 0; | ||
| 84 | RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2); | ||
| 85 | |||
| 86 | /* clear alarm interrupt if it has occurred */ | ||
| 87 | if (rtsr & RTSR_AL) | ||
| 88 | rtsr &= ~RTSR_ALE; | ||
| 89 | RTSR = rtsr & (RTSR_ALE | RTSR_HZE); | ||
| 90 | |||
| 91 | /* update irq data & counter */ | ||
| 92 | if (rtsr & RTSR_AL) | ||
| 93 | events |= RTC_AF | RTC_IRQF; | ||
| 94 | if (rtsr & RTSR_HZ) | ||
| 95 | events |= RTC_UF | RTC_IRQF; | ||
| 96 | |||
| 97 | rtc_update_irq(&rtc->class_dev, 1, events); | ||
| 98 | |||
| 99 | if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm)) | ||
| 100 | rtc_update_alarm(&rtc_alarm); | ||
| 101 | |||
| 102 | spin_unlock(&sa1100_rtc_lock); | ||
| 103 | |||
| 104 | return IRQ_HANDLED; | ||
| 105 | } | ||
| 106 | |||
| 107 | static int rtc_timer1_count; | ||
| 108 | |||
| 109 | static irqreturn_t timer1_interrupt(int irq, void *dev_id, | ||
| 110 | struct pt_regs *regs) | ||
| 111 | { | ||
| 112 | struct platform_device *pdev = to_platform_device(dev_id); | ||
| 113 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
| 114 | |||
| 115 | /* | ||
| 116 | * If we match for the first time, rtc_timer1_count will be 1. | ||
| 117 | * Otherwise, we wrapped around (very unlikely but | ||
| 118 | * still possible) so compute the amount of missed periods. | ||
| 119 | * The match reg is updated only when the data is actually retrieved | ||
| 120 | * to avoid unnecessary interrupts. | ||
| 121 | */ | ||
| 122 | OSSR = OSSR_M1; /* clear match on timer1 */ | ||
| 123 | |||
| 124 | rtc_update_irq(&rtc->class_dev, rtc_timer1_count, RTC_PF | RTC_IRQF); | ||
| 125 | |||
| 126 | if (rtc_timer1_count == 1) | ||
| 127 | rtc_timer1_count = (rtc_freq * ((1<<30)/(TIMER_FREQ>>2))); | ||
| 128 | |||
| 129 | return IRQ_HANDLED; | ||
| 130 | } | ||
| 131 | |||
| 132 | static int sa1100_rtc_read_callback(struct device *dev, int data) | ||
| 133 | { | ||
| 134 | if (data & RTC_PF) { | ||
| 135 | /* interpolate missed periods and set match for the next */ | ||
| 136 | unsigned long period = TIMER_FREQ/rtc_freq; | ||
| 137 | unsigned long oscr = OSCR; | ||
| 138 | unsigned long osmr1 = OSMR1; | ||
| 139 | unsigned long missed = (oscr - osmr1)/period; | ||
| 140 | data += missed << 8; | ||
| 141 | OSSR = OSSR_M1; /* clear match on timer 1 */ | ||
| 142 | OSMR1 = osmr1 + (missed + 1)*period; | ||
| 143 | /* Ensure we didn't miss another match in the mean time. | ||
| 144 | * Here we compare (match - OSCR) 8 instead of 0 -- | ||
| 145 | * see comment in pxa_timer_interrupt() for explanation. | ||
| 146 | */ | ||
| 147 | while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) { | ||
| 148 | data += 0x100; | ||
| 149 | OSSR = OSSR_M1; /* clear match on timer 1 */ | ||
| 150 | OSMR1 = osmr1 + period; | ||
| 151 | } | ||
| 152 | } | ||
| 153 | return data; | ||
| 154 | } | ||
| 155 | |||
| 156 | static int sa1100_rtc_open(struct device *dev) | ||
| 157 | { | ||
| 158 | int ret; | ||
| 159 | |||
| 160 | ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, SA_INTERRUPT, | ||
| 161 | "rtc 1Hz", dev); | ||
| 162 | if (ret) { | ||
| 163 | printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTC1Hz); | ||
| 164 | goto fail_ui; | ||
| 165 | } | ||
| 166 | ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, SA_INTERRUPT, | ||
| 167 | "rtc Alrm", dev); | ||
| 168 | if (ret) { | ||
| 169 | printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTCAlrm); | ||
| 170 | goto fail_ai; | ||
| 171 | } | ||
| 172 | ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT, | ||
| 173 | "rtc timer", dev); | ||
| 174 | if (ret) { | ||
| 175 | printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_OST1); | ||
| 176 | goto fail_pi; | ||
| 177 | } | ||
| 178 | return 0; | ||
| 179 | |||
| 180 | fail_pi: | ||
| 181 | free_irq(IRQ_RTCAlrm, NULL); | ||
| 182 | fail_ai: | ||
| 183 | free_irq(IRQ_RTC1Hz, NULL); | ||
| 184 | fail_ui: | ||
| 185 | return ret; | ||
| 186 | } | ||
| 187 | |||
| 188 | static void sa1100_rtc_release(struct device *dev) | ||
| 189 | { | ||
| 190 | spin_lock_irq(&sa1100_rtc_lock); | ||
| 191 | RTSR = 0; | ||
| 192 | OIER &= ~OIER_E1; | ||
| 193 | OSSR = OSSR_M1; | ||
| 194 | spin_unlock_irq(&sa1100_rtc_lock); | ||
| 195 | |||
| 196 | free_irq(IRQ_OST1, dev); | ||
| 197 | free_irq(IRQ_RTCAlrm, dev); | ||
| 198 | free_irq(IRQ_RTC1Hz, dev); | ||
| 199 | } | ||
| 200 | |||
| 201 | |||
| 202 | static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
| 203 | unsigned long arg) | ||
| 204 | { | ||
| 205 | switch(cmd) { | ||
| 206 | case RTC_AIE_OFF: | ||
| 207 | spin_lock_irq(&sa1100_rtc_lock); | ||
| 208 | RTSR &= ~RTSR_ALE; | ||
| 209 | spin_unlock_irq(&sa1100_rtc_lock); | ||
| 210 | return 0; | ||
| 211 | case RTC_AIE_ON: | ||
| 212 | spin_lock_irq(&sa1100_rtc_lock); | ||
| 213 | RTSR |= RTSR_ALE; | ||
| 214 | spin_unlock_irq(&sa1100_rtc_lock); | ||
| 215 | return 0; | ||
| 216 | case RTC_UIE_OFF: | ||
| 217 | spin_lock_irq(&sa1100_rtc_lock); | ||
| 218 | RTSR &= ~RTSR_HZE; | ||
| 219 | spin_unlock_irq(&sa1100_rtc_lock); | ||
| 220 | return 0; | ||
| 221 | case RTC_UIE_ON: | ||
| 222 | spin_lock_irq(&sa1100_rtc_lock); | ||
| 223 | RTSR |= RTSR_HZE; | ||
| 224 | spin_unlock_irq(&sa1100_rtc_lock); | ||
| 225 | return 0; | ||
| 226 | case RTC_PIE_OFF: | ||
| 227 | spin_lock_irq(&sa1100_rtc_lock); | ||
| 228 | OIER &= ~OIER_E1; | ||
| 229 | spin_unlock_irq(&sa1100_rtc_lock); | ||
| 230 | return 0; | ||
| 231 | case RTC_PIE_ON: | ||
| 232 | if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE)) | ||
| 233 | return -EACCES; | ||
| 234 | spin_lock_irq(&sa1100_rtc_lock); | ||
| 235 | OSMR1 = TIMER_FREQ/rtc_freq + OSCR; | ||
| 236 | OIER |= OIER_E1; | ||
| 237 | rtc_timer1_count = 1; | ||
| 238 | spin_unlock_irq(&sa1100_rtc_lock); | ||
| 239 | return 0; | ||
| 240 | case RTC_IRQP_READ: | ||
| 241 | return put_user(rtc_freq, (unsigned long *)arg); | ||
| 242 | case RTC_IRQP_SET: | ||
| 243 | if (arg < 1 || arg > TIMER_FREQ) | ||
| 244 | return -EINVAL; | ||
| 245 | if ((arg > 64) && (!capable(CAP_SYS_RESOURCE))) | ||
| 246 | return -EACCES; | ||
| 247 | rtc_freq = arg; | ||
| 248 | return 0; | ||
| 249 | } | ||
| 250 | return -EINVAL; | ||
| 251 | } | ||
| 252 | |||
| 253 | static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
| 254 | { | ||
| 255 | rtc_time_to_tm(RCNR, tm); | ||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
| 260 | { | ||
| 261 | unsigned long time; | ||
| 262 | int ret; | ||
| 263 | |||
| 264 | ret = rtc_tm_to_time(tm, &time); | ||
| 265 | if (ret == 0) | ||
| 266 | RCNR = time; | ||
| 267 | return ret; | ||
| 268 | } | ||
| 269 | |||
| 270 | static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 271 | { | ||
| 272 | memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time)); | ||
| 273 | alrm->pending = RTSR & RTSR_AL ? 1 : 0; | ||
| 274 | return 0; | ||
| 275 | } | ||
| 276 | |||
| 277 | static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
| 278 | { | ||
| 279 | int ret; | ||
| 280 | |||
| 281 | spin_lock_irq(&sa1100_rtc_lock); | ||
| 282 | ret = rtc_update_alarm(&alrm->time); | ||
| 283 | if (ret == 0) { | ||
| 284 | memcpy(&rtc_alarm, &alrm->time, sizeof(struct rtc_time)); | ||
| 285 | |||
| 286 | if (alrm->enabled) | ||
| 287 | enable_irq_wake(IRQ_RTCAlrm); | ||
| 288 | else | ||
| 289 | disable_irq_wake(IRQ_RTCAlrm); | ||
| 290 | } | ||
| 291 | spin_unlock_irq(&sa1100_rtc_lock); | ||
| 292 | |||
| 293 | return ret; | ||
| 294 | } | ||
| 295 | |||
| 296 | static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq) | ||
| 297 | { | ||
| 298 | seq_printf(seq, "trim/divider\t: 0x%08x\n", RTTR); | ||
| 299 | seq_printf(seq, "alarm_IRQ\t: %s\n", | ||
| 300 | (RTSR & RTSR_ALE) ? "yes" : "no" ); | ||
| 301 | seq_printf(seq, "update_IRQ\t: %s\n", | ||
| 302 | (RTSR & RTSR_HZE) ? "yes" : "no"); | ||
| 303 | seq_printf(seq, "periodic_IRQ\t: %s\n", | ||
| 304 | (OIER & OIER_E1) ? "yes" : "no"); | ||
| 305 | seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq); | ||
| 306 | |||
| 307 | return 0; | ||
| 308 | } | ||
| 309 | |||
| 310 | static struct rtc_class_ops sa1100_rtc_ops = { | ||
| 311 | .open = sa1100_rtc_open, | ||
| 312 | .read_callback = sa1100_rtc_read_callback, | ||
| 313 | .release = sa1100_rtc_release, | ||
| 314 | .ioctl = sa1100_rtc_ioctl, | ||
| 315 | .read_time = sa1100_rtc_read_time, | ||
| 316 | .set_time = sa1100_rtc_set_time, | ||
| 317 | .read_alarm = sa1100_rtc_read_alarm, | ||
| 318 | .set_alarm = sa1100_rtc_set_alarm, | ||
| 319 | .proc = sa1100_rtc_proc, | ||
| 320 | }; | ||
| 321 | |||
| 322 | static int sa1100_rtc_probe(struct platform_device *pdev) | ||
| 323 | { | ||
| 324 | struct rtc_device *rtc; | ||
| 325 | |||
| 326 | /* | ||
| 327 | * According to the manual we should be able to let RTTR be zero | ||
| 328 | * and then a default diviser for a 32.768KHz clock is used. | ||
| 329 | * Apparently this doesn't work, at least for my SA1110 rev 5. | ||
| 330 | * If the clock divider is uninitialized then reset it to the | ||
| 331 | * default value to get the 1Hz clock. | ||
| 332 | */ | ||
| 333 | if (RTTR == 0) { | ||
| 334 | RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); | ||
| 335 | printk(KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n"); | ||
| 336 | /* The current RTC value probably doesn't make sense either */ | ||
| 337 | RCNR = 0; | ||
| 338 | } | ||
| 339 | |||
| 340 | rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, | ||
| 341 | THIS_MODULE); | ||
| 342 | |||
| 343 | if (IS_ERR(rtc)) { | ||
| 344 | dev_err(&pdev->dev, "Unable to register the RTC device\n"); | ||
| 345 | return PTR_ERR(rtc); | ||
| 346 | } | ||
| 347 | |||
| 348 | platform_set_drvdata(pdev, rtc); | ||
| 349 | |||
| 350 | dev_info(&pdev->dev, "SA11xx/PXA2xx RTC Registered\n"); | ||
| 351 | |||
| 352 | return 0; | ||
| 353 | } | ||
| 354 | |||
| 355 | static int sa1100_rtc_remove(struct platform_device *pdev) | ||
| 356 | { | ||
| 357 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
| 358 | |||
| 359 | if (rtc) | ||
| 360 | rtc_device_unregister(rtc); | ||
| 361 | |||
| 362 | return 0; | ||
| 363 | } | ||
| 364 | |||
| 365 | static struct platform_driver sa1100_rtc_driver = { | ||
| 366 | .probe = sa1100_rtc_probe, | ||
| 367 | .remove = sa1100_rtc_remove, | ||
| 368 | .driver = { | ||
| 369 | .name = "sa1100-rtc", | ||
| 370 | }, | ||
| 371 | }; | ||
| 372 | |||
| 373 | static int __init sa1100_rtc_init(void) | ||
| 374 | { | ||
| 375 | return platform_driver_register(&sa1100_rtc_driver); | ||
| 376 | } | ||
| 377 | |||
| 378 | static void __exit sa1100_rtc_exit(void) | ||
| 379 | { | ||
| 380 | platform_driver_unregister(&sa1100_rtc_driver); | ||
| 381 | } | ||
| 382 | |||
| 383 | module_init(sa1100_rtc_init); | ||
| 384 | module_exit(sa1100_rtc_exit); | ||
| 385 | |||
| 386 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
| 387 | MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)"); | ||
| 388 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c new file mode 100644 index 000000000000..7c1f3d2e53c4 --- /dev/null +++ b/drivers/rtc/rtc-sysfs.c | |||
| @@ -0,0 +1,124 @@ | |||
| 1 | /* | ||
| 2 | * RTC subsystem, sysfs interface | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Tower Technologies | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/rtc.h> | ||
| 14 | |||
| 15 | /* device attributes */ | ||
| 16 | |||
| 17 | static ssize_t rtc_sysfs_show_name(struct class_device *dev, char *buf) | ||
| 18 | { | ||
| 19 | return sprintf(buf, "%s\n", to_rtc_device(dev)->name); | ||
| 20 | } | ||
| 21 | static CLASS_DEVICE_ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL); | ||
| 22 | |||
| 23 | static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf) | ||
| 24 | { | ||
| 25 | ssize_t retval; | ||
| 26 | struct rtc_time tm; | ||
| 27 | |||
| 28 | retval = rtc_read_time(dev, &tm); | ||
| 29 | if (retval == 0) { | ||
| 30 | retval = sprintf(buf, "%04d-%02d-%02d\n", | ||
| 31 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); | ||
| 32 | } | ||
| 33 | |||
| 34 | return retval; | ||
| 35 | } | ||
| 36 | static CLASS_DEVICE_ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL); | ||
| 37 | |||
| 38 | static ssize_t rtc_sysfs_show_time(struct class_device *dev, char *buf) | ||
| 39 | { | ||
| 40 | ssize_t retval; | ||
| 41 | struct rtc_time tm; | ||
| 42 | |||
| 43 | retval = rtc_read_time(dev, &tm); | ||
| 44 | if (retval == 0) { | ||
| 45 | retval = sprintf(buf, "%02d:%02d:%02d\n", | ||
| 46 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
| 47 | } | ||
| 48 | |||
| 49 | return retval; | ||
| 50 | } | ||
| 51 | static CLASS_DEVICE_ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL); | ||
| 52 | |||
| 53 | static ssize_t rtc_sysfs_show_since_epoch(struct class_device *dev, char *buf) | ||
| 54 | { | ||
| 55 | ssize_t retval; | ||
| 56 | struct rtc_time tm; | ||
| 57 | |||
| 58 | retval = rtc_read_time(dev, &tm); | ||
| 59 | if (retval == 0) { | ||
| 60 | unsigned long time; | ||
| 61 | rtc_tm_to_time(&tm, &time); | ||
| 62 | retval = sprintf(buf, "%lu\n", time); | ||
| 63 | } | ||
| 64 | |||
| 65 | return retval; | ||
| 66 | } | ||
| 67 | static CLASS_DEVICE_ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL); | ||
| 68 | |||
| 69 | static struct attribute *rtc_attrs[] = { | ||
| 70 | &class_device_attr_name.attr, | ||
| 71 | &class_device_attr_date.attr, | ||
| 72 | &class_device_attr_time.attr, | ||
| 73 | &class_device_attr_since_epoch.attr, | ||
| 74 | NULL, | ||
| 75 | }; | ||
| 76 | |||
| 77 | static struct attribute_group rtc_attr_group = { | ||
| 78 | .attrs = rtc_attrs, | ||
| 79 | }; | ||
| 80 | |||
| 81 | static int __devinit rtc_sysfs_add_device(struct class_device *class_dev, | ||
| 82 | struct class_interface *class_intf) | ||
| 83 | { | ||
| 84 | int err; | ||
| 85 | |||
| 86 | dev_info(class_dev->dev, "rtc intf: sysfs\n"); | ||
| 87 | |||
| 88 | err = sysfs_create_group(&class_dev->kobj, &rtc_attr_group); | ||
| 89 | if (err) | ||
| 90 | dev_err(class_dev->dev, | ||
| 91 | "failed to create sysfs attributes\n"); | ||
| 92 | |||
| 93 | return err; | ||
| 94 | } | ||
| 95 | |||
| 96 | static void rtc_sysfs_remove_device(struct class_device *class_dev, | ||
| 97 | struct class_interface *class_intf) | ||
| 98 | { | ||
| 99 | sysfs_remove_group(&class_dev->kobj, &rtc_attr_group); | ||
| 100 | } | ||
| 101 | |||
| 102 | /* interface registration */ | ||
| 103 | |||
| 104 | static struct class_interface rtc_sysfs_interface = { | ||
| 105 | .add = &rtc_sysfs_add_device, | ||
| 106 | .remove = &rtc_sysfs_remove_device, | ||
| 107 | }; | ||
| 108 | |||
| 109 | static int __init rtc_sysfs_init(void) | ||
| 110 | { | ||
| 111 | return rtc_interface_register(&rtc_sysfs_interface); | ||
| 112 | } | ||
| 113 | |||
| 114 | static void __exit rtc_sysfs_exit(void) | ||
| 115 | { | ||
| 116 | class_interface_unregister(&rtc_sysfs_interface); | ||
| 117 | } | ||
| 118 | |||
| 119 | module_init(rtc_sysfs_init); | ||
| 120 | module_exit(rtc_sysfs_exit); | ||
| 121 | |||
| 122 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 123 | MODULE_DESCRIPTION("RTC class sysfs interface"); | ||
| 124 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c new file mode 100644 index 000000000000..43d107487820 --- /dev/null +++ b/drivers/rtc/rtc-test.c | |||
| @@ -0,0 +1,204 @@ | |||
| 1 | /* | ||
| 2 | * An RTC test device/driver | ||
| 3 | * Copyright (C) 2005 Tower Technologies | ||
| 4 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/err.h> | ||
| 13 | #include <linux/rtc.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | |||
| 16 | static struct platform_device *test0 = NULL, *test1 = NULL; | ||
| 17 | |||
| 18 | static int test_rtc_read_alarm(struct device *dev, | ||
| 19 | struct rtc_wkalrm *alrm) | ||
| 20 | { | ||
| 21 | return 0; | ||
| 22 | } | ||
| 23 | |||
| 24 | static int test_rtc_set_alarm(struct device *dev, | ||
| 25 | struct rtc_wkalrm *alrm) | ||
| 26 | { | ||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | |||
| 30 | static int test_rtc_read_time(struct device *dev, | ||
| 31 | struct rtc_time *tm) | ||
| 32 | { | ||
| 33 | rtc_time_to_tm(get_seconds(), tm); | ||
| 34 | return 0; | ||
| 35 | } | ||
| 36 | |||
| 37 | static int test_rtc_set_time(struct device *dev, | ||
| 38 | struct rtc_time *tm) | ||
| 39 | { | ||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | static int test_rtc_set_mmss(struct device *dev, unsigned long secs) | ||
| 44 | { | ||
| 45 | return 0; | ||
| 46 | } | ||
| 47 | |||
| 48 | static int test_rtc_proc(struct device *dev, struct seq_file *seq) | ||
| 49 | { | ||
| 50 | struct platform_device *plat_dev = to_platform_device(dev); | ||
| 51 | |||
| 52 | seq_printf(seq, "24hr\t\t: yes\n"); | ||
| 53 | seq_printf(seq, "test\t\t: yes\n"); | ||
| 54 | seq_printf(seq, "id\t\t: %d\n", plat_dev->id); | ||
| 55 | |||
| 56 | return 0; | ||
| 57 | } | ||
| 58 | |||
| 59 | static int test_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
| 60 | unsigned long arg) | ||
| 61 | { | ||
| 62 | /* We do support interrupts, they're generated | ||
| 63 | * using the sysfs interface. | ||
| 64 | */ | ||
| 65 | switch (cmd) { | ||
| 66 | case RTC_PIE_ON: | ||
| 67 | case RTC_PIE_OFF: | ||
| 68 | case RTC_UIE_ON: | ||
| 69 | case RTC_UIE_OFF: | ||
| 70 | case RTC_AIE_ON: | ||
| 71 | case RTC_AIE_OFF: | ||
| 72 | return 0; | ||
| 73 | |||
| 74 | default: | ||
| 75 | return -EINVAL; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | static struct rtc_class_ops test_rtc_ops = { | ||
| 80 | .proc = test_rtc_proc, | ||
| 81 | .read_time = test_rtc_read_time, | ||
| 82 | .set_time = test_rtc_set_time, | ||
| 83 | .read_alarm = test_rtc_read_alarm, | ||
| 84 | .set_alarm = test_rtc_set_alarm, | ||
| 85 | .set_mmss = test_rtc_set_mmss, | ||
| 86 | .ioctl = test_rtc_ioctl, | ||
| 87 | }; | ||
| 88 | |||
| 89 | static ssize_t test_irq_show(struct device *dev, | ||
| 90 | struct device_attribute *attr, char *buf) | ||
| 91 | { | ||
| 92 | return sprintf(buf, "%d\n", 42); | ||
| 93 | } | ||
| 94 | static ssize_t test_irq_store(struct device *dev, | ||
| 95 | struct device_attribute *attr, | ||
| 96 | const char *buf, size_t count) | ||
| 97 | { | ||
| 98 | int retval; | ||
| 99 | struct platform_device *plat_dev = to_platform_device(dev); | ||
| 100 | struct rtc_device *rtc = platform_get_drvdata(plat_dev); | ||
| 101 | |||
| 102 | retval = count; | ||
| 103 | if (strncmp(buf, "tick", 4) == 0) | ||
| 104 | rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF); | ||
| 105 | else if (strncmp(buf, "alarm", 5) == 0) | ||
| 106 | rtc_update_irq(&rtc->class_dev, 1, RTC_AF | RTC_IRQF); | ||
| 107 | else if (strncmp(buf, "update", 6) == 0) | ||
| 108 | rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF); | ||
| 109 | else | ||
| 110 | retval = -EINVAL; | ||
| 111 | |||
| 112 | return retval; | ||
| 113 | } | ||
| 114 | static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store); | ||
| 115 | |||
| 116 | static int test_probe(struct platform_device *plat_dev) | ||
| 117 | { | ||
| 118 | int err; | ||
| 119 | struct rtc_device *rtc = rtc_device_register("test", &plat_dev->dev, | ||
| 120 | &test_rtc_ops, THIS_MODULE); | ||
| 121 | if (IS_ERR(rtc)) { | ||
| 122 | err = PTR_ERR(rtc); | ||
| 123 | dev_err(&plat_dev->dev, | ||
| 124 | "unable to register the class device\n"); | ||
| 125 | return err; | ||
| 126 | } | ||
| 127 | device_create_file(&plat_dev->dev, &dev_attr_irq); | ||
| 128 | |||
| 129 | platform_set_drvdata(plat_dev, rtc); | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int __devexit test_remove(struct platform_device *plat_dev) | ||
| 135 | { | ||
| 136 | struct rtc_device *rtc = platform_get_drvdata(plat_dev); | ||
| 137 | |||
| 138 | rtc_device_unregister(rtc); | ||
| 139 | device_remove_file(&plat_dev->dev, &dev_attr_irq); | ||
| 140 | |||
| 141 | return 0; | ||
| 142 | } | ||
| 143 | |||
| 144 | static struct platform_driver test_drv = { | ||
| 145 | .probe = test_probe, | ||
| 146 | .remove = __devexit_p(test_remove), | ||
| 147 | .driver = { | ||
| 148 | .name = "rtc-test", | ||
| 149 | .owner = THIS_MODULE, | ||
| 150 | }, | ||
| 151 | }; | ||
| 152 | |||
| 153 | static int __init test_init(void) | ||
| 154 | { | ||
| 155 | int err; | ||
| 156 | |||
| 157 | if ((err = platform_driver_register(&test_drv))) | ||
| 158 | return err; | ||
| 159 | |||
| 160 | if ((test0 = platform_device_alloc("rtc-test", 0)) == NULL) { | ||
| 161 | err = -ENOMEM; | ||
| 162 | goto exit_driver_unregister; | ||
| 163 | } | ||
| 164 | |||
| 165 | if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) { | ||
| 166 | err = -ENOMEM; | ||
| 167 | goto exit_free_test0; | ||
| 168 | } | ||
| 169 | |||
| 170 | if ((err = platform_device_add(test0))) | ||
| 171 | goto exit_free_test1; | ||
| 172 | |||
| 173 | if ((err = platform_device_add(test1))) | ||
| 174 | goto exit_device_unregister; | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | |||
| 178 | exit_device_unregister: | ||
| 179 | platform_device_unregister(test0); | ||
| 180 | |||
| 181 | exit_free_test1: | ||
| 182 | platform_device_put(test1); | ||
| 183 | |||
| 184 | exit_free_test0: | ||
| 185 | platform_device_put(test0); | ||
| 186 | |||
| 187 | exit_driver_unregister: | ||
| 188 | platform_driver_unregister(&test_drv); | ||
| 189 | return err; | ||
| 190 | } | ||
| 191 | |||
| 192 | static void __exit test_exit(void) | ||
| 193 | { | ||
| 194 | platform_device_unregister(test0); | ||
| 195 | platform_device_unregister(test1); | ||
| 196 | platform_driver_unregister(&test_drv); | ||
| 197 | } | ||
| 198 | |||
| 199 | MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
| 200 | MODULE_DESCRIPTION("RTC test driver/device"); | ||
| 201 | MODULE_LICENSE("GPL"); | ||
| 202 | |||
| 203 | module_init(test_init); | ||
| 204 | module_exit(test_exit); | ||
diff --git a/drivers/i2c/chips/x1205.c b/drivers/rtc/rtc-x1205.c index 245fffa92dbd..621d17afc0d9 100644 --- a/drivers/i2c/chips/x1205.c +++ b/drivers/rtc/rtc-x1205.c | |||
| @@ -1,32 +1,25 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * x1205.c - An i2c driver for the Xicor X1205 RTC | 2 | * An i2c driver for the Xicor/Intersil X1205 RTC |
| 3 | * Copyright 2004 Karen Spearel | 3 | * Copyright 2004 Karen Spearel |
| 4 | * Copyright 2005 Alessandro Zummo | 4 | * Copyright 2005 Alessandro Zummo |
| 5 | * | 5 | * |
| 6 | * please send all reports to: | 6 | * please send all reports to: |
| 7 | * kas11 at tampabay dot rr dot com | 7 | * Karen Spearel <kas111 at gmail dot com> |
| 8 | * a dot zummo at towertech dot it | 8 | * Alessandro Zummo <a.zummo@towertech.it> |
| 9 | * | 9 | * |
| 10 | * based on the other drivers in this same directory. | 10 | * based on a lot of other RTC drivers. |
| 11 | * | 11 | * |
| 12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
| 13 | * it under the terms of the GNU General Public License as published by | 13 | * it under the terms of the GNU General Public License version 2 as |
| 14 | * the Free Software Foundation; either version 2 of the License, or | 14 | * published by the Free Software Foundation. |
| 15 | * (at your option) any later version. | ||
| 16 | */ | 15 | */ |
| 17 | 16 | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/init.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
| 22 | #include <linux/string.h> | ||
| 23 | #include <linux/bcd.h> | 18 | #include <linux/bcd.h> |
| 24 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
| 25 | #include <linux/list.h> | 20 | #include <linux/delay.h> |
| 26 | 21 | ||
| 27 | #include <linux/x1205.h> | 22 | #define DRV_VERSION "1.0.6" |
| 28 | |||
| 29 | #define DRV_VERSION "0.9.9" | ||
| 30 | 23 | ||
| 31 | /* Addresses to scan: none. This chip is located at | 24 | /* Addresses to scan: none. This chip is located at |
| 32 | * 0x6f and uses a two bytes register addressing. | 25 | * 0x6f and uses a two bytes register addressing. |
| @@ -40,8 +33,6 @@ static unsigned short normal_i2c[] = { I2C_CLIENT_END }; | |||
| 40 | 33 | ||
| 41 | /* Insmod parameters */ | 34 | /* Insmod parameters */ |
| 42 | I2C_CLIENT_INSMOD; | 35 | I2C_CLIENT_INSMOD; |
| 43 | I2C_CLIENT_MODULE_PARM(hctosys, | ||
| 44 | "Set the system time from the hardware clock upon initialization"); | ||
| 45 | 36 | ||
| 46 | /* offsets into CCR area */ | 37 | /* offsets into CCR area */ |
| 47 | 38 | ||
| @@ -101,107 +92,35 @@ I2C_CLIENT_MODULE_PARM(hctosys, | |||
| 101 | static int x1205_attach(struct i2c_adapter *adapter); | 92 | static int x1205_attach(struct i2c_adapter *adapter); |
| 102 | static int x1205_detach(struct i2c_client *client); | 93 | static int x1205_detach(struct i2c_client *client); |
| 103 | static int x1205_probe(struct i2c_adapter *adapter, int address, int kind); | 94 | static int x1205_probe(struct i2c_adapter *adapter, int address, int kind); |
| 104 | static int x1205_command(struct i2c_client *client, unsigned int cmd, | ||
| 105 | void *arg); | ||
| 106 | 95 | ||
| 107 | static struct i2c_driver x1205_driver = { | 96 | static struct i2c_driver x1205_driver = { |
| 108 | .driver = { | 97 | .driver = { |
| 109 | .name = "x1205", | 98 | .name = "x1205", |
| 110 | }, | 99 | }, |
| 100 | .id = I2C_DRIVERID_X1205, | ||
| 111 | .attach_adapter = &x1205_attach, | 101 | .attach_adapter = &x1205_attach, |
| 112 | .detach_client = &x1205_detach, | 102 | .detach_client = &x1205_detach, |
| 113 | }; | 103 | }; |
| 114 | 104 | ||
| 115 | struct x1205_data { | ||
| 116 | struct i2c_client client; | ||
| 117 | struct list_head list; | ||
| 118 | unsigned int epoch; | ||
| 119 | }; | ||
| 120 | |||
| 121 | static const unsigned char days_in_mo[] = | ||
| 122 | { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; | ||
| 123 | |||
| 124 | static LIST_HEAD(x1205_clients); | ||
| 125 | |||
| 126 | /* Workaround until the I2C subsytem will allow to send | ||
| 127 | * commands to a specific client. This function will send the command | ||
| 128 | * to the first client. | ||
| 129 | */ | ||
| 130 | int x1205_do_command(unsigned int cmd, void *arg) | ||
| 131 | { | ||
| 132 | struct list_head *walk; | ||
| 133 | struct list_head *tmp; | ||
| 134 | struct x1205_data *data; | ||
| 135 | |||
| 136 | list_for_each_safe(walk, tmp, &x1205_clients) { | ||
| 137 | data = list_entry(walk, struct x1205_data, list); | ||
| 138 | return x1205_command(&data->client, cmd, arg); | ||
| 139 | } | ||
| 140 | |||
| 141 | return -ENODEV; | ||
| 142 | } | ||
| 143 | |||
| 144 | #define is_leap(year) \ | ||
| 145 | ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) | ||
| 146 | |||
| 147 | /* make sure the rtc_time values are in bounds */ | ||
| 148 | static int x1205_validate_tm(struct rtc_time *tm) | ||
| 149 | { | ||
| 150 | int year = tm->tm_year + 1900; | ||
| 151 | |||
| 152 | if ((tm->tm_year < 70) || (tm->tm_year > 255)) | ||
| 153 | return -EINVAL; | ||
| 154 | |||
| 155 | if ((tm->tm_mon > 11) || (tm->tm_mday == 0)) | ||
| 156 | return -EINVAL; | ||
| 157 | |||
| 158 | if (tm->tm_mday > days_in_mo[tm->tm_mon] | ||
| 159 | + ((tm->tm_mon == 1) && is_leap(year))) | ||
| 160 | return -EINVAL; | ||
| 161 | |||
| 162 | if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60)) | ||
| 163 | return -EINVAL; | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | /* | 105 | /* |
| 169 | * In the routines that deal directly with the x1205 hardware, we use | 106 | * In the routines that deal directly with the x1205 hardware, we use |
| 170 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch | 107 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch |
| 171 | * Epoch is initialized as 2000. Time is set to UTC. | 108 | * Epoch is initialized as 2000. Time is set to UTC. |
| 172 | */ | 109 | */ |
| 173 | static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, | 110 | static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, |
| 174 | u8 reg_base) | 111 | unsigned char reg_base) |
| 175 | { | 112 | { |
| 176 | unsigned char dt_addr[2] = { 0, reg_base }; | 113 | unsigned char dt_addr[2] = { 0, reg_base }; |
| 177 | static unsigned char sr_addr[2] = { 0, X1205_REG_SR }; | ||
| 178 | 114 | ||
| 179 | unsigned char buf[8], sr; | 115 | unsigned char buf[8]; |
| 180 | 116 | ||
| 181 | struct i2c_msg msgs[] = { | 117 | struct i2c_msg msgs[] = { |
| 182 | { client->addr, 0, 2, sr_addr }, /* setup read ptr */ | ||
| 183 | { client->addr, I2C_M_RD, 1, &sr }, /* read status */ | ||
| 184 | { client->addr, 0, 2, dt_addr }, /* setup read ptr */ | 118 | { client->addr, 0, 2, dt_addr }, /* setup read ptr */ |
| 185 | { client->addr, I2C_M_RD, 8, buf }, /* read date */ | 119 | { client->addr, I2C_M_RD, 8, buf }, /* read date */ |
| 186 | }; | 120 | }; |
| 187 | 121 | ||
| 188 | struct x1205_data *data = i2c_get_clientdata(client); | ||
| 189 | |||
| 190 | /* read status register */ | ||
| 191 | if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { | ||
| 192 | dev_err(&client->dev, "%s: read error\n", __FUNCTION__); | ||
| 193 | return -EIO; | ||
| 194 | } | ||
| 195 | |||
| 196 | /* check for battery failure */ | ||
| 197 | if (sr & X1205_SR_RTCF) { | ||
| 198 | dev_warn(&client->dev, | ||
| 199 | "Clock had a power failure, you must set the date.\n"); | ||
| 200 | return -EINVAL; | ||
| 201 | } | ||
| 202 | |||
| 203 | /* read date registers */ | 122 | /* read date registers */ |
| 204 | if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) { | 123 | if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { |
| 205 | dev_err(&client->dev, "%s: read error\n", __FUNCTION__); | 124 | dev_err(&client->dev, "%s: read error\n", __FUNCTION__); |
| 206 | return -EIO; | 125 | return -EIO; |
| 207 | } | 126 | } |
| @@ -217,9 +136,9 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
| 217 | tm->tm_min = BCD2BIN(buf[CCR_MIN]); | 136 | tm->tm_min = BCD2BIN(buf[CCR_MIN]); |
| 218 | tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */ | 137 | tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */ |
| 219 | tm->tm_mday = BCD2BIN(buf[CCR_MDAY]); | 138 | tm->tm_mday = BCD2BIN(buf[CCR_MDAY]); |
| 220 | tm->tm_mon = BCD2BIN(buf[CCR_MONTH]); | 139 | tm->tm_mon = BCD2BIN(buf[CCR_MONTH]) - 1; /* mon is 0-11 */ |
| 221 | data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100; | 140 | tm->tm_year = BCD2BIN(buf[CCR_YEAR]) |
| 222 | tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900; | 141 | + (BCD2BIN(buf[CCR_Y2K]) * 100) - 1900; |
| 223 | tm->tm_wday = buf[CCR_WDAY]; | 142 | tm->tm_wday = buf[CCR_WDAY]; |
| 224 | 143 | ||
| 225 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | 144 | dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " |
| @@ -231,11 +150,28 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
| 231 | return 0; | 150 | return 0; |
| 232 | } | 151 | } |
| 233 | 152 | ||
| 153 | static int x1205_get_status(struct i2c_client *client, unsigned char *sr) | ||
| 154 | { | ||
| 155 | static unsigned char sr_addr[2] = { 0, X1205_REG_SR }; | ||
| 156 | |||
| 157 | struct i2c_msg msgs[] = { | ||
| 158 | { client->addr, 0, 2, sr_addr }, /* setup read ptr */ | ||
| 159 | { client->addr, I2C_M_RD, 1, sr }, /* read status */ | ||
| 160 | }; | ||
| 161 | |||
| 162 | /* read status register */ | ||
| 163 | if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { | ||
| 164 | dev_err(&client->dev, "%s: read error\n", __FUNCTION__); | ||
| 165 | return -EIO; | ||
| 166 | } | ||
| 167 | |||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 234 | static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | 171 | static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, |
| 235 | int datetoo, u8 reg_base) | 172 | int datetoo, u8 reg_base) |
| 236 | { | 173 | { |
| 237 | int i, err, xfer; | 174 | int i, xfer; |
| 238 | |||
| 239 | unsigned char buf[8]; | 175 | unsigned char buf[8]; |
| 240 | 176 | ||
| 241 | static const unsigned char wel[3] = { 0, X1205_REG_SR, | 177 | static const unsigned char wel[3] = { 0, X1205_REG_SR, |
| @@ -246,17 +182,10 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
| 246 | 182 | ||
| 247 | static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; | 183 | static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; |
| 248 | 184 | ||
| 249 | struct x1205_data *data = i2c_get_clientdata(client); | 185 | dev_dbg(&client->dev, |
| 250 | 186 | "%s: secs=%d, mins=%d, hours=%d\n", | |
| 251 | /* check if all values in the tm struct are correct */ | ||
| 252 | if ((err = x1205_validate_tm(tm)) < 0) | ||
| 253 | return err; | ||
| 254 | |||
| 255 | dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, " | ||
| 256 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 257 | __FUNCTION__, | 187 | __FUNCTION__, |
| 258 | tm->tm_sec, tm->tm_min, tm->tm_hour, | 188 | tm->tm_sec, tm->tm_min, tm->tm_hour); |
| 259 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 260 | 189 | ||
| 261 | buf[CCR_SEC] = BIN2BCD(tm->tm_sec); | 190 | buf[CCR_SEC] = BIN2BCD(tm->tm_sec); |
| 262 | buf[CCR_MIN] = BIN2BCD(tm->tm_min); | 191 | buf[CCR_MIN] = BIN2BCD(tm->tm_min); |
| @@ -266,26 +195,29 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
| 266 | 195 | ||
| 267 | /* should we also set the date? */ | 196 | /* should we also set the date? */ |
| 268 | if (datetoo) { | 197 | if (datetoo) { |
| 198 | dev_dbg(&client->dev, | ||
| 199 | "%s: mday=%d, mon=%d, year=%d, wday=%d\n", | ||
| 200 | __FUNCTION__, | ||
| 201 | tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); | ||
| 202 | |||
| 269 | buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); | 203 | buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); |
| 270 | 204 | ||
| 271 | /* month, 0 - 11 */ | 205 | /* month, 1 - 12 */ |
| 272 | buf[CCR_MONTH] = BIN2BCD(tm->tm_mon); | 206 | buf[CCR_MONTH] = BIN2BCD(tm->tm_mon + 1); |
| 273 | 207 | ||
| 274 | /* year, since 1900 */ | 208 | /* year, since the rtc epoch*/ |
| 275 | buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch); | 209 | buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100); |
| 276 | buf[CCR_WDAY] = tm->tm_wday & 0x07; | 210 | buf[CCR_WDAY] = tm->tm_wday & 0x07; |
| 277 | buf[CCR_Y2K] = BIN2BCD(data->epoch / 100); | 211 | buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100); |
| 278 | } | 212 | } |
| 279 | 213 | ||
| 280 | /* this sequence is required to unlock the chip */ | 214 | /* this sequence is required to unlock the chip */ |
| 281 | xfer = i2c_master_send(client, wel, 3); | 215 | if ((xfer = i2c_master_send(client, wel, 3)) != 3) { |
| 282 | if (xfer != 3) { | ||
| 283 | dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer); | 216 | dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer); |
| 284 | return -EIO; | 217 | return -EIO; |
| 285 | } | 218 | } |
| 286 | 219 | ||
| 287 | xfer = i2c_master_send(client, rwel, 3); | 220 | if ((xfer = i2c_master_send(client, rwel, 3)) != 3) { |
| 288 | if (xfer != 3) { | ||
| 289 | dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer); | 221 | dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer); |
| 290 | return -EIO; | 222 | return -EIO; |
| 291 | } | 223 | } |
| @@ -305,8 +237,7 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
| 305 | }; | 237 | }; |
| 306 | 238 | ||
| 307 | /* disable further writes */ | 239 | /* disable further writes */ |
| 308 | xfer = i2c_master_send(client, diswe, 3); | 240 | if ((xfer = i2c_master_send(client, diswe, 3)) != 3) { |
| 309 | if (xfer != 3) { | ||
| 310 | dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer); | 241 | dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer); |
| 311 | return -EIO; | 242 | return -EIO; |
| 312 | } | 243 | } |
| @@ -314,6 +245,20 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
| 314 | return 0; | 245 | return 0; |
| 315 | } | 246 | } |
| 316 | 247 | ||
| 248 | static int x1205_fix_osc(struct i2c_client *client) | ||
| 249 | { | ||
| 250 | int err; | ||
| 251 | struct rtc_time tm; | ||
| 252 | |||
| 253 | tm.tm_hour = tm.tm_min = tm.tm_sec = 0; | ||
| 254 | |||
| 255 | if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0) | ||
| 256 | dev_err(&client->dev, | ||
| 257 | "unable to restart the oscillator\n"); | ||
| 258 | |||
| 259 | return err; | ||
| 260 | } | ||
| 261 | |||
| 317 | static int x1205_get_dtrim(struct i2c_client *client, int *trim) | 262 | static int x1205_get_dtrim(struct i2c_client *client, int *trim) |
| 318 | { | 263 | { |
| 319 | unsigned char dtr; | 264 | unsigned char dtr; |
| @@ -380,60 +325,9 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim) | |||
| 380 | return 0; | 325 | return 0; |
| 381 | } | 326 | } |
| 382 | 327 | ||
| 383 | static int x1205_hctosys(struct i2c_client *client) | ||
| 384 | { | ||
| 385 | int err; | ||
| 386 | |||
| 387 | struct rtc_time tm; | ||
| 388 | struct timespec tv; | ||
| 389 | |||
| 390 | err = x1205_command(client, X1205_CMD_GETDATETIME, &tm); | ||
| 391 | |||
| 392 | if (err) { | ||
| 393 | dev_err(&client->dev, | ||
| 394 | "Unable to set the system clock\n"); | ||
| 395 | return err; | ||
| 396 | } | ||
| 397 | |||
| 398 | /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary | ||
| 399 | * whether it stores the most close value or the value with partial | ||
| 400 | * seconds truncated. However, it is important that we use it to store | ||
| 401 | * the truncated value. This is because otherwise it is necessary, | ||
| 402 | * in an rtc sync function, to read both xtime.tv_sec and | ||
| 403 | * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read | ||
| 404 | * of >32bits is not possible. So storing the most close value would | ||
| 405 | * slow down the sync API. So here we have the truncated value and | ||
| 406 | * the best guess is to add 0.5s. | ||
| 407 | */ | ||
| 408 | |||
| 409 | tv.tv_nsec = NSEC_PER_SEC >> 1; | ||
| 410 | |||
| 411 | /* WARNING: this is not the C library 'mktime' call, it is a built in | ||
| 412 | * inline function from include/linux/time.h. It expects (requires) | ||
| 413 | * the month to be in the range 1-12 | ||
| 414 | */ | ||
| 415 | |||
| 416 | tv.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1, | ||
| 417 | tm.tm_mday, tm.tm_hour, | ||
| 418 | tm.tm_min, tm.tm_sec); | ||
| 419 | |||
| 420 | do_settimeofday(&tv); | ||
| 421 | |||
| 422 | dev_info(&client->dev, | ||
| 423 | "setting the system clock to %d-%d-%d %d:%d:%d\n", | ||
| 424 | tm.tm_year + 1900, tm.tm_mon + 1, | ||
| 425 | tm.tm_mday, tm.tm_hour, tm.tm_min, | ||
| 426 | tm.tm_sec); | ||
| 427 | |||
| 428 | return 0; | ||
| 429 | } | ||
| 430 | |||
| 431 | struct x1205_limit | 328 | struct x1205_limit |
| 432 | { | 329 | { |
| 433 | unsigned char reg; | 330 | unsigned char reg, mask, min, max; |
| 434 | unsigned char mask; | ||
| 435 | unsigned char min; | ||
| 436 | unsigned char max; | ||
| 437 | }; | 331 | }; |
| 438 | 332 | ||
| 439 | static int x1205_validate_client(struct i2c_client *client) | 333 | static int x1205_validate_client(struct i2c_client *client) |
| @@ -477,11 +371,10 @@ static int x1205_validate_client(struct i2c_client *client) | |||
| 477 | { client->addr, I2C_M_RD, 1, &buf }, | 371 | { client->addr, I2C_M_RD, 1, &buf }, |
| 478 | }; | 372 | }; |
| 479 | 373 | ||
| 480 | xfer = i2c_transfer(client->adapter, msgs, 2); | 374 | if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { |
| 481 | if (xfer != 2) { | ||
| 482 | dev_err(&client->adapter->dev, | 375 | dev_err(&client->adapter->dev, |
| 483 | "%s: could not read register %x\n", | 376 | "%s: could not read register %x\n", |
| 484 | __FUNCTION__, addr[1]); | 377 | __FUNCTION__, probe_zero_pattern[i]); |
| 485 | 378 | ||
| 486 | return -EIO; | 379 | return -EIO; |
| 487 | } | 380 | } |
| @@ -489,7 +382,7 @@ static int x1205_validate_client(struct i2c_client *client) | |||
| 489 | if ((buf & probe_zero_pattern[i+1]) != 0) { | 382 | if ((buf & probe_zero_pattern[i+1]) != 0) { |
| 490 | dev_err(&client->adapter->dev, | 383 | dev_err(&client->adapter->dev, |
| 491 | "%s: register=%02x, zero pattern=%d, value=%x\n", | 384 | "%s: register=%02x, zero pattern=%d, value=%x\n", |
| 492 | __FUNCTION__, addr[1], i, buf); | 385 | __FUNCTION__, probe_zero_pattern[i], i, buf); |
| 493 | 386 | ||
| 494 | return -ENODEV; | 387 | return -ENODEV; |
| 495 | } | 388 | } |
| @@ -506,12 +399,10 @@ static int x1205_validate_client(struct i2c_client *client) | |||
| 506 | { client->addr, I2C_M_RD, 1, ® }, | 399 | { client->addr, I2C_M_RD, 1, ® }, |
| 507 | }; | 400 | }; |
| 508 | 401 | ||
| 509 | xfer = i2c_transfer(client->adapter, msgs, 2); | 402 | if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { |
| 510 | |||
| 511 | if (xfer != 2) { | ||
| 512 | dev_err(&client->adapter->dev, | 403 | dev_err(&client->adapter->dev, |
| 513 | "%s: could not read register %x\n", | 404 | "%s: could not read register %x\n", |
| 514 | __FUNCTION__, addr[1]); | 405 | __FUNCTION__, probe_limits_pattern[i].reg); |
| 515 | 406 | ||
| 516 | return -EIO; | 407 | return -EIO; |
| 517 | } | 408 | } |
| @@ -522,7 +413,8 @@ static int x1205_validate_client(struct i2c_client *client) | |||
| 522 | value < probe_limits_pattern[i].min) { | 413 | value < probe_limits_pattern[i].min) { |
| 523 | dev_dbg(&client->adapter->dev, | 414 | dev_dbg(&client->adapter->dev, |
| 524 | "%s: register=%x, lim pattern=%d, value=%d\n", | 415 | "%s: register=%x, lim pattern=%d, value=%d\n", |
| 525 | __FUNCTION__, addr[1], i, value); | 416 | __FUNCTION__, probe_limits_pattern[i].reg, |
| 417 | i, value); | ||
| 526 | 418 | ||
| 527 | return -ENODEV; | 419 | return -ENODEV; |
| 528 | } | 420 | } |
| @@ -531,37 +423,89 @@ static int x1205_validate_client(struct i2c_client *client) | |||
| 531 | return 0; | 423 | return 0; |
| 532 | } | 424 | } |
| 533 | 425 | ||
| 534 | static int x1205_attach(struct i2c_adapter *adapter) | 426 | static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
| 535 | { | 427 | { |
| 536 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | 428 | return x1205_get_datetime(to_i2c_client(dev), |
| 429 | &alrm->time, X1205_ALM0_BASE); | ||
| 430 | } | ||
| 537 | 431 | ||
| 538 | return i2c_probe(adapter, &addr_data, x1205_probe); | 432 | static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
| 433 | { | ||
| 434 | return x1205_set_datetime(to_i2c_client(dev), | ||
| 435 | &alrm->time, 1, X1205_ALM0_BASE); | ||
| 539 | } | 436 | } |
| 540 | 437 | ||
| 541 | int x1205_direct_attach(int adapter_id, | 438 | static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm) |
| 542 | struct i2c_client_address_data *address_data) | ||
| 543 | { | 439 | { |
| 544 | int err; | 440 | return x1205_get_datetime(to_i2c_client(dev), |
| 545 | struct i2c_adapter *adapter = i2c_get_adapter(adapter_id); | 441 | tm, X1205_CCR_BASE); |
| 442 | } | ||
| 546 | 443 | ||
| 547 | if (adapter) { | 444 | static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm) |
| 548 | err = i2c_probe(adapter, | 445 | { |
| 549 | address_data, x1205_probe); | 446 | return x1205_set_datetime(to_i2c_client(dev), |
| 447 | tm, 1, X1205_CCR_BASE); | ||
| 448 | } | ||
| 550 | 449 | ||
| 551 | i2c_put_adapter(adapter); | 450 | static int x1205_rtc_proc(struct device *dev, struct seq_file *seq) |
| 451 | { | ||
| 452 | int err, dtrim, atrim; | ||
| 552 | 453 | ||
| 553 | return err; | 454 | seq_printf(seq, "24hr\t\t: yes\n"); |
| 554 | } | ||
| 555 | 455 | ||
| 556 | return -ENODEV; | 456 | if ((err = x1205_get_dtrim(to_i2c_client(dev), &dtrim)) == 0) |
| 457 | seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim); | ||
| 458 | |||
| 459 | if ((err = x1205_get_atrim(to_i2c_client(dev), &atrim)) == 0) | ||
| 460 | seq_printf(seq, "analog_trim\t: %d.%02d pF\n", | ||
| 461 | atrim / 1000, atrim % 1000); | ||
| 462 | return 0; | ||
| 557 | } | 463 | } |
| 558 | 464 | ||
| 559 | static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) | 465 | static struct rtc_class_ops x1205_rtc_ops = { |
| 466 | .proc = x1205_rtc_proc, | ||
| 467 | .read_time = x1205_rtc_read_time, | ||
| 468 | .set_time = x1205_rtc_set_time, | ||
| 469 | .read_alarm = x1205_rtc_read_alarm, | ||
| 470 | .set_alarm = x1205_rtc_set_alarm, | ||
| 471 | }; | ||
| 472 | |||
| 473 | static ssize_t x1205_sysfs_show_atrim(struct device *dev, | ||
| 474 | struct device_attribute *attr, char *buf) | ||
| 560 | { | 475 | { |
| 561 | struct i2c_client *client; | 476 | int atrim; |
| 562 | struct x1205_data *data; | 477 | |
| 478 | if (x1205_get_atrim(to_i2c_client(dev), &atrim) == 0) | ||
| 479 | return sprintf(buf, "%d.%02d pF\n", | ||
| 480 | atrim / 1000, atrim % 1000); | ||
| 481 | return 0; | ||
| 482 | } | ||
| 483 | static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL); | ||
| 484 | |||
| 485 | static ssize_t x1205_sysfs_show_dtrim(struct device *dev, | ||
| 486 | struct device_attribute *attr, char *buf) | ||
| 487 | { | ||
| 488 | int dtrim; | ||
| 489 | |||
| 490 | if (x1205_get_dtrim(to_i2c_client(dev), &dtrim) == 0) | ||
| 491 | return sprintf(buf, "%d ppm\n", dtrim); | ||
| 492 | |||
| 493 | return 0; | ||
| 494 | } | ||
| 495 | static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL); | ||
| 563 | 496 | ||
| 497 | static int x1205_attach(struct i2c_adapter *adapter) | ||
| 498 | { | ||
| 499 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | ||
| 500 | return i2c_probe(adapter, &addr_data, x1205_probe); | ||
| 501 | } | ||
| 502 | |||
| 503 | static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) | ||
| 504 | { | ||
| 564 | int err = 0; | 505 | int err = 0; |
| 506 | unsigned char sr; | ||
| 507 | struct i2c_client *client; | ||
| 508 | struct rtc_device *rtc; | ||
| 565 | 509 | ||
| 566 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); | 510 | dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); |
| 567 | 511 | ||
| @@ -570,22 +514,17 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) | |||
| 570 | goto exit; | 514 | goto exit; |
| 571 | } | 515 | } |
| 572 | 516 | ||
| 573 | if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) { | 517 | if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { |
| 574 | err = -ENOMEM; | 518 | err = -ENOMEM; |
| 575 | goto exit; | 519 | goto exit; |
| 576 | } | 520 | } |
| 577 | 521 | ||
| 578 | /* Initialize our structures */ | 522 | /* I2C client */ |
| 579 | data->epoch = 2000; | ||
| 580 | |||
| 581 | client = &data->client; | ||
| 582 | client->addr = address; | 523 | client->addr = address; |
| 583 | client->driver = &x1205_driver; | 524 | client->driver = &x1205_driver; |
| 584 | client->adapter = adapter; | 525 | client->adapter = adapter; |
| 585 | 526 | ||
| 586 | strlcpy(client->name, "x1205", I2C_NAME_SIZE); | 527 | strlcpy(client->name, x1205_driver.driver.name, I2C_NAME_SIZE); |
| 587 | |||
| 588 | i2c_set_clientdata(client, data); | ||
| 589 | 528 | ||
| 590 | /* Verify the chip is really an X1205 */ | 529 | /* Verify the chip is really an X1205 */ |
| 591 | if (kind < 0) { | 530 | if (kind < 0) { |
| @@ -599,18 +538,43 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) | |||
| 599 | if ((err = i2c_attach_client(client))) | 538 | if ((err = i2c_attach_client(client))) |
| 600 | goto exit_kfree; | 539 | goto exit_kfree; |
| 601 | 540 | ||
| 602 | list_add(&data->list, &x1205_clients); | ||
| 603 | |||
| 604 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); | 541 | dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); |
| 605 | 542 | ||
| 606 | /* If requested, set the system time */ | 543 | rtc = rtc_device_register(x1205_driver.driver.name, &client->dev, |
| 607 | if (hctosys) | 544 | &x1205_rtc_ops, THIS_MODULE); |
| 608 | x1205_hctosys(client); | 545 | |
| 546 | if (IS_ERR(rtc)) { | ||
| 547 | err = PTR_ERR(rtc); | ||
| 548 | dev_err(&client->dev, | ||
| 549 | "unable to register the class device\n"); | ||
| 550 | goto exit_detach; | ||
| 551 | } | ||
| 552 | |||
| 553 | i2c_set_clientdata(client, rtc); | ||
| 554 | |||
| 555 | /* Check for power failures and eventualy enable the osc */ | ||
| 556 | if ((err = x1205_get_status(client, &sr)) == 0) { | ||
| 557 | if (sr & X1205_SR_RTCF) { | ||
| 558 | dev_err(&client->dev, | ||
| 559 | "power failure detected, " | ||
| 560 | "please set the clock\n"); | ||
| 561 | udelay(50); | ||
| 562 | x1205_fix_osc(client); | ||
| 563 | } | ||
| 564 | } | ||
| 565 | else | ||
| 566 | dev_err(&client->dev, "couldn't read status\n"); | ||
| 567 | |||
| 568 | device_create_file(&client->dev, &dev_attr_atrim); | ||
| 569 | device_create_file(&client->dev, &dev_attr_dtrim); | ||
| 609 | 570 | ||
| 610 | return 0; | 571 | return 0; |
| 611 | 572 | ||
| 573 | exit_detach: | ||
| 574 | i2c_detach_client(client); | ||
| 575 | |||
| 612 | exit_kfree: | 576 | exit_kfree: |
| 613 | kfree(data); | 577 | kfree(client); |
| 614 | 578 | ||
| 615 | exit: | 579 | exit: |
| 616 | return err; | 580 | return err; |
| @@ -619,61 +583,21 @@ exit: | |||
| 619 | static int x1205_detach(struct i2c_client *client) | 583 | static int x1205_detach(struct i2c_client *client) |
| 620 | { | 584 | { |
| 621 | int err; | 585 | int err; |
| 622 | struct x1205_data *data = i2c_get_clientdata(client); | 586 | struct rtc_device *rtc = i2c_get_clientdata(client); |
| 623 | 587 | ||
| 624 | dev_dbg(&client->dev, "%s\n", __FUNCTION__); | 588 | dev_dbg(&client->dev, "%s\n", __FUNCTION__); |
| 625 | 589 | ||
| 590 | if (rtc) | ||
| 591 | rtc_device_unregister(rtc); | ||
| 592 | |||
| 626 | if ((err = i2c_detach_client(client))) | 593 | if ((err = i2c_detach_client(client))) |
| 627 | return err; | 594 | return err; |
| 628 | 595 | ||
| 629 | list_del(&data->list); | 596 | kfree(client); |
| 630 | |||
| 631 | kfree(data); | ||
| 632 | 597 | ||
| 633 | return 0; | 598 | return 0; |
| 634 | } | 599 | } |
| 635 | 600 | ||
| 636 | static int x1205_command(struct i2c_client *client, unsigned int cmd, | ||
| 637 | void *param) | ||
| 638 | { | ||
| 639 | if (param == NULL) | ||
| 640 | return -EINVAL; | ||
| 641 | |||
| 642 | if (!capable(CAP_SYS_TIME)) | ||
| 643 | return -EACCES; | ||
| 644 | |||
| 645 | dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd); | ||
| 646 | |||
| 647 | switch (cmd) { | ||
| 648 | case X1205_CMD_GETDATETIME: | ||
| 649 | return x1205_get_datetime(client, param, X1205_CCR_BASE); | ||
| 650 | |||
| 651 | case X1205_CMD_SETTIME: | ||
| 652 | return x1205_set_datetime(client, param, 0, | ||
| 653 | X1205_CCR_BASE); | ||
| 654 | |||
| 655 | case X1205_CMD_SETDATETIME: | ||
| 656 | return x1205_set_datetime(client, param, 1, | ||
| 657 | X1205_CCR_BASE); | ||
| 658 | |||
| 659 | case X1205_CMD_GETALARM: | ||
| 660 | return x1205_get_datetime(client, param, X1205_ALM0_BASE); | ||
| 661 | |||
| 662 | case X1205_CMD_SETALARM: | ||
| 663 | return x1205_set_datetime(client, param, 1, | ||
| 664 | X1205_ALM0_BASE); | ||
| 665 | |||
| 666 | case X1205_CMD_GETDTRIM: | ||
| 667 | return x1205_get_dtrim(client, param); | ||
| 668 | |||
| 669 | case X1205_CMD_GETATRIM: | ||
| 670 | return x1205_get_atrim(client, param); | ||
| 671 | |||
| 672 | default: | ||
| 673 | return -EINVAL; | ||
| 674 | } | ||
| 675 | } | ||
| 676 | |||
| 677 | static int __init x1205_init(void) | 601 | static int __init x1205_init(void) |
| 678 | { | 602 | { |
| 679 | return i2c_add_driver(&x1205_driver); | 603 | return i2c_add_driver(&x1205_driver); |
| @@ -685,14 +609,11 @@ static void __exit x1205_exit(void) | |||
| 685 | } | 609 | } |
| 686 | 610 | ||
| 687 | MODULE_AUTHOR( | 611 | MODULE_AUTHOR( |
| 688 | "Karen Spearel <kas11@tampabay.rr.com>, " | 612 | "Karen Spearel <kas111 at gmail dot com>, " |
| 689 | "Alessandro Zummo <a.zummo@towertech.it>"); | 613 | "Alessandro Zummo <a.zummo@towertech.it>"); |
| 690 | MODULE_DESCRIPTION("Xicor X1205 RTC driver"); | 614 | MODULE_DESCRIPTION("Xicor/Intersil X1205 RTC driver"); |
| 691 | MODULE_LICENSE("GPL"); | 615 | MODULE_LICENSE("GPL"); |
| 692 | MODULE_VERSION(DRV_VERSION); | 616 | MODULE_VERSION(DRV_VERSION); |
| 693 | 617 | ||
| 694 | EXPORT_SYMBOL_GPL(x1205_do_command); | ||
| 695 | EXPORT_SYMBOL_GPL(x1205_direct_attach); | ||
| 696 | |||
| 697 | module_init(x1205_init); | 618 | module_init(x1205_init); |
| 698 | module_exit(x1205_exit); | 619 | module_exit(x1205_exit); |
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 0ab26d01877b..0d2b447c50ed 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c | |||
| @@ -1026,7 +1026,7 @@ static void twa_free_request_id(TW_Device_Extension *tw_dev, int request_id) | |||
| 1026 | tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH; | 1026 | tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH; |
| 1027 | } /* End twa_free_request_id() */ | 1027 | } /* End twa_free_request_id() */ |
| 1028 | 1028 | ||
| 1029 | /* This function will get parameter table entires from the firmware */ | 1029 | /* This function will get parameter table entries from the firmware */ |
| 1030 | static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes) | 1030 | static void *twa_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes) |
| 1031 | { | 1031 | { |
| 1032 | TW_Command_Full *full_command_packet; | 1032 | TW_Command_Full *full_command_packet; |
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 1c459343292b..bde3d5834ade 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c | |||
| @@ -41,6 +41,8 @@ | |||
| 41 | #include <linux/stat.h> | 41 | #include <linux/stat.h> |
| 42 | #include <linux/pci.h> | 42 | #include <linux/pci.h> |
| 43 | #include <linux/spinlock.h> | 43 | #include <linux/spinlock.h> |
| 44 | #include <linux/jiffies.h> | ||
| 45 | #include <linux/dma-mapping.h> | ||
| 44 | #include <scsi/scsicam.h> | 46 | #include <scsi/scsicam.h> |
| 45 | 47 | ||
| 46 | #include <asm/dma.h> | 48 | #include <asm/dma.h> |
| @@ -676,7 +678,7 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd | |||
| 676 | if (pci_enable_device(PCI_Device)) | 678 | if (pci_enable_device(PCI_Device)) |
| 677 | continue; | 679 | continue; |
| 678 | 680 | ||
| 679 | if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff)) | 681 | if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK )) |
| 680 | continue; | 682 | continue; |
| 681 | 683 | ||
| 682 | Bus = PCI_Device->bus->number; | 684 | Bus = PCI_Device->bus->number; |
| @@ -831,7 +833,7 @@ static int __init BusLogic_InitializeMultiMasterProbeInfo(struct BusLogic_HostAd | |||
| 831 | if (pci_enable_device(PCI_Device)) | 833 | if (pci_enable_device(PCI_Device)) |
| 832 | continue; | 834 | continue; |
| 833 | 835 | ||
| 834 | if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff)) | 836 | if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK)) |
| 835 | continue; | 837 | continue; |
| 836 | 838 | ||
| 837 | Bus = PCI_Device->bus->number; | 839 | Bus = PCI_Device->bus->number; |
| @@ -885,7 +887,7 @@ static int __init BusLogic_InitializeFlashPointProbeInfo(struct BusLogic_HostAda | |||
| 885 | if (pci_enable_device(PCI_Device)) | 887 | if (pci_enable_device(PCI_Device)) |
| 886 | continue; | 888 | continue; |
| 887 | 889 | ||
| 888 | if (pci_set_dma_mask(PCI_Device, (u64) 0xffffffff)) | 890 | if (pci_set_dma_mask(PCI_Device, DMA_32BIT_MASK)) |
| 889 | continue; | 891 | continue; |
| 890 | 892 | ||
| 891 | Bus = PCI_Device->bus->number; | 893 | Bus = PCI_Device->bus->number; |
| @@ -2896,7 +2898,7 @@ static int BusLogic_QueueCommand(struct scsi_cmnd *Command, void (*CompletionRou | |||
| 2896 | */ | 2898 | */ |
| 2897 | if (HostAdapter->ActiveCommands[TargetID] == 0) | 2899 | if (HostAdapter->ActiveCommands[TargetID] == 0) |
| 2898 | HostAdapter->LastSequencePoint[TargetID] = jiffies; | 2900 | HostAdapter->LastSequencePoint[TargetID] = jiffies; |
| 2899 | else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4 * HZ) { | 2901 | else if (time_after(jiffies, HostAdapter->LastSequencePoint[TargetID] + 4 * HZ)) { |
| 2900 | HostAdapter->LastSequencePoint[TargetID] = jiffies; | 2902 | HostAdapter->LastSequencePoint[TargetID] = jiffies; |
| 2901 | QueueTag = BusLogic_OrderedQueueTag; | 2903 | QueueTag = BusLogic_OrderedQueueTag; |
| 2902 | } | 2904 | } |
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 9f45ae1745da..3dce21c78737 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c | |||
| @@ -89,6 +89,7 @@ | |||
| 89 | #include <linux/string.h> | 89 | #include <linux/string.h> |
| 90 | #include <linux/ioport.h> | 90 | #include <linux/ioport.h> |
| 91 | #include <linux/slab.h> | 91 | #include <linux/slab.h> |
| 92 | #include <linux/dma-mapping.h> | ||
| 92 | 93 | ||
| 93 | #include <asm/io.h> | 94 | #include <asm/io.h> |
| 94 | #include <asm/irq.h> | 95 | #include <asm/irq.h> |
| @@ -1052,7 +1053,7 @@ static int __devinit inia100_probe_one(struct pci_dev *pdev, | |||
| 1052 | 1053 | ||
| 1053 | if (pci_enable_device(pdev)) | 1054 | if (pci_enable_device(pdev)) |
| 1054 | goto out; | 1055 | goto out; |
| 1055 | if (pci_set_dma_mask(pdev, 0xffffffffULL)) { | 1056 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { |
| 1056 | printk(KERN_WARNING "Unable to set 32bit DMA " | 1057 | printk(KERN_WARNING "Unable to set 32bit DMA " |
| 1057 | "on inia100 adapter, ignoring.\n"); | 1058 | "on inia100 adapter, ignoring.\n"); |
| 1058 | goto out_disable_device; | 1059 | goto out_disable_device; |
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index a16f8ded8f1d..8df4a0ea3761 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/completion.h> | 33 | #include <linux/completion.h> |
| 34 | #include <linux/blkdev.h> | 34 | #include <linux/blkdev.h> |
| 35 | #include <linux/dma-mapping.h> | ||
| 35 | #include <asm/semaphore.h> | 36 | #include <asm/semaphore.h> |
| 36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
| 37 | 38 | ||
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index c2596335549d..720330778648 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | #include <linux/pci.h> | 45 | #include <linux/pci.h> |
| 46 | #include <linux/slab.h> | 46 | #include <linux/slab.h> |
| 47 | #include <linux/spinlock.h> | 47 | #include <linux/spinlock.h> |
| 48 | #include <linux/dma-mapping.h> | ||
| 48 | #include <linux/syscalls.h> | 49 | #include <linux/syscalls.h> |
| 49 | #include <linux/delay.h> | 50 | #include <linux/delay.h> |
| 50 | #include <linux/smp_lock.h> | 51 | #include <linux/smp_lock.h> |
| @@ -806,8 +807,8 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, | |||
| 806 | * to driver communication memory to be allocated below 2gig | 807 | * to driver communication memory to be allocated below 2gig |
| 807 | */ | 808 | */ |
| 808 | if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) | 809 | if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) |
| 809 | if (pci_set_dma_mask(pdev, 0x7FFFFFFFULL) || | 810 | if (pci_set_dma_mask(pdev, DMA_31BIT_MASK) || |
| 810 | pci_set_consistent_dma_mask(pdev, 0x7FFFFFFFULL)) | 811 | pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK)) |
| 811 | goto out; | 812 | goto out; |
| 812 | 813 | ||
| 813 | pci_set_master(pdev); | 814 | pci_set_master(pdev); |
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 5227a779c05c..a198d86667e9 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
| 29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
| 30 | #include <linux/blkdev.h> | 30 | #include <linux/blkdev.h> |
| 31 | #include <linux/dma-mapping.h> | ||
| 31 | #include <asm/system.h> | 32 | #include <asm/system.h> |
| 32 | #include <asm/io.h> | 33 | #include <asm/io.h> |
| 33 | 34 | ||
| @@ -2631,7 +2632,7 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2631 | if (pci_enable_device(pdev)) | 2632 | if (pci_enable_device(pdev)) |
| 2632 | return -EIO; | 2633 | return -EIO; |
| 2633 | 2634 | ||
| 2634 | if (!pci_set_dma_mask(pdev, 0xFFFFFFFFUL)) { | 2635 | if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { |
| 2635 | printk(KERN_INFO "atp870u: use 32bit DMA mask.\n"); | 2636 | printk(KERN_INFO "atp870u: use 32bit DMA mask.\n"); |
| 2636 | } else { | 2637 | } else { |
| 2637 | printk(KERN_ERR "atp870u: DMA mask required but not available.\n"); | 2638 | printk(KERN_ERR "atp870u: DMA mask required but not available.\n"); |
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 6e6b293dcb28..b1b704a42efd 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c | |||
| @@ -57,6 +57,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Driver"); | |||
| 57 | #include <linux/reboot.h> | 57 | #include <linux/reboot.h> |
| 58 | #include <linux/spinlock.h> | 58 | #include <linux/spinlock.h> |
| 59 | #include <linux/smp_lock.h> | 59 | #include <linux/smp_lock.h> |
| 60 | #include <linux/dma-mapping.h> | ||
| 60 | 61 | ||
| 61 | #include <linux/timer.h> | 62 | #include <linux/timer.h> |
| 62 | #include <linux/string.h> | 63 | #include <linux/string.h> |
| @@ -906,8 +907,8 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev | |||
| 906 | } | 907 | } |
| 907 | 908 | ||
| 908 | pci_set_master(pDev); | 909 | pci_set_master(pDev); |
| 909 | if (pci_set_dma_mask(pDev, 0xffffffffffffffffULL) && | 910 | if (pci_set_dma_mask(pDev, DMA_64BIT_MASK) && |
| 910 | pci_set_dma_mask(pDev, 0xffffffffULL)) | 911 | pci_set_dma_mask(pDev, DMA_32BIT_MASK)) |
| 911 | return -EINVAL; | 912 | return -EINVAL; |
| 912 | 913 | ||
| 913 | base_addr0_phys = pci_resource_start(pDev,0); | 914 | base_addr0_phys = pci_resource_start(pDev,0); |
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index b3f9de8f7595..059eeee4b554 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c | |||
| @@ -490,6 +490,7 @@ | |||
| 490 | #include <linux/init.h> | 490 | #include <linux/init.h> |
| 491 | #include <linux/ctype.h> | 491 | #include <linux/ctype.h> |
| 492 | #include <linux/spinlock.h> | 492 | #include <linux/spinlock.h> |
| 493 | #include <linux/dma-mapping.h> | ||
| 493 | #include <asm/byteorder.h> | 494 | #include <asm/byteorder.h> |
| 494 | #include <asm/dma.h> | 495 | #include <asm/dma.h> |
| 495 | #include <asm/io.h> | 496 | #include <asm/io.h> |
| @@ -1426,7 +1427,7 @@ static int port_detect(unsigned long port_base, unsigned int j, | |||
| 1426 | 1427 | ||
| 1427 | if (ha->pdev) { | 1428 | if (ha->pdev) { |
| 1428 | pci_set_master(ha->pdev); | 1429 | pci_set_master(ha->pdev); |
| 1429 | if (pci_set_dma_mask(ha->pdev, 0xffffffff)) | 1430 | if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) |
| 1430 | printk("%s: warning, pci_set_dma_mask failed.\n", | 1431 | printk("%s: warning, pci_set_dma_mask failed.\n", |
| 1431 | ha->board_name); | 1432 | ha->board_name); |
| 1432 | } | 1433 | } |
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 62e3cda859af..d5740bbdef3e 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c | |||
| @@ -388,6 +388,7 @@ | |||
| 388 | #include <linux/proc_fs.h> | 388 | #include <linux/proc_fs.h> |
| 389 | #include <linux/time.h> | 389 | #include <linux/time.h> |
| 390 | #include <linux/timer.h> | 390 | #include <linux/timer.h> |
| 391 | #include <linux/dma-mapping.h> | ||
| 391 | #ifdef GDTH_RTC | 392 | #ifdef GDTH_RTC |
| 392 | #include <linux/mc146818rtc.h> | 393 | #include <linux/mc146818rtc.h> |
| 393 | #endif | 394 | #endif |
| @@ -671,7 +672,7 @@ static struct file_operations gdth_fops = { | |||
| 671 | static struct notifier_block gdth_notifier = { | 672 | static struct notifier_block gdth_notifier = { |
| 672 | gdth_halt, NULL, 0 | 673 | gdth_halt, NULL, 0 |
| 673 | }; | 674 | }; |
| 674 | 675 | static int notifier_disabled = 0; | |
| 675 | 676 | ||
| 676 | static void gdth_delay(int milliseconds) | 677 | static void gdth_delay(int milliseconds) |
| 677 | { | 678 | { |
| @@ -4527,15 +4528,15 @@ static int __init gdth_detect(struct scsi_host_template *shtp) | |||
| 4527 | if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)|| | 4528 | if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)|| |
| 4528 | /* 64-bit DMA only supported from FW >= x.43 */ | 4529 | /* 64-bit DMA only supported from FW >= x.43 */ |
| 4529 | (!ha->dma64_support)) { | 4530 | (!ha->dma64_support)) { |
| 4530 | if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) { | 4531 | if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { |
| 4531 | printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum); | 4532 | printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum); |
| 4532 | err = TRUE; | 4533 | err = TRUE; |
| 4533 | } | 4534 | } |
| 4534 | } else { | 4535 | } else { |
| 4535 | shp->max_cmd_len = 16; | 4536 | shp->max_cmd_len = 16; |
| 4536 | if (!pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffffffffffffULL)) { | 4537 | if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) { |
| 4537 | printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum); | 4538 | printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum); |
| 4538 | } else if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) { | 4539 | } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { |
| 4539 | printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum); | 4540 | printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum); |
| 4540 | err = TRUE; | 4541 | err = TRUE; |
| 4541 | } | 4542 | } |
| @@ -4595,13 +4596,13 @@ static int __init gdth_detect(struct scsi_host_template *shtp) | |||
| 4595 | add_timer(&gdth_timer); | 4596 | add_timer(&gdth_timer); |
| 4596 | #endif | 4597 | #endif |
| 4597 | major = register_chrdev(0,"gdth",&gdth_fops); | 4598 | major = register_chrdev(0,"gdth",&gdth_fops); |
| 4599 | notifier_disabled = 0; | ||
| 4598 | register_reboot_notifier(&gdth_notifier); | 4600 | register_reboot_notifier(&gdth_notifier); |
| 4599 | } | 4601 | } |
| 4600 | gdth_polling = FALSE; | 4602 | gdth_polling = FALSE; |
| 4601 | return gdth_ctr_vcount; | 4603 | return gdth_ctr_vcount; |
| 4602 | } | 4604 | } |
| 4603 | 4605 | ||
| 4604 | |||
| 4605 | static int gdth_release(struct Scsi_Host *shp) | 4606 | static int gdth_release(struct Scsi_Host *shp) |
| 4606 | { | 4607 | { |
| 4607 | int hanum; | 4608 | int hanum; |
| @@ -5632,10 +5633,14 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) | |||
| 5632 | char cmnd[MAX_COMMAND_SIZE]; | 5633 | char cmnd[MAX_COMMAND_SIZE]; |
| 5633 | #endif | 5634 | #endif |
| 5634 | 5635 | ||
| 5636 | if (notifier_disabled) | ||
| 5637 | return NOTIFY_OK; | ||
| 5638 | |||
| 5635 | TRACE2(("gdth_halt() event %d\n",(int)event)); | 5639 | TRACE2(("gdth_halt() event %d\n",(int)event)); |
| 5636 | if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) | 5640 | if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) |
| 5637 | return NOTIFY_DONE; | 5641 | return NOTIFY_DONE; |
| 5638 | 5642 | ||
| 5643 | notifier_disabled = 1; | ||
| 5639 | printk("GDT-HA: Flushing all host drives .. "); | 5644 | printk("GDT-HA: Flushing all host drives .. "); |
| 5640 | for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { | 5645 | for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { |
| 5641 | gdth_flush(hanum); | 5646 | gdth_flush(hanum); |
| @@ -5679,7 +5684,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) | |||
| 5679 | #ifdef GDTH_STATISTICS | 5684 | #ifdef GDTH_STATISTICS |
| 5680 | del_timer(&gdth_timer); | 5685 | del_timer(&gdth_timer); |
| 5681 | #endif | 5686 | #endif |
| 5682 | unregister_reboot_notifier(&gdth_notifier); | ||
| 5683 | return NOTIFY_OK; | 5687 | return NOTIFY_OK; |
| 5684 | } | 5688 | } |
| 5685 | 5689 | ||
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index ea6f3c0e05d9..0cc7f65b584f 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c | |||
| @@ -127,6 +127,7 @@ | |||
| 127 | #include <linux/sched.h> | 127 | #include <linux/sched.h> |
| 128 | #include <linux/slab.h> | 128 | #include <linux/slab.h> |
| 129 | #include <linux/jiffies.h> | 129 | #include <linux/jiffies.h> |
| 130 | #include <linux/dma-mapping.h> | ||
| 130 | #include <asm/io.h> | 131 | #include <asm/io.h> |
| 131 | 132 | ||
| 132 | #include <scsi/scsi.h> | 133 | #include <scsi/scsi.h> |
| @@ -2780,7 +2781,7 @@ static int tul_NewReturnNumberOfAdapters(void) | |||
| 2780 | if (((dRegValue & 0xFF00) >> 8) == 0xFF) | 2781 | if (((dRegValue & 0xFF00) >> 8) == 0xFF) |
| 2781 | dRegValue = 0; | 2782 | dRegValue = 0; |
| 2782 | wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); | 2783 | wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8)); |
| 2783 | if (pci_set_dma_mask(pDev, 0xffffffff)) { | 2784 | if (pci_set_dma_mask(pDev, DMA_32BIT_MASK)) { |
| 2784 | printk(KERN_WARNING | 2785 | printk(KERN_WARNING |
| 2785 | "i91u: Could not set 32 bit DMA mask\n"); | 2786 | "i91u: Could not set 32 bit DMA mask\n"); |
| 2786 | continue; | 2787 | continue; |
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 481708d527ae..a4c0b04cfdbd 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c | |||
| @@ -179,6 +179,7 @@ | |||
| 179 | 179 | ||
| 180 | #include <linux/blkdev.h> | 180 | #include <linux/blkdev.h> |
| 181 | #include <linux/types.h> | 181 | #include <linux/types.h> |
| 182 | #include <linux/dma-mapping.h> | ||
| 182 | 183 | ||
| 183 | #include <scsi/sg.h> | 184 | #include <scsi/sg.h> |
| 184 | 185 | ||
| @@ -7284,10 +7285,10 @@ ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr) | |||
| 7284 | * are guaranteed to be < 4G. | 7285 | * are guaranteed to be < 4G. |
| 7285 | */ | 7286 | */ |
| 7286 | if (IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) && | 7287 | if (IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) && |
| 7287 | !pci_set_dma_mask(ha->pcidev, 0xffffffffffffffffULL)) { | 7288 | !pci_set_dma_mask(ha->pcidev, DMA_64BIT_MASK)) { |
| 7288 | (ha)->flags |= IPS_HA_ENH_SG; | 7289 | (ha)->flags |= IPS_HA_ENH_SG; |
| 7289 | } else { | 7290 | } else { |
| 7290 | if (pci_set_dma_mask(ha->pcidev, 0xffffffffULL) != 0) { | 7291 | if (pci_set_dma_mask(ha->pcidev, DMA_32BIT_MASK) != 0) { |
| 7291 | printk(KERN_WARNING "Unable to set DMA Mask\n"); | 7292 | printk(KERN_WARNING "Unable to set DMA Mask\n"); |
| 7292 | return ips_abort_init(ha, index); | 7293 | return ips_abort_init(ha, index); |
| 7293 | } | 7294 | } |
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 7144674bc8e6..80b68a2481b3 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
| 46 | #include <linux/pci.h> | 46 | #include <linux/pci.h> |
| 47 | #include <linux/init.h> | 47 | #include <linux/init.h> |
| 48 | #include <linux/dma-mapping.h> | ||
| 48 | #include <scsi/scsicam.h> | 49 | #include <scsi/scsicam.h> |
| 49 | 50 | ||
| 50 | #include "scsi.h" | 51 | #include "scsi.h" |
| @@ -2094,7 +2095,7 @@ make_local_pdev(adapter_t *adapter, struct pci_dev **pdev) | |||
| 2094 | 2095 | ||
| 2095 | memcpy(*pdev, adapter->dev, sizeof(struct pci_dev)); | 2096 | memcpy(*pdev, adapter->dev, sizeof(struct pci_dev)); |
| 2096 | 2097 | ||
| 2097 | if( pci_set_dma_mask(*pdev, 0xffffffff) != 0 ) { | 2098 | if( pci_set_dma_mask(*pdev, DMA_32BIT_MASK) != 0 ) { |
| 2098 | kfree(*pdev); | 2099 | kfree(*pdev); |
| 2099 | return -1; | 2100 | return -1; |
| 2100 | } | 2101 | } |
| @@ -4859,10 +4860,10 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 4859 | 4860 | ||
| 4860 | /* Set the Mode of addressing to 64 bit if we can */ | 4861 | /* Set the Mode of addressing to 64 bit if we can */ |
| 4861 | if ((adapter->flag & BOARD_64BIT) && (sizeof(dma_addr_t) == 8)) { | 4862 | if ((adapter->flag & BOARD_64BIT) && (sizeof(dma_addr_t) == 8)) { |
| 4862 | pci_set_dma_mask(pdev, 0xffffffffffffffffULL); | 4863 | pci_set_dma_mask(pdev, DMA_64BIT_MASK); |
| 4863 | adapter->has_64bit_addr = 1; | 4864 | adapter->has_64bit_addr = 1; |
| 4864 | } else { | 4865 | } else { |
| 4865 | pci_set_dma_mask(pdev, 0xffffffff); | 4866 | pci_set_dma_mask(pdev, DMA_32BIT_MASK); |
| 4866 | adapter->has_64bit_addr = 0; | 4867 | adapter->has_64bit_addr = 0; |
| 4867 | } | 4868 | } |
| 4868 | 4869 | ||
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index a279ebb61447..30ee0ef4b459 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
| 39 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
| 40 | #include <linux/ctype.h> | 40 | #include <linux/ctype.h> |
| 41 | #include <linux/dma-mapping.h> | ||
| 41 | 42 | ||
| 42 | #include <asm/dma.h> | 43 | #include <asm/dma.h> |
| 43 | #include <asm/system.h> | 44 | #include <asm/system.h> |
| @@ -2776,7 +2777,7 @@ static int nsp32_detect(struct scsi_host_template *sht) | |||
| 2776 | /* | 2777 | /* |
| 2777 | * setup DMA | 2778 | * setup DMA |
| 2778 | */ | 2779 | */ |
| 2779 | if (pci_set_dma_mask(PCIDEV, 0xffffffffUL) != 0) { | 2780 | if (pci_set_dma_mask(PCIDEV, DMA_32BIT_MASK) != 0) { |
| 2780 | nsp32_msg (KERN_ERR, "failed to set PCI DMA mask"); | 2781 | nsp32_msg (KERN_ERR, "failed to set PCI DMA mask"); |
| 2781 | goto scsi_unregister; | 2782 | goto scsi_unregister; |
| 2782 | } | 2783 | } |
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 66ea47a9c53c..e3bd4bc339f4 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c | |||
| @@ -49,6 +49,7 @@ static const char * osst_version = "0.99.4"; | |||
| 49 | #include <linux/blkdev.h> | 49 | #include <linux/blkdev.h> |
| 50 | #include <linux/moduleparam.h> | 50 | #include <linux/moduleparam.h> |
| 51 | #include <linux/delay.h> | 51 | #include <linux/delay.h> |
| 52 | #include <linux/jiffies.h> | ||
| 52 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
| 53 | #include <asm/dma.h> | 54 | #include <asm/dma.h> |
| 54 | #include <asm/system.h> | 55 | #include <asm/system.h> |
| @@ -856,7 +857,7 @@ static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt | |||
| 856 | ) && result >= 0) | 857 | ) && result >= 0) |
| 857 | { | 858 | { |
| 858 | #if DEBUG | 859 | #if DEBUG |
| 859 | if (debugging || jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC) | 860 | if (debugging || time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC)) |
| 860 | printk (OSST_DEB_MSG | 861 | printk (OSST_DEB_MSG |
| 861 | "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n", | 862 | "%s:D: Succ wait f fr %i (>%i): %i-%i %i (%i): %3li.%li s\n", |
| 862 | name, curr, curr+minlast, STp->first_frame_position, | 863 | name, curr, curr+minlast, STp->first_frame_position, |
| @@ -867,7 +868,7 @@ static int osst_wait_frame(struct osst_tape * STp, struct osst_request ** aSRpnt | |||
| 867 | return 0; | 868 | return 0; |
| 868 | } | 869 | } |
| 869 | #if DEBUG | 870 | #if DEBUG |
| 870 | if (jiffies - startwait >= 2*HZ/OSST_POLL_PER_SEC && notyetprinted) | 871 | if (time_after_eq(jiffies, startwait + 2*HZ/OSST_POLL_PER_SEC) && notyetprinted) |
| 871 | { | 872 | { |
| 872 | printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n", | 873 | printk (OSST_DEB_MSG "%s:D: Wait for frame %i (>%i): %i-%i %i (%i)\n", |
| 873 | name, curr, curr+minlast, STp->first_frame_position, | 874 | name, curr, curr+minlast, STp->first_frame_position, |
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 05347eed9dd5..fee843fab1c7 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/parport.h> | 18 | #include <linux/parport.h> |
| 19 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
| 20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
| 21 | #include <linux/jiffies.h> | ||
| 21 | #include <asm/io.h> | 22 | #include <asm/io.h> |
| 22 | 23 | ||
| 23 | #include <scsi/scsi.h> | 24 | #include <scsi/scsi.h> |
| @@ -726,7 +727,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) | |||
| 726 | retv--; | 727 | retv--; |
| 727 | 728 | ||
| 728 | if (retv) { | 729 | if (retv) { |
| 729 | if ((jiffies - dev->jstart) > (1 * HZ)) { | 730 | if (time_after(jiffies, dev->jstart + (1 * HZ))) { |
| 730 | printk | 731 | printk |
| 731 | ("ppa: Parallel port cable is unplugged!!\n"); | 732 | ("ppa: Parallel port cable is unplugged!!\n"); |
| 732 | ppa_fail(dev, DID_BUS_BUSY); | 733 | ppa_fail(dev, DID_BUS_BUSY); |
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index e0230249fa0f..5a48e55f9418 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c | |||
| @@ -350,6 +350,7 @@ | |||
| 350 | #include <linux/pci_ids.h> | 350 | #include <linux/pci_ids.h> |
| 351 | #include <linux/interrupt.h> | 351 | #include <linux/interrupt.h> |
| 352 | #include <linux/init.h> | 352 | #include <linux/init.h> |
| 353 | #include <linux/dma-mapping.h> | ||
| 353 | 354 | ||
| 354 | #include <asm/io.h> | 355 | #include <asm/io.h> |
| 355 | #include <asm/irq.h> | 356 | #include <asm/irq.h> |
| @@ -4321,7 +4322,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 4321 | 4322 | ||
| 4322 | #ifdef QLA_64BIT_PTR | 4323 | #ifdef QLA_64BIT_PTR |
| 4323 | if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) { | 4324 | if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) { |
| 4324 | if (pci_set_dma_mask(ha->pdev, 0xffffffff)) { | 4325 | if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) { |
| 4325 | printk(KERN_WARNING "scsi(%li): Unable to set a " | 4326 | printk(KERN_WARNING "scsi(%li): Unable to set a " |
| 4326 | "suitable DMA mask - aborting\n", ha->host_no); | 4327 | "suitable DMA mask - aborting\n", ha->host_no); |
| 4327 | error = -ENODEV; | 4328 | error = -ENODEV; |
| @@ -4331,7 +4332,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 4331 | dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n", | 4332 | dprintk(2, "scsi(%li): 64 Bit PCI Addressing Enabled\n", |
| 4332 | ha->host_no); | 4333 | ha->host_no); |
| 4333 | #else | 4334 | #else |
| 4334 | if (pci_set_dma_mask(ha->pdev, 0xffffffff)) { | 4335 | if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) { |
| 4335 | printk(KERN_WARNING "scsi(%li): Unable to set a " | 4336 | printk(KERN_WARNING "scsi(%li): Unable to set a " |
| 4336 | "suitable DMA mask - aborting\n", ha->host_no); | 4337 | "suitable DMA mask - aborting\n", ha->host_no); |
| 4337 | error = -ENODEV; | 4338 | error = -ENODEV; |
diff --git a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c index 94ef3f08d378..52b224a5d6fd 100644 --- a/drivers/scsi/qlogicfc.c +++ b/drivers/scsi/qlogicfc.c | |||
| @@ -61,6 +61,8 @@ | |||
| 61 | #include <linux/unistd.h> | 61 | #include <linux/unistd.h> |
| 62 | #include <linux/spinlock.h> | 62 | #include <linux/spinlock.h> |
| 63 | #include <linux/interrupt.h> | 63 | #include <linux/interrupt.h> |
| 64 | #include <linux/dma-mapping.h> | ||
| 65 | #include <linux/jiffies.h> | ||
| 64 | #include <asm/io.h> | 66 | #include <asm/io.h> |
| 65 | #include <asm/irq.h> | 67 | #include <asm/irq.h> |
| 66 | #include "scsi.h" | 68 | #include "scsi.h" |
| @@ -737,8 +739,8 @@ static int isp2x00_detect(struct scsi_host_template * tmpt) | |||
| 737 | continue; | 739 | continue; |
| 738 | 740 | ||
| 739 | /* Try to configure DMA attributes. */ | 741 | /* Try to configure DMA attributes. */ |
| 740 | if (pci_set_dma_mask(pdev, 0xffffffffffffffffULL) && | 742 | if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) && |
| 741 | pci_set_dma_mask(pdev, 0xffffffffULL)) | 743 | pci_set_dma_mask(pdev, DMA_32BIT_MASK)) |
| 742 | continue; | 744 | continue; |
| 743 | 745 | ||
| 744 | host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata)); | 746 | host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata)); |
| @@ -1325,7 +1327,7 @@ static int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *)) | |||
| 1325 | cmd->control_flags = cpu_to_le16(CFLAG_READ); | 1327 | cmd->control_flags = cpu_to_le16(CFLAG_READ); |
| 1326 | 1328 | ||
| 1327 | if (Cmnd->device->tagged_supported) { | 1329 | if (Cmnd->device->tagged_supported) { |
| 1328 | if ((jiffies - hostdata->tag_ages[Cmnd->device->id]) > (2 * ISP_TIMEOUT)) { | 1330 | if (time_after(jiffies, hostdata->tag_ages[Cmnd->device->id] + (2 * ISP_TIMEOUT))) { |
| 1329 | cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG); | 1331 | cmd->control_flags |= cpu_to_le16(CFLAG_ORDERED_TAG); |
| 1330 | hostdata->tag_ages[Cmnd->device->id] = jiffies; | 1332 | hostdata->tag_ages[Cmnd->device->id] = jiffies; |
| 1331 | } else | 1333 | } else |
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 1fd5fc6d0fe3..c7e78dcf09df 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
| 25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/jiffies.h> | ||
| 27 | 28 | ||
| 28 | #include <asm/byteorder.h> | 29 | #include <asm/byteorder.h> |
| 29 | 30 | ||
| @@ -1017,7 +1018,7 @@ static inline void cmd_frob(struct Command_Entry *cmd, struct scsi_cmnd *Cmnd, | |||
| 1017 | if (Cmnd->device->tagged_supported) { | 1018 | if (Cmnd->device->tagged_supported) { |
| 1018 | if (qpti->cmd_count[Cmnd->device->id] == 0) | 1019 | if (qpti->cmd_count[Cmnd->device->id] == 0) |
| 1019 | qpti->tag_ages[Cmnd->device->id] = jiffies; | 1020 | qpti->tag_ages[Cmnd->device->id] = jiffies; |
| 1020 | if ((jiffies - qpti->tag_ages[Cmnd->device->id]) > (5*HZ)) { | 1021 | if (time_after(jiffies, qpti->tag_ages[Cmnd->device->id] + (5*HZ))) { |
| 1021 | cmd->control_flags = CFLAG_ORDERED_TAG; | 1022 | cmd->control_flags = CFLAG_ORDERED_TAG; |
| 1022 | qpti->tag_ages[Cmnd->device->id] = jiffies; | 1023 | qpti->tag_ages[Cmnd->device->id] = jiffies; |
| 1023 | } else | 1024 | } else |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 5996d3cd0ed8..674b15c78f68 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
| @@ -1528,7 +1528,7 @@ static int serial8250_startup(struct uart_port *port) | |||
| 1528 | 1528 | ||
| 1529 | /* | 1529 | /* |
| 1530 | * Clear the FIFO buffers and disable them. | 1530 | * Clear the FIFO buffers and disable them. |
| 1531 | * (they will be reeanbled in set_termios()) | 1531 | * (they will be reenabled in set_termios()) |
| 1532 | */ | 1532 | */ |
| 1533 | serial8250_clear_fifos(up); | 1533 | serial8250_clear_fifos(up); |
| 1534 | 1534 | ||
diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c index 8d8d7a70d03e..3d1bfd07208d 100644 --- a/drivers/serial/8250_au1x00.c +++ b/drivers/serial/8250_au1x00.c | |||
| @@ -51,7 +51,7 @@ static struct plat_serial8250_port au1x00_data[] = { | |||
| 51 | #elif defined(CONFIG_SOC_AU1100) | 51 | #elif defined(CONFIG_SOC_AU1100) |
| 52 | PORT(UART0_ADDR, AU1100_UART0_INT), | 52 | PORT(UART0_ADDR, AU1100_UART0_INT), |
| 53 | PORT(UART1_ADDR, AU1100_UART1_INT), | 53 | PORT(UART1_ADDR, AU1100_UART1_INT), |
| 54 | PORT(UART2_ADDR, AU1100_UART2_INT), | 54 | /* The internal UART2 does not exist on the AU1100 processor. */ |
| 55 | PORT(UART3_ADDR, AU1100_UART3_INT), | 55 | PORT(UART3_ADDR, AU1100_UART3_INT), |
| 56 | #elif defined(CONFIG_SOC_AU1550) | 56 | #elif defined(CONFIG_SOC_AU1550) |
| 57 | PORT(UART0_ADDR, AU1550_UART0_INT), | 57 | PORT(UART0_ADDR, AU1550_UART0_INT), |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ceb3697bf84d..fe0d8b8e91c8 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
| @@ -620,22 +620,6 @@ config SERIAL_SH_SCI_CONSOLE | |||
| 620 | depends on SERIAL_SH_SCI=y | 620 | depends on SERIAL_SH_SCI=y |
| 621 | select SERIAL_CORE_CONSOLE | 621 | select SERIAL_CORE_CONSOLE |
| 622 | 622 | ||
| 623 | config SERIAL_AU1X00 | ||
| 624 | bool "Enable Au1x00 UART Support" | ||
| 625 | depends on MIPS && SOC_AU1X00 | ||
| 626 | select SERIAL_CORE | ||
| 627 | help | ||
| 628 | If you have an Alchemy AU1X00 processor (MIPS based) and you want | ||
| 629 | to use serial ports, say Y. Otherwise, say N. | ||
| 630 | |||
| 631 | config SERIAL_AU1X00_CONSOLE | ||
| 632 | bool "Enable Au1x00 serial console" | ||
| 633 | depends on SERIAL_AU1X00 | ||
| 634 | select SERIAL_CORE_CONSOLE | ||
| 635 | help | ||
| 636 | If you have an Alchemy AU1X00 processor (MIPS based) and you want | ||
| 637 | to use a console on a serial port, say Y. Otherwise, say N. | ||
| 638 | |||
| 639 | config SERIAL_CORE | 623 | config SERIAL_CORE |
| 640 | tristate | 624 | tristate |
| 641 | 625 | ||
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index a3a4323d9c86..d2b4c214876b 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
| @@ -41,7 +41,6 @@ obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o | |||
| 41 | obj-$(CONFIG_V850E_UART) += v850e_uart.o | 41 | obj-$(CONFIG_V850E_UART) += v850e_uart.o |
| 42 | obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o | 42 | obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o |
| 43 | obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o | 43 | obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o |
| 44 | obj-$(CONFIG_SERIAL_AU1X00) += au1x00_uart.o | ||
| 45 | obj-$(CONFIG_SERIAL_DZ) += dz.o | 44 | obj-$(CONFIG_SERIAL_DZ) += dz.o |
| 46 | obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o | 45 | obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o |
| 47 | obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o | 46 | obj-$(CONFIG_SERIAL_SGI_L1_CONSOLE) += sn_console.o |
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 127d6cd5de7f..1631414000a2 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
| @@ -51,8 +51,6 @@ | |||
| 51 | #include <linux/amba/serial.h> | 51 | #include <linux/amba/serial.h> |
| 52 | 52 | ||
| 53 | #include <asm/io.h> | 53 | #include <asm/io.h> |
| 54 | #include <asm/irq.h> | ||
| 55 | #include <asm/hardware.h> | ||
| 56 | 54 | ||
| 57 | #define UART_NR 2 | 55 | #define UART_NR 2 |
| 58 | 56 | ||
| @@ -65,26 +63,16 @@ | |||
| 65 | #define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0) | 63 | #define UART_RX_DATA(s) (((s) & UART01x_FR_RXFE) == 0) |
| 66 | #define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0) | 64 | #define UART_TX_READY(s) (((s) & UART01x_FR_TXFF) == 0) |
| 67 | 65 | ||
| 68 | #define UART_DUMMY_RSR_RX /*256*/0 | 66 | #define UART_DUMMY_RSR_RX 256 |
| 69 | #define UART_PORT_SIZE 64 | 67 | #define UART_PORT_SIZE 64 |
| 70 | 68 | ||
| 71 | /* | 69 | /* |
| 72 | * On the Integrator platform, the port RTS and DTR are provided by | ||
| 73 | * bits in the following SC_CTRLS register bits: | ||
| 74 | * RTS DTR | ||
| 75 | * UART0 7 6 | ||
| 76 | * UART1 5 4 | ||
| 77 | */ | ||
| 78 | #define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) | ||
| 79 | #define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) | ||
| 80 | |||
| 81 | /* | ||
| 82 | * We wrap our port structure around the generic uart_port. | 70 | * We wrap our port structure around the generic uart_port. |
| 83 | */ | 71 | */ |
| 84 | struct uart_amba_port { | 72 | struct uart_amba_port { |
| 85 | struct uart_port port; | 73 | struct uart_port port; |
| 86 | unsigned int dtr_mask; | 74 | struct amba_device *dev; |
| 87 | unsigned int rts_mask; | 75 | struct amba_pl010_data *data; |
| 88 | unsigned int old_status; | 76 | unsigned int old_status; |
| 89 | }; | 77 | }; |
| 90 | 78 | ||
| @@ -300,20 +288,9 @@ static unsigned int pl010_get_mctrl(struct uart_port *port) | |||
| 300 | static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl) | 288 | static void pl010_set_mctrl(struct uart_port *port, unsigned int mctrl) |
| 301 | { | 289 | { |
| 302 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 290 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
| 303 | unsigned int ctrls = 0, ctrlc = 0; | ||
| 304 | |||
| 305 | if (mctrl & TIOCM_RTS) | ||
| 306 | ctrlc |= uap->rts_mask; | ||
| 307 | else | ||
| 308 | ctrls |= uap->rts_mask; | ||
| 309 | 291 | ||
| 310 | if (mctrl & TIOCM_DTR) | 292 | if (uap->data) |
| 311 | ctrlc |= uap->dtr_mask; | 293 | uap->data->set_mctrl(uap->dev, uap->port.membase, mctrl); |
| 312 | else | ||
| 313 | ctrls |= uap->dtr_mask; | ||
| 314 | |||
| 315 | __raw_writel(ctrls, SC_CTRLS); | ||
| 316 | __raw_writel(ctrlc, SC_CTRLC); | ||
| 317 | } | 294 | } |
| 318 | 295 | ||
| 319 | static void pl010_break_ctl(struct uart_port *port, int break_state) | 296 | static void pl010_break_ctl(struct uart_port *port, int break_state) |
| @@ -539,38 +516,7 @@ static struct uart_ops amba_pl010_pops = { | |||
| 539 | .verify_port = pl010_verify_port, | 516 | .verify_port = pl010_verify_port, |
| 540 | }; | 517 | }; |
| 541 | 518 | ||
| 542 | static struct uart_amba_port amba_ports[UART_NR] = { | 519 | static struct uart_amba_port *amba_ports[UART_NR]; |
| 543 | { | ||
| 544 | .port = { | ||
| 545 | .membase = (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE), | ||
| 546 | .mapbase = INTEGRATOR_UART0_BASE, | ||
| 547 | .iotype = UPIO_MEM, | ||
| 548 | .irq = IRQ_UARTINT0, | ||
| 549 | .uartclk = 14745600, | ||
| 550 | .fifosize = 16, | ||
| 551 | .ops = &amba_pl010_pops, | ||
| 552 | .flags = UPF_BOOT_AUTOCONF, | ||
| 553 | .line = 0, | ||
| 554 | }, | ||
| 555 | .dtr_mask = 1 << 5, | ||
| 556 | .rts_mask = 1 << 4, | ||
| 557 | }, | ||
| 558 | { | ||
| 559 | .port = { | ||
| 560 | .membase = (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE), | ||
| 561 | .mapbase = INTEGRATOR_UART1_BASE, | ||
| 562 | .iotype = UPIO_MEM, | ||
| 563 | .irq = IRQ_UARTINT1, | ||
| 564 | .uartclk = 14745600, | ||
| 565 | .fifosize = 16, | ||
| 566 | .ops = &amba_pl010_pops, | ||
| 567 | .flags = UPF_BOOT_AUTOCONF, | ||
| 568 | .line = 1, | ||
| 569 | }, | ||
| 570 | .dtr_mask = 1 << 7, | ||
| 571 | .rts_mask = 1 << 6, | ||
| 572 | } | ||
| 573 | }; | ||
| 574 | 520 | ||
| 575 | #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE | 521 | #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE |
| 576 | 522 | ||
| @@ -588,7 +534,7 @@ static void pl010_console_putchar(struct uart_port *port, int ch) | |||
| 588 | static void | 534 | static void |
| 589 | pl010_console_write(struct console *co, const char *s, unsigned int count) | 535 | pl010_console_write(struct console *co, const char *s, unsigned int count) |
| 590 | { | 536 | { |
| 591 | struct uart_port *port = &amba_ports[co->index].port; | 537 | struct uart_port *port = &amba_ports[co->index]->port; |
| 592 | unsigned int status, old_cr; | 538 | unsigned int status, old_cr; |
| 593 | 539 | ||
| 594 | /* | 540 | /* |
| @@ -651,7 +597,7 @@ static int __init pl010_console_setup(struct console *co, char *options) | |||
| 651 | */ | 597 | */ |
| 652 | if (co->index >= UART_NR) | 598 | if (co->index >= UART_NR) |
| 653 | co->index = 0; | 599 | co->index = 0; |
| 654 | port = &amba_ports[co->index].port; | 600 | port = &amba_ports[co->index]->port; |
| 655 | 601 | ||
| 656 | if (options) | 602 | if (options) |
| 657 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 603 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
| @@ -672,24 +618,6 @@ static struct console amba_console = { | |||
| 672 | .data = &amba_reg, | 618 | .data = &amba_reg, |
| 673 | }; | 619 | }; |
| 674 | 620 | ||
| 675 | static int __init amba_console_init(void) | ||
| 676 | { | ||
| 677 | /* | ||
| 678 | * All port initializations are done statically | ||
| 679 | */ | ||
| 680 | register_console(&amba_console); | ||
| 681 | return 0; | ||
| 682 | } | ||
| 683 | console_initcall(amba_console_init); | ||
| 684 | |||
| 685 | static int __init amba_late_console_init(void) | ||
| 686 | { | ||
| 687 | if (!(amba_console.flags & CON_ENABLED)) | ||
| 688 | register_console(&amba_console); | ||
| 689 | return 0; | ||
| 690 | } | ||
| 691 | late_initcall(amba_late_console_init); | ||
| 692 | |||
| 693 | #define AMBA_CONSOLE &amba_console | 621 | #define AMBA_CONSOLE &amba_console |
| 694 | #else | 622 | #else |
| 695 | #define AMBA_CONSOLE NULL | 623 | #define AMBA_CONSOLE NULL |
| @@ -707,30 +635,76 @@ static struct uart_driver amba_reg = { | |||
| 707 | 635 | ||
| 708 | static int pl010_probe(struct amba_device *dev, void *id) | 636 | static int pl010_probe(struct amba_device *dev, void *id) |
| 709 | { | 637 | { |
| 710 | int i; | 638 | struct uart_amba_port *port; |
| 639 | void __iomem *base; | ||
| 640 | int i, ret; | ||
| 711 | 641 | ||
| 712 | for (i = 0; i < UART_NR; i++) { | 642 | for (i = 0; i < ARRAY_SIZE(amba_ports); i++) |
| 713 | if (amba_ports[i].port.mapbase != dev->res.start) | 643 | if (amba_ports[i] == NULL) |
| 714 | continue; | 644 | break; |
| 715 | 645 | ||
| 716 | amba_ports[i].port.dev = &dev->dev; | 646 | if (i == ARRAY_SIZE(amba_ports)) { |
| 717 | uart_add_one_port(&amba_reg, &amba_ports[i].port); | 647 | ret = -EBUSY; |
| 718 | amba_set_drvdata(dev, &amba_ports[i]); | 648 | goto out; |
| 719 | break; | ||
| 720 | } | 649 | } |
| 721 | 650 | ||
| 722 | return 0; | 651 | port = kzalloc(sizeof(struct uart_amba_port), GFP_KERNEL); |
| 652 | if (!port) { | ||
| 653 | ret = -ENOMEM; | ||
| 654 | goto out; | ||
| 655 | } | ||
| 656 | |||
| 657 | base = ioremap(dev->res.start, PAGE_SIZE); | ||
| 658 | if (!base) { | ||
| 659 | ret = -ENOMEM; | ||
| 660 | goto free; | ||
| 661 | } | ||
| 662 | |||
| 663 | port->port.dev = &dev->dev; | ||
| 664 | port->port.mapbase = dev->res.start; | ||
| 665 | port->port.membase = base; | ||
| 666 | port->port.iotype = UPIO_MEM; | ||
| 667 | port->port.irq = dev->irq[0]; | ||
| 668 | port->port.uartclk = 14745600; | ||
| 669 | port->port.fifosize = 16; | ||
| 670 | port->port.ops = &amba_pl010_pops; | ||
| 671 | port->port.flags = UPF_BOOT_AUTOCONF; | ||
| 672 | port->port.line = i; | ||
| 673 | port->dev = dev; | ||
| 674 | port->data = dev->dev.platform_data; | ||
| 675 | |||
| 676 | amba_ports[i] = port; | ||
| 677 | |||
| 678 | amba_set_drvdata(dev, port); | ||
| 679 | ret = uart_add_one_port(&amba_reg, &port->port); | ||
| 680 | if (ret) { | ||
| 681 | amba_set_drvdata(dev, NULL); | ||
| 682 | amba_ports[i] = NULL; | ||
| 683 | iounmap(base); | ||
| 684 | free: | ||
| 685 | kfree(port); | ||
| 686 | } | ||
| 687 | |||
| 688 | out: | ||
| 689 | return ret; | ||
| 723 | } | 690 | } |
| 724 | 691 | ||
| 725 | static int pl010_remove(struct amba_device *dev) | 692 | static int pl010_remove(struct amba_device *dev) |
| 726 | { | 693 | { |
| 727 | struct uart_amba_port *uap = amba_get_drvdata(dev); | 694 | struct uart_amba_port *port = amba_get_drvdata(dev); |
| 728 | 695 | int i; | |
| 729 | if (uap) | ||
| 730 | uart_remove_one_port(&amba_reg, &uap->port); | ||
| 731 | 696 | ||
| 732 | amba_set_drvdata(dev, NULL); | 697 | amba_set_drvdata(dev, NULL); |
| 733 | 698 | ||
| 699 | uart_remove_one_port(&amba_reg, &port->port); | ||
| 700 | |||
| 701 | for (i = 0; i < ARRAY_SIZE(amba_ports); i++) | ||
| 702 | if (amba_ports[i] == port) | ||
| 703 | amba_ports[i] = NULL; | ||
| 704 | |||
| 705 | iounmap(port->port.membase); | ||
| 706 | kfree(port); | ||
| 707 | |||
| 734 | return 0; | 708 | return 0; |
| 735 | } | 709 | } |
| 736 | 710 | ||
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c deleted file mode 100644 index 948880ac5878..000000000000 --- a/drivers/serial/au1x00_uart.c +++ /dev/null | |||
| @@ -1,1287 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Driver for 8250/16550-type serial ports | ||
| 3 | * | ||
| 4 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2001 Russell King. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * A note about mapbase / membase | ||
| 14 | * | ||
| 15 | * mapbase is the physical address of the IO port. Currently, we don't | ||
| 16 | * support this very well, and it may well be dropped from this driver | ||
| 17 | * in future. As such, mapbase should be NULL. | ||
| 18 | * | ||
| 19 | * membase is an 'ioremapped' cookie. This is compatible with the old | ||
| 20 | * serial.c driver, and is currently the preferred form. | ||
| 21 | */ | ||
| 22 | #include <linux/config.h> | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/tty.h> | ||
| 25 | #include <linux/ioport.h> | ||
| 26 | #include <linux/init.h> | ||
| 27 | #include <linux/console.h> | ||
| 28 | #include <linux/sysrq.h> | ||
| 29 | #include <linux/serial.h> | ||
| 30 | #include <linux/serialP.h> | ||
| 31 | #include <linux/delay.h> | ||
| 32 | |||
| 33 | #include <asm/serial.h> | ||
| 34 | #include <asm/io.h> | ||
| 35 | #include <asm/irq.h> | ||
| 36 | #include <asm/mach-au1x00/au1000.h> | ||
| 37 | |||
| 38 | #if defined(CONFIG_SERIAL_AU1X00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | ||
| 39 | #define SUPPORT_SYSRQ | ||
| 40 | #endif | ||
| 41 | |||
| 42 | #include <linux/serial_core.h> | ||
| 43 | #include "8250.h" | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Debugging. | ||
| 47 | */ | ||
| 48 | #if 0 | ||
| 49 | #define DEBUG_AUTOCONF(fmt...) printk(fmt) | ||
| 50 | #else | ||
| 51 | #define DEBUG_AUTOCONF(fmt...) do { } while (0) | ||
| 52 | #endif | ||
| 53 | |||
| 54 | #if 0 | ||
| 55 | #define DEBUG_INTR(fmt...) printk(fmt) | ||
| 56 | #else | ||
| 57 | #define DEBUG_INTR(fmt...) do { } while (0) | ||
| 58 | #endif | ||
| 59 | |||
| 60 | #define PASS_LIMIT 256 | ||
| 61 | |||
| 62 | /* | ||
| 63 | * We default to IRQ0 for the "no irq" hack. Some | ||
| 64 | * machine types want others as well - they're free | ||
| 65 | * to redefine this in their header file. | ||
| 66 | */ | ||
| 67 | #define is_real_interrupt(irq) ((irq) != 0) | ||
| 68 | |||
| 69 | static struct old_serial_port old_serial_port[] = { | ||
| 70 | { .baud_base = 0, | ||
| 71 | .iomem_base = (u8 *)UART0_ADDR, | ||
| 72 | .irq = AU1000_UART0_INT, | ||
| 73 | .flags = STD_COM_FLAGS, | ||
| 74 | .iomem_reg_shift = 2, | ||
| 75 | }, { | ||
| 76 | .baud_base = 0, | ||
| 77 | .iomem_base = (u8 *)UART1_ADDR, | ||
| 78 | .irq = AU1000_UART1_INT, | ||
| 79 | .flags = STD_COM_FLAGS, | ||
| 80 | .iomem_reg_shift = 2 | ||
| 81 | }, { | ||
| 82 | .baud_base = 0, | ||
| 83 | .iomem_base = (u8 *)UART2_ADDR, | ||
| 84 | .irq = AU1000_UART2_INT, | ||
| 85 | .flags = STD_COM_FLAGS, | ||
| 86 | .iomem_reg_shift = 2 | ||
| 87 | }, { | ||
| 88 | .baud_base = 0, | ||
| 89 | .iomem_base = (u8 *)UART3_ADDR, | ||
| 90 | .irq = AU1000_UART3_INT, | ||
| 91 | .flags = STD_COM_FLAGS, | ||
| 92 | .iomem_reg_shift = 2 | ||
| 93 | } | ||
| 94 | }; | ||
| 95 | |||
| 96 | #define UART_NR ARRAY_SIZE(old_serial_port) | ||
| 97 | |||
| 98 | struct uart_8250_port { | ||
| 99 | struct uart_port port; | ||
| 100 | struct timer_list timer; /* "no irq" timer */ | ||
| 101 | struct list_head list; /* ports on this IRQ */ | ||
| 102 | unsigned short rev; | ||
| 103 | unsigned char acr; | ||
| 104 | unsigned char ier; | ||
| 105 | unsigned char lcr; | ||
| 106 | unsigned char mcr_mask; /* mask of user bits */ | ||
| 107 | unsigned char mcr_force; /* mask of forced bits */ | ||
| 108 | unsigned char lsr_break_flag; | ||
| 109 | |||
| 110 | /* | ||
| 111 | * We provide a per-port pm hook. | ||
| 112 | */ | ||
| 113 | void (*pm)(struct uart_port *port, | ||
| 114 | unsigned int state, unsigned int old); | ||
| 115 | }; | ||
| 116 | |||
| 117 | struct irq_info { | ||
| 118 | spinlock_t lock; | ||
| 119 | struct list_head *head; | ||
| 120 | }; | ||
| 121 | |||
| 122 | static struct irq_info irq_lists[NR_IRQS]; | ||
| 123 | |||
| 124 | /* | ||
| 125 | * Here we define the default xmit fifo size used for each type of UART. | ||
| 126 | */ | ||
| 127 | static const struct serial_uart_config uart_config[PORT_MAX_8250+1] = { | ||
| 128 | { "unknown", 1, 0 }, | ||
| 129 | { "8250", 1, 0 }, | ||
| 130 | { "16450", 1, 0 }, | ||
| 131 | { "16550", 1, 0 }, | ||
| 132 | /* PORT_16550A */ | ||
| 133 | { "AU1X00_UART",16, UART_CLEAR_FIFO | UART_USE_FIFO }, | ||
| 134 | }; | ||
| 135 | |||
| 136 | static unsigned int serial_in(struct uart_8250_port *up, int offset) | ||
| 137 | { | ||
| 138 | return au_readl((unsigned long)up->port.membase + offset); | ||
| 139 | } | ||
| 140 | |||
| 141 | static void serial_out(struct uart_8250_port *up, int offset, int value) | ||
| 142 | { | ||
| 143 | au_writel(value, (unsigned long)up->port.membase + offset); | ||
| 144 | } | ||
| 145 | |||
| 146 | #define serial_inp(up, offset) serial_in(up, offset) | ||
| 147 | #define serial_outp(up, offset, value) serial_out(up, offset, value) | ||
| 148 | |||
| 149 | /* | ||
| 150 | * This routine is called by rs_init() to initialize a specific serial | ||
| 151 | * port. It determines what type of UART chip this serial port is | ||
| 152 | * using: 8250, 16450, 16550, 16550A. The important question is | ||
| 153 | * whether or not this UART is a 16550A or not, since this will | ||
| 154 | * determine whether or not we can use its FIFO features or not. | ||
| 155 | */ | ||
| 156 | static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | ||
| 157 | { | ||
| 158 | unsigned char save_lcr, save_mcr; | ||
| 159 | unsigned long flags; | ||
| 160 | |||
| 161 | if (!up->port.iobase && !up->port.mapbase && !up->port.membase) | ||
| 162 | return; | ||
| 163 | |||
| 164 | DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%08lx): ", | ||
| 165 | up->port.line, up->port.iobase, up->port.membase); | ||
| 166 | |||
| 167 | /* | ||
| 168 | * We really do need global IRQs disabled here - we're going to | ||
| 169 | * be frobbing the chips IRQ enable register to see if it exists. | ||
| 170 | */ | ||
| 171 | spin_lock_irqsave(&up->port.lock, flags); | ||
| 172 | // save_flags(flags); cli(); | ||
| 173 | |||
| 174 | save_mcr = serial_in(up, UART_MCR); | ||
| 175 | save_lcr = serial_in(up, UART_LCR); | ||
| 176 | |||
| 177 | up->port.type = PORT_16550A; | ||
| 178 | serial_outp(up, UART_LCR, save_lcr); | ||
| 179 | |||
| 180 | up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; | ||
| 181 | |||
| 182 | if (up->port.type == PORT_UNKNOWN) | ||
| 183 | goto out; | ||
| 184 | |||
| 185 | /* | ||
| 186 | * Reset the UART. | ||
| 187 | */ | ||
| 188 | serial_outp(up, UART_MCR, save_mcr); | ||
| 189 | serial_outp(up, UART_FCR, (UART_FCR_ENABLE_FIFO | | ||
| 190 | UART_FCR_CLEAR_RCVR | | ||
| 191 | UART_FCR_CLEAR_XMIT)); | ||
| 192 | serial_outp(up, UART_FCR, 0); | ||
| 193 | (void)serial_in(up, UART_RX); | ||
| 194 | serial_outp(up, UART_IER, 0); | ||
| 195 | |||
| 196 | out: | ||
| 197 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
| 198 | // restore_flags(flags); | ||
| 199 | DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name); | ||
| 200 | } | ||
| 201 | |||
| 202 | static void serial8250_stop_tx(struct uart_port *port) | ||
| 203 | { | ||
| 204 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 205 | |||
| 206 | if (up->ier & UART_IER_THRI) { | ||
| 207 | up->ier &= ~UART_IER_THRI; | ||
| 208 | serial_out(up, UART_IER, up->ier); | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | static void serial8250_start_tx(struct uart_port *port) | ||
| 213 | { | ||
| 214 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 215 | |||
| 216 | if (!(up->ier & UART_IER_THRI)) { | ||
| 217 | up->ier |= UART_IER_THRI; | ||
| 218 | serial_out(up, UART_IER, up->ier); | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | static void serial8250_stop_rx(struct uart_port *port) | ||
| 223 | { | ||
| 224 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 225 | |||
| 226 | up->ier &= ~UART_IER_RLSI; | ||
| 227 | up->port.read_status_mask &= ~UART_LSR_DR; | ||
| 228 | serial_out(up, UART_IER, up->ier); | ||
| 229 | } | ||
| 230 | |||
| 231 | static void serial8250_enable_ms(struct uart_port *port) | ||
| 232 | { | ||
| 233 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 234 | |||
| 235 | up->ier |= UART_IER_MSI; | ||
| 236 | serial_out(up, UART_IER, up->ier); | ||
| 237 | } | ||
| 238 | |||
| 239 | static void | ||
| 240 | receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs) | ||
| 241 | { | ||
| 242 | struct tty_struct *tty = up->port.info->tty; | ||
| 243 | unsigned char ch, flag; | ||
| 244 | int max_count = 256; | ||
| 245 | |||
| 246 | do { | ||
| 247 | ch = serial_inp(up, UART_RX); | ||
| 248 | flag = TTY_NORMAL; | ||
| 249 | up->port.icount.rx++; | ||
| 250 | |||
| 251 | if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | | ||
| 252 | UART_LSR_FE | UART_LSR_OE))) { | ||
| 253 | /* | ||
| 254 | * For statistics only | ||
| 255 | */ | ||
| 256 | if (*status & UART_LSR_BI) { | ||
| 257 | *status &= ~(UART_LSR_FE | UART_LSR_PE); | ||
| 258 | up->port.icount.brk++; | ||
| 259 | /* | ||
| 260 | * We do the SysRQ and SAK checking | ||
| 261 | * here because otherwise the break | ||
| 262 | * may get masked by ignore_status_mask | ||
| 263 | * or read_status_mask. | ||
| 264 | */ | ||
| 265 | if (uart_handle_break(&up->port)) | ||
| 266 | goto ignore_char; | ||
| 267 | } else if (*status & UART_LSR_PE) | ||
| 268 | up->port.icount.parity++; | ||
| 269 | else if (*status & UART_LSR_FE) | ||
| 270 | up->port.icount.frame++; | ||
| 271 | if (*status & UART_LSR_OE) | ||
| 272 | up->port.icount.overrun++; | ||
| 273 | |||
| 274 | /* | ||
| 275 | * Mask off conditions which should be ingored. | ||
| 276 | */ | ||
| 277 | *status &= up->port.read_status_mask; | ||
| 278 | |||
| 279 | #ifdef CONFIG_SERIAL_AU1X00_CONSOLE | ||
| 280 | if (up->port.line == up->port.cons->index) { | ||
| 281 | /* Recover the break flag from console xmit */ | ||
| 282 | *status |= up->lsr_break_flag; | ||
| 283 | up->lsr_break_flag = 0; | ||
| 284 | } | ||
| 285 | #endif | ||
| 286 | if (*status & UART_LSR_BI) { | ||
| 287 | DEBUG_INTR("handling break...."); | ||
| 288 | flag = TTY_BREAK; | ||
| 289 | } else if (*status & UART_LSR_PE) | ||
| 290 | flag = TTY_PARITY; | ||
| 291 | else if (*status & UART_LSR_FE) | ||
| 292 | flag = TTY_FRAME; | ||
| 293 | } | ||
| 294 | if (uart_handle_sysrq_char(&up->port, ch, regs)) | ||
| 295 | goto ignore_char; | ||
| 296 | if ((*status & up->port.ignore_status_mask) == 0) | ||
| 297 | tty_insert_flip_char(tty, ch, flag); | ||
| 298 | if (*status & UART_LSR_OE) | ||
| 299 | /* | ||
| 300 | * Overrun is special, since it's reported | ||
| 301 | * immediately, and doesn't affect the current | ||
| 302 | * character. | ||
| 303 | */ | ||
| 304 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
| 305 | } | ||
| 306 | ignore_char: | ||
| 307 | *status = serial_inp(up, UART_LSR); | ||
| 308 | } while ((*status & UART_LSR_DR) && (max_count-- > 0)); | ||
| 309 | spin_unlock(&up->port.lock); | ||
| 310 | tty_flip_buffer_push(tty); | ||
| 311 | spin_lock(&up->port.lock); | ||
| 312 | } | ||
| 313 | |||
| 314 | static void transmit_chars(struct uart_8250_port *up) | ||
| 315 | { | ||
| 316 | struct circ_buf *xmit = &up->port.info->xmit; | ||
| 317 | int count; | ||
| 318 | |||
| 319 | if (up->port.x_char) { | ||
| 320 | serial_outp(up, UART_TX, up->port.x_char); | ||
| 321 | up->port.icount.tx++; | ||
| 322 | up->port.x_char = 0; | ||
| 323 | return; | ||
| 324 | } | ||
| 325 | if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { | ||
| 326 | serial8250_stop_tx(&up->port); | ||
| 327 | return; | ||
| 328 | } | ||
| 329 | |||
| 330 | count = up->port.fifosize; | ||
| 331 | do { | ||
| 332 | serial_out(up, UART_TX, xmit->buf[xmit->tail]); | ||
| 333 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
| 334 | up->port.icount.tx++; | ||
| 335 | if (uart_circ_empty(xmit)) | ||
| 336 | break; | ||
| 337 | } while (--count > 0); | ||
| 338 | |||
| 339 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
| 340 | uart_write_wakeup(&up->port); | ||
| 341 | |||
| 342 | DEBUG_INTR("THRE..."); | ||
| 343 | |||
| 344 | if (uart_circ_empty(xmit)) | ||
| 345 | serial8250_stop_tx(&up->port); | ||
| 346 | } | ||
| 347 | |||
| 348 | static void check_modem_status(struct uart_8250_port *up) | ||
| 349 | { | ||
| 350 | int status; | ||
| 351 | |||
| 352 | status = serial_in(up, UART_MSR); | ||
| 353 | |||
| 354 | if ((status & UART_MSR_ANY_DELTA) == 0) | ||
| 355 | return; | ||
| 356 | |||
| 357 | if (status & UART_MSR_TERI) | ||
| 358 | up->port.icount.rng++; | ||
| 359 | if (status & UART_MSR_DDSR) | ||
| 360 | up->port.icount.dsr++; | ||
| 361 | if (status & UART_MSR_DDCD) | ||
| 362 | uart_handle_dcd_change(&up->port, status & UART_MSR_DCD); | ||
| 363 | if (status & UART_MSR_DCTS) | ||
| 364 | uart_handle_cts_change(&up->port, status & UART_MSR_CTS); | ||
| 365 | |||
| 366 | wake_up_interruptible(&up->port.info->delta_msr_wait); | ||
| 367 | } | ||
| 368 | |||
| 369 | /* | ||
| 370 | * This handles the interrupt from one port. | ||
| 371 | */ | ||
| 372 | static inline void | ||
| 373 | serial8250_handle_port(struct uart_8250_port *up, struct pt_regs *regs) | ||
| 374 | { | ||
| 375 | unsigned int status = serial_inp(up, UART_LSR); | ||
| 376 | |||
| 377 | DEBUG_INTR("status = %x...", status); | ||
| 378 | |||
| 379 | if (status & UART_LSR_DR) | ||
| 380 | receive_chars(up, &status, regs); | ||
| 381 | check_modem_status(up); | ||
| 382 | if (status & UART_LSR_THRE) | ||
| 383 | transmit_chars(up); | ||
| 384 | } | ||
| 385 | |||
| 386 | /* | ||
| 387 | * This is the serial driver's interrupt routine. | ||
| 388 | * | ||
| 389 | * Arjan thinks the old way was overly complex, so it got simplified. | ||
| 390 | * Alan disagrees, saying that need the complexity to handle the weird | ||
| 391 | * nature of ISA shared interrupts. (This is a special exception.) | ||
| 392 | * | ||
| 393 | * In order to handle ISA shared interrupts properly, we need to check | ||
| 394 | * that all ports have been serviced, and therefore the ISA interrupt | ||
| 395 | * line has been de-asserted. | ||
| 396 | * | ||
| 397 | * This means we need to loop through all ports. checking that they | ||
| 398 | * don't have an interrupt pending. | ||
| 399 | */ | ||
| 400 | static irqreturn_t serial8250_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
| 401 | { | ||
| 402 | struct irq_info *i = dev_id; | ||
| 403 | struct list_head *l, *end = NULL; | ||
| 404 | int pass_counter = 0; | ||
| 405 | |||
| 406 | DEBUG_INTR("serial8250_interrupt(%d)...", irq); | ||
| 407 | |||
| 408 | spin_lock(&i->lock); | ||
| 409 | |||
| 410 | l = i->head; | ||
| 411 | do { | ||
| 412 | struct uart_8250_port *up; | ||
| 413 | unsigned int iir; | ||
| 414 | |||
| 415 | up = list_entry(l, struct uart_8250_port, list); | ||
| 416 | |||
| 417 | iir = serial_in(up, UART_IIR); | ||
| 418 | if (!(iir & UART_IIR_NO_INT)) { | ||
| 419 | spin_lock(&up->port.lock); | ||
| 420 | serial8250_handle_port(up, regs); | ||
| 421 | spin_unlock(&up->port.lock); | ||
| 422 | |||
| 423 | end = NULL; | ||
| 424 | } else if (end == NULL) | ||
| 425 | end = l; | ||
| 426 | |||
| 427 | l = l->next; | ||
| 428 | |||
| 429 | if (l == i->head && pass_counter++ > PASS_LIMIT) { | ||
| 430 | /* If we hit this, we're dead. */ | ||
| 431 | printk(KERN_ERR "serial8250: too much work for " | ||
| 432 | "irq%d\n", irq); | ||
| 433 | break; | ||
| 434 | } | ||
| 435 | } while (l != end); | ||
| 436 | |||
| 437 | spin_unlock(&i->lock); | ||
| 438 | |||
| 439 | DEBUG_INTR("end.\n"); | ||
| 440 | /* FIXME! Was it really ours? */ | ||
| 441 | return IRQ_HANDLED; | ||
| 442 | } | ||
| 443 | |||
| 444 | /* | ||
| 445 | * To support ISA shared interrupts, we need to have one interrupt | ||
| 446 | * handler that ensures that the IRQ line has been deasserted | ||
| 447 | * before returning. Failing to do this will result in the IRQ | ||
| 448 | * line being stuck active, and, since ISA irqs are edge triggered, | ||
| 449 | * no more IRQs will be seen. | ||
| 450 | */ | ||
| 451 | static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up) | ||
| 452 | { | ||
| 453 | spin_lock_irq(&i->lock); | ||
| 454 | |||
| 455 | if (!list_empty(i->head)) { | ||
| 456 | if (i->head == &up->list) | ||
| 457 | i->head = i->head->next; | ||
| 458 | list_del(&up->list); | ||
| 459 | } else { | ||
| 460 | BUG_ON(i->head != &up->list); | ||
| 461 | i->head = NULL; | ||
| 462 | } | ||
| 463 | |||
| 464 | spin_unlock_irq(&i->lock); | ||
| 465 | } | ||
| 466 | |||
| 467 | static int serial_link_irq_chain(struct uart_8250_port *up) | ||
| 468 | { | ||
| 469 | struct irq_info *i = irq_lists + up->port.irq; | ||
| 470 | int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? SA_SHIRQ : 0; | ||
| 471 | |||
| 472 | spin_lock_irq(&i->lock); | ||
| 473 | |||
| 474 | if (i->head) { | ||
| 475 | list_add(&up->list, i->head); | ||
| 476 | spin_unlock_irq(&i->lock); | ||
| 477 | |||
| 478 | ret = 0; | ||
| 479 | } else { | ||
| 480 | INIT_LIST_HEAD(&up->list); | ||
| 481 | i->head = &up->list; | ||
| 482 | spin_unlock_irq(&i->lock); | ||
| 483 | |||
| 484 | ret = request_irq(up->port.irq, serial8250_interrupt, | ||
| 485 | irq_flags, "serial", i); | ||
| 486 | if (ret < 0) | ||
| 487 | serial_do_unlink(i, up); | ||
| 488 | } | ||
| 489 | |||
| 490 | return ret; | ||
| 491 | } | ||
| 492 | |||
| 493 | static void serial_unlink_irq_chain(struct uart_8250_port *up) | ||
| 494 | { | ||
| 495 | struct irq_info *i = irq_lists + up->port.irq; | ||
| 496 | |||
| 497 | BUG_ON(i->head == NULL); | ||
| 498 | |||
| 499 | if (list_empty(i->head)) | ||
| 500 | free_irq(up->port.irq, i); | ||
| 501 | |||
| 502 | serial_do_unlink(i, up); | ||
| 503 | } | ||
| 504 | |||
| 505 | /* | ||
| 506 | * This function is used to handle ports that do not have an | ||
| 507 | * interrupt. This doesn't work very well for 16450's, but gives | ||
| 508 | * barely passable results for a 16550A. (Although at the expense | ||
| 509 | * of much CPU overhead). | ||
| 510 | */ | ||
| 511 | static void serial8250_timeout(unsigned long data) | ||
| 512 | { | ||
| 513 | struct uart_8250_port *up = (struct uart_8250_port *)data; | ||
| 514 | unsigned int timeout; | ||
| 515 | unsigned int iir; | ||
| 516 | |||
| 517 | iir = serial_in(up, UART_IIR); | ||
| 518 | if (!(iir & UART_IIR_NO_INT)) { | ||
| 519 | spin_lock(&up->port.lock); | ||
| 520 | serial8250_handle_port(up, NULL); | ||
| 521 | spin_unlock(&up->port.lock); | ||
| 522 | } | ||
| 523 | |||
| 524 | timeout = up->port.timeout; | ||
| 525 | timeout = timeout > 6 ? (timeout / 2 - 2) : 1; | ||
| 526 | mod_timer(&up->timer, jiffies + timeout); | ||
| 527 | } | ||
| 528 | |||
| 529 | static unsigned int serial8250_tx_empty(struct uart_port *port) | ||
| 530 | { | ||
| 531 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 532 | unsigned long flags; | ||
| 533 | unsigned int ret; | ||
| 534 | |||
| 535 | spin_lock_irqsave(&up->port.lock, flags); | ||
| 536 | ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0; | ||
| 537 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
| 538 | |||
| 539 | return ret; | ||
| 540 | } | ||
| 541 | |||
| 542 | static unsigned int serial8250_get_mctrl(struct uart_port *port) | ||
| 543 | { | ||
| 544 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 545 | unsigned char status; | ||
| 546 | unsigned int ret; | ||
| 547 | |||
| 548 | status = serial_in(up, UART_MSR); | ||
| 549 | |||
| 550 | ret = 0; | ||
| 551 | if (status & UART_MSR_DCD) | ||
| 552 | ret |= TIOCM_CAR; | ||
| 553 | if (status & UART_MSR_RI) | ||
| 554 | ret |= TIOCM_RNG; | ||
| 555 | if (status & UART_MSR_DSR) | ||
| 556 | ret |= TIOCM_DSR; | ||
| 557 | if (status & UART_MSR_CTS) | ||
| 558 | ret |= TIOCM_CTS; | ||
| 559 | return ret; | ||
| 560 | } | ||
| 561 | |||
| 562 | static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
| 563 | { | ||
| 564 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 565 | unsigned char mcr = 0; | ||
| 566 | |||
| 567 | if (mctrl & TIOCM_RTS) | ||
| 568 | mcr |= UART_MCR_RTS; | ||
| 569 | if (mctrl & TIOCM_DTR) | ||
| 570 | mcr |= UART_MCR_DTR; | ||
| 571 | if (mctrl & TIOCM_OUT1) | ||
| 572 | mcr |= UART_MCR_OUT1; | ||
| 573 | if (mctrl & TIOCM_OUT2) | ||
| 574 | mcr |= UART_MCR_OUT2; | ||
| 575 | if (mctrl & TIOCM_LOOP) | ||
| 576 | mcr |= UART_MCR_LOOP; | ||
| 577 | |||
| 578 | mcr = (mcr & up->mcr_mask) | up->mcr_force; | ||
| 579 | |||
| 580 | serial_out(up, UART_MCR, mcr); | ||
| 581 | } | ||
| 582 | |||
| 583 | static void serial8250_break_ctl(struct uart_port *port, int break_state) | ||
| 584 | { | ||
| 585 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 586 | unsigned long flags; | ||
| 587 | |||
| 588 | spin_lock_irqsave(&up->port.lock, flags); | ||
| 589 | if (break_state == -1) | ||
| 590 | up->lcr |= UART_LCR_SBC; | ||
| 591 | else | ||
| 592 | up->lcr &= ~UART_LCR_SBC; | ||
| 593 | serial_out(up, UART_LCR, up->lcr); | ||
| 594 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
| 595 | } | ||
| 596 | |||
| 597 | static int serial8250_startup(struct uart_port *port) | ||
| 598 | { | ||
| 599 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 600 | unsigned long flags; | ||
| 601 | int retval; | ||
| 602 | |||
| 603 | /* | ||
| 604 | * Clear the FIFO buffers and disable them. | ||
| 605 | * (they will be reeanbled in set_termios()) | ||
| 606 | */ | ||
| 607 | if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) { | ||
| 608 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); | ||
| 609 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | | ||
| 610 | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); | ||
| 611 | serial_outp(up, UART_FCR, 0); | ||
| 612 | } | ||
| 613 | |||
| 614 | /* | ||
| 615 | * Clear the interrupt registers. | ||
| 616 | */ | ||
| 617 | (void) serial_inp(up, UART_LSR); | ||
| 618 | (void) serial_inp(up, UART_RX); | ||
| 619 | (void) serial_inp(up, UART_IIR); | ||
| 620 | (void) serial_inp(up, UART_MSR); | ||
| 621 | |||
| 622 | /* | ||
| 623 | * At this point, there's no way the LSR could still be 0xff; | ||
| 624 | * if it is, then bail out, because there's likely no UART | ||
| 625 | * here. | ||
| 626 | */ | ||
| 627 | if (!(up->port.flags & UPF_BUGGY_UART) && | ||
| 628 | (serial_inp(up, UART_LSR) == 0xff)) { | ||
| 629 | printk("ttyS%d: LSR safety check engaged!\n", up->port.line); | ||
| 630 | return -ENODEV; | ||
| 631 | } | ||
| 632 | |||
| 633 | retval = serial_link_irq_chain(up); | ||
| 634 | if (retval) | ||
| 635 | return retval; | ||
| 636 | |||
| 637 | /* | ||
| 638 | * Now, initialize the UART | ||
| 639 | */ | ||
| 640 | serial_outp(up, UART_LCR, UART_LCR_WLEN8); | ||
| 641 | |||
| 642 | spin_lock_irqsave(&up->port.lock, flags); | ||
| 643 | if (up->port.flags & UPF_FOURPORT) { | ||
| 644 | if (!is_real_interrupt(up->port.irq)) | ||
| 645 | up->port.mctrl |= TIOCM_OUT1; | ||
| 646 | } else | ||
| 647 | /* | ||
| 648 | * Most PC uarts need OUT2 raised to enable interrupts. | ||
| 649 | */ | ||
| 650 | if (is_real_interrupt(up->port.irq)) | ||
| 651 | up->port.mctrl |= TIOCM_OUT2; | ||
| 652 | |||
| 653 | serial8250_set_mctrl(&up->port, up->port.mctrl); | ||
| 654 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
| 655 | |||
| 656 | /* | ||
| 657 | * Finally, enable interrupts. Note: Modem status interrupts | ||
| 658 | * are set via set_termios(), which will be occurring imminently | ||
| 659 | * anyway, so we don't enable them here. | ||
| 660 | */ | ||
| 661 | up->ier = UART_IER_RLSI | UART_IER_RDI; | ||
| 662 | serial_outp(up, UART_IER, up->ier); | ||
| 663 | |||
| 664 | if (up->port.flags & UPF_FOURPORT) { | ||
| 665 | unsigned int icp; | ||
| 666 | /* | ||
| 667 | * Enable interrupts on the AST Fourport board | ||
| 668 | */ | ||
| 669 | icp = (up->port.iobase & 0xfe0) | 0x01f; | ||
| 670 | outb_p(0x80, icp); | ||
| 671 | (void) inb_p(icp); | ||
| 672 | } | ||
| 673 | |||
| 674 | /* | ||
| 675 | * And clear the interrupt registers again for luck. | ||
| 676 | */ | ||
| 677 | (void) serial_inp(up, UART_LSR); | ||
| 678 | (void) serial_inp(up, UART_RX); | ||
| 679 | (void) serial_inp(up, UART_IIR); | ||
| 680 | (void) serial_inp(up, UART_MSR); | ||
| 681 | |||
| 682 | return 0; | ||
| 683 | } | ||
| 684 | |||
| 685 | static void serial8250_shutdown(struct uart_port *port) | ||
| 686 | { | ||
| 687 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 688 | unsigned long flags; | ||
| 689 | |||
| 690 | /* | ||
| 691 | * Disable interrupts from this port | ||
| 692 | */ | ||
| 693 | up->ier = 0; | ||
| 694 | serial_outp(up, UART_IER, 0); | ||
| 695 | |||
| 696 | spin_lock_irqsave(&up->port.lock, flags); | ||
| 697 | if (up->port.flags & UPF_FOURPORT) { | ||
| 698 | /* reset interrupts on the AST Fourport board */ | ||
| 699 | inb((up->port.iobase & 0xfe0) | 0x1f); | ||
| 700 | up->port.mctrl |= TIOCM_OUT1; | ||
| 701 | } else | ||
| 702 | up->port.mctrl &= ~TIOCM_OUT2; | ||
| 703 | |||
| 704 | serial8250_set_mctrl(&up->port, up->port.mctrl); | ||
| 705 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
| 706 | |||
| 707 | /* | ||
| 708 | * Disable break condition and FIFOs | ||
| 709 | */ | ||
| 710 | serial_out(up, UART_LCR, serial_inp(up, UART_LCR) & ~UART_LCR_SBC); | ||
| 711 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | | ||
| 712 | UART_FCR_CLEAR_RCVR | | ||
| 713 | UART_FCR_CLEAR_XMIT); | ||
| 714 | serial_outp(up, UART_FCR, 0); | ||
| 715 | |||
| 716 | /* | ||
| 717 | * Read data port to reset things, and then unlink from | ||
| 718 | * the IRQ chain. | ||
| 719 | */ | ||
| 720 | (void) serial_in(up, UART_RX); | ||
| 721 | |||
| 722 | if (!is_real_interrupt(up->port.irq)) | ||
| 723 | del_timer_sync(&up->timer); | ||
| 724 | else | ||
| 725 | serial_unlink_irq_chain(up); | ||
| 726 | } | ||
| 727 | |||
| 728 | static unsigned int serial8250_get_divisor(struct uart_port *port, unsigned int baud) | ||
| 729 | { | ||
| 730 | unsigned int quot; | ||
| 731 | |||
| 732 | /* | ||
| 733 | * Handle magic divisors for baud rates above baud_base on | ||
| 734 | * SMSC SuperIO chips. | ||
| 735 | */ | ||
| 736 | if ((port->flags & UPF_MAGIC_MULTIPLIER) && | ||
| 737 | baud == (port->uartclk/4)) | ||
| 738 | quot = 0x8001; | ||
| 739 | else if ((port->flags & UPF_MAGIC_MULTIPLIER) && | ||
| 740 | baud == (port->uartclk/8)) | ||
| 741 | quot = 0x8002; | ||
| 742 | else | ||
| 743 | quot = uart_get_divisor(port, baud); | ||
| 744 | |||
| 745 | return quot; | ||
| 746 | } | ||
| 747 | |||
| 748 | static void | ||
| 749 | serial8250_set_termios(struct uart_port *port, struct termios *termios, | ||
| 750 | struct termios *old) | ||
| 751 | { | ||
| 752 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 753 | unsigned char cval, fcr = 0; | ||
| 754 | unsigned long flags; | ||
| 755 | unsigned int baud, quot; | ||
| 756 | |||
| 757 | switch (termios->c_cflag & CSIZE) { | ||
| 758 | case CS5: | ||
| 759 | cval = UART_LCR_WLEN5; | ||
| 760 | break; | ||
| 761 | case CS6: | ||
| 762 | cval = UART_LCR_WLEN6; | ||
| 763 | break; | ||
| 764 | case CS7: | ||
| 765 | cval = UART_LCR_WLEN7; | ||
| 766 | break; | ||
| 767 | default: | ||
| 768 | case CS8: | ||
| 769 | cval = UART_LCR_WLEN8; | ||
| 770 | break; | ||
| 771 | } | ||
| 772 | |||
| 773 | if (termios->c_cflag & CSTOPB) | ||
| 774 | cval |= UART_LCR_STOP; | ||
| 775 | if (termios->c_cflag & PARENB) | ||
| 776 | cval |= UART_LCR_PARITY; | ||
| 777 | if (!(termios->c_cflag & PARODD)) | ||
| 778 | cval |= UART_LCR_EPAR; | ||
| 779 | #ifdef CMSPAR | ||
| 780 | if (termios->c_cflag & CMSPAR) | ||
| 781 | cval |= UART_LCR_SPAR; | ||
| 782 | #endif | ||
| 783 | |||
| 784 | /* | ||
| 785 | * Ask the core to calculate the divisor for us. | ||
| 786 | */ | ||
| 787 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); | ||
| 788 | quot = serial8250_get_divisor(port, baud); | ||
| 789 | quot = 0x35; /* FIXME */ | ||
| 790 | |||
| 791 | /* | ||
| 792 | * Work around a bug in the Oxford Semiconductor 952 rev B | ||
| 793 | * chip which causes it to seriously miscalculate baud rates | ||
| 794 | * when DLL is 0. | ||
| 795 | */ | ||
| 796 | if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 && | ||
| 797 | up->rev == 0x5201) | ||
| 798 | quot ++; | ||
| 799 | |||
| 800 | if (uart_config[up->port.type].flags & UART_USE_FIFO) { | ||
| 801 | if (baud < 2400) | ||
| 802 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_1; | ||
| 803 | else | ||
| 804 | fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_8; | ||
| 805 | } | ||
| 806 | |||
| 807 | /* | ||
| 808 | * Ok, we're now changing the port state. Do it with | ||
| 809 | * interrupts disabled. | ||
| 810 | */ | ||
| 811 | spin_lock_irqsave(&up->port.lock, flags); | ||
| 812 | |||
| 813 | /* | ||
| 814 | * Update the per-port timeout. | ||
| 815 | */ | ||
| 816 | uart_update_timeout(port, termios->c_cflag, baud); | ||
| 817 | |||
| 818 | up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | ||
| 819 | if (termios->c_iflag & INPCK) | ||
| 820 | up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE; | ||
| 821 | if (termios->c_iflag & (BRKINT | PARMRK)) | ||
| 822 | up->port.read_status_mask |= UART_LSR_BI; | ||
| 823 | |||
| 824 | /* | ||
| 825 | * Characteres to ignore | ||
| 826 | */ | ||
| 827 | up->port.ignore_status_mask = 0; | ||
| 828 | if (termios->c_iflag & IGNPAR) | ||
| 829 | up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; | ||
| 830 | if (termios->c_iflag & IGNBRK) { | ||
| 831 | up->port.ignore_status_mask |= UART_LSR_BI; | ||
| 832 | /* | ||
| 833 | * If we're ignoring parity and break indicators, | ||
| 834 | * ignore overruns too (for real raw support). | ||
| 835 | */ | ||
| 836 | if (termios->c_iflag & IGNPAR) | ||
| 837 | up->port.ignore_status_mask |= UART_LSR_OE; | ||
| 838 | } | ||
| 839 | |||
| 840 | /* | ||
| 841 | * ignore all characters if CREAD is not set | ||
| 842 | */ | ||
| 843 | if ((termios->c_cflag & CREAD) == 0) | ||
| 844 | up->port.ignore_status_mask |= UART_LSR_DR; | ||
| 845 | |||
| 846 | /* | ||
| 847 | * CTS flow control flag and modem status interrupts | ||
| 848 | */ | ||
| 849 | up->ier &= ~UART_IER_MSI; | ||
| 850 | if (UART_ENABLE_MS(&up->port, termios->c_cflag)) | ||
| 851 | up->ier |= UART_IER_MSI; | ||
| 852 | |||
| 853 | serial_out(up, UART_IER, up->ier); | ||
| 854 | serial_outp(up, 0x28, quot & 0xffff); | ||
| 855 | up->lcr = cval; /* Save LCR */ | ||
| 856 | if (up->port.type != PORT_16750) { | ||
| 857 | if (fcr & UART_FCR_ENABLE_FIFO) { | ||
| 858 | /* emulated UARTs (Lucent Venus 167x) need two steps */ | ||
| 859 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); | ||
| 860 | } | ||
| 861 | serial_outp(up, UART_FCR, fcr); /* set fcr */ | ||
| 862 | } | ||
| 863 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
| 864 | } | ||
| 865 | |||
| 866 | static void | ||
| 867 | serial8250_pm(struct uart_port *port, unsigned int state, | ||
| 868 | unsigned int oldstate) | ||
| 869 | { | ||
| 870 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 871 | if (state) { | ||
| 872 | /* sleep */ | ||
| 873 | if (up->pm) | ||
| 874 | up->pm(port, state, oldstate); | ||
| 875 | } else { | ||
| 876 | /* wake */ | ||
| 877 | if (up->pm) | ||
| 878 | up->pm(port, state, oldstate); | ||
| 879 | } | ||
| 880 | } | ||
| 881 | |||
| 882 | /* | ||
| 883 | * Resource handling. This is complicated by the fact that resources | ||
| 884 | * depend on the port type. Maybe we should be claiming the standard | ||
| 885 | * 8250 ports, and then trying to get other resources as necessary? | ||
| 886 | */ | ||
| 887 | static int | ||
| 888 | serial8250_request_std_resource(struct uart_8250_port *up, struct resource **res) | ||
| 889 | { | ||
| 890 | unsigned int size = 8 << up->port.regshift; | ||
| 891 | int ret = 0; | ||
| 892 | |||
| 893 | switch (up->port.iotype) { | ||
| 894 | case UPIO_MEM: | ||
| 895 | if (up->port.mapbase) { | ||
| 896 | *res = request_mem_region(up->port.mapbase, size, "serial"); | ||
| 897 | if (!*res) | ||
| 898 | ret = -EBUSY; | ||
| 899 | } | ||
| 900 | break; | ||
| 901 | |||
| 902 | case UPIO_HUB6: | ||
| 903 | case UPIO_PORT: | ||
| 904 | *res = request_region(up->port.iobase, size, "serial"); | ||
| 905 | if (!*res) | ||
| 906 | ret = -EBUSY; | ||
| 907 | break; | ||
| 908 | } | ||
| 909 | return ret; | ||
| 910 | } | ||
| 911 | |||
| 912 | |||
| 913 | static void serial8250_release_port(struct uart_port *port) | ||
| 914 | { | ||
| 915 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 916 | unsigned long start, offset = 0, size = 0; | ||
| 917 | |||
| 918 | size <<= up->port.regshift; | ||
| 919 | |||
| 920 | switch (up->port.iotype) { | ||
| 921 | case UPIO_MEM: | ||
| 922 | if (up->port.mapbase) { | ||
| 923 | /* | ||
| 924 | * Unmap the area. | ||
| 925 | */ | ||
| 926 | iounmap(up->port.membase); | ||
| 927 | up->port.membase = NULL; | ||
| 928 | |||
| 929 | start = up->port.mapbase; | ||
| 930 | |||
| 931 | if (size) | ||
| 932 | release_mem_region(start + offset, size); | ||
| 933 | release_mem_region(start, 8 << up->port.regshift); | ||
| 934 | } | ||
| 935 | break; | ||
| 936 | |||
| 937 | case UPIO_HUB6: | ||
| 938 | case UPIO_PORT: | ||
| 939 | start = up->port.iobase; | ||
| 940 | |||
| 941 | if (size) | ||
| 942 | release_region(start + offset, size); | ||
| 943 | release_region(start + offset, 8 << up->port.regshift); | ||
| 944 | break; | ||
| 945 | |||
| 946 | default: | ||
| 947 | break; | ||
| 948 | } | ||
| 949 | } | ||
| 950 | |||
| 951 | static int serial8250_request_port(struct uart_port *port) | ||
| 952 | { | ||
| 953 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 954 | struct resource *res = NULL, *res_rsa = NULL; | ||
| 955 | int ret = 0; | ||
| 956 | |||
| 957 | ret = serial8250_request_std_resource(up, &res); | ||
| 958 | |||
| 959 | /* | ||
| 960 | * If we have a mapbase, then request that as well. | ||
| 961 | */ | ||
| 962 | if (ret == 0 && up->port.flags & UPF_IOREMAP) { | ||
| 963 | int size = res->end - res->start + 1; | ||
| 964 | |||
| 965 | up->port.membase = ioremap(up->port.mapbase, size); | ||
| 966 | if (!up->port.membase) | ||
| 967 | ret = -ENOMEM; | ||
| 968 | } | ||
| 969 | |||
| 970 | if (ret < 0) { | ||
| 971 | if (res_rsa) | ||
| 972 | release_resource(res_rsa); | ||
| 973 | if (res) | ||
| 974 | release_resource(res); | ||
| 975 | } | ||
| 976 | return ret; | ||
| 977 | } | ||
| 978 | |||
| 979 | static void serial8250_config_port(struct uart_port *port, int flags) | ||
| 980 | { | ||
| 981 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 982 | struct resource *res_std = NULL, *res_rsa = NULL; | ||
| 983 | int probeflags = PROBE_ANY; | ||
| 984 | |||
| 985 | probeflags &= ~PROBE_RSA; | ||
| 986 | |||
| 987 | if (flags & UART_CONFIG_TYPE) | ||
| 988 | autoconfig(up, probeflags); | ||
| 989 | |||
| 990 | /* | ||
| 991 | * If the port wasn't an RSA port, release the resource. | ||
| 992 | */ | ||
| 993 | if (up->port.type != PORT_RSA && res_rsa) | ||
| 994 | release_resource(res_rsa); | ||
| 995 | |||
| 996 | if (up->port.type == PORT_UNKNOWN && res_std) | ||
| 997 | release_resource(res_std); | ||
| 998 | } | ||
| 999 | |||
| 1000 | static int | ||
| 1001 | serial8250_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
| 1002 | { | ||
| 1003 | if (ser->irq >= NR_IRQS || ser->irq < 0 || | ||
| 1004 | ser->baud_base < 9600 || ser->type < PORT_UNKNOWN || | ||
| 1005 | ser->type > PORT_MAX_8250 || ser->type == PORT_CIRRUS || | ||
| 1006 | ser->type == PORT_STARTECH) | ||
| 1007 | return -EINVAL; | ||
| 1008 | return 0; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | static const char * | ||
| 1012 | serial8250_type(struct uart_port *port) | ||
| 1013 | { | ||
| 1014 | int type = port->type; | ||
| 1015 | |||
| 1016 | if (type >= ARRAY_SIZE(uart_config)) | ||
| 1017 | type = 0; | ||
| 1018 | return uart_config[type].name; | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | static struct uart_ops serial8250_pops = { | ||
| 1022 | .tx_empty = serial8250_tx_empty, | ||
| 1023 | .set_mctrl = serial8250_set_mctrl, | ||
| 1024 | .get_mctrl = serial8250_get_mctrl, | ||
| 1025 | .stop_tx = serial8250_stop_tx, | ||
| 1026 | .start_tx = serial8250_start_tx, | ||
| 1027 | .stop_rx = serial8250_stop_rx, | ||
| 1028 | .enable_ms = serial8250_enable_ms, | ||
| 1029 | .break_ctl = serial8250_break_ctl, | ||
| 1030 | .startup = serial8250_startup, | ||
| 1031 | .shutdown = serial8250_shutdown, | ||
| 1032 | .set_termios = serial8250_set_termios, | ||
| 1033 | .pm = serial8250_pm, | ||
| 1034 | .type = serial8250_type, | ||
| 1035 | .release_port = serial8250_release_port, | ||
| 1036 | .request_port = serial8250_request_port, | ||
| 1037 | .config_port = serial8250_config_port, | ||
| 1038 | .verify_port = serial8250_verify_port, | ||
| 1039 | }; | ||
| 1040 | |||
| 1041 | static struct uart_8250_port serial8250_ports[UART_NR]; | ||
| 1042 | |||
| 1043 | static void __init serial8250_isa_init_ports(void) | ||
| 1044 | { | ||
| 1045 | struct uart_8250_port *up; | ||
| 1046 | static int first = 1; | ||
| 1047 | int i; | ||
| 1048 | |||
| 1049 | if (!first) | ||
| 1050 | return; | ||
| 1051 | first = 0; | ||
| 1052 | |||
| 1053 | for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port); | ||
| 1054 | i++, up++) { | ||
| 1055 | up->port.iobase = old_serial_port[i].port; | ||
| 1056 | up->port.irq = old_serial_port[i].irq; | ||
| 1057 | up->port.uartclk = get_au1x00_uart_baud_base(); | ||
| 1058 | up->port.flags = old_serial_port[i].flags; | ||
| 1059 | up->port.hub6 = old_serial_port[i].hub6; | ||
| 1060 | up->port.membase = old_serial_port[i].iomem_base; | ||
| 1061 | up->port.iotype = old_serial_port[i].io_type; | ||
| 1062 | up->port.regshift = old_serial_port[i].iomem_reg_shift; | ||
| 1063 | up->port.ops = &serial8250_pops; | ||
| 1064 | } | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | static void __init serial8250_register_ports(struct uart_driver *drv) | ||
| 1068 | { | ||
| 1069 | int i; | ||
| 1070 | |||
| 1071 | serial8250_isa_init_ports(); | ||
| 1072 | |||
| 1073 | for (i = 0; i < UART_NR; i++) { | ||
| 1074 | struct uart_8250_port *up = &serial8250_ports[i]; | ||
| 1075 | |||
| 1076 | up->port.line = i; | ||
| 1077 | up->port.ops = &serial8250_pops; | ||
| 1078 | init_timer(&up->timer); | ||
| 1079 | up->timer.function = serial8250_timeout; | ||
| 1080 | |||
| 1081 | /* | ||
| 1082 | * ALPHA_KLUDGE_MCR needs to be killed. | ||
| 1083 | */ | ||
| 1084 | up->mcr_mask = ~ALPHA_KLUDGE_MCR; | ||
| 1085 | up->mcr_force = ALPHA_KLUDGE_MCR; | ||
| 1086 | |||
| 1087 | uart_add_one_port(drv, &up->port); | ||
| 1088 | } | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | #ifdef CONFIG_SERIAL_AU1X00_CONSOLE | ||
| 1092 | |||
| 1093 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) | ||
| 1094 | |||
| 1095 | /* | ||
| 1096 | * Wait for transmitter & holding register to empty | ||
| 1097 | */ | ||
| 1098 | static inline void wait_for_xmitr(struct uart_8250_port *up) | ||
| 1099 | { | ||
| 1100 | unsigned int status, tmout = 10000; | ||
| 1101 | |||
| 1102 | /* Wait up to 10ms for the character(s) to be sent. */ | ||
| 1103 | do { | ||
| 1104 | status = serial_in(up, UART_LSR); | ||
| 1105 | |||
| 1106 | if (status & UART_LSR_BI) | ||
| 1107 | up->lsr_break_flag = UART_LSR_BI; | ||
| 1108 | |||
| 1109 | if (--tmout == 0) | ||
| 1110 | break; | ||
| 1111 | udelay(1); | ||
| 1112 | } while ((status & BOTH_EMPTY) != BOTH_EMPTY); | ||
| 1113 | |||
| 1114 | /* Wait up to 1s for flow control if necessary */ | ||
| 1115 | if (up->port.flags & UPF_CONS_FLOW) { | ||
| 1116 | tmout = 1000000; | ||
| 1117 | while (--tmout && | ||
| 1118 | ((serial_in(up, UART_MSR) & UART_MSR_CTS) == 0)) | ||
| 1119 | udelay(1); | ||
| 1120 | } | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | static void au1x00_console_putchar(struct uart_port *port, int ch) | ||
| 1124 | { | ||
| 1125 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
| 1126 | |||
| 1127 | wait_for_xmitr(up); | ||
| 1128 | serial_out(up, UART_TX, ch); | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | /* | ||
| 1132 | * Print a string to the serial port trying not to disturb | ||
| 1133 | * any possible real use of the port... | ||
| 1134 | * | ||
| 1135 | * The console_lock must be held when we get here. | ||
| 1136 | */ | ||
| 1137 | static void | ||
| 1138 | serial8250_console_write(struct console *co, const char *s, unsigned int count) | ||
| 1139 | { | ||
| 1140 | struct uart_8250_port *up = &serial8250_ports[co->index]; | ||
| 1141 | unsigned int ier; | ||
| 1142 | |||
| 1143 | /* | ||
| 1144 | * First save the UER then disable the interrupts | ||
| 1145 | */ | ||
| 1146 | ier = serial_in(up, UART_IER); | ||
| 1147 | serial_out(up, UART_IER, 0); | ||
| 1148 | |||
| 1149 | uart_console_write(&up->port, s, count, au1x00_console_putchar); | ||
| 1150 | |||
| 1151 | /* | ||
| 1152 | * Finally, wait for transmitter to become empty | ||
| 1153 | * and restore the IER | ||
| 1154 | */ | ||
| 1155 | wait_for_xmitr(up); | ||
| 1156 | serial_out(up, UART_IER, ier); | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | static int __init serial8250_console_setup(struct console *co, char *options) | ||
| 1160 | { | ||
| 1161 | struct uart_port *port; | ||
| 1162 | int baud = 9600; | ||
| 1163 | int bits = 8; | ||
| 1164 | int parity = 'n'; | ||
| 1165 | int flow = 'n'; | ||
| 1166 | |||
| 1167 | /* | ||
| 1168 | * Check whether an invalid uart number has been specified, and | ||
| 1169 | * if so, search for the first available port that does have | ||
| 1170 | * console support. | ||
| 1171 | */ | ||
| 1172 | if (co->index >= UART_NR) | ||
| 1173 | co->index = 0; | ||
| 1174 | port = &serial8250_ports[co->index].port; | ||
| 1175 | |||
| 1176 | /* | ||
| 1177 | * Temporary fix. | ||
| 1178 | */ | ||
| 1179 | spin_lock_init(&port->lock); | ||
| 1180 | |||
| 1181 | if (options) | ||
| 1182 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
| 1183 | |||
| 1184 | return uart_set_options(port, co, baud, parity, bits, flow); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | extern struct uart_driver serial8250_reg; | ||
| 1188 | static struct console serial8250_console = { | ||
| 1189 | .name = "ttyS", | ||
| 1190 | .write = serial8250_console_write, | ||
| 1191 | .device = uart_console_device, | ||
| 1192 | .setup = serial8250_console_setup, | ||
| 1193 | .flags = CON_PRINTBUFFER, | ||
| 1194 | .index = -1, | ||
| 1195 | .data = &serial8250_reg, | ||
| 1196 | }; | ||
| 1197 | |||
| 1198 | static int __init serial8250_console_init(void) | ||
| 1199 | { | ||
| 1200 | serial8250_isa_init_ports(); | ||
| 1201 | register_console(&serial8250_console); | ||
| 1202 | return 0; | ||
| 1203 | } | ||
| 1204 | console_initcall(serial8250_console_init); | ||
| 1205 | |||
| 1206 | #define SERIAL8250_CONSOLE &serial8250_console | ||
| 1207 | #else | ||
| 1208 | #define SERIAL8250_CONSOLE NULL | ||
| 1209 | #endif | ||
| 1210 | |||
| 1211 | static struct uart_driver serial8250_reg = { | ||
| 1212 | .owner = THIS_MODULE, | ||
| 1213 | .driver_name = "serial", | ||
| 1214 | .devfs_name = "tts/", | ||
| 1215 | .dev_name = "ttyS", | ||
| 1216 | .major = TTY_MAJOR, | ||
| 1217 | .minor = 64, | ||
| 1218 | .nr = UART_NR, | ||
| 1219 | .cons = SERIAL8250_CONSOLE, | ||
| 1220 | }; | ||
| 1221 | |||
| 1222 | int __init early_serial_setup(struct uart_port *port) | ||
| 1223 | { | ||
| 1224 | serial8250_isa_init_ports(); | ||
| 1225 | serial8250_ports[port->line].port = *port; | ||
| 1226 | serial8250_ports[port->line].port.ops = &serial8250_pops; | ||
| 1227 | return 0; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | /** | ||
| 1231 | * serial8250_suspend_port - suspend one serial port | ||
| 1232 | * @line: serial line number | ||
| 1233 | * @level: the level of port suspension, as per uart_suspend_port | ||
| 1234 | * | ||
| 1235 | * Suspend one serial port. | ||
| 1236 | */ | ||
| 1237 | void serial8250_suspend_port(int line) | ||
| 1238 | { | ||
| 1239 | uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port); | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | /** | ||
| 1243 | * serial8250_resume_port - resume one serial port | ||
| 1244 | * @line: serial line number | ||
| 1245 | * @level: the level of port resumption, as per uart_resume_port | ||
| 1246 | * | ||
| 1247 | * Resume one serial port. | ||
| 1248 | */ | ||
| 1249 | void serial8250_resume_port(int line) | ||
| 1250 | { | ||
| 1251 | uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | static int __init serial8250_init(void) | ||
| 1255 | { | ||
| 1256 | int ret, i; | ||
| 1257 | |||
| 1258 | printk(KERN_INFO "Serial: Au1x00 driver\n"); | ||
| 1259 | |||
| 1260 | for (i = 0; i < NR_IRQS; i++) | ||
| 1261 | spin_lock_init(&irq_lists[i].lock); | ||
| 1262 | |||
| 1263 | ret = uart_register_driver(&serial8250_reg); | ||
| 1264 | if (ret >= 0) | ||
| 1265 | serial8250_register_ports(&serial8250_reg); | ||
| 1266 | |||
| 1267 | return ret; | ||
| 1268 | } | ||
| 1269 | |||
| 1270 | static void __exit serial8250_exit(void) | ||
| 1271 | { | ||
| 1272 | int i; | ||
| 1273 | |||
| 1274 | for (i = 0; i < UART_NR; i++) | ||
| 1275 | uart_remove_one_port(&serial8250_reg, &serial8250_ports[i].port); | ||
| 1276 | |||
| 1277 | uart_unregister_driver(&serial8250_reg); | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | module_init(serial8250_init); | ||
| 1281 | module_exit(serial8250_exit); | ||
| 1282 | |||
| 1283 | EXPORT_SYMBOL(serial8250_suspend_port); | ||
| 1284 | EXPORT_SYMBOL(serial8250_resume_port); | ||
| 1285 | |||
| 1286 | MODULE_LICENSE("GPL"); | ||
| 1287 | MODULE_DESCRIPTION("Au1x00 serial driver\n"); | ||
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index b848b7d94412..3bdee64d1a99 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c | |||
| @@ -483,7 +483,7 @@ static int serial_txx9_startup(struct uart_port *port) | |||
| 483 | 483 | ||
| 484 | /* | 484 | /* |
| 485 | * Clear the FIFO buffers and disable them. | 485 | * Clear the FIFO buffers and disable them. |
| 486 | * (they will be reeanbled in set_termios()) | 486 | * (they will be reenabled in set_termios()) |
| 487 | */ | 487 | */ |
| 488 | sio_set(up, TXX9_SIFCR, | 488 | sio_set(up, TXX9_SIFCR, |
| 489 | TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE); | 489 | TXX9_SIFCR_TFRST | TXX9_SIFCR_RFRST | TXX9_SIFCR_FRSTE); |
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 9fe2283d91e5..1c4396c2962d 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c | |||
| @@ -641,7 +641,7 @@ static int sunsu_startup(struct uart_port *port) | |||
| 641 | 641 | ||
| 642 | /* | 642 | /* |
| 643 | * Clear the FIFO buffers and disable them. | 643 | * Clear the FIFO buffers and disable them. |
| 644 | * (they will be reeanbled in set_termios()) | 644 | * (they will be reenabled in set_termios()) |
| 645 | */ | 645 | */ |
| 646 | if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) { | 646 | if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) { |
| 647 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); | 647 | serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); |
diff --git a/drivers/telephony/phonedev.c b/drivers/telephony/phonedev.c index 7a6db1c5c8c5..e166fffea86b 100644 --- a/drivers/telephony/phonedev.c +++ b/drivers/telephony/phonedev.c | |||
| @@ -49,7 +49,7 @@ static int phone_open(struct inode *inode, struct file *file) | |||
| 49 | unsigned int minor = iminor(inode); | 49 | unsigned int minor = iminor(inode); |
| 50 | int err = 0; | 50 | int err = 0; |
| 51 | struct phone_device *p; | 51 | struct phone_device *p; |
| 52 | struct file_operations *old_fops, *new_fops = NULL; | 52 | const struct file_operations *old_fops, *new_fops = NULL; |
| 53 | 53 | ||
| 54 | if (minor >= PHONE_NUM_DEVICES) | 54 | if (minor >= PHONE_NUM_DEVICES) |
| 55 | return -ENODEV; | 55 | return -ENODEV; |
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 37b13368c814..b263a54a13c0 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c | |||
| @@ -24,15 +24,15 @@ | |||
| 24 | #include "usb.h" | 24 | #include "usb.h" |
| 25 | 25 | ||
| 26 | #define MAX_USB_MINORS 256 | 26 | #define MAX_USB_MINORS 256 |
| 27 | static struct file_operations *usb_minors[MAX_USB_MINORS]; | 27 | static const struct file_operations *usb_minors[MAX_USB_MINORS]; |
| 28 | static DEFINE_SPINLOCK(minor_lock); | 28 | static DEFINE_SPINLOCK(minor_lock); |
| 29 | 29 | ||
| 30 | static int usb_open(struct inode * inode, struct file * file) | 30 | static int usb_open(struct inode * inode, struct file * file) |
| 31 | { | 31 | { |
| 32 | int minor = iminor(inode); | 32 | int minor = iminor(inode); |
| 33 | struct file_operations *c; | 33 | const struct file_operations *c; |
| 34 | int err = -ENODEV; | 34 | int err = -ENODEV; |
| 35 | struct file_operations *old_fops, *new_fops = NULL; | 35 | const struct file_operations *old_fops, *new_fops = NULL; |
| 36 | 36 | ||
| 37 | spin_lock (&minor_lock); | 37 | spin_lock (&minor_lock); |
| 38 | c = usb_minors[minor]; | 38 | c = usb_minors[minor]; |
diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index 4b55285de9a0..fe0ed54fa0ae 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c | |||
| @@ -16,57 +16,7 @@ | |||
| 16 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
| 17 | #include "usb.h" | 17 | #include "usb.h" |
| 18 | 18 | ||
| 19 | 19 | static BLOCKING_NOTIFIER_HEAD(usb_notifier_list); | |
| 20 | static struct notifier_block *usb_notifier_list; | ||
| 21 | static DEFINE_MUTEX(usb_notifier_lock); | ||
| 22 | |||
| 23 | static void usb_notifier_chain_register(struct notifier_block **list, | ||
| 24 | struct notifier_block *n) | ||
| 25 | { | ||
| 26 | mutex_lock(&usb_notifier_lock); | ||
| 27 | while (*list) { | ||
| 28 | if (n->priority > (*list)->priority) | ||
| 29 | break; | ||
| 30 | list = &((*list)->next); | ||
| 31 | } | ||
| 32 | n->next = *list; | ||
| 33 | *list = n; | ||
| 34 | mutex_unlock(&usb_notifier_lock); | ||
| 35 | } | ||
| 36 | |||
| 37 | static void usb_notifier_chain_unregister(struct notifier_block **nl, | ||
| 38 | struct notifier_block *n) | ||
| 39 | { | ||
| 40 | mutex_lock(&usb_notifier_lock); | ||
| 41 | while ((*nl)!=NULL) { | ||
| 42 | if ((*nl)==n) { | ||
| 43 | *nl = n->next; | ||
| 44 | goto exit; | ||
| 45 | } | ||
| 46 | nl=&((*nl)->next); | ||
| 47 | } | ||
| 48 | exit: | ||
| 49 | mutex_unlock(&usb_notifier_lock); | ||
| 50 | } | ||
| 51 | |||
| 52 | static int usb_notifier_call_chain(struct notifier_block **n, | ||
| 53 | unsigned long val, void *v) | ||
| 54 | { | ||
| 55 | int ret=NOTIFY_DONE; | ||
| 56 | struct notifier_block *nb = *n; | ||
| 57 | |||
| 58 | mutex_lock(&usb_notifier_lock); | ||
| 59 | while (nb) { | ||
| 60 | ret = nb->notifier_call(nb,val,v); | ||
| 61 | if (ret&NOTIFY_STOP_MASK) { | ||
| 62 | goto exit; | ||
| 63 | } | ||
| 64 | nb = nb->next; | ||
| 65 | } | ||
| 66 | exit: | ||
| 67 | mutex_unlock(&usb_notifier_lock); | ||
| 68 | return ret; | ||
| 69 | } | ||
| 70 | 20 | ||
| 71 | /** | 21 | /** |
| 72 | * usb_register_notify - register a notifier callback whenever a usb change happens | 22 | * usb_register_notify - register a notifier callback whenever a usb change happens |
| @@ -76,7 +26,7 @@ exit: | |||
| 76 | */ | 26 | */ |
| 77 | void usb_register_notify(struct notifier_block *nb) | 27 | void usb_register_notify(struct notifier_block *nb) |
| 78 | { | 28 | { |
| 79 | usb_notifier_chain_register(&usb_notifier_list, nb); | 29 | blocking_notifier_chain_register(&usb_notifier_list, nb); |
| 80 | } | 30 | } |
| 81 | EXPORT_SYMBOL_GPL(usb_register_notify); | 31 | EXPORT_SYMBOL_GPL(usb_register_notify); |
| 82 | 32 | ||
| @@ -89,27 +39,28 @@ EXPORT_SYMBOL_GPL(usb_register_notify); | |||
| 89 | */ | 39 | */ |
| 90 | void usb_unregister_notify(struct notifier_block *nb) | 40 | void usb_unregister_notify(struct notifier_block *nb) |
| 91 | { | 41 | { |
| 92 | usb_notifier_chain_unregister(&usb_notifier_list, nb); | 42 | blocking_notifier_chain_unregister(&usb_notifier_list, nb); |
| 93 | } | 43 | } |
| 94 | EXPORT_SYMBOL_GPL(usb_unregister_notify); | 44 | EXPORT_SYMBOL_GPL(usb_unregister_notify); |
| 95 | 45 | ||
| 96 | 46 | ||
| 97 | void usb_notify_add_device(struct usb_device *udev) | 47 | void usb_notify_add_device(struct usb_device *udev) |
| 98 | { | 48 | { |
| 99 | usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); | 49 | blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_ADD, udev); |
| 100 | } | 50 | } |
| 101 | 51 | ||
| 102 | void usb_notify_remove_device(struct usb_device *udev) | 52 | void usb_notify_remove_device(struct usb_device *udev) |
| 103 | { | 53 | { |
| 104 | usb_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev); | 54 | blocking_notifier_call_chain(&usb_notifier_list, |
| 55 | USB_DEVICE_REMOVE, udev); | ||
| 105 | } | 56 | } |
| 106 | 57 | ||
| 107 | void usb_notify_add_bus(struct usb_bus *ubus) | 58 | void usb_notify_add_bus(struct usb_bus *ubus) |
| 108 | { | 59 | { |
| 109 | usb_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); | 60 | blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_ADD, ubus); |
| 110 | } | 61 | } |
| 111 | 62 | ||
| 112 | void usb_notify_remove_bus(struct usb_bus *ubus) | 63 | void usb_notify_remove_bus(struct usb_bus *ubus) |
| 113 | { | 64 | { |
| 114 | usb_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); | 65 | blocking_notifier_call_chain(&usb_notifier_list, USB_BUS_REMOVE, ubus); |
| 115 | } | 66 | } |
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index b44cfda76b61..3f618ce6998d 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
| @@ -1581,7 +1581,7 @@ restart: | |||
| 1581 | 1581 | ||
| 1582 | static struct inode * | 1582 | static struct inode * |
| 1583 | gadgetfs_create_file (struct super_block *sb, char const *name, | 1583 | gadgetfs_create_file (struct super_block *sb, char const *name, |
| 1584 | void *data, struct file_operations *fops, | 1584 | void *data, const struct file_operations *fops, |
| 1585 | struct dentry **dentry_p); | 1585 | struct dentry **dentry_p); |
| 1586 | 1586 | ||
| 1587 | static int activate_ep_files (struct dev_data *dev) | 1587 | static int activate_ep_files (struct dev_data *dev) |
| @@ -1955,7 +1955,7 @@ module_param (default_perm, uint, 0644); | |||
| 1955 | 1955 | ||
| 1956 | static struct inode * | 1956 | static struct inode * |
| 1957 | gadgetfs_make_inode (struct super_block *sb, | 1957 | gadgetfs_make_inode (struct super_block *sb, |
| 1958 | void *data, struct file_operations *fops, | 1958 | void *data, const struct file_operations *fops, |
| 1959 | int mode) | 1959 | int mode) |
| 1960 | { | 1960 | { |
| 1961 | struct inode *inode = new_inode (sb); | 1961 | struct inode *inode = new_inode (sb); |
| @@ -1979,7 +1979,7 @@ gadgetfs_make_inode (struct super_block *sb, | |||
| 1979 | */ | 1979 | */ |
| 1980 | static struct inode * | 1980 | static struct inode * |
| 1981 | gadgetfs_create_file (struct super_block *sb, char const *name, | 1981 | gadgetfs_create_file (struct super_block *sb, char const *name, |
| 1982 | void *data, struct file_operations *fops, | 1982 | void *data, const struct file_operations *fops, |
| 1983 | struct dentry **dentry_p) | 1983 | struct dentry **dentry_p) |
| 1984 | { | 1984 | { |
| 1985 | struct dentry *dentry; | 1985 | struct dentry *dentry; |
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 372527a83593..682bf2215660 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c | |||
| @@ -158,7 +158,7 @@ static int ohci_s3c2410_hub_control ( | |||
| 158 | "s3c2410_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n", | 158 | "s3c2410_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n", |
| 159 | hcd, typeReq, wValue, wIndex, buf, wLength); | 159 | hcd, typeReq, wValue, wIndex, buf, wLength); |
| 160 | 160 | ||
| 161 | /* if we are only an humble host without any special capabilites | 161 | /* if we are only an humble host without any special capabilities |
| 162 | * process the request straight away and exit */ | 162 | * process the request straight away and exit */ |
| 163 | 163 | ||
| 164 | if (info == NULL) { | 164 | if (info == NULL) { |
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c index 9c5ab251370c..f7ac9d6b9856 100644 --- a/drivers/usb/net/zaurus.c +++ b/drivers/usb/net/zaurus.c | |||
| @@ -217,7 +217,7 @@ static int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf) | |||
| 217 | * with devices that use it and those that don't. | 217 | * with devices that use it and those that don't. |
| 218 | */ | 218 | */ |
| 219 | if ((detail->bDetailData[1] & ~0x02) != 0x01) { | 219 | if ((detail->bDetailData[1] & ~0x02) != 0x01) { |
| 220 | /* bmDataCapabilites == 0 would be fine too, | 220 | /* bmDataCapabilities == 0 would be fine too, |
| 221 | * but framing is minidriver-coupled for now. | 221 | * but framing is minidriver-coupled for now. |
| 222 | */ | 222 | */ |
| 223 | bad_detail: | 223 | bad_detail: |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index fdebd60a3250..22e9d696fdd2 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -70,6 +70,22 @@ config FB_MACMODES | |||
| 70 | depends on FB | 70 | depends on FB |
| 71 | default n | 71 | default n |
| 72 | 72 | ||
| 73 | config FB_FIRMWARE_EDID | ||
| 74 | bool "Enable firmware EDID" | ||
| 75 | depends on FB | ||
| 76 | default y | ||
| 77 | ---help--- | ||
| 78 | This enables access to the EDID transferred from the firmware. | ||
| 79 | On the i386, this is from the Video BIOS. Enable this if DDC/I2C | ||
| 80 | transfers do not work for your driver and if you are using | ||
| 81 | nvidiafb, i810fb or savagefb. | ||
| 82 | |||
| 83 | In general, choosing Y for this option is safe. If you | ||
| 84 | experience extremely long delays while booting before you get | ||
| 85 | something on your display, try setting this to N. Matrox cards in | ||
| 86 | combination with certain motherboards and monitors are known to | ||
| 87 | suffer from this problem. | ||
| 88 | |||
| 73 | config FB_MODE_HELPERS | 89 | config FB_MODE_HELPERS |
| 74 | bool "Enable Video Mode Handling Helpers" | 90 | bool "Enable Video Mode Handling Helpers" |
| 75 | depends on FB | 91 | depends on FB |
| @@ -1202,6 +1218,17 @@ config FB_AU1100 | |||
| 1202 | bool "Au1100 LCD Driver" | 1218 | bool "Au1100 LCD Driver" |
| 1203 | depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y | 1219 | depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y |
| 1204 | 1220 | ||
| 1221 | config FB_AU1200 | ||
| 1222 | bool "Au1200 LCD Driver" | ||
| 1223 | depends on FB && MIPS && SOC_AU1200 | ||
| 1224 | select FB_CFB_FILLRECT | ||
| 1225 | select FB_CFB_COPYAREA | ||
| 1226 | select FB_CFB_IMAGEBLIT | ||
| 1227 | help | ||
| 1228 | This is the framebuffer driver for the AMD Au1200 SOC. It can drive | ||
| 1229 | various panels and CRTs by passing in kernel cmd line option | ||
| 1230 | au1200fb:panel=<name>. | ||
| 1231 | |||
| 1205 | source "drivers/video/geode/Kconfig" | 1232 | source "drivers/video/geode/Kconfig" |
| 1206 | 1233 | ||
| 1207 | config FB_FFB | 1234 | config FB_FFB |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index aa434e725c0d..cb90218515ac 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
| @@ -86,6 +86,7 @@ obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o | |||
| 86 | obj-$(CONFIG_FB_PXA) += pxafb.o | 86 | obj-$(CONFIG_FB_PXA) += pxafb.o |
| 87 | obj-$(CONFIG_FB_W100) += w100fb.o | 87 | obj-$(CONFIG_FB_W100) += w100fb.o |
| 88 | obj-$(CONFIG_FB_AU1100) += au1100fb.o | 88 | obj-$(CONFIG_FB_AU1100) += au1100fb.o |
| 89 | obj-$(CONFIG_FB_AU1200) += au1200fb.o | ||
| 89 | obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o | 90 | obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o |
| 90 | obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o | 91 | obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o |
| 91 | obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o | 92 | obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o |
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 76448d6ae896..98baecccb3fd 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c | |||
| @@ -1308,7 +1308,7 @@ static int __init acornfb_probe(struct platform_device *dev) | |||
| 1308 | /* | 1308 | /* |
| 1309 | * Try to select a suitable default mode | 1309 | * Try to select a suitable default mode |
| 1310 | */ | 1310 | */ |
| 1311 | for (i = 0; i < sizeof(modedb) / sizeof(*modedb); i++) { | 1311 | for (i = 0; i < ARRAY_SIZE(modedb); i++) { |
| 1312 | unsigned long hs; | 1312 | unsigned long hs; |
| 1313 | 1313 | ||
| 1314 | hs = modedb[i].refresh * | 1314 | hs = modedb[i].refresh * |
| @@ -1380,7 +1380,7 @@ static int __init acornfb_probe(struct platform_device *dev) | |||
| 1380 | */ | 1380 | */ |
| 1381 | free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE); | 1381 | free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE); |
| 1382 | #endif | 1382 | #endif |
| 1383 | 1383 | ||
| 1384 | fb_info.fix.smem_len = size; | 1384 | fb_info.fix.smem_len = size; |
| 1385 | current_par.palette_size = VIDC_PALETTE_SIZE; | 1385 | current_par.palette_size = VIDC_PALETTE_SIZE; |
| 1386 | 1386 | ||
| @@ -1391,7 +1391,7 @@ static int __init acornfb_probe(struct platform_device *dev) | |||
| 1391 | */ | 1391 | */ |
| 1392 | do { | 1392 | do { |
| 1393 | rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb, | 1393 | rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb, |
| 1394 | sizeof(modedb) / sizeof(*modedb), | 1394 | ARRAY_SIZE(modedb), |
| 1395 | &acornfb_default_mode, DEFAULT_BPP); | 1395 | &acornfb_default_mode, DEFAULT_BPP); |
| 1396 | /* | 1396 | /* |
| 1397 | * If we found an exact match, all ok. | 1397 | * If we found an exact match, all ok. |
| @@ -1408,7 +1408,7 @@ static int __init acornfb_probe(struct platform_device *dev) | |||
| 1408 | break; | 1408 | break; |
| 1409 | 1409 | ||
| 1410 | rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb, | 1410 | rc = fb_find_mode(&fb_info.var, &fb_info, NULL, modedb, |
| 1411 | sizeof(modedb) / sizeof(*modedb), | 1411 | ARRAY_SIZE(modedb), |
| 1412 | &acornfb_default_mode, DEFAULT_BPP); | 1412 | &acornfb_default_mode, DEFAULT_BPP); |
| 1413 | if (rc) | 1413 | if (rc) |
| 1414 | break; | 1414 | break; |
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index c924d81f7978..29f9f0dfe3b4 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c | |||
| @@ -353,8 +353,6 @@ struct chips_init_reg { | |||
| 353 | unsigned char data; | 353 | unsigned char data; |
| 354 | }; | 354 | }; |
| 355 | 355 | ||
| 356 | #define N_ELTS(x) (sizeof(x) / sizeof(x[0])) | ||
| 357 | |||
| 358 | static struct chips_init_reg chips_init_sr[] = | 356 | static struct chips_init_reg chips_init_sr[] = |
| 359 | { | 357 | { |
| 360 | {0x00, 0x03}, /* Reset register */ | 358 | {0x00, 0x03}, /* Reset register */ |
| @@ -460,22 +458,22 @@ static void __devinit chips_hw_init(struct fb_info *p) | |||
| 460 | { | 458 | { |
| 461 | int i; | 459 | int i; |
| 462 | 460 | ||
| 463 | for (i = 0; i < N_ELTS(chips_init_xr); ++i) | 461 | for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i) |
| 464 | write_xr(chips_init_xr[i].addr, chips_init_xr[i].data); | 462 | write_xr(chips_init_xr[i].addr, chips_init_xr[i].data); |
| 465 | write_xr(0x81, 0x12); | 463 | write_xr(0x81, 0x12); |
| 466 | write_xr(0x82, 0x08); | 464 | write_xr(0x82, 0x08); |
| 467 | write_xr(0x20, 0x00); | 465 | write_xr(0x20, 0x00); |
| 468 | for (i = 0; i < N_ELTS(chips_init_sr); ++i) | 466 | for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i) |
| 469 | write_sr(chips_init_sr[i].addr, chips_init_sr[i].data); | 467 | write_sr(chips_init_sr[i].addr, chips_init_sr[i].data); |
| 470 | for (i = 0; i < N_ELTS(chips_init_gr); ++i) | 468 | for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i) |
| 471 | write_gr(chips_init_gr[i].addr, chips_init_gr[i].data); | 469 | write_gr(chips_init_gr[i].addr, chips_init_gr[i].data); |
| 472 | for (i = 0; i < N_ELTS(chips_init_ar); ++i) | 470 | for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i) |
| 473 | write_ar(chips_init_ar[i].addr, chips_init_ar[i].data); | 471 | write_ar(chips_init_ar[i].addr, chips_init_ar[i].data); |
| 474 | /* Enable video output in attribute index register */ | 472 | /* Enable video output in attribute index register */ |
| 475 | writeb(0x20, mmio_base + 0x780); | 473 | writeb(0x20, mmio_base + 0x780); |
| 476 | for (i = 0; i < N_ELTS(chips_init_cr); ++i) | 474 | for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i) |
| 477 | write_cr(chips_init_cr[i].addr, chips_init_cr[i].data); | 475 | write_cr(chips_init_cr[i].addr, chips_init_cr[i].data); |
| 478 | for (i = 0; i < N_ELTS(chips_init_fr); ++i) | 476 | for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i) |
| 479 | write_fr(chips_init_fr[i].addr, chips_init_fr[i].data); | 477 | write_fr(chips_init_fr[i].addr, chips_init_fr[i].data); |
| 480 | } | 478 | } |
| 481 | 479 | ||
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 620c9a934e0e..821c6da8e42c 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
| @@ -1725,9 +1725,9 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id * | |||
| 1725 | strcpy(video_card, "Rage128 XX "); | 1725 | strcpy(video_card, "Rage128 XX "); |
| 1726 | video_card[8] = ent->device >> 8; | 1726 | video_card[8] = ent->device >> 8; |
| 1727 | video_card[9] = ent->device & 0xFF; | 1727 | video_card[9] = ent->device & 0xFF; |
| 1728 | 1728 | ||
| 1729 | /* range check to make sure */ | 1729 | /* range check to make sure */ |
| 1730 | if (ent->driver_data < (sizeof(r128_family)/sizeof(char *))) | 1730 | if (ent->driver_data < ARRAY_SIZE(r128_family)) |
| 1731 | strncat(video_card, r128_family[ent->driver_data], sizeof(video_card)); | 1731 | strncat(video_card, r128_family[ent->driver_data], sizeof(video_card)); |
| 1732 | 1732 | ||
| 1733 | printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev); | 1733 | printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev); |
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 485be386a8ff..e799fcca365a 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c | |||
| @@ -434,7 +434,7 @@ static int __devinit correct_chipset(struct atyfb_par *par) | |||
| 434 | const char *name; | 434 | const char *name; |
| 435 | int i; | 435 | int i; |
| 436 | 436 | ||
| 437 | for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--) | 437 | for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--) |
| 438 | if (par->pci_id == aty_chips[i].pci_id) | 438 | if (par->pci_id == aty_chips[i].pci_id) |
| 439 | break; | 439 | break; |
| 440 | 440 | ||
| @@ -2168,10 +2168,10 @@ static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk) | |||
| 2168 | 2168 | ||
| 2169 | if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) { | 2169 | if (IS_XL(par->pci_id) || IS_MOBILITY(par->pci_id)) { |
| 2170 | refresh_tbl = ragexl_tbl; | 2170 | refresh_tbl = ragexl_tbl; |
| 2171 | size = sizeof(ragexl_tbl)/sizeof(int); | 2171 | size = ARRAY_SIZE(ragexl_tbl); |
| 2172 | } else { | 2172 | } else { |
| 2173 | refresh_tbl = ragepro_tbl; | 2173 | refresh_tbl = ragepro_tbl; |
| 2174 | size = sizeof(ragepro_tbl)/sizeof(int); | 2174 | size = ARRAY_SIZE(ragepro_tbl); |
| 2175 | } | 2175 | } |
| 2176 | 2176 | ||
| 2177 | for (i=0; i < size; i++) { | 2177 | for (i=0; i < size; i++) { |
| @@ -2298,6 +2298,10 @@ static int __init aty_init(struct fb_info *info, const char *name) | |||
| 2298 | case CLK_ATI18818_1: | 2298 | case CLK_ATI18818_1: |
| 2299 | par->pll_ops = &aty_pll_ati18818_1; | 2299 | par->pll_ops = &aty_pll_ati18818_1; |
| 2300 | break; | 2300 | break; |
| 2301 | case CLK_IBMRGB514: | ||
| 2302 | par->pll_ops = &aty_pll_ibm514; | ||
| 2303 | break; | ||
| 2304 | #if 0 /* dead code */ | ||
| 2301 | case CLK_STG1703: | 2305 | case CLK_STG1703: |
| 2302 | par->pll_ops = &aty_pll_stg1703; | 2306 | par->pll_ops = &aty_pll_stg1703; |
| 2303 | break; | 2307 | break; |
| @@ -2307,9 +2311,7 @@ static int __init aty_init(struct fb_info *info, const char *name) | |||
| 2307 | case CLK_ATT20C408: | 2311 | case CLK_ATT20C408: |
| 2308 | par->pll_ops = &aty_pll_att20c408; | 2312 | par->pll_ops = &aty_pll_att20c408; |
| 2309 | break; | 2313 | break; |
| 2310 | case CLK_IBMRGB514: | 2314 | #endif |
| 2311 | par->pll_ops = &aty_pll_ibm514; | ||
| 2312 | break; | ||
| 2313 | default: | 2315 | default: |
| 2314 | PRINTKI("aty_init: CLK type not implemented yet!"); | 2316 | PRINTKI("aty_init: CLK type not implemented yet!"); |
| 2315 | par->pll_ops = &aty_pll_unsupported; | 2317 | par->pll_ops = &aty_pll_unsupported; |
| @@ -3397,7 +3399,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi | |||
| 3397 | struct atyfb_par *par; | 3399 | struct atyfb_par *par; |
| 3398 | int i, rc = -ENOMEM; | 3400 | int i, rc = -ENOMEM; |
| 3399 | 3401 | ||
| 3400 | for (i = sizeof(aty_chips) / sizeof(*aty_chips) - 1; i >= 0; i--) | 3402 | for (i = ARRAY_SIZE(aty_chips); i >= 0; i--) |
| 3401 | if (pdev->device == aty_chips[i].pci_id) | 3403 | if (pdev->device == aty_chips[i].pci_id) |
| 3402 | break; | 3404 | break; |
| 3403 | 3405 | ||
diff --git a/drivers/video/aty/mach64_gx.c b/drivers/video/aty/mach64_gx.c index 01fdff79483b..2045639cb671 100644 --- a/drivers/video/aty/mach64_gx.c +++ b/drivers/video/aty/mach64_gx.c | |||
| @@ -149,8 +149,7 @@ static int aty_var_to_pll_514(const struct fb_info *info, u32 vclk_per, | |||
| 149 | }; | 149 | }; |
| 150 | int i; | 150 | int i; |
| 151 | 151 | ||
| 152 | for (i = 0; i < sizeof(RGB514_clocks) / sizeof(*RGB514_clocks); | 152 | for (i = 0; i < ARRAY_SIZE(RGB514_clocks); i++) |
| 153 | i++) | ||
| 154 | if (vclk_per <= RGB514_clocks[i].limit) { | 153 | if (vclk_per <= RGB514_clocks[i].limit) { |
| 155 | pll->ibm514.m = RGB514_clocks[i].m; | 154 | pll->ibm514.m = RGB514_clocks[i].m; |
| 156 | pll->ibm514.n = RGB514_clocks[i].n; | 155 | pll->ibm514.n = RGB514_clocks[i].n; |
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index c9f0c5a07e6e..9a6b5b39b88e 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
| @@ -1067,7 +1067,7 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, | |||
| 1067 | 1067 | ||
| 1068 | 1068 | ||
| 1069 | if (regno > 255) | 1069 | if (regno > 255) |
| 1070 | return 1; | 1070 | return -EINVAL; |
| 1071 | 1071 | ||
| 1072 | red >>= 8; | 1072 | red >>= 8; |
| 1073 | green >>= 8; | 1073 | green >>= 8; |
| @@ -1086,9 +1086,9 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, | |||
| 1086 | pindex = regno * 8; | 1086 | pindex = regno * 8; |
| 1087 | 1087 | ||
| 1088 | if (rinfo->depth == 16 && regno > 63) | 1088 | if (rinfo->depth == 16 && regno > 63) |
| 1089 | return 1; | 1089 | return -EINVAL; |
| 1090 | if (rinfo->depth == 15 && regno > 31) | 1090 | if (rinfo->depth == 15 && regno > 31) |
| 1091 | return 1; | 1091 | return -EINVAL; |
| 1092 | 1092 | ||
| 1093 | /* For 565, the green component is mixed one order | 1093 | /* For 565, the green component is mixed one order |
| 1094 | * below | 1094 | * below |
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c new file mode 100644 index 000000000000..b367de30b98c --- /dev/null +++ b/drivers/video/au1200fb.c | |||
| @@ -0,0 +1,3844 @@ | |||
| 1 | /* | ||
| 2 | * BRIEF MODULE DESCRIPTION | ||
| 3 | * Au1200 LCD Driver. | ||
| 4 | * | ||
| 5 | * Copyright 2004-2005 AMD | ||
| 6 | * Author: AMD | ||
| 7 | * | ||
| 8 | * Based on: | ||
| 9 | * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device | ||
| 10 | * Created 28 Dec 1997 by Geert Uytterhoeven | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify it | ||
| 13 | * under the terms of the GNU General Public License as published by the | ||
| 14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 15 | * option) any later version. | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
| 18 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
| 19 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
| 20 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
| 23 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| 24 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 27 | * | ||
| 28 | * You should have received a copy of the GNU General Public License along | ||
| 29 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 30 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 31 | */ | ||
| 32 | |||
| 33 | #include <linux/module.h> | ||
| 34 | #include <linux/platform_device.h> | ||
| 35 | #include <linux/kernel.h> | ||
| 36 | #include <linux/errno.h> | ||
| 37 | #include <linux/string.h> | ||
| 38 | #include <linux/mm.h> | ||
| 39 | #include <linux/fb.h> | ||
| 40 | #include <linux/init.h> | ||
| 41 | #include <linux/interrupt.h> | ||
| 42 | #include <linux/ctype.h> | ||
| 43 | #include <linux/dma-mapping.h> | ||
| 44 | |||
| 45 | #include <asm/mach-au1x00/au1000.h> | ||
| 46 | #include "au1200fb.h" | ||
| 47 | |||
| 48 | #ifdef CONFIG_PM | ||
| 49 | #include <asm/mach-au1x00/au1xxx_pm.h> | ||
| 50 | #endif | ||
| 51 | |||
| 52 | #ifndef CONFIG_FB_AU1200_DEVS | ||
| 53 | #define CONFIG_FB_AU1200_DEVS 4 | ||
| 54 | #endif | ||
| 55 | |||
| 56 | #define DRIVER_NAME "au1200fb" | ||
| 57 | #define DRIVER_DESC "LCD controller driver for AU1200 processors" | ||
| 58 | |||
| 59 | #define DEBUG 1 | ||
| 60 | |||
| 61 | #define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) | ||
| 62 | #define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) | ||
| 63 | #define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) | ||
| 64 | |||
| 65 | #if DEBUG | ||
| 66 | #define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg) | ||
| 67 | #else | ||
| 68 | #define print_dbg(f, arg...) do {} while (0) | ||
| 69 | #endif | ||
| 70 | |||
| 71 | |||
| 72 | #define AU1200_LCD_FB_IOCTL 0x46FF | ||
| 73 | |||
| 74 | #define AU1200_LCD_SET_SCREEN 1 | ||
| 75 | #define AU1200_LCD_GET_SCREEN 2 | ||
| 76 | #define AU1200_LCD_SET_WINDOW 3 | ||
| 77 | #define AU1200_LCD_GET_WINDOW 4 | ||
| 78 | #define AU1200_LCD_SET_PANEL 5 | ||
| 79 | #define AU1200_LCD_GET_PANEL 6 | ||
| 80 | |||
| 81 | #define SCREEN_SIZE (1<< 1) | ||
| 82 | #define SCREEN_BACKCOLOR (1<< 2) | ||
| 83 | #define SCREEN_BRIGHTNESS (1<< 3) | ||
| 84 | #define SCREEN_COLORKEY (1<< 4) | ||
| 85 | #define SCREEN_MASK (1<< 5) | ||
| 86 | |||
| 87 | struct au1200_lcd_global_regs_t { | ||
| 88 | unsigned int flags; | ||
| 89 | unsigned int xsize; | ||
| 90 | unsigned int ysize; | ||
| 91 | unsigned int backcolor; | ||
| 92 | unsigned int brightness; | ||
| 93 | unsigned int colorkey; | ||
| 94 | unsigned int mask; | ||
| 95 | unsigned int panel_choice; | ||
| 96 | char panel_desc[80]; | ||
| 97 | |||
| 98 | }; | ||
| 99 | |||
| 100 | #define WIN_POSITION (1<< 0) | ||
| 101 | #define WIN_ALPHA_COLOR (1<< 1) | ||
| 102 | #define WIN_ALPHA_MODE (1<< 2) | ||
| 103 | #define WIN_PRIORITY (1<< 3) | ||
| 104 | #define WIN_CHANNEL (1<< 4) | ||
| 105 | #define WIN_BUFFER_FORMAT (1<< 5) | ||
| 106 | #define WIN_COLOR_ORDER (1<< 6) | ||
| 107 | #define WIN_PIXEL_ORDER (1<< 7) | ||
| 108 | #define WIN_SIZE (1<< 8) | ||
| 109 | #define WIN_COLORKEY_MODE (1<< 9) | ||
| 110 | #define WIN_DOUBLE_BUFFER_MODE (1<< 10) | ||
| 111 | #define WIN_RAM_ARRAY_MODE (1<< 11) | ||
| 112 | #define WIN_BUFFER_SCALE (1<< 12) | ||
| 113 | #define WIN_ENABLE (1<< 13) | ||
| 114 | |||
| 115 | struct au1200_lcd_window_regs_t { | ||
| 116 | unsigned int flags; | ||
| 117 | unsigned int xpos; | ||
| 118 | unsigned int ypos; | ||
| 119 | unsigned int alpha_color; | ||
| 120 | unsigned int alpha_mode; | ||
| 121 | unsigned int priority; | ||
| 122 | unsigned int channel; | ||
| 123 | unsigned int buffer_format; | ||
| 124 | unsigned int color_order; | ||
| 125 | unsigned int pixel_order; | ||
| 126 | unsigned int xsize; | ||
| 127 | unsigned int ysize; | ||
| 128 | unsigned int colorkey_mode; | ||
| 129 | unsigned int double_buffer_mode; | ||
| 130 | unsigned int ram_array_mode; | ||
| 131 | unsigned int xscale; | ||
| 132 | unsigned int yscale; | ||
| 133 | unsigned int enable; | ||
| 134 | }; | ||
| 135 | |||
| 136 | |||
| 137 | struct au1200_lcd_iodata_t { | ||
| 138 | unsigned int subcmd; | ||
| 139 | struct au1200_lcd_global_regs_t global; | ||
| 140 | struct au1200_lcd_window_regs_t window; | ||
| 141 | }; | ||
| 142 | |||
| 143 | #if defined(__BIG_ENDIAN) | ||
| 144 | #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11 | ||
| 145 | #else | ||
| 146 | #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00 | ||
| 147 | #endif | ||
| 148 | #define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565 | ||
| 149 | |||
| 150 | /* Private, per-framebuffer management information (independent of the panel itself) */ | ||
| 151 | struct au1200fb_device { | ||
| 152 | struct fb_info fb_info; /* FB driver info record */ | ||
| 153 | |||
| 154 | int plane; | ||
| 155 | unsigned char* fb_mem; /* FrameBuffer memory map */ | ||
| 156 | unsigned int fb_len; | ||
| 157 | dma_addr_t fb_phys; | ||
| 158 | }; | ||
| 159 | |||
| 160 | static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; | ||
| 161 | /********************************************************************/ | ||
| 162 | |||
| 163 | /* LCD controller restrictions */ | ||
| 164 | #define AU1200_LCD_MAX_XRES 1280 | ||
| 165 | #define AU1200_LCD_MAX_YRES 1024 | ||
| 166 | #define AU1200_LCD_MAX_BPP 32 | ||
| 167 | #define AU1200_LCD_MAX_CLK 96000000 /* fixme: this needs to go away ? */ | ||
| 168 | #define AU1200_LCD_NBR_PALETTE_ENTRIES 256 | ||
| 169 | |||
| 170 | /* Default number of visible screen buffer to allocate */ | ||
| 171 | #define AU1200FB_NBR_VIDEO_BUFFERS 1 | ||
| 172 | |||
| 173 | /********************************************************************/ | ||
| 174 | |||
| 175 | static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; | ||
| 176 | static int window_index = 2; /* default is zero */ | ||
| 177 | static int panel_index = 2; /* default is zero */ | ||
| 178 | static struct window_settings *win; | ||
| 179 | static struct panel_settings *panel; | ||
| 180 | static int noblanking = 1; | ||
| 181 | static int nohwcursor = 0; | ||
| 182 | |||
| 183 | struct window_settings { | ||
| 184 | unsigned char name[64]; | ||
| 185 | uint32 mode_backcolor; | ||
| 186 | uint32 mode_colorkey; | ||
| 187 | uint32 mode_colorkeymsk; | ||
| 188 | struct { | ||
| 189 | int xres; | ||
| 190 | int yres; | ||
| 191 | int xpos; | ||
| 192 | int ypos; | ||
| 193 | uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */ | ||
| 194 | uint32 mode_winenable; | ||
| 195 | } w[4]; | ||
| 196 | }; | ||
| 197 | |||
| 198 | #if defined(__BIG_ENDIAN) | ||
| 199 | #define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00 | ||
| 200 | #else | ||
| 201 | #define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01 | ||
| 202 | #endif | ||
| 203 | |||
| 204 | extern int board_au1200fb_panel_init (void); | ||
| 205 | extern int board_au1200fb_panel_shutdown (void); | ||
| 206 | |||
| 207 | #ifdef CONFIG_PM | ||
| 208 | int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | ||
| 209 | au1xxx_request_t request, void *data); | ||
| 210 | au1xxx_power_dev_t *LCD_pm_dev; | ||
| 211 | #endif | ||
| 212 | |||
| 213 | /* | ||
| 214 | * Default window configurations | ||
| 215 | */ | ||
| 216 | static struct window_settings windows[] = { | ||
| 217 | { /* Index 0 */ | ||
| 218 | "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", | ||
| 219 | /* mode_backcolor */ 0x006600ff, | ||
| 220 | /* mode_colorkey,msk*/ 0, 0, | ||
| 221 | { | ||
| 222 | { | ||
| 223 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 224 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 225 | LCD_WINCTRL1_PO_16BPP, | ||
| 226 | /* mode_winenable*/ LCD_WINENABLE_WEN0, | ||
| 227 | }, | ||
| 228 | { | ||
| 229 | /* xres, yres, xpos, ypos */ 100, 100, 100, 100, | ||
| 230 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 231 | LCD_WINCTRL1_PO_16BPP | | ||
| 232 | LCD_WINCTRL1_PIPE, | ||
| 233 | /* mode_winenable*/ LCD_WINENABLE_WEN1, | ||
| 234 | }, | ||
| 235 | { | ||
| 236 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 237 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 238 | LCD_WINCTRL1_PO_16BPP, | ||
| 239 | /* mode_winenable*/ 0, | ||
| 240 | }, | ||
| 241 | { | ||
| 242 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 243 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 244 | LCD_WINCTRL1_PO_16BPP | | ||
| 245 | LCD_WINCTRL1_PIPE, | ||
| 246 | /* mode_winenable*/ 0, | ||
| 247 | }, | ||
| 248 | }, | ||
| 249 | }, | ||
| 250 | |||
| 251 | { /* Index 1 */ | ||
| 252 | "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", | ||
| 253 | /* mode_backcolor */ 0x006600ff, | ||
| 254 | /* mode_colorkey,msk*/ 0, 0, | ||
| 255 | { | ||
| 256 | { | ||
| 257 | /* xres, yres, xpos, ypos */ 320, 240, 5, 5, | ||
| 258 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP | | ||
| 259 | LCD_WINCTRL1_PO_00, | ||
| 260 | /* mode_winenable*/ LCD_WINENABLE_WEN0, | ||
| 261 | }, | ||
| 262 | { | ||
| 263 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 264 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | ||
| 265 | | LCD_WINCTRL1_PO_16BPP, | ||
| 266 | /* mode_winenable*/ 0, | ||
| 267 | }, | ||
| 268 | { | ||
| 269 | /* xres, yres, xpos, ypos */ 100, 100, 0, 0, | ||
| 270 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 271 | LCD_WINCTRL1_PO_16BPP | | ||
| 272 | LCD_WINCTRL1_PIPE, | ||
| 273 | /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, | ||
| 274 | }, | ||
| 275 | { | ||
| 276 | /* xres, yres, xpos, ypos */ 200, 25, 0, 0, | ||
| 277 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 278 | LCD_WINCTRL1_PO_16BPP | | ||
| 279 | LCD_WINCTRL1_PIPE, | ||
| 280 | /* mode_winenable*/ 0, | ||
| 281 | }, | ||
| 282 | }, | ||
| 283 | }, | ||
| 284 | { /* Index 2 */ | ||
| 285 | "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", | ||
| 286 | /* mode_backcolor */ 0x006600ff, | ||
| 287 | /* mode_colorkey,msk*/ 0, 0, | ||
| 288 | { | ||
| 289 | { | ||
| 290 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 291 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 292 | LCD_WINCTRL1_PO_16BPP, | ||
| 293 | /* mode_winenable*/ LCD_WINENABLE_WEN0, | ||
| 294 | }, | ||
| 295 | { | ||
| 296 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 297 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 298 | LCD_WINCTRL1_PO_16BPP, | ||
| 299 | /* mode_winenable*/ 0, | ||
| 300 | }, | ||
| 301 | { | ||
| 302 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 303 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP | | ||
| 304 | LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE, | ||
| 305 | /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, | ||
| 306 | }, | ||
| 307 | { | ||
| 308 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 309 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 310 | LCD_WINCTRL1_PO_16BPP | | ||
| 311 | LCD_WINCTRL1_PIPE, | ||
| 312 | /* mode_winenable*/ 0, | ||
| 313 | }, | ||
| 314 | }, | ||
| 315 | }, | ||
| 316 | /* Need VGA 640 @ 24bpp, @ 32bpp */ | ||
| 317 | /* Need VGA 800 @ 24bpp, @ 32bpp */ | ||
| 318 | /* Need VGA 1024 @ 24bpp, @ 32bpp */ | ||
| 319 | }; | ||
| 320 | |||
| 321 | /* | ||
| 322 | * Controller configurations for various panels. | ||
| 323 | */ | ||
| 324 | |||
| 325 | struct panel_settings | ||
| 326 | { | ||
| 327 | const char name[25]; /* Full name <vendor>_<model> */ | ||
| 328 | |||
| 329 | struct fb_monspecs monspecs; /* FB monitor specs */ | ||
| 330 | |||
| 331 | /* panel timings */ | ||
| 332 | uint32 mode_screen; | ||
| 333 | uint32 mode_horztiming; | ||
| 334 | uint32 mode_verttiming; | ||
| 335 | uint32 mode_clkcontrol; | ||
| 336 | uint32 mode_pwmdiv; | ||
| 337 | uint32 mode_pwmhi; | ||
| 338 | uint32 mode_outmask; | ||
| 339 | uint32 mode_fifoctrl; | ||
| 340 | uint32 mode_toyclksrc; | ||
| 341 | uint32 mode_backlight; | ||
| 342 | uint32 mode_auxpll; | ||
| 343 | int (*device_init)(void); | ||
| 344 | int (*device_shutdown)(void); | ||
| 345 | #define Xres min_xres | ||
| 346 | #define Yres min_yres | ||
| 347 | u32 min_xres; /* Minimum horizontal resolution */ | ||
| 348 | u32 max_xres; /* Maximum horizontal resolution */ | ||
| 349 | u32 min_yres; /* Minimum vertical resolution */ | ||
| 350 | u32 max_yres; /* Maximum vertical resolution */ | ||
| 351 | }; | ||
| 352 | |||
| 353 | /********************************************************************/ | ||
| 354 | /* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */ | ||
| 355 | |||
| 356 | /* List of panels known to work with the AU1200 LCD controller. | ||
| 357 | * To add a new panel, enter the same specifications as the | ||
| 358 | * Generic_TFT one, and MAKE SURE that it doesn't conflicts | ||
| 359 | * with the controller restrictions. Restrictions are: | ||
| 360 | * | ||
| 361 | * STN color panels: max_bpp <= 12 | ||
| 362 | * STN mono panels: max_bpp <= 4 | ||
| 363 | * TFT panels: max_bpp <= 16 | ||
| 364 | * max_xres <= 800 | ||
| 365 | * max_yres <= 600 | ||
| 366 | */ | ||
| 367 | static struct panel_settings known_lcd_panels[] = | ||
| 368 | { | ||
| 369 | [0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */ | ||
| 370 | .name = "QVGA_320x240", | ||
| 371 | .monspecs = { | ||
| 372 | .modedb = NULL, | ||
| 373 | .modedb_len = 0, | ||
| 374 | .hfmin = 30000, | ||
| 375 | .hfmax = 70000, | ||
| 376 | .vfmin = 60, | ||
| 377 | .vfmax = 60, | ||
| 378 | .dclkmin = 6000000, | ||
| 379 | .dclkmax = 28000000, | ||
| 380 | .input = FB_DISP_RGB, | ||
| 381 | }, | ||
| 382 | .mode_screen = LCD_SCREEN_SX_N(320) | | ||
| 383 | LCD_SCREEN_SY_N(240), | ||
| 384 | .mode_horztiming = 0x00c4623b, | ||
| 385 | .mode_verttiming = 0x00502814, | ||
| 386 | .mode_clkcontrol = 0x00020002, /* /4=24Mhz */ | ||
| 387 | .mode_pwmdiv = 0x00000000, | ||
| 388 | .mode_pwmhi = 0x00000000, | ||
| 389 | .mode_outmask = 0x00FFFFFF, | ||
| 390 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 391 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 392 | .mode_backlight = 0x00000000, | ||
| 393 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 394 | .device_init = NULL, | ||
| 395 | .device_shutdown = NULL, | ||
| 396 | 320, 320, | ||
| 397 | 240, 240, | ||
| 398 | }, | ||
| 399 | |||
| 400 | [1] = { /* VGA 640x480 H:30.3kHz V:58Hz */ | ||
| 401 | .name = "VGA_640x480", | ||
| 402 | .monspecs = { | ||
| 403 | .modedb = NULL, | ||
| 404 | .modedb_len = 0, | ||
| 405 | .hfmin = 30000, | ||
| 406 | .hfmax = 70000, | ||
| 407 | .vfmin = 60, | ||
| 408 | .vfmax = 60, | ||
| 409 | .dclkmin = 6000000, | ||
| 410 | .dclkmax = 28000000, | ||
| 411 | .input = FB_DISP_RGB, | ||
| 412 | }, | ||
| 413 | .mode_screen = 0x13f9df80, | ||
| 414 | .mode_horztiming = 0x003c5859, | ||
| 415 | .mode_verttiming = 0x00741201, | ||
| 416 | .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ | ||
| 417 | .mode_pwmdiv = 0x00000000, | ||
| 418 | .mode_pwmhi = 0x00000000, | ||
| 419 | .mode_outmask = 0x00FFFFFF, | ||
| 420 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 421 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 422 | .mode_backlight = 0x00000000, | ||
| 423 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 424 | .device_init = NULL, | ||
| 425 | .device_shutdown = NULL, | ||
| 426 | 640, 480, | ||
| 427 | 640, 480, | ||
| 428 | }, | ||
| 429 | |||
| 430 | [2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */ | ||
| 431 | .name = "SVGA_800x600", | ||
| 432 | .monspecs = { | ||
| 433 | .modedb = NULL, | ||
| 434 | .modedb_len = 0, | ||
| 435 | .hfmin = 30000, | ||
| 436 | .hfmax = 70000, | ||
| 437 | .vfmin = 60, | ||
| 438 | .vfmax = 60, | ||
| 439 | .dclkmin = 6000000, | ||
| 440 | .dclkmax = 28000000, | ||
| 441 | .input = FB_DISP_RGB, | ||
| 442 | }, | ||
| 443 | .mode_screen = 0x18fa5780, | ||
| 444 | .mode_horztiming = 0x00dc7e77, | ||
| 445 | .mode_verttiming = 0x00584805, | ||
| 446 | .mode_clkcontrol = 0x00020000, /* /2=48Mhz */ | ||
| 447 | .mode_pwmdiv = 0x00000000, | ||
| 448 | .mode_pwmhi = 0x00000000, | ||
| 449 | .mode_outmask = 0x00FFFFFF, | ||
| 450 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 451 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 452 | .mode_backlight = 0x00000000, | ||
| 453 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 454 | .device_init = NULL, | ||
| 455 | .device_shutdown = NULL, | ||
| 456 | 800, 800, | ||
| 457 | 600, 600, | ||
| 458 | }, | ||
| 459 | |||
| 460 | [3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */ | ||
| 461 | .name = "XVGA_1024x768", | ||
| 462 | .monspecs = { | ||
| 463 | .modedb = NULL, | ||
| 464 | .modedb_len = 0, | ||
| 465 | .hfmin = 30000, | ||
| 466 | .hfmax = 70000, | ||
| 467 | .vfmin = 60, | ||
| 468 | .vfmax = 60, | ||
| 469 | .dclkmin = 6000000, | ||
| 470 | .dclkmax = 28000000, | ||
| 471 | .input = FB_DISP_RGB, | ||
| 472 | }, | ||
| 473 | .mode_screen = 0x1ffaff80, | ||
| 474 | .mode_horztiming = 0x007d0e57, | ||
| 475 | .mode_verttiming = 0x00740a01, | ||
| 476 | .mode_clkcontrol = 0x000A0000, /* /1 */ | ||
| 477 | .mode_pwmdiv = 0x00000000, | ||
| 478 | .mode_pwmhi = 0x00000000, | ||
| 479 | .mode_outmask = 0x00FFFFFF, | ||
| 480 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 481 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 482 | .mode_backlight = 0x00000000, | ||
| 483 | .mode_auxpll = 6, /* 72MHz AUXPLL */ | ||
| 484 | .device_init = NULL, | ||
| 485 | .device_shutdown = NULL, | ||
| 486 | 1024, 1024, | ||
| 487 | 768, 768, | ||
| 488 | }, | ||
| 489 | |||
| 490 | [4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */ | ||
| 491 | .name = "XVGA_1280x1024", | ||
| 492 | .monspecs = { | ||
| 493 | .modedb = NULL, | ||
| 494 | .modedb_len = 0, | ||
| 495 | .hfmin = 30000, | ||
| 496 | .hfmax = 70000, | ||
| 497 | .vfmin = 60, | ||
| 498 | .vfmax = 60, | ||
| 499 | .dclkmin = 6000000, | ||
| 500 | .dclkmax = 28000000, | ||
| 501 | .input = FB_DISP_RGB, | ||
| 502 | }, | ||
| 503 | .mode_screen = 0x27fbff80, | ||
| 504 | .mode_horztiming = 0x00cdb2c7, | ||
| 505 | .mode_verttiming = 0x00600002, | ||
| 506 | .mode_clkcontrol = 0x000A0000, /* /1 */ | ||
| 507 | .mode_pwmdiv = 0x00000000, | ||
| 508 | .mode_pwmhi = 0x00000000, | ||
| 509 | .mode_outmask = 0x00FFFFFF, | ||
| 510 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 511 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 512 | .mode_backlight = 0x00000000, | ||
| 513 | .mode_auxpll = 10, /* 120MHz AUXPLL */ | ||
| 514 | .device_init = NULL, | ||
| 515 | .device_shutdown = NULL, | ||
| 516 | 1280, 1280, | ||
| 517 | 1024, 1024, | ||
| 518 | }, | ||
| 519 | |||
| 520 | [5] = { /* Samsung 1024x768 TFT */ | ||
| 521 | .name = "Samsung_1024x768_TFT", | ||
| 522 | .monspecs = { | ||
| 523 | .modedb = NULL, | ||
| 524 | .modedb_len = 0, | ||
| 525 | .hfmin = 30000, | ||
| 526 | .hfmax = 70000, | ||
| 527 | .vfmin = 60, | ||
| 528 | .vfmax = 60, | ||
| 529 | .dclkmin = 6000000, | ||
| 530 | .dclkmax = 28000000, | ||
| 531 | .input = FB_DISP_RGB, | ||
| 532 | }, | ||
| 533 | .mode_screen = 0x1ffaff80, | ||
| 534 | .mode_horztiming = 0x018cc677, | ||
| 535 | .mode_verttiming = 0x00241217, | ||
| 536 | .mode_clkcontrol = 0x00000000, /* SCB 0x1 /4=24Mhz */ | ||
| 537 | .mode_pwmdiv = 0x8000063f, /* SCB 0x0 */ | ||
| 538 | .mode_pwmhi = 0x03400000, /* SCB 0x0 */ | ||
| 539 | .mode_outmask = 0x00FFFFFF, | ||
| 540 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 541 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 542 | .mode_backlight = 0x00000000, | ||
| 543 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 544 | .device_init = board_au1200fb_panel_init, | ||
| 545 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 546 | 1024, 1024, | ||
| 547 | 768, 768, | ||
| 548 | }, | ||
| 549 | |||
| 550 | [6] = { /* Toshiba 640x480 TFT */ | ||
| 551 | .name = "Toshiba_640x480_TFT", | ||
| 552 | .monspecs = { | ||
| 553 | .modedb = NULL, | ||
| 554 | .modedb_len = 0, | ||
| 555 | .hfmin = 30000, | ||
| 556 | .hfmax = 70000, | ||
| 557 | .vfmin = 60, | ||
| 558 | .vfmax = 60, | ||
| 559 | .dclkmin = 6000000, | ||
| 560 | .dclkmax = 28000000, | ||
| 561 | .input = FB_DISP_RGB, | ||
| 562 | }, | ||
| 563 | .mode_screen = LCD_SCREEN_SX_N(640) | | ||
| 564 | LCD_SCREEN_SY_N(480), | ||
| 565 | .mode_horztiming = LCD_HORZTIMING_HPW_N(96) | | ||
| 566 | LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51), | ||
| 567 | .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | | ||
| 568 | LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32), | ||
| 569 | .mode_clkcontrol = 0x00000000, /* /4=24Mhz */ | ||
| 570 | .mode_pwmdiv = 0x8000063f, | ||
| 571 | .mode_pwmhi = 0x03400000, | ||
| 572 | .mode_outmask = 0x00fcfcfc, | ||
| 573 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 574 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 575 | .mode_backlight = 0x00000000, | ||
| 576 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 577 | .device_init = board_au1200fb_panel_init, | ||
| 578 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 579 | 640, 480, | ||
| 580 | 640, 480, | ||
| 581 | }, | ||
| 582 | |||
| 583 | [7] = { /* Sharp 320x240 TFT */ | ||
| 584 | .name = "Sharp_320x240_TFT", | ||
| 585 | .monspecs = { | ||
| 586 | .modedb = NULL, | ||
| 587 | .modedb_len = 0, | ||
| 588 | .hfmin = 12500, | ||
| 589 | .hfmax = 20000, | ||
| 590 | .vfmin = 38, | ||
| 591 | .vfmax = 81, | ||
| 592 | .dclkmin = 4500000, | ||
| 593 | .dclkmax = 6800000, | ||
| 594 | .input = FB_DISP_RGB, | ||
| 595 | }, | ||
| 596 | .mode_screen = LCD_SCREEN_SX_N(320) | | ||
| 597 | LCD_SCREEN_SY_N(240), | ||
| 598 | .mode_horztiming = LCD_HORZTIMING_HPW_N(60) | | ||
| 599 | LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2), | ||
| 600 | .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | | ||
| 601 | LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5), | ||
| 602 | .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/ | ||
| 603 | .mode_pwmdiv = 0x8000063f, | ||
| 604 | .mode_pwmhi = 0x03400000, | ||
| 605 | .mode_outmask = 0x00fcfcfc, | ||
| 606 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 607 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 608 | .mode_backlight = 0x00000000, | ||
| 609 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 610 | .device_init = board_au1200fb_panel_init, | ||
| 611 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 612 | 320, 320, | ||
| 613 | 240, 240, | ||
| 614 | }, | ||
| 615 | |||
| 616 | [8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */ | ||
| 617 | .name = "Toppoly_TD070WGCB2", | ||
| 618 | .monspecs = { | ||
| 619 | .modedb = NULL, | ||
| 620 | .modedb_len = 0, | ||
| 621 | .hfmin = 30000, | ||
| 622 | .hfmax = 70000, | ||
| 623 | .vfmin = 60, | ||
| 624 | .vfmax = 60, | ||
| 625 | .dclkmin = 6000000, | ||
| 626 | .dclkmax = 28000000, | ||
| 627 | .input = FB_DISP_RGB, | ||
| 628 | }, | ||
| 629 | .mode_screen = LCD_SCREEN_SX_N(856) | | ||
| 630 | LCD_SCREEN_SY_N(480), | ||
| 631 | .mode_horztiming = LCD_HORZTIMING_HND2_N(43) | | ||
| 632 | LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114), | ||
| 633 | .mode_verttiming = LCD_VERTTIMING_VND2_N(20) | | ||
| 634 | LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4), | ||
| 635 | .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ | ||
| 636 | .mode_pwmdiv = 0x8000063f, | ||
| 637 | .mode_pwmhi = 0x03400000, | ||
| 638 | .mode_outmask = 0x00fcfcfc, | ||
| 639 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 640 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 641 | .mode_backlight = 0x00000000, | ||
| 642 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 643 | .device_init = board_au1200fb_panel_init, | ||
| 644 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 645 | 856, 856, | ||
| 646 | 480, 480, | ||
| 647 | }, | ||
| 648 | }; | ||
| 649 | |||
| 650 | #define NUM_PANELS (ARRAY_SIZE(known_lcd_panels)) | ||
| 651 | |||
| 652 | /********************************************************************/ | ||
| 653 | |||
| 654 | #ifdef CONFIG_PM | ||
| 655 | static int set_brightness(unsigned int brightness) | ||
| 656 | { | ||
| 657 | unsigned int hi1, divider; | ||
| 658 | |||
| 659 | /* limit brightness pwm duty to >= 30/1600 */ | ||
| 660 | if (brightness < 30) { | ||
| 661 | brightness = 30; | ||
| 662 | } | ||
| 663 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
| 664 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
| 665 | hi1 = (((brightness & 0xFF) + 1) * divider >> 8); | ||
| 666 | lcd->pwmhi &= 0xFFFF; | ||
| 667 | lcd->pwmhi |= (hi1 << 16); | ||
| 668 | |||
| 669 | return brightness; | ||
| 670 | } | ||
| 671 | #endif /* CONFIG_PM */ | ||
| 672 | |||
| 673 | static int winbpp (unsigned int winctrl1) | ||
| 674 | { | ||
| 675 | int bits = 0; | ||
| 676 | |||
| 677 | /* how many bits are needed for each pixel format */ | ||
| 678 | switch (winctrl1 & LCD_WINCTRL1_FRM) { | ||
| 679 | case LCD_WINCTRL1_FRM_1BPP: | ||
| 680 | bits = 1; | ||
| 681 | break; | ||
| 682 | case LCD_WINCTRL1_FRM_2BPP: | ||
| 683 | bits = 2; | ||
| 684 | break; | ||
| 685 | case LCD_WINCTRL1_FRM_4BPP: | ||
| 686 | bits = 4; | ||
| 687 | break; | ||
| 688 | case LCD_WINCTRL1_FRM_8BPP: | ||
| 689 | bits = 8; | ||
| 690 | break; | ||
| 691 | case LCD_WINCTRL1_FRM_12BPP: | ||
| 692 | case LCD_WINCTRL1_FRM_16BPP655: | ||
| 693 | case LCD_WINCTRL1_FRM_16BPP565: | ||
| 694 | case LCD_WINCTRL1_FRM_16BPP556: | ||
| 695 | case LCD_WINCTRL1_FRM_16BPPI1555: | ||
| 696 | case LCD_WINCTRL1_FRM_16BPPI5551: | ||
| 697 | case LCD_WINCTRL1_FRM_16BPPA1555: | ||
| 698 | case LCD_WINCTRL1_FRM_16BPPA5551: | ||
| 699 | bits = 16; | ||
| 700 | break; | ||
| 701 | case LCD_WINCTRL1_FRM_24BPP: | ||
| 702 | case LCD_WINCTRL1_FRM_32BPP: | ||
| 703 | bits = 32; | ||
| 704 | break; | ||
| 705 | } | ||
| 706 | |||
| 707 | return bits; | ||
| 708 | } | ||
| 709 | |||
| 710 | static int fbinfo2index (struct fb_info *fb_info) | ||
| 711 | { | ||
| 712 | int i; | ||
| 713 | |||
| 714 | for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { | ||
| 715 | if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info)) | ||
| 716 | return i; | ||
| 717 | } | ||
| 718 | printk("au1200fb: ERROR: fbinfo2index failed!\n"); | ||
| 719 | return -1; | ||
| 720 | } | ||
| 721 | |||
| 722 | static int au1200_setlocation (struct au1200fb_device *fbdev, int plane, | ||
| 723 | int xpos, int ypos) | ||
| 724 | { | ||
| 725 | uint32 winctrl0, winctrl1, winenable, fb_offset = 0; | ||
| 726 | int xsz, ysz; | ||
| 727 | |||
| 728 | /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */ | ||
| 729 | |||
| 730 | winctrl0 = lcd->window[plane].winctrl0; | ||
| 731 | winctrl1 = lcd->window[plane].winctrl1; | ||
| 732 | winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN); | ||
| 733 | winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY); | ||
| 734 | |||
| 735 | /* Check for off-screen adjustments */ | ||
| 736 | xsz = win->w[plane].xres; | ||
| 737 | ysz = win->w[plane].yres; | ||
| 738 | if ((xpos + win->w[plane].xres) > panel->Xres) { | ||
| 739 | /* Off-screen to the right */ | ||
| 740 | xsz = panel->Xres - xpos; /* off by 1 ??? */ | ||
| 741 | /*printk("off screen right\n");*/ | ||
| 742 | } | ||
| 743 | |||
| 744 | if ((ypos + win->w[plane].yres) > panel->Yres) { | ||
| 745 | /* Off-screen to the bottom */ | ||
| 746 | ysz = panel->Yres - ypos; /* off by 1 ??? */ | ||
| 747 | /*printk("off screen bottom\n");*/ | ||
| 748 | } | ||
| 749 | |||
| 750 | if (xpos < 0) { | ||
| 751 | /* Off-screen to the left */ | ||
| 752 | xsz = win->w[plane].xres + xpos; | ||
| 753 | fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8); | ||
| 754 | xpos = 0; | ||
| 755 | /*printk("off screen left\n");*/ | ||
| 756 | } | ||
| 757 | |||
| 758 | if (ypos < 0) { | ||
| 759 | /* Off-screen to the top */ | ||
| 760 | ysz = win->w[plane].yres + ypos; | ||
| 761 | /* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */ | ||
| 762 | ypos = 0; | ||
| 763 | /*printk("off screen top\n");*/ | ||
| 764 | } | ||
| 765 | |||
| 766 | /* record settings */ | ||
| 767 | win->w[plane].xpos = xpos; | ||
| 768 | win->w[plane].ypos = ypos; | ||
| 769 | |||
| 770 | xsz -= 1; | ||
| 771 | ysz -= 1; | ||
| 772 | winctrl0 |= (xpos << 21); | ||
| 773 | winctrl0 |= (ypos << 10); | ||
| 774 | winctrl1 |= (xsz << 11); | ||
| 775 | winctrl1 |= (ysz << 0); | ||
| 776 | |||
| 777 | /* Disable the window while making changes, then restore WINEN */ | ||
| 778 | winenable = lcd->winenable & (1 << plane); | ||
| 779 | au_sync(); | ||
| 780 | lcd->winenable &= ~(1 << plane); | ||
| 781 | lcd->window[plane].winctrl0 = winctrl0; | ||
| 782 | lcd->window[plane].winctrl1 = winctrl1; | ||
| 783 | lcd->window[plane].winbuf0 = | ||
| 784 | lcd->window[plane].winbuf1 = fbdev->fb_phys; | ||
| 785 | lcd->window[plane].winbufctrl = 0; /* select winbuf0 */ | ||
| 786 | lcd->winenable |= winenable; | ||
| 787 | au_sync(); | ||
| 788 | |||
| 789 | return 0; | ||
| 790 | } | ||
| 791 | |||
| 792 | static void au1200_setpanel (struct panel_settings *newpanel) | ||
| 793 | { | ||
| 794 | /* | ||
| 795 | * Perform global setup/init of LCD controller | ||
| 796 | */ | ||
| 797 | uint32 winenable; | ||
| 798 | |||
| 799 | /* Make sure all windows disabled */ | ||
| 800 | winenable = lcd->winenable; | ||
| 801 | lcd->winenable = 0; | ||
| 802 | au_sync(); | ||
| 803 | /* | ||
| 804 | * Ensure everything is disabled before reconfiguring | ||
| 805 | */ | ||
| 806 | if (lcd->screen & LCD_SCREEN_SEN) { | ||
| 807 | /* Wait for vertical sync period */ | ||
| 808 | lcd->intstatus = LCD_INT_SS; | ||
| 809 | while ((lcd->intstatus & LCD_INT_SS) == 0) { | ||
| 810 | au_sync(); | ||
| 811 | } | ||
| 812 | |||
| 813 | lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/ | ||
| 814 | |||
| 815 | do { | ||
| 816 | lcd->intstatus = lcd->intstatus; /*clear interrupts*/ | ||
| 817 | au_sync(); | ||
| 818 | /*wait for controller to shut down*/ | ||
| 819 | } while ((lcd->intstatus & LCD_INT_SD) == 0); | ||
| 820 | |||
| 821 | /* Call shutdown of current panel (if up) */ | ||
| 822 | /* this must occur last, because if an external clock is driving | ||
| 823 | the controller, the clock cannot be turned off before first | ||
| 824 | shutting down the controller. | ||
| 825 | */ | ||
| 826 | if (panel->device_shutdown != NULL) | ||
| 827 | panel->device_shutdown(); | ||
| 828 | } | ||
| 829 | |||
| 830 | /* Newpanel == NULL indicates a shutdown operation only */ | ||
| 831 | if (newpanel == NULL) | ||
| 832 | return; | ||
| 833 | |||
| 834 | panel = newpanel; | ||
| 835 | |||
| 836 | printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres); | ||
| 837 | |||
| 838 | /* | ||
| 839 | * Setup clocking if internal LCD clock source (assumes sys_auxpll valid) | ||
| 840 | */ | ||
| 841 | if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT)) | ||
| 842 | { | ||
| 843 | uint32 sys_clksrc; | ||
| 844 | au_writel(panel->mode_auxpll, SYS_AUXPLL); | ||
| 845 | sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f; | ||
| 846 | sys_clksrc |= panel->mode_toyclksrc; | ||
| 847 | au_writel(sys_clksrc, SYS_CLKSRC); | ||
| 848 | } | ||
| 849 | |||
| 850 | /* | ||
| 851 | * Configure panel timings | ||
| 852 | */ | ||
| 853 | lcd->screen = panel->mode_screen; | ||
| 854 | lcd->horztiming = panel->mode_horztiming; | ||
| 855 | lcd->verttiming = panel->mode_verttiming; | ||
| 856 | lcd->clkcontrol = panel->mode_clkcontrol; | ||
| 857 | lcd->pwmdiv = panel->mode_pwmdiv; | ||
| 858 | lcd->pwmhi = panel->mode_pwmhi; | ||
| 859 | lcd->outmask = panel->mode_outmask; | ||
| 860 | lcd->fifoctrl = panel->mode_fifoctrl; | ||
| 861 | au_sync(); | ||
| 862 | |||
| 863 | /* fixme: Check window settings to make sure still valid | ||
| 864 | * for new geometry */ | ||
| 865 | #if 0 | ||
| 866 | au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos); | ||
| 867 | au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos); | ||
| 868 | au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos); | ||
| 869 | au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos); | ||
| 870 | #endif | ||
| 871 | lcd->winenable = winenable; | ||
| 872 | |||
| 873 | /* | ||
| 874 | * Re-enable screen now that it is configured | ||
| 875 | */ | ||
| 876 | lcd->screen |= LCD_SCREEN_SEN; | ||
| 877 | au_sync(); | ||
| 878 | |||
| 879 | /* Call init of panel */ | ||
| 880 | if (panel->device_init != NULL) panel->device_init(); | ||
| 881 | |||
| 882 | /* FIX!!!! not appropriate on panel change!!! Global setup/init */ | ||
| 883 | lcd->intenable = 0; | ||
| 884 | lcd->intstatus = ~0; | ||
| 885 | lcd->backcolor = win->mode_backcolor; | ||
| 886 | |||
| 887 | /* Setup Color Key - FIX!!! */ | ||
| 888 | lcd->colorkey = win->mode_colorkey; | ||
| 889 | lcd->colorkeymsk = win->mode_colorkeymsk; | ||
| 890 | |||
| 891 | /* Setup HWCursor - FIX!!! Need to support this eventually */ | ||
| 892 | lcd->hwc.cursorctrl = 0; | ||
| 893 | lcd->hwc.cursorpos = 0; | ||
| 894 | lcd->hwc.cursorcolor0 = 0; | ||
| 895 | lcd->hwc.cursorcolor1 = 0; | ||
| 896 | lcd->hwc.cursorcolor2 = 0; | ||
| 897 | lcd->hwc.cursorcolor3 = 0; | ||
| 898 | |||
| 899 | |||
| 900 | #if 0 | ||
| 901 | #define D(X) printk("%25s: %08X\n", #X, X) | ||
| 902 | D(lcd->screen); | ||
| 903 | D(lcd->horztiming); | ||
| 904 | D(lcd->verttiming); | ||
| 905 | D(lcd->clkcontrol); | ||
| 906 | D(lcd->pwmdiv); | ||
| 907 | D(lcd->pwmhi); | ||
| 908 | D(lcd->outmask); | ||
| 909 | D(lcd->fifoctrl); | ||
| 910 | D(lcd->window[0].winctrl0); | ||
| 911 | D(lcd->window[0].winctrl1); | ||
| 912 | D(lcd->window[0].winctrl2); | ||
| 913 | D(lcd->window[0].winbuf0); | ||
| 914 | D(lcd->window[0].winbuf1); | ||
| 915 | D(lcd->window[0].winbufctrl); | ||
| 916 | D(lcd->window[1].winctrl0); | ||
| 917 | D(lcd->window[1].winctrl1); | ||
| 918 | D(lcd->window[1].winctrl2); | ||
| 919 | D(lcd->window[1].winbuf0); | ||
| 920 | D(lcd->window[1].winbuf1); | ||
| 921 | D(lcd->window[1].winbufctrl); | ||
| 922 | D(lcd->window[2].winctrl0); | ||
| 923 | D(lcd->window[2].winctrl1); | ||
| 924 | D(lcd->window[2].winctrl2); | ||
| 925 | D(lcd->window[2].winbuf0); | ||
| 926 | D(lcd->window[2].winbuf1); | ||
| 927 | D(lcd->window[2].winbufctrl); | ||
| 928 | D(lcd->window[3].winctrl0); | ||
| 929 | D(lcd->window[3].winctrl1); | ||
| 930 | D(lcd->window[3].winctrl2); | ||
| 931 | D(lcd->window[3].winbuf0); | ||
| 932 | D(lcd->window[3].winbuf1); | ||
| 933 | D(lcd->window[3].winbufctrl); | ||
| 934 | D(lcd->winenable); | ||
| 935 | D(lcd->intenable); | ||
| 936 | D(lcd->intstatus); | ||
| 937 | D(lcd->backcolor); | ||
| 938 | D(lcd->winenable); | ||
| 939 | D(lcd->colorkey); | ||
| 940 | D(lcd->colorkeymsk); | ||
| 941 | D(lcd->hwc.cursorctrl); | ||
| 942 | D(lcd->hwc.cursorpos); | ||
| 943 | D(lcd->hwc.cursorcolor0); | ||
| 944 | D(lcd->hwc.cursorcolor1); | ||
| 945 | D(lcd->hwc.cursorcolor2); | ||
| 946 | D(lcd->hwc.cursorcolor3); | ||
| 947 | #endif | ||
| 948 | } | ||
| 949 | |||
| 950 | static void au1200_setmode(struct au1200fb_device *fbdev) | ||
| 951 | { | ||
| 952 | int plane = fbdev->plane; | ||
| 953 | /* Window/plane setup */ | ||
| 954 | lcd->window[plane].winctrl1 = ( 0 | ||
| 955 | | LCD_WINCTRL1_PRI_N(plane) | ||
| 956 | | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */ | ||
| 957 | ) ; | ||
| 958 | |||
| 959 | au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos); | ||
| 960 | |||
| 961 | lcd->window[plane].winctrl2 = ( 0 | ||
| 962 | | LCD_WINCTRL2_CKMODE_00 | ||
| 963 | | LCD_WINCTRL2_DBM | ||
| 964 | | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) | ||
| 965 | | LCD_WINCTRL2_SCX_1 | ||
| 966 | | LCD_WINCTRL2_SCY_1 | ||
| 967 | ) ; | ||
| 968 | lcd->winenable |= win->w[plane].mode_winenable; | ||
| 969 | au_sync(); | ||
| 970 | } | ||
| 971 | |||
| 972 | |||
| 973 | /* Inline helpers */ | ||
| 974 | |||
| 975 | /*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ | ||
| 976 | /*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ | ||
| 977 | |||
| 978 | #define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN) | ||
| 979 | |||
| 980 | /* Bitfields format supported by the controller. */ | ||
| 981 | static struct fb_bitfield rgb_bitfields[][4] = { | ||
| 982 | /* Red, Green, Blue, Transp */ | ||
| 983 | [LCD_WINCTRL1_FRM_16BPP655 >> 25] = | ||
| 984 | { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
| 985 | |||
| 986 | [LCD_WINCTRL1_FRM_16BPP565 >> 25] = | ||
| 987 | { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
| 988 | |||
| 989 | [LCD_WINCTRL1_FRM_16BPP556 >> 25] = | ||
| 990 | { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } }, | ||
| 991 | |||
| 992 | [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] = | ||
| 993 | { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
| 994 | |||
| 995 | [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] = | ||
| 996 | { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } }, | ||
| 997 | |||
| 998 | [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] = | ||
| 999 | { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } }, | ||
| 1000 | |||
| 1001 | [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] = | ||
| 1002 | { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } }, | ||
| 1003 | |||
| 1004 | [LCD_WINCTRL1_FRM_24BPP >> 25] = | ||
| 1005 | { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } }, | ||
| 1006 | |||
| 1007 | [LCD_WINCTRL1_FRM_32BPP >> 25] = | ||
| 1008 | { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } }, | ||
| 1009 | }; | ||
| 1010 | |||
| 1011 | /*-------------------------------------------------------------------------*/ | ||
| 1012 | |||
| 1013 | /* Helpers */ | ||
| 1014 | |||
| 1015 | static void au1200fb_update_fbinfo(struct fb_info *fbi) | ||
| 1016 | { | ||
| 1017 | /* FIX!!!! This also needs to take the window pixel format into account!!! */ | ||
| 1018 | |||
| 1019 | /* Update var-dependent FB info */ | ||
| 1020 | if (panel_is_color(panel)) { | ||
| 1021 | if (fbi->var.bits_per_pixel <= 8) { | ||
| 1022 | /* palettized */ | ||
| 1023 | fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
| 1024 | fbi->fix.line_length = fbi->var.xres_virtual / | ||
| 1025 | (8/fbi->var.bits_per_pixel); | ||
| 1026 | } else { | ||
| 1027 | /* non-palettized */ | ||
| 1028 | fbi->fix.visual = FB_VISUAL_TRUECOLOR; | ||
| 1029 | fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8); | ||
| 1030 | } | ||
| 1031 | } else { | ||
| 1032 | /* mono FIX!!! mono 8 and 4 bits */ | ||
| 1033 | fbi->fix.visual = FB_VISUAL_MONO10; | ||
| 1034 | fbi->fix.line_length = fbi->var.xres_virtual / 8; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual; | ||
| 1038 | print_dbg("line length: %d\n", fbi->fix.line_length); | ||
| 1039 | print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel); | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | /*-------------------------------------------------------------------------*/ | ||
| 1043 | |||
| 1044 | /* AU1200 framebuffer driver */ | ||
| 1045 | |||
| 1046 | /* fb_check_var | ||
| 1047 | * Validate var settings with hardware restrictions and modify it if necessary | ||
| 1048 | */ | ||
| 1049 | static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, | ||
| 1050 | struct fb_info *fbi) | ||
| 1051 | { | ||
| 1052 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | ||
| 1053 | u32 pixclock; | ||
| 1054 | int screen_size, plane; | ||
| 1055 | |||
| 1056 | plane = fbdev->plane; | ||
| 1057 | |||
| 1058 | /* Make sure that the mode respect all LCD controller and | ||
| 1059 | * panel restrictions. */ | ||
| 1060 | var->xres = win->w[plane].xres; | ||
| 1061 | var->yres = win->w[plane].yres; | ||
| 1062 | |||
| 1063 | /* No need for virtual resolution support */ | ||
| 1064 | var->xres_virtual = var->xres; | ||
| 1065 | var->yres_virtual = var->yres; | ||
| 1066 | |||
| 1067 | var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1); | ||
| 1068 | |||
| 1069 | screen_size = var->xres_virtual * var->yres_virtual; | ||
| 1070 | if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8); | ||
| 1071 | else screen_size /= (8/var->bits_per_pixel); | ||
| 1072 | |||
| 1073 | if (fbdev->fb_len < screen_size) | ||
| 1074 | return -EINVAL; /* Virtual screen is to big, abort */ | ||
| 1075 | |||
| 1076 | /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */ | ||
| 1077 | /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel | ||
| 1078 | * clock can only be obtain by dividing this value by an even integer. | ||
| 1079 | * Fallback to a slower pixel clock if necessary. */ | ||
| 1080 | pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); | ||
| 1081 | pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2)); | ||
| 1082 | |||
| 1083 | if (AU1200_LCD_MAX_CLK % pixclock) { | ||
| 1084 | int diff = AU1200_LCD_MAX_CLK % pixclock; | ||
| 1085 | pixclock -= diff; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | var->pixclock = KHZ2PICOS(pixclock/1000); | ||
| 1089 | #if 0 | ||
| 1090 | if (!panel_is_active(panel)) { | ||
| 1091 | int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1; | ||
| 1092 | |||
| 1093 | if (!panel_is_color(panel) | ||
| 1094 | && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) { | ||
| 1095 | /* STN 8bit mono panel support is up to 6MHz pixclock */ | ||
| 1096 | var->pixclock = KHZ2PICOS(6000); | ||
| 1097 | } else if (!pcd) { | ||
| 1098 | /* Other STN panel support is up to 12MHz */ | ||
| 1099 | var->pixclock = KHZ2PICOS(12000); | ||
| 1100 | } | ||
| 1101 | } | ||
| 1102 | #endif | ||
| 1103 | /* Set bitfield accordingly */ | ||
| 1104 | switch (var->bits_per_pixel) { | ||
| 1105 | case 16: | ||
| 1106 | { | ||
| 1107 | /* 16bpp True color. | ||
| 1108 | * These must be set to MATCH WINCTRL[FORM] */ | ||
| 1109 | int idx; | ||
| 1110 | idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; | ||
| 1111 | var->red = rgb_bitfields[idx][0]; | ||
| 1112 | var->green = rgb_bitfields[idx][1]; | ||
| 1113 | var->blue = rgb_bitfields[idx][2]; | ||
| 1114 | var->transp = rgb_bitfields[idx][3]; | ||
| 1115 | break; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | case 32: | ||
| 1119 | { | ||
| 1120 | /* 32bpp True color. | ||
| 1121 | * These must be set to MATCH WINCTRL[FORM] */ | ||
| 1122 | int idx; | ||
| 1123 | idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; | ||
| 1124 | var->red = rgb_bitfields[idx][0]; | ||
| 1125 | var->green = rgb_bitfields[idx][1]; | ||
| 1126 | var->blue = rgb_bitfields[idx][2]; | ||
| 1127 | var->transp = rgb_bitfields[idx][3]; | ||
| 1128 | break; | ||
| 1129 | } | ||
| 1130 | default: | ||
| 1131 | print_dbg("Unsupported depth %dbpp", var->bits_per_pixel); | ||
| 1132 | return -EINVAL; | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | return 0; | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | /* fb_set_par | ||
| 1139 | * Set hardware with var settings. This will enable the controller with a | ||
| 1140 | * specific mode, normally validated with the fb_check_var method | ||
| 1141 | */ | ||
| 1142 | static int au1200fb_fb_set_par(struct fb_info *fbi) | ||
| 1143 | { | ||
| 1144 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | ||
| 1145 | |||
| 1146 | au1200fb_update_fbinfo(fbi); | ||
| 1147 | au1200_setmode(fbdev); | ||
| 1148 | |||
| 1149 | return 0; | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | /* fb_setcolreg | ||
| 1153 | * Set color in LCD palette. | ||
| 1154 | */ | ||
| 1155 | static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
| 1156 | unsigned blue, unsigned transp, struct fb_info *fbi) | ||
| 1157 | { | ||
| 1158 | volatile u32 *palette = lcd->palette; | ||
| 1159 | u32 value; | ||
| 1160 | |||
| 1161 | if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1)) | ||
| 1162 | return -EINVAL; | ||
| 1163 | |||
| 1164 | if (fbi->var.grayscale) { | ||
| 1165 | /* Convert color to grayscale */ | ||
| 1166 | red = green = blue = | ||
| 1167 | (19595 * red + 38470 * green + 7471 * blue) >> 16; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) { | ||
| 1171 | /* Place color in the pseudopalette */ | ||
| 1172 | if (regno > 16) | ||
| 1173 | return -EINVAL; | ||
| 1174 | |||
| 1175 | palette = (u32*) fbi->pseudo_palette; | ||
| 1176 | |||
| 1177 | red >>= (16 - fbi->var.red.length); | ||
| 1178 | green >>= (16 - fbi->var.green.length); | ||
| 1179 | blue >>= (16 - fbi->var.blue.length); | ||
| 1180 | |||
| 1181 | value = (red << fbi->var.red.offset) | | ||
| 1182 | (green << fbi->var.green.offset)| | ||
| 1183 | (blue << fbi->var.blue.offset); | ||
| 1184 | value &= 0xFFFF; | ||
| 1185 | |||
| 1186 | } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) { | ||
| 1187 | /* COLOR TFT PALLETTIZED (use RGB 565) */ | ||
| 1188 | value = (red & 0xF800)|((green >> 5) & | ||
| 1189 | 0x07E0)|((blue >> 11) & 0x001F); | ||
| 1190 | value &= 0xFFFF; | ||
| 1191 | |||
| 1192 | } else if (0 /*panel_is_color(fbdev->panel)*/) { | ||
| 1193 | /* COLOR STN MODE */ | ||
| 1194 | value = 0x1234; | ||
| 1195 | value &= 0xFFF; | ||
| 1196 | } else { | ||
| 1197 | /* MONOCHROME MODE */ | ||
| 1198 | value = (green >> 12) & 0x000F; | ||
| 1199 | value &= 0xF; | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | palette[regno] = value; | ||
| 1203 | |||
| 1204 | return 0; | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | /* fb_blank | ||
| 1208 | * Blank the screen. Depending on the mode, the screen will be | ||
| 1209 | * activated with the backlight color, or desactivated | ||
| 1210 | */ | ||
| 1211 | static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi) | ||
| 1212 | { | ||
| 1213 | /* Short-circuit screen blanking */ | ||
| 1214 | if (noblanking) | ||
| 1215 | return 0; | ||
| 1216 | |||
| 1217 | switch (blank_mode) { | ||
| 1218 | |||
| 1219 | case FB_BLANK_UNBLANK: | ||
| 1220 | case FB_BLANK_NORMAL: | ||
| 1221 | /* printk("turn on panel\n"); */ | ||
| 1222 | au1200_setpanel(panel); | ||
| 1223 | break; | ||
| 1224 | case FB_BLANK_VSYNC_SUSPEND: | ||
| 1225 | case FB_BLANK_HSYNC_SUSPEND: | ||
| 1226 | case FB_BLANK_POWERDOWN: | ||
| 1227 | /* printk("turn off panel\n"); */ | ||
| 1228 | au1200_setpanel(NULL); | ||
| 1229 | break; | ||
| 1230 | default: | ||
| 1231 | break; | ||
| 1232 | |||
| 1233 | } | ||
| 1234 | |||
| 1235 | /* FB_BLANK_NORMAL is a soft blank */ | ||
| 1236 | return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0; | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | /* fb_mmap | ||
| 1240 | * Map video memory in user space. We don't use the generic fb_mmap | ||
| 1241 | * method mainly to allow the use of the TLB streaming flag (CCA=6) | ||
| 1242 | */ | ||
| 1243 | static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
| 1244 | |||
| 1245 | { | ||
| 1246 | unsigned int len; | ||
| 1247 | unsigned long start=0, off; | ||
| 1248 | struct au1200fb_device *fbdev = (struct au1200fb_device *) info; | ||
| 1249 | |||
| 1250 | #ifdef CONFIG_PM | ||
| 1251 | au1xxx_pm_access(LCD_pm_dev); | ||
| 1252 | #endif | ||
| 1253 | |||
| 1254 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { | ||
| 1255 | return -EINVAL; | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | start = fbdev->fb_phys & PAGE_MASK; | ||
| 1259 | len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); | ||
| 1260 | |||
| 1261 | off = vma->vm_pgoff << PAGE_SHIFT; | ||
| 1262 | |||
| 1263 | if ((vma->vm_end - vma->vm_start + off) > len) { | ||
| 1264 | return -EINVAL; | ||
| 1265 | } | ||
| 1266 | |||
| 1267 | off += start; | ||
| 1268 | vma->vm_pgoff = off >> PAGE_SHIFT; | ||
| 1269 | |||
| 1270 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
| 1271 | pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */ | ||
| 1272 | |||
| 1273 | vma->vm_flags |= VM_IO; | ||
| 1274 | |||
| 1275 | return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | ||
| 1276 | vma->vm_end - vma->vm_start, | ||
| 1277 | vma->vm_page_prot); | ||
| 1278 | |||
| 1279 | return 0; | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) | ||
| 1283 | { | ||
| 1284 | |||
| 1285 | unsigned int hi1, divider; | ||
| 1286 | |||
| 1287 | /* SCREEN_SIZE: user cannot reset size, must switch panel choice */ | ||
| 1288 | |||
| 1289 | if (pdata->flags & SCREEN_BACKCOLOR) | ||
| 1290 | lcd->backcolor = pdata->backcolor; | ||
| 1291 | |||
| 1292 | if (pdata->flags & SCREEN_BRIGHTNESS) { | ||
| 1293 | |||
| 1294 | // limit brightness pwm duty to >= 30/1600 | ||
| 1295 | if (pdata->brightness < 30) { | ||
| 1296 | pdata->brightness = 30; | ||
| 1297 | } | ||
| 1298 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
| 1299 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
| 1300 | hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8); | ||
| 1301 | lcd->pwmhi &= 0xFFFF; | ||
| 1302 | lcd->pwmhi |= (hi1 << 16); | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | if (pdata->flags & SCREEN_COLORKEY) | ||
| 1306 | lcd->colorkey = pdata->colorkey; | ||
| 1307 | |||
| 1308 | if (pdata->flags & SCREEN_MASK) | ||
| 1309 | lcd->colorkeymsk = pdata->mask; | ||
| 1310 | au_sync(); | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) | ||
| 1314 | { | ||
| 1315 | unsigned int hi1, divider; | ||
| 1316 | |||
| 1317 | pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1; | ||
| 1318 | pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1; | ||
| 1319 | |||
| 1320 | pdata->backcolor = lcd->backcolor; | ||
| 1321 | pdata->colorkey = lcd->colorkey; | ||
| 1322 | pdata->mask = lcd->colorkeymsk; | ||
| 1323 | |||
| 1324 | // brightness | ||
| 1325 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
| 1326 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
| 1327 | pdata->brightness = ((hi1 << 8) / divider) - 1; | ||
| 1328 | au_sync(); | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | static void set_window(unsigned int plane, | ||
| 1332 | struct au1200_lcd_window_regs_t *pdata) | ||
| 1333 | { | ||
| 1334 | unsigned int val, bpp; | ||
| 1335 | |||
| 1336 | /* Window control register 0 */ | ||
| 1337 | if (pdata->flags & WIN_POSITION) { | ||
| 1338 | val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX | | ||
| 1339 | LCD_WINCTRL0_OY); | ||
| 1340 | val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX); | ||
| 1341 | val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY); | ||
| 1342 | lcd->window[plane].winctrl0 = val; | ||
| 1343 | } | ||
| 1344 | if (pdata->flags & WIN_ALPHA_COLOR) { | ||
| 1345 | val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A); | ||
| 1346 | val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A); | ||
| 1347 | lcd->window[plane].winctrl0 = val; | ||
| 1348 | } | ||
| 1349 | if (pdata->flags & WIN_ALPHA_MODE) { | ||
| 1350 | val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN); | ||
| 1351 | val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN); | ||
| 1352 | lcd->window[plane].winctrl0 = val; | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | /* Window control register 1 */ | ||
| 1356 | if (pdata->flags & WIN_PRIORITY) { | ||
| 1357 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI); | ||
| 1358 | val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI); | ||
| 1359 | lcd->window[plane].winctrl1 = val; | ||
| 1360 | } | ||
| 1361 | if (pdata->flags & WIN_CHANNEL) { | ||
| 1362 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE); | ||
| 1363 | val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE); | ||
| 1364 | lcd->window[plane].winctrl1 = val; | ||
| 1365 | } | ||
| 1366 | if (pdata->flags & WIN_BUFFER_FORMAT) { | ||
| 1367 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM); | ||
| 1368 | val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM); | ||
| 1369 | lcd->window[plane].winctrl1 = val; | ||
| 1370 | } | ||
| 1371 | if (pdata->flags & WIN_COLOR_ORDER) { | ||
| 1372 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO); | ||
| 1373 | val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO); | ||
| 1374 | lcd->window[plane].winctrl1 = val; | ||
| 1375 | } | ||
| 1376 | if (pdata->flags & WIN_PIXEL_ORDER) { | ||
| 1377 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO); | ||
| 1378 | val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO); | ||
| 1379 | lcd->window[plane].winctrl1 = val; | ||
| 1380 | } | ||
| 1381 | if (pdata->flags & WIN_SIZE) { | ||
| 1382 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX | | ||
| 1383 | LCD_WINCTRL1_SZY); | ||
| 1384 | val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX); | ||
| 1385 | val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY); | ||
| 1386 | lcd->window[plane].winctrl1 = val; | ||
| 1387 | /* program buffer line width */ | ||
| 1388 | bpp = winbpp(val) / 8; | ||
| 1389 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX); | ||
| 1390 | val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX); | ||
| 1391 | lcd->window[plane].winctrl2 = val; | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | /* Window control register 2 */ | ||
| 1395 | if (pdata->flags & WIN_COLORKEY_MODE) { | ||
| 1396 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE); | ||
| 1397 | val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE); | ||
| 1398 | lcd->window[plane].winctrl2 = val; | ||
| 1399 | } | ||
| 1400 | if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) { | ||
| 1401 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM); | ||
| 1402 | val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM); | ||
| 1403 | lcd->window[plane].winctrl2 = val; | ||
| 1404 | } | ||
| 1405 | if (pdata->flags & WIN_RAM_ARRAY_MODE) { | ||
| 1406 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM); | ||
| 1407 | val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM); | ||
| 1408 | lcd->window[plane].winctrl2 = val; | ||
| 1409 | } | ||
| 1410 | |||
| 1411 | /* Buffer line width programmed with WIN_SIZE */ | ||
| 1412 | |||
| 1413 | if (pdata->flags & WIN_BUFFER_SCALE) { | ||
| 1414 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX | | ||
| 1415 | LCD_WINCTRL2_SCY); | ||
| 1416 | val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX); | ||
| 1417 | val |= ((pdata->ysize) & LCD_WINCTRL2_SCY); | ||
| 1418 | lcd->window[plane].winctrl2 = val; | ||
| 1419 | } | ||
| 1420 | |||
| 1421 | if (pdata->flags & WIN_ENABLE) { | ||
| 1422 | val = lcd->winenable; | ||
| 1423 | val &= ~(1<<plane); | ||
| 1424 | val |= (pdata->enable & 1) << plane; | ||
| 1425 | lcd->winenable = val; | ||
| 1426 | } | ||
| 1427 | au_sync(); | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | static void get_window(unsigned int plane, | ||
| 1431 | struct au1200_lcd_window_regs_t *pdata) | ||
| 1432 | { | ||
| 1433 | /* Window control register 0 */ | ||
| 1434 | pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21; | ||
| 1435 | pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10; | ||
| 1436 | pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2; | ||
| 1437 | pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1; | ||
| 1438 | |||
| 1439 | /* Window control register 1 */ | ||
| 1440 | pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30; | ||
| 1441 | pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29; | ||
| 1442 | pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25; | ||
| 1443 | pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24; | ||
| 1444 | pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22; | ||
| 1445 | pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1; | ||
| 1446 | pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1; | ||
| 1447 | |||
| 1448 | /* Window control register 2 */ | ||
| 1449 | pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24; | ||
| 1450 | pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23; | ||
| 1451 | pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21; | ||
| 1452 | |||
| 1453 | pdata->enable = (lcd->winenable >> plane) & 1; | ||
| 1454 | au_sync(); | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, | ||
| 1458 | unsigned long arg) | ||
| 1459 | { | ||
| 1460 | int plane; | ||
| 1461 | int val; | ||
| 1462 | |||
| 1463 | #ifdef CONFIG_PM | ||
| 1464 | au1xxx_pm_access(LCD_pm_dev); | ||
| 1465 | #endif | ||
| 1466 | |||
| 1467 | plane = fbinfo2index(info); | ||
| 1468 | print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); | ||
| 1469 | |||
| 1470 | if (cmd == AU1200_LCD_FB_IOCTL) { | ||
| 1471 | struct au1200_lcd_iodata_t iodata; | ||
| 1472 | |||
| 1473 | if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata))) | ||
| 1474 | return -EFAULT; | ||
| 1475 | |||
| 1476 | print_dbg("FB IOCTL called\n"); | ||
| 1477 | |||
| 1478 | switch (iodata.subcmd) { | ||
| 1479 | case AU1200_LCD_SET_SCREEN: | ||
| 1480 | print_dbg("AU1200_LCD_SET_SCREEN\n"); | ||
| 1481 | set_global(cmd, &iodata.global); | ||
| 1482 | break; | ||
| 1483 | |||
| 1484 | case AU1200_LCD_GET_SCREEN: | ||
| 1485 | print_dbg("AU1200_LCD_GET_SCREEN\n"); | ||
| 1486 | get_global(cmd, &iodata.global); | ||
| 1487 | break; | ||
| 1488 | |||
| 1489 | case AU1200_LCD_SET_WINDOW: | ||
| 1490 | print_dbg("AU1200_LCD_SET_WINDOW\n"); | ||
| 1491 | set_window(plane, &iodata.window); | ||
| 1492 | break; | ||
| 1493 | |||
| 1494 | case AU1200_LCD_GET_WINDOW: | ||
| 1495 | print_dbg("AU1200_LCD_GET_WINDOW\n"); | ||
| 1496 | get_window(plane, &iodata.window); | ||
| 1497 | break; | ||
| 1498 | |||
| 1499 | case AU1200_LCD_SET_PANEL: | ||
| 1500 | print_dbg("AU1200_LCD_SET_PANEL\n"); | ||
| 1501 | if ((iodata.global.panel_choice >= 0) && | ||
| 1502 | (iodata.global.panel_choice < | ||
| 1503 | NUM_PANELS)) | ||
| 1504 | { | ||
| 1505 | struct panel_settings *newpanel; | ||
| 1506 | panel_index = iodata.global.panel_choice; | ||
| 1507 | newpanel = &known_lcd_panels[panel_index]; | ||
| 1508 | au1200_setpanel(newpanel); | ||
| 1509 | } | ||
| 1510 | break; | ||
| 1511 | |||
| 1512 | case AU1200_LCD_GET_PANEL: | ||
| 1513 | print_dbg("AU1200_LCD_GET_PANEL\n"); | ||
| 1514 | iodata.global.panel_choice = panel_index; | ||
| 1515 | break; | ||
| 1516 | |||
| 1517 | default: | ||
| 1518 | return -EINVAL; | ||
| 1519 | } | ||
| 1520 | |||
| 1521 | val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata)); | ||
| 1522 | if (val) { | ||
| 1523 | print_dbg("error: could not copy %d bytes\n", val); | ||
| 1524 | return -EFAULT; | ||
| 1525 | } | ||
| 1526 | } | ||
| 1527 | |||
| 1528 | return 0; | ||
| 1529 | } | ||
| 1530 | |||
| 1531 | |||
| 1532 | static struct fb_ops au1200fb_fb_ops = { | ||
| 1533 | .owner = THIS_MODULE, | ||
| 1534 | .fb_check_var = au1200fb_fb_check_var, | ||
| 1535 | .fb_set_par = au1200fb_fb_set_par, | ||
| 1536 | .fb_setcolreg = au1200fb_fb_setcolreg, | ||
| 1537 | .fb_blank = au1200fb_fb_blank, | ||
| 1538 | .fb_fillrect = cfb_fillrect, | ||
| 1539 | .fb_copyarea = cfb_copyarea, | ||
| 1540 | .fb_imageblit = cfb_imageblit, | ||
| 1541 | .fb_sync = NULL, | ||
| 1542 | .fb_ioctl = au1200fb_ioctl, | ||
| 1543 | .fb_mmap = au1200fb_fb_mmap, | ||
| 1544 | }; | ||
| 1545 | |||
| 1546 | /*-------------------------------------------------------------------------*/ | ||
| 1547 | |||
| 1548 | static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs) | ||
| 1549 | { | ||
| 1550 | /* Nothing to do for now, just clear any pending interrupt */ | ||
| 1551 | lcd->intstatus = lcd->intstatus; | ||
| 1552 | au_sync(); | ||
| 1553 | |||
| 1554 | return IRQ_HANDLED; | ||
| 1555 | } | ||
| 1556 | |||
| 1557 | /*-------------------------------------------------------------------------*/ | ||
| 1558 | |||
| 1559 | /* AU1200 LCD device probe helpers */ | ||
| 1560 | |||
| 1561 | static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) | ||
| 1562 | { | ||
| 1563 | struct fb_info *fbi = &fbdev->fb_info; | ||
| 1564 | int bpp; | ||
| 1565 | |||
| 1566 | memset(fbi, 0, sizeof(struct fb_info)); | ||
| 1567 | fbi->fbops = &au1200fb_fb_ops; | ||
| 1568 | |||
| 1569 | bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); | ||
| 1570 | |||
| 1571 | /* Copy monitor specs from panel data */ | ||
| 1572 | /* fixme: we're setting up LCD controller windows, so these dont give a | ||
| 1573 | damn as to what the monitor specs are (the panel itself does, but that | ||
| 1574 | isnt done here...so maybe need a generic catchall monitor setting??? */ | ||
| 1575 | memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs)); | ||
| 1576 | |||
| 1577 | /* We first try the user mode passed in argument. If that failed, | ||
| 1578 | * or if no one has been specified, we default to the first mode of the | ||
| 1579 | * panel list. Note that after this call, var data will be set */ | ||
| 1580 | if (!fb_find_mode(&fbi->var, | ||
| 1581 | fbi, | ||
| 1582 | NULL, /* drv_info.opt_mode, */ | ||
| 1583 | fbi->monspecs.modedb, | ||
| 1584 | fbi->monspecs.modedb_len, | ||
| 1585 | fbi->monspecs.modedb, | ||
| 1586 | bpp)) { | ||
| 1587 | |||
| 1588 | print_err("Cannot find valid mode for panel %s", panel->name); | ||
| 1589 | return -EFAULT; | ||
| 1590 | } | ||
| 1591 | |||
| 1592 | fbi->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); | ||
| 1593 | if (!fbi->pseudo_palette) { | ||
| 1594 | return -ENOMEM; | ||
| 1595 | } | ||
| 1596 | memset(fbi->pseudo_palette, 0, sizeof(u32) * 16); | ||
| 1597 | |||
| 1598 | if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { | ||
| 1599 | print_err("Fail to allocate colormap (%d entries)", | ||
| 1600 | AU1200_LCD_NBR_PALETTE_ENTRIES); | ||
| 1601 | kfree(fbi->pseudo_palette); | ||
| 1602 | return -EFAULT; | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id)); | ||
| 1606 | fbi->fix.smem_start = fbdev->fb_phys; | ||
| 1607 | fbi->fix.smem_len = fbdev->fb_len; | ||
| 1608 | fbi->fix.type = FB_TYPE_PACKED_PIXELS; | ||
| 1609 | fbi->fix.xpanstep = 0; | ||
| 1610 | fbi->fix.ypanstep = 0; | ||
| 1611 | fbi->fix.mmio_start = 0; | ||
| 1612 | fbi->fix.mmio_len = 0; | ||
| 1613 | fbi->fix.accel = FB_ACCEL_NONE; | ||
| 1614 | |||
| 1615 | fbi->screen_base = (char __iomem *) fbdev->fb_mem; | ||
| 1616 | |||
| 1617 | au1200fb_update_fbinfo(fbi); | ||
| 1618 | |||
| 1619 | return 0; | ||
| 1620 | } | ||
| 1621 | |||
| 1622 | /*-------------------------------------------------------------------------*/ | ||
| 1623 | |||
| 1624 | /* AU1200 LCD controller device driver */ | ||
| 1625 | |||
| 1626 | static int au1200fb_drv_probe(struct device *dev) | ||
| 1627 | { | ||
| 1628 | struct au1200fb_device *fbdev; | ||
| 1629 | unsigned long page; | ||
| 1630 | int bpp, plane, ret; | ||
| 1631 | |||
| 1632 | if (!dev) | ||
| 1633 | return -EINVAL; | ||
| 1634 | |||
| 1635 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | ||
| 1636 | bpp = winbpp(win->w[plane].mode_winctrl1); | ||
| 1637 | if (win->w[plane].xres == 0) | ||
| 1638 | win->w[plane].xres = panel->Xres; | ||
| 1639 | if (win->w[plane].yres == 0) | ||
| 1640 | win->w[plane].yres = panel->Yres; | ||
| 1641 | |||
| 1642 | fbdev = &_au1200fb_devices[plane]; | ||
| 1643 | memset(fbdev, 0, sizeof(struct au1200fb_device)); | ||
| 1644 | fbdev->plane = plane; | ||
| 1645 | |||
| 1646 | /* Allocate the framebuffer to the maximum screen size */ | ||
| 1647 | fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; | ||
| 1648 | |||
| 1649 | fbdev->fb_mem = dma_alloc_noncoherent(dev, | ||
| 1650 | PAGE_ALIGN(fbdev->fb_len), | ||
| 1651 | &fbdev->fb_phys, GFP_KERNEL); | ||
| 1652 | if (!fbdev->fb_mem) { | ||
| 1653 | print_err("fail to allocate frambuffer (size: %dK))", | ||
| 1654 | fbdev->fb_len / 1024); | ||
| 1655 | return -ENOMEM; | ||
| 1656 | } | ||
| 1657 | |||
| 1658 | /* | ||
| 1659 | * Set page reserved so that mmap will work. This is necessary | ||
| 1660 | * since we'll be remapping normal memory. | ||
| 1661 | */ | ||
| 1662 | for (page = (unsigned long)fbdev->fb_phys; | ||
| 1663 | page < PAGE_ALIGN((unsigned long)fbdev->fb_phys + | ||
| 1664 | fbdev->fb_len); | ||
| 1665 | page += PAGE_SIZE) { | ||
| 1666 | SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */ | ||
| 1667 | } | ||
| 1668 | print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); | ||
| 1669 | print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); | ||
| 1670 | |||
| 1671 | /* Init FB data */ | ||
| 1672 | if ((ret = au1200fb_init_fbinfo(fbdev)) < 0) | ||
| 1673 | goto failed; | ||
| 1674 | |||
| 1675 | /* Register new framebuffer */ | ||
| 1676 | if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) { | ||
| 1677 | print_err("cannot register new framebuffer"); | ||
| 1678 | goto failed; | ||
| 1679 | } | ||
| 1680 | |||
| 1681 | au1200fb_fb_set_par(&fbdev->fb_info); | ||
| 1682 | |||
| 1683 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) | ||
| 1684 | if (plane == 0) | ||
| 1685 | if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) { | ||
| 1686 | /* Start display and show logo on boot */ | ||
| 1687 | fb_set_cmap(&fbdev->fb_info.cmap, | ||
| 1688 | &fbdev->fb_info); | ||
| 1689 | |||
| 1690 | fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR); | ||
| 1691 | } | ||
| 1692 | #endif | ||
| 1693 | } | ||
| 1694 | |||
| 1695 | /* Now hook interrupt too */ | ||
| 1696 | if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq, | ||
| 1697 | SA_INTERRUPT | SA_SHIRQ, "lcd", (void *)dev)) < 0) { | ||
| 1698 | print_err("fail to request interrupt line %d (err: %d)", | ||
| 1699 | AU1200_LCD_INT, ret); | ||
| 1700 | goto failed; | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | return 0; | ||
| 1704 | |||
| 1705 | failed: | ||
| 1706 | /* NOTE: This only does the current plane/window that failed; others are still active */ | ||
| 1707 | if (fbdev->fb_mem) | ||
| 1708 | dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), | ||
| 1709 | fbdev->fb_mem, fbdev->fb_phys); | ||
| 1710 | if (fbdev->fb_info.cmap.len != 0) | ||
| 1711 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | ||
| 1712 | if (fbdev->fb_info.pseudo_palette) | ||
| 1713 | kfree(fbdev->fb_info.pseudo_palette); | ||
| 1714 | if (plane == 0) | ||
| 1715 | free_irq(AU1200_LCD_INT, (void*)dev); | ||
| 1716 | return ret; | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | static int au1200fb_drv_remove(struct device *dev) | ||
| 1720 | { | ||
| 1721 | struct au1200fb_device *fbdev; | ||
| 1722 | int plane; | ||
| 1723 | |||
| 1724 | if (!dev) | ||
| 1725 | return -ENODEV; | ||
| 1726 | |||
| 1727 | /* Turn off the panel */ | ||
| 1728 | au1200_setpanel(NULL); | ||
| 1729 | |||
| 1730 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) | ||
| 1731 | { | ||
| 1732 | fbdev = &_au1200fb_devices[plane]; | ||
| 1733 | |||
| 1734 | /* Clean up all probe data */ | ||
| 1735 | unregister_framebuffer(&fbdev->fb_info); | ||
| 1736 | if (fbdev->fb_mem) | ||
| 1737 | dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), | ||
| 1738 | fbdev->fb_mem, fbdev->fb_phys); | ||
| 1739 | if (fbdev->fb_info.cmap.len != 0) | ||
| 1740 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | ||
| 1741 | if (fbdev->fb_info.pseudo_palette) | ||
| 1742 | kfree(fbdev->fb_info.pseudo_palette); | ||
| 1743 | } | ||
| 1744 | |||
| 1745 | free_irq(AU1200_LCD_INT, (void *)dev); | ||
| 1746 | |||
| 1747 | return 0; | ||
| 1748 | } | ||
| 1749 | |||
| 1750 | #ifdef CONFIG_PM | ||
| 1751 | static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level) | ||
| 1752 | { | ||
| 1753 | /* TODO */ | ||
| 1754 | return 0; | ||
| 1755 | } | ||
| 1756 | |||
| 1757 | static int au1200fb_drv_resume(struct device *dev, u32 level) | ||
| 1758 | { | ||
| 1759 | /* TODO */ | ||
| 1760 | return 0; | ||
| 1761 | } | ||
| 1762 | #endif /* CONFIG_PM */ | ||
| 1763 | |||
| 1764 | static struct device_driver au1200fb_driver = { | ||
| 1765 | .name = "au1200-lcd", | ||
| 1766 | .bus = &platform_bus_type, | ||
| 1767 | .probe = au1200fb_drv_probe, | ||
| 1768 | .remove = au1200fb_drv_remove, | ||
| 1769 | #ifdef CONFIG_PM | ||
| 1770 | .suspend = au1200fb_drv_suspend, | ||
| 1771 | .resume = au1200fb_drv_resume, | ||
| 1772 | #endif | ||
| 1773 | }; | ||
| 1774 | |||
| 1775 | /*-------------------------------------------------------------------------*/ | ||
| 1776 | |||
| 1777 | /* Kernel driver */ | ||
| 1778 | |||
| 1779 | static void au1200fb_setup(void) | ||
| 1780 | { | ||
| 1781 | char* options = NULL; | ||
| 1782 | char* this_opt; | ||
| 1783 | int num_panels = ARRAY_SIZE(known_lcd_panels); | ||
| 1784 | int panel_idx = -1; | ||
| 1785 | |||
| 1786 | fb_get_options(DRIVER_NAME, &options); | ||
| 1787 | |||
| 1788 | if (options) { | ||
| 1789 | while ((this_opt = strsep(&options,",")) != NULL) { | ||
| 1790 | /* Panel option - can be panel name, | ||
| 1791 | * "bs" for board-switch, or number/index */ | ||
| 1792 | if (!strncmp(this_opt, "panel:", 6)) { | ||
| 1793 | int i; | ||
| 1794 | long int li; | ||
| 1795 | char *endptr; | ||
| 1796 | this_opt += 6; | ||
| 1797 | /* First check for index, which allows | ||
| 1798 | * to short circuit this mess */ | ||
| 1799 | li = simple_strtol(this_opt, &endptr, 0); | ||
| 1800 | if (*endptr == '\0') { | ||
| 1801 | panel_idx = (int)li; | ||
| 1802 | } | ||
| 1803 | else if (strcmp(this_opt, "bs") == 0) { | ||
| 1804 | extern int board_au1200fb_panel(void); | ||
| 1805 | panel_idx = board_au1200fb_panel(); | ||
| 1806 | } | ||
| 1807 | |||
| 1808 | else | ||
| 1809 | for (i = 0; i < num_panels; i++) { | ||
| 1810 | if (!strcmp(this_opt, known_lcd_panels[i].name)) { | ||
| 1811 | panel_idx = i; | ||
| 1812 | break; | ||
| 1813 | } | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | if ((panel_idx < 0) || (panel_idx >= num_panels)) { | ||
| 1817 | print_warn("Panel %s not supported!", this_opt); | ||
| 1818 | } | ||
| 1819 | else | ||
| 1820 | panel_index = panel_idx; | ||
| 1821 | } | ||
| 1822 | |||
| 1823 | else if (strncmp(this_opt, "nohwcursor", 10) == 0) { | ||
| 1824 | nohwcursor = 1; | ||
| 1825 | } | ||
| 1826 | |||
| 1827 | /* Unsupported option */ | ||
| 1828 | else { | ||
| 1829 | print_warn("Unsupported option \"%s\"", this_opt); | ||
| 1830 | } | ||
| 1831 | } | ||
| 1832 | } | ||
| 1833 | } | ||
| 1834 | |||
| 1835 | #ifdef CONFIG_PM | ||
| 1836 | static int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | ||
| 1837 | au1xxx_request_t request, void *data) { | ||
| 1838 | int retval = -1; | ||
| 1839 | unsigned int d = 0; | ||
| 1840 | unsigned int brightness = 0; | ||
| 1841 | |||
| 1842 | if (request == AU1XXX_PM_SLEEP) { | ||
| 1843 | board_au1200fb_panel_shutdown(); | ||
| 1844 | } | ||
| 1845 | else if (request == AU1XXX_PM_WAKEUP) { | ||
| 1846 | if(dev->prev_state == SLEEP_STATE) | ||
| 1847 | { | ||
| 1848 | int plane; | ||
| 1849 | au1200_setpanel(panel); | ||
| 1850 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | ||
| 1851 | struct au1200fb_device *fbdev; | ||
| 1852 | fbdev = &_au1200fb_devices[plane]; | ||
| 1853 | au1200fb_fb_set_par(&fbdev->fb_info); | ||
| 1854 | } | ||
| 1855 | } | ||
| 1856 | |||
| 1857 | d = *((unsigned int*)data); | ||
| 1858 | if(d <=10) brightness = 26; | ||
| 1859 | else if(d<=20) brightness = 51; | ||
| 1860 | else if(d<=30) brightness = 77; | ||
| 1861 | else if(d<=40) brightness = 102; | ||
| 1862 | else if(d<=50) brightness = 128; | ||
| 1863 | else if(d<=60) brightness = 153; | ||
| 1864 | else if(d<=70) brightness = 179; | ||
| 1865 | else if(d<=80) brightness = 204; | ||
| 1866 | else if(d<=90) brightness = 230; | ||
| 1867 | else brightness = 255; | ||
| 1868 | set_brightness(brightness); | ||
| 1869 | } else if (request == AU1XXX_PM_GETSTATUS) { | ||
| 1870 | return dev->cur_state; | ||
| 1871 | } else if (request == AU1XXX_PM_ACCESS) { | ||
| 1872 | if (dev->cur_state != SLEEP_STATE) | ||
| 1873 | return retval; | ||
| 1874 | else { | ||
| 1875 | au1200_setpanel(panel); | ||
| 1876 | } | ||
| 1877 | } else if (request == AU1XXX_PM_IDLE) { | ||
| 1878 | } else if (request == AU1XXX_PM_CLEANUP) { | ||
| 1879 | } | ||
| 1880 | |||
| 1881 | return retval; | ||
| 1882 | } | ||
| 1883 | #endif | ||
| 1884 | |||
| 1885 | static int __init au1200fb_init(void) | ||
| 1886 | { | ||
| 1887 | print_info("" DRIVER_DESC ""); | ||
| 1888 | |||
| 1889 | /* Setup driver with options */ | ||
| 1890 | au1200fb_setup(); | ||
| 1891 | |||
| 1892 | /* Point to the panel selected */ | ||
| 1893 | panel = &known_lcd_panels[panel_index]; | ||
| 1894 | win = &windows[window_index]; | ||
| 1895 | |||
| 1896 | printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); | ||
| 1897 | printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); | ||
| 1898 | |||
| 1899 | /* Kickstart the panel, the framebuffers/windows come soon enough */ | ||
| 1900 | au1200_setpanel(panel); | ||
| 1901 | |||
| 1902 | #ifdef CONFIG_PM | ||
| 1903 | LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL); | ||
| 1904 | if ( LCD_pm_dev == NULL) | ||
| 1905 | printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n"); | ||
| 1906 | else | ||
| 1907 | printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); | ||
| 1908 | #endif | ||
| 1909 | |||
| 1910 | return driver_register(&au1200fb_driver); | ||
| 1911 | } | ||
| 1912 | |||
| 1913 | static void __exit au1200fb_cleanup(void) | ||
| 1914 | { | ||
| 1915 | driver_unregister(&au1200fb_driver); | ||
| 1916 | } | ||
| 1917 | |||
| 1918 | module_init(au1200fb_init); | ||
| 1919 | module_exit(au1200fb_cleanup); | ||
| 1920 | |||
| 1921 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 1922 | MODULE_LICENSE("GPL"); | ||
| 1923 | /* | ||
| 1924 | * BRIEF MODULE DESCRIPTION | ||
| 1925 | * Au1200 LCD Driver. | ||
| 1926 | * | ||
| 1927 | * Copyright 2004-2005 AMD | ||
| 1928 | * Author: AMD | ||
| 1929 | * | ||
| 1930 | * Based on: | ||
| 1931 | * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device | ||
| 1932 | * Created 28 Dec 1997 by Geert Uytterhoeven | ||
| 1933 | * | ||
| 1934 | * This program is free software; you can redistribute it and/or modify it | ||
| 1935 | * under the terms of the GNU General Public License as published by the | ||
| 1936 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 1937 | * option) any later version. | ||
| 1938 | * | ||
| 1939 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
| 1940 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
| 1941 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
| 1942 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 1943 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 1944 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
| 1945 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| 1946 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 1947 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 1948 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 1949 | * | ||
| 1950 | * You should have received a copy of the GNU General Public License along | ||
| 1951 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 1952 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 1953 | */ | ||
| 1954 | |||
| 1955 | #include <linux/module.h> | ||
| 1956 | #include <linux/platform_device.h> | ||
| 1957 | #include <linux/kernel.h> | ||
| 1958 | #include <linux/errno.h> | ||
| 1959 | #include <linux/string.h> | ||
| 1960 | #include <linux/mm.h> | ||
| 1961 | #include <linux/fb.h> | ||
| 1962 | #include <linux/init.h> | ||
| 1963 | #include <linux/interrupt.h> | ||
| 1964 | #include <linux/ctype.h> | ||
| 1965 | #include <linux/dma-mapping.h> | ||
| 1966 | |||
| 1967 | #include <asm/mach-au1x00/au1000.h> | ||
| 1968 | #include "au1200fb.h" | ||
| 1969 | |||
| 1970 | #ifdef CONFIG_PM | ||
| 1971 | #include <asm/mach-au1x00/au1xxx_pm.h> | ||
| 1972 | #endif | ||
| 1973 | |||
| 1974 | #ifndef CONFIG_FB_AU1200_DEVS | ||
| 1975 | #define CONFIG_FB_AU1200_DEVS 4 | ||
| 1976 | #endif | ||
| 1977 | |||
| 1978 | #define DRIVER_NAME "au1200fb" | ||
| 1979 | #define DRIVER_DESC "LCD controller driver for AU1200 processors" | ||
| 1980 | |||
| 1981 | #define DEBUG 1 | ||
| 1982 | |||
| 1983 | #define print_err(f, arg...) printk(KERN_ERR DRIVER_NAME ": " f "\n", ## arg) | ||
| 1984 | #define print_warn(f, arg...) printk(KERN_WARNING DRIVER_NAME ": " f "\n", ## arg) | ||
| 1985 | #define print_info(f, arg...) printk(KERN_INFO DRIVER_NAME ": " f "\n", ## arg) | ||
| 1986 | |||
| 1987 | #if DEBUG | ||
| 1988 | #define print_dbg(f, arg...) printk(KERN_DEBUG __FILE__ ": " f "\n", ## arg) | ||
| 1989 | #else | ||
| 1990 | #define print_dbg(f, arg...) do {} while (0) | ||
| 1991 | #endif | ||
| 1992 | |||
| 1993 | |||
| 1994 | #define AU1200_LCD_FB_IOCTL 0x46FF | ||
| 1995 | |||
| 1996 | #define AU1200_LCD_SET_SCREEN 1 | ||
| 1997 | #define AU1200_LCD_GET_SCREEN 2 | ||
| 1998 | #define AU1200_LCD_SET_WINDOW 3 | ||
| 1999 | #define AU1200_LCD_GET_WINDOW 4 | ||
| 2000 | #define AU1200_LCD_SET_PANEL 5 | ||
| 2001 | #define AU1200_LCD_GET_PANEL 6 | ||
| 2002 | |||
| 2003 | #define SCREEN_SIZE (1<< 1) | ||
| 2004 | #define SCREEN_BACKCOLOR (1<< 2) | ||
| 2005 | #define SCREEN_BRIGHTNESS (1<< 3) | ||
| 2006 | #define SCREEN_COLORKEY (1<< 4) | ||
| 2007 | #define SCREEN_MASK (1<< 5) | ||
| 2008 | |||
| 2009 | struct au1200_lcd_global_regs_t { | ||
| 2010 | unsigned int flags; | ||
| 2011 | unsigned int xsize; | ||
| 2012 | unsigned int ysize; | ||
| 2013 | unsigned int backcolor; | ||
| 2014 | unsigned int brightness; | ||
| 2015 | unsigned int colorkey; | ||
| 2016 | unsigned int mask; | ||
| 2017 | unsigned int panel_choice; | ||
| 2018 | char panel_desc[80]; | ||
| 2019 | |||
| 2020 | }; | ||
| 2021 | |||
| 2022 | #define WIN_POSITION (1<< 0) | ||
| 2023 | #define WIN_ALPHA_COLOR (1<< 1) | ||
| 2024 | #define WIN_ALPHA_MODE (1<< 2) | ||
| 2025 | #define WIN_PRIORITY (1<< 3) | ||
| 2026 | #define WIN_CHANNEL (1<< 4) | ||
| 2027 | #define WIN_BUFFER_FORMAT (1<< 5) | ||
| 2028 | #define WIN_COLOR_ORDER (1<< 6) | ||
| 2029 | #define WIN_PIXEL_ORDER (1<< 7) | ||
| 2030 | #define WIN_SIZE (1<< 8) | ||
| 2031 | #define WIN_COLORKEY_MODE (1<< 9) | ||
| 2032 | #define WIN_DOUBLE_BUFFER_MODE (1<< 10) | ||
| 2033 | #define WIN_RAM_ARRAY_MODE (1<< 11) | ||
| 2034 | #define WIN_BUFFER_SCALE (1<< 12) | ||
| 2035 | #define WIN_ENABLE (1<< 13) | ||
| 2036 | |||
| 2037 | struct au1200_lcd_window_regs_t { | ||
| 2038 | unsigned int flags; | ||
| 2039 | unsigned int xpos; | ||
| 2040 | unsigned int ypos; | ||
| 2041 | unsigned int alpha_color; | ||
| 2042 | unsigned int alpha_mode; | ||
| 2043 | unsigned int priority; | ||
| 2044 | unsigned int channel; | ||
| 2045 | unsigned int buffer_format; | ||
| 2046 | unsigned int color_order; | ||
| 2047 | unsigned int pixel_order; | ||
| 2048 | unsigned int xsize; | ||
| 2049 | unsigned int ysize; | ||
| 2050 | unsigned int colorkey_mode; | ||
| 2051 | unsigned int double_buffer_mode; | ||
| 2052 | unsigned int ram_array_mode; | ||
| 2053 | unsigned int xscale; | ||
| 2054 | unsigned int yscale; | ||
| 2055 | unsigned int enable; | ||
| 2056 | }; | ||
| 2057 | |||
| 2058 | |||
| 2059 | struct au1200_lcd_iodata_t { | ||
| 2060 | unsigned int subcmd; | ||
| 2061 | struct au1200_lcd_global_regs_t global; | ||
| 2062 | struct au1200_lcd_window_regs_t window; | ||
| 2063 | }; | ||
| 2064 | |||
| 2065 | #if defined(__BIG_ENDIAN) | ||
| 2066 | #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_11 | ||
| 2067 | #else | ||
| 2068 | #define LCD_CONTROL_DEFAULT_PO LCD_CONTROL_PO_00 | ||
| 2069 | #endif | ||
| 2070 | #define LCD_CONTROL_DEFAULT_SBPPF LCD_CONTROL_SBPPF_565 | ||
| 2071 | |||
| 2072 | /* Private, per-framebuffer management information (independent of the panel itself) */ | ||
| 2073 | struct au1200fb_device { | ||
| 2074 | struct fb_info fb_info; /* FB driver info record */ | ||
| 2075 | |||
| 2076 | int plane; | ||
| 2077 | unsigned char* fb_mem; /* FrameBuffer memory map */ | ||
| 2078 | unsigned int fb_len; | ||
| 2079 | dma_addr_t fb_phys; | ||
| 2080 | }; | ||
| 2081 | |||
| 2082 | static struct au1200fb_device _au1200fb_devices[CONFIG_FB_AU1200_DEVS]; | ||
| 2083 | /********************************************************************/ | ||
| 2084 | |||
| 2085 | /* LCD controller restrictions */ | ||
| 2086 | #define AU1200_LCD_MAX_XRES 1280 | ||
| 2087 | #define AU1200_LCD_MAX_YRES 1024 | ||
| 2088 | #define AU1200_LCD_MAX_BPP 32 | ||
| 2089 | #define AU1200_LCD_MAX_CLK 96000000 /* fixme: this needs to go away ? */ | ||
| 2090 | #define AU1200_LCD_NBR_PALETTE_ENTRIES 256 | ||
| 2091 | |||
| 2092 | /* Default number of visible screen buffer to allocate */ | ||
| 2093 | #define AU1200FB_NBR_VIDEO_BUFFERS 1 | ||
| 2094 | |||
| 2095 | /********************************************************************/ | ||
| 2096 | |||
| 2097 | static struct au1200_lcd *lcd = (struct au1200_lcd *) AU1200_LCD_ADDR; | ||
| 2098 | static int window_index = 2; /* default is zero */ | ||
| 2099 | static int panel_index = 2; /* default is zero */ | ||
| 2100 | static struct window_settings *win; | ||
| 2101 | static struct panel_settings *panel; | ||
| 2102 | static int noblanking = 1; | ||
| 2103 | static int nohwcursor = 0; | ||
| 2104 | |||
| 2105 | struct window_settings { | ||
| 2106 | unsigned char name[64]; | ||
| 2107 | uint32 mode_backcolor; | ||
| 2108 | uint32 mode_colorkey; | ||
| 2109 | uint32 mode_colorkeymsk; | ||
| 2110 | struct { | ||
| 2111 | int xres; | ||
| 2112 | int yres; | ||
| 2113 | int xpos; | ||
| 2114 | int ypos; | ||
| 2115 | uint32 mode_winctrl1; /* winctrl1[FRM,CCO,PO,PIPE] */ | ||
| 2116 | uint32 mode_winenable; | ||
| 2117 | } w[4]; | ||
| 2118 | }; | ||
| 2119 | |||
| 2120 | #if defined(__BIG_ENDIAN) | ||
| 2121 | #define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_00 | ||
| 2122 | #else | ||
| 2123 | #define LCD_WINCTRL1_PO_16BPP LCD_WINCTRL1_PO_01 | ||
| 2124 | #endif | ||
| 2125 | |||
| 2126 | extern int board_au1200fb_panel_init (void); | ||
| 2127 | extern int board_au1200fb_panel_shutdown (void); | ||
| 2128 | |||
| 2129 | #ifdef CONFIG_PM | ||
| 2130 | int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | ||
| 2131 | au1xxx_request_t request, void *data); | ||
| 2132 | au1xxx_power_dev_t *LCD_pm_dev; | ||
| 2133 | #endif | ||
| 2134 | |||
| 2135 | /* | ||
| 2136 | * Default window configurations | ||
| 2137 | */ | ||
| 2138 | static struct window_settings windows[] = { | ||
| 2139 | { /* Index 0 */ | ||
| 2140 | "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", | ||
| 2141 | /* mode_backcolor */ 0x006600ff, | ||
| 2142 | /* mode_colorkey,msk*/ 0, 0, | ||
| 2143 | { | ||
| 2144 | { | ||
| 2145 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2146 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2147 | LCD_WINCTRL1_PO_16BPP, | ||
| 2148 | /* mode_winenable*/ LCD_WINENABLE_WEN0, | ||
| 2149 | }, | ||
| 2150 | { | ||
| 2151 | /* xres, yres, xpos, ypos */ 100, 100, 100, 100, | ||
| 2152 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2153 | LCD_WINCTRL1_PO_16BPP | | ||
| 2154 | LCD_WINCTRL1_PIPE, | ||
| 2155 | /* mode_winenable*/ LCD_WINENABLE_WEN1, | ||
| 2156 | }, | ||
| 2157 | { | ||
| 2158 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2159 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2160 | LCD_WINCTRL1_PO_16BPP, | ||
| 2161 | /* mode_winenable*/ 0, | ||
| 2162 | }, | ||
| 2163 | { | ||
| 2164 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2165 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2166 | LCD_WINCTRL1_PO_16BPP | | ||
| 2167 | LCD_WINCTRL1_PIPE, | ||
| 2168 | /* mode_winenable*/ 0, | ||
| 2169 | }, | ||
| 2170 | }, | ||
| 2171 | }, | ||
| 2172 | |||
| 2173 | { /* Index 1 */ | ||
| 2174 | "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", | ||
| 2175 | /* mode_backcolor */ 0x006600ff, | ||
| 2176 | /* mode_colorkey,msk*/ 0, 0, | ||
| 2177 | { | ||
| 2178 | { | ||
| 2179 | /* xres, yres, xpos, ypos */ 320, 240, 5, 5, | ||
| 2180 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_24BPP | | ||
| 2181 | LCD_WINCTRL1_PO_00, | ||
| 2182 | /* mode_winenable*/ LCD_WINENABLE_WEN0, | ||
| 2183 | }, | ||
| 2184 | { | ||
| 2185 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2186 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | ||
| 2187 | | LCD_WINCTRL1_PO_16BPP, | ||
| 2188 | /* mode_winenable*/ 0, | ||
| 2189 | }, | ||
| 2190 | { | ||
| 2191 | /* xres, yres, xpos, ypos */ 100, 100, 0, 0, | ||
| 2192 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2193 | LCD_WINCTRL1_PO_16BPP | | ||
| 2194 | LCD_WINCTRL1_PIPE, | ||
| 2195 | /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, | ||
| 2196 | }, | ||
| 2197 | { | ||
| 2198 | /* xres, yres, xpos, ypos */ 200, 25, 0, 0, | ||
| 2199 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2200 | LCD_WINCTRL1_PO_16BPP | | ||
| 2201 | LCD_WINCTRL1_PIPE, | ||
| 2202 | /* mode_winenable*/ 0, | ||
| 2203 | }, | ||
| 2204 | }, | ||
| 2205 | }, | ||
| 2206 | { /* Index 2 */ | ||
| 2207 | "0-FS gfx, 1-video, 2-ovly gfx, 3-ovly gfx", | ||
| 2208 | /* mode_backcolor */ 0x006600ff, | ||
| 2209 | /* mode_colorkey,msk*/ 0, 0, | ||
| 2210 | { | ||
| 2211 | { | ||
| 2212 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2213 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2214 | LCD_WINCTRL1_PO_16BPP, | ||
| 2215 | /* mode_winenable*/ LCD_WINENABLE_WEN0, | ||
| 2216 | }, | ||
| 2217 | { | ||
| 2218 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2219 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2220 | LCD_WINCTRL1_PO_16BPP, | ||
| 2221 | /* mode_winenable*/ 0, | ||
| 2222 | }, | ||
| 2223 | { | ||
| 2224 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2225 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_32BPP | | ||
| 2226 | LCD_WINCTRL1_PO_00|LCD_WINCTRL1_PIPE, | ||
| 2227 | /* mode_winenable*/ 0/*LCD_WINENABLE_WEN2*/, | ||
| 2228 | }, | ||
| 2229 | { | ||
| 2230 | /* xres, yres, xpos, ypos */ 0, 0, 0, 0, | ||
| 2231 | /* mode_winctrl1 */ LCD_WINCTRL1_FRM_16BPP565 | | ||
| 2232 | LCD_WINCTRL1_PO_16BPP | | ||
| 2233 | LCD_WINCTRL1_PIPE, | ||
| 2234 | /* mode_winenable*/ 0, | ||
| 2235 | }, | ||
| 2236 | }, | ||
| 2237 | }, | ||
| 2238 | /* Need VGA 640 @ 24bpp, @ 32bpp */ | ||
| 2239 | /* Need VGA 800 @ 24bpp, @ 32bpp */ | ||
| 2240 | /* Need VGA 1024 @ 24bpp, @ 32bpp */ | ||
| 2241 | }; | ||
| 2242 | |||
| 2243 | /* | ||
| 2244 | * Controller configurations for various panels. | ||
| 2245 | */ | ||
| 2246 | |||
| 2247 | struct panel_settings | ||
| 2248 | { | ||
| 2249 | const char name[25]; /* Full name <vendor>_<model> */ | ||
| 2250 | |||
| 2251 | struct fb_monspecs monspecs; /* FB monitor specs */ | ||
| 2252 | |||
| 2253 | /* panel timings */ | ||
| 2254 | uint32 mode_screen; | ||
| 2255 | uint32 mode_horztiming; | ||
| 2256 | uint32 mode_verttiming; | ||
| 2257 | uint32 mode_clkcontrol; | ||
| 2258 | uint32 mode_pwmdiv; | ||
| 2259 | uint32 mode_pwmhi; | ||
| 2260 | uint32 mode_outmask; | ||
| 2261 | uint32 mode_fifoctrl; | ||
| 2262 | uint32 mode_toyclksrc; | ||
| 2263 | uint32 mode_backlight; | ||
| 2264 | uint32 mode_auxpll; | ||
| 2265 | int (*device_init)(void); | ||
| 2266 | int (*device_shutdown)(void); | ||
| 2267 | #define Xres min_xres | ||
| 2268 | #define Yres min_yres | ||
| 2269 | u32 min_xres; /* Minimum horizontal resolution */ | ||
| 2270 | u32 max_xres; /* Maximum horizontal resolution */ | ||
| 2271 | u32 min_yres; /* Minimum vertical resolution */ | ||
| 2272 | u32 max_yres; /* Maximum vertical resolution */ | ||
| 2273 | }; | ||
| 2274 | |||
| 2275 | /********************************************************************/ | ||
| 2276 | /* fixme: Maybe a modedb for the CRT ? otherwise panels should be as-is */ | ||
| 2277 | |||
| 2278 | /* List of panels known to work with the AU1200 LCD controller. | ||
| 2279 | * To add a new panel, enter the same specifications as the | ||
| 2280 | * Generic_TFT one, and MAKE SURE that it doesn't conflicts | ||
| 2281 | * with the controller restrictions. Restrictions are: | ||
| 2282 | * | ||
| 2283 | * STN color panels: max_bpp <= 12 | ||
| 2284 | * STN mono panels: max_bpp <= 4 | ||
| 2285 | * TFT panels: max_bpp <= 16 | ||
| 2286 | * max_xres <= 800 | ||
| 2287 | * max_yres <= 600 | ||
| 2288 | */ | ||
| 2289 | static struct panel_settings known_lcd_panels[] = | ||
| 2290 | { | ||
| 2291 | [0] = { /* QVGA 320x240 H:33.3kHz V:110Hz */ | ||
| 2292 | .name = "QVGA_320x240", | ||
| 2293 | .monspecs = { | ||
| 2294 | .modedb = NULL, | ||
| 2295 | .modedb_len = 0, | ||
| 2296 | .hfmin = 30000, | ||
| 2297 | .hfmax = 70000, | ||
| 2298 | .vfmin = 60, | ||
| 2299 | .vfmax = 60, | ||
| 2300 | .dclkmin = 6000000, | ||
| 2301 | .dclkmax = 28000000, | ||
| 2302 | .input = FB_DISP_RGB, | ||
| 2303 | }, | ||
| 2304 | .mode_screen = LCD_SCREEN_SX_N(320) | | ||
| 2305 | LCD_SCREEN_SY_N(240), | ||
| 2306 | .mode_horztiming = 0x00c4623b, | ||
| 2307 | .mode_verttiming = 0x00502814, | ||
| 2308 | .mode_clkcontrol = 0x00020002, /* /4=24Mhz */ | ||
| 2309 | .mode_pwmdiv = 0x00000000, | ||
| 2310 | .mode_pwmhi = 0x00000000, | ||
| 2311 | .mode_outmask = 0x00FFFFFF, | ||
| 2312 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2313 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2314 | .mode_backlight = 0x00000000, | ||
| 2315 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2316 | .device_init = NULL, | ||
| 2317 | .device_shutdown = NULL, | ||
| 2318 | 320, 320, | ||
| 2319 | 240, 240, | ||
| 2320 | }, | ||
| 2321 | |||
| 2322 | [1] = { /* VGA 640x480 H:30.3kHz V:58Hz */ | ||
| 2323 | .name = "VGA_640x480", | ||
| 2324 | .monspecs = { | ||
| 2325 | .modedb = NULL, | ||
| 2326 | .modedb_len = 0, | ||
| 2327 | .hfmin = 30000, | ||
| 2328 | .hfmax = 70000, | ||
| 2329 | .vfmin = 60, | ||
| 2330 | .vfmax = 60, | ||
| 2331 | .dclkmin = 6000000, | ||
| 2332 | .dclkmax = 28000000, | ||
| 2333 | .input = FB_DISP_RGB, | ||
| 2334 | }, | ||
| 2335 | .mode_screen = 0x13f9df80, | ||
| 2336 | .mode_horztiming = 0x003c5859, | ||
| 2337 | .mode_verttiming = 0x00741201, | ||
| 2338 | .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ | ||
| 2339 | .mode_pwmdiv = 0x00000000, | ||
| 2340 | .mode_pwmhi = 0x00000000, | ||
| 2341 | .mode_outmask = 0x00FFFFFF, | ||
| 2342 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2343 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2344 | .mode_backlight = 0x00000000, | ||
| 2345 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2346 | .device_init = NULL, | ||
| 2347 | .device_shutdown = NULL, | ||
| 2348 | 640, 480, | ||
| 2349 | 640, 480, | ||
| 2350 | }, | ||
| 2351 | |||
| 2352 | [2] = { /* SVGA 800x600 H:46.1kHz V:69Hz */ | ||
| 2353 | .name = "SVGA_800x600", | ||
| 2354 | .monspecs = { | ||
| 2355 | .modedb = NULL, | ||
| 2356 | .modedb_len = 0, | ||
| 2357 | .hfmin = 30000, | ||
| 2358 | .hfmax = 70000, | ||
| 2359 | .vfmin = 60, | ||
| 2360 | .vfmax = 60, | ||
| 2361 | .dclkmin = 6000000, | ||
| 2362 | .dclkmax = 28000000, | ||
| 2363 | .input = FB_DISP_RGB, | ||
| 2364 | }, | ||
| 2365 | .mode_screen = 0x18fa5780, | ||
| 2366 | .mode_horztiming = 0x00dc7e77, | ||
| 2367 | .mode_verttiming = 0x00584805, | ||
| 2368 | .mode_clkcontrol = 0x00020000, /* /2=48Mhz */ | ||
| 2369 | .mode_pwmdiv = 0x00000000, | ||
| 2370 | .mode_pwmhi = 0x00000000, | ||
| 2371 | .mode_outmask = 0x00FFFFFF, | ||
| 2372 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2373 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2374 | .mode_backlight = 0x00000000, | ||
| 2375 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2376 | .device_init = NULL, | ||
| 2377 | .device_shutdown = NULL, | ||
| 2378 | 800, 800, | ||
| 2379 | 600, 600, | ||
| 2380 | }, | ||
| 2381 | |||
| 2382 | [3] = { /* XVGA 1024x768 H:56.2kHz V:70Hz */ | ||
| 2383 | .name = "XVGA_1024x768", | ||
| 2384 | .monspecs = { | ||
| 2385 | .modedb = NULL, | ||
| 2386 | .modedb_len = 0, | ||
| 2387 | .hfmin = 30000, | ||
| 2388 | .hfmax = 70000, | ||
| 2389 | .vfmin = 60, | ||
| 2390 | .vfmax = 60, | ||
| 2391 | .dclkmin = 6000000, | ||
| 2392 | .dclkmax = 28000000, | ||
| 2393 | .input = FB_DISP_RGB, | ||
| 2394 | }, | ||
| 2395 | .mode_screen = 0x1ffaff80, | ||
| 2396 | .mode_horztiming = 0x007d0e57, | ||
| 2397 | .mode_verttiming = 0x00740a01, | ||
| 2398 | .mode_clkcontrol = 0x000A0000, /* /1 */ | ||
| 2399 | .mode_pwmdiv = 0x00000000, | ||
| 2400 | .mode_pwmhi = 0x00000000, | ||
| 2401 | .mode_outmask = 0x00FFFFFF, | ||
| 2402 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2403 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2404 | .mode_backlight = 0x00000000, | ||
| 2405 | .mode_auxpll = 6, /* 72MHz AUXPLL */ | ||
| 2406 | .device_init = NULL, | ||
| 2407 | .device_shutdown = NULL, | ||
| 2408 | 1024, 1024, | ||
| 2409 | 768, 768, | ||
| 2410 | }, | ||
| 2411 | |||
| 2412 | [4] = { /* XVGA XVGA 1280x1024 H:68.5kHz V:65Hz */ | ||
| 2413 | .name = "XVGA_1280x1024", | ||
| 2414 | .monspecs = { | ||
| 2415 | .modedb = NULL, | ||
| 2416 | .modedb_len = 0, | ||
| 2417 | .hfmin = 30000, | ||
| 2418 | .hfmax = 70000, | ||
| 2419 | .vfmin = 60, | ||
| 2420 | .vfmax = 60, | ||
| 2421 | .dclkmin = 6000000, | ||
| 2422 | .dclkmax = 28000000, | ||
| 2423 | .input = FB_DISP_RGB, | ||
| 2424 | }, | ||
| 2425 | .mode_screen = 0x27fbff80, | ||
| 2426 | .mode_horztiming = 0x00cdb2c7, | ||
| 2427 | .mode_verttiming = 0x00600002, | ||
| 2428 | .mode_clkcontrol = 0x000A0000, /* /1 */ | ||
| 2429 | .mode_pwmdiv = 0x00000000, | ||
| 2430 | .mode_pwmhi = 0x00000000, | ||
| 2431 | .mode_outmask = 0x00FFFFFF, | ||
| 2432 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2433 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2434 | .mode_backlight = 0x00000000, | ||
| 2435 | .mode_auxpll = 10, /* 120MHz AUXPLL */ | ||
| 2436 | .device_init = NULL, | ||
| 2437 | .device_shutdown = NULL, | ||
| 2438 | 1280, 1280, | ||
| 2439 | 1024, 1024, | ||
| 2440 | }, | ||
| 2441 | |||
| 2442 | [5] = { /* Samsung 1024x768 TFT */ | ||
| 2443 | .name = "Samsung_1024x768_TFT", | ||
| 2444 | .monspecs = { | ||
| 2445 | .modedb = NULL, | ||
| 2446 | .modedb_len = 0, | ||
| 2447 | .hfmin = 30000, | ||
| 2448 | .hfmax = 70000, | ||
| 2449 | .vfmin = 60, | ||
| 2450 | .vfmax = 60, | ||
| 2451 | .dclkmin = 6000000, | ||
| 2452 | .dclkmax = 28000000, | ||
| 2453 | .input = FB_DISP_RGB, | ||
| 2454 | }, | ||
| 2455 | .mode_screen = 0x1ffaff80, | ||
| 2456 | .mode_horztiming = 0x018cc677, | ||
| 2457 | .mode_verttiming = 0x00241217, | ||
| 2458 | .mode_clkcontrol = 0x00000000, /* SCB 0x1 /4=24Mhz */ | ||
| 2459 | .mode_pwmdiv = 0x8000063f, /* SCB 0x0 */ | ||
| 2460 | .mode_pwmhi = 0x03400000, /* SCB 0x0 */ | ||
| 2461 | .mode_outmask = 0x00FFFFFF, | ||
| 2462 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2463 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2464 | .mode_backlight = 0x00000000, | ||
| 2465 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2466 | .device_init = board_au1200fb_panel_init, | ||
| 2467 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 2468 | 1024, 1024, | ||
| 2469 | 768, 768, | ||
| 2470 | }, | ||
| 2471 | |||
| 2472 | [6] = { /* Toshiba 640x480 TFT */ | ||
| 2473 | .name = "Toshiba_640x480_TFT", | ||
| 2474 | .monspecs = { | ||
| 2475 | .modedb = NULL, | ||
| 2476 | .modedb_len = 0, | ||
| 2477 | .hfmin = 30000, | ||
| 2478 | .hfmax = 70000, | ||
| 2479 | .vfmin = 60, | ||
| 2480 | .vfmax = 60, | ||
| 2481 | .dclkmin = 6000000, | ||
| 2482 | .dclkmax = 28000000, | ||
| 2483 | .input = FB_DISP_RGB, | ||
| 2484 | }, | ||
| 2485 | .mode_screen = LCD_SCREEN_SX_N(640) | | ||
| 2486 | LCD_SCREEN_SY_N(480), | ||
| 2487 | .mode_horztiming = LCD_HORZTIMING_HPW_N(96) | | ||
| 2488 | LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(51), | ||
| 2489 | .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | | ||
| 2490 | LCD_VERTTIMING_VND1_N(11) | LCD_VERTTIMING_VND2_N(32), | ||
| 2491 | .mode_clkcontrol = 0x00000000, /* /4=24Mhz */ | ||
| 2492 | .mode_pwmdiv = 0x8000063f, | ||
| 2493 | .mode_pwmhi = 0x03400000, | ||
| 2494 | .mode_outmask = 0x00fcfcfc, | ||
| 2495 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2496 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2497 | .mode_backlight = 0x00000000, | ||
| 2498 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2499 | .device_init = board_au1200fb_panel_init, | ||
| 2500 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 2501 | 640, 480, | ||
| 2502 | 640, 480, | ||
| 2503 | }, | ||
| 2504 | |||
| 2505 | [7] = { /* Sharp 320x240 TFT */ | ||
| 2506 | .name = "Sharp_320x240_TFT", | ||
| 2507 | .monspecs = { | ||
| 2508 | .modedb = NULL, | ||
| 2509 | .modedb_len = 0, | ||
| 2510 | .hfmin = 12500, | ||
| 2511 | .hfmax = 20000, | ||
| 2512 | .vfmin = 38, | ||
| 2513 | .vfmax = 81, | ||
| 2514 | .dclkmin = 4500000, | ||
| 2515 | .dclkmax = 6800000, | ||
| 2516 | .input = FB_DISP_RGB, | ||
| 2517 | }, | ||
| 2518 | .mode_screen = LCD_SCREEN_SX_N(320) | | ||
| 2519 | LCD_SCREEN_SY_N(240), | ||
| 2520 | .mode_horztiming = LCD_HORZTIMING_HPW_N(60) | | ||
| 2521 | LCD_HORZTIMING_HND1_N(13) | LCD_HORZTIMING_HND2_N(2), | ||
| 2522 | .mode_verttiming = LCD_VERTTIMING_VPW_N(2) | | ||
| 2523 | LCD_VERTTIMING_VND1_N(2) | LCD_VERTTIMING_VND2_N(5), | ||
| 2524 | .mode_clkcontrol = LCD_CLKCONTROL_PCD_N(7), /*16=6Mhz*/ | ||
| 2525 | .mode_pwmdiv = 0x8000063f, | ||
| 2526 | .mode_pwmhi = 0x03400000, | ||
| 2527 | .mode_outmask = 0x00fcfcfc, | ||
| 2528 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2529 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2530 | .mode_backlight = 0x00000000, | ||
| 2531 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2532 | .device_init = board_au1200fb_panel_init, | ||
| 2533 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 2534 | 320, 320, | ||
| 2535 | 240, 240, | ||
| 2536 | }, | ||
| 2537 | |||
| 2538 | [8] = { /* Toppoly TD070WGCB2 7" 856x480 TFT */ | ||
| 2539 | .name = "Toppoly_TD070WGCB2", | ||
| 2540 | .monspecs = { | ||
| 2541 | .modedb = NULL, | ||
| 2542 | .modedb_len = 0, | ||
| 2543 | .hfmin = 30000, | ||
| 2544 | .hfmax = 70000, | ||
| 2545 | .vfmin = 60, | ||
| 2546 | .vfmax = 60, | ||
| 2547 | .dclkmin = 6000000, | ||
| 2548 | .dclkmax = 28000000, | ||
| 2549 | .input = FB_DISP_RGB, | ||
| 2550 | }, | ||
| 2551 | .mode_screen = LCD_SCREEN_SX_N(856) | | ||
| 2552 | LCD_SCREEN_SY_N(480), | ||
| 2553 | .mode_horztiming = LCD_HORZTIMING_HND2_N(43) | | ||
| 2554 | LCD_HORZTIMING_HND1_N(43) | LCD_HORZTIMING_HPW_N(114), | ||
| 2555 | .mode_verttiming = LCD_VERTTIMING_VND2_N(20) | | ||
| 2556 | LCD_VERTTIMING_VND1_N(21) | LCD_VERTTIMING_VPW_N(4), | ||
| 2557 | .mode_clkcontrol = 0x00020001, /* /4=24Mhz */ | ||
| 2558 | .mode_pwmdiv = 0x8000063f, | ||
| 2559 | .mode_pwmhi = 0x03400000, | ||
| 2560 | .mode_outmask = 0x00fcfcfc, | ||
| 2561 | .mode_fifoctrl = 0x2f2f2f2f, | ||
| 2562 | .mode_toyclksrc = 0x00000004, /* AUXPLL directly */ | ||
| 2563 | .mode_backlight = 0x00000000, | ||
| 2564 | .mode_auxpll = 8, /* 96MHz AUXPLL */ | ||
| 2565 | .device_init = board_au1200fb_panel_init, | ||
| 2566 | .device_shutdown = board_au1200fb_panel_shutdown, | ||
| 2567 | 856, 856, | ||
| 2568 | 480, 480, | ||
| 2569 | }, | ||
| 2570 | }; | ||
| 2571 | |||
| 2572 | #define NUM_PANELS (ARRAY_SIZE(known_lcd_panels)) | ||
| 2573 | |||
| 2574 | /********************************************************************/ | ||
| 2575 | |||
| 2576 | #ifdef CONFIG_PM | ||
| 2577 | static int set_brightness(unsigned int brightness) | ||
| 2578 | { | ||
| 2579 | unsigned int hi1, divider; | ||
| 2580 | |||
| 2581 | /* limit brightness pwm duty to >= 30/1600 */ | ||
| 2582 | if (brightness < 30) { | ||
| 2583 | brightness = 30; | ||
| 2584 | } | ||
| 2585 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
| 2586 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
| 2587 | hi1 = (((brightness & 0xFF) + 1) * divider >> 8); | ||
| 2588 | lcd->pwmhi &= 0xFFFF; | ||
| 2589 | lcd->pwmhi |= (hi1 << 16); | ||
| 2590 | |||
| 2591 | return brightness; | ||
| 2592 | } | ||
| 2593 | #endif /* CONFIG_PM */ | ||
| 2594 | |||
| 2595 | static int winbpp (unsigned int winctrl1) | ||
| 2596 | { | ||
| 2597 | int bits = 0; | ||
| 2598 | |||
| 2599 | /* how many bits are needed for each pixel format */ | ||
| 2600 | switch (winctrl1 & LCD_WINCTRL1_FRM) { | ||
| 2601 | case LCD_WINCTRL1_FRM_1BPP: | ||
| 2602 | bits = 1; | ||
| 2603 | break; | ||
| 2604 | case LCD_WINCTRL1_FRM_2BPP: | ||
| 2605 | bits = 2; | ||
| 2606 | break; | ||
| 2607 | case LCD_WINCTRL1_FRM_4BPP: | ||
| 2608 | bits = 4; | ||
| 2609 | break; | ||
| 2610 | case LCD_WINCTRL1_FRM_8BPP: | ||
| 2611 | bits = 8; | ||
| 2612 | break; | ||
| 2613 | case LCD_WINCTRL1_FRM_12BPP: | ||
| 2614 | case LCD_WINCTRL1_FRM_16BPP655: | ||
| 2615 | case LCD_WINCTRL1_FRM_16BPP565: | ||
| 2616 | case LCD_WINCTRL1_FRM_16BPP556: | ||
| 2617 | case LCD_WINCTRL1_FRM_16BPPI1555: | ||
| 2618 | case LCD_WINCTRL1_FRM_16BPPI5551: | ||
| 2619 | case LCD_WINCTRL1_FRM_16BPPA1555: | ||
| 2620 | case LCD_WINCTRL1_FRM_16BPPA5551: | ||
| 2621 | bits = 16; | ||
| 2622 | break; | ||
| 2623 | case LCD_WINCTRL1_FRM_24BPP: | ||
| 2624 | case LCD_WINCTRL1_FRM_32BPP: | ||
| 2625 | bits = 32; | ||
| 2626 | break; | ||
| 2627 | } | ||
| 2628 | |||
| 2629 | return bits; | ||
| 2630 | } | ||
| 2631 | |||
| 2632 | static int fbinfo2index (struct fb_info *fb_info) | ||
| 2633 | { | ||
| 2634 | int i; | ||
| 2635 | |||
| 2636 | for (i = 0; i < CONFIG_FB_AU1200_DEVS; ++i) { | ||
| 2637 | if (fb_info == (struct fb_info *)(&_au1200fb_devices[i].fb_info)) | ||
| 2638 | return i; | ||
| 2639 | } | ||
| 2640 | printk("au1200fb: ERROR: fbinfo2index failed!\n"); | ||
| 2641 | return -1; | ||
| 2642 | } | ||
| 2643 | |||
| 2644 | static int au1200_setlocation (struct au1200fb_device *fbdev, int plane, | ||
| 2645 | int xpos, int ypos) | ||
| 2646 | { | ||
| 2647 | uint32 winctrl0, winctrl1, winenable, fb_offset = 0; | ||
| 2648 | int xsz, ysz; | ||
| 2649 | |||
| 2650 | /* FIX!!! NOT CHECKING FOR COMPLETE OFFSCREEN YET */ | ||
| 2651 | |||
| 2652 | winctrl0 = lcd->window[plane].winctrl0; | ||
| 2653 | winctrl1 = lcd->window[plane].winctrl1; | ||
| 2654 | winctrl0 &= (LCD_WINCTRL0_A | LCD_WINCTRL0_AEN); | ||
| 2655 | winctrl1 &= ~(LCD_WINCTRL1_SZX | LCD_WINCTRL1_SZY); | ||
| 2656 | |||
| 2657 | /* Check for off-screen adjustments */ | ||
| 2658 | xsz = win->w[plane].xres; | ||
| 2659 | ysz = win->w[plane].yres; | ||
| 2660 | if ((xpos + win->w[plane].xres) > panel->Xres) { | ||
| 2661 | /* Off-screen to the right */ | ||
| 2662 | xsz = panel->Xres - xpos; /* off by 1 ??? */ | ||
| 2663 | /*printk("off screen right\n");*/ | ||
| 2664 | } | ||
| 2665 | |||
| 2666 | if ((ypos + win->w[plane].yres) > panel->Yres) { | ||
| 2667 | /* Off-screen to the bottom */ | ||
| 2668 | ysz = panel->Yres - ypos; /* off by 1 ??? */ | ||
| 2669 | /*printk("off screen bottom\n");*/ | ||
| 2670 | } | ||
| 2671 | |||
| 2672 | if (xpos < 0) { | ||
| 2673 | /* Off-screen to the left */ | ||
| 2674 | xsz = win->w[plane].xres + xpos; | ||
| 2675 | fb_offset += (((0 - xpos) * winbpp(lcd->window[plane].winctrl1))/8); | ||
| 2676 | xpos = 0; | ||
| 2677 | /*printk("off screen left\n");*/ | ||
| 2678 | } | ||
| 2679 | |||
| 2680 | if (ypos < 0) { | ||
| 2681 | /* Off-screen to the top */ | ||
| 2682 | ysz = win->w[plane].yres + ypos; | ||
| 2683 | /* fixme: fb_offset += ((0-ypos)*fb_pars[plane].line_length); */ | ||
| 2684 | ypos = 0; | ||
| 2685 | /*printk("off screen top\n");*/ | ||
| 2686 | } | ||
| 2687 | |||
| 2688 | /* record settings */ | ||
| 2689 | win->w[plane].xpos = xpos; | ||
| 2690 | win->w[plane].ypos = ypos; | ||
| 2691 | |||
| 2692 | xsz -= 1; | ||
| 2693 | ysz -= 1; | ||
| 2694 | winctrl0 |= (xpos << 21); | ||
| 2695 | winctrl0 |= (ypos << 10); | ||
| 2696 | winctrl1 |= (xsz << 11); | ||
| 2697 | winctrl1 |= (ysz << 0); | ||
| 2698 | |||
| 2699 | /* Disable the window while making changes, then restore WINEN */ | ||
| 2700 | winenable = lcd->winenable & (1 << plane); | ||
| 2701 | au_sync(); | ||
| 2702 | lcd->winenable &= ~(1 << plane); | ||
| 2703 | lcd->window[plane].winctrl0 = winctrl0; | ||
| 2704 | lcd->window[plane].winctrl1 = winctrl1; | ||
| 2705 | lcd->window[plane].winbuf0 = | ||
| 2706 | lcd->window[plane].winbuf1 = fbdev->fb_phys; | ||
| 2707 | lcd->window[plane].winbufctrl = 0; /* select winbuf0 */ | ||
| 2708 | lcd->winenable |= winenable; | ||
| 2709 | au_sync(); | ||
| 2710 | |||
| 2711 | return 0; | ||
| 2712 | } | ||
| 2713 | |||
| 2714 | static void au1200_setpanel (struct panel_settings *newpanel) | ||
| 2715 | { | ||
| 2716 | /* | ||
| 2717 | * Perform global setup/init of LCD controller | ||
| 2718 | */ | ||
| 2719 | uint32 winenable; | ||
| 2720 | |||
| 2721 | /* Make sure all windows disabled */ | ||
| 2722 | winenable = lcd->winenable; | ||
| 2723 | lcd->winenable = 0; | ||
| 2724 | au_sync(); | ||
| 2725 | /* | ||
| 2726 | * Ensure everything is disabled before reconfiguring | ||
| 2727 | */ | ||
| 2728 | if (lcd->screen & LCD_SCREEN_SEN) { | ||
| 2729 | /* Wait for vertical sync period */ | ||
| 2730 | lcd->intstatus = LCD_INT_SS; | ||
| 2731 | while ((lcd->intstatus & LCD_INT_SS) == 0) { | ||
| 2732 | au_sync(); | ||
| 2733 | } | ||
| 2734 | |||
| 2735 | lcd->screen &= ~LCD_SCREEN_SEN; /*disable the controller*/ | ||
| 2736 | |||
| 2737 | do { | ||
| 2738 | lcd->intstatus = lcd->intstatus; /*clear interrupts*/ | ||
| 2739 | au_sync(); | ||
| 2740 | /*wait for controller to shut down*/ | ||
| 2741 | } while ((lcd->intstatus & LCD_INT_SD) == 0); | ||
| 2742 | |||
| 2743 | /* Call shutdown of current panel (if up) */ | ||
| 2744 | /* this must occur last, because if an external clock is driving | ||
| 2745 | the controller, the clock cannot be turned off before first | ||
| 2746 | shutting down the controller. | ||
| 2747 | */ | ||
| 2748 | if (panel->device_shutdown != NULL) | ||
| 2749 | panel->device_shutdown(); | ||
| 2750 | } | ||
| 2751 | |||
| 2752 | /* Newpanel == NULL indicates a shutdown operation only */ | ||
| 2753 | if (newpanel == NULL) | ||
| 2754 | return; | ||
| 2755 | |||
| 2756 | panel = newpanel; | ||
| 2757 | |||
| 2758 | printk("Panel(%s), %dx%d\n", panel->name, panel->Xres, panel->Yres); | ||
| 2759 | |||
| 2760 | /* | ||
| 2761 | * Setup clocking if internal LCD clock source (assumes sys_auxpll valid) | ||
| 2762 | */ | ||
| 2763 | if (!(panel->mode_clkcontrol & LCD_CLKCONTROL_EXT)) | ||
| 2764 | { | ||
| 2765 | uint32 sys_clksrc; | ||
| 2766 | au_writel(panel->mode_auxpll, SYS_AUXPLL); | ||
| 2767 | sys_clksrc = au_readl(SYS_CLKSRC) & ~0x0000001f; | ||
| 2768 | sys_clksrc |= panel->mode_toyclksrc; | ||
| 2769 | au_writel(sys_clksrc, SYS_CLKSRC); | ||
| 2770 | } | ||
| 2771 | |||
| 2772 | /* | ||
| 2773 | * Configure panel timings | ||
| 2774 | */ | ||
| 2775 | lcd->screen = panel->mode_screen; | ||
| 2776 | lcd->horztiming = panel->mode_horztiming; | ||
| 2777 | lcd->verttiming = panel->mode_verttiming; | ||
| 2778 | lcd->clkcontrol = panel->mode_clkcontrol; | ||
| 2779 | lcd->pwmdiv = panel->mode_pwmdiv; | ||
| 2780 | lcd->pwmhi = panel->mode_pwmhi; | ||
| 2781 | lcd->outmask = panel->mode_outmask; | ||
| 2782 | lcd->fifoctrl = panel->mode_fifoctrl; | ||
| 2783 | au_sync(); | ||
| 2784 | |||
| 2785 | /* fixme: Check window settings to make sure still valid | ||
| 2786 | * for new geometry */ | ||
| 2787 | #if 0 | ||
| 2788 | au1200_setlocation(fbdev, 0, win->w[0].xpos, win->w[0].ypos); | ||
| 2789 | au1200_setlocation(fbdev, 1, win->w[1].xpos, win->w[1].ypos); | ||
| 2790 | au1200_setlocation(fbdev, 2, win->w[2].xpos, win->w[2].ypos); | ||
| 2791 | au1200_setlocation(fbdev, 3, win->w[3].xpos, win->w[3].ypos); | ||
| 2792 | #endif | ||
| 2793 | lcd->winenable = winenable; | ||
| 2794 | |||
| 2795 | /* | ||
| 2796 | * Re-enable screen now that it is configured | ||
| 2797 | */ | ||
| 2798 | lcd->screen |= LCD_SCREEN_SEN; | ||
| 2799 | au_sync(); | ||
| 2800 | |||
| 2801 | /* Call init of panel */ | ||
| 2802 | if (panel->device_init != NULL) panel->device_init(); | ||
| 2803 | |||
| 2804 | /* FIX!!!! not appropriate on panel change!!! Global setup/init */ | ||
| 2805 | lcd->intenable = 0; | ||
| 2806 | lcd->intstatus = ~0; | ||
| 2807 | lcd->backcolor = win->mode_backcolor; | ||
| 2808 | |||
| 2809 | /* Setup Color Key - FIX!!! */ | ||
| 2810 | lcd->colorkey = win->mode_colorkey; | ||
| 2811 | lcd->colorkeymsk = win->mode_colorkeymsk; | ||
| 2812 | |||
| 2813 | /* Setup HWCursor - FIX!!! Need to support this eventually */ | ||
| 2814 | lcd->hwc.cursorctrl = 0; | ||
| 2815 | lcd->hwc.cursorpos = 0; | ||
| 2816 | lcd->hwc.cursorcolor0 = 0; | ||
| 2817 | lcd->hwc.cursorcolor1 = 0; | ||
| 2818 | lcd->hwc.cursorcolor2 = 0; | ||
| 2819 | lcd->hwc.cursorcolor3 = 0; | ||
| 2820 | |||
| 2821 | |||
| 2822 | #if 0 | ||
| 2823 | #define D(X) printk("%25s: %08X\n", #X, X) | ||
| 2824 | D(lcd->screen); | ||
| 2825 | D(lcd->horztiming); | ||
| 2826 | D(lcd->verttiming); | ||
| 2827 | D(lcd->clkcontrol); | ||
| 2828 | D(lcd->pwmdiv); | ||
| 2829 | D(lcd->pwmhi); | ||
| 2830 | D(lcd->outmask); | ||
| 2831 | D(lcd->fifoctrl); | ||
| 2832 | D(lcd->window[0].winctrl0); | ||
| 2833 | D(lcd->window[0].winctrl1); | ||
| 2834 | D(lcd->window[0].winctrl2); | ||
| 2835 | D(lcd->window[0].winbuf0); | ||
| 2836 | D(lcd->window[0].winbuf1); | ||
| 2837 | D(lcd->window[0].winbufctrl); | ||
| 2838 | D(lcd->window[1].winctrl0); | ||
| 2839 | D(lcd->window[1].winctrl1); | ||
| 2840 | D(lcd->window[1].winctrl2); | ||
| 2841 | D(lcd->window[1].winbuf0); | ||
| 2842 | D(lcd->window[1].winbuf1); | ||
| 2843 | D(lcd->window[1].winbufctrl); | ||
| 2844 | D(lcd->window[2].winctrl0); | ||
| 2845 | D(lcd->window[2].winctrl1); | ||
| 2846 | D(lcd->window[2].winctrl2); | ||
| 2847 | D(lcd->window[2].winbuf0); | ||
| 2848 | D(lcd->window[2].winbuf1); | ||
| 2849 | D(lcd->window[2].winbufctrl); | ||
| 2850 | D(lcd->window[3].winctrl0); | ||
| 2851 | D(lcd->window[3].winctrl1); | ||
| 2852 | D(lcd->window[3].winctrl2); | ||
| 2853 | D(lcd->window[3].winbuf0); | ||
| 2854 | D(lcd->window[3].winbuf1); | ||
| 2855 | D(lcd->window[3].winbufctrl); | ||
| 2856 | D(lcd->winenable); | ||
| 2857 | D(lcd->intenable); | ||
| 2858 | D(lcd->intstatus); | ||
| 2859 | D(lcd->backcolor); | ||
| 2860 | D(lcd->winenable); | ||
| 2861 | D(lcd->colorkey); | ||
| 2862 | D(lcd->colorkeymsk); | ||
| 2863 | D(lcd->hwc.cursorctrl); | ||
| 2864 | D(lcd->hwc.cursorpos); | ||
| 2865 | D(lcd->hwc.cursorcolor0); | ||
| 2866 | D(lcd->hwc.cursorcolor1); | ||
| 2867 | D(lcd->hwc.cursorcolor2); | ||
| 2868 | D(lcd->hwc.cursorcolor3); | ||
| 2869 | #endif | ||
| 2870 | } | ||
| 2871 | |||
| 2872 | static void au1200_setmode(struct au1200fb_device *fbdev) | ||
| 2873 | { | ||
| 2874 | int plane = fbdev->plane; | ||
| 2875 | /* Window/plane setup */ | ||
| 2876 | lcd->window[plane].winctrl1 = ( 0 | ||
| 2877 | | LCD_WINCTRL1_PRI_N(plane) | ||
| 2878 | | win->w[plane].mode_winctrl1 /* FRM,CCO,PO,PIPE */ | ||
| 2879 | ) ; | ||
| 2880 | |||
| 2881 | au1200_setlocation(fbdev, plane, win->w[plane].xpos, win->w[plane].ypos); | ||
| 2882 | |||
| 2883 | lcd->window[plane].winctrl2 = ( 0 | ||
| 2884 | | LCD_WINCTRL2_CKMODE_00 | ||
| 2885 | | LCD_WINCTRL2_DBM | ||
| 2886 | | LCD_WINCTRL2_BX_N( fbdev->fb_info.fix.line_length) | ||
| 2887 | | LCD_WINCTRL2_SCX_1 | ||
| 2888 | | LCD_WINCTRL2_SCY_1 | ||
| 2889 | ) ; | ||
| 2890 | lcd->winenable |= win->w[plane].mode_winenable; | ||
| 2891 | au_sync(); | ||
| 2892 | } | ||
| 2893 | |||
| 2894 | |||
| 2895 | /* Inline helpers */ | ||
| 2896 | |||
| 2897 | /*#define panel_is_dual(panel) ((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ | ||
| 2898 | /*#define panel_is_active(panel)((panel->mode_screen & LCD_SCREEN_PT) == LCD_SCREEN_PT_010)*/ | ||
| 2899 | |||
| 2900 | #define panel_is_color(panel) ((panel->mode_screen & LCD_SCREEN_PT) <= LCD_SCREEN_PT_CDSTN) | ||
| 2901 | |||
| 2902 | /* Bitfields format supported by the controller. */ | ||
| 2903 | static struct fb_bitfield rgb_bitfields[][4] = { | ||
| 2904 | /* Red, Green, Blue, Transp */ | ||
| 2905 | [LCD_WINCTRL1_FRM_16BPP655 >> 25] = | ||
| 2906 | { { 10, 6, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
| 2907 | |||
| 2908 | [LCD_WINCTRL1_FRM_16BPP565 >> 25] = | ||
| 2909 | { { 11, 5, 0 }, { 5, 6, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
| 2910 | |||
| 2911 | [LCD_WINCTRL1_FRM_16BPP556 >> 25] = | ||
| 2912 | { { 11, 5, 0 }, { 6, 5, 0 }, { 0, 6, 0 }, { 0, 0, 0 } }, | ||
| 2913 | |||
| 2914 | [LCD_WINCTRL1_FRM_16BPPI1555 >> 25] = | ||
| 2915 | { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 0, 0, 0 } }, | ||
| 2916 | |||
| 2917 | [LCD_WINCTRL1_FRM_16BPPI5551 >> 25] = | ||
| 2918 | { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 0, 0 } }, | ||
| 2919 | |||
| 2920 | [LCD_WINCTRL1_FRM_16BPPA1555 >> 25] = | ||
| 2921 | { { 10, 5, 0 }, { 5, 5, 0 }, { 0, 5, 0 }, { 15, 1, 0 } }, | ||
| 2922 | |||
| 2923 | [LCD_WINCTRL1_FRM_16BPPA5551 >> 25] = | ||
| 2924 | { { 11, 5, 0 }, { 6, 5, 0 }, { 1, 5, 0 }, { 0, 1, 0 } }, | ||
| 2925 | |||
| 2926 | [LCD_WINCTRL1_FRM_24BPP >> 25] = | ||
| 2927 | { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 0, 0, 0 } }, | ||
| 2928 | |||
| 2929 | [LCD_WINCTRL1_FRM_32BPP >> 25] = | ||
| 2930 | { { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 0, 0 } }, | ||
| 2931 | }; | ||
| 2932 | |||
| 2933 | /*-------------------------------------------------------------------------*/ | ||
| 2934 | |||
| 2935 | /* Helpers */ | ||
| 2936 | |||
| 2937 | static void au1200fb_update_fbinfo(struct fb_info *fbi) | ||
| 2938 | { | ||
| 2939 | /* FIX!!!! This also needs to take the window pixel format into account!!! */ | ||
| 2940 | |||
| 2941 | /* Update var-dependent FB info */ | ||
| 2942 | if (panel_is_color(panel)) { | ||
| 2943 | if (fbi->var.bits_per_pixel <= 8) { | ||
| 2944 | /* palettized */ | ||
| 2945 | fbi->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
| 2946 | fbi->fix.line_length = fbi->var.xres_virtual / | ||
| 2947 | (8/fbi->var.bits_per_pixel); | ||
| 2948 | } else { | ||
| 2949 | /* non-palettized */ | ||
| 2950 | fbi->fix.visual = FB_VISUAL_TRUECOLOR; | ||
| 2951 | fbi->fix.line_length = fbi->var.xres_virtual * (fbi->var.bits_per_pixel / 8); | ||
| 2952 | } | ||
| 2953 | } else { | ||
| 2954 | /* mono FIX!!! mono 8 and 4 bits */ | ||
| 2955 | fbi->fix.visual = FB_VISUAL_MONO10; | ||
| 2956 | fbi->fix.line_length = fbi->var.xres_virtual / 8; | ||
| 2957 | } | ||
| 2958 | |||
| 2959 | fbi->screen_size = fbi->fix.line_length * fbi->var.yres_virtual; | ||
| 2960 | print_dbg("line length: %d\n", fbi->fix.line_length); | ||
| 2961 | print_dbg("bits_per_pixel: %d\n", fbi->var.bits_per_pixel); | ||
| 2962 | } | ||
| 2963 | |||
| 2964 | /*-------------------------------------------------------------------------*/ | ||
| 2965 | |||
| 2966 | /* AU1200 framebuffer driver */ | ||
| 2967 | |||
| 2968 | /* fb_check_var | ||
| 2969 | * Validate var settings with hardware restrictions and modify it if necessary | ||
| 2970 | */ | ||
| 2971 | static int au1200fb_fb_check_var(struct fb_var_screeninfo *var, | ||
| 2972 | struct fb_info *fbi) | ||
| 2973 | { | ||
| 2974 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | ||
| 2975 | u32 pixclock; | ||
| 2976 | int screen_size, plane; | ||
| 2977 | |||
| 2978 | plane = fbdev->plane; | ||
| 2979 | |||
| 2980 | /* Make sure that the mode respect all LCD controller and | ||
| 2981 | * panel restrictions. */ | ||
| 2982 | var->xres = win->w[plane].xres; | ||
| 2983 | var->yres = win->w[plane].yres; | ||
| 2984 | |||
| 2985 | /* No need for virtual resolution support */ | ||
| 2986 | var->xres_virtual = var->xres; | ||
| 2987 | var->yres_virtual = var->yres; | ||
| 2988 | |||
| 2989 | var->bits_per_pixel = winbpp(win->w[plane].mode_winctrl1); | ||
| 2990 | |||
| 2991 | screen_size = var->xres_virtual * var->yres_virtual; | ||
| 2992 | if (var->bits_per_pixel > 8) screen_size *= (var->bits_per_pixel / 8); | ||
| 2993 | else screen_size /= (8/var->bits_per_pixel); | ||
| 2994 | |||
| 2995 | if (fbdev->fb_len < screen_size) | ||
| 2996 | return -EINVAL; /* Virtual screen is to big, abort */ | ||
| 2997 | |||
| 2998 | /* FIX!!!! what are the implicaitons of ignoring this for windows ??? */ | ||
| 2999 | /* The max LCD clock is fixed to 48MHz (value of AUX_CLK). The pixel | ||
| 3000 | * clock can only be obtain by dividing this value by an even integer. | ||
| 3001 | * Fallback to a slower pixel clock if necessary. */ | ||
| 3002 | pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin); | ||
| 3003 | pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2)); | ||
| 3004 | |||
| 3005 | if (AU1200_LCD_MAX_CLK % pixclock) { | ||
| 3006 | int diff = AU1200_LCD_MAX_CLK % pixclock; | ||
| 3007 | pixclock -= diff; | ||
| 3008 | } | ||
| 3009 | |||
| 3010 | var->pixclock = KHZ2PICOS(pixclock/1000); | ||
| 3011 | #if 0 | ||
| 3012 | if (!panel_is_active(panel)) { | ||
| 3013 | int pcd = AU1200_LCD_MAX_CLK / (pixclock * 2) - 1; | ||
| 3014 | |||
| 3015 | if (!panel_is_color(panel) | ||
| 3016 | && (panel->control_base & LCD_CONTROL_MPI) && (pcd < 3)) { | ||
| 3017 | /* STN 8bit mono panel support is up to 6MHz pixclock */ | ||
| 3018 | var->pixclock = KHZ2PICOS(6000); | ||
| 3019 | } else if (!pcd) { | ||
| 3020 | /* Other STN panel support is up to 12MHz */ | ||
| 3021 | var->pixclock = KHZ2PICOS(12000); | ||
| 3022 | } | ||
| 3023 | } | ||
| 3024 | #endif | ||
| 3025 | /* Set bitfield accordingly */ | ||
| 3026 | switch (var->bits_per_pixel) { | ||
| 3027 | case 16: | ||
| 3028 | { | ||
| 3029 | /* 16bpp True color. | ||
| 3030 | * These must be set to MATCH WINCTRL[FORM] */ | ||
| 3031 | int idx; | ||
| 3032 | idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; | ||
| 3033 | var->red = rgb_bitfields[idx][0]; | ||
| 3034 | var->green = rgb_bitfields[idx][1]; | ||
| 3035 | var->blue = rgb_bitfields[idx][2]; | ||
| 3036 | var->transp = rgb_bitfields[idx][3]; | ||
| 3037 | break; | ||
| 3038 | } | ||
| 3039 | |||
| 3040 | case 32: | ||
| 3041 | { | ||
| 3042 | /* 32bpp True color. | ||
| 3043 | * These must be set to MATCH WINCTRL[FORM] */ | ||
| 3044 | int idx; | ||
| 3045 | idx = (win->w[0].mode_winctrl1 & LCD_WINCTRL1_FRM) >> 25; | ||
| 3046 | var->red = rgb_bitfields[idx][0]; | ||
| 3047 | var->green = rgb_bitfields[idx][1]; | ||
| 3048 | var->blue = rgb_bitfields[idx][2]; | ||
| 3049 | var->transp = rgb_bitfields[idx][3]; | ||
| 3050 | break; | ||
| 3051 | } | ||
| 3052 | default: | ||
| 3053 | print_dbg("Unsupported depth %dbpp", var->bits_per_pixel); | ||
| 3054 | return -EINVAL; | ||
| 3055 | } | ||
| 3056 | |||
| 3057 | return 0; | ||
| 3058 | } | ||
| 3059 | |||
| 3060 | /* fb_set_par | ||
| 3061 | * Set hardware with var settings. This will enable the controller with a | ||
| 3062 | * specific mode, normally validated with the fb_check_var method | ||
| 3063 | */ | ||
| 3064 | static int au1200fb_fb_set_par(struct fb_info *fbi) | ||
| 3065 | { | ||
| 3066 | struct au1200fb_device *fbdev = (struct au1200fb_device *)fbi; | ||
| 3067 | |||
| 3068 | au1200fb_update_fbinfo(fbi); | ||
| 3069 | au1200_setmode(fbdev); | ||
| 3070 | |||
| 3071 | return 0; | ||
| 3072 | } | ||
| 3073 | |||
| 3074 | /* fb_setcolreg | ||
| 3075 | * Set color in LCD palette. | ||
| 3076 | */ | ||
| 3077 | static int au1200fb_fb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
| 3078 | unsigned blue, unsigned transp, struct fb_info *fbi) | ||
| 3079 | { | ||
| 3080 | volatile u32 *palette = lcd->palette; | ||
| 3081 | u32 value; | ||
| 3082 | |||
| 3083 | if (regno > (AU1200_LCD_NBR_PALETTE_ENTRIES - 1)) | ||
| 3084 | return -EINVAL; | ||
| 3085 | |||
| 3086 | if (fbi->var.grayscale) { | ||
| 3087 | /* Convert color to grayscale */ | ||
| 3088 | red = green = blue = | ||
| 3089 | (19595 * red + 38470 * green + 7471 * blue) >> 16; | ||
| 3090 | } | ||
| 3091 | |||
| 3092 | if (fbi->fix.visual == FB_VISUAL_TRUECOLOR) { | ||
| 3093 | /* Place color in the pseudopalette */ | ||
| 3094 | if (regno > 16) | ||
| 3095 | return -EINVAL; | ||
| 3096 | |||
| 3097 | palette = (u32*) fbi->pseudo_palette; | ||
| 3098 | |||
| 3099 | red >>= (16 - fbi->var.red.length); | ||
| 3100 | green >>= (16 - fbi->var.green.length); | ||
| 3101 | blue >>= (16 - fbi->var.blue.length); | ||
| 3102 | |||
| 3103 | value = (red << fbi->var.red.offset) | | ||
| 3104 | (green << fbi->var.green.offset)| | ||
| 3105 | (blue << fbi->var.blue.offset); | ||
| 3106 | value &= 0xFFFF; | ||
| 3107 | |||
| 3108 | } else if (1 /*FIX!!! panel_is_active(fbdev->panel)*/) { | ||
| 3109 | /* COLOR TFT PALLETTIZED (use RGB 565) */ | ||
| 3110 | value = (red & 0xF800)|((green >> 5) & | ||
| 3111 | 0x07E0)|((blue >> 11) & 0x001F); | ||
| 3112 | value &= 0xFFFF; | ||
| 3113 | |||
| 3114 | } else if (0 /*panel_is_color(fbdev->panel)*/) { | ||
| 3115 | /* COLOR STN MODE */ | ||
| 3116 | value = 0x1234; | ||
| 3117 | value &= 0xFFF; | ||
| 3118 | } else { | ||
| 3119 | /* MONOCHROME MODE */ | ||
| 3120 | value = (green >> 12) & 0x000F; | ||
| 3121 | value &= 0xF; | ||
| 3122 | } | ||
| 3123 | |||
| 3124 | palette[regno] = value; | ||
| 3125 | |||
| 3126 | return 0; | ||
| 3127 | } | ||
| 3128 | |||
| 3129 | /* fb_blank | ||
| 3130 | * Blank the screen. Depending on the mode, the screen will be | ||
| 3131 | * activated with the backlight color, or desactivated | ||
| 3132 | */ | ||
| 3133 | static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi) | ||
| 3134 | { | ||
| 3135 | /* Short-circuit screen blanking */ | ||
| 3136 | if (noblanking) | ||
| 3137 | return 0; | ||
| 3138 | |||
| 3139 | switch (blank_mode) { | ||
| 3140 | |||
| 3141 | case FB_BLANK_UNBLANK: | ||
| 3142 | case FB_BLANK_NORMAL: | ||
| 3143 | /* printk("turn on panel\n"); */ | ||
| 3144 | au1200_setpanel(panel); | ||
| 3145 | break; | ||
| 3146 | case FB_BLANK_VSYNC_SUSPEND: | ||
| 3147 | case FB_BLANK_HSYNC_SUSPEND: | ||
| 3148 | case FB_BLANK_POWERDOWN: | ||
| 3149 | /* printk("turn off panel\n"); */ | ||
| 3150 | au1200_setpanel(NULL); | ||
| 3151 | break; | ||
| 3152 | default: | ||
| 3153 | break; | ||
| 3154 | |||
| 3155 | } | ||
| 3156 | |||
| 3157 | /* FB_BLANK_NORMAL is a soft blank */ | ||
| 3158 | return (blank_mode == FB_BLANK_NORMAL) ? -EINVAL : 0; | ||
| 3159 | } | ||
| 3160 | |||
| 3161 | /* fb_mmap | ||
| 3162 | * Map video memory in user space. We don't use the generic fb_mmap | ||
| 3163 | * method mainly to allow the use of the TLB streaming flag (CCA=6) | ||
| 3164 | */ | ||
| 3165 | static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
| 3166 | |||
| 3167 | { | ||
| 3168 | unsigned int len; | ||
| 3169 | unsigned long start=0, off; | ||
| 3170 | struct au1200fb_device *fbdev = (struct au1200fb_device *) info; | ||
| 3171 | |||
| 3172 | #ifdef CONFIG_PM | ||
| 3173 | au1xxx_pm_access(LCD_pm_dev); | ||
| 3174 | #endif | ||
| 3175 | |||
| 3176 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { | ||
| 3177 | return -EINVAL; | ||
| 3178 | } | ||
| 3179 | |||
| 3180 | start = fbdev->fb_phys & PAGE_MASK; | ||
| 3181 | len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); | ||
| 3182 | |||
| 3183 | off = vma->vm_pgoff << PAGE_SHIFT; | ||
| 3184 | |||
| 3185 | if ((vma->vm_end - vma->vm_start + off) > len) { | ||
| 3186 | return -EINVAL; | ||
| 3187 | } | ||
| 3188 | |||
| 3189 | off += start; | ||
| 3190 | vma->vm_pgoff = off >> PAGE_SHIFT; | ||
| 3191 | |||
| 3192 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
| 3193 | pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */ | ||
| 3194 | |||
| 3195 | vma->vm_flags |= VM_IO; | ||
| 3196 | |||
| 3197 | return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, | ||
| 3198 | vma->vm_end - vma->vm_start, | ||
| 3199 | vma->vm_page_prot); | ||
| 3200 | |||
| 3201 | return 0; | ||
| 3202 | } | ||
| 3203 | |||
| 3204 | static void set_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) | ||
| 3205 | { | ||
| 3206 | |||
| 3207 | unsigned int hi1, divider; | ||
| 3208 | |||
| 3209 | /* SCREEN_SIZE: user cannot reset size, must switch panel choice */ | ||
| 3210 | |||
| 3211 | if (pdata->flags & SCREEN_BACKCOLOR) | ||
| 3212 | lcd->backcolor = pdata->backcolor; | ||
| 3213 | |||
| 3214 | if (pdata->flags & SCREEN_BRIGHTNESS) { | ||
| 3215 | |||
| 3216 | // limit brightness pwm duty to >= 30/1600 | ||
| 3217 | if (pdata->brightness < 30) { | ||
| 3218 | pdata->brightness = 30; | ||
| 3219 | } | ||
| 3220 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
| 3221 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
| 3222 | hi1 = (((pdata->brightness & 0xFF)+1) * divider >> 8); | ||
| 3223 | lcd->pwmhi &= 0xFFFF; | ||
| 3224 | lcd->pwmhi |= (hi1 << 16); | ||
| 3225 | } | ||
| 3226 | |||
| 3227 | if (pdata->flags & SCREEN_COLORKEY) | ||
| 3228 | lcd->colorkey = pdata->colorkey; | ||
| 3229 | |||
| 3230 | if (pdata->flags & SCREEN_MASK) | ||
| 3231 | lcd->colorkeymsk = pdata->mask; | ||
| 3232 | au_sync(); | ||
| 3233 | } | ||
| 3234 | |||
| 3235 | static void get_global(u_int cmd, struct au1200_lcd_global_regs_t *pdata) | ||
| 3236 | { | ||
| 3237 | unsigned int hi1, divider; | ||
| 3238 | |||
| 3239 | pdata->xsize = ((lcd->screen & LCD_SCREEN_SX) >> 19) + 1; | ||
| 3240 | pdata->ysize = ((lcd->screen & LCD_SCREEN_SY) >> 8) + 1; | ||
| 3241 | |||
| 3242 | pdata->backcolor = lcd->backcolor; | ||
| 3243 | pdata->colorkey = lcd->colorkey; | ||
| 3244 | pdata->mask = lcd->colorkeymsk; | ||
| 3245 | |||
| 3246 | // brightness | ||
| 3247 | hi1 = (lcd->pwmhi >> 16) + 1; | ||
| 3248 | divider = (lcd->pwmdiv & 0x3FFFF) + 1; | ||
| 3249 | pdata->brightness = ((hi1 << 8) / divider) - 1; | ||
| 3250 | au_sync(); | ||
| 3251 | } | ||
| 3252 | |||
| 3253 | static void set_window(unsigned int plane, | ||
| 3254 | struct au1200_lcd_window_regs_t *pdata) | ||
| 3255 | { | ||
| 3256 | unsigned int val, bpp; | ||
| 3257 | |||
| 3258 | /* Window control register 0 */ | ||
| 3259 | if (pdata->flags & WIN_POSITION) { | ||
| 3260 | val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_OX | | ||
| 3261 | LCD_WINCTRL0_OY); | ||
| 3262 | val |= ((pdata->xpos << 21) & LCD_WINCTRL0_OX); | ||
| 3263 | val |= ((pdata->ypos << 10) & LCD_WINCTRL0_OY); | ||
| 3264 | lcd->window[plane].winctrl0 = val; | ||
| 3265 | } | ||
| 3266 | if (pdata->flags & WIN_ALPHA_COLOR) { | ||
| 3267 | val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_A); | ||
| 3268 | val |= ((pdata->alpha_color << 2) & LCD_WINCTRL0_A); | ||
| 3269 | lcd->window[plane].winctrl0 = val; | ||
| 3270 | } | ||
| 3271 | if (pdata->flags & WIN_ALPHA_MODE) { | ||
| 3272 | val = lcd->window[plane].winctrl0 & ~(LCD_WINCTRL0_AEN); | ||
| 3273 | val |= ((pdata->alpha_mode << 1) & LCD_WINCTRL0_AEN); | ||
| 3274 | lcd->window[plane].winctrl0 = val; | ||
| 3275 | } | ||
| 3276 | |||
| 3277 | /* Window control register 1 */ | ||
| 3278 | if (pdata->flags & WIN_PRIORITY) { | ||
| 3279 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PRI); | ||
| 3280 | val |= ((pdata->priority << 30) & LCD_WINCTRL1_PRI); | ||
| 3281 | lcd->window[plane].winctrl1 = val; | ||
| 3282 | } | ||
| 3283 | if (pdata->flags & WIN_CHANNEL) { | ||
| 3284 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PIPE); | ||
| 3285 | val |= ((pdata->channel << 29) & LCD_WINCTRL1_PIPE); | ||
| 3286 | lcd->window[plane].winctrl1 = val; | ||
| 3287 | } | ||
| 3288 | if (pdata->flags & WIN_BUFFER_FORMAT) { | ||
| 3289 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_FRM); | ||
| 3290 | val |= ((pdata->buffer_format << 25) & LCD_WINCTRL1_FRM); | ||
| 3291 | lcd->window[plane].winctrl1 = val; | ||
| 3292 | } | ||
| 3293 | if (pdata->flags & WIN_COLOR_ORDER) { | ||
| 3294 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_CCO); | ||
| 3295 | val |= ((pdata->color_order << 24) & LCD_WINCTRL1_CCO); | ||
| 3296 | lcd->window[plane].winctrl1 = val; | ||
| 3297 | } | ||
| 3298 | if (pdata->flags & WIN_PIXEL_ORDER) { | ||
| 3299 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_PO); | ||
| 3300 | val |= ((pdata->pixel_order << 22) & LCD_WINCTRL1_PO); | ||
| 3301 | lcd->window[plane].winctrl1 = val; | ||
| 3302 | } | ||
| 3303 | if (pdata->flags & WIN_SIZE) { | ||
| 3304 | val = lcd->window[plane].winctrl1 & ~(LCD_WINCTRL1_SZX | | ||
| 3305 | LCD_WINCTRL1_SZY); | ||
| 3306 | val |= (((pdata->xsize << 11) - 1) & LCD_WINCTRL1_SZX); | ||
| 3307 | val |= (((pdata->ysize) - 1) & LCD_WINCTRL1_SZY); | ||
| 3308 | lcd->window[plane].winctrl1 = val; | ||
| 3309 | /* program buffer line width */ | ||
| 3310 | bpp = winbpp(val) / 8; | ||
| 3311 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_BX); | ||
| 3312 | val |= (((pdata->xsize * bpp) << 8) & LCD_WINCTRL2_BX); | ||
| 3313 | lcd->window[plane].winctrl2 = val; | ||
| 3314 | } | ||
| 3315 | |||
| 3316 | /* Window control register 2 */ | ||
| 3317 | if (pdata->flags & WIN_COLORKEY_MODE) { | ||
| 3318 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_CKMODE); | ||
| 3319 | val |= ((pdata->colorkey_mode << 24) & LCD_WINCTRL2_CKMODE); | ||
| 3320 | lcd->window[plane].winctrl2 = val; | ||
| 3321 | } | ||
| 3322 | if (pdata->flags & WIN_DOUBLE_BUFFER_MODE) { | ||
| 3323 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_DBM); | ||
| 3324 | val |= ((pdata->double_buffer_mode << 23) & LCD_WINCTRL2_DBM); | ||
| 3325 | lcd->window[plane].winctrl2 = val; | ||
| 3326 | } | ||
| 3327 | if (pdata->flags & WIN_RAM_ARRAY_MODE) { | ||
| 3328 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_RAM); | ||
| 3329 | val |= ((pdata->ram_array_mode << 21) & LCD_WINCTRL2_RAM); | ||
| 3330 | lcd->window[plane].winctrl2 = val; | ||
| 3331 | } | ||
| 3332 | |||
| 3333 | /* Buffer line width programmed with WIN_SIZE */ | ||
| 3334 | |||
| 3335 | if (pdata->flags & WIN_BUFFER_SCALE) { | ||
| 3336 | val = lcd->window[plane].winctrl2 & ~(LCD_WINCTRL2_SCX | | ||
| 3337 | LCD_WINCTRL2_SCY); | ||
| 3338 | val |= ((pdata->xsize << 11) & LCD_WINCTRL2_SCX); | ||
| 3339 | val |= ((pdata->ysize) & LCD_WINCTRL2_SCY); | ||
| 3340 | lcd->window[plane].winctrl2 = val; | ||
| 3341 | } | ||
| 3342 | |||
| 3343 | if (pdata->flags & WIN_ENABLE) { | ||
| 3344 | val = lcd->winenable; | ||
| 3345 | val &= ~(1<<plane); | ||
| 3346 | val |= (pdata->enable & 1) << plane; | ||
| 3347 | lcd->winenable = val; | ||
| 3348 | } | ||
| 3349 | au_sync(); | ||
| 3350 | } | ||
| 3351 | |||
| 3352 | static void get_window(unsigned int plane, | ||
| 3353 | struct au1200_lcd_window_regs_t *pdata) | ||
| 3354 | { | ||
| 3355 | /* Window control register 0 */ | ||
| 3356 | pdata->xpos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OX) >> 21; | ||
| 3357 | pdata->ypos = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_OY) >> 10; | ||
| 3358 | pdata->alpha_color = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_A) >> 2; | ||
| 3359 | pdata->alpha_mode = (lcd->window[plane].winctrl0 & LCD_WINCTRL0_AEN) >> 1; | ||
| 3360 | |||
| 3361 | /* Window control register 1 */ | ||
| 3362 | pdata->priority = (lcd->window[plane].winctrl1& LCD_WINCTRL1_PRI) >> 30; | ||
| 3363 | pdata->channel = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PIPE) >> 29; | ||
| 3364 | pdata->buffer_format = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_FRM) >> 25; | ||
| 3365 | pdata->color_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_CCO) >> 24; | ||
| 3366 | pdata->pixel_order = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_PO) >> 22; | ||
| 3367 | pdata->xsize = ((lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZX) >> 11) + 1; | ||
| 3368 | pdata->ysize = (lcd->window[plane].winctrl1 & LCD_WINCTRL1_SZY) + 1; | ||
| 3369 | |||
| 3370 | /* Window control register 2 */ | ||
| 3371 | pdata->colorkey_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_CKMODE) >> 24; | ||
| 3372 | pdata->double_buffer_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_DBM) >> 23; | ||
| 3373 | pdata->ram_array_mode = (lcd->window[plane].winctrl2 & LCD_WINCTRL2_RAM) >> 21; | ||
| 3374 | |||
| 3375 | pdata->enable = (lcd->winenable >> plane) & 1; | ||
| 3376 | au_sync(); | ||
| 3377 | } | ||
| 3378 | |||
| 3379 | static int au1200fb_ioctl(struct fb_info *info, unsigned int cmd, | ||
| 3380 | unsigned long arg) | ||
| 3381 | { | ||
| 3382 | int plane; | ||
| 3383 | int val; | ||
| 3384 | |||
| 3385 | #ifdef CONFIG_PM | ||
| 3386 | au1xxx_pm_access(LCD_pm_dev); | ||
| 3387 | #endif | ||
| 3388 | |||
| 3389 | plane = fbinfo2index(info); | ||
| 3390 | print_dbg("au1200fb: ioctl %d on plane %d\n", cmd, plane); | ||
| 3391 | |||
| 3392 | if (cmd == AU1200_LCD_FB_IOCTL) { | ||
| 3393 | struct au1200_lcd_iodata_t iodata; | ||
| 3394 | |||
| 3395 | if (copy_from_user(&iodata, (void __user *) arg, sizeof(iodata))) | ||
| 3396 | return -EFAULT; | ||
| 3397 | |||
| 3398 | print_dbg("FB IOCTL called\n"); | ||
| 3399 | |||
| 3400 | switch (iodata.subcmd) { | ||
| 3401 | case AU1200_LCD_SET_SCREEN: | ||
| 3402 | print_dbg("AU1200_LCD_SET_SCREEN\n"); | ||
| 3403 | set_global(cmd, &iodata.global); | ||
| 3404 | break; | ||
| 3405 | |||
| 3406 | case AU1200_LCD_GET_SCREEN: | ||
| 3407 | print_dbg("AU1200_LCD_GET_SCREEN\n"); | ||
| 3408 | get_global(cmd, &iodata.global); | ||
| 3409 | break; | ||
| 3410 | |||
| 3411 | case AU1200_LCD_SET_WINDOW: | ||
| 3412 | print_dbg("AU1200_LCD_SET_WINDOW\n"); | ||
| 3413 | set_window(plane, &iodata.window); | ||
| 3414 | break; | ||
| 3415 | |||
| 3416 | case AU1200_LCD_GET_WINDOW: | ||
| 3417 | print_dbg("AU1200_LCD_GET_WINDOW\n"); | ||
| 3418 | get_window(plane, &iodata.window); | ||
| 3419 | break; | ||
| 3420 | |||
| 3421 | case AU1200_LCD_SET_PANEL: | ||
| 3422 | print_dbg("AU1200_LCD_SET_PANEL\n"); | ||
| 3423 | if ((iodata.global.panel_choice >= 0) && | ||
| 3424 | (iodata.global.panel_choice < | ||
| 3425 | NUM_PANELS)) | ||
| 3426 | { | ||
| 3427 | struct panel_settings *newpanel; | ||
| 3428 | panel_index = iodata.global.panel_choice; | ||
| 3429 | newpanel = &known_lcd_panels[panel_index]; | ||
| 3430 | au1200_setpanel(newpanel); | ||
| 3431 | } | ||
| 3432 | break; | ||
| 3433 | |||
| 3434 | case AU1200_LCD_GET_PANEL: | ||
| 3435 | print_dbg("AU1200_LCD_GET_PANEL\n"); | ||
| 3436 | iodata.global.panel_choice = panel_index; | ||
| 3437 | break; | ||
| 3438 | |||
| 3439 | default: | ||
| 3440 | return -EINVAL; | ||
| 3441 | } | ||
| 3442 | |||
| 3443 | val = copy_to_user((void __user *) arg, &iodata, sizeof(iodata)); | ||
| 3444 | if (val) { | ||
| 3445 | print_dbg("error: could not copy %d bytes\n", val); | ||
| 3446 | return -EFAULT; | ||
| 3447 | } | ||
| 3448 | } | ||
| 3449 | |||
| 3450 | return 0; | ||
| 3451 | } | ||
| 3452 | |||
| 3453 | |||
| 3454 | static struct fb_ops au1200fb_fb_ops = { | ||
| 3455 | .owner = THIS_MODULE, | ||
| 3456 | .fb_check_var = au1200fb_fb_check_var, | ||
| 3457 | .fb_set_par = au1200fb_fb_set_par, | ||
| 3458 | .fb_setcolreg = au1200fb_fb_setcolreg, | ||
| 3459 | .fb_blank = au1200fb_fb_blank, | ||
| 3460 | .fb_fillrect = cfb_fillrect, | ||
| 3461 | .fb_copyarea = cfb_copyarea, | ||
| 3462 | .fb_imageblit = cfb_imageblit, | ||
| 3463 | .fb_sync = NULL, | ||
| 3464 | .fb_ioctl = au1200fb_ioctl, | ||
| 3465 | .fb_mmap = au1200fb_fb_mmap, | ||
| 3466 | }; | ||
| 3467 | |||
| 3468 | /*-------------------------------------------------------------------------*/ | ||
| 3469 | |||
| 3470 | static irqreturn_t au1200fb_handle_irq(int irq, void* dev_id, struct pt_regs *regs) | ||
| 3471 | { | ||
| 3472 | /* Nothing to do for now, just clear any pending interrupt */ | ||
| 3473 | lcd->intstatus = lcd->intstatus; | ||
| 3474 | au_sync(); | ||
| 3475 | |||
| 3476 | return IRQ_HANDLED; | ||
| 3477 | } | ||
| 3478 | |||
| 3479 | /*-------------------------------------------------------------------------*/ | ||
| 3480 | |||
| 3481 | /* AU1200 LCD device probe helpers */ | ||
| 3482 | |||
| 3483 | static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) | ||
| 3484 | { | ||
| 3485 | struct fb_info *fbi = &fbdev->fb_info; | ||
| 3486 | int bpp; | ||
| 3487 | |||
| 3488 | memset(fbi, 0, sizeof(struct fb_info)); | ||
| 3489 | fbi->fbops = &au1200fb_fb_ops; | ||
| 3490 | |||
| 3491 | bpp = winbpp(win->w[fbdev->plane].mode_winctrl1); | ||
| 3492 | |||
| 3493 | /* Copy monitor specs from panel data */ | ||
| 3494 | /* fixme: we're setting up LCD controller windows, so these dont give a | ||
| 3495 | damn as to what the monitor specs are (the panel itself does, but that | ||
| 3496 | isnt done here...so maybe need a generic catchall monitor setting??? */ | ||
| 3497 | memcpy(&fbi->monspecs, &panel->monspecs, sizeof(struct fb_monspecs)); | ||
| 3498 | |||
| 3499 | /* We first try the user mode passed in argument. If that failed, | ||
| 3500 | * or if no one has been specified, we default to the first mode of the | ||
| 3501 | * panel list. Note that after this call, var data will be set */ | ||
| 3502 | if (!fb_find_mode(&fbi->var, | ||
| 3503 | fbi, | ||
| 3504 | NULL, /* drv_info.opt_mode, */ | ||
| 3505 | fbi->monspecs.modedb, | ||
| 3506 | fbi->monspecs.modedb_len, | ||
| 3507 | fbi->monspecs.modedb, | ||
| 3508 | bpp)) { | ||
| 3509 | |||
| 3510 | print_err("Cannot find valid mode for panel %s", panel->name); | ||
| 3511 | return -EFAULT; | ||
| 3512 | } | ||
| 3513 | |||
| 3514 | fbi->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); | ||
| 3515 | if (!fbi->pseudo_palette) { | ||
| 3516 | return -ENOMEM; | ||
| 3517 | } | ||
| 3518 | memset(fbi->pseudo_palette, 0, sizeof(u32) * 16); | ||
| 3519 | |||
| 3520 | if (fb_alloc_cmap(&fbi->cmap, AU1200_LCD_NBR_PALETTE_ENTRIES, 0) < 0) { | ||
| 3521 | print_err("Fail to allocate colormap (%d entries)", | ||
| 3522 | AU1200_LCD_NBR_PALETTE_ENTRIES); | ||
| 3523 | kfree(fbi->pseudo_palette); | ||
| 3524 | return -EFAULT; | ||
| 3525 | } | ||
| 3526 | |||
| 3527 | strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id)); | ||
| 3528 | fbi->fix.smem_start = fbdev->fb_phys; | ||
| 3529 | fbi->fix.smem_len = fbdev->fb_len; | ||
| 3530 | fbi->fix.type = FB_TYPE_PACKED_PIXELS; | ||
| 3531 | fbi->fix.xpanstep = 0; | ||
| 3532 | fbi->fix.ypanstep = 0; | ||
| 3533 | fbi->fix.mmio_start = 0; | ||
| 3534 | fbi->fix.mmio_len = 0; | ||
| 3535 | fbi->fix.accel = FB_ACCEL_NONE; | ||
| 3536 | |||
| 3537 | fbi->screen_base = (char __iomem *) fbdev->fb_mem; | ||
| 3538 | |||
| 3539 | au1200fb_update_fbinfo(fbi); | ||
| 3540 | |||
| 3541 | return 0; | ||
| 3542 | } | ||
| 3543 | |||
| 3544 | /*-------------------------------------------------------------------------*/ | ||
| 3545 | |||
| 3546 | /* AU1200 LCD controller device driver */ | ||
| 3547 | |||
| 3548 | static int au1200fb_drv_probe(struct device *dev) | ||
| 3549 | { | ||
| 3550 | struct au1200fb_device *fbdev; | ||
| 3551 | unsigned long page; | ||
| 3552 | int bpp, plane, ret; | ||
| 3553 | |||
| 3554 | if (!dev) | ||
| 3555 | return -EINVAL; | ||
| 3556 | |||
| 3557 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | ||
| 3558 | bpp = winbpp(win->w[plane].mode_winctrl1); | ||
| 3559 | if (win->w[plane].xres == 0) | ||
| 3560 | win->w[plane].xres = panel->Xres; | ||
| 3561 | if (win->w[plane].yres == 0) | ||
| 3562 | win->w[plane].yres = panel->Yres; | ||
| 3563 | |||
| 3564 | fbdev = &_au1200fb_devices[plane]; | ||
| 3565 | memset(fbdev, 0, sizeof(struct au1200fb_device)); | ||
| 3566 | fbdev->plane = plane; | ||
| 3567 | |||
| 3568 | /* Allocate the framebuffer to the maximum screen size */ | ||
| 3569 | fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; | ||
| 3570 | |||
| 3571 | fbdev->fb_mem = dma_alloc_noncoherent(dev, | ||
| 3572 | PAGE_ALIGN(fbdev->fb_len), | ||
| 3573 | &fbdev->fb_phys, GFP_KERNEL); | ||
| 3574 | if (!fbdev->fb_mem) { | ||
| 3575 | print_err("fail to allocate frambuffer (size: %dK))", | ||
| 3576 | fbdev->fb_len / 1024); | ||
| 3577 | return -ENOMEM; | ||
| 3578 | } | ||
| 3579 | |||
| 3580 | /* | ||
| 3581 | * Set page reserved so that mmap will work. This is necessary | ||
| 3582 | * since we'll be remapping normal memory. | ||
| 3583 | */ | ||
| 3584 | for (page = (unsigned long)fbdev->fb_phys; | ||
| 3585 | page < PAGE_ALIGN((unsigned long)fbdev->fb_phys + | ||
| 3586 | fbdev->fb_len); | ||
| 3587 | page += PAGE_SIZE) { | ||
| 3588 | SetPageReserved(pfn_to_page(page >> PAGE_SHIFT)); /* LCD DMA is NOT coherent on Au1200 */ | ||
| 3589 | } | ||
| 3590 | print_dbg("Framebuffer memory map at %p", fbdev->fb_mem); | ||
| 3591 | print_dbg("phys=0x%08x, size=%dK", fbdev->fb_phys, fbdev->fb_len / 1024); | ||
| 3592 | |||
| 3593 | /* Init FB data */ | ||
| 3594 | if ((ret = au1200fb_init_fbinfo(fbdev)) < 0) | ||
| 3595 | goto failed; | ||
| 3596 | |||
| 3597 | /* Register new framebuffer */ | ||
| 3598 | if ((ret = register_framebuffer(&fbdev->fb_info)) < 0) { | ||
| 3599 | print_err("cannot register new framebuffer"); | ||
| 3600 | goto failed; | ||
| 3601 | } | ||
| 3602 | |||
| 3603 | au1200fb_fb_set_par(&fbdev->fb_info); | ||
| 3604 | |||
| 3605 | #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) | ||
| 3606 | if (plane == 0) | ||
| 3607 | if (fb_prepare_logo(&fbdev->fb_info, FB_ROTATE_UR)) { | ||
| 3608 | /* Start display and show logo on boot */ | ||
| 3609 | fb_set_cmap(&fbdev->fb_info.cmap, | ||
| 3610 | &fbdev->fb_info); | ||
| 3611 | |||
| 3612 | fb_show_logo(&fbdev->fb_info, FB_ROTATE_UR); | ||
| 3613 | } | ||
| 3614 | #endif | ||
| 3615 | } | ||
| 3616 | |||
| 3617 | /* Now hook interrupt too */ | ||
| 3618 | if ((ret = request_irq(AU1200_LCD_INT, au1200fb_handle_irq, | ||
| 3619 | SA_INTERRUPT | SA_SHIRQ, "lcd", (void *)dev)) < 0) { | ||
| 3620 | print_err("fail to request interrupt line %d (err: %d)", | ||
| 3621 | AU1200_LCD_INT, ret); | ||
| 3622 | goto failed; | ||
| 3623 | } | ||
| 3624 | |||
| 3625 | return 0; | ||
| 3626 | |||
| 3627 | failed: | ||
| 3628 | /* NOTE: This only does the current plane/window that failed; others are still active */ | ||
| 3629 | if (fbdev->fb_mem) | ||
| 3630 | dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), | ||
| 3631 | fbdev->fb_mem, fbdev->fb_phys); | ||
| 3632 | if (fbdev->fb_info.cmap.len != 0) | ||
| 3633 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | ||
| 3634 | if (fbdev->fb_info.pseudo_palette) | ||
| 3635 | kfree(fbdev->fb_info.pseudo_palette); | ||
| 3636 | if (plane == 0) | ||
| 3637 | free_irq(AU1200_LCD_INT, (void*)dev); | ||
| 3638 | return ret; | ||
| 3639 | } | ||
| 3640 | |||
| 3641 | static int au1200fb_drv_remove(struct device *dev) | ||
| 3642 | { | ||
| 3643 | struct au1200fb_device *fbdev; | ||
| 3644 | int plane; | ||
| 3645 | |||
| 3646 | if (!dev) | ||
| 3647 | return -ENODEV; | ||
| 3648 | |||
| 3649 | /* Turn off the panel */ | ||
| 3650 | au1200_setpanel(NULL); | ||
| 3651 | |||
| 3652 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) | ||
| 3653 | { | ||
| 3654 | fbdev = &_au1200fb_devices[plane]; | ||
| 3655 | |||
| 3656 | /* Clean up all probe data */ | ||
| 3657 | unregister_framebuffer(&fbdev->fb_info); | ||
| 3658 | if (fbdev->fb_mem) | ||
| 3659 | dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), | ||
| 3660 | fbdev->fb_mem, fbdev->fb_phys); | ||
| 3661 | if (fbdev->fb_info.cmap.len != 0) | ||
| 3662 | fb_dealloc_cmap(&fbdev->fb_info.cmap); | ||
| 3663 | if (fbdev->fb_info.pseudo_palette) | ||
| 3664 | kfree(fbdev->fb_info.pseudo_palette); | ||
| 3665 | } | ||
| 3666 | |||
| 3667 | free_irq(AU1200_LCD_INT, (void *)dev); | ||
| 3668 | |||
| 3669 | return 0; | ||
| 3670 | } | ||
| 3671 | |||
| 3672 | #ifdef CONFIG_PM | ||
| 3673 | static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level) | ||
| 3674 | { | ||
| 3675 | /* TODO */ | ||
| 3676 | return 0; | ||
| 3677 | } | ||
| 3678 | |||
| 3679 | static int au1200fb_drv_resume(struct device *dev, u32 level) | ||
| 3680 | { | ||
| 3681 | /* TODO */ | ||
| 3682 | return 0; | ||
| 3683 | } | ||
| 3684 | #endif /* CONFIG_PM */ | ||
| 3685 | |||
| 3686 | static struct device_driver au1200fb_driver = { | ||
| 3687 | .name = "au1200-lcd", | ||
| 3688 | .bus = &platform_bus_type, | ||
| 3689 | .probe = au1200fb_drv_probe, | ||
| 3690 | .remove = au1200fb_drv_remove, | ||
| 3691 | #ifdef CONFIG_PM | ||
| 3692 | .suspend = au1200fb_drv_suspend, | ||
| 3693 | .resume = au1200fb_drv_resume, | ||
| 3694 | #endif | ||
| 3695 | }; | ||
| 3696 | |||
| 3697 | /*-------------------------------------------------------------------------*/ | ||
| 3698 | |||
| 3699 | /* Kernel driver */ | ||
| 3700 | |||
| 3701 | static void au1200fb_setup(void) | ||
| 3702 | { | ||
| 3703 | char* options = NULL; | ||
| 3704 | char* this_opt; | ||
| 3705 | int num_panels = ARRAY_SIZE(known_lcd_panels); | ||
| 3706 | int panel_idx = -1; | ||
| 3707 | |||
| 3708 | fb_get_options(DRIVER_NAME, &options); | ||
| 3709 | |||
| 3710 | if (options) { | ||
| 3711 | while ((this_opt = strsep(&options,",")) != NULL) { | ||
| 3712 | /* Panel option - can be panel name, | ||
| 3713 | * "bs" for board-switch, or number/index */ | ||
| 3714 | if (!strncmp(this_opt, "panel:", 6)) { | ||
| 3715 | int i; | ||
| 3716 | long int li; | ||
| 3717 | char *endptr; | ||
| 3718 | this_opt += 6; | ||
| 3719 | /* First check for index, which allows | ||
| 3720 | * to short circuit this mess */ | ||
| 3721 | li = simple_strtol(this_opt, &endptr, 0); | ||
| 3722 | if (*endptr == '\0') { | ||
| 3723 | panel_idx = (int)li; | ||
| 3724 | } | ||
| 3725 | else if (strcmp(this_opt, "bs") == 0) { | ||
| 3726 | extern int board_au1200fb_panel(void); | ||
| 3727 | panel_idx = board_au1200fb_panel(); | ||
| 3728 | } | ||
| 3729 | |||
| 3730 | else | ||
| 3731 | for (i = 0; i < num_panels; i++) { | ||
| 3732 | if (!strcmp(this_opt, known_lcd_panels[i].name)) { | ||
| 3733 | panel_idx = i; | ||
| 3734 | break; | ||
| 3735 | } | ||
| 3736 | } | ||
| 3737 | |||
| 3738 | if ((panel_idx < 0) || (panel_idx >= num_panels)) { | ||
| 3739 | print_warn("Panel %s not supported!", this_opt); | ||
| 3740 | } | ||
| 3741 | else | ||
| 3742 | panel_index = panel_idx; | ||
| 3743 | } | ||
| 3744 | |||
| 3745 | else if (strncmp(this_opt, "nohwcursor", 10) == 0) { | ||
| 3746 | nohwcursor = 1; | ||
| 3747 | } | ||
| 3748 | |||
| 3749 | /* Unsupported option */ | ||
| 3750 | else { | ||
| 3751 | print_warn("Unsupported option \"%s\"", this_opt); | ||
| 3752 | } | ||
| 3753 | } | ||
| 3754 | } | ||
| 3755 | } | ||
| 3756 | |||
| 3757 | #ifdef CONFIG_PM | ||
| 3758 | static int au1200fb_pm_callback(au1xxx_power_dev_t *dev, | ||
| 3759 | au1xxx_request_t request, void *data) { | ||
| 3760 | int retval = -1; | ||
| 3761 | unsigned int d = 0; | ||
| 3762 | unsigned int brightness = 0; | ||
| 3763 | |||
| 3764 | if (request == AU1XXX_PM_SLEEP) { | ||
| 3765 | board_au1200fb_panel_shutdown(); | ||
| 3766 | } | ||
| 3767 | else if (request == AU1XXX_PM_WAKEUP) { | ||
| 3768 | if(dev->prev_state == SLEEP_STATE) | ||
| 3769 | { | ||
| 3770 | int plane; | ||
| 3771 | au1200_setpanel(panel); | ||
| 3772 | for (plane = 0; plane < CONFIG_FB_AU1200_DEVS; ++plane) { | ||
| 3773 | struct au1200fb_device *fbdev; | ||
| 3774 | fbdev = &_au1200fb_devices[plane]; | ||
| 3775 | au1200fb_fb_set_par(&fbdev->fb_info); | ||
| 3776 | } | ||
| 3777 | } | ||
| 3778 | |||
| 3779 | d = *((unsigned int*)data); | ||
| 3780 | if(d <=10) brightness = 26; | ||
| 3781 | else if(d<=20) brightness = 51; | ||
| 3782 | else if(d<=30) brightness = 77; | ||
| 3783 | else if(d<=40) brightness = 102; | ||
| 3784 | else if(d<=50) brightness = 128; | ||
| 3785 | else if(d<=60) brightness = 153; | ||
| 3786 | else if(d<=70) brightness = 179; | ||
| 3787 | else if(d<=80) brightness = 204; | ||
| 3788 | else if(d<=90) brightness = 230; | ||
| 3789 | else brightness = 255; | ||
| 3790 | set_brightness(brightness); | ||
| 3791 | } else if (request == AU1XXX_PM_GETSTATUS) { | ||
| 3792 | return dev->cur_state; | ||
| 3793 | } else if (request == AU1XXX_PM_ACCESS) { | ||
| 3794 | if (dev->cur_state != SLEEP_STATE) | ||
| 3795 | return retval; | ||
| 3796 | else { | ||
| 3797 | au1200_setpanel(panel); | ||
| 3798 | } | ||
| 3799 | } else if (request == AU1XXX_PM_IDLE) { | ||
| 3800 | } else if (request == AU1XXX_PM_CLEANUP) { | ||
| 3801 | } | ||
| 3802 | |||
| 3803 | return retval; | ||
| 3804 | } | ||
| 3805 | #endif | ||
| 3806 | |||
| 3807 | static int __init au1200fb_init(void) | ||
| 3808 | { | ||
| 3809 | print_info("" DRIVER_DESC ""); | ||
| 3810 | |||
| 3811 | /* Setup driver with options */ | ||
| 3812 | au1200fb_setup(); | ||
| 3813 | |||
| 3814 | /* Point to the panel selected */ | ||
| 3815 | panel = &known_lcd_panels[panel_index]; | ||
| 3816 | win = &windows[window_index]; | ||
| 3817 | |||
| 3818 | printk(DRIVER_NAME ": Panel %d %s\n", panel_index, panel->name); | ||
| 3819 | printk(DRIVER_NAME ": Win %d %s\n", window_index, win->name); | ||
| 3820 | |||
| 3821 | /* Kickstart the panel, the framebuffers/windows come soon enough */ | ||
| 3822 | au1200_setpanel(panel); | ||
| 3823 | |||
| 3824 | #ifdef CONFIG_PM | ||
| 3825 | LCD_pm_dev = new_au1xxx_power_device("LCD", &au1200fb_pm_callback, NULL); | ||
| 3826 | if ( LCD_pm_dev == NULL) | ||
| 3827 | printk(KERN_INFO "Unable to create a power management device entry for the au1200fb.\n"); | ||
| 3828 | else | ||
| 3829 | printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); | ||
| 3830 | #endif | ||
| 3831 | |||
| 3832 | return driver_register(&au1200fb_driver); | ||
| 3833 | } | ||
| 3834 | |||
| 3835 | static void __exit au1200fb_cleanup(void) | ||
| 3836 | { | ||
| 3837 | driver_unregister(&au1200fb_driver); | ||
| 3838 | } | ||
| 3839 | |||
| 3840 | module_init(au1200fb_init); | ||
| 3841 | module_exit(au1200fb_cleanup); | ||
| 3842 | |||
| 3843 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 3844 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/au1200fb.h b/drivers/video/au1200fb.h new file mode 100644 index 000000000000..e2672714d8d4 --- /dev/null +++ b/drivers/video/au1200fb.h | |||
| @@ -0,0 +1,572 @@ | |||
| 1 | /* | ||
| 2 | * BRIEF MODULE DESCRIPTION | ||
| 3 | * Hardware definitions for the Au1200 LCD controller | ||
| 4 | * | ||
| 5 | * Copyright 2004 AMD | ||
| 6 | * Author: AMD | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | * | ||
| 13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
| 14 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
| 15 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
| 16 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 17 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 18 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
| 19 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| 20 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 22 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 23 | * | ||
| 24 | * You should have received a copy of the GNU General Public License along | ||
| 25 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 26 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 27 | */ | ||
| 28 | |||
| 29 | #ifndef _AU1200LCD_H | ||
| 30 | #define _AU1200LCD_H | ||
| 31 | |||
| 32 | /********************************************************************/ | ||
| 33 | #define AU1200_LCD_ADDR 0xB5000000 | ||
| 34 | |||
| 35 | #define uint8 unsigned char | ||
| 36 | #define uint32 unsigned int | ||
| 37 | |||
| 38 | struct au1200_lcd { | ||
| 39 | volatile uint32 reserved0; | ||
| 40 | volatile uint32 screen; | ||
| 41 | volatile uint32 backcolor; | ||
| 42 | volatile uint32 horztiming; | ||
| 43 | volatile uint32 verttiming; | ||
| 44 | volatile uint32 clkcontrol; | ||
| 45 | volatile uint32 pwmdiv; | ||
| 46 | volatile uint32 pwmhi; | ||
| 47 | volatile uint32 reserved1; | ||
| 48 | volatile uint32 winenable; | ||
| 49 | volatile uint32 colorkey; | ||
| 50 | volatile uint32 colorkeymsk; | ||
| 51 | struct | ||
| 52 | { | ||
| 53 | volatile uint32 cursorctrl; | ||
| 54 | volatile uint32 cursorpos; | ||
| 55 | volatile uint32 cursorcolor0; | ||
| 56 | volatile uint32 cursorcolor1; | ||
| 57 | volatile uint32 cursorcolor2; | ||
| 58 | uint32 cursorcolor3; | ||
| 59 | } hwc; | ||
| 60 | volatile uint32 intstatus; | ||
| 61 | volatile uint32 intenable; | ||
| 62 | volatile uint32 outmask; | ||
| 63 | volatile uint32 fifoctrl; | ||
| 64 | uint32 reserved2[(0x0100-0x0058)/4]; | ||
| 65 | struct | ||
| 66 | { | ||
| 67 | volatile uint32 winctrl0; | ||
| 68 | volatile uint32 winctrl1; | ||
| 69 | volatile uint32 winctrl2; | ||
| 70 | volatile uint32 winbuf0; | ||
| 71 | volatile uint32 winbuf1; | ||
| 72 | volatile uint32 winbufctrl; | ||
| 73 | uint32 winreserved0; | ||
| 74 | uint32 winreserved1; | ||
| 75 | } window[4]; | ||
| 76 | |||
| 77 | uint32 reserved3[(0x0400-0x0180)/4]; | ||
| 78 | |||
| 79 | volatile uint32 palette[(0x0800-0x0400)/4]; | ||
| 80 | |||
| 81 | volatile uint8 cursorpattern[256]; | ||
| 82 | }; | ||
| 83 | |||
| 84 | /* lcd_screen */ | ||
| 85 | #define LCD_SCREEN_SEN (1<<31) | ||
| 86 | #define LCD_SCREEN_SX (0x07FF<<19) | ||
| 87 | #define LCD_SCREEN_SY (0x07FF<< 8) | ||
| 88 | #define LCD_SCREEN_SWP (1<<7) | ||
| 89 | #define LCD_SCREEN_SWD (1<<6) | ||
| 90 | #define LCD_SCREEN_PT (7<<0) | ||
| 91 | #define LCD_SCREEN_PT_TFT (0<<0) | ||
| 92 | #define LCD_SCREEN_SX_N(WIDTH) ((WIDTH-1)<<19) | ||
| 93 | #define LCD_SCREEN_SY_N(HEIGHT) ((HEIGHT-1)<<8) | ||
| 94 | #define LCD_SCREEN_PT_CSTN (1<<0) | ||
| 95 | #define LCD_SCREEN_PT_CDSTN (2<<0) | ||
| 96 | #define LCD_SCREEN_PT_M8STN (3<<0) | ||
| 97 | #define LCD_SCREEN_PT_M4STN (4<<0) | ||
| 98 | |||
| 99 | /* lcd_backcolor */ | ||
| 100 | #define LCD_BACKCOLOR_SBGR (0xFF<<16) | ||
| 101 | #define LCD_BACKCOLOR_SBGG (0xFF<<8) | ||
| 102 | #define LCD_BACKCOLOR_SBGB (0xFF<<0) | ||
| 103 | #define LCD_BACKCOLOR_SBGR_N(N) ((N)<<16) | ||
| 104 | #define LCD_BACKCOLOR_SBGG_N(N) ((N)<<8) | ||
| 105 | #define LCD_BACKCOLOR_SBGB_N(N) ((N)<<0) | ||
| 106 | |||
| 107 | /* lcd_winenable */ | ||
| 108 | #define LCD_WINENABLE_WEN3 (1<<3) | ||
| 109 | #define LCD_WINENABLE_WEN2 (1<<2) | ||
| 110 | #define LCD_WINENABLE_WEN1 (1<<1) | ||
| 111 | #define LCD_WINENABLE_WEN0 (1<<0) | ||
| 112 | |||
| 113 | /* lcd_colorkey */ | ||
| 114 | #define LCD_COLORKEY_CKR (0xFF<<16) | ||
| 115 | #define LCD_COLORKEY_CKG (0xFF<<8) | ||
| 116 | #define LCD_COLORKEY_CKB (0xFF<<0) | ||
| 117 | #define LCD_COLORKEY_CKR_N(N) ((N)<<16) | ||
| 118 | #define LCD_COLORKEY_CKG_N(N) ((N)<<8) | ||
| 119 | #define LCD_COLORKEY_CKB_N(N) ((N)<<0) | ||
| 120 | |||
| 121 | /* lcd_colorkeymsk */ | ||
| 122 | #define LCD_COLORKEYMSK_CKMR (0xFF<<16) | ||
| 123 | #define LCD_COLORKEYMSK_CKMG (0xFF<<8) | ||
| 124 | #define LCD_COLORKEYMSK_CKMB (0xFF<<0) | ||
| 125 | #define LCD_COLORKEYMSK_CKMR_N(N) ((N)<<16) | ||
| 126 | #define LCD_COLORKEYMSK_CKMG_N(N) ((N)<<8) | ||
| 127 | #define LCD_COLORKEYMSK_CKMB_N(N) ((N)<<0) | ||
| 128 | |||
| 129 | /* lcd windows control 0 */ | ||
| 130 | #define LCD_WINCTRL0_OX (0x07FF<<21) | ||
| 131 | #define LCD_WINCTRL0_OY (0x07FF<<10) | ||
| 132 | #define LCD_WINCTRL0_A (0x00FF<<2) | ||
| 133 | #define LCD_WINCTRL0_AEN (1<<1) | ||
| 134 | #define LCD_WINCTRL0_OX_N(N) ((N)<<21) | ||
| 135 | #define LCD_WINCTRL0_OY_N(N) ((N)<<10) | ||
| 136 | #define LCD_WINCTRL0_A_N(N) ((N)<<2) | ||
| 137 | |||
| 138 | /* lcd windows control 1 */ | ||
| 139 | #define LCD_WINCTRL1_PRI (3<<30) | ||
| 140 | #define LCD_WINCTRL1_PIPE (1<<29) | ||
| 141 | #define LCD_WINCTRL1_FRM (0xF<<25) | ||
| 142 | #define LCD_WINCTRL1_CCO (1<<24) | ||
| 143 | #define LCD_WINCTRL1_PO (3<<22) | ||
| 144 | #define LCD_WINCTRL1_SZX (0x07FF<<11) | ||
| 145 | #define LCD_WINCTRL1_SZY (0x07FF<<0) | ||
| 146 | #define LCD_WINCTRL1_FRM_1BPP (0<<25) | ||
| 147 | #define LCD_WINCTRL1_FRM_2BPP (1<<25) | ||
| 148 | #define LCD_WINCTRL1_FRM_4BPP (2<<25) | ||
| 149 | #define LCD_WINCTRL1_FRM_8BPP (3<<25) | ||
| 150 | #define LCD_WINCTRL1_FRM_12BPP (4<<25) | ||
| 151 | #define LCD_WINCTRL1_FRM_16BPP655 (5<<25) | ||
| 152 | #define LCD_WINCTRL1_FRM_16BPP565 (6<<25) | ||
| 153 | #define LCD_WINCTRL1_FRM_16BPP556 (7<<25) | ||
| 154 | #define LCD_WINCTRL1_FRM_16BPPI1555 (8<<25) | ||
| 155 | #define LCD_WINCTRL1_FRM_16BPPI5551 (9<<25) | ||
| 156 | #define LCD_WINCTRL1_FRM_16BPPA1555 (10<<25) | ||
| 157 | #define LCD_WINCTRL1_FRM_16BPPA5551 (11<<25) | ||
| 158 | #define LCD_WINCTRL1_FRM_24BPP (12<<25) | ||
| 159 | #define LCD_WINCTRL1_FRM_32BPP (13<<25) | ||
| 160 | #define LCD_WINCTRL1_PRI_N(N) ((N)<<30) | ||
| 161 | #define LCD_WINCTRL1_PO_00 (0<<22) | ||
| 162 | #define LCD_WINCTRL1_PO_01 (1<<22) | ||
| 163 | #define LCD_WINCTRL1_PO_10 (2<<22) | ||
| 164 | #define LCD_WINCTRL1_PO_11 (3<<22) | ||
| 165 | #define LCD_WINCTRL1_SZX_N(N) ((N-1)<<11) | ||
| 166 | #define LCD_WINCTRL1_SZY_N(N) ((N-1)<<0) | ||
| 167 | |||
| 168 | /* lcd windows control 2 */ | ||
| 169 | #define LCD_WINCTRL2_CKMODE (3<<24) | ||
| 170 | #define LCD_WINCTRL2_DBM (1<<23) | ||
| 171 | #define LCD_WINCTRL2_RAM (3<<21) | ||
| 172 | #define LCD_WINCTRL2_BX (0x1FFF<<8) | ||
| 173 | #define LCD_WINCTRL2_SCX (0xF<<4) | ||
| 174 | #define LCD_WINCTRL2_SCY (0xF<<0) | ||
| 175 | #define LCD_WINCTRL2_CKMODE_00 (0<<24) | ||
| 176 | #define LCD_WINCTRL2_CKMODE_01 (1<<24) | ||
| 177 | #define LCD_WINCTRL2_CKMODE_10 (2<<24) | ||
| 178 | #define LCD_WINCTRL2_CKMODE_11 (3<<24) | ||
| 179 | #define LCD_WINCTRL2_RAM_NONE (0<<21) | ||
| 180 | #define LCD_WINCTRL2_RAM_PALETTE (1<<21) | ||
| 181 | #define LCD_WINCTRL2_RAM_GAMMA (2<<21) | ||
| 182 | #define LCD_WINCTRL2_RAM_BUFFER (3<<21) | ||
| 183 | #define LCD_WINCTRL2_BX_N(N) ((N)<<8) | ||
| 184 | #define LCD_WINCTRL2_SCX_1 (0<<4) | ||
| 185 | #define LCD_WINCTRL2_SCX_2 (1<<4) | ||
| 186 | #define LCD_WINCTRL2_SCX_4 (2<<4) | ||
| 187 | #define LCD_WINCTRL2_SCY_1 (0<<0) | ||
| 188 | #define LCD_WINCTRL2_SCY_2 (1<<0) | ||
| 189 | #define LCD_WINCTRL2_SCY_4 (2<<0) | ||
| 190 | |||
| 191 | /* lcd windows buffer control */ | ||
| 192 | #define LCD_WINBUFCTRL_DB (1<<1) | ||
| 193 | #define LCD_WINBUFCTRL_DBN (1<<0) | ||
| 194 | |||
| 195 | /* lcd_intstatus, lcd_intenable */ | ||
| 196 | #define LCD_INT_IFO (0xF<<14) | ||
| 197 | #define LCD_INT_IFU (0xF<<10) | ||
| 198 | #define LCD_INT_OFO (1<<9) | ||
| 199 | #define LCD_INT_OFU (1<<8) | ||
| 200 | #define LCD_INT_WAIT (1<<3) | ||
| 201 | #define LCD_INT_SD (1<<2) | ||
| 202 | #define LCD_INT_SA (1<<1) | ||
| 203 | #define LCD_INT_SS (1<<0) | ||
| 204 | |||
| 205 | /* lcd_horztiming */ | ||
| 206 | #define LCD_HORZTIMING_HND2 (0x1FF<<18) | ||
| 207 | #define LCD_HORZTIMING_HND1 (0x1FF<<9) | ||
| 208 | #define LCD_HORZTIMING_HPW (0x1FF<<0) | ||
| 209 | #define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18) | ||
| 210 | #define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9) | ||
| 211 | #define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<0) | ||
| 212 | |||
| 213 | /* lcd_verttiming */ | ||
| 214 | #define LCD_VERTTIMING_VND2 (0x1FF<<18) | ||
| 215 | #define LCD_VERTTIMING_VND1 (0x1FF<<9) | ||
| 216 | #define LCD_VERTTIMING_VPW (0x1FF<<0) | ||
| 217 | #define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18) | ||
| 218 | #define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9) | ||
| 219 | #define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<0) | ||
| 220 | |||
| 221 | /* lcd_clkcontrol */ | ||
| 222 | #define LCD_CLKCONTROL_EXT (1<<22) | ||
| 223 | #define LCD_CLKCONTROL_DELAY (3<<20) | ||
| 224 | #define LCD_CLKCONTROL_CDD (1<<19) | ||
| 225 | #define LCD_CLKCONTROL_IB (1<<18) | ||
| 226 | #define LCD_CLKCONTROL_IC (1<<17) | ||
| 227 | #define LCD_CLKCONTROL_IH (1<<16) | ||
| 228 | #define LCD_CLKCONTROL_IV (1<<15) | ||
| 229 | #define LCD_CLKCONTROL_BF (0x1F<<10) | ||
| 230 | #define LCD_CLKCONTROL_PCD (0x3FF<<0) | ||
| 231 | #define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10) | ||
| 232 | #define LCD_CLKCONTROL_PCD_N(N) ((N)<<0) | ||
| 233 | |||
| 234 | /* lcd_pwmdiv */ | ||
| 235 | #define LCD_PWMDIV_EN (1<<31) | ||
| 236 | #define LCD_PWMDIV_PWMDIV (0x1FFFF<<0) | ||
| 237 | #define LCD_PWMDIV_PWMDIV_N(N) ((N)<<0) | ||
| 238 | |||
| 239 | /* lcd_pwmhi */ | ||
| 240 | #define LCD_PWMHI_PWMHI1 (0xFFFF<<16) | ||
| 241 | #define LCD_PWMHI_PWMHI0 (0xFFFF<<0) | ||
| 242 | #define LCD_PWMHI_PWMHI1_N(N) ((N)<<16) | ||
| 243 | #define LCD_PWMHI_PWMHI0_N(N) ((N)<<0) | ||
| 244 | |||
| 245 | /* lcd_hwccon */ | ||
| 246 | #define LCD_HWCCON_EN (1<<0) | ||
| 247 | |||
| 248 | /* lcd_cursorpos */ | ||
| 249 | #define LCD_CURSORPOS_HWCXOFF (0x1F<<27) | ||
| 250 | #define LCD_CURSORPOS_HWCXPOS (0x07FF<<16) | ||
| 251 | #define LCD_CURSORPOS_HWCYOFF (0x1F<<11) | ||
| 252 | #define LCD_CURSORPOS_HWCYPOS (0x07FF<<0) | ||
| 253 | #define LCD_CURSORPOS_HWCXOFF_N(N) ((N)<<27) | ||
| 254 | #define LCD_CURSORPOS_HWCXPOS_N(N) ((N)<<16) | ||
| 255 | #define LCD_CURSORPOS_HWCYOFF_N(N) ((N)<<11) | ||
| 256 | #define LCD_CURSORPOS_HWCYPOS_N(N) ((N)<<0) | ||
| 257 | |||
| 258 | /* lcd_cursorcolor */ | ||
| 259 | #define LCD_CURSORCOLOR_HWCA (0xFF<<24) | ||
| 260 | #define LCD_CURSORCOLOR_HWCR (0xFF<<16) | ||
| 261 | #define LCD_CURSORCOLOR_HWCG (0xFF<<8) | ||
| 262 | #define LCD_CURSORCOLOR_HWCB (0xFF<<0) | ||
| 263 | #define LCD_CURSORCOLOR_HWCA_N(N) ((N)<<24) | ||
| 264 | #define LCD_CURSORCOLOR_HWCR_N(N) ((N)<<16) | ||
| 265 | #define LCD_CURSORCOLOR_HWCG_N(N) ((N)<<8) | ||
| 266 | #define LCD_CURSORCOLOR_HWCB_N(N) ((N)<<0) | ||
| 267 | |||
| 268 | /* lcd_fifoctrl */ | ||
| 269 | #define LCD_FIFOCTRL_F3IF (1<<29) | ||
| 270 | #define LCD_FIFOCTRL_F3REQ (0x1F<<24) | ||
| 271 | #define LCD_FIFOCTRL_F2IF (1<<29) | ||
| 272 | #define LCD_FIFOCTRL_F2REQ (0x1F<<16) | ||
| 273 | #define LCD_FIFOCTRL_F1IF (1<<29) | ||
| 274 | #define LCD_FIFOCTRL_F1REQ (0x1F<<8) | ||
| 275 | #define LCD_FIFOCTRL_F0IF (1<<29) | ||
| 276 | #define LCD_FIFOCTRL_F0REQ (0x1F<<0) | ||
| 277 | #define LCD_FIFOCTRL_F3REQ_N(N) ((N-1)<<24) | ||
| 278 | #define LCD_FIFOCTRL_F2REQ_N(N) ((N-1)<<16) | ||
| 279 | #define LCD_FIFOCTRL_F1REQ_N(N) ((N-1)<<8) | ||
| 280 | #define LCD_FIFOCTRL_F0REQ_N(N) ((N-1)<<0) | ||
| 281 | |||
| 282 | /* lcd_outmask */ | ||
| 283 | #define LCD_OUTMASK_MASK (0x00FFFFFF) | ||
| 284 | |||
| 285 | /********************************************************************/ | ||
| 286 | #endif /* _AU1200LCD_H */ | ||
| 287 | /* | ||
| 288 | * BRIEF MODULE DESCRIPTION | ||
| 289 | * Hardware definitions for the Au1200 LCD controller | ||
| 290 | * | ||
| 291 | * Copyright 2004 AMD | ||
| 292 | * Author: AMD | ||
| 293 | * | ||
| 294 | * This program is free software; you can redistribute it and/or modify it | ||
| 295 | * under the terms of the GNU General Public License as published by the | ||
| 296 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 297 | * option) any later version. | ||
| 298 | * | ||
| 299 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
| 300 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
| 301 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
| 302 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 303 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 304 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
| 305 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| 306 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 307 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 308 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 309 | * | ||
| 310 | * You should have received a copy of the GNU General Public License along | ||
| 311 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 312 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 313 | */ | ||
| 314 | |||
| 315 | #ifndef _AU1200LCD_H | ||
| 316 | #define _AU1200LCD_H | ||
| 317 | |||
| 318 | /********************************************************************/ | ||
| 319 | #define AU1200_LCD_ADDR 0xB5000000 | ||
| 320 | |||
| 321 | #define uint8 unsigned char | ||
| 322 | #define uint32 unsigned int | ||
| 323 | |||
| 324 | struct au1200_lcd { | ||
| 325 | volatile uint32 reserved0; | ||
| 326 | volatile uint32 screen; | ||
| 327 | volatile uint32 backcolor; | ||
| 328 | volatile uint32 horztiming; | ||
| 329 | volatile uint32 verttiming; | ||
| 330 | volatile uint32 clkcontrol; | ||
| 331 | volatile uint32 pwmdiv; | ||
| 332 | volatile uint32 pwmhi; | ||
| 333 | volatile uint32 reserved1; | ||
| 334 | volatile uint32 winenable; | ||
| 335 | volatile uint32 colorkey; | ||
| 336 | volatile uint32 colorkeymsk; | ||
| 337 | struct | ||
| 338 | { | ||
| 339 | volatile uint32 cursorctrl; | ||
| 340 | volatile uint32 cursorpos; | ||
| 341 | volatile uint32 cursorcolor0; | ||
| 342 | volatile uint32 cursorcolor1; | ||
| 343 | volatile uint32 cursorcolor2; | ||
| 344 | uint32 cursorcolor3; | ||
| 345 | } hwc; | ||
| 346 | volatile uint32 intstatus; | ||
| 347 | volatile uint32 intenable; | ||
| 348 | volatile uint32 outmask; | ||
| 349 | volatile uint32 fifoctrl; | ||
| 350 | uint32 reserved2[(0x0100-0x0058)/4]; | ||
| 351 | struct | ||
| 352 | { | ||
| 353 | volatile uint32 winctrl0; | ||
| 354 | volatile uint32 winctrl1; | ||
| 355 | volatile uint32 winctrl2; | ||
| 356 | volatile uint32 winbuf0; | ||
| 357 | volatile uint32 winbuf1; | ||
| 358 | volatile uint32 winbufctrl; | ||
| 359 | uint32 winreserved0; | ||
| 360 | uint32 winreserved1; | ||
| 361 | } window[4]; | ||
| 362 | |||
| 363 | uint32 reserved3[(0x0400-0x0180)/4]; | ||
| 364 | |||
| 365 | volatile uint32 palette[(0x0800-0x0400)/4]; | ||
| 366 | |||
| 367 | volatile uint8 cursorpattern[256]; | ||
| 368 | }; | ||
| 369 | |||
| 370 | /* lcd_screen */ | ||
| 371 | #define LCD_SCREEN_SEN (1<<31) | ||
| 372 | #define LCD_SCREEN_SX (0x07FF<<19) | ||
| 373 | #define LCD_SCREEN_SY (0x07FF<< 8) | ||
| 374 | #define LCD_SCREEN_SWP (1<<7) | ||
| 375 | #define LCD_SCREEN_SWD (1<<6) | ||
| 376 | #define LCD_SCREEN_PT (7<<0) | ||
| 377 | #define LCD_SCREEN_PT_TFT (0<<0) | ||
| 378 | #define LCD_SCREEN_SX_N(WIDTH) ((WIDTH-1)<<19) | ||
| 379 | #define LCD_SCREEN_SY_N(HEIGHT) ((HEIGHT-1)<<8) | ||
| 380 | #define LCD_SCREEN_PT_CSTN (1<<0) | ||
| 381 | #define LCD_SCREEN_PT_CDSTN (2<<0) | ||
| 382 | #define LCD_SCREEN_PT_M8STN (3<<0) | ||
| 383 | #define LCD_SCREEN_PT_M4STN (4<<0) | ||
| 384 | |||
| 385 | /* lcd_backcolor */ | ||
| 386 | #define LCD_BACKCOLOR_SBGR (0xFF<<16) | ||
| 387 | #define LCD_BACKCOLOR_SBGG (0xFF<<8) | ||
| 388 | #define LCD_BACKCOLOR_SBGB (0xFF<<0) | ||
| 389 | #define LCD_BACKCOLOR_SBGR_N(N) ((N)<<16) | ||
| 390 | #define LCD_BACKCOLOR_SBGG_N(N) ((N)<<8) | ||
| 391 | #define LCD_BACKCOLOR_SBGB_N(N) ((N)<<0) | ||
| 392 | |||
| 393 | /* lcd_winenable */ | ||
| 394 | #define LCD_WINENABLE_WEN3 (1<<3) | ||
| 395 | #define LCD_WINENABLE_WEN2 (1<<2) | ||
| 396 | #define LCD_WINENABLE_WEN1 (1<<1) | ||
| 397 | #define LCD_WINENABLE_WEN0 (1<<0) | ||
| 398 | |||
| 399 | /* lcd_colorkey */ | ||
| 400 | #define LCD_COLORKEY_CKR (0xFF<<16) | ||
| 401 | #define LCD_COLORKEY_CKG (0xFF<<8) | ||
| 402 | #define LCD_COLORKEY_CKB (0xFF<<0) | ||
| 403 | #define LCD_COLORKEY_CKR_N(N) ((N)<<16) | ||
| 404 | #define LCD_COLORKEY_CKG_N(N) ((N)<<8) | ||
| 405 | #define LCD_COLORKEY_CKB_N(N) ((N)<<0) | ||
| 406 | |||
| 407 | /* lcd_colorkeymsk */ | ||
| 408 | #define LCD_COLORKEYMSK_CKMR (0xFF<<16) | ||
| 409 | #define LCD_COLORKEYMSK_CKMG (0xFF<<8) | ||
| 410 | #define LCD_COLORKEYMSK_CKMB (0xFF<<0) | ||
| 411 | #define LCD_COLORKEYMSK_CKMR_N(N) ((N)<<16) | ||
| 412 | #define LCD_COLORKEYMSK_CKMG_N(N) ((N)<<8) | ||
| 413 | #define LCD_COLORKEYMSK_CKMB_N(N) ((N)<<0) | ||
| 414 | |||
| 415 | /* lcd windows control 0 */ | ||
| 416 | #define LCD_WINCTRL0_OX (0x07FF<<21) | ||
| 417 | #define LCD_WINCTRL0_OY (0x07FF<<10) | ||
| 418 | #define LCD_WINCTRL0_A (0x00FF<<2) | ||
| 419 | #define LCD_WINCTRL0_AEN (1<<1) | ||
| 420 | #define LCD_WINCTRL0_OX_N(N) ((N)<<21) | ||
| 421 | #define LCD_WINCTRL0_OY_N(N) ((N)<<10) | ||
| 422 | #define LCD_WINCTRL0_A_N(N) ((N)<<2) | ||
| 423 | |||
| 424 | /* lcd windows control 1 */ | ||
| 425 | #define LCD_WINCTRL1_PRI (3<<30) | ||
| 426 | #define LCD_WINCTRL1_PIPE (1<<29) | ||
| 427 | #define LCD_WINCTRL1_FRM (0xF<<25) | ||
| 428 | #define LCD_WINCTRL1_CCO (1<<24) | ||
| 429 | #define LCD_WINCTRL1_PO (3<<22) | ||
| 430 | #define LCD_WINCTRL1_SZX (0x07FF<<11) | ||
| 431 | #define LCD_WINCTRL1_SZY (0x07FF<<0) | ||
| 432 | #define LCD_WINCTRL1_FRM_1BPP (0<<25) | ||
| 433 | #define LCD_WINCTRL1_FRM_2BPP (1<<25) | ||
| 434 | #define LCD_WINCTRL1_FRM_4BPP (2<<25) | ||
| 435 | #define LCD_WINCTRL1_FRM_8BPP (3<<25) | ||
| 436 | #define LCD_WINCTRL1_FRM_12BPP (4<<25) | ||
| 437 | #define LCD_WINCTRL1_FRM_16BPP655 (5<<25) | ||
| 438 | #define LCD_WINCTRL1_FRM_16BPP565 (6<<25) | ||
| 439 | #define LCD_WINCTRL1_FRM_16BPP556 (7<<25) | ||
| 440 | #define LCD_WINCTRL1_FRM_16BPPI1555 (8<<25) | ||
| 441 | #define LCD_WINCTRL1_FRM_16BPPI5551 (9<<25) | ||
| 442 | #define LCD_WINCTRL1_FRM_16BPPA1555 (10<<25) | ||
| 443 | #define LCD_WINCTRL1_FRM_16BPPA5551 (11<<25) | ||
| 444 | #define LCD_WINCTRL1_FRM_24BPP (12<<25) | ||
| 445 | #define LCD_WINCTRL1_FRM_32BPP (13<<25) | ||
| 446 | #define LCD_WINCTRL1_PRI_N(N) ((N)<<30) | ||
| 447 | #define LCD_WINCTRL1_PO_00 (0<<22) | ||
| 448 | #define LCD_WINCTRL1_PO_01 (1<<22) | ||
| 449 | #define LCD_WINCTRL1_PO_10 (2<<22) | ||
| 450 | #define LCD_WINCTRL1_PO_11 (3<<22) | ||
| 451 | #define LCD_WINCTRL1_SZX_N(N) ((N-1)<<11) | ||
| 452 | #define LCD_WINCTRL1_SZY_N(N) ((N-1)<<0) | ||
| 453 | |||
| 454 | /* lcd windows control 2 */ | ||
| 455 | #define LCD_WINCTRL2_CKMODE (3<<24) | ||
| 456 | #define LCD_WINCTRL2_DBM (1<<23) | ||
| 457 | #define LCD_WINCTRL2_RAM (3<<21) | ||
| 458 | #define LCD_WINCTRL2_BX (0x1FFF<<8) | ||
| 459 | #define LCD_WINCTRL2_SCX (0xF<<4) | ||
| 460 | #define LCD_WINCTRL2_SCY (0xF<<0) | ||
| 461 | #define LCD_WINCTRL2_CKMODE_00 (0<<24) | ||
| 462 | #define LCD_WINCTRL2_CKMODE_01 (1<<24) | ||
| 463 | #define LCD_WINCTRL2_CKMODE_10 (2<<24) | ||
| 464 | #define LCD_WINCTRL2_CKMODE_11 (3<<24) | ||
| 465 | #define LCD_WINCTRL2_RAM_NONE (0<<21) | ||
| 466 | #define LCD_WINCTRL2_RAM_PALETTE (1<<21) | ||
| 467 | #define LCD_WINCTRL2_RAM_GAMMA (2<<21) | ||
| 468 | #define LCD_WINCTRL2_RAM_BUFFER (3<<21) | ||
| 469 | #define LCD_WINCTRL2_BX_N(N) ((N)<<8) | ||
| 470 | #define LCD_WINCTRL2_SCX_1 (0<<4) | ||
| 471 | #define LCD_WINCTRL2_SCX_2 (1<<4) | ||
| 472 | #define LCD_WINCTRL2_SCX_4 (2<<4) | ||
| 473 | #define LCD_WINCTRL2_SCY_1 (0<<0) | ||
| 474 | #define LCD_WINCTRL2_SCY_2 (1<<0) | ||
| 475 | #define LCD_WINCTRL2_SCY_4 (2<<0) | ||
| 476 | |||
| 477 | /* lcd windows buffer control */ | ||
| 478 | #define LCD_WINBUFCTRL_DB (1<<1) | ||
| 479 | #define LCD_WINBUFCTRL_DBN (1<<0) | ||
| 480 | |||
| 481 | /* lcd_intstatus, lcd_intenable */ | ||
| 482 | #define LCD_INT_IFO (0xF<<14) | ||
| 483 | #define LCD_INT_IFU (0xF<<10) | ||
| 484 | #define LCD_INT_OFO (1<<9) | ||
| 485 | #define LCD_INT_OFU (1<<8) | ||
| 486 | #define LCD_INT_WAIT (1<<3) | ||
| 487 | #define LCD_INT_SD (1<<2) | ||
| 488 | #define LCD_INT_SA (1<<1) | ||
| 489 | #define LCD_INT_SS (1<<0) | ||
| 490 | |||
| 491 | /* lcd_horztiming */ | ||
| 492 | #define LCD_HORZTIMING_HND2 (0x1FF<<18) | ||
| 493 | #define LCD_HORZTIMING_HND1 (0x1FF<<9) | ||
| 494 | #define LCD_HORZTIMING_HPW (0x1FF<<0) | ||
| 495 | #define LCD_HORZTIMING_HND2_N(N)(((N)-1)<<18) | ||
| 496 | #define LCD_HORZTIMING_HND1_N(N)(((N)-1)<<9) | ||
| 497 | #define LCD_HORZTIMING_HPW_N(N) (((N)-1)<<0) | ||
| 498 | |||
| 499 | /* lcd_verttiming */ | ||
| 500 | #define LCD_VERTTIMING_VND2 (0x1FF<<18) | ||
| 501 | #define LCD_VERTTIMING_VND1 (0x1FF<<9) | ||
| 502 | #define LCD_VERTTIMING_VPW (0x1FF<<0) | ||
| 503 | #define LCD_VERTTIMING_VND2_N(N)(((N)-1)<<18) | ||
| 504 | #define LCD_VERTTIMING_VND1_N(N)(((N)-1)<<9) | ||
| 505 | #define LCD_VERTTIMING_VPW_N(N) (((N)-1)<<0) | ||
| 506 | |||
| 507 | /* lcd_clkcontrol */ | ||
| 508 | #define LCD_CLKCONTROL_EXT (1<<22) | ||
| 509 | #define LCD_CLKCONTROL_DELAY (3<<20) | ||
| 510 | #define LCD_CLKCONTROL_CDD (1<<19) | ||
| 511 | #define LCD_CLKCONTROL_IB (1<<18) | ||
| 512 | #define LCD_CLKCONTROL_IC (1<<17) | ||
| 513 | #define LCD_CLKCONTROL_IH (1<<16) | ||
| 514 | #define LCD_CLKCONTROL_IV (1<<15) | ||
| 515 | #define LCD_CLKCONTROL_BF (0x1F<<10) | ||
| 516 | #define LCD_CLKCONTROL_PCD (0x3FF<<0) | ||
| 517 | #define LCD_CLKCONTROL_BF_N(N) (((N)-1)<<10) | ||
| 518 | #define LCD_CLKCONTROL_PCD_N(N) ((N)<<0) | ||
| 519 | |||
| 520 | /* lcd_pwmdiv */ | ||
| 521 | #define LCD_PWMDIV_EN (1<<31) | ||
| 522 | #define LCD_PWMDIV_PWMDIV (0x1FFFF<<0) | ||
| 523 | #define LCD_PWMDIV_PWMDIV_N(N) ((N)<<0) | ||
| 524 | |||
| 525 | /* lcd_pwmhi */ | ||
| 526 | #define LCD_PWMHI_PWMHI1 (0xFFFF<<16) | ||
| 527 | #define LCD_PWMHI_PWMHI0 (0xFFFF<<0) | ||
| 528 | #define LCD_PWMHI_PWMHI1_N(N) ((N)<<16) | ||
| 529 | #define LCD_PWMHI_PWMHI0_N(N) ((N)<<0) | ||
| 530 | |||
| 531 | /* lcd_hwccon */ | ||
| 532 | #define LCD_HWCCON_EN (1<<0) | ||
| 533 | |||
| 534 | /* lcd_cursorpos */ | ||
| 535 | #define LCD_CURSORPOS_HWCXOFF (0x1F<<27) | ||
| 536 | #define LCD_CURSORPOS_HWCXPOS (0x07FF<<16) | ||
| 537 | #define LCD_CURSORPOS_HWCYOFF (0x1F<<11) | ||
| 538 | #define LCD_CURSORPOS_HWCYPOS (0x07FF<<0) | ||
| 539 | #define LCD_CURSORPOS_HWCXOFF_N(N) ((N)<<27) | ||
| 540 | #define LCD_CURSORPOS_HWCXPOS_N(N) ((N)<<16) | ||
| 541 | #define LCD_CURSORPOS_HWCYOFF_N(N) ((N)<<11) | ||
| 542 | #define LCD_CURSORPOS_HWCYPOS_N(N) ((N)<<0) | ||
| 543 | |||
| 544 | /* lcd_cursorcolor */ | ||
| 545 | #define LCD_CURSORCOLOR_HWCA (0xFF<<24) | ||
| 546 | #define LCD_CURSORCOLOR_HWCR (0xFF<<16) | ||
| 547 | #define LCD_CURSORCOLOR_HWCG (0xFF<<8) | ||
| 548 | #define LCD_CURSORCOLOR_HWCB (0xFF<<0) | ||
| 549 | #define LCD_CURSORCOLOR_HWCA_N(N) ((N)<<24) | ||
| 550 | #define LCD_CURSORCOLOR_HWCR_N(N) ((N)<<16) | ||
| 551 | #define LCD_CURSORCOLOR_HWCG_N(N) ((N)<<8) | ||
| 552 | #define LCD_CURSORCOLOR_HWCB_N(N) ((N)<<0) | ||
| 553 | |||
| 554 | /* lcd_fifoctrl */ | ||
| 555 | #define LCD_FIFOCTRL_F3IF (1<<29) | ||
| 556 | #define LCD_FIFOCTRL_F3REQ (0x1F<<24) | ||
| 557 | #define LCD_FIFOCTRL_F2IF (1<<29) | ||
| 558 | #define LCD_FIFOCTRL_F2REQ (0x1F<<16) | ||
| 559 | #define LCD_FIFOCTRL_F1IF (1<<29) | ||
| 560 | #define LCD_FIFOCTRL_F1REQ (0x1F<<8) | ||
| 561 | #define LCD_FIFOCTRL_F0IF (1<<29) | ||
| 562 | #define LCD_FIFOCTRL_F0REQ (0x1F<<0) | ||
| 563 | #define LCD_FIFOCTRL_F3REQ_N(N) ((N-1)<<24) | ||
| 564 | #define LCD_FIFOCTRL_F2REQ_N(N) ((N-1)<<16) | ||
| 565 | #define LCD_FIFOCTRL_F1REQ_N(N) ((N-1)<<8) | ||
| 566 | #define LCD_FIFOCTRL_F0REQ_N(N) ((N-1)<<0) | ||
| 567 | |||
| 568 | /* lcd_outmask */ | ||
| 569 | #define LCD_OUTMASK_MASK (0x00FFFFFF) | ||
| 570 | |||
| 571 | /********************************************************************/ | ||
| 572 | #endif /* _AU1200LCD_H */ | ||
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index bc061d4ec786..72ff6bf75e5e 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c | |||
| @@ -178,8 +178,6 @@ struct chips_init_reg { | |||
| 178 | unsigned char data; | 178 | unsigned char data; |
| 179 | }; | 179 | }; |
| 180 | 180 | ||
| 181 | #define N_ELTS(x) (sizeof(x) / sizeof(x[0])) | ||
| 182 | |||
| 183 | static struct chips_init_reg chips_init_sr[] = { | 181 | static struct chips_init_reg chips_init_sr[] = { |
| 184 | { 0x00, 0x03 }, | 182 | { 0x00, 0x03 }, |
| 185 | { 0x01, 0x01 }, | 183 | { 0x01, 0x01 }, |
| @@ -287,18 +285,18 @@ static void __init chips_hw_init(void) | |||
| 287 | { | 285 | { |
| 288 | int i; | 286 | int i; |
| 289 | 287 | ||
| 290 | for (i = 0; i < N_ELTS(chips_init_xr); ++i) | 288 | for (i = 0; i < ARRAY_SIZE(chips_init_xr); ++i) |
| 291 | write_xr(chips_init_xr[i].addr, chips_init_xr[i].data); | 289 | write_xr(chips_init_xr[i].addr, chips_init_xr[i].data); |
| 292 | outb(0x29, 0x3c2); /* set misc output reg */ | 290 | outb(0x29, 0x3c2); /* set misc output reg */ |
| 293 | for (i = 0; i < N_ELTS(chips_init_sr); ++i) | 291 | for (i = 0; i < ARRAY_SIZE(chips_init_sr); ++i) |
| 294 | write_sr(chips_init_sr[i].addr, chips_init_sr[i].data); | 292 | write_sr(chips_init_sr[i].addr, chips_init_sr[i].data); |
| 295 | for (i = 0; i < N_ELTS(chips_init_gr); ++i) | 293 | for (i = 0; i < ARRAY_SIZE(chips_init_gr); ++i) |
| 296 | write_gr(chips_init_gr[i].addr, chips_init_gr[i].data); | 294 | write_gr(chips_init_gr[i].addr, chips_init_gr[i].data); |
| 297 | for (i = 0; i < N_ELTS(chips_init_ar); ++i) | 295 | for (i = 0; i < ARRAY_SIZE(chips_init_ar); ++i) |
| 298 | write_ar(chips_init_ar[i].addr, chips_init_ar[i].data); | 296 | write_ar(chips_init_ar[i].addr, chips_init_ar[i].data); |
| 299 | for (i = 0; i < N_ELTS(chips_init_cr); ++i) | 297 | for (i = 0; i < ARRAY_SIZE(chips_init_cr); ++i) |
| 300 | write_cr(chips_init_cr[i].addr, chips_init_cr[i].data); | 298 | write_cr(chips_init_cr[i].addr, chips_init_cr[i].data); |
| 301 | for (i = 0; i < N_ELTS(chips_init_fr); ++i) | 299 | for (i = 0; i < ARRAY_SIZE(chips_init_fr); ++i) |
| 302 | write_fr(chips_init_fr[i].addr, chips_init_fr[i].data); | 300 | write_fr(chips_init_fr[i].addr, chips_init_fr[i].data); |
| 303 | } | 301 | } |
| 304 | 302 | ||
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 6ee449858a5c..4444bef68fba 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig | |||
| @@ -26,6 +26,30 @@ config VGA_CONSOLE | |||
| 26 | # fi | 26 | # fi |
| 27 | # fi | 27 | # fi |
| 28 | 28 | ||
| 29 | config VGACON_SOFT_SCROLLBACK | ||
| 30 | bool "Enable Scrollback Buffer in System RAM" | ||
| 31 | depends on VGA_CONSOLE | ||
| 32 | default n | ||
| 33 | help | ||
| 34 | The scrollback buffer of the standard VGA console is located in | ||
| 35 | the VGA RAM. The size of this RAM is fixed and is quite small. | ||
| 36 | If you require a larger scrollback buffer, this can be placed in | ||
| 37 | System RAM which is dynamically allocated during intialization. | ||
| 38 | Placing the scrollback buffer in System RAM will slightly slow | ||
| 39 | down the console. | ||
| 40 | |||
| 41 | If you want this feature, say 'Y' here and enter the amount of | ||
| 42 | RAM to allocate for this buffer. If unsure, say 'N'. | ||
| 43 | |||
| 44 | config VGACON_SOFT_SCROLLBACK_SIZE | ||
| 45 | int "Scrollback Buffer Size (in KB)" | ||
| 46 | depends on VGACON_SOFT_SCROLLBACK | ||
| 47 | default "64" | ||
| 48 | help | ||
| 49 | Enter the amount of System RAM to allocate for the scrollback | ||
| 50 | buffer. Each 64KB will give you approximately 16 80x25 | ||
| 51 | screenfuls of scrollback buffer | ||
| 52 | |||
| 29 | config VIDEO_SELECT | 53 | config VIDEO_SELECT |
| 30 | bool "Video mode selection support" | 54 | bool "Video mode selection support" |
| 31 | depends on X86 && VGA_CONSOLE | 55 | depends on X86 && VGA_CONSOLE |
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index 4fd07d9eca03..0cc1bfda76a6 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c | |||
| @@ -66,7 +66,7 @@ static const struct font_desc *fonts[] = { | |||
| 66 | #endif | 66 | #endif |
| 67 | }; | 67 | }; |
| 68 | 68 | ||
| 69 | #define num_fonts (sizeof(fonts)/sizeof(*fonts)) | 69 | #define num_fonts ARRAY_SIZE(fonts) |
| 70 | 70 | ||
| 71 | #ifdef NO_FONTS | 71 | #ifdef NO_FONTS |
| 72 | #error No fonts configured. | 72 | #error No fonts configured. |
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index 762c7a593141..e99fe30e568c 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c | |||
| @@ -149,7 +149,7 @@ static inline void newport_clear_lines(int ystart, int yend, int ci) | |||
| 149 | newport_clear_screen(0, ystart, 1280 + 63, yend, ci); | 149 | newport_clear_screen(0, ystart, 1280 + 63, yend, ci); |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | void newport_reset(void) | 152 | static void newport_reset(void) |
| 153 | { | 153 | { |
| 154 | unsigned short treg; | 154 | unsigned short treg; |
| 155 | int i; | 155 | int i; |
| @@ -193,7 +193,7 @@ void newport_reset(void) | |||
| 193 | * calculate the actual screen size by reading | 193 | * calculate the actual screen size by reading |
| 194 | * the video timing out of the VC2 | 194 | * the video timing out of the VC2 |
| 195 | */ | 195 | */ |
| 196 | void newport_get_screensize(void) | 196 | static void newport_get_screensize(void) |
| 197 | { | 197 | { |
| 198 | int i, cols; | 198 | int i, cols; |
| 199 | unsigned short ventry, treg; | 199 | unsigned short ventry, treg; |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 5a86978537d2..d5a04b68c4d4 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
| @@ -93,7 +93,6 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, | |||
| 93 | static void vgacon_invert_region(struct vc_data *c, u16 * p, int count); | 93 | static void vgacon_invert_region(struct vc_data *c, u16 * p, int count); |
| 94 | static unsigned long vgacon_uni_pagedir[2]; | 94 | static unsigned long vgacon_uni_pagedir[2]; |
| 95 | 95 | ||
| 96 | |||
| 97 | /* Description of the hardware situation */ | 96 | /* Description of the hardware situation */ |
| 98 | static unsigned long vga_vram_base; /* Base of video memory */ | 97 | static unsigned long vga_vram_base; /* Base of video memory */ |
| 99 | static unsigned long vga_vram_end; /* End of video memory */ | 98 | static unsigned long vga_vram_end; /* End of video memory */ |
| @@ -161,6 +160,201 @@ static inline void write_vga(unsigned char reg, unsigned int val) | |||
| 161 | spin_unlock_irqrestore(&vga_lock, flags); | 160 | spin_unlock_irqrestore(&vga_lock, flags); |
| 162 | } | 161 | } |
| 163 | 162 | ||
| 163 | static inline void vga_set_mem_top(struct vc_data *c) | ||
| 164 | { | ||
| 165 | write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2); | ||
| 166 | } | ||
| 167 | |||
| 168 | #ifdef CONFIG_VGACON_SOFT_SCROLLBACK | ||
| 169 | #include <linux/bootmem.h> | ||
| 170 | /* software scrollback */ | ||
| 171 | static void *vgacon_scrollback; | ||
| 172 | static int vgacon_scrollback_tail; | ||
| 173 | static int vgacon_scrollback_size; | ||
| 174 | static int vgacon_scrollback_rows; | ||
| 175 | static int vgacon_scrollback_cnt; | ||
| 176 | static int vgacon_scrollback_cur; | ||
| 177 | static int vgacon_scrollback_save; | ||
| 178 | static int vgacon_scrollback_restore; | ||
| 179 | |||
| 180 | static void vgacon_scrollback_init(int pitch) | ||
| 181 | { | ||
| 182 | int rows = CONFIG_VGACON_SOFT_SCROLLBACK_SIZE * 1024/pitch; | ||
| 183 | |||
| 184 | if (vgacon_scrollback) { | ||
| 185 | vgacon_scrollback_cnt = 0; | ||
| 186 | vgacon_scrollback_tail = 0; | ||
| 187 | vgacon_scrollback_cur = 0; | ||
| 188 | vgacon_scrollback_rows = rows - 1; | ||
| 189 | vgacon_scrollback_size = rows * pitch; | ||
| 190 | } | ||
| 191 | } | ||
| 192 | |||
| 193 | static void __init vgacon_scrollback_startup(void) | ||
| 194 | { | ||
| 195 | vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE | ||
| 196 | * 1024); | ||
| 197 | vgacon_scrollback_init(vga_video_num_columns * 2); | ||
| 198 | } | ||
| 199 | |||
| 200 | static void vgacon_scrollback_update(struct vc_data *c, int t, int count) | ||
| 201 | { | ||
| 202 | void *p; | ||
| 203 | |||
| 204 | if (!vgacon_scrollback_size || c->vc_num != fg_console) | ||
| 205 | return; | ||
| 206 | |||
| 207 | p = (void *) (c->vc_origin + t * c->vc_size_row); | ||
| 208 | |||
| 209 | while (count--) { | ||
| 210 | scr_memcpyw(vgacon_scrollback + vgacon_scrollback_tail, | ||
| 211 | p, c->vc_size_row); | ||
| 212 | vgacon_scrollback_cnt++; | ||
| 213 | p += c->vc_size_row; | ||
| 214 | vgacon_scrollback_tail += c->vc_size_row; | ||
| 215 | |||
| 216 | if (vgacon_scrollback_tail >= vgacon_scrollback_size) | ||
| 217 | vgacon_scrollback_tail = 0; | ||
| 218 | |||
| 219 | if (vgacon_scrollback_cnt > vgacon_scrollback_rows) | ||
| 220 | vgacon_scrollback_cnt = vgacon_scrollback_rows; | ||
| 221 | |||
| 222 | vgacon_scrollback_cur = vgacon_scrollback_cnt; | ||
| 223 | } | ||
| 224 | } | ||
| 225 | |||
| 226 | static void vgacon_restore_screen(struct vc_data *c) | ||
| 227 | { | ||
| 228 | vgacon_scrollback_save = 0; | ||
| 229 | |||
| 230 | if (!vga_is_gfx && !vgacon_scrollback_restore) { | ||
| 231 | scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, | ||
| 232 | c->vc_screenbuf_size > vga_vram_size ? | ||
| 233 | vga_vram_size : c->vc_screenbuf_size); | ||
| 234 | vgacon_scrollback_restore = 1; | ||
| 235 | vgacon_scrollback_cur = vgacon_scrollback_cnt; | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | static int vgacon_scrolldelta(struct vc_data *c, int lines) | ||
| 240 | { | ||
| 241 | int start, end, count, soff, diff; | ||
| 242 | void *d, *s; | ||
| 243 | |||
| 244 | if (!lines) { | ||
| 245 | c->vc_visible_origin = c->vc_origin; | ||
| 246 | vga_set_mem_top(c); | ||
| 247 | return 1; | ||
| 248 | } | ||
| 249 | |||
| 250 | if (!vgacon_scrollback) | ||
| 251 | return 1; | ||
| 252 | |||
| 253 | if (!vgacon_scrollback_save) { | ||
| 254 | vgacon_cursor(c, CM_ERASE); | ||
| 255 | vgacon_save_screen(c); | ||
| 256 | vgacon_scrollback_save = 1; | ||
| 257 | } | ||
| 258 | |||
| 259 | vgacon_scrollback_restore = 0; | ||
| 260 | start = vgacon_scrollback_cur + lines; | ||
| 261 | end = start + abs(lines); | ||
| 262 | |||
| 263 | if (start < 0) | ||
| 264 | start = 0; | ||
| 265 | |||
| 266 | if (start > vgacon_scrollback_cnt) | ||
| 267 | start = vgacon_scrollback_cnt; | ||
| 268 | |||
| 269 | if (end < 0) | ||
| 270 | end = 0; | ||
| 271 | |||
| 272 | if (end > vgacon_scrollback_cnt) | ||
| 273 | end = vgacon_scrollback_cnt; | ||
| 274 | |||
| 275 | vgacon_scrollback_cur = start; | ||
| 276 | count = end - start; | ||
| 277 | soff = vgacon_scrollback_tail - ((vgacon_scrollback_cnt - end) * | ||
| 278 | c->vc_size_row); | ||
| 279 | soff -= count * c->vc_size_row; | ||
| 280 | |||
| 281 | if (soff < 0) | ||
| 282 | soff += vgacon_scrollback_size; | ||
| 283 | |||
| 284 | count = vgacon_scrollback_cnt - start; | ||
| 285 | |||
| 286 | if (count > c->vc_rows) | ||
| 287 | count = c->vc_rows; | ||
| 288 | |||
| 289 | diff = c->vc_rows - count; | ||
| 290 | |||
| 291 | d = (void *) c->vc_origin; | ||
| 292 | s = (void *) c->vc_screenbuf; | ||
| 293 | |||
| 294 | while (count--) { | ||
| 295 | scr_memcpyw(d, vgacon_scrollback + soff, c->vc_size_row); | ||
| 296 | d += c->vc_size_row; | ||
| 297 | soff += c->vc_size_row; | ||
| 298 | |||
| 299 | if (soff >= vgacon_scrollback_size) | ||
| 300 | soff = 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | if (diff == c->vc_rows) { | ||
| 304 | vgacon_cursor(c, CM_MOVE); | ||
| 305 | } else { | ||
| 306 | while (diff--) { | ||
| 307 | scr_memcpyw(d, s, c->vc_size_row); | ||
| 308 | d += c->vc_size_row; | ||
| 309 | s += c->vc_size_row; | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | return 1; | ||
| 314 | } | ||
| 315 | #else | ||
| 316 | #define vgacon_scrollback_startup(...) do { } while (0) | ||
| 317 | #define vgacon_scrollback_init(...) do { } while (0) | ||
| 318 | #define vgacon_scrollback_update(...) do { } while (0) | ||
| 319 | |||
| 320 | static void vgacon_restore_screen(struct vc_data *c) | ||
| 321 | { | ||
| 322 | if (c->vc_origin != c->vc_visible_origin) | ||
| 323 | vgacon_scrolldelta(c, 0); | ||
| 324 | } | ||
| 325 | |||
| 326 | static int vgacon_scrolldelta(struct vc_data *c, int lines) | ||
| 327 | { | ||
| 328 | if (!lines) /* Turn scrollback off */ | ||
| 329 | c->vc_visible_origin = c->vc_origin; | ||
| 330 | else { | ||
| 331 | int margin = c->vc_size_row * 4; | ||
| 332 | int ul, we, p, st; | ||
| 333 | |||
| 334 | if (vga_rolled_over > | ||
| 335 | (c->vc_scr_end - vga_vram_base) + margin) { | ||
| 336 | ul = c->vc_scr_end - vga_vram_base; | ||
| 337 | we = vga_rolled_over + c->vc_size_row; | ||
| 338 | } else { | ||
| 339 | ul = 0; | ||
| 340 | we = vga_vram_size; | ||
| 341 | } | ||
| 342 | p = (c->vc_visible_origin - vga_vram_base - ul + we) % we + | ||
| 343 | lines * c->vc_size_row; | ||
| 344 | st = (c->vc_origin - vga_vram_base - ul + we) % we; | ||
| 345 | if (st < 2 * margin) | ||
| 346 | margin = 0; | ||
| 347 | if (p < margin) | ||
| 348 | p = 0; | ||
| 349 | if (p > st - margin) | ||
| 350 | p = st; | ||
| 351 | c->vc_visible_origin = vga_vram_base + (p + ul) % we; | ||
| 352 | } | ||
| 353 | vga_set_mem_top(c); | ||
| 354 | return 1; | ||
| 355 | } | ||
| 356 | #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */ | ||
| 357 | |||
| 164 | static const char __init *vgacon_startup(void) | 358 | static const char __init *vgacon_startup(void) |
| 165 | { | 359 | { |
| 166 | const char *display_desc = NULL; | 360 | const char *display_desc = NULL; |
| @@ -330,7 +524,7 @@ static const char __init *vgacon_startup(void) | |||
| 330 | 524 | ||
| 331 | vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH; | 525 | vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH; |
| 332 | vgacon_yres = vga_scan_lines; | 526 | vgacon_yres = vga_scan_lines; |
| 333 | 527 | vgacon_scrollback_startup(); | |
| 334 | return display_desc; | 528 | return display_desc; |
| 335 | } | 529 | } |
| 336 | 530 | ||
| @@ -357,11 +551,6 @@ static void vgacon_init(struct vc_data *c, int init) | |||
| 357 | con_set_default_unimap(c); | 551 | con_set_default_unimap(c); |
| 358 | } | 552 | } |
| 359 | 553 | ||
| 360 | static inline void vga_set_mem_top(struct vc_data *c) | ||
| 361 | { | ||
| 362 | write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2); | ||
| 363 | } | ||
| 364 | |||
| 365 | static void vgacon_deinit(struct vc_data *c) | 554 | static void vgacon_deinit(struct vc_data *c) |
| 366 | { | 555 | { |
| 367 | /* When closing the last console, reset video origin */ | 556 | /* When closing the last console, reset video origin */ |
| @@ -433,29 +622,37 @@ static void vgacon_set_cursor_size(int xpos, int from, int to) | |||
| 433 | cursor_size_lastto = to; | 622 | cursor_size_lastto = to; |
| 434 | 623 | ||
| 435 | spin_lock_irqsave(&vga_lock, flags); | 624 | spin_lock_irqsave(&vga_lock, flags); |
| 436 | outb_p(0x0a, vga_video_port_reg); /* Cursor start */ | 625 | if (vga_video_type >= VIDEO_TYPE_VGAC) { |
| 437 | curs = inb_p(vga_video_port_val); | 626 | outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg); |
| 438 | outb_p(0x0b, vga_video_port_reg); /* Cursor end */ | 627 | curs = inb_p(vga_video_port_val); |
| 439 | cure = inb_p(vga_video_port_val); | 628 | outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg); |
| 629 | cure = inb_p(vga_video_port_val); | ||
| 630 | } else { | ||
| 631 | curs = 0; | ||
| 632 | cure = 0; | ||
| 633 | } | ||
| 440 | 634 | ||
| 441 | curs = (curs & 0xc0) | from; | 635 | curs = (curs & 0xc0) | from; |
| 442 | cure = (cure & 0xe0) | to; | 636 | cure = (cure & 0xe0) | to; |
| 443 | 637 | ||
| 444 | outb_p(0x0a, vga_video_port_reg); /* Cursor start */ | 638 | outb_p(VGA_CRTC_CURSOR_START, vga_video_port_reg); |
| 445 | outb_p(curs, vga_video_port_val); | 639 | outb_p(curs, vga_video_port_val); |
| 446 | outb_p(0x0b, vga_video_port_reg); /* Cursor end */ | 640 | outb_p(VGA_CRTC_CURSOR_END, vga_video_port_reg); |
| 447 | outb_p(cure, vga_video_port_val); | 641 | outb_p(cure, vga_video_port_val); |
| 448 | spin_unlock_irqrestore(&vga_lock, flags); | 642 | spin_unlock_irqrestore(&vga_lock, flags); |
| 449 | } | 643 | } |
| 450 | 644 | ||
| 451 | static void vgacon_cursor(struct vc_data *c, int mode) | 645 | static void vgacon_cursor(struct vc_data *c, int mode) |
| 452 | { | 646 | { |
| 453 | if (c->vc_origin != c->vc_visible_origin) | 647 | vgacon_restore_screen(c); |
| 454 | vgacon_scrolldelta(c, 0); | 648 | |
| 455 | switch (mode) { | 649 | switch (mode) { |
| 456 | case CM_ERASE: | 650 | case CM_ERASE: |
| 457 | write_vga(14, (c->vc_pos - vga_vram_base) / 2); | 651 | write_vga(14, (c->vc_pos - vga_vram_base) / 2); |
| 458 | vgacon_set_cursor_size(c->vc_x, 31, 30); | 652 | if (vga_video_type >= VIDEO_TYPE_VGAC) |
| 653 | vgacon_set_cursor_size(c->vc_x, 31, 30); | ||
| 654 | else | ||
| 655 | vgacon_set_cursor_size(c->vc_x, 31, 31); | ||
| 459 | break; | 656 | break; |
| 460 | 657 | ||
| 461 | case CM_MOVE: | 658 | case CM_MOVE: |
| @@ -493,7 +690,10 @@ static void vgacon_cursor(struct vc_data *c, int mode) | |||
| 493 | 10 ? 1 : 2)); | 690 | 10 ? 1 : 2)); |
| 494 | break; | 691 | break; |
| 495 | case CUR_NONE: | 692 | case CUR_NONE: |
| 496 | vgacon_set_cursor_size(c->vc_x, 31, 30); | 693 | if (vga_video_type >= VIDEO_TYPE_VGAC) |
| 694 | vgacon_set_cursor_size(c->vc_x, 31, 30); | ||
| 695 | else | ||
| 696 | vgacon_set_cursor_size(c->vc_x, 31, 31); | ||
| 497 | break; | 697 | break; |
| 498 | default: | 698 | default: |
| 499 | vgacon_set_cursor_size(c->vc_x, 1, | 699 | vgacon_set_cursor_size(c->vc_x, 1, |
| @@ -595,6 +795,7 @@ static int vgacon_switch(struct vc_data *c) | |||
| 595 | vgacon_doresize(c, c->vc_cols, c->vc_rows); | 795 | vgacon_doresize(c, c->vc_cols, c->vc_rows); |
| 596 | } | 796 | } |
| 597 | 797 | ||
| 798 | vgacon_scrollback_init(c->vc_size_row); | ||
| 598 | return 0; /* Redrawing not needed */ | 799 | return 0; /* Redrawing not needed */ |
| 599 | } | 800 | } |
| 600 | 801 | ||
| @@ -1062,37 +1263,6 @@ static int vgacon_resize(struct vc_data *c, unsigned int width, | |||
| 1062 | return 0; | 1263 | return 0; |
| 1063 | } | 1264 | } |
| 1064 | 1265 | ||
| 1065 | static int vgacon_scrolldelta(struct vc_data *c, int lines) | ||
| 1066 | { | ||
| 1067 | if (!lines) /* Turn scrollback off */ | ||
| 1068 | c->vc_visible_origin = c->vc_origin; | ||
| 1069 | else { | ||
| 1070 | int margin = c->vc_size_row * 4; | ||
| 1071 | int ul, we, p, st; | ||
| 1072 | |||
| 1073 | if (vga_rolled_over > | ||
| 1074 | (c->vc_scr_end - vga_vram_base) + margin) { | ||
| 1075 | ul = c->vc_scr_end - vga_vram_base; | ||
| 1076 | we = vga_rolled_over + c->vc_size_row; | ||
| 1077 | } else { | ||
| 1078 | ul = 0; | ||
| 1079 | we = vga_vram_size; | ||
| 1080 | } | ||
| 1081 | p = (c->vc_visible_origin - vga_vram_base - ul + we) % we + | ||
| 1082 | lines * c->vc_size_row; | ||
| 1083 | st = (c->vc_origin - vga_vram_base - ul + we) % we; | ||
| 1084 | if (st < 2 * margin) | ||
| 1085 | margin = 0; | ||
| 1086 | if (p < margin) | ||
| 1087 | p = 0; | ||
| 1088 | if (p > st - margin) | ||
| 1089 | p = st; | ||
| 1090 | c->vc_visible_origin = vga_vram_base + (p + ul) % we; | ||
| 1091 | } | ||
| 1092 | vga_set_mem_top(c); | ||
| 1093 | return 1; | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | static int vgacon_set_origin(struct vc_data *c) | 1266 | static int vgacon_set_origin(struct vc_data *c) |
| 1097 | { | 1267 | { |
| 1098 | if (vga_is_gfx || /* We don't play origin tricks in graphic modes */ | 1268 | if (vga_is_gfx || /* We don't play origin tricks in graphic modes */ |
| @@ -1135,15 +1305,14 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, | |||
| 1135 | if (t || b != c->vc_rows || vga_is_gfx) | 1305 | if (t || b != c->vc_rows || vga_is_gfx) |
| 1136 | return 0; | 1306 | return 0; |
| 1137 | 1307 | ||
| 1138 | if (c->vc_origin != c->vc_visible_origin) | ||
| 1139 | vgacon_scrolldelta(c, 0); | ||
| 1140 | |||
| 1141 | if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2) | 1308 | if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2) |
| 1142 | return 0; | 1309 | return 0; |
| 1143 | 1310 | ||
| 1311 | vgacon_restore_screen(c); | ||
| 1144 | oldo = c->vc_origin; | 1312 | oldo = c->vc_origin; |
| 1145 | delta = lines * c->vc_size_row; | 1313 | delta = lines * c->vc_size_row; |
| 1146 | if (dir == SM_UP) { | 1314 | if (dir == SM_UP) { |
| 1315 | vgacon_scrollback_update(c, t, lines); | ||
| 1147 | if (c->vc_scr_end + delta >= vga_vram_end) { | 1316 | if (c->vc_scr_end + delta >= vga_vram_end) { |
| 1148 | scr_memcpyw((u16 *) vga_vram_base, | 1317 | scr_memcpyw((u16 *) vga_vram_base, |
| 1149 | (u16 *) (oldo + delta), | 1318 | (u16 *) (oldo + delta), |
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index c32a2a50bfa2..1f98392a43b3 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c | |||
| @@ -85,7 +85,7 @@ static struct fb_cmap default_16_colors = { | |||
| 85 | * Allocates memory for a colormap @cmap. @len is the | 85 | * Allocates memory for a colormap @cmap. @len is the |
| 86 | * number of entries in the palette. | 86 | * number of entries in the palette. |
| 87 | * | 87 | * |
| 88 | * Returns -1 errno on error, or zero on success. | 88 | * Returns negative errno on error, or zero on success. |
| 89 | * | 89 | * |
| 90 | */ | 90 | */ |
| 91 | 91 | ||
| @@ -116,7 +116,7 @@ int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp) | |||
| 116 | 116 | ||
| 117 | fail: | 117 | fail: |
| 118 | fb_dealloc_cmap(cmap); | 118 | fb_dealloc_cmap(cmap); |
| 119 | return -1; | 119 | return -ENOMEM; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | /** | 122 | /** |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 07d882b14396..b1a8dca76430 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
| @@ -55,7 +55,7 @@ | |||
| 55 | 55 | ||
| 56 | #define FBPIXMAPSIZE (1024 * 8) | 56 | #define FBPIXMAPSIZE (1024 * 8) |
| 57 | 57 | ||
| 58 | static struct notifier_block *fb_notifier_list; | 58 | static BLOCKING_NOTIFIER_HEAD(fb_notifier_list); |
| 59 | struct fb_info *registered_fb[FB_MAX]; | 59 | struct fb_info *registered_fb[FB_MAX]; |
| 60 | int num_registered_fb; | 60 | int num_registered_fb; |
| 61 | 61 | ||
| @@ -784,7 +784,7 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) | |||
| 784 | 784 | ||
| 785 | event.info = info; | 785 | event.info = info; |
| 786 | event.data = &mode1; | 786 | event.data = &mode1; |
| 787 | ret = notifier_call_chain(&fb_notifier_list, | 787 | ret = blocking_notifier_call_chain(&fb_notifier_list, |
| 788 | FB_EVENT_MODE_DELETE, &event); | 788 | FB_EVENT_MODE_DELETE, &event); |
| 789 | } | 789 | } |
| 790 | 790 | ||
| @@ -830,8 +830,8 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) | |||
| 830 | 830 | ||
| 831 | info->flags &= ~FBINFO_MISC_USEREVENT; | 831 | info->flags &= ~FBINFO_MISC_USEREVENT; |
| 832 | event.info = info; | 832 | event.info = info; |
| 833 | notifier_call_chain(&fb_notifier_list, evnt, | 833 | blocking_notifier_call_chain(&fb_notifier_list, |
| 834 | &event); | 834 | evnt, &event); |
| 835 | } | 835 | } |
| 836 | } | 836 | } |
| 837 | } | 837 | } |
| @@ -854,7 +854,8 @@ fb_blank(struct fb_info *info, int blank) | |||
| 854 | 854 | ||
| 855 | event.info = info; | 855 | event.info = info; |
| 856 | event.data = ␣ | 856 | event.data = ␣ |
| 857 | notifier_call_chain(&fb_notifier_list, FB_EVENT_BLANK, &event); | 857 | blocking_notifier_call_chain(&fb_notifier_list, |
| 858 | FB_EVENT_BLANK, &event); | ||
| 858 | } | 859 | } |
| 859 | 860 | ||
| 860 | return ret; | 861 | return ret; |
| @@ -925,7 +926,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 925 | con2fb.framebuffer = -1; | 926 | con2fb.framebuffer = -1; |
| 926 | event.info = info; | 927 | event.info = info; |
| 927 | event.data = &con2fb; | 928 | event.data = &con2fb; |
| 928 | notifier_call_chain(&fb_notifier_list, | 929 | blocking_notifier_call_chain(&fb_notifier_list, |
| 929 | FB_EVENT_GET_CONSOLE_MAP, &event); | 930 | FB_EVENT_GET_CONSOLE_MAP, &event); |
| 930 | return copy_to_user(argp, &con2fb, | 931 | return copy_to_user(argp, &con2fb, |
| 931 | sizeof(con2fb)) ? -EFAULT : 0; | 932 | sizeof(con2fb)) ? -EFAULT : 0; |
| @@ -944,7 +945,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 944 | return -EINVAL; | 945 | return -EINVAL; |
| 945 | event.info = info; | 946 | event.info = info; |
| 946 | event.data = &con2fb; | 947 | event.data = &con2fb; |
| 947 | return notifier_call_chain(&fb_notifier_list, | 948 | return blocking_notifier_call_chain(&fb_notifier_list, |
| 948 | FB_EVENT_SET_CONSOLE_MAP, | 949 | FB_EVENT_SET_CONSOLE_MAP, |
| 949 | &event); | 950 | &event); |
| 950 | case FBIOBLANK: | 951 | case FBIOBLANK: |
| @@ -1324,7 +1325,7 @@ register_framebuffer(struct fb_info *fb_info) | |||
| 1324 | devfs_mk_cdev(MKDEV(FB_MAJOR, i), | 1325 | devfs_mk_cdev(MKDEV(FB_MAJOR, i), |
| 1325 | S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i); | 1326 | S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i); |
| 1326 | event.info = fb_info; | 1327 | event.info = fb_info; |
| 1327 | notifier_call_chain(&fb_notifier_list, | 1328 | blocking_notifier_call_chain(&fb_notifier_list, |
| 1328 | FB_EVENT_FB_REGISTERED, &event); | 1329 | FB_EVENT_FB_REGISTERED, &event); |
| 1329 | return 0; | 1330 | return 0; |
| 1330 | } | 1331 | } |
| @@ -1366,7 +1367,7 @@ unregister_framebuffer(struct fb_info *fb_info) | |||
| 1366 | */ | 1367 | */ |
| 1367 | int fb_register_client(struct notifier_block *nb) | 1368 | int fb_register_client(struct notifier_block *nb) |
| 1368 | { | 1369 | { |
| 1369 | return notifier_chain_register(&fb_notifier_list, nb); | 1370 | return blocking_notifier_chain_register(&fb_notifier_list, nb); |
| 1370 | } | 1371 | } |
| 1371 | 1372 | ||
| 1372 | /** | 1373 | /** |
| @@ -1375,7 +1376,7 @@ int fb_register_client(struct notifier_block *nb) | |||
| 1375 | */ | 1376 | */ |
| 1376 | int fb_unregister_client(struct notifier_block *nb) | 1377 | int fb_unregister_client(struct notifier_block *nb) |
| 1377 | { | 1378 | { |
| 1378 | return notifier_chain_unregister(&fb_notifier_list, nb); | 1379 | return blocking_notifier_chain_unregister(&fb_notifier_list, nb); |
| 1379 | } | 1380 | } |
| 1380 | 1381 | ||
| 1381 | /** | 1382 | /** |
| @@ -1393,11 +1394,13 @@ void fb_set_suspend(struct fb_info *info, int state) | |||
| 1393 | 1394 | ||
| 1394 | event.info = info; | 1395 | event.info = info; |
| 1395 | if (state) { | 1396 | if (state) { |
| 1396 | notifier_call_chain(&fb_notifier_list, FB_EVENT_SUSPEND, &event); | 1397 | blocking_notifier_call_chain(&fb_notifier_list, |
| 1398 | FB_EVENT_SUSPEND, &event); | ||
| 1397 | info->state = FBINFO_STATE_SUSPENDED; | 1399 | info->state = FBINFO_STATE_SUSPENDED; |
| 1398 | } else { | 1400 | } else { |
| 1399 | info->state = FBINFO_STATE_RUNNING; | 1401 | info->state = FBINFO_STATE_RUNNING; |
| 1400 | notifier_call_chain(&fb_notifier_list, FB_EVENT_RESUME, &event); | 1402 | blocking_notifier_call_chain(&fb_notifier_list, |
| 1403 | FB_EVENT_RESUME, &event); | ||
| 1401 | } | 1404 | } |
| 1402 | } | 1405 | } |
| 1403 | 1406 | ||
| @@ -1469,7 +1472,7 @@ int fb_new_modelist(struct fb_info *info) | |||
| 1469 | 1472 | ||
| 1470 | if (!list_empty(&info->modelist)) { | 1473 | if (!list_empty(&info->modelist)) { |
| 1471 | event.info = info; | 1474 | event.info = info; |
| 1472 | err = notifier_call_chain(&fb_notifier_list, | 1475 | err = blocking_notifier_call_chain(&fb_notifier_list, |
| 1473 | FB_EVENT_NEW_MODELIST, | 1476 | FB_EVENT_NEW_MODELIST, |
| 1474 | &event); | 1477 | &event); |
| 1475 | } | 1478 | } |
| @@ -1495,7 +1498,7 @@ int fb_con_duit(struct fb_info *info, int event, void *data) | |||
| 1495 | evnt.info = info; | 1498 | evnt.info = info; |
| 1496 | evnt.data = data; | 1499 | evnt.data = data; |
| 1497 | 1500 | ||
| 1498 | return notifier_call_chain(&fb_notifier_list, event, &evnt); | 1501 | return blocking_notifier_call_chain(&fb_notifier_list, event, &evnt); |
| 1499 | } | 1502 | } |
| 1500 | EXPORT_SYMBOL(fb_con_duit); | 1503 | EXPORT_SYMBOL(fb_con_duit); |
| 1501 | 1504 | ||
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 7c74e7325d95..53beeb4a9998 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c | |||
| @@ -1281,7 +1281,7 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) | |||
| 1281 | -EINVAL : 0; | 1281 | -EINVAL : 0; |
| 1282 | } | 1282 | } |
| 1283 | 1283 | ||
| 1284 | #if defined(__i386__) | 1284 | #if defined(CONFIG_FB_FIRMWARE_EDID) && defined(__i386__) |
| 1285 | #include <linux/pci.h> | 1285 | #include <linux/pci.h> |
| 1286 | 1286 | ||
| 1287 | /* | 1287 | /* |
| @@ -1311,11 +1311,11 @@ const unsigned char *fb_firmware_edid(struct device *device) | |||
| 1311 | { | 1311 | { |
| 1312 | return NULL; | 1312 | return NULL; |
| 1313 | } | 1313 | } |
| 1314 | #endif /* _i386_ */ | 1314 | #endif |
| 1315 | EXPORT_SYMBOL(fb_firmware_edid); | ||
| 1315 | 1316 | ||
| 1316 | EXPORT_SYMBOL(fb_parse_edid); | 1317 | EXPORT_SYMBOL(fb_parse_edid); |
| 1317 | EXPORT_SYMBOL(fb_edid_to_monspecs); | 1318 | EXPORT_SYMBOL(fb_edid_to_monspecs); |
| 1318 | EXPORT_SYMBOL(fb_firmware_edid); | ||
| 1319 | EXPORT_SYMBOL(fb_get_mode); | 1319 | EXPORT_SYMBOL(fb_get_mode); |
| 1320 | EXPORT_SYMBOL(fb_validate_mode); | 1320 | EXPORT_SYMBOL(fb_validate_mode); |
| 1321 | EXPORT_SYMBOL(fb_destroy_modedb); | 1321 | EXPORT_SYMBOL(fb_destroy_modedb); |
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 6d26057337e2..b72b05250a9d 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c | |||
| @@ -348,7 +348,7 @@ static ssize_t store_cmap(struct class_device *class_device, const char *buf, | |||
| 348 | fb_copy_cmap(&umap, &fb_info->cmap); | 348 | fb_copy_cmap(&umap, &fb_info->cmap); |
| 349 | fb_dealloc_cmap(&umap); | 349 | fb_dealloc_cmap(&umap); |
| 350 | 350 | ||
| 351 | return rc; | 351 | return rc ?: count; |
| 352 | } | 352 | } |
| 353 | for (i = 0; i < length; i++) { | 353 | for (i = 0; i < length; i++) { |
| 354 | u16 red, blue, green, tsp; | 354 | u16 red, blue, green, tsp; |
| @@ -367,7 +367,7 @@ static ssize_t store_cmap(struct class_device *class_device, const char *buf, | |||
| 367 | if (transp) | 367 | if (transp) |
| 368 | fb_info->cmap.transp[i] = tsp; | 368 | fb_info->cmap.transp[i] = tsp; |
| 369 | } | 369 | } |
| 370 | return 0; | 370 | return count; |
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | static ssize_t show_cmap(struct class_device *class_device, char *buf) | 373 | static ssize_t show_cmap(struct class_device *class_device, char *buf) |
diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index 42fb9a89a792..4e173ef20a7d 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig | |||
| @@ -8,9 +8,24 @@ config FB_GEODE | |||
| 8 | Say 'Y' here to allow you to select framebuffer drivers for | 8 | Say 'Y' here to allow you to select framebuffer drivers for |
| 9 | the AMD Geode family of processors. | 9 | the AMD Geode family of processors. |
| 10 | 10 | ||
| 11 | config FB_GEODE_GX | ||
| 12 | tristate "AMD Geode GX framebuffer support (EXPERIMENTAL)" | ||
| 13 | depends on FB && FB_GEODE && EXPERIMENTAL | ||
| 14 | select FB_CFB_FILLRECT | ||
| 15 | select FB_CFB_COPYAREA | ||
| 16 | select FB_CFB_IMAGEBLIT | ||
| 17 | ---help--- | ||
| 18 | Framebuffer driver for the display controller integrated into the | ||
| 19 | AMD Geode GX processors. | ||
| 20 | |||
| 21 | To compile this driver as a module, choose M here: the module will be | ||
| 22 | called gxfb. | ||
| 23 | |||
| 24 | If unsure, say N. | ||
| 25 | |||
| 11 | config FB_GEODE_GX1 | 26 | config FB_GEODE_GX1 |
| 12 | tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)" | 27 | tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)" |
| 13 | depends on FB_GEODE && EXPERIMENTAL | 28 | depends on FB && FB_GEODE && EXPERIMENTAL |
| 14 | select FB_CFB_FILLRECT | 29 | select FB_CFB_FILLRECT |
| 15 | select FB_CFB_COPYAREA | 30 | select FB_CFB_COPYAREA |
| 16 | select FB_CFB_IMAGEBLIT | 31 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile index 13ad501ea990..f896565bc312 100644 --- a/drivers/video/geode/Makefile +++ b/drivers/video/geode/Makefile | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | # Makefile for the Geode family framebuffer drivers | 1 | # Makefile for the Geode family framebuffer drivers |
| 2 | 2 | ||
| 3 | obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o | 3 | obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o |
| 4 | obj-$(CONFIG_FB_GEODE_GX) += gxfb.o | ||
| 4 | 5 | ||
| 5 | gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o | 6 | gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o |
| 7 | gxfb-objs := gxfb_core.o display_gx.o video_gx.o | ||
diff --git a/drivers/video/geode/display_gx.c b/drivers/video/geode/display_gx.c new file mode 100644 index 000000000000..825c3405f5c2 --- /dev/null +++ b/drivers/video/geode/display_gx.c | |||
| @@ -0,0 +1,156 @@ | |||
| 1 | /* | ||
| 2 | * Geode GX display controller. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 Arcom Control Systems Ltd. | ||
| 5 | * | ||
| 6 | * Portions from AMD's original 2.4 driver: | ||
| 7 | * Copyright (C) 2004 Advanced Micro Devices, Inc. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by * the | ||
| 11 | * Free Software Foundation; either version 2 of the License, or * (at your | ||
| 12 | * option) any later version. | ||
| 13 | */ | ||
| 14 | #include <linux/spinlock.h> | ||
| 15 | #include <linux/fb.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <asm/io.h> | ||
| 18 | #include <asm/div64.h> | ||
| 19 | #include <asm/delay.h> | ||
| 20 | |||
| 21 | #include "geodefb.h" | ||
| 22 | #include "display_gx.h" | ||
| 23 | |||
| 24 | int gx_frame_buffer_size(void) | ||
| 25 | { | ||
| 26 | /* Assuming 16 MiB. */ | ||
| 27 | return 16*1024*1024; | ||
| 28 | } | ||
| 29 | |||
| 30 | int gx_line_delta(int xres, int bpp) | ||
| 31 | { | ||
| 32 | /* Must be a multiple of 8 bytes. */ | ||
| 33 | return (xres * (bpp >> 3) + 7) & ~0x7; | ||
| 34 | } | ||
| 35 | |||
| 36 | static void gx_set_mode(struct fb_info *info) | ||
| 37 | { | ||
| 38 | struct geodefb_par *par = info->par; | ||
| 39 | u32 gcfg, dcfg; | ||
| 40 | int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal; | ||
| 41 | int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; | ||
| 42 | |||
| 43 | /* Unlock the display controller registers. */ | ||
| 44 | readl(par->dc_regs + DC_UNLOCK); | ||
| 45 | writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK); | ||
| 46 | |||
| 47 | gcfg = readl(par->dc_regs + DC_GENERAL_CFG); | ||
| 48 | dcfg = readl(par->dc_regs + DC_DISPLAY_CFG); | ||
| 49 | |||
| 50 | /* Disable the timing generator. */ | ||
| 51 | dcfg &= ~(DC_DCFG_TGEN); | ||
| 52 | writel(dcfg, par->dc_regs + DC_DISPLAY_CFG); | ||
| 53 | |||
| 54 | /* Wait for pending memory requests before disabling the FIFO load. */ | ||
| 55 | udelay(100); | ||
| 56 | |||
| 57 | /* Disable FIFO load and compression. */ | ||
| 58 | gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE); | ||
| 59 | writel(gcfg, par->dc_regs + DC_GENERAL_CFG); | ||
| 60 | |||
| 61 | /* Setup DCLK and its divisor. */ | ||
| 62 | par->vid_ops->set_dclk(info); | ||
| 63 | |||
| 64 | /* | ||
| 65 | * Setup new mode. | ||
| 66 | */ | ||
| 67 | |||
| 68 | /* Clear all unused feature bits. */ | ||
| 69 | gcfg &= DC_GCFG_YUVM | DC_GCFG_VDSE; | ||
| 70 | dcfg = 0; | ||
| 71 | |||
| 72 | /* Set FIFO priority (default 6/5) and enable. */ | ||
| 73 | /* FIXME: increase fifo priority for 1280x1024 and higher modes? */ | ||
| 74 | gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE; | ||
| 75 | |||
| 76 | /* Framebuffer start offset. */ | ||
| 77 | writel(0, par->dc_regs + DC_FB_ST_OFFSET); | ||
| 78 | |||
| 79 | /* Line delta and line buffer length. */ | ||
| 80 | writel(info->fix.line_length >> 3, par->dc_regs + DC_GFX_PITCH); | ||
| 81 | writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2, | ||
| 82 | par->dc_regs + DC_LINE_SIZE); | ||
| 83 | |||
| 84 | /* Enable graphics and video data and unmask address lines. */ | ||
| 85 | dcfg |= DC_DCFG_GDEN | DC_DCFG_VDEN | DC_DCFG_A20M | DC_DCFG_A18M; | ||
| 86 | |||
| 87 | /* Set pixel format. */ | ||
| 88 | switch (info->var.bits_per_pixel) { | ||
| 89 | case 8: | ||
| 90 | dcfg |= DC_DCFG_DISP_MODE_8BPP; | ||
| 91 | break; | ||
| 92 | case 16: | ||
| 93 | dcfg |= DC_DCFG_DISP_MODE_16BPP; | ||
| 94 | dcfg |= DC_DCFG_16BPP_MODE_565; | ||
| 95 | break; | ||
| 96 | case 32: | ||
| 97 | dcfg |= DC_DCFG_DISP_MODE_24BPP; | ||
| 98 | dcfg |= DC_DCFG_PALB; | ||
| 99 | break; | ||
| 100 | } | ||
| 101 | |||
| 102 | /* Enable timing generator. */ | ||
| 103 | dcfg |= DC_DCFG_TGEN; | ||
| 104 | |||
| 105 | /* Horizontal and vertical timings. */ | ||
| 106 | hactive = info->var.xres; | ||
| 107 | hblankstart = hactive; | ||
| 108 | hsyncstart = hblankstart + info->var.right_margin; | ||
| 109 | hsyncend = hsyncstart + info->var.hsync_len; | ||
| 110 | hblankend = hsyncend + info->var.left_margin; | ||
| 111 | htotal = hblankend; | ||
| 112 | |||
| 113 | vactive = info->var.yres; | ||
| 114 | vblankstart = vactive; | ||
| 115 | vsyncstart = vblankstart + info->var.lower_margin; | ||
| 116 | vsyncend = vsyncstart + info->var.vsync_len; | ||
| 117 | vblankend = vsyncend + info->var.upper_margin; | ||
| 118 | vtotal = vblankend; | ||
| 119 | |||
| 120 | writel((hactive - 1) | ((htotal - 1) << 16), par->dc_regs + DC_H_ACTIVE_TIMING); | ||
| 121 | writel((hblankstart - 1) | ((hblankend - 1) << 16), par->dc_regs + DC_H_BLANK_TIMING); | ||
| 122 | writel((hsyncstart - 1) | ((hsyncend - 1) << 16), par->dc_regs + DC_H_SYNC_TIMING); | ||
| 123 | |||
| 124 | writel((vactive - 1) | ((vtotal - 1) << 16), par->dc_regs + DC_V_ACTIVE_TIMING); | ||
| 125 | writel((vblankstart - 1) | ((vblankend - 1) << 16), par->dc_regs + DC_V_BLANK_TIMING); | ||
| 126 | writel((vsyncstart - 1) | ((vsyncend - 1) << 16), par->dc_regs + DC_V_SYNC_TIMING); | ||
| 127 | |||
| 128 | /* Write final register values. */ | ||
| 129 | writel(dcfg, par->dc_regs + DC_DISPLAY_CFG); | ||
| 130 | writel(gcfg, par->dc_regs + DC_GENERAL_CFG); | ||
| 131 | |||
| 132 | par->vid_ops->configure_display(info); | ||
| 133 | |||
| 134 | /* Relock display controller registers */ | ||
| 135 | writel(0, par->dc_regs + DC_UNLOCK); | ||
| 136 | } | ||
| 137 | |||
| 138 | static void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno, | ||
| 139 | unsigned red, unsigned green, unsigned blue) | ||
| 140 | { | ||
| 141 | struct geodefb_par *par = info->par; | ||
| 142 | int val; | ||
| 143 | |||
| 144 | /* Hardware palette is in RGB 8-8-8 format. */ | ||
| 145 | val = (red << 8) & 0xff0000; | ||
| 146 | val |= (green) & 0x00ff00; | ||
| 147 | val |= (blue >> 8) & 0x0000ff; | ||
| 148 | |||
| 149 | writel(regno, par->dc_regs + DC_PAL_ADDRESS); | ||
| 150 | writel(val, par->dc_regs + DC_PAL_DATA); | ||
| 151 | } | ||
| 152 | |||
| 153 | struct geode_dc_ops gx_dc_ops = { | ||
| 154 | .set_mode = gx_set_mode, | ||
| 155 | .set_palette_reg = gx_set_hw_palette_reg, | ||
| 156 | }; | ||
diff --git a/drivers/video/geode/display_gx.h b/drivers/video/geode/display_gx.h new file mode 100644 index 000000000000..86c623361305 --- /dev/null +++ b/drivers/video/geode/display_gx.h | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | /* | ||
| 2 | * Geode GX display controller | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Arcom Control Systems Ltd. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #ifndef __DISPLAY_GX_H__ | ||
| 12 | #define __DISPLAY_GX_H__ | ||
| 13 | |||
| 14 | int gx_frame_buffer_size(void); | ||
| 15 | int gx_line_delta(int xres, int bpp); | ||
| 16 | |||
| 17 | extern struct geode_dc_ops gx_dc_ops; | ||
| 18 | |||
| 19 | /* Display controller registers */ | ||
| 20 | |||
| 21 | #define DC_UNLOCK 0x00 | ||
| 22 | # define DC_UNLOCK_CODE 0x00004758 | ||
| 23 | |||
| 24 | #define DC_GENERAL_CFG 0x04 | ||
| 25 | # define DC_GCFG_DFLE 0x00000001 | ||
| 26 | # define DC_GCFG_CURE 0x00000002 | ||
| 27 | # define DC_GCFG_ICNE 0x00000004 | ||
| 28 | # define DC_GCFG_VIDE 0x00000008 | ||
| 29 | # define DC_GCFG_CMPE 0x00000020 | ||
| 30 | # define DC_GCFG_DECE 0x00000040 | ||
| 31 | # define DC_GCFG_VGAE 0x00000080 | ||
| 32 | # define DC_GCFG_DFHPSL_MASK 0x00000F00 | ||
| 33 | # define DC_GCFG_DFHPSL_POS 8 | ||
| 34 | # define DC_GCFG_DFHPEL_MASK 0x0000F000 | ||
| 35 | # define DC_GCFG_DFHPEL_POS 12 | ||
| 36 | # define DC_GCFG_STFM 0x00010000 | ||
| 37 | # define DC_GCFG_FDTY 0x00020000 | ||
| 38 | # define DC_GCFG_VGAFT 0x00040000 | ||
| 39 | # define DC_GCFG_VDSE 0x00080000 | ||
| 40 | # define DC_GCFG_YUVM 0x00100000 | ||
| 41 | # define DC_GCFG_VFSL 0x00800000 | ||
| 42 | # define DC_GCFG_SIGE 0x01000000 | ||
| 43 | # define DC_GCFG_SGRE 0x02000000 | ||
| 44 | # define DC_GCFG_SGFR 0x04000000 | ||
| 45 | # define DC_GCFG_CRC_MODE 0x08000000 | ||
| 46 | # define DC_GCFG_DIAG 0x10000000 | ||
| 47 | # define DC_GCFG_CFRW 0x20000000 | ||
| 48 | |||
| 49 | #define DC_DISPLAY_CFG 0x08 | ||
| 50 | # define DC_DCFG_TGEN 0x00000001 | ||
| 51 | # define DC_DCFG_GDEN 0x00000008 | ||
| 52 | # define DC_DCFG_VDEN 0x00000010 | ||
| 53 | # define DC_DCFG_TRUP 0x00000040 | ||
| 54 | # define DC_DCFG_DISP_MODE_MASK 0x00000300 | ||
| 55 | # define DC_DCFG_DISP_MODE_8BPP 0x00000000 | ||
| 56 | # define DC_DCFG_DISP_MODE_16BPP 0x00000100 | ||
| 57 | # define DC_DCFG_DISP_MODE_24BPP 0x00000200 | ||
| 58 | # define DC_DCFG_16BPP_MODE_MASK 0x00000c00 | ||
| 59 | # define DC_DCFG_16BPP_MODE_565 0x00000000 | ||
| 60 | # define DC_DCFG_16BPP_MODE_555 0x00000100 | ||
| 61 | # define DC_DCFG_16BPP_MODE_444 0x00000200 | ||
| 62 | # define DC_DCFG_DCEN 0x00080000 | ||
| 63 | # define DC_DCFG_PALB 0x02000000 | ||
| 64 | # define DC_DCFG_FRLK 0x04000000 | ||
| 65 | # define DC_DCFG_VISL 0x08000000 | ||
| 66 | # define DC_DCFG_FRSL 0x20000000 | ||
| 67 | # define DC_DCFG_A18M 0x40000000 | ||
| 68 | # define DC_DCFG_A20M 0x80000000 | ||
| 69 | |||
| 70 | #define DC_FB_ST_OFFSET 0x10 | ||
| 71 | |||
| 72 | #define DC_LINE_SIZE 0x30 | ||
| 73 | # define DC_LINE_SIZE_FB_LINE_SIZE_MASK 0x000007ff | ||
| 74 | # define DC_LINE_SIZE_FB_LINE_SIZE_POS 0 | ||
| 75 | # define DC_LINE_SIZE_CB_LINE_SIZE_MASK 0x007f0000 | ||
| 76 | # define DC_LINE_SIZE_CB_LINE_SIZE_POS 16 | ||
| 77 | # define DC_LINE_SIZE_VID_LINE_SIZE_MASK 0xff000000 | ||
| 78 | # define DC_LINE_SIZE_VID_LINE_SIZE_POS 24 | ||
| 79 | |||
| 80 | #define DC_GFX_PITCH 0x34 | ||
| 81 | # define DC_GFX_PITCH_FB_PITCH_MASK 0x0000ffff | ||
| 82 | # define DC_GFX_PITCH_FB_PITCH_POS 0 | ||
| 83 | # define DC_GFX_PITCH_CB_PITCH_MASK 0xffff0000 | ||
| 84 | # define DC_GFX_PITCH_CB_PITCH_POS 16 | ||
| 85 | |||
| 86 | #define DC_H_ACTIVE_TIMING 0x40 | ||
| 87 | #define DC_H_BLANK_TIMING 0x44 | ||
| 88 | #define DC_H_SYNC_TIMING 0x48 | ||
| 89 | #define DC_V_ACTIVE_TIMING 0x50 | ||
| 90 | #define DC_V_BLANK_TIMING 0x54 | ||
| 91 | #define DC_V_SYNC_TIMING 0x58 | ||
| 92 | |||
| 93 | #define DC_PAL_ADDRESS 0x70 | ||
| 94 | #define DC_PAL_DATA 0x74 | ||
| 95 | |||
| 96 | #endif /* !__DISPLAY_GX1_H__ */ | ||
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c new file mode 100644 index 000000000000..89c34b15f5d4 --- /dev/null +++ b/drivers/video/geode/gxfb_core.c | |||
| @@ -0,0 +1,423 @@ | |||
| 1 | /* | ||
| 2 | * Geode GX framebuffer driver. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Arcom Control Systems Ltd. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * option) any later version. | ||
| 10 | * | ||
| 11 | * | ||
| 12 | * This driver assumes that the BIOS has created a virtual PCI device header | ||
| 13 | * for the video device. The PCI header is assumed to contain the following | ||
| 14 | * BARs: | ||
| 15 | * | ||
| 16 | * BAR0 - framebuffer memory | ||
| 17 | * BAR1 - graphics processor registers | ||
| 18 | * BAR2 - display controller registers | ||
| 19 | * BAR3 - video processor and flat panel control registers. | ||
| 20 | * | ||
| 21 | * 16 MiB of framebuffer memory is assumed to be available. | ||
| 22 | */ | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/errno.h> | ||
| 26 | #include <linux/string.h> | ||
| 27 | #include <linux/mm.h> | ||
| 28 | #include <linux/tty.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <linux/delay.h> | ||
| 31 | #include <linux/fb.h> | ||
| 32 | #include <linux/init.h> | ||
| 33 | #include <linux/pci.h> | ||
| 34 | |||
| 35 | #include "geodefb.h" | ||
| 36 | #include "display_gx.h" | ||
| 37 | #include "video_gx.h" | ||
| 38 | |||
| 39 | static char mode_option[32] = "640x480-16@60"; | ||
| 40 | |||
| 41 | /* Modes relevant to the GX (taken from modedb.c) */ | ||
| 42 | static const struct fb_videomode __initdata gx_modedb[] = { | ||
| 43 | /* 640x480-60 VESA */ | ||
| 44 | { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, | ||
| 45 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 46 | /* 640x480-75 VESA */ | ||
| 47 | { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3, | ||
| 48 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 49 | /* 640x480-85 VESA */ | ||
| 50 | { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3, | ||
| 51 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 52 | /* 800x600-60 VESA */ | ||
| 53 | { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4, | ||
| 54 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 55 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 56 | /* 800x600-75 VESA */ | ||
| 57 | { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3, | ||
| 58 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 59 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 60 | /* 800x600-85 VESA */ | ||
| 61 | { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3, | ||
| 62 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 63 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 64 | /* 1024x768-60 VESA */ | ||
| 65 | { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6, | ||
| 66 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 67 | /* 1024x768-75 VESA */ | ||
| 68 | { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3, | ||
| 69 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 70 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 71 | /* 1024x768-85 VESA */ | ||
| 72 | { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3, | ||
| 73 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 74 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 75 | /* 1280x960-60 VESA */ | ||
| 76 | { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3, | ||
| 77 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 78 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 79 | /* 1280x960-85 VESA */ | ||
| 80 | { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3, | ||
| 81 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 82 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 83 | /* 1280x1024-60 VESA */ | ||
| 84 | { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, | ||
| 85 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 86 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 87 | /* 1280x1024-75 VESA */ | ||
| 88 | { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3, | ||
| 89 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 90 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 91 | /* 1280x1024-85 VESA */ | ||
| 92 | { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3, | ||
| 93 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 94 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 95 | /* 1600x1200-60 VESA */ | ||
| 96 | { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, | ||
| 97 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 98 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 99 | /* 1600x1200-75 VESA */ | ||
| 100 | { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, | ||
| 101 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 102 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 103 | /* 1600x1200-85 VESA */ | ||
| 104 | { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3, | ||
| 105 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
| 106 | FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | ||
| 107 | }; | ||
| 108 | |||
| 109 | static int gxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | ||
| 110 | { | ||
| 111 | if (var->xres > 1600 || var->yres > 1200) | ||
| 112 | return -EINVAL; | ||
| 113 | if ((var->xres > 1280 || var->yres > 1024) && var->bits_per_pixel > 16) | ||
| 114 | return -EINVAL; | ||
| 115 | |||
| 116 | if (var->bits_per_pixel == 32) { | ||
| 117 | var->red.offset = 16; var->red.length = 8; | ||
| 118 | var->green.offset = 8; var->green.length = 8; | ||
| 119 | var->blue.offset = 0; var->blue.length = 8; | ||
| 120 | } else if (var->bits_per_pixel == 16) { | ||
| 121 | var->red.offset = 11; var->red.length = 5; | ||
| 122 | var->green.offset = 5; var->green.length = 6; | ||
| 123 | var->blue.offset = 0; var->blue.length = 5; | ||
| 124 | } else if (var->bits_per_pixel == 8) { | ||
| 125 | var->red.offset = 0; var->red.length = 8; | ||
| 126 | var->green.offset = 0; var->green.length = 8; | ||
| 127 | var->blue.offset = 0; var->blue.length = 8; | ||
| 128 | } else | ||
| 129 | return -EINVAL; | ||
| 130 | var->transp.offset = 0; var->transp.length = 0; | ||
| 131 | |||
| 132 | /* Enough video memory? */ | ||
| 133 | if (gx_line_delta(var->xres, var->bits_per_pixel) * var->yres > info->fix.smem_len) | ||
| 134 | return -EINVAL; | ||
| 135 | |||
| 136 | /* FIXME: Check timing parameters here? */ | ||
| 137 | |||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | static int gxfb_set_par(struct fb_info *info) | ||
| 142 | { | ||
| 143 | struct geodefb_par *par = info->par; | ||
| 144 | |||
| 145 | if (info->var.bits_per_pixel > 8) { | ||
| 146 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
| 147 | fb_dealloc_cmap(&info->cmap); | ||
| 148 | } else { | ||
| 149 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
| 150 | fb_alloc_cmap(&info->cmap, 1<<info->var.bits_per_pixel, 0); | ||
| 151 | } | ||
| 152 | |||
| 153 | info->fix.line_length = gx_line_delta(info->var.xres, info->var.bits_per_pixel); | ||
| 154 | |||
| 155 | par->dc_ops->set_mode(info); | ||
| 156 | |||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) | ||
| 161 | { | ||
| 162 | chan &= 0xffff; | ||
| 163 | chan >>= 16 - bf->length; | ||
| 164 | return chan << bf->offset; | ||
| 165 | } | ||
| 166 | |||
| 167 | static int gxfb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
| 168 | unsigned blue, unsigned transp, | ||
| 169 | struct fb_info *info) | ||
| 170 | { | ||
| 171 | struct geodefb_par *par = info->par; | ||
| 172 | |||
| 173 | if (info->var.grayscale) { | ||
| 174 | /* grayscale = 0.30*R + 0.59*G + 0.11*B */ | ||
| 175 | red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; | ||
| 176 | } | ||
| 177 | |||
| 178 | /* Truecolor has hardware independent palette */ | ||
| 179 | if (info->fix.visual == FB_VISUAL_TRUECOLOR) { | ||
| 180 | u32 *pal = info->pseudo_palette; | ||
| 181 | u32 v; | ||
| 182 | |||
| 183 | if (regno >= 16) | ||
| 184 | return -EINVAL; | ||
| 185 | |||
| 186 | v = chan_to_field(red, &info->var.red); | ||
| 187 | v |= chan_to_field(green, &info->var.green); | ||
| 188 | v |= chan_to_field(blue, &info->var.blue); | ||
| 189 | |||
| 190 | pal[regno] = v; | ||
| 191 | } else { | ||
| 192 | if (regno >= 256) | ||
| 193 | return -EINVAL; | ||
| 194 | |||
| 195 | par->dc_ops->set_palette_reg(info, regno, red, green, blue); | ||
| 196 | } | ||
| 197 | |||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | static int gxfb_blank(int blank_mode, struct fb_info *info) | ||
| 202 | { | ||
| 203 | struct geodefb_par *par = info->par; | ||
| 204 | |||
| 205 | return par->vid_ops->blank_display(info, blank_mode); | ||
| 206 | } | ||
| 207 | |||
| 208 | static int __init gxfb_map_video_memory(struct fb_info *info, struct pci_dev *dev) | ||
| 209 | { | ||
| 210 | struct geodefb_par *par = info->par; | ||
| 211 | int fb_len; | ||
| 212 | int ret; | ||
| 213 | |||
| 214 | ret = pci_enable_device(dev); | ||
| 215 | if (ret < 0) | ||
| 216 | return ret; | ||
| 217 | |||
| 218 | ret = pci_request_region(dev, 3, "gxfb (video processor)"); | ||
| 219 | if (ret < 0) | ||
| 220 | return ret; | ||
| 221 | par->vid_regs = ioremap(pci_resource_start(dev, 3), | ||
| 222 | pci_resource_len(dev, 3)); | ||
| 223 | if (!par->vid_regs) | ||
| 224 | return -ENOMEM; | ||
| 225 | |||
| 226 | ret = pci_request_region(dev, 2, "gxfb (display controller)"); | ||
| 227 | if (ret < 0) | ||
| 228 | return ret; | ||
| 229 | par->dc_regs = ioremap(pci_resource_start(dev, 2), pci_resource_len(dev, 2)); | ||
| 230 | if (!par->dc_regs) | ||
| 231 | return -ENOMEM; | ||
| 232 | |||
| 233 | ret = pci_request_region(dev, 0, "gxfb (framebuffer)"); | ||
| 234 | if (ret < 0) | ||
| 235 | return ret; | ||
| 236 | if ((fb_len = gx_frame_buffer_size()) < 0) | ||
| 237 | return -ENOMEM; | ||
| 238 | info->fix.smem_start = pci_resource_start(dev, 0); | ||
| 239 | info->fix.smem_len = fb_len; | ||
| 240 | info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); | ||
| 241 | if (!info->screen_base) | ||
| 242 | return -ENOMEM; | ||
| 243 | |||
| 244 | dev_info(&dev->dev, "%d Kibyte of video memory at 0x%lx\n", | ||
| 245 | info->fix.smem_len / 1024, info->fix.smem_start); | ||
| 246 | |||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | |||
| 250 | static struct fb_ops gxfb_ops = { | ||
| 251 | .owner = THIS_MODULE, | ||
| 252 | .fb_check_var = gxfb_check_var, | ||
| 253 | .fb_set_par = gxfb_set_par, | ||
| 254 | .fb_setcolreg = gxfb_setcolreg, | ||
| 255 | .fb_blank = gxfb_blank, | ||
| 256 | /* No HW acceleration for now. */ | ||
| 257 | .fb_fillrect = cfb_fillrect, | ||
| 258 | .fb_copyarea = cfb_copyarea, | ||
| 259 | .fb_imageblit = cfb_imageblit, | ||
| 260 | }; | ||
| 261 | |||
| 262 | static struct fb_info * __init gxfb_init_fbinfo(struct device *dev) | ||
| 263 | { | ||
| 264 | struct geodefb_par *par; | ||
| 265 | struct fb_info *info; | ||
| 266 | |||
| 267 | /* Alloc enough space for the pseudo palette. */ | ||
| 268 | info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, dev); | ||
| 269 | if (!info) | ||
| 270 | return NULL; | ||
| 271 | |||
| 272 | par = info->par; | ||
| 273 | |||
| 274 | strcpy(info->fix.id, "Geode GX"); | ||
| 275 | |||
| 276 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
| 277 | info->fix.type_aux = 0; | ||
| 278 | info->fix.xpanstep = 0; | ||
| 279 | info->fix.ypanstep = 0; | ||
| 280 | info->fix.ywrapstep = 0; | ||
| 281 | info->fix.accel = FB_ACCEL_NONE; | ||
| 282 | |||
| 283 | info->var.nonstd = 0; | ||
| 284 | info->var.activate = FB_ACTIVATE_NOW; | ||
| 285 | info->var.height = -1; | ||
| 286 | info->var.width = -1; | ||
| 287 | info->var.accel_flags = 0; | ||
| 288 | info->var.vmode = FB_VMODE_NONINTERLACED; | ||
| 289 | |||
| 290 | info->fbops = &gxfb_ops; | ||
| 291 | info->flags = FBINFO_DEFAULT; | ||
| 292 | info->node = -1; | ||
| 293 | |||
| 294 | info->pseudo_palette = (void *)par + sizeof(struct geodefb_par); | ||
| 295 | |||
| 296 | info->var.grayscale = 0; | ||
| 297 | |||
| 298 | return info; | ||
| 299 | } | ||
| 300 | |||
| 301 | static int __init gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
| 302 | { | ||
| 303 | struct geodefb_par *par; | ||
| 304 | struct fb_info *info; | ||
| 305 | int ret; | ||
| 306 | |||
| 307 | info = gxfb_init_fbinfo(&pdev->dev); | ||
| 308 | if (!info) | ||
| 309 | return -ENOMEM; | ||
| 310 | par = info->par; | ||
| 311 | |||
| 312 | /* GX display controller and GX video device. */ | ||
| 313 | par->dc_ops = &gx_dc_ops; | ||
| 314 | par->vid_ops = &gx_vid_ops; | ||
| 315 | |||
| 316 | if ((ret = gxfb_map_video_memory(info, pdev)) < 0) { | ||
| 317 | dev_err(&pdev->dev, "failed to map frame buffer or controller registers\n"); | ||
| 318 | goto err; | ||
| 319 | } | ||
| 320 | |||
| 321 | ret = fb_find_mode(&info->var, info, mode_option, | ||
| 322 | gx_modedb, ARRAY_SIZE(gx_modedb), NULL, 16); | ||
| 323 | if (ret == 0 || ret == 4) { | ||
| 324 | dev_err(&pdev->dev, "could not find valid video mode\n"); | ||
| 325 | ret = -EINVAL; | ||
| 326 | goto err; | ||
| 327 | } | ||
| 328 | |||
| 329 | /* Clear the frame buffer of garbage. */ | ||
| 330 | memset_io(info->screen_base, 0, info->fix.smem_len); | ||
| 331 | |||
| 332 | gxfb_check_var(&info->var, info); | ||
| 333 | gxfb_set_par(info); | ||
| 334 | |||
| 335 | if (register_framebuffer(info) < 0) { | ||
| 336 | ret = -EINVAL; | ||
| 337 | goto err; | ||
| 338 | } | ||
| 339 | pci_set_drvdata(pdev, info); | ||
| 340 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); | ||
| 341 | return 0; | ||
| 342 | |||
| 343 | err: | ||
| 344 | if (info->screen_base) { | ||
| 345 | iounmap(info->screen_base); | ||
| 346 | pci_release_region(pdev, 0); | ||
| 347 | } | ||
| 348 | if (par->vid_regs) { | ||
| 349 | iounmap(par->vid_regs); | ||
| 350 | pci_release_region(pdev, 3); | ||
| 351 | } | ||
| 352 | if (par->dc_regs) { | ||
| 353 | iounmap(par->dc_regs); | ||
| 354 | pci_release_region(pdev, 2); | ||
| 355 | } | ||
| 356 | |||
| 357 | pci_disable_device(pdev); | ||
| 358 | |||
| 359 | if (info) | ||
| 360 | framebuffer_release(info); | ||
| 361 | return ret; | ||
| 362 | } | ||
| 363 | |||
| 364 | static void gxfb_remove(struct pci_dev *pdev) | ||
| 365 | { | ||
| 366 | struct fb_info *info = pci_get_drvdata(pdev); | ||
| 367 | struct geodefb_par *par = info->par; | ||
| 368 | |||
| 369 | unregister_framebuffer(info); | ||
| 370 | |||
| 371 | iounmap((void __iomem *)info->screen_base); | ||
| 372 | pci_release_region(pdev, 0); | ||
| 373 | |||
| 374 | iounmap(par->vid_regs); | ||
| 375 | pci_release_region(pdev, 3); | ||
| 376 | |||
| 377 | iounmap(par->dc_regs); | ||
| 378 | pci_release_region(pdev, 2); | ||
| 379 | |||
| 380 | pci_disable_device(pdev); | ||
| 381 | pci_set_drvdata(pdev, NULL); | ||
| 382 | |||
| 383 | framebuffer_release(info); | ||
| 384 | } | ||
| 385 | |||
| 386 | static struct pci_device_id gxfb_id_table[] = { | ||
| 387 | { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_VIDEO, | ||
| 388 | PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, | ||
| 389 | 0xff0000, 0 }, | ||
| 390 | { 0, } | ||
| 391 | }; | ||
| 392 | |||
| 393 | MODULE_DEVICE_TABLE(pci, gxfb_id_table); | ||
| 394 | |||
| 395 | static struct pci_driver gxfb_driver = { | ||
| 396 | .name = "gxfb", | ||
| 397 | .id_table = gxfb_id_table, | ||
| 398 | .probe = gxfb_probe, | ||
| 399 | .remove = gxfb_remove, | ||
| 400 | }; | ||
| 401 | |||
| 402 | static int __init gxfb_init(void) | ||
| 403 | { | ||
| 404 | #ifndef MODULE | ||
| 405 | if (fb_get_options("gxfb", NULL)) | ||
| 406 | return -ENODEV; | ||
| 407 | #endif | ||
| 408 | return pci_register_driver(&gxfb_driver); | ||
| 409 | } | ||
| 410 | |||
| 411 | static void __exit gxfb_cleanup(void) | ||
| 412 | { | ||
| 413 | pci_unregister_driver(&gxfb_driver); | ||
| 414 | } | ||
| 415 | |||
| 416 | module_init(gxfb_init); | ||
| 417 | module_exit(gxfb_cleanup); | ||
| 418 | |||
| 419 | module_param_string(mode, mode_option, sizeof(mode_option), 0444); | ||
| 420 | MODULE_PARM_DESC(mode, "video mode (<x>x<y>[-<bpp>][@<refr>])"); | ||
| 421 | |||
| 422 | MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode GX"); | ||
| 423 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/geode/video_gx.c b/drivers/video/geode/video_gx.c new file mode 100644 index 000000000000..2b2a7880ea75 --- /dev/null +++ b/drivers/video/geode/video_gx.c | |||
| @@ -0,0 +1,262 @@ | |||
| 1 | /* | ||
| 2 | * Geode GX video processor device. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Arcom Control Systems Ltd. | ||
| 5 | * | ||
| 6 | * Portions from AMD's original 2.4 driver: | ||
| 7 | * Copyright (C) 2004 Advanced Micro Devices, Inc. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the | ||
| 11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 12 | * option) any later version. | ||
| 13 | */ | ||
| 14 | #include <linux/fb.h> | ||
| 15 | #include <linux/delay.h> | ||
| 16 | #include <asm/io.h> | ||
| 17 | #include <asm/delay.h> | ||
| 18 | #include <asm/msr.h> | ||
| 19 | |||
| 20 | #include "geodefb.h" | ||
| 21 | #include "video_gx.h" | ||
| 22 | |||
| 23 | |||
| 24 | /* | ||
| 25 | * Tables of register settings for various DOTCLKs. | ||
| 26 | */ | ||
| 27 | struct gx_pll_entry { | ||
| 28 | long pixclock; /* ps */ | ||
| 29 | u32 sys_rstpll_bits; | ||
| 30 | u32 dotpll_value; | ||
| 31 | }; | ||
| 32 | |||
| 33 | #define POSTDIV3 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3) | ||
| 34 | #define PREMULT2 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPREMULT2) | ||
| 35 | #define PREDIV2 ((u32)MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3) | ||
| 36 | |||
| 37 | static const struct gx_pll_entry gx_pll_table_48MHz[] = { | ||
| 38 | { 40123, POSTDIV3, 0x00000BF2 }, /* 24.9230 */ | ||
| 39 | { 39721, 0, 0x00000037 }, /* 25.1750 */ | ||
| 40 | { 35308, POSTDIV3|PREMULT2, 0x00000B1A }, /* 28.3220 */ | ||
| 41 | { 31746, POSTDIV3, 0x000002D2 }, /* 31.5000 */ | ||
| 42 | { 27777, POSTDIV3|PREMULT2, 0x00000FE2 }, /* 36.0000 */ | ||
| 43 | { 26666, POSTDIV3, 0x0000057A }, /* 37.5000 */ | ||
| 44 | { 25000, POSTDIV3, 0x0000030A }, /* 40.0000 */ | ||
| 45 | { 22271, 0, 0x00000063 }, /* 44.9000 */ | ||
| 46 | { 20202, 0, 0x0000054B }, /* 49.5000 */ | ||
| 47 | { 20000, 0, 0x0000026E }, /* 50.0000 */ | ||
| 48 | { 19860, PREMULT2, 0x00000037 }, /* 50.3500 */ | ||
| 49 | { 18518, POSTDIV3|PREMULT2, 0x00000B0D }, /* 54.0000 */ | ||
| 50 | { 17777, 0, 0x00000577 }, /* 56.2500 */ | ||
| 51 | { 17733, 0, 0x000007F7 }, /* 56.3916 */ | ||
| 52 | { 17653, 0, 0x0000057B }, /* 56.6444 */ | ||
| 53 | { 16949, PREMULT2, 0x00000707 }, /* 59.0000 */ | ||
| 54 | { 15873, POSTDIV3|PREMULT2, 0x00000B39 }, /* 63.0000 */ | ||
| 55 | { 15384, POSTDIV3|PREMULT2, 0x00000B45 }, /* 65.0000 */ | ||
| 56 | { 14814, POSTDIV3|PREMULT2, 0x00000FC1 }, /* 67.5000 */ | ||
| 57 | { 14124, POSTDIV3, 0x00000561 }, /* 70.8000 */ | ||
| 58 | { 13888, POSTDIV3, 0x000007E1 }, /* 72.0000 */ | ||
| 59 | { 13426, PREMULT2, 0x00000F4A }, /* 74.4810 */ | ||
| 60 | { 13333, 0, 0x00000052 }, /* 75.0000 */ | ||
| 61 | { 12698, 0, 0x00000056 }, /* 78.7500 */ | ||
| 62 | { 12500, POSTDIV3|PREMULT2, 0x00000709 }, /* 80.0000 */ | ||
| 63 | { 11135, PREMULT2, 0x00000262 }, /* 89.8000 */ | ||
| 64 | { 10582, 0, 0x000002D2 }, /* 94.5000 */ | ||
| 65 | { 10101, PREMULT2, 0x00000B4A }, /* 99.0000 */ | ||
| 66 | { 10000, PREMULT2, 0x00000036 }, /* 100.0000 */ | ||
| 67 | { 9259, 0, 0x000007E2 }, /* 108.0000 */ | ||
| 68 | { 8888, 0, 0x000007F6 }, /* 112.5000 */ | ||
| 69 | { 7692, POSTDIV3|PREMULT2, 0x00000FB0 }, /* 130.0000 */ | ||
| 70 | { 7407, POSTDIV3|PREMULT2, 0x00000B50 }, /* 135.0000 */ | ||
| 71 | { 6349, 0, 0x00000055 }, /* 157.5000 */ | ||
| 72 | { 6172, 0, 0x000009C1 }, /* 162.0000 */ | ||
| 73 | { 5787, PREMULT2, 0x0000002D }, /* 172.798 */ | ||
| 74 | { 5698, 0, 0x000002C1 }, /* 175.5000 */ | ||
| 75 | { 5291, 0, 0x000002D1 }, /* 189.0000 */ | ||
| 76 | { 4938, 0, 0x00000551 }, /* 202.5000 */ | ||
| 77 | { 4357, 0, 0x0000057D }, /* 229.5000 */ | ||
| 78 | }; | ||
| 79 | |||
| 80 | static const struct gx_pll_entry gx_pll_table_14MHz[] = { | ||
| 81 | { 39721, 0, 0x00000037 }, /* 25.1750 */ | ||
| 82 | { 35308, 0, 0x00000B7B }, /* 28.3220 */ | ||
| 83 | { 31746, 0, 0x000004D3 }, /* 31.5000 */ | ||
| 84 | { 27777, 0, 0x00000BE3 }, /* 36.0000 */ | ||
| 85 | { 26666, 0, 0x0000074F }, /* 37.5000 */ | ||
| 86 | { 25000, 0, 0x0000050B }, /* 40.0000 */ | ||
| 87 | { 22271, 0, 0x00000063 }, /* 44.9000 */ | ||
| 88 | { 20202, 0, 0x0000054B }, /* 49.5000 */ | ||
| 89 | { 20000, 0, 0x0000026E }, /* 50.0000 */ | ||
| 90 | { 19860, 0, 0x000007C3 }, /* 50.3500 */ | ||
| 91 | { 18518, 0, 0x000007E3 }, /* 54.0000 */ | ||
| 92 | { 17777, 0, 0x00000577 }, /* 56.2500 */ | ||
| 93 | { 17733, 0, 0x000002FB }, /* 56.3916 */ | ||
| 94 | { 17653, 0, 0x0000057B }, /* 56.6444 */ | ||
| 95 | { 16949, 0, 0x0000058B }, /* 59.0000 */ | ||
| 96 | { 15873, 0, 0x0000095E }, /* 63.0000 */ | ||
| 97 | { 15384, 0, 0x0000096A }, /* 65.0000 */ | ||
| 98 | { 14814, 0, 0x00000BC2 }, /* 67.5000 */ | ||
| 99 | { 14124, 0, 0x0000098A }, /* 70.8000 */ | ||
| 100 | { 13888, 0, 0x00000BE2 }, /* 72.0000 */ | ||
| 101 | { 13333, 0, 0x00000052 }, /* 75.0000 */ | ||
| 102 | { 12698, 0, 0x00000056 }, /* 78.7500 */ | ||
| 103 | { 12500, 0, 0x0000050A }, /* 80.0000 */ | ||
| 104 | { 11135, 0, 0x0000078E }, /* 89.8000 */ | ||
| 105 | { 10582, 0, 0x000002D2 }, /* 94.5000 */ | ||
| 106 | { 10101, 0, 0x000011F6 }, /* 99.0000 */ | ||
| 107 | { 10000, 0, 0x0000054E }, /* 100.0000 */ | ||
| 108 | { 9259, 0, 0x000007E2 }, /* 108.0000 */ | ||
| 109 | { 8888, 0, 0x000002FA }, /* 112.5000 */ | ||
| 110 | { 7692, 0, 0x00000BB1 }, /* 130.0000 */ | ||
| 111 | { 7407, 0, 0x00000975 }, /* 135.0000 */ | ||
| 112 | { 6349, 0, 0x00000055 }, /* 157.5000 */ | ||
| 113 | { 6172, 0, 0x000009C1 }, /* 162.0000 */ | ||
| 114 | { 5698, 0, 0x000002C1 }, /* 175.5000 */ | ||
| 115 | { 5291, 0, 0x00000539 }, /* 189.0000 */ | ||
| 116 | { 4938, 0, 0x00000551 }, /* 202.5000 */ | ||
| 117 | { 4357, 0, 0x0000057D }, /* 229.5000 */ | ||
| 118 | }; | ||
| 119 | |||
| 120 | static void gx_set_dclk_frequency(struct fb_info *info) | ||
| 121 | { | ||
| 122 | const struct gx_pll_entry *pll_table; | ||
| 123 | int pll_table_len; | ||
| 124 | int i, best_i; | ||
| 125 | long min, diff; | ||
| 126 | u64 dotpll, sys_rstpll; | ||
| 127 | int timeout = 1000; | ||
| 128 | |||
| 129 | /* Rev. 1 Geode GXs use a 14 MHz reference clock instead of 48 MHz. */ | ||
| 130 | if (cpu_data->x86_mask == 1) { | ||
| 131 | pll_table = gx_pll_table_14MHz; | ||
| 132 | pll_table_len = ARRAY_SIZE(gx_pll_table_14MHz); | ||
| 133 | } else { | ||
| 134 | pll_table = gx_pll_table_48MHz; | ||
| 135 | pll_table_len = ARRAY_SIZE(gx_pll_table_48MHz); | ||
| 136 | } | ||
| 137 | |||
| 138 | /* Search the table for the closest pixclock. */ | ||
| 139 | best_i = 0; | ||
| 140 | min = abs(pll_table[0].pixclock - info->var.pixclock); | ||
| 141 | for (i = 1; i < pll_table_len; i++) { | ||
| 142 | diff = abs(pll_table[i].pixclock - info->var.pixclock); | ||
| 143 | if (diff < min) { | ||
| 144 | min = diff; | ||
| 145 | best_i = i; | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | rdmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll); | ||
| 150 | rdmsrl(MSR_GLCP_DOTPLL, dotpll); | ||
| 151 | |||
| 152 | /* Program new M, N and P. */ | ||
| 153 | dotpll &= 0x00000000ffffffffull; | ||
| 154 | dotpll |= (u64)pll_table[best_i].dotpll_value << 32; | ||
| 155 | dotpll |= MSR_GLCP_DOTPLL_DOTRESET; | ||
| 156 | dotpll &= ~MSR_GLCP_DOTPLL_BYPASS; | ||
| 157 | |||
| 158 | wrmsrl(MSR_GLCP_DOTPLL, dotpll); | ||
| 159 | |||
| 160 | /* Program dividers. */ | ||
| 161 | sys_rstpll &= ~( MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 | ||
| 162 | | MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 | ||
| 163 | | MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 ); | ||
| 164 | sys_rstpll |= pll_table[best_i].sys_rstpll_bits; | ||
| 165 | |||
| 166 | wrmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll); | ||
| 167 | |||
| 168 | /* Clear reset bit to start PLL. */ | ||
| 169 | dotpll &= ~(MSR_GLCP_DOTPLL_DOTRESET); | ||
| 170 | wrmsrl(MSR_GLCP_DOTPLL, dotpll); | ||
| 171 | |||
| 172 | /* Wait for LOCK bit. */ | ||
| 173 | do { | ||
| 174 | rdmsrl(MSR_GLCP_DOTPLL, dotpll); | ||
| 175 | } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK)); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void gx_configure_display(struct fb_info *info) | ||
| 179 | { | ||
| 180 | struct geodefb_par *par = info->par; | ||
| 181 | u32 dcfg, fp_pm; | ||
| 182 | |||
| 183 | dcfg = readl(par->vid_regs + GX_DCFG); | ||
| 184 | |||
| 185 | /* Clear bits from existing mode. */ | ||
| 186 | dcfg &= ~(GX_DCFG_CRT_SYNC_SKW_MASK | ||
| 187 | | GX_DCFG_CRT_HSYNC_POL | GX_DCFG_CRT_VSYNC_POL | ||
| 188 | | GX_DCFG_VSYNC_EN | GX_DCFG_HSYNC_EN); | ||
| 189 | |||
| 190 | /* Set default sync skew. */ | ||
| 191 | dcfg |= GX_DCFG_CRT_SYNC_SKW_DFLT; | ||
| 192 | |||
| 193 | /* Enable hsync and vsync. */ | ||
| 194 | dcfg |= GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN; | ||
| 195 | |||
| 196 | /* Sync polarities. */ | ||
| 197 | if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) | ||
| 198 | dcfg |= GX_DCFG_CRT_HSYNC_POL; | ||
| 199 | if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) | ||
| 200 | dcfg |= GX_DCFG_CRT_VSYNC_POL; | ||
| 201 | |||
| 202 | writel(dcfg, par->vid_regs + GX_DCFG); | ||
| 203 | |||
| 204 | /* Power on flat panel. */ | ||
| 205 | fp_pm = readl(par->vid_regs + GX_FP_PM); | ||
| 206 | fp_pm |= GX_FP_PM_P; | ||
| 207 | writel(fp_pm, par->vid_regs + GX_FP_PM); | ||
| 208 | } | ||
| 209 | |||
| 210 | static int gx_blank_display(struct fb_info *info, int blank_mode) | ||
| 211 | { | ||
| 212 | struct geodefb_par *par = info->par; | ||
| 213 | u32 dcfg, fp_pm; | ||
| 214 | int blank, hsync, vsync; | ||
| 215 | |||
| 216 | /* CRT power saving modes. */ | ||
| 217 | switch (blank_mode) { | ||
| 218 | case FB_BLANK_UNBLANK: | ||
| 219 | blank = 0; hsync = 1; vsync = 1; | ||
| 220 | break; | ||
| 221 | case FB_BLANK_NORMAL: | ||
| 222 | blank = 1; hsync = 1; vsync = 1; | ||
| 223 | break; | ||
| 224 | case FB_BLANK_VSYNC_SUSPEND: | ||
| 225 | blank = 1; hsync = 1; vsync = 0; | ||
| 226 | break; | ||
| 227 | case FB_BLANK_HSYNC_SUSPEND: | ||
| 228 | blank = 1; hsync = 0; vsync = 1; | ||
| 229 | break; | ||
| 230 | case FB_BLANK_POWERDOWN: | ||
| 231 | blank = 1; hsync = 0; vsync = 0; | ||
| 232 | break; | ||
| 233 | default: | ||
| 234 | return -EINVAL; | ||
| 235 | } | ||
| 236 | dcfg = readl(par->vid_regs + GX_DCFG); | ||
| 237 | dcfg &= ~(GX_DCFG_DAC_BL_EN | ||
| 238 | | GX_DCFG_HSYNC_EN | GX_DCFG_VSYNC_EN); | ||
| 239 | if (!blank) | ||
| 240 | dcfg |= GX_DCFG_DAC_BL_EN; | ||
| 241 | if (hsync) | ||
| 242 | dcfg |= GX_DCFG_HSYNC_EN; | ||
| 243 | if (vsync) | ||
| 244 | dcfg |= GX_DCFG_VSYNC_EN; | ||
| 245 | writel(dcfg, par->vid_regs + GX_DCFG); | ||
| 246 | |||
| 247 | /* Power on/off flat panel. */ | ||
| 248 | fp_pm = readl(par->vid_regs + GX_FP_PM); | ||
| 249 | if (blank_mode == FB_BLANK_POWERDOWN) | ||
| 250 | fp_pm &= ~GX_FP_PM_P; | ||
| 251 | else | ||
| 252 | fp_pm |= GX_FP_PM_P; | ||
| 253 | writel(fp_pm, par->vid_regs + GX_FP_PM); | ||
| 254 | |||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | struct geode_vid_ops gx_vid_ops = { | ||
| 259 | .set_dclk = gx_set_dclk_frequency, | ||
| 260 | .configure_display = gx_configure_display, | ||
| 261 | .blank_display = gx_blank_display, | ||
| 262 | }; | ||
diff --git a/drivers/video/geode/video_gx.h b/drivers/video/geode/video_gx.h new file mode 100644 index 000000000000..2d9211f3ed84 --- /dev/null +++ b/drivers/video/geode/video_gx.h | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | /* | ||
| 2 | * Geode GX video device | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Arcom Control Systems Ltd. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #ifndef __VIDEO_GX_H__ | ||
| 12 | #define __VIDEO_GX_H__ | ||
| 13 | |||
| 14 | extern struct geode_vid_ops gx_vid_ops; | ||
| 15 | |||
| 16 | /* Geode GX video processor registers */ | ||
| 17 | |||
| 18 | #define GX_DCFG 0x0008 | ||
| 19 | # define GX_DCFG_CRT_EN 0x00000001 | ||
| 20 | # define GX_DCFG_HSYNC_EN 0x00000002 | ||
| 21 | # define GX_DCFG_VSYNC_EN 0x00000004 | ||
| 22 | # define GX_DCFG_DAC_BL_EN 0x00000008 | ||
| 23 | # define GX_DCFG_CRT_HSYNC_POL 0x00000100 | ||
| 24 | # define GX_DCFG_CRT_VSYNC_POL 0x00000200 | ||
| 25 | # define GX_DCFG_CRT_SYNC_SKW_MASK 0x0001C000 | ||
| 26 | # define GX_DCFG_CRT_SYNC_SKW_DFLT 0x00010000 | ||
| 27 | # define GX_DCFG_VG_CK 0x00100000 | ||
| 28 | # define GX_DCFG_GV_GAM 0x00200000 | ||
| 29 | # define GX_DCFG_DAC_VREF 0x04000000 | ||
| 30 | |||
| 31 | /* Geode GX flat panel display control registers */ | ||
| 32 | #define GX_FP_PM 0x410 | ||
| 33 | # define GX_FP_PM_P 0x01000000 | ||
| 34 | |||
| 35 | /* Geode GX clock control MSRs */ | ||
| 36 | |||
| 37 | #define MSR_GLCP_SYS_RSTPLL 0x4c000014 | ||
| 38 | # define MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 (0x0000000000000002ull) | ||
| 39 | # define MSR_GLCP_SYS_RSTPLL_DOTPREMULT2 (0x0000000000000004ull) | ||
| 40 | # define MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 (0x0000000000000008ull) | ||
| 41 | |||
| 42 | #define MSR_GLCP_DOTPLL 0x4c000015 | ||
| 43 | # define MSR_GLCP_DOTPLL_DOTRESET (0x0000000000000001ull) | ||
| 44 | # define MSR_GLCP_DOTPLL_BYPASS (0x0000000000008000ull) | ||
| 45 | # define MSR_GLCP_DOTPLL_LOCK (0x0000000002000000ull) | ||
| 46 | |||
| 47 | #endif /* !__VIDEO_GX_H__ */ | ||
diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/i810/i810-i2c.c index e3c8b5f1ca76..3fe3ae1aff12 100644 --- a/drivers/video/i810/i810-i2c.c +++ b/drivers/video/i810/i810-i2c.c | |||
| @@ -210,8 +210,7 @@ int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) | |||
| 210 | } | 210 | } |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | if (out_edid) | 213 | *out_edid = edid; |
| 214 | *out_edid = edid; | ||
| 215 | 214 | ||
| 216 | return (edid) ? 0 : 1; | 215 | return (edid) ? 0 : 1; |
| 217 | } | 216 | } |
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index 7db42542eb19..f73c642b50c2 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c | |||
| @@ -440,9 +440,9 @@ getclkMHz(struct imstt_par *par) | |||
| 440 | static void | 440 | static void |
| 441 | setclkMHz(struct imstt_par *par, __u32 MHz) | 441 | setclkMHz(struct imstt_par *par, __u32 MHz) |
| 442 | { | 442 | { |
| 443 | __u32 clk_m, clk_n, clk_p, x, stage, spilled; | 443 | __u32 clk_m, clk_n, x, stage, spilled; |
| 444 | 444 | ||
| 445 | clk_m = clk_n = clk_p = 0; | 445 | clk_m = clk_n = 0; |
| 446 | stage = spilled = 0; | 446 | stage = spilled = 0; |
| 447 | for (;;) { | 447 | for (;;) { |
| 448 | switch (stage) { | 448 | switch (stage) { |
| @@ -453,7 +453,7 @@ setclkMHz(struct imstt_par *par, __u32 MHz) | |||
| 453 | clk_n++; | 453 | clk_n++; |
| 454 | break; | 454 | break; |
| 455 | } | 455 | } |
| 456 | x = 20 * (clk_m + 1) / ((clk_n + 1) * (clk_p ? 2 * clk_p : 1)); | 456 | x = 20 * (clk_m + 1) / (clk_n + 1); |
| 457 | if (x == MHz) | 457 | if (x == MHz) |
| 458 | break; | 458 | break; |
| 459 | if (x > MHz) { | 459 | if (x > MHz) { |
| @@ -466,7 +466,7 @@ setclkMHz(struct imstt_par *par, __u32 MHz) | |||
| 466 | 466 | ||
| 467 | par->init.pclk_m = clk_m; | 467 | par->init.pclk_m = clk_m; |
| 468 | par->init.pclk_n = clk_n; | 468 | par->init.pclk_n = clk_n; |
| 469 | par->init.pclk_p = clk_p; | 469 | par->init.pclk_p = 0; |
| 470 | } | 470 | } |
| 471 | 471 | ||
| 472 | static struct imstt_regvals * | 472 | static struct imstt_regvals * |
| @@ -1372,18 +1372,24 @@ init_imstt(struct fb_info *info) | |||
| 1372 | write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1); | 1372 | write_reg_le32(par->dc_regs, STGCTL, tmp & ~0x1); |
| 1373 | write_reg_le32(par->dc_regs, SSR, 0); | 1373 | write_reg_le32(par->dc_regs, SSR, 0); |
| 1374 | 1374 | ||
| 1375 | /* set default values for DAC registers */ | 1375 | /* set default values for DAC registers */ |
| 1376 | if (par->ramdac == IBM) { | 1376 | if (par->ramdac == IBM) { |
| 1377 | par->cmap_regs[PPMASK] = 0xff; eieio(); | 1377 | par->cmap_regs[PPMASK] = 0xff; |
| 1378 | par->cmap_regs[PIDXHI] = 0; eieio(); | 1378 | eieio(); |
| 1379 | for (i = 0; i < sizeof(ibm_initregs) / sizeof(*ibm_initregs); i++) { | 1379 | par->cmap_regs[PIDXHI] = 0; |
| 1380 | par->cmap_regs[PIDXLO] = ibm_initregs[i].addr; eieio(); | 1380 | eieio(); |
| 1381 | par->cmap_regs[PIDXDATA] = ibm_initregs[i].value; eieio(); | 1381 | for (i = 0; i < ARRAY_SIZE(ibm_initregs); i++) { |
| 1382 | par->cmap_regs[PIDXLO] = ibm_initregs[i].addr; | ||
| 1383 | eieio(); | ||
| 1384 | par->cmap_regs[PIDXDATA] = ibm_initregs[i].value; | ||
| 1385 | eieio(); | ||
| 1382 | } | 1386 | } |
| 1383 | } else { | 1387 | } else { |
| 1384 | for (i = 0; i < sizeof(tvp_initregs) / sizeof(*tvp_initregs); i++) { | 1388 | for (i = 0; i < ARRAY_SIZE(tvp_initregs); i++) { |
| 1385 | par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr; eieio(); | 1389 | par->cmap_regs[TVPADDRW] = tvp_initregs[i].addr; |
| 1386 | par->cmap_regs[TVPIDATA] = tvp_initregs[i].value; eieio(); | 1390 | eieio(); |
| 1391 | par->cmap_regs[TVPIDATA] = tvp_initregs[i].value; | ||
| 1392 | eieio(); | ||
| 1387 | } | 1393 | } |
| 1388 | } | 1394 | } |
| 1389 | 1395 | ||
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c index 2fc71081f7e7..c0385c6f7db5 100644 --- a/drivers/video/macmodes.c +++ b/drivers/video/macmodes.c | |||
| @@ -380,7 +380,7 @@ int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info, | |||
| 380 | if (mode_option && !strncmp(mode_option, "mac", 3)) { | 380 | if (mode_option && !strncmp(mode_option, "mac", 3)) { |
| 381 | mode_option += 3; | 381 | mode_option += 3; |
| 382 | db = mac_modedb; | 382 | db = mac_modedb; |
| 383 | dbsize = sizeof(mac_modedb)/sizeof(*mac_modedb); | 383 | dbsize = ARRAY_SIZE(mac_modedb); |
| 384 | } | 384 | } |
| 385 | return fb_find_mode(var, info, mode_option, db, dbsize, | 385 | return fb_find_mode(var, info, mode_option, db, dbsize, |
| 386 | &mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp); | 386 | &mac_modedb[DEFAULT_MODEDB_INDEX], default_bpp); |
diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c index c122d8743dd2..4d610b405d45 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c | |||
| @@ -59,7 +59,7 @@ static const struct mctl g450_controls[] = | |||
| 59 | }, offsetof(struct matrox_fb_info, altout.tvo_params.testout) }, | 59 | }, offsetof(struct matrox_fb_info, altout.tvo_params.testout) }, |
| 60 | }; | 60 | }; |
| 61 | 61 | ||
| 62 | #define G450CTRLS (sizeof(g450_controls)/sizeof(g450_controls[0])) | 62 | #define G450CTRLS ARRAY_SIZE(g450_controls) |
| 63 | 63 | ||
| 64 | /* Return: positive number: id found | 64 | /* Return: positive number: id found |
| 65 | -EINVAL: id not found, return failure | 65 | -EINVAL: id not found, return failure |
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index 6019710dc298..5d29a26b8cdf 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c | |||
| @@ -89,12 +89,12 @@ static const struct mctl maven_controls[] = | |||
| 89 | }, offsetof(struct matrox_fb_info, altout.tvo_params.hue) }, | 89 | }, offsetof(struct matrox_fb_info, altout.tvo_params.hue) }, |
| 90 | { { V4L2_CID_GAMMA, V4L2_CTRL_TYPE_INTEGER, | 90 | { { V4L2_CID_GAMMA, V4L2_CTRL_TYPE_INTEGER, |
| 91 | "gamma", | 91 | "gamma", |
| 92 | 0, sizeof(maven_gamma)/sizeof(maven_gamma[0])-1, 1, 3, | 92 | 0, ARRAY_SIZE(maven_gamma) - 1, 1, 3, |
| 93 | 0, | 93 | 0, |
| 94 | }, offsetof(struct matrox_fb_info, altout.tvo_params.gamma) }, | 94 | }, offsetof(struct matrox_fb_info, altout.tvo_params.gamma) }, |
| 95 | { { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN, | 95 | { { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN, |
| 96 | "test output", | 96 | "test output", |
| 97 | 0, 1, 1, 0, | 97 | 0, 1, 1, 0, |
| 98 | 0, | 98 | 0, |
| 99 | }, offsetof(struct matrox_fb_info, altout.tvo_params.testout) }, | 99 | }, offsetof(struct matrox_fb_info, altout.tvo_params.testout) }, |
| 100 | { { MATROXFB_CID_DEFLICKER, V4L2_CTRL_TYPE_INTEGER, | 100 | { { MATROXFB_CID_DEFLICKER, V4L2_CTRL_TYPE_INTEGER, |
| @@ -105,7 +105,7 @@ static const struct mctl maven_controls[] = | |||
| 105 | 105 | ||
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | #define MAVCTRLS (sizeof(maven_controls)/sizeof(maven_controls[0])) | 108 | #define MAVCTRLS ARRAY_SIZE(maven_controls) |
| 109 | 109 | ||
| 110 | /* Return: positive number: id found | 110 | /* Return: positive number: id found |
| 111 | -EINVAL: id not found, return failure | 111 | -EINVAL: id not found, return failure |
| @@ -129,7 +129,7 @@ static int get_ctrl_id(__u32 v4l2_id) { | |||
| 129 | 129 | ||
| 130 | struct maven_data { | 130 | struct maven_data { |
| 131 | struct matrox_fb_info* primary_head; | 131 | struct matrox_fb_info* primary_head; |
| 132 | struct i2c_client* client; | 132 | struct i2c_client client; |
| 133 | int version; | 133 | int version; |
| 134 | }; | 134 | }; |
| 135 | 135 | ||
| @@ -970,7 +970,7 @@ static inline int maven_compute_timming(struct maven_data* md, | |||
| 970 | 970 | ||
| 971 | static int maven_program_timming(struct maven_data* md, | 971 | static int maven_program_timming(struct maven_data* md, |
| 972 | const struct mavenregs* m) { | 972 | const struct mavenregs* m) { |
| 973 | struct i2c_client* c = md->client; | 973 | struct i2c_client* c = &md->client; |
| 974 | 974 | ||
| 975 | if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) { | 975 | if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) { |
| 976 | LR(0x80); | 976 | LR(0x80); |
| @@ -1007,7 +1007,7 @@ static int maven_program_timming(struct maven_data* md, | |||
| 1007 | } | 1007 | } |
| 1008 | 1008 | ||
| 1009 | static inline int maven_resync(struct maven_data* md) { | 1009 | static inline int maven_resync(struct maven_data* md) { |
| 1010 | struct i2c_client* c = md->client; | 1010 | struct i2c_client* c = &md->client; |
| 1011 | maven_set_reg(c, 0x95, 0x20); /* start whole thing */ | 1011 | maven_set_reg(c, 0x95, 0x20); /* start whole thing */ |
| 1012 | return 0; | 1012 | return 0; |
| 1013 | } | 1013 | } |
| @@ -1065,48 +1065,48 @@ static int maven_set_control (struct maven_data* md, | |||
| 1065 | maven_compute_bwlevel(md, &blacklevel, &whitelevel); | 1065 | maven_compute_bwlevel(md, &blacklevel, &whitelevel); |
| 1066 | blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8); | 1066 | blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8); |
| 1067 | whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8); | 1067 | whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8); |
| 1068 | maven_set_reg_pair(md->client, 0x0e, blacklevel); | 1068 | maven_set_reg_pair(&md->client, 0x0e, blacklevel); |
| 1069 | maven_set_reg_pair(md->client, 0x1e, whitelevel); | 1069 | maven_set_reg_pair(&md->client, 0x1e, whitelevel); |
| 1070 | } | 1070 | } |
| 1071 | break; | 1071 | break; |
| 1072 | case V4L2_CID_SATURATION: | 1072 | case V4L2_CID_SATURATION: |
| 1073 | { | 1073 | { |
| 1074 | maven_set_reg(md->client, 0x20, p->value); | 1074 | maven_set_reg(&md->client, 0x20, p->value); |
| 1075 | maven_set_reg(md->client, 0x22, p->value); | 1075 | maven_set_reg(&md->client, 0x22, p->value); |
| 1076 | } | 1076 | } |
| 1077 | break; | 1077 | break; |
| 1078 | case V4L2_CID_HUE: | 1078 | case V4L2_CID_HUE: |
| 1079 | { | 1079 | { |
| 1080 | maven_set_reg(md->client, 0x25, p->value); | 1080 | maven_set_reg(&md->client, 0x25, p->value); |
| 1081 | } | 1081 | } |
| 1082 | break; | 1082 | break; |
| 1083 | case V4L2_CID_GAMMA: | 1083 | case V4L2_CID_GAMMA: |
| 1084 | { | 1084 | { |
| 1085 | const struct maven_gamma* g; | 1085 | const struct maven_gamma* g; |
| 1086 | g = maven_compute_gamma(md); | 1086 | g = maven_compute_gamma(md); |
| 1087 | maven_set_reg(md->client, 0x83, g->reg83); | 1087 | maven_set_reg(&md->client, 0x83, g->reg83); |
| 1088 | maven_set_reg(md->client, 0x84, g->reg84); | 1088 | maven_set_reg(&md->client, 0x84, g->reg84); |
| 1089 | maven_set_reg(md->client, 0x85, g->reg85); | 1089 | maven_set_reg(&md->client, 0x85, g->reg85); |
| 1090 | maven_set_reg(md->client, 0x86, g->reg86); | 1090 | maven_set_reg(&md->client, 0x86, g->reg86); |
| 1091 | maven_set_reg(md->client, 0x87, g->reg87); | 1091 | maven_set_reg(&md->client, 0x87, g->reg87); |
| 1092 | maven_set_reg(md->client, 0x88, g->reg88); | 1092 | maven_set_reg(&md->client, 0x88, g->reg88); |
| 1093 | maven_set_reg(md->client, 0x89, g->reg89); | 1093 | maven_set_reg(&md->client, 0x89, g->reg89); |
| 1094 | maven_set_reg(md->client, 0x8a, g->reg8a); | 1094 | maven_set_reg(&md->client, 0x8a, g->reg8a); |
| 1095 | maven_set_reg(md->client, 0x8b, g->reg8b); | 1095 | maven_set_reg(&md->client, 0x8b, g->reg8b); |
| 1096 | } | 1096 | } |
| 1097 | break; | 1097 | break; |
| 1098 | case MATROXFB_CID_TESTOUT: | 1098 | case MATROXFB_CID_TESTOUT: |
| 1099 | { | 1099 | { |
| 1100 | unsigned char val | 1100 | unsigned char val |
| 1101 | = maven_get_reg (md->client,0x8d); | 1101 | = maven_get_reg(&md->client,0x8d); |
| 1102 | if (p->value) val |= 0x10; | 1102 | if (p->value) val |= 0x10; |
| 1103 | else val &= ~0x10; | 1103 | else val &= ~0x10; |
| 1104 | maven_set_reg (md->client, 0x8d, val); | 1104 | maven_set_reg(&md->client, 0x8d, val); |
| 1105 | } | 1105 | } |
| 1106 | break; | 1106 | break; |
| 1107 | case MATROXFB_CID_DEFLICKER: | 1107 | case MATROXFB_CID_DEFLICKER: |
| 1108 | { | 1108 | { |
| 1109 | maven_set_reg(md->client, 0x93, maven_compute_deflicker(md)); | 1109 | maven_set_reg(&md->client, 0x93, maven_compute_deflicker(md)); |
| 1110 | } | 1110 | } |
| 1111 | break; | 1111 | break; |
| 1112 | } | 1112 | } |
| @@ -1185,7 +1185,6 @@ static int maven_init_client(struct i2c_client* clnt) { | |||
| 1185 | MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo); | 1185 | MINFO_FROM(container_of(clnt->adapter, struct i2c_bit_adapter, adapter)->minfo); |
| 1186 | 1186 | ||
| 1187 | md->primary_head = MINFO; | 1187 | md->primary_head = MINFO; |
| 1188 | md->client = clnt; | ||
| 1189 | down_write(&ACCESS_FBINFO(altout.lock)); | 1188 | down_write(&ACCESS_FBINFO(altout.lock)); |
| 1190 | ACCESS_FBINFO(outputs[1]).output = &maven_altout; | 1189 | ACCESS_FBINFO(outputs[1]).output = &maven_altout; |
| 1191 | ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; | 1190 | ACCESS_FBINFO(outputs[1]).src = ACCESS_FBINFO(outputs[1]).default_src; |
| @@ -1243,19 +1242,17 @@ static int maven_detect_client(struct i2c_adapter* adapter, int address, int kin | |||
| 1243 | I2C_FUNC_SMBUS_BYTE_DATA | | 1242 | I2C_FUNC_SMBUS_BYTE_DATA | |
| 1244 | I2C_FUNC_PROTOCOL_MANGLING)) | 1243 | I2C_FUNC_PROTOCOL_MANGLING)) |
| 1245 | goto ERROR0; | 1244 | goto ERROR0; |
| 1246 | if (!(new_client = (struct i2c_client*)kmalloc(sizeof(*new_client) + sizeof(*data), | 1245 | if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) { |
| 1247 | GFP_KERNEL))) { | ||
| 1248 | err = -ENOMEM; | 1246 | err = -ENOMEM; |
| 1249 | goto ERROR0; | 1247 | goto ERROR0; |
| 1250 | } | 1248 | } |
| 1251 | memset(new_client, 0, sizeof(*new_client) + sizeof(*data)); | 1249 | new_client = &data->client; |
| 1252 | data = (struct maven_data*)(new_client + 1); | ||
| 1253 | i2c_set_clientdata(new_client, data); | 1250 | i2c_set_clientdata(new_client, data); |
| 1254 | new_client->addr = address; | 1251 | new_client->addr = address; |
| 1255 | new_client->adapter = adapter; | 1252 | new_client->adapter = adapter; |
| 1256 | new_client->driver = &maven_driver; | 1253 | new_client->driver = &maven_driver; |
| 1257 | new_client->flags = 0; | 1254 | new_client->flags = 0; |
| 1258 | strcpy(new_client->name, "maven client"); | 1255 | strlcpy(new_client->name, "maven", I2C_NAME_SIZE); |
| 1259 | if ((err = i2c_attach_client(new_client))) | 1256 | if ((err = i2c_attach_client(new_client))) |
| 1260 | goto ERROR3; | 1257 | goto ERROR3; |
| 1261 | err = maven_init_client(new_client); | 1258 | err = maven_init_client(new_client); |
| @@ -1279,12 +1276,10 @@ static int maven_attach_adapter(struct i2c_adapter* adapter) { | |||
| 1279 | static int maven_detach_client(struct i2c_client* client) { | 1276 | static int maven_detach_client(struct i2c_client* client) { |
| 1280 | int err; | 1277 | int err; |
| 1281 | 1278 | ||
| 1282 | if ((err = i2c_detach_client(client))) { | 1279 | if ((err = i2c_detach_client(client))) |
| 1283 | printk(KERN_ERR "maven: Cannot deregister client\n"); | ||
| 1284 | return err; | 1280 | return err; |
| 1285 | } | ||
| 1286 | maven_shutdown_client(client); | 1281 | maven_shutdown_client(client); |
| 1287 | kfree(client); | 1282 | kfree(i2c_get_clientdata(client)); |
| 1288 | return 0; | 1283 | return 0; |
| 1289 | } | 1284 | } |
| 1290 | 1285 | ||
| @@ -1297,20 +1292,13 @@ static struct i2c_driver maven_driver={ | |||
| 1297 | .detach_client = maven_detach_client, | 1292 | .detach_client = maven_detach_client, |
| 1298 | }; | 1293 | }; |
| 1299 | 1294 | ||
| 1300 | /* ************************** */ | 1295 | static int __init matroxfb_maven_init(void) |
| 1301 | 1296 | { | |
| 1302 | static int matroxfb_maven_init(void) { | 1297 | return i2c_add_driver(&maven_driver); |
| 1303 | int err; | ||
| 1304 | |||
| 1305 | err = i2c_add_driver(&maven_driver); | ||
| 1306 | if (err) { | ||
| 1307 | printk(KERN_ERR "maven: Maven driver failed to register (%d).\n", err); | ||
| 1308 | return err; | ||
| 1309 | } | ||
| 1310 | return 0; | ||
| 1311 | } | 1298 | } |
| 1312 | 1299 | ||
| 1313 | static void matroxfb_maven_exit(void) { | 1300 | static void __exit matroxfb_maven_exit(void) |
| 1301 | { | ||
| 1314 | i2c_del_driver(&maven_driver); | 1302 | i2c_del_driver(&maven_driver); |
| 1315 | } | 1303 | } |
| 1316 | 1304 | ||
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 1da2f84bdc25..26a1c618a205 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c | |||
| @@ -183,6 +183,10 @@ static const struct fb_videomode modedb[] = { | |||
| 183 | NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, | 183 | NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, |
| 184 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 184 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
| 185 | }, { | 185 | }, { |
| 186 | /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */ | ||
| 187 | NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6, | ||
| 188 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | ||
| 189 | }, { | ||
| 186 | /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */ | 190 | /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */ |
| 187 | NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3, | 191 | NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3, |
| 188 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED | 192 | FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
| @@ -496,7 +500,7 @@ int fb_find_mode(struct fb_var_screeninfo *var, | |||
| 496 | /* Set up defaults */ | 500 | /* Set up defaults */ |
| 497 | if (!db) { | 501 | if (!db) { |
| 498 | db = modedb; | 502 | db = modedb; |
| 499 | dbsize = sizeof(modedb)/sizeof(*modedb); | 503 | dbsize = ARRAY_SIZE(modedb); |
| 500 | } | 504 | } |
| 501 | if (!default_mode) | 505 | if (!default_mode) |
| 502 | default_mode = &modedb[DEFAULT_MODEDB_INDEX]; | 506 | default_mode = &modedb[DEFAULT_MODEDB_INDEX]; |
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index b961d5601bd9..24b12f71d5a8 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c | |||
| @@ -165,20 +165,20 @@ static int neoFindMode(int xres, int yres, int depth) | |||
| 165 | 165 | ||
| 166 | switch (depth) { | 166 | switch (depth) { |
| 167 | case 8: | 167 | case 8: |
| 168 | size = sizeof(bios8) / sizeof(biosMode); | 168 | size = ARRAY_SIZE(bios8); |
| 169 | mode = bios8; | 169 | mode = bios8; |
| 170 | break; | 170 | break; |
| 171 | case 16: | 171 | case 16: |
| 172 | size = sizeof(bios16) / sizeof(biosMode); | 172 | size = ARRAY_SIZE(bios16); |
| 173 | mode = bios16; | 173 | mode = bios16; |
| 174 | break; | 174 | break; |
| 175 | case 24: | 175 | case 24: |
| 176 | size = sizeof(bios24) / sizeof(biosMode); | 176 | size = ARRAY_SIZE(bios24); |
| 177 | mode = bios24; | 177 | mode = bios24; |
| 178 | break; | 178 | break; |
| 179 | #ifdef NO_32BIT_SUPPORT_YET | 179 | #ifdef NO_32BIT_SUPPORT_YET |
| 180 | case 32: | 180 | case 32: |
| 181 | size = sizeof(bios32) / sizeof(biosMode); | 181 | size = ARRAY_SIZE(bios32); |
| 182 | mode = bios32; | 182 | mode = bios32; |
| 183 | break; | 183 | break; |
| 184 | #endif | 184 | #endif |
diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c index f377a29ec97a..4aefb8f41637 100644 --- a/drivers/video/nvidia/nv_accel.c +++ b/drivers/video/nvidia/nv_accel.c | |||
| @@ -300,6 +300,9 @@ int nvidiafb_sync(struct fb_info *info) | |||
| 300 | { | 300 | { |
| 301 | struct nvidia_par *par = info->par; | 301 | struct nvidia_par *par = info->par; |
| 302 | 302 | ||
| 303 | if (info->state != FBINFO_STATE_RUNNING) | ||
| 304 | return 0; | ||
| 305 | |||
| 303 | if (!par->lockup) | 306 | if (!par->lockup) |
| 304 | NVFlush(par); | 307 | NVFlush(par); |
| 305 | 308 | ||
| @@ -313,6 +316,9 @@ void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region) | |||
| 313 | { | 316 | { |
| 314 | struct nvidia_par *par = info->par; | 317 | struct nvidia_par *par = info->par; |
| 315 | 318 | ||
| 319 | if (info->state != FBINFO_STATE_RUNNING) | ||
| 320 | return; | ||
| 321 | |||
| 316 | if (par->lockup) | 322 | if (par->lockup) |
| 317 | return cfb_copyarea(info, region); | 323 | return cfb_copyarea(info, region); |
| 318 | 324 | ||
| @@ -329,6 +335,9 @@ void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | |||
| 329 | struct nvidia_par *par = info->par; | 335 | struct nvidia_par *par = info->par; |
| 330 | u32 color; | 336 | u32 color; |
| 331 | 337 | ||
| 338 | if (info->state != FBINFO_STATE_RUNNING) | ||
| 339 | return; | ||
| 340 | |||
| 332 | if (par->lockup) | 341 | if (par->lockup) |
| 333 | return cfb_fillrect(info, rect); | 342 | return cfb_fillrect(info, rect); |
| 334 | 343 | ||
| @@ -412,6 +421,9 @@ void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
| 412 | { | 421 | { |
| 413 | struct nvidia_par *par = info->par; | 422 | struct nvidia_par *par = info->par; |
| 414 | 423 | ||
| 424 | if (info->state != FBINFO_STATE_RUNNING) | ||
| 425 | return; | ||
| 426 | |||
| 415 | if (image->depth == 1 && !par->lockup) | 427 | if (image->depth == 1 && !par->lockup) |
| 416 | nvidiafb_mono_color_expand(info, image); | 428 | nvidiafb_mono_color_expand(info, image); |
| 417 | else | 429 | else |
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c index bd9eca05e146..1edb1c432b75 100644 --- a/drivers/video/nvidia/nv_i2c.c +++ b/drivers/video/nvidia/nv_i2c.c | |||
| @@ -218,8 +218,7 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) | |||
| 218 | } | 218 | } |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | if (out_edid) | 221 | *out_edid = edid; |
| 222 | *out_edid = edid; | ||
| 223 | 222 | ||
| 224 | return (edid) ? 0 : 1; | 223 | return (edid) ? 0 : 1; |
| 225 | } | 224 | } |
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h index e4a5b1da71c4..acdc26693402 100644 --- a/drivers/video/nvidia/nv_type.h +++ b/drivers/video/nvidia/nv_type.h | |||
| @@ -129,6 +129,7 @@ struct nvidia_par { | |||
| 129 | int fpHeight; | 129 | int fpHeight; |
| 130 | int PanelTweak; | 130 | int PanelTweak; |
| 131 | int paneltweak; | 131 | int paneltweak; |
| 132 | int pm_state; | ||
| 132 | u32 crtcSync_read; | 133 | u32 crtcSync_read; |
| 133 | u32 fpSyncs; | 134 | u32 fpSyncs; |
| 134 | u32 dmaPut; | 135 | u32 dmaPut; |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index a7c4e5e8ead6..6d3e4890cb43 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/fb.h> | 21 | #include <linux/fb.h> |
| 22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
| 24 | #include <linux/console.h> | ||
| 24 | #ifdef CONFIG_MTRR | 25 | #ifdef CONFIG_MTRR |
| 25 | #include <asm/mtrr.h> | 26 | #include <asm/mtrr.h> |
| 26 | #endif | 27 | #endif |
| @@ -296,6 +297,8 @@ static struct pci_device_id nvidiafb_pci_tbl[] = { | |||
| 296 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 297 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
| 297 | {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT, | 298 | {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT, |
| 298 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 299 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
| 300 | {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280, | ||
| 301 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
| 299 | {PCI_VENDOR_ID_NVIDIA, 0x0252, | 302 | {PCI_VENDOR_ID_NVIDIA, 0x0252, |
| 300 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 303 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
| 301 | {PCI_VENDOR_ID_NVIDIA, 0x0313, | 304 | {PCI_VENDOR_ID_NVIDIA, 0x0313, |
| @@ -615,6 +618,30 @@ static int nvidia_panel_tweak(struct nvidia_par *par, | |||
| 615 | return tweak; | 618 | return tweak; |
| 616 | } | 619 | } |
| 617 | 620 | ||
| 621 | static void nvidia_vga_protect(struct nvidia_par *par, int on) | ||
| 622 | { | ||
| 623 | unsigned char tmp; | ||
| 624 | |||
| 625 | if (on) { | ||
| 626 | /* | ||
| 627 | * Turn off screen and disable sequencer. | ||
| 628 | */ | ||
| 629 | tmp = NVReadSeq(par, 0x01); | ||
| 630 | |||
| 631 | NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */ | ||
| 632 | NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */ | ||
| 633 | } else { | ||
| 634 | /* | ||
| 635 | * Reenable sequencer, then turn on screen. | ||
| 636 | */ | ||
| 637 | |||
| 638 | tmp = NVReadSeq(par, 0x01); | ||
| 639 | |||
| 640 | NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */ | ||
| 641 | NVWriteSeq(par, 0x00, 0x03); /* End Reset */ | ||
| 642 | } | ||
| 643 | } | ||
| 644 | |||
| 618 | static void nvidia_save_vga(struct nvidia_par *par, | 645 | static void nvidia_save_vga(struct nvidia_par *par, |
| 619 | struct _riva_hw_state *state) | 646 | struct _riva_hw_state *state) |
| 620 | { | 647 | { |
| @@ -643,9 +670,9 @@ static void nvidia_save_vga(struct nvidia_par *par, | |||
| 643 | 670 | ||
| 644 | #undef DUMP_REG | 671 | #undef DUMP_REG |
| 645 | 672 | ||
| 646 | static void nvidia_write_regs(struct nvidia_par *par) | 673 | static void nvidia_write_regs(struct nvidia_par *par, |
| 674 | struct _riva_hw_state *state) | ||
| 647 | { | 675 | { |
| 648 | struct _riva_hw_state *state = &par->ModeReg; | ||
| 649 | int i; | 676 | int i; |
| 650 | 677 | ||
| 651 | NVTRACE_ENTER(); | 678 | NVTRACE_ENTER(); |
| @@ -694,32 +721,6 @@ static void nvidia_write_regs(struct nvidia_par *par) | |||
| 694 | NVTRACE_LEAVE(); | 721 | NVTRACE_LEAVE(); |
| 695 | } | 722 | } |
| 696 | 723 | ||
| 697 | static void nvidia_vga_protect(struct nvidia_par *par, int on) | ||
| 698 | { | ||
| 699 | unsigned char tmp; | ||
| 700 | |||
| 701 | if (on) { | ||
| 702 | /* | ||
| 703 | * Turn off screen and disable sequencer. | ||
| 704 | */ | ||
| 705 | tmp = NVReadSeq(par, 0x01); | ||
| 706 | |||
| 707 | NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */ | ||
| 708 | NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */ | ||
| 709 | } else { | ||
| 710 | /* | ||
| 711 | * Reenable sequencer, then turn on screen. | ||
| 712 | */ | ||
| 713 | |||
| 714 | tmp = NVReadSeq(par, 0x01); | ||
| 715 | |||
| 716 | NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */ | ||
| 717 | NVWriteSeq(par, 0x00, 0x03); /* End Reset */ | ||
| 718 | } | ||
| 719 | } | ||
| 720 | |||
| 721 | |||
| 722 | |||
| 723 | static int nvidia_calc_regs(struct fb_info *info) | 724 | static int nvidia_calc_regs(struct fb_info *info) |
| 724 | { | 725 | { |
| 725 | struct nvidia_par *par = info->par; | 726 | struct nvidia_par *par = info->par; |
| @@ -1068,7 +1069,8 @@ static int nvidiafb_set_par(struct fb_info *info) | |||
| 1068 | 1069 | ||
| 1069 | nvidia_vga_protect(par, 1); | 1070 | nvidia_vga_protect(par, 1); |
| 1070 | 1071 | ||
| 1071 | nvidia_write_regs(par); | 1072 | nvidia_write_regs(par, &par->ModeReg); |
| 1073 | NVSetStartAddress(par, 0); | ||
| 1072 | 1074 | ||
| 1073 | #if defined (__BIG_ENDIAN) | 1075 | #if defined (__BIG_ENDIAN) |
| 1074 | /* turn on LFB swapping */ | 1076 | /* turn on LFB swapping */ |
| @@ -1377,6 +1379,57 @@ static struct fb_ops nvidia_fb_ops = { | |||
| 1377 | .fb_sync = nvidiafb_sync, | 1379 | .fb_sync = nvidiafb_sync, |
| 1378 | }; | 1380 | }; |
| 1379 | 1381 | ||
| 1382 | #ifdef CONFIG_PM | ||
| 1383 | static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t state) | ||
| 1384 | { | ||
| 1385 | struct fb_info *info = pci_get_drvdata(dev); | ||
| 1386 | struct nvidia_par *par = info->par; | ||
| 1387 | |||
| 1388 | acquire_console_sem(); | ||
| 1389 | par->pm_state = state.event; | ||
| 1390 | |||
| 1391 | if (state.event == PM_EVENT_FREEZE) { | ||
| 1392 | dev->dev.power.power_state = state; | ||
| 1393 | } else { | ||
| 1394 | fb_set_suspend(info, 1); | ||
| 1395 | nvidiafb_blank(FB_BLANK_POWERDOWN, info); | ||
| 1396 | nvidia_write_regs(par, &par->SavedReg); | ||
| 1397 | pci_save_state(dev); | ||
| 1398 | pci_disable_device(dev); | ||
| 1399 | pci_set_power_state(dev, pci_choose_state(dev, state)); | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | release_console_sem(); | ||
| 1403 | return 0; | ||
| 1404 | } | ||
| 1405 | |||
| 1406 | static int nvidiafb_resume(struct pci_dev *dev) | ||
| 1407 | { | ||
| 1408 | struct fb_info *info = pci_get_drvdata(dev); | ||
| 1409 | struct nvidia_par *par = info->par; | ||
| 1410 | |||
| 1411 | acquire_console_sem(); | ||
| 1412 | pci_set_power_state(dev, PCI_D0); | ||
| 1413 | |||
| 1414 | if (par->pm_state != PM_EVENT_FREEZE) { | ||
| 1415 | pci_restore_state(dev); | ||
| 1416 | pci_enable_device(dev); | ||
| 1417 | pci_set_master(dev); | ||
| 1418 | } | ||
| 1419 | |||
| 1420 | par->pm_state = PM_EVENT_ON; | ||
| 1421 | nvidiafb_set_par(info); | ||
| 1422 | fb_set_suspend (info, 0); | ||
| 1423 | nvidiafb_blank(FB_BLANK_UNBLANK, info); | ||
| 1424 | |||
| 1425 | release_console_sem(); | ||
| 1426 | return 0; | ||
| 1427 | } | ||
| 1428 | #else | ||
| 1429 | #define nvidiafb_suspend NULL | ||
| 1430 | #define nvidiafb_resume NULL | ||
| 1431 | #endif | ||
| 1432 | |||
| 1380 | static int __devinit nvidia_set_fbinfo(struct fb_info *info) | 1433 | static int __devinit nvidia_set_fbinfo(struct fb_info *info) |
| 1381 | { | 1434 | { |
| 1382 | struct fb_monspecs *specs = &info->monspecs; | 1435 | struct fb_monspecs *specs = &info->monspecs; |
| @@ -1720,8 +1773,6 @@ static void __exit nvidiafb_remove(struct pci_dev *pd) | |||
| 1720 | struct nvidia_par *par = info->par; | 1773 | struct nvidia_par *par = info->par; |
| 1721 | 1774 | ||
| 1722 | NVTRACE_ENTER(); | 1775 | NVTRACE_ENTER(); |
| 1723 | if (!info) | ||
| 1724 | return; | ||
| 1725 | 1776 | ||
| 1726 | unregister_framebuffer(info); | 1777 | unregister_framebuffer(info); |
| 1727 | #ifdef CONFIG_MTRR | 1778 | #ifdef CONFIG_MTRR |
| @@ -1798,8 +1849,10 @@ static int __devinit nvidiafb_setup(char *options) | |||
| 1798 | static struct pci_driver nvidiafb_driver = { | 1849 | static struct pci_driver nvidiafb_driver = { |
| 1799 | .name = "nvidiafb", | 1850 | .name = "nvidiafb", |
| 1800 | .id_table = nvidiafb_pci_tbl, | 1851 | .id_table = nvidiafb_pci_tbl, |
| 1801 | .probe = nvidiafb_probe, | 1852 | .probe = nvidiafb_probe, |
| 1802 | .remove = __exit_p(nvidiafb_remove), | 1853 | .suspend = nvidiafb_suspend, |
| 1854 | .resume = nvidiafb_resume, | ||
| 1855 | .remove = __exit_p(nvidiafb_remove), | ||
| 1803 | }; | 1856 | }; |
| 1804 | 1857 | ||
| 1805 | /* ------------------------------------------------------------------------- * | 1858 | /* ------------------------------------------------------------------------- * |
diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index eeeac924b500..73e2d7d16608 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c | |||
| @@ -228,7 +228,7 @@ static void __init pmagbbfb_osc_setup(struct fb_info *info) | |||
| 228 | 228 | ||
| 229 | freq1 = (par->osc0 * count1 + count0 / 2) / count0; | 229 | freq1 = (par->osc0 * count1 + count0 / 2) / count0; |
| 230 | par->osc1 = freq1; | 230 | par->osc1 = freq1; |
| 231 | for (i = 0; i < sizeof(pmagbbfb_freqs) / sizeof(*pmagbbfb_freqs); i++) | 231 | for (i = 0; i < ARRAY_SIZE(pmagbbfb_freqs); i++) |
| 232 | if (freq1 >= pmagbbfb_freqs[i] - | 232 | if (freq1 >= pmagbbfb_freqs[i] - |
| 233 | (pmagbbfb_freqs[i] + 128) / 256 && | 233 | (pmagbbfb_freqs[i] + 128) / 256 && |
| 234 | freq1 <= pmagbbfb_freqs[i] + | 234 | freq1 <= pmagbbfb_freqs[i] + |
diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index db9fb9074dbc..24982adb3aa2 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c | |||
| @@ -759,7 +759,7 @@ static void __iomem *radeon_find_rom(struct radeonfb_info *rinfo) | |||
| 759 | rom = rom_base; | 759 | rom = rom_base; |
| 760 | 760 | ||
| 761 | for (i = 0; (i < 512) && (stage != 4); i++) { | 761 | for (i = 0; (i < 512) && (stage != 4); i++) { |
| 762 | for(j = 0;j < sizeof(radeon_sig)/sizeof(char *);j++) { | 762 | for (j = 0; j < ARRAY_SIZE(radeon_sig); j++) { |
| 763 | if (radeon_sig[j][0] == *rom) | 763 | if (radeon_sig[j][0] == *rom) |
| 764 | if (strncmp(radeon_sig[j], rom, | 764 | if (strncmp(radeon_sig[j], rom, |
| 765 | strlen(radeon_sig[j])) == 0) { | 765 | strlen(radeon_sig[j])) == 0) { |
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c index 6c19ab6afb01..f841f013b96f 100644 --- a/drivers/video/riva/fbdev.c +++ b/drivers/video/riva/fbdev.c | |||
| @@ -2072,8 +2072,6 @@ static void __exit rivafb_remove(struct pci_dev *pd) | |||
| 2072 | struct riva_par *par = info->par; | 2072 | struct riva_par *par = info->par; |
| 2073 | 2073 | ||
| 2074 | NVTRACE_ENTER(); | 2074 | NVTRACE_ENTER(); |
| 2075 | if (!info) | ||
| 2076 | return; | ||
| 2077 | 2075 | ||
| 2078 | #ifdef CONFIG_FB_RIVA_I2C | 2076 | #ifdef CONFIG_FB_RIVA_I2C |
| 2079 | riva_delete_i2c_busses(par); | 2077 | riva_delete_i2c_busses(par); |
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 00719a91479f..21debed863ac 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c | |||
| @@ -273,8 +273,7 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid) | |||
| 273 | } | 273 | } |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | if (out_edid) | 276 | *out_edid = edid; |
| 277 | *out_edid = edid; | ||
| 278 | 277 | ||
| 279 | return (edid) ? 0 : 1; | 278 | return (edid) ? 0 : 1; |
| 280 | } | 279 | } |
diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c index 2d88f908170a..c3e070a6effd 100644 --- a/drivers/video/sis/init301.c +++ b/drivers/video/sis/init301.c | |||
| @@ -8564,11 +8564,9 @@ SiS_ChrontelDoSomething3(struct SiS_Private *SiS_Pr, unsigned short ModeNo) | |||
| 8564 | static void | 8564 | static void |
| 8565 | SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr) | 8565 | SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr) |
| 8566 | { | 8566 | { |
| 8567 | unsigned short temp,tempcl,tempch; | 8567 | unsigned short temp; |
| 8568 | 8568 | ||
| 8569 | SiS_LongDelay(SiS_Pr, 1); | 8569 | SiS_LongDelay(SiS_Pr, 1); |
| 8570 | tempcl = 3; | ||
| 8571 | tempch = 0; | ||
| 8572 | 8570 | ||
| 8573 | do { | 8571 | do { |
| 8574 | temp = SiS_GetCH701x(SiS_Pr,0x66); | 8572 | temp = SiS_GetCH701x(SiS_Pr,0x66); |
| @@ -8582,13 +8580,6 @@ SiS_ChrontelDoSomething2(struct SiS_Private *SiS_Pr) | |||
| 8582 | 8580 | ||
| 8583 | SiS_SetCH701xForLCD(SiS_Pr); | 8581 | SiS_SetCH701xForLCD(SiS_Pr); |
| 8584 | 8582 | ||
| 8585 | if(tempcl == 0) { | ||
| 8586 | if(tempch == 3) break; | ||
| 8587 | SiS_ChrontelResetDB(SiS_Pr); | ||
| 8588 | tempcl = 3; | ||
| 8589 | tempch++; | ||
| 8590 | } | ||
| 8591 | tempcl--; | ||
| 8592 | temp = SiS_GetCH701x(SiS_Pr,0x76); | 8583 | temp = SiS_GetCH701x(SiS_Pr,0x76); |
| 8593 | temp &= 0xfb; /* Reset PLL */ | 8584 | temp &= 0xfb; /* Reset PLL */ |
| 8594 | SiS_SetCH701x(SiS_Pr,0x76,temp); | 8585 | SiS_SetCH701x(SiS_Pr,0x76,temp); |
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 8c1a8b5135c6..c44de90ca12e 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c | |||
| @@ -1194,10 +1194,11 @@ static struct dac_switch dacs[] __devinitdata = { | |||
| 1194 | static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par) | 1194 | static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par) |
| 1195 | { | 1195 | { |
| 1196 | int i, ret = 0; | 1196 | int i, ret = 0; |
| 1197 | 1197 | ||
| 1198 | for (i=0; i<sizeof(dacs)/sizeof(dacs[0]); i++) { | 1198 | for (i = 0; i < ARRAY_SIZE(dacs); i++) { |
| 1199 | ret = dacs[i].detect(info); | 1199 | ret = dacs[i].detect(info); |
| 1200 | if (ret) break; | 1200 | if (ret) |
| 1201 | break; | ||
| 1201 | } | 1202 | } |
| 1202 | if (!ret) | 1203 | if (!ret) |
| 1203 | return 0; | 1204 | return 0; |
| @@ -1604,8 +1605,8 @@ static int sstfb_dump_regs(struct fb_info *info) | |||
| 1604 | {FBZMODE,"fbzmode"}, | 1605 | {FBZMODE,"fbzmode"}, |
| 1605 | }; | 1606 | }; |
| 1606 | 1607 | ||
| 1607 | const int pci_s = sizeof(pci_regs)/sizeof(pci_regs[0]); | 1608 | const int pci_s = ARRAY_SIZE(pci_regs); |
| 1608 | const int sst_s = sizeof(sst_regs)/sizeof(sst_regs[0]); | 1609 | const int sst_s = ARRAY_SIZE(sst_regs); |
| 1609 | struct sstfb_par *par = info->par; | 1610 | struct sstfb_par *par = info->par; |
| 1610 | struct pci_dev *dev = par->dev; | 1611 | struct pci_dev *dev = par->dev; |
| 1611 | u32 pci_res[pci_s]; | 1612 | u32 pci_res[pci_s]; |
diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c index ed78747487e2..5ea2345dab99 100644 --- a/drivers/video/virgefb.c +++ b/drivers/video/virgefb.c | |||
| @@ -616,8 +616,7 @@ static struct { | |||
| 616 | #endif | 616 | #endif |
| 617 | }; | 617 | }; |
| 618 | 618 | ||
| 619 | #define arraysize(x) (sizeof(x)/sizeof(*(x))) | 619 | #define NUM_TOTAL_MODES ARRAY_SIZE(virgefb_predefined) |
| 620 | #define NUM_TOTAL_MODES arraysize(virgefb_predefined) | ||
| 621 | 620 | ||
| 622 | /* | 621 | /* |
| 623 | * Default to 800x600 for video=virge8:, virge16: or virge32: | 622 | * Default to 800x600 for video=virge8:, virge16: or virge32: |
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 43c9f7de0314..f867b8d3e973 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
| @@ -39,8 +39,8 @@ | |||
| 39 | 39 | ||
| 40 | extern struct file_system_type v9fs_fs_type; | 40 | extern struct file_system_type v9fs_fs_type; |
| 41 | extern struct address_space_operations v9fs_addr_operations; | 41 | extern struct address_space_operations v9fs_addr_operations; |
| 42 | extern struct file_operations v9fs_file_operations; | 42 | extern const struct file_operations v9fs_file_operations; |
| 43 | extern struct file_operations v9fs_dir_operations; | 43 | extern const struct file_operations v9fs_dir_operations; |
| 44 | extern struct dentry_operations v9fs_dentry_operations; | 44 | extern struct dentry_operations v9fs_dentry_operations; |
| 45 | 45 | ||
| 46 | struct inode *v9fs_get_inode(struct super_block *sb, int mode); | 46 | struct inode *v9fs_get_inode(struct super_block *sb, int mode); |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 766f11f1215c..e32d5971039b 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
| @@ -204,7 +204,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp) | |||
| 204 | return 0; | 204 | return 0; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | struct file_operations v9fs_dir_operations = { | 207 | const struct file_operations v9fs_dir_operations = { |
| 208 | .read = generic_read_dir, | 208 | .read = generic_read_dir, |
| 209 | .readdir = v9fs_dir_readdir, | 209 | .readdir = v9fs_dir_readdir, |
| 210 | .open = v9fs_file_open, | 210 | .open = v9fs_file_open, |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 59e744163407..083dcfcd158e 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
| @@ -266,7 +266,7 @@ v9fs_file_write(struct file *filp, const char __user * data, | |||
| 266 | return total; | 266 | return total; |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | struct file_operations v9fs_file_operations = { | 269 | const struct file_operations v9fs_file_operations = { |
| 270 | .llseek = generic_file_llseek, | 270 | .llseek = generic_file_llseek, |
| 271 | .read = v9fs_file_read, | 271 | .read = v9fs_file_read, |
| 272 | .write = v9fs_file_write, | 272 | .write = v9fs_file_write, |
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index f6cd01352cc8..29217ff36d44 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h | |||
| @@ -85,7 +85,7 @@ void __adfs_error(struct super_block *sb, const char *function, | |||
| 85 | 85 | ||
| 86 | /* dir_*.c */ | 86 | /* dir_*.c */ |
| 87 | extern struct inode_operations adfs_dir_inode_operations; | 87 | extern struct inode_operations adfs_dir_inode_operations; |
| 88 | extern struct file_operations adfs_dir_operations; | 88 | extern const struct file_operations adfs_dir_operations; |
| 89 | extern struct dentry_operations adfs_dentry_operations; | 89 | extern struct dentry_operations adfs_dentry_operations; |
| 90 | extern struct adfs_dir_ops adfs_f_dir_ops; | 90 | extern struct adfs_dir_ops adfs_f_dir_ops; |
| 91 | extern struct adfs_dir_ops adfs_fplus_dir_ops; | 91 | extern struct adfs_dir_ops adfs_fplus_dir_ops; |
| @@ -94,7 +94,7 @@ extern int adfs_dir_update(struct super_block *sb, struct object_info *obj); | |||
| 94 | 94 | ||
| 95 | /* file.c */ | 95 | /* file.c */ |
| 96 | extern struct inode_operations adfs_file_inode_operations; | 96 | extern struct inode_operations adfs_file_inode_operations; |
| 97 | extern struct file_operations adfs_file_operations; | 97 | extern const struct file_operations adfs_file_operations; |
| 98 | 98 | ||
| 99 | static inline __u32 signed_asl(__u32 val, signed int shift) | 99 | static inline __u32 signed_asl(__u32 val, signed int shift) |
| 100 | { | 100 | { |
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c index 0b4c3a028076..7b075fc397da 100644 --- a/fs/adfs/dir.c +++ b/fs/adfs/dir.c | |||
| @@ -196,7 +196,7 @@ out: | |||
| 196 | return ret; | 196 | return ret; |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | struct file_operations adfs_dir_operations = { | 199 | const struct file_operations adfs_dir_operations = { |
| 200 | .read = generic_read_dir, | 200 | .read = generic_read_dir, |
| 201 | .readdir = adfs_readdir, | 201 | .readdir = adfs_readdir, |
| 202 | .fsync = file_fsync, | 202 | .fsync = file_fsync, |
diff --git a/fs/adfs/file.c b/fs/adfs/file.c index 6af10885f9d6..1014b9f2117b 100644 --- a/fs/adfs/file.c +++ b/fs/adfs/file.c | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | #include "adfs.h" | 26 | #include "adfs.h" |
| 27 | 27 | ||
| 28 | struct file_operations adfs_file_operations = { | 28 | const struct file_operations adfs_file_operations = { |
| 29 | .llseek = generic_file_llseek, | 29 | .llseek = generic_file_llseek, |
| 30 | .read = generic_file_read, | 30 | .read = generic_file_read, |
| 31 | .mmap = generic_file_mmap, | 31 | .mmap = generic_file_mmap, |
diff --git a/fs/affs/affs.h b/fs/affs/affs.h index 0c6799f2137a..a43a876742b8 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h | |||
| @@ -192,9 +192,9 @@ extern void affs_dir_truncate(struct inode *); | |||
| 192 | extern struct inode_operations affs_file_inode_operations; | 192 | extern struct inode_operations affs_file_inode_operations; |
| 193 | extern struct inode_operations affs_dir_inode_operations; | 193 | extern struct inode_operations affs_dir_inode_operations; |
| 194 | extern struct inode_operations affs_symlink_inode_operations; | 194 | extern struct inode_operations affs_symlink_inode_operations; |
| 195 | extern struct file_operations affs_file_operations; | 195 | extern const struct file_operations affs_file_operations; |
| 196 | extern struct file_operations affs_file_operations_ofs; | 196 | extern const struct file_operations affs_file_operations_ofs; |
| 197 | extern struct file_operations affs_dir_operations; | 197 | extern const struct file_operations affs_dir_operations; |
| 198 | extern struct address_space_operations affs_symlink_aops; | 198 | extern struct address_space_operations affs_symlink_aops; |
| 199 | extern struct address_space_operations affs_aops; | 199 | extern struct address_space_operations affs_aops; |
| 200 | extern struct address_space_operations affs_aops_ofs; | 200 | extern struct address_space_operations affs_aops_ofs; |
diff --git a/fs/affs/dir.c b/fs/affs/dir.c index 548efd0ee98c..5d9649fa1814 100644 --- a/fs/affs/dir.c +++ b/fs/affs/dir.c | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | static int affs_readdir(struct file *, void *, filldir_t); | 18 | static int affs_readdir(struct file *, void *, filldir_t); |
| 19 | 19 | ||
| 20 | struct file_operations affs_dir_operations = { | 20 | const struct file_operations affs_dir_operations = { |
| 21 | .read = generic_read_dir, | 21 | .read = generic_read_dir, |
| 22 | .readdir = affs_readdir, | 22 | .readdir = affs_readdir, |
| 23 | .fsync = file_fsync, | 23 | .fsync = file_fsync, |
diff --git a/fs/affs/file.c b/fs/affs/file.c index f72fb776ecdf..7076262af39b 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c | |||
| @@ -25,7 +25,7 @@ static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext); | |||
| 25 | static int affs_file_open(struct inode *inode, struct file *filp); | 25 | static int affs_file_open(struct inode *inode, struct file *filp); |
| 26 | static int affs_file_release(struct inode *inode, struct file *filp); | 26 | static int affs_file_release(struct inode *inode, struct file *filp); |
| 27 | 27 | ||
| 28 | struct file_operations affs_file_operations = { | 28 | const struct file_operations affs_file_operations = { |
| 29 | .llseek = generic_file_llseek, | 29 | .llseek = generic_file_llseek, |
| 30 | .read = generic_file_read, | 30 | .read = generic_file_read, |
| 31 | .write = generic_file_write, | 31 | .write = generic_file_write, |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 5c61c24dab2a..a6dff6a4f204 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
| @@ -32,7 +32,7 @@ static int afs_d_delete(struct dentry *dentry); | |||
| 32 | static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, | 32 | static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, |
| 33 | loff_t fpos, ino_t ino, unsigned dtype); | 33 | loff_t fpos, ino_t ino, unsigned dtype); |
| 34 | 34 | ||
| 35 | struct file_operations afs_dir_file_operations = { | 35 | const struct file_operations afs_dir_file_operations = { |
| 36 | .open = afs_dir_open, | 36 | .open = afs_dir_open, |
| 37 | .readdir = afs_dir_readdir, | 37 | .readdir = afs_dir_readdir, |
| 38 | }; | 38 | }; |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index ab8f87c66319..72febdf9a35a 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
| @@ -64,7 +64,7 @@ extern struct cachefs_index_def afs_cache_cell_index_def; | |||
| 64 | * dir.c | 64 | * dir.c |
| 65 | */ | 65 | */ |
| 66 | extern struct inode_operations afs_dir_inode_operations; | 66 | extern struct inode_operations afs_dir_inode_operations; |
| 67 | extern struct file_operations afs_dir_file_operations; | 67 | extern const struct file_operations afs_dir_file_operations; |
| 68 | 68 | ||
| 69 | /* | 69 | /* |
| 70 | * file.c | 70 | * file.c |
| @@ -105,7 +105,7 @@ extern struct cachefs_netfs afs_cache_netfs; | |||
| 105 | * mntpt.c | 105 | * mntpt.c |
| 106 | */ | 106 | */ |
| 107 | extern struct inode_operations afs_mntpt_inode_operations; | 107 | extern struct inode_operations afs_mntpt_inode_operations; |
| 108 | extern struct file_operations afs_mntpt_file_operations; | 108 | extern const struct file_operations afs_mntpt_file_operations; |
| 109 | extern struct afs_timer afs_mntpt_expiry_timer; | 109 | extern struct afs_timer afs_mntpt_expiry_timer; |
| 110 | extern struct afs_timer_ops afs_mntpt_expiry_timer_ops; | 110 | extern struct afs_timer_ops afs_mntpt_expiry_timer_ops; |
| 111 | extern unsigned long afs_mntpt_expiry_timeout; | 111 | extern unsigned long afs_mntpt_expiry_timeout; |
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 31ee06590de5..4e6eeb59b83c 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
| @@ -32,7 +32,7 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir, | |||
| 32 | static int afs_mntpt_open(struct inode *inode, struct file *file); | 32 | static int afs_mntpt_open(struct inode *inode, struct file *file); |
| 33 | static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); | 33 | static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); |
| 34 | 34 | ||
| 35 | struct file_operations afs_mntpt_file_operations = { | 35 | const struct file_operations afs_mntpt_file_operations = { |
| 36 | .open = afs_mntpt_open, | 36 | .open = afs_mntpt_open, |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
diff --git a/fs/afs/proc.c b/fs/afs/proc.c index 9c81b8f7eef0..101d21b6c037 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c | |||
| @@ -37,7 +37,7 @@ static struct seq_operations afs_proc_cells_ops = { | |||
| 37 | .show = afs_proc_cells_show, | 37 | .show = afs_proc_cells_show, |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | static struct file_operations afs_proc_cells_fops = { | 40 | static const struct file_operations afs_proc_cells_fops = { |
| 41 | .open = afs_proc_cells_open, | 41 | .open = afs_proc_cells_open, |
| 42 | .read = seq_read, | 42 | .read = seq_read, |
| 43 | .write = afs_proc_cells_write, | 43 | .write = afs_proc_cells_write, |
| @@ -53,7 +53,7 @@ static ssize_t afs_proc_rootcell_write(struct file *file, | |||
| 53 | const char __user *buf, | 53 | const char __user *buf, |
| 54 | size_t size, loff_t *_pos); | 54 | size_t size, loff_t *_pos); |
| 55 | 55 | ||
| 56 | static struct file_operations afs_proc_rootcell_fops = { | 56 | static const struct file_operations afs_proc_rootcell_fops = { |
| 57 | .open = afs_proc_rootcell_open, | 57 | .open = afs_proc_rootcell_open, |
| 58 | .read = afs_proc_rootcell_read, | 58 | .read = afs_proc_rootcell_read, |
| 59 | .write = afs_proc_rootcell_write, | 59 | .write = afs_proc_rootcell_write, |
| @@ -77,7 +77,7 @@ static struct seq_operations afs_proc_cell_volumes_ops = { | |||
| 77 | .show = afs_proc_cell_volumes_show, | 77 | .show = afs_proc_cell_volumes_show, |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | static struct file_operations afs_proc_cell_volumes_fops = { | 80 | static const struct file_operations afs_proc_cell_volumes_fops = { |
| 81 | .open = afs_proc_cell_volumes_open, | 81 | .open = afs_proc_cell_volumes_open, |
| 82 | .read = seq_read, | 82 | .read = seq_read, |
| 83 | .llseek = seq_lseek, | 83 | .llseek = seq_lseek, |
| @@ -101,7 +101,7 @@ static struct seq_operations afs_proc_cell_vlservers_ops = { | |||
| 101 | .show = afs_proc_cell_vlservers_show, | 101 | .show = afs_proc_cell_vlservers_show, |
| 102 | }; | 102 | }; |
| 103 | 103 | ||
| 104 | static struct file_operations afs_proc_cell_vlservers_fops = { | 104 | static const struct file_operations afs_proc_cell_vlservers_fops = { |
| 105 | .open = afs_proc_cell_vlservers_open, | 105 | .open = afs_proc_cell_vlservers_open, |
| 106 | .read = seq_read, | 106 | .read = seq_read, |
| 107 | .llseek = seq_lseek, | 107 | .llseek = seq_lseek, |
| @@ -124,7 +124,7 @@ static struct seq_operations afs_proc_cell_servers_ops = { | |||
| 124 | .show = afs_proc_cell_servers_show, | 124 | .show = afs_proc_cell_servers_show, |
| 125 | }; | 125 | }; |
| 126 | 126 | ||
| 127 | static struct file_operations afs_proc_cell_servers_fops = { | 127 | static const struct file_operations afs_proc_cell_servers_fops = { |
| 128 | .open = afs_proc_cell_servers_open, | 128 | .open = afs_proc_cell_servers_open, |
| 129 | .read = seq_read, | 129 | .read = seq_read, |
| 130 | .llseek = seq_lseek, | 130 | .llseek = seq_lseek, |
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 990c28da5aec..a62327f1bdff 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h | |||
| @@ -146,7 +146,7 @@ struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info | |||
| 146 | 146 | ||
| 147 | extern struct inode_operations autofs_root_inode_operations; | 147 | extern struct inode_operations autofs_root_inode_operations; |
| 148 | extern struct inode_operations autofs_symlink_inode_operations; | 148 | extern struct inode_operations autofs_symlink_inode_operations; |
| 149 | extern struct file_operations autofs_root_operations; | 149 | extern const struct file_operations autofs_root_operations; |
| 150 | 150 | ||
| 151 | /* Initializing function */ | 151 | /* Initializing function */ |
| 152 | 152 | ||
diff --git a/fs/autofs/dirhash.c b/fs/autofs/dirhash.c index 5ccfcf26310d..3fded389d06b 100644 --- a/fs/autofs/dirhash.c +++ b/fs/autofs/dirhash.c | |||
| @@ -92,7 +92,7 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb, | |||
| 92 | ; | 92 | ; |
| 93 | dput(dentry); | 93 | dput(dentry); |
| 94 | 94 | ||
| 95 | if ( may_umount(mnt) == 0 ) { | 95 | if ( may_umount(mnt) ) { |
| 96 | mntput(mnt); | 96 | mntput(mnt); |
| 97 | DPRINTK(("autofs: signaling expire on %s\n", ent->name)); | 97 | DPRINTK(("autofs: signaling expire on %s\n", ent->name)); |
| 98 | return ent; /* Expirable! */ | 98 | return ent; /* Expirable! */ |
diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 870e2cf33016..9cac08d6a873 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c | |||
| @@ -26,7 +26,7 @@ static int autofs_root_rmdir(struct inode *,struct dentry *); | |||
| 26 | static int autofs_root_mkdir(struct inode *,struct dentry *,int); | 26 | static int autofs_root_mkdir(struct inode *,struct dentry *,int); |
| 27 | static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long); | 27 | static int autofs_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long); |
| 28 | 28 | ||
| 29 | struct file_operations autofs_root_operations = { | 29 | const struct file_operations autofs_root_operations = { |
| 30 | .read = generic_read_dir, | 30 | .read = generic_read_dir, |
| 31 | .readdir = autofs_root_readdir, | 31 | .readdir = autofs_root_readdir, |
| 32 | .ioctl = autofs_root_ioctl, | 32 | .ioctl = autofs_root_ioctl, |
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index f54c5b21f876..57c4903614e5 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * linux/fs/autofs/autofs_i.h | 3 | * linux/fs/autofs/autofs_i.h |
| 4 | * | 4 | * |
| 5 | * Copyright 1997-1998 Transmeta Corporation - All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation - All Rights Reserved |
| 6 | * Copyright 2005-2006 Ian Kent <raven@themaw.net> | ||
| 6 | * | 7 | * |
| 7 | * This file is part of the Linux kernel and is made available under | 8 | * This file is part of the Linux kernel and is made available under |
| 8 | * the terms of the GNU General Public License, version 2, or at your | 9 | * the terms of the GNU General Public License, version 2, or at your |
| @@ -41,14 +42,6 @@ | |||
| 41 | 42 | ||
| 42 | #define AUTOFS_SUPER_MAGIC 0x0187 | 43 | #define AUTOFS_SUPER_MAGIC 0x0187 |
| 43 | 44 | ||
| 44 | /* | ||
| 45 | * If the daemon returns a negative response (AUTOFS_IOC_FAIL) then the | ||
| 46 | * kernel will keep the negative response cached for up to the time given | ||
| 47 | * here, although the time can be shorter if the kernel throws the dcache | ||
| 48 | * entry away. This probably should be settable from user space. | ||
| 49 | */ | ||
| 50 | #define AUTOFS_NEGATIVE_TIMEOUT (60*HZ) /* 1 minute */ | ||
| 51 | |||
| 52 | /* Unified info structure. This is pointed to by both the dentry and | 45 | /* Unified info structure. This is pointed to by both the dentry and |
| 53 | inode structures. Each file in the filesystem has an instance of this | 46 | inode structures. Each file in the filesystem has an instance of this |
| 54 | structure. It holds a reference to the dentry, so dentries are never | 47 | structure. It holds a reference to the dentry, so dentries are never |
| @@ -63,6 +56,7 @@ struct autofs_info { | |||
| 63 | 56 | ||
| 64 | struct autofs_sb_info *sbi; | 57 | struct autofs_sb_info *sbi; |
| 65 | unsigned long last_used; | 58 | unsigned long last_used; |
| 59 | atomic_t count; | ||
| 66 | 60 | ||
| 67 | mode_t mode; | 61 | mode_t mode; |
| 68 | size_t size; | 62 | size_t size; |
| @@ -83,23 +77,37 @@ struct autofs_wait_queue { | |||
| 83 | int hash; | 77 | int hash; |
| 84 | int len; | 78 | int len; |
| 85 | char *name; | 79 | char *name; |
| 80 | u32 dev; | ||
| 81 | u64 ino; | ||
| 82 | uid_t uid; | ||
| 83 | gid_t gid; | ||
| 84 | pid_t pid; | ||
| 85 | pid_t tgid; | ||
| 86 | /* This is for status reporting upon return */ | 86 | /* This is for status reporting upon return */ |
| 87 | int status; | 87 | int status; |
| 88 | atomic_t notified; | 88 | atomic_t notify; |
| 89 | atomic_t wait_ctr; | 89 | atomic_t wait_ctr; |
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | #define AUTOFS_SBI_MAGIC 0x6d4a556d | 92 | #define AUTOFS_SBI_MAGIC 0x6d4a556d |
| 93 | 93 | ||
| 94 | #define AUTOFS_TYPE_INDIRECT 0x0001 | ||
| 95 | #define AUTOFS_TYPE_DIRECT 0x0002 | ||
| 96 | #define AUTOFS_TYPE_OFFSET 0x0004 | ||
| 97 | |||
| 94 | struct autofs_sb_info { | 98 | struct autofs_sb_info { |
| 95 | u32 magic; | 99 | u32 magic; |
| 96 | struct dentry *root; | 100 | struct dentry *root; |
| 101 | int pipefd; | ||
| 97 | struct file *pipe; | 102 | struct file *pipe; |
| 98 | pid_t oz_pgrp; | 103 | pid_t oz_pgrp; |
| 99 | int catatonic; | 104 | int catatonic; |
| 100 | int version; | 105 | int version; |
| 101 | int sub_version; | 106 | int sub_version; |
| 107 | int min_proto; | ||
| 108 | int max_proto; | ||
| 102 | unsigned long exp_timeout; | 109 | unsigned long exp_timeout; |
| 110 | unsigned int type; | ||
| 103 | int reghost_enabled; | 111 | int reghost_enabled; |
| 104 | int needs_reghost; | 112 | int needs_reghost; |
| 105 | struct super_block *sb; | 113 | struct super_block *sb; |
| @@ -166,8 +174,10 @@ int autofs4_expire_multi(struct super_block *, struct vfsmount *, | |||
| 166 | extern struct inode_operations autofs4_symlink_inode_operations; | 174 | extern struct inode_operations autofs4_symlink_inode_operations; |
| 167 | extern struct inode_operations autofs4_dir_inode_operations; | 175 | extern struct inode_operations autofs4_dir_inode_operations; |
| 168 | extern struct inode_operations autofs4_root_inode_operations; | 176 | extern struct inode_operations autofs4_root_inode_operations; |
| 169 | extern struct file_operations autofs4_dir_operations; | 177 | extern struct inode_operations autofs4_indirect_root_inode_operations; |
| 170 | extern struct file_operations autofs4_root_operations; | 178 | extern struct inode_operations autofs4_direct_root_inode_operations; |
| 179 | extern const struct file_operations autofs4_dir_operations; | ||
| 180 | extern const struct file_operations autofs4_root_operations; | ||
| 171 | 181 | ||
| 172 | /* Initializing function */ | 182 | /* Initializing function */ |
| 173 | 183 | ||
| @@ -176,13 +186,6 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *, struct autofs_sb_info | |||
| 176 | 186 | ||
| 177 | /* Queue management functions */ | 187 | /* Queue management functions */ |
| 178 | 188 | ||
| 179 | enum autofs_notify | ||
| 180 | { | ||
| 181 | NFY_NONE, | ||
| 182 | NFY_MOUNT, | ||
| 183 | NFY_EXPIRE | ||
| 184 | }; | ||
| 185 | |||
| 186 | int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify); | 189 | int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify); |
| 187 | int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int); | 190 | int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int); |
| 188 | void autofs4_catatonic_mode(struct autofs_sb_info *); | 191 | void autofs4_catatonic_mode(struct autofs_sb_info *); |
| @@ -200,12 +203,22 @@ static inline int autofs4_follow_mount(struct vfsmount **mnt, struct dentry **de | |||
| 200 | return res; | 203 | return res; |
| 201 | } | 204 | } |
| 202 | 205 | ||
| 206 | static inline u32 autofs4_get_dev(struct autofs_sb_info *sbi) | ||
| 207 | { | ||
| 208 | return new_encode_dev(sbi->sb->s_dev); | ||
| 209 | } | ||
| 210 | |||
| 211 | static inline u64 autofs4_get_ino(struct autofs_sb_info *sbi) | ||
| 212 | { | ||
| 213 | return sbi->sb->s_root->d_inode->i_ino; | ||
| 214 | } | ||
| 215 | |||
| 203 | static inline int simple_positive(struct dentry *dentry) | 216 | static inline int simple_positive(struct dentry *dentry) |
| 204 | { | 217 | { |
| 205 | return dentry->d_inode && !d_unhashed(dentry); | 218 | return dentry->d_inode && !d_unhashed(dentry); |
| 206 | } | 219 | } |
| 207 | 220 | ||
| 208 | static inline int simple_empty_nolock(struct dentry *dentry) | 221 | static inline int __simple_empty(struct dentry *dentry) |
| 209 | { | 222 | { |
| 210 | struct dentry *child; | 223 | struct dentry *child; |
| 211 | int ret = 0; | 224 | int ret = 0; |
| @@ -217,3 +230,6 @@ static inline int simple_empty_nolock(struct dentry *dentry) | |||
| 217 | out: | 230 | out: |
| 218 | return ret; | 231 | return ret; |
| 219 | } | 232 | } |
| 233 | |||
| 234 | void autofs4_dentry_release(struct dentry *); | ||
| 235 | |||
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index dc39589df165..b8ce02607d66 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | * | 4 | * |
| 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
| 6 | * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> | 6 | * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> |
| 7 | * Copyright 2001-2003 Ian Kent <raven@themaw.net> | 7 | * Copyright 2001-2006 Ian Kent <raven@themaw.net> |
| 8 | * | 8 | * |
| 9 | * This file is part of the Linux kernel and is made available under | 9 | * This file is part of the Linux kernel and is made available under |
| 10 | * the terms of the GNU General Public License, version 2, or at your | 10 | * the terms of the GNU General Public License, version 2, or at your |
| @@ -16,7 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | static unsigned long now; | 17 | static unsigned long now; |
| 18 | 18 | ||
| 19 | /* Check if a dentry can be expired return 1 if it can else return 0 */ | 19 | /* Check if a dentry can be expired */ |
| 20 | static inline int autofs4_can_expire(struct dentry *dentry, | 20 | static inline int autofs4_can_expire(struct dentry *dentry, |
| 21 | unsigned long timeout, int do_now) | 21 | unsigned long timeout, int do_now) |
| 22 | { | 22 | { |
| @@ -41,14 +41,14 @@ static inline int autofs4_can_expire(struct dentry *dentry, | |||
| 41 | attempts if expire fails the first time */ | 41 | attempts if expire fails the first time */ |
| 42 | ino->last_used = now; | 42 | ino->last_used = now; |
| 43 | } | 43 | } |
| 44 | |||
| 45 | return 1; | 44 | return 1; |
| 46 | } | 45 | } |
| 47 | 46 | ||
| 48 | /* Check a mount point for busyness return 1 if not busy, otherwise */ | 47 | /* Check a mount point for busyness */ |
| 49 | static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry) | 48 | static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) |
| 50 | { | 49 | { |
| 51 | int status = 0; | 50 | struct dentry *top = dentry; |
| 51 | int status = 1; | ||
| 52 | 52 | ||
| 53 | DPRINTK("dentry %p %.*s", | 53 | DPRINTK("dentry %p %.*s", |
| 54 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 54 | dentry, (int)dentry->d_name.len, dentry->d_name.name); |
| @@ -63,9 +63,14 @@ static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry) | |||
| 63 | if (is_autofs4_dentry(dentry)) | 63 | if (is_autofs4_dentry(dentry)) |
| 64 | goto done; | 64 | goto done; |
| 65 | 65 | ||
| 66 | /* The big question */ | 66 | /* Update the expiry counter if fs is busy */ |
| 67 | if (may_umount_tree(mnt) == 0) | 67 | if (!may_umount_tree(mnt)) { |
| 68 | status = 1; | 68 | struct autofs_info *ino = autofs4_dentry_ino(top); |
| 69 | ino->last_used = jiffies; | ||
| 70 | goto done; | ||
| 71 | } | ||
| 72 | |||
| 73 | status = 0; | ||
| 69 | done: | 74 | done: |
| 70 | DPRINTK("returning = %d", status); | 75 | DPRINTK("returning = %d", status); |
| 71 | mntput(mnt); | 76 | mntput(mnt); |
| @@ -73,78 +78,124 @@ done: | |||
| 73 | return status; | 78 | return status; |
| 74 | } | 79 | } |
| 75 | 80 | ||
| 81 | /* | ||
| 82 | * Calculate next entry in top down tree traversal. | ||
| 83 | * From next_mnt in namespace.c - elegant. | ||
| 84 | */ | ||
| 85 | static struct dentry *next_dentry(struct dentry *p, struct dentry *root) | ||
| 86 | { | ||
| 87 | struct list_head *next = p->d_subdirs.next; | ||
| 88 | |||
| 89 | if (next == &p->d_subdirs) { | ||
| 90 | while (1) { | ||
| 91 | if (p == root) | ||
| 92 | return NULL; | ||
| 93 | next = p->d_u.d_child.next; | ||
| 94 | if (next != &p->d_parent->d_subdirs) | ||
| 95 | break; | ||
| 96 | p = p->d_parent; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | return list_entry(next, struct dentry, d_u.d_child); | ||
| 100 | } | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Check a direct mount point for busyness. | ||
| 104 | * Direct mounts have similar expiry semantics to tree mounts. | ||
| 105 | * The tree is not busy iff no mountpoints are busy and there are no | ||
| 106 | * autofs submounts. | ||
| 107 | */ | ||
| 108 | static int autofs4_direct_busy(struct vfsmount *mnt, | ||
| 109 | struct dentry *top, | ||
| 110 | unsigned long timeout, | ||
| 111 | int do_now) | ||
| 112 | { | ||
| 113 | DPRINTK("top %p %.*s", | ||
| 114 | top, (int) top->d_name.len, top->d_name.name); | ||
| 115 | |||
| 116 | /* If it's busy update the expiry counters */ | ||
| 117 | if (!may_umount_tree(mnt)) { | ||
| 118 | struct autofs_info *ino = autofs4_dentry_ino(top); | ||
| 119 | if (ino) | ||
| 120 | ino->last_used = jiffies; | ||
| 121 | return 1; | ||
| 122 | } | ||
| 123 | |||
| 124 | /* Timeout of a direct mount is determined by its top dentry */ | ||
| 125 | if (!autofs4_can_expire(top, timeout, do_now)) | ||
| 126 | return 1; | ||
| 127 | |||
| 128 | return 0; | ||
| 129 | } | ||
| 130 | |||
| 76 | /* Check a directory tree of mount points for busyness | 131 | /* Check a directory tree of mount points for busyness |
| 77 | * The tree is not busy iff no mountpoints are busy | 132 | * The tree is not busy iff no mountpoints are busy |
| 78 | * Return 1 if the tree is busy or 0 otherwise | ||
| 79 | */ | 133 | */ |
| 80 | static int autofs4_check_tree(struct vfsmount *mnt, | 134 | static int autofs4_tree_busy(struct vfsmount *mnt, |
| 81 | struct dentry *top, | 135 | struct dentry *top, |
| 82 | unsigned long timeout, | 136 | unsigned long timeout, |
| 83 | int do_now) | 137 | int do_now) |
| 84 | { | 138 | { |
| 85 | struct dentry *this_parent = top; | 139 | struct autofs_info *top_ino = autofs4_dentry_ino(top); |
| 86 | struct list_head *next; | 140 | struct dentry *p; |
| 87 | 141 | ||
| 88 | DPRINTK("parent %p %.*s", | 142 | DPRINTK("top %p %.*s", |
| 89 | top, (int)top->d_name.len, top->d_name.name); | 143 | top, (int)top->d_name.len, top->d_name.name); |
| 90 | 144 | ||
| 91 | /* Negative dentry - give up */ | 145 | /* Negative dentry - give up */ |
| 92 | if (!simple_positive(top)) | 146 | if (!simple_positive(top)) |
| 93 | return 0; | 147 | return 1; |
| 94 | |||
| 95 | /* Timeout of a tree mount is determined by its top dentry */ | ||
| 96 | if (!autofs4_can_expire(top, timeout, do_now)) | ||
| 97 | return 0; | ||
| 98 | |||
| 99 | /* Is someone visiting anywhere in the tree ? */ | ||
| 100 | if (may_umount_tree(mnt)) | ||
| 101 | return 0; | ||
| 102 | 148 | ||
| 103 | spin_lock(&dcache_lock); | 149 | spin_lock(&dcache_lock); |
| 104 | repeat: | 150 | for (p = top; p; p = next_dentry(p, top)) { |
| 105 | next = this_parent->d_subdirs.next; | ||
| 106 | resume: | ||
| 107 | while (next != &this_parent->d_subdirs) { | ||
| 108 | struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); | ||
| 109 | |||
| 110 | /* Negative dentry - give up */ | 151 | /* Negative dentry - give up */ |
| 111 | if (!simple_positive(dentry)) { | 152 | if (!simple_positive(p)) |
| 112 | next = next->next; | ||
| 113 | continue; | 153 | continue; |
| 114 | } | ||
| 115 | 154 | ||
| 116 | DPRINTK("dentry %p %.*s", | 155 | DPRINTK("dentry %p %.*s", |
| 117 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 156 | p, (int) p->d_name.len, p->d_name.name); |
| 118 | |||
| 119 | if (!simple_empty_nolock(dentry)) { | ||
| 120 | this_parent = dentry; | ||
| 121 | goto repeat; | ||
| 122 | } | ||
| 123 | 157 | ||
| 124 | dentry = dget(dentry); | 158 | p = dget(p); |
| 125 | spin_unlock(&dcache_lock); | 159 | spin_unlock(&dcache_lock); |
| 126 | 160 | ||
| 127 | if (d_mountpoint(dentry)) { | 161 | /* |
| 128 | /* First busy => tree busy */ | 162 | * Is someone visiting anywhere in the subtree ? |
| 129 | if (!autofs4_check_mount(mnt, dentry)) { | 163 | * If there's no mount we need to check the usage |
| 130 | dput(dentry); | 164 | * count for the autofs dentry. |
| 131 | return 0; | 165 | * If the fs is busy update the expiry counter. |
| 166 | */ | ||
| 167 | if (d_mountpoint(p)) { | ||
| 168 | if (autofs4_mount_busy(mnt, p)) { | ||
| 169 | top_ino->last_used = jiffies; | ||
| 170 | dput(p); | ||
| 171 | return 1; | ||
| 172 | } | ||
| 173 | } else { | ||
| 174 | struct autofs_info *ino = autofs4_dentry_ino(p); | ||
| 175 | unsigned int ino_count = atomic_read(&ino->count); | ||
| 176 | |||
| 177 | /* allow for dget above and top is already dgot */ | ||
| 178 | if (p == top) | ||
| 179 | ino_count += 2; | ||
| 180 | else | ||
| 181 | ino_count++; | ||
| 182 | |||
| 183 | if (atomic_read(&p->d_count) > ino_count) { | ||
| 184 | top_ino->last_used = jiffies; | ||
| 185 | dput(p); | ||
| 186 | return 1; | ||
| 132 | } | 187 | } |
| 133 | } | 188 | } |
| 134 | 189 | dput(p); | |
| 135 | dput(dentry); | ||
| 136 | spin_lock(&dcache_lock); | 190 | spin_lock(&dcache_lock); |
| 137 | next = next->next; | ||
| 138 | } | ||
| 139 | |||
| 140 | if (this_parent != top) { | ||
| 141 | next = this_parent->d_u.d_child.next; | ||
| 142 | this_parent = this_parent->d_parent; | ||
| 143 | goto resume; | ||
| 144 | } | 191 | } |
| 145 | spin_unlock(&dcache_lock); | 192 | spin_unlock(&dcache_lock); |
| 146 | 193 | ||
| 147 | return 1; | 194 | /* Timeout of a tree mount is ultimately determined by its top dentry */ |
| 195 | if (!autofs4_can_expire(top, timeout, do_now)) | ||
| 196 | return 1; | ||
| 197 | |||
| 198 | return 0; | ||
| 148 | } | 199 | } |
| 149 | 200 | ||
| 150 | static struct dentry *autofs4_check_leaves(struct vfsmount *mnt, | 201 | static struct dentry *autofs4_check_leaves(struct vfsmount *mnt, |
| @@ -152,58 +203,68 @@ static struct dentry *autofs4_check_leaves(struct vfsmount *mnt, | |||
| 152 | unsigned long timeout, | 203 | unsigned long timeout, |
| 153 | int do_now) | 204 | int do_now) |
| 154 | { | 205 | { |
| 155 | struct dentry *this_parent = parent; | 206 | struct dentry *p; |
| 156 | struct list_head *next; | ||
| 157 | 207 | ||
| 158 | DPRINTK("parent %p %.*s", | 208 | DPRINTK("parent %p %.*s", |
| 159 | parent, (int)parent->d_name.len, parent->d_name.name); | 209 | parent, (int)parent->d_name.len, parent->d_name.name); |
| 160 | 210 | ||
| 161 | spin_lock(&dcache_lock); | 211 | spin_lock(&dcache_lock); |
| 162 | repeat: | 212 | for (p = parent; p; p = next_dentry(p, parent)) { |
| 163 | next = this_parent->d_subdirs.next; | ||
| 164 | resume: | ||
| 165 | while (next != &this_parent->d_subdirs) { | ||
| 166 | struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); | ||
| 167 | |||
| 168 | /* Negative dentry - give up */ | 213 | /* Negative dentry - give up */ |
| 169 | if (!simple_positive(dentry)) { | 214 | if (!simple_positive(p)) |
| 170 | next = next->next; | ||
| 171 | continue; | 215 | continue; |
| 172 | } | ||
| 173 | 216 | ||
| 174 | DPRINTK("dentry %p %.*s", | 217 | DPRINTK("dentry %p %.*s", |
| 175 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 218 | p, (int) p->d_name.len, p->d_name.name); |
| 176 | |||
| 177 | if (!list_empty(&dentry->d_subdirs)) { | ||
| 178 | this_parent = dentry; | ||
| 179 | goto repeat; | ||
| 180 | } | ||
| 181 | 219 | ||
| 182 | dentry = dget(dentry); | 220 | p = dget(p); |
| 183 | spin_unlock(&dcache_lock); | 221 | spin_unlock(&dcache_lock); |
| 184 | 222 | ||
| 185 | if (d_mountpoint(dentry)) { | 223 | if (d_mountpoint(p)) { |
| 186 | /* Can we expire this guy */ | ||
| 187 | if (!autofs4_can_expire(dentry, timeout, do_now)) | ||
| 188 | goto cont; | ||
| 189 | |||
| 190 | /* Can we umount this guy */ | 224 | /* Can we umount this guy */ |
| 191 | if (autofs4_check_mount(mnt, dentry)) | 225 | if (autofs4_mount_busy(mnt, p)) |
| 192 | return dentry; | 226 | goto cont; |
| 193 | 227 | ||
| 228 | /* Can we expire this guy */ | ||
| 229 | if (autofs4_can_expire(p, timeout, do_now)) | ||
| 230 | return p; | ||
| 194 | } | 231 | } |
| 195 | cont: | 232 | cont: |
| 196 | dput(dentry); | 233 | dput(p); |
| 197 | spin_lock(&dcache_lock); | 234 | spin_lock(&dcache_lock); |
| 198 | next = next->next; | ||
| 199 | } | 235 | } |
| 236 | spin_unlock(&dcache_lock); | ||
| 237 | return NULL; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* Check if we can expire a direct mount (possibly a tree) */ | ||
| 241 | static struct dentry *autofs4_expire_direct(struct super_block *sb, | ||
| 242 | struct vfsmount *mnt, | ||
| 243 | struct autofs_sb_info *sbi, | ||
| 244 | int how) | ||
| 245 | { | ||
| 246 | unsigned long timeout; | ||
| 247 | struct dentry *root = dget(sb->s_root); | ||
| 248 | int do_now = how & AUTOFS_EXP_IMMEDIATE; | ||
| 249 | |||
| 250 | if (!sbi->exp_timeout || !root) | ||
| 251 | return NULL; | ||
| 252 | |||
| 253 | now = jiffies; | ||
| 254 | timeout = sbi->exp_timeout; | ||
| 255 | |||
| 256 | /* Lock the tree as we must expire as a whole */ | ||
| 257 | spin_lock(&sbi->fs_lock); | ||
| 258 | if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { | ||
| 259 | struct autofs_info *ino = autofs4_dentry_ino(root); | ||
| 200 | 260 | ||
| 201 | if (this_parent != parent) { | 261 | /* Set this flag early to catch sys_chdir and the like */ |
| 202 | next = this_parent->d_u.d_child.next; | 262 | ino->flags |= AUTOFS_INF_EXPIRING; |
| 203 | this_parent = this_parent->d_parent; | 263 | spin_unlock(&sbi->fs_lock); |
| 204 | goto resume; | 264 | return root; |
| 205 | } | 265 | } |
| 206 | spin_unlock(&dcache_lock); | 266 | spin_unlock(&sbi->fs_lock); |
| 267 | dput(root); | ||
| 207 | 268 | ||
| 208 | return NULL; | 269 | return NULL; |
| 209 | } | 270 | } |
| @@ -214,10 +275,10 @@ cont: | |||
| 214 | * - it is unused by any user process | 275 | * - it is unused by any user process |
| 215 | * - it has been unused for exp_timeout time | 276 | * - it has been unused for exp_timeout time |
| 216 | */ | 277 | */ |
| 217 | static struct dentry *autofs4_expire(struct super_block *sb, | 278 | static struct dentry *autofs4_expire_indirect(struct super_block *sb, |
| 218 | struct vfsmount *mnt, | 279 | struct vfsmount *mnt, |
| 219 | struct autofs_sb_info *sbi, | 280 | struct autofs_sb_info *sbi, |
| 220 | int how) | 281 | int how) |
| 221 | { | 282 | { |
| 222 | unsigned long timeout; | 283 | unsigned long timeout; |
| 223 | struct dentry *root = sb->s_root; | 284 | struct dentry *root = sb->s_root; |
| @@ -241,7 +302,7 @@ static struct dentry *autofs4_expire(struct super_block *sb, | |||
| 241 | struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); | 302 | struct dentry *dentry = list_entry(next, struct dentry, d_u.d_child); |
| 242 | 303 | ||
| 243 | /* Negative dentry - give up */ | 304 | /* Negative dentry - give up */ |
| 244 | if ( !simple_positive(dentry) ) { | 305 | if (!simple_positive(dentry)) { |
| 245 | next = next->next; | 306 | next = next->next; |
| 246 | continue; | 307 | continue; |
| 247 | } | 308 | } |
| @@ -249,31 +310,36 @@ static struct dentry *autofs4_expire(struct super_block *sb, | |||
| 249 | dentry = dget(dentry); | 310 | dentry = dget(dentry); |
| 250 | spin_unlock(&dcache_lock); | 311 | spin_unlock(&dcache_lock); |
| 251 | 312 | ||
| 252 | /* Case 1: indirect mount or top level direct mount */ | 313 | /* |
| 314 | * Case 1: (i) indirect mount or top level pseudo direct mount | ||
| 315 | * (autofs-4.1). | ||
| 316 | * (ii) indirect mount with offset mount, check the "/" | ||
| 317 | * offset (autofs-5.0+). | ||
| 318 | */ | ||
| 253 | if (d_mountpoint(dentry)) { | 319 | if (d_mountpoint(dentry)) { |
| 254 | DPRINTK("checking mountpoint %p %.*s", | 320 | DPRINTK("checking mountpoint %p %.*s", |
| 255 | dentry, (int)dentry->d_name.len, dentry->d_name.name); | 321 | dentry, (int)dentry->d_name.len, dentry->d_name.name); |
| 256 | 322 | ||
| 257 | /* Can we expire this guy */ | 323 | /* Can we umount this guy */ |
| 258 | if (!autofs4_can_expire(dentry, timeout, do_now)) | 324 | if (autofs4_mount_busy(mnt, dentry)) |
| 259 | goto next; | 325 | goto next; |
| 260 | 326 | ||
| 261 | /* Can we umount this guy */ | 327 | /* Can we expire this guy */ |
| 262 | if (autofs4_check_mount(mnt, dentry)) { | 328 | if (autofs4_can_expire(dentry, timeout, do_now)) { |
| 263 | expired = dentry; | 329 | expired = dentry; |
| 264 | break; | 330 | break; |
| 265 | } | 331 | } |
| 266 | goto next; | 332 | goto next; |
| 267 | } | 333 | } |
| 268 | 334 | ||
| 269 | if ( simple_empty(dentry) ) | 335 | if (simple_empty(dentry)) |
| 270 | goto next; | 336 | goto next; |
| 271 | 337 | ||
| 272 | /* Case 2: tree mount, expire iff entire tree is not busy */ | 338 | /* Case 2: tree mount, expire iff entire tree is not busy */ |
| 273 | if (!exp_leaves) { | 339 | if (!exp_leaves) { |
| 274 | /* Lock the tree as we must expire as a whole */ | 340 | /* Lock the tree as we must expire as a whole */ |
| 275 | spin_lock(&sbi->fs_lock); | 341 | spin_lock(&sbi->fs_lock); |
| 276 | if (autofs4_check_tree(mnt, dentry, timeout, do_now)) { | 342 | if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) { |
| 277 | struct autofs_info *inf = autofs4_dentry_ino(dentry); | 343 | struct autofs_info *inf = autofs4_dentry_ino(dentry); |
| 278 | 344 | ||
| 279 | /* Set this flag early to catch sys_chdir and the like */ | 345 | /* Set this flag early to catch sys_chdir and the like */ |
| @@ -283,7 +349,10 @@ static struct dentry *autofs4_expire(struct super_block *sb, | |||
| 283 | break; | 349 | break; |
| 284 | } | 350 | } |
| 285 | spin_unlock(&sbi->fs_lock); | 351 | spin_unlock(&sbi->fs_lock); |
| 286 | /* Case 3: direct mount, expire individual leaves */ | 352 | /* |
| 353 | * Case 3: pseudo direct mount, expire individual leaves | ||
| 354 | * (autofs-4.1). | ||
| 355 | */ | ||
| 287 | } else { | 356 | } else { |
| 288 | expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); | 357 | expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); |
| 289 | if (expired) { | 358 | if (expired) { |
| @@ -297,7 +366,7 @@ next: | |||
| 297 | next = next->next; | 366 | next = next->next; |
| 298 | } | 367 | } |
| 299 | 368 | ||
| 300 | if ( expired ) { | 369 | if (expired) { |
| 301 | DPRINTK("returning %p %.*s", | 370 | DPRINTK("returning %p %.*s", |
| 302 | expired, (int)expired->d_name.len, expired->d_name.name); | 371 | expired, (int)expired->d_name.len, expired->d_name.name); |
| 303 | spin_lock(&dcache_lock); | 372 | spin_lock(&dcache_lock); |
| @@ -325,7 +394,7 @@ int autofs4_expire_run(struct super_block *sb, | |||
| 325 | pkt.hdr.proto_version = sbi->version; | 394 | pkt.hdr.proto_version = sbi->version; |
| 326 | pkt.hdr.type = autofs_ptype_expire; | 395 | pkt.hdr.type = autofs_ptype_expire; |
| 327 | 396 | ||
| 328 | if ((dentry = autofs4_expire(sb, mnt, sbi, 0)) == NULL) | 397 | if ((dentry = autofs4_expire_indirect(sb, mnt, sbi, 0)) == NULL) |
| 329 | return -EAGAIN; | 398 | return -EAGAIN; |
| 330 | 399 | ||
| 331 | pkt.len = dentry->d_name.len; | 400 | pkt.len = dentry->d_name.len; |
| @@ -351,17 +420,22 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt, | |||
| 351 | if (arg && get_user(do_now, arg)) | 420 | if (arg && get_user(do_now, arg)) |
| 352 | return -EFAULT; | 421 | return -EFAULT; |
| 353 | 422 | ||
| 354 | if ((dentry = autofs4_expire(sb, mnt, sbi, do_now)) != NULL) { | 423 | if (sbi->type & AUTOFS_TYPE_DIRECT) |
| 355 | struct autofs_info *de_info = autofs4_dentry_ino(dentry); | 424 | dentry = autofs4_expire_direct(sb, mnt, sbi, do_now); |
| 425 | else | ||
| 426 | dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now); | ||
| 427 | |||
| 428 | if (dentry) { | ||
| 429 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
| 356 | 430 | ||
| 357 | /* This is synchronous because it makes the daemon a | 431 | /* This is synchronous because it makes the daemon a |
| 358 | little easier */ | 432 | little easier */ |
| 359 | de_info->flags |= AUTOFS_INF_EXPIRING; | 433 | ino->flags |= AUTOFS_INF_EXPIRING; |
| 360 | ret = autofs4_wait(sbi, dentry, NFY_EXPIRE); | 434 | ret = autofs4_wait(sbi, dentry, NFY_EXPIRE); |
| 361 | de_info->flags &= ~AUTOFS_INF_EXPIRING; | 435 | ino->flags &= ~AUTOFS_INF_EXPIRING; |
| 362 | dput(dentry); | 436 | dput(dentry); |
| 363 | } | 437 | } |
| 364 | 438 | ||
| 365 | return ret; | 439 | return ret; |
| 366 | } | 440 | } |
| 367 | 441 | ||
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index 1ad98d48e550..fde78b110ddd 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * linux/fs/autofs/inode.c | 3 | * linux/fs/autofs/inode.c |
| 4 | * | 4 | * |
| 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
| 6 | * Copyright 2005-2006 Ian Kent <raven@themaw.net> | ||
| 6 | * | 7 | * |
| 7 | * This file is part of the Linux kernel and is made available under | 8 | * This file is part of the Linux kernel and is made available under |
| 8 | * the terms of the GNU General Public License, version 2, or at your | 9 | * the terms of the GNU General Public License, version 2, or at your |
| @@ -13,6 +14,7 @@ | |||
| 13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 15 | #include <linux/file.h> | 16 | #include <linux/file.h> |
| 17 | #include <linux/seq_file.h> | ||
| 16 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
| 17 | #include <linux/parser.h> | 19 | #include <linux/parser.h> |
| 18 | #include <linux/bitops.h> | 20 | #include <linux/bitops.h> |
| @@ -46,6 +48,7 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, | |||
| 46 | ino->size = 0; | 48 | ino->size = 0; |
| 47 | 49 | ||
| 48 | ino->last_used = jiffies; | 50 | ino->last_used = jiffies; |
| 51 | atomic_set(&ino->count, 0); | ||
| 49 | 52 | ||
| 50 | ino->sbi = sbi; | 53 | ino->sbi = sbi; |
| 51 | 54 | ||
| @@ -64,10 +67,19 @@ struct autofs_info *autofs4_init_ino(struct autofs_info *ino, | |||
| 64 | 67 | ||
| 65 | void autofs4_free_ino(struct autofs_info *ino) | 68 | void autofs4_free_ino(struct autofs_info *ino) |
| 66 | { | 69 | { |
| 70 | struct autofs_info *p_ino; | ||
| 71 | |||
| 67 | if (ino->dentry) { | 72 | if (ino->dentry) { |
| 68 | ino->dentry->d_fsdata = NULL; | 73 | ino->dentry->d_fsdata = NULL; |
| 69 | if (ino->dentry->d_inode) | 74 | if (ino->dentry->d_inode) { |
| 75 | struct dentry *parent = ino->dentry->d_parent; | ||
| 76 | if (atomic_dec_and_test(&ino->count)) { | ||
| 77 | p_ino = autofs4_dentry_ino(parent); | ||
| 78 | if (p_ino && parent != ino->dentry) | ||
| 79 | atomic_dec(&p_ino->count); | ||
| 80 | } | ||
| 70 | dput(ino->dentry); | 81 | dput(ino->dentry); |
| 82 | } | ||
| 71 | ino->dentry = NULL; | 83 | ino->dentry = NULL; |
| 72 | } | 84 | } |
| 73 | if (ino->free) | 85 | if (ino->free) |
| @@ -145,20 +157,44 @@ static void autofs4_put_super(struct super_block *sb) | |||
| 145 | autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ | 157 | autofs4_catatonic_mode(sbi); /* Free wait queues, close pipe */ |
| 146 | 158 | ||
| 147 | /* Clean up and release dangling references */ | 159 | /* Clean up and release dangling references */ |
| 148 | if (sbi) | 160 | autofs4_force_release(sbi); |
| 149 | autofs4_force_release(sbi); | ||
| 150 | 161 | ||
| 151 | kfree(sbi); | 162 | kfree(sbi); |
| 152 | 163 | ||
| 153 | DPRINTK("shutting down"); | 164 | DPRINTK("shutting down"); |
| 154 | } | 165 | } |
| 155 | 166 | ||
| 167 | static int autofs4_show_options(struct seq_file *m, struct vfsmount *mnt) | ||
| 168 | { | ||
| 169 | struct autofs_sb_info *sbi = autofs4_sbi(mnt->mnt_sb); | ||
| 170 | |||
| 171 | if (!sbi) | ||
| 172 | return 0; | ||
| 173 | |||
| 174 | seq_printf(m, ",fd=%d", sbi->pipefd); | ||
| 175 | seq_printf(m, ",pgrp=%d", sbi->oz_pgrp); | ||
| 176 | seq_printf(m, ",timeout=%lu", sbi->exp_timeout/HZ); | ||
| 177 | seq_printf(m, ",minproto=%d", sbi->min_proto); | ||
| 178 | seq_printf(m, ",maxproto=%d", sbi->max_proto); | ||
| 179 | |||
| 180 | if (sbi->type & AUTOFS_TYPE_OFFSET) | ||
| 181 | seq_printf(m, ",offset"); | ||
| 182 | else if (sbi->type & AUTOFS_TYPE_DIRECT) | ||
| 183 | seq_printf(m, ",direct"); | ||
| 184 | else | ||
| 185 | seq_printf(m, ",indirect"); | ||
| 186 | |||
| 187 | return 0; | ||
| 188 | } | ||
| 189 | |||
| 156 | static struct super_operations autofs4_sops = { | 190 | static struct super_operations autofs4_sops = { |
| 157 | .put_super = autofs4_put_super, | 191 | .put_super = autofs4_put_super, |
| 158 | .statfs = simple_statfs, | 192 | .statfs = simple_statfs, |
| 193 | .show_options = autofs4_show_options, | ||
| 159 | }; | 194 | }; |
| 160 | 195 | ||
| 161 | enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto}; | 196 | enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto, |
| 197 | Opt_indirect, Opt_direct, Opt_offset}; | ||
| 162 | 198 | ||
| 163 | static match_table_t tokens = { | 199 | static match_table_t tokens = { |
| 164 | {Opt_fd, "fd=%u"}, | 200 | {Opt_fd, "fd=%u"}, |
| @@ -167,11 +203,15 @@ static match_table_t tokens = { | |||
| 167 | {Opt_pgrp, "pgrp=%u"}, | 203 | {Opt_pgrp, "pgrp=%u"}, |
| 168 | {Opt_minproto, "minproto=%u"}, | 204 | {Opt_minproto, "minproto=%u"}, |
| 169 | {Opt_maxproto, "maxproto=%u"}, | 205 | {Opt_maxproto, "maxproto=%u"}, |
| 206 | {Opt_indirect, "indirect"}, | ||
| 207 | {Opt_direct, "direct"}, | ||
| 208 | {Opt_offset, "offset"}, | ||
| 170 | {Opt_err, NULL} | 209 | {Opt_err, NULL} |
| 171 | }; | 210 | }; |
| 172 | 211 | ||
| 173 | static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, | 212 | static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, |
| 174 | pid_t *pgrp, int *minproto, int *maxproto) | 213 | pid_t *pgrp, unsigned int *type, |
| 214 | int *minproto, int *maxproto) | ||
| 175 | { | 215 | { |
| 176 | char *p; | 216 | char *p; |
| 177 | substring_t args[MAX_OPT_ARGS]; | 217 | substring_t args[MAX_OPT_ARGS]; |
| @@ -225,6 +265,15 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, | |||
| 225 | return 1; | 265 | return 1; |
| 226 | *maxproto = option; | 266 | *maxproto = option; |
| 227 | break; | 267 | break; |
| 268 | case Opt_indirect: | ||
| 269 | *type = AUTOFS_TYPE_INDIRECT; | ||
| 270 | break; | ||
| 271 | case Opt_direct: | ||
| 272 | *type = AUTOFS_TYPE_DIRECT; | ||
| 273 | break; | ||
| 274 | case Opt_offset: | ||
| 275 | *type = AUTOFS_TYPE_DIRECT | AUTOFS_TYPE_OFFSET; | ||
| 276 | break; | ||
| 228 | default: | 277 | default: |
| 229 | return 1; | 278 | return 1; |
| 230 | } | 279 | } |
| @@ -243,6 +292,10 @@ static struct autofs_info *autofs4_mkroot(struct autofs_sb_info *sbi) | |||
| 243 | return ino; | 292 | return ino; |
| 244 | } | 293 | } |
| 245 | 294 | ||
| 295 | static struct dentry_operations autofs4_sb_dentry_operations = { | ||
| 296 | .d_release = autofs4_dentry_release, | ||
| 297 | }; | ||
| 298 | |||
| 246 | int autofs4_fill_super(struct super_block *s, void *data, int silent) | 299 | int autofs4_fill_super(struct super_block *s, void *data, int silent) |
| 247 | { | 300 | { |
| 248 | struct inode * root_inode; | 301 | struct inode * root_inode; |
| @@ -251,7 +304,6 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
| 251 | int pipefd; | 304 | int pipefd; |
| 252 | struct autofs_sb_info *sbi; | 305 | struct autofs_sb_info *sbi; |
| 253 | struct autofs_info *ino; | 306 | struct autofs_info *ino; |
| 254 | int minproto, maxproto; | ||
| 255 | 307 | ||
| 256 | sbi = (struct autofs_sb_info *) kmalloc(sizeof(*sbi), GFP_KERNEL); | 308 | sbi = (struct autofs_sb_info *) kmalloc(sizeof(*sbi), GFP_KERNEL); |
| 257 | if ( !sbi ) | 309 | if ( !sbi ) |
| @@ -263,12 +315,16 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
| 263 | s->s_fs_info = sbi; | 315 | s->s_fs_info = sbi; |
| 264 | sbi->magic = AUTOFS_SBI_MAGIC; | 316 | sbi->magic = AUTOFS_SBI_MAGIC; |
| 265 | sbi->root = NULL; | 317 | sbi->root = NULL; |
| 318 | sbi->pipefd = -1; | ||
| 266 | sbi->catatonic = 0; | 319 | sbi->catatonic = 0; |
| 267 | sbi->exp_timeout = 0; | 320 | sbi->exp_timeout = 0; |
| 268 | sbi->oz_pgrp = process_group(current); | 321 | sbi->oz_pgrp = process_group(current); |
| 269 | sbi->sb = s; | 322 | sbi->sb = s; |
| 270 | sbi->version = 0; | 323 | sbi->version = 0; |
| 271 | sbi->sub_version = 0; | 324 | sbi->sub_version = 0; |
| 325 | sbi->type = 0; | ||
| 326 | sbi->min_proto = 0; | ||
| 327 | sbi->max_proto = 0; | ||
| 272 | mutex_init(&sbi->wq_mutex); | 328 | mutex_init(&sbi->wq_mutex); |
| 273 | spin_lock_init(&sbi->fs_lock); | 329 | spin_lock_init(&sbi->fs_lock); |
| 274 | sbi->queues = NULL; | 330 | sbi->queues = NULL; |
| @@ -285,38 +341,46 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
| 285 | if (!ino) | 341 | if (!ino) |
| 286 | goto fail_free; | 342 | goto fail_free; |
| 287 | root_inode = autofs4_get_inode(s, ino); | 343 | root_inode = autofs4_get_inode(s, ino); |
| 288 | kfree(ino); | ||
| 289 | if (!root_inode) | 344 | if (!root_inode) |
| 290 | goto fail_free; | 345 | goto fail_ino; |
| 291 | 346 | ||
| 292 | root_inode->i_op = &autofs4_root_inode_operations; | ||
| 293 | root_inode->i_fop = &autofs4_root_operations; | ||
| 294 | root = d_alloc_root(root_inode); | 347 | root = d_alloc_root(root_inode); |
| 295 | pipe = NULL; | ||
| 296 | |||
| 297 | if (!root) | 348 | if (!root) |
| 298 | goto fail_iput; | 349 | goto fail_iput; |
| 350 | pipe = NULL; | ||
| 351 | |||
| 352 | root->d_op = &autofs4_sb_dentry_operations; | ||
| 353 | root->d_fsdata = ino; | ||
| 299 | 354 | ||
| 300 | /* Can this call block? */ | 355 | /* Can this call block? */ |
| 301 | if (parse_options(data, &pipefd, | 356 | if (parse_options(data, &pipefd, |
| 302 | &root_inode->i_uid, &root_inode->i_gid, | 357 | &root_inode->i_uid, &root_inode->i_gid, |
| 303 | &sbi->oz_pgrp, | 358 | &sbi->oz_pgrp, &sbi->type, |
| 304 | &minproto, &maxproto)) { | 359 | &sbi->min_proto, &sbi->max_proto)) { |
| 305 | printk("autofs: called with bogus options\n"); | 360 | printk("autofs: called with bogus options\n"); |
| 306 | goto fail_dput; | 361 | goto fail_dput; |
| 307 | } | 362 | } |
| 308 | 363 | ||
| 364 | root_inode->i_fop = &autofs4_root_operations; | ||
| 365 | root_inode->i_op = sbi->type & AUTOFS_TYPE_DIRECT ? | ||
| 366 | &autofs4_direct_root_inode_operations : | ||
| 367 | &autofs4_indirect_root_inode_operations; | ||
| 368 | |||
| 309 | /* Couldn't this be tested earlier? */ | 369 | /* Couldn't this be tested earlier? */ |
| 310 | if (maxproto < AUTOFS_MIN_PROTO_VERSION || | 370 | if (sbi->max_proto < AUTOFS_MIN_PROTO_VERSION || |
| 311 | minproto > AUTOFS_MAX_PROTO_VERSION) { | 371 | sbi->min_proto > AUTOFS_MAX_PROTO_VERSION) { |
| 312 | printk("autofs: kernel does not match daemon version " | 372 | printk("autofs: kernel does not match daemon version " |
| 313 | "daemon (%d, %d) kernel (%d, %d)\n", | 373 | "daemon (%d, %d) kernel (%d, %d)\n", |
| 314 | minproto, maxproto, | 374 | sbi->min_proto, sbi->max_proto, |
| 315 | AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION); | 375 | AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION); |
| 316 | goto fail_dput; | 376 | goto fail_dput; |
| 317 | } | 377 | } |
| 318 | 378 | ||
| 319 | sbi->version = maxproto > AUTOFS_MAX_PROTO_VERSION ? AUTOFS_MAX_PROTO_VERSION : maxproto; | 379 | /* Establish highest kernel protocol version */ |
| 380 | if (sbi->max_proto > AUTOFS_MAX_PROTO_VERSION) | ||
| 381 | sbi->version = AUTOFS_MAX_PROTO_VERSION; | ||
| 382 | else | ||
| 383 | sbi->version = sbi->max_proto; | ||
| 320 | sbi->sub_version = AUTOFS_PROTO_SUBVERSION; | 384 | sbi->sub_version = AUTOFS_PROTO_SUBVERSION; |
| 321 | 385 | ||
| 322 | DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp); | 386 | DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp); |
| @@ -329,6 +393,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) | |||
| 329 | if ( !pipe->f_op || !pipe->f_op->write ) | 393 | if ( !pipe->f_op || !pipe->f_op->write ) |
| 330 | goto fail_fput; | 394 | goto fail_fput; |
| 331 | sbi->pipe = pipe; | 395 | sbi->pipe = pipe; |
| 396 | sbi->pipefd = pipefd; | ||
| 332 | 397 | ||
| 333 | /* | 398 | /* |
| 334 | * Take a reference to the root dentry so we get a chance to | 399 | * Take a reference to the root dentry so we get a chance to |
| @@ -356,6 +421,8 @@ fail_dput: | |||
| 356 | fail_iput: | 421 | fail_iput: |
| 357 | printk("autofs: get root dentry failed\n"); | 422 | printk("autofs: get root dentry failed\n"); |
| 358 | iput(root_inode); | 423 | iput(root_inode); |
| 424 | fail_ino: | ||
| 425 | kfree(ino); | ||
| 359 | fail_free: | 426 | fail_free: |
| 360 | kfree(sbi); | 427 | kfree(sbi); |
| 361 | fail_unlock: | 428 | fail_unlock: |
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 62d8d4acb8bb..84e030c8ddd0 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | * | 4 | * |
| 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
| 6 | * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> | 6 | * Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org> |
| 7 | * Copyright 2001-2003 Ian Kent <raven@themaw.net> | 7 | * Copyright 2001-2006 Ian Kent <raven@themaw.net> |
| 8 | * | 8 | * |
| 9 | * This file is part of the Linux kernel and is made available under | 9 | * This file is part of the Linux kernel and is made available under |
| 10 | * the terms of the GNU General Public License, version 2, or at your | 10 | * the terms of the GNU General Public License, version 2, or at your |
| @@ -30,9 +30,9 @@ static int autofs4_dir_close(struct inode *inode, struct file *file); | |||
| 30 | static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); | 30 | static int autofs4_dir_readdir(struct file * filp, void * dirent, filldir_t filldir); |
| 31 | static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir); | 31 | static int autofs4_root_readdir(struct file * filp, void * dirent, filldir_t filldir); |
| 32 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); | 32 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); |
| 33 | static int autofs4_dcache_readdir(struct file *, void *, filldir_t); | 33 | static void *autofs4_follow_link(struct dentry *, struct nameidata *); |
| 34 | 34 | ||
| 35 | struct file_operations autofs4_root_operations = { | 35 | const struct file_operations autofs4_root_operations = { |
| 36 | .open = dcache_dir_open, | 36 | .open = dcache_dir_open, |
| 37 | .release = dcache_dir_close, | 37 | .release = dcache_dir_close, |
| 38 | .read = generic_read_dir, | 38 | .read = generic_read_dir, |
| @@ -40,14 +40,14 @@ struct file_operations autofs4_root_operations = { | |||
| 40 | .ioctl = autofs4_root_ioctl, | 40 | .ioctl = autofs4_root_ioctl, |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | struct file_operations autofs4_dir_operations = { | 43 | const struct file_operations autofs4_dir_operations = { |
| 44 | .open = autofs4_dir_open, | 44 | .open = autofs4_dir_open, |
| 45 | .release = autofs4_dir_close, | 45 | .release = autofs4_dir_close, |
| 46 | .read = generic_read_dir, | 46 | .read = generic_read_dir, |
| 47 | .readdir = autofs4_dir_readdir, | 47 | .readdir = autofs4_dir_readdir, |
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| 50 | struct inode_operations autofs4_root_inode_operations = { | 50 | struct inode_operations autofs4_indirect_root_inode_operations = { |
| 51 | .lookup = autofs4_lookup, | 51 | .lookup = autofs4_lookup, |
| 52 | .unlink = autofs4_dir_unlink, | 52 | .unlink = autofs4_dir_unlink, |
| 53 | .symlink = autofs4_dir_symlink, | 53 | .symlink = autofs4_dir_symlink, |
| @@ -55,6 +55,14 @@ struct inode_operations autofs4_root_inode_operations = { | |||
| 55 | .rmdir = autofs4_dir_rmdir, | 55 | .rmdir = autofs4_dir_rmdir, |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | struct inode_operations autofs4_direct_root_inode_operations = { | ||
| 59 | .lookup = autofs4_lookup, | ||
| 60 | .unlink = autofs4_dir_unlink, | ||
| 61 | .mkdir = autofs4_dir_mkdir, | ||
| 62 | .rmdir = autofs4_dir_rmdir, | ||
| 63 | .follow_link = autofs4_follow_link, | ||
| 64 | }; | ||
| 65 | |||
| 58 | struct inode_operations autofs4_dir_inode_operations = { | 66 | struct inode_operations autofs4_dir_inode_operations = { |
| 59 | .lookup = autofs4_lookup, | 67 | .lookup = autofs4_lookup, |
| 60 | .unlink = autofs4_dir_unlink, | 68 | .unlink = autofs4_dir_unlink, |
| @@ -82,87 +90,7 @@ static int autofs4_root_readdir(struct file *file, void *dirent, | |||
| 82 | 90 | ||
| 83 | DPRINTK("needs_reghost = %d", sbi->needs_reghost); | 91 | DPRINTK("needs_reghost = %d", sbi->needs_reghost); |
| 84 | 92 | ||
| 85 | return autofs4_dcache_readdir(file, dirent, filldir); | 93 | return dcache_readdir(file, dirent, filldir); |
| 86 | } | ||
| 87 | |||
| 88 | /* Update usage from here to top of tree, so that scan of | ||
| 89 | top-level directories will give a useful result */ | ||
| 90 | static void autofs4_update_usage(struct vfsmount *mnt, struct dentry *dentry) | ||
| 91 | { | ||
| 92 | struct dentry *top = dentry->d_sb->s_root; | ||
| 93 | |||
| 94 | spin_lock(&dcache_lock); | ||
| 95 | for(; dentry != top; dentry = dentry->d_parent) { | ||
| 96 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
| 97 | |||
| 98 | if (ino) { | ||
| 99 | touch_atime(mnt, dentry); | ||
| 100 | ino->last_used = jiffies; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | spin_unlock(&dcache_lock); | ||
| 104 | } | ||
| 105 | |||
| 106 | /* | ||
| 107 | * From 2.4 kernel readdir.c | ||
| 108 | */ | ||
| 109 | static int autofs4_dcache_readdir(struct file * filp, void * dirent, filldir_t filldir) | ||
| 110 | { | ||
| 111 | int i; | ||
| 112 | struct dentry *dentry = filp->f_dentry; | ||
| 113 | |||
| 114 | i = filp->f_pos; | ||
| 115 | switch (i) { | ||
| 116 | case 0: | ||
| 117 | if (filldir(dirent, ".", 1, i, dentry->d_inode->i_ino, DT_DIR) < 0) | ||
| 118 | break; | ||
| 119 | i++; | ||
| 120 | filp->f_pos++; | ||
| 121 | /* fallthrough */ | ||
| 122 | case 1: | ||
| 123 | if (filldir(dirent, "..", 2, i, dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) | ||
| 124 | break; | ||
| 125 | i++; | ||
| 126 | filp->f_pos++; | ||
| 127 | /* fallthrough */ | ||
| 128 | default: { | ||
| 129 | struct list_head *list; | ||
| 130 | int j = i-2; | ||
| 131 | |||
| 132 | spin_lock(&dcache_lock); | ||
| 133 | list = dentry->d_subdirs.next; | ||
| 134 | |||
| 135 | for (;;) { | ||
| 136 | if (list == &dentry->d_subdirs) { | ||
| 137 | spin_unlock(&dcache_lock); | ||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | if (!j) | ||
| 141 | break; | ||
| 142 | j--; | ||
| 143 | list = list->next; | ||
| 144 | } | ||
| 145 | |||
| 146 | while(1) { | ||
| 147 | struct dentry *de = list_entry(list, | ||
| 148 | struct dentry, d_u.d_child); | ||
| 149 | |||
| 150 | if (!d_unhashed(de) && de->d_inode) { | ||
| 151 | spin_unlock(&dcache_lock); | ||
| 152 | if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino, DT_UNKNOWN) < 0) | ||
| 153 | break; | ||
| 154 | spin_lock(&dcache_lock); | ||
| 155 | } | ||
| 156 | filp->f_pos++; | ||
| 157 | list = list->next; | ||
| 158 | if (list != &dentry->d_subdirs) | ||
| 159 | continue; | ||
| 160 | spin_unlock(&dcache_lock); | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | } | ||
| 165 | return 0; | ||
| 166 | } | 94 | } |
| 167 | 95 | ||
| 168 | static int autofs4_dir_open(struct inode *inode, struct file *file) | 96 | static int autofs4_dir_open(struct inode *inode, struct file *file) |
| @@ -170,8 +98,16 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
| 170 | struct dentry *dentry = file->f_dentry; | 98 | struct dentry *dentry = file->f_dentry; |
| 171 | struct vfsmount *mnt = file->f_vfsmnt; | 99 | struct vfsmount *mnt = file->f_vfsmnt; |
| 172 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 100 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
| 101 | struct dentry *cursor; | ||
| 173 | int status; | 102 | int status; |
| 174 | 103 | ||
| 104 | status = dcache_dir_open(inode, file); | ||
| 105 | if (status) | ||
| 106 | goto out; | ||
| 107 | |||
| 108 | cursor = file->private_data; | ||
| 109 | cursor->d_fsdata = NULL; | ||
| 110 | |||
| 175 | DPRINTK("file=%p dentry=%p %.*s", | 111 | DPRINTK("file=%p dentry=%p %.*s", |
| 176 | file, dentry, dentry->d_name.len, dentry->d_name.name); | 112 | file, dentry, dentry->d_name.len, dentry->d_name.name); |
| 177 | 113 | ||
| @@ -180,12 +116,15 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
| 180 | 116 | ||
| 181 | if (autofs4_ispending(dentry)) { | 117 | if (autofs4_ispending(dentry)) { |
| 182 | DPRINTK("dentry busy"); | 118 | DPRINTK("dentry busy"); |
| 183 | return -EBUSY; | 119 | dcache_dir_close(inode, file); |
| 120 | status = -EBUSY; | ||
| 121 | goto out; | ||
| 184 | } | 122 | } |
| 185 | 123 | ||
| 124 | status = -ENOENT; | ||
| 186 | if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) { | 125 | if (!d_mountpoint(dentry) && dentry->d_op && dentry->d_op->d_revalidate) { |
| 187 | struct nameidata nd; | 126 | struct nameidata nd; |
| 188 | int empty; | 127 | int empty, ret; |
| 189 | 128 | ||
| 190 | /* In case there are stale directory dentrys from a failed mount */ | 129 | /* In case there are stale directory dentrys from a failed mount */ |
| 191 | spin_lock(&dcache_lock); | 130 | spin_lock(&dcache_lock); |
| @@ -195,13 +134,13 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
| 195 | if (!empty) | 134 | if (!empty) |
| 196 | d_invalidate(dentry); | 135 | d_invalidate(dentry); |
| 197 | 136 | ||
| 198 | nd.dentry = dentry; | ||
| 199 | nd.mnt = mnt; | ||
| 200 | nd.flags = LOOKUP_DIRECTORY; | 137 | nd.flags = LOOKUP_DIRECTORY; |
| 201 | status = (dentry->d_op->d_revalidate)(dentry, &nd); | 138 | ret = (dentry->d_op->d_revalidate)(dentry, &nd); |
| 202 | 139 | ||
| 203 | if (!status) | 140 | if (!ret) { |
| 204 | return -ENOENT; | 141 | dcache_dir_close(inode, file); |
| 142 | goto out; | ||
| 143 | } | ||
| 205 | } | 144 | } |
| 206 | 145 | ||
| 207 | if (d_mountpoint(dentry)) { | 146 | if (d_mountpoint(dentry)) { |
| @@ -212,25 +151,29 @@ static int autofs4_dir_open(struct inode *inode, struct file *file) | |||
| 212 | if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) { | 151 | if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) { |
| 213 | dput(fp_dentry); | 152 | dput(fp_dentry); |
| 214 | mntput(fp_mnt); | 153 | mntput(fp_mnt); |
| 215 | return -ENOENT; | 154 | dcache_dir_close(inode, file); |
| 155 | goto out; | ||
| 216 | } | 156 | } |
| 217 | 157 | ||
| 218 | fp = dentry_open(fp_dentry, fp_mnt, file->f_flags); | 158 | fp = dentry_open(fp_dentry, fp_mnt, file->f_flags); |
| 219 | status = PTR_ERR(fp); | 159 | status = PTR_ERR(fp); |
| 220 | if (IS_ERR(fp)) { | 160 | if (IS_ERR(fp)) { |
| 221 | file->private_data = NULL; | 161 | dcache_dir_close(inode, file); |
| 222 | return status; | 162 | goto out; |
| 223 | } | 163 | } |
| 224 | file->private_data = fp; | 164 | cursor->d_fsdata = fp; |
| 225 | } | 165 | } |
| 226 | out: | ||
| 227 | return 0; | 166 | return 0; |
| 167 | out: | ||
| 168 | return status; | ||
| 228 | } | 169 | } |
| 229 | 170 | ||
| 230 | static int autofs4_dir_close(struct inode *inode, struct file *file) | 171 | static int autofs4_dir_close(struct inode *inode, struct file *file) |
| 231 | { | 172 | { |
| 232 | struct dentry *dentry = file->f_dentry; | 173 | struct dentry *dentry = file->f_dentry; |
| 233 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 174 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
| 175 | struct dentry *cursor = file->private_data; | ||
| 176 | int status = 0; | ||
| 234 | 177 | ||
| 235 | DPRINTK("file=%p dentry=%p %.*s", | 178 | DPRINTK("file=%p dentry=%p %.*s", |
| 236 | file, dentry, dentry->d_name.len, dentry->d_name.name); | 179 | file, dentry, dentry->d_name.len, dentry->d_name.name); |
| @@ -240,26 +183,28 @@ static int autofs4_dir_close(struct inode *inode, struct file *file) | |||
| 240 | 183 | ||
| 241 | if (autofs4_ispending(dentry)) { | 184 | if (autofs4_ispending(dentry)) { |
| 242 | DPRINTK("dentry busy"); | 185 | DPRINTK("dentry busy"); |
| 243 | return -EBUSY; | 186 | status = -EBUSY; |
| 187 | goto out; | ||
| 244 | } | 188 | } |
| 245 | 189 | ||
| 246 | if (d_mountpoint(dentry)) { | 190 | if (d_mountpoint(dentry)) { |
| 247 | struct file *fp = file->private_data; | 191 | struct file *fp = cursor->d_fsdata; |
| 248 | 192 | if (!fp) { | |
| 249 | if (!fp) | 193 | status = -ENOENT; |
| 250 | return -ENOENT; | 194 | goto out; |
| 251 | 195 | } | |
| 252 | filp_close(fp, current->files); | 196 | filp_close(fp, current->files); |
| 253 | file->private_data = NULL; | ||
| 254 | } | 197 | } |
| 255 | out: | 198 | out: |
| 256 | return 0; | 199 | dcache_dir_close(inode, file); |
| 200 | return status; | ||
| 257 | } | 201 | } |
| 258 | 202 | ||
| 259 | static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir) | 203 | static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldir) |
| 260 | { | 204 | { |
| 261 | struct dentry *dentry = file->f_dentry; | 205 | struct dentry *dentry = file->f_dentry; |
| 262 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 206 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
| 207 | struct dentry *cursor = file->private_data; | ||
| 263 | int status; | 208 | int status; |
| 264 | 209 | ||
| 265 | DPRINTK("file=%p dentry=%p %.*s", | 210 | DPRINTK("file=%p dentry=%p %.*s", |
| @@ -274,7 +219,7 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi | |||
| 274 | } | 219 | } |
| 275 | 220 | ||
| 276 | if (d_mountpoint(dentry)) { | 221 | if (d_mountpoint(dentry)) { |
| 277 | struct file *fp = file->private_data; | 222 | struct file *fp = cursor->d_fsdata; |
| 278 | 223 | ||
| 279 | if (!fp) | 224 | if (!fp) |
| 280 | return -ENOENT; | 225 | return -ENOENT; |
| @@ -289,27 +234,26 @@ static int autofs4_dir_readdir(struct file *file, void *dirent, filldir_t filldi | |||
| 289 | return status; | 234 | return status; |
| 290 | } | 235 | } |
| 291 | out: | 236 | out: |
| 292 | return autofs4_dcache_readdir(file, dirent, filldir); | 237 | return dcache_readdir(file, dirent, filldir); |
| 293 | } | 238 | } |
| 294 | 239 | ||
| 295 | static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int flags) | 240 | static int try_to_fill_dentry(struct dentry *dentry, int flags) |
| 296 | { | 241 | { |
| 297 | struct super_block *sb = mnt->mnt_sb; | 242 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
| 298 | struct autofs_sb_info *sbi = autofs4_sbi(sb); | 243 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
| 299 | struct autofs_info *de_info = autofs4_dentry_ino(dentry); | ||
| 300 | int status = 0; | 244 | int status = 0; |
| 301 | 245 | ||
| 302 | /* Block on any pending expiry here; invalidate the dentry | 246 | /* Block on any pending expiry here; invalidate the dentry |
| 303 | when expiration is done to trigger mount request with a new | 247 | when expiration is done to trigger mount request with a new |
| 304 | dentry */ | 248 | dentry */ |
| 305 | if (de_info && (de_info->flags & AUTOFS_INF_EXPIRING)) { | 249 | if (ino && (ino->flags & AUTOFS_INF_EXPIRING)) { |
| 306 | DPRINTK("waiting for expire %p name=%.*s", | 250 | DPRINTK("waiting for expire %p name=%.*s", |
| 307 | dentry, dentry->d_name.len, dentry->d_name.name); | 251 | dentry, dentry->d_name.len, dentry->d_name.name); |
| 308 | 252 | ||
| 309 | status = autofs4_wait(sbi, dentry, NFY_NONE); | 253 | status = autofs4_wait(sbi, dentry, NFY_NONE); |
| 310 | 254 | ||
| 311 | DPRINTK("expire done status=%d", status); | 255 | DPRINTK("expire done status=%d", status); |
| 312 | 256 | ||
| 313 | /* | 257 | /* |
| 314 | * If the directory still exists the mount request must | 258 | * If the directory still exists the mount request must |
| 315 | * continue otherwise it can't be followed at the right | 259 | * continue otherwise it can't be followed at the right |
| @@ -317,34 +261,36 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f | |||
| 317 | */ | 261 | */ |
| 318 | status = d_invalidate(dentry); | 262 | status = d_invalidate(dentry); |
| 319 | if (status != -EBUSY) | 263 | if (status != -EBUSY) |
| 320 | return 0; | 264 | return -ENOENT; |
| 321 | } | 265 | } |
| 322 | 266 | ||
| 323 | DPRINTK("dentry=%p %.*s ino=%p", | 267 | DPRINTK("dentry=%p %.*s ino=%p", |
| 324 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); | 268 | dentry, dentry->d_name.len, dentry->d_name.name, dentry->d_inode); |
| 325 | 269 | ||
| 326 | /* Wait for a pending mount, triggering one if there isn't one already */ | 270 | /* |
| 271 | * Wait for a pending mount, triggering one if there | ||
| 272 | * isn't one already | ||
| 273 | */ | ||
| 327 | if (dentry->d_inode == NULL) { | 274 | if (dentry->d_inode == NULL) { |
| 328 | DPRINTK("waiting for mount name=%.*s", | 275 | DPRINTK("waiting for mount name=%.*s", |
| 329 | dentry->d_name.len, dentry->d_name.name); | 276 | dentry->d_name.len, dentry->d_name.name); |
| 330 | 277 | ||
| 331 | status = autofs4_wait(sbi, dentry, NFY_MOUNT); | 278 | status = autofs4_wait(sbi, dentry, NFY_MOUNT); |
| 332 | 279 | ||
| 333 | DPRINTK("mount done status=%d", status); | 280 | DPRINTK("mount done status=%d", status); |
| 334 | 281 | ||
| 335 | if (status && dentry->d_inode) | 282 | if (status && dentry->d_inode) |
| 336 | return 0; /* Try to get the kernel to invalidate this dentry */ | 283 | return status; /* Try to get the kernel to invalidate this dentry */ |
| 337 | 284 | ||
| 338 | /* Turn this into a real negative dentry? */ | 285 | /* Turn this into a real negative dentry? */ |
| 339 | if (status == -ENOENT) { | 286 | if (status == -ENOENT) { |
| 340 | dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT; | ||
| 341 | spin_lock(&dentry->d_lock); | 287 | spin_lock(&dentry->d_lock); |
| 342 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 288 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
| 343 | spin_unlock(&dentry->d_lock); | 289 | spin_unlock(&dentry->d_lock); |
| 344 | return 1; | 290 | return status; |
| 345 | } else if (status) { | 291 | } else if (status) { |
| 346 | /* Return a negative dentry, but leave it "pending" */ | 292 | /* Return a negative dentry, but leave it "pending" */ |
| 347 | return 1; | 293 | return status; |
| 348 | } | 294 | } |
| 349 | /* Trigger mount for path component or follow link */ | 295 | /* Trigger mount for path component or follow link */ |
| 350 | } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) || | 296 | } else if (flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY) || |
| @@ -363,19 +309,87 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f | |||
| 363 | spin_lock(&dentry->d_lock); | 309 | spin_lock(&dentry->d_lock); |
| 364 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 310 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
| 365 | spin_unlock(&dentry->d_lock); | 311 | spin_unlock(&dentry->d_lock); |
| 366 | return 0; | 312 | return status; |
| 367 | } | 313 | } |
| 368 | } | 314 | } |
| 369 | 315 | ||
| 370 | /* We don't update the usages for the autofs daemon itself, this | 316 | /* Initialize expiry counter after successful mount */ |
| 371 | is necessary for recursive autofs mounts */ | 317 | if (ino) |
| 372 | if (!autofs4_oz_mode(sbi)) | 318 | ino->last_used = jiffies; |
| 373 | autofs4_update_usage(mnt, dentry); | ||
| 374 | 319 | ||
| 375 | spin_lock(&dentry->d_lock); | 320 | spin_lock(&dentry->d_lock); |
| 376 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; | 321 | dentry->d_flags &= ~DCACHE_AUTOFS_PENDING; |
| 377 | spin_unlock(&dentry->d_lock); | 322 | spin_unlock(&dentry->d_lock); |
| 378 | return 1; | 323 | return status; |
| 324 | } | ||
| 325 | |||
| 326 | /* For autofs direct mounts the follow link triggers the mount */ | ||
| 327 | static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
| 328 | { | ||
| 329 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | ||
| 330 | int oz_mode = autofs4_oz_mode(sbi); | ||
| 331 | unsigned int lookup_type; | ||
| 332 | int status; | ||
| 333 | |||
| 334 | DPRINTK("dentry=%p %.*s oz_mode=%d nd->flags=%d", | ||
| 335 | dentry, dentry->d_name.len, dentry->d_name.name, oz_mode, | ||
| 336 | nd->flags); | ||
| 337 | |||
| 338 | /* If it's our master or we shouldn't trigger a mount we're done */ | ||
| 339 | lookup_type = nd->flags & (LOOKUP_CONTINUE | LOOKUP_DIRECTORY); | ||
| 340 | if (oz_mode || !lookup_type) | ||
| 341 | goto done; | ||
| 342 | |||
| 343 | /* | ||
| 344 | * If a request is pending wait for it. | ||
| 345 | * If it's a mount then it won't be expired till at least | ||
| 346 | * a liitle later and if it's an expire then we might need | ||
| 347 | * to mount it again. | ||
| 348 | */ | ||
| 349 | if (autofs4_ispending(dentry)) { | ||
| 350 | DPRINTK("waiting for active request %p name=%.*s", | ||
| 351 | dentry, dentry->d_name.len, dentry->d_name.name); | ||
| 352 | |||
| 353 | status = autofs4_wait(sbi, dentry, NFY_NONE); | ||
| 354 | |||
| 355 | DPRINTK("request done status=%d", status); | ||
| 356 | } | ||
| 357 | |||
| 358 | /* | ||
| 359 | * If the dentry contains directories then it is an | ||
| 360 | * autofs multi-mount with no root mount offset. So | ||
| 361 | * don't try to mount it again. | ||
| 362 | */ | ||
| 363 | spin_lock(&dcache_lock); | ||
| 364 | if (!d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { | ||
| 365 | spin_unlock(&dcache_lock); | ||
| 366 | |||
| 367 | status = try_to_fill_dentry(dentry, 0); | ||
| 368 | if (status) | ||
| 369 | goto out_error; | ||
| 370 | |||
| 371 | /* | ||
| 372 | * The mount succeeded but if there is no root mount | ||
| 373 | * it must be an autofs multi-mount with no root offset | ||
| 374 | * so we don't need to follow the mount. | ||
| 375 | */ | ||
| 376 | if (d_mountpoint(dentry)) { | ||
| 377 | if (!autofs4_follow_mount(&nd->mnt, &nd->dentry)) { | ||
| 378 | status = -ENOENT; | ||
| 379 | goto out_error; | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | goto done; | ||
| 384 | } | ||
| 385 | spin_unlock(&dcache_lock); | ||
| 386 | |||
| 387 | done: | ||
| 388 | return NULL; | ||
| 389 | |||
| 390 | out_error: | ||
| 391 | path_release(nd); | ||
| 392 | return ERR_PTR(status); | ||
| 379 | } | 393 | } |
| 380 | 394 | ||
| 381 | /* | 395 | /* |
| @@ -384,47 +398,43 @@ static int try_to_fill_dentry(struct vfsmount *mnt, struct dentry *dentry, int f | |||
| 384 | * yet completely filled in, and revalidate has to delay such | 398 | * yet completely filled in, and revalidate has to delay such |
| 385 | * lookups.. | 399 | * lookups.. |
| 386 | */ | 400 | */ |
| 387 | static int autofs4_revalidate(struct dentry * dentry, struct nameidata *nd) | 401 | static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd) |
| 388 | { | 402 | { |
| 389 | struct inode * dir = dentry->d_parent->d_inode; | 403 | struct inode *dir = dentry->d_parent->d_inode; |
| 390 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); | 404 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); |
| 391 | int oz_mode = autofs4_oz_mode(sbi); | 405 | int oz_mode = autofs4_oz_mode(sbi); |
| 392 | int flags = nd ? nd->flags : 0; | 406 | int flags = nd ? nd->flags : 0; |
| 393 | int status = 1; | 407 | int status = 0; |
| 394 | 408 | ||
| 395 | /* Pending dentry */ | 409 | /* Pending dentry */ |
| 396 | if (autofs4_ispending(dentry)) { | 410 | if (autofs4_ispending(dentry)) { |
| 397 | if (!oz_mode) | 411 | if (!oz_mode) |
| 398 | status = try_to_fill_dentry(nd->mnt, dentry, flags); | 412 | status = try_to_fill_dentry(dentry, flags); |
| 399 | return status; | 413 | return !status; |
| 400 | } | 414 | } |
| 401 | 415 | ||
| 402 | /* Negative dentry.. invalidate if "old" */ | 416 | /* Negative dentry.. invalidate if "old" */ |
| 403 | if (dentry->d_inode == NULL) | 417 | if (dentry->d_inode == NULL) |
| 404 | return (dentry->d_time - jiffies <= AUTOFS_NEGATIVE_TIMEOUT); | 418 | return 0; |
| 405 | 419 | ||
| 406 | /* Check for a non-mountpoint directory with no contents */ | 420 | /* Check for a non-mountpoint directory with no contents */ |
| 407 | spin_lock(&dcache_lock); | 421 | spin_lock(&dcache_lock); |
| 408 | if (S_ISDIR(dentry->d_inode->i_mode) && | 422 | if (S_ISDIR(dentry->d_inode->i_mode) && |
| 409 | !d_mountpoint(dentry) && | 423 | !d_mountpoint(dentry) && |
| 410 | list_empty(&dentry->d_subdirs)) { | 424 | __simple_empty(dentry)) { |
| 411 | DPRINTK("dentry=%p %.*s, emptydir", | 425 | DPRINTK("dentry=%p %.*s, emptydir", |
| 412 | dentry, dentry->d_name.len, dentry->d_name.name); | 426 | dentry, dentry->d_name.len, dentry->d_name.name); |
| 413 | spin_unlock(&dcache_lock); | 427 | spin_unlock(&dcache_lock); |
| 414 | if (!oz_mode) | 428 | if (!oz_mode) |
| 415 | status = try_to_fill_dentry(nd->mnt, dentry, flags); | 429 | status = try_to_fill_dentry(dentry, flags); |
| 416 | return status; | 430 | return !status; |
| 417 | } | 431 | } |
| 418 | spin_unlock(&dcache_lock); | 432 | spin_unlock(&dcache_lock); |
| 419 | 433 | ||
| 420 | /* Update the usage list */ | ||
| 421 | if (!oz_mode) | ||
| 422 | autofs4_update_usage(nd->mnt, dentry); | ||
| 423 | |||
| 424 | return 1; | 434 | return 1; |
| 425 | } | 435 | } |
| 426 | 436 | ||
| 427 | static void autofs4_dentry_release(struct dentry *de) | 437 | void autofs4_dentry_release(struct dentry *de) |
| 428 | { | 438 | { |
| 429 | struct autofs_info *inf; | 439 | struct autofs_info *inf; |
| 430 | 440 | ||
| @@ -462,12 +472,13 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
| 462 | DPRINTK("name = %.*s", | 472 | DPRINTK("name = %.*s", |
| 463 | dentry->d_name.len, dentry->d_name.name); | 473 | dentry->d_name.len, dentry->d_name.name); |
| 464 | 474 | ||
| 475 | /* File name too long to exist */ | ||
| 465 | if (dentry->d_name.len > NAME_MAX) | 476 | if (dentry->d_name.len > NAME_MAX) |
| 466 | return ERR_PTR(-ENAMETOOLONG);/* File name too long to exist */ | 477 | return ERR_PTR(-ENAMETOOLONG); |
| 467 | 478 | ||
| 468 | sbi = autofs4_sbi(dir->i_sb); | 479 | sbi = autofs4_sbi(dir->i_sb); |
| 469 | |||
| 470 | oz_mode = autofs4_oz_mode(sbi); | 480 | oz_mode = autofs4_oz_mode(sbi); |
| 481 | |||
| 471 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", | 482 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", |
| 472 | current->pid, process_group(current), sbi->catatonic, oz_mode); | 483 | current->pid, process_group(current), sbi->catatonic, oz_mode); |
| 473 | 484 | ||
| @@ -519,7 +530,7 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
| 519 | * doesn't do the right thing for all system calls, but it should | 530 | * doesn't do the right thing for all system calls, but it should |
| 520 | * be OK for the operations we permit from an autofs. | 531 | * be OK for the operations we permit from an autofs. |
| 521 | */ | 532 | */ |
| 522 | if ( dentry->d_inode && d_unhashed(dentry) ) | 533 | if (dentry->d_inode && d_unhashed(dentry)) |
| 523 | return ERR_PTR(-ENOENT); | 534 | return ERR_PTR(-ENOENT); |
| 524 | 535 | ||
| 525 | return NULL; | 536 | return NULL; |
| @@ -531,6 +542,7 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
| 531 | { | 542 | { |
| 532 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); | 543 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); |
| 533 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 544 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
| 545 | struct autofs_info *p_ino; | ||
| 534 | struct inode *inode; | 546 | struct inode *inode; |
| 535 | char *cp; | 547 | char *cp; |
| 536 | 548 | ||
| @@ -564,6 +576,10 @@ static int autofs4_dir_symlink(struct inode *dir, | |||
| 564 | 576 | ||
| 565 | dentry->d_fsdata = ino; | 577 | dentry->d_fsdata = ino; |
| 566 | ino->dentry = dget(dentry); | 578 | ino->dentry = dget(dentry); |
| 579 | atomic_inc(&ino->count); | ||
| 580 | p_ino = autofs4_dentry_ino(dentry->d_parent); | ||
| 581 | if (p_ino && dentry->d_parent != dentry) | ||
| 582 | atomic_inc(&p_ino->count); | ||
| 567 | ino->inode = inode; | 583 | ino->inode = inode; |
| 568 | 584 | ||
| 569 | dir->i_mtime = CURRENT_TIME; | 585 | dir->i_mtime = CURRENT_TIME; |
| @@ -590,11 +606,17 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry) | |||
| 590 | { | 606 | { |
| 591 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); | 607 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); |
| 592 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 608 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
| 609 | struct autofs_info *p_ino; | ||
| 593 | 610 | ||
| 594 | /* This allows root to remove symlinks */ | 611 | /* This allows root to remove symlinks */ |
| 595 | if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) | 612 | if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) |
| 596 | return -EACCES; | 613 | return -EACCES; |
| 597 | 614 | ||
| 615 | if (atomic_dec_and_test(&ino->count)) { | ||
| 616 | p_ino = autofs4_dentry_ino(dentry->d_parent); | ||
| 617 | if (p_ino && dentry->d_parent != dentry) | ||
| 618 | atomic_dec(&p_ino->count); | ||
| 619 | } | ||
| 598 | dput(ino->dentry); | 620 | dput(ino->dentry); |
| 599 | 621 | ||
| 600 | dentry->d_inode->i_size = 0; | 622 | dentry->d_inode->i_size = 0; |
| @@ -611,6 +633,7 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 611 | { | 633 | { |
| 612 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); | 634 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); |
| 613 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 635 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
| 636 | struct autofs_info *p_ino; | ||
| 614 | 637 | ||
| 615 | if (!autofs4_oz_mode(sbi)) | 638 | if (!autofs4_oz_mode(sbi)) |
| 616 | return -EACCES; | 639 | return -EACCES; |
| @@ -625,8 +648,12 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 625 | spin_unlock(&dentry->d_lock); | 648 | spin_unlock(&dentry->d_lock); |
| 626 | spin_unlock(&dcache_lock); | 649 | spin_unlock(&dcache_lock); |
| 627 | 650 | ||
| 651 | if (atomic_dec_and_test(&ino->count)) { | ||
| 652 | p_ino = autofs4_dentry_ino(dentry->d_parent); | ||
| 653 | if (p_ino && dentry->d_parent != dentry) | ||
| 654 | atomic_dec(&p_ino->count); | ||
| 655 | } | ||
| 628 | dput(ino->dentry); | 656 | dput(ino->dentry); |
| 629 | |||
| 630 | dentry->d_inode->i_size = 0; | 657 | dentry->d_inode->i_size = 0; |
| 631 | dentry->d_inode->i_nlink = 0; | 658 | dentry->d_inode->i_nlink = 0; |
| 632 | 659 | ||
| @@ -640,6 +667,7 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 640 | { | 667 | { |
| 641 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); | 668 | struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb); |
| 642 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 669 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
| 670 | struct autofs_info *p_ino; | ||
| 643 | struct inode *inode; | 671 | struct inode *inode; |
| 644 | 672 | ||
| 645 | if ( !autofs4_oz_mode(sbi) ) | 673 | if ( !autofs4_oz_mode(sbi) ) |
| @@ -662,6 +690,10 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 662 | 690 | ||
| 663 | dentry->d_fsdata = ino; | 691 | dentry->d_fsdata = ino; |
| 664 | ino->dentry = dget(dentry); | 692 | ino->dentry = dget(dentry); |
| 693 | atomic_inc(&ino->count); | ||
| 694 | p_ino = autofs4_dentry_ino(dentry->d_parent); | ||
| 695 | if (p_ino && dentry->d_parent != dentry) | ||
| 696 | atomic_inc(&p_ino->count); | ||
| 665 | ino->inode = inode; | 697 | ino->inode = inode; |
| 666 | dir->i_nlink++; | 698 | dir->i_nlink++; |
| 667 | dir->i_mtime = CURRENT_TIME; | 699 | dir->i_mtime = CURRENT_TIME; |
| @@ -745,7 +777,7 @@ static inline int autofs4_ask_umount(struct vfsmount *mnt, int __user *p) | |||
| 745 | { | 777 | { |
| 746 | int status = 0; | 778 | int status = 0; |
| 747 | 779 | ||
| 748 | if (may_umount(mnt) == 0) | 780 | if (may_umount(mnt)) |
| 749 | status = 1; | 781 | status = 1; |
| 750 | 782 | ||
| 751 | DPRINTK("returning %d", status); | 783 | DPRINTK("returning %d", status); |
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index be78e9378c03..142ab6aa2aa1 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * linux/fs/autofs/waitq.c | 3 | * linux/fs/autofs/waitq.c |
| 4 | * | 4 | * |
| 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved | 5 | * Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved |
| 6 | * Copyright 2001-2003 Ian Kent <raven@themaw.net> | 6 | * Copyright 2001-2006 Ian Kent <raven@themaw.net> |
| 7 | * | 7 | * |
| 8 | * This file is part of the Linux kernel and is made available under | 8 | * This file is part of the Linux kernel and is made available under |
| 9 | * the terms of the GNU General Public License, version 2, or at your | 9 | * the terms of the GNU General Public License, version 2, or at your |
| @@ -33,7 +33,7 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) | |||
| 33 | sbi->catatonic = 1; | 33 | sbi->catatonic = 1; |
| 34 | wq = sbi->queues; | 34 | wq = sbi->queues; |
| 35 | sbi->queues = NULL; /* Erase all wait queues */ | 35 | sbi->queues = NULL; /* Erase all wait queues */ |
| 36 | while ( wq ) { | 36 | while (wq) { |
| 37 | nwq = wq->next; | 37 | nwq = wq->next; |
| 38 | wq->status = -ENOENT; /* Magic is gone - report failure */ | 38 | wq->status = -ENOENT; /* Magic is gone - report failure */ |
| 39 | kfree(wq->name); | 39 | kfree(wq->name); |
| @@ -45,7 +45,6 @@ void autofs4_catatonic_mode(struct autofs_sb_info *sbi) | |||
| 45 | fput(sbi->pipe); /* Close the pipe */ | 45 | fput(sbi->pipe); /* Close the pipe */ |
| 46 | sbi->pipe = NULL; | 46 | sbi->pipe = NULL; |
| 47 | } | 47 | } |
| 48 | |||
| 49 | shrink_dcache_sb(sbi->sb); | 48 | shrink_dcache_sb(sbi->sb); |
| 50 | } | 49 | } |
| 51 | 50 | ||
| @@ -98,7 +97,10 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
| 98 | 97 | ||
| 99 | pkt.hdr.proto_version = sbi->version; | 98 | pkt.hdr.proto_version = sbi->version; |
| 100 | pkt.hdr.type = type; | 99 | pkt.hdr.type = type; |
| 101 | if (type == autofs_ptype_missing) { | 100 | switch (type) { |
| 101 | /* Kernel protocol v4 missing and expire packets */ | ||
| 102 | case autofs_ptype_missing: | ||
| 103 | { | ||
| 102 | struct autofs_packet_missing *mp = &pkt.missing; | 104 | struct autofs_packet_missing *mp = &pkt.missing; |
| 103 | 105 | ||
| 104 | pktsz = sizeof(*mp); | 106 | pktsz = sizeof(*mp); |
| @@ -107,7 +109,10 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
| 107 | mp->len = wq->len; | 109 | mp->len = wq->len; |
| 108 | memcpy(mp->name, wq->name, wq->len); | 110 | memcpy(mp->name, wq->name, wq->len); |
| 109 | mp->name[wq->len] = '\0'; | 111 | mp->name[wq->len] = '\0'; |
| 110 | } else if (type == autofs_ptype_expire_multi) { | 112 | break; |
| 113 | } | ||
| 114 | case autofs_ptype_expire_multi: | ||
| 115 | { | ||
| 111 | struct autofs_packet_expire_multi *ep = &pkt.expire_multi; | 116 | struct autofs_packet_expire_multi *ep = &pkt.expire_multi; |
| 112 | 117 | ||
| 113 | pktsz = sizeof(*ep); | 118 | pktsz = sizeof(*ep); |
| @@ -116,7 +121,34 @@ static void autofs4_notify_daemon(struct autofs_sb_info *sbi, | |||
| 116 | ep->len = wq->len; | 121 | ep->len = wq->len; |
| 117 | memcpy(ep->name, wq->name, wq->len); | 122 | memcpy(ep->name, wq->name, wq->len); |
| 118 | ep->name[wq->len] = '\0'; | 123 | ep->name[wq->len] = '\0'; |
| 119 | } else { | 124 | break; |
| 125 | } | ||
| 126 | /* | ||
| 127 | * Kernel protocol v5 packet for handling indirect and direct | ||
| 128 | * mount missing and expire requests | ||
| 129 | */ | ||
| 130 | case autofs_ptype_missing_indirect: | ||
| 131 | case autofs_ptype_expire_indirect: | ||
| 132 | case autofs_ptype_missing_direct: | ||
| 133 | case autofs_ptype_expire_direct: | ||
| 134 | { | ||
| 135 | struct autofs_v5_packet *packet = &pkt.v5_packet; | ||
| 136 | |||
| 137 | pktsz = sizeof(*packet); | ||
| 138 | |||
| 139 | packet->wait_queue_token = wq->wait_queue_token; | ||
| 140 | packet->len = wq->len; | ||
| 141 | memcpy(packet->name, wq->name, wq->len); | ||
| 142 | packet->name[wq->len] = '\0'; | ||
| 143 | packet->dev = wq->dev; | ||
| 144 | packet->ino = wq->ino; | ||
| 145 | packet->uid = wq->uid; | ||
| 146 | packet->gid = wq->gid; | ||
| 147 | packet->pid = wq->pid; | ||
| 148 | packet->tgid = wq->tgid; | ||
| 149 | break; | ||
| 150 | } | ||
| 151 | default: | ||
| 120 | printk("autofs4_notify_daemon: bad type %d!\n", type); | 152 | printk("autofs4_notify_daemon: bad type %d!\n", type); |
| 121 | return; | 153 | return; |
| 122 | } | 154 | } |
| @@ -162,21 +194,29 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
| 162 | { | 194 | { |
| 163 | struct autofs_wait_queue *wq; | 195 | struct autofs_wait_queue *wq; |
| 164 | char *name; | 196 | char *name; |
| 165 | int len, status; | 197 | unsigned int len = 0; |
| 198 | unsigned int hash = 0; | ||
| 199 | int status; | ||
| 166 | 200 | ||
| 167 | /* In catatonic mode, we don't wait for nobody */ | 201 | /* In catatonic mode, we don't wait for nobody */ |
| 168 | if ( sbi->catatonic ) | 202 | if (sbi->catatonic) |
| 169 | return -ENOENT; | 203 | return -ENOENT; |
| 170 | 204 | ||
| 171 | name = kmalloc(NAME_MAX + 1, GFP_KERNEL); | 205 | name = kmalloc(NAME_MAX + 1, GFP_KERNEL); |
| 172 | if (!name) | 206 | if (!name) |
| 173 | return -ENOMEM; | 207 | return -ENOMEM; |
| 174 | 208 | ||
| 175 | len = autofs4_getpath(sbi, dentry, &name); | 209 | /* If this is a direct mount request create a dummy name */ |
| 176 | if (!len) { | 210 | if (IS_ROOT(dentry) && (sbi->type & AUTOFS_TYPE_DIRECT)) |
| 177 | kfree(name); | 211 | len = sprintf(name, "%p", dentry); |
| 178 | return -ENOENT; | 212 | else { |
| 213 | len = autofs4_getpath(sbi, dentry, &name); | ||
| 214 | if (!len) { | ||
| 215 | kfree(name); | ||
| 216 | return -ENOENT; | ||
| 217 | } | ||
| 179 | } | 218 | } |
| 219 | hash = full_name_hash(name, len); | ||
| 180 | 220 | ||
| 181 | if (mutex_lock_interruptible(&sbi->wq_mutex)) { | 221 | if (mutex_lock_interruptible(&sbi->wq_mutex)) { |
| 182 | kfree(name); | 222 | kfree(name); |
| @@ -190,7 +230,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
| 190 | break; | 230 | break; |
| 191 | } | 231 | } |
| 192 | 232 | ||
| 193 | if ( !wq ) { | 233 | if (!wq) { |
| 194 | /* Can't wait for an expire if there's no mount */ | 234 | /* Can't wait for an expire if there's no mount */ |
| 195 | if (notify == NFY_NONE && !d_mountpoint(dentry)) { | 235 | if (notify == NFY_NONE && !d_mountpoint(dentry)) { |
| 196 | kfree(name); | 236 | kfree(name); |
| @@ -200,7 +240,7 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
| 200 | 240 | ||
| 201 | /* Create a new wait queue */ | 241 | /* Create a new wait queue */ |
| 202 | wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL); | 242 | wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL); |
| 203 | if ( !wq ) { | 243 | if (!wq) { |
| 204 | kfree(name); | 244 | kfree(name); |
| 205 | mutex_unlock(&sbi->wq_mutex); | 245 | mutex_unlock(&sbi->wq_mutex); |
| 206 | return -ENOMEM; | 246 | return -ENOMEM; |
| @@ -212,12 +252,18 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
| 212 | wq->next = sbi->queues; | 252 | wq->next = sbi->queues; |
| 213 | sbi->queues = wq; | 253 | sbi->queues = wq; |
| 214 | init_waitqueue_head(&wq->queue); | 254 | init_waitqueue_head(&wq->queue); |
| 215 | wq->hash = dentry->d_name.hash; | 255 | wq->hash = hash; |
| 216 | wq->name = name; | 256 | wq->name = name; |
| 217 | wq->len = len; | 257 | wq->len = len; |
| 258 | wq->dev = autofs4_get_dev(sbi); | ||
| 259 | wq->ino = autofs4_get_ino(sbi); | ||
| 260 | wq->uid = current->uid; | ||
| 261 | wq->gid = current->gid; | ||
| 262 | wq->pid = current->pid; | ||
| 263 | wq->tgid = current->tgid; | ||
| 218 | wq->status = -EINTR; /* Status return if interrupted */ | 264 | wq->status = -EINTR; /* Status return if interrupted */ |
| 219 | atomic_set(&wq->wait_ctr, 2); | 265 | atomic_set(&wq->wait_ctr, 2); |
| 220 | atomic_set(&wq->notified, 1); | 266 | atomic_set(&wq->notify, 1); |
| 221 | mutex_unlock(&sbi->wq_mutex); | 267 | mutex_unlock(&sbi->wq_mutex); |
| 222 | } else { | 268 | } else { |
| 223 | atomic_inc(&wq->wait_ctr); | 269 | atomic_inc(&wq->wait_ctr); |
| @@ -227,9 +273,26 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
| 227 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); | 273 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); |
| 228 | } | 274 | } |
| 229 | 275 | ||
| 230 | if (notify != NFY_NONE && atomic_dec_and_test(&wq->notified)) { | 276 | if (notify != NFY_NONE && atomic_read(&wq->notify)) { |
| 231 | int type = (notify == NFY_MOUNT ? | 277 | int type; |
| 232 | autofs_ptype_missing : autofs_ptype_expire_multi); | 278 | |
| 279 | atomic_dec(&wq->notify); | ||
| 280 | |||
| 281 | if (sbi->version < 5) { | ||
| 282 | if (notify == NFY_MOUNT) | ||
| 283 | type = autofs_ptype_missing; | ||
| 284 | else | ||
| 285 | type = autofs_ptype_expire_multi; | ||
| 286 | } else { | ||
| 287 | if (notify == NFY_MOUNT) | ||
| 288 | type = (sbi->type & AUTOFS_TYPE_DIRECT) ? | ||
| 289 | autofs_ptype_missing_direct : | ||
| 290 | autofs_ptype_missing_indirect; | ||
| 291 | else | ||
| 292 | type = (sbi->type & AUTOFS_TYPE_DIRECT) ? | ||
| 293 | autofs_ptype_expire_direct : | ||
| 294 | autofs_ptype_expire_indirect; | ||
| 295 | } | ||
| 233 | 296 | ||
| 234 | DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", | 297 | DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", |
| 235 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); | 298 | (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); |
| @@ -240,14 +303,14 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, | |||
| 240 | 303 | ||
| 241 | /* wq->name is NULL if and only if the lock is already released */ | 304 | /* wq->name is NULL if and only if the lock is already released */ |
| 242 | 305 | ||
| 243 | if ( sbi->catatonic ) { | 306 | if (sbi->catatonic) { |
| 244 | /* We might have slept, so check again for catatonic mode */ | 307 | /* We might have slept, so check again for catatonic mode */ |
| 245 | wq->status = -ENOENT; | 308 | wq->status = -ENOENT; |
| 246 | kfree(wq->name); | 309 | kfree(wq->name); |
| 247 | wq->name = NULL; | 310 | wq->name = NULL; |
| 248 | } | 311 | } |
| 249 | 312 | ||
| 250 | if ( wq->name ) { | 313 | if (wq->name) { |
| 251 | /* Block all but "shutdown" signals while waiting */ | 314 | /* Block all but "shutdown" signals while waiting */ |
| 252 | sigset_t oldset; | 315 | sigset_t oldset; |
| 253 | unsigned long irqflags; | 316 | unsigned long irqflags; |
| @@ -283,12 +346,12 @@ int autofs4_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_tok | |||
| 283 | struct autofs_wait_queue *wq, **wql; | 346 | struct autofs_wait_queue *wq, **wql; |
| 284 | 347 | ||
| 285 | mutex_lock(&sbi->wq_mutex); | 348 | mutex_lock(&sbi->wq_mutex); |
| 286 | for ( wql = &sbi->queues ; (wq = *wql) != 0 ; wql = &wq->next ) { | 349 | for (wql = &sbi->queues ; (wq = *wql) != 0 ; wql = &wq->next) { |
| 287 | if ( wq->wait_queue_token == wait_queue_token ) | 350 | if (wq->wait_queue_token == wait_queue_token) |
| 288 | break; | 351 | break; |
| 289 | } | 352 | } |
| 290 | 353 | ||
| 291 | if ( !wq ) { | 354 | if (!wq) { |
| 292 | mutex_unlock(&sbi->wq_mutex); | 355 | mutex_unlock(&sbi->wq_mutex); |
| 293 | return -EINVAL; | 356 | return -EINVAL; |
| 294 | } | 357 | } |
diff --git a/fs/bad_inode.c b/fs/bad_inode.c index e172180a1d8c..80599ae33966 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c | |||
| @@ -22,7 +22,7 @@ static int return_EIO(void) | |||
| 22 | 22 | ||
| 23 | #define EIO_ERROR ((void *) (return_EIO)) | 23 | #define EIO_ERROR ((void *) (return_EIO)) |
| 24 | 24 | ||
| 25 | static struct file_operations bad_file_ops = | 25 | static const struct file_operations bad_file_ops = |
| 26 | { | 26 | { |
| 27 | .llseek = EIO_ERROR, | 27 | .llseek = EIO_ERROR, |
| 28 | .aio_read = EIO_ERROR, | 28 | .aio_read = EIO_ERROR, |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 044a59587829..68ebd10f345d 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
| @@ -64,7 +64,7 @@ static const struct super_operations befs_sops = { | |||
| 64 | /* slab cache for befs_inode_info objects */ | 64 | /* slab cache for befs_inode_info objects */ |
| 65 | static kmem_cache_t *befs_inode_cachep; | 65 | static kmem_cache_t *befs_inode_cachep; |
| 66 | 66 | ||
| 67 | static struct file_operations befs_dir_operations = { | 67 | static const struct file_operations befs_dir_operations = { |
| 68 | .read = generic_read_dir, | 68 | .read = generic_read_dir, |
| 69 | .readdir = befs_readdir, | 69 | .readdir = befs_readdir, |
| 70 | }; | 70 | }; |
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h index 1fbc53f14aba..9d791004b21c 100644 --- a/fs/bfs/bfs.h +++ b/fs/bfs/bfs.h | |||
| @@ -49,11 +49,11 @@ static inline struct bfs_inode_info *BFS_I(struct inode *inode) | |||
| 49 | 49 | ||
| 50 | /* file.c */ | 50 | /* file.c */ |
| 51 | extern struct inode_operations bfs_file_inops; | 51 | extern struct inode_operations bfs_file_inops; |
| 52 | extern struct file_operations bfs_file_operations; | 52 | extern const struct file_operations bfs_file_operations; |
| 53 | extern struct address_space_operations bfs_aops; | 53 | extern struct address_space_operations bfs_aops; |
| 54 | 54 | ||
| 55 | /* dir.c */ | 55 | /* dir.c */ |
| 56 | extern struct inode_operations bfs_dir_inops; | 56 | extern struct inode_operations bfs_dir_inops; |
| 57 | extern struct file_operations bfs_dir_operations; | 57 | extern const struct file_operations bfs_dir_operations; |
| 58 | 58 | ||
| 59 | #endif /* _FS_BFS_BFS_H */ | 59 | #endif /* _FS_BFS_BFS_H */ |
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c index 5af928fa0449..26fad9621738 100644 --- a/fs/bfs/dir.c +++ b/fs/bfs/dir.c | |||
| @@ -70,7 +70,7 @@ static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir) | |||
| 70 | return 0; | 70 | return 0; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | struct file_operations bfs_dir_operations = { | 73 | const struct file_operations bfs_dir_operations = { |
| 74 | .read = generic_read_dir, | 74 | .read = generic_read_dir, |
| 75 | .readdir = bfs_readdir, | 75 | .readdir = bfs_readdir, |
| 76 | .fsync = file_fsync, | 76 | .fsync = file_fsync, |
diff --git a/fs/bfs/file.c b/fs/bfs/file.c index 807723b65daf..d83cd74a2e4e 100644 --- a/fs/bfs/file.c +++ b/fs/bfs/file.c | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #define dprintf(x...) | 17 | #define dprintf(x...) |
| 18 | #endif | 18 | #endif |
| 19 | 19 | ||
| 20 | struct file_operations bfs_file_operations = { | 20 | const struct file_operations bfs_file_operations = { |
| 21 | .llseek = generic_file_llseek, | 21 | .llseek = generic_file_llseek, |
| 22 | .read = generic_file_read, | 22 | .read = generic_file_read, |
| 23 | .write = generic_file_write, | 23 | .write = generic_file_write, |
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 6a7b730c206b..d73d75591a39 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
| @@ -600,7 +600,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer, | |||
| 600 | return count; | 600 | return count; |
| 601 | } | 601 | } |
| 602 | 602 | ||
| 603 | static struct file_operations bm_entry_operations = { | 603 | static const struct file_operations bm_entry_operations = { |
| 604 | .read = bm_entry_read, | 604 | .read = bm_entry_read, |
| 605 | .write = bm_entry_write, | 605 | .write = bm_entry_write, |
| 606 | }; | 606 | }; |
| @@ -668,7 +668,7 @@ out: | |||
| 668 | return count; | 668 | return count; |
| 669 | } | 669 | } |
| 670 | 670 | ||
| 671 | static struct file_operations bm_register_operations = { | 671 | static const struct file_operations bm_register_operations = { |
| 672 | .write = bm_register_write, | 672 | .write = bm_register_write, |
| 673 | }; | 673 | }; |
| 674 | 674 | ||
| @@ -715,7 +715,7 @@ static ssize_t bm_status_write(struct file * file, const char __user * buffer, | |||
| 715 | return count; | 715 | return count; |
| 716 | } | 716 | } |
| 717 | 717 | ||
| 718 | static struct file_operations bm_status_operations = { | 718 | static const struct file_operations bm_status_operations = { |
| 719 | .read = bm_status_read, | 719 | .read = bm_status_read, |
| 720 | .write = bm_status_write, | 720 | .write = bm_status_write, |
| 721 | }; | 721 | }; |
diff --git a/fs/block_dev.c b/fs/block_dev.c index 5983d42df015..af88c43043d5 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -266,6 +266,9 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | |||
| 266 | mutex_init(&bdev->bd_mount_mutex); | 266 | mutex_init(&bdev->bd_mount_mutex); |
| 267 | INIT_LIST_HEAD(&bdev->bd_inodes); | 267 | INIT_LIST_HEAD(&bdev->bd_inodes); |
| 268 | INIT_LIST_HEAD(&bdev->bd_list); | 268 | INIT_LIST_HEAD(&bdev->bd_list); |
| 269 | #ifdef CONFIG_SYSFS | ||
| 270 | INIT_LIST_HEAD(&bdev->bd_holder_list); | ||
| 271 | #endif | ||
| 269 | inode_init_once(&ei->vfs_inode); | 272 | inode_init_once(&ei->vfs_inode); |
| 270 | } | 273 | } |
| 271 | } | 274 | } |
| @@ -490,6 +493,300 @@ void bd_release(struct block_device *bdev) | |||
| 490 | 493 | ||
| 491 | EXPORT_SYMBOL(bd_release); | 494 | EXPORT_SYMBOL(bd_release); |
| 492 | 495 | ||
| 496 | #ifdef CONFIG_SYSFS | ||
| 497 | /* | ||
| 498 | * Functions for bd_claim_by_kobject / bd_release_from_kobject | ||
| 499 | * | ||
| 500 | * If a kobject is passed to bd_claim_by_kobject() | ||
| 501 | * and the kobject has a parent directory, | ||
| 502 | * following symlinks are created: | ||
| 503 | * o from the kobject to the claimed bdev | ||
| 504 | * o from "holders" directory of the bdev to the parent of the kobject | ||
| 505 | * bd_release_from_kobject() removes these symlinks. | ||
| 506 | * | ||
| 507 | * Example: | ||
| 508 | * If /dev/dm-0 maps to /dev/sda, kobject corresponding to | ||
| 509 | * /sys/block/dm-0/slaves is passed to bd_claim_by_kobject(), then: | ||
| 510 | * /sys/block/dm-0/slaves/sda --> /sys/block/sda | ||
| 511 | * /sys/block/sda/holders/dm-0 --> /sys/block/dm-0 | ||
| 512 | */ | ||
| 513 | |||
| 514 | static struct kobject *bdev_get_kobj(struct block_device *bdev) | ||
| 515 | { | ||
| 516 | if (bdev->bd_contains != bdev) | ||
| 517 | return kobject_get(&bdev->bd_part->kobj); | ||
| 518 | else | ||
| 519 | return kobject_get(&bdev->bd_disk->kobj); | ||
| 520 | } | ||
| 521 | |||
| 522 | static struct kobject *bdev_get_holder(struct block_device *bdev) | ||
| 523 | { | ||
| 524 | if (bdev->bd_contains != bdev) | ||
| 525 | return kobject_get(bdev->bd_part->holder_dir); | ||
| 526 | else | ||
| 527 | return kobject_get(bdev->bd_disk->holder_dir); | ||
| 528 | } | ||
| 529 | |||
| 530 | static void add_symlink(struct kobject *from, struct kobject *to) | ||
| 531 | { | ||
| 532 | if (!from || !to) | ||
| 533 | return; | ||
| 534 | sysfs_create_link(from, to, kobject_name(to)); | ||
| 535 | } | ||
| 536 | |||
| 537 | static void del_symlink(struct kobject *from, struct kobject *to) | ||
| 538 | { | ||
| 539 | if (!from || !to) | ||
| 540 | return; | ||
| 541 | sysfs_remove_link(from, kobject_name(to)); | ||
| 542 | } | ||
| 543 | |||
| 544 | /* | ||
| 545 | * 'struct bd_holder' contains pointers to kobjects symlinked by | ||
| 546 | * bd_claim_by_kobject. | ||
| 547 | * It's connected to bd_holder_list which is protected by bdev->bd_sem. | ||
| 548 | */ | ||
| 549 | struct bd_holder { | ||
| 550 | struct list_head list; /* chain of holders of the bdev */ | ||
| 551 | int count; /* references from the holder */ | ||
| 552 | struct kobject *sdir; /* holder object, e.g. "/block/dm-0/slaves" */ | ||
| 553 | struct kobject *hdev; /* e.g. "/block/dm-0" */ | ||
| 554 | struct kobject *hdir; /* e.g. "/block/sda/holders" */ | ||
| 555 | struct kobject *sdev; /* e.g. "/block/sda" */ | ||
| 556 | }; | ||
| 557 | |||
| 558 | /* | ||
| 559 | * Get references of related kobjects at once. | ||
| 560 | * Returns 1 on success. 0 on failure. | ||
| 561 | * | ||
| 562 | * Should call bd_holder_release_dirs() after successful use. | ||
| 563 | */ | ||
| 564 | static int bd_holder_grab_dirs(struct block_device *bdev, | ||
| 565 | struct bd_holder *bo) | ||
| 566 | { | ||
| 567 | if (!bdev || !bo) | ||
| 568 | return 0; | ||
| 569 | |||
| 570 | bo->sdir = kobject_get(bo->sdir); | ||
| 571 | if (!bo->sdir) | ||
| 572 | return 0; | ||
| 573 | |||
| 574 | bo->hdev = kobject_get(bo->sdir->parent); | ||
| 575 | if (!bo->hdev) | ||
| 576 | goto fail_put_sdir; | ||
| 577 | |||
| 578 | bo->sdev = bdev_get_kobj(bdev); | ||
| 579 | if (!bo->sdev) | ||
| 580 | goto fail_put_hdev; | ||
| 581 | |||
| 582 | bo->hdir = bdev_get_holder(bdev); | ||
| 583 | if (!bo->hdir) | ||
| 584 | goto fail_put_sdev; | ||
| 585 | |||
| 586 | return 1; | ||
| 587 | |||
| 588 | fail_put_sdev: | ||
| 589 | kobject_put(bo->sdev); | ||
| 590 | fail_put_hdev: | ||
| 591 | kobject_put(bo->hdev); | ||
| 592 | fail_put_sdir: | ||
| 593 | kobject_put(bo->sdir); | ||
| 594 | |||
| 595 | return 0; | ||
| 596 | } | ||
| 597 | |||
| 598 | /* Put references of related kobjects at once. */ | ||
| 599 | static void bd_holder_release_dirs(struct bd_holder *bo) | ||
| 600 | { | ||
| 601 | kobject_put(bo->hdir); | ||
| 602 | kobject_put(bo->sdev); | ||
| 603 | kobject_put(bo->hdev); | ||
| 604 | kobject_put(bo->sdir); | ||
| 605 | } | ||
| 606 | |||
| 607 | static struct bd_holder *alloc_bd_holder(struct kobject *kobj) | ||
| 608 | { | ||
| 609 | struct bd_holder *bo; | ||
| 610 | |||
| 611 | bo = kzalloc(sizeof(*bo), GFP_KERNEL); | ||
| 612 | if (!bo) | ||
| 613 | return NULL; | ||
| 614 | |||
| 615 | bo->count = 1; | ||
| 616 | bo->sdir = kobj; | ||
| 617 | |||
| 618 | return bo; | ||
| 619 | } | ||
| 620 | |||
| 621 | static void free_bd_holder(struct bd_holder *bo) | ||
| 622 | { | ||
| 623 | kfree(bo); | ||
| 624 | } | ||
| 625 | |||
| 626 | /** | ||
| 627 | * add_bd_holder - create sysfs symlinks for bd_claim() relationship | ||
| 628 | * | ||
| 629 | * @bdev: block device to be bd_claimed | ||
| 630 | * @bo: preallocated and initialized by alloc_bd_holder() | ||
| 631 | * | ||
| 632 | * If there is no matching entry with @bo in @bdev->bd_holder_list, | ||
| 633 | * add @bo to the list, create symlinks. | ||
| 634 | * | ||
| 635 | * Returns 1 if @bo was added to the list. | ||
| 636 | * Returns 0 if @bo wasn't used by any reason and should be freed. | ||
| 637 | */ | ||
| 638 | static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) | ||
| 639 | { | ||
| 640 | struct bd_holder *tmp; | ||
| 641 | |||
| 642 | if (!bo) | ||
| 643 | return 0; | ||
| 644 | |||
| 645 | list_for_each_entry(tmp, &bdev->bd_holder_list, list) { | ||
| 646 | if (tmp->sdir == bo->sdir) { | ||
| 647 | tmp->count++; | ||
| 648 | return 0; | ||
| 649 | } | ||
| 650 | } | ||
| 651 | |||
| 652 | if (!bd_holder_grab_dirs(bdev, bo)) | ||
| 653 | return 0; | ||
| 654 | |||
| 655 | add_symlink(bo->sdir, bo->sdev); | ||
| 656 | add_symlink(bo->hdir, bo->hdev); | ||
| 657 | list_add_tail(&bo->list, &bdev->bd_holder_list); | ||
| 658 | return 1; | ||
| 659 | } | ||
| 660 | |||
| 661 | /** | ||
| 662 | * del_bd_holder - delete sysfs symlinks for bd_claim() relationship | ||
| 663 | * | ||
| 664 | * @bdev: block device to be bd_claimed | ||
| 665 | * @kobj: holder's kobject | ||
| 666 | * | ||
| 667 | * If there is matching entry with @kobj in @bdev->bd_holder_list | ||
| 668 | * and no other bd_claim() from the same kobject, | ||
| 669 | * remove the struct bd_holder from the list, delete symlinks for it. | ||
| 670 | * | ||
| 671 | * Returns a pointer to the struct bd_holder when it's removed from the list | ||
| 672 | * and ready to be freed. | ||
| 673 | * Returns NULL if matching claim isn't found or there is other bd_claim() | ||
| 674 | * by the same kobject. | ||
| 675 | */ | ||
| 676 | static struct bd_holder *del_bd_holder(struct block_device *bdev, | ||
| 677 | struct kobject *kobj) | ||
| 678 | { | ||
| 679 | struct bd_holder *bo; | ||
| 680 | |||
| 681 | list_for_each_entry(bo, &bdev->bd_holder_list, list) { | ||
| 682 | if (bo->sdir == kobj) { | ||
| 683 | bo->count--; | ||
| 684 | BUG_ON(bo->count < 0); | ||
| 685 | if (!bo->count) { | ||
| 686 | list_del(&bo->list); | ||
| 687 | del_symlink(bo->sdir, bo->sdev); | ||
| 688 | del_symlink(bo->hdir, bo->hdev); | ||
| 689 | bd_holder_release_dirs(bo); | ||
| 690 | return bo; | ||
| 691 | } | ||
| 692 | break; | ||
| 693 | } | ||
| 694 | } | ||
| 695 | |||
| 696 | return NULL; | ||
| 697 | } | ||
| 698 | |||
| 699 | /** | ||
| 700 | * bd_claim_by_kobject - bd_claim() with additional kobject signature | ||
| 701 | * | ||
| 702 | * @bdev: block device to be claimed | ||
| 703 | * @holder: holder's signature | ||
| 704 | * @kobj: holder's kobject | ||
| 705 | * | ||
| 706 | * Do bd_claim() and if it succeeds, create sysfs symlinks between | ||
| 707 | * the bdev and the holder's kobject. | ||
| 708 | * Use bd_release_from_kobject() when relesing the claimed bdev. | ||
| 709 | * | ||
| 710 | * Returns 0 on success. (same as bd_claim()) | ||
| 711 | * Returns errno on failure. | ||
| 712 | */ | ||
| 713 | static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | ||
| 714 | struct kobject *kobj) | ||
| 715 | { | ||
| 716 | int res; | ||
| 717 | struct bd_holder *bo; | ||
| 718 | |||
| 719 | if (!kobj) | ||
| 720 | return -EINVAL; | ||
| 721 | |||
| 722 | bo = alloc_bd_holder(kobj); | ||
| 723 | if (!bo) | ||
| 724 | return -ENOMEM; | ||
| 725 | |||
| 726 | mutex_lock(&bdev->bd_mutex); | ||
| 727 | res = bd_claim(bdev, holder); | ||
| 728 | if (res || !add_bd_holder(bdev, bo)) | ||
| 729 | free_bd_holder(bo); | ||
| 730 | mutex_unlock(&bdev->bd_mutex); | ||
| 731 | |||
| 732 | return res; | ||
| 733 | } | ||
| 734 | |||
| 735 | /** | ||
| 736 | * bd_release_from_kobject - bd_release() with additional kobject signature | ||
| 737 | * | ||
| 738 | * @bdev: block device to be released | ||
| 739 | * @kobj: holder's kobject | ||
| 740 | * | ||
| 741 | * Do bd_release() and remove sysfs symlinks created by bd_claim_by_kobject(). | ||
| 742 | */ | ||
| 743 | static void bd_release_from_kobject(struct block_device *bdev, | ||
| 744 | struct kobject *kobj) | ||
| 745 | { | ||
| 746 | struct bd_holder *bo; | ||
| 747 | |||
| 748 | if (!kobj) | ||
| 749 | return; | ||
| 750 | |||
| 751 | mutex_lock(&bdev->bd_mutex); | ||
| 752 | bd_release(bdev); | ||
| 753 | if ((bo = del_bd_holder(bdev, kobj))) | ||
| 754 | free_bd_holder(bo); | ||
| 755 | mutex_unlock(&bdev->bd_mutex); | ||
| 756 | } | ||
| 757 | |||
| 758 | /** | ||
| 759 | * bd_claim_by_disk - wrapper function for bd_claim_by_kobject() | ||
| 760 | * | ||
| 761 | * @bdev: block device to be claimed | ||
| 762 | * @holder: holder's signature | ||
| 763 | * @disk: holder's gendisk | ||
| 764 | * | ||
| 765 | * Call bd_claim_by_kobject() with getting @disk->slave_dir. | ||
| 766 | */ | ||
| 767 | int bd_claim_by_disk(struct block_device *bdev, void *holder, | ||
| 768 | struct gendisk *disk) | ||
| 769 | { | ||
| 770 | return bd_claim_by_kobject(bdev, holder, kobject_get(disk->slave_dir)); | ||
| 771 | } | ||
| 772 | EXPORT_SYMBOL_GPL(bd_claim_by_disk); | ||
| 773 | |||
| 774 | /** | ||
| 775 | * bd_release_from_disk - wrapper function for bd_release_from_kobject() | ||
| 776 | * | ||
| 777 | * @bdev: block device to be claimed | ||
| 778 | * @disk: holder's gendisk | ||
| 779 | * | ||
| 780 | * Call bd_release_from_kobject() and put @disk->slave_dir. | ||
| 781 | */ | ||
| 782 | void bd_release_from_disk(struct block_device *bdev, struct gendisk *disk) | ||
| 783 | { | ||
| 784 | bd_release_from_kobject(bdev, disk->slave_dir); | ||
| 785 | kobject_put(disk->slave_dir); | ||
| 786 | } | ||
| 787 | EXPORT_SYMBOL_GPL(bd_release_from_disk); | ||
| 788 | #endif | ||
| 789 | |||
| 493 | /* | 790 | /* |
| 494 | * Tries to open block device by device number. Use it ONLY if you | 791 | * Tries to open block device by device number. Use it ONLY if you |
| 495 | * really do not have anything better - i.e. when you are behind a | 792 | * really do not have anything better - i.e. when you are behind a |
| @@ -790,7 +1087,7 @@ struct address_space_operations def_blk_aops = { | |||
| 790 | .direct_IO = blkdev_direct_IO, | 1087 | .direct_IO = blkdev_direct_IO, |
| 791 | }; | 1088 | }; |
| 792 | 1089 | ||
| 793 | struct file_operations def_blk_fops = { | 1090 | const struct file_operations def_blk_fops = { |
| 794 | .open = blkdev_open, | 1091 | .open = blkdev_open, |
| 795 | .release = blkdev_close, | 1092 | .release = blkdev_close, |
| 796 | .llseek = block_llseek, | 1093 | .llseek = block_llseek, |
diff --git a/fs/buffer.c b/fs/buffer.c index d597758dd129..23f1f3a68077 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -493,7 +493,7 @@ static void free_more_memory(void) | |||
| 493 | wakeup_pdflush(1024); | 493 | wakeup_pdflush(1024); |
| 494 | yield(); | 494 | yield(); |
| 495 | 495 | ||
| 496 | for_each_pgdat(pgdat) { | 496 | for_each_online_pgdat(pgdat) { |
| 497 | zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones; | 497 | zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones; |
| 498 | if (*zones) | 498 | if (*zones) |
| 499 | try_to_free_pages(zones, GFP_NOFS); | 499 | try_to_free_pages(zones, GFP_NOFS); |
diff --git a/fs/char_dev.c b/fs/char_dev.c index 8c6eb04d31e2..4e1b849f912f 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
| @@ -250,7 +250,7 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, | |||
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | int register_chrdev(unsigned int major, const char *name, | 252 | int register_chrdev(unsigned int major, const char *name, |
| 253 | struct file_operations *fops) | 253 | const struct file_operations *fops) |
| 254 | { | 254 | { |
| 255 | struct char_device_struct *cd; | 255 | struct char_device_struct *cd; |
| 256 | struct cdev *cdev; | 256 | struct cdev *cdev; |
| @@ -406,7 +406,7 @@ static void cdev_purge(struct cdev *cdev) | |||
| 406 | * is contain the open that then fills in the correct operations | 406 | * is contain the open that then fills in the correct operations |
| 407 | * depending on the special file... | 407 | * depending on the special file... |
| 408 | */ | 408 | */ |
| 409 | struct file_operations def_chr_fops = { | 409 | const struct file_operations def_chr_fops = { |
| 410 | .open = chrdev_open, | 410 | .open = chrdev_open, |
| 411 | }; | 411 | }; |
| 412 | 412 | ||
| @@ -473,7 +473,7 @@ struct cdev *cdev_alloc(void) | |||
| 473 | return p; | 473 | return p; |
| 474 | } | 474 | } |
| 475 | 475 | ||
| 476 | void cdev_init(struct cdev *cdev, struct file_operations *fops) | 476 | void cdev_init(struct cdev *cdev, const struct file_operations *fops) |
| 477 | { | 477 | { |
| 478 | memset(cdev, 0, sizeof *cdev); | 478 | memset(cdev, 0, sizeof *cdev); |
| 479 | INIT_LIST_HEAD(&cdev->list); | 479 | INIT_LIST_HEAD(&cdev->list); |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 6b99b51d6694..4bbc544857bc 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -583,7 +583,7 @@ struct inode_operations cifs_symlink_inode_ops = { | |||
| 583 | #endif | 583 | #endif |
| 584 | }; | 584 | }; |
| 585 | 585 | ||
| 586 | struct file_operations cifs_file_ops = { | 586 | const struct file_operations cifs_file_ops = { |
| 587 | .read = do_sync_read, | 587 | .read = do_sync_read, |
| 588 | .write = do_sync_write, | 588 | .write = do_sync_write, |
| 589 | .readv = generic_file_readv, | 589 | .readv = generic_file_readv, |
| @@ -607,7 +607,7 @@ struct file_operations cifs_file_ops = { | |||
| 607 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 607 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 608 | }; | 608 | }; |
| 609 | 609 | ||
| 610 | struct file_operations cifs_file_direct_ops = { | 610 | const struct file_operations cifs_file_direct_ops = { |
| 611 | /* no mmap, no aio, no readv - | 611 | /* no mmap, no aio, no readv - |
| 612 | BB reevaluate whether they can be done with directio, no cache */ | 612 | BB reevaluate whether they can be done with directio, no cache */ |
| 613 | .read = cifs_user_read, | 613 | .read = cifs_user_read, |
| @@ -626,7 +626,7 @@ struct file_operations cifs_file_direct_ops = { | |||
| 626 | .dir_notify = cifs_dir_notify, | 626 | .dir_notify = cifs_dir_notify, |
| 627 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 627 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 628 | }; | 628 | }; |
| 629 | struct file_operations cifs_file_nobrl_ops = { | 629 | const struct file_operations cifs_file_nobrl_ops = { |
| 630 | .read = do_sync_read, | 630 | .read = do_sync_read, |
| 631 | .write = do_sync_write, | 631 | .write = do_sync_write, |
| 632 | .readv = generic_file_readv, | 632 | .readv = generic_file_readv, |
| @@ -649,7 +649,7 @@ struct file_operations cifs_file_nobrl_ops = { | |||
| 649 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 649 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 650 | }; | 650 | }; |
| 651 | 651 | ||
| 652 | struct file_operations cifs_file_direct_nobrl_ops = { | 652 | const struct file_operations cifs_file_direct_nobrl_ops = { |
| 653 | /* no mmap, no aio, no readv - | 653 | /* no mmap, no aio, no readv - |
| 654 | BB reevaluate whether they can be done with directio, no cache */ | 654 | BB reevaluate whether they can be done with directio, no cache */ |
| 655 | .read = cifs_user_read, | 655 | .read = cifs_user_read, |
| @@ -668,7 +668,7 @@ struct file_operations cifs_file_direct_nobrl_ops = { | |||
| 668 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 668 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 669 | }; | 669 | }; |
| 670 | 670 | ||
| 671 | struct file_operations cifs_dir_ops = { | 671 | const struct file_operations cifs_dir_ops = { |
| 672 | .readdir = cifs_readdir, | 672 | .readdir = cifs_readdir, |
| 673 | .release = cifs_closedir, | 673 | .release = cifs_closedir, |
| 674 | .read = generic_read_dir, | 674 | .read = generic_read_dir, |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 821a8eb22559..74f405ae4da3 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -61,10 +61,10 @@ extern struct inode_operations cifs_file_inode_ops; | |||
| 61 | extern struct inode_operations cifs_symlink_inode_ops; | 61 | extern struct inode_operations cifs_symlink_inode_ops; |
| 62 | 62 | ||
| 63 | /* Functions related to files and directories */ | 63 | /* Functions related to files and directories */ |
| 64 | extern struct file_operations cifs_file_ops; | 64 | extern const struct file_operations cifs_file_ops; |
| 65 | extern struct file_operations cifs_file_direct_ops; /* if directio mount */ | 65 | extern const struct file_operations cifs_file_direct_ops; /* if directio mount */ |
| 66 | extern struct file_operations cifs_file_nobrl_ops; | 66 | extern const struct file_operations cifs_file_nobrl_ops; |
| 67 | extern struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */ | 67 | extern const struct file_operations cifs_file_direct_nobrl_ops; /* if directio mount */ |
| 68 | extern int cifs_open(struct inode *inode, struct file *file); | 68 | extern int cifs_open(struct inode *inode, struct file *file); |
| 69 | extern int cifs_close(struct inode *inode, struct file *file); | 69 | extern int cifs_close(struct inode *inode, struct file *file); |
| 70 | extern int cifs_closedir(struct inode *inode, struct file *file); | 70 | extern int cifs_closedir(struct inode *inode, struct file *file); |
| @@ -76,7 +76,7 @@ extern int cifs_lock(struct file *, int, struct file_lock *); | |||
| 76 | extern int cifs_fsync(struct file *, struct dentry *, int); | 76 | extern int cifs_fsync(struct file *, struct dentry *, int); |
| 77 | extern int cifs_flush(struct file *); | 77 | extern int cifs_flush(struct file *); |
| 78 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); | 78 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); |
| 79 | extern struct file_operations cifs_dir_ops; | 79 | extern const struct file_operations cifs_dir_ops; |
| 80 | extern int cifs_dir_open(struct inode *inode, struct file *file); | 80 | extern int cifs_dir_open(struct inode *inode, struct file *file); |
| 81 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); | 81 | extern int cifs_readdir(struct file *file, void *direntry, filldir_t filldir); |
| 82 | extern int cifs_dir_notify(struct file *, unsigned long arg); | 82 | extern int cifs_dir_notify(struct file *, unsigned long arg); |
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 54f76de8a686..71f2ea632e53 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
| @@ -82,7 +82,7 @@ struct inode_operations coda_dir_inode_operations = | |||
| 82 | .setattr = coda_setattr, | 82 | .setattr = coda_setattr, |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | struct file_operations coda_dir_operations = { | 85 | const struct file_operations coda_dir_operations = { |
| 86 | .llseek = generic_file_llseek, | 86 | .llseek = generic_file_llseek, |
| 87 | .read = generic_read_dir, | 87 | .read = generic_read_dir, |
| 88 | .readdir = coda_readdir, | 88 | .readdir = coda_readdir, |
diff --git a/fs/coda/file.c b/fs/coda/file.c index 146a991d6eb5..7c2642431fa5 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c | |||
| @@ -288,7 +288,7 @@ int coda_fsync(struct file *coda_file, struct dentry *coda_dentry, int datasync) | |||
| 288 | return err; | 288 | return err; |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | struct file_operations coda_file_operations = { | 291 | const struct file_operations coda_file_operations = { |
| 292 | .llseek = generic_file_llseek, | 292 | .llseek = generic_file_llseek, |
| 293 | .read = coda_file_read, | 293 | .read = coda_file_read, |
| 294 | .write = coda_file_write, | 294 | .write = coda_file_write, |
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 127714936c66..214822be87bd 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c | |||
| @@ -36,7 +36,7 @@ struct inode_operations coda_ioctl_inode_operations = | |||
| 36 | .setattr = coda_setattr, | 36 | .setattr = coda_setattr, |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| 39 | struct file_operations coda_ioctl_operations = { | 39 | const struct file_operations coda_ioctl_operations = { |
| 40 | .owner = THIS_MODULE, | 40 | .owner = THIS_MODULE, |
| 41 | .ioctl = coda_pioctl, | 41 | .ioctl = coda_pioctl, |
| 42 | }; | 42 | }; |
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 98c74fe2e139..6c6771db36da 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c | |||
| @@ -342,7 +342,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file) | |||
| 342 | } | 342 | } |
| 343 | 343 | ||
| 344 | 344 | ||
| 345 | static struct file_operations coda_psdev_fops = { | 345 | static const struct file_operations coda_psdev_fops = { |
| 346 | .owner = THIS_MODULE, | 346 | .owner = THIS_MODULE, |
| 347 | .read = coda_psdev_read, | 347 | .read = coda_psdev_read, |
| 348 | .write = coda_psdev_write, | 348 | .write = coda_psdev_write, |
diff --git a/fs/compat.c b/fs/compat.c index ef5a0771592d..7f8e26ea427c 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
| @@ -1639,15 +1639,6 @@ void compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, | |||
| 1639 | * This is a virtual copy of sys_select from fs/select.c and probably | 1639 | * This is a virtual copy of sys_select from fs/select.c and probably |
| 1640 | * should be compared to it from time to time | 1640 | * should be compared to it from time to time |
| 1641 | */ | 1641 | */ |
| 1642 | static void *select_bits_alloc(int size) | ||
| 1643 | { | ||
| 1644 | return kmalloc(6 * size, GFP_KERNEL); | ||
| 1645 | } | ||
| 1646 | |||
| 1647 | static void select_bits_free(void *bits, int size) | ||
| 1648 | { | ||
| 1649 | kfree(bits); | ||
| 1650 | } | ||
| 1651 | 1642 | ||
| 1652 | /* | 1643 | /* |
| 1653 | * We can actually return ERESTARTSYS instead of EINTR, but I'd | 1644 | * We can actually return ERESTARTSYS instead of EINTR, but I'd |
| @@ -1686,7 +1677,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, | |||
| 1686 | */ | 1677 | */ |
| 1687 | ret = -ENOMEM; | 1678 | ret = -ENOMEM; |
| 1688 | size = FDS_BYTES(n); | 1679 | size = FDS_BYTES(n); |
| 1689 | bits = select_bits_alloc(size); | 1680 | bits = kmalloc(6 * size, GFP_KERNEL); |
| 1690 | if (!bits) | 1681 | if (!bits) |
| 1691 | goto out_nofds; | 1682 | goto out_nofds; |
| 1692 | fds.in = (unsigned long *) bits; | 1683 | fds.in = (unsigned long *) bits; |
| @@ -1720,7 +1711,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp, | |||
| 1720 | compat_set_fd_set(n, exp, fds.res_ex); | 1711 | compat_set_fd_set(n, exp, fds.res_ex); |
| 1721 | 1712 | ||
| 1722 | out: | 1713 | out: |
| 1723 | select_bits_free(bits, size); | 1714 | kfree(bits); |
| 1724 | out_nofds: | 1715 | out_nofds: |
| 1725 | return ret; | 1716 | return ret; |
| 1726 | } | 1717 | } |
diff --git a/fs/configfs/configfs_internal.h b/fs/configfs/configfs_internal.h index f70e46951b37..3f4ff7a242b9 100644 --- a/fs/configfs/configfs_internal.h +++ b/fs/configfs/configfs_internal.h | |||
| @@ -72,9 +72,9 @@ extern void configfs_release_fs(void); | |||
| 72 | 72 | ||
| 73 | extern struct rw_semaphore configfs_rename_sem; | 73 | extern struct rw_semaphore configfs_rename_sem; |
| 74 | extern struct super_block * configfs_sb; | 74 | extern struct super_block * configfs_sb; |
| 75 | extern struct file_operations configfs_dir_operations; | 75 | extern const struct file_operations configfs_dir_operations; |
| 76 | extern struct file_operations configfs_file_operations; | 76 | extern const struct file_operations configfs_file_operations; |
| 77 | extern struct file_operations bin_fops; | 77 | extern const struct file_operations bin_fops; |
| 78 | extern struct inode_operations configfs_dir_inode_operations; | 78 | extern struct inode_operations configfs_dir_inode_operations; |
| 79 | extern struct inode_operations configfs_symlink_inode_operations; | 79 | extern struct inode_operations configfs_symlink_inode_operations; |
| 80 | 80 | ||
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index ca60e3abef45..8ed9b06a9828 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
| @@ -1027,7 +1027,7 @@ static loff_t configfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
| 1027 | return offset; | 1027 | return offset; |
| 1028 | } | 1028 | } |
| 1029 | 1029 | ||
| 1030 | struct file_operations configfs_dir_operations = { | 1030 | const struct file_operations configfs_dir_operations = { |
| 1031 | .open = configfs_dir_open, | 1031 | .open = configfs_dir_open, |
| 1032 | .release = configfs_dir_close, | 1032 | .release = configfs_dir_close, |
| 1033 | .llseek = configfs_dir_lseek, | 1033 | .llseek = configfs_dir_lseek, |
diff --git a/fs/configfs/file.c b/fs/configfs/file.c index 3921920d8716..f499803743e0 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c | |||
| @@ -322,7 +322,7 @@ static int configfs_release(struct inode * inode, struct file * filp) | |||
| 322 | return 0; | 322 | return 0; |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | struct file_operations configfs_file_operations = { | 325 | const struct file_operations configfs_file_operations = { |
| 326 | .read = configfs_read_file, | 326 | .read = configfs_read_file, |
| 327 | .write = configfs_write_file, | 327 | .write = configfs_write_file, |
| 328 | .llseek = generic_file_llseek, | 328 | .llseek = generic_file_llseek, |
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index acc1b2c10a86..9efcc3a164e8 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | 29 | ||
| 30 | static struct super_operations cramfs_ops; | 30 | static struct super_operations cramfs_ops; |
| 31 | static struct inode_operations cramfs_dir_inode_operations; | 31 | static struct inode_operations cramfs_dir_inode_operations; |
| 32 | static struct file_operations cramfs_directory_operations; | 32 | static const struct file_operations cramfs_directory_operations; |
| 33 | static struct address_space_operations cramfs_aops; | 33 | static struct address_space_operations cramfs_aops; |
| 34 | 34 | ||
| 35 | static DEFINE_MUTEX(read_mutex); | 35 | static DEFINE_MUTEX(read_mutex); |
| @@ -512,7 +512,7 @@ static struct address_space_operations cramfs_aops = { | |||
| 512 | /* | 512 | /* |
| 513 | * A directory can only readdir | 513 | * A directory can only readdir |
| 514 | */ | 514 | */ |
| 515 | static struct file_operations cramfs_directory_operations = { | 515 | static const struct file_operations cramfs_directory_operations = { |
| 516 | .llseek = generic_file_llseek, | 516 | .llseek = generic_file_llseek, |
| 517 | .read = generic_read_dir, | 517 | .read = generic_read_dir, |
| 518 | .readdir = cramfs_readdir, | 518 | .readdir = cramfs_readdir, |
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c index 40c4fc973fad..66a505422e5c 100644 --- a/fs/debugfs/file.c +++ b/fs/debugfs/file.c | |||
| @@ -39,7 +39,7 @@ static int default_open(struct inode *inode, struct file *file) | |||
| 39 | return 0; | 39 | return 0; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | struct file_operations debugfs_file_operations = { | 42 | const struct file_operations debugfs_file_operations = { |
| 43 | .read = default_read_file, | 43 | .read = default_read_file, |
| 44 | .write = default_write_file, | 44 | .write = default_write_file, |
| 45 | .open = default_open, | 45 | .open = default_open, |
| @@ -213,7 +213,7 @@ static ssize_t write_file_bool(struct file *file, const char __user *user_buf, | |||
| 213 | return count; | 213 | return count; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | static struct file_operations fops_bool = { | 216 | static const struct file_operations fops_bool = { |
| 217 | .read = read_file_bool, | 217 | .read = read_file_bool, |
| 218 | .write = write_file_bool, | 218 | .write = write_file_bool, |
| 219 | .open = default_open, | 219 | .open = default_open, |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index d4f1a2cddd47..85d166cdcae4 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
| @@ -191,7 +191,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode, | |||
| 191 | */ | 191 | */ |
| 192 | struct dentry *debugfs_create_file(const char *name, mode_t mode, | 192 | struct dentry *debugfs_create_file(const char *name, mode_t mode, |
| 193 | struct dentry *parent, void *data, | 193 | struct dentry *parent, void *data, |
| 194 | struct file_operations *fops) | 194 | const struct file_operations *fops) |
| 195 | { | 195 | { |
| 196 | struct dentry *dentry = NULL; | 196 | struct dentry *dentry = NULL; |
| 197 | int error; | 197 | int error; |
diff --git a/fs/devfs/base.c b/fs/devfs/base.c index b621521e09d4..52f5059c4f31 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c | |||
| @@ -856,14 +856,14 @@ static int devfsd_close(struct inode *inode, struct file *file); | |||
| 856 | #ifdef CONFIG_DEVFS_DEBUG | 856 | #ifdef CONFIG_DEVFS_DEBUG |
| 857 | static ssize_t stat_read(struct file *file, char __user *buf, size_t len, | 857 | static ssize_t stat_read(struct file *file, char __user *buf, size_t len, |
| 858 | loff_t * ppos); | 858 | loff_t * ppos); |
| 859 | static struct file_operations stat_fops = { | 859 | static const struct file_operations stat_fops = { |
| 860 | .open = nonseekable_open, | 860 | .open = nonseekable_open, |
| 861 | .read = stat_read, | 861 | .read = stat_read, |
| 862 | }; | 862 | }; |
| 863 | #endif | 863 | #endif |
| 864 | 864 | ||
| 865 | /* Devfs daemon file operations */ | 865 | /* Devfs daemon file operations */ |
| 866 | static struct file_operations devfsd_fops = { | 866 | static const struct file_operations devfsd_fops = { |
| 867 | .open = nonseekable_open, | 867 | .open = nonseekable_open, |
| 868 | .read = devfsd_read, | 868 | .read = devfsd_read, |
| 869 | .ioctl = devfsd_ioctl, | 869 | .ioctl = devfsd_ioctl, |
| @@ -1842,8 +1842,8 @@ static int try_modload(struct devfs_entry *parent, struct fs_info *fs_info, | |||
| 1842 | 1842 | ||
| 1843 | static struct inode_operations devfs_iops; | 1843 | static struct inode_operations devfs_iops; |
| 1844 | static struct inode_operations devfs_dir_iops; | 1844 | static struct inode_operations devfs_dir_iops; |
| 1845 | static struct file_operations devfs_fops; | 1845 | static const struct file_operations devfs_fops; |
| 1846 | static struct file_operations devfs_dir_fops; | 1846 | static const struct file_operations devfs_dir_fops; |
| 1847 | static struct inode_operations devfs_symlink_iops; | 1847 | static struct inode_operations devfs_symlink_iops; |
| 1848 | 1848 | ||
| 1849 | static int devfs_notify_change(struct dentry *dentry, struct iattr *iattr) | 1849 | static int devfs_notify_change(struct dentry *dentry, struct iattr *iattr) |
| @@ -2061,11 +2061,11 @@ static int devfs_open(struct inode *inode, struct file *file) | |||
| 2061 | return err; | 2061 | return err; |
| 2062 | } /* End Function devfs_open */ | 2062 | } /* End Function devfs_open */ |
| 2063 | 2063 | ||
| 2064 | static struct file_operations devfs_fops = { | 2064 | static const struct file_operations devfs_fops = { |
| 2065 | .open = devfs_open, | 2065 | .open = devfs_open, |
| 2066 | }; | 2066 | }; |
| 2067 | 2067 | ||
| 2068 | static struct file_operations devfs_dir_fops = { | 2068 | static const struct file_operations devfs_dir_fops = { |
| 2069 | .read = generic_read_dir, | 2069 | .read = generic_read_dir, |
| 2070 | .readdir = devfs_readdir, | 2070 | .readdir = devfs_readdir, |
| 2071 | }; | 2071 | }; |
diff --git a/fs/efs/dir.c b/fs/efs/dir.c index 777c614ff360..17f5b2d3c16a 100644 --- a/fs/efs/dir.c +++ b/fs/efs/dir.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | static int efs_readdir(struct file *, void *, filldir_t); | 11 | static int efs_readdir(struct file *, void *, filldir_t); |
| 12 | 12 | ||
| 13 | struct file_operations efs_dir_operations = { | 13 | const struct file_operations efs_dir_operations = { |
| 14 | .read = generic_read_dir, | 14 | .read = generic_read_dir, |
| 15 | .readdir = efs_readdir, | 15 | .readdir = efs_readdir, |
| 16 | }; | 16 | }; |
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index e067a06c6464..242fe1a66ce5 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
| @@ -290,7 +290,7 @@ static kmem_cache_t *pwq_cache __read_mostly; | |||
| 290 | static struct vfsmount *eventpoll_mnt __read_mostly; | 290 | static struct vfsmount *eventpoll_mnt __read_mostly; |
| 291 | 291 | ||
| 292 | /* File callbacks that implement the eventpoll file behaviour */ | 292 | /* File callbacks that implement the eventpoll file behaviour */ |
| 293 | static struct file_operations eventpoll_fops = { | 293 | static const struct file_operations eventpoll_fops = { |
| 294 | .release = ep_eventpoll_close, | 294 | .release = ep_eventpoll_close, |
| 295 | .poll = ep_eventpoll_poll | 295 | .poll = ep_eventpoll_poll |
| 296 | }; | 296 | }; |
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 0165388c425c..d672aa9f4061 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
| @@ -658,7 +658,7 @@ not_empty: | |||
| 658 | return 0; | 658 | return 0; |
| 659 | } | 659 | } |
| 660 | 660 | ||
| 661 | struct file_operations ext2_dir_operations = { | 661 | const struct file_operations ext2_dir_operations = { |
| 662 | .llseek = generic_file_llseek, | 662 | .llseek = generic_file_llseek, |
| 663 | .read = generic_read_dir, | 663 | .read = generic_read_dir, |
| 664 | .readdir = ext2_readdir, | 664 | .readdir = ext2_readdir, |
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h index 11035ac7986f..9f74a62be555 100644 --- a/fs/ext2/ext2.h +++ b/fs/ext2/ext2.h | |||
| @@ -154,12 +154,12 @@ extern void ext2_write_super (struct super_block *); | |||
| 154 | */ | 154 | */ |
| 155 | 155 | ||
| 156 | /* dir.c */ | 156 | /* dir.c */ |
| 157 | extern struct file_operations ext2_dir_operations; | 157 | extern const struct file_operations ext2_dir_operations; |
| 158 | 158 | ||
| 159 | /* file.c */ | 159 | /* file.c */ |
| 160 | extern struct inode_operations ext2_file_inode_operations; | 160 | extern struct inode_operations ext2_file_inode_operations; |
| 161 | extern struct file_operations ext2_file_operations; | 161 | extern const struct file_operations ext2_file_operations; |
| 162 | extern struct file_operations ext2_xip_file_operations; | 162 | extern const struct file_operations ext2_xip_file_operations; |
| 163 | 163 | ||
| 164 | /* inode.c */ | 164 | /* inode.c */ |
| 165 | extern struct address_space_operations ext2_aops; | 165 | extern struct address_space_operations ext2_aops; |
diff --git a/fs/ext2/file.c b/fs/ext2/file.c index a484412fc782..509cceca04db 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c | |||
| @@ -39,7 +39,7 @@ static int ext2_release_file (struct inode * inode, struct file * filp) | |||
| 39 | * We have mostly NULL's here: the current defaults are ok for | 39 | * We have mostly NULL's here: the current defaults are ok for |
| 40 | * the ext2 filesystem. | 40 | * the ext2 filesystem. |
| 41 | */ | 41 | */ |
| 42 | struct file_operations ext2_file_operations = { | 42 | const struct file_operations ext2_file_operations = { |
| 43 | .llseek = generic_file_llseek, | 43 | .llseek = generic_file_llseek, |
| 44 | .read = generic_file_read, | 44 | .read = generic_file_read, |
| 45 | .write = generic_file_write, | 45 | .write = generic_file_write, |
| @@ -56,7 +56,7 @@ struct file_operations ext2_file_operations = { | |||
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | #ifdef CONFIG_EXT2_FS_XIP | 58 | #ifdef CONFIG_EXT2_FS_XIP |
| 59 | struct file_operations ext2_xip_file_operations = { | 59 | const struct file_operations ext2_xip_file_operations = { |
| 60 | .llseek = generic_file_llseek, | 60 | .llseek = generic_file_llseek, |
| 61 | .read = xip_file_read, | 61 | .read = xip_file_read, |
| 62 | .write = xip_file_write, | 62 | .write = xip_file_write, |
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 38bd3f6ec147..f37528ed222e 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
| @@ -39,7 +39,7 @@ static int ext3_dx_readdir(struct file * filp, | |||
| 39 | static int ext3_release_dir (struct inode * inode, | 39 | static int ext3_release_dir (struct inode * inode, |
| 40 | struct file * filp); | 40 | struct file * filp); |
| 41 | 41 | ||
| 42 | struct file_operations ext3_dir_operations = { | 42 | const struct file_operations ext3_dir_operations = { |
| 43 | .llseek = generic_file_llseek, | 43 | .llseek = generic_file_llseek, |
| 44 | .read = generic_read_dir, | 44 | .read = generic_read_dir, |
| 45 | .readdir = ext3_readdir, /* we take BKL. needed?*/ | 45 | .readdir = ext3_readdir, /* we take BKL. needed?*/ |
diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 59098ea56711..783a796220bb 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c | |||
| @@ -105,7 +105,7 @@ force_commit: | |||
| 105 | return ret; | 105 | return ret; |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | struct file_operations ext3_file_operations = { | 108 | const struct file_operations ext3_file_operations = { |
| 109 | .llseek = generic_file_llseek, | 109 | .llseek = generic_file_llseek, |
| 110 | .read = do_sync_read, | 110 | .read = do_sync_read, |
| 111 | .write = do_sync_write, | 111 | .write = do_sync_write, |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 4095bc149eb1..698b85bb1dd4 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
| @@ -741,7 +741,7 @@ static int fat_dir_ioctl(struct inode * inode, struct file * filp, | |||
| 741 | return ret; | 741 | return ret; |
| 742 | } | 742 | } |
| 743 | 743 | ||
| 744 | struct file_operations fat_dir_operations = { | 744 | const struct file_operations fat_dir_operations = { |
| 745 | .read = generic_read_dir, | 745 | .read = generic_read_dir, |
| 746 | .readdir = fat_readdir, | 746 | .readdir = fat_readdir, |
| 747 | .ioctl = fat_dir_ioctl, | 747 | .ioctl = fat_dir_ioctl, |
diff --git a/fs/fat/file.c b/fs/fat/file.c index 88aa1ae13f9f..1ee25232e6af 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
| @@ -112,7 +112,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, | |||
| 112 | } | 112 | } |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | struct file_operations fat_file_operations = { | 115 | const struct file_operations fat_file_operations = { |
| 116 | .llseek = generic_file_llseek, | 116 | .llseek = generic_file_llseek, |
| 117 | .read = do_sync_read, | 117 | .read = do_sync_read, |
| 118 | .write = do_sync_write, | 118 | .write = do_sync_write, |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 404bfc9f7385..c1ce284f8a94 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
| @@ -1435,9 +1435,6 @@ out_fail: | |||
| 1435 | 1435 | ||
| 1436 | EXPORT_SYMBOL_GPL(fat_fill_super); | 1436 | EXPORT_SYMBOL_GPL(fat_fill_super); |
| 1437 | 1437 | ||
| 1438 | int __init fat_cache_init(void); | ||
| 1439 | void fat_cache_destroy(void); | ||
| 1440 | |||
| 1441 | static int __init init_fat_fs(void) | 1438 | static int __init init_fat_fs(void) |
| 1442 | { | 1439 | { |
| 1443 | int err; | 1440 | int err; |
| @@ -145,6 +145,6 @@ err_nocleanup: | |||
| 145 | * is contain the open that then fills in the correct operations | 145 | * is contain the open that then fills in the correct operations |
| 146 | * depending on the access mode of the file... | 146 | * depending on the access mode of the file... |
| 147 | */ | 147 | */ |
| 148 | struct file_operations def_fifo_fops = { | 148 | const struct file_operations def_fifo_fops = { |
| 149 | .open = fifo_open, /* will set read or write pipe_fops */ | 149 | .open = fifo_open, /* will set read or write pipe_fops */ |
| 150 | }; | 150 | }; |
| @@ -373,6 +373,6 @@ static void __devinit fdtable_defer_list_init(int cpu) | |||
| 373 | void __init files_defer_init(void) | 373 | void __init files_defer_init(void) |
| 374 | { | 374 | { |
| 375 | int i; | 375 | int i; |
| 376 | for_each_cpu(i) | 376 | for_each_possible_cpu(i) |
| 377 | fdtable_defer_list_init(i); | 377 | fdtable_defer_list_init(i); |
| 378 | } | 378 | } |
diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index 927acf70c591..1cf1fe8466a2 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h | |||
| @@ -63,7 +63,7 @@ extern void vxfs_clear_inode(struct inode *); | |||
| 63 | 63 | ||
| 64 | /* vxfs_lookup.c */ | 64 | /* vxfs_lookup.c */ |
| 65 | extern struct inode_operations vxfs_dir_inode_ops; | 65 | extern struct inode_operations vxfs_dir_inode_ops; |
| 66 | extern struct file_operations vxfs_dir_operations; | 66 | extern const struct file_operations vxfs_dir_operations; |
| 67 | 67 | ||
| 68 | /* vxfs_olt.c */ | 68 | /* vxfs_olt.c */ |
| 69 | extern int vxfs_read_olt(struct super_block *, u_long); | 69 | extern int vxfs_read_olt(struct super_block *, u_long); |
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c index 554eb455722c..29cce456c7ce 100644 --- a/fs/freevxfs/vxfs_lookup.c +++ b/fs/freevxfs/vxfs_lookup.c | |||
| @@ -56,7 +56,7 @@ struct inode_operations vxfs_dir_inode_ops = { | |||
| 56 | .lookup = vxfs_lookup, | 56 | .lookup = vxfs_lookup, |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | struct file_operations vxfs_dir_operations = { | 59 | const struct file_operations vxfs_dir_operations = { |
| 60 | .readdir = vxfs_readdir, | 60 | .readdir = vxfs_readdir, |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 0c9a2ee54c91..23d1f52eb1b8 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
| @@ -922,7 +922,7 @@ static int fuse_dev_release(struct inode *inode, struct file *file) | |||
| 922 | return 0; | 922 | return 0; |
| 923 | } | 923 | } |
| 924 | 924 | ||
| 925 | struct file_operations fuse_dev_operations = { | 925 | const struct file_operations fuse_dev_operations = { |
| 926 | .owner = THIS_MODULE, | 926 | .owner = THIS_MODULE, |
| 927 | .llseek = no_llseek, | 927 | .llseek = no_llseek, |
| 928 | .read = fuse_dev_read, | 928 | .read = fuse_dev_read, |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index c72a8a97935c..256355b80256 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -1170,7 +1170,7 @@ static struct inode_operations fuse_dir_inode_operations = { | |||
| 1170 | .removexattr = fuse_removexattr, | 1170 | .removexattr = fuse_removexattr, |
| 1171 | }; | 1171 | }; |
| 1172 | 1172 | ||
| 1173 | static struct file_operations fuse_dir_operations = { | 1173 | static const struct file_operations fuse_dir_operations = { |
| 1174 | .llseek = generic_file_llseek, | 1174 | .llseek = generic_file_llseek, |
| 1175 | .read = generic_read_dir, | 1175 | .read = generic_read_dir, |
| 1176 | .readdir = fuse_readdir, | 1176 | .readdir = fuse_readdir, |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 6f05379b0a0d..975f2697e866 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 14 | 14 | ||
| 15 | static struct file_operations fuse_direct_io_file_operations; | 15 | static const struct file_operations fuse_direct_io_file_operations; |
| 16 | 16 | ||
| 17 | static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | 17 | static int fuse_send_open(struct inode *inode, struct file *file, int isdir, |
| 18 | struct fuse_open_out *outargp) | 18 | struct fuse_open_out *outargp) |
| @@ -611,7 +611,7 @@ static int fuse_set_page_dirty(struct page *page) | |||
| 611 | return 0; | 611 | return 0; |
| 612 | } | 612 | } |
| 613 | 613 | ||
| 614 | static struct file_operations fuse_file_operations = { | 614 | static const struct file_operations fuse_file_operations = { |
| 615 | .llseek = generic_file_llseek, | 615 | .llseek = generic_file_llseek, |
| 616 | .read = generic_file_read, | 616 | .read = generic_file_read, |
| 617 | .write = generic_file_write, | 617 | .write = generic_file_write, |
| @@ -623,7 +623,7 @@ static struct file_operations fuse_file_operations = { | |||
| 623 | .sendfile = generic_file_sendfile, | 623 | .sendfile = generic_file_sendfile, |
| 624 | }; | 624 | }; |
| 625 | 625 | ||
| 626 | static struct file_operations fuse_direct_io_file_operations = { | 626 | static const struct file_operations fuse_direct_io_file_operations = { |
| 627 | .llseek = generic_file_llseek, | 627 | .llseek = generic_file_llseek, |
| 628 | .read = fuse_direct_read, | 628 | .read = fuse_direct_read, |
| 629 | .write = fuse_direct_write, | 629 | .write = fuse_direct_write, |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 4a83adfec968..a16a04fcf41e 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
| @@ -346,7 +346,7 @@ static inline u64 get_node_id(struct inode *inode) | |||
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | /** Device operations */ | 348 | /** Device operations */ |
| 349 | extern struct file_operations fuse_dev_operations; | 349 | extern const struct file_operations fuse_dev_operations; |
| 350 | 350 | ||
| 351 | /** | 351 | /** |
| 352 | * This is the single global spinlock which protects FUSE's structures | 352 | * This is the single global spinlock which protects FUSE's structures |
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c index 534e5a7480ef..7cd8cc03aea7 100644 --- a/fs/hfs/dir.c +++ b/fs/hfs/dir.c | |||
| @@ -313,7 +313,7 @@ static int hfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 313 | return res; | 313 | return res; |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | struct file_operations hfs_dir_operations = { | 316 | const struct file_operations hfs_dir_operations = { |
| 317 | .read = generic_read_dir, | 317 | .read = generic_read_dir, |
| 318 | .readdir = hfs_readdir, | 318 | .readdir = hfs_readdir, |
| 319 | .llseek = generic_file_llseek, | 319 | .llseek = generic_file_llseek, |
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index 18ce47ab1b71..3ed8663a8db1 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h | |||
| @@ -169,7 +169,7 @@ extern int hfs_cat_move(u32, struct inode *, struct qstr *, | |||
| 169 | extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qstr *); | 169 | extern void hfs_cat_build_key(struct super_block *, btree_key *, u32, struct qstr *); |
| 170 | 170 | ||
| 171 | /* dir.c */ | 171 | /* dir.c */ |
| 172 | extern struct file_operations hfs_dir_operations; | 172 | extern const struct file_operations hfs_dir_operations; |
| 173 | extern struct inode_operations hfs_dir_inode_operations; | 173 | extern struct inode_operations hfs_dir_inode_operations; |
| 174 | 174 | ||
| 175 | /* extent.c */ | 175 | /* extent.c */ |
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 2c564701724f..2d4ced22201b 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | #include "hfs_fs.h" | 17 | #include "hfs_fs.h" |
| 18 | #include "btree.h" | 18 | #include "btree.h" |
| 19 | 19 | ||
| 20 | static struct file_operations hfs_file_operations; | 20 | static const struct file_operations hfs_file_operations; |
| 21 | static struct inode_operations hfs_file_inode_operations; | 21 | static struct inode_operations hfs_file_inode_operations; |
| 22 | 22 | ||
| 23 | /*================ Variable-like macros ================*/ | 23 | /*================ Variable-like macros ================*/ |
| @@ -601,7 +601,7 @@ int hfs_inode_setattr(struct dentry *dentry, struct iattr * attr) | |||
| 601 | } | 601 | } |
| 602 | 602 | ||
| 603 | 603 | ||
| 604 | static struct file_operations hfs_file_operations = { | 604 | static const struct file_operations hfs_file_operations = { |
| 605 | .llseek = generic_file_llseek, | 605 | .llseek = generic_file_llseek, |
| 606 | .read = generic_file_read, | 606 | .read = generic_file_read, |
| 607 | .write = generic_file_write, | 607 | .write = generic_file_write, |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 01a6fe3a395c..1f9ece0de326 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
| @@ -483,7 +483,7 @@ struct inode_operations hfsplus_dir_inode_operations = { | |||
| 483 | .rename = hfsplus_rename, | 483 | .rename = hfsplus_rename, |
| 484 | }; | 484 | }; |
| 485 | 485 | ||
| 486 | struct file_operations hfsplus_dir_operations = { | 486 | const struct file_operations hfsplus_dir_operations = { |
| 487 | .read = generic_read_dir, | 487 | .read = generic_read_dir, |
| 488 | .readdir = hfsplus_readdir, | 488 | .readdir = hfsplus_readdir, |
| 489 | .ioctl = hfsplus_ioctl, | 489 | .ioctl = hfsplus_ioctl, |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 9fbe4d2aeece..acf66dba3e01 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
| @@ -280,7 +280,7 @@ static struct inode_operations hfsplus_file_inode_operations = { | |||
| 280 | .listxattr = hfsplus_listxattr, | 280 | .listxattr = hfsplus_listxattr, |
| 281 | }; | 281 | }; |
| 282 | 282 | ||
| 283 | static struct file_operations hfsplus_file_operations = { | 283 | static const struct file_operations hfsplus_file_operations = { |
| 284 | .llseek = generic_file_llseek, | 284 | .llseek = generic_file_llseek, |
| 285 | .read = generic_file_read, | 285 | .read = generic_file_read, |
| 286 | .write = generic_file_write, | 286 | .write = generic_file_write, |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index b3ad0bd0312f..bf0f8e16e433 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
| @@ -384,7 +384,7 @@ int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
| 384 | return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync); | 384 | return fsync_file(HOSTFS_I(dentry->d_inode)->fd, datasync); |
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | static struct file_operations hostfs_file_fops = { | 387 | static const struct file_operations hostfs_file_fops = { |
| 388 | .llseek = generic_file_llseek, | 388 | .llseek = generic_file_llseek, |
| 389 | .read = generic_file_read, | 389 | .read = generic_file_read, |
| 390 | .sendfile = generic_file_sendfile, | 390 | .sendfile = generic_file_sendfile, |
| @@ -399,7 +399,7 @@ static struct file_operations hostfs_file_fops = { | |||
| 399 | .fsync = hostfs_fsync, | 399 | .fsync = hostfs_fsync, |
| 400 | }; | 400 | }; |
| 401 | 401 | ||
| 402 | static struct file_operations hostfs_dir_fops = { | 402 | static const struct file_operations hostfs_dir_fops = { |
| 403 | .llseek = generic_file_llseek, | 403 | .llseek = generic_file_llseek, |
| 404 | .readdir = hostfs_readdir, | 404 | .readdir = hostfs_readdir, |
| 405 | .read = generic_read_dir, | 405 | .read = generic_read_dir, |
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index b97809deba66..23b7cee72123 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c | |||
| @@ -360,7 +360,6 @@ int do_statfs(char *root, long *bsize_out, long long *blocks_out, | |||
| 360 | spare_out[2] = buf.f_spare[2]; | 360 | spare_out[2] = buf.f_spare[2]; |
| 361 | spare_out[3] = buf.f_spare[3]; | 361 | spare_out[3] = buf.f_spare[3]; |
| 362 | spare_out[4] = buf.f_spare[4]; | 362 | spare_out[4] = buf.f_spare[4]; |
| 363 | spare_out[5] = buf.f_spare[5]; | ||
| 364 | return(0); | 363 | return(0); |
| 365 | } | 364 | } |
| 366 | 365 | ||
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 5591f9623aa2..ecc9180645ae 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c | |||
| @@ -310,7 +310,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name | |||
| 310 | return ERR_PTR(-ENOENT); | 310 | return ERR_PTR(-ENOENT); |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | struct file_operations hpfs_dir_ops = | 313 | const struct file_operations hpfs_dir_ops = |
| 314 | { | 314 | { |
| 315 | .llseek = hpfs_dir_lseek, | 315 | .llseek = hpfs_dir_lseek, |
| 316 | .read = generic_read_dir, | 316 | .read = generic_read_dir, |
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 7c995ac4081b..d3b9fffe45a1 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c | |||
| @@ -119,7 +119,7 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf, | |||
| 119 | return retval; | 119 | return retval; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | struct file_operations hpfs_file_ops = | 122 | const struct file_operations hpfs_file_ops = |
| 123 | { | 123 | { |
| 124 | .llseek = generic_file_llseek, | 124 | .llseek = generic_file_llseek, |
| 125 | .read = generic_file_read, | 125 | .read = generic_file_read, |
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 4c6473ab3b34..29b7a3e55173 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
| @@ -240,7 +240,7 @@ void hpfs_set_dentry_operations(struct dentry *); | |||
| 240 | /* dir.c */ | 240 | /* dir.c */ |
| 241 | 241 | ||
| 242 | struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *); | 242 | struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *); |
| 243 | extern struct file_operations hpfs_dir_ops; | 243 | extern const struct file_operations hpfs_dir_ops; |
| 244 | 244 | ||
| 245 | /* dnode.c */ | 245 | /* dnode.c */ |
| 246 | 246 | ||
| @@ -266,7 +266,7 @@ void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int); | |||
| 266 | /* file.c */ | 266 | /* file.c */ |
| 267 | 267 | ||
| 268 | int hpfs_file_fsync(struct file *, struct dentry *, int); | 268 | int hpfs_file_fsync(struct file *, struct dentry *, int); |
| 269 | extern struct file_operations hpfs_file_ops; | 269 | extern const struct file_operations hpfs_file_ops; |
| 270 | extern struct inode_operations hpfs_file_iops; | 270 | extern struct inode_operations hpfs_file_iops; |
| 271 | extern struct address_space_operations hpfs_aops; | 271 | extern struct address_space_operations hpfs_aops; |
| 272 | 272 | ||
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index a44dc5897399..2ba20cdb5baa 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c | |||
| @@ -558,7 +558,7 @@ static loff_t hppfs_llseek(struct file *file, loff_t off, int where) | |||
| 558 | return(default_llseek(file, off, where)); | 558 | return(default_llseek(file, off, where)); |
| 559 | } | 559 | } |
| 560 | 560 | ||
| 561 | static struct file_operations hppfs_file_fops = { | 561 | static const struct file_operations hppfs_file_fops = { |
| 562 | .owner = NULL, | 562 | .owner = NULL, |
| 563 | .llseek = hppfs_llseek, | 563 | .llseek = hppfs_llseek, |
| 564 | .read = hppfs_read, | 564 | .read = hppfs_read, |
| @@ -609,7 +609,7 @@ static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
| 609 | return(0); | 609 | return(0); |
| 610 | } | 610 | } |
| 611 | 611 | ||
| 612 | static struct file_operations hppfs_dir_fops = { | 612 | static const struct file_operations hppfs_dir_fops = { |
| 613 | .owner = NULL, | 613 | .owner = NULL, |
| 614 | .readdir = hppfs_readdir, | 614 | .readdir = hppfs_readdir, |
| 615 | .open = hppfs_dir_open, | 615 | .open = hppfs_dir_open, |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 25fa8bba8cb5..3a5b4e923455 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | static struct super_operations hugetlbfs_ops; | 36 | static struct super_operations hugetlbfs_ops; |
| 37 | static struct address_space_operations hugetlbfs_aops; | 37 | static struct address_space_operations hugetlbfs_aops; |
| 38 | struct file_operations hugetlbfs_file_operations; | 38 | const struct file_operations hugetlbfs_file_operations; |
| 39 | static struct inode_operations hugetlbfs_dir_inode_operations; | 39 | static struct inode_operations hugetlbfs_dir_inode_operations; |
| 40 | static struct inode_operations hugetlbfs_inode_operations; | 40 | static struct inode_operations hugetlbfs_inode_operations; |
| 41 | 41 | ||
| @@ -566,7 +566,7 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) | |||
| 566 | inode_init_once(&ei->vfs_inode); | 566 | inode_init_once(&ei->vfs_inode); |
| 567 | } | 567 | } |
| 568 | 568 | ||
| 569 | struct file_operations hugetlbfs_file_operations = { | 569 | const struct file_operations hugetlbfs_file_operations = { |
| 570 | .mmap = hugetlbfs_file_mmap, | 570 | .mmap = hugetlbfs_file_mmap, |
| 571 | .fsync = simple_sync_file, | 571 | .fsync = simple_sync_file, |
| 572 | .get_unmapped_area = hugetlb_get_unmapped_area, | 572 | .get_unmapped_area = hugetlb_get_unmapped_area, |
diff --git a/fs/inode.c b/fs/inode.c index 1fddf2803af8..32b7c3375021 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -104,7 +104,7 @@ static struct inode *alloc_inode(struct super_block *sb) | |||
| 104 | { | 104 | { |
| 105 | static struct address_space_operations empty_aops; | 105 | static struct address_space_operations empty_aops; |
| 106 | static struct inode_operations empty_iops; | 106 | static struct inode_operations empty_iops; |
| 107 | static struct file_operations empty_fops; | 107 | static const struct file_operations empty_fops; |
| 108 | struct inode *inode; | 108 | struct inode *inode; |
| 109 | 109 | ||
| 110 | if (sb->s_op->alloc_inode) | 110 | if (sb->s_op->alloc_inode) |
diff --git a/fs/inotify.c b/fs/inotify.c index f48a3dae0712..367c487c014b 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
| @@ -920,7 +920,7 @@ static long inotify_ioctl(struct file *file, unsigned int cmd, | |||
| 920 | return ret; | 920 | return ret; |
| 921 | } | 921 | } |
| 922 | 922 | ||
| 923 | static struct file_operations inotify_fops = { | 923 | static const struct file_operations inotify_fops = { |
| 924 | .poll = inotify_poll, | 924 | .poll = inotify_poll, |
| 925 | .read = inotify_read, | 925 | .read = inotify_read, |
| 926 | .release = inotify_release, | 926 | .release = inotify_release, |
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 7901ac9f97ab..5440ea292c69 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | static int isofs_readdir(struct file *, void *, filldir_t); | 17 | static int isofs_readdir(struct file *, void *, filldir_t); |
| 18 | 18 | ||
| 19 | struct file_operations isofs_dir_operations = | 19 | const struct file_operations isofs_dir_operations = |
| 20 | { | 20 | { |
| 21 | .read = generic_read_dir, | 21 | .read = generic_read_dir, |
| 22 | .readdir = isofs_readdir, | 22 | .readdir = isofs_readdir, |
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index 439a19b1bf3e..b87ba066f5e7 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h | |||
| @@ -175,6 +175,6 @@ isofs_normalize_block_and_offset(struct iso_directory_record* de, | |||
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | extern struct inode_operations isofs_dir_inode_operations; | 177 | extern struct inode_operations isofs_dir_inode_operations; |
| 178 | extern struct file_operations isofs_dir_operations; | 178 | extern const struct file_operations isofs_dir_operations; |
| 179 | extern struct address_space_operations isofs_symlink_aops; | 179 | extern struct address_space_operations isofs_symlink_aops; |
| 180 | extern struct export_operations isofs_export_ops; | 180 | extern struct export_operations isofs_export_ops; |
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 5a4519e834da..020cc097c539 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c | |||
| @@ -55,9 +55,9 @@ | |||
| 55 | static int jffs_remove(struct inode *dir, struct dentry *dentry, int type); | 55 | static int jffs_remove(struct inode *dir, struct dentry *dentry, int type); |
| 56 | 56 | ||
| 57 | static struct super_operations jffs_ops; | 57 | static struct super_operations jffs_ops; |
| 58 | static struct file_operations jffs_file_operations; | 58 | static const struct file_operations jffs_file_operations; |
| 59 | static struct inode_operations jffs_file_inode_operations; | 59 | static struct inode_operations jffs_file_inode_operations; |
| 60 | static struct file_operations jffs_dir_operations; | 60 | static const struct file_operations jffs_dir_operations; |
| 61 | static struct inode_operations jffs_dir_inode_operations; | 61 | static struct inode_operations jffs_dir_inode_operations; |
| 62 | static struct address_space_operations jffs_address_operations; | 62 | static struct address_space_operations jffs_address_operations; |
| 63 | 63 | ||
| @@ -1629,7 +1629,7 @@ static int jffs_fsync(struct file *f, struct dentry *d, int datasync) | |||
| 1629 | } | 1629 | } |
| 1630 | 1630 | ||
| 1631 | 1631 | ||
| 1632 | static struct file_operations jffs_file_operations = | 1632 | static const struct file_operations jffs_file_operations = |
| 1633 | { | 1633 | { |
| 1634 | .open = generic_file_open, | 1634 | .open = generic_file_open, |
| 1635 | .llseek = generic_file_llseek, | 1635 | .llseek = generic_file_llseek, |
| @@ -1649,7 +1649,7 @@ static struct inode_operations jffs_file_inode_operations = | |||
| 1649 | }; | 1649 | }; |
| 1650 | 1650 | ||
| 1651 | 1651 | ||
| 1652 | static struct file_operations jffs_dir_operations = | 1652 | static const struct file_operations jffs_dir_operations = |
| 1653 | { | 1653 | { |
| 1654 | .readdir = jffs_readdir, | 1654 | .readdir = jffs_readdir, |
| 1655 | }; | 1655 | }; |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index a7bf9cb2567f..8bc7a5018e40 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
| @@ -37,7 +37,7 @@ static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t); | |||
| 37 | static int jffs2_rename (struct inode *, struct dentry *, | 37 | static int jffs2_rename (struct inode *, struct dentry *, |
| 38 | struct inode *, struct dentry *); | 38 | struct inode *, struct dentry *); |
| 39 | 39 | ||
| 40 | struct file_operations jffs2_dir_operations = | 40 | const struct file_operations jffs2_dir_operations = |
| 41 | { | 41 | { |
| 42 | .read = generic_read_dir, | 42 | .read = generic_read_dir, |
| 43 | .readdir = jffs2_readdir, | 43 | .readdir = jffs2_readdir, |
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 935f273dc57b..9f4171213e58 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c | |||
| @@ -38,7 +38,7 @@ int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync) | |||
| 38 | return 0; | 38 | return 0; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | struct file_operations jffs2_file_operations = | 41 | const struct file_operations jffs2_file_operations = |
| 42 | { | 42 | { |
| 43 | .llseek = generic_file_llseek, | 43 | .llseek = generic_file_llseek, |
| 44 | .open = generic_file_open, | 44 | .open = generic_file_open, |
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 59e7a393200c..d307cf548625 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h | |||
| @@ -159,11 +159,11 @@ void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c); | |||
| 159 | void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); | 159 | void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); |
| 160 | 160 | ||
| 161 | /* dir.c */ | 161 | /* dir.c */ |
| 162 | extern struct file_operations jffs2_dir_operations; | 162 | extern const struct file_operations jffs2_dir_operations; |
| 163 | extern struct inode_operations jffs2_dir_inode_operations; | 163 | extern struct inode_operations jffs2_dir_inode_operations; |
| 164 | 164 | ||
| 165 | /* file.c */ | 165 | /* file.c */ |
| 166 | extern struct file_operations jffs2_file_operations; | 166 | extern const struct file_operations jffs2_file_operations; |
| 167 | extern struct inode_operations jffs2_file_inode_operations; | 167 | extern struct inode_operations jffs2_file_inode_operations; |
| 168 | extern struct address_space_operations jffs2_file_address_operations; | 168 | extern struct address_space_operations jffs2_file_address_operations; |
| 169 | int jffs2_fsync(struct file *, struct dentry *, int); | 169 | int jffs2_fsync(struct file *, struct dentry *, int); |
diff --git a/fs/jfs/file.c b/fs/jfs/file.c index e1ac6e497e2b..1c9745be5ada 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c | |||
| @@ -100,7 +100,7 @@ struct inode_operations jfs_file_inode_operations = { | |||
| 100 | #endif | 100 | #endif |
| 101 | }; | 101 | }; |
| 102 | 102 | ||
| 103 | struct file_operations jfs_file_operations = { | 103 | const struct file_operations jfs_file_operations = { |
| 104 | .open = jfs_open, | 104 | .open = jfs_open, |
| 105 | .llseek = generic_file_llseek, | 105 | .llseek = generic_file_llseek, |
| 106 | .write = generic_file_write, | 106 | .write = generic_file_write, |
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h index 095d471b9f9a..c30072674464 100644 --- a/fs/jfs/jfs_inode.h +++ b/fs/jfs/jfs_inode.h | |||
| @@ -35,9 +35,9 @@ extern void jfs_set_inode_flags(struct inode *); | |||
| 35 | 35 | ||
| 36 | extern struct address_space_operations jfs_aops; | 36 | extern struct address_space_operations jfs_aops; |
| 37 | extern struct inode_operations jfs_dir_inode_operations; | 37 | extern struct inode_operations jfs_dir_inode_operations; |
| 38 | extern struct file_operations jfs_dir_operations; | 38 | extern const struct file_operations jfs_dir_operations; |
| 39 | extern struct inode_operations jfs_file_inode_operations; | 39 | extern struct inode_operations jfs_file_inode_operations; |
| 40 | extern struct file_operations jfs_file_operations; | 40 | extern const struct file_operations jfs_file_operations; |
| 41 | extern struct inode_operations jfs_symlink_inode_operations; | 41 | extern struct inode_operations jfs_symlink_inode_operations; |
| 42 | extern struct dentry_operations jfs_ci_dentry_operations; | 42 | extern struct dentry_operations jfs_ci_dentry_operations; |
| 43 | #endif /* _H_JFS_INODE */ | 43 | #endif /* _H_JFS_INODE */ |
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 309cee575f7d..09ea03f62277 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c | |||
| @@ -1519,7 +1519,7 @@ struct inode_operations jfs_dir_inode_operations = { | |||
| 1519 | #endif | 1519 | #endif |
| 1520 | }; | 1520 | }; |
| 1521 | 1521 | ||
| 1522 | struct file_operations jfs_dir_operations = { | 1522 | const struct file_operations jfs_dir_operations = { |
| 1523 | .read = generic_read_dir, | 1523 | .read = generic_read_dir, |
| 1524 | .readdir = jfs_readdir, | 1524 | .readdir = jfs_readdir, |
| 1525 | .fsync = jfs_fsync, | 1525 | .fsync = jfs_fsync, |
diff --git a/fs/libfs.c b/fs/libfs.c index 4fdeaceb892c..7145ba7a48d0 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
| @@ -179,7 +179,7 @@ ssize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t | |||
| 179 | return -EISDIR; | 179 | return -EISDIR; |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | struct file_operations simple_dir_operations = { | 182 | const struct file_operations simple_dir_operations = { |
| 183 | .open = dcache_dir_open, | 183 | .open = dcache_dir_open, |
| 184 | .release = dcache_dir_close, | 184 | .release = dcache_dir_close, |
| 185 | .llseek = dcache_dir_lseek, | 185 | .llseek = dcache_dir_lseek, |
diff --git a/fs/mbcache.c b/fs/mbcache.c index 73e754fea2d8..e4fde1ab22cd 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c | |||
| @@ -311,7 +311,7 @@ fail: | |||
| 311 | /* | 311 | /* |
| 312 | * mb_cache_shrink() | 312 | * mb_cache_shrink() |
| 313 | * | 313 | * |
| 314 | * Removes all cache entires of a device from the cache. All cache entries | 314 | * Removes all cache entries of a device from the cache. All cache entries |
| 315 | * currently in use cannot be freed, and thus remain in the cache. All others | 315 | * currently in use cannot be freed, and thus remain in the cache. All others |
| 316 | * are freed. | 316 | * are freed. |
| 317 | * | 317 | * |
diff --git a/fs/minix/dir.c b/fs/minix/dir.c index 732502aabc05..69224d1fe043 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c | |||
| @@ -14,7 +14,7 @@ typedef struct minix_dir_entry minix_dirent; | |||
| 14 | 14 | ||
| 15 | static int minix_readdir(struct file *, void *, filldir_t); | 15 | static int minix_readdir(struct file *, void *, filldir_t); |
| 16 | 16 | ||
| 17 | struct file_operations minix_dir_operations = { | 17 | const struct file_operations minix_dir_operations = { |
| 18 | .read = generic_read_dir, | 18 | .read = generic_read_dir, |
| 19 | .readdir = minix_readdir, | 19 | .readdir = minix_readdir, |
| 20 | .fsync = minix_sync_file, | 20 | .fsync = minix_sync_file, |
diff --git a/fs/minix/file.c b/fs/minix/file.c index f1d77acb3f01..420b32882a10 100644 --- a/fs/minix/file.c +++ b/fs/minix/file.c | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | */ | 15 | */ |
| 16 | int minix_sync_file(struct file *, struct dentry *, int); | 16 | int minix_sync_file(struct file *, struct dentry *, int); |
| 17 | 17 | ||
| 18 | struct file_operations minix_file_operations = { | 18 | const struct file_operations minix_file_operations = { |
| 19 | .llseek = generic_file_llseek, | 19 | .llseek = generic_file_llseek, |
| 20 | .read = generic_file_read, | 20 | .read = generic_file_read, |
| 21 | .write = generic_file_write, | 21 | .write = generic_file_write, |
diff --git a/fs/minix/minix.h b/fs/minix/minix.h index e42a8bb89001..c55b77cdcc8e 100644 --- a/fs/minix/minix.h +++ b/fs/minix/minix.h | |||
| @@ -81,8 +81,8 @@ extern int minix_sync_file(struct file *, struct dentry *, int); | |||
| 81 | 81 | ||
| 82 | extern struct inode_operations minix_file_inode_operations; | 82 | extern struct inode_operations minix_file_inode_operations; |
| 83 | extern struct inode_operations minix_dir_inode_operations; | 83 | extern struct inode_operations minix_dir_inode_operations; |
| 84 | extern struct file_operations minix_file_operations; | 84 | extern const struct file_operations minix_file_operations; |
| 85 | extern struct file_operations minix_dir_operations; | 85 | extern const struct file_operations minix_dir_operations; |
| 86 | extern struct dentry_operations minix_dentry_operations; | 86 | extern struct dentry_operations minix_dentry_operations; |
| 87 | 87 | ||
| 88 | static inline struct minix_sb_info *minix_sb(struct super_block *sb) | 88 | static inline struct minix_sb_info *minix_sb(struct super_block *sb) |
diff --git a/fs/namei.c b/fs/namei.c index 98dc2e134362..22f6e8d16aa8 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -546,6 +546,22 @@ struct path { | |||
| 546 | struct dentry *dentry; | 546 | struct dentry *dentry; |
| 547 | }; | 547 | }; |
| 548 | 548 | ||
| 549 | static inline void dput_path(struct path *path, struct nameidata *nd) | ||
| 550 | { | ||
| 551 | dput(path->dentry); | ||
| 552 | if (path->mnt != nd->mnt) | ||
| 553 | mntput(path->mnt); | ||
| 554 | } | ||
| 555 | |||
| 556 | static inline void path_to_nameidata(struct path *path, struct nameidata *nd) | ||
| 557 | { | ||
| 558 | dput(nd->dentry); | ||
| 559 | if (nd->mnt != path->mnt) | ||
| 560 | mntput(nd->mnt); | ||
| 561 | nd->mnt = path->mnt; | ||
| 562 | nd->dentry = path->dentry; | ||
| 563 | } | ||
| 564 | |||
| 549 | static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) | 565 | static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) |
| 550 | { | 566 | { |
| 551 | int error; | 567 | int error; |
| @@ -555,8 +571,11 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata | |||
| 555 | touch_atime(path->mnt, dentry); | 571 | touch_atime(path->mnt, dentry); |
| 556 | nd_set_link(nd, NULL); | 572 | nd_set_link(nd, NULL); |
| 557 | 573 | ||
| 558 | if (path->mnt == nd->mnt) | 574 | if (path->mnt != nd->mnt) { |
| 559 | mntget(path->mnt); | 575 | path_to_nameidata(path, nd); |
| 576 | dget(dentry); | ||
| 577 | } | ||
| 578 | mntget(path->mnt); | ||
| 560 | cookie = dentry->d_inode->i_op->follow_link(dentry, nd); | 579 | cookie = dentry->d_inode->i_op->follow_link(dentry, nd); |
| 561 | error = PTR_ERR(cookie); | 580 | error = PTR_ERR(cookie); |
| 562 | if (!IS_ERR(cookie)) { | 581 | if (!IS_ERR(cookie)) { |
| @@ -573,22 +592,6 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata | |||
| 573 | return error; | 592 | return error; |
| 574 | } | 593 | } |
| 575 | 594 | ||
| 576 | static inline void dput_path(struct path *path, struct nameidata *nd) | ||
| 577 | { | ||
| 578 | dput(path->dentry); | ||
| 579 | if (path->mnt != nd->mnt) | ||
| 580 | mntput(path->mnt); | ||
| 581 | } | ||
| 582 | |||
| 583 | static inline void path_to_nameidata(struct path *path, struct nameidata *nd) | ||
| 584 | { | ||
| 585 | dput(nd->dentry); | ||
| 586 | if (nd->mnt != path->mnt) | ||
| 587 | mntput(nd->mnt); | ||
| 588 | nd->mnt = path->mnt; | ||
| 589 | nd->dentry = path->dentry; | ||
| 590 | } | ||
| 591 | |||
| 592 | /* | 595 | /* |
| 593 | * This limits recursive symlink follows to 8, while | 596 | * This limits recursive symlink follows to 8, while |
| 594 | * limiting consecutive symlinks to 40. | 597 | * limiting consecutive symlinks to 40. |
diff --git a/fs/namespace.c b/fs/namespace.c index e069a4c5e389..bf478addb852 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -459,9 +459,9 @@ int may_umount_tree(struct vfsmount *mnt) | |||
| 459 | spin_unlock(&vfsmount_lock); | 459 | spin_unlock(&vfsmount_lock); |
| 460 | 460 | ||
| 461 | if (actual_refs > minimum_refs) | 461 | if (actual_refs > minimum_refs) |
| 462 | return -EBUSY; | 462 | return 0; |
| 463 | 463 | ||
| 464 | return 0; | 464 | return 1; |
| 465 | } | 465 | } |
| 466 | 466 | ||
| 467 | EXPORT_SYMBOL(may_umount_tree); | 467 | EXPORT_SYMBOL(may_umount_tree); |
| @@ -481,10 +481,10 @@ EXPORT_SYMBOL(may_umount_tree); | |||
| 481 | */ | 481 | */ |
| 482 | int may_umount(struct vfsmount *mnt) | 482 | int may_umount(struct vfsmount *mnt) |
| 483 | { | 483 | { |
| 484 | int ret = 0; | 484 | int ret = 1; |
| 485 | spin_lock(&vfsmount_lock); | 485 | spin_lock(&vfsmount_lock); |
| 486 | if (propagate_mount_busy(mnt, 2)) | 486 | if (propagate_mount_busy(mnt, 2)) |
| 487 | ret = -EBUSY; | 487 | ret = 0; |
| 488 | spin_unlock(&vfsmount_lock); | 488 | spin_unlock(&vfsmount_lock); |
| 489 | return ret; | 489 | return ret; |
| 490 | } | 490 | } |
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c index cfd76f431dc0..f0860c602d8b 100644 --- a/fs/ncpfs/dir.c +++ b/fs/ncpfs/dir.c | |||
| @@ -49,7 +49,7 @@ extern int ncp_symlink(struct inode *, struct dentry *, const char *); | |||
| 49 | #define ncp_symlink NULL | 49 | #define ncp_symlink NULL |
| 50 | #endif | 50 | #endif |
| 51 | 51 | ||
| 52 | struct file_operations ncp_dir_operations = | 52 | const struct file_operations ncp_dir_operations = |
| 53 | { | 53 | { |
| 54 | .read = generic_read_dir, | 54 | .read = generic_read_dir, |
| 55 | .readdir = ncp_readdir, | 55 | .readdir = ncp_readdir, |
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index ebdad8f6398f..e6b7c67cf057 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c | |||
| @@ -283,7 +283,7 @@ static int ncp_release(struct inode *inode, struct file *file) { | |||
| 283 | return 0; | 283 | return 0; |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | struct file_operations ncp_file_operations = | 286 | const struct file_operations ncp_file_operations = |
| 287 | { | 287 | { |
| 288 | .llseek = remote_llseek, | 288 | .llseek = remote_llseek, |
| 289 | .read = ncp_file_read, | 289 | .read = ncp_file_read, |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 06c48b385c94..a23f34894167 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -54,7 +54,7 @@ static int nfs_rename(struct inode *, struct dentry *, | |||
| 54 | static int nfs_fsync_dir(struct file *, struct dentry *, int); | 54 | static int nfs_fsync_dir(struct file *, struct dentry *, int); |
| 55 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); | 55 | static loff_t nfs_llseek_dir(struct file *, loff_t, int); |
| 56 | 56 | ||
| 57 | struct file_operations nfs_dir_operations = { | 57 | const struct file_operations nfs_dir_operations = { |
| 58 | .llseek = nfs_llseek_dir, | 58 | .llseek = nfs_llseek_dir, |
| 59 | .read = generic_read_dir, | 59 | .read = generic_read_dir, |
| 60 | .readdir = nfs_readdir, | 60 | .readdir = nfs_readdir, |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index dee49a0cb995..f1df2c8d9259 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
| @@ -49,7 +49,7 @@ static int nfs_check_flags(int flags); | |||
| 49 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); | 49 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); |
| 50 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); | 50 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); |
| 51 | 51 | ||
| 52 | struct file_operations nfs_file_operations = { | 52 | const struct file_operations nfs_file_operations = { |
| 53 | .llseek = nfs_file_llseek, | 53 | .llseek = nfs_file_llseek, |
| 54 | .read = do_sync_read, | 54 | .read = do_sync_read, |
| 55 | .write = do_sync_write, | 55 | .write = do_sync_write, |
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 417ec02df44f..c340be0a3f59 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
| @@ -57,27 +57,17 @@ static int exp_verify_string(char *cp, int max); | |||
| 57 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) | 57 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) |
| 58 | static struct cache_head *expkey_table[EXPKEY_HASHMAX]; | 58 | static struct cache_head *expkey_table[EXPKEY_HASHMAX]; |
| 59 | 59 | ||
| 60 | static inline int svc_expkey_hash(struct svc_expkey *item) | 60 | static void expkey_put(struct kref *ref) |
| 61 | { | 61 | { |
| 62 | int hash = item->ek_fsidtype; | 62 | struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); |
| 63 | char * cp = (char*)item->ek_fsid; | ||
| 64 | int len = key_len(item->ek_fsidtype); | ||
| 65 | 63 | ||
| 66 | hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); | 64 | if (test_bit(CACHE_VALID, &key->h.flags) && |
| 67 | hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS); | 65 | !test_bit(CACHE_NEGATIVE, &key->h.flags)) { |
| 68 | return hash & EXPKEY_HASHMASK; | 66 | dput(key->ek_dentry); |
| 69 | } | 67 | mntput(key->ek_mnt); |
| 70 | |||
| 71 | void expkey_put(struct cache_head *item, struct cache_detail *cd) | ||
| 72 | { | ||
| 73 | if (cache_put(item, cd)) { | ||
| 74 | struct svc_expkey *key = container_of(item, struct svc_expkey, h); | ||
| 75 | if (test_bit(CACHE_VALID, &item->flags) && | ||
| 76 | !test_bit(CACHE_NEGATIVE, &item->flags)) | ||
| 77 | exp_put(key->ek_export); | ||
| 78 | auth_domain_put(key->ek_client); | ||
| 79 | kfree(key); | ||
| 80 | } | 68 | } |
| 69 | auth_domain_put(key->ek_client); | ||
| 70 | kfree(key); | ||
| 81 | } | 71 | } |
| 82 | 72 | ||
| 83 | static void expkey_request(struct cache_detail *cd, | 73 | static void expkey_request(struct cache_detail *cd, |
| @@ -95,7 +85,10 @@ static void expkey_request(struct cache_detail *cd, | |||
| 95 | (*bpp)[-1] = '\n'; | 85 | (*bpp)[-1] = '\n'; |
| 96 | } | 86 | } |
| 97 | 87 | ||
| 98 | static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int); | 88 | static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old); |
| 89 | static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *); | ||
| 90 | static struct cache_detail svc_expkey_cache; | ||
| 91 | |||
| 99 | static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | 92 | static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) |
| 100 | { | 93 | { |
| 101 | /* client fsidtype fsid [path] */ | 94 | /* client fsidtype fsid [path] */ |
| @@ -106,6 +99,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
| 106 | int fsidtype; | 99 | int fsidtype; |
| 107 | char *ep; | 100 | char *ep; |
| 108 | struct svc_expkey key; | 101 | struct svc_expkey key; |
| 102 | struct svc_expkey *ek; | ||
| 109 | 103 | ||
| 110 | if (mesg[mlen-1] != '\n') | 104 | if (mesg[mlen-1] != '\n') |
| 111 | return -EINVAL; | 105 | return -EINVAL; |
| @@ -150,40 +144,38 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
| 150 | key.ek_fsidtype = fsidtype; | 144 | key.ek_fsidtype = fsidtype; |
| 151 | memcpy(key.ek_fsid, buf, len); | 145 | memcpy(key.ek_fsid, buf, len); |
| 152 | 146 | ||
| 147 | ek = svc_expkey_lookup(&key); | ||
| 148 | err = -ENOMEM; | ||
| 149 | if (!ek) | ||
| 150 | goto out; | ||
| 151 | |||
| 153 | /* now we want a pathname, or empty meaning NEGATIVE */ | 152 | /* now we want a pathname, or empty meaning NEGATIVE */ |
| 153 | err = -EINVAL; | ||
| 154 | if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0) | 154 | if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0) |
| 155 | goto out; | 155 | goto out; |
| 156 | dprintk("Path seems to be <%s>\n", buf); | 156 | dprintk("Path seems to be <%s>\n", buf); |
| 157 | err = 0; | 157 | err = 0; |
| 158 | if (len == 0) { | 158 | if (len == 0) { |
| 159 | struct svc_expkey *ek; | ||
| 160 | set_bit(CACHE_NEGATIVE, &key.h.flags); | 159 | set_bit(CACHE_NEGATIVE, &key.h.flags); |
| 161 | ek = svc_expkey_lookup(&key, 1); | 160 | ek = svc_expkey_update(&key, ek); |
| 162 | if (ek) | 161 | if (ek) |
| 163 | expkey_put(&ek->h, &svc_expkey_cache); | 162 | cache_put(&ek->h, &svc_expkey_cache); |
| 163 | else err = -ENOMEM; | ||
| 164 | } else { | 164 | } else { |
| 165 | struct nameidata nd; | 165 | struct nameidata nd; |
| 166 | struct svc_expkey *ek; | ||
| 167 | struct svc_export *exp; | ||
| 168 | err = path_lookup(buf, 0, &nd); | 166 | err = path_lookup(buf, 0, &nd); |
| 169 | if (err) | 167 | if (err) |
| 170 | goto out; | 168 | goto out; |
| 171 | 169 | ||
| 172 | dprintk("Found the path %s\n", buf); | 170 | dprintk("Found the path %s\n", buf); |
| 173 | exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); | 171 | key.ek_mnt = nd.mnt; |
| 174 | 172 | key.ek_dentry = nd.dentry; | |
| 175 | err = -ENOENT; | ||
| 176 | if (!exp) | ||
| 177 | goto out_nd; | ||
| 178 | key.ek_export = exp; | ||
| 179 | dprintk("And found export\n"); | ||
| 180 | 173 | ||
| 181 | ek = svc_expkey_lookup(&key, 1); | 174 | ek = svc_expkey_update(&key, ek); |
| 182 | if (ek) | 175 | if (ek) |
| 183 | expkey_put(&ek->h, &svc_expkey_cache); | 176 | cache_put(&ek->h, &svc_expkey_cache); |
| 184 | exp_put(exp); | 177 | else |
| 185 | err = 0; | 178 | err = -ENOMEM; |
| 186 | out_nd: | ||
| 187 | path_release(&nd); | 179 | path_release(&nd); |
| 188 | } | 180 | } |
| 189 | cache_flush(); | 181 | cache_flush(); |
| @@ -214,35 +206,31 @@ static int expkey_show(struct seq_file *m, | |||
| 214 | if (test_bit(CACHE_VALID, &h->flags) && | 206 | if (test_bit(CACHE_VALID, &h->flags) && |
| 215 | !test_bit(CACHE_NEGATIVE, &h->flags)) { | 207 | !test_bit(CACHE_NEGATIVE, &h->flags)) { |
| 216 | seq_printf(m, " "); | 208 | seq_printf(m, " "); |
| 217 | seq_path(m, ek->ek_export->ex_mnt, ek->ek_export->ex_dentry, "\\ \t\n"); | 209 | seq_path(m, ek->ek_mnt, ek->ek_dentry, "\\ \t\n"); |
| 218 | } | 210 | } |
| 219 | seq_printf(m, "\n"); | 211 | seq_printf(m, "\n"); |
| 220 | return 0; | 212 | return 0; |
| 221 | } | 213 | } |
| 222 | |||
| 223 | struct cache_detail svc_expkey_cache = { | ||
| 224 | .owner = THIS_MODULE, | ||
| 225 | .hash_size = EXPKEY_HASHMAX, | ||
| 226 | .hash_table = expkey_table, | ||
| 227 | .name = "nfsd.fh", | ||
| 228 | .cache_put = expkey_put, | ||
| 229 | .cache_request = expkey_request, | ||
| 230 | .cache_parse = expkey_parse, | ||
| 231 | .cache_show = expkey_show, | ||
| 232 | }; | ||
| 233 | 214 | ||
| 234 | static inline int svc_expkey_match (struct svc_expkey *a, struct svc_expkey *b) | 215 | static inline int expkey_match (struct cache_head *a, struct cache_head *b) |
| 235 | { | 216 | { |
| 236 | if (a->ek_fsidtype != b->ek_fsidtype || | 217 | struct svc_expkey *orig = container_of(a, struct svc_expkey, h); |
| 237 | a->ek_client != b->ek_client || | 218 | struct svc_expkey *new = container_of(b, struct svc_expkey, h); |
| 238 | memcmp(a->ek_fsid, b->ek_fsid, key_len(a->ek_fsidtype)) != 0) | 219 | |
| 220 | if (orig->ek_fsidtype != new->ek_fsidtype || | ||
| 221 | orig->ek_client != new->ek_client || | ||
| 222 | memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0) | ||
| 239 | return 0; | 223 | return 0; |
| 240 | return 1; | 224 | return 1; |
| 241 | } | 225 | } |
| 242 | 226 | ||
| 243 | static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *item) | 227 | static inline void expkey_init(struct cache_head *cnew, |
| 228 | struct cache_head *citem) | ||
| 244 | { | 229 | { |
| 245 | cache_get(&item->ek_client->h); | 230 | struct svc_expkey *new = container_of(cnew, struct svc_expkey, h); |
| 231 | struct svc_expkey *item = container_of(citem, struct svc_expkey, h); | ||
| 232 | |||
| 233 | kref_get(&item->ek_client->ref); | ||
| 246 | new->ek_client = item->ek_client; | 234 | new->ek_client = item->ek_client; |
| 247 | new->ek_fsidtype = item->ek_fsidtype; | 235 | new->ek_fsidtype = item->ek_fsidtype; |
| 248 | new->ek_fsid[0] = item->ek_fsid[0]; | 236 | new->ek_fsid[0] = item->ek_fsid[0]; |
| @@ -250,39 +238,94 @@ static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *it | |||
| 250 | new->ek_fsid[2] = item->ek_fsid[2]; | 238 | new->ek_fsid[2] = item->ek_fsid[2]; |
| 251 | } | 239 | } |
| 252 | 240 | ||
| 253 | static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item) | 241 | static inline void expkey_update(struct cache_head *cnew, |
| 242 | struct cache_head *citem) | ||
| 243 | { | ||
| 244 | struct svc_expkey *new = container_of(cnew, struct svc_expkey, h); | ||
| 245 | struct svc_expkey *item = container_of(citem, struct svc_expkey, h); | ||
| 246 | |||
| 247 | new->ek_mnt = mntget(item->ek_mnt); | ||
| 248 | new->ek_dentry = dget(item->ek_dentry); | ||
| 249 | } | ||
| 250 | |||
| 251 | static struct cache_head *expkey_alloc(void) | ||
| 254 | { | 252 | { |
| 255 | cache_get(&item->ek_export->h); | 253 | struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL); |
| 256 | new->ek_export = item->ek_export; | 254 | if (i) |
| 255 | return &i->h; | ||
| 256 | else | ||
| 257 | return NULL; | ||
| 257 | } | 258 | } |
| 258 | 259 | ||
| 259 | static DefineSimpleCacheLookup(svc_expkey,0) /* no inplace updates */ | 260 | static struct cache_detail svc_expkey_cache = { |
| 261 | .owner = THIS_MODULE, | ||
| 262 | .hash_size = EXPKEY_HASHMAX, | ||
| 263 | .hash_table = expkey_table, | ||
| 264 | .name = "nfsd.fh", | ||
| 265 | .cache_put = expkey_put, | ||
| 266 | .cache_request = expkey_request, | ||
| 267 | .cache_parse = expkey_parse, | ||
| 268 | .cache_show = expkey_show, | ||
| 269 | .match = expkey_match, | ||
| 270 | .init = expkey_init, | ||
| 271 | .update = expkey_update, | ||
| 272 | .alloc = expkey_alloc, | ||
| 273 | }; | ||
| 260 | 274 | ||
| 261 | #define EXPORT_HASHBITS 8 | 275 | static struct svc_expkey * |
| 262 | #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) | 276 | svc_expkey_lookup(struct svc_expkey *item) |
| 263 | #define EXPORT_HASHMASK (EXPORT_HASHMAX -1) | 277 | { |
| 278 | struct cache_head *ch; | ||
| 279 | int hash = item->ek_fsidtype; | ||
| 280 | char * cp = (char*)item->ek_fsid; | ||
| 281 | int len = key_len(item->ek_fsidtype); | ||
| 264 | 282 | ||
| 265 | static struct cache_head *export_table[EXPORT_HASHMAX]; | 283 | hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); |
| 284 | hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS); | ||
| 285 | hash &= EXPKEY_HASHMASK; | ||
| 266 | 286 | ||
| 267 | static inline int svc_export_hash(struct svc_export *item) | 287 | ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h, |
| 288 | hash); | ||
| 289 | if (ch) | ||
| 290 | return container_of(ch, struct svc_expkey, h); | ||
| 291 | else | ||
| 292 | return NULL; | ||
| 293 | } | ||
| 294 | |||
| 295 | static struct svc_expkey * | ||
| 296 | svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) | ||
| 268 | { | 297 | { |
| 269 | int rv; | 298 | struct cache_head *ch; |
| 299 | int hash = new->ek_fsidtype; | ||
| 300 | char * cp = (char*)new->ek_fsid; | ||
| 301 | int len = key_len(new->ek_fsidtype); | ||
| 270 | 302 | ||
| 271 | rv = hash_ptr(item->ex_client, EXPORT_HASHBITS); | 303 | hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); |
| 272 | rv ^= hash_ptr(item->ex_dentry, EXPORT_HASHBITS); | 304 | hash ^= hash_ptr(new->ek_client, EXPKEY_HASHBITS); |
| 273 | rv ^= hash_ptr(item->ex_mnt, EXPORT_HASHBITS); | 305 | hash &= EXPKEY_HASHMASK; |
| 274 | return rv; | 306 | |
| 307 | ch = sunrpc_cache_update(&svc_expkey_cache, &new->h, | ||
| 308 | &old->h, hash); | ||
| 309 | if (ch) | ||
| 310 | return container_of(ch, struct svc_expkey, h); | ||
| 311 | else | ||
| 312 | return NULL; | ||
| 275 | } | 313 | } |
| 276 | 314 | ||
| 277 | void svc_export_put(struct cache_head *item, struct cache_detail *cd) | 315 | |
| 316 | #define EXPORT_HASHBITS 8 | ||
| 317 | #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) | ||
| 318 | #define EXPORT_HASHMASK (EXPORT_HASHMAX -1) | ||
| 319 | |||
| 320 | static struct cache_head *export_table[EXPORT_HASHMAX]; | ||
| 321 | |||
| 322 | static void svc_export_put(struct kref *ref) | ||
| 278 | { | 323 | { |
| 279 | if (cache_put(item, cd)) { | 324 | struct svc_export *exp = container_of(ref, struct svc_export, h.ref); |
| 280 | struct svc_export *exp = container_of(item, struct svc_export, h); | 325 | dput(exp->ex_dentry); |
| 281 | dput(exp->ex_dentry); | 326 | mntput(exp->ex_mnt); |
| 282 | mntput(exp->ex_mnt); | 327 | auth_domain_put(exp->ex_client); |
| 283 | auth_domain_put(exp->ex_client); | 328 | kfree(exp); |
| 284 | kfree(exp); | ||
| 285 | } | ||
| 286 | } | 329 | } |
| 287 | 330 | ||
| 288 | static void svc_export_request(struct cache_detail *cd, | 331 | static void svc_export_request(struct cache_detail *cd, |
| @@ -304,7 +347,9 @@ static void svc_export_request(struct cache_detail *cd, | |||
| 304 | (*bpp)[-1] = '\n'; | 347 | (*bpp)[-1] = '\n'; |
| 305 | } | 348 | } |
| 306 | 349 | ||
| 307 | static struct svc_export *svc_export_lookup(struct svc_export *, int); | 350 | static struct svc_export *svc_export_update(struct svc_export *new, |
| 351 | struct svc_export *old); | ||
| 352 | static struct svc_export *svc_export_lookup(struct svc_export *); | ||
| 308 | 353 | ||
| 309 | static int check_export(struct inode *inode, int flags) | 354 | static int check_export(struct inode *inode, int flags) |
| 310 | { | 355 | { |
| @@ -417,11 +462,16 @@ static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) | |||
| 417 | if (err) goto out; | 462 | if (err) goto out; |
| 418 | } | 463 | } |
| 419 | 464 | ||
| 420 | expp = svc_export_lookup(&exp, 1); | 465 | expp = svc_export_lookup(&exp); |
| 421 | if (expp) | 466 | if (expp) |
| 422 | exp_put(expp); | 467 | expp = svc_export_update(&exp, expp); |
| 423 | err = 0; | 468 | else |
| 469 | err = -ENOMEM; | ||
| 424 | cache_flush(); | 470 | cache_flush(); |
| 471 | if (expp == NULL) | ||
| 472 | err = -ENOMEM; | ||
| 473 | else | ||
| 474 | exp_put(expp); | ||
| 425 | out: | 475 | out: |
| 426 | if (nd.dentry) | 476 | if (nd.dentry) |
| 427 | path_release(&nd); | 477 | path_release(&nd); |
| @@ -455,6 +505,46 @@ static int svc_export_show(struct seq_file *m, | |||
| 455 | seq_puts(m, ")\n"); | 505 | seq_puts(m, ")\n"); |
| 456 | return 0; | 506 | return 0; |
| 457 | } | 507 | } |
| 508 | static int svc_export_match(struct cache_head *a, struct cache_head *b) | ||
| 509 | { | ||
| 510 | struct svc_export *orig = container_of(a, struct svc_export, h); | ||
| 511 | struct svc_export *new = container_of(b, struct svc_export, h); | ||
| 512 | return orig->ex_client == new->ex_client && | ||
| 513 | orig->ex_dentry == new->ex_dentry && | ||
| 514 | orig->ex_mnt == new->ex_mnt; | ||
| 515 | } | ||
| 516 | |||
| 517 | static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) | ||
| 518 | { | ||
| 519 | struct svc_export *new = container_of(cnew, struct svc_export, h); | ||
| 520 | struct svc_export *item = container_of(citem, struct svc_export, h); | ||
| 521 | |||
| 522 | kref_get(&item->ex_client->ref); | ||
| 523 | new->ex_client = item->ex_client; | ||
| 524 | new->ex_dentry = dget(item->ex_dentry); | ||
| 525 | new->ex_mnt = mntget(item->ex_mnt); | ||
| 526 | } | ||
| 527 | |||
| 528 | static void export_update(struct cache_head *cnew, struct cache_head *citem) | ||
| 529 | { | ||
| 530 | struct svc_export *new = container_of(cnew, struct svc_export, h); | ||
| 531 | struct svc_export *item = container_of(citem, struct svc_export, h); | ||
| 532 | |||
| 533 | new->ex_flags = item->ex_flags; | ||
| 534 | new->ex_anon_uid = item->ex_anon_uid; | ||
| 535 | new->ex_anon_gid = item->ex_anon_gid; | ||
| 536 | new->ex_fsid = item->ex_fsid; | ||
| 537 | } | ||
| 538 | |||
| 539 | static struct cache_head *svc_export_alloc(void) | ||
| 540 | { | ||
| 541 | struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL); | ||
| 542 | if (i) | ||
| 543 | return &i->h; | ||
| 544 | else | ||
| 545 | return NULL; | ||
| 546 | } | ||
| 547 | |||
| 458 | struct cache_detail svc_export_cache = { | 548 | struct cache_detail svc_export_cache = { |
| 459 | .owner = THIS_MODULE, | 549 | .owner = THIS_MODULE, |
| 460 | .hash_size = EXPORT_HASHMAX, | 550 | .hash_size = EXPORT_HASHMAX, |
| @@ -464,34 +554,49 @@ struct cache_detail svc_export_cache = { | |||
| 464 | .cache_request = svc_export_request, | 554 | .cache_request = svc_export_request, |
| 465 | .cache_parse = svc_export_parse, | 555 | .cache_parse = svc_export_parse, |
| 466 | .cache_show = svc_export_show, | 556 | .cache_show = svc_export_show, |
| 557 | .match = svc_export_match, | ||
| 558 | .init = svc_export_init, | ||
| 559 | .update = export_update, | ||
| 560 | .alloc = svc_export_alloc, | ||
| 467 | }; | 561 | }; |
| 468 | 562 | ||
| 469 | static inline int svc_export_match(struct svc_export *a, struct svc_export *b) | 563 | static struct svc_export * |
| 564 | svc_export_lookup(struct svc_export *exp) | ||
| 470 | { | 565 | { |
| 471 | return a->ex_client == b->ex_client && | 566 | struct cache_head *ch; |
| 472 | a->ex_dentry == b->ex_dentry && | 567 | int hash; |
| 473 | a->ex_mnt == b->ex_mnt; | 568 | hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS); |
| 474 | } | 569 | hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS); |
| 475 | static inline void svc_export_init(struct svc_export *new, struct svc_export *item) | 570 | hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS); |
| 476 | { | 571 | |
| 477 | cache_get(&item->ex_client->h); | 572 | ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h, |
| 478 | new->ex_client = item->ex_client; | 573 | hash); |
| 479 | new->ex_dentry = dget(item->ex_dentry); | 574 | if (ch) |
| 480 | new->ex_mnt = mntget(item->ex_mnt); | 575 | return container_of(ch, struct svc_export, h); |
| 576 | else | ||
| 577 | return NULL; | ||
| 481 | } | 578 | } |
| 482 | 579 | ||
| 483 | static inline void svc_export_update(struct svc_export *new, struct svc_export *item) | 580 | static struct svc_export * |
| 581 | svc_export_update(struct svc_export *new, struct svc_export *old) | ||
| 484 | { | 582 | { |
| 485 | new->ex_flags = item->ex_flags; | 583 | struct cache_head *ch; |
| 486 | new->ex_anon_uid = item->ex_anon_uid; | 584 | int hash; |
| 487 | new->ex_anon_gid = item->ex_anon_gid; | 585 | hash = hash_ptr(old->ex_client, EXPORT_HASHBITS); |
| 488 | new->ex_fsid = item->ex_fsid; | 586 | hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS); |
| 587 | hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS); | ||
| 588 | |||
| 589 | ch = sunrpc_cache_update(&svc_export_cache, &new->h, | ||
| 590 | &old->h, | ||
| 591 | hash); | ||
| 592 | if (ch) | ||
| 593 | return container_of(ch, struct svc_export, h); | ||
| 594 | else | ||
| 595 | return NULL; | ||
| 489 | } | 596 | } |
| 490 | 597 | ||
| 491 | static DefineSimpleCacheLookup(svc_export,1) /* allow inplace updates */ | ||
| 492 | 598 | ||
| 493 | 599 | static struct svc_expkey * | |
| 494 | struct svc_expkey * | ||
| 495 | exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) | 600 | exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) |
| 496 | { | 601 | { |
| 497 | struct svc_expkey key, *ek; | 602 | struct svc_expkey key, *ek; |
| @@ -504,7 +609,7 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) | |||
| 504 | key.ek_fsidtype = fsid_type; | 609 | key.ek_fsidtype = fsid_type; |
| 505 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); | 610 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); |
| 506 | 611 | ||
| 507 | ek = svc_expkey_lookup(&key, 0); | 612 | ek = svc_expkey_lookup(&key); |
| 508 | if (ek != NULL) | 613 | if (ek != NULL) |
| 509 | if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) | 614 | if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) |
| 510 | ek = ERR_PTR(err); | 615 | ek = ERR_PTR(err); |
| @@ -519,13 +624,16 @@ static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv, | |||
| 519 | key.ek_client = clp; | 624 | key.ek_client = clp; |
| 520 | key.ek_fsidtype = fsid_type; | 625 | key.ek_fsidtype = fsid_type; |
| 521 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); | 626 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); |
| 522 | key.ek_export = exp; | 627 | key.ek_mnt = exp->ex_mnt; |
| 628 | key.ek_dentry = exp->ex_dentry; | ||
| 523 | key.h.expiry_time = NEVER; | 629 | key.h.expiry_time = NEVER; |
| 524 | key.h.flags = 0; | 630 | key.h.flags = 0; |
| 525 | 631 | ||
| 526 | ek = svc_expkey_lookup(&key, 1); | 632 | ek = svc_expkey_lookup(&key); |
| 633 | if (ek) | ||
| 634 | ek = svc_expkey_update(&key,ek); | ||
| 527 | if (ek) { | 635 | if (ek) { |
| 528 | expkey_put(&ek->h, &svc_expkey_cache); | 636 | cache_put(&ek->h, &svc_expkey_cache); |
| 529 | return 0; | 637 | return 0; |
| 530 | } | 638 | } |
| 531 | return -ENOMEM; | 639 | return -ENOMEM; |
| @@ -573,7 +681,7 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, | |||
| 573 | key.ex_mnt = mnt; | 681 | key.ex_mnt = mnt; |
| 574 | key.ex_dentry = dentry; | 682 | key.ex_dentry = dentry; |
| 575 | 683 | ||
| 576 | exp = svc_export_lookup(&key, 0); | 684 | exp = svc_export_lookup(&key); |
| 577 | if (exp != NULL) | 685 | if (exp != NULL) |
| 578 | switch (cache_check(&svc_export_cache, &exp->h, reqp)) { | 686 | switch (cache_check(&svc_export_cache, &exp->h, reqp)) { |
| 579 | case 0: break; | 687 | case 0: break; |
| @@ -654,7 +762,7 @@ static void exp_fsid_unhash(struct svc_export *exp) | |||
| 654 | ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); | 762 | ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); |
| 655 | if (ek && !IS_ERR(ek)) { | 763 | if (ek && !IS_ERR(ek)) { |
| 656 | ek->h.expiry_time = get_seconds()-1; | 764 | ek->h.expiry_time = get_seconds()-1; |
| 657 | expkey_put(&ek->h, &svc_expkey_cache); | 765 | cache_put(&ek->h, &svc_expkey_cache); |
| 658 | } | 766 | } |
| 659 | svc_expkey_cache.nextcheck = get_seconds(); | 767 | svc_expkey_cache.nextcheck = get_seconds(); |
| 660 | } | 768 | } |
| @@ -692,7 +800,7 @@ static void exp_unhash(struct svc_export *exp) | |||
| 692 | ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); | 800 | ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); |
| 693 | if (ek && !IS_ERR(ek)) { | 801 | if (ek && !IS_ERR(ek)) { |
| 694 | ek->h.expiry_time = get_seconds()-1; | 802 | ek->h.expiry_time = get_seconds()-1; |
| 695 | expkey_put(&ek->h, &svc_expkey_cache); | 803 | cache_put(&ek->h, &svc_expkey_cache); |
| 696 | } | 804 | } |
| 697 | svc_expkey_cache.nextcheck = get_seconds(); | 805 | svc_expkey_cache.nextcheck = get_seconds(); |
| 698 | } | 806 | } |
| @@ -741,8 +849,8 @@ exp_export(struct nfsctl_export *nxp) | |||
| 741 | if ((nxp->ex_flags & NFSEXP_FSID) && | 849 | if ((nxp->ex_flags & NFSEXP_FSID) && |
| 742 | (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && | 850 | (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && |
| 743 | !IS_ERR(fsid_key) && | 851 | !IS_ERR(fsid_key) && |
| 744 | fsid_key->ek_export && | 852 | fsid_key->ek_mnt && |
| 745 | fsid_key->ek_export != exp) | 853 | (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) ) |
| 746 | goto finish; | 854 | goto finish; |
| 747 | 855 | ||
| 748 | if (exp) { | 856 | if (exp) { |
| @@ -775,13 +883,13 @@ exp_export(struct nfsctl_export *nxp) | |||
| 775 | new.ex_anon_gid = nxp->ex_anon_gid; | 883 | new.ex_anon_gid = nxp->ex_anon_gid; |
| 776 | new.ex_fsid = nxp->ex_dev; | 884 | new.ex_fsid = nxp->ex_dev; |
| 777 | 885 | ||
| 778 | exp = svc_export_lookup(&new, 1); | 886 | exp = svc_export_lookup(&new); |
| 887 | if (exp) | ||
| 888 | exp = svc_export_update(&new, exp); | ||
| 779 | 889 | ||
| 780 | if (exp == NULL) | 890 | if (!exp) |
| 781 | goto finish; | 891 | goto finish; |
| 782 | 892 | ||
| 783 | err = 0; | ||
| 784 | |||
| 785 | if (exp_hash(clp, exp) || | 893 | if (exp_hash(clp, exp) || |
| 786 | exp_fsid_hash(clp, exp)) { | 894 | exp_fsid_hash(clp, exp)) { |
| 787 | /* failed to create at least one index */ | 895 | /* failed to create at least one index */ |
| @@ -794,7 +902,7 @@ finish: | |||
| 794 | if (exp) | 902 | if (exp) |
| 795 | exp_put(exp); | 903 | exp_put(exp); |
| 796 | if (fsid_key && !IS_ERR(fsid_key)) | 904 | if (fsid_key && !IS_ERR(fsid_key)) |
| 797 | expkey_put(&fsid_key->h, &svc_expkey_cache); | 905 | cache_put(&fsid_key->h, &svc_expkey_cache); |
| 798 | if (clp) | 906 | if (clp) |
| 799 | auth_domain_put(clp); | 907 | auth_domain_put(clp); |
| 800 | path_release(&nd); | 908 | path_release(&nd); |
| @@ -912,6 +1020,24 @@ out: | |||
| 912 | return err; | 1020 | return err; |
| 913 | } | 1021 | } |
| 914 | 1022 | ||
| 1023 | struct svc_export * | ||
| 1024 | exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, | ||
| 1025 | struct cache_req *reqp) | ||
| 1026 | { | ||
| 1027 | struct svc_export *exp; | ||
| 1028 | struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); | ||
| 1029 | if (!ek || IS_ERR(ek)) | ||
| 1030 | return ERR_PTR(PTR_ERR(ek)); | ||
| 1031 | |||
| 1032 | exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp); | ||
| 1033 | cache_put(&ek->h, &svc_expkey_cache); | ||
| 1034 | |||
| 1035 | if (!exp || IS_ERR(exp)) | ||
| 1036 | return ERR_PTR(PTR_ERR(exp)); | ||
| 1037 | return exp; | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | |||
| 915 | /* | 1041 | /* |
| 916 | * Called when we need the filehandle for the root of the pseudofs, | 1042 | * Called when we need the filehandle for the root of the pseudofs, |
| 917 | * for a given NFSv4 client. The root is defined to be the | 1043 | * for a given NFSv4 client. The root is defined to be the |
| @@ -922,6 +1048,7 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, | |||
| 922 | struct cache_req *creq) | 1048 | struct cache_req *creq) |
| 923 | { | 1049 | { |
| 924 | struct svc_expkey *fsid_key; | 1050 | struct svc_expkey *fsid_key; |
| 1051 | struct svc_export *exp; | ||
| 925 | int rv; | 1052 | int rv; |
| 926 | u32 fsidv[2]; | 1053 | u32 fsidv[2]; |
| 927 | 1054 | ||
| @@ -933,9 +1060,15 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, | |||
| 933 | if (!fsid_key || IS_ERR(fsid_key)) | 1060 | if (!fsid_key || IS_ERR(fsid_key)) |
| 934 | return nfserr_perm; | 1061 | return nfserr_perm; |
| 935 | 1062 | ||
| 936 | rv = fh_compose(fhp, fsid_key->ek_export, | 1063 | exp = exp_get_by_name(clp, fsid_key->ek_mnt, fsid_key->ek_dentry, creq); |
| 937 | fsid_key->ek_export->ex_dentry, NULL); | 1064 | if (exp == NULL) |
| 938 | expkey_put(&fsid_key->h, &svc_expkey_cache); | 1065 | rv = nfserr_perm; |
| 1066 | else if (IS_ERR(exp)) | ||
| 1067 | rv = nfserrno(PTR_ERR(exp)); | ||
| 1068 | else | ||
| 1069 | rv = fh_compose(fhp, exp, | ||
| 1070 | fsid_key->ek_dentry, NULL); | ||
| 1071 | cache_put(&fsid_key->h, &svc_expkey_cache); | ||
| 939 | return rv; | 1072 | return rv; |
| 940 | } | 1073 | } |
| 941 | 1074 | ||
| @@ -1054,7 +1187,7 @@ static int e_show(struct seq_file *m, void *p) | |||
| 1054 | cache_get(&exp->h); | 1187 | cache_get(&exp->h); |
| 1055 | if (cache_check(&svc_export_cache, &exp->h, NULL)) | 1188 | if (cache_check(&svc_export_cache, &exp->h, NULL)) |
| 1056 | return 0; | 1189 | return 0; |
| 1057 | if (cache_put(&exp->h, &svc_export_cache)) BUG(); | 1190 | cache_put(&exp->h, &svc_export_cache); |
| 1058 | return svc_export_show(m, &svc_export_cache, cp); | 1191 | return svc_export_show(m, &svc_export_cache, cp); |
| 1059 | } | 1192 | } |
| 1060 | 1193 | ||
| @@ -1129,7 +1262,6 @@ exp_delclient(struct nfsctl_client *ncp) | |||
| 1129 | */ | 1262 | */ |
| 1130 | if (dom) { | 1263 | if (dom) { |
| 1131 | err = auth_unix_forget_old(dom); | 1264 | err = auth_unix_forget_old(dom); |
| 1132 | dom->h.expiry_time = get_seconds(); | ||
| 1133 | auth_domain_put(dom); | 1265 | auth_domain_put(dom); |
| 1134 | } | 1266 | } |
| 1135 | 1267 | ||
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 13369650cdf9..4b6aa60dfceb 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
| @@ -76,21 +76,18 @@ struct ent { | |||
| 76 | char authname[IDMAP_NAMESZ]; | 76 | char authname[IDMAP_NAMESZ]; |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | #define DefineSimpleCacheLookupMap(STRUCT, FUNC) \ | ||
| 80 | DefineCacheLookup(struct STRUCT, h, FUNC##_lookup, \ | ||
| 81 | (struct STRUCT *item, int set), /*no setup */, \ | ||
| 82 | & FUNC##_cache, FUNC##_hash(item), FUNC##_match(item, tmp), \ | ||
| 83 | STRUCT##_init(new, item), STRUCT##_update(tmp, item), 0) | ||
| 84 | |||
| 85 | /* Common entry handling */ | 79 | /* Common entry handling */ |
| 86 | 80 | ||
| 87 | #define ENT_HASHBITS 8 | 81 | #define ENT_HASHBITS 8 |
| 88 | #define ENT_HASHMAX (1 << ENT_HASHBITS) | 82 | #define ENT_HASHMAX (1 << ENT_HASHBITS) |
| 89 | #define ENT_HASHMASK (ENT_HASHMAX - 1) | 83 | #define ENT_HASHMASK (ENT_HASHMAX - 1) |
| 90 | 84 | ||
| 91 | static inline void | 85 | static void |
| 92 | ent_init(struct ent *new, struct ent *itm) | 86 | ent_init(struct cache_head *cnew, struct cache_head *citm) |
| 93 | { | 87 | { |
| 88 | struct ent *new = container_of(cnew, struct ent, h); | ||
| 89 | struct ent *itm = container_of(citm, struct ent, h); | ||
| 90 | |||
| 94 | new->id = itm->id; | 91 | new->id = itm->id; |
| 95 | new->type = itm->type; | 92 | new->type = itm->type; |
| 96 | 93 | ||
| @@ -98,19 +95,21 @@ ent_init(struct ent *new, struct ent *itm) | |||
| 98 | strlcpy(new->authname, itm->authname, sizeof(new->name)); | 95 | strlcpy(new->authname, itm->authname, sizeof(new->name)); |
| 99 | } | 96 | } |
| 100 | 97 | ||
| 101 | static inline void | 98 | static void |
| 102 | ent_update(struct ent *new, struct ent *itm) | 99 | ent_put(struct kref *ref) |
| 103 | { | 100 | { |
| 104 | ent_init(new, itm); | 101 | struct ent *map = container_of(ref, struct ent, h.ref); |
| 102 | kfree(map); | ||
| 105 | } | 103 | } |
| 106 | 104 | ||
| 107 | static void | 105 | static struct cache_head * |
| 108 | ent_put(struct cache_head *ch, struct cache_detail *cd) | 106 | ent_alloc(void) |
| 109 | { | 107 | { |
| 110 | if (cache_put(ch, cd)) { | 108 | struct ent *e = kmalloc(sizeof(*e), GFP_KERNEL); |
| 111 | struct ent *map = container_of(ch, struct ent, h); | 109 | if (e) |
| 112 | kfree(map); | 110 | return &e->h; |
| 113 | } | 111 | else |
| 112 | return NULL; | ||
| 114 | } | 113 | } |
| 115 | 114 | ||
| 116 | /* | 115 | /* |
| @@ -149,9 +148,12 @@ idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, | |||
| 149 | (*bpp)[-1] = '\n'; | 148 | (*bpp)[-1] = '\n'; |
| 150 | } | 149 | } |
| 151 | 150 | ||
| 152 | static inline int | 151 | static int |
| 153 | idtoname_match(struct ent *a, struct ent *b) | 152 | idtoname_match(struct cache_head *ca, struct cache_head *cb) |
| 154 | { | 153 | { |
| 154 | struct ent *a = container_of(ca, struct ent, h); | ||
| 155 | struct ent *b = container_of(cb, struct ent, h); | ||
| 156 | |||
| 155 | return (a->id == b->id && a->type == b->type && | 157 | return (a->id == b->id && a->type == b->type && |
| 156 | strcmp(a->authname, b->authname) == 0); | 158 | strcmp(a->authname, b->authname) == 0); |
| 157 | } | 159 | } |
| @@ -184,7 +186,8 @@ warn_no_idmapd(struct cache_detail *detail) | |||
| 184 | 186 | ||
| 185 | 187 | ||
| 186 | static int idtoname_parse(struct cache_detail *, char *, int); | 188 | static int idtoname_parse(struct cache_detail *, char *, int); |
| 187 | static struct ent *idtoname_lookup(struct ent *, int); | 189 | static struct ent *idtoname_lookup(struct ent *); |
| 190 | static struct ent *idtoname_update(struct ent *, struct ent *); | ||
| 188 | 191 | ||
| 189 | static struct cache_detail idtoname_cache = { | 192 | static struct cache_detail idtoname_cache = { |
| 190 | .owner = THIS_MODULE, | 193 | .owner = THIS_MODULE, |
| @@ -196,6 +199,10 @@ static struct cache_detail idtoname_cache = { | |||
| 196 | .cache_parse = idtoname_parse, | 199 | .cache_parse = idtoname_parse, |
| 197 | .cache_show = idtoname_show, | 200 | .cache_show = idtoname_show, |
| 198 | .warn_no_listener = warn_no_idmapd, | 201 | .warn_no_listener = warn_no_idmapd, |
| 202 | .match = idtoname_match, | ||
| 203 | .init = ent_init, | ||
| 204 | .update = ent_init, | ||
| 205 | .alloc = ent_alloc, | ||
| 199 | }; | 206 | }; |
| 200 | 207 | ||
| 201 | int | 208 | int |
| @@ -238,6 +245,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) | |||
| 238 | if (ent.h.expiry_time == 0) | 245 | if (ent.h.expiry_time == 0) |
| 239 | goto out; | 246 | goto out; |
| 240 | 247 | ||
| 248 | error = -ENOMEM; | ||
| 249 | res = idtoname_lookup(&ent); | ||
| 250 | if (!res) | ||
| 251 | goto out; | ||
| 252 | |||
| 241 | /* Name */ | 253 | /* Name */ |
| 242 | error = qword_get(&buf, buf1, PAGE_SIZE); | 254 | error = qword_get(&buf, buf1, PAGE_SIZE); |
| 243 | if (error == -EINVAL) | 255 | if (error == -EINVAL) |
| @@ -252,10 +264,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) | |||
| 252 | memcpy(ent.name, buf1, sizeof(ent.name)); | 264 | memcpy(ent.name, buf1, sizeof(ent.name)); |
| 253 | } | 265 | } |
| 254 | error = -ENOMEM; | 266 | error = -ENOMEM; |
| 255 | if ((res = idtoname_lookup(&ent, 1)) == NULL) | 267 | res = idtoname_update(&ent, res); |
| 268 | if (res == NULL) | ||
| 256 | goto out; | 269 | goto out; |
| 257 | 270 | ||
| 258 | ent_put(&res->h, &idtoname_cache); | 271 | cache_put(&res->h, &idtoname_cache); |
| 259 | 272 | ||
| 260 | error = 0; | 273 | error = 0; |
| 261 | out: | 274 | out: |
| @@ -264,7 +277,31 @@ out: | |||
| 264 | return error; | 277 | return error; |
| 265 | } | 278 | } |
| 266 | 279 | ||
| 267 | static DefineSimpleCacheLookupMap(ent, idtoname); | 280 | |
| 281 | static struct ent * | ||
| 282 | idtoname_lookup(struct ent *item) | ||
| 283 | { | ||
| 284 | struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache, | ||
| 285 | &item->h, | ||
| 286 | idtoname_hash(item)); | ||
| 287 | if (ch) | ||
| 288 | return container_of(ch, struct ent, h); | ||
| 289 | else | ||
| 290 | return NULL; | ||
| 291 | } | ||
| 292 | |||
| 293 | static struct ent * | ||
| 294 | idtoname_update(struct ent *new, struct ent *old) | ||
| 295 | { | ||
| 296 | struct cache_head *ch = sunrpc_cache_update(&idtoname_cache, | ||
| 297 | &new->h, &old->h, | ||
| 298 | idtoname_hash(new)); | ||
| 299 | if (ch) | ||
| 300 | return container_of(ch, struct ent, h); | ||
| 301 | else | ||
| 302 | return NULL; | ||
| 303 | } | ||
| 304 | |||
| 268 | 305 | ||
| 269 | /* | 306 | /* |
| 270 | * Name -> ID cache | 307 | * Name -> ID cache |
| @@ -291,9 +328,12 @@ nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp, | |||
| 291 | (*bpp)[-1] = '\n'; | 328 | (*bpp)[-1] = '\n'; |
| 292 | } | 329 | } |
| 293 | 330 | ||
| 294 | static inline int | 331 | static int |
| 295 | nametoid_match(struct ent *a, struct ent *b) | 332 | nametoid_match(struct cache_head *ca, struct cache_head *cb) |
| 296 | { | 333 | { |
| 334 | struct ent *a = container_of(ca, struct ent, h); | ||
| 335 | struct ent *b = container_of(cb, struct ent, h); | ||
| 336 | |||
| 297 | return (a->type == b->type && strcmp(a->name, b->name) == 0 && | 337 | return (a->type == b->type && strcmp(a->name, b->name) == 0 && |
| 298 | strcmp(a->authname, b->authname) == 0); | 338 | strcmp(a->authname, b->authname) == 0); |
| 299 | } | 339 | } |
| @@ -317,7 +357,8 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h) | |||
| 317 | return 0; | 357 | return 0; |
| 318 | } | 358 | } |
| 319 | 359 | ||
| 320 | static struct ent *nametoid_lookup(struct ent *, int); | 360 | static struct ent *nametoid_lookup(struct ent *); |
| 361 | static struct ent *nametoid_update(struct ent *, struct ent *); | ||
| 321 | static int nametoid_parse(struct cache_detail *, char *, int); | 362 | static int nametoid_parse(struct cache_detail *, char *, int); |
| 322 | 363 | ||
| 323 | static struct cache_detail nametoid_cache = { | 364 | static struct cache_detail nametoid_cache = { |
| @@ -330,6 +371,10 @@ static struct cache_detail nametoid_cache = { | |||
| 330 | .cache_parse = nametoid_parse, | 371 | .cache_parse = nametoid_parse, |
| 331 | .cache_show = nametoid_show, | 372 | .cache_show = nametoid_show, |
| 332 | .warn_no_listener = warn_no_idmapd, | 373 | .warn_no_listener = warn_no_idmapd, |
| 374 | .match = nametoid_match, | ||
| 375 | .init = ent_init, | ||
| 376 | .update = ent_init, | ||
| 377 | .alloc = ent_alloc, | ||
| 333 | }; | 378 | }; |
| 334 | 379 | ||
| 335 | static int | 380 | static int |
| @@ -379,10 +424,14 @@ nametoid_parse(struct cache_detail *cd, char *buf, int buflen) | |||
| 379 | set_bit(CACHE_NEGATIVE, &ent.h.flags); | 424 | set_bit(CACHE_NEGATIVE, &ent.h.flags); |
| 380 | 425 | ||
| 381 | error = -ENOMEM; | 426 | error = -ENOMEM; |
| 382 | if ((res = nametoid_lookup(&ent, 1)) == NULL) | 427 | res = nametoid_lookup(&ent); |
| 428 | if (res == NULL) | ||
| 429 | goto out; | ||
| 430 | res = nametoid_update(&ent, res); | ||
| 431 | if (res == NULL) | ||
| 383 | goto out; | 432 | goto out; |
| 384 | 433 | ||
| 385 | ent_put(&res->h, &nametoid_cache); | 434 | cache_put(&res->h, &nametoid_cache); |
| 386 | error = 0; | 435 | error = 0; |
| 387 | out: | 436 | out: |
| 388 | kfree(buf1); | 437 | kfree(buf1); |
| @@ -390,7 +439,30 @@ out: | |||
| 390 | return (error); | 439 | return (error); |
| 391 | } | 440 | } |
| 392 | 441 | ||
| 393 | static DefineSimpleCacheLookupMap(ent, nametoid); | 442 | |
| 443 | static struct ent * | ||
| 444 | nametoid_lookup(struct ent *item) | ||
| 445 | { | ||
| 446 | struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache, | ||
| 447 | &item->h, | ||
| 448 | nametoid_hash(item)); | ||
| 449 | if (ch) | ||
| 450 | return container_of(ch, struct ent, h); | ||
| 451 | else | ||
| 452 | return NULL; | ||
| 453 | } | ||
| 454 | |||
| 455 | static struct ent * | ||
| 456 | nametoid_update(struct ent *new, struct ent *old) | ||
| 457 | { | ||
| 458 | struct cache_head *ch = sunrpc_cache_update(&nametoid_cache, | ||
| 459 | &new->h, &old->h, | ||
| 460 | nametoid_hash(new)); | ||
| 461 | if (ch) | ||
| 462 | return container_of(ch, struct ent, h); | ||
| 463 | else | ||
| 464 | return NULL; | ||
| 465 | } | ||
| 394 | 466 | ||
| 395 | /* | 467 | /* |
| 396 | * Exported API | 468 | * Exported API |
| @@ -458,24 +530,24 @@ idmap_defer(struct cache_req *req) | |||
| 458 | } | 530 | } |
| 459 | 531 | ||
| 460 | static inline int | 532 | static inline int |
| 461 | do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *, int), struct ent *key, | 533 | do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *), struct ent *key, |
| 462 | struct cache_detail *detail, struct ent **item, | 534 | struct cache_detail *detail, struct ent **item, |
| 463 | struct idmap_defer_req *mdr) | 535 | struct idmap_defer_req *mdr) |
| 464 | { | 536 | { |
| 465 | *item = lookup_fn(key, 0); | 537 | *item = lookup_fn(key); |
| 466 | if (!*item) | 538 | if (!*item) |
| 467 | return -ENOMEM; | 539 | return -ENOMEM; |
| 468 | return cache_check(detail, &(*item)->h, &mdr->req); | 540 | return cache_check(detail, &(*item)->h, &mdr->req); |
| 469 | } | 541 | } |
| 470 | 542 | ||
| 471 | static inline int | 543 | static inline int |
| 472 | do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int), | 544 | do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *), |
| 473 | struct ent *key, struct cache_detail *detail, | 545 | struct ent *key, struct cache_detail *detail, |
| 474 | struct ent **item) | 546 | struct ent **item) |
| 475 | { | 547 | { |
| 476 | int ret = -ENOMEM; | 548 | int ret = -ENOMEM; |
| 477 | 549 | ||
| 478 | *item = lookup_fn(key, 0); | 550 | *item = lookup_fn(key); |
| 479 | if (!*item) | 551 | if (!*item) |
| 480 | goto out_err; | 552 | goto out_err; |
| 481 | ret = -ETIMEDOUT; | 553 | ret = -ETIMEDOUT; |
| @@ -488,7 +560,7 @@ do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *, int), | |||
| 488 | goto out_put; | 560 | goto out_put; |
| 489 | return 0; | 561 | return 0; |
| 490 | out_put: | 562 | out_put: |
| 491 | ent_put(&(*item)->h, detail); | 563 | cache_put(&(*item)->h, detail); |
| 492 | out_err: | 564 | out_err: |
| 493 | *item = NULL; | 565 | *item = NULL; |
| 494 | return ret; | 566 | return ret; |
| @@ -496,7 +568,7 @@ out_err: | |||
| 496 | 568 | ||
| 497 | static int | 569 | static int |
| 498 | idmap_lookup(struct svc_rqst *rqstp, | 570 | idmap_lookup(struct svc_rqst *rqstp, |
| 499 | struct ent *(*lookup_fn)(struct ent *, int), struct ent *key, | 571 | struct ent *(*lookup_fn)(struct ent *), struct ent *key, |
| 500 | struct cache_detail *detail, struct ent **item) | 572 | struct cache_detail *detail, struct ent **item) |
| 501 | { | 573 | { |
| 502 | struct idmap_defer_req *mdr; | 574 | struct idmap_defer_req *mdr; |
| @@ -539,7 +611,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen | |||
| 539 | if (ret) | 611 | if (ret) |
| 540 | return ret; | 612 | return ret; |
| 541 | *id = item->id; | 613 | *id = item->id; |
| 542 | ent_put(&item->h, &nametoid_cache); | 614 | cache_put(&item->h, &nametoid_cache); |
| 543 | return 0; | 615 | return 0; |
| 544 | } | 616 | } |
| 545 | 617 | ||
| @@ -561,7 +633,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) | |||
| 561 | ret = strlen(item->name); | 633 | ret = strlen(item->name); |
| 562 | BUG_ON(ret > IDMAP_NAMESZ); | 634 | BUG_ON(ret > IDMAP_NAMESZ); |
| 563 | memcpy(name, item->name, ret); | 635 | memcpy(name, item->name, ret); |
| 564 | ent_put(&item->h, &idtoname_cache); | 636 | cache_put(&item->h, &idtoname_cache); |
| 565 | return ret; | 637 | return ret; |
| 566 | } | 638 | } |
| 567 | 639 | ||
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index c8960aff0968..3ef017b3b5bd 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -134,7 +134,7 @@ static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size | |||
| 134 | return simple_transaction_read(file, buf, size, pos); | 134 | return simple_transaction_read(file, buf, size, pos); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static struct file_operations transaction_ops = { | 137 | static const struct file_operations transaction_ops = { |
| 138 | .write = nfsctl_transaction_write, | 138 | .write = nfsctl_transaction_write, |
| 139 | .read = nfsctl_transaction_read, | 139 | .read = nfsctl_transaction_read, |
| 140 | .release = simple_transaction_release, | 140 | .release = simple_transaction_release, |
| @@ -146,7 +146,7 @@ static int exports_open(struct inode *inode, struct file *file) | |||
| 146 | return seq_open(file, &nfs_exports_op); | 146 | return seq_open(file, &nfs_exports_op); |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | static struct file_operations exports_operations = { | 149 | static const struct file_operations exports_operations = { |
| 150 | .open = exports_open, | 150 | .open = exports_open, |
| 151 | .read = seq_read, | 151 | .read = seq_read, |
| 152 | .llseek = seq_lseek, | 152 | .llseek = seq_lseek, |
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 7a3e397b4ed3..3f2ec2e6d06c 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c | |||
| @@ -506,7 +506,7 @@ fh_put(struct svc_fh *fhp) | |||
| 506 | nfsd_nr_put++; | 506 | nfsd_nr_put++; |
| 507 | } | 507 | } |
| 508 | if (exp) { | 508 | if (exp) { |
| 509 | svc_export_put(&exp->h, &svc_export_cache); | 509 | cache_put(&exp->h, &svc_export_cache); |
| 510 | fhp->fh_export = NULL; | 510 | fhp->fh_export = NULL; |
| 511 | } | 511 | } |
| 512 | return; | 512 | return; |
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c index 1cf955bcc526..57265d563804 100644 --- a/fs/nfsd/stats.c +++ b/fs/nfsd/stats.c | |||
| @@ -80,7 +80,7 @@ static int nfsd_proc_open(struct inode *inode, struct file *file) | |||
| 80 | return single_open(file, nfsd_proc_show, NULL); | 80 | return single_open(file, nfsd_proc_show, NULL); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | static struct file_operations nfsd_proc_fops = { | 83 | static const struct file_operations nfsd_proc_fops = { |
| 84 | .owner = THIS_MODULE, | 84 | .owner = THIS_MODULE, |
| 85 | .open = nfsd_proc_open, | 85 | .open = nfsd_proc_open, |
| 86 | .read = seq_read, | 86 | .read = seq_read, |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 5320e5afaddb..31018333dc38 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -706,7 +706,7 @@ nfsd_close(struct file *filp) | |||
| 706 | * after it. | 706 | * after it. |
| 707 | */ | 707 | */ |
| 708 | static inline int nfsd_dosync(struct file *filp, struct dentry *dp, | 708 | static inline int nfsd_dosync(struct file *filp, struct dentry *dp, |
| 709 | struct file_operations *fop) | 709 | const struct file_operations *fop) |
| 710 | { | 710 | { |
| 711 | struct inode *inode = dp->d_inode; | 711 | struct inode *inode = dp->d_inode; |
| 712 | int (*fsync) (struct file *, struct dentry *, int); | 712 | int (*fsync) (struct file *, struct dentry *, int); |
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index 9d9ed3fe371d..d1e2c6f9f05e 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c | |||
| @@ -1553,7 +1553,7 @@ static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry, | |||
| 1553 | 1553 | ||
| 1554 | #endif /* NTFS_RW */ | 1554 | #endif /* NTFS_RW */ |
| 1555 | 1555 | ||
| 1556 | struct file_operations ntfs_dir_ops = { | 1556 | const struct file_operations ntfs_dir_ops = { |
| 1557 | .llseek = generic_file_llseek, /* Seek inside directory. */ | 1557 | .llseek = generic_file_llseek, /* Seek inside directory. */ |
| 1558 | .read = generic_read_dir, /* Return -EISDIR. */ | 1558 | .read = generic_read_dir, /* Return -EISDIR. */ |
| 1559 | .readdir = ntfs_readdir, /* Read directory contents. */ | 1559 | .readdir = ntfs_readdir, /* Read directory contents. */ |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index f5d057e4acc2..c63a83e8da98 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
| @@ -2294,7 +2294,7 @@ static int ntfs_file_fsync(struct file *filp, struct dentry *dentry, | |||
| 2294 | 2294 | ||
| 2295 | #endif /* NTFS_RW */ | 2295 | #endif /* NTFS_RW */ |
| 2296 | 2296 | ||
| 2297 | struct file_operations ntfs_file_ops = { | 2297 | const struct file_operations ntfs_file_ops = { |
| 2298 | .llseek = generic_file_llseek, /* Seek inside file. */ | 2298 | .llseek = generic_file_llseek, /* Seek inside file. */ |
| 2299 | .read = generic_file_read, /* Read from file. */ | 2299 | .read = generic_file_read, /* Read from file. */ |
| 2300 | .aio_read = generic_file_aio_read, /* Async read from file. */ | 2300 | .aio_read = generic_file_aio_read, /* Async read from file. */ |
| @@ -2337,6 +2337,6 @@ struct inode_operations ntfs_file_inode_ops = { | |||
| 2337 | #endif /* NTFS_RW */ | 2337 | #endif /* NTFS_RW */ |
| 2338 | }; | 2338 | }; |
| 2339 | 2339 | ||
| 2340 | struct file_operations ntfs_empty_file_ops = {}; | 2340 | const struct file_operations ntfs_empty_file_ops = {}; |
| 2341 | 2341 | ||
| 2342 | struct inode_operations ntfs_empty_inode_ops = {}; | 2342 | struct inode_operations ntfs_empty_inode_ops = {}; |
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h index 166142960b53..bf7b3d7c0930 100644 --- a/fs/ntfs/ntfs.h +++ b/fs/ntfs/ntfs.h | |||
| @@ -60,13 +60,13 @@ extern struct kmem_cache *ntfs_index_ctx_cache; | |||
| 60 | extern struct address_space_operations ntfs_aops; | 60 | extern struct address_space_operations ntfs_aops; |
| 61 | extern struct address_space_operations ntfs_mst_aops; | 61 | extern struct address_space_operations ntfs_mst_aops; |
| 62 | 62 | ||
| 63 | extern struct file_operations ntfs_file_ops; | 63 | extern const struct file_operations ntfs_file_ops; |
| 64 | extern struct inode_operations ntfs_file_inode_ops; | 64 | extern struct inode_operations ntfs_file_inode_ops; |
| 65 | 65 | ||
| 66 | extern struct file_operations ntfs_dir_ops; | 66 | extern const struct file_operations ntfs_dir_ops; |
| 67 | extern struct inode_operations ntfs_dir_inode_ops; | 67 | extern struct inode_operations ntfs_dir_inode_ops; |
| 68 | 68 | ||
| 69 | extern struct file_operations ntfs_empty_file_ops; | 69 | extern const struct file_operations ntfs_empty_file_ops; |
| 70 | extern struct inode_operations ntfs_empty_inode_ops; | 70 | extern struct inode_operations ntfs_empty_inode_ops; |
| 71 | 71 | ||
| 72 | extern struct export_operations ntfs_export_ops; | 72 | extern struct export_operations ntfs_export_ops; |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 84f153aca692..64cd52860c87 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
| @@ -2017,7 +2017,7 @@ out: | |||
| 2017 | return ret; | 2017 | return ret; |
| 2018 | } | 2018 | } |
| 2019 | 2019 | ||
| 2020 | static struct file_operations ocfs2_dlm_debug_fops = { | 2020 | static const struct file_operations ocfs2_dlm_debug_fops = { |
| 2021 | .open = ocfs2_dlm_debug_open, | 2021 | .open = ocfs2_dlm_debug_open, |
| 2022 | .release = ocfs2_dlm_debug_release, | 2022 | .release = ocfs2_dlm_debug_release, |
| 2023 | .read = seq_read, | 2023 | .read = seq_read, |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 4b4cbadd5838..34e903a6a46b 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -1176,7 +1176,7 @@ struct inode_operations ocfs2_special_file_iops = { | |||
| 1176 | .getattr = ocfs2_getattr, | 1176 | .getattr = ocfs2_getattr, |
| 1177 | }; | 1177 | }; |
| 1178 | 1178 | ||
| 1179 | struct file_operations ocfs2_fops = { | 1179 | const struct file_operations ocfs2_fops = { |
| 1180 | .read = do_sync_read, | 1180 | .read = do_sync_read, |
| 1181 | .write = do_sync_write, | 1181 | .write = do_sync_write, |
| 1182 | .sendfile = generic_file_sendfile, | 1182 | .sendfile = generic_file_sendfile, |
| @@ -1188,7 +1188,7 @@ struct file_operations ocfs2_fops = { | |||
| 1188 | .aio_write = ocfs2_file_aio_write, | 1188 | .aio_write = ocfs2_file_aio_write, |
| 1189 | }; | 1189 | }; |
| 1190 | 1190 | ||
| 1191 | struct file_operations ocfs2_dops = { | 1191 | const struct file_operations ocfs2_dops = { |
| 1192 | .read = generic_read_dir, | 1192 | .read = generic_read_dir, |
| 1193 | .readdir = ocfs2_readdir, | 1193 | .readdir = ocfs2_readdir, |
| 1194 | .fsync = ocfs2_sync_file, | 1194 | .fsync = ocfs2_sync_file, |
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index a5ea33b24060..740c9e7ca599 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h | |||
| @@ -26,8 +26,8 @@ | |||
| 26 | #ifndef OCFS2_FILE_H | 26 | #ifndef OCFS2_FILE_H |
| 27 | #define OCFS2_FILE_H | 27 | #define OCFS2_FILE_H |
| 28 | 28 | ||
| 29 | extern struct file_operations ocfs2_fops; | 29 | extern const struct file_operations ocfs2_fops; |
| 30 | extern struct file_operations ocfs2_dops; | 30 | extern const struct file_operations ocfs2_dops; |
| 31 | extern struct inode_operations ocfs2_file_iops; | 31 | extern struct inode_operations ocfs2_file_iops; |
| 32 | extern struct inode_operations ocfs2_special_file_iops; | 32 | extern struct inode_operations ocfs2_special_file_iops; |
| 33 | struct ocfs2_alloc_context; | 33 | struct ocfs2_alloc_context; |
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index aeb0106890e4..0f14276a2e51 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c | |||
| @@ -581,17 +581,17 @@ int property_release (struct inode *inode, struct file *filp) | |||
| 581 | return 0; | 581 | return 0; |
| 582 | } | 582 | } |
| 583 | 583 | ||
| 584 | static struct file_operations openpromfs_prop_ops = { | 584 | static const struct file_operations openpromfs_prop_ops = { |
| 585 | .read = property_read, | 585 | .read = property_read, |
| 586 | .write = property_write, | 586 | .write = property_write, |
| 587 | .release = property_release, | 587 | .release = property_release, |
| 588 | }; | 588 | }; |
| 589 | 589 | ||
| 590 | static struct file_operations openpromfs_nodenum_ops = { | 590 | static const struct file_operations openpromfs_nodenum_ops = { |
| 591 | .read = nodenum_read, | 591 | .read = nodenum_read, |
| 592 | }; | 592 | }; |
| 593 | 593 | ||
| 594 | static struct file_operations openprom_operations = { | 594 | static const struct file_operations openprom_operations = { |
| 595 | .read = generic_read_dir, | 595 | .read = generic_read_dir, |
| 596 | .readdir = openpromfs_readdir, | 596 | .readdir = openpromfs_readdir, |
| 597 | }; | 597 | }; |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index f924f459bdb8..af0cb4b9e784 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
| @@ -297,6 +297,25 @@ struct kobj_type ktype_part = { | |||
| 297 | .sysfs_ops = &part_sysfs_ops, | 297 | .sysfs_ops = &part_sysfs_ops, |
| 298 | }; | 298 | }; |
| 299 | 299 | ||
| 300 | static inline void partition_sysfs_add_subdir(struct hd_struct *p) | ||
| 301 | { | ||
| 302 | struct kobject *k; | ||
| 303 | |||
| 304 | k = kobject_get(&p->kobj); | ||
| 305 | p->holder_dir = kobject_add_dir(k, "holders"); | ||
| 306 | kobject_put(k); | ||
| 307 | } | ||
| 308 | |||
| 309 | static inline void disk_sysfs_add_subdirs(struct gendisk *disk) | ||
| 310 | { | ||
| 311 | struct kobject *k; | ||
| 312 | |||
| 313 | k = kobject_get(&disk->kobj); | ||
| 314 | disk->holder_dir = kobject_add_dir(k, "holders"); | ||
| 315 | disk->slave_dir = kobject_add_dir(k, "slaves"); | ||
| 316 | kobject_put(k); | ||
| 317 | } | ||
| 318 | |||
| 300 | void delete_partition(struct gendisk *disk, int part) | 319 | void delete_partition(struct gendisk *disk, int part) |
| 301 | { | 320 | { |
| 302 | struct hd_struct *p = disk->part[part-1]; | 321 | struct hd_struct *p = disk->part[part-1]; |
| @@ -310,6 +329,8 @@ void delete_partition(struct gendisk *disk, int part) | |||
| 310 | p->ios[0] = p->ios[1] = 0; | 329 | p->ios[0] = p->ios[1] = 0; |
| 311 | p->sectors[0] = p->sectors[1] = 0; | 330 | p->sectors[0] = p->sectors[1] = 0; |
| 312 | devfs_remove("%s/part%d", disk->devfs_name, part); | 331 | devfs_remove("%s/part%d", disk->devfs_name, part); |
| 332 | if (p->holder_dir) | ||
| 333 | kobject_unregister(p->holder_dir); | ||
| 313 | kobject_unregister(&p->kobj); | 334 | kobject_unregister(&p->kobj); |
| 314 | } | 335 | } |
| 315 | 336 | ||
| @@ -337,6 +358,7 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) | |||
| 337 | p->kobj.parent = &disk->kobj; | 358 | p->kobj.parent = &disk->kobj; |
| 338 | p->kobj.ktype = &ktype_part; | 359 | p->kobj.ktype = &ktype_part; |
| 339 | kobject_register(&p->kobj); | 360 | kobject_register(&p->kobj); |
| 361 | partition_sysfs_add_subdir(p); | ||
| 340 | disk->part[part-1] = p; | 362 | disk->part[part-1] = p; |
| 341 | } | 363 | } |
| 342 | 364 | ||
| @@ -383,6 +405,7 @@ void register_disk(struct gendisk *disk) | |||
| 383 | if ((err = kobject_add(&disk->kobj))) | 405 | if ((err = kobject_add(&disk->kobj))) |
| 384 | return; | 406 | return; |
| 385 | disk_sysfs_symlinks(disk); | 407 | disk_sysfs_symlinks(disk); |
| 408 | disk_sysfs_add_subdirs(disk); | ||
| 386 | kobject_uevent(&disk->kobj, KOBJ_ADD); | 409 | kobject_uevent(&disk->kobj, KOBJ_ADD); |
| 387 | 410 | ||
| 388 | /* No minors to use for partitions */ | 411 | /* No minors to use for partitions */ |
| @@ -483,6 +506,10 @@ void del_gendisk(struct gendisk *disk) | |||
| 483 | 506 | ||
| 484 | devfs_remove_disk(disk); | 507 | devfs_remove_disk(disk); |
| 485 | 508 | ||
| 509 | if (disk->holder_dir) | ||
| 510 | kobject_unregister(disk->holder_dir); | ||
| 511 | if (disk->slave_dir) | ||
| 512 | kobject_unregister(disk->slave_dir); | ||
| 486 | if (disk->driverfs_dev) { | 513 | if (disk->driverfs_dev) { |
| 487 | char *disk_name = make_block_name(disk); | 514 | char *disk_name = make_block_name(disk); |
| 488 | sysfs_remove_link(&disk->kobj, "device"); | 515 | sysfs_remove_link(&disk->kobj, "device"); |
| @@ -568,7 +568,7 @@ pipe_rdwr_open(struct inode *inode, struct file *filp) | |||
| 568 | * The file_operations structs are not static because they | 568 | * The file_operations structs are not static because they |
| 569 | * are also used in linux/fs/fifo.c to do operations on FIFOs. | 569 | * are also used in linux/fs/fifo.c to do operations on FIFOs. |
| 570 | */ | 570 | */ |
| 571 | struct file_operations read_fifo_fops = { | 571 | const struct file_operations read_fifo_fops = { |
| 572 | .llseek = no_llseek, | 572 | .llseek = no_llseek, |
| 573 | .read = pipe_read, | 573 | .read = pipe_read, |
| 574 | .readv = pipe_readv, | 574 | .readv = pipe_readv, |
| @@ -580,7 +580,7 @@ struct file_operations read_fifo_fops = { | |||
| 580 | .fasync = pipe_read_fasync, | 580 | .fasync = pipe_read_fasync, |
| 581 | }; | 581 | }; |
| 582 | 582 | ||
| 583 | struct file_operations write_fifo_fops = { | 583 | const struct file_operations write_fifo_fops = { |
| 584 | .llseek = no_llseek, | 584 | .llseek = no_llseek, |
| 585 | .read = bad_pipe_r, | 585 | .read = bad_pipe_r, |
| 586 | .write = pipe_write, | 586 | .write = pipe_write, |
| @@ -592,7 +592,7 @@ struct file_operations write_fifo_fops = { | |||
| 592 | .fasync = pipe_write_fasync, | 592 | .fasync = pipe_write_fasync, |
| 593 | }; | 593 | }; |
| 594 | 594 | ||
| 595 | struct file_operations rdwr_fifo_fops = { | 595 | const struct file_operations rdwr_fifo_fops = { |
| 596 | .llseek = no_llseek, | 596 | .llseek = no_llseek, |
| 597 | .read = pipe_read, | 597 | .read = pipe_read, |
| 598 | .readv = pipe_readv, | 598 | .readv = pipe_readv, |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 47b7a20d45eb..4ba03009cf72 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
| @@ -560,7 +560,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de) | |||
| 560 | struct file * filp = list_entry(p, struct file, f_u.fu_list); | 560 | struct file * filp = list_entry(p, struct file, f_u.fu_list); |
| 561 | struct dentry * dentry = filp->f_dentry; | 561 | struct dentry * dentry = filp->f_dentry; |
| 562 | struct inode * inode; | 562 | struct inode * inode; |
| 563 | struct file_operations *fops; | 563 | const struct file_operations *fops; |
| 564 | 564 | ||
| 565 | if (dentry->d_op != &proc_dentry_operations) | 565 | if (dentry->d_op != &proc_dentry_operations) |
| 566 | continue; | 566 | continue; |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 95a1cf32b838..0502f17b860d 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
| @@ -30,7 +30,7 @@ do { \ | |||
| 30 | 30 | ||
| 31 | #endif | 31 | #endif |
| 32 | 32 | ||
| 33 | extern void create_seq_entry(char *name, mode_t mode, struct file_operations *f); | 33 | extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f); |
| 34 | extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **); | 34 | extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **); |
| 35 | extern int proc_tid_stat(struct task_struct *, char *); | 35 | extern int proc_tid_stat(struct task_struct *, char *); |
| 36 | extern int proc_tgid_stat(struct task_struct *, char *); | 36 | extern int proc_tgid_stat(struct task_struct *, char *); |
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index adc2cd95169a..17f6e8fa1397 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c | |||
| @@ -31,7 +31,7 @@ static int open_kcore(struct inode * inode, struct file * filp) | |||
| 31 | 31 | ||
| 32 | static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *); | 32 | static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *); |
| 33 | 33 | ||
| 34 | struct file_operations proc_kcore_operations = { | 34 | const struct file_operations proc_kcore_operations = { |
| 35 | .read = read_kcore, | 35 | .read = read_kcore, |
| 36 | .open = open_kcore, | 36 | .open = open_kcore, |
| 37 | }; | 37 | }; |
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index 10d37bf25206..ff3b90b56e9d 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c | |||
| @@ -47,7 +47,7 @@ static unsigned int kmsg_poll(struct file *file, poll_table *wait) | |||
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | 49 | ||
| 50 | struct file_operations proc_kmsg_operations = { | 50 | const struct file_operations proc_kmsg_operations = { |
| 51 | .read = kmsg_read, | 51 | .read = kmsg_read, |
| 52 | .poll = kmsg_poll, | 52 | .poll = kmsg_poll, |
| 53 | .open = kmsg_open, | 53 | .open = kmsg_open, |
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 1e9ea37d457e..ef5a3323f4b5 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
| @@ -534,7 +534,7 @@ static int show_stat(struct seq_file *p, void *v) | |||
| 534 | if (wall_to_monotonic.tv_nsec) | 534 | if (wall_to_monotonic.tv_nsec) |
| 535 | --jif; | 535 | --jif; |
| 536 | 536 | ||
| 537 | for_each_cpu(i) { | 537 | for_each_possible_cpu(i) { |
| 538 | int j; | 538 | int j; |
| 539 | 539 | ||
| 540 | user = cputime64_add(user, kstat_cpu(i).cpustat.user); | 540 | user = cputime64_add(user, kstat_cpu(i).cpustat.user); |
| @@ -731,7 +731,7 @@ static struct file_operations proc_sysrq_trigger_operations = { | |||
| 731 | 731 | ||
| 732 | struct proc_dir_entry *proc_root_kcore; | 732 | struct proc_dir_entry *proc_root_kcore; |
| 733 | 733 | ||
| 734 | void create_seq_entry(char *name, mode_t mode, struct file_operations *f) | 734 | void create_seq_entry(char *name, mode_t mode, const struct file_operations *f) |
| 735 | { | 735 | { |
| 736 | struct proc_dir_entry *entry; | 736 | struct proc_dir_entry *entry; |
| 737 | entry = create_proc_entry(name, mode, NULL); | 737 | entry = create_proc_entry(name, mode, NULL); |
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 4063fb32f78c..7efa73d44c9a 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c | |||
| @@ -172,7 +172,7 @@ static int open_vmcore(struct inode *inode, struct file *filp) | |||
| 172 | return 0; | 172 | return 0; |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | struct file_operations proc_vmcore_operations = { | 175 | const struct file_operations proc_vmcore_operations = { |
| 176 | .read = read_vmcore, | 176 | .read = read_vmcore, |
| 177 | .open = open_vmcore, | 177 | .open = open_vmcore, |
| 178 | }; | 178 | }; |
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c index 7a8f5595c26f..9031948fefd0 100644 --- a/fs/qnx4/dir.c +++ b/fs/qnx4/dir.c | |||
| @@ -81,7 +81,7 @@ out: | |||
| 81 | return 0; | 81 | return 0; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | struct file_operations qnx4_dir_operations = | 84 | const struct file_operations qnx4_dir_operations = |
| 85 | { | 85 | { |
| 86 | .read = generic_read_dir, | 86 | .read = generic_read_dir, |
| 87 | .readdir = qnx4_readdir, | 87 | .readdir = qnx4_readdir, |
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c index c33963fded9e..62af4b1348bd 100644 --- a/fs/qnx4/file.c +++ b/fs/qnx4/file.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | * We have mostly NULL's here: the current defaults are ok for | 19 | * We have mostly NULL's here: the current defaults are ok for |
| 20 | * the qnx4 filesystem. | 20 | * the qnx4 filesystem. |
| 21 | */ | 21 | */ |
| 22 | struct file_operations qnx4_file_operations = | 22 | const struct file_operations qnx4_file_operations = |
| 23 | { | 23 | { |
| 24 | .llseek = generic_file_llseek, | 24 | .llseek = generic_file_llseek, |
| 25 | .read = generic_file_read, | 25 | .read = generic_file_read, |
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c index 6ada2095b9ac..00a933eb820c 100644 --- a/fs/ramfs/file-mmu.c +++ b/fs/ramfs/file-mmu.c | |||
| @@ -32,7 +32,7 @@ struct address_space_operations ramfs_aops = { | |||
| 32 | .commit_write = simple_commit_write | 32 | .commit_write = simple_commit_write |
| 33 | }; | 33 | }; |
| 34 | 34 | ||
| 35 | struct file_operations ramfs_file_operations = { | 35 | const struct file_operations ramfs_file_operations = { |
| 36 | .read = generic_file_read, | 36 | .read = generic_file_read, |
| 37 | .write = generic_file_write, | 37 | .write = generic_file_write, |
| 38 | .mmap = generic_file_mmap, | 38 | .mmap = generic_file_mmap, |
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index b1ca234068f6..f443a84b98a5 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
| @@ -33,7 +33,7 @@ struct address_space_operations ramfs_aops = { | |||
| 33 | .commit_write = simple_commit_write | 33 | .commit_write = simple_commit_write |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | struct file_operations ramfs_file_operations = { | 36 | const struct file_operations ramfs_file_operations = { |
| 37 | .mmap = ramfs_nommu_mmap, | 37 | .mmap = ramfs_nommu_mmap, |
| 38 | .get_unmapped_area = ramfs_nommu_get_unmapped_area, | 38 | .get_unmapped_area = ramfs_nommu_get_unmapped_area, |
| 39 | .read = generic_file_read, | 39 | .read = generic_file_read, |
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h index 272c8a7120b0..313237631b49 100644 --- a/fs/ramfs/internal.h +++ b/fs/ramfs/internal.h | |||
| @@ -11,5 +11,5 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | extern struct address_space_operations ramfs_aops; | 13 | extern struct address_space_operations ramfs_aops; |
| 14 | extern struct file_operations ramfs_file_operations; | 14 | extern const struct file_operations ramfs_file_operations; |
| 15 | extern struct inode_operations ramfs_file_inode_operations; | 15 | extern struct inode_operations ramfs_file_inode_operations; |
diff --git a/fs/read_write.c b/fs/read_write.c index 34b1bf259efd..6256ca81a718 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
| 20 | #include <asm/unistd.h> | 20 | #include <asm/unistd.h> |
| 21 | 21 | ||
| 22 | struct file_operations generic_ro_fops = { | 22 | const struct file_operations generic_ro_fops = { |
| 23 | .llseek = generic_file_llseek, | 23 | .llseek = generic_file_llseek, |
| 24 | .read = generic_file_read, | 24 | .read = generic_file_read, |
| 25 | .mmap = generic_file_readonly_mmap, | 25 | .mmap = generic_file_readonly_mmap, |
diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index d71ac6579289..973c819f8033 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c | |||
| @@ -18,7 +18,7 @@ static int reiserfs_readdir(struct file *, void *, filldir_t); | |||
| 18 | static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, | 18 | static int reiserfs_dir_fsync(struct file *filp, struct dentry *dentry, |
| 19 | int datasync); | 19 | int datasync); |
| 20 | 20 | ||
| 21 | struct file_operations reiserfs_dir_operations = { | 21 | const struct file_operations reiserfs_dir_operations = { |
| 22 | .read = generic_read_dir, | 22 | .read = generic_read_dir, |
| 23 | .readdir = reiserfs_readdir, | 23 | .readdir = reiserfs_readdir, |
| 24 | .fsync = reiserfs_dir_fsync, | 24 | .fsync = reiserfs_dir_fsync, |
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index d0c1e865963e..010094d14da6 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
| @@ -1566,7 +1566,7 @@ static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user * buf, | |||
| 1566 | return generic_file_aio_write(iocb, buf, count, pos); | 1566 | return generic_file_aio_write(iocb, buf, count, pos); |
| 1567 | } | 1567 | } |
| 1568 | 1568 | ||
| 1569 | struct file_operations reiserfs_file_operations = { | 1569 | const struct file_operations reiserfs_file_operations = { |
| 1570 | .read = generic_file_read, | 1570 | .read = generic_file_read, |
| 1571 | .write = reiserfs_file_write, | 1571 | .write = reiserfs_file_write, |
| 1572 | .ioctl = reiserfs_ioctl, | 1572 | .ioctl = reiserfs_ioctl, |
diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index ef6caed9336b..731688e1cfe3 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c | |||
| @@ -470,7 +470,7 @@ static int r_open(struct inode *inode, struct file *file) | |||
| 470 | return ret; | 470 | return ret; |
| 471 | } | 471 | } |
| 472 | 472 | ||
| 473 | static struct file_operations r_file_operations = { | 473 | static const struct file_operations r_file_operations = { |
| 474 | .open = r_open, | 474 | .open = r_open, |
| 475 | .read = seq_read, | 475 | .read = seq_read, |
| 476 | .llseek = seq_lseek, | 476 | .llseek = seq_lseek, |
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index c2fc424d7d5c..9b9eda7b335c 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c | |||
| @@ -463,7 +463,7 @@ static struct address_space_operations romfs_aops = { | |||
| 463 | .readpage = romfs_readpage | 463 | .readpage = romfs_readpage |
| 464 | }; | 464 | }; |
| 465 | 465 | ||
| 466 | static struct file_operations romfs_dir_operations = { | 466 | static const struct file_operations romfs_dir_operations = { |
| 467 | .read = generic_read_dir, | 467 | .read = generic_read_dir, |
| 468 | .readdir = romfs_readdir, | 468 | .readdir = romfs_readdir, |
| 469 | }; | 469 | }; |
diff --git a/fs/select.c b/fs/select.c index 1815a57d2255..b3a3a1326af6 100644 --- a/fs/select.c +++ b/fs/select.c | |||
| @@ -29,12 +29,6 @@ | |||
| 29 | #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) | 29 | #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) |
| 30 | #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) | 30 | #define DEFAULT_POLLMASK (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM) |
| 31 | 31 | ||
| 32 | struct poll_table_entry { | ||
| 33 | struct file * filp; | ||
| 34 | wait_queue_t wait; | ||
| 35 | wait_queue_head_t * wait_address; | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct poll_table_page { | 32 | struct poll_table_page { |
| 39 | struct poll_table_page * next; | 33 | struct poll_table_page * next; |
| 40 | struct poll_table_entry * entry; | 34 | struct poll_table_entry * entry; |
| @@ -64,13 +58,23 @@ void poll_initwait(struct poll_wqueues *pwq) | |||
| 64 | init_poll_funcptr(&pwq->pt, __pollwait); | 58 | init_poll_funcptr(&pwq->pt, __pollwait); |
| 65 | pwq->error = 0; | 59 | pwq->error = 0; |
| 66 | pwq->table = NULL; | 60 | pwq->table = NULL; |
| 61 | pwq->inline_index = 0; | ||
| 67 | } | 62 | } |
| 68 | 63 | ||
| 69 | EXPORT_SYMBOL(poll_initwait); | 64 | EXPORT_SYMBOL(poll_initwait); |
| 70 | 65 | ||
| 66 | static void free_poll_entry(struct poll_table_entry *entry) | ||
| 67 | { | ||
| 68 | remove_wait_queue(entry->wait_address,&entry->wait); | ||
| 69 | fput(entry->filp); | ||
| 70 | } | ||
| 71 | |||
| 71 | void poll_freewait(struct poll_wqueues *pwq) | 72 | void poll_freewait(struct poll_wqueues *pwq) |
| 72 | { | 73 | { |
| 73 | struct poll_table_page * p = pwq->table; | 74 | struct poll_table_page * p = pwq->table; |
| 75 | int i; | ||
| 76 | for (i = 0; i < pwq->inline_index; i++) | ||
| 77 | free_poll_entry(pwq->inline_entries + i); | ||
| 74 | while (p) { | 78 | while (p) { |
| 75 | struct poll_table_entry * entry; | 79 | struct poll_table_entry * entry; |
| 76 | struct poll_table_page *old; | 80 | struct poll_table_page *old; |
| @@ -78,8 +82,7 @@ void poll_freewait(struct poll_wqueues *pwq) | |||
| 78 | entry = p->entry; | 82 | entry = p->entry; |
| 79 | do { | 83 | do { |
| 80 | entry--; | 84 | entry--; |
| 81 | remove_wait_queue(entry->wait_address,&entry->wait); | 85 | free_poll_entry(entry); |
| 82 | fput(entry->filp); | ||
| 83 | } while (entry > p->entries); | 86 | } while (entry > p->entries); |
| 84 | old = p; | 87 | old = p; |
| 85 | p = p->next; | 88 | p = p->next; |
| @@ -89,12 +92,14 @@ void poll_freewait(struct poll_wqueues *pwq) | |||
| 89 | 92 | ||
| 90 | EXPORT_SYMBOL(poll_freewait); | 93 | EXPORT_SYMBOL(poll_freewait); |
| 91 | 94 | ||
| 92 | static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, | 95 | static struct poll_table_entry *poll_get_entry(poll_table *_p) |
| 93 | poll_table *_p) | ||
| 94 | { | 96 | { |
| 95 | struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt); | 97 | struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt); |
| 96 | struct poll_table_page *table = p->table; | 98 | struct poll_table_page *table = p->table; |
| 97 | 99 | ||
| 100 | if (p->inline_index < N_INLINE_POLL_ENTRIES) | ||
| 101 | return p->inline_entries + p->inline_index++; | ||
| 102 | |||
| 98 | if (!table || POLL_TABLE_FULL(table)) { | 103 | if (!table || POLL_TABLE_FULL(table)) { |
| 99 | struct poll_table_page *new_table; | 104 | struct poll_table_page *new_table; |
| 100 | 105 | ||
| @@ -102,7 +107,7 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, | |||
| 102 | if (!new_table) { | 107 | if (!new_table) { |
| 103 | p->error = -ENOMEM; | 108 | p->error = -ENOMEM; |
| 104 | __set_current_state(TASK_RUNNING); | 109 | __set_current_state(TASK_RUNNING); |
| 105 | return; | 110 | return NULL; |
| 106 | } | 111 | } |
| 107 | new_table->entry = new_table->entries; | 112 | new_table->entry = new_table->entries; |
| 108 | new_table->next = table; | 113 | new_table->next = table; |
| @@ -110,16 +115,21 @@ static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, | |||
| 110 | table = new_table; | 115 | table = new_table; |
| 111 | } | 116 | } |
| 112 | 117 | ||
| 113 | /* Add a new entry */ | 118 | return table->entry++; |
| 114 | { | 119 | } |
| 115 | struct poll_table_entry * entry = table->entry; | 120 | |
| 116 | table->entry = entry+1; | 121 | /* Add a new entry */ |
| 117 | get_file(filp); | 122 | static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, |
| 118 | entry->filp = filp; | 123 | poll_table *p) |
| 119 | entry->wait_address = wait_address; | 124 | { |
| 120 | init_waitqueue_entry(&entry->wait, current); | 125 | struct poll_table_entry *entry = poll_get_entry(p); |
| 121 | add_wait_queue(wait_address,&entry->wait); | 126 | if (!entry) |
| 122 | } | 127 | return; |
| 128 | get_file(filp); | ||
| 129 | entry->filp = filp; | ||
| 130 | entry->wait_address = wait_address; | ||
| 131 | init_waitqueue_entry(&entry->wait, current); | ||
| 132 | add_wait_queue(wait_address,&entry->wait); | ||
| 123 | } | 133 | } |
| 124 | 134 | ||
| 125 | #define FDS_IN(fds, n) (fds->in + n) | 135 | #define FDS_IN(fds, n) (fds->in + n) |
| @@ -210,7 +220,7 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout) | |||
| 210 | for (i = 0; i < n; ++rinp, ++routp, ++rexp) { | 220 | for (i = 0; i < n; ++rinp, ++routp, ++rexp) { |
| 211 | unsigned long in, out, ex, all_bits, bit = 1, mask, j; | 221 | unsigned long in, out, ex, all_bits, bit = 1, mask, j; |
| 212 | unsigned long res_in = 0, res_out = 0, res_ex = 0; | 222 | unsigned long res_in = 0, res_out = 0, res_ex = 0; |
| 213 | struct file_operations *f_op = NULL; | 223 | const struct file_operations *f_op = NULL; |
| 214 | struct file *file = NULL; | 224 | struct file *file = NULL; |
| 215 | 225 | ||
| 216 | in = *inp++; out = *outp++; ex = *exp++; | 226 | in = *inp++; out = *outp++; ex = *exp++; |
| @@ -221,17 +231,18 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout) | |||
| 221 | } | 231 | } |
| 222 | 232 | ||
| 223 | for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) { | 233 | for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) { |
| 234 | int fput_needed; | ||
| 224 | if (i >= n) | 235 | if (i >= n) |
| 225 | break; | 236 | break; |
| 226 | if (!(bit & all_bits)) | 237 | if (!(bit & all_bits)) |
| 227 | continue; | 238 | continue; |
| 228 | file = fget(i); | 239 | file = fget_light(i, &fput_needed); |
| 229 | if (file) { | 240 | if (file) { |
| 230 | f_op = file->f_op; | 241 | f_op = file->f_op; |
| 231 | mask = DEFAULT_POLLMASK; | 242 | mask = DEFAULT_POLLMASK; |
| 232 | if (f_op && f_op->poll) | 243 | if (f_op && f_op->poll) |
| 233 | mask = (*f_op->poll)(file, retval ? NULL : wait); | 244 | mask = (*f_op->poll)(file, retval ? NULL : wait); |
| 234 | fput(file); | 245 | fput_light(file, fput_needed); |
| 235 | if ((mask & POLLIN_SET) && (in & bit)) { | 246 | if ((mask & POLLIN_SET) && (in & bit)) { |
| 236 | res_in |= bit; | 247 | res_in |= bit; |
| 237 | retval++; | 248 | retval++; |
| @@ -284,16 +295,6 @@ int do_select(int n, fd_set_bits *fds, s64 *timeout) | |||
| 284 | return retval; | 295 | return retval; |
| 285 | } | 296 | } |
| 286 | 297 | ||
| 287 | static void *select_bits_alloc(int size) | ||
| 288 | { | ||
| 289 | return kmalloc(6 * size, GFP_KERNEL); | ||
| 290 | } | ||
| 291 | |||
| 292 | static void select_bits_free(void *bits, int size) | ||
| 293 | { | ||
| 294 | kfree(bits); | ||
| 295 | } | ||
| 296 | |||
| 297 | /* | 298 | /* |
| 298 | * We can actually return ERESTARTSYS instead of EINTR, but I'd | 299 | * We can actually return ERESTARTSYS instead of EINTR, but I'd |
| 299 | * like to be certain this leads to no problems. So I return | 300 | * like to be certain this leads to no problems. So I return |
| @@ -312,6 +313,8 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, | |||
| 312 | char *bits; | 313 | char *bits; |
| 313 | int ret, size, max_fdset; | 314 | int ret, size, max_fdset; |
| 314 | struct fdtable *fdt; | 315 | struct fdtable *fdt; |
| 316 | /* Allocate small arguments on the stack to save memory and be faster */ | ||
| 317 | char stack_fds[SELECT_STACK_ALLOC]; | ||
| 315 | 318 | ||
| 316 | ret = -EINVAL; | 319 | ret = -EINVAL; |
| 317 | if (n < 0) | 320 | if (n < 0) |
| @@ -332,7 +335,10 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, | |||
| 332 | */ | 335 | */ |
| 333 | ret = -ENOMEM; | 336 | ret = -ENOMEM; |
| 334 | size = FDS_BYTES(n); | 337 | size = FDS_BYTES(n); |
| 335 | bits = select_bits_alloc(size); | 338 | if (6*size < SELECT_STACK_ALLOC) |
| 339 | bits = stack_fds; | ||
| 340 | else | ||
| 341 | bits = kmalloc(6 * size, GFP_KERNEL); | ||
| 336 | if (!bits) | 342 | if (!bits) |
| 337 | goto out_nofds; | 343 | goto out_nofds; |
| 338 | fds.in = (unsigned long *) bits; | 344 | fds.in = (unsigned long *) bits; |
| @@ -367,7 +373,8 @@ static int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp, | |||
| 367 | ret = -EFAULT; | 373 | ret = -EFAULT; |
| 368 | 374 | ||
| 369 | out: | 375 | out: |
| 370 | select_bits_free(bits, size); | 376 | if (bits != stack_fds) |
| 377 | kfree(bits); | ||
| 371 | out_nofds: | 378 | out_nofds: |
| 372 | return ret; | 379 | return ret; |
| 373 | } | 380 | } |
| @@ -551,14 +558,15 @@ static void do_pollfd(unsigned int num, struct pollfd * fdpage, | |||
| 551 | fdp = fdpage+i; | 558 | fdp = fdpage+i; |
| 552 | fd = fdp->fd; | 559 | fd = fdp->fd; |
| 553 | if (fd >= 0) { | 560 | if (fd >= 0) { |
| 554 | struct file * file = fget(fd); | 561 | int fput_needed; |
| 562 | struct file * file = fget_light(fd, &fput_needed); | ||
| 555 | mask = POLLNVAL; | 563 | mask = POLLNVAL; |
| 556 | if (file != NULL) { | 564 | if (file != NULL) { |
| 557 | mask = DEFAULT_POLLMASK; | 565 | mask = DEFAULT_POLLMASK; |
| 558 | if (file->f_op && file->f_op->poll) | 566 | if (file->f_op && file->f_op->poll) |
| 559 | mask = file->f_op->poll(file, *pwait); | 567 | mask = file->f_op->poll(file, *pwait); |
| 560 | mask &= fdp->events | POLLERR | POLLHUP; | 568 | mask &= fdp->events | POLLERR | POLLHUP; |
| 561 | fput(file); | 569 | fput_light(file, fput_needed); |
| 562 | } | 570 | } |
| 563 | if (mask) { | 571 | if (mask) { |
| 564 | *pwait = NULL; | 572 | *pwait = NULL; |
| @@ -619,6 +627,9 @@ static int do_poll(unsigned int nfds, struct poll_list *list, | |||
| 619 | return count; | 627 | return count; |
| 620 | } | 628 | } |
| 621 | 629 | ||
| 630 | #define N_STACK_PPS ((sizeof(stack_pps) - sizeof(struct poll_list)) / \ | ||
| 631 | sizeof(struct pollfd)) | ||
| 632 | |||
| 622 | int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) | 633 | int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) |
| 623 | { | 634 | { |
| 624 | struct poll_wqueues table; | 635 | struct poll_wqueues table; |
| @@ -628,6 +639,9 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) | |||
| 628 | struct poll_list *walk; | 639 | struct poll_list *walk; |
| 629 | struct fdtable *fdt; | 640 | struct fdtable *fdt; |
| 630 | int max_fdset; | 641 | int max_fdset; |
| 642 | /* Allocate small arguments on the stack to save memory and be faster */ | ||
| 643 | char stack_pps[POLL_STACK_ALLOC]; | ||
| 644 | struct poll_list *stack_pp = NULL; | ||
| 631 | 645 | ||
| 632 | /* Do a sanity check on nfds ... */ | 646 | /* Do a sanity check on nfds ... */ |
| 633 | rcu_read_lock(); | 647 | rcu_read_lock(); |
| @@ -645,14 +659,23 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) | |||
| 645 | err = -ENOMEM; | 659 | err = -ENOMEM; |
| 646 | while(i!=0) { | 660 | while(i!=0) { |
| 647 | struct poll_list *pp; | 661 | struct poll_list *pp; |
| 648 | pp = kmalloc(sizeof(struct poll_list)+ | 662 | int num, size; |
| 649 | sizeof(struct pollfd)* | 663 | if (stack_pp == NULL) |
| 650 | (i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i), | 664 | num = N_STACK_PPS; |
| 651 | GFP_KERNEL); | 665 | else |
| 652 | if(pp==NULL) | 666 | num = POLLFD_PER_PAGE; |
| 653 | goto out_fds; | 667 | if (num > i) |
| 668 | num = i; | ||
| 669 | size = sizeof(struct poll_list) + sizeof(struct pollfd)*num; | ||
| 670 | if (!stack_pp) | ||
| 671 | stack_pp = pp = (struct poll_list *)stack_pps; | ||
| 672 | else { | ||
| 673 | pp = kmalloc(size, GFP_KERNEL); | ||
| 674 | if (!pp) | ||
| 675 | goto out_fds; | ||
| 676 | } | ||
| 654 | pp->next=NULL; | 677 | pp->next=NULL; |
| 655 | pp->len = (i>POLLFD_PER_PAGE?POLLFD_PER_PAGE:i); | 678 | pp->len = num; |
| 656 | if (head == NULL) | 679 | if (head == NULL) |
| 657 | head = pp; | 680 | head = pp; |
| 658 | else | 681 | else |
| @@ -660,7 +683,7 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, s64 *timeout) | |||
| 660 | 683 | ||
| 661 | walk = pp; | 684 | walk = pp; |
| 662 | if (copy_from_user(pp->entries, ufds + nfds-i, | 685 | if (copy_from_user(pp->entries, ufds + nfds-i, |
| 663 | sizeof(struct pollfd)*pp->len)) { | 686 | sizeof(struct pollfd)*num)) { |
| 664 | err = -EFAULT; | 687 | err = -EFAULT; |
| 665 | goto out_fds; | 688 | goto out_fds; |
| 666 | } | 689 | } |
| @@ -689,7 +712,8 @@ out_fds: | |||
| 689 | walk = head; | 712 | walk = head; |
| 690 | while(walk!=NULL) { | 713 | while(walk!=NULL) { |
| 691 | struct poll_list *pp = walk->next; | 714 | struct poll_list *pp = walk->next; |
| 692 | kfree(walk); | 715 | if (walk != stack_pp) |
| 716 | kfree(walk); | ||
| 693 | walk = pp; | 717 | walk = pp; |
| 694 | } | 718 | } |
| 695 | poll_freewait(&table); | 719 | poll_freewait(&table); |
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c index 0424d06b147e..34c7a11d91f0 100644 --- a/fs/smbfs/dir.c +++ b/fs/smbfs/dir.c | |||
| @@ -34,7 +34,7 @@ static int smb_rename(struct inode *, struct dentry *, | |||
| 34 | static int smb_make_node(struct inode *,struct dentry *,int,dev_t); | 34 | static int smb_make_node(struct inode *,struct dentry *,int,dev_t); |
| 35 | static int smb_link(struct dentry *, struct inode *, struct dentry *); | 35 | static int smb_link(struct dentry *, struct inode *, struct dentry *); |
| 36 | 36 | ||
| 37 | struct file_operations smb_dir_operations = | 37 | const struct file_operations smb_dir_operations = |
| 38 | { | 38 | { |
| 39 | .read = generic_read_dir, | 39 | .read = generic_read_dir, |
| 40 | .readdir = smb_readdir, | 40 | .readdir = smb_readdir, |
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c index 7042e62726a4..c56bd99a9701 100644 --- a/fs/smbfs/file.c +++ b/fs/smbfs/file.c | |||
| @@ -401,7 +401,7 @@ smb_file_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
| 401 | return error; | 401 | return error; |
| 402 | } | 402 | } |
| 403 | 403 | ||
| 404 | struct file_operations smb_file_operations = | 404 | const struct file_operations smb_file_operations = |
| 405 | { | 405 | { |
| 406 | .llseek = remote_llseek, | 406 | .llseek = remote_llseek, |
| 407 | .read = smb_file_read, | 407 | .read = smb_file_read, |
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h index e866ec8660d0..47664597e6b1 100644 --- a/fs/smbfs/proto.h +++ b/fs/smbfs/proto.h | |||
| @@ -35,7 +35,7 @@ extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const | |||
| 35 | extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry); | 35 | extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry); |
| 36 | extern void smb_install_null_ops(struct smb_ops *ops); | 36 | extern void smb_install_null_ops(struct smb_ops *ops); |
| 37 | /* dir.c */ | 37 | /* dir.c */ |
| 38 | extern struct file_operations smb_dir_operations; | 38 | extern const struct file_operations smb_dir_operations; |
| 39 | extern struct inode_operations smb_dir_inode_operations; | 39 | extern struct inode_operations smb_dir_inode_operations; |
| 40 | extern struct inode_operations smb_dir_inode_operations_unix; | 40 | extern struct inode_operations smb_dir_inode_operations_unix; |
| 41 | extern void smb_new_dentry(struct dentry *dentry); | 41 | extern void smb_new_dentry(struct dentry *dentry); |
| @@ -64,7 +64,7 @@ extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat | |||
| 64 | extern int smb_notify_change(struct dentry *dentry, struct iattr *attr); | 64 | extern int smb_notify_change(struct dentry *dentry, struct iattr *attr); |
| 65 | /* file.c */ | 65 | /* file.c */ |
| 66 | extern struct address_space_operations smb_file_aops; | 66 | extern struct address_space_operations smb_file_aops; |
| 67 | extern struct file_operations smb_file_operations; | 67 | extern const struct file_operations smb_file_operations; |
| 68 | extern struct inode_operations smb_file_inode_operations; | 68 | extern struct inode_operations smb_file_inode_operations; |
| 69 | /* ioctl.c */ | 69 | /* ioctl.c */ |
| 70 | extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); | 70 | extern int smb_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); |
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 78899eeab974..c16a93c353c0 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
| @@ -163,7 +163,7 @@ static int release(struct inode * inode, struct file * file) | |||
| 163 | return 0; | 163 | return 0; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | struct file_operations bin_fops = { | 166 | const struct file_operations bin_fops = { |
| 167 | .read = read, | 167 | .read = read, |
| 168 | .write = write, | 168 | .write = write, |
| 169 | .mmap = mmap, | 169 | .mmap = mmap, |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 9ee956864445..f26880a4785e 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -503,7 +503,7 @@ static loff_t sysfs_dir_lseek(struct file * file, loff_t offset, int origin) | |||
| 503 | return offset; | 503 | return offset; |
| 504 | } | 504 | } |
| 505 | 505 | ||
| 506 | struct file_operations sysfs_dir_operations = { | 506 | const struct file_operations sysfs_dir_operations = { |
| 507 | .open = sysfs_dir_open, | 507 | .open = sysfs_dir_open, |
| 508 | .release = sysfs_dir_close, | 508 | .release = sysfs_dir_close, |
| 509 | .llseek = sysfs_dir_lseek, | 509 | .llseek = sysfs_dir_lseek, |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 5e83e7246788..830f76fa098c 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
| @@ -348,7 +348,7 @@ static int sysfs_release(struct inode * inode, struct file * filp) | |||
| 348 | return 0; | 348 | return 0; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | struct file_operations sysfs_file_operations = { | 351 | const struct file_operations sysfs_file_operations = { |
| 352 | .read = sysfs_read_file, | 352 | .read = sysfs_read_file, |
| 353 | .write = sysfs_write_file, | 353 | .write = sysfs_write_file, |
| 354 | .llseek = generic_file_llseek, | 354 | .llseek = generic_file_llseek, |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index cf11d5b789d9..32958a7c50e9 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
| @@ -21,9 +21,9 @@ extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr); | |||
| 21 | 21 | ||
| 22 | extern struct rw_semaphore sysfs_rename_sem; | 22 | extern struct rw_semaphore sysfs_rename_sem; |
| 23 | extern struct super_block * sysfs_sb; | 23 | extern struct super_block * sysfs_sb; |
| 24 | extern struct file_operations sysfs_dir_operations; | 24 | extern const struct file_operations sysfs_dir_operations; |
| 25 | extern struct file_operations sysfs_file_operations; | 25 | extern const struct file_operations sysfs_file_operations; |
| 26 | extern struct file_operations bin_fops; | 26 | extern const struct file_operations bin_fops; |
| 27 | extern struct inode_operations sysfs_dir_inode_operations; | 27 | extern struct inode_operations sysfs_dir_inode_operations; |
| 28 | extern struct inode_operations sysfs_symlink_inode_operations; | 28 | extern struct inode_operations sysfs_symlink_inode_operations; |
| 29 | 29 | ||
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index cce8b05cba5a..8c66e9270dd6 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | static int sysv_readdir(struct file *, void *, filldir_t); | 21 | static int sysv_readdir(struct file *, void *, filldir_t); |
| 22 | 22 | ||
| 23 | struct file_operations sysv_dir_operations = { | 23 | const struct file_operations sysv_dir_operations = { |
| 24 | .read = generic_read_dir, | 24 | .read = generic_read_dir, |
| 25 | .readdir = sysv_readdir, | 25 | .readdir = sysv_readdir, |
| 26 | .fsync = sysv_sync_file, | 26 | .fsync = sysv_sync_file, |
diff --git a/fs/sysv/file.c b/fs/sysv/file.c index da69abc06240..a59e303135fa 100644 --- a/fs/sysv/file.c +++ b/fs/sysv/file.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | * We have mostly NULLs here: the current defaults are OK for | 19 | * We have mostly NULLs here: the current defaults are OK for |
| 20 | * the coh filesystem. | 20 | * the coh filesystem. |
| 21 | */ | 21 | */ |
| 22 | struct file_operations sysv_file_operations = { | 22 | const struct file_operations sysv_file_operations = { |
| 23 | .llseek = generic_file_llseek, | 23 | .llseek = generic_file_llseek, |
| 24 | .read = generic_file_read, | 24 | .read = generic_file_read, |
| 25 | .write = generic_file_write, | 25 | .write = generic_file_write, |
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h index b7f9b4a42aab..393a480e4deb 100644 --- a/fs/sysv/sysv.h +++ b/fs/sysv/sysv.h | |||
| @@ -159,8 +159,8 @@ extern ino_t sysv_inode_by_name(struct dentry *); | |||
| 159 | extern struct inode_operations sysv_file_inode_operations; | 159 | extern struct inode_operations sysv_file_inode_operations; |
| 160 | extern struct inode_operations sysv_dir_inode_operations; | 160 | extern struct inode_operations sysv_dir_inode_operations; |
| 161 | extern struct inode_operations sysv_fast_symlink_inode_operations; | 161 | extern struct inode_operations sysv_fast_symlink_inode_operations; |
| 162 | extern struct file_operations sysv_file_operations; | 162 | extern const struct file_operations sysv_file_operations; |
| 163 | extern struct file_operations sysv_dir_operations; | 163 | extern const struct file_operations sysv_dir_operations; |
| 164 | extern struct address_space_operations sysv_aops; | 164 | extern struct address_space_operations sysv_aops; |
| 165 | extern struct super_operations sysv_sops; | 165 | extern struct super_operations sysv_sops; |
| 166 | extern struct dentry_operations sysv_dentry_operations; | 166 | extern struct dentry_operations sysv_dentry_operations; |
diff --git a/fs/udf/dir.c b/fs/udf/dir.c index f5222527fe39..8c28efa3b8ff 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c | |||
| @@ -42,7 +42,7 @@ static int do_udf_readdir(struct inode *, struct file *, filldir_t, void *); | |||
| 42 | 42 | ||
| 43 | /* readdir and lookup functions */ | 43 | /* readdir and lookup functions */ |
| 44 | 44 | ||
| 45 | struct file_operations udf_dir_operations = { | 45 | const struct file_operations udf_dir_operations = { |
| 46 | .read = generic_read_dir, | 46 | .read = generic_read_dir, |
| 47 | .readdir = udf_readdir, | 47 | .readdir = udf_readdir, |
| 48 | .ioctl = udf_ioctl, | 48 | .ioctl = udf_ioctl, |
diff --git a/fs/udf/file.c b/fs/udf/file.c index a6f2acc1f15c..e34b00e303f1 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
| @@ -248,7 +248,7 @@ static int udf_release_file(struct inode * inode, struct file * filp) | |||
| 248 | return 0; | 248 | return 0; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | struct file_operations udf_file_operations = { | 251 | const struct file_operations udf_file_operations = { |
| 252 | .read = generic_file_read, | 252 | .read = generic_file_read, |
| 253 | .ioctl = udf_ioctl, | 253 | .ioctl = udf_ioctl, |
| 254 | .open = generic_file_open, | 254 | .open = generic_file_open, |
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 1d5800e0cbe7..023e19ba5a2e 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h | |||
| @@ -44,9 +44,9 @@ struct buffer_head; | |||
| 44 | struct super_block; | 44 | struct super_block; |
| 45 | 45 | ||
| 46 | extern struct inode_operations udf_dir_inode_operations; | 46 | extern struct inode_operations udf_dir_inode_operations; |
| 47 | extern struct file_operations udf_dir_operations; | 47 | extern const struct file_operations udf_dir_operations; |
| 48 | extern struct inode_operations udf_file_inode_operations; | 48 | extern struct inode_operations udf_file_inode_operations; |
| 49 | extern struct file_operations udf_file_operations; | 49 | extern const struct file_operations udf_file_operations; |
| 50 | extern struct address_space_operations udf_aops; | 50 | extern struct address_space_operations udf_aops; |
| 51 | extern struct address_space_operations udf_adinicb_aops; | 51 | extern struct address_space_operations udf_adinicb_aops; |
| 52 | extern struct address_space_operations udf_symlink_aops; | 52 | extern struct address_space_operations udf_symlink_aops; |
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 7c10c68902ae..1a561202d3f4 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c | |||
| @@ -620,7 +620,7 @@ int ufs_empty_dir (struct inode * inode) | |||
| 620 | return 1; | 620 | return 1; |
| 621 | } | 621 | } |
| 622 | 622 | ||
| 623 | struct file_operations ufs_dir_operations = { | 623 | const struct file_operations ufs_dir_operations = { |
| 624 | .read = generic_read_dir, | 624 | .read = generic_read_dir, |
| 625 | .readdir = ufs_readdir, | 625 | .readdir = ufs_readdir, |
| 626 | .fsync = file_fsync, | 626 | .fsync = file_fsync, |
diff --git a/fs/ufs/file.c b/fs/ufs/file.c index 62ad481810ef..312fd3f86313 100644 --- a/fs/ufs/file.c +++ b/fs/ufs/file.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | * the ufs filesystem. | 31 | * the ufs filesystem. |
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | struct file_operations ufs_file_operations = { | 34 | const struct file_operations ufs_file_operations = { |
| 35 | .llseek = generic_file_llseek, | 35 | .llseek = generic_file_llseek, |
| 36 | .read = generic_file_read, | 36 | .read = generic_file_read, |
| 37 | .write = generic_file_write, | 37 | .write = generic_file_write, |
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 185567a6a561..85997b1205f5 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
| @@ -528,7 +528,7 @@ open_exec_out: | |||
| 528 | } | 528 | } |
| 529 | #endif /* HAVE_FOP_OPEN_EXEC */ | 529 | #endif /* HAVE_FOP_OPEN_EXEC */ |
| 530 | 530 | ||
| 531 | struct file_operations xfs_file_operations = { | 531 | const struct file_operations xfs_file_operations = { |
| 532 | .llseek = generic_file_llseek, | 532 | .llseek = generic_file_llseek, |
| 533 | .read = do_sync_read, | 533 | .read = do_sync_read, |
| 534 | .write = do_sync_write, | 534 | .write = do_sync_write, |
| @@ -550,7 +550,7 @@ struct file_operations xfs_file_operations = { | |||
| 550 | #endif | 550 | #endif |
| 551 | }; | 551 | }; |
| 552 | 552 | ||
| 553 | struct file_operations xfs_invis_file_operations = { | 553 | const struct file_operations xfs_invis_file_operations = { |
| 554 | .llseek = generic_file_llseek, | 554 | .llseek = generic_file_llseek, |
| 555 | .read = do_sync_read, | 555 | .read = do_sync_read, |
| 556 | .write = do_sync_write, | 556 | .write = do_sync_write, |
| @@ -570,7 +570,7 @@ struct file_operations xfs_invis_file_operations = { | |||
| 570 | }; | 570 | }; |
| 571 | 571 | ||
| 572 | 572 | ||
| 573 | struct file_operations xfs_dir_file_operations = { | 573 | const struct file_operations xfs_dir_file_operations = { |
| 574 | .read = generic_read_dir, | 574 | .read = generic_read_dir, |
| 575 | .readdir = xfs_file_readdir, | 575 | .readdir = xfs_file_readdir, |
| 576 | .unlocked_ioctl = xfs_file_ioctl, | 576 | .unlocked_ioctl = xfs_file_ioctl, |
diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index a8417d7af5f9..ad6173da5678 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h | |||
| @@ -22,9 +22,9 @@ extern struct inode_operations xfs_inode_operations; | |||
| 22 | extern struct inode_operations xfs_dir_inode_operations; | 22 | extern struct inode_operations xfs_dir_inode_operations; |
| 23 | extern struct inode_operations xfs_symlink_inode_operations; | 23 | extern struct inode_operations xfs_symlink_inode_operations; |
| 24 | 24 | ||
| 25 | extern struct file_operations xfs_file_operations; | 25 | extern const struct file_operations xfs_file_operations; |
| 26 | extern struct file_operations xfs_dir_file_operations; | 26 | extern const struct file_operations xfs_dir_file_operations; |
| 27 | extern struct file_operations xfs_invis_file_operations; | 27 | extern const struct file_operations xfs_invis_file_operations; |
| 28 | 28 | ||
| 29 | extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *, | 29 | extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *, |
| 30 | int, unsigned int, void __user *); | 30 | int, unsigned int, void __user *); |
diff --git a/include/asm-alpha/mmzone.h b/include/asm-alpha/mmzone.h index a011ef4cf3d3..192d80c875b0 100644 --- a/include/asm-alpha/mmzone.h +++ b/include/asm-alpha/mmzone.h | |||
| @@ -59,9 +59,6 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n) | |||
| 59 | #define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr)) | 59 | #define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr)) |
| 60 | #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) | 60 | #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) |
| 61 | 61 | ||
| 62 | #define local_mapnr(kvaddr) \ | ||
| 63 | ((__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr))) | ||
| 64 | |||
| 65 | /* | 62 | /* |
| 66 | * Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory | 63 | * Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory |
| 67 | * and returns the kaddr corresponding to first physical page in the | 64 | * and returns the kaddr corresponding to first physical page in the |
| @@ -86,8 +83,7 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n) | |||
| 86 | pte_t pte; \ | 83 | pte_t pte; \ |
| 87 | unsigned long pfn; \ | 84 | unsigned long pfn; \ |
| 88 | \ | 85 | \ |
| 89 | pfn = ((unsigned long)((page)-page_zone(page)->zone_mem_map)) << 32; \ | 86 | pfn = page_to_pfn(page) << 32; \ |
| 90 | pfn += page_zone(page)->zone_start_pfn << 32; \ | ||
| 91 | pte_val(pte) = pfn | pgprot_val(pgprot); \ | 87 | pte_val(pte) = pfn | pgprot_val(pgprot); \ |
| 92 | \ | 88 | \ |
| 93 | pte; \ | 89 | pte; \ |
| @@ -104,19 +100,8 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n) | |||
| 104 | __xx; \ | 100 | __xx; \ |
| 105 | }) | 101 | }) |
| 106 | 102 | ||
| 107 | #define pfn_to_page(pfn) \ | ||
| 108 | ({ \ | ||
| 109 | unsigned long kaddr = (unsigned long)__va((pfn) << PAGE_SHIFT); \ | ||
| 110 | (NODE_DATA(kvaddr_to_nid(kaddr))->node_mem_map + local_mapnr(kaddr)); \ | ||
| 111 | }) | ||
| 112 | |||
| 113 | #define page_to_pfn(page) \ | ||
| 114 | ((page) - page_zone(page)->zone_mem_map + \ | ||
| 115 | (page_zone(page)->zone_start_pfn)) | ||
| 116 | |||
| 117 | #define page_to_pa(page) \ | 103 | #define page_to_pa(page) \ |
| 118 | ((( (page) - page_zone(page)->zone_mem_map ) \ | 104 | (page_to_pfn(page) << PAGE_SHIFT) |
| 119 | + page_zone(page)->zone_start_pfn) << PAGE_SHIFT) | ||
| 120 | 105 | ||
| 121 | #define pfn_to_nid(pfn) pa_to_nid(((u64)(pfn) << PAGE_SHIFT)) | 106 | #define pfn_to_nid(pfn) pa_to_nid(((u64)(pfn) << PAGE_SHIFT)) |
| 122 | #define pfn_valid(pfn) \ | 107 | #define pfn_valid(pfn) \ |
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h index fa0b41b164a7..61bcf70b5eac 100644 --- a/include/asm-alpha/page.h +++ b/include/asm-alpha/page.h | |||
| @@ -85,8 +85,6 @@ typedef unsigned long pgprot_t; | |||
| 85 | #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) | 85 | #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) |
| 86 | #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) | 86 | #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) |
| 87 | #ifndef CONFIG_DISCONTIGMEM | 87 | #ifndef CONFIG_DISCONTIGMEM |
| 88 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
| 89 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map)) | ||
| 90 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | 88 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) |
| 91 | 89 | ||
| 92 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | 90 | #define pfn_valid(pfn) ((pfn) < max_mapnr) |
| @@ -95,9 +93,9 @@ typedef unsigned long pgprot_t; | |||
| 95 | 93 | ||
| 96 | #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ | 94 | #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ |
| 97 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | 95 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
| 98 | |||
| 99 | #endif /* __KERNEL__ */ | 96 | #endif /* __KERNEL__ */ |
| 100 | 97 | ||
| 98 | #include <asm-generic/memory_model.h> | ||
| 101 | #include <asm-generic/page.h> | 99 | #include <asm-generic/page.h> |
| 102 | 100 | ||
| 103 | #endif /* _ALPHA_PAGE_H */ | 101 | #endif /* _ALPHA_PAGE_H */ |
diff --git a/include/asm-alpha/poll.h b/include/asm-alpha/poll.h index 95707182b3ed..76f89356b6a7 100644 --- a/include/asm-alpha/poll.h +++ b/include/asm-alpha/poll.h | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | #define POLLWRNORM (1 << 8) | 12 | #define POLLWRNORM (1 << 8) |
| 13 | #define POLLWRBAND (1 << 9) | 13 | #define POLLWRBAND (1 << 9) |
| 14 | #define POLLMSG (1 << 10) | 14 | #define POLLMSG (1 << 10) |
| 15 | #define POLLREMOVE (1 << 11) | 15 | #define POLLREMOVE (1 << 12) |
| 16 | #define POLLRDHUP (1 << 12) | 16 | #define POLLRDHUP (1 << 13) |
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | struct pollfd { | 19 | struct pollfd { |
diff --git a/include/asm-arm/arch-aaec2000/uncompress.h b/include/asm-arm/arch-aaec2000/uncompress.h index fff0c94b75c4..300f4bf3bc74 100644 --- a/include/asm-arm/arch-aaec2000/uncompress.h +++ b/include/asm-arm/arch-aaec2000/uncompress.h | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | #define UART(x) (*(volatile unsigned long *)(serial_port + (x))) | 16 | #define UART(x) (*(volatile unsigned long *)(serial_port + (x))) |
| 17 | 17 | ||
| 18 | static void putstr( const char *s ) | 18 | static void putc(int c) |
| 19 | { | 19 | { |
| 20 | unsigned long serial_port; | 20 | unsigned long serial_port; |
| 21 | do { | 21 | do { |
| @@ -28,17 +28,16 @@ static void putstr( const char *s ) | |||
| 28 | return; | 28 | return; |
| 29 | } while (0); | 29 | } while (0); |
| 30 | 30 | ||
| 31 | for (; *s; s++) { | 31 | /* wait for space in the UART's transmitter */ |
| 32 | /* wait for space in the UART's transmitter */ | 32 | while ((UART(UART_SR) & UART_SR_TxFF)) |
| 33 | while ((UART(UART_SR) & UART_SR_TxFF)); | 33 | barrier(); |
| 34 | /* send the character out. */ | 34 | |
| 35 | UART(UART_DR) = *s; | 35 | /* send the character out. */ |
| 36 | /* if a LF, also do CR... */ | 36 | UART(UART_DR) = c; |
| 37 | if (*s == 10) { | 37 | } |
| 38 | while ((UART(UART_SR) & UART_SR_TxFF)); | 38 | |
| 39 | UART(UART_DR) = 13; | 39 | static inline void flush(void) |
| 40 | } | 40 | { |
| 41 | } | ||
| 42 | } | 41 | } |
| 43 | 42 | ||
| 44 | #define arch_decomp_setup() | 43 | #define arch_decomp_setup() |
diff --git a/include/asm-arm/arch-at91rm9200/uncompress.h b/include/asm-arm/arch-at91rm9200/uncompress.h index b30dd5520713..7b38497c24b5 100644 --- a/include/asm-arm/arch-at91rm9200/uncompress.h +++ b/include/asm-arm/arch-at91rm9200/uncompress.h | |||
| @@ -31,21 +31,22 @@ | |||
| 31 | * | 31 | * |
| 32 | * This does not append a newline | 32 | * This does not append a newline |
| 33 | */ | 33 | */ |
| 34 | static void putstr(const char *s) | 34 | static void putc(int c) |
| 35 | { | ||
| 36 | void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */ | ||
| 37 | |||
| 38 | while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) | ||
| 39 | barrier(); | ||
| 40 | __raw_writel(c, sys + AT91_DBGU_THR); | ||
| 41 | } | ||
| 42 | |||
| 43 | static inline void flush(void) | ||
| 35 | { | 44 | { |
| 36 | void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */ | 45 | void __iomem *sys = (void __iomem *) AT91_BASE_SYS; /* physical address */ |
| 37 | 46 | ||
| 38 | while (*s) { | ||
| 39 | while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) { barrier(); } | ||
| 40 | __raw_writel(*s, sys + AT91_DBGU_THR); | ||
| 41 | if (*s == '\n') { | ||
| 42 | while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY)) { barrier(); } | ||
| 43 | __raw_writel('\r', sys + AT91_DBGU_THR); | ||
| 44 | } | ||
| 45 | s++; | ||
| 46 | } | ||
| 47 | /* wait for transmission to complete */ | 47 | /* wait for transmission to complete */ |
| 48 | while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY)) { barrier(); } | 48 | while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY)) |
| 49 | barrier(); | ||
| 49 | } | 50 | } |
| 50 | 51 | ||
| 51 | #define arch_decomp_setup() | 52 | #define arch_decomp_setup() |
diff --git a/include/asm-arm/arch-cl7500/uncompress.h b/include/asm-arm/arch-cl7500/uncompress.h index 68601b3e3b95..c437e0c88c3f 100644 --- a/include/asm-arm/arch-cl7500/uncompress.h +++ b/include/asm-arm/arch-cl7500/uncompress.h | |||
| @@ -3,27 +3,19 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1999, 2000 Nexus Electronics Ltd. | 4 | * Copyright (C) 1999, 2000 Nexus Electronics Ltd. |
| 5 | */ | 5 | */ |
| 6 | |||
| 7 | #define BASE 0x03010000 | 6 | #define BASE 0x03010000 |
| 8 | #define SERBASE (BASE + (0x2f8 << 2)) | 7 | #define SERBASE (BASE + (0x2f8 << 2)) |
| 9 | 8 | ||
| 10 | static __inline__ void putc(char c) | 9 | static inline void putc(char c) |
| 11 | { | 10 | { |
| 12 | while (!(*((volatile unsigned int *)(SERBASE + 0x14)) & 0x20)); | 11 | while (!(*((volatile unsigned int *)(SERBASE + 0x14)) & 0x20)) |
| 12 | barrier(); | ||
| 13 | |||
| 13 | *((volatile unsigned int *)(SERBASE)) = c; | 14 | *((volatile unsigned int *)(SERBASE)) = c; |
| 14 | } | 15 | } |
| 15 | 16 | ||
| 16 | /* | 17 | static inline void flush(void) |
| 17 | * This does not append a newline | ||
| 18 | */ | ||
| 19 | static void putstr(const char *s) | ||
| 20 | { | 18 | { |
| 21 | while (*s) { | ||
| 22 | putc(*s); | ||
| 23 | if (*s == '\n') | ||
| 24 | putc('\r'); | ||
| 25 | s++; | ||
| 26 | } | ||
| 27 | } | 19 | } |
| 28 | 20 | ||
| 29 | static __inline__ void arch_decomp_setup(void) | 21 | static __inline__ void arch_decomp_setup(void) |
diff --git a/include/asm-arm/arch-clps711x/uncompress.h b/include/asm-arm/arch-clps711x/uncompress.h index 9fc4bcfa1681..07157b7e4b20 100644 --- a/include/asm-arm/arch-clps711x/uncompress.h +++ b/include/asm-arm/arch-clps711x/uncompress.h | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #undef CLPS7111_BASE | 25 | #undef CLPS7111_BASE |
| 26 | #define CLPS7111_BASE CLPS7111_PHYS_BASE | 26 | #define CLPS7111_BASE CLPS7111_PHYS_BASE |
| 27 | 27 | ||
| 28 | #define barrier() __asm__ __volatile__("": : :"memory") | ||
| 29 | #define __raw_readl(p) (*(unsigned long *)(p)) | 28 | #define __raw_readl(p) (*(unsigned long *)(p)) |
| 30 | #define __raw_writel(v,p) (*(unsigned long *)(p) = (v)) | 29 | #define __raw_writel(v,p) (*(unsigned long *)(p) = (v)) |
| 31 | 30 | ||
| @@ -40,21 +39,15 @@ | |||
| 40 | /* | 39 | /* |
| 41 | * This does not append a newline | 40 | * This does not append a newline |
| 42 | */ | 41 | */ |
| 43 | static void putstr(const char *s) | 42 | static inline void putc(int c) |
| 44 | { | 43 | { |
| 45 | char c; | 44 | while (clps_readl(SYSFLGx) & SYSFLG_UTXFF) |
| 46 | 45 | barrier(); | |
| 47 | while ((c = *s++) != '\0') { | 46 | clps_writel(c, UARTDRx); |
| 48 | while (clps_readl(SYSFLGx) & SYSFLG_UTXFF) | 47 | } |
| 49 | barrier(); | ||
| 50 | clps_writel(c, UARTDRx); | ||
| 51 | 48 | ||
| 52 | if (c == '\n') { | 49 | static inline void flush(void) |
| 53 | while (clps_readl(SYSFLGx) & SYSFLG_UTXFF) | 50 | { |
| 54 | barrier(); | ||
| 55 | clps_writel('\r', UARTDRx); | ||
| 56 | } | ||
| 57 | } | ||
| 58 | while (clps_readl(SYSFLGx) & SYSFLG_UBUSY) | 51 | while (clps_readl(SYSFLGx) & SYSFLG_UBUSY) |
| 59 | barrier(); | 52 | barrier(); |
| 60 | } | 53 | } |
diff --git a/include/asm-arm/arch-ebsa110/uncompress.h b/include/asm-arm/arch-ebsa110/uncompress.h index eee95581a923..66b19c7fd908 100644 --- a/include/asm-arm/arch-ebsa110/uncompress.h +++ b/include/asm-arm/arch-ebsa110/uncompress.h | |||
| @@ -8,33 +8,34 @@ | |||
| 8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/serial_reg.h> | ||
| 12 | |||
| 13 | #define SERIAL_BASE ((unsigned char *)0xfe000be0) | ||
| 14 | |||
| 11 | /* | 15 | /* |
| 12 | * This does not append a newline | 16 | * This does not append a newline |
| 13 | */ | 17 | */ |
| 14 | static void putstr(const char *s) | 18 | static inline void putc(int c) |
| 19 | { | ||
| 20 | unsigned char v, *base = SERIAL_BASE; | ||
| 21 | |||
| 22 | do { | ||
| 23 | v = base[UART_LSR << 2]; | ||
| 24 | barrier(); | ||
| 25 | } while (!(v & UART_LSR_THRE)); | ||
| 26 | |||
| 27 | base[UART_TX << 2] = c; | ||
| 28 | } | ||
| 29 | |||
| 30 | static inline void flush(void) | ||
| 15 | { | 31 | { |
| 16 | unsigned long tmp1, tmp2; | 32 | unsigned char v, *base = SERIAL_BASE; |
| 17 | __asm__ __volatile__( | 33 | |
| 18 | "ldrb %0, [%2], #1\n" | 34 | do { |
| 19 | " teq %0, #0\n" | 35 | v = base[UART_LSR << 2]; |
| 20 | " beq 3f\n" | 36 | barrier(); |
| 21 | "1: strb %0, [%3]\n" | 37 | } while ((v & (UART_LSR_TEMT|UART_LSR_THRE)) != |
| 22 | "2: ldrb %1, [%3, #0x14]\n" | 38 | (UART_LSR_TEMT|UART_LSR_THRE)); |
| 23 | " and %1, %1, #0x60\n" | ||
| 24 | " teq %1, #0x60\n" | ||
| 25 | " bne 2b\n" | ||
| 26 | " teq %0, #'\n'\n" | ||
| 27 | " moveq %0, #'\r'\n" | ||
| 28 | " beq 1b\n" | ||
| 29 | " ldrb %0, [%2], #1\n" | ||
| 30 | " teq %0, #0\n" | ||
| 31 | " bne 1b\n" | ||
| 32 | "3: ldrb %1, [%3, #0x14]\n" | ||
| 33 | " and %1, %1, #0x60\n" | ||
| 34 | " teq %1, #0x60\n" | ||
| 35 | " bne 3b" | ||
| 36 | : "=&r" (tmp1), "=&r" (tmp2) | ||
| 37 | : "r" (s), "r" (0xf0000be0) : "cc"); | ||
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | /* | 41 | /* |
diff --git a/include/asm-arm/arch-ebsa285/uncompress.h b/include/asm-arm/arch-ebsa285/uncompress.h index c2fd84e2d90e..86142c882b3a 100644 --- a/include/asm-arm/arch-ebsa285/uncompress.h +++ b/include/asm-arm/arch-ebsa285/uncompress.h | |||
| @@ -15,10 +15,11 @@ | |||
| 15 | #define DC21285_BASE ((volatile unsigned int *)0x42000160) | 15 | #define DC21285_BASE ((volatile unsigned int *)0x42000160) |
| 16 | #define SER0_BASE ((volatile unsigned char *)0x7c0003f8) | 16 | #define SER0_BASE ((volatile unsigned char *)0x7c0003f8) |
| 17 | 17 | ||
| 18 | static __inline__ void putc(char c) | 18 | static inline void putc(char c) |
| 19 | { | 19 | { |
| 20 | if (machine_is_netwinder()) { | 20 | if (machine_is_netwinder()) { |
| 21 | while ((SER0_BASE[5] & 0x60) != 0x60); | 21 | while ((SER0_BASE[5] & 0x60) != 0x60) |
| 22 | barrier(); | ||
| 22 | SER0_BASE[0] = c; | 23 | SER0_BASE[0] = c; |
| 23 | } else { | 24 | } else { |
| 24 | while (DC21285_BASE[6] & 8); | 25 | while (DC21285_BASE[6] & 8); |
| @@ -26,17 +27,8 @@ static __inline__ void putc(char c) | |||
| 26 | } | 27 | } |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | /* | 30 | static inline void flush(void) |
| 30 | * This does not append a newline | ||
| 31 | */ | ||
| 32 | static void putstr(const char *s) | ||
| 33 | { | 31 | { |
| 34 | while (*s) { | ||
| 35 | putc(*s); | ||
| 36 | if (*s == '\n') | ||
| 37 | putc('\r'); | ||
| 38 | s++; | ||
| 39 | } | ||
| 40 | } | 32 | } |
| 41 | 33 | ||
| 42 | /* | 34 | /* |
diff --git a/include/asm-arm/arch-ep93xx/uncompress.h b/include/asm-arm/arch-ep93xx/uncompress.h index 4410d217077e..c15274c85d5d 100644 --- a/include/asm-arm/arch-ep93xx/uncompress.h +++ b/include/asm-arm/arch-ep93xx/uncompress.h | |||
| @@ -16,17 +16,27 @@ static unsigned char __raw_readb(unsigned int ptr) | |||
| 16 | return *((volatile unsigned char *)ptr); | 16 | return *((volatile unsigned char *)ptr); |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | static unsigned int __raw_readl(unsigned int ptr) | ||
| 20 | { | ||
| 21 | return *((volatile unsigned int *)ptr); | ||
| 22 | } | ||
| 23 | |||
| 19 | static void __raw_writeb(unsigned char value, unsigned int ptr) | 24 | static void __raw_writeb(unsigned char value, unsigned int ptr) |
| 20 | { | 25 | { |
| 21 | *((volatile unsigned char *)ptr) = value; | 26 | *((volatile unsigned char *)ptr) = value; |
| 22 | } | 27 | } |
| 23 | 28 | ||
| 29 | static void __raw_writel(unsigned int value, unsigned int ptr) | ||
| 30 | { | ||
| 31 | *((volatile unsigned int *)ptr) = value; | ||
| 32 | } | ||
| 33 | |||
| 24 | 34 | ||
| 25 | #define PHYS_UART1_DATA 0x808c0000 | 35 | #define PHYS_UART1_DATA 0x808c0000 |
| 26 | #define PHYS_UART1_FLAG 0x808c0018 | 36 | #define PHYS_UART1_FLAG 0x808c0018 |
| 27 | #define UART1_FLAG_TXFF 0x20 | 37 | #define UART1_FLAG_TXFF 0x20 |
| 28 | 38 | ||
| 29 | static __inline__ void putc(char c) | 39 | static inline void putc(int c) |
| 30 | { | 40 | { |
| 31 | int i; | 41 | int i; |
| 32 | 42 | ||
| @@ -39,15 +49,37 @@ static __inline__ void putc(char c) | |||
| 39 | __raw_writeb(c, PHYS_UART1_DATA); | 49 | __raw_writeb(c, PHYS_UART1_DATA); |
| 40 | } | 50 | } |
| 41 | 51 | ||
| 42 | static void putstr(const char *s) | 52 | static inline void flush(void) |
| 43 | { | 53 | { |
| 44 | while (*s) { | ||
| 45 | putc(*s); | ||
| 46 | if (*s == '\n') | ||
| 47 | putc('\r'); | ||
| 48 | s++; | ||
| 49 | } | ||
| 50 | } | 54 | } |
| 51 | 55 | ||
| 52 | #define arch_decomp_setup() | 56 | |
| 57 | /* | ||
| 58 | * Some bootloaders don't turn off DMA from the ethernet MAC before | ||
| 59 | * jumping to linux, which means that we might end up with bits of RX | ||
| 60 | * status and packet data scribbled over the uncompressed kernel image. | ||
| 61 | * Work around this by resetting the ethernet MAC before we uncompress. | ||
| 62 | */ | ||
| 63 | #define PHYS_ETH_SELF_CTL 0x80010020 | ||
| 64 | #define ETH_SELF_CTL_RESET 0x00000001 | ||
| 65 | |||
| 66 | static void ethernet_reset(void) | ||
| 67 | { | ||
| 68 | unsigned int v; | ||
| 69 | |||
| 70 | /* Reset the ethernet MAC. */ | ||
| 71 | v = __raw_readl(PHYS_ETH_SELF_CTL); | ||
| 72 | __raw_writel(v | ETH_SELF_CTL_RESET, PHYS_ETH_SELF_CTL); | ||
| 73 | |||
| 74 | /* Wait for reset to finish. */ | ||
| 75 | while (__raw_readl(PHYS_ETH_SELF_CTL) & ETH_SELF_CTL_RESET) | ||
| 76 | ; | ||
| 77 | } | ||
| 78 | |||
| 79 | |||
| 80 | static void arch_decomp_setup(void) | ||
| 81 | { | ||
| 82 | ethernet_reset(); | ||
| 83 | } | ||
| 84 | |||
| 53 | #define arch_decomp_wdog() | 85 | #define arch_decomp_wdog() |
diff --git a/include/asm-arm/arch-h720x/uncompress.h b/include/asm-arm/arch-h720x/uncompress.h index 9535764bcc71..18c69e0f3585 100644 --- a/include/asm-arm/arch-h720x/uncompress.h +++ b/include/asm-arm/arch-h720x/uncompress.h | |||
| @@ -12,22 +12,20 @@ | |||
| 12 | #define LSR 0x14 | 12 | #define LSR 0x14 |
| 13 | #define TEMPTY 0x40 | 13 | #define TEMPTY 0x40 |
| 14 | 14 | ||
| 15 | static void putstr(const char *s) | 15 | static inline void putc(int c) |
| 16 | { | 16 | { |
| 17 | char c; | ||
| 18 | volatile unsigned char *p = (volatile unsigned char *)(IO_PHYS+0x20000); | 17 | volatile unsigned char *p = (volatile unsigned char *)(IO_PHYS+0x20000); |
| 19 | 18 | ||
| 20 | while ( (c = *s++) != '\0') { | 19 | /* wait until transmit buffer is empty */ |
| 21 | /* wait until transmit buffer is empty */ | 20 | while((p[LSR] & TEMPTY) == 0x0) |
| 22 | while((p[LSR] & TEMPTY) == 0x0); | 21 | barrier(); |
| 23 | /* write next character */ | 22 | |
| 24 | *p = c; | 23 | /* write next character */ |
| 25 | 24 | *p = c; | |
| 26 | if(c == '\n') { | 25 | } |
| 27 | while((p[LSR] & TEMPTY) == 0x0); | 26 | |
| 28 | *p = '\r'; | 27 | static inline void flush(void) |
| 29 | } | 28 | { |
| 30 | } | ||
| 31 | } | 29 | } |
| 32 | 30 | ||
| 33 | /* | 31 | /* |
diff --git a/include/asm-arm/arch-imx/uncompress.h b/include/asm-arm/arch-imx/uncompress.h index 096077f2750b..da333f69136f 100644 --- a/include/asm-arm/arch-imx/uncompress.h +++ b/include/asm-arm/arch-imx/uncompress.h | |||
| @@ -39,8 +39,7 @@ | |||
| 39 | * | 39 | * |
| 40 | * This does not append a newline | 40 | * This does not append a newline |
| 41 | */ | 41 | */ |
| 42 | static void | 42 | static void putc(int c) |
| 43 | putstr(const char *s) | ||
| 44 | { | 43 | { |
| 45 | unsigned long serial_port; | 44 | unsigned long serial_port; |
| 46 | 45 | ||
| @@ -54,20 +53,14 @@ putstr(const char *s) | |||
| 54 | return; | 53 | return; |
| 55 | } while(0); | 54 | } while(0); |
| 56 | 55 | ||
| 57 | while (*s) { | 56 | while (!(UART(USR2) & USR2_TXFE)) |
| 58 | while ( !(UART(USR2) & USR2_TXFE) ) | 57 | barrier(); |
| 59 | barrier(); | ||
| 60 | 58 | ||
| 61 | UART(TXR) = *s; | 59 | UART(TXR) = c; |
| 62 | 60 | } | |
| 63 | if (*s == '\n') { | ||
| 64 | while ( !(UART(USR2) & USR2_TXFE) ) | ||
| 65 | barrier(); | ||
| 66 | 61 | ||
| 67 | UART(TXR) = '\r'; | 62 | static inline void flush(void) |
| 68 | } | 63 | { |
| 69 | s++; | ||
| 70 | } | ||
| 71 | } | 64 | } |
| 72 | 65 | ||
| 73 | /* | 66 | /* |
diff --git a/include/asm-arm/arch-integrator/uncompress.h b/include/asm-arm/arch-integrator/uncompress.h index 3957402741d3..f61825c4d901 100644 --- a/include/asm-arm/arch-integrator/uncompress.h +++ b/include/asm-arm/arch-integrator/uncompress.h | |||
| @@ -28,21 +28,18 @@ | |||
| 28 | /* | 28 | /* |
| 29 | * This does not append a newline | 29 | * This does not append a newline |
| 30 | */ | 30 | */ |
| 31 | static void putstr(const char *s) | 31 | static void putc(int c) |
| 32 | { | 32 | { |
| 33 | while (*s) { | 33 | while (AMBA_UART_FR & (1 << 5)) |
| 34 | while (AMBA_UART_FR & (1 << 5)); | 34 | barrier(); |
| 35 | 35 | ||
| 36 | AMBA_UART_DR = *s; | 36 | AMBA_UART_DR = c; |
| 37 | 37 | } | |
| 38 | if (*s == '\n') { | ||
| 39 | while (AMBA_UART_FR & (1 << 5)); | ||
| 40 | 38 | ||
| 41 | AMBA_UART_DR = '\r'; | 39 | static inline void flush(void) |
| 42 | } | 40 | { |
| 43 | s++; | 41 | while (AMBA_UART_FR & (1 << 3)) |
| 44 | } | 42 | barrier(); |
| 45 | while (AMBA_UART_FR & (1 << 3)); | ||
| 46 | } | 43 | } |
| 47 | 44 | ||
| 48 | /* | 45 | /* |
diff --git a/include/asm-arm/arch-iop3xx/uncompress.h b/include/asm-arm/arch-iop3xx/uncompress.h index 82b88762c3cc..c98eb6254b1f 100644 --- a/include/asm-arm/arch-iop3xx/uncompress.h +++ b/include/asm-arm/arch-iop3xx/uncompress.h | |||
| @@ -19,23 +19,15 @@ static volatile UTYPE uart_base; | |||
| 19 | 19 | ||
| 20 | #define TX_DONE (UART_LSR_TEMT|UART_LSR_THRE) | 20 | #define TX_DONE (UART_LSR_TEMT|UART_LSR_THRE) |
| 21 | 21 | ||
| 22 | static __inline__ void putc(char c) | 22 | static inline void putc(char c) |
| 23 | { | 23 | { |
| 24 | while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE); | 24 | while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE) |
| 25 | barrier(); | ||
| 25 | *uart_base = c; | 26 | *uart_base = c; |
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | /* | 29 | static inline void flush(void) |
| 29 | * This does not append a newline | ||
| 30 | */ | ||
| 31 | static void putstr(const char *s) | ||
| 32 | { | 30 | { |
| 33 | while (*s) { | ||
| 34 | putc(*s); | ||
| 35 | if (*s == '\n') | ||
| 36 | putc('\r'); | ||
| 37 | s++; | ||
| 38 | } | ||
| 39 | } | 31 | } |
| 40 | 32 | ||
| 41 | static __inline__ void __arch_decomp_setup(unsigned long arch_id) | 33 | static __inline__ void __arch_decomp_setup(unsigned long arch_id) |
diff --git a/include/asm-arm/arch-ixp2000/uncompress.h b/include/asm-arm/arch-ixp2000/uncompress.h index 3d3d5b2ed6e9..f66b408f363e 100644 --- a/include/asm-arm/arch-ixp2000/uncompress.h +++ b/include/asm-arm/arch-ixp2000/uncompress.h | |||
| @@ -29,23 +29,18 @@ | |||
| 29 | #define UARTSR PHYS(0x14) /* Status reg */ | 29 | #define UARTSR PHYS(0x14) /* Status reg */ |
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | static __inline__ void putc(char c) | 32 | static inline void putc(int c) |
| 33 | { | 33 | { |
| 34 | int j = 0x1000; | 34 | int j = 0x1000; |
| 35 | 35 | ||
| 36 | while (--j && !(*UARTSR & UART_LSR_THRE)); | 36 | while (--j && !(*UARTSR & UART_LSR_THRE)) |
| 37 | barrier(); | ||
| 38 | |||
| 37 | *UARTDR = c; | 39 | *UARTDR = c; |
| 38 | } | 40 | } |
| 39 | 41 | ||
| 40 | static void putstr(const char *s) | 42 | static inline void flush(void) |
| 41 | { | 43 | { |
| 42 | while (*s) | ||
| 43 | { | ||
| 44 | putc(*s); | ||
| 45 | if (*s == '\n') | ||
| 46 | putc('\r'); | ||
| 47 | s++; | ||
| 48 | } | ||
| 49 | } | 44 | } |
| 50 | 45 | ||
| 51 | #define arch_decomp_setup() | 46 | #define arch_decomp_setup() |
diff --git a/include/asm-arm/arch-ixp23xx/debug-macro.S b/include/asm-arm/arch-ixp23xx/debug-macro.S new file mode 100644 index 000000000000..eb99fd69fd24 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/debug-macro.S | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/debug-macro.S | ||
| 3 | * | ||
| 4 | * Debugging macro include header | ||
| 5 | * | ||
| 6 | * Copyright (C) 1994-1999 Russell King | ||
| 7 | * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | #include <asm/arch/ixp23xx.h> | ||
| 14 | |||
| 15 | .macro addruart,rx | ||
| 16 | mrc p15, 0, \rx, c1, c0 | ||
| 17 | tst \rx, #1 @ mmu enabled? | ||
| 18 | ldreq \rx, =IXP23XX_PERIPHERAL_PHYS @ physical | ||
| 19 | ldrne \rx, =IXP23XX_PERIPHERAL_VIRT @ virtual | ||
| 20 | .endm | ||
| 21 | |||
| 22 | #define UART_SHIFT 2 | ||
| 23 | #include <asm/hardware/debug-8250.S> | ||
diff --git a/include/asm-arm/arch-ixp23xx/dma.h b/include/asm-arm/arch-ixp23xx/dma.h new file mode 100644 index 000000000000..2f4335e3b836 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/dma.h | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/dma.h | ||
| 3 | */ | ||
diff --git a/include/asm-arm/arch-ixp23xx/entry-macro.S b/include/asm-arm/arch-ixp23xx/entry-macro.S new file mode 100644 index 000000000000..0ef4e6016ac4 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/entry-macro.S | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/entry-macro.S | ||
| 3 | */ | ||
| 4 | |||
| 5 | .macro disable_fiq | ||
| 6 | .endm | ||
| 7 | |||
| 8 | .macro get_irqnr_and_base, irqnr, irqstat, base, tmp | ||
| 9 | ldr \irqnr, =(IXP23XX_INTC_VIRT + IXP23XX_INTR_IRQ_ENC_ST_OFFSET) | ||
| 10 | ldr \irqnr, [\irqnr] @ get interrupt number | ||
| 11 | cmp \irqnr, #0x0 @ suprious interrupt ? | ||
| 12 | movne \irqnr, \irqnr, lsr #2 @ skip unwanted low order bits | ||
| 13 | subne \irqnr, \irqnr, #1 @ convert to 0 based | ||
| 14 | |||
| 15 | #if 0 | ||
| 16 | cmp \irqnr, #IRQ_IXP23XX_PCI_INT_RPH | ||
| 17 | bne 1001f | ||
| 18 | mov \irqnr, #IRQ_IXP23XX_INTA | ||
| 19 | |||
| 20 | ldr \irqnr, =0xf5000030 | ||
| 21 | |||
| 22 | mov \tmp, #(1<<26) | ||
| 23 | tst \irqnr, \tmp | ||
| 24 | movne \irqnr, #IRQ_IXP23XX_INTB | ||
| 25 | |||
| 26 | mov \tmp, #(1<<27) | ||
| 27 | tst \irqnr, \tmp | ||
| 28 | movne \irqnr, #IRQ_IXP23XX_INTA | ||
| 29 | 1001: | ||
| 30 | #endif | ||
| 31 | .endm | ||
diff --git a/include/asm-arm/arch-ixp23xx/hardware.h b/include/asm-arm/arch-ixp23xx/hardware.h new file mode 100644 index 000000000000..c0010d21a684 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/hardware.h | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/hardware.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002-2004 Intel Corporation. | ||
| 5 | * Copyricht (C) 2005 MontaVista Software, Inc. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | * Hardware definitions for IXP23XX based systems | ||
| 12 | */ | ||
| 13 | |||
| 14 | #ifndef __ASM_ARCH_HARDWARE_H | ||
| 15 | #define __ASM_ARCH_HARDWARE_H | ||
| 16 | |||
| 17 | /* PCI IO info */ | ||
| 18 | #define PCIO_BASE IXP23XX_PCI_IO_VIRT | ||
| 19 | #define PCIBIOS_MIN_IO 0x00000000 | ||
| 20 | #define PCIBIOS_MIN_MEM 0xe0000000 | ||
| 21 | |||
| 22 | #include "ixp23xx.h" | ||
| 23 | |||
| 24 | #define pcibios_assign_all_busses() 0 | ||
| 25 | |||
| 26 | /* | ||
| 27 | * Platform helper functions | ||
| 28 | */ | ||
| 29 | #include "platform.h" | ||
| 30 | |||
| 31 | /* | ||
| 32 | * Platform-specific headers | ||
| 33 | */ | ||
| 34 | #include "ixdp2351.h" | ||
| 35 | |||
| 36 | |||
| 37 | #endif | ||
diff --git a/include/asm-arm/arch-ixp23xx/io.h b/include/asm-arm/arch-ixp23xx/io.h new file mode 100644 index 000000000000..18415a81ac74 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/io.h | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/io.h | ||
| 3 | * | ||
| 4 | * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com> | ||
| 5 | * Maintainer: Deepak Saxena <dsaxena@plexity.net> | ||
| 6 | * | ||
| 7 | * Copyright (C) 2003-2005 Intel Corp. | ||
| 8 | * Copyright (C) 2005 MontaVista Software, Inc | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef __ASM_ARCH_IO_H | ||
| 16 | #define __ASM_ARCH_IO_H | ||
| 17 | |||
| 18 | #define IO_SPACE_LIMIT 0xffffffff | ||
| 19 | |||
| 20 | #define __io(p) ((void __iomem*)((p) + IXP23XX_PCI_IO_VIRT)) | ||
| 21 | #define __mem_pci(a) (a) | ||
| 22 | |||
| 23 | #include <linux/kernel.h> /* For BUG */ | ||
| 24 | |||
| 25 | static inline void __iomem * | ||
| 26 | ixp23xx_ioremap(unsigned long addr, unsigned long size, unsigned long flags) | ||
| 27 | { | ||
| 28 | if (addr >= IXP23XX_PCI_MEM_START && | ||
| 29 | addr <= IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE) { | ||
| 30 | if (addr + size > IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE) | ||
| 31 | return NULL; | ||
| 32 | |||
| 33 | return (void __iomem *) | ||
| 34 | ((addr - IXP23XX_PCI_MEM_START) + IXP23XX_PCI_MEM_VIRT); | ||
| 35 | } | ||
| 36 | |||
| 37 | return __ioremap(addr, size, flags); | ||
| 38 | } | ||
| 39 | |||
| 40 | static inline void | ||
| 41 | ixp23xx_iounmap(void __iomem *addr) | ||
| 42 | { | ||
| 43 | if ((((u32)addr) >= IXP23XX_PCI_MEM_VIRT) && | ||
| 44 | (((u32)addr) < IXP23XX_PCI_MEM_VIRT + IXP23XX_PCI_MEM_SIZE)) | ||
| 45 | return; | ||
| 46 | |||
| 47 | __iounmap(addr); | ||
| 48 | } | ||
| 49 | |||
| 50 | #define __arch_ioremap(a,s,f) ixp23xx_ioremap(a,s,f) | ||
| 51 | #define __arch_iounmap(a) ixp23xx_iounmap(a) | ||
| 52 | |||
| 53 | |||
| 54 | #endif | ||
diff --git a/include/asm-arm/arch-ixp23xx/irqs.h b/include/asm-arm/arch-ixp23xx/irqs.h new file mode 100644 index 000000000000..e69639585721 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/irqs.h | |||
| @@ -0,0 +1,223 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/irqs.h | ||
| 3 | * | ||
| 4 | * IRQ definitions for IXP23XX based systems | ||
| 5 | * | ||
| 6 | * Author: Naeem Afzal <naeem.m.afzal@intel.com> | ||
| 7 | * | ||
| 8 | * Copyright (C) 2003-2004 Intel Corporation. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef __ASM_ARCH_IRQS_H | ||
| 16 | #define __ASM_ARCH_IRQS_H | ||
| 17 | |||
| 18 | #define NR_IXP23XX_IRQS IRQ_IXP23XX_INTB+1 | ||
| 19 | #define IRQ_IXP23XX_EXTIRQS NR_IXP23XX_IRQS | ||
| 20 | |||
| 21 | |||
| 22 | #define IRQ_IXP23XX_DBG0 0 /* Debug/Execution/MBox */ | ||
| 23 | #define IRQ_IXP23XX_DBG1 1 /* Debug/Execution/MBox */ | ||
| 24 | #define IRQ_IXP23XX_NPE_TRG 2 /* npe_trigger */ | ||
| 25 | #define IRQ_IXP23XX_TIMER1 3 /* Timer[0] */ | ||
| 26 | #define IRQ_IXP23XX_TIMER2 4 /* Timer[1] */ | ||
| 27 | #define IRQ_IXP23XX_TIMESTAMP 5 /* Timer[2], Time-stamp */ | ||
| 28 | #define IRQ_IXP23XX_WDOG 6 /* Time[3], Watchdog Timer */ | ||
| 29 | #define IRQ_IXP23XX_PCI_DBELL 7 /* PCI Doorbell */ | ||
| 30 | #define IRQ_IXP23XX_PCI_DMA1 8 /* PCI DMA Channel 1 */ | ||
| 31 | #define IRQ_IXP23XX_PCI_DMA2 9 /* PCI DMA Channel 2 */ | ||
| 32 | #define IRQ_IXP23XX_PCI_DMA3 10 /* PCI DMA Channel 3 */ | ||
| 33 | #define IRQ_IXP23XX_PCI_INT_RPH 11 /* pcxg_pci_int_rph */ | ||
| 34 | #define IRQ_IXP23XX_CPP_PMU 12 /* xpxg_pm_int_rpl */ | ||
| 35 | #define IRQ_IXP23XX_SWINT0 13 /* S/W Interrupt0 */ | ||
| 36 | #define IRQ_IXP23XX_SWINT1 14 /* S/W Interrupt1 */ | ||
| 37 | #define IRQ_IXP23XX_UART2 15 /* UART1 Interrupt */ | ||
| 38 | #define IRQ_IXP23XX_UART1 16 /* UART0 Interrupt */ | ||
| 39 | #define IRQ_IXP23XX_XSI_PMU_ROLLOVER 17 /* AHB Performance M. Unit counter rollover */ | ||
| 40 | #define IRQ_IXP23XX_XSI_AHB_PM0 18 /* intr_pm_o */ | ||
| 41 | #define IRQ_IXP23XX_XSI_AHB_ECE0 19 /* intr_ece_o */ | ||
| 42 | #define IRQ_IXP23XX_XSI_AHB_GASKET 20 /* gas_intr_o */ | ||
| 43 | #define IRQ_IXP23XX_XSI_CPP 21 /* xsi2cpp_int */ | ||
| 44 | #define IRQ_IXP23XX_CPP_XSI 22 /* cpp2xsi_int */ | ||
| 45 | #define IRQ_IXP23XX_ME_ATTN0 23 /* ME_ATTN */ | ||
| 46 | #define IRQ_IXP23XX_ME_ATTN1 24 /* ME_ATTN */ | ||
| 47 | #define IRQ_IXP23XX_ME_ATTN2 25 /* ME_ATTN */ | ||
| 48 | #define IRQ_IXP23XX_ME_ATTN3 26 /* ME_ATTN */ | ||
| 49 | #define IRQ_IXP23XX_PCI_ERR_RPH 27 /* PCXG_PCI_ERR_RPH */ | ||
| 50 | #define IRQ_IXP23XX_D0XG_ECC_CORR 28 /* D0XG_DRAM_ECC_CORR */ | ||
| 51 | #define IRQ_IXP23XX_D0XG_ECC_UNCORR 29 /* D0XG_DRAM_ECC_UNCORR */ | ||
| 52 | #define IRQ_IXP23XX_SRAM_ERR1 30 /* SRAM1_ERR */ | ||
| 53 | #define IRQ_IXP23XX_SRAM_ERR0 31 /* SRAM0_ERR */ | ||
| 54 | #define IRQ_IXP23XX_MEDIA_ERR 32 /* MEDIA_ERR */ | ||
| 55 | #define IRQ_IXP23XX_STH_DRAM_ECC_MAJ 33 /* STH_DRAM0_ECC_MAJ */ | ||
| 56 | #define IRQ_IXP23XX_GPIO6 34 /* GPIO0 interrupts */ | ||
| 57 | #define IRQ_IXP23XX_GPIO7 35 /* GPIO1 interrupts */ | ||
| 58 | #define IRQ_IXP23XX_GPIO8 36 /* GPIO2 interrupts */ | ||
| 59 | #define IRQ_IXP23XX_GPIO9 37 /* GPIO3 interrupts */ | ||
| 60 | #define IRQ_IXP23XX_GPIO10 38 /* GPIO4 interrupts */ | ||
| 61 | #define IRQ_IXP23XX_GPIO11 39 /* GPIO5 interrupts */ | ||
| 62 | #define IRQ_IXP23XX_GPIO12 40 /* GPIO6 interrupts */ | ||
| 63 | #define IRQ_IXP23XX_GPIO13 41 /* GPIO7 interrupts */ | ||
| 64 | #define IRQ_IXP23XX_GPIO14 42 /* GPIO8 interrupts */ | ||
| 65 | #define IRQ_IXP23XX_GPIO15 43 /* GPIO9 interrupts */ | ||
| 66 | #define IRQ_IXP23XX_SHAC_RING0 44 /* SHAC Ring Full */ | ||
| 67 | #define IRQ_IXP23XX_SHAC_RING1 45 /* SHAC Ring Full */ | ||
| 68 | #define IRQ_IXP23XX_SHAC_RING2 46 /* SHAC Ring Full */ | ||
| 69 | #define IRQ_IXP23XX_SHAC_RING3 47 /* SHAC Ring Full */ | ||
| 70 | #define IRQ_IXP23XX_SHAC_RING4 48 /* SHAC Ring Full */ | ||
| 71 | #define IRQ_IXP23XX_SHAC_RING5 49 /* SHAC Ring Full */ | ||
| 72 | #define IRQ_IXP23XX_SHAC_RING6 50 /* SHAC RING Full */ | ||
| 73 | #define IRQ_IXP23XX_SHAC_RING7 51 /* SHAC Ring Full */ | ||
| 74 | #define IRQ_IXP23XX_SHAC_RING8 52 /* SHAC Ring Full */ | ||
| 75 | #define IRQ_IXP23XX_SHAC_RING9 53 /* SHAC Ring Full */ | ||
| 76 | #define IRQ_IXP23XX_SHAC_RING10 54 /* SHAC Ring Full */ | ||
| 77 | #define IRQ_IXP23XX_SHAC_RING11 55 /* SHAC Ring Full */ | ||
| 78 | #define IRQ_IXP23XX_ME_THREAD_A0_ME0 56 /* ME_THREAD_A */ | ||
| 79 | #define IRQ_IXP23XX_ME_THREAD_A1_ME0 57 /* ME_THREAD_A */ | ||
| 80 | #define IRQ_IXP23XX_ME_THREAD_A2_ME0 58 /* ME_THREAD_A */ | ||
| 81 | #define IRQ_IXP23XX_ME_THREAD_A3_ME0 59 /* ME_THREAD_A */ | ||
| 82 | #define IRQ_IXP23XX_ME_THREAD_A4_ME0 60 /* ME_THREAD_A */ | ||
| 83 | #define IRQ_IXP23XX_ME_THREAD_A5_ME0 61 /* ME_THREAD_A */ | ||
| 84 | #define IRQ_IXP23XX_ME_THREAD_A6_ME0 62 /* ME_THREAD_A */ | ||
| 85 | #define IRQ_IXP23XX_ME_THREAD_A7_ME0 63 /* ME_THREAD_A */ | ||
| 86 | #define IRQ_IXP23XX_ME_THREAD_A8_ME1 64 /* ME_THREAD_A */ | ||
| 87 | #define IRQ_IXP23XX_ME_THREAD_A9_ME1 65 /* ME_THREAD_A */ | ||
| 88 | #define IRQ_IXP23XX_ME_THREAD_A10_ME1 66 /* ME_THREAD_A */ | ||
| 89 | #define IRQ_IXP23XX_ME_THREAD_A11_ME1 67 /* ME_THREAD_A */ | ||
| 90 | #define IRQ_IXP23XX_ME_THREAD_A12_ME1 68 /* ME_THREAD_A */ | ||
| 91 | #define IRQ_IXP23XX_ME_THREAD_A13_ME1 69 /* ME_THREAD_A */ | ||
| 92 | #define IRQ_IXP23XX_ME_THREAD_A14_ME1 70 /* ME_THREAD_A */ | ||
| 93 | #define IRQ_IXP23XX_ME_THREAD_A15_ME1 71 /* ME_THREAD_A */ | ||
| 94 | #define IRQ_IXP23XX_ME_THREAD_A16_ME2 72 /* ME_THREAD_A */ | ||
| 95 | #define IRQ_IXP23XX_ME_THREAD_A17_ME2 73 /* ME_THREAD_A */ | ||
| 96 | #define IRQ_IXP23XX_ME_THREAD_A18_ME2 74 /* ME_THREAD_A */ | ||
| 97 | #define IRQ_IXP23XX_ME_THREAD_A19_ME2 75 /* ME_THREAD_A */ | ||
| 98 | #define IRQ_IXP23XX_ME_THREAD_A20_ME2 76 /* ME_THREAD_A */ | ||
| 99 | #define IRQ_IXP23XX_ME_THREAD_A21_ME2 77 /* ME_THREAD_A */ | ||
| 100 | #define IRQ_IXP23XX_ME_THREAD_A22_ME2 78 /* ME_THREAD_A */ | ||
| 101 | #define IRQ_IXP23XX_ME_THREAD_A23_ME2 79 /* ME_THREAD_A */ | ||
| 102 | #define IRQ_IXP23XX_ME_THREAD_A24_ME3 80 /* ME_THREAD_A */ | ||
| 103 | #define IRQ_IXP23XX_ME_THREAD_A25_ME3 81 /* ME_THREAD_A */ | ||
| 104 | #define IRQ_IXP23XX_ME_THREAD_A26_ME3 82 /* ME_THREAD_A */ | ||
| 105 | #define IRQ_IXP23XX_ME_THREAD_A27_ME3 83 /* ME_THREAD_A */ | ||
| 106 | #define IRQ_IXP23XX_ME_THREAD_A28_ME3 84 /* ME_THREAD_A */ | ||
| 107 | #define IRQ_IXP23XX_ME_THREAD_A29_ME3 85 /* ME_THREAD_A */ | ||
| 108 | #define IRQ_IXP23XX_ME_THREAD_A30_ME3 86 /* ME_THREAD_A */ | ||
| 109 | #define IRQ_IXP23XX_ME_THREAD_A31_ME3 87 /* ME_THREAD_A */ | ||
| 110 | #define IRQ_IXP23XX_ME_THREAD_B0_ME0 88 /* ME_THREAD_B */ | ||
| 111 | #define IRQ_IXP23XX_ME_THREAD_B1_ME0 89 /* ME_THREAD_B */ | ||
| 112 | #define IRQ_IXP23XX_ME_THREAD_B2_ME0 90 /* ME_THREAD_B */ | ||
| 113 | #define IRQ_IXP23XX_ME_THREAD_B3_ME0 91 /* ME_THREAD_B */ | ||
| 114 | #define IRQ_IXP23XX_ME_THREAD_B4_ME0 92 /* ME_THREAD_B */ | ||
| 115 | #define IRQ_IXP23XX_ME_THREAD_B5_ME0 93 /* ME_THREAD_B */ | ||
| 116 | #define IRQ_IXP23XX_ME_THREAD_B6_ME0 94 /* ME_THREAD_B */ | ||
| 117 | #define IRQ_IXP23XX_ME_THREAD_B7_ME0 95 /* ME_THREAD_B */ | ||
| 118 | #define IRQ_IXP23XX_ME_THREAD_B8_ME1 96 /* ME_THREAD_B */ | ||
| 119 | #define IRQ_IXP23XX_ME_THREAD_B9_ME1 97 /* ME_THREAD_B */ | ||
| 120 | #define IRQ_IXP23XX_ME_THREAD_B10_ME1 98 /* ME_THREAD_B */ | ||
| 121 | #define IRQ_IXP23XX_ME_THREAD_B11_ME1 99 /* ME_THREAD_B */ | ||
| 122 | #define IRQ_IXP23XX_ME_THREAD_B12_ME1 100 /* ME_THREAD_B */ | ||
| 123 | #define IRQ_IXP23XX_ME_THREAD_B13_ME1 101 /* ME_THREAD_B */ | ||
| 124 | #define IRQ_IXP23XX_ME_THREAD_B14_ME1 102 /* ME_THREAD_B */ | ||
| 125 | #define IRQ_IXP23XX_ME_THREAD_B15_ME1 103 /* ME_THREAD_B */ | ||
| 126 | #define IRQ_IXP23XX_ME_THREAD_B16_ME2 104 /* ME_THREAD_B */ | ||
| 127 | #define IRQ_IXP23XX_ME_THREAD_B17_ME2 105 /* ME_THREAD_B */ | ||
| 128 | #define IRQ_IXP23XX_ME_THREAD_B18_ME2 106 /* ME_THREAD_B */ | ||
| 129 | #define IRQ_IXP23XX_ME_THREAD_B19_ME2 107 /* ME_THREAD_B */ | ||
| 130 | #define IRQ_IXP23XX_ME_THREAD_B20_ME2 108 /* ME_THREAD_B */ | ||
| 131 | #define IRQ_IXP23XX_ME_THREAD_B21_ME2 109 /* ME_THREAD_B */ | ||
| 132 | #define IRQ_IXP23XX_ME_THREAD_B22_ME2 110 /* ME_THREAD_B */ | ||
| 133 | #define IRQ_IXP23XX_ME_THREAD_B23_ME2 111 /* ME_THREAD_B */ | ||
| 134 | #define IRQ_IXP23XX_ME_THREAD_B24_ME3 112 /* ME_THREAD_B */ | ||
| 135 | #define IRQ_IXP23XX_ME_THREAD_B25_ME3 113 /* ME_THREAD_B */ | ||
| 136 | #define IRQ_IXP23XX_ME_THREAD_B26_ME3 114 /* ME_THREAD_B */ | ||
| 137 | #define IRQ_IXP23XX_ME_THREAD_B27_ME3 115 /* ME_THREAD_B */ | ||
| 138 | #define IRQ_IXP23XX_ME_THREAD_B28_ME3 116 /* ME_THREAD_B */ | ||
| 139 | #define IRQ_IXP23XX_ME_THREAD_B29_ME3 117 /* ME_THREAD_B */ | ||
| 140 | #define IRQ_IXP23XX_ME_THREAD_B30_ME3 118 /* ME_THREAD_B */ | ||
| 141 | #define IRQ_IXP23XX_ME_THREAD_B31_ME3 119 /* ME_THREAD_B */ | ||
| 142 | |||
| 143 | #define NUM_IXP23XX_RAW_IRQS 120 | ||
| 144 | |||
| 145 | #define IRQ_IXP23XX_INTA 120 /* Indirect pcxg_pci_int_rph */ | ||
| 146 | #define IRQ_IXP23XX_INTB 121 /* Indirect pcxg_pci_int_rph */ | ||
| 147 | |||
| 148 | #define NR_IXP23XX_IRQ (IRQ_IXP23XX_INTB + 1) | ||
| 149 | |||
| 150 | /* | ||
| 151 | * We default to 32 per-board IRQs. Increase this number if you need | ||
| 152 | * more, but keep it realistic. | ||
| 153 | */ | ||
| 154 | #define NR_IXP23XX_MACH_IRQS 32 | ||
| 155 | |||
| 156 | #define NR_IRQS NR_IXP23XX_IRQS + NR_IXP23XX_MACH_IRQS | ||
| 157 | |||
| 158 | #define IXP23XX_MACH_IRQ(irq) (NR_IXP23XX_IRQ + (irq)) | ||
| 159 | |||
| 160 | |||
| 161 | /* | ||
| 162 | * IXDP2351-specific interrupts | ||
| 163 | */ | ||
| 164 | |||
| 165 | /* | ||
| 166 | * External PCI interrupts signaled through INTB | ||
| 167 | * | ||
| 168 | */ | ||
| 169 | #define IXDP2351_INTB_IRQ_BASE 0 | ||
| 170 | #define IRQ_IXDP2351_INTA_82546 IXP23XX_MACH_IRQ(0) | ||
| 171 | #define IRQ_IXDP2351_INTB_82546 IXP23XX_MACH_IRQ(1) | ||
| 172 | #define IRQ_IXDP2351_SPCI_DB_0 IXP23XX_MACH_IRQ(2) | ||
| 173 | #define IRQ_IXDP2351_SPCI_DB_1 IXP23XX_MACH_IRQ(3) | ||
| 174 | #define IRQ_IXDP2351_SPCI_PMC_INTA IXP23XX_MACH_IRQ(4) | ||
| 175 | #define IRQ_IXDP2351_SPCI_PMC_INTB IXP23XX_MACH_IRQ(5) | ||
| 176 | #define IRQ_IXDP2351_SPCI_PMC_INTC IXP23XX_MACH_IRQ(6) | ||
| 177 | #define IRQ_IXDP2351_SPCI_PMC_INTD IXP23XX_MACH_IRQ(7) | ||
| 178 | #define IRQ_IXDP2351_SPCI_FIC IXP23XX_MACH_IRQ(8) | ||
| 179 | |||
| 180 | #define IXDP2351_INTB_IRQ_BIT(irq) (irq - IXP23XX_MACH_IRQ(0)) | ||
| 181 | #define IXDP2351_INTB_IRQ_MASK(irq) (1 << IXDP2351_INTB_IRQ_BIT(irq)) | ||
| 182 | #define IXDP2351_INTB_IRQ_VALID 0x01FF | ||
| 183 | #define IXDP2351_INTB_IRQ_NUM 16 | ||
| 184 | |||
| 185 | /* | ||
| 186 | * Other external interrupts signaled through INTA | ||
| 187 | */ | ||
| 188 | #define IXDP2351_INTA_IRQ_BASE 16 | ||
| 189 | #define IRQ_IXDP2351_IPMI_FROM IXP23XX_MACH_IRQ(16) | ||
| 190 | #define IRQ_IXDP2351_125US IXP23XX_MACH_IRQ(17) | ||
| 191 | #define IRQ_IXDP2351_DB_0_ADD IXP23XX_MACH_IRQ(18) | ||
| 192 | #define IRQ_IXDP2351_DB_1_ADD IXP23XX_MACH_IRQ(19) | ||
| 193 | #define IRQ_IXDP2351_DEBUG1 IXP23XX_MACH_IRQ(20) | ||
| 194 | #define IRQ_IXDP2351_ADD_UART IXP23XX_MACH_IRQ(21) | ||
| 195 | #define IRQ_IXDP2351_FIC_ADD IXP23XX_MACH_IRQ(24) | ||
| 196 | #define IRQ_IXDP2351_CS8900 IXP23XX_MACH_IRQ(25) | ||
| 197 | #define IRQ_IXDP2351_BBSRAM IXP23XX_MACH_IRQ(26) | ||
| 198 | #define IRQ_IXDP2351_CONFIG_MEDIA IXP23XX_MACH_IRQ(27) | ||
| 199 | #define IRQ_IXDP2351_CLOCK_REF IXP23XX_MACH_IRQ(28) | ||
| 200 | #define IRQ_IXDP2351_A10_NP IXP23XX_MACH_IRQ(29) | ||
| 201 | #define IRQ_IXDP2351_A11_NP IXP23XX_MACH_IRQ(30) | ||
| 202 | #define IRQ_IXDP2351_DEBUG_NP IXP23XX_MACH_IRQ(31) | ||
| 203 | |||
| 204 | #define IXDP2351_INTA_IRQ_BIT(irq) (irq - IXP23XX_MACH_IRQ(16)) | ||
| 205 | #define IXDP2351_INTA_IRQ_MASK(irq) (1 << IXDP2351_INTA_IRQ_BIT(irq)) | ||
| 206 | #define IXDP2351_INTA_IRQ_VALID 0xFF3F | ||
| 207 | #define IXDP2351_INTA_IRQ_NUM 16 | ||
| 208 | |||
| 209 | |||
| 210 | /* | ||
| 211 | * ADI RoadRunner IRQs | ||
| 212 | */ | ||
| 213 | #define IRQ_ROADRUNNER_PCI_INTA IRQ_IXP23XX_INTA | ||
| 214 | #define IRQ_ROADRUNNER_PCI_INTB IRQ_IXP23XX_INTB | ||
| 215 | #define IRQ_ROADRUNNER_PCI_INTC IRQ_IXP23XX_GPIO11 | ||
| 216 | #define IRQ_ROADRUNNER_PCI_INTD IRQ_IXP23XX_GPIO12 | ||
| 217 | |||
| 218 | /* | ||
| 219 | * Put new board definitions here | ||
| 220 | */ | ||
| 221 | |||
| 222 | |||
| 223 | #endif | ||
diff --git a/include/asm-arm/arch-ixp23xx/ixdp2351.h b/include/asm-arm/arch-ixp23xx/ixdp2351.h new file mode 100644 index 000000000000..4a24f8f15655 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/ixdp2351.h | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/ixdp2351.h | ||
| 3 | * | ||
| 4 | * Register and other defines for IXDP2351 | ||
| 5 | * | ||
| 6 | * Copyright (c) 2002-2004 Intel Corp. | ||
| 7 | * Copytight (c) 2005 MontaVista Software, Inc. | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify it | ||
| 10 | * under the terms of the GNU General Public License as published by the | ||
| 11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 12 | * option) any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef __ASM_ARCH_IXDP2351_H | ||
| 16 | #define __ASM_ARCH_IXDP2351_H | ||
| 17 | |||
| 18 | /* | ||
| 19 | * NP module memory map | ||
| 20 | */ | ||
| 21 | #define IXDP2351_NP_PHYS_BASE (IXP23XX_EXP_BUS_CS4_BASE) | ||
| 22 | #define IXDP2351_NP_PHYS_SIZE 0x00100000 | ||
| 23 | #define IXDP2351_NP_VIRT_BASE 0xeff00000 | ||
| 24 | |||
| 25 | #define IXDP2351_VIRT_CS8900_BASE (IXDP2351_NP_VIRT_BASE) | ||
| 26 | #define IXDP2351_VIRT_CS8900_END (IXDP2351_VIRT_CS8900_BASE + 16) | ||
| 27 | |||
| 28 | #define IXDP2351_VIRT_NP_CPLD_BASE (IXP23XX_EXP_BUS_CS4_BASE_VIRT + 0x00010000) | ||
| 29 | |||
| 30 | #define IXDP2351_NP_CPLD_REG(reg) ((volatile u16 *)(IXDP2351_VIRT_NP_CPLD_BASE + reg)) | ||
| 31 | |||
| 32 | #define IXDP2351_NP_CPLD_RESET1_REG IXDP2351_NP_CPLD_REG(0x00) | ||
| 33 | #define IXDP2351_NP_CPLD_LED_REG IXDP2351_NP_CPLD_REG(0x02) | ||
| 34 | #define IXDP2351_NP_CPLD_VERSION_REG IXDP2351_NP_CPLD_REG(0x04) | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Base board module memory map | ||
| 38 | */ | ||
| 39 | |||
| 40 | #define IXDP2351_BB_BASE_PHYS (IXP23XX_EXP_BUS_CS5_BASE) | ||
| 41 | #define IXDP2351_BB_SIZE 0x01000000 | ||
| 42 | #define IXDP2351_BB_BASE_VIRT (0xee000000) | ||
| 43 | |||
| 44 | #define IXDP2351_BB_AREA_BASE(offset) (IXDP2351_BB_BASE_VIRT + offset) | ||
| 45 | |||
| 46 | #define IXDP2351_VIRT_NVRAM_BASE IXDP2351_BB_AREA_BASE(0x0) | ||
| 47 | #define IXDP2351_NVRAM_SIZE (0x20000) | ||
| 48 | |||
| 49 | #define IXDP2351_VIRT_MB_IXF1104_BASE IXDP3251_BB_AREA_BASE(0x00020000) | ||
| 50 | #define IXDP2351_VIRT_ADD_UART_BASE IXDP2351_BB_AREA_BASE(0x000240C0) | ||
| 51 | #define IXDP2351_VIRT_FIC_BASE IXDP2351_BB_AREA_BASE(0x00200000) | ||
| 52 | #define IXDP2351_VIRT_DB0_BASE IXDP2351_BB_AREA_BASE(0x00400000) | ||
| 53 | #define IXDP2351_VIRT_DB1_BASE IXDP2351_BB_AREA_BASE(0x00600000) | ||
| 54 | #define IXDP2351_VIRT_CPLD_BASE IXDP2351_BB_AREA_BASE(0x00024000) | ||
| 55 | |||
| 56 | /* | ||
| 57 | * On board CPLD registers | ||
| 58 | */ | ||
| 59 | #define IXDP2351_CPLD_BB_REG(reg) ((volatile u16 *)(IXDP2351_VIRT_CPLD_BASE + reg)) | ||
| 60 | |||
| 61 | #define IXDP2351_CPLD_RESET0_REG IXDP2351_CPLD_BB_REG(0x00) | ||
| 62 | #define IXDP2351_CPLD_RESET1_REG IXDP2351_CPLD_BB_REG(0x04) | ||
| 63 | |||
| 64 | #define IXDP2351_CPLD_RESET1_MAGIC 0x55AA | ||
| 65 | #define IXDP2351_CPLD_RESET1_ENABLE 0x8000 | ||
| 66 | |||
| 67 | #define IXDP2351_CPLD_FPGA_CONFIG_REG IXDP2351_CPLD_BB_REG(0x08) | ||
| 68 | #define IXDP2351_CPLD_INTB_MASK_SET_REG IXDP2351_CPLD_BB_REG(0x10) | ||
| 69 | #define IXDP2351_CPLD_INTA_MASK_SET_REG IXDP2351_CPLD_BB_REG(0x14) | ||
| 70 | #define IXDP2351_CPLD_INTB_STAT_REG IXDP2351_CPLD_BB_REG(0x18) | ||
| 71 | #define IXDP2351_CPLD_INTA_STAT_REG IXDP2351_CPLD_BB_REG(0x1C) | ||
| 72 | #define IXDP2351_CPLD_INTB_RAW_REG IXDP2351_CPLD_BB_REG(0x20) /* read */ | ||
| 73 | #define IXDP2351_CPLD_INTA_RAW_REG IXDP2351_CPLD_BB_REG(0x24) /* read */ | ||
| 74 | #define IXDP2351_CPLD_INTB_MASK_CLR_REG IXDP2351_CPLD_INTB_RAW_REG /* write */ | ||
| 75 | #define IXDP2351_CPLD_INTA_MASK_CLR_REG IXDP2351_CPLD_INTA_RAW_REG /* write */ | ||
| 76 | #define IXDP2351_CPLD_INTB_SIM_REG IXDP2351_CPLD_BB_REG(0x28) | ||
| 77 | #define IXDP2351_CPLD_INTA_SIM_REG IXDP2351_CPLD_BB_REG(0x2C) | ||
| 78 | /* Interrupt bits are defined in irqs.h */ | ||
| 79 | #define IXDP2351_CPLD_BB_GBE0_REG IXDP2351_CPLD_BB_REG(0x30) | ||
| 80 | #define IXDP2351_CPLD_BB_GBE1_REG IXDP2351_CPLD_BB_REG(0x34) | ||
| 81 | |||
| 82 | /* #define IXDP2351_CPLD_BB_MISC_REG IXDP2351_CPLD_REG(0x1C) */ | ||
| 83 | /* #define IXDP2351_CPLD_BB_MISC_REV_MASK 0xFF */ | ||
| 84 | /* #define IXDP2351_CPLD_BB_GDXCS0_REG IXDP2351_CPLD_REG(0x24) */ | ||
| 85 | /* #define IXDP2351_CPLD_BB_GDXCS1_REG IXDP2351_CPLD_REG(0x28) */ | ||
| 86 | /* #define IXDP2351_CPLD_BB_CLOCK_REG IXDP2351_CPLD_REG(0x04) */ | ||
| 87 | |||
| 88 | |||
| 89 | #endif | ||
diff --git a/include/asm-arm/arch-ixp23xx/ixp23xx.h b/include/asm-arm/arch-ixp23xx/ixp23xx.h new file mode 100644 index 000000000000..e49e1ca61b1a --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/ixp23xx.h | |||
| @@ -0,0 +1,306 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/ixp23xx.h | ||
| 3 | * | ||
| 4 | * Register definitions for IXP23XX | ||
| 5 | * | ||
| 6 | * Copyright (C) 2003-2005 Intel Corporation. | ||
| 7 | * Copyright (C) 2005 MontaVista Software, Inc. | ||
| 8 | * | ||
| 9 | * Maintainer: Deepak Saxena <dsaxena@plexity.net> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | ||
| 12 | * it under the terms of the GNU General Public License version 2 as | ||
| 13 | * published by the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef __ASM_ARCH_IXP23XX_H | ||
| 17 | #define __ASM_ARCH_IXP23XX_H | ||
| 18 | |||
| 19 | /* | ||
| 20 | * IXP2300 linux memory map: | ||
| 21 | * | ||
| 22 | * virt phys size | ||
| 23 | * fffd0000 a0000000 64K XSI2CPP_CSR | ||
| 24 | * fffc0000 c4000000 4K EXP_CFG | ||
| 25 | * fff00000 c8000000 64K PERIPHERAL | ||
| 26 | * fe000000 1c0000000 16M CAP_CSR | ||
| 27 | * fd000000 1c8000000 16M MSF_CSR | ||
| 28 | * fb000000 16M --- | ||
| 29 | * fa000000 1d8000000 32M PCI_IO | ||
| 30 | * f8000000 1da000000 32M PCI_CFG | ||
| 31 | * f6000000 1de000000 32M PCI_CREG | ||
| 32 | * f4000000 32M --- | ||
| 33 | * f0000000 1e0000000 64M PCI_MEM | ||
| 34 | * e[c-f]000000 per-platform mappings | ||
| 35 | */ | ||
| 36 | |||
| 37 | |||
| 38 | /**************************************************************************** | ||
| 39 | * Static mappings. | ||
| 40 | ****************************************************************************/ | ||
| 41 | #define IXP23XX_XSI2CPP_CSR_PHYS 0xa0000000 | ||
| 42 | #define IXP23XX_XSI2CPP_CSR_VIRT 0xfffd0000 | ||
| 43 | #define IXP23XX_XSI2CPP_CSR_SIZE 0x00010000 | ||
| 44 | |||
| 45 | #define IXP23XX_EXP_CFG_PHYS 0xc4000000 | ||
| 46 | #define IXP23XX_EXP_CFG_VIRT 0xfffc0000 | ||
| 47 | #define IXP23XX_EXP_CFG_SIZE 0x00001000 | ||
| 48 | |||
| 49 | #define IXP23XX_PERIPHERAL_PHYS 0xc8000000 | ||
| 50 | #define IXP23XX_PERIPHERAL_VIRT 0xfff00000 | ||
| 51 | #define IXP23XX_PERIPHERAL_SIZE 0x00010000 | ||
| 52 | |||
| 53 | #define IXP23XX_CAP_CSR_PHYS 0x1c0000000ULL | ||
| 54 | #define IXP23XX_CAP_CSR_VIRT 0xfe000000 | ||
| 55 | #define IXP23XX_CAP_CSR_SIZE 0x01000000 | ||
| 56 | |||
| 57 | #define IXP23XX_MSF_CSR_PHYS 0x1c8000000ULL | ||
| 58 | #define IXP23XX_MSF_CSR_VIRT 0xfd000000 | ||
| 59 | #define IXP23XX_MSF_CSR_SIZE 0x01000000 | ||
| 60 | |||
| 61 | #define IXP23XX_PCI_IO_PHYS 0x1d8000000ULL | ||
| 62 | #define IXP23XX_PCI_IO_VIRT 0xfa000000 | ||
| 63 | #define IXP23XX_PCI_IO_SIZE 0x02000000 | ||
| 64 | |||
| 65 | #define IXP23XX_PCI_CFG_PHYS 0x1da000000ULL | ||
| 66 | #define IXP23XX_PCI_CFG_VIRT 0xf8000000 | ||
| 67 | #define IXP23XX_PCI_CFG_SIZE 0x02000000 | ||
| 68 | #define IXP23XX_PCI_CFG0_VIRT IXP23XX_PCI_CFG_VIRT | ||
| 69 | #define IXP23XX_PCI_CFG1_VIRT (IXP23XX_PCI_CFG_VIRT + 0x01000000) | ||
| 70 | |||
| 71 | #define IXP23XX_PCI_CREG_PHYS 0x1de000000ULL | ||
| 72 | #define IXP23XX_PCI_CREG_VIRT 0xf6000000 | ||
| 73 | #define IXP23XX_PCI_CREG_SIZE 0x02000000 | ||
| 74 | #define IXP23XX_PCI_CSR_VIRT (IXP23XX_PCI_CREG_VIRT + 0x01000000) | ||
| 75 | |||
| 76 | #define IXP23XX_PCI_MEM_START 0xe0000000 | ||
| 77 | #define IXP23XX_PCI_MEM_PHYS 0x1e0000000ULL | ||
| 78 | #define IXP23XX_PCI_MEM_VIRT 0xf0000000 | ||
| 79 | #define IXP23XX_PCI_MEM_SIZE 0x04000000 | ||
| 80 | |||
| 81 | |||
| 82 | /**************************************************************************** | ||
| 83 | * XSI2CPP CSRs. | ||
| 84 | ****************************************************************************/ | ||
| 85 | #define IXP23XX_XSI2CPP_REG(x) ((volatile unsigned long *)(IXP23XX_XSI2CPP_CSR_VIRT + (x))) | ||
| 86 | #define IXP23XX_CPP2XSI_CURR_XFER_REG3 IXP23XX_XSI2CPP_REG(0xf8) | ||
| 87 | #define IXP23XX_CPP2XSI_ADDR_31 (1 << 19) | ||
| 88 | #define IXP23XX_CPP2XSI_PSH_OFF (1 << 20) | ||
| 89 | #define IXP23XX_CPP2XSI_COH_OFF (1 << 21) | ||
| 90 | |||
| 91 | |||
| 92 | /**************************************************************************** | ||
| 93 | * Expansion Bus Config. | ||
| 94 | ****************************************************************************/ | ||
| 95 | #define IXP23XX_EXP_CFG_REG(x) ((volatile unsigned long *)(IXP23XX_EXP_CFG_VIRT + (x))) | ||
| 96 | #define IXP23XX_EXP_CS0 IXP23XX_EXP_CFG_REG(0x00) | ||
| 97 | #define IXP23XX_EXP_CS1 IXP23XX_EXP_CFG_REG(0x04) | ||
| 98 | #define IXP23XX_EXP_CS2 IXP23XX_EXP_CFG_REG(0x08) | ||
| 99 | #define IXP23XX_EXP_CS3 IXP23XX_EXP_CFG_REG(0x0c) | ||
| 100 | #define IXP23XX_EXP_CS4 IXP23XX_EXP_CFG_REG(0x10) | ||
| 101 | #define IXP23XX_EXP_CS5 IXP23XX_EXP_CFG_REG(0x14) | ||
| 102 | #define IXP23XX_EXP_CS6 IXP23XX_EXP_CFG_REG(0x18) | ||
| 103 | #define IXP23XX_EXP_CS7 IXP23XX_EXP_CFG_REG(0x1c) | ||
| 104 | #define IXP23XX_FLASH_WRITABLE (0x2) | ||
| 105 | #define IXP23XX_FLASH_BUS8 (0x1) | ||
| 106 | |||
| 107 | #define IXP23XX_EXP_CFG0 IXP23XX_EXP_CFG_REG(0x20) | ||
| 108 | #define IXP23XX_EXP_CFG1 IXP23XX_EXP_CFG_REG(0x24) | ||
| 109 | #define IXP23XX_EXP_CFG0_MEM_MAP (1 << 31) | ||
| 110 | #define IXP23XX_EXP_CFG0_XSCALE_SPEED_SEL (3 << 22) | ||
| 111 | #define IXP23XX_EXP_CFG0_XSCALE_SPEED_EN (1 << 21) | ||
| 112 | #define IXP23XX_EXP_CFG0_CPP_SPEED_SEL (3 << 19) | ||
| 113 | #define IXP23XX_EXP_CFG0_CPP_SPEED_EN (1 << 18) | ||
| 114 | #define IXP23XX_EXP_CFG0_PCI_SWIN (3 << 16) | ||
| 115 | #define IXP23XX_EXP_CFG0_PCI_DWIN (3 << 14) | ||
| 116 | #define IXP23XX_EXP_CFG0_PCI33_MODE (1 << 13) | ||
| 117 | #define IXP23XX_EXP_CFG0_QDR_SPEED_SEL (1 << 12) | ||
| 118 | #define IXP23XX_EXP_CFG0_CPP_DIV_SEL (1 << 5) | ||
| 119 | #define IXP23XX_EXP_CFG0_XSI_NOT_PRES (1 << 4) | ||
| 120 | #define IXP23XX_EXP_CFG0_PROM_BOOT (1 << 3) | ||
| 121 | #define IXP23XX_EXP_CFG0_PCI_ARB (1 << 2) | ||
| 122 | #define IXP23XX_EXP_CFG0_PCI_HOST (1 << 1) | ||
| 123 | #define IXP23XX_EXP_CFG0_FLASH_WIDTH (1 << 0) | ||
| 124 | |||
| 125 | #define IXP23XX_EXP_UNIT_FUSE IXP23XX_EXP_CFG_REG(0x28) | ||
| 126 | #define IXP23XX_EXP_MSF_MUX IXP23XX_EXP_CFG_REG(0x30) | ||
| 127 | |||
| 128 | #define IXP23XX_EXP_BUS_PHYS 0x90000000 | ||
| 129 | #define IXP23XX_EXP_BUS_WINDOW_SIZE 0x01000000 | ||
| 130 | |||
| 131 | #define IXP23XX_EXP_BUS_CS0_BASE (IXP23XX_EXP_BUS_PHYS + 0x00000000) | ||
| 132 | #define IXP23XX_EXP_BUS_CS1_BASE (IXP23XX_EXP_BUS_PHYS + 0x01000000) | ||
| 133 | #define IXP23XX_EXP_BUS_CS2_BASE (IXP23XX_EXP_BUS_PHYS + 0x02000000) | ||
| 134 | #define IXP23XX_EXP_BUS_CS3_BASE (IXP23XX_EXP_BUS_PHYS + 0x03000000) | ||
| 135 | #define IXP23XX_EXP_BUS_CS4_BASE (IXP23XX_EXP_BUS_PHYS + 0x04000000) | ||
| 136 | #define IXP23XX_EXP_BUS_CS5_BASE (IXP23XX_EXP_BUS_PHYS + 0x05000000) | ||
| 137 | #define IXP23XX_EXP_BUS_CS6_BASE (IXP23XX_EXP_BUS_PHYS + 0x06000000) | ||
| 138 | #define IXP23XX_EXP_BUS_CS7_BASE (IXP23XX_EXP_BUS_PHYS + 0x07000000) | ||
| 139 | |||
| 140 | |||
| 141 | /**************************************************************************** | ||
| 142 | * Peripherals. | ||
| 143 | ****************************************************************************/ | ||
| 144 | #define IXP23XX_UART1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x0000) | ||
| 145 | #define IXP23XX_UART2_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x1000) | ||
| 146 | #define IXP23XX_PMU_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x2000) | ||
| 147 | #define IXP23XX_INTC_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x3000) | ||
| 148 | #define IXP23XX_GPIO_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x4000) | ||
| 149 | #define IXP23XX_TIMER_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x5000) | ||
| 150 | #define IXP23XX_NPE0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x6000) | ||
| 151 | #define IXP23XX_DSR_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x7000) | ||
| 152 | #define IXP23XX_NPE1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x8000) | ||
| 153 | #define IXP23XX_ETH0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0x9000) | ||
| 154 | #define IXP23XX_ETH1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xA000) | ||
| 155 | #define IXP23XX_GIG0_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xB000) | ||
| 156 | #define IXP23XX_GIG1_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xC000) | ||
| 157 | #define IXP23XX_DDRS_VIRT (IXP23XX_PERIPHERAL_VIRT + 0xD000) | ||
| 158 | |||
| 159 | #define IXP23XX_UART1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x0000) | ||
| 160 | #define IXP23XX_UART2_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x1000) | ||
| 161 | #define IXP23XX_PMU_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x2000) | ||
| 162 | #define IXP23XX_INTC_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x3000) | ||
| 163 | #define IXP23XX_GPIO_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x4000) | ||
| 164 | #define IXP23XX_TIMER_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x5000) | ||
| 165 | #define IXP23XX_NPE0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x6000) | ||
| 166 | #define IXP23XX_DSR_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x7000) | ||
| 167 | #define IXP23XX_NPE1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x8000) | ||
| 168 | #define IXP23XX_ETH0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0x9000) | ||
| 169 | #define IXP23XX_ETH1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xA000) | ||
| 170 | #define IXP23XX_GIG0_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xB000) | ||
| 171 | #define IXP23XX_GIG1_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xC000) | ||
| 172 | #define IXP23XX_DDRS_PHYS (IXP23XX_PERIPHERAL_PHYS + 0xD000) | ||
| 173 | |||
| 174 | |||
| 175 | /**************************************************************************** | ||
| 176 | * Interrupt controller. | ||
| 177 | ****************************************************************************/ | ||
| 178 | #define IXP23XX_INTC_REG(x) ((volatile unsigned long *)(IXP23XX_INTC_VIRT + (x))) | ||
| 179 | #define IXP23XX_INTR_ST1 IXP23XX_INTC_REG(0x00) | ||
| 180 | #define IXP23XX_INTR_ST2 IXP23XX_INTC_REG(0x04) | ||
| 181 | #define IXP23XX_INTR_ST3 IXP23XX_INTC_REG(0x08) | ||
| 182 | #define IXP23XX_INTR_ST4 IXP23XX_INTC_REG(0x0c) | ||
| 183 | #define IXP23XX_INTR_EN1 IXP23XX_INTC_REG(0x10) | ||
| 184 | #define IXP23XX_INTR_EN2 IXP23XX_INTC_REG(0x14) | ||
| 185 | #define IXP23XX_INTR_EN3 IXP23XX_INTC_REG(0x18) | ||
| 186 | #define IXP23XX_INTR_EN4 IXP23XX_INTC_REG(0x1c) | ||
| 187 | #define IXP23XX_INTR_SEL1 IXP23XX_INTC_REG(0x20) | ||
| 188 | #define IXP23XX_INTR_SEL2 IXP23XX_INTC_REG(0x24) | ||
| 189 | #define IXP23XX_INTR_SEL3 IXP23XX_INTC_REG(0x28) | ||
| 190 | #define IXP23XX_INTR_SEL4 IXP23XX_INTC_REG(0x2c) | ||
| 191 | #define IXP23XX_INTR_IRQ_ST1 IXP23XX_INTC_REG(0x30) | ||
| 192 | #define IXP23XX_INTR_IRQ_ST2 IXP23XX_INTC_REG(0x34) | ||
| 193 | #define IXP23XX_INTR_IRQ_ST3 IXP23XX_INTC_REG(0x38) | ||
| 194 | #define IXP23XX_INTR_IRQ_ST4 IXP23XX_INTC_REG(0x3c) | ||
| 195 | #define IXP23XX_INTR_IRQ_ENC_ST_OFFSET 0x54 | ||
| 196 | |||
| 197 | |||
| 198 | /**************************************************************************** | ||
| 199 | * GPIO. | ||
| 200 | ****************************************************************************/ | ||
| 201 | #define IXP23XX_GPIO_REG(x) ((volatile unsigned long *)(IXP23XX_GPIO_VIRT + (x))) | ||
| 202 | #define IXP23XX_GPIO_GPOUTR IXP23XX_GPIO_REG(0x00) | ||
| 203 | #define IXP23XX_GPIO_GPOER IXP23XX_GPIO_REG(0x04) | ||
| 204 | #define IXP23XX_GPIO_GPINR IXP23XX_GPIO_REG(0x08) | ||
| 205 | #define IXP23XX_GPIO_GPISR IXP23XX_GPIO_REG(0x0c) | ||
| 206 | #define IXP23XX_GPIO_GPIT1R IXP23XX_GPIO_REG(0x10) | ||
| 207 | #define IXP23XX_GPIO_GPIT2R IXP23XX_GPIO_REG(0x14) | ||
| 208 | #define IXP23XX_GPIO_GPCLKR IXP23XX_GPIO_REG(0x18) | ||
| 209 | #define IXP23XX_GPIO_GPDBSELR IXP23XX_GPIO_REG(0x1c) | ||
| 210 | |||
| 211 | #define IXP23XX_GPIO_STYLE_MASK 0x7 | ||
| 212 | #define IXP23XX_GPIO_STYLE_ACTIVE_HIGH 0x0 | ||
| 213 | #define IXP23XX_GPIO_STYLE_ACTIVE_LOW 0x1 | ||
| 214 | #define IXP23XX_GPIO_STYLE_RISING_EDGE 0x2 | ||
| 215 | #define IXP23XX_GPIO_STYLE_FALLING_EDGE 0x3 | ||
| 216 | #define IXP23XX_GPIO_STYLE_TRANSITIONAL 0x4 | ||
| 217 | |||
| 218 | #define IXP23XX_GPIO_STYLE_SIZE 3 | ||
| 219 | |||
| 220 | |||
| 221 | /**************************************************************************** | ||
| 222 | * Timer. | ||
| 223 | ****************************************************************************/ | ||
| 224 | #define IXP23XX_TIMER_REG(x) ((volatile unsigned long *)(IXP23XX_TIMER_VIRT + (x))) | ||
| 225 | #define IXP23XX_TIMER_CONT IXP23XX_TIMER_REG(0x00) | ||
| 226 | #define IXP23XX_TIMER1_TIMESTAMP IXP23XX_TIMER_REG(0x04) | ||
| 227 | #define IXP23XX_TIMER1_RELOAD IXP23XX_TIMER_REG(0x08) | ||
| 228 | #define IXP23XX_TIMER2_TIMESTAMP IXP23XX_TIMER_REG(0x0c) | ||
| 229 | #define IXP23XX_TIMER2_RELOAD IXP23XX_TIMER_REG(0x10) | ||
| 230 | #define IXP23XX_TIMER_WDOG IXP23XX_TIMER_REG(0x14) | ||
| 231 | #define IXP23XX_TIMER_WDOG_EN IXP23XX_TIMER_REG(0x18) | ||
| 232 | #define IXP23XX_TIMER_WDOG_KEY IXP23XX_TIMER_REG(0x1c) | ||
| 233 | #define IXP23XX_TIMER_WDOG_KEY_MAGIC 0x482e | ||
| 234 | #define IXP23XX_TIMER_STATUS IXP23XX_TIMER_REG(0x20) | ||
| 235 | #define IXP23XX_TIMER_SOFT_RESET IXP23XX_TIMER_REG(0x24) | ||
| 236 | #define IXP23XX_TIMER_SOFT_RESET_EN IXP23XX_TIMER_REG(0x28) | ||
| 237 | |||
| 238 | #define IXP23XX_TIMER_ENABLE (1 << 0) | ||
| 239 | #define IXP23XX_TIMER_ONE_SHOT (1 << 1) | ||
| 240 | /* Low order bits of reload value ignored */ | ||
| 241 | #define IXP23XX_TIMER_RELOAD_MASK (0x3) | ||
| 242 | #define IXP23XX_TIMER_DISABLED (0x0) | ||
| 243 | #define IXP23XX_TIMER1_INT_PEND (1 << 0) | ||
| 244 | #define IXP23XX_TIMER2_INT_PEND (1 << 1) | ||
| 245 | #define IXP23XX_TIMER_STATUS_TS_PEND (1 << 2) | ||
| 246 | #define IXP23XX_TIMER_STATUS_WDOG_PEND (1 << 3) | ||
| 247 | #define IXP23XX_TIMER_STATUS_WARM_RESET (1 << 4) | ||
| 248 | |||
| 249 | |||
| 250 | /**************************************************************************** | ||
| 251 | * CAP CSRs. | ||
| 252 | ****************************************************************************/ | ||
| 253 | #define IXP23XX_GLOBAL_REG(x) ((volatile unsigned long *)(IXP23XX_CAP_CSR_VIRT + 0x4a00 + (x))) | ||
| 254 | #define IXP23XX_PROD_IDG IXP23XX_GLOBAL_REG(0x00) | ||
| 255 | #define IXP23XX_MISC_CONTROL IXP23XX_GLOBAL_REG(0x04) | ||
| 256 | #define IXP23XX_MSF_CLK_CNTRL IXP23XX_GLOBAL_REG(0x08) | ||
| 257 | #define IXP23XX_RESET0 IXP23XX_GLOBAL_REG(0x0c) | ||
| 258 | #define IXP23XX_RESET1 IXP23XX_GLOBAL_REG(0x10) | ||
| 259 | #define IXP23XX_STRAP_OPTIONS IXP23XX_GLOBAL_REG(0x18) | ||
| 260 | |||
| 261 | #define IXP23XX_ENABLE_WATCHDOG (1 << 24) | ||
| 262 | #define IXP23XX_SHPC_INIT_COMP (1 << 21) | ||
| 263 | #define IXP23XX_RST_ALL (1 << 16) | ||
| 264 | #define IXP23XX_RESET_PCI (1 << 2) | ||
| 265 | #define IXP23XX_PCI_UNIT_RESET (1 << 1) | ||
| 266 | #define IXP23XX_XSCALE_RESET (1 << 0) | ||
| 267 | |||
| 268 | |||
| 269 | /**************************************************************************** | ||
| 270 | * PCI CSRs. | ||
| 271 | ****************************************************************************/ | ||
| 272 | #define IXP23XX_PCI_CREG(x) ((volatile unsigned long *)(IXP23XX_PCI_CREG_VIRT + (x))) | ||
| 273 | #define IXP23XX_PCI_CMDSTAT IXP23XX_PCI_CREG(0x04) | ||
| 274 | #define IXP23XX_PCI_SRAM_BAR IXP23XX_PCI_CREG(0x14) | ||
| 275 | #define IXP23XX_PCI_SDRAM_BAR IXP23XX_PCI_CREG(0x18) | ||
| 276 | |||
| 277 | |||
| 278 | #define IXP23XX_PCI_CSR(x) ((volatile unsigned long *)(IXP23XX_PCI_CREG_VIRT + 0x01000000 + (x))) | ||
| 279 | #define IXP23XX_PCI_OUT_INT_STATUS IXP23XX_PCI_CSR(0x0030) | ||
| 280 | #define IXP23XX_PCI_OUT_INT_MASK IXP23XX_PCI_CSR(0x0034) | ||
| 281 | #define IXP23XX_PCI_SRAM_BASE_ADDR_MASK IXP23XX_PCI_CSR(0x00fc) | ||
| 282 | #define IXP23XX_PCI_DRAM_BASE_ADDR_MASK IXP23XX_PCI_CSR(0x0100) | ||
| 283 | #define IXP23XX_PCI_CONTROL IXP23XX_PCI_CSR(0x013c) | ||
| 284 | #define IXP23XX_PCI_ADDR_EXT IXP23XX_PCI_CSR(0x0140) | ||
| 285 | #define IXP23XX_PCI_ME_PUSH_STATUS IXP23XX_PCI_CSR(0x0148) | ||
| 286 | #define IXP23XX_PCI_ME_PUSH_EN IXP23XX_PCI_CSR(0x014c) | ||
| 287 | #define IXP23XX_PCI_ERR_STATUS IXP23XX_PCI_CSR(0x0150) | ||
| 288 | #define IXP23XX_PCI_ERROR_STATUS IXP23XX_PCI_CSR(0x0150) | ||
| 289 | #define IXP23XX_PCI_ERR_ENABLE IXP23XX_PCI_CSR(0x0154) | ||
| 290 | #define IXP23XX_PCI_XSCALE_INT_STATUS IXP23XX_PCI_CSR(0x0158) | ||
| 291 | #define IXP23XX_PCI_XSCALE_INT_ENABLE IXP23XX_PCI_CSR(0x015c) | ||
| 292 | #define IXP23XX_PCI_CPP_ADDR_BITS IXP23XX_PCI_CSR(0x0160) | ||
| 293 | |||
| 294 | |||
| 295 | #ifndef __ASSEMBLY__ | ||
| 296 | /* | ||
| 297 | * Is system memory on the XSI or CPP bus? | ||
| 298 | */ | ||
| 299 | static inline unsigned ixp23xx_cpp_boot(void) | ||
| 300 | { | ||
| 301 | return (*IXP23XX_EXP_CFG0 & IXP23XX_EXP_CFG0_XSI_NOT_PRES); | ||
| 302 | } | ||
| 303 | #endif | ||
| 304 | |||
| 305 | |||
| 306 | #endif | ||
diff --git a/include/asm-arm/arch-ixp23xx/memory.h b/include/asm-arm/arch-ixp23xx/memory.h new file mode 100644 index 000000000000..bebcf0aa0d72 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/memory.h | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/memory.h | ||
| 3 | * | ||
| 4 | * Copyright (c) 2003-2004 Intel Corp. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef __ASM_ARCH_MEMORY_H | ||
| 13 | #define __ASM_ARCH_MEMORY_H | ||
| 14 | |||
| 15 | #include <asm/hardware.h> | ||
| 16 | |||
| 17 | /* | ||
| 18 | * Physical DRAM offset. | ||
| 19 | */ | ||
| 20 | #define PHYS_OFFSET (0x00000000) | ||
| 21 | |||
| 22 | |||
| 23 | /* | ||
| 24 | * Virtual view <-> DMA view memory address translations | ||
| 25 | * virt_to_bus: Used to translate the virtual address to an | ||
| 26 | * address suitable to be passed to set_dma_addr | ||
| 27 | * bus_to_virt: Used to convert an address for DMA operations | ||
| 28 | * to an address that the kernel can use. | ||
| 29 | */ | ||
| 30 | #ifndef __ASSEMBLY__ | ||
| 31 | |||
| 32 | #define __virt_to_bus(v) \ | ||
| 33 | ({ unsigned int ret; \ | ||
| 34 | ret = ((__virt_to_phys(v) - 0x00000000) + \ | ||
| 35 | (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0)); \ | ||
| 36 | ret; }) | ||
| 37 | |||
| 38 | #define __bus_to_virt(b) \ | ||
| 39 | ({ unsigned int data; \ | ||
| 40 | data = *((volatile int *)IXP23XX_PCI_SDRAM_BAR); \ | ||
| 41 | __phys_to_virt((((b - (data & 0xfffffff0)) + 0x00000000))); }) | ||
| 42 | |||
| 43 | #endif | ||
| 44 | |||
| 45 | |||
| 46 | #endif | ||
diff --git a/include/asm-arm/arch-ixp23xx/platform.h b/include/asm-arm/arch-ixp23xx/platform.h new file mode 100644 index 000000000000..f85b4685a491 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/platform.h | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/platform.h | ||
| 3 | * | ||
| 4 | * Various bits of code used by platform-level code. | ||
| 5 | * | ||
| 6 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
| 7 | * | ||
| 8 | * Copyright 2005 (c) MontaVista Software, Inc. | ||
| 9 | * | ||
| 10 | * This file is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2. This program is licensed "as is" without any | ||
| 12 | * warranty of any kind, whether express or implied. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef __ASSEMBLY__ | ||
| 16 | |||
| 17 | struct pci_sys_data; | ||
| 18 | |||
| 19 | void ixp23xx_map_io(void); | ||
| 20 | void ixp23xx_init_irq(void); | ||
| 21 | void ixp23xx_sys_init(void); | ||
| 22 | int ixp23xx_pci_setup(int, struct pci_sys_data *); | ||
| 23 | void ixp23xx_pci_preinit(void); | ||
| 24 | struct pci_bus *ixp23xx_pci_scan_bus(int, struct pci_sys_data*); | ||
| 25 | |||
| 26 | extern struct sys_timer ixp23xx_timer; | ||
| 27 | |||
| 28 | #define IXP23XX_UART_XTAL 14745600 | ||
| 29 | |||
| 30 | |||
| 31 | #endif | ||
diff --git a/include/asm-arm/arch-ixp23xx/system.h b/include/asm-arm/arch-ixp23xx/system.h new file mode 100644 index 000000000000..925e6b0c338b --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/system.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/system.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2003 Intel Corporation. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <asm/hardware.h> | ||
| 12 | #include <asm/mach-types.h> | ||
| 13 | |||
| 14 | static inline void arch_idle(void) | ||
| 15 | { | ||
| 16 | #if 0 | ||
| 17 | if (!hlt_counter) | ||
| 18 | cpu_do_idle(); | ||
| 19 | #endif | ||
| 20 | } | ||
| 21 | |||
| 22 | static inline void arch_reset(char mode) | ||
| 23 | { | ||
| 24 | /* First try machine specific support */ | ||
| 25 | if (machine_is_ixdp2351()) { | ||
| 26 | *IXDP2351_CPLD_RESET1_REG = IXDP2351_CPLD_RESET1_MAGIC; | ||
| 27 | (void) *IXDP2351_CPLD_RESET1_REG; | ||
| 28 | *IXDP2351_CPLD_RESET1_REG = IXDP2351_CPLD_RESET1_ENABLE; | ||
| 29 | } | ||
| 30 | |||
| 31 | /* Use on-chip reset capability */ | ||
| 32 | *IXP23XX_RESET0 |= IXP23XX_RST_ALL; | ||
| 33 | } | ||
diff --git a/include/asm-arm/arch-ixp23xx/time.h b/include/asm-arm/arch-ixp23xx/time.h new file mode 100644 index 000000000000..f6828fdd2883 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/time.h | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/time.h | ||
| 3 | */ | ||
diff --git a/include/asm-arm/arch-ixp23xx/timex.h b/include/asm-arm/arch-ixp23xx/timex.h new file mode 100644 index 000000000000..516f72fe6082 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/timex.h | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/timex.h | ||
| 3 | * | ||
| 4 | * XScale architecture timex specifications | ||
| 5 | */ | ||
| 6 | |||
| 7 | #define CLOCK_TICK_RATE 75000000 | ||
diff --git a/include/asm-arm/arch-ixp23xx/uncompress.h b/include/asm-arm/arch-ixp23xx/uncompress.h new file mode 100644 index 000000000000..62623fa9b2f7 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/uncompress.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/uncompress.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002-2004 Intel Corporation. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef __ASM_ARCH_UNCOMPRESS_H | ||
| 12 | #define __ASM_ARCH_UNCOMPRESS_H | ||
| 13 | |||
| 14 | #include <asm/hardware.h> | ||
| 15 | #include <linux/serial_reg.h> | ||
| 16 | |||
| 17 | #define UART_BASE ((volatile u32 *)IXP23XX_UART1_PHYS) | ||
| 18 | |||
| 19 | static __inline__ void putc(char c) | ||
| 20 | { | ||
| 21 | int j; | ||
| 22 | |||
| 23 | for (j = 0; j < 0x1000; j++) { | ||
| 24 | if (UART_BASE[UART_LSR] & UART_LSR_THRE) | ||
| 25 | break; | ||
| 26 | } | ||
| 27 | |||
| 28 | UART_BASE[UART_TX] = c; | ||
| 29 | } | ||
| 30 | |||
| 31 | static void putstr(const char *s) | ||
| 32 | { | ||
| 33 | while (*s) { | ||
| 34 | putc(*s); | ||
| 35 | if (*s == '\n') | ||
| 36 | putc('\r'); | ||
| 37 | s++; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | #define arch_decomp_setup() | ||
| 42 | #define arch_decomp_wdog() | ||
| 43 | |||
| 44 | |||
| 45 | #endif | ||
diff --git a/include/asm-arm/arch-ixp23xx/vmalloc.h b/include/asm-arm/arch-ixp23xx/vmalloc.h new file mode 100644 index 000000000000..9f2566658541 --- /dev/null +++ b/include/asm-arm/arch-ixp23xx/vmalloc.h | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-ixp23xx/vmalloc.h | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 MontaVista Software, Inc. | ||
| 5 | * | ||
| 6 | * NPU mappings end at 0xf0000000 and we allocate 64MB for board | ||
| 7 | * specific static I/O. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #define VMALLOC_END (0xec000000) | ||
diff --git a/include/asm-arm/arch-ixp4xx/uncompress.h b/include/asm-arm/arch-ixp4xx/uncompress.h index 960c35810a22..09ae6c91be60 100644 --- a/include/asm-arm/arch-ixp4xx/uncompress.h +++ b/include/asm-arm/arch-ixp4xx/uncompress.h | |||
| @@ -21,26 +21,18 @@ | |||
| 21 | 21 | ||
| 22 | static volatile u32* uart_base; | 22 | static volatile u32* uart_base; |
| 23 | 23 | ||
| 24 | static __inline__ void putc(char c) | 24 | static inline void putc(int c) |
| 25 | { | 25 | { |
| 26 | /* Check THRE and TEMT bits before we transmit the character. | 26 | /* Check THRE and TEMT bits before we transmit the character. |
| 27 | */ | 27 | */ |
| 28 | while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE); | 28 | while ((uart_base[UART_LSR] & TX_DONE) != TX_DONE) |
| 29 | barrier(); | ||
| 30 | |||
| 29 | *uart_base = c; | 31 | *uart_base = c; |
| 30 | } | 32 | } |
| 31 | 33 | ||
| 32 | /* | 34 | static void flush(void) |
| 33 | * This does not append a newline | ||
| 34 | */ | ||
| 35 | static void putstr(const char *s) | ||
| 36 | { | 35 | { |
| 37 | while (*s) | ||
| 38 | { | ||
| 39 | putc(*s); | ||
| 40 | if (*s == '\n') | ||
| 41 | putc('\r'); | ||
| 42 | s++; | ||
| 43 | } | ||
| 44 | } | 36 | } |
| 45 | 37 | ||
| 46 | static __inline__ void __arch_decomp_setup(unsigned long arch_id) | 38 | static __inline__ void __arch_decomp_setup(unsigned long arch_id) |
diff --git a/include/asm-arm/arch-l7200/uncompress.h b/include/asm-arm/arch-l7200/uncompress.h index 1caa2b560f53..9fcd40aee3e3 100644 --- a/include/asm-arm/arch-l7200/uncompress.h +++ b/include/asm-arm/arch-l7200/uncompress.h | |||
| @@ -16,22 +16,17 @@ | |||
| 16 | #define __raw_writeb(v,p) (*(volatile unsigned char *)(p) = (v)) | 16 | #define __raw_writeb(v,p) (*(volatile unsigned char *)(p) = (v)) |
| 17 | #define __raw_readb(p) (*(volatile unsigned char *)(p)) | 17 | #define __raw_readb(p) (*(volatile unsigned char *)(p)) |
| 18 | 18 | ||
| 19 | static __inline__ void putc(char c) | 19 | static inline void putc(int c) |
| 20 | { | 20 | { |
| 21 | while(__raw_readb(IO_UART + 0x18) & 0x20 || | 21 | while(__raw_readb(IO_UART + 0x18) & 0x20 || |
| 22 | __raw_readb(IO_UART + 0x18) & 0x08); | 22 | __raw_readb(IO_UART + 0x18) & 0x08) |
| 23 | barrier(); | ||
| 24 | |||
| 23 | __raw_writeb(c, IO_UART + 0x00); | 25 | __raw_writeb(c, IO_UART + 0x00); |
| 24 | } | 26 | } |
| 25 | 27 | ||
| 26 | static void putstr(const char *s) | 28 | static inline void flush(void) |
| 27 | { | 29 | { |
| 28 | while (*s) { | ||
| 29 | if (*s == 10) { /* If a LF, add CR */ | ||
| 30 | putc(10); | ||
| 31 | putc(13); | ||
| 32 | } | ||
| 33 | putc(*(s++)); | ||
| 34 | } | ||
| 35 | } | 30 | } |
| 36 | 31 | ||
| 37 | static __inline__ void arch_decomp_setup(void) | 32 | static __inline__ void arch_decomp_setup(void) |
diff --git a/include/asm-arm/arch-lh7a40x/uncompress.h b/include/asm-arm/arch-lh7a40x/uncompress.h index ec8ab67122f3..f8053346f608 100644 --- a/include/asm-arm/arch-lh7a40x/uncompress.h +++ b/include/asm-arm/arch-lh7a40x/uncompress.h | |||
| @@ -22,20 +22,15 @@ | |||
| 22 | #define UART_STATUS (*(volatile unsigned long*) (UART2_PHYS + UART_R_STATUS)) | 22 | #define UART_STATUS (*(volatile unsigned long*) (UART2_PHYS + UART_R_STATUS)) |
| 23 | #define UART_DATA (*(volatile unsigned long*) (UART2_PHYS + UART_R_DATA)) | 23 | #define UART_DATA (*(volatile unsigned long*) (UART2_PHYS + UART_R_DATA)) |
| 24 | 24 | ||
| 25 | static __inline__ void putc (char ch) | 25 | static inline void putc(int ch) |
| 26 | { | 26 | { |
| 27 | while (UART_STATUS & nTxRdy) | 27 | while (UART_STATUS & nTxRdy) |
| 28 | ; | 28 | barrier(); |
| 29 | UART_DATA = ch; | 29 | UART_DATA = ch; |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | static void putstr (const char* sz) | 32 | static inline void flush(void) |
| 33 | { | 33 | { |
| 34 | for (; *sz; ++sz) { | ||
| 35 | putc (*sz); | ||
| 36 | if (*sz == '\n') | ||
| 37 | putc ('\r'); | ||
| 38 | } | ||
| 39 | } | 34 | } |
| 40 | 35 | ||
| 41 | /* NULL functions; we don't presently need them */ | 36 | /* NULL functions; we don't presently need them */ |
diff --git a/include/asm-arm/arch-omap/uncompress.h b/include/asm-arm/arch-omap/uncompress.h index c718264affbd..ca2c8bec82e7 100644 --- a/include/asm-arm/arch-omap/uncompress.h +++ b/include/asm-arm/arch-omap/uncompress.h | |||
| @@ -30,8 +30,7 @@ unsigned int system_rev; | |||
| 30 | #define check_port(base, shift) ((base[UART_OMAP_MDR1 << shift] & 7) == 0) | 30 | #define check_port(base, shift) ((base[UART_OMAP_MDR1 << shift] & 7) == 0) |
| 31 | #define omap_get_id() ((*(volatile unsigned int *)(0xfffed404)) >> 12) & ID_MASK | 31 | #define omap_get_id() ((*(volatile unsigned int *)(0xfffed404)) >> 12) & ID_MASK |
| 32 | 32 | ||
| 33 | static void | 33 | static void putc(int c) |
| 34 | putstr(const char *s) | ||
| 35 | { | 34 | { |
| 36 | volatile u8 * uart = 0; | 35 | volatile u8 * uart = 0; |
| 37 | int shift = 2; | 36 | int shift = 2; |
| @@ -69,16 +68,13 @@ putstr(const char *s) | |||
| 69 | /* | 68 | /* |
| 70 | * Now, xmit each character | 69 | * Now, xmit each character |
| 71 | */ | 70 | */ |
| 72 | while (*s) { | 71 | while (!(uart[UART_LSR << shift] & UART_LSR_THRE)) |
| 73 | while (!(uart[UART_LSR << shift] & UART_LSR_THRE)) | 72 | barrier(); |
| 74 | barrier(); | 73 | uart[UART_TX << shift] = c; |
| 75 | uart[UART_TX << shift] = *s; | 74 | } |
| 76 | if (*s++ == '\n') { | 75 | |
| 77 | while (!(uart[UART_LSR << shift] & UART_LSR_THRE)) | 76 | static inline void flush(void) |
| 78 | barrier(); | 77 | { |
| 79 | uart[UART_TX << shift] = '\r'; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | } | 78 | } |
| 83 | 79 | ||
| 84 | /* | 80 | /* |
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h index 05c4b7027592..67af238a8f8e 100644 --- a/include/asm-arm/arch-pxa/irqs.h +++ b/include/asm-arm/arch-pxa/irqs.h | |||
| @@ -176,6 +176,7 @@ | |||
| 176 | #elif defined(CONFIG_SHARP_LOCOMO) | 176 | #elif defined(CONFIG_SHARP_LOCOMO) |
| 177 | #define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1) | 177 | #define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1) |
| 178 | #elif defined(CONFIG_ARCH_LUBBOCK) || \ | 178 | #elif defined(CONFIG_ARCH_LUBBOCK) || \ |
| 179 | defined(CONFIG_MACH_LOGICPD_PXA270) || \ | ||
| 179 | defined(CONFIG_MACH_MAINSTONE) | 180 | defined(CONFIG_MACH_MAINSTONE) |
| 180 | #define NR_IRQS (IRQ_BOARD_END) | 181 | #define NR_IRQS (IRQ_BOARD_END) |
| 181 | #else | 182 | #else |
| @@ -196,6 +197,11 @@ | |||
| 196 | #define LUBBOCK_USB_DISC_IRQ LUBBOCK_IRQ(6) /* usb disconnect */ | 197 | #define LUBBOCK_USB_DISC_IRQ LUBBOCK_IRQ(6) /* usb disconnect */ |
| 197 | #define LUBBOCK_LAST_IRQ LUBBOCK_IRQ(6) | 198 | #define LUBBOCK_LAST_IRQ LUBBOCK_IRQ(6) |
| 198 | 199 | ||
| 200 | #define LPD270_IRQ(x) (IRQ_BOARD_START + (x)) | ||
| 201 | #define LPD270_USBC_IRQ LPD270_IRQ(2) | ||
| 202 | #define LPD270_ETHERNET_IRQ LPD270_IRQ(3) | ||
| 203 | #define LPD270_AC97_IRQ LPD270_IRQ(4) | ||
| 204 | |||
| 199 | #define MAINSTONE_IRQ(x) (IRQ_BOARD_START + (x)) | 205 | #define MAINSTONE_IRQ(x) (IRQ_BOARD_START + (x)) |
| 200 | #define MAINSTONE_MMC_IRQ MAINSTONE_IRQ(0) | 206 | #define MAINSTONE_MMC_IRQ MAINSTONE_IRQ(0) |
| 201 | #define MAINSTONE_USIM_IRQ MAINSTONE_IRQ(1) | 207 | #define MAINSTONE_USIM_IRQ MAINSTONE_IRQ(1) |
diff --git a/include/asm-arm/arch-pxa/lpd270.h b/include/asm-arm/arch-pxa/lpd270.h new file mode 100644 index 000000000000..501d240ac120 --- /dev/null +++ b/include/asm-arm/arch-pxa/lpd270.h | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-arm/arch-pxa/lpd270.h | ||
| 3 | * | ||
| 4 | * Author: Lennert Buytenhek | ||
| 5 | * Created: Feb 10, 2006 | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef __ASM_ARCH_LPD270_H | ||
| 13 | #define __ASM_ARCH_LPD270_H | ||
| 14 | |||
| 15 | #define LPD270_CPLD_PHYS PXA_CS2_PHYS | ||
| 16 | #define LPD270_CPLD_VIRT 0xf0000000 | ||
| 17 | #define LPD270_CPLD_SIZE 0x00100000 | ||
| 18 | |||
| 19 | #define LPD270_ETH_PHYS (PXA_CS2_PHYS + 0x01000000) | ||
| 20 | |||
| 21 | /* CPLD registers */ | ||
| 22 | #define LPD270_CPLD_REG(x) ((unsigned long)(LPD270_CPLD_VIRT + (x))) | ||
| 23 | #define LPD270_CONTROL LPD270_CPLD_REG(0x00) | ||
| 24 | #define LPD270_PERIPHERAL0 LPD270_CPLD_REG(0x04) | ||
| 25 | #define LPD270_PERIPHERAL1 LPD270_CPLD_REG(0x08) | ||
| 26 | #define LPD270_CPLD_REVISION LPD270_CPLD_REG(0x14) | ||
| 27 | #define LPD270_EEPROM_SPI_ITF LPD270_CPLD_REG(0x20) | ||
| 28 | #define LPD270_MODE_PINS LPD270_CPLD_REG(0x24) | ||
| 29 | #define LPD270_EGPIO LPD270_CPLD_REG(0x30) | ||
| 30 | #define LPD270_INT_MASK LPD270_CPLD_REG(0x40) | ||
| 31 | #define LPD270_INT_STATUS LPD270_CPLD_REG(0x50) | ||
| 32 | |||
| 33 | #define LPD270_INT_AC97 (1 << 4) /* AC'97 CODEC IRQ */ | ||
| 34 | #define LPD270_INT_ETHERNET (1 << 3) /* Ethernet controller IRQ */ | ||
| 35 | #define LPD270_INT_USBC (1 << 2) /* USB client cable detection IRQ */ | ||
| 36 | |||
| 37 | |||
| 38 | #endif | ||
diff --git a/include/asm-arm/arch-pxa/uncompress.h b/include/asm-arm/arch-pxa/uncompress.h index fe38090444e0..178aa2e073ac 100644 --- a/include/asm-arm/arch-pxa/uncompress.h +++ b/include/asm-arm/arch-pxa/uncompress.h | |||
| @@ -17,23 +17,18 @@ | |||
| 17 | #define UART FFUART | 17 | #define UART FFUART |
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | static __inline__ void putc(char c) | 20 | static inline void putc(char c) |
| 21 | { | 21 | { |
| 22 | while (!(UART[5] & 0x20)); | 22 | while (!(UART[5] & 0x20)) |
| 23 | barrier(); | ||
| 23 | UART[0] = c; | 24 | UART[0] = c; |
| 24 | } | 25 | } |
| 25 | 26 | ||
| 26 | /* | 27 | /* |
| 27 | * This does not append a newline | 28 | * This does not append a newline |
| 28 | */ | 29 | */ |
| 29 | static void putstr(const char *s) | 30 | static inline void flush(void) |
| 30 | { | 31 | { |
| 31 | while (*s) { | ||
| 32 | putc(*s); | ||
| 33 | if (*s == '\n') | ||
| 34 | putc('\r'); | ||
| 35 | s++; | ||
| 36 | } | ||
| 37 | } | 32 | } |
| 38 | 33 | ||
| 39 | /* | 34 | /* |
diff --git a/include/asm-arm/arch-realview/uncompress.h b/include/asm-arm/arch-realview/uncompress.h index b5e4d360665b..f05631d76743 100644 --- a/include/asm-arm/arch-realview/uncompress.h +++ b/include/asm-arm/arch-realview/uncompress.h | |||
| @@ -27,22 +27,16 @@ | |||
| 27 | /* | 27 | /* |
| 28 | * This does not append a newline | 28 | * This does not append a newline |
| 29 | */ | 29 | */ |
| 30 | static void putstr(const char *s) | 30 | static inline void putc(int c) |
| 31 | { | 31 | { |
| 32 | while (*s) { | 32 | while (AMBA_UART_FR & (1 << 5)) |
| 33 | while (AMBA_UART_FR & (1 << 5)) | 33 | barrier(); |
| 34 | barrier(); | ||
| 35 | |||
| 36 | AMBA_UART_DR = *s; | ||
| 37 | 34 | ||
| 38 | if (*s == '\n') { | 35 | AMBA_UART_DR = c; |
| 39 | while (AMBA_UART_FR & (1 << 5)) | 36 | } |
| 40 | barrier(); | ||
| 41 | 37 | ||
| 42 | AMBA_UART_DR = '\r'; | 38 | static inline void flush(void) |
| 43 | } | 39 | { |
| 44 | s++; | ||
| 45 | } | ||
| 46 | while (AMBA_UART_FR & (1 << 3)) | 40 | while (AMBA_UART_FR & (1 << 3)) |
| 47 | barrier(); | 41 | barrier(); |
| 48 | } | 42 | } |
diff --git a/include/asm-arm/arch-rpc/uncompress.h b/include/asm-arm/arch-rpc/uncompress.h index 43035fec64d2..06231ede54e5 100644 --- a/include/asm-arm/arch-rpc/uncompress.h +++ b/include/asm-arm/arch-rpc/uncompress.h | |||
| @@ -67,31 +67,28 @@ extern __attribute__((pure)) struct param_struct *params(void); | |||
| 67 | /* | 67 | /* |
| 68 | * This does not append a newline | 68 | * This does not append a newline |
| 69 | */ | 69 | */ |
| 70 | static void putstr(const char *s) | 70 | static void putc(int c) |
| 71 | { | 71 | { |
| 72 | extern void ll_write_char(char *, char c, char white); | 72 | extern void ll_write_char(char *, char c, char white); |
| 73 | int x,y; | 73 | int x,y; |
| 74 | unsigned char c; | ||
| 75 | char *ptr; | 74 | char *ptr; |
| 76 | 75 | ||
| 77 | x = params->video_x; | 76 | x = params->video_x; |
| 78 | y = params->video_y; | 77 | y = params->video_y; |
| 79 | 78 | ||
| 80 | while ( ( c = *(unsigned char *)s++ ) != '\0' ) { | 79 | if (c == '\n') { |
| 81 | if ( c == '\n' ) { | 80 | if (++y >= video_num_lines) |
| 81 | y--; | ||
| 82 | } else if (c == '\r') { | ||
| 83 | x = 0; | ||
| 84 | } else { | ||
| 85 | ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h); | ||
| 86 | ll_write_char(ptr, c, white); | ||
| 87 | if (++x >= video_num_columns) { | ||
| 82 | x = 0; | 88 | x = 0; |
| 83 | if ( ++y >= video_num_lines ) { | 89 | if ( ++y >= video_num_lines ) { |
| 84 | y--; | 90 | y--; |
| 85 | } | 91 | } |
| 86 | } else { | ||
| 87 | ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h); | ||
| 88 | ll_write_char(ptr, c, white); | ||
| 89 | if ( ++x >= video_num_columns ) { | ||
| 90 | x = 0; | ||
| 91 | if ( ++y >= video_num_lines ) { | ||
| 92 | y--; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | } | 92 | } |
| 96 | } | 93 | } |
| 97 | 94 | ||
| @@ -99,6 +96,10 @@ static void putstr(const char *s) | |||
| 99 | params->video_y = y; | 96 | params->video_y = y; |
| 100 | } | 97 | } |
| 101 | 98 | ||
| 99 | static inline void flush(void) | ||
| 100 | { | ||
| 101 | } | ||
| 102 | |||
| 102 | static void error(char *x); | 103 | static void error(char *x); |
| 103 | 104 | ||
| 104 | /* | 105 | /* |
diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h index 4367ec054b51..a6f6a0e44afa 100644 --- a/include/asm-arm/arch-s3c2410/uncompress.h +++ b/include/asm-arm/arch-s3c2410/uncompress.h | |||
| @@ -67,8 +67,7 @@ uart_rd(unsigned int reg) | |||
| 67 | * waiting for tx to happen... | 67 | * waiting for tx to happen... |
| 68 | */ | 68 | */ |
| 69 | 69 | ||
| 70 | static void | 70 | static void putc(int ch) |
| 71 | putc(char ch) | ||
| 72 | { | 71 | { |
| 73 | int cpuid = S3C2410_GSTATUS1_2410; | 72 | int cpuid = S3C2410_GSTATUS1_2410; |
| 74 | 73 | ||
| @@ -77,9 +76,6 @@ putc(char ch) | |||
| 77 | cpuid &= S3C2410_GSTATUS1_IDMASK; | 76 | cpuid &= S3C2410_GSTATUS1_IDMASK; |
| 78 | #endif | 77 | #endif |
| 79 | 78 | ||
| 80 | if (ch == '\n') | ||
| 81 | putc('\r'); /* expand newline to \r\n */ | ||
| 82 | |||
| 83 | if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) { | 79 | if (uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) { |
| 84 | int level; | 80 | int level; |
| 85 | 81 | ||
| @@ -101,19 +97,16 @@ putc(char ch) | |||
| 101 | } else { | 97 | } else { |
| 102 | /* not using fifos */ | 98 | /* not using fifos */ |
| 103 | 99 | ||
| 104 | while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE); | 100 | while ((uart_rd(S3C2410_UTRSTAT) & S3C2410_UTRSTAT_TXE) != S3C2410_UTRSTAT_TXE) |
| 101 | barrier(); | ||
| 105 | } | 102 | } |
| 106 | 103 | ||
| 107 | /* write byte to transmission register */ | 104 | /* write byte to transmission register */ |
| 108 | uart_wr(S3C2410_UTXH, ch); | 105 | uart_wr(S3C2410_UTXH, ch); |
| 109 | } | 106 | } |
| 110 | 107 | ||
| 111 | static void | 108 | static inline void flush(void) |
| 112 | putstr(const char *ptr) | ||
| 113 | { | 109 | { |
| 114 | for (; *ptr != '\0'; ptr++) { | ||
| 115 | putc(*ptr); | ||
| 116 | } | ||
| 117 | } | 110 | } |
| 118 | 111 | ||
| 119 | #define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0) | 112 | #define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0) |
diff --git a/include/asm-arm/arch-sa1100/uncompress.h b/include/asm-arm/arch-sa1100/uncompress.h index 43453501ee66..2601a77a6dda 100644 --- a/include/asm-arm/arch-sa1100/uncompress.h +++ b/include/asm-arm/arch-sa1100/uncompress.h | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | 17 | ||
| 18 | #define UART(x) (*(volatile unsigned long *)(serial_port + (x))) | 18 | #define UART(x) (*(volatile unsigned long *)(serial_port + (x))) |
| 19 | 19 | ||
| 20 | static void putstr( const char *s ) | 20 | static void putc(int c) |
| 21 | { | 21 | { |
| 22 | unsigned long serial_port; | 22 | unsigned long serial_port; |
| 23 | 23 | ||
| @@ -31,19 +31,16 @@ static void putstr( const char *s ) | |||
| 31 | return; | 31 | return; |
| 32 | } while (0); | 32 | } while (0); |
| 33 | 33 | ||
| 34 | for (; *s; s++) { | 34 | /* wait for space in the UART's transmitter */ |
| 35 | /* wait for space in the UART's transmitter */ | 35 | while (!(UART(UTSR1) & UTSR1_TNF)) |
| 36 | while (!(UART(UTSR1) & UTSR1_TNF)); | 36 | barrier(); |
| 37 | 37 | ||
| 38 | /* send the character out. */ | 38 | /* send the character out. */ |
| 39 | UART(UTDR) = *s; | 39 | UART(UTDR) = c; |
| 40 | } | ||
| 40 | 41 | ||
| 41 | /* if a LF, also do CR... */ | 42 | static inline void flush(void) |
| 42 | if (*s == 10) { | 43 | { |
| 43 | while (!(UART(UTSR1) & UTSR1_TNF)); | ||
| 44 | UART(UTDR) = 13; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | } | 44 | } |
| 48 | 45 | ||
| 49 | /* | 46 | /* |
diff --git a/include/asm-arm/arch-shark/uncompress.h b/include/asm-arm/arch-shark/uncompress.h index 910a8e0a0ca5..7eca6534f1bb 100644 --- a/include/asm-arm/arch-shark/uncompress.h +++ b/include/asm-arm/arch-shark/uncompress.h | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #define SERIAL_BASE ((volatile unsigned char *)0x400003f8) | 10 | #define SERIAL_BASE ((volatile unsigned char *)0x400003f8) |
| 11 | 11 | ||
| 12 | static __inline__ void putc(char c) | 12 | static inline void putc(int c) |
| 13 | { | 13 | { |
| 14 | int t; | 14 | int t; |
| 15 | 15 | ||
| @@ -18,17 +18,8 @@ static __inline__ void putc(char c) | |||
| 18 | while (t--); | 18 | while (t--); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | /* | 21 | static inline void flush(void) |
| 22 | * This does not append a newline | ||
| 23 | */ | ||
| 24 | static void putstr(const char *s) | ||
| 25 | { | 22 | { |
| 26 | while (*s) { | ||
| 27 | putc(*s); | ||
| 28 | if (*s == '\n') | ||
| 29 | putc('\r'); | ||
| 30 | s++; | ||
| 31 | } | ||
| 32 | } | 23 | } |
| 33 | 24 | ||
| 34 | #ifdef DEBUG | 25 | #ifdef DEBUG |
diff --git a/include/asm-arm/arch-versatile/uncompress.h b/include/asm-arm/arch-versatile/uncompress.h index 2f57499c7b92..7215133d0514 100644 --- a/include/asm-arm/arch-versatile/uncompress.h +++ b/include/asm-arm/arch-versatile/uncompress.h | |||
| @@ -25,22 +25,16 @@ | |||
| 25 | /* | 25 | /* |
| 26 | * This does not append a newline | 26 | * This does not append a newline |
| 27 | */ | 27 | */ |
| 28 | static void putstr(const char *s) | 28 | static inline void putc(int c) |
| 29 | { | 29 | { |
| 30 | while (*s) { | 30 | while (AMBA_UART_FR & (1 << 5)) |
| 31 | while (AMBA_UART_FR & (1 << 5)) | 31 | barrier(); |
| 32 | barrier(); | ||
| 33 | |||
| 34 | AMBA_UART_DR = *s; | ||
| 35 | 32 | ||
| 36 | if (*s == '\n') { | 33 | AMBA_UART_DR = c; |
| 37 | while (AMBA_UART_FR & (1 << 5)) | 34 | } |
| 38 | barrier(); | ||
| 39 | 35 | ||
| 40 | AMBA_UART_DR = '\r'; | 36 | static inline void flush(void) |
| 41 | } | 37 | { |
| 42 | s++; | ||
| 43 | } | ||
| 44 | while (AMBA_UART_FR & (1 << 3)) | 38 | while (AMBA_UART_FR & (1 << 3)) |
| 45 | barrier(); | 39 | barrier(); |
| 46 | } | 40 | } |
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index 09e19a783a51..746be56b1b70 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h | |||
| @@ -71,6 +71,14 @@ | |||
| 71 | # endif | 71 | # endif |
| 72 | #endif | 72 | #endif |
| 73 | 73 | ||
| 74 | #if defined(CONFIG_CPU_XSC3) | ||
| 75 | # ifdef _CACHE | ||
| 76 | # define MULTI_CACHE 1 | ||
| 77 | # else | ||
| 78 | # define _CACHE xsc3 | ||
| 79 | # endif | ||
| 80 | #endif | ||
| 81 | |||
| 74 | #if defined(CONFIG_CPU_V6) | 82 | #if defined(CONFIG_CPU_V6) |
| 75 | //# ifdef _CACHE | 83 | //# ifdef _CACHE |
| 76 | # define MULTI_CACHE 1 | 84 | # define MULTI_CACHE 1 |
diff --git a/include/asm-arm/domain.h b/include/asm-arm/domain.h index da1d960387d9..f8ea2de4848e 100644 --- a/include/asm-arm/domain.h +++ b/include/asm-arm/domain.h | |||
| @@ -16,11 +16,29 @@ | |||
| 16 | * DOMAIN_IO - domain 2 includes all IO only | 16 | * DOMAIN_IO - domain 2 includes all IO only |
| 17 | * DOMAIN_USER - domain 1 includes all user memory only | 17 | * DOMAIN_USER - domain 1 includes all user memory only |
| 18 | * DOMAIN_KERNEL - domain 0 includes all kernel memory only | 18 | * DOMAIN_KERNEL - domain 0 includes all kernel memory only |
| 19 | * | ||
| 20 | * The domain numbering depends on whether we support 36 physical | ||
| 21 | * address for I/O or not. Addresses above the 32 bit boundary can | ||
| 22 | * only be mapped using supersections and supersections can only | ||
| 23 | * be set for domain 0. We could just default to DOMAIN_IO as zero, | ||
| 24 | * but there may be systems with supersection support and no 36-bit | ||
| 25 | * addressing. In such cases, we want to map system memory with | ||
| 26 | * supersections to reduce TLB misses and footprint. | ||
| 27 | * | ||
| 28 | * 36-bit addressing and supersections are only available on | ||
| 29 | * CPUs based on ARMv6+ or the Intel XSC3 core. | ||
| 19 | */ | 30 | */ |
| 31 | #ifndef CONFIG_IO_36 | ||
| 20 | #define DOMAIN_KERNEL 0 | 32 | #define DOMAIN_KERNEL 0 |
| 21 | #define DOMAIN_TABLE 0 | 33 | #define DOMAIN_TABLE 0 |
| 22 | #define DOMAIN_USER 1 | 34 | #define DOMAIN_USER 1 |
| 23 | #define DOMAIN_IO 2 | 35 | #define DOMAIN_IO 2 |
| 36 | #else | ||
| 37 | #define DOMAIN_KERNEL 2 | ||
| 38 | #define DOMAIN_TABLE 2 | ||
| 39 | #define DOMAIN_USER 1 | ||
| 40 | #define DOMAIN_IO 0 | ||
| 41 | #endif | ||
| 24 | 42 | ||
| 25 | /* | 43 | /* |
| 26 | * Domain types | 44 | * Domain types |
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h index b4e1146ab682..afa5c3ea077c 100644 --- a/include/asm-arm/memory.h +++ b/include/asm-arm/memory.h | |||
| @@ -172,9 +172,7 @@ static inline __deprecated void *bus_to_virt(unsigned long x) | |||
| 172 | * virt_addr_valid(k) indicates whether a virtual address is valid | 172 | * virt_addr_valid(k) indicates whether a virtual address is valid |
| 173 | */ | 173 | */ |
| 174 | #ifndef CONFIG_DISCONTIGMEM | 174 | #ifndef CONFIG_DISCONTIGMEM |
| 175 | 175 | #define ARCH_PFN_OFFSET (PHYS_PFN_OFFSET) | |
| 176 | #define page_to_pfn(page) (((page) - mem_map) + PHYS_PFN_OFFSET) | ||
| 177 | #define pfn_to_page(pfn) ((mem_map + (pfn)) - PHYS_PFN_OFFSET) | ||
| 178 | #define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr)) | 176 | #define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr)) |
| 179 | 177 | ||
| 180 | #define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)) | 178 | #define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)) |
| @@ -189,13 +187,8 @@ static inline __deprecated void *bus_to_virt(unsigned long x) | |||
| 189 | * around in memory. | 187 | * around in memory. |
| 190 | */ | 188 | */ |
| 191 | #include <linux/numa.h> | 189 | #include <linux/numa.h> |
| 192 | 190 | #define arch_pfn_to_nid(pfn) (PFN_TO_NID(pfn)) | |
| 193 | #define page_to_pfn(page) \ | 191 | #define arch_local_page_offset(pfn, nid) (LOCAL_MAP_NR((pfn) << PAGE_OFFSET)) |
| 194 | (( (page) - page_zone(page)->zone_mem_map) \ | ||
| 195 | + page_zone(page)->zone_start_pfn) | ||
| 196 | |||
| 197 | #define pfn_to_page(pfn) \ | ||
| 198 | (PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT)) | ||
| 199 | 192 | ||
| 200 | #define pfn_valid(pfn) \ | 193 | #define pfn_valid(pfn) \ |
| 201 | ({ \ | 194 | ({ \ |
| @@ -243,4 +236,6 @@ static inline __deprecated void *bus_to_virt(unsigned long x) | |||
| 243 | 236 | ||
| 244 | #endif | 237 | #endif |
| 245 | 238 | ||
| 239 | #include <asm-generic/memory_model.h> | ||
| 240 | |||
| 246 | #endif | 241 | #endif |
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h index 416320d95419..a404d2bf0c68 100644 --- a/include/asm-arm/page.h +++ b/include/asm-arm/page.h | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | * v4wb - ARMv4 with writeback cache, without minicache | 40 | * v4wb - ARMv4 with writeback cache, without minicache |
| 41 | * v4_mc - ARMv4 with minicache | 41 | * v4_mc - ARMv4 with minicache |
| 42 | * xscale - Xscale | 42 | * xscale - Xscale |
| 43 | * xsc3 - XScalev3 | ||
| 43 | */ | 44 | */ |
| 44 | #undef _USER | 45 | #undef _USER |
| 45 | #undef MULTI_USER | 46 | #undef MULTI_USER |
| @@ -84,6 +85,14 @@ | |||
| 84 | # endif | 85 | # endif |
| 85 | #endif | 86 | #endif |
| 86 | 87 | ||
| 88 | #ifdef CONFIG_CPU_XSC3 | ||
| 89 | # ifdef _USER | ||
| 90 | # define MULTI_USER 1 | ||
| 91 | # else | ||
| 92 | # define _USER xsc3_mc | ||
| 93 | # endif | ||
| 94 | #endif | ||
| 95 | |||
| 87 | #ifdef CONFIG_CPU_COPY_V6 | 96 | #ifdef CONFIG_CPU_COPY_V6 |
| 88 | # define MULTI_USER 1 | 97 | # define MULTI_USER 1 |
| 89 | #endif | 98 | #endif |
diff --git a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h index 7bef2bf6be51..106045edb862 100644 --- a/include/asm-arm/proc-fns.h +++ b/include/asm-arm/proc-fns.h | |||
| @@ -138,6 +138,14 @@ | |||
| 138 | # define CPU_NAME cpu_xscale | 138 | # define CPU_NAME cpu_xscale |
| 139 | # endif | 139 | # endif |
| 140 | # endif | 140 | # endif |
| 141 | # ifdef CONFIG_CPU_XSC3 | ||
| 142 | # ifdef CPU_NAME | ||
| 143 | # undef MULTI_CPU | ||
| 144 | # define MULTI_CPU | ||
| 145 | # else | ||
| 146 | # define CPU_NAME cpu_xsc3 | ||
| 147 | # endif | ||
| 148 | # endif | ||
| 141 | # ifdef CONFIG_CPU_V6 | 149 | # ifdef CONFIG_CPU_V6 |
| 142 | # ifdef CPU_NAME | 150 | # ifdef CPU_NAME |
| 143 | # undef MULTI_CPU | 151 | # undef MULTI_CPU |
diff --git a/include/asm-arm/rtc.h b/include/asm-arm/rtc.h index 370dfe77589d..1a5c9232a91e 100644 --- a/include/asm-arm/rtc.h +++ b/include/asm-arm/rtc.h | |||
| @@ -25,9 +25,6 @@ struct rtc_ops { | |||
| 25 | int (*proc)(char *buf); | 25 | int (*proc)(char *buf); |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | void rtc_time_to_tm(unsigned long, struct rtc_time *); | ||
| 29 | int rtc_tm_to_time(struct rtc_time *, unsigned long *); | ||
| 30 | int rtc_valid_tm(struct rtc_time *); | ||
| 31 | void rtc_next_alarm_time(struct rtc_time *, struct rtc_time *, struct rtc_time *); | 28 | void rtc_next_alarm_time(struct rtc_time *, struct rtc_time *, struct rtc_time *); |
| 32 | void rtc_update(unsigned long, unsigned long); | 29 | void rtc_update(unsigned long, unsigned long); |
| 33 | int register_rtc(struct rtc_ops *); | 30 | int register_rtc(struct rtc_ops *); |
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h index ec91d1ff032a..95b3abf4851b 100644 --- a/include/asm-arm/system.h +++ b/include/asm-arm/system.h | |||
| @@ -108,6 +108,25 @@ extern void __show_regs(struct pt_regs *); | |||
| 108 | extern int cpu_architecture(void); | 108 | extern int cpu_architecture(void); |
| 109 | extern void cpu_init(void); | 109 | extern void cpu_init(void); |
| 110 | 110 | ||
| 111 | /* | ||
| 112 | * Intel's XScale3 core supports some v6 features (supersections, L2) | ||
| 113 | * but advertises itself as v5 as it does not support the v6 ISA. For | ||
| 114 | * this reason, we need a way to explicitly test for this type of CPU. | ||
| 115 | */ | ||
| 116 | #ifndef CONFIG_CPU_XSC3 | ||
| 117 | #define cpu_is_xsc3() 0 | ||
| 118 | #else | ||
| 119 | static inline int cpu_is_xsc3(void) | ||
| 120 | { | ||
| 121 | extern unsigned int processor_id; | ||
| 122 | |||
| 123 | if ((processor_id & 0xffffe000) == 0x69056000) | ||
| 124 | return 1; | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | #endif | ||
| 129 | |||
| 111 | #define set_cr(x) \ | 130 | #define set_cr(x) \ |
| 112 | __asm__ __volatile__( \ | 131 | __asm__ __volatile__( \ |
| 113 | "mcr p15, 0, %0, c1, c0, 0 @ set CR" \ | 132 | "mcr p15, 0, %0, c1, c0, 0 @ set CR" \ |
diff --git a/include/asm-arm26/memory.h b/include/asm-arm26/memory.h index 20d78616f650..a65f10b80dfb 100644 --- a/include/asm-arm26/memory.h +++ b/include/asm-arm26/memory.h | |||
| @@ -81,8 +81,7 @@ static inline void *phys_to_virt(unsigned long x) | |||
| 81 | * virt_to_page(k) convert a _valid_ virtual address to struct page * | 81 | * virt_to_page(k) convert a _valid_ virtual address to struct page * |
| 82 | * virt_addr_valid(k) indicates whether a virtual address is valid | 82 | * virt_addr_valid(k) indicates whether a virtual address is valid |
| 83 | */ | 83 | */ |
| 84 | #define page_to_pfn(page) (((page) - mem_map) + PHYS_PFN_OFFSET) | 84 | #define ARCH_PFN_OFFSET (PHYS_PFN_OFFSET) |
| 85 | #define pfn_to_page(pfn) ((mem_map + (pfn)) - PHYS_PFN_OFFSET) | ||
| 86 | #define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr)) | 85 | #define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr)) |
| 87 | 86 | ||
| 88 | #define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)) | 87 | #define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)) |
| @@ -98,4 +97,5 @@ static inline void *phys_to_virt(unsigned long x) | |||
| 98 | */ | 97 | */ |
| 99 | #define page_to_bus(page) (page_address(page)) | 98 | #define page_to_bus(page) (page_address(page)) |
| 100 | 99 | ||
| 100 | #include <asm-generic/memory_model.h> | ||
| 101 | #endif | 101 | #endif |
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h index c99c478c482f..3787633e6209 100644 --- a/include/asm-cris/page.h +++ b/include/asm-cris/page.h | |||
| @@ -43,8 +43,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 43 | 43 | ||
| 44 | /* On CRIS the PFN numbers doesn't start at 0 so we have to compensate */ | 44 | /* On CRIS the PFN numbers doesn't start at 0 so we have to compensate */ |
| 45 | /* for that before indexing into the page table starting at mem_map */ | 45 | /* for that before indexing into the page table starting at mem_map */ |
| 46 | #define pfn_to_page(pfn) (mem_map + ((pfn) - (PAGE_OFFSET >> PAGE_SHIFT))) | 46 | #define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) |
| 47 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map) + (PAGE_OFFSET >> PAGE_SHIFT)) | ||
| 48 | #define pfn_valid(pfn) (((pfn) - (PAGE_OFFSET >> PAGE_SHIFT)) < max_mapnr) | 47 | #define pfn_valid(pfn) (((pfn) - (PAGE_OFFSET >> PAGE_SHIFT)) < max_mapnr) |
| 49 | 48 | ||
| 50 | /* to index into the page map. our pages all start at physical addr PAGE_OFFSET so | 49 | /* to index into the page map. our pages all start at physical addr PAGE_OFFSET so |
| @@ -77,6 +76,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 77 | 76 | ||
| 78 | #endif /* __KERNEL__ */ | 77 | #endif /* __KERNEL__ */ |
| 79 | 78 | ||
| 79 | #include <asm-generic/memory_model.h> | ||
| 80 | #include <asm-generic/page.h> | 80 | #include <asm-generic/page.h> |
| 81 | 81 | ||
| 82 | #endif /* _CRIS_PAGE_H */ | 82 | #endif /* _CRIS_PAGE_H */ |
diff --git a/include/asm-frv/futex.h b/include/asm-frv/futex.h index fca9d90e32c9..08b3d1da3583 100644 --- a/include/asm-frv/futex.h +++ b/include/asm-frv/futex.h | |||
| @@ -9,5 +9,11 @@ | |||
| 9 | 9 | ||
| 10 | extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr); | 10 | extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr); |
| 11 | 11 | ||
| 12 | static inline int | ||
| 13 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | ||
| 14 | { | ||
| 15 | return -ENOSYS; | ||
| 16 | } | ||
| 17 | |||
| 12 | #endif | 18 | #endif |
| 13 | #endif | 19 | #endif |
diff --git a/include/asm-frv/page.h b/include/asm-frv/page.h index b8221b611b5c..dc0f7e08a4c2 100644 --- a/include/asm-frv/page.h +++ b/include/asm-frv/page.h | |||
| @@ -57,13 +57,9 @@ extern unsigned long min_low_pfn; | |||
| 57 | extern unsigned long max_pfn; | 57 | extern unsigned long max_pfn; |
| 58 | 58 | ||
| 59 | #ifdef CONFIG_MMU | 59 | #ifdef CONFIG_MMU |
| 60 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
| 61 | #define page_to_pfn(page) ((unsigned long) ((page) - mem_map)) | ||
| 62 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | 60 | #define pfn_valid(pfn) ((pfn) < max_mapnr) |
| 63 | |||
| 64 | #else | 61 | #else |
| 65 | #define pfn_to_page(pfn) (&mem_map[(pfn) - (PAGE_OFFSET >> PAGE_SHIFT)]) | 62 | #define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) |
| 66 | #define page_to_pfn(page) ((PAGE_OFFSET >> PAGE_SHIFT) + (unsigned long) ((page) - mem_map)) | ||
| 67 | #define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) < max_low_pfn) | 63 | #define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) < max_low_pfn) |
| 68 | 64 | ||
| 69 | #endif | 65 | #endif |
| @@ -87,6 +83,7 @@ extern unsigned long max_pfn; | |||
| 87 | #define WANT_PAGE_VIRTUAL 1 | 83 | #define WANT_PAGE_VIRTUAL 1 |
| 88 | #endif | 84 | #endif |
| 89 | 85 | ||
| 86 | #include <asm-generic/memory_model.h> | ||
| 90 | #include <asm-generic/page.h> | 87 | #include <asm-generic/page.h> |
| 91 | 88 | ||
| 92 | #endif /* _ASM_PAGE_H */ | 89 | #endif /* _ASM_PAGE_H */ |
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h index 3ae2c7347549..df893c160318 100644 --- a/include/asm-generic/futex.h +++ b/include/asm-generic/futex.h | |||
| @@ -49,5 +49,11 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
| 49 | return ret; | 49 | return ret; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | static inline int | ||
| 53 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | ||
| 54 | { | ||
| 55 | return -ENOSYS; | ||
| 56 | } | ||
| 57 | |||
| 52 | #endif | 58 | #endif |
| 53 | #endif | 59 | #endif |
diff --git a/include/asm-generic/local.h b/include/asm-generic/local.h index 16fc00360f75..de4614840c2c 100644 --- a/include/asm-generic/local.h +++ b/include/asm-generic/local.h | |||
| @@ -4,28 +4,28 @@ | |||
| 4 | #include <linux/config.h> | 4 | #include <linux/config.h> |
| 5 | #include <linux/percpu.h> | 5 | #include <linux/percpu.h> |
| 6 | #include <linux/hardirq.h> | 6 | #include <linux/hardirq.h> |
| 7 | #include <asm/atomic.h> | ||
| 7 | #include <asm/types.h> | 8 | #include <asm/types.h> |
| 8 | 9 | ||
| 9 | /* An unsigned long type for operations which are atomic for a single | 10 | /* An unsigned long type for operations which are atomic for a single |
| 10 | * CPU. Usually used in combination with per-cpu variables. */ | 11 | * CPU. Usually used in combination with per-cpu variables. */ |
| 11 | 12 | ||
| 12 | #if BITS_PER_LONG == 32 | ||
| 13 | /* Implement in terms of atomics. */ | 13 | /* Implement in terms of atomics. */ |
| 14 | 14 | ||
| 15 | /* Don't use typedef: don't want them to be mixed with atomic_t's. */ | 15 | /* Don't use typedef: don't want them to be mixed with atomic_t's. */ |
| 16 | typedef struct | 16 | typedef struct |
| 17 | { | 17 | { |
| 18 | atomic_t a; | 18 | atomic_long_t a; |
| 19 | } local_t; | 19 | } local_t; |
| 20 | 20 | ||
| 21 | #define LOCAL_INIT(i) { ATOMIC_INIT(i) } | 21 | #define LOCAL_INIT(i) { ATOMIC_LONG_INIT(i) } |
| 22 | 22 | ||
| 23 | #define local_read(l) ((unsigned long)atomic_read(&(l)->a)) | 23 | #define local_read(l) ((unsigned long)atomic_long_read(&(l)->a)) |
| 24 | #define local_set(l,i) atomic_set((&(l)->a),(i)) | 24 | #define local_set(l,i) atomic_long_set((&(l)->a),(i)) |
| 25 | #define local_inc(l) atomic_inc(&(l)->a) | 25 | #define local_inc(l) atomic_long_inc(&(l)->a) |
| 26 | #define local_dec(l) atomic_dec(&(l)->a) | 26 | #define local_dec(l) atomic_long_dec(&(l)->a) |
| 27 | #define local_add(i,l) atomic_add((i),(&(l)->a)) | 27 | #define local_add(i,l) atomic_long_add((i),(&(l)->a)) |
| 28 | #define local_sub(i,l) atomic_sub((i),(&(l)->a)) | 28 | #define local_sub(i,l) atomic_long_sub((i),(&(l)->a)) |
| 29 | 29 | ||
| 30 | /* Non-atomic variants, ie. preemption disabled and won't be touched | 30 | /* Non-atomic variants, ie. preemption disabled and won't be touched |
| 31 | * in interrupt, etc. Some archs can optimize this case well. */ | 31 | * in interrupt, etc. Some archs can optimize this case well. */ |
| @@ -34,68 +34,6 @@ typedef struct | |||
| 34 | #define __local_add(i,l) local_set((l), local_read(l) + (i)) | 34 | #define __local_add(i,l) local_set((l), local_read(l) + (i)) |
| 35 | #define __local_sub(i,l) local_set((l), local_read(l) - (i)) | 35 | #define __local_sub(i,l) local_set((l), local_read(l) - (i)) |
| 36 | 36 | ||
| 37 | #else /* ... can't use atomics. */ | ||
| 38 | /* Implement in terms of three variables. | ||
| 39 | Another option would be to use local_irq_save/restore. */ | ||
| 40 | |||
| 41 | typedef struct | ||
| 42 | { | ||
| 43 | /* 0 = in hardirq, 1 = in softirq, 2 = usermode. */ | ||
| 44 | unsigned long v[3]; | ||
| 45 | } local_t; | ||
| 46 | |||
| 47 | #define _LOCAL_VAR(l) ((l)->v[!in_interrupt() + !in_irq()]) | ||
| 48 | |||
| 49 | #define LOCAL_INIT(i) { { (i), 0, 0 } } | ||
| 50 | |||
| 51 | static inline unsigned long local_read(local_t *l) | ||
| 52 | { | ||
| 53 | return l->v[0] + l->v[1] + l->v[2]; | ||
| 54 | } | ||
| 55 | |||
| 56 | static inline void local_set(local_t *l, unsigned long v) | ||
| 57 | { | ||
| 58 | l->v[0] = v; | ||
| 59 | l->v[1] = l->v[2] = 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | static inline void local_inc(local_t *l) | ||
| 63 | { | ||
| 64 | preempt_disable(); | ||
| 65 | _LOCAL_VAR(l)++; | ||
| 66 | preempt_enable(); | ||
| 67 | } | ||
| 68 | |||
| 69 | static inline void local_dec(local_t *l) | ||
| 70 | { | ||
| 71 | preempt_disable(); | ||
| 72 | _LOCAL_VAR(l)--; | ||
| 73 | preempt_enable(); | ||
| 74 | } | ||
| 75 | |||
| 76 | static inline void local_add(unsigned long v, local_t *l) | ||
| 77 | { | ||
| 78 | preempt_disable(); | ||
| 79 | _LOCAL_VAR(l) += v; | ||
| 80 | preempt_enable(); | ||
| 81 | } | ||
| 82 | |||
| 83 | static inline void local_sub(unsigned long v, local_t *l) | ||
| 84 | { | ||
| 85 | preempt_disable(); | ||
| 86 | _LOCAL_VAR(l) -= v; | ||
| 87 | preempt_enable(); | ||
| 88 | } | ||
| 89 | |||
| 90 | /* Non-atomic variants, ie. preemption disabled and won't be touched | ||
| 91 | * in interrupt, etc. Some archs can optimize this case well. */ | ||
| 92 | #define __local_inc(l) ((l)->v[0]++) | ||
| 93 | #define __local_dec(l) ((l)->v[0]--) | ||
| 94 | #define __local_add(i,l) ((l)->v[0] += (i)) | ||
| 95 | #define __local_sub(i,l) ((l)->v[0] -= (i)) | ||
| 96 | |||
| 97 | #endif /* Non-atomic implementation */ | ||
| 98 | |||
| 99 | /* Use these for per-cpu local_t variables: on some archs they are | 37 | /* Use these for per-cpu local_t variables: on some archs they are |
| 100 | * much more efficient than these naive implementations. Note they take | 38 | * much more efficient than these naive implementations. Note they take |
| 101 | * a variable (eg. mystruct.foo), not an address. | 39 | * a variable (eg. mystruct.foo), not an address. |
diff --git a/include/asm-generic/memory_model.h b/include/asm-generic/memory_model.h new file mode 100644 index 000000000000..0cfb086dd373 --- /dev/null +++ b/include/asm-generic/memory_model.h | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | #ifndef __ASM_MEMORY_MODEL_H | ||
| 2 | #define __ASM_MEMORY_MODEL_H | ||
| 3 | |||
| 4 | #ifdef __KERNEL__ | ||
| 5 | #ifndef __ASSEMBLY__ | ||
| 6 | |||
| 7 | #if defined(CONFIG_FLATMEM) | ||
| 8 | |||
| 9 | #ifndef ARCH_PFN_OFFSET | ||
| 10 | #define ARCH_PFN_OFFSET (0UL) | ||
| 11 | #endif | ||
| 12 | |||
| 13 | #elif defined(CONFIG_DISCONTIGMEM) | ||
| 14 | |||
| 15 | #ifndef arch_pfn_to_nid | ||
| 16 | #define arch_pfn_to_nid(pfn) pfn_to_nid(pfn) | ||
| 17 | #endif | ||
| 18 | |||
| 19 | #ifndef arch_local_page_offset | ||
| 20 | #define arch_local_page_offset(pfn, nid) \ | ||
| 21 | ((pfn) - NODE_DATA(nid)->node_start_pfn) | ||
| 22 | #endif | ||
| 23 | |||
| 24 | #endif /* CONFIG_DISCONTIGMEM */ | ||
| 25 | |||
| 26 | #ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE | ||
| 27 | struct page; | ||
| 28 | /* this is useful when inlined pfn_to_page is too big */ | ||
| 29 | extern struct page *pfn_to_page(unsigned long pfn); | ||
| 30 | extern unsigned long page_to_pfn(struct page *page); | ||
| 31 | #else | ||
| 32 | /* | ||
| 33 | * supports 3 memory models. | ||
| 34 | */ | ||
| 35 | #if defined(CONFIG_FLATMEM) | ||
| 36 | |||
| 37 | #define pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET)) | ||
| 38 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map) + \ | ||
| 39 | ARCH_PFN_OFFSET) | ||
| 40 | #elif defined(CONFIG_DISCONTIGMEM) | ||
| 41 | |||
| 42 | #define pfn_to_page(pfn) \ | ||
| 43 | ({ unsigned long __pfn = (pfn); \ | ||
| 44 | unsigned long __nid = arch_pfn_to_nid(pfn); \ | ||
| 45 | NODE_DATA(__nid)->node_mem_map + arch_local_page_offset(__pfn, __nid);\ | ||
| 46 | }) | ||
| 47 | |||
| 48 | #define page_to_pfn(pg) \ | ||
| 49 | ({ struct page *__pg = (pg); \ | ||
| 50 | struct pglist_data *__pgdat = NODE_DATA(page_to_nid(__pg)); \ | ||
| 51 | (unsigned long)(__pg - __pgdat->node_mem_map) + \ | ||
| 52 | __pgdat->node_start_pfn; \ | ||
| 53 | }) | ||
| 54 | |||
| 55 | #elif defined(CONFIG_SPARSEMEM) | ||
| 56 | /* | ||
| 57 | * Note: section's mem_map is encorded to reflect its start_pfn. | ||
| 58 | * section[i].section_mem_map == mem_map's address - start_pfn; | ||
| 59 | */ | ||
| 60 | #define page_to_pfn(pg) \ | ||
| 61 | ({ struct page *__pg = (pg); \ | ||
| 62 | int __sec = page_to_section(__pg); \ | ||
| 63 | __pg - __section_mem_map_addr(__nr_to_section(__sec)); \ | ||
| 64 | }) | ||
| 65 | |||
| 66 | #define pfn_to_page(pfn) \ | ||
| 67 | ({ unsigned long __pfn = (pfn); \ | ||
| 68 | struct mem_section *__sec = __pfn_to_section(__pfn); \ | ||
| 69 | __section_mem_map_addr(__sec) + __pfn; \ | ||
| 70 | }) | ||
| 71 | #endif /* CONFIG_FLATMEM/DISCONTIGMEM/SPARSEMEM */ | ||
| 72 | #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */ | ||
| 73 | |||
| 74 | #endif /* __ASSEMBLY__ */ | ||
| 75 | #endif /* __KERNEL__ */ | ||
| 76 | |||
| 77 | #endif | ||
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h index 78cf45547e31..c0caf433a7d7 100644 --- a/include/asm-generic/percpu.h +++ b/include/asm-generic/percpu.h | |||
| @@ -19,7 +19,7 @@ extern unsigned long __per_cpu_offset[NR_CPUS]; | |||
| 19 | #define percpu_modcopy(pcpudst, src, size) \ | 19 | #define percpu_modcopy(pcpudst, src, size) \ |
| 20 | do { \ | 20 | do { \ |
| 21 | unsigned int __i; \ | 21 | unsigned int __i; \ |
| 22 | for_each_cpu(__i) \ | 22 | for_each_possible_cpu(__i) \ |
| 23 | memcpy((pcpudst)+__per_cpu_offset[__i], \ | 23 | memcpy((pcpudst)+__per_cpu_offset[__i], \ |
| 24 | (src), (size)); \ | 24 | (src), (size)); \ |
| 25 | } while (0) | 25 | } while (0) |
diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h index cd35b1cc6cde..6472c9f88227 100644 --- a/include/asm-h8300/page.h +++ b/include/asm-h8300/page.h | |||
| @@ -71,8 +71,7 @@ extern unsigned long memory_end; | |||
| 71 | #define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) | 71 | #define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) |
| 72 | #define pfn_valid(page) (page < max_mapnr) | 72 | #define pfn_valid(page) (page < max_mapnr) |
| 73 | 73 | ||
| 74 | #define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn)) | 74 | #define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) |
| 75 | #define page_to_pfn(page) virt_to_pfn(page_to_virt(page)) | ||
| 76 | 75 | ||
| 77 | #define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \ | 76 | #define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \ |
| 78 | ((void *)(kaddr) < (void *)memory_end)) | 77 | ((void *)(kaddr) < (void *)memory_end)) |
| @@ -81,6 +80,7 @@ extern unsigned long memory_end; | |||
| 81 | 80 | ||
| 82 | #endif /* __KERNEL__ */ | 81 | #endif /* __KERNEL__ */ |
| 83 | 82 | ||
| 83 | #include <asm-generic/memory_model.h> | ||
| 84 | #include <asm-generic/page.h> | 84 | #include <asm-generic/page.h> |
| 85 | 85 | ||
| 86 | #endif /* _H8300_PAGE_H */ | 86 | #endif /* _H8300_PAGE_H */ |
diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h index 44b9db806474..7b8ceefd010f 100644 --- a/include/asm-i386/futex.h +++ b/include/asm-i386/futex.h | |||
| @@ -104,5 +104,32 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
| 104 | return ret; | 104 | return ret; |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | static inline int | ||
| 108 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | ||
| 109 | { | ||
| 110 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) | ||
| 111 | return -EFAULT; | ||
| 112 | |||
| 113 | __asm__ __volatile__( | ||
| 114 | "1: " LOCK_PREFIX "cmpxchgl %3, %1 \n" | ||
| 115 | |||
| 116 | "2: .section .fixup, \"ax\" \n" | ||
| 117 | "3: mov %2, %0 \n" | ||
| 118 | " jmp 2b \n" | ||
| 119 | " .previous \n" | ||
| 120 | |||
| 121 | " .section __ex_table, \"a\" \n" | ||
| 122 | " .align 8 \n" | ||
| 123 | " .long 1b,3b \n" | ||
| 124 | " .previous \n" | ||
| 125 | |||
| 126 | : "=a" (oldval), "=m" (*uaddr) | ||
| 127 | : "i" (-EFAULT), "r" (newval), "0" (oldval) | ||
| 128 | : "memory" | ||
| 129 | ); | ||
| 130 | |||
| 131 | return oldval; | ||
| 132 | } | ||
| 133 | |||
| 107 | #endif | 134 | #endif |
| 108 | #endif | 135 | #endif |
diff --git a/include/asm-i386/kdebug.h b/include/asm-i386/kdebug.h index 316138e89910..96d0828ce096 100644 --- a/include/asm-i386/kdebug.h +++ b/include/asm-i386/kdebug.h | |||
| @@ -17,11 +17,9 @@ struct die_args { | |||
| 17 | int signr; | 17 | int signr; |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | /* Note - you should never unregister because that can race with NMIs. | 20 | extern int register_die_notifier(struct notifier_block *); |
| 21 | If you really want to do it first unregister - then synchronize_sched - then free. | 21 | extern int unregister_die_notifier(struct notifier_block *); |
| 22 | */ | 22 | extern struct atomic_notifier_head i386die_chain; |
| 23 | int register_die_notifier(struct notifier_block *nb); | ||
| 24 | extern struct notifier_block *i386die_chain; | ||
| 25 | 23 | ||
| 26 | 24 | ||
| 27 | /* Grossly misnamed. */ | 25 | /* Grossly misnamed. */ |
| @@ -51,7 +49,7 @@ static inline int notify_die(enum die_val val, const char *str, | |||
| 51 | .trapnr = trap, | 49 | .trapnr = trap, |
| 52 | .signr = sig | 50 | .signr = sig |
| 53 | }; | 51 | }; |
| 54 | return notifier_call_chain(&i386die_chain, val, &args); | 52 | return atomic_notifier_call_chain(&i386die_chain, val, &args); |
| 55 | } | 53 | } |
| 56 | 54 | ||
| 57 | #endif | 55 | #endif |
diff --git a/include/asm-i386/mach-default/mach_time.h b/include/asm-i386/mach-default/mach_time.h index b749aa44a86f..31eb5de6f3dc 100644 --- a/include/asm-i386/mach-default/mach_time.h +++ b/include/asm-i386/mach-default/mach_time.h | |||
| @@ -82,21 +82,8 @@ static inline int mach_set_rtc_mmss(unsigned long nowtime) | |||
| 82 | static inline unsigned long mach_get_cmos_time(void) | 82 | static inline unsigned long mach_get_cmos_time(void) |
| 83 | { | 83 | { |
| 84 | unsigned int year, mon, day, hour, min, sec; | 84 | unsigned int year, mon, day, hour, min, sec; |
| 85 | int i; | ||
| 86 | 85 | ||
| 87 | /* The Linux interpretation of the CMOS clock register contents: | 86 | do { |
| 88 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
| 89 | * RTC registers show the second which has precisely just started. | ||
| 90 | * Let's hope other operating systems interpret the RTC the same way. | ||
| 91 | */ | ||
| 92 | /* read RTC exactly on falling edge of update flag */ | ||
| 93 | for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ | ||
| 94 | if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) | ||
| 95 | break; | ||
| 96 | for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ | ||
| 97 | if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) | ||
| 98 | break; | ||
| 99 | do { /* Isn't this overkill ? UIP above should guarantee consistency */ | ||
| 100 | sec = CMOS_READ(RTC_SECONDS); | 87 | sec = CMOS_READ(RTC_SECONDS); |
| 101 | min = CMOS_READ(RTC_MINUTES); | 88 | min = CMOS_READ(RTC_MINUTES); |
| 102 | hour = CMOS_READ(RTC_HOURS); | 89 | hour = CMOS_READ(RTC_HOURS); |
| @@ -104,16 +91,18 @@ static inline unsigned long mach_get_cmos_time(void) | |||
| 104 | mon = CMOS_READ(RTC_MONTH); | 91 | mon = CMOS_READ(RTC_MONTH); |
| 105 | year = CMOS_READ(RTC_YEAR); | 92 | year = CMOS_READ(RTC_YEAR); |
| 106 | } while (sec != CMOS_READ(RTC_SECONDS)); | 93 | } while (sec != CMOS_READ(RTC_SECONDS)); |
| 107 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | 94 | |
| 108 | { | 95 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
| 109 | BCD_TO_BIN(sec); | 96 | BCD_TO_BIN(sec); |
| 110 | BCD_TO_BIN(min); | 97 | BCD_TO_BIN(min); |
| 111 | BCD_TO_BIN(hour); | 98 | BCD_TO_BIN(hour); |
| 112 | BCD_TO_BIN(day); | 99 | BCD_TO_BIN(day); |
| 113 | BCD_TO_BIN(mon); | 100 | BCD_TO_BIN(mon); |
| 114 | BCD_TO_BIN(year); | 101 | BCD_TO_BIN(year); |
| 115 | } | 102 | } |
| 116 | if ((year += 1900) < 1970) | 103 | |
| 104 | year += 1900; | ||
| 105 | if (year < 1970) | ||
| 117 | year += 100; | 106 | year += 100; |
| 118 | 107 | ||
| 119 | return mktime(year, mon, day, hour, min, sec); | 108 | return mktime(year, mon, day, hour, min, sec); |
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h index 74f595d80579..e33e9f9e4c66 100644 --- a/include/asm-i386/mmzone.h +++ b/include/asm-i386/mmzone.h | |||
| @@ -70,8 +70,6 @@ static inline int pfn_to_nid(unsigned long pfn) | |||
| 70 | #endif | 70 | #endif |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | #define node_localnr(pfn, nid) ((pfn) - node_data[nid]->node_start_pfn) | ||
| 74 | |||
| 75 | /* | 73 | /* |
| 76 | * Following are macros that each numa implmentation must define. | 74 | * Following are macros that each numa implmentation must define. |
| 77 | */ | 75 | */ |
| @@ -86,21 +84,6 @@ static inline int pfn_to_nid(unsigned long pfn) | |||
| 86 | /* XXX: FIXME -- wli */ | 84 | /* XXX: FIXME -- wli */ |
| 87 | #define kern_addr_valid(kaddr) (0) | 85 | #define kern_addr_valid(kaddr) (0) |
| 88 | 86 | ||
| 89 | #define pfn_to_page(pfn) \ | ||
| 90 | ({ \ | ||
| 91 | unsigned long __pfn = pfn; \ | ||
| 92 | int __node = pfn_to_nid(__pfn); \ | ||
| 93 | &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \ | ||
| 94 | }) | ||
| 95 | |||
| 96 | #define page_to_pfn(pg) \ | ||
| 97 | ({ \ | ||
| 98 | struct page *__page = pg; \ | ||
| 99 | struct zone *__zone = page_zone(__page); \ | ||
| 100 | (unsigned long)(__page - __zone->zone_mem_map) \ | ||
| 101 | + __zone->zone_start_pfn; \ | ||
| 102 | }) | ||
| 103 | |||
| 104 | #ifdef CONFIG_X86_NUMAQ /* we have contiguous memory on NUMA-Q */ | 87 | #ifdef CONFIG_X86_NUMAQ /* we have contiguous memory on NUMA-Q */ |
| 105 | #define pfn_valid(pfn) ((pfn) < num_physpages) | 88 | #define pfn_valid(pfn) ((pfn) < num_physpages) |
| 106 | #else | 89 | #else |
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h index 997ca5d17876..30f52a2263ba 100644 --- a/include/asm-i386/page.h +++ b/include/asm-i386/page.h | |||
| @@ -126,8 +126,6 @@ extern int page_is_ram(unsigned long pagenr); | |||
| 126 | #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) | 126 | #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) |
| 127 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) | 127 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) |
| 128 | #ifdef CONFIG_FLATMEM | 128 | #ifdef CONFIG_FLATMEM |
| 129 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
| 130 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map)) | ||
| 131 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | 129 | #define pfn_valid(pfn) ((pfn) < max_mapnr) |
| 132 | #endif /* CONFIG_FLATMEM */ | 130 | #endif /* CONFIG_FLATMEM */ |
| 133 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | 131 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) |
| @@ -141,6 +139,7 @@ extern int page_is_ram(unsigned long pagenr); | |||
| 141 | 139 | ||
| 142 | #endif /* __KERNEL__ */ | 140 | #endif /* __KERNEL__ */ |
| 143 | 141 | ||
| 142 | #include <asm-generic/memory_model.h> | ||
| 144 | #include <asm-generic/page.h> | 143 | #include <asm-generic/page.h> |
| 145 | 144 | ||
| 146 | #endif /* _I386_PAGE_H */ | 145 | #endif /* _I386_PAGE_H */ |
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index feca5d961e2b..805f0dcda468 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/config.h> | 20 | #include <linux/config.h> |
| 21 | #include <linux/threads.h> | 21 | #include <linux/threads.h> |
| 22 | #include <asm/percpu.h> | 22 | #include <asm/percpu.h> |
| 23 | #include <linux/cpumask.h> | ||
| 23 | 24 | ||
| 24 | /* flag for disabling the tsc */ | 25 | /* flag for disabling the tsc */ |
| 25 | extern int tsc_disable; | 26 | extern int tsc_disable; |
| @@ -67,6 +68,9 @@ struct cpuinfo_x86 { | |||
| 67 | char pad0; | 68 | char pad0; |
| 68 | int x86_power; | 69 | int x86_power; |
| 69 | unsigned long loops_per_jiffy; | 70 | unsigned long loops_per_jiffy; |
| 71 | #ifdef CONFIG_SMP | ||
| 72 | cpumask_t llc_shared_map; /* cpus sharing the last level cache */ | ||
| 73 | #endif | ||
| 70 | unsigned char x86_max_cores; /* cpuid returned max cores value */ | 74 | unsigned char x86_max_cores; /* cpuid returned max cores value */ |
| 71 | unsigned char booted_cores; /* number of cores as seen by OS */ | 75 | unsigned char booted_cores; /* number of cores as seen by OS */ |
| 72 | unsigned char apicid; | 76 | unsigned char apicid; |
| @@ -103,6 +107,7 @@ extern struct cpuinfo_x86 cpu_data[]; | |||
| 103 | 107 | ||
| 104 | extern int phys_proc_id[NR_CPUS]; | 108 | extern int phys_proc_id[NR_CPUS]; |
| 105 | extern int cpu_core_id[NR_CPUS]; | 109 | extern int cpu_core_id[NR_CPUS]; |
| 110 | extern int cpu_llc_id[NR_CPUS]; | ||
| 106 | extern char ignore_fpu_irq; | 111 | extern char ignore_fpu_irq; |
| 107 | 112 | ||
| 108 | extern void identify_cpu(struct cpuinfo_x86 *); | 113 | extern void identify_cpu(struct cpuinfo_x86 *); |
| @@ -616,8 +621,6 @@ struct extended_sigtable { | |||
| 616 | unsigned int reserved[3]; | 621 | unsigned int reserved[3]; |
| 617 | struct extended_signature sigs[0]; | 622 | struct extended_signature sigs[0]; |
| 618 | }; | 623 | }; |
| 619 | /* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */ | ||
| 620 | #define MICROCODE_IOCFREE _IO('6',0) | ||
| 621 | 624 | ||
| 622 | /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ | 625 | /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ |
| 623 | static inline void rep_nop(void) | 626 | static inline void rep_nop(void) |
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h index 826a8ca50ac8..ee941457b55d 100644 --- a/include/asm-i386/setup.h +++ b/include/asm-i386/setup.h | |||
| @@ -6,9 +6,7 @@ | |||
| 6 | #ifndef _i386_SETUP_H | 6 | #ifndef _i386_SETUP_H |
| 7 | #define _i386_SETUP_H | 7 | #define _i386_SETUP_H |
| 8 | 8 | ||
| 9 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | 9 | #include <linux/pfn.h> |
| 10 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
| 11 | #define PFN_PHYS(x) ((x) << PAGE_SHIFT) | ||
| 12 | 10 | ||
| 13 | /* | 11 | /* |
| 14 | * Reserved space for vmalloc and iomap - defined in asm/page.h | 12 | * Reserved space for vmalloc and iomap - defined in asm/page.h |
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h index aa958c6ee83e..b94e5eeef917 100644 --- a/include/asm-i386/topology.h +++ b/include/asm-i386/topology.h | |||
| @@ -112,4 +112,6 @@ extern unsigned long node_remap_size[]; | |||
| 112 | 112 | ||
| 113 | #endif /* CONFIG_NUMA */ | 113 | #endif /* CONFIG_NUMA */ |
| 114 | 114 | ||
| 115 | extern cpumask_t cpu_coregroup_map(int cpu); | ||
| 116 | |||
| 115 | #endif /* _ASM_I386_TOPOLOGY_H */ | 117 | #endif /* _ASM_I386_TOPOLOGY_H */ |
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h index d8afd0e3b81a..014e3562895b 100644 --- a/include/asm-i386/unistd.h +++ b/include/asm-i386/unistd.h | |||
| @@ -316,8 +316,10 @@ | |||
| 316 | #define __NR_pselect6 308 | 316 | #define __NR_pselect6 308 |
| 317 | #define __NR_ppoll 309 | 317 | #define __NR_ppoll 309 |
| 318 | #define __NR_unshare 310 | 318 | #define __NR_unshare 310 |
| 319 | #define __NR_set_robust_list 311 | ||
| 320 | #define __NR_get_robust_list 312 | ||
| 319 | 321 | ||
| 320 | #define NR_syscalls 311 | 322 | #define NR_syscalls 313 |
| 321 | 323 | ||
| 322 | /* | 324 | /* |
| 323 | * user-visible error numbers are in the range -1 - -128: see | 325 | * user-visible error numbers are in the range -1 - -128: see |
diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h index c0b19106665c..40d01d80610d 100644 --- a/include/asm-ia64/compat.h +++ b/include/asm-ia64/compat.h | |||
| @@ -189,6 +189,12 @@ compat_ptr (compat_uptr_t uptr) | |||
| 189 | return (void __user *) (unsigned long) uptr; | 189 | return (void __user *) (unsigned long) uptr; |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | static inline compat_uptr_t | ||
| 193 | ptr_to_compat(void __user *uptr) | ||
| 194 | { | ||
| 195 | return (u32)(unsigned long)uptr; | ||
| 196 | } | ||
| 197 | |||
| 192 | static __inline__ void __user * | 198 | static __inline__ void __user * |
| 193 | compat_alloc_user_space (long len) | 199 | compat_alloc_user_space (long len) |
| 194 | { | 200 | { |
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h index 8b01a083dde6..218c458ab60c 100644 --- a/include/asm-ia64/kdebug.h +++ b/include/asm-ia64/kdebug.h | |||
| @@ -40,7 +40,7 @@ struct die_args { | |||
| 40 | 40 | ||
| 41 | extern int register_die_notifier(struct notifier_block *); | 41 | extern int register_die_notifier(struct notifier_block *); |
| 42 | extern int unregister_die_notifier(struct notifier_block *); | 42 | extern int unregister_die_notifier(struct notifier_block *); |
| 43 | extern struct notifier_block *ia64die_chain; | 43 | extern struct atomic_notifier_head ia64die_chain; |
| 44 | 44 | ||
| 45 | enum die_val { | 45 | enum die_val { |
| 46 | DIE_BREAK = 1, | 46 | DIE_BREAK = 1, |
| @@ -81,7 +81,7 @@ static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs, | |||
| 81 | .signr = sig | 81 | .signr = sig |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | return notifier_call_chain(&ia64die_chain, val, &args); | 84 | return atomic_notifier_call_chain(&ia64die_chain, val, &args); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | #endif | 87 | #endif |
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h index 6e9aa23250c4..2087825eefa4 100644 --- a/include/asm-ia64/page.h +++ b/include/asm-ia64/page.h | |||
| @@ -106,17 +106,25 @@ extern int ia64_pfn_valid (unsigned long pfn); | |||
| 106 | # define ia64_pfn_valid(pfn) 1 | 106 | # define ia64_pfn_valid(pfn) 1 |
| 107 | #endif | 107 | #endif |
| 108 | 108 | ||
| 109 | #ifdef CONFIG_VIRTUAL_MEM_MAP | ||
| 110 | extern struct page *vmem_map; | ||
| 111 | #ifdef CONFIG_DISCONTIGMEM | ||
| 112 | # define page_to_pfn(page) ((unsigned long) (page - vmem_map)) | ||
| 113 | # define pfn_to_page(pfn) (vmem_map + (pfn)) | ||
| 114 | #endif | ||
| 115 | #endif | ||
| 116 | |||
| 117 | #if defined(CONFIG_FLATMEM) || defined(CONFIG_SPARSEMEM) | ||
| 118 | /* FLATMEM always configures mem_map (mem_map = vmem_map if necessary) */ | ||
| 119 | #include <asm-generic/memory_model.h> | ||
| 120 | #endif | ||
| 121 | |||
| 109 | #ifdef CONFIG_FLATMEM | 122 | #ifdef CONFIG_FLATMEM |
| 110 | # define pfn_valid(pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn)) | 123 | # define pfn_valid(pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn)) |
| 111 | # define page_to_pfn(page) ((unsigned long) (page - mem_map)) | ||
| 112 | # define pfn_to_page(pfn) (mem_map + (pfn)) | ||
| 113 | #elif defined(CONFIG_DISCONTIGMEM) | 124 | #elif defined(CONFIG_DISCONTIGMEM) |
| 114 | extern struct page *vmem_map; | ||
| 115 | extern unsigned long min_low_pfn; | 125 | extern unsigned long min_low_pfn; |
| 116 | extern unsigned long max_low_pfn; | 126 | extern unsigned long max_low_pfn; |
| 117 | # define pfn_valid(pfn) (((pfn) >= min_low_pfn) && ((pfn) < max_low_pfn) && ia64_pfn_valid(pfn)) | 127 | # define pfn_valid(pfn) (((pfn) >= min_low_pfn) && ((pfn) < max_low_pfn) && ia64_pfn_valid(pfn)) |
| 118 | # define page_to_pfn(page) ((unsigned long) (page - vmem_map)) | ||
| 119 | # define pfn_to_page(pfn) (vmem_map + (pfn)) | ||
| 120 | #endif | 128 | #endif |
| 121 | 129 | ||
| 122 | #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) | 130 | #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) |
diff --git a/include/asm-m32r/mmzone.h b/include/asm-m32r/mmzone.h index adc7970a77ec..9f3b5accda88 100644 --- a/include/asm-m32r/mmzone.h +++ b/include/asm-m32r/mmzone.h | |||
| @@ -21,20 +21,6 @@ extern struct pglist_data *node_data[]; | |||
| 21 | __pgdat->node_start_pfn + __pgdat->node_spanned_pages - 1; \ | 21 | __pgdat->node_start_pfn + __pgdat->node_spanned_pages - 1; \ |
| 22 | }) | 22 | }) |
| 23 | 23 | ||
| 24 | #define pfn_to_page(pfn) \ | ||
| 25 | ({ \ | ||
| 26 | unsigned long __pfn = pfn; \ | ||
| 27 | int __node = pfn_to_nid(__pfn); \ | ||
| 28 | &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \ | ||
| 29 | }) | ||
| 30 | |||
| 31 | #define page_to_pfn(pg) \ | ||
| 32 | ({ \ | ||
| 33 | struct page *__page = pg; \ | ||
| 34 | struct zone *__zone = page_zone(__page); \ | ||
| 35 | (unsigned long)(__page - __zone->zone_mem_map) \ | ||
| 36 | + __zone->zone_start_pfn; \ | ||
| 37 | }) | ||
| 38 | #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) | 24 | #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) |
| 39 | /* | 25 | /* |
| 40 | * pfn_valid should be made as fast as possible, and the current definition | 26 | * pfn_valid should be made as fast as possible, and the current definition |
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h index 4ab578876361..9ddbc087dbc5 100644 --- a/include/asm-m32r/page.h +++ b/include/asm-m32r/page.h | |||
| @@ -76,9 +76,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 76 | 76 | ||
| 77 | #ifndef CONFIG_DISCONTIGMEM | 77 | #ifndef CONFIG_DISCONTIGMEM |
| 78 | #define PFN_BASE (CONFIG_MEMORY_START >> PAGE_SHIFT) | 78 | #define PFN_BASE (CONFIG_MEMORY_START >> PAGE_SHIFT) |
| 79 | #define pfn_to_page(pfn) (mem_map + ((pfn) - PFN_BASE)) | 79 | #define ARCH_PFN_OFFSET PFN_BASE |
| 80 | #define page_to_pfn(page) \ | ||
| 81 | ((unsigned long)((page) - mem_map) + PFN_BASE) | ||
| 82 | #define pfn_valid(pfn) (((pfn) - PFN_BASE) < max_mapnr) | 80 | #define pfn_valid(pfn) (((pfn) - PFN_BASE) < max_mapnr) |
| 83 | #endif /* !CONFIG_DISCONTIGMEM */ | 81 | #endif /* !CONFIG_DISCONTIGMEM */ |
| 84 | 82 | ||
| @@ -92,6 +90,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 92 | 90 | ||
| 93 | #endif /* __KERNEL__ */ | 91 | #endif /* __KERNEL__ */ |
| 94 | 92 | ||
| 93 | #include <asm-generic/memory_model.h> | ||
| 95 | #include <asm-generic/page.h> | 94 | #include <asm-generic/page.h> |
| 96 | 95 | ||
| 97 | #endif /* _ASM_M32R_PAGE_H */ | 96 | #endif /* _ASM_M32R_PAGE_H */ |
diff --git a/include/asm-m32r/setup.h b/include/asm-m32r/setup.h index 5f028dc26a9b..52f4fa29abfc 100644 --- a/include/asm-m32r/setup.h +++ b/include/asm-m32r/setup.h | |||
| @@ -24,10 +24,6 @@ | |||
| 24 | #define RAMDISK_PROMPT_FLAG (0x8000) | 24 | #define RAMDISK_PROMPT_FLAG (0x8000) |
| 25 | #define RAMDISK_LOAD_FLAG (0x4000) | 25 | #define RAMDISK_LOAD_FLAG (0x4000) |
| 26 | 26 | ||
| 27 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | ||
| 28 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
| 29 | #define PFN_PHYS(x) ((x) << PAGE_SHIFT) | ||
| 30 | |||
| 31 | extern unsigned long memory_start; | 27 | extern unsigned long memory_start; |
| 32 | extern unsigned long memory_end; | 28 | extern unsigned long memory_end; |
| 33 | 29 | ||
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h index 0012bd804d2d..986511db54a6 100644 --- a/include/asm-mips/compat.h +++ b/include/asm-mips/compat.h | |||
| @@ -133,6 +133,11 @@ static inline void __user *compat_ptr(compat_uptr_t uptr) | |||
| 133 | return (void __user *)(long)uptr; | 133 | return (void __user *)(long)uptr; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | static inline compat_uptr_t ptr_to_compat(void __user *uptr) | ||
| 137 | { | ||
| 138 | return (u32)(unsigned long)uptr; | ||
| 139 | } | ||
| 140 | |||
| 136 | static inline void __user *compat_alloc_user_space(long len) | 141 | static inline void __user *compat_alloc_user_space(long len) |
| 137 | { | 142 | { |
| 138 | struct pt_regs *regs = (struct pt_regs *) | 143 | struct pt_regs *regs = (struct pt_regs *) |
diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h index 2454c44a8f54..a554089991f2 100644 --- a/include/asm-mips/futex.h +++ b/include/asm-mips/futex.h | |||
| @@ -99,5 +99,11 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
| 99 | return ret; | 99 | return ret; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | static inline int | ||
| 103 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | ||
| 104 | { | ||
| 105 | return -ENOSYS; | ||
| 106 | } | ||
| 107 | |||
| 102 | #endif | 108 | #endif |
| 103 | #endif | 109 | #endif |
diff --git a/include/asm-mips/mc146818-time.h b/include/asm-mips/mc146818-time.h index 47214861093b..41ac8d363c67 100644 --- a/include/asm-mips/mc146818-time.h +++ b/include/asm-mips/mc146818-time.h | |||
| @@ -86,43 +86,14 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime) | |||
| 86 | return retval; | 86 | return retval; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | /* | ||
| 90 | * Returns true if a clock update is in progress | ||
| 91 | */ | ||
| 92 | static inline unsigned char rtc_is_updating(void) | ||
| 93 | { | ||
| 94 | unsigned char uip; | ||
| 95 | unsigned long flags; | ||
| 96 | |||
| 97 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 98 | uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); | ||
| 99 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 100 | return uip; | ||
| 101 | } | ||
| 102 | |||
| 103 | static inline unsigned long mc146818_get_cmos_time(void) | 89 | static inline unsigned long mc146818_get_cmos_time(void) |
| 104 | { | 90 | { |
| 105 | unsigned int year, mon, day, hour, min, sec; | 91 | unsigned int year, mon, day, hour, min, sec; |
| 106 | int i; | ||
| 107 | unsigned long flags; | 92 | unsigned long flags; |
| 108 | 93 | ||
| 109 | /* | ||
| 110 | * The Linux interpretation of the CMOS clock register contents: | ||
| 111 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
| 112 | * RTC registers show the second which has precisely just started. | ||
| 113 | * Let's hope other operating systems interpret the RTC the same way. | ||
| 114 | */ | ||
| 115 | |||
| 116 | /* read RTC exactly on falling edge of update flag */ | ||
| 117 | for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ | ||
| 118 | if (rtc_is_updating()) | ||
| 119 | break; | ||
| 120 | for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ | ||
| 121 | if (!rtc_is_updating()) | ||
| 122 | break; | ||
| 123 | |||
| 124 | spin_lock_irqsave(&rtc_lock, flags); | 94 | spin_lock_irqsave(&rtc_lock, flags); |
| 125 | do { /* Isn't this overkill ? UIP above should guarantee consistency */ | 95 | |
| 96 | do { | ||
| 126 | sec = CMOS_READ(RTC_SECONDS); | 97 | sec = CMOS_READ(RTC_SECONDS); |
| 127 | min = CMOS_READ(RTC_MINUTES); | 98 | min = CMOS_READ(RTC_MINUTES); |
| 128 | hour = CMOS_READ(RTC_HOURS); | 99 | hour = CMOS_READ(RTC_HOURS); |
diff --git a/include/asm-mips/mmzone.h b/include/asm-mips/mmzone.h index 011caebac369..7bde4432092b 100644 --- a/include/asm-mips/mmzone.h +++ b/include/asm-mips/mmzone.h | |||
| @@ -22,20 +22,6 @@ | |||
| 22 | NODE_DATA(__n)->node_spanned_pages) : 0);\ | 22 | NODE_DATA(__n)->node_spanned_pages) : 0);\ |
| 23 | }) | 23 | }) |
| 24 | 24 | ||
| 25 | #define pfn_to_page(pfn) \ | ||
| 26 | ({ \ | ||
| 27 | unsigned long __pfn = (pfn); \ | ||
| 28 | pg_data_t *__pg = NODE_DATA(pfn_to_nid(__pfn)); \ | ||
| 29 | __pg->node_mem_map + (__pfn - __pg->node_start_pfn); \ | ||
| 30 | }) | ||
| 31 | |||
| 32 | #define page_to_pfn(p) \ | ||
| 33 | ({ \ | ||
| 34 | struct page *__p = (p); \ | ||
| 35 | struct zone *__z = page_zone(__p); \ | ||
| 36 | ((__p - __z->zone_mem_map) + __z->zone_start_pfn); \ | ||
| 37 | }) | ||
| 38 | |||
| 39 | /* XXX: FIXME -- wli */ | 25 | /* XXX: FIXME -- wli */ |
| 40 | #define kern_addr_valid(addr) (0) | 26 | #define kern_addr_valid(addr) (0) |
| 41 | 27 | ||
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h index ee25a779bf49..a1eab136ff6c 100644 --- a/include/asm-mips/page.h +++ b/include/asm-mips/page.h | |||
| @@ -140,8 +140,6 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 140 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) | 140 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) |
| 141 | 141 | ||
| 142 | #ifndef CONFIG_NEED_MULTIPLE_NODES | 142 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
| 143 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
| 144 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map)) | ||
| 145 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | 143 | #define pfn_valid(pfn) ((pfn) < max_mapnr) |
| 146 | #endif | 144 | #endif |
| 147 | 145 | ||
| @@ -160,6 +158,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 160 | #define WANT_PAGE_VIRTUAL | 158 | #define WANT_PAGE_VIRTUAL |
| 161 | #endif | 159 | #endif |
| 162 | 160 | ||
| 161 | #include <asm-generic/memory_model.h> | ||
| 163 | #include <asm-generic/page.h> | 162 | #include <asm-generic/page.h> |
| 164 | 163 | ||
| 165 | #endif /* _ASM_PAGE_H */ | 164 | #endif /* _ASM_PAGE_H */ |
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h index e796d75f027e..7b2366412203 100644 --- a/include/asm-mips/serial.h +++ b/include/asm-mips/serial.h | |||
| @@ -103,88 +103,6 @@ | |||
| 103 | #define IVR_SERIAL_PORT_DEFNS | 103 | #define IVR_SERIAL_PORT_DEFNS |
| 104 | #endif | 104 | #endif |
| 105 | 105 | ||
| 106 | #ifdef CONFIG_SERIAL_AU1X00 | ||
| 107 | #include <asm/mach-au1x00/au1000.h> | ||
| 108 | #ifdef CONFIG_SOC_AU1000 | ||
| 109 | #define AU1000_SERIAL_PORT_DEFNS \ | ||
| 110 | { .baud_base = 0, .port = UART0_ADDR, \ | ||
| 111 | .iomem_base = (unsigned char *)UART0_ADDR, \ | ||
| 112 | .irq = AU1000_UART0_INT, .flags = STD_COM_FLAGS, \ | ||
| 113 | .iomem_reg_shift = 2 }, \ | ||
| 114 | { .baud_base = 0, .port = UART1_ADDR, \ | ||
| 115 | .iomem_base = (unsigned char *)UART1_ADDR, \ | ||
| 116 | .irq = AU1000_UART1_INT, .flags = STD_COM_FLAGS, \ | ||
| 117 | .iomem_reg_shift = 2 }, \ | ||
| 118 | { .baud_base = 0, .port = UART2_ADDR, \ | ||
| 119 | .iomem_base = (unsigned char *)UART2_ADDR, \ | ||
| 120 | .irq = AU1000_UART2_INT, .flags = STD_COM_FLAGS, \ | ||
| 121 | .iomem_reg_shift = 2 }, \ | ||
| 122 | { .baud_base = 0, .port = UART3_ADDR, \ | ||
| 123 | .iomem_base = (unsigned char *)UART3_ADDR, \ | ||
| 124 | .irq = AU1000_UART3_INT, .flags = STD_COM_FLAGS, \ | ||
| 125 | .iomem_reg_shift = 2 }, | ||
| 126 | #endif | ||
| 127 | |||
| 128 | #ifdef CONFIG_SOC_AU1500 | ||
| 129 | #define AU1000_SERIAL_PORT_DEFNS \ | ||
| 130 | { .baud_base = 0, .port = UART0_ADDR, \ | ||
| 131 | .iomem_base = (unsigned char *)UART0_ADDR, \ | ||
| 132 | .irq = AU1500_UART0_INT, .flags = STD_COM_FLAGS, \ | ||
| 133 | .iomem_reg_shift = 2 }, \ | ||
| 134 | { .baud_base = 0, .port = UART3_ADDR, \ | ||
| 135 | .iomem_base = (unsigned char *)UART3_ADDR, \ | ||
| 136 | .irq = AU1500_UART3_INT, .flags = STD_COM_FLAGS, \ | ||
| 137 | .iomem_reg_shift = 2 }, | ||
| 138 | #endif | ||
| 139 | |||
| 140 | #ifdef CONFIG_SOC_AU1100 | ||
| 141 | #define AU1000_SERIAL_PORT_DEFNS \ | ||
| 142 | { .baud_base = 0, .port = UART0_ADDR, \ | ||
| 143 | .iomem_base = (unsigned char *)UART0_ADDR, \ | ||
| 144 | .irq = AU1100_UART0_INT, .flags = STD_COM_FLAGS, \ | ||
| 145 | .iomem_reg_shift = 2 }, \ | ||
| 146 | { .baud_base = 0, .port = UART1_ADDR, \ | ||
| 147 | .iomem_base = (unsigned char *)UART1_ADDR, \ | ||
| 148 | .irq = AU1100_UART1_INT, .flags = STD_COM_FLAGS, \ | ||
| 149 | .iomem_reg_shift = 2 }, \ | ||
| 150 | { .baud_base = 0, .port = UART3_ADDR, \ | ||
| 151 | .iomem_base = (unsigned char *)UART3_ADDR, \ | ||
| 152 | .irq = AU1100_UART3_INT, .flags = STD_COM_FLAGS, \ | ||
| 153 | .iomem_reg_shift = 2 }, | ||
| 154 | #endif | ||
| 155 | |||
| 156 | #ifdef CONFIG_SOC_AU1550 | ||
| 157 | #define AU1000_SERIAL_PORT_DEFNS \ | ||
| 158 | { .baud_base = 0, .port = UART0_ADDR, \ | ||
| 159 | .iomem_base = (unsigned char *)UART0_ADDR, \ | ||
| 160 | .irq = AU1550_UART0_INT, .flags = STD_COM_FLAGS, \ | ||
| 161 | .iomem_reg_shift = 2 }, \ | ||
| 162 | { .baud_base = 0, .port = UART1_ADDR, \ | ||
| 163 | .iomem_base = (unsigned char *)UART1_ADDR, \ | ||
| 164 | .irq = AU1550_UART1_INT, .flags = STD_COM_FLAGS, \ | ||
| 165 | .iomem_reg_shift = 2 }, \ | ||
| 166 | { .baud_base = 0, .port = UART3_ADDR, \ | ||
| 167 | .iomem_base = (unsigned char *)UART3_ADDR, \ | ||
| 168 | .irq = AU1550_UART3_INT, .flags = STD_COM_FLAGS,\ | ||
| 169 | .iomem_reg_shift = 2 }, | ||
| 170 | #endif | ||
| 171 | |||
| 172 | #ifdef CONFIG_SOC_AU1200 | ||
| 173 | #define AU1000_SERIAL_PORT_DEFNS \ | ||
| 174 | { .baud_base = 0, .port = UART0_ADDR, \ | ||
| 175 | .iomem_base = (unsigned char *)UART0_ADDR, \ | ||
| 176 | .irq = AU1200_UART0_INT, .flags = STD_COM_FLAGS, \ | ||
| 177 | .iomem_reg_shift = 2 }, \ | ||
| 178 | { .baud_base = 0, .port = UART1_ADDR, \ | ||
| 179 | .iomem_base = (unsigned char *)UART1_ADDR, \ | ||
| 180 | .irq = AU1200_UART1_INT, .flags = STD_COM_FLAGS, \ | ||
| 181 | .iomem_reg_shift = 2 }, | ||
| 182 | #endif | ||
| 183 | |||
| 184 | #else | ||
| 185 | #define AU1000_SERIAL_PORT_DEFNS | ||
| 186 | #endif | ||
| 187 | |||
| 188 | #ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT | 106 | #ifdef CONFIG_HAVE_STD_PC_SERIAL_PORT |
| 189 | #define STD_SERIAL_PORT_DEFNS \ | 107 | #define STD_SERIAL_PORT_DEFNS \ |
| 190 | /* UART CLK PORT IRQ FLAGS */ \ | 108 | /* UART CLK PORT IRQ FLAGS */ \ |
| @@ -331,7 +249,6 @@ | |||
| 331 | MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS \ | 249 | MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS \ |
| 332 | MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \ | 250 | MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS \ |
| 333 | MOMENCO_OCELOT_SERIAL_PORT_DEFNS \ | 251 | MOMENCO_OCELOT_SERIAL_PORT_DEFNS \ |
| 334 | MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS \ | 252 | MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS |
| 335 | AU1000_SERIAL_PORT_DEFNS | ||
| 336 | 253 | ||
| 337 | #endif /* _ASM_SERIAL_H */ | 254 | #endif /* _ASM_SERIAL_H */ |
diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index 9cc3564cc2c9..d897c8bb554d 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h | |||
| @@ -26,14 +26,14 @@ extern spinlock_t rtc_lock; | |||
| 26 | 26 | ||
| 27 | /* | 27 | /* |
| 28 | * RTC ops. By default, they point to no-RTC functions. | 28 | * RTC ops. By default, they point to no-RTC functions. |
| 29 | * rtc_get_time - mktime(year, mon, day, hour, min, sec) in seconds. | 29 | * rtc_mips_get_time - mktime(year, mon, day, hour, min, sec) in seconds. |
| 30 | * rtc_set_time - reverse the above translation and set time to RTC. | 30 | * rtc_mips_set_time - reverse the above translation and set time to RTC. |
| 31 | * rtc_set_mmss - similar to rtc_set_time, but only min and sec need | 31 | * rtc_mips_set_mmss - similar to rtc_set_time, but only min and sec need |
| 32 | * to be set. Used by RTC sync-up. | 32 | * to be set. Used by RTC sync-up. |
| 33 | */ | 33 | */ |
| 34 | extern unsigned long (*rtc_get_time)(void); | 34 | extern unsigned long (*rtc_mips_get_time)(void); |
| 35 | extern int (*rtc_set_time)(unsigned long); | 35 | extern int (*rtc_mips_set_time)(unsigned long); |
| 36 | extern int (*rtc_set_mmss)(unsigned long); | 36 | extern int (*rtc_mips_set_mmss)(unsigned long); |
| 37 | 37 | ||
| 38 | /* | 38 | /* |
| 39 | * Timer interrupt functions. | 39 | * Timer interrupt functions. |
diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h index 38b918feead9..289624d8b2d4 100644 --- a/include/asm-parisc/compat.h +++ b/include/asm-parisc/compat.h | |||
| @@ -138,6 +138,11 @@ static inline void __user *compat_ptr(compat_uptr_t uptr) | |||
| 138 | return (void __user *)(unsigned long)uptr; | 138 | return (void __user *)(unsigned long)uptr; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | static inline compat_uptr_t ptr_to_compat(void __user *uptr) | ||
| 142 | { | ||
| 143 | return (u32)(unsigned long)uptr; | ||
| 144 | } | ||
| 145 | |||
| 141 | static __inline__ void __user *compat_alloc_user_space(long len) | 146 | static __inline__ void __user *compat_alloc_user_space(long len) |
| 142 | { | 147 | { |
| 143 | struct pt_regs *regs = ¤t->thread.regs; | 148 | struct pt_regs *regs = ¤t->thread.regs; |
diff --git a/include/asm-parisc/mmzone.h b/include/asm-parisc/mmzone.h index ae039f4fd711..ceb9b73199d1 100644 --- a/include/asm-parisc/mmzone.h +++ b/include/asm-parisc/mmzone.h | |||
| @@ -25,23 +25,6 @@ extern struct node_map_data node_data[]; | |||
| 25 | pg_data_t *__pgdat = NODE_DATA(nid); \ | 25 | pg_data_t *__pgdat = NODE_DATA(nid); \ |
| 26 | __pgdat->node_start_pfn + __pgdat->node_spanned_pages; \ | 26 | __pgdat->node_start_pfn + __pgdat->node_spanned_pages; \ |
| 27 | }) | 27 | }) |
| 28 | #define node_localnr(pfn, nid) ((pfn) - node_start_pfn(nid)) | ||
| 29 | |||
| 30 | #define pfn_to_page(pfn) \ | ||
| 31 | ({ \ | ||
| 32 | unsigned long __pfn = (pfn); \ | ||
| 33 | int __node = pfn_to_nid(__pfn); \ | ||
| 34 | &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \ | ||
| 35 | }) | ||
| 36 | |||
| 37 | #define page_to_pfn(pg) \ | ||
| 38 | ({ \ | ||
| 39 | struct page *__page = pg; \ | ||
| 40 | struct zone *__zone = page_zone(__page); \ | ||
| 41 | BUG_ON(__zone == NULL); \ | ||
| 42 | (unsigned long)(__page - __zone->zone_mem_map) \ | ||
| 43 | + __zone->zone_start_pfn; \ | ||
| 44 | }) | ||
| 45 | 28 | ||
| 46 | /* We have these possible memory map layouts: | 29 | /* We have these possible memory map layouts: |
| 47 | * Astro: 0-3.75, 67.75-68, 4-64 | 30 | * Astro: 0-3.75, 67.75-68, 4-64 |
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h index 4a6752b0afed..9f303c0c3cd7 100644 --- a/include/asm-parisc/page.h +++ b/include/asm-parisc/page.h | |||
| @@ -130,8 +130,6 @@ extern int npmem_ranges; | |||
| 130 | #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) | 130 | #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) |
| 131 | 131 | ||
| 132 | #ifndef CONFIG_DISCONTIGMEM | 132 | #ifndef CONFIG_DISCONTIGMEM |
| 133 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
| 134 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map)) | ||
| 135 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | 133 | #define pfn_valid(pfn) ((pfn) < max_mapnr) |
| 136 | #endif /* CONFIG_DISCONTIGMEM */ | 134 | #endif /* CONFIG_DISCONTIGMEM */ |
| 137 | 135 | ||
| @@ -152,6 +150,7 @@ extern int npmem_ranges; | |||
| 152 | 150 | ||
| 153 | #endif /* __KERNEL__ */ | 151 | #endif /* __KERNEL__ */ |
| 154 | 152 | ||
| 153 | #include <asm-generic/memory_model.h> | ||
| 155 | #include <asm-generic/page.h> | 154 | #include <asm-generic/page.h> |
| 156 | 155 | ||
| 157 | #endif /* _PARISC_PAGE_H */ | 156 | #endif /* _PARISC_PAGE_H */ |
diff --git a/include/asm-parisc/pdc.h b/include/asm-parisc/pdc.h index 8e23e4c674f6..0a3face6c480 100644 --- a/include/asm-parisc/pdc.h +++ b/include/asm-parisc/pdc.h | |||
| @@ -333,7 +333,7 @@ struct pdc_model { /* for PDC_MODEL */ | |||
| 333 | unsigned long curr_key; | 333 | unsigned long curr_key; |
| 334 | }; | 334 | }; |
| 335 | 335 | ||
| 336 | /* Values for PDC_MODEL_CAPABILITES non-equivalent virtual aliasing support */ | 336 | /* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */ |
| 337 | 337 | ||
| 338 | #define PDC_MODEL_IOPDIR_FDC (1 << 2) /* see sba_iommu.c */ | 338 | #define PDC_MODEL_IOPDIR_FDC (1 << 2) /* see sba_iommu.c */ |
| 339 | #define PDC_MODEL_NVA_MASK (3 << 4) | 339 | #define PDC_MODEL_NVA_MASK (3 << 4) |
diff --git a/include/asm-powerpc/futex.h b/include/asm-powerpc/futex.h index 39e85f320a76..f1b3c00bc1ce 100644 --- a/include/asm-powerpc/futex.h +++ b/include/asm-powerpc/futex.h | |||
| @@ -81,5 +81,11 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
| 81 | return ret; | 81 | return ret; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static inline int | ||
| 85 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | ||
| 86 | { | ||
| 87 | return -ENOSYS; | ||
| 88 | } | ||
| 89 | |||
| 84 | #endif /* __KERNEL__ */ | 90 | #endif /* __KERNEL__ */ |
| 85 | #endif /* _ASM_POWERPC_FUTEX_H */ | 91 | #endif /* _ASM_POWERPC_FUTEX_H */ |
diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h index 7c16265568e0..c01786ab5fa6 100644 --- a/include/asm-powerpc/kdebug.h +++ b/include/asm-powerpc/kdebug.h | |||
| @@ -16,13 +16,9 @@ struct die_args { | |||
| 16 | int signr; | 16 | int signr; |
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | /* | 19 | extern int register_die_notifier(struct notifier_block *); |
| 20 | Note - you should never unregister because that can race with NMIs. | 20 | extern int unregister_die_notifier(struct notifier_block *); |
| 21 | If you really want to do it first unregister - then synchronize_sched - | 21 | extern struct atomic_notifier_head powerpc_die_chain; |
| 22 | then free. | ||
| 23 | */ | ||
| 24 | int register_die_notifier(struct notifier_block *nb); | ||
| 25 | extern struct notifier_block *powerpc_die_chain; | ||
| 26 | 22 | ||
| 27 | /* Grossly misnamed. */ | 23 | /* Grossly misnamed. */ |
| 28 | enum die_val { | 24 | enum die_val { |
| @@ -37,7 +33,7 @@ enum die_val { | |||
| 37 | static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig) | 33 | static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig) |
| 38 | { | 34 | { |
| 39 | struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig }; | 35 | struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig }; |
| 40 | return notifier_call_chain(&powerpc_die_chain, val, &args); | 36 | return atomic_notifier_call_chain(&powerpc_die_chain, val, &args); |
| 41 | } | 37 | } |
| 42 | 38 | ||
| 43 | #endif /* __KERNEL__ */ | 39 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h index 0b82df483f7f..2fbecebe1c92 100644 --- a/include/asm-powerpc/page.h +++ b/include/asm-powerpc/page.h | |||
| @@ -69,8 +69,6 @@ | |||
| 69 | #endif | 69 | #endif |
| 70 | 70 | ||
| 71 | #ifdef CONFIG_FLATMEM | 71 | #ifdef CONFIG_FLATMEM |
| 72 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
| 73 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map)) | ||
| 74 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | 72 | #define pfn_valid(pfn) ((pfn) < max_mapnr) |
| 75 | #endif | 73 | #endif |
| 76 | 74 | ||
| @@ -200,6 +198,7 @@ extern void copy_user_page(void *to, void *from, unsigned long vaddr, | |||
| 200 | struct page *p); | 198 | struct page *p); |
| 201 | extern int page_is_ram(unsigned long pfn); | 199 | extern int page_is_ram(unsigned long pfn); |
| 202 | 200 | ||
| 201 | #include <asm-generic/memory_model.h> | ||
| 203 | #endif /* __ASSEMBLY__ */ | 202 | #endif /* __ASSEMBLY__ */ |
| 204 | 203 | ||
| 205 | #endif /* __KERNEL__ */ | 204 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h index 538e0c8ab243..a70ba2ee552d 100644 --- a/include/asm-ppc/page.h +++ b/include/asm-ppc/page.h | |||
| @@ -149,8 +149,7 @@ extern int page_is_ram(unsigned long pfn); | |||
| 149 | #define __pa(x) ___pa((unsigned long)(x)) | 149 | #define __pa(x) ___pa((unsigned long)(x)) |
| 150 | #define __va(x) ((void *)(___va((unsigned long)(x)))) | 150 | #define __va(x) ((void *)(___va((unsigned long)(x)))) |
| 151 | 151 | ||
| 152 | #define pfn_to_page(pfn) (mem_map + ((pfn) - PPC_PGSTART)) | 152 | #define ARCH_PFN_OFFSET (PPC_PGSTART) |
| 153 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PPC_PGSTART) | ||
| 154 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | 153 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) |
| 155 | #define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT) | 154 | #define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT) |
| 156 | 155 | ||
| @@ -175,5 +174,6 @@ extern __inline__ int get_order(unsigned long size) | |||
| 175 | /* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */ | 174 | /* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */ |
| 176 | #define __HAVE_ARCH_GATE_AREA 1 | 175 | #define __HAVE_ARCH_GATE_AREA 1 |
| 177 | 176 | ||
| 177 | #include <asm-generic/memory_model.h> | ||
| 178 | #endif /* __KERNEL__ */ | 178 | #endif /* __KERNEL__ */ |
| 179 | #endif /* _PPC_PAGE_H */ | 179 | #endif /* _PPC_PAGE_H */ |
diff --git a/include/asm-s390/compat.h b/include/asm-s390/compat.h index a007715f4aea..356a0b183539 100644 --- a/include/asm-s390/compat.h +++ b/include/asm-s390/compat.h | |||
| @@ -128,6 +128,11 @@ static inline void __user *compat_ptr(compat_uptr_t uptr) | |||
| 128 | return (void __user *)(unsigned long)(uptr & 0x7fffffffUL); | 128 | return (void __user *)(unsigned long)(uptr & 0x7fffffffUL); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | static inline compat_uptr_t ptr_to_compat(void __user *uptr) | ||
| 132 | { | ||
| 133 | return (u32)(unsigned long)uptr; | ||
| 134 | } | ||
| 135 | |||
| 131 | static inline void __user *compat_alloc_user_space(long len) | 136 | static inline void __user *compat_alloc_user_space(long len) |
| 132 | { | 137 | { |
| 133 | unsigned long stack; | 138 | unsigned long stack; |
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h index 2430c561e021..3b1138ac7e79 100644 --- a/include/asm-s390/page.h +++ b/include/asm-s390/page.h | |||
| @@ -181,8 +181,6 @@ page_get_storage_key(unsigned long addr) | |||
| 181 | #define PAGE_OFFSET 0x0UL | 181 | #define PAGE_OFFSET 0x0UL |
| 182 | #define __pa(x) (unsigned long)(x) | 182 | #define __pa(x) (unsigned long)(x) |
| 183 | #define __va(x) (void *)(unsigned long)(x) | 183 | #define __va(x) (void *)(unsigned long)(x) |
| 184 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
| 185 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map)) | ||
| 186 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | 184 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) |
| 187 | 185 | ||
| 188 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | 186 | #define pfn_valid(pfn) ((pfn) < max_mapnr) |
| @@ -193,6 +191,7 @@ page_get_storage_key(unsigned long addr) | |||
| 193 | 191 | ||
| 194 | #endif /* __KERNEL__ */ | 192 | #endif /* __KERNEL__ */ |
| 195 | 193 | ||
| 194 | #include <asm-generic/memory_model.h> | ||
| 196 | #include <asm-generic/page.h> | 195 | #include <asm-generic/page.h> |
| 197 | 196 | ||
| 198 | #endif /* _S390_PAGE_H */ | 197 | #endif /* _S390_PAGE_H */ |
diff --git a/include/asm-sh/addrspace.h b/include/asm-sh/addrspace.h index dbb05d1a26d1..720afc11c2ca 100644 --- a/include/asm-sh/addrspace.h +++ b/include/asm-sh/addrspace.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | #include <asm/cpu/addrspace.h> | 14 | #include <asm/cpu/addrspace.h> |
| 15 | 15 | ||
| 16 | /* Memory segments (32bit Priviledged mode addresses) */ | 16 | /* Memory segments (32bit Privileged mode addresses) */ |
| 17 | #define P0SEG 0x00000000 | 17 | #define P0SEG 0x00000000 |
| 18 | #define P1SEG 0x80000000 | 18 | #define P1SEG 0x80000000 |
| 19 | #define P2SEG 0xa0000000 | 19 | #define P2SEG 0xa0000000 |
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h index 972c3f655b2a..9c89287c3e56 100644 --- a/include/asm-sh/page.h +++ b/include/asm-sh/page.h | |||
| @@ -105,9 +105,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 105 | 105 | ||
| 106 | /* PFN start number, because of __MEMORY_START */ | 106 | /* PFN start number, because of __MEMORY_START */ |
| 107 | #define PFN_START (__MEMORY_START >> PAGE_SHIFT) | 107 | #define PFN_START (__MEMORY_START >> PAGE_SHIFT) |
| 108 | 108 | #define ARCH_PFN_OFFSET (FPN_START) | |
| 109 | #define pfn_to_page(pfn) (mem_map + (pfn) - PFN_START) | ||
| 110 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PFN_START) | ||
| 111 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | 109 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) |
| 112 | #define pfn_valid(pfn) (((pfn) - PFN_START) < max_mapnr) | 110 | #define pfn_valid(pfn) (((pfn) - PFN_START) < max_mapnr) |
| 113 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) | 111 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) |
| @@ -117,6 +115,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 117 | 115 | ||
| 118 | #endif /* __KERNEL__ */ | 116 | #endif /* __KERNEL__ */ |
| 119 | 117 | ||
| 118 | #include <asm-generic/memory_model.h> | ||
| 120 | #include <asm-generic/page.h> | 119 | #include <asm-generic/page.h> |
| 121 | 120 | ||
| 122 | #endif /* __ASM_SH_PAGE_H */ | 121 | #endif /* __ASM_SH_PAGE_H */ |
diff --git a/include/asm-sh64/page.h b/include/asm-sh64/page.h index c86df90f7cbd..e4937cdabebd 100644 --- a/include/asm-sh64/page.h +++ b/include/asm-sh64/page.h | |||
| @@ -105,9 +105,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 105 | 105 | ||
| 106 | /* PFN start number, because of __MEMORY_START */ | 106 | /* PFN start number, because of __MEMORY_START */ |
| 107 | #define PFN_START (__MEMORY_START >> PAGE_SHIFT) | 107 | #define PFN_START (__MEMORY_START >> PAGE_SHIFT) |
| 108 | 108 | #define ARCH_PFN_OFFSET (PFN_START) | |
| 109 | #define pfn_to_page(pfn) (mem_map + (pfn) - PFN_START) | ||
| 110 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map) + PFN_START) | ||
| 111 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | 109 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) |
| 112 | #define pfn_valid(pfn) (((pfn) - PFN_START) < max_mapnr) | 110 | #define pfn_valid(pfn) (((pfn) - PFN_START) < max_mapnr) |
| 113 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) | 111 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) |
| @@ -117,6 +115,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 117 | 115 | ||
| 118 | #endif /* __KERNEL__ */ | 116 | #endif /* __KERNEL__ */ |
| 119 | 117 | ||
| 118 | #include <asm-generic/memory_model.h> | ||
| 120 | #include <asm-generic/page.h> | 119 | #include <asm-generic/page.h> |
| 121 | 120 | ||
| 122 | #endif /* __ASM_SH64_PAGE_H */ | 121 | #endif /* __ASM_SH64_PAGE_H */ |
diff --git a/include/asm-sh64/platform.h b/include/asm-sh64/platform.h index 7046a9014027..bd0d9c405a80 100644 --- a/include/asm-sh64/platform.h +++ b/include/asm-sh64/platform.h | |||
| @@ -61,9 +61,4 @@ extern int platform_int_priority[NR_INTC_IRQS]; | |||
| 61 | #define code_resource (platform_parms.kram_res_p[STANDARD_KRAM_RESOURCES - 2]) | 61 | #define code_resource (platform_parms.kram_res_p[STANDARD_KRAM_RESOURCES - 2]) |
| 62 | #define data_resource (platform_parms.kram_res_p[STANDARD_KRAM_RESOURCES - 1]) | 62 | #define data_resource (platform_parms.kram_res_p[STANDARD_KRAM_RESOURCES - 1]) |
| 63 | 63 | ||
| 64 | /* Be prepared to 64-bit sign extensions */ | ||
| 65 | #define PFN_UP(x) ((((x) + PAGE_SIZE-1) >> PAGE_SHIFT) & 0x000fffff) | ||
| 66 | #define PFN_DOWN(x) (((x) >> PAGE_SHIFT) & 0x000fffff) | ||
| 67 | #define PFN_PHYS(x) ((x) << PAGE_SHIFT) | ||
| 68 | |||
| 69 | #endif /* __ASM_SH64_PLATFORM_H */ | 64 | #endif /* __ASM_SH64_PLATFORM_H */ |
diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h index 9122684f6c1e..ec3274b7ddf4 100644 --- a/include/asm-sparc/page.h +++ b/include/asm-sparc/page.h | |||
| @@ -152,8 +152,7 @@ extern unsigned long pfn_base; | |||
| 152 | #define virt_to_phys __pa | 152 | #define virt_to_phys __pa |
| 153 | #define phys_to_virt __va | 153 | #define phys_to_virt __va |
| 154 | 154 | ||
| 155 | #define pfn_to_page(pfn) (mem_map + ((pfn)-(pfn_base))) | 155 | #define ARCH_PFN_OFFSET (pfn_base) |
| 156 | #define page_to_pfn(page) ((unsigned long)(((page) - mem_map) + pfn_base)) | ||
| 157 | #define virt_to_page(kaddr) (mem_map + ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT))) | 156 | #define virt_to_page(kaddr) (mem_map + ((((unsigned long)(kaddr)-PAGE_OFFSET)>>PAGE_SHIFT))) |
| 158 | 157 | ||
| 159 | #define pfn_valid(pfn) (((pfn) >= (pfn_base)) && (((pfn)-(pfn_base)) < max_mapnr)) | 158 | #define pfn_valid(pfn) (((pfn) >= (pfn_base)) && (((pfn)-(pfn_base)) < max_mapnr)) |
| @@ -164,6 +163,7 @@ extern unsigned long pfn_base; | |||
| 164 | 163 | ||
| 165 | #endif /* __KERNEL__ */ | 164 | #endif /* __KERNEL__ */ |
| 166 | 165 | ||
| 166 | #include <asm-generic/memory_model.h> | ||
| 167 | #include <asm-generic/page.h> | 167 | #include <asm-generic/page.h> |
| 168 | 168 | ||
| 169 | #endif /* _SPARC_PAGE_H */ | 169 | #endif /* _SPARC_PAGE_H */ |
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h index 49d49a285943..6a95d5d0c576 100644 --- a/include/asm-sparc64/floppy.h +++ b/include/asm-sparc64/floppy.h | |||
| @@ -738,7 +738,7 @@ static unsigned long __init sun_floppy_init(void) | |||
| 738 | if (!sun_floppy_types[0] && sun_floppy_types[1]) { | 738 | if (!sun_floppy_types[0] && sun_floppy_types[1]) { |
| 739 | /* | 739 | /* |
| 740 | * Set the drive exchange bit in FCR on NS87303, | 740 | * Set the drive exchange bit in FCR on NS87303, |
| 741 | * make shure other bits are sane before doing so. | 741 | * make sure other bits are sane before doing so. |
| 742 | */ | 742 | */ |
| 743 | ns87303_modify(config, FER, FER_EDM, 0); | 743 | ns87303_modify(config, FER, FER_EDM, 0); |
| 744 | ns87303_modify(config, ASC, ASC_DRV2_SEL, 0); | 744 | ns87303_modify(config, ASC, ASC_DRV2_SEL, 0); |
diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h index 34c4b43d3f98..dee40206b221 100644 --- a/include/asm-sparc64/futex.h +++ b/include/asm-sparc64/futex.h | |||
| @@ -83,4 +83,28 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) | |||
| 83 | return ret; | 83 | return ret; |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | static inline int | ||
| 87 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | ||
| 88 | { | ||
| 89 | __asm__ __volatile__( | ||
| 90 | "\n1: lduwa [%2] %%asi, %0\n" | ||
| 91 | "2: casa [%2] %%asi, %0, %1\n" | ||
| 92 | "3:\n" | ||
| 93 | " .section .fixup,#alloc,#execinstr\n" | ||
| 94 | " .align 4\n" | ||
| 95 | "4: ba 3b\n" | ||
| 96 | " mov %3, %0\n" | ||
| 97 | " .previous\n" | ||
| 98 | " .section __ex_table,\"a\"\n" | ||
| 99 | " .align 4\n" | ||
| 100 | " .word 1b, 4b\n" | ||
| 101 | " .word 2b, 4b\n" | ||
| 102 | " .previous\n" | ||
| 103 | : "=&r" (oldval) | ||
| 104 | : "r" (newval), "r" (uaddr), "i" (-EFAULT) | ||
| 105 | : "memory"); | ||
| 106 | |||
| 107 | return oldval; | ||
| 108 | } | ||
| 109 | |||
| 86 | #endif /* !(_SPARC64_FUTEX_H) */ | 110 | #endif /* !(_SPARC64_FUTEX_H) */ |
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h index 6321f5a0198d..4040d127ac3e 100644 --- a/include/asm-sparc64/kdebug.h +++ b/include/asm-sparc64/kdebug.h | |||
| @@ -15,12 +15,9 @@ struct die_args { | |||
| 15 | int signr; | 15 | int signr; |
| 16 | }; | 16 | }; |
| 17 | 17 | ||
| 18 | /* Note - you should never unregister because that can race with NMIs. | 18 | extern int register_die_notifier(struct notifier_block *); |
| 19 | * If you really want to do it first unregister - then synchronize_sched | 19 | extern int unregister_die_notifier(struct notifier_block *); |
| 20 | * - then free. | 20 | extern struct atomic_notifier_head sparc64die_chain; |
| 21 | */ | ||
| 22 | int register_die_notifier(struct notifier_block *nb); | ||
| 23 | extern struct notifier_block *sparc64die_chain; | ||
| 24 | 21 | ||
| 25 | extern void bad_trap(struct pt_regs *, long); | 22 | extern void bad_trap(struct pt_regs *, long); |
| 26 | 23 | ||
| @@ -46,7 +43,7 @@ static inline int notify_die(enum die_val val,char *str, struct pt_regs *regs, | |||
| 46 | .trapnr = trap, | 43 | .trapnr = trap, |
| 47 | .signr = sig }; | 44 | .signr = sig }; |
| 48 | 45 | ||
| 49 | return notifier_call_chain(&sparc64die_chain, val, &args); | 46 | return atomic_notifier_call_chain(&sparc64die_chain, val, &args); |
| 50 | } | 47 | } |
| 51 | 48 | ||
| 52 | #endif | 49 | #endif |
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h index 66fe4ac59fd6..aabb21906724 100644 --- a/include/asm-sparc64/page.h +++ b/include/asm-sparc64/page.h | |||
| @@ -111,6 +111,8 @@ typedef unsigned long pgprot_t; | |||
| 111 | (_AC(0x0000000070000000,UL)) : \ | 111 | (_AC(0x0000000070000000,UL)) : \ |
| 112 | (_AC(0xfffff80000000000,UL) + (1UL << 32UL))) | 112 | (_AC(0xfffff80000000000,UL) + (1UL << 32UL))) |
| 113 | 113 | ||
| 114 | #include <asm-generic/memory_model.h> | ||
| 115 | |||
| 114 | #endif /* !(__ASSEMBLY__) */ | 116 | #endif /* !(__ASSEMBLY__) */ |
| 115 | 117 | ||
| 116 | /* to align the pointer to the (next) page boundary */ | 118 | /* to align the pointer to the (next) page boundary */ |
diff --git a/include/asm-um/page.h b/include/asm-um/page.h index 0229814af31e..41364330aff1 100644 --- a/include/asm-um/page.h +++ b/include/asm-um/page.h | |||
| @@ -106,9 +106,6 @@ extern unsigned long uml_physmem; | |||
| 106 | #define __pa(virt) to_phys((void *) (unsigned long) (virt)) | 106 | #define __pa(virt) to_phys((void *) (unsigned long) (virt)) |
| 107 | #define __va(phys) to_virt((unsigned long) (phys)) | 107 | #define __va(phys) to_virt((unsigned long) (phys)) |
| 108 | 108 | ||
| 109 | #define page_to_pfn(page) ((page) - mem_map) | ||
| 110 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
| 111 | |||
| 112 | #define phys_to_pfn(p) ((p) >> PAGE_SHIFT) | 109 | #define phys_to_pfn(p) ((p) >> PAGE_SHIFT) |
| 113 | #define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) | 110 | #define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) |
| 114 | 111 | ||
| @@ -121,6 +118,7 @@ extern struct page *arch_validate(struct page *page, gfp_t mask, int order); | |||
| 121 | extern void arch_free_page(struct page *page, int order); | 118 | extern void arch_free_page(struct page *page, int order); |
| 122 | #define HAVE_ARCH_FREE_PAGE | 119 | #define HAVE_ARCH_FREE_PAGE |
| 123 | 120 | ||
| 121 | #include <asm-generic/memory_model.h> | ||
| 124 | #include <asm-generic/page.h> | 122 | #include <asm-generic/page.h> |
| 125 | 123 | ||
| 126 | #endif | 124 | #endif |
diff --git a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h index 2ee028b8de9d..4e460d6f5ac8 100644 --- a/include/asm-um/uaccess.h +++ b/include/asm-um/uaccess.h | |||
| @@ -41,16 +41,16 @@ | |||
| 41 | 41 | ||
| 42 | #define __get_user(x, ptr) \ | 42 | #define __get_user(x, ptr) \ |
| 43 | ({ \ | 43 | ({ \ |
| 44 | const __typeof__(ptr) __private_ptr = ptr; \ | 44 | const __typeof__(ptr) __private_ptr = ptr; \ |
| 45 | __typeof__(*(__private_ptr)) __private_val; \ | 45 | __typeof__(x) __private_val; \ |
| 46 | int __private_ret = -EFAULT; \ | 46 | int __private_ret = -EFAULT; \ |
| 47 | (x) = (__typeof__(*(__private_ptr)))0; \ | 47 | (x) = (__typeof__(*(__private_ptr)))0; \ |
| 48 | if (__copy_from_user(&__private_val, (__private_ptr), \ | 48 | if (__copy_from_user((void *) &__private_val, (__private_ptr), \ |
| 49 | sizeof(*(__private_ptr))) == 0) {\ | 49 | sizeof(*(__private_ptr))) == 0) { \ |
| 50 | (x) = (__typeof__(*(__private_ptr))) __private_val; \ | 50 | (x) = (__typeof__(*(__private_ptr))) __private_val; \ |
| 51 | __private_ret = 0; \ | 51 | __private_ret = 0; \ |
| 52 | } \ | 52 | } \ |
| 53 | __private_ret; \ | 53 | __private_ret; \ |
| 54 | }) | 54 | }) |
| 55 | 55 | ||
| 56 | #define get_user(x, ptr) \ | 56 | #define get_user(x, ptr) \ |
| @@ -89,14 +89,3 @@ struct exception_table_entry | |||
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | #endif | 91 | #endif |
| 92 | |||
| 93 | /* | ||
| 94 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
| 95 | * Emacs will notice this stuff at the end of the file and automatically | ||
| 96 | * adjust the settings for this buffer only. This must remain at the end | ||
| 97 | * of the file. | ||
| 98 | * --------------------------------------------------------------------------- | ||
| 99 | * Local variables: | ||
| 100 | * c-file-style: "linux" | ||
| 101 | * End: | ||
| 102 | */ | ||
diff --git a/include/asm-v850/page.h b/include/asm-v850/page.h index b4bc85e7b91a..ad03c46a1f92 100644 --- a/include/asm-v850/page.h +++ b/include/asm-v850/page.h | |||
| @@ -111,8 +111,7 @@ typedef unsigned long pgprot_t; | |||
| 111 | #define page_to_virt(page) \ | 111 | #define page_to_virt(page) \ |
| 112 | ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) | 112 | ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) |
| 113 | 113 | ||
| 114 | #define pfn_to_page(pfn) virt_to_page (pfn_to_virt (pfn)) | 114 | #define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) |
| 115 | #define page_to_pfn(page) virt_to_pfn (page_to_virt (page)) | ||
| 116 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | 115 | #define pfn_valid(pfn) ((pfn) < max_mapnr) |
| 117 | 116 | ||
| 118 | #define virt_addr_valid(kaddr) \ | 117 | #define virt_addr_valid(kaddr) \ |
| @@ -125,6 +124,7 @@ typedef unsigned long pgprot_t; | |||
| 125 | 124 | ||
| 126 | #endif /* KERNEL */ | 125 | #endif /* KERNEL */ |
| 127 | 126 | ||
| 127 | #include <asm-generic/memory_model.h> | ||
| 128 | #include <asm-generic/page.h> | 128 | #include <asm-generic/page.h> |
| 129 | 129 | ||
| 130 | #endif /* __V850_PAGE_H__ */ | 130 | #endif /* __V850_PAGE_H__ */ |
diff --git a/include/asm-x86_64/futex.h b/include/asm-x86_64/futex.h index 8602c09bf89e..9804bf07b092 100644 --- a/include/asm-x86_64/futex.h +++ b/include/asm-x86_64/futex.h | |||
| @@ -94,5 +94,32 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
| 94 | return ret; | 94 | return ret; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | static inline int | ||
| 98 | futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) | ||
| 99 | { | ||
| 100 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) | ||
| 101 | return -EFAULT; | ||
| 102 | |||
| 103 | __asm__ __volatile__( | ||
| 104 | "1: " LOCK_PREFIX "cmpxchgl %3, %1 \n" | ||
| 105 | |||
| 106 | "2: .section .fixup, \"ax\" \n" | ||
| 107 | "3: mov %2, %0 \n" | ||
| 108 | " jmp 2b \n" | ||
| 109 | " .previous \n" | ||
| 110 | |||
| 111 | " .section __ex_table, \"a\" \n" | ||
| 112 | " .align 8 \n" | ||
| 113 | " .quad 1b,3b \n" | ||
| 114 | " .previous \n" | ||
| 115 | |||
| 116 | : "=a" (oldval), "=m" (*uaddr) | ||
| 117 | : "i" (-EFAULT), "r" (newval), "0" (oldval) | ||
| 118 | : "memory" | ||
| 119 | ); | ||
| 120 | |||
| 121 | return oldval; | ||
| 122 | } | ||
| 123 | |||
| 97 | #endif | 124 | #endif |
| 98 | #endif | 125 | #endif |
diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h index b9ed4c0c8783..cf795631d9b4 100644 --- a/include/asm-x86_64/kdebug.h +++ b/include/asm-x86_64/kdebug.h | |||
| @@ -5,21 +5,20 @@ | |||
| 5 | 5 | ||
| 6 | struct pt_regs; | 6 | struct pt_regs; |
| 7 | 7 | ||
| 8 | struct die_args { | 8 | struct die_args { |
| 9 | struct pt_regs *regs; | 9 | struct pt_regs *regs; |
| 10 | const char *str; | 10 | const char *str; |
| 11 | long err; | 11 | long err; |
| 12 | int trapnr; | 12 | int trapnr; |
| 13 | int signr; | 13 | int signr; |
| 14 | }; | 14 | }; |
| 15 | |||
| 16 | extern int register_die_notifier(struct notifier_block *); | ||
| 17 | extern int unregister_die_notifier(struct notifier_block *); | ||
| 18 | extern struct atomic_notifier_head die_chain; | ||
| 15 | 19 | ||
| 16 | /* Note - you should never unregister because that can race with NMIs. | ||
| 17 | If you really want to do it first unregister - then synchronize_sched - then free. | ||
| 18 | */ | ||
| 19 | int register_die_notifier(struct notifier_block *nb); | ||
| 20 | extern struct notifier_block *die_chain; | ||
| 21 | /* Grossly misnamed. */ | 20 | /* Grossly misnamed. */ |
| 22 | enum die_val { | 21 | enum die_val { |
| 23 | DIE_OOPS = 1, | 22 | DIE_OOPS = 1, |
| 24 | DIE_INT3, | 23 | DIE_INT3, |
| 25 | DIE_DEBUG, | 24 | DIE_DEBUG, |
| @@ -33,8 +32,8 @@ enum die_val { | |||
| 33 | DIE_CALL, | 32 | DIE_CALL, |
| 34 | DIE_NMI_IPI, | 33 | DIE_NMI_IPI, |
| 35 | DIE_PAGE_FAULT, | 34 | DIE_PAGE_FAULT, |
| 36 | }; | 35 | }; |
| 37 | 36 | ||
| 38 | static inline int notify_die(enum die_val val, const char *str, | 37 | static inline int notify_die(enum die_val val, const char *str, |
| 39 | struct pt_regs *regs, long err, int trap, int sig) | 38 | struct pt_regs *regs, long err, int trap, int sig) |
| 40 | { | 39 | { |
| @@ -45,7 +44,7 @@ static inline int notify_die(enum die_val val, const char *str, | |||
| 45 | .trapnr = trap, | 44 | .trapnr = trap, |
| 46 | .signr = sig | 45 | .signr = sig |
| 47 | }; | 46 | }; |
| 48 | return notifier_call_chain(&die_chain, val, &args); | 47 | return atomic_notifier_call_chain(&die_chain, val, &args); |
| 49 | } | 48 | } |
| 50 | 49 | ||
| 51 | extern int printk_address(unsigned long address); | 50 | extern int printk_address(unsigned long address); |
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h index 937f99b26883..6b18cd8f293d 100644 --- a/include/asm-x86_64/mmzone.h +++ b/include/asm-x86_64/mmzone.h | |||
| @@ -44,12 +44,8 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr) | |||
| 44 | #define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT) | 44 | #define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT) |
| 45 | #define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr)) | 45 | #define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr)) |
| 46 | 46 | ||
| 47 | extern struct page *pfn_to_page(unsigned long pfn); | ||
| 48 | extern unsigned long page_to_pfn(struct page *page); | ||
| 49 | extern int pfn_valid(unsigned long pfn); | 47 | extern int pfn_valid(unsigned long pfn); |
| 50 | #endif | 48 | #endif |
| 51 | 49 | ||
| 52 | #define local_mapnr(kvaddr) \ | ||
| 53 | ( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) ) | ||
| 54 | #endif | 50 | #endif |
| 55 | #endif | 51 | #endif |
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h index 615e3e494929..408185bac351 100644 --- a/include/asm-x86_64/page.h +++ b/include/asm-x86_64/page.h | |||
| @@ -123,8 +123,6 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 123 | #define __boot_va(x) __va(x) | 123 | #define __boot_va(x) __va(x) |
| 124 | #define __boot_pa(x) __pa(x) | 124 | #define __boot_pa(x) __pa(x) |
| 125 | #ifdef CONFIG_FLATMEM | 125 | #ifdef CONFIG_FLATMEM |
| 126 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
| 127 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map)) | ||
| 128 | #define pfn_valid(pfn) ((pfn) < end_pfn) | 126 | #define pfn_valid(pfn) ((pfn) < end_pfn) |
| 129 | #endif | 127 | #endif |
| 130 | 128 | ||
| @@ -140,6 +138,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; | |||
| 140 | 138 | ||
| 141 | #endif /* __KERNEL__ */ | 139 | #endif /* __KERNEL__ */ |
| 142 | 140 | ||
| 141 | #include <asm-generic/memory_model.h> | ||
| 143 | #include <asm-generic/page.h> | 142 | #include <asm-generic/page.h> |
| 144 | 143 | ||
| 145 | #endif /* _X86_64_PAGE_H */ | 144 | #endif /* _X86_64_PAGE_H */ |
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index 8c8d88c036ed..37a3ec433ee5 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <asm/mmsegment.h> | 20 | #include <asm/mmsegment.h> |
| 21 | #include <asm/percpu.h> | 21 | #include <asm/percpu.h> |
| 22 | #include <linux/personality.h> | 22 | #include <linux/personality.h> |
| 23 | #include <linux/cpumask.h> | ||
| 23 | 24 | ||
| 24 | #define TF_MASK 0x00000100 | 25 | #define TF_MASK 0x00000100 |
| 25 | #define IF_MASK 0x00000200 | 26 | #define IF_MASK 0x00000200 |
| @@ -65,6 +66,9 @@ struct cpuinfo_x86 { | |||
| 65 | __u32 x86_power; | 66 | __u32 x86_power; |
| 66 | __u32 extended_cpuid_level; /* Max extended CPUID function supported */ | 67 | __u32 extended_cpuid_level; /* Max extended CPUID function supported */ |
| 67 | unsigned long loops_per_jiffy; | 68 | unsigned long loops_per_jiffy; |
| 69 | #ifdef CONFIG_SMP | ||
| 70 | cpumask_t llc_shared_map; /* cpus sharing the last level cache */ | ||
| 71 | #endif | ||
| 68 | __u8 apicid; | 72 | __u8 apicid; |
| 69 | __u8 booted_cores; /* number of cores as seen by OS */ | 73 | __u8 booted_cores; /* number of cores as seen by OS */ |
| 70 | } ____cacheline_aligned; | 74 | } ____cacheline_aligned; |
| @@ -354,9 +358,6 @@ struct extended_sigtable { | |||
| 354 | struct extended_signature sigs[0]; | 358 | struct extended_signature sigs[0]; |
| 355 | }; | 359 | }; |
| 356 | 360 | ||
| 357 | /* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */ | ||
| 358 | #define MICROCODE_IOCFREE _IO('6',0) | ||
| 359 | |||
| 360 | 361 | ||
| 361 | #define ASM_NOP1 K8_NOP1 | 362 | #define ASM_NOP1 K8_NOP1 |
| 362 | #define ASM_NOP2 K8_NOP2 | 363 | #define ASM_NOP2 K8_NOP2 |
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h index 9ccbb2cfd5c0..a4fdaeb5c397 100644 --- a/include/asm-x86_64/smp.h +++ b/include/asm-x86_64/smp.h | |||
| @@ -56,6 +56,7 @@ extern cpumask_t cpu_sibling_map[NR_CPUS]; | |||
| 56 | extern cpumask_t cpu_core_map[NR_CPUS]; | 56 | extern cpumask_t cpu_core_map[NR_CPUS]; |
| 57 | extern u8 phys_proc_id[NR_CPUS]; | 57 | extern u8 phys_proc_id[NR_CPUS]; |
| 58 | extern u8 cpu_core_id[NR_CPUS]; | 58 | extern u8 cpu_core_id[NR_CPUS]; |
| 59 | extern u8 cpu_llc_id[NR_CPUS]; | ||
| 59 | 60 | ||
| 60 | #define SMP_TRAMPOLINE_BASE 0x6000 | 61 | #define SMP_TRAMPOLINE_BASE 0x6000 |
| 61 | 62 | ||
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h index c642f5d9882d..9db54e9d17bb 100644 --- a/include/asm-x86_64/topology.h +++ b/include/asm-x86_64/topology.h | |||
| @@ -68,4 +68,6 @@ extern int __node_distance(int, int); | |||
| 68 | 68 | ||
| 69 | #include <asm-generic/topology.h> | 69 | #include <asm-generic/topology.h> |
| 70 | 70 | ||
| 71 | extern cpumask_t cpu_coregroup_map(int cpu); | ||
| 72 | |||
| 71 | #endif | 73 | #endif |
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h index da0341c57949..fcc516353087 100644 --- a/include/asm-x86_64/unistd.h +++ b/include/asm-x86_64/unistd.h | |||
| @@ -605,8 +605,12 @@ __SYSCALL(__NR_pselect6, sys_ni_syscall) /* for now */ | |||
| 605 | __SYSCALL(__NR_ppoll, sys_ni_syscall) /* for now */ | 605 | __SYSCALL(__NR_ppoll, sys_ni_syscall) /* for now */ |
| 606 | #define __NR_unshare 272 | 606 | #define __NR_unshare 272 |
| 607 | __SYSCALL(__NR_unshare, sys_unshare) | 607 | __SYSCALL(__NR_unshare, sys_unshare) |
| 608 | #define __NR_set_robust_list 273 | ||
| 609 | __SYSCALL(__NR_set_robust_list, sys_set_robust_list) | ||
| 610 | #define __NR_get_robust_list 274 | ||
| 611 | __SYSCALL(__NR_get_robust_list, sys_get_robust_list) | ||
| 608 | 612 | ||
| 609 | #define __NR_syscall_max __NR_unshare | 613 | #define __NR_syscall_max __NR_get_robust_list |
| 610 | 614 | ||
| 611 | #ifndef __NO_STUBS | 615 | #ifndef __NO_STUBS |
| 612 | 616 | ||
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h index 8ded36f255a2..992bac5c1258 100644 --- a/include/asm-xtensa/page.h +++ b/include/asm-xtensa/page.h | |||
| @@ -109,10 +109,7 @@ void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page); | |||
| 109 | #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) | 109 | #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) |
| 110 | #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) | 110 | #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) |
| 111 | #define pfn_valid(pfn) ((unsigned long)pfn < max_mapnr) | 111 | #define pfn_valid(pfn) ((unsigned long)pfn < max_mapnr) |
| 112 | #ifndef CONFIG_DISCONTIGMEM | 112 | #ifdef CONFIG_DISCONTIGMEM |
| 113 | # define pfn_to_page(pfn) (mem_map + (pfn)) | ||
| 114 | # define page_to_pfn(page) ((unsigned long)((page) - mem_map)) | ||
| 115 | #else | ||
| 116 | # error CONFIG_DISCONTIGMEM not supported | 113 | # error CONFIG_DISCONTIGMEM not supported |
| 117 | #endif | 114 | #endif |
| 118 | 115 | ||
| @@ -130,4 +127,5 @@ void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page); | |||
| 130 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | 127 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
| 131 | 128 | ||
| 132 | #endif /* __KERNEL__ */ | 129 | #endif /* __KERNEL__ */ |
| 130 | #include <asm-generic/memory_model.h> | ||
| 133 | #endif /* _XTENSA_PAGE_H */ | 131 | #endif /* _XTENSA_PAGE_H */ |
diff --git a/include/linux/adb.h b/include/linux/adb.h index e9fdc63483c7..b7305b178279 100644 --- a/include/linux/adb.h +++ b/include/linux/adb.h | |||
| @@ -85,7 +85,7 @@ enum adb_message { | |||
| 85 | ADB_MSG_POST_RESET /* Called after resetting the bus (re-do init & register) */ | 85 | ADB_MSG_POST_RESET /* Called after resetting the bus (re-do init & register) */ |
| 86 | }; | 86 | }; |
| 87 | extern struct adb_driver *adb_controller; | 87 | extern struct adb_driver *adb_controller; |
| 88 | extern struct notifier_block *adb_client_list; | 88 | extern struct blocking_notifier_head adb_client_list; |
| 89 | 89 | ||
| 90 | int adb_request(struct adb_request *req, void (*done)(struct adb_request *), | 90 | int adb_request(struct adb_request *req, void (*done)(struct adb_request *), |
| 91 | int flags, int nbytes, ...); | 91 | int flags, int nbytes, ...); |
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h index dc726ffccebd..48ee32a18ac5 100644 --- a/include/linux/amba/serial.h +++ b/include/linux/amba/serial.h | |||
| @@ -158,4 +158,10 @@ | |||
| 158 | #define UART01x_RSR_ANY (UART01x_RSR_OE|UART01x_RSR_BE|UART01x_RSR_PE|UART01x_RSR_FE) | 158 | #define UART01x_RSR_ANY (UART01x_RSR_OE|UART01x_RSR_BE|UART01x_RSR_PE|UART01x_RSR_FE) |
| 159 | #define UART01x_FR_MODEM_ANY (UART01x_FR_DCD|UART01x_FR_DSR|UART01x_FR_CTS) | 159 | #define UART01x_FR_MODEM_ANY (UART01x_FR_DCD|UART01x_FR_DSR|UART01x_FR_CTS) |
| 160 | 160 | ||
| 161 | #ifndef __ASSEMBLY__ | ||
| 162 | struct amba_pl010_data { | ||
| 163 | void (*set_mctrl)(struct amba_device *dev, void __iomem *base, unsigned int mctrl); | ||
| 164 | }; | ||
| 165 | #endif | ||
| 166 | |||
| 161 | #endif | 167 | #endif |
diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h index 9343c89d843c..0a6bc52ffe88 100644 --- a/include/linux/auto_fs4.h +++ b/include/linux/auto_fs4.h | |||
| @@ -19,18 +19,37 @@ | |||
| 19 | #undef AUTOFS_MIN_PROTO_VERSION | 19 | #undef AUTOFS_MIN_PROTO_VERSION |
| 20 | #undef AUTOFS_MAX_PROTO_VERSION | 20 | #undef AUTOFS_MAX_PROTO_VERSION |
| 21 | 21 | ||
| 22 | #define AUTOFS_PROTO_VERSION 4 | 22 | #define AUTOFS_PROTO_VERSION 5 |
| 23 | #define AUTOFS_MIN_PROTO_VERSION 3 | 23 | #define AUTOFS_MIN_PROTO_VERSION 3 |
| 24 | #define AUTOFS_MAX_PROTO_VERSION 4 | 24 | #define AUTOFS_MAX_PROTO_VERSION 5 |
| 25 | 25 | ||
| 26 | #define AUTOFS_PROTO_SUBVERSION 7 | 26 | #define AUTOFS_PROTO_SUBVERSION 0 |
| 27 | 27 | ||
| 28 | /* Mask for expire behaviour */ | 28 | /* Mask for expire behaviour */ |
| 29 | #define AUTOFS_EXP_IMMEDIATE 1 | 29 | #define AUTOFS_EXP_IMMEDIATE 1 |
| 30 | #define AUTOFS_EXP_LEAVES 2 | 30 | #define AUTOFS_EXP_LEAVES 2 |
| 31 | 31 | ||
| 32 | /* New message type */ | 32 | /* Daemon notification packet types */ |
| 33 | #define autofs_ptype_expire_multi 2 /* Expire entry (umount request) */ | 33 | enum autofs_notify { |
| 34 | NFY_NONE, | ||
| 35 | NFY_MOUNT, | ||
| 36 | NFY_EXPIRE | ||
| 37 | }; | ||
| 38 | |||
| 39 | /* Kernel protocol version 4 packet types */ | ||
| 40 | |||
| 41 | /* Expire entry (umount request) */ | ||
| 42 | #define autofs_ptype_expire_multi 2 | ||
| 43 | |||
| 44 | /* Kernel protocol version 5 packet types */ | ||
| 45 | |||
| 46 | /* Indirect mount missing and expire requests. */ | ||
| 47 | #define autofs_ptype_missing_indirect 3 | ||
| 48 | #define autofs_ptype_expire_indirect 4 | ||
| 49 | |||
| 50 | /* Direct mount missing and expire requests */ | ||
| 51 | #define autofs_ptype_missing_direct 5 | ||
| 52 | #define autofs_ptype_expire_direct 6 | ||
| 34 | 53 | ||
| 35 | /* v4 multi expire (via pipe) */ | 54 | /* v4 multi expire (via pipe) */ |
| 36 | struct autofs_packet_expire_multi { | 55 | struct autofs_packet_expire_multi { |
| @@ -40,14 +59,36 @@ struct autofs_packet_expire_multi { | |||
| 40 | char name[NAME_MAX+1]; | 59 | char name[NAME_MAX+1]; |
| 41 | }; | 60 | }; |
| 42 | 61 | ||
| 62 | /* autofs v5 common packet struct */ | ||
| 63 | struct autofs_v5_packet { | ||
| 64 | struct autofs_packet_hdr hdr; | ||
| 65 | autofs_wqt_t wait_queue_token; | ||
| 66 | __u32 dev; | ||
| 67 | __u64 ino; | ||
| 68 | __u32 uid; | ||
| 69 | __u32 gid; | ||
| 70 | __u32 pid; | ||
| 71 | __u32 tgid; | ||
| 72 | __u32 len; | ||
| 73 | char name[NAME_MAX+1]; | ||
| 74 | }; | ||
| 75 | |||
| 76 | typedef struct autofs_v5_packet autofs_packet_missing_indirect_t; | ||
| 77 | typedef struct autofs_v5_packet autofs_packet_expire_indirect_t; | ||
| 78 | typedef struct autofs_v5_packet autofs_packet_missing_direct_t; | ||
| 79 | typedef struct autofs_v5_packet autofs_packet_expire_direct_t; | ||
| 80 | |||
| 43 | union autofs_packet_union { | 81 | union autofs_packet_union { |
| 44 | struct autofs_packet_hdr hdr; | 82 | struct autofs_packet_hdr hdr; |
| 45 | struct autofs_packet_missing missing; | 83 | struct autofs_packet_missing missing; |
| 46 | struct autofs_packet_expire expire; | 84 | struct autofs_packet_expire expire; |
| 47 | struct autofs_packet_expire_multi expire_multi; | 85 | struct autofs_packet_expire_multi expire_multi; |
| 86 | struct autofs_v5_packet v5_packet; | ||
| 48 | }; | 87 | }; |
| 49 | 88 | ||
| 50 | #define AUTOFS_IOC_EXPIRE_MULTI _IOW(0x93,0x66,int) | 89 | #define AUTOFS_IOC_EXPIRE_MULTI _IOW(0x93,0x66,int) |
| 90 | #define AUTOFS_IOC_EXPIRE_INDIRECT AUTOFS_IOC_EXPIRE_MULTI | ||
| 91 | #define AUTOFS_IOC_EXPIRE_DIRECT AUTOFS_IOC_EXPIRE_MULTI | ||
| 51 | #define AUTOFS_IOC_PROTOSUBVER _IOR(0x93,0x67,int) | 92 | #define AUTOFS_IOC_PROTOSUBVER _IOR(0x93,0x67,int) |
| 52 | #define AUTOFS_IOC_ASKREGHOST _IOR(0x93,0x68,int) | 93 | #define AUTOFS_IOC_ASKREGHOST _IOR(0x93,0x68,int) |
| 53 | #define AUTOFS_IOC_TOGGLEREGHOST _IOR(0x93,0x69,int) | 94 | #define AUTOFS_IOC_TOGGLEREGHOST _IOR(0x93,0x69,int) |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index c179966f1a2f..d0cac8b58de7 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
| @@ -55,25 +55,29 @@ struct as_io_context { | |||
| 55 | 55 | ||
| 56 | struct cfq_queue; | 56 | struct cfq_queue; |
| 57 | struct cfq_io_context { | 57 | struct cfq_io_context { |
| 58 | /* | 58 | struct rb_node rb_node; |
| 59 | * circular list of cfq_io_contexts belonging to a process io context | ||
| 60 | */ | ||
| 61 | struct list_head list; | ||
| 62 | struct cfq_queue *cfqq[2]; | ||
| 63 | void *key; | 59 | void *key; |
| 64 | 60 | ||
| 61 | struct cfq_queue *cfqq[2]; | ||
| 62 | |||
| 65 | struct io_context *ioc; | 63 | struct io_context *ioc; |
| 66 | 64 | ||
| 67 | unsigned long last_end_request; | 65 | unsigned long last_end_request; |
| 68 | unsigned long last_queue; | 66 | sector_t last_request_pos; |
| 67 | unsigned long last_queue; | ||
| 68 | |||
| 69 | unsigned long ttime_total; | 69 | unsigned long ttime_total; |
| 70 | unsigned long ttime_samples; | 70 | unsigned long ttime_samples; |
| 71 | unsigned long ttime_mean; | 71 | unsigned long ttime_mean; |
| 72 | 72 | ||
| 73 | unsigned int seek_samples; | ||
| 74 | u64 seek_total; | ||
| 75 | sector_t seek_mean; | ||
| 76 | |||
| 73 | struct list_head queue_list; | 77 | struct list_head queue_list; |
| 74 | 78 | ||
| 75 | void (*dtor)(struct cfq_io_context *); | 79 | void (*dtor)(struct io_context *); /* destructor */ |
| 76 | void (*exit)(struct cfq_io_context *); | 80 | void (*exit)(struct io_context *); /* called on task exit */ |
| 77 | }; | 81 | }; |
| 78 | 82 | ||
| 79 | /* | 83 | /* |
| @@ -94,7 +98,7 @@ struct io_context { | |||
| 94 | int nr_batch_requests; /* Number of requests left in the batch */ | 98 | int nr_batch_requests; /* Number of requests left in the batch */ |
| 95 | 99 | ||
| 96 | struct as_io_context *aic; | 100 | struct as_io_context *aic; |
| 97 | struct cfq_io_context *cic; | 101 | struct rb_root cic_root; |
| 98 | }; | 102 | }; |
| 99 | 103 | ||
| 100 | void put_io_context(struct io_context *ioc); | 104 | void put_io_context(struct io_context *ioc); |
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index 7155452fb4a8..de3eb8d8ae26 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h | |||
| @@ -38,6 +38,7 @@ typedef struct bootmem_data { | |||
| 38 | unsigned long last_pos; | 38 | unsigned long last_pos; |
| 39 | unsigned long last_success; /* Previous allocation point. To speed | 39 | unsigned long last_success; /* Previous allocation point. To speed |
| 40 | * up searching */ | 40 | * up searching */ |
| 41 | struct list_head list; | ||
| 41 | } bootmem_data_t; | 42 | } bootmem_data_t; |
| 42 | 43 | ||
| 43 | extern unsigned long __init bootmem_bootmap_pages (unsigned long); | 44 | extern unsigned long __init bootmem_bootmap_pages (unsigned long); |
diff --git a/include/linux/cdev.h b/include/linux/cdev.h index 8da37e29cb87..2216638962d2 100644 --- a/include/linux/cdev.h +++ b/include/linux/cdev.h | |||
| @@ -5,13 +5,13 @@ | |||
| 5 | struct cdev { | 5 | struct cdev { |
| 6 | struct kobject kobj; | 6 | struct kobject kobj; |
| 7 | struct module *owner; | 7 | struct module *owner; |
| 8 | struct file_operations *ops; | 8 | const struct file_operations *ops; |
| 9 | struct list_head list; | 9 | struct list_head list; |
| 10 | dev_t dev; | 10 | dev_t dev; |
| 11 | unsigned int count; | 11 | unsigned int count; |
| 12 | }; | 12 | }; |
| 13 | 13 | ||
| 14 | void cdev_init(struct cdev *, struct file_operations *); | 14 | void cdev_init(struct cdev *, const struct file_operations *); |
| 15 | 15 | ||
| 16 | struct cdev *cdev_alloc(void); | 16 | struct cdev *cdev_alloc(void); |
| 17 | 17 | ||
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h index cc621ec409d8..b3ecf8f71d97 100644 --- a/include/linux/coda_linux.h +++ b/include/linux/coda_linux.h | |||
| @@ -30,9 +30,9 @@ extern struct inode_operations coda_ioctl_inode_operations; | |||
| 30 | extern struct address_space_operations coda_file_aops; | 30 | extern struct address_space_operations coda_file_aops; |
| 31 | extern struct address_space_operations coda_symlink_aops; | 31 | extern struct address_space_operations coda_symlink_aops; |
| 32 | 32 | ||
| 33 | extern struct file_operations coda_dir_operations; | 33 | extern const struct file_operations coda_dir_operations; |
| 34 | extern struct file_operations coda_file_operations; | 34 | extern const struct file_operations coda_file_operations; |
| 35 | extern struct file_operations coda_ioctl_operations; | 35 | extern const struct file_operations coda_ioctl_operations; |
| 36 | 36 | ||
| 37 | /* operations shared over more than one file */ | 37 | /* operations shared over more than one file */ |
| 38 | int coda_open(struct inode *i, struct file *f); | 38 | int coda_open(struct inode *i, struct file *f); |
diff --git a/include/linux/compat.h b/include/linux/compat.h index 24d659cdbafe..6d3a654be1ae 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
| @@ -147,6 +147,24 @@ typedef struct compat_sigevent { | |||
| 147 | } _sigev_un; | 147 | } _sigev_un; |
| 148 | } compat_sigevent_t; | 148 | } compat_sigevent_t; |
| 149 | 149 | ||
| 150 | struct compat_robust_list { | ||
| 151 | compat_uptr_t next; | ||
| 152 | }; | ||
| 153 | |||
| 154 | struct compat_robust_list_head { | ||
| 155 | struct compat_robust_list list; | ||
| 156 | compat_long_t futex_offset; | ||
| 157 | compat_uptr_t list_op_pending; | ||
| 158 | }; | ||
| 159 | |||
| 160 | extern void compat_exit_robust_list(struct task_struct *curr); | ||
| 161 | |||
| 162 | asmlinkage long | ||
| 163 | compat_sys_set_robust_list(struct compat_robust_list_head __user *head, | ||
| 164 | compat_size_t len); | ||
| 165 | asmlinkage long | ||
| 166 | compat_sys_get_robust_list(int pid, compat_uptr_t *head_ptr, | ||
| 167 | compat_size_t __user *len_ptr); | ||
| 150 | 168 | ||
| 151 | long compat_sys_semctl(int first, int second, int third, void __user *uptr); | 169 | long compat_sys_semctl(int first, int second, int third, void __user *uptr); |
| 152 | long compat_sys_msgsnd(int first, int second, int third, void __user *uptr); | 170 | long compat_sys_msgsnd(int first, int second, int third, void __user *uptr); |
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index efb518f16bb3..89ab677cb993 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h | |||
| @@ -140,6 +140,7 @@ COMPATIBLE_IOCTL(DM_TABLE_DEPS_32) | |||
| 140 | COMPATIBLE_IOCTL(DM_TABLE_STATUS_32) | 140 | COMPATIBLE_IOCTL(DM_TABLE_STATUS_32) |
| 141 | COMPATIBLE_IOCTL(DM_LIST_VERSIONS_32) | 141 | COMPATIBLE_IOCTL(DM_LIST_VERSIONS_32) |
| 142 | COMPATIBLE_IOCTL(DM_TARGET_MSG_32) | 142 | COMPATIBLE_IOCTL(DM_TARGET_MSG_32) |
| 143 | COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY_32) | ||
| 143 | COMPATIBLE_IOCTL(DM_VERSION) | 144 | COMPATIBLE_IOCTL(DM_VERSION) |
| 144 | COMPATIBLE_IOCTL(DM_REMOVE_ALL) | 145 | COMPATIBLE_IOCTL(DM_REMOVE_ALL) |
| 145 | COMPATIBLE_IOCTL(DM_LIST_DEVICES) | 146 | COMPATIBLE_IOCTL(DM_LIST_DEVICES) |
| @@ -155,6 +156,7 @@ COMPATIBLE_IOCTL(DM_TABLE_DEPS) | |||
| 155 | COMPATIBLE_IOCTL(DM_TABLE_STATUS) | 156 | COMPATIBLE_IOCTL(DM_TABLE_STATUS) |
| 156 | COMPATIBLE_IOCTL(DM_LIST_VERSIONS) | 157 | COMPATIBLE_IOCTL(DM_LIST_VERSIONS) |
| 157 | COMPATIBLE_IOCTL(DM_TARGET_MSG) | 158 | COMPATIBLE_IOCTL(DM_TARGET_MSG) |
| 159 | COMPATIBLE_IOCTL(DM_DEV_SET_GEOMETRY) | ||
| 158 | /* Big K */ | 160 | /* Big K */ |
| 159 | COMPATIBLE_IOCTL(PIO_FONT) | 161 | COMPATIBLE_IOCTL(PIO_FONT) |
| 160 | COMPATIBLE_IOCTL(GIO_FONT) | 162 | COMPATIBLE_IOCTL(GIO_FONT) |
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 99e6115d8e52..9cbb781d6f80 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h | |||
| @@ -67,7 +67,7 @@ | |||
| 67 | * | 67 | * |
| 68 | * int any_online_cpu(mask) First online cpu in mask | 68 | * int any_online_cpu(mask) First online cpu in mask |
| 69 | * | 69 | * |
| 70 | * for_each_cpu(cpu) for-loop cpu over cpu_possible_map | 70 | * for_each_possible_cpu(cpu) for-loop cpu over cpu_possible_map |
| 71 | * for_each_online_cpu(cpu) for-loop cpu over cpu_online_map | 71 | * for_each_online_cpu(cpu) for-loop cpu over cpu_online_map |
| 72 | * for_each_present_cpu(cpu) for-loop cpu over cpu_present_map | 72 | * for_each_present_cpu(cpu) for-loop cpu over cpu_present_map |
| 73 | * | 73 | * |
| @@ -405,7 +405,8 @@ int __any_online_cpu(const cpumask_t *mask); | |||
| 405 | #define any_online_cpu(mask) 0 | 405 | #define any_online_cpu(mask) 0 |
| 406 | #endif | 406 | #endif |
| 407 | 407 | ||
| 408 | #define for_each_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map) | 408 | #define for_each_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map) |
| 409 | #define for_each_possible_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map) | ||
| 409 | #define for_each_online_cpu(cpu) for_each_cpu_mask((cpu), cpu_online_map) | 410 | #define for_each_online_cpu(cpu) for_each_cpu_mask((cpu), cpu_online_map) |
| 410 | #define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map) | 411 | #define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map) |
| 411 | 412 | ||
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h index 534d750d922d..32503657f14f 100644 --- a/include/linux/crash_dump.h +++ b/include/linux/crash_dump.h | |||
| @@ -11,7 +11,7 @@ | |||
| 11 | extern unsigned long long elfcorehdr_addr; | 11 | extern unsigned long long elfcorehdr_addr; |
| 12 | extern ssize_t copy_oldmem_page(unsigned long, char *, size_t, | 12 | extern ssize_t copy_oldmem_page(unsigned long, char *, size_t, |
| 13 | unsigned long, int); | 13 | unsigned long, int); |
| 14 | extern struct file_operations proc_vmcore_operations; | 14 | extern const struct file_operations proc_vmcore_operations; |
| 15 | extern struct proc_dir_entry *proc_vmcore; | 15 | extern struct proc_dir_entry *proc_vmcore; |
| 16 | 16 | ||
| 17 | #endif /* CONFIG_CRASH_DUMP */ | 17 | #endif /* CONFIG_CRASH_DUMP */ |
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index 4b0428e335be..176e2d371577 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h | |||
| @@ -29,7 +29,7 @@ struct debugfs_blob_wrapper { | |||
| 29 | #if defined(CONFIG_DEBUG_FS) | 29 | #if defined(CONFIG_DEBUG_FS) |
| 30 | struct dentry *debugfs_create_file(const char *name, mode_t mode, | 30 | struct dentry *debugfs_create_file(const char *name, mode_t mode, |
| 31 | struct dentry *parent, void *data, | 31 | struct dentry *parent, void *data, |
| 32 | struct file_operations *fops); | 32 | const struct file_operations *fops); |
| 33 | 33 | ||
| 34 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); | 34 | struct dentry *debugfs_create_dir(const char *name, struct dentry *parent); |
| 35 | 35 | ||
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 51e0e95a421a..aee10b2ea4c6 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h | |||
| @@ -97,6 +97,7 @@ struct io_restrictions { | |||
| 97 | unsigned short hardsect_size; | 97 | unsigned short hardsect_size; |
| 98 | unsigned int max_segment_size; | 98 | unsigned int max_segment_size; |
| 99 | unsigned long seg_boundary_mask; | 99 | unsigned long seg_boundary_mask; |
| 100 | unsigned char no_cluster; /* inverted so that 0 is default */ | ||
| 100 | }; | 101 | }; |
| 101 | 102 | ||
| 102 | struct dm_target { | 103 | struct dm_target { |
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index fa75ba0d635e..c67c6786612a 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h | |||
| @@ -80,6 +80,16 @@ | |||
| 80 | * | 80 | * |
| 81 | * DM_TARGET_MSG: | 81 | * DM_TARGET_MSG: |
| 82 | * Pass a message string to the target at a specific offset of a device. | 82 | * Pass a message string to the target at a specific offset of a device. |
| 83 | * | ||
| 84 | * DM_DEV_SET_GEOMETRY: | ||
| 85 | * Set the geometry of a device by passing in a string in this format: | ||
| 86 | * | ||
| 87 | * "cylinders heads sectors_per_track start_sector" | ||
| 88 | * | ||
| 89 | * Beware that CHS geometry is nearly obsolete and only provided | ||
| 90 | * for compatibility with dm devices that can be booted by a PC | ||
| 91 | * BIOS. See struct hd_geometry for range limits. Also note that | ||
| 92 | * the geometry is erased if the device size changes. | ||
| 83 | */ | 93 | */ |
| 84 | 94 | ||
| 85 | /* | 95 | /* |
| @@ -218,6 +228,7 @@ enum { | |||
| 218 | /* Added later */ | 228 | /* Added later */ |
| 219 | DM_LIST_VERSIONS_CMD, | 229 | DM_LIST_VERSIONS_CMD, |
| 220 | DM_TARGET_MSG_CMD, | 230 | DM_TARGET_MSG_CMD, |
| 231 | DM_DEV_SET_GEOMETRY_CMD | ||
| 221 | }; | 232 | }; |
| 222 | 233 | ||
| 223 | /* | 234 | /* |
| @@ -247,6 +258,7 @@ typedef char ioctl_struct[308]; | |||
| 247 | #define DM_TABLE_STATUS_32 _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, ioctl_struct) | 258 | #define DM_TABLE_STATUS_32 _IOWR(DM_IOCTL, DM_TABLE_STATUS_CMD, ioctl_struct) |
| 248 | #define DM_LIST_VERSIONS_32 _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, ioctl_struct) | 259 | #define DM_LIST_VERSIONS_32 _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, ioctl_struct) |
| 249 | #define DM_TARGET_MSG_32 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, ioctl_struct) | 260 | #define DM_TARGET_MSG_32 _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, ioctl_struct) |
| 261 | #define DM_DEV_SET_GEOMETRY_32 _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, ioctl_struct) | ||
| 250 | #endif | 262 | #endif |
| 251 | 263 | ||
| 252 | #define DM_IOCTL 0xfd | 264 | #define DM_IOCTL 0xfd |
| @@ -270,11 +282,12 @@ typedef char ioctl_struct[308]; | |||
| 270 | #define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl) | 282 | #define DM_LIST_VERSIONS _IOWR(DM_IOCTL, DM_LIST_VERSIONS_CMD, struct dm_ioctl) |
| 271 | 283 | ||
| 272 | #define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) | 284 | #define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) |
| 285 | #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) | ||
| 273 | 286 | ||
| 274 | #define DM_VERSION_MAJOR 4 | 287 | #define DM_VERSION_MAJOR 4 |
| 275 | #define DM_VERSION_MINOR 5 | 288 | #define DM_VERSION_MINOR 6 |
| 276 | #define DM_VERSION_PATCHLEVEL 0 | 289 | #define DM_VERSION_PATCHLEVEL 0 |
| 277 | #define DM_VERSION_EXTRA "-ioctl (2005-10-04)" | 290 | #define DM_VERSION_EXTRA "-ioctl (2006-02-17)" |
| 278 | 291 | ||
| 279 | /* Status bits */ | 292 | /* Status bits */ |
| 280 | #define DM_READONLY_FLAG (1 << 0) /* In/Out */ | 293 | #define DM_READONLY_FLAG (1 << 0) /* In/Out */ |
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h index a8731062a74c..9b4751aecc23 100644 --- a/include/linux/dma-mapping.h +++ b/include/linux/dma-mapping.h | |||
| @@ -21,6 +21,7 @@ enum dma_data_direction { | |||
| 21 | #define DMA_30BIT_MASK 0x000000003fffffffULL | 21 | #define DMA_30BIT_MASK 0x000000003fffffffULL |
| 22 | #define DMA_29BIT_MASK 0x000000001fffffffULL | 22 | #define DMA_29BIT_MASK 0x000000001fffffffULL |
| 23 | #define DMA_28BIT_MASK 0x000000000fffffffULL | 23 | #define DMA_28BIT_MASK 0x000000000fffffffULL |
| 24 | #define DMA_24BIT_MASK 0x0000000000ffffffULL | ||
| 24 | 25 | ||
| 25 | #include <asm/dma-mapping.h> | 26 | #include <asm/dma-mapping.h> |
| 26 | 27 | ||
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h index 28f368c526fb..fbfa6b52e2fb 100644 --- a/include/linux/efs_fs.h +++ b/include/linux/efs_fs.h | |||
| @@ -37,7 +37,7 @@ static inline struct efs_sb_info *SUPER_INFO(struct super_block *sb) | |||
| 37 | struct statfs; | 37 | struct statfs; |
| 38 | 38 | ||
| 39 | extern struct inode_operations efs_dir_inode_operations; | 39 | extern struct inode_operations efs_dir_inode_operations; |
| 40 | extern struct file_operations efs_dir_operations; | 40 | extern const struct file_operations efs_dir_operations; |
| 41 | extern struct address_space_operations efs_symlink_aops; | 41 | extern struct address_space_operations efs_symlink_aops; |
| 42 | 42 | ||
| 43 | extern void efs_read_inode(struct inode *); | 43 | extern void efs_read_inode(struct inode *); |
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 8bb4f842cded..3ade6a4e3bdd 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h | |||
| @@ -833,11 +833,11 @@ do { \ | |||
| 833 | */ | 833 | */ |
| 834 | 834 | ||
| 835 | /* dir.c */ | 835 | /* dir.c */ |
| 836 | extern struct file_operations ext3_dir_operations; | 836 | extern const struct file_operations ext3_dir_operations; |
| 837 | 837 | ||
| 838 | /* file.c */ | 838 | /* file.c */ |
| 839 | extern struct inode_operations ext3_file_inode_operations; | 839 | extern struct inode_operations ext3_file_inode_operations; |
| 840 | extern struct file_operations ext3_file_operations; | 840 | extern const struct file_operations ext3_file_operations; |
| 841 | 841 | ||
| 842 | /* namei.c */ | 842 | /* namei.c */ |
| 843 | extern struct inode_operations ext3_dir_inode_operations; | 843 | extern struct inode_operations ext3_dir_inode_operations; |
diff --git a/include/linux/fb.h b/include/linux/fb.h index 2cb19e6503aa..d03fadfcafe3 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
| @@ -734,7 +734,7 @@ struct fb_tile_ops { | |||
| 734 | 734 | ||
| 735 | /* A driver may set this flag to indicate that it does want a set_par to be | 735 | /* A driver may set this flag to indicate that it does want a set_par to be |
| 736 | * called every time when fbcon_switch is executed. The advantage is that with | 736 | * called every time when fbcon_switch is executed. The advantage is that with |
| 737 | * this flag set you can really be shure that set_par is always called before | 737 | * this flag set you can really be sure that set_par is always called before |
| 738 | * any of the functions dependant on the correct hardware state or altering | 738 | * any of the functions dependant on the correct hardware state or altering |
| 739 | * that state, even if you are using some broken X releases. The disadvantage | 739 | * that state, even if you are using some broken X releases. The disadvantage |
| 740 | * is that it introduces unwanted delays to every console switch if set_par | 740 | * is that it introduces unwanted delays to every console switch if set_par |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 9d9674946956..408fe89498f4 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -410,6 +410,9 @@ struct block_device { | |||
| 410 | struct list_head bd_inodes; | 410 | struct list_head bd_inodes; |
| 411 | void * bd_holder; | 411 | void * bd_holder; |
| 412 | int bd_holders; | 412 | int bd_holders; |
| 413 | #ifdef CONFIG_SYSFS | ||
| 414 | struct list_head bd_holder_list; | ||
| 415 | #endif | ||
| 413 | struct block_device * bd_contains; | 416 | struct block_device * bd_contains; |
| 414 | unsigned bd_block_size; | 417 | unsigned bd_block_size; |
| 415 | struct hd_struct * bd_part; | 418 | struct hd_struct * bd_part; |
| @@ -493,7 +496,7 @@ struct inode { | |||
| 493 | struct mutex i_mutex; | 496 | struct mutex i_mutex; |
| 494 | struct rw_semaphore i_alloc_sem; | 497 | struct rw_semaphore i_alloc_sem; |
| 495 | struct inode_operations *i_op; | 498 | struct inode_operations *i_op; |
| 496 | struct file_operations *i_fop; /* former ->i_op->default_file_ops */ | 499 | const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ |
| 497 | struct super_block *i_sb; | 500 | struct super_block *i_sb; |
| 498 | struct file_lock *i_flock; | 501 | struct file_lock *i_flock; |
| 499 | struct address_space *i_mapping; | 502 | struct address_space *i_mapping; |
| @@ -633,7 +636,7 @@ struct file { | |||
| 633 | } f_u; | 636 | } f_u; |
| 634 | struct dentry *f_dentry; | 637 | struct dentry *f_dentry; |
| 635 | struct vfsmount *f_vfsmnt; | 638 | struct vfsmount *f_vfsmnt; |
| 636 | struct file_operations *f_op; | 639 | const struct file_operations *f_op; |
| 637 | atomic_t f_count; | 640 | atomic_t f_count; |
| 638 | unsigned int f_flags; | 641 | unsigned int f_flags; |
| 639 | mode_t f_mode; | 642 | mode_t f_mode; |
| @@ -1387,11 +1390,11 @@ extern void bd_set_size(struct block_device *, loff_t size); | |||
| 1387 | extern void bd_forget(struct inode *inode); | 1390 | extern void bd_forget(struct inode *inode); |
| 1388 | extern void bdput(struct block_device *); | 1391 | extern void bdput(struct block_device *); |
| 1389 | extern struct block_device *open_by_devnum(dev_t, unsigned); | 1392 | extern struct block_device *open_by_devnum(dev_t, unsigned); |
| 1390 | extern struct file_operations def_blk_fops; | 1393 | extern const struct file_operations def_blk_fops; |
| 1391 | extern struct address_space_operations def_blk_aops; | 1394 | extern struct address_space_operations def_blk_aops; |
| 1392 | extern struct file_operations def_chr_fops; | 1395 | extern const struct file_operations def_chr_fops; |
| 1393 | extern struct file_operations bad_sock_fops; | 1396 | extern const struct file_operations bad_sock_fops; |
| 1394 | extern struct file_operations def_fifo_fops; | 1397 | extern const struct file_operations def_fifo_fops; |
| 1395 | extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long); | 1398 | extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long); |
| 1396 | extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long); | 1399 | extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long); |
| 1397 | extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); | 1400 | extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); |
| @@ -1399,12 +1402,19 @@ extern int blkdev_get(struct block_device *, mode_t, unsigned); | |||
| 1399 | extern int blkdev_put(struct block_device *); | 1402 | extern int blkdev_put(struct block_device *); |
| 1400 | extern int bd_claim(struct block_device *, void *); | 1403 | extern int bd_claim(struct block_device *, void *); |
| 1401 | extern void bd_release(struct block_device *); | 1404 | extern void bd_release(struct block_device *); |
| 1405 | #ifdef CONFIG_SYSFS | ||
| 1406 | extern int bd_claim_by_disk(struct block_device *, void *, struct gendisk *); | ||
| 1407 | extern void bd_release_from_disk(struct block_device *, struct gendisk *); | ||
| 1408 | #else | ||
| 1409 | #define bd_claim_by_disk(bdev, holder, disk) bd_claim(bdev, holder) | ||
| 1410 | #define bd_release_from_disk(bdev, disk) bd_release(bdev) | ||
| 1411 | #endif | ||
| 1402 | 1412 | ||
| 1403 | /* fs/char_dev.c */ | 1413 | /* fs/char_dev.c */ |
| 1404 | extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); | 1414 | extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); |
| 1405 | extern int register_chrdev_region(dev_t, unsigned, const char *); | 1415 | extern int register_chrdev_region(dev_t, unsigned, const char *); |
| 1406 | extern int register_chrdev(unsigned int, const char *, | 1416 | extern int register_chrdev(unsigned int, const char *, |
| 1407 | struct file_operations *); | 1417 | const struct file_operations *); |
| 1408 | extern int unregister_chrdev(unsigned int, const char *); | 1418 | extern int unregister_chrdev(unsigned int, const char *); |
| 1409 | extern void unregister_chrdev_region(dev_t, unsigned); | 1419 | extern void unregister_chrdev_region(dev_t, unsigned); |
| 1410 | extern int chrdev_open(struct inode *, struct file *); | 1420 | extern int chrdev_open(struct inode *, struct file *); |
| @@ -1434,9 +1444,9 @@ extern void init_special_inode(struct inode *, umode_t, dev_t); | |||
| 1434 | extern void make_bad_inode(struct inode *); | 1444 | extern void make_bad_inode(struct inode *); |
| 1435 | extern int is_bad_inode(struct inode *); | 1445 | extern int is_bad_inode(struct inode *); |
| 1436 | 1446 | ||
| 1437 | extern struct file_operations read_fifo_fops; | 1447 | extern const struct file_operations read_fifo_fops; |
| 1438 | extern struct file_operations write_fifo_fops; | 1448 | extern const struct file_operations write_fifo_fops; |
| 1439 | extern struct file_operations rdwr_fifo_fops; | 1449 | extern const struct file_operations rdwr_fifo_fops; |
| 1440 | 1450 | ||
| 1441 | extern int fs_may_remount_ro(struct super_block *); | 1451 | extern int fs_may_remount_ro(struct super_block *); |
| 1442 | 1452 | ||
| @@ -1678,7 +1688,7 @@ static inline ssize_t blockdev_direct_IO_own_locking(int rw, struct kiocb *iocb, | |||
| 1678 | nr_segs, get_block, end_io, DIO_OWN_LOCKING); | 1688 | nr_segs, get_block, end_io, DIO_OWN_LOCKING); |
| 1679 | } | 1689 | } |
| 1680 | 1690 | ||
| 1681 | extern struct file_operations generic_ro_fops; | 1691 | extern const struct file_operations generic_ro_fops; |
| 1682 | 1692 | ||
| 1683 | #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) | 1693 | #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) |
| 1684 | 1694 | ||
| @@ -1734,9 +1744,9 @@ extern int simple_commit_write(struct file *file, struct page *page, | |||
| 1734 | 1744 | ||
| 1735 | extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *); | 1745 | extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *); |
| 1736 | extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); | 1746 | extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); |
| 1737 | extern struct file_operations simple_dir_operations; | 1747 | extern const struct file_operations simple_dir_operations; |
| 1738 | extern struct inode_operations simple_dir_inode_operations; | 1748 | extern struct inode_operations simple_dir_inode_operations; |
| 1739 | struct tree_descr { char *name; struct file_operations *ops; int mode; }; | 1749 | struct tree_descr { char *name; const struct file_operations *ops; int mode; }; |
| 1740 | struct dentry *d_alloc_name(struct dentry *, const char *); | 1750 | struct dentry *d_alloc_name(struct dentry *, const char *); |
| 1741 | extern int simple_fill_super(struct super_block *, int, struct tree_descr *); | 1751 | extern int simple_fill_super(struct super_block *, int, struct tree_descr *); |
| 1742 | extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count); | 1752 | extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count); |
diff --git a/include/linux/futex.h b/include/linux/futex.h index 10f96c31971e..966a5b3da439 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | #ifndef _LINUX_FUTEX_H | 1 | #ifndef _LINUX_FUTEX_H |
| 2 | #define _LINUX_FUTEX_H | 2 | #define _LINUX_FUTEX_H |
| 3 | 3 | ||
| 4 | #include <linux/sched.h> | ||
| 5 | |||
| 4 | /* Second argument to futex syscall */ | 6 | /* Second argument to futex syscall */ |
| 5 | 7 | ||
| 6 | 8 | ||
| @@ -11,10 +13,97 @@ | |||
| 11 | #define FUTEX_CMP_REQUEUE 4 | 13 | #define FUTEX_CMP_REQUEUE 4 |
| 12 | #define FUTEX_WAKE_OP 5 | 14 | #define FUTEX_WAKE_OP 5 |
| 13 | 15 | ||
| 16 | /* | ||
| 17 | * Support for robust futexes: the kernel cleans up held futexes at | ||
| 18 | * thread exit time. | ||
| 19 | */ | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Per-lock list entry - embedded in user-space locks, somewhere close | ||
| 23 | * to the futex field. (Note: user-space uses a double-linked list to | ||
| 24 | * achieve O(1) list add and remove, but the kernel only needs to know | ||
| 25 | * about the forward link) | ||
| 26 | * | ||
| 27 | * NOTE: this structure is part of the syscall ABI, and must not be | ||
| 28 | * changed. | ||
| 29 | */ | ||
| 30 | struct robust_list { | ||
| 31 | struct robust_list __user *next; | ||
| 32 | }; | ||
| 33 | |||
| 34 | /* | ||
| 35 | * Per-thread list head: | ||
| 36 | * | ||
| 37 | * NOTE: this structure is part of the syscall ABI, and must only be | ||
| 38 | * changed if the change is first communicated with the glibc folks. | ||
| 39 | * (When an incompatible change is done, we'll increase the structure | ||
| 40 | * size, which glibc will detect) | ||
| 41 | */ | ||
| 42 | struct robust_list_head { | ||
| 43 | /* | ||
| 44 | * The head of the list. Points back to itself if empty: | ||
| 45 | */ | ||
| 46 | struct robust_list list; | ||
| 47 | |||
| 48 | /* | ||
| 49 | * This relative offset is set by user-space, it gives the kernel | ||
| 50 | * the relative position of the futex field to examine. This way | ||
| 51 | * we keep userspace flexible, to freely shape its data-structure, | ||
| 52 | * without hardcoding any particular offset into the kernel: | ||
| 53 | */ | ||
| 54 | long futex_offset; | ||
| 55 | |||
| 56 | /* | ||
| 57 | * The death of the thread may race with userspace setting | ||
| 58 | * up a lock's links. So to handle this race, userspace first | ||
| 59 | * sets this field to the address of the to-be-taken lock, | ||
| 60 | * then does the lock acquire, and then adds itself to the | ||
| 61 | * list, and then clears this field. Hence the kernel will | ||
| 62 | * always have full knowledge of all locks that the thread | ||
| 63 | * _might_ have taken. We check the owner TID in any case, | ||
| 64 | * so only truly owned locks will be handled. | ||
| 65 | */ | ||
| 66 | struct robust_list __user *list_op_pending; | ||
| 67 | }; | ||
| 68 | |||
| 69 | /* | ||
| 70 | * Are there any waiters for this robust futex: | ||
| 71 | */ | ||
| 72 | #define FUTEX_WAITERS 0x80000000 | ||
| 73 | |||
| 74 | /* | ||
| 75 | * The kernel signals via this bit that a thread holding a futex | ||
| 76 | * has exited without unlocking the futex. The kernel also does | ||
| 77 | * a FUTEX_WAKE on such futexes, after setting the bit, to wake | ||
| 78 | * up any possible waiters: | ||
| 79 | */ | ||
| 80 | #define FUTEX_OWNER_DIED 0x40000000 | ||
| 81 | |||
| 82 | /* | ||
| 83 | * The rest of the robust-futex field is for the TID: | ||
| 84 | */ | ||
| 85 | #define FUTEX_TID_MASK 0x3fffffff | ||
| 86 | |||
| 87 | /* | ||
| 88 | * This limit protects against a deliberately circular list. | ||
| 89 | * (Not worth introducing an rlimit for it) | ||
| 90 | */ | ||
| 91 | #define ROBUST_LIST_LIMIT 2048 | ||
| 92 | |||
| 14 | long do_futex(unsigned long uaddr, int op, int val, | 93 | long do_futex(unsigned long uaddr, int op, int val, |
| 15 | unsigned long timeout, unsigned long uaddr2, int val2, | 94 | unsigned long timeout, unsigned long uaddr2, int val2, |
| 16 | int val3); | 95 | int val3); |
| 17 | 96 | ||
| 97 | extern int handle_futex_death(u32 __user *uaddr, struct task_struct *curr); | ||
| 98 | |||
| 99 | #ifdef CONFIG_FUTEX | ||
| 100 | extern void exit_robust_list(struct task_struct *curr); | ||
| 101 | #else | ||
| 102 | static inline void exit_robust_list(struct task_struct *curr) | ||
| 103 | { | ||
| 104 | } | ||
| 105 | #endif | ||
| 106 | |||
| 18 | #define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */ | 107 | #define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */ |
| 19 | #define FUTEX_OP_ADD 1 /* *(int *)UADDR2 += OPARG; */ | 108 | #define FUTEX_OP_ADD 1 /* *(int *)UADDR2 += OPARG; */ |
| 20 | #define FUTEX_OP_OR 2 /* *(int *)UADDR2 |= OPARG; */ | 109 | #define FUTEX_OP_OR 2 /* *(int *)UADDR2 |= OPARG; */ |
diff --git a/include/linux/genhd.h b/include/linux/genhd.h index fd647fde5ec1..10a27f29d692 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h | |||
| @@ -78,6 +78,7 @@ struct hd_struct { | |||
| 78 | sector_t start_sect; | 78 | sector_t start_sect; |
| 79 | sector_t nr_sects; | 79 | sector_t nr_sects; |
| 80 | struct kobject kobj; | 80 | struct kobject kobj; |
| 81 | struct kobject *holder_dir; | ||
| 81 | unsigned ios[2], sectors[2]; /* READs and WRITEs */ | 82 | unsigned ios[2], sectors[2]; /* READs and WRITEs */ |
| 82 | int policy, partno; | 83 | int policy, partno; |
| 83 | }; | 84 | }; |
| @@ -89,12 +90,12 @@ struct hd_struct { | |||
| 89 | #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 | 90 | #define GENHD_FL_SUPPRESS_PARTITION_INFO 32 |
| 90 | 91 | ||
| 91 | struct disk_stats { | 92 | struct disk_stats { |
| 92 | unsigned sectors[2]; /* READs and WRITEs */ | 93 | unsigned long sectors[2]; /* READs and WRITEs */ |
| 93 | unsigned ios[2]; | 94 | unsigned long ios[2]; |
| 94 | unsigned merges[2]; | 95 | unsigned long merges[2]; |
| 95 | unsigned ticks[2]; | 96 | unsigned long ticks[2]; |
| 96 | unsigned io_ticks; | 97 | unsigned long io_ticks; |
| 97 | unsigned time_in_queue; | 98 | unsigned long time_in_queue; |
| 98 | }; | 99 | }; |
| 99 | 100 | ||
| 100 | struct gendisk { | 101 | struct gendisk { |
| @@ -114,6 +115,8 @@ struct gendisk { | |||
| 114 | int number; /* more of the same */ | 115 | int number; /* more of the same */ |
| 115 | struct device *driverfs_dev; | 116 | struct device *driverfs_dev; |
| 116 | struct kobject kobj; | 117 | struct kobject kobj; |
| 118 | struct kobject *holder_dir; | ||
| 119 | struct kobject *slave_dir; | ||
| 117 | 120 | ||
| 118 | struct timer_rand_state *random; | 121 | struct timer_rand_state *random; |
| 119 | int policy; | 122 | int policy; |
| @@ -149,14 +152,14 @@ struct disk_attribute { | |||
| 149 | ({ \ | 152 | ({ \ |
| 150 | typeof(gendiskp->dkstats->field) res = 0; \ | 153 | typeof(gendiskp->dkstats->field) res = 0; \ |
| 151 | int i; \ | 154 | int i; \ |
| 152 | for_each_cpu(i) \ | 155 | for_each_possible_cpu(i) \ |
| 153 | res += per_cpu_ptr(gendiskp->dkstats, i)->field; \ | 156 | res += per_cpu_ptr(gendiskp->dkstats, i)->field; \ |
| 154 | res; \ | 157 | res; \ |
| 155 | }) | 158 | }) |
| 156 | 159 | ||
| 157 | static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { | 160 | static inline void disk_stat_set_all(struct gendisk *gendiskp, int value) { |
| 158 | int i; | 161 | int i; |
| 159 | for_each_cpu(i) | 162 | for_each_possible_cpu(i) |
| 160 | memset(per_cpu_ptr(gendiskp->dkstats, i), value, | 163 | memset(per_cpu_ptr(gendiskp->dkstats, i), value, |
| 161 | sizeof (struct disk_stats)); | 164 | sizeof (struct disk_stats)); |
| 162 | } | 165 | } |
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index d6f1019625af..4c5e610fe442 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h | |||
| @@ -154,7 +154,7 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb) | |||
| 154 | return sb->s_fs_info; | 154 | return sb->s_fs_info; |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | extern struct file_operations hugetlbfs_file_operations; | 157 | extern const struct file_operations hugetlbfs_file_operations; |
| 158 | extern struct vm_operations_struct hugetlb_vm_ops; | 158 | extern struct vm_operations_struct hugetlb_vm_ops; |
| 159 | struct file *hugetlb_zero_setup(size_t); | 159 | struct file *hugetlb_zero_setup(size_t); |
| 160 | int hugetlb_extend_reservation(struct hugetlbfs_inode_info *info, | 160 | int hugetlb_extend_reservation(struct hugetlbfs_inode_info *info, |
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 679b46a6a565..c8b81f419fd8 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h | |||
| @@ -108,6 +108,10 @@ | |||
| 108 | #define I2C_DRIVERID_UPD64083 78 /* upd64083 video processor */ | 108 | #define I2C_DRIVERID_UPD64083 78 /* upd64083 video processor */ |
| 109 | #define I2C_DRIVERID_UPD64031A 79 /* upd64031a video processor */ | 109 | #define I2C_DRIVERID_UPD64031A 79 /* upd64031a video processor */ |
| 110 | #define I2C_DRIVERID_SAA717X 80 /* saa717x video encoder */ | 110 | #define I2C_DRIVERID_SAA717X 80 /* saa717x video encoder */ |
| 111 | #define I2C_DRIVERID_DS1672 81 /* Dallas/Maxim DS1672 RTC */ | ||
| 112 | #define I2C_DRIVERID_X1205 82 /* Xicor/Intersil X1205 RTC */ | ||
| 113 | #define I2C_DRIVERID_PCF8563 83 /* Philips PCF8563 RTC */ | ||
| 114 | #define I2C_DRIVERID_RS5C372 84 /* Ricoh RS5C372 RTC */ | ||
| 111 | 115 | ||
| 112 | #define I2C_DRIVERID_I2CDEV 900 | 116 | #define I2C_DRIVERID_I2CDEV 900 |
| 113 | #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ | 117 | #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ |
diff --git a/include/linux/input.h b/include/linux/input.h index 6d4cc3c110d6..1d4e341b72e6 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
| @@ -957,7 +957,7 @@ struct input_handler { | |||
| 957 | struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id); | 957 | struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id); |
| 958 | void (*disconnect)(struct input_handle *handle); | 958 | void (*disconnect)(struct input_handle *handle); |
| 959 | 959 | ||
| 960 | struct file_operations *fops; | 960 | const struct file_operations *fops; |
| 961 | int minor; | 961 | int minor; |
| 962 | char *name; | 962 | char *name; |
| 963 | 963 | ||
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 03d6cfaa5b8a..a3720f973ea5 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
| @@ -87,7 +87,7 @@ extern int cond_resched(void); | |||
| 87 | (__x < 0) ? -__x : __x; \ | 87 | (__x < 0) ? -__x : __x; \ |
| 88 | }) | 88 | }) |
| 89 | 89 | ||
| 90 | extern struct notifier_block *panic_notifier_list; | 90 | extern struct atomic_notifier_head panic_notifier_list; |
| 91 | extern long (*panic_blink)(long time); | 91 | extern long (*panic_blink)(long time); |
| 92 | NORET_TYPE void panic(const char * fmt, ...) | 92 | NORET_TYPE void panic(const char * fmt, ...) |
| 93 | __attribute__ ((NORET_AND format (printf, 1, 2))); | 93 | __attribute__ ((NORET_AND format (printf, 1, 2))); |
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index a484572c302e..b46249082cca 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h | |||
| @@ -46,7 +46,7 @@ static inline int kstat_irqs(int irq) | |||
| 46 | { | 46 | { |
| 47 | int cpu, sum = 0; | 47 | int cpu, sum = 0; |
| 48 | 48 | ||
| 49 | for_each_cpu(cpu) | 49 | for_each_possible_cpu(cpu) |
| 50 | sum += kstat_cpu(cpu).irqs[irq]; | 50 | sum += kstat_cpu(cpu).irqs[irq]; |
| 51 | 51 | ||
| 52 | return sum; | 52 | return sum; |
diff --git a/include/linux/m48t86.h b/include/linux/m48t86.h new file mode 100644 index 000000000000..9065199319d0 --- /dev/null +++ b/include/linux/m48t86.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | /* | ||
| 2 | * ST M48T86 / Dallas DS12887 RTC driver | ||
| 3 | * Copyright (c) 2006 Tower Technologies | ||
| 4 | * | ||
| 5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | struct m48t86_ops | ||
| 13 | { | ||
| 14 | void (*writeb)(unsigned char value, unsigned long addr); | ||
| 15 | unsigned char (*readb)(unsigned long addr); | ||
| 16 | }; | ||
diff --git a/include/linux/memory.h b/include/linux/memory.h index e251dc43d0f5..8f04143ca363 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h | |||
| @@ -77,7 +77,6 @@ extern int remove_memory_block(unsigned long, struct mem_section *, int); | |||
| 77 | 77 | ||
| 78 | #define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT) | 78 | #define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT) |
| 79 | 79 | ||
| 80 | struct notifier_block; | ||
| 81 | 80 | ||
| 82 | #endif /* CONFIG_MEMORY_HOTPLUG */ | 81 | #endif /* CONFIG_MEMORY_HOTPLUG */ |
| 83 | 82 | ||
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index 14ceebfc1efa..5b584dafb5a6 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h | |||
| @@ -36,7 +36,7 @@ struct class_device; | |||
| 36 | struct miscdevice { | 36 | struct miscdevice { |
| 37 | int minor; | 37 | int minor; |
| 38 | const char *name; | 38 | const char *name; |
| 39 | struct file_operations *fops; | 39 | const struct file_operations *fops; |
| 40 | struct list_head list; | 40 | struct list_head list; |
| 41 | struct device *dev; | 41 | struct device *dev; |
| 42 | struct class_device *class; | 42 | struct class_device *class; |
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index ebfc238cc243..b5c21122c299 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/numa.h> | 13 | #include <linux/numa.h> |
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/seqlock.h> | 15 | #include <linux/seqlock.h> |
| 16 | #include <linux/nodemask.h> | ||
| 16 | #include <asm/atomic.h> | 17 | #include <asm/atomic.h> |
| 17 | 18 | ||
| 18 | /* Free memory management - zoned buddy allocator. */ | 19 | /* Free memory management - zoned buddy allocator. */ |
| @@ -225,7 +226,6 @@ struct zone { | |||
| 225 | * Discontig memory support fields. | 226 | * Discontig memory support fields. |
| 226 | */ | 227 | */ |
| 227 | struct pglist_data *zone_pgdat; | 228 | struct pglist_data *zone_pgdat; |
| 228 | struct page *zone_mem_map; | ||
| 229 | /* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */ | 229 | /* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */ |
| 230 | unsigned long zone_start_pfn; | 230 | unsigned long zone_start_pfn; |
| 231 | 231 | ||
| @@ -307,7 +307,6 @@ typedef struct pglist_data { | |||
| 307 | unsigned long node_spanned_pages; /* total size of physical page | 307 | unsigned long node_spanned_pages; /* total size of physical page |
| 308 | range, including holes */ | 308 | range, including holes */ |
| 309 | int node_id; | 309 | int node_id; |
| 310 | struct pglist_data *pgdat_next; | ||
| 311 | wait_queue_head_t kswapd_wait; | 310 | wait_queue_head_t kswapd_wait; |
| 312 | struct task_struct *kswapd; | 311 | struct task_struct *kswapd; |
| 313 | int kswapd_max_order; | 312 | int kswapd_max_order; |
| @@ -324,8 +323,6 @@ typedef struct pglist_data { | |||
| 324 | 323 | ||
| 325 | #include <linux/memory_hotplug.h> | 324 | #include <linux/memory_hotplug.h> |
| 326 | 325 | ||
| 327 | extern struct pglist_data *pgdat_list; | ||
| 328 | |||
| 329 | void __get_zone_counts(unsigned long *active, unsigned long *inactive, | 326 | void __get_zone_counts(unsigned long *active, unsigned long *inactive, |
| 330 | unsigned long *free, struct pglist_data *pgdat); | 327 | unsigned long *free, struct pglist_data *pgdat); |
| 331 | void get_zone_counts(unsigned long *active, unsigned long *inactive, | 328 | void get_zone_counts(unsigned long *active, unsigned long *inactive, |
| @@ -350,57 +347,6 @@ unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long); | |||
| 350 | */ | 347 | */ |
| 351 | #define zone_idx(zone) ((zone) - (zone)->zone_pgdat->node_zones) | 348 | #define zone_idx(zone) ((zone) - (zone)->zone_pgdat->node_zones) |
| 352 | 349 | ||
| 353 | /** | ||
| 354 | * for_each_pgdat - helper macro to iterate over all nodes | ||
| 355 | * @pgdat - pointer to a pg_data_t variable | ||
| 356 | * | ||
| 357 | * Meant to help with common loops of the form | ||
| 358 | * pgdat = pgdat_list; | ||
| 359 | * while(pgdat) { | ||
| 360 | * ... | ||
| 361 | * pgdat = pgdat->pgdat_next; | ||
| 362 | * } | ||
| 363 | */ | ||
| 364 | #define for_each_pgdat(pgdat) \ | ||
| 365 | for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next) | ||
| 366 | |||
| 367 | /* | ||
| 368 | * next_zone - helper magic for for_each_zone() | ||
| 369 | * Thanks to William Lee Irwin III for this piece of ingenuity. | ||
| 370 | */ | ||
| 371 | static inline struct zone *next_zone(struct zone *zone) | ||
| 372 | { | ||
| 373 | pg_data_t *pgdat = zone->zone_pgdat; | ||
| 374 | |||
| 375 | if (zone < pgdat->node_zones + MAX_NR_ZONES - 1) | ||
| 376 | zone++; | ||
| 377 | else if (pgdat->pgdat_next) { | ||
| 378 | pgdat = pgdat->pgdat_next; | ||
| 379 | zone = pgdat->node_zones; | ||
| 380 | } else | ||
| 381 | zone = NULL; | ||
| 382 | |||
| 383 | return zone; | ||
| 384 | } | ||
| 385 | |||
| 386 | /** | ||
| 387 | * for_each_zone - helper macro to iterate over all memory zones | ||
| 388 | * @zone - pointer to struct zone variable | ||
| 389 | * | ||
| 390 | * The user only needs to declare the zone variable, for_each_zone | ||
| 391 | * fills it in. This basically means for_each_zone() is an | ||
| 392 | * easier to read version of this piece of code: | ||
| 393 | * | ||
| 394 | * for (pgdat = pgdat_list; pgdat; pgdat = pgdat->node_next) | ||
| 395 | * for (i = 0; i < MAX_NR_ZONES; ++i) { | ||
| 396 | * struct zone * z = pgdat->node_zones + i; | ||
| 397 | * ... | ||
| 398 | * } | ||
| 399 | * } | ||
| 400 | */ | ||
| 401 | #define for_each_zone(zone) \ | ||
| 402 | for (zone = pgdat_list->node_zones; zone; zone = next_zone(zone)) | ||
| 403 | |||
| 404 | static inline int populated_zone(struct zone *zone) | 350 | static inline int populated_zone(struct zone *zone) |
| 405 | { | 351 | { |
| 406 | return (!!zone->present_pages); | 352 | return (!!zone->present_pages); |
| @@ -472,6 +418,30 @@ extern struct pglist_data contig_page_data; | |||
| 472 | 418 | ||
| 473 | #endif /* !CONFIG_NEED_MULTIPLE_NODES */ | 419 | #endif /* !CONFIG_NEED_MULTIPLE_NODES */ |
| 474 | 420 | ||
| 421 | extern struct pglist_data *first_online_pgdat(void); | ||
| 422 | extern struct pglist_data *next_online_pgdat(struct pglist_data *pgdat); | ||
| 423 | extern struct zone *next_zone(struct zone *zone); | ||
| 424 | |||
| 425 | /** | ||
| 426 | * for_each_pgdat - helper macro to iterate over all nodes | ||
| 427 | * @pgdat - pointer to a pg_data_t variable | ||
| 428 | */ | ||
| 429 | #define for_each_online_pgdat(pgdat) \ | ||
| 430 | for (pgdat = first_online_pgdat(); \ | ||
| 431 | pgdat; \ | ||
| 432 | pgdat = next_online_pgdat(pgdat)) | ||
| 433 | /** | ||
| 434 | * for_each_zone - helper macro to iterate over all memory zones | ||
| 435 | * @zone - pointer to struct zone variable | ||
| 436 | * | ||
| 437 | * The user only needs to declare the zone variable, for_each_zone | ||
| 438 | * fills it in. | ||
| 439 | */ | ||
| 440 | #define for_each_zone(zone) \ | ||
| 441 | for (zone = (first_online_pgdat())->node_zones; \ | ||
| 442 | zone; \ | ||
| 443 | zone = next_zone(zone)) | ||
| 444 | |||
| 475 | #ifdef CONFIG_SPARSEMEM | 445 | #ifdef CONFIG_SPARSEMEM |
| 476 | #include <asm/sparsemem.h> | 446 | #include <asm/sparsemem.h> |
| 477 | #endif | 447 | #endif |
| @@ -602,17 +572,6 @@ static inline struct mem_section *__pfn_to_section(unsigned long pfn) | |||
| 602 | return __nr_to_section(pfn_to_section_nr(pfn)); | 572 | return __nr_to_section(pfn_to_section_nr(pfn)); |
| 603 | } | 573 | } |
| 604 | 574 | ||
| 605 | #define pfn_to_page(pfn) \ | ||
| 606 | ({ \ | ||
| 607 | unsigned long __pfn = (pfn); \ | ||
| 608 | __section_mem_map_addr(__pfn_to_section(__pfn)) + __pfn; \ | ||
| 609 | }) | ||
| 610 | #define page_to_pfn(page) \ | ||
| 611 | ({ \ | ||
| 612 | page - __section_mem_map_addr(__nr_to_section( \ | ||
| 613 | page_to_section(page))); \ | ||
| 614 | }) | ||
| 615 | |||
| 616 | static inline int pfn_valid(unsigned long pfn) | 575 | static inline int pfn_valid(unsigned long pfn) |
| 617 | { | 576 | { |
| 618 | if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS) | 577 | if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS) |
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index 779e6a5744c7..d9035c73e5d1 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h | |||
| @@ -334,7 +334,7 @@ extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, | |||
| 334 | unsigned long *mapped_blocks); | 334 | unsigned long *mapped_blocks); |
| 335 | 335 | ||
| 336 | /* fat/dir.c */ | 336 | /* fat/dir.c */ |
| 337 | extern struct file_operations fat_dir_operations; | 337 | extern const struct file_operations fat_dir_operations; |
| 338 | extern int fat_search_long(struct inode *inode, const unsigned char *name, | 338 | extern int fat_search_long(struct inode *inode, const unsigned char *name, |
| 339 | int name_len, struct fat_slot_info *sinfo); | 339 | int name_len, struct fat_slot_info *sinfo); |
| 340 | extern int fat_dir_empty(struct inode *dir); | 340 | extern int fat_dir_empty(struct inode *dir); |
| @@ -397,7 +397,7 @@ extern int fat_count_free_clusters(struct super_block *sb); | |||
| 397 | /* fat/file.c */ | 397 | /* fat/file.c */ |
| 398 | extern int fat_generic_ioctl(struct inode *inode, struct file *filp, | 398 | extern int fat_generic_ioctl(struct inode *inode, struct file *filp, |
| 399 | unsigned int cmd, unsigned long arg); | 399 | unsigned int cmd, unsigned long arg); |
| 400 | extern struct file_operations fat_file_operations; | 400 | extern const struct file_operations fat_file_operations; |
| 401 | extern struct inode_operations fat_file_inode_operations; | 401 | extern struct inode_operations fat_file_inode_operations; |
| 402 | extern int fat_notify_change(struct dentry * dentry, struct iattr * attr); | 402 | extern int fat_notify_change(struct dentry * dentry, struct iattr * attr); |
| 403 | extern void fat_truncate(struct inode *inode); | 403 | extern void fat_truncate(struct inode *inode); |
| @@ -420,6 +420,9 @@ extern int date_dos2unix(unsigned short time, unsigned short date); | |||
| 420 | extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date); | 420 | extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date); |
| 421 | extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs); | 421 | extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs); |
| 422 | 422 | ||
| 423 | int fat_cache_init(void); | ||
| 424 | void fat_cache_destroy(void); | ||
| 425 | |||
| 423 | #endif /* __KERNEL__ */ | 426 | #endif /* __KERNEL__ */ |
| 424 | 427 | ||
| 425 | #endif | 428 | #endif |
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h index e01342568530..96dc237b8f03 100644 --- a/include/linux/ncp_fs.h +++ b/include/linux/ncp_fs.h | |||
| @@ -209,7 +209,7 @@ void ncp_update_inode2(struct inode *, struct ncp_entry_info *); | |||
| 209 | 209 | ||
| 210 | /* linux/fs/ncpfs/dir.c */ | 210 | /* linux/fs/ncpfs/dir.c */ |
| 211 | extern struct inode_operations ncp_dir_inode_operations; | 211 | extern struct inode_operations ncp_dir_inode_operations; |
| 212 | extern struct file_operations ncp_dir_operations; | 212 | extern const struct file_operations ncp_dir_operations; |
| 213 | int ncp_conn_logged_in(struct super_block *); | 213 | int ncp_conn_logged_in(struct super_block *); |
| 214 | int ncp_date_dos2unix(__le16 time, __le16 date); | 214 | int ncp_date_dos2unix(__le16 time, __le16 date); |
| 215 | void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date); | 215 | void ncp_date_unix2dos(int unix_date, __le16 * time, __le16 * date); |
| @@ -230,7 +230,7 @@ void ncp_unlock_server(struct ncp_server *server); | |||
| 230 | 230 | ||
| 231 | /* linux/fs/ncpfs/file.c */ | 231 | /* linux/fs/ncpfs/file.c */ |
| 232 | extern struct inode_operations ncp_file_inode_operations; | 232 | extern struct inode_operations ncp_file_inode_operations; |
| 233 | extern struct file_operations ncp_file_operations; | 233 | extern const struct file_operations ncp_file_operations; |
| 234 | int ncp_make_open(struct inode *, int); | 234 | int ncp_make_open(struct inode *, int); |
| 235 | 235 | ||
| 236 | /* linux/fs/ncpfs/mmap.c */ | 236 | /* linux/fs/ncpfs/mmap.c */ |
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index f32d75c4f4cf..d54d7b278e96 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h | |||
| @@ -308,29 +308,30 @@ DECLARE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache); | |||
| 308 | 308 | ||
| 309 | #define CONNTRACK_ECACHE(x) (__get_cpu_var(ip_conntrack_ecache).x) | 309 | #define CONNTRACK_ECACHE(x) (__get_cpu_var(ip_conntrack_ecache).x) |
| 310 | 310 | ||
| 311 | extern struct notifier_block *ip_conntrack_chain; | 311 | extern struct atomic_notifier_head ip_conntrack_chain; |
| 312 | extern struct notifier_block *ip_conntrack_expect_chain; | 312 | extern struct atomic_notifier_head ip_conntrack_expect_chain; |
| 313 | 313 | ||
| 314 | static inline int ip_conntrack_register_notifier(struct notifier_block *nb) | 314 | static inline int ip_conntrack_register_notifier(struct notifier_block *nb) |
| 315 | { | 315 | { |
| 316 | return notifier_chain_register(&ip_conntrack_chain, nb); | 316 | return atomic_notifier_chain_register(&ip_conntrack_chain, nb); |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb) | 319 | static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb) |
| 320 | { | 320 | { |
| 321 | return notifier_chain_unregister(&ip_conntrack_chain, nb); | 321 | return atomic_notifier_chain_unregister(&ip_conntrack_chain, nb); |
| 322 | } | 322 | } |
| 323 | 323 | ||
| 324 | static inline int | 324 | static inline int |
| 325 | ip_conntrack_expect_register_notifier(struct notifier_block *nb) | 325 | ip_conntrack_expect_register_notifier(struct notifier_block *nb) |
| 326 | { | 326 | { |
| 327 | return notifier_chain_register(&ip_conntrack_expect_chain, nb); | 327 | return atomic_notifier_chain_register(&ip_conntrack_expect_chain, nb); |
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | static inline int | 330 | static inline int |
| 331 | ip_conntrack_expect_unregister_notifier(struct notifier_block *nb) | 331 | ip_conntrack_expect_unregister_notifier(struct notifier_block *nb) |
| 332 | { | 332 | { |
| 333 | return notifier_chain_unregister(&ip_conntrack_expect_chain, nb); | 333 | return atomic_notifier_chain_unregister(&ip_conntrack_expect_chain, |
| 334 | nb); | ||
| 334 | } | 335 | } |
| 335 | 336 | ||
| 336 | extern void ip_ct_deliver_cached_events(const struct ip_conntrack *ct); | 337 | extern void ip_ct_deliver_cached_events(const struct ip_conntrack *ct); |
| @@ -355,14 +356,14 @@ static inline void ip_conntrack_event(enum ip_conntrack_events event, | |||
| 355 | struct ip_conntrack *ct) | 356 | struct ip_conntrack *ct) |
| 356 | { | 357 | { |
| 357 | if (is_confirmed(ct) && !is_dying(ct)) | 358 | if (is_confirmed(ct) && !is_dying(ct)) |
| 358 | notifier_call_chain(&ip_conntrack_chain, event, ct); | 359 | atomic_notifier_call_chain(&ip_conntrack_chain, event, ct); |
| 359 | } | 360 | } |
| 360 | 361 | ||
| 361 | static inline void | 362 | static inline void |
| 362 | ip_conntrack_expect_event(enum ip_conntrack_expect_events event, | 363 | ip_conntrack_expect_event(enum ip_conntrack_expect_events event, |
| 363 | struct ip_conntrack_expect *exp) | 364 | struct ip_conntrack_expect *exp) |
| 364 | { | 365 | { |
| 365 | notifier_call_chain(&ip_conntrack_expect_chain, event, exp); | 366 | atomic_notifier_call_chain(&ip_conntrack_expect_chain, event, exp); |
| 366 | } | 367 | } |
| 367 | #else /* CONFIG_IP_NF_CONNTRACK_EVENTS */ | 368 | #else /* CONFIG_IP_NF_CONNTRACK_EVENTS */ |
| 368 | static inline void ip_conntrack_event_cache(enum ip_conntrack_events event, | 369 | static inline void ip_conntrack_event_cache(enum ip_conntrack_events event, |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index cbebd7d1b9e8..c71227dd4389 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
| @@ -324,7 +324,7 @@ extern struct inode_operations nfs_file_inode_operations; | |||
| 324 | #ifdef CONFIG_NFS_V3 | 324 | #ifdef CONFIG_NFS_V3 |
| 325 | extern struct inode_operations nfs3_file_inode_operations; | 325 | extern struct inode_operations nfs3_file_inode_operations; |
| 326 | #endif /* CONFIG_NFS_V3 */ | 326 | #endif /* CONFIG_NFS_V3 */ |
| 327 | extern struct file_operations nfs_file_operations; | 327 | extern const struct file_operations nfs_file_operations; |
| 328 | extern struct address_space_operations nfs_file_aops; | 328 | extern struct address_space_operations nfs_file_aops; |
| 329 | 329 | ||
| 330 | static inline struct rpc_cred *nfs_file_cred(struct file *file) | 330 | static inline struct rpc_cred *nfs_file_cred(struct file *file) |
| @@ -371,7 +371,7 @@ extern struct inode_operations nfs_dir_inode_operations; | |||
| 371 | #ifdef CONFIG_NFS_V3 | 371 | #ifdef CONFIG_NFS_V3 |
| 372 | extern struct inode_operations nfs3_dir_inode_operations; | 372 | extern struct inode_operations nfs3_dir_inode_operations; |
| 373 | #endif /* CONFIG_NFS_V3 */ | 373 | #endif /* CONFIG_NFS_V3 */ |
| 374 | extern struct file_operations nfs_dir_operations; | 374 | extern const struct file_operations nfs_dir_operations; |
| 375 | extern struct dentry_operations nfs_dentry_operations; | 375 | extern struct dentry_operations nfs_dentry_operations; |
| 376 | 376 | ||
| 377 | extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr); | 377 | extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr); |
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 6bad4766d3d9..d2a8abb5011a 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h | |||
| @@ -67,7 +67,8 @@ struct svc_expkey { | |||
| 67 | int ek_fsidtype; | 67 | int ek_fsidtype; |
| 68 | u32 ek_fsid[3]; | 68 | u32 ek_fsid[3]; |
| 69 | 69 | ||
| 70 | struct svc_export * ek_export; | 70 | struct vfsmount * ek_mnt; |
| 71 | struct dentry * ek_dentry; | ||
| 71 | }; | 72 | }; |
| 72 | 73 | ||
| 73 | #define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT)) | 74 | #define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT)) |
| @@ -85,9 +86,6 @@ void nfsd_export_shutdown(void); | |||
| 85 | void nfsd_export_flush(void); | 86 | void nfsd_export_flush(void); |
| 86 | void exp_readlock(void); | 87 | void exp_readlock(void); |
| 87 | void exp_readunlock(void); | 88 | void exp_readunlock(void); |
| 88 | struct svc_expkey * exp_find_key(struct auth_domain *clp, | ||
| 89 | int fsid_type, u32 *fsidv, | ||
| 90 | struct cache_req *reqp); | ||
| 91 | struct svc_export * exp_get_by_name(struct auth_domain *clp, | 89 | struct svc_export * exp_get_by_name(struct auth_domain *clp, |
| 92 | struct vfsmount *mnt, | 90 | struct vfsmount *mnt, |
| 93 | struct dentry *dentry, | 91 | struct dentry *dentry, |
| @@ -101,35 +99,20 @@ int exp_rootfh(struct auth_domain *, | |||
| 101 | int exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq); | 99 | int exp_pseudoroot(struct auth_domain *, struct svc_fh *fhp, struct cache_req *creq); |
| 102 | int nfserrno(int errno); | 100 | int nfserrno(int errno); |
| 103 | 101 | ||
| 104 | extern void expkey_put(struct cache_head *item, struct cache_detail *cd); | 102 | extern struct cache_detail svc_export_cache; |
| 105 | extern void svc_export_put(struct cache_head *item, struct cache_detail *cd); | ||
| 106 | extern struct cache_detail svc_export_cache, svc_expkey_cache; | ||
| 107 | 103 | ||
| 108 | static inline void exp_put(struct svc_export *exp) | 104 | static inline void exp_put(struct svc_export *exp) |
| 109 | { | 105 | { |
| 110 | svc_export_put(&exp->h, &svc_export_cache); | 106 | cache_put(&exp->h, &svc_export_cache); |
| 111 | } | 107 | } |
| 112 | 108 | ||
| 113 | static inline void exp_get(struct svc_export *exp) | 109 | static inline void exp_get(struct svc_export *exp) |
| 114 | { | 110 | { |
| 115 | cache_get(&exp->h); | 111 | cache_get(&exp->h); |
| 116 | } | 112 | } |
| 117 | static inline struct svc_export * | 113 | extern struct svc_export * |
| 118 | exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, | 114 | exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, |
| 119 | struct cache_req *reqp) | 115 | struct cache_req *reqp); |
| 120 | { | ||
| 121 | struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); | ||
| 122 | if (ek && !IS_ERR(ek)) { | ||
| 123 | struct svc_export *exp = ek->ek_export; | ||
| 124 | int err; | ||
| 125 | exp_get(exp); | ||
| 126 | expkey_put(&ek->h, &svc_expkey_cache); | ||
| 127 | if ((err = cache_check(&svc_export_cache, &exp->h, reqp))) | ||
| 128 | exp = ERR_PTR(err); | ||
| 129 | return exp; | ||
| 130 | } else | ||
| 131 | return ERR_PTR(PTR_ERR(ek)); | ||
| 132 | } | ||
| 133 | 116 | ||
| 134 | #endif /* __KERNEL__ */ | 117 | #endif /* __KERNEL__ */ |
| 135 | 118 | ||
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h index b959a4525cbd..1a9ef3e627d1 100644 --- a/include/linux/nodemask.h +++ b/include/linux/nodemask.h | |||
| @@ -350,11 +350,15 @@ extern nodemask_t node_possible_map; | |||
| 350 | #define num_possible_nodes() nodes_weight(node_possible_map) | 350 | #define num_possible_nodes() nodes_weight(node_possible_map) |
| 351 | #define node_online(node) node_isset((node), node_online_map) | 351 | #define node_online(node) node_isset((node), node_online_map) |
| 352 | #define node_possible(node) node_isset((node), node_possible_map) | 352 | #define node_possible(node) node_isset((node), node_possible_map) |
| 353 | #define first_online_node first_node(node_online_map) | ||
| 354 | #define next_online_node(nid) next_node((nid), node_online_map) | ||
| 353 | #else | 355 | #else |
| 354 | #define num_online_nodes() 1 | 356 | #define num_online_nodes() 1 |
| 355 | #define num_possible_nodes() 1 | 357 | #define num_possible_nodes() 1 |
| 356 | #define node_online(node) ((node) == 0) | 358 | #define node_online(node) ((node) == 0) |
| 357 | #define node_possible(node) ((node) == 0) | 359 | #define node_possible(node) ((node) == 0) |
| 360 | #define first_online_node 0 | ||
| 361 | #define next_online_node(nid) (MAX_NUMNODES) | ||
| 358 | #endif | 362 | #endif |
| 359 | 363 | ||
| 360 | #define any_online_node(mask) \ | 364 | #define any_online_node(mask) \ |
diff --git a/include/linux/notifier.h b/include/linux/notifier.h index 5937dd6053c3..51dbab9710c7 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h | |||
| @@ -10,25 +10,107 @@ | |||
| 10 | #ifndef _LINUX_NOTIFIER_H | 10 | #ifndef _LINUX_NOTIFIER_H |
| 11 | #define _LINUX_NOTIFIER_H | 11 | #define _LINUX_NOTIFIER_H |
| 12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
| 13 | #include <linux/mutex.h> | ||
| 14 | #include <linux/rwsem.h> | ||
| 13 | 15 | ||
| 14 | struct notifier_block | 16 | /* |
| 15 | { | 17 | * Notifier chains are of three types: |
| 16 | int (*notifier_call)(struct notifier_block *self, unsigned long, void *); | 18 | * |
| 19 | * Atomic notifier chains: Chain callbacks run in interrupt/atomic | ||
| 20 | * context. Callouts are not allowed to block. | ||
| 21 | * Blocking notifier chains: Chain callbacks run in process context. | ||
| 22 | * Callouts are allowed to block. | ||
| 23 | * Raw notifier chains: There are no restrictions on callbacks, | ||
| 24 | * registration, or unregistration. All locking and protection | ||
| 25 | * must be provided by the caller. | ||
| 26 | * | ||
| 27 | * atomic_notifier_chain_register() may be called from an atomic context, | ||
| 28 | * but blocking_notifier_chain_register() must be called from a process | ||
| 29 | * context. Ditto for the corresponding _unregister() routines. | ||
| 30 | * | ||
| 31 | * atomic_notifier_chain_unregister() and blocking_notifier_chain_unregister() | ||
| 32 | * _must not_ be called from within the call chain. | ||
| 33 | */ | ||
| 34 | |||
| 35 | struct notifier_block { | ||
| 36 | int (*notifier_call)(struct notifier_block *, unsigned long, void *); | ||
| 17 | struct notifier_block *next; | 37 | struct notifier_block *next; |
| 18 | int priority; | 38 | int priority; |
| 19 | }; | 39 | }; |
| 20 | 40 | ||
| 41 | struct atomic_notifier_head { | ||
| 42 | spinlock_t lock; | ||
| 43 | struct notifier_block *head; | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct blocking_notifier_head { | ||
| 47 | struct rw_semaphore rwsem; | ||
| 48 | struct notifier_block *head; | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct raw_notifier_head { | ||
| 52 | struct notifier_block *head; | ||
| 53 | }; | ||
| 54 | |||
| 55 | #define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \ | ||
| 56 | spin_lock_init(&(name)->lock); \ | ||
| 57 | (name)->head = NULL; \ | ||
| 58 | } while (0) | ||
| 59 | #define BLOCKING_INIT_NOTIFIER_HEAD(name) do { \ | ||
| 60 | init_rwsem(&(name)->rwsem); \ | ||
| 61 | (name)->head = NULL; \ | ||
| 62 | } while (0) | ||
| 63 | #define RAW_INIT_NOTIFIER_HEAD(name) do { \ | ||
| 64 | (name)->head = NULL; \ | ||
| 65 | } while (0) | ||
| 66 | |||
| 67 | #define ATOMIC_NOTIFIER_INIT(name) { \ | ||
| 68 | .lock = SPIN_LOCK_UNLOCKED, \ | ||
| 69 | .head = NULL } | ||
| 70 | #define BLOCKING_NOTIFIER_INIT(name) { \ | ||
| 71 | .rwsem = __RWSEM_INITIALIZER((name).rwsem), \ | ||
| 72 | .head = NULL } | ||
| 73 | #define RAW_NOTIFIER_INIT(name) { \ | ||
| 74 | .head = NULL } | ||
| 75 | |||
| 76 | #define ATOMIC_NOTIFIER_HEAD(name) \ | ||
| 77 | struct atomic_notifier_head name = \ | ||
| 78 | ATOMIC_NOTIFIER_INIT(name) | ||
| 79 | #define BLOCKING_NOTIFIER_HEAD(name) \ | ||
| 80 | struct blocking_notifier_head name = \ | ||
| 81 | BLOCKING_NOTIFIER_INIT(name) | ||
| 82 | #define RAW_NOTIFIER_HEAD(name) \ | ||
| 83 | struct raw_notifier_head name = \ | ||
| 84 | RAW_NOTIFIER_INIT(name) | ||
| 21 | 85 | ||
| 22 | #ifdef __KERNEL__ | 86 | #ifdef __KERNEL__ |
| 23 | 87 | ||
| 24 | extern int notifier_chain_register(struct notifier_block **list, struct notifier_block *n); | 88 | extern int atomic_notifier_chain_register(struct atomic_notifier_head *, |
| 25 | extern int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n); | 89 | struct notifier_block *); |
| 26 | extern int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v); | 90 | extern int blocking_notifier_chain_register(struct blocking_notifier_head *, |
| 91 | struct notifier_block *); | ||
| 92 | extern int raw_notifier_chain_register(struct raw_notifier_head *, | ||
| 93 | struct notifier_block *); | ||
| 94 | |||
| 95 | extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *, | ||
| 96 | struct notifier_block *); | ||
| 97 | extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *, | ||
| 98 | struct notifier_block *); | ||
| 99 | extern int raw_notifier_chain_unregister(struct raw_notifier_head *, | ||
| 100 | struct notifier_block *); | ||
| 101 | |||
| 102 | extern int atomic_notifier_call_chain(struct atomic_notifier_head *, | ||
| 103 | unsigned long val, void *v); | ||
| 104 | extern int blocking_notifier_call_chain(struct blocking_notifier_head *, | ||
| 105 | unsigned long val, void *v); | ||
| 106 | extern int raw_notifier_call_chain(struct raw_notifier_head *, | ||
| 107 | unsigned long val, void *v); | ||
| 27 | 108 | ||
| 28 | #define NOTIFY_DONE 0x0000 /* Don't care */ | 109 | #define NOTIFY_DONE 0x0000 /* Don't care */ |
| 29 | #define NOTIFY_OK 0x0001 /* Suits me */ | 110 | #define NOTIFY_OK 0x0001 /* Suits me */ |
| 30 | #define NOTIFY_STOP_MASK 0x8000 /* Don't call further */ | 111 | #define NOTIFY_STOP_MASK 0x8000 /* Don't call further */ |
| 31 | #define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) /* Bad/Veto action */ | 112 | #define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002) |
| 113 | /* Bad/Veto action */ | ||
| 32 | /* | 114 | /* |
| 33 | * Clean way to return from the notifier and stop further calls. | 115 | * Clean way to return from the notifier and stop further calls. |
| 34 | */ | 116 | */ |
diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h index 559c4c38a9c7..0d514b252454 100644 --- a/include/linux/oprofile.h +++ b/include/linux/oprofile.h | |||
| @@ -61,6 +61,16 @@ void oprofile_arch_exit(void); | |||
| 61 | */ | 61 | */ |
| 62 | void oprofile_add_sample(struct pt_regs * const regs, unsigned long event); | 62 | void oprofile_add_sample(struct pt_regs * const regs, unsigned long event); |
| 63 | 63 | ||
| 64 | /** | ||
| 65 | * Add an extended sample. Use this when the PC is not from the regs, and | ||
| 66 | * we cannot determine if we're in kernel mode from the regs. | ||
| 67 | * | ||
| 68 | * This function does perform a backtrace. | ||
| 69 | * | ||
| 70 | */ | ||
| 71 | void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, | ||
| 72 | unsigned long event, int is_kernel); | ||
| 73 | |||
| 64 | /* Use this instead when the PC value is not from the regs. Doesn't | 74 | /* Use this instead when the PC value is not from the regs. Doesn't |
| 65 | * backtrace. */ | 75 | * backtrace. */ |
| 66 | void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event); | 76 | void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event); |
| @@ -74,10 +84,10 @@ void oprofile_add_trace(unsigned long eip); | |||
| 74 | * the specified file operations. | 84 | * the specified file operations. |
| 75 | */ | 85 | */ |
| 76 | int oprofilefs_create_file(struct super_block * sb, struct dentry * root, | 86 | int oprofilefs_create_file(struct super_block * sb, struct dentry * root, |
| 77 | char const * name, struct file_operations * fops); | 87 | char const * name, const struct file_operations * fops); |
| 78 | 88 | ||
| 79 | int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root, | 89 | int oprofilefs_create_file_perm(struct super_block * sb, struct dentry * root, |
| 80 | char const * name, struct file_operations * fops, int perm); | 90 | char const * name, const struct file_operations * fops, int perm); |
| 81 | 91 | ||
| 82 | /** Create a file for read/write access to an unsigned long. */ | 92 | /** Create a file for read/write access to an unsigned long. */ |
| 83 | int oprofilefs_create_ulong(struct super_block * sb, struct dentry * root, | 93 | int oprofilefs_create_ulong(struct super_block * sb, struct dentry * root, |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 6f080ae59286..e2ab2ac18d6b 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
| @@ -642,6 +642,7 @@ | |||
| 642 | #define PCI_DEVICE_ID_SI_965 0x0965 | 642 | #define PCI_DEVICE_ID_SI_965 0x0965 |
| 643 | #define PCI_DEVICE_ID_SI_5511 0x5511 | 643 | #define PCI_DEVICE_ID_SI_5511 0x5511 |
| 644 | #define PCI_DEVICE_ID_SI_5513 0x5513 | 644 | #define PCI_DEVICE_ID_SI_5513 0x5513 |
| 645 | #define PCI_DEVICE_ID_SI_5517 0x5517 | ||
| 645 | #define PCI_DEVICE_ID_SI_5518 0x5518 | 646 | #define PCI_DEVICE_ID_SI_5518 0x5518 |
| 646 | #define PCI_DEVICE_ID_SI_5571 0x5571 | 647 | #define PCI_DEVICE_ID_SI_5571 0x5571 |
| 647 | #define PCI_DEVICE_ID_SI_5581 0x5581 | 648 | #define PCI_DEVICE_ID_SI_5581 0x5581 |
| @@ -1052,6 +1053,7 @@ | |||
| 1052 | #define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2 | 1053 | #define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2 |
| 1053 | #define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3 | 1054 | #define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3 |
| 1054 | #define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x00f9 | 1055 | #define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT 0x00f9 |
| 1056 | #define PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280 0x00fd | ||
| 1055 | #define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100 | 1057 | #define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR 0x0100 |
| 1056 | #define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101 | 1058 | #define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR 0x0101 |
| 1057 | #define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103 | 1059 | #define PCI_DEVICE_ID_NVIDIA_QUADRO 0x0103 |
diff --git a/include/linux/pfn.h b/include/linux/pfn.h new file mode 100644 index 000000000000..bb01f8b92b56 --- /dev/null +++ b/include/linux/pfn.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #ifndef _LINUX_PFN_H_ | ||
| 2 | #define _LINUX_PFN_H_ | ||
| 3 | |||
| 4 | #define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) | ||
| 5 | #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) | ||
| 6 | #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) | ||
| 7 | #define PFN_PHYS(x) ((x) << PAGE_SHIFT) | ||
| 8 | |||
| 9 | #endif | ||
diff --git a/include/linux/poll.h b/include/linux/poll.h index 8e8f6098508a..51e1b56741fb 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h | |||
| @@ -11,6 +11,15 @@ | |||
| 11 | #include <linux/mm.h> | 11 | #include <linux/mm.h> |
| 12 | #include <asm/uaccess.h> | 12 | #include <asm/uaccess.h> |
| 13 | 13 | ||
| 14 | /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating | ||
| 15 | additional memory. */ | ||
| 16 | #define MAX_STACK_ALLOC 832 | ||
| 17 | #define FRONTEND_STACK_ALLOC 256 | ||
| 18 | #define SELECT_STACK_ALLOC FRONTEND_STACK_ALLOC | ||
| 19 | #define POLL_STACK_ALLOC FRONTEND_STACK_ALLOC | ||
| 20 | #define WQUEUES_STACK_ALLOC (MAX_STACK_ALLOC - FRONTEND_STACK_ALLOC) | ||
| 21 | #define N_INLINE_POLL_ENTRIES (WQUEUES_STACK_ALLOC / sizeof(struct poll_table_entry)) | ||
| 22 | |||
| 14 | struct poll_table_struct; | 23 | struct poll_table_struct; |
| 15 | 24 | ||
| 16 | /* | 25 | /* |
| @@ -33,6 +42,12 @@ static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc) | |||
| 33 | pt->qproc = qproc; | 42 | pt->qproc = qproc; |
| 34 | } | 43 | } |
| 35 | 44 | ||
| 45 | struct poll_table_entry { | ||
| 46 | struct file * filp; | ||
| 47 | wait_queue_t wait; | ||
| 48 | wait_queue_head_t * wait_address; | ||
| 49 | }; | ||
| 50 | |||
| 36 | /* | 51 | /* |
| 37 | * Structures and helpers for sys_poll/sys_poll | 52 | * Structures and helpers for sys_poll/sys_poll |
| 38 | */ | 53 | */ |
| @@ -40,6 +55,8 @@ struct poll_wqueues { | |||
| 40 | poll_table pt; | 55 | poll_table pt; |
| 41 | struct poll_table_page * table; | 56 | struct poll_table_page * table; |
| 42 | int error; | 57 | int error; |
| 58 | int inline_index; | ||
| 59 | struct poll_table_entry inline_entries[N_INLINE_POLL_ENTRIES]; | ||
| 43 | }; | 60 | }; |
| 44 | 61 | ||
| 45 | extern void poll_initwait(struct poll_wqueues *pwq); | 62 | extern void poll_initwait(struct poll_wqueues *pwq); |
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index cb224cf653b1..135871df9911 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h | |||
| @@ -58,7 +58,7 @@ struct proc_dir_entry { | |||
| 58 | gid_t gid; | 58 | gid_t gid; |
| 59 | loff_t size; | 59 | loff_t size; |
| 60 | struct inode_operations * proc_iops; | 60 | struct inode_operations * proc_iops; |
| 61 | struct file_operations * proc_fops; | 61 | const struct file_operations * proc_fops; |
| 62 | get_info_t *get_info; | 62 | get_info_t *get_info; |
| 63 | struct module *owner; | 63 | struct module *owner; |
| 64 | struct proc_dir_entry *next, *parent, *subdir; | 64 | struct proc_dir_entry *next, *parent, *subdir; |
| @@ -128,9 +128,9 @@ extern int proc_match(int, const char *,struct proc_dir_entry *); | |||
| 128 | extern int proc_readdir(struct file *, void *, filldir_t); | 128 | extern int proc_readdir(struct file *, void *, filldir_t); |
| 129 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *); | 129 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *); |
| 130 | 130 | ||
| 131 | extern struct file_operations proc_kcore_operations; | 131 | extern const struct file_operations proc_kcore_operations; |
| 132 | extern struct file_operations proc_kmsg_operations; | 132 | extern const struct file_operations proc_kmsg_operations; |
| 133 | extern struct file_operations ppc_htab_operations; | 133 | extern const struct file_operations ppc_htab_operations; |
| 134 | 134 | ||
| 135 | /* | 135 | /* |
| 136 | * proc_tty.c | 136 | * proc_tty.c |
| @@ -189,7 +189,7 @@ static inline struct proc_dir_entry *proc_net_create(const char *name, | |||
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | static inline struct proc_dir_entry *proc_net_fops_create(const char *name, | 191 | static inline struct proc_dir_entry *proc_net_fops_create(const char *name, |
| 192 | mode_t mode, struct file_operations *fops) | 192 | mode_t mode, const struct file_operations *fops) |
| 193 | { | 193 | { |
| 194 | struct proc_dir_entry *res = create_proc_entry(name, mode, proc_net); | 194 | struct proc_dir_entry *res = create_proc_entry(name, mode, proc_net); |
| 195 | if (res) | 195 | if (res) |
diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h index fc610bb0f733..27f49c85d5d6 100644 --- a/include/linux/qnx4_fs.h +++ b/include/linux/qnx4_fs.h | |||
| @@ -118,8 +118,8 @@ extern struct buffer_head *qnx4_bread(struct inode *, int, int); | |||
| 118 | 118 | ||
| 119 | extern struct inode_operations qnx4_file_inode_operations; | 119 | extern struct inode_operations qnx4_file_inode_operations; |
| 120 | extern struct inode_operations qnx4_dir_inode_operations; | 120 | extern struct inode_operations qnx4_dir_inode_operations; |
| 121 | extern struct file_operations qnx4_file_operations; | 121 | extern const struct file_operations qnx4_file_operations; |
| 122 | extern struct file_operations qnx4_dir_operations; | 122 | extern const struct file_operations qnx4_dir_operations; |
| 123 | extern int qnx4_is_free(struct super_block *sb, long block); | 123 | extern int qnx4_is_free(struct super_block *sb, long block); |
| 124 | extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy); | 124 | extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy); |
| 125 | extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode, struct nameidata *nd); | 125 | extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode, struct nameidata *nd); |
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index b6e0bcad84e1..66b44e5e0d6e 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h | |||
| @@ -92,7 +92,10 @@ extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, | |||
| 92 | extern void md_super_wait(mddev_t *mddev); | 92 | extern void md_super_wait(mddev_t *mddev); |
| 93 | extern int sync_page_io(struct block_device *bdev, sector_t sector, int size, | 93 | extern int sync_page_io(struct block_device *bdev, sector_t sector, int size, |
| 94 | struct page *page, int rw); | 94 | struct page *page, int rw); |
| 95 | extern void md_do_sync(mddev_t *mddev); | ||
| 96 | extern void md_new_event(mddev_t *mddev); | ||
| 95 | 97 | ||
| 98 | extern void md_update_sb(mddev_t * mddev); | ||
| 96 | 99 | ||
| 97 | #define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); } | 100 | #define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); } |
| 98 | 101 | ||
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 617b9506c760..e2df61f5b09a 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h | |||
| @@ -132,6 +132,14 @@ struct mddev_s | |||
| 132 | 132 | ||
| 133 | char uuid[16]; | 133 | char uuid[16]; |
| 134 | 134 | ||
| 135 | /* If the array is being reshaped, we need to record the | ||
| 136 | * new shape and an indication of where we are up to. | ||
| 137 | * This is written to the superblock. | ||
| 138 | * If reshape_position is MaxSector, then no reshape is happening (yet). | ||
| 139 | */ | ||
| 140 | sector_t reshape_position; | ||
| 141 | int delta_disks, new_level, new_layout, new_chunk; | ||
| 142 | |||
| 135 | struct mdk_thread_s *thread; /* management thread */ | 143 | struct mdk_thread_s *thread; /* management thread */ |
| 136 | struct mdk_thread_s *sync_thread; /* doing resync or reconstruct */ | 144 | struct mdk_thread_s *sync_thread; /* doing resync or reconstruct */ |
| 137 | sector_t curr_resync; /* blocks scheduled */ | 145 | sector_t curr_resync; /* blocks scheduled */ |
| @@ -143,6 +151,10 @@ struct mddev_s | |||
| 143 | sector_t resync_mismatches; /* count of sectors where | 151 | sector_t resync_mismatches; /* count of sectors where |
| 144 | * parity/replica mismatch found | 152 | * parity/replica mismatch found |
| 145 | */ | 153 | */ |
| 154 | |||
| 155 | /* allow user-space to request suspension of IO to regions of the array */ | ||
| 156 | sector_t suspend_lo; | ||
| 157 | sector_t suspend_hi; | ||
| 146 | /* if zero, use the system-wide default */ | 158 | /* if zero, use the system-wide default */ |
| 147 | int sync_speed_min; | 159 | int sync_speed_min; |
| 148 | int sync_speed_max; | 160 | int sync_speed_max; |
| @@ -157,6 +169,9 @@ struct mddev_s | |||
| 157 | * DONE: thread is done and is waiting to be reaped | 169 | * DONE: thread is done and is waiting to be reaped |
| 158 | * REQUEST: user-space has requested a sync (used with SYNC) | 170 | * REQUEST: user-space has requested a sync (used with SYNC) |
| 159 | * CHECK: user-space request for for check-only, no repair | 171 | * CHECK: user-space request for for check-only, no repair |
| 172 | * RESHAPE: A reshape is happening | ||
| 173 | * | ||
| 174 | * If neither SYNC or RESHAPE are set, then it is a recovery. | ||
| 160 | */ | 175 | */ |
| 161 | #define MD_RECOVERY_RUNNING 0 | 176 | #define MD_RECOVERY_RUNNING 0 |
| 162 | #define MD_RECOVERY_SYNC 1 | 177 | #define MD_RECOVERY_SYNC 1 |
| @@ -166,10 +181,11 @@ struct mddev_s | |||
| 166 | #define MD_RECOVERY_NEEDED 5 | 181 | #define MD_RECOVERY_NEEDED 5 |
| 167 | #define MD_RECOVERY_REQUESTED 6 | 182 | #define MD_RECOVERY_REQUESTED 6 |
| 168 | #define MD_RECOVERY_CHECK 7 | 183 | #define MD_RECOVERY_CHECK 7 |
| 184 | #define MD_RECOVERY_RESHAPE 8 | ||
| 169 | unsigned long recovery; | 185 | unsigned long recovery; |
| 170 | 186 | ||
| 171 | int in_sync; /* know to not need resync */ | 187 | int in_sync; /* know to not need resync */ |
| 172 | struct semaphore reconfig_sem; | 188 | struct mutex reconfig_mutex; |
| 173 | atomic_t active; | 189 | atomic_t active; |
| 174 | 190 | ||
| 175 | int changed; /* true if we might need to reread partition info */ | 191 | int changed; /* true if we might need to reread partition info */ |
| @@ -249,7 +265,8 @@ struct mdk_personality | |||
| 249 | int (*spare_active) (mddev_t *mddev); | 265 | int (*spare_active) (mddev_t *mddev); |
| 250 | sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster); | 266 | sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster); |
| 251 | int (*resize) (mddev_t *mddev, sector_t sectors); | 267 | int (*resize) (mddev_t *mddev, sector_t sectors); |
| 252 | int (*reshape) (mddev_t *mddev, int raid_disks); | 268 | int (*check_reshape) (mddev_t *mddev); |
| 269 | int (*start_reshape) (mddev_t *mddev); | ||
| 253 | int (*reconfig) (mddev_t *mddev, int layout, int chunk_size); | 270 | int (*reconfig) (mddev_t *mddev, int layout, int chunk_size); |
| 254 | /* quiesce moves between quiescence states | 271 | /* quiesce moves between quiescence states |
| 255 | * 0 - fully active | 272 | * 0 - fully active |
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h index c100fa5d4bfa..774e1acfb8c4 100644 --- a/include/linux/raid/md_p.h +++ b/include/linux/raid/md_p.h | |||
| @@ -102,6 +102,18 @@ typedef struct mdp_device_descriptor_s { | |||
| 102 | #define MD_SB_ERRORS 1 | 102 | #define MD_SB_ERRORS 1 |
| 103 | 103 | ||
| 104 | #define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */ | 104 | #define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */ |
| 105 | |||
| 106 | /* | ||
| 107 | * Notes: | ||
| 108 | * - if an array is being reshaped (restriped) in order to change the | ||
| 109 | * the number of active devices in the array, 'raid_disks' will be | ||
| 110 | * the larger of the old and new numbers. 'delta_disks' will | ||
| 111 | * be the "new - old". So if +ve, raid_disks is the new value, and | ||
| 112 | * "raid_disks-delta_disks" is the old. If -ve, raid_disks is the | ||
| 113 | * old value and "raid_disks+delta_disks" is the new (smaller) value. | ||
| 114 | */ | ||
| 115 | |||
| 116 | |||
| 105 | typedef struct mdp_superblock_s { | 117 | typedef struct mdp_superblock_s { |
| 106 | /* | 118 | /* |
| 107 | * Constant generic information | 119 | * Constant generic information |
| @@ -146,7 +158,13 @@ typedef struct mdp_superblock_s { | |||
| 146 | __u32 cp_events_hi; /* 10 high-order of checkpoint update count */ | 158 | __u32 cp_events_hi; /* 10 high-order of checkpoint update count */ |
| 147 | #endif | 159 | #endif |
| 148 | __u32 recovery_cp; /* 11 recovery checkpoint sector count */ | 160 | __u32 recovery_cp; /* 11 recovery checkpoint sector count */ |
| 149 | __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 12]; | 161 | /* There are only valid for minor_version > 90 */ |
| 162 | __u64 reshape_position; /* 12,13 next address in array-space for reshape */ | ||
| 163 | __u32 new_level; /* 14 new level we are reshaping to */ | ||
| 164 | __u32 delta_disks; /* 15 change in number of raid_disks */ | ||
| 165 | __u32 new_layout; /* 16 new layout */ | ||
| 166 | __u32 new_chunk; /* 17 new chunk size (bytes) */ | ||
| 167 | __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18]; | ||
| 150 | 168 | ||
| 151 | /* | 169 | /* |
| 152 | * Personality information | 170 | * Personality information |
| @@ -207,7 +225,14 @@ struct mdp_superblock_1 { | |||
| 207 | * NOTE: signed, so bitmap can be before superblock | 225 | * NOTE: signed, so bitmap can be before superblock |
| 208 | * only meaningful of feature_map[0] is set. | 226 | * only meaningful of feature_map[0] is set. |
| 209 | */ | 227 | */ |
| 210 | __u8 pad1[128-100]; /* set to 0 when written */ | 228 | |
| 229 | /* These are only valid with feature bit '4' */ | ||
| 230 | __u64 reshape_position; /* next address in array-space for reshape */ | ||
| 231 | __u32 new_level; /* new level we are reshaping to */ | ||
| 232 | __u32 delta_disks; /* change in number of raid_disks */ | ||
| 233 | __u32 new_layout; /* new layout */ | ||
| 234 | __u32 new_chunk; /* new chunk size (bytes) */ | ||
| 235 | __u8 pad1[128-124]; /* set to 0 when written */ | ||
| 211 | 236 | ||
| 212 | /* constant this-device information - 64 bytes */ | 237 | /* constant this-device information - 64 bytes */ |
| 213 | __u64 data_offset; /* sector start of data, often 0 */ | 238 | __u64 data_offset; /* sector start of data, often 0 */ |
| @@ -240,8 +265,9 @@ struct mdp_superblock_1 { | |||
| 240 | 265 | ||
| 241 | /* feature_map bits */ | 266 | /* feature_map bits */ |
| 242 | #define MD_FEATURE_BITMAP_OFFSET 1 | 267 | #define MD_FEATURE_BITMAP_OFFSET 1 |
| 268 | #define MD_FEATURE_RESHAPE_ACTIVE 4 | ||
| 243 | 269 | ||
| 244 | #define MD_FEATURE_ALL 1 | 270 | #define MD_FEATURE_ALL 5 |
| 245 | 271 | ||
| 246 | #endif | 272 | #endif |
| 247 | 273 | ||
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index 394da8207b34..914af667044f 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h | |||
| @@ -135,6 +135,7 @@ struct stripe_head { | |||
| 135 | atomic_t count; /* nr of active thread/requests */ | 135 | atomic_t count; /* nr of active thread/requests */ |
| 136 | spinlock_t lock; | 136 | spinlock_t lock; |
| 137 | int bm_seq; /* sequence number for bitmap flushes */ | 137 | int bm_seq; /* sequence number for bitmap flushes */ |
| 138 | int disks; /* disks in stripe */ | ||
| 138 | struct r5dev { | 139 | struct r5dev { |
| 139 | struct bio req; | 140 | struct bio req; |
| 140 | struct bio_vec vec; | 141 | struct bio_vec vec; |
| @@ -156,6 +157,7 @@ struct stripe_head { | |||
| 156 | #define R5_ReadError 8 /* seen a read error here recently */ | 157 | #define R5_ReadError 8 /* seen a read error here recently */ |
| 157 | #define R5_ReWrite 9 /* have tried to over-write the readerror */ | 158 | #define R5_ReWrite 9 /* have tried to over-write the readerror */ |
| 158 | 159 | ||
| 160 | #define R5_Expanded 10 /* This block now has post-expand data */ | ||
| 159 | /* | 161 | /* |
| 160 | * Write method | 162 | * Write method |
| 161 | */ | 163 | */ |
| @@ -174,7 +176,9 @@ struct stripe_head { | |||
| 174 | #define STRIPE_DELAYED 6 | 176 | #define STRIPE_DELAYED 6 |
| 175 | #define STRIPE_DEGRADED 7 | 177 | #define STRIPE_DEGRADED 7 |
| 176 | #define STRIPE_BIT_DELAY 8 | 178 | #define STRIPE_BIT_DELAY 8 |
| 177 | 179 | #define STRIPE_EXPANDING 9 | |
| 180 | #define STRIPE_EXPAND_SOURCE 10 | ||
| 181 | #define STRIPE_EXPAND_READY 11 | ||
| 178 | /* | 182 | /* |
| 179 | * Plugging: | 183 | * Plugging: |
| 180 | * | 184 | * |
| @@ -211,12 +215,24 @@ struct raid5_private_data { | |||
| 211 | int raid_disks, working_disks, failed_disks; | 215 | int raid_disks, working_disks, failed_disks; |
| 212 | int max_nr_stripes; | 216 | int max_nr_stripes; |
| 213 | 217 | ||
| 218 | /* used during an expand */ | ||
| 219 | sector_t expand_progress; /* MaxSector when no expand happening */ | ||
| 220 | sector_t expand_lo; /* from here up to expand_progress it out-of-bounds | ||
| 221 | * as we haven't flushed the metadata yet | ||
| 222 | */ | ||
| 223 | int previous_raid_disks; | ||
| 224 | |||
| 214 | struct list_head handle_list; /* stripes needing handling */ | 225 | struct list_head handle_list; /* stripes needing handling */ |
| 215 | struct list_head delayed_list; /* stripes that have plugged requests */ | 226 | struct list_head delayed_list; /* stripes that have plugged requests */ |
| 216 | struct list_head bitmap_list; /* stripes delaying awaiting bitmap update */ | 227 | struct list_head bitmap_list; /* stripes delaying awaiting bitmap update */ |
| 217 | atomic_t preread_active_stripes; /* stripes with scheduled io */ | 228 | atomic_t preread_active_stripes; /* stripes with scheduled io */ |
| 218 | 229 | ||
| 219 | char cache_name[20]; | 230 | atomic_t reshape_stripes; /* stripes with pending writes for reshape */ |
| 231 | /* unfortunately we need two cache names as we temporarily have | ||
| 232 | * two caches. | ||
| 233 | */ | ||
| 234 | int active_name; | ||
| 235 | char cache_name[2][20]; | ||
| 220 | kmem_cache_t *slab_cache; /* for allocating stripes */ | 236 | kmem_cache_t *slab_cache; /* for allocating stripes */ |
| 221 | 237 | ||
| 222 | int seq_flush, seq_write; | 238 | int seq_flush, seq_write; |
| @@ -238,9 +254,10 @@ struct raid5_private_data { | |||
| 238 | wait_queue_head_t wait_for_overlap; | 254 | wait_queue_head_t wait_for_overlap; |
| 239 | int inactive_blocked; /* release of inactive stripes blocked, | 255 | int inactive_blocked; /* release of inactive stripes blocked, |
| 240 | * waiting for 25% to be free | 256 | * waiting for 25% to be free |
| 241 | */ | 257 | */ |
| 258 | int pool_size; /* number of disks in stripeheads in pool */ | ||
| 242 | spinlock_t device_lock; | 259 | spinlock_t device_lock; |
| 243 | struct disk_info disks[0]; | 260 | struct disk_info *disks; |
| 244 | }; | 261 | }; |
| 245 | 262 | ||
| 246 | typedef struct raid5_private_data raid5_conf_t; | 263 | typedef struct raid5_private_data raid5_conf_t; |
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h index 953b6df5d037..78ecfa28b1c2 100644 --- a/include/linux/ramfs.h +++ b/include/linux/ramfs.h | |||
| @@ -15,7 +15,7 @@ extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file, | |||
| 15 | extern int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma); | 15 | extern int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma); |
| 16 | #endif | 16 | #endif |
| 17 | 17 | ||
| 18 | extern struct file_operations ramfs_file_operations; | 18 | extern const struct file_operations ramfs_file_operations; |
| 19 | extern struct vm_operations_struct generic_file_vm_ops; | 19 | extern struct vm_operations_struct generic_file_vm_ops; |
| 20 | 20 | ||
| 21 | #endif | 21 | #endif |
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 912f1b7cb18f..5676c4210e2c 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h | |||
| @@ -1960,7 +1960,7 @@ int reiserfs_global_version_in_proc(char *buffer, char **start, off_t offset, | |||
| 1960 | extern struct inode_operations reiserfs_dir_inode_operations; | 1960 | extern struct inode_operations reiserfs_dir_inode_operations; |
| 1961 | extern struct inode_operations reiserfs_symlink_inode_operations; | 1961 | extern struct inode_operations reiserfs_symlink_inode_operations; |
| 1962 | extern struct inode_operations reiserfs_special_inode_operations; | 1962 | extern struct inode_operations reiserfs_special_inode_operations; |
| 1963 | extern struct file_operations reiserfs_dir_operations; | 1963 | extern const struct file_operations reiserfs_dir_operations; |
| 1964 | 1964 | ||
| 1965 | /* tail_conversion.c */ | 1965 | /* tail_conversion.c */ |
| 1966 | int direct2indirect(struct reiserfs_transaction_handle *, struct inode *, | 1966 | int direct2indirect(struct reiserfs_transaction_handle *, struct inode *, |
| @@ -1972,7 +1972,7 @@ void reiserfs_unmap_buffer(struct buffer_head *); | |||
| 1972 | 1972 | ||
| 1973 | /* file.c */ | 1973 | /* file.c */ |
| 1974 | extern struct inode_operations reiserfs_file_inode_operations; | 1974 | extern struct inode_operations reiserfs_file_inode_operations; |
| 1975 | extern struct file_operations reiserfs_file_operations; | 1975 | extern const struct file_operations reiserfs_file_operations; |
| 1976 | extern struct address_space_operations reiserfs_address_space_operations; | 1976 | extern struct address_space_operations reiserfs_address_space_operations; |
| 1977 | 1977 | ||
| 1978 | /* fix_nodes.c */ | 1978 | /* fix_nodes.c */ |
diff --git a/include/linux/relayfs_fs.h b/include/linux/relayfs_fs.h deleted file mode 100644 index 7342e66247fb..000000000000 --- a/include/linux/relayfs_fs.h +++ /dev/null | |||
| @@ -1,287 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * linux/include/linux/relayfs_fs.h | ||
| 3 | * | ||
| 4 | * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp | ||
| 5 | * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com) | ||
| 6 | * | ||
| 7 | * RelayFS definitions and declarations | ||
| 8 | */ | ||
| 9 | |||
| 10 | #ifndef _LINUX_RELAYFS_FS_H | ||
| 11 | #define _LINUX_RELAYFS_FS_H | ||
| 12 | |||
| 13 | #include <linux/config.h> | ||
| 14 | #include <linux/types.h> | ||
| 15 | #include <linux/sched.h> | ||
| 16 | #include <linux/wait.h> | ||
| 17 | #include <linux/list.h> | ||
| 18 | #include <linux/fs.h> | ||
| 19 | #include <linux/poll.h> | ||
| 20 | #include <linux/kref.h> | ||
| 21 | |||
| 22 | /* | ||
| 23 | * Tracks changes to rchan/rchan_buf structs | ||
| 24 | */ | ||
| 25 | #define RELAYFS_CHANNEL_VERSION 6 | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Per-cpu relay channel buffer | ||
| 29 | */ | ||
| 30 | struct rchan_buf | ||
| 31 | { | ||
| 32 | void *start; /* start of channel buffer */ | ||
| 33 | void *data; /* start of current sub-buffer */ | ||
| 34 | size_t offset; /* current offset into sub-buffer */ | ||
| 35 | size_t subbufs_produced; /* count of sub-buffers produced */ | ||
| 36 | size_t subbufs_consumed; /* count of sub-buffers consumed */ | ||
| 37 | struct rchan *chan; /* associated channel */ | ||
| 38 | wait_queue_head_t read_wait; /* reader wait queue */ | ||
| 39 | struct work_struct wake_readers; /* reader wake-up work struct */ | ||
| 40 | struct dentry *dentry; /* channel file dentry */ | ||
| 41 | struct kref kref; /* channel buffer refcount */ | ||
| 42 | struct page **page_array; /* array of current buffer pages */ | ||
| 43 | unsigned int page_count; /* number of current buffer pages */ | ||
| 44 | unsigned int finalized; /* buffer has been finalized */ | ||
| 45 | size_t *padding; /* padding counts per sub-buffer */ | ||
| 46 | size_t prev_padding; /* temporary variable */ | ||
| 47 | size_t bytes_consumed; /* bytes consumed in cur read subbuf */ | ||
| 48 | unsigned int cpu; /* this buf's cpu */ | ||
| 49 | } ____cacheline_aligned; | ||
| 50 | |||
| 51 | /* | ||
| 52 | * Relay channel data structure | ||
| 53 | */ | ||
| 54 | struct rchan | ||
| 55 | { | ||
| 56 | u32 version; /* the version of this struct */ | ||
| 57 | size_t subbuf_size; /* sub-buffer size */ | ||
| 58 | size_t n_subbufs; /* number of sub-buffers per buffer */ | ||
| 59 | size_t alloc_size; /* total buffer size allocated */ | ||
| 60 | struct rchan_callbacks *cb; /* client callbacks */ | ||
| 61 | struct kref kref; /* channel refcount */ | ||
| 62 | void *private_data; /* for user-defined data */ | ||
| 63 | size_t last_toobig; /* tried to log event > subbuf size */ | ||
| 64 | struct rchan_buf *buf[NR_CPUS]; /* per-cpu channel buffers */ | ||
| 65 | }; | ||
| 66 | |||
| 67 | /* | ||
| 68 | * Relay channel client callbacks | ||
| 69 | */ | ||
| 70 | struct rchan_callbacks | ||
| 71 | { | ||
| 72 | /* | ||
| 73 | * subbuf_start - called on buffer-switch to a new sub-buffer | ||
| 74 | * @buf: the channel buffer containing the new sub-buffer | ||
| 75 | * @subbuf: the start of the new sub-buffer | ||
| 76 | * @prev_subbuf: the start of the previous sub-buffer | ||
| 77 | * @prev_padding: unused space at the end of previous sub-buffer | ||
| 78 | * | ||
| 79 | * The client should return 1 to continue logging, 0 to stop | ||
| 80 | * logging. | ||
| 81 | * | ||
| 82 | * NOTE: subbuf_start will also be invoked when the buffer is | ||
| 83 | * created, so that the first sub-buffer can be initialized | ||
| 84 | * if necessary. In this case, prev_subbuf will be NULL. | ||
| 85 | * | ||
| 86 | * NOTE: the client can reserve bytes at the beginning of the new | ||
| 87 | * sub-buffer by calling subbuf_start_reserve() in this callback. | ||
| 88 | */ | ||
| 89 | int (*subbuf_start) (struct rchan_buf *buf, | ||
| 90 | void *subbuf, | ||
| 91 | void *prev_subbuf, | ||
| 92 | size_t prev_padding); | ||
| 93 | |||
| 94 | /* | ||
| 95 | * buf_mapped - relayfs buffer mmap notification | ||
| 96 | * @buf: the channel buffer | ||
| 97 | * @filp: relayfs file pointer | ||
| 98 | * | ||
| 99 | * Called when a relayfs file is successfully mmapped | ||
| 100 | */ | ||
| 101 | void (*buf_mapped)(struct rchan_buf *buf, | ||
| 102 | struct file *filp); | ||
| 103 | |||
| 104 | /* | ||
| 105 | * buf_unmapped - relayfs buffer unmap notification | ||
| 106 | * @buf: the channel buffer | ||
| 107 | * @filp: relayfs file pointer | ||
| 108 | * | ||
| 109 | * Called when a relayfs file is successfully unmapped | ||
| 110 | */ | ||
| 111 | void (*buf_unmapped)(struct rchan_buf *buf, | ||
| 112 | struct file *filp); | ||
| 113 | /* | ||
| 114 | * create_buf_file - create file to represent a relayfs channel buffer | ||
| 115 | * @filename: the name of the file to create | ||
| 116 | * @parent: the parent of the file to create | ||
| 117 | * @mode: the mode of the file to create | ||
| 118 | * @buf: the channel buffer | ||
| 119 | * @is_global: outparam - set non-zero if the buffer should be global | ||
| 120 | * | ||
| 121 | * Called during relay_open(), once for each per-cpu buffer, | ||
| 122 | * to allow the client to create a file to be used to | ||
| 123 | * represent the corresponding channel buffer. If the file is | ||
| 124 | * created outside of relayfs, the parent must also exist in | ||
| 125 | * that filesystem. | ||
| 126 | * | ||
| 127 | * The callback should return the dentry of the file created | ||
| 128 | * to represent the relay buffer. | ||
| 129 | * | ||
| 130 | * Setting the is_global outparam to a non-zero value will | ||
| 131 | * cause relay_open() to create a single global buffer rather | ||
| 132 | * than the default set of per-cpu buffers. | ||
| 133 | * | ||
| 134 | * See Documentation/filesystems/relayfs.txt for more info. | ||
| 135 | */ | ||
| 136 | struct dentry *(*create_buf_file)(const char *filename, | ||
| 137 | struct dentry *parent, | ||
| 138 | int mode, | ||
| 139 | struct rchan_buf *buf, | ||
| 140 | int *is_global); | ||
| 141 | |||
| 142 | /* | ||
| 143 | * remove_buf_file - remove file representing a relayfs channel buffer | ||
| 144 | * @dentry: the dentry of the file to remove | ||
| 145 | * | ||
| 146 | * Called during relay_close(), once for each per-cpu buffer, | ||
| 147 | * to allow the client to remove a file used to represent a | ||
| 148 | * channel buffer. | ||
| 149 | * | ||
| 150 | * The callback should return 0 if successful, negative if not. | ||
| 151 | */ | ||
| 152 | int (*remove_buf_file)(struct dentry *dentry); | ||
| 153 | }; | ||
| 154 | |||
| 155 | /* | ||
| 156 | * relayfs kernel API, fs/relayfs/relay.c | ||
| 157 | */ | ||
| 158 | |||
| 159 | struct rchan *relay_open(const char *base_filename, | ||
| 160 | struct dentry *parent, | ||
| 161 | size_t subbuf_size, | ||
| 162 | size_t n_subbufs, | ||
| 163 | struct rchan_callbacks *cb); | ||
| 164 | extern void relay_close(struct rchan *chan); | ||
| 165 | extern void relay_flush(struct rchan *chan); | ||
| 166 | extern void relay_subbufs_consumed(struct rchan *chan, | ||
| 167 | unsigned int cpu, | ||
| 168 | size_t consumed); | ||
| 169 | extern void relay_reset(struct rchan *chan); | ||
| 170 | extern int relay_buf_full(struct rchan_buf *buf); | ||
| 171 | |||
| 172 | extern size_t relay_switch_subbuf(struct rchan_buf *buf, | ||
| 173 | size_t length); | ||
| 174 | extern struct dentry *relayfs_create_dir(const char *name, | ||
| 175 | struct dentry *parent); | ||
| 176 | extern int relayfs_remove_dir(struct dentry *dentry); | ||
| 177 | extern struct dentry *relayfs_create_file(const char *name, | ||
| 178 | struct dentry *parent, | ||
| 179 | int mode, | ||
| 180 | struct file_operations *fops, | ||
| 181 | void *data); | ||
| 182 | extern int relayfs_remove_file(struct dentry *dentry); | ||
| 183 | |||
| 184 | /** | ||
| 185 | * relay_write - write data into the channel | ||
| 186 | * @chan: relay channel | ||
| 187 | * @data: data to be written | ||
| 188 | * @length: number of bytes to write | ||
| 189 | * | ||
| 190 | * Writes data into the current cpu's channel buffer. | ||
| 191 | * | ||
| 192 | * Protects the buffer by disabling interrupts. Use this | ||
| 193 | * if you might be logging from interrupt context. Try | ||
| 194 | * __relay_write() if you know you won't be logging from | ||
| 195 | * interrupt context. | ||
| 196 | */ | ||
| 197 | static inline void relay_write(struct rchan *chan, | ||
| 198 | const void *data, | ||
| 199 | size_t length) | ||
| 200 | { | ||
| 201 | unsigned long flags; | ||
| 202 | struct rchan_buf *buf; | ||
| 203 | |||
| 204 | local_irq_save(flags); | ||
| 205 | buf = chan->buf[smp_processor_id()]; | ||
| 206 | if (unlikely(buf->offset + length > chan->subbuf_size)) | ||
| 207 | length = relay_switch_subbuf(buf, length); | ||
| 208 | memcpy(buf->data + buf->offset, data, length); | ||
| 209 | buf->offset += length; | ||
| 210 | local_irq_restore(flags); | ||
| 211 | } | ||
| 212 | |||
| 213 | /** | ||
| 214 | * __relay_write - write data into the channel | ||
| 215 | * @chan: relay channel | ||
| 216 | * @data: data to be written | ||
| 217 | * @length: number of bytes to write | ||
| 218 | * | ||
| 219 | * Writes data into the current cpu's channel buffer. | ||
| 220 | * | ||
| 221 | * Protects the buffer by disabling preemption. Use | ||
| 222 | * relay_write() if you might be logging from interrupt | ||
| 223 | * context. | ||
| 224 | */ | ||
| 225 | static inline void __relay_write(struct rchan *chan, | ||
| 226 | const void *data, | ||
| 227 | size_t length) | ||
| 228 | { | ||
| 229 | struct rchan_buf *buf; | ||
| 230 | |||
| 231 | buf = chan->buf[get_cpu()]; | ||
| 232 | if (unlikely(buf->offset + length > buf->chan->subbuf_size)) | ||
| 233 | length = relay_switch_subbuf(buf, length); | ||
| 234 | memcpy(buf->data + buf->offset, data, length); | ||
| 235 | buf->offset += length; | ||
| 236 | put_cpu(); | ||
| 237 | } | ||
| 238 | |||
| 239 | /** | ||
| 240 | * relay_reserve - reserve slot in channel buffer | ||
| 241 | * @chan: relay channel | ||
| 242 | * @length: number of bytes to reserve | ||
| 243 | * | ||
| 244 | * Returns pointer to reserved slot, NULL if full. | ||
| 245 | * | ||
| 246 | * Reserves a slot in the current cpu's channel buffer. | ||
| 247 | * Does not protect the buffer at all - caller must provide | ||
| 248 | * appropriate synchronization. | ||
| 249 | */ | ||
| 250 | static inline void *relay_reserve(struct rchan *chan, size_t length) | ||
| 251 | { | ||
| 252 | void *reserved; | ||
| 253 | struct rchan_buf *buf = chan->buf[smp_processor_id()]; | ||
| 254 | |||
| 255 | if (unlikely(buf->offset + length > buf->chan->subbuf_size)) { | ||
| 256 | length = relay_switch_subbuf(buf, length); | ||
| 257 | if (!length) | ||
| 258 | return NULL; | ||
| 259 | } | ||
| 260 | reserved = buf->data + buf->offset; | ||
| 261 | buf->offset += length; | ||
| 262 | |||
| 263 | return reserved; | ||
| 264 | } | ||
| 265 | |||
| 266 | /** | ||
| 267 | * subbuf_start_reserve - reserve bytes at the start of a sub-buffer | ||
| 268 | * @buf: relay channel buffer | ||
| 269 | * @length: number of bytes to reserve | ||
| 270 | * | ||
| 271 | * Helper function used to reserve bytes at the beginning of | ||
| 272 | * a sub-buffer in the subbuf_start() callback. | ||
| 273 | */ | ||
| 274 | static inline void subbuf_start_reserve(struct rchan_buf *buf, | ||
| 275 | size_t length) | ||
| 276 | { | ||
| 277 | BUG_ON(length >= buf->chan->subbuf_size - 1); | ||
| 278 | buf->offset = length; | ||
| 279 | } | ||
| 280 | |||
| 281 | /* | ||
| 282 | * exported relay file operations, fs/relayfs/inode.c | ||
| 283 | */ | ||
| 284 | extern struct file_operations relay_file_operations; | ||
| 285 | |||
| 286 | #endif /* _LINUX_RELAYFS_FS_H */ | ||
| 287 | |||
diff --git a/include/linux/rtc.h b/include/linux/rtc.h index b739ac1f7ca0..ab61cd1199f2 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h | |||
| @@ -91,10 +91,102 @@ struct rtc_pll_info { | |||
| 91 | #define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ | 91 | #define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ |
| 92 | #define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ | 92 | #define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ |
| 93 | 93 | ||
| 94 | /* interrupt flags */ | ||
| 95 | #define RTC_IRQF 0x80 /* any of the following is active */ | ||
| 96 | #define RTC_PF 0x40 | ||
| 97 | #define RTC_AF 0x20 | ||
| 98 | #define RTC_UF 0x10 | ||
| 99 | |||
| 94 | #ifdef __KERNEL__ | 100 | #ifdef __KERNEL__ |
| 95 | 101 | ||
| 96 | #include <linux/interrupt.h> | 102 | #include <linux/interrupt.h> |
| 97 | 103 | ||
| 104 | extern int rtc_month_days(unsigned int month, unsigned int year); | ||
| 105 | extern int rtc_valid_tm(struct rtc_time *tm); | ||
| 106 | extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time); | ||
| 107 | extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm); | ||
| 108 | |||
| 109 | #include <linux/device.h> | ||
| 110 | #include <linux/seq_file.h> | ||
| 111 | #include <linux/cdev.h> | ||
| 112 | #include <linux/poll.h> | ||
| 113 | #include <linux/mutex.h> | ||
| 114 | |||
| 115 | extern struct class *rtc_class; | ||
| 116 | |||
| 117 | struct rtc_class_ops { | ||
| 118 | int (*open)(struct device *); | ||
| 119 | void (*release)(struct device *); | ||
| 120 | int (*ioctl)(struct device *, unsigned int, unsigned long); | ||
| 121 | int (*read_time)(struct device *, struct rtc_time *); | ||
| 122 | int (*set_time)(struct device *, struct rtc_time *); | ||
| 123 | int (*read_alarm)(struct device *, struct rtc_wkalrm *); | ||
| 124 | int (*set_alarm)(struct device *, struct rtc_wkalrm *); | ||
| 125 | int (*proc)(struct device *, struct seq_file *); | ||
| 126 | int (*set_mmss)(struct device *, unsigned long secs); | ||
| 127 | int (*irq_set_state)(struct device *, int enabled); | ||
| 128 | int (*irq_set_freq)(struct device *, int freq); | ||
| 129 | int (*read_callback)(struct device *, int data); | ||
| 130 | }; | ||
| 131 | |||
| 132 | #define RTC_DEVICE_NAME_SIZE 20 | ||
| 133 | struct rtc_task; | ||
| 134 | |||
| 135 | struct rtc_device | ||
| 136 | { | ||
| 137 | struct class_device class_dev; | ||
| 138 | struct module *owner; | ||
| 139 | |||
| 140 | int id; | ||
| 141 | char name[RTC_DEVICE_NAME_SIZE]; | ||
| 142 | |||
| 143 | struct rtc_class_ops *ops; | ||
| 144 | struct mutex ops_lock; | ||
| 145 | |||
| 146 | struct class_device *rtc_dev; | ||
| 147 | struct cdev char_dev; | ||
| 148 | struct mutex char_lock; | ||
| 149 | |||
| 150 | unsigned long irq_data; | ||
| 151 | spinlock_t irq_lock; | ||
| 152 | wait_queue_head_t irq_queue; | ||
| 153 | struct fasync_struct *async_queue; | ||
| 154 | |||
| 155 | struct rtc_task *irq_task; | ||
| 156 | spinlock_t irq_task_lock; | ||
| 157 | int irq_freq; | ||
| 158 | }; | ||
| 159 | #define to_rtc_device(d) container_of(d, struct rtc_device, class_dev) | ||
| 160 | |||
| 161 | extern struct rtc_device *rtc_device_register(const char *name, | ||
| 162 | struct device *dev, | ||
| 163 | struct rtc_class_ops *ops, | ||
| 164 | struct module *owner); | ||
| 165 | extern void rtc_device_unregister(struct rtc_device *rdev); | ||
| 166 | extern int rtc_interface_register(struct class_interface *intf); | ||
| 167 | |||
| 168 | extern int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm); | ||
| 169 | extern int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm); | ||
| 170 | extern int rtc_set_mmss(struct class_device *class_dev, unsigned long secs); | ||
| 171 | extern int rtc_read_alarm(struct class_device *class_dev, | ||
| 172 | struct rtc_wkalrm *alrm); | ||
| 173 | extern int rtc_set_alarm(struct class_device *class_dev, | ||
| 174 | struct rtc_wkalrm *alrm); | ||
| 175 | extern void rtc_update_irq(struct class_device *class_dev, | ||
| 176 | unsigned long num, unsigned long events); | ||
| 177 | |||
| 178 | extern struct class_device *rtc_class_open(char *name); | ||
| 179 | extern void rtc_class_close(struct class_device *class_dev); | ||
| 180 | |||
| 181 | extern int rtc_irq_register(struct class_device *class_dev, | ||
| 182 | struct rtc_task *task); | ||
| 183 | extern void rtc_irq_unregister(struct class_device *class_dev, | ||
| 184 | struct rtc_task *task); | ||
| 185 | extern int rtc_irq_set_state(struct class_device *class_dev, | ||
| 186 | struct rtc_task *task, int enabled); | ||
| 187 | extern int rtc_irq_set_freq(struct class_device *class_dev, | ||
| 188 | struct rtc_task *task, int freq); | ||
| 189 | |||
| 98 | typedef struct rtc_task { | 190 | typedef struct rtc_task { |
| 99 | void (*func)(void *private_data); | 191 | void (*func)(void *private_data); |
| 100 | void *private_data; | 192 | void *private_data; |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 036d14d2bf90..20b4f0372e44 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/topology.h> | 35 | #include <linux/topology.h> |
| 36 | #include <linux/seccomp.h> | 36 | #include <linux/seccomp.h> |
| 37 | #include <linux/rcupdate.h> | 37 | #include <linux/rcupdate.h> |
| 38 | #include <linux/futex.h> | ||
| 38 | 39 | ||
| 39 | #include <linux/auxvec.h> /* For AT_VECTOR_SIZE */ | 40 | #include <linux/auxvec.h> /* For AT_VECTOR_SIZE */ |
| 40 | 41 | ||
| @@ -872,6 +873,11 @@ struct task_struct { | |||
| 872 | int cpuset_mems_generation; | 873 | int cpuset_mems_generation; |
| 873 | int cpuset_mem_spread_rotor; | 874 | int cpuset_mem_spread_rotor; |
| 874 | #endif | 875 | #endif |
| 876 | struct robust_list_head __user *robust_list; | ||
| 877 | #ifdef CONFIG_COMPAT | ||
| 878 | struct compat_robust_list_head __user *compat_robust_list; | ||
| 879 | #endif | ||
| 880 | |||
| 875 | atomic_t fs_excl; /* holding fs exclusive resources */ | 881 | atomic_t fs_excl; /* holding fs exclusive resources */ |
| 876 | struct rcu_head rcu; | 882 | struct rcu_head rcu; |
| 877 | }; | 883 | }; |
diff --git a/include/linux/sound.h b/include/linux/sound.h index 72b9af4c3fd4..f63d8342ffa3 100644 --- a/include/linux/sound.h +++ b/include/linux/sound.h | |||
| @@ -30,12 +30,12 @@ | |||
| 30 | */ | 30 | */ |
| 31 | 31 | ||
| 32 | struct device; | 32 | struct device; |
| 33 | extern int register_sound_special(struct file_operations *fops, int unit); | 33 | extern int register_sound_special(const struct file_operations *fops, int unit); |
| 34 | extern int register_sound_special_device(struct file_operations *fops, int unit, struct device *dev); | 34 | extern int register_sound_special_device(const struct file_operations *fops, int unit, struct device *dev); |
| 35 | extern int register_sound_mixer(struct file_operations *fops, int dev); | 35 | extern int register_sound_mixer(const struct file_operations *fops, int dev); |
| 36 | extern int register_sound_midi(struct file_operations *fops, int dev); | 36 | extern int register_sound_midi(const struct file_operations *fops, int dev); |
| 37 | extern int register_sound_dsp(struct file_operations *fops, int dev); | 37 | extern int register_sound_dsp(const struct file_operations *fops, int dev); |
| 38 | extern int register_sound_synth(struct file_operations *fops, int dev); | 38 | extern int register_sound_synth(const struct file_operations *fops, int dev); |
| 39 | 39 | ||
| 40 | extern void unregister_sound_special(int unit); | 40 | extern void unregister_sound_special(int unit); |
| 41 | extern void unregister_sound_mixer(int unit); | 41 | extern void unregister_sound_mixer(int unit); |
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index c4e3ea7cf154..b5612c958cce 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h | |||
| @@ -50,7 +50,7 @@ struct cache_head { | |||
| 50 | time_t last_refresh; /* If CACHE_PENDING, this is when upcall | 50 | time_t last_refresh; /* If CACHE_PENDING, this is when upcall |
| 51 | * was sent, else this is when update was received | 51 | * was sent, else this is when update was received |
| 52 | */ | 52 | */ |
| 53 | atomic_t refcnt; | 53 | struct kref ref; |
| 54 | unsigned long flags; | 54 | unsigned long flags; |
| 55 | }; | 55 | }; |
| 56 | #define CACHE_VALID 0 /* Entry contains valid data */ | 56 | #define CACHE_VALID 0 /* Entry contains valid data */ |
| @@ -68,8 +68,7 @@ struct cache_detail { | |||
| 68 | atomic_t inuse; /* active user-space update or lookup */ | 68 | atomic_t inuse; /* active user-space update or lookup */ |
| 69 | 69 | ||
| 70 | char *name; | 70 | char *name; |
| 71 | void (*cache_put)(struct cache_head *, | 71 | void (*cache_put)(struct kref *); |
| 72 | struct cache_detail*); | ||
| 73 | 72 | ||
| 74 | void (*cache_request)(struct cache_detail *cd, | 73 | void (*cache_request)(struct cache_detail *cd, |
| 75 | struct cache_head *h, | 74 | struct cache_head *h, |
| @@ -81,6 +80,11 @@ struct cache_detail { | |||
| 81 | struct cache_detail *cd, | 80 | struct cache_detail *cd, |
| 82 | struct cache_head *h); | 81 | struct cache_head *h); |
| 83 | 82 | ||
| 83 | struct cache_head * (*alloc)(void); | ||
| 84 | int (*match)(struct cache_head *orig, struct cache_head *new); | ||
| 85 | void (*init)(struct cache_head *orig, struct cache_head *new); | ||
| 86 | void (*update)(struct cache_head *orig, struct cache_head *new); | ||
| 87 | |||
| 84 | /* fields below this comment are for internal use | 88 | /* fields below this comment are for internal use |
| 85 | * and should not be touched by cache owners | 89 | * and should not be touched by cache owners |
| 86 | */ | 90 | */ |
| @@ -123,126 +127,14 @@ struct cache_deferred_req { | |||
| 123 | int too_many); | 127 | int too_many); |
| 124 | }; | 128 | }; |
| 125 | 129 | ||
| 126 | /* | ||
| 127 | * just like a template in C++, this macro does cache lookup | ||
| 128 | * for us. | ||
| 129 | * The function is passed some sort of HANDLE from which a cache_detail | ||
| 130 | * structure can be determined (via SETUP, DETAIL), a template | ||
| 131 | * cache entry (type RTN*), and a "set" flag. Using the HASHFN and the | ||
| 132 | * TEST, the function will try to find a matching cache entry in the cache. | ||
| 133 | * If "set" == 0 : | ||
| 134 | * If an entry is found, it is returned | ||
| 135 | * If no entry is found, a new non-VALID entry is created. | ||
| 136 | * If "set" == 1 and INPLACE == 0 : | ||
| 137 | * If no entry is found a new one is inserted with data from "template" | ||
| 138 | * If a non-CACHE_VALID entry is found, it is updated from template using UPDATE | ||
| 139 | * If a CACHE_VALID entry is found, a new entry is swapped in with data | ||
| 140 | * from "template" | ||
| 141 | * If set == 1, and INPLACE == 1 : | ||
| 142 | * As above, except that if a CACHE_VALID entry is found, we UPDATE in place | ||
| 143 | * instead of swapping in a new entry. | ||
| 144 | * | ||
| 145 | * If the passed handle has the CACHE_NEGATIVE flag set, then UPDATE is not | ||
| 146 | * run but insteead CACHE_NEGATIVE is set in any new item. | ||
| 147 | 130 | ||
| 148 | * In any case, the new entry is returned with a reference count. | 131 | extern struct cache_head * |
| 149 | * | 132 | sunrpc_cache_lookup(struct cache_detail *detail, |
| 150 | * | 133 | struct cache_head *key, int hash); |
| 151 | * RTN is a struct type for a cache entry | 134 | extern struct cache_head * |
| 152 | * MEMBER is the member of the cache which is cache_head, which must be first | 135 | sunrpc_cache_update(struct cache_detail *detail, |
| 153 | * FNAME is the name for the function | 136 | struct cache_head *new, struct cache_head *old, int hash); |
| 154 | * ARGS are arguments to function and must contain RTN *item, int set. May | ||
| 155 | * also contain something to be usedby SETUP or DETAIL to find cache_detail. | ||
| 156 | * SETUP locates the cache detail and makes it available as... | ||
| 157 | * DETAIL identifies the cache detail, possibly set up by SETUP | ||
| 158 | * HASHFN returns a hash value of the cache entry "item" | ||
| 159 | * TEST tests if "tmp" matches "item" | ||
| 160 | * INIT copies key information from "item" to "new" | ||
| 161 | * UPDATE copies content information from "item" to "tmp" | ||
| 162 | * INPLACE is true if updates can happen inplace rather than allocating a new structure | ||
| 163 | * | ||
| 164 | * WARNING: any substantial changes to this must be reflected in | ||
| 165 | * net/sunrpc/svcauth.c(auth_domain_lookup) | ||
| 166 | * which is a similar routine that is open-coded. | ||
| 167 | */ | ||
| 168 | #define DefineCacheLookup(RTN,MEMBER,FNAME,ARGS,SETUP,DETAIL,HASHFN,TEST,INIT,UPDATE,INPLACE) \ | ||
| 169 | RTN *FNAME ARGS \ | ||
| 170 | { \ | ||
| 171 | RTN *tmp, *new=NULL; \ | ||
| 172 | struct cache_head **hp, **head; \ | ||
| 173 | SETUP; \ | ||
| 174 | head = &(DETAIL)->hash_table[HASHFN]; \ | ||
| 175 | retry: \ | ||
| 176 | if (set||new) write_lock(&(DETAIL)->hash_lock); \ | ||
| 177 | else read_lock(&(DETAIL)->hash_lock); \ | ||
| 178 | for(hp=head; *hp != NULL; hp = &tmp->MEMBER.next) { \ | ||
| 179 | tmp = container_of(*hp, RTN, MEMBER); \ | ||
| 180 | if (TEST) { /* found a match */ \ | ||
| 181 | \ | ||
| 182 | if (set && !INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags) && !new) \ | ||
| 183 | break; \ | ||
| 184 | \ | ||
| 185 | if (new) \ | ||
| 186 | {INIT;} \ | ||
| 187 | if (set) { \ | ||
| 188 | if (!INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags))\ | ||
| 189 | { /* need to swap in new */ \ | ||
| 190 | RTN *t2; \ | ||
| 191 | \ | ||
| 192 | new->MEMBER.next = tmp->MEMBER.next; \ | ||
| 193 | *hp = &new->MEMBER; \ | ||
| 194 | tmp->MEMBER.next = NULL; \ | ||
| 195 | t2 = tmp; tmp = new; new = t2; \ | ||
| 196 | } \ | ||
| 197 | if (test_bit(CACHE_NEGATIVE, &item->MEMBER.flags)) \ | ||
| 198 | set_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags); \ | ||
| 199 | else { \ | ||
| 200 | UPDATE; \ | ||
| 201 | clear_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags); \ | ||
| 202 | } \ | ||
| 203 | } \ | ||
| 204 | cache_get(&tmp->MEMBER); \ | ||
| 205 | if (set||new) write_unlock(&(DETAIL)->hash_lock); \ | ||
| 206 | else read_unlock(&(DETAIL)->hash_lock); \ | ||
| 207 | if (set) \ | ||
| 208 | cache_fresh(DETAIL, &tmp->MEMBER, item->MEMBER.expiry_time); \ | ||
| 209 | if (set && !INPLACE && new) cache_fresh(DETAIL, &new->MEMBER, 0); \ | ||
| 210 | if (new) (DETAIL)->cache_put(&new->MEMBER, DETAIL); \ | ||
| 211 | return tmp; \ | ||
| 212 | } \ | ||
| 213 | } \ | ||
| 214 | /* Didn't find anything */ \ | ||
| 215 | if (new) { \ | ||
| 216 | INIT; \ | ||
| 217 | new->MEMBER.next = *head; \ | ||
| 218 | *head = &new->MEMBER; \ | ||
| 219 | (DETAIL)->entries ++; \ | ||
| 220 | cache_get(&new->MEMBER); \ | ||
| 221 | if (set) { \ | ||
| 222 | tmp = new; \ | ||
| 223 | if (test_bit(CACHE_NEGATIVE, &item->MEMBER.flags)) \ | ||
| 224 | set_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags); \ | ||
| 225 | else {UPDATE;} \ | ||
| 226 | } \ | ||
| 227 | } \ | ||
| 228 | if (set||new) write_unlock(&(DETAIL)->hash_lock); \ | ||
| 229 | else read_unlock(&(DETAIL)->hash_lock); \ | ||
| 230 | if (new && set) \ | ||
| 231 | cache_fresh(DETAIL, &new->MEMBER, item->MEMBER.expiry_time); \ | ||
| 232 | if (new) \ | ||
| 233 | return new; \ | ||
| 234 | new = kmalloc(sizeof(*new), GFP_KERNEL); \ | ||
| 235 | if (new) { \ | ||
| 236 | cache_init(&new->MEMBER); \ | ||
| 237 | goto retry; \ | ||
| 238 | } \ | ||
| 239 | return NULL; \ | ||
| 240 | } | ||
| 241 | 137 | ||
| 242 | #define DefineSimpleCacheLookup(STRUCT,INPLACE) \ | ||
| 243 | DefineCacheLookup(struct STRUCT, h, STRUCT##_lookup, (struct STRUCT *item, int set), /*no setup */, \ | ||
| 244 | & STRUCT##_cache, STRUCT##_hash(item), STRUCT##_match(item, tmp),\ | ||
| 245 | STRUCT##_init(new, item), STRUCT##_update(tmp, item),INPLACE) | ||
| 246 | 138 | ||
| 247 | #define cache_for_each(pos, detail, index, member) \ | 139 | #define cache_for_each(pos, detail, index, member) \ |
| 248 | for (({read_lock(&(detail)->hash_lock); index = (detail)->hash_size;}) ; \ | 140 | for (({read_lock(&(detail)->hash_lock); index = (detail)->hash_size;}) ; \ |
| @@ -258,22 +150,19 @@ extern void cache_clean_deferred(void *owner); | |||
| 258 | 150 | ||
| 259 | static inline struct cache_head *cache_get(struct cache_head *h) | 151 | static inline struct cache_head *cache_get(struct cache_head *h) |
| 260 | { | 152 | { |
| 261 | atomic_inc(&h->refcnt); | 153 | kref_get(&h->ref); |
| 262 | return h; | 154 | return h; |
| 263 | } | 155 | } |
| 264 | 156 | ||
| 265 | 157 | ||
| 266 | static inline int cache_put(struct cache_head *h, struct cache_detail *cd) | 158 | static inline void cache_put(struct cache_head *h, struct cache_detail *cd) |
| 267 | { | 159 | { |
| 268 | if (atomic_read(&h->refcnt) <= 2 && | 160 | if (atomic_read(&h->ref.refcount) <= 2 && |
| 269 | h->expiry_time < cd->nextcheck) | 161 | h->expiry_time < cd->nextcheck) |
| 270 | cd->nextcheck = h->expiry_time; | 162 | cd->nextcheck = h->expiry_time; |
| 271 | return atomic_dec_and_test(&h->refcnt); | 163 | kref_put(&h->ref, cd->cache_put); |
| 272 | } | 164 | } |
| 273 | 165 | ||
| 274 | extern void cache_init(struct cache_head *h); | ||
| 275 | extern void cache_fresh(struct cache_detail *detail, | ||
| 276 | struct cache_head *head, time_t expiry); | ||
| 277 | extern int cache_check(struct cache_detail *detail, | 166 | extern int cache_check(struct cache_detail *detail, |
| 278 | struct cache_head *h, struct cache_req *rqstp); | 167 | struct cache_head *h, struct cache_req *rqstp); |
| 279 | extern void cache_flush(void); | 168 | extern void cache_flush(void); |
diff --git a/include/linux/sunrpc/stats.h b/include/linux/sunrpc/stats.h index 0d6ed3c8bdc4..d93c24b47f3f 100644 --- a/include/linux/sunrpc/stats.h +++ b/include/linux/sunrpc/stats.h | |||
| @@ -50,7 +50,7 @@ struct proc_dir_entry * rpc_proc_register(struct rpc_stat *); | |||
| 50 | void rpc_proc_unregister(const char *); | 50 | void rpc_proc_unregister(const char *); |
| 51 | void rpc_proc_zero(struct rpc_program *); | 51 | void rpc_proc_zero(struct rpc_program *); |
| 52 | struct proc_dir_entry * svc_proc_register(struct svc_stat *, | 52 | struct proc_dir_entry * svc_proc_register(struct svc_stat *, |
| 53 | struct file_operations *); | 53 | const struct file_operations *); |
| 54 | void svc_proc_unregister(const char *); | 54 | void svc_proc_unregister(const char *); |
| 55 | 55 | ||
| 56 | void svc_seq_show(struct seq_file *, | 56 | void svc_seq_show(struct seq_file *, |
| @@ -65,7 +65,7 @@ static inline void rpc_proc_unregister(const char *p) {} | |||
| 65 | static inline void rpc_proc_zero(struct rpc_program *p) {} | 65 | static inline void rpc_proc_zero(struct rpc_program *p) {} |
| 66 | 66 | ||
| 67 | static inline struct proc_dir_entry *svc_proc_register(struct svc_stat *s, | 67 | static inline struct proc_dir_entry *svc_proc_register(struct svc_stat *s, |
| 68 | struct file_operations *f) { return NULL; } | 68 | const struct file_operations *f) { return NULL; } |
| 69 | static inline void svc_proc_unregister(const char *p) {} | 69 | static inline void svc_proc_unregister(const char *p) {} |
| 70 | 70 | ||
| 71 | static inline void svc_seq_show(struct seq_file *seq, | 71 | static inline void svc_seq_show(struct seq_file *seq, |
diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h index c119ce7cbd22..2fe2087edd66 100644 --- a/include/linux/sunrpc/svcauth.h +++ b/include/linux/sunrpc/svcauth.h | |||
| @@ -45,9 +45,10 @@ struct svc_rqst; /* forward decl */ | |||
| 45 | * of ip addresses to the given client. | 45 | * of ip addresses to the given client. |
| 46 | */ | 46 | */ |
| 47 | struct auth_domain { | 47 | struct auth_domain { |
| 48 | struct cache_head h; | 48 | struct kref ref; |
| 49 | struct hlist_node hash; | ||
| 49 | char *name; | 50 | char *name; |
| 50 | int flavour; | 51 | struct auth_ops *flavour; |
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| 53 | /* | 54 | /* |
| @@ -86,6 +87,9 @@ struct auth_domain { | |||
| 86 | * | 87 | * |
| 87 | * domain_release() | 88 | * domain_release() |
| 88 | * This call releases a domain. | 89 | * This call releases a domain. |
| 90 | * set_client() | ||
| 91 | * Givens a pending request (struct svc_rqst), finds and assigns | ||
| 92 | * an appropriate 'auth_domain' as the client. | ||
| 89 | */ | 93 | */ |
| 90 | struct auth_ops { | 94 | struct auth_ops { |
| 91 | char * name; | 95 | char * name; |
| @@ -117,7 +121,7 @@ extern void svc_auth_unregister(rpc_authflavor_t flavor); | |||
| 117 | extern struct auth_domain *unix_domain_find(char *name); | 121 | extern struct auth_domain *unix_domain_find(char *name); |
| 118 | extern void auth_domain_put(struct auth_domain *item); | 122 | extern void auth_domain_put(struct auth_domain *item); |
| 119 | extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom); | 123 | extern int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom); |
| 120 | extern struct auth_domain *auth_domain_lookup(struct auth_domain *item, int set); | 124 | extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new); |
| 121 | extern struct auth_domain *auth_domain_find(char *name); | 125 | extern struct auth_domain *auth_domain_find(char *name); |
| 122 | extern struct auth_domain *auth_unix_lookup(struct in_addr addr); | 126 | extern struct auth_domain *auth_unix_lookup(struct in_addr addr); |
| 123 | extern int auth_unix_forget_old(struct auth_domain *dom); | 127 | extern int auth_unix_forget_old(struct auth_domain *dom); |
| @@ -160,8 +164,6 @@ static inline unsigned long hash_mem(char *buf, int length, int bits) | |||
| 160 | return hash >> (BITS_PER_LONG - bits); | 164 | return hash >> (BITS_PER_LONG - bits); |
| 161 | } | 165 | } |
| 162 | 166 | ||
| 163 | extern struct cache_detail auth_domain_cache, ip_map_cache; | ||
| 164 | |||
| 165 | #endif /* __KERNEL__ */ | 167 | #endif /* __KERNEL__ */ |
| 166 | 168 | ||
| 167 | #endif /* _LINUX_SUNRPC_SVCAUTH_H_ */ | 169 | #endif /* _LINUX_SUNRPC_SVCAUTH_H_ */ |
diff --git a/include/linux/synclink.h b/include/linux/synclink.h index 1b7cd8d1a71b..2993302f7923 100644 --- a/include/linux/synclink.h +++ b/include/linux/synclink.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * SyncLink Multiprotocol Serial Adapter Driver | 2 | * SyncLink Multiprotocol Serial Adapter Driver |
| 3 | * | 3 | * |
| 4 | * $Id: synclink.h,v 3.10 2005/11/08 19:50:54 paulkf Exp $ | 4 | * $Id: synclink.h,v 3.11 2006/02/06 21:20:29 paulkf Exp $ |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 1998-2000 by Microgate Corporation | 6 | * Copyright (C) 1998-2000 by Microgate Corporation |
| 7 | * | 7 | * |
| @@ -221,6 +221,12 @@ struct mgsl_icount { | |||
| 221 | __u32 rxidle; | 221 | __u32 rxidle; |
| 222 | }; | 222 | }; |
| 223 | 223 | ||
| 224 | struct gpio_desc { | ||
| 225 | __u32 state; | ||
| 226 | __u32 smask; | ||
| 227 | __u32 dir; | ||
| 228 | __u32 dmask; | ||
| 229 | }; | ||
| 224 | 230 | ||
| 225 | #define DEBUG_LEVEL_DATA 1 | 231 | #define DEBUG_LEVEL_DATA 1 |
| 226 | #define DEBUG_LEVEL_ERROR 2 | 232 | #define DEBUG_LEVEL_ERROR 2 |
| @@ -276,5 +282,8 @@ struct mgsl_icount { | |||
| 276 | #define MGSL_IOCLOOPTXDONE _IO(MGSL_MAGIC_IOC,9) | 282 | #define MGSL_IOCLOOPTXDONE _IO(MGSL_MAGIC_IOC,9) |
| 277 | #define MGSL_IOCSIF _IO(MGSL_MAGIC_IOC,10) | 283 | #define MGSL_IOCSIF _IO(MGSL_MAGIC_IOC,10) |
| 278 | #define MGSL_IOCGIF _IO(MGSL_MAGIC_IOC,11) | 284 | #define MGSL_IOCGIF _IO(MGSL_MAGIC_IOC,11) |
| 285 | #define MGSL_IOCSGPIO _IOW(MGSL_MAGIC_IOC,16,struct gpio_desc) | ||
| 286 | #define MGSL_IOCGGPIO _IOR(MGSL_MAGIC_IOC,17,struct gpio_desc) | ||
| 287 | #define MGSL_IOCWAITGPIO _IOWR(MGSL_MAGIC_IOC,18,struct gpio_desc) | ||
| 279 | 288 | ||
| 280 | #endif /* _SYNCLINK_H_ */ | 289 | #endif /* _SYNCLINK_H_ */ |
diff --git a/include/linux/threads.h b/include/linux/threads.h index b59738ac6197..e646bcdf2614 100644 --- a/include/linux/threads.h +++ b/include/linux/threads.h | |||
| @@ -28,7 +28,8 @@ | |||
| 28 | #define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000) | 28 | #define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000) |
| 29 | 29 | ||
| 30 | /* | 30 | /* |
| 31 | * A maximum of 4 million PIDs should be enough for a while: | 31 | * A maximum of 4 million PIDs should be enough for a while. |
| 32 | * [NOTE: PID/TIDs are limited to 2^29 ~= 500+ million, see futex.h.] | ||
| 32 | */ | 33 | */ |
| 33 | #define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \ | 34 | #define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \ |
| 34 | (sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT)) | 35 | (sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT)) |
diff --git a/include/linux/topology.h b/include/linux/topology.h index e8eb0040ce3a..a305ae2e44b6 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h | |||
| @@ -164,6 +164,15 @@ | |||
| 164 | .nr_balance_failed = 0, \ | 164 | .nr_balance_failed = 0, \ |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | #ifdef CONFIG_SCHED_MC | ||
| 168 | #ifndef SD_MC_INIT | ||
| 169 | /* for now its same as SD_CPU_INIT. | ||
| 170 | * TBD: Tune Domain parameters! | ||
| 171 | */ | ||
| 172 | #define SD_MC_INIT SD_CPU_INIT | ||
| 173 | #endif | ||
| 174 | #endif | ||
| 175 | |||
| 167 | #ifdef CONFIG_NUMA | 176 | #ifdef CONFIG_NUMA |
| 168 | #ifndef SD_NODE_INIT | 177 | #ifndef SD_NODE_INIT |
| 169 | #error Please define an appropriate SD_NODE_INIT in include/asm/topology.h!!! | 178 | #error Please define an appropriate SD_NODE_INIT in include/asm/topology.h!!! |
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h index b0ffe4356e5a..843aeaaa79d4 100644 --- a/include/linux/ufs_fs.h +++ b/include/linux/ufs_fs.h | |||
| @@ -895,7 +895,7 @@ extern void ufs_set_link(struct inode *, struct ufs_dir_entry *, struct buffer_h | |||
| 895 | 895 | ||
| 896 | /* file.c */ | 896 | /* file.c */ |
| 897 | extern struct inode_operations ufs_file_inode_operations; | 897 | extern struct inode_operations ufs_file_inode_operations; |
| 898 | extern struct file_operations ufs_file_operations; | 898 | extern const struct file_operations ufs_file_operations; |
| 899 | 899 | ||
| 900 | extern struct address_space_operations ufs_aops; | 900 | extern struct address_space_operations ufs_aops; |
| 901 | 901 | ||
| @@ -915,7 +915,7 @@ extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *); | |||
| 915 | extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create); | 915 | extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create); |
| 916 | 916 | ||
| 917 | /* namei.c */ | 917 | /* namei.c */ |
| 918 | extern struct file_operations ufs_dir_operations; | 918 | extern const struct file_operations ufs_dir_operations; |
| 919 | 919 | ||
| 920 | /* super.c */ | 920 | /* super.c */ |
| 921 | extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); | 921 | extern void ufs_warning (struct super_block *, const char *, const char *, ...) __attribute__ ((format (printf, 3, 4))); |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 130d125fda12..e34e5e3dce52 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
| @@ -615,7 +615,7 @@ extern struct bus_type usb_bus_type; | |||
| 615 | */ | 615 | */ |
| 616 | struct usb_class_driver { | 616 | struct usb_class_driver { |
| 617 | char *name; | 617 | char *name; |
| 618 | struct file_operations *fops; | 618 | const struct file_operations *fops; |
| 619 | int minor_base; | 619 | int minor_base; |
| 620 | }; | 620 | }; |
| 621 | 621 | ||
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 2275bfec5b68..af2d6155d3fe 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h | |||
| @@ -75,7 +75,7 @@ struct video_device | |||
| 75 | int minor; | 75 | int minor; |
| 76 | 76 | ||
| 77 | /* device ops + callbacks */ | 77 | /* device ops + callbacks */ |
| 78 | struct file_operations *fops; | 78 | const struct file_operations *fops; |
| 79 | void (*release)(struct video_device *vfd); | 79 | void (*release)(struct video_device *vfd); |
| 80 | 80 | ||
| 81 | 81 | ||
diff --git a/include/linux/x1205.h b/include/linux/x1205.h deleted file mode 100644 index 64fd3af894a5..000000000000 --- a/include/linux/x1205.h +++ /dev/null | |||
| @@ -1,31 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * x1205.h - defines for drivers/i2c/chips/x1205.c | ||
| 3 | * Copyright 2004 Karen Spearel | ||
| 4 | * Copyright 2005 Alessandro Zummo | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef __LINUX_X1205_H__ | ||
| 13 | #define __LINUX_X1205_H__ | ||
| 14 | |||
| 15 | /* commands */ | ||
| 16 | |||
| 17 | #define X1205_CMD_GETDATETIME 0 | ||
| 18 | #define X1205_CMD_SETTIME 1 | ||
| 19 | #define X1205_CMD_SETDATETIME 2 | ||
| 20 | #define X1205_CMD_GETALARM 3 | ||
| 21 | #define X1205_CMD_SETALARM 4 | ||
| 22 | #define X1205_CMD_GETDTRIM 5 | ||
| 23 | #define X1205_CMD_SETDTRIM 6 | ||
| 24 | #define X1205_CMD_GETATRIM 7 | ||
| 25 | #define X1205_CMD_SETATRIM 8 | ||
| 26 | |||
| 27 | extern int x1205_do_command(unsigned int cmd, void *arg); | ||
| 28 | extern int x1205_direct_attach(int adapter_id, | ||
| 29 | struct i2c_client_address_data *address_data); | ||
| 30 | |||
| 31 | #endif /* __LINUX_X1205_H__ */ | ||
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index b6f0905a4ee2..916013ca4a5c 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
| @@ -300,29 +300,30 @@ DECLARE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); | |||
| 300 | 300 | ||
| 301 | #define CONNTRACK_ECACHE(x) (__get_cpu_var(nf_conntrack_ecache).x) | 301 | #define CONNTRACK_ECACHE(x) (__get_cpu_var(nf_conntrack_ecache).x) |
| 302 | 302 | ||
| 303 | extern struct notifier_block *nf_conntrack_chain; | 303 | extern struct atomic_notifier_head nf_conntrack_chain; |
| 304 | extern struct notifier_block *nf_conntrack_expect_chain; | 304 | extern struct atomic_notifier_head nf_conntrack_expect_chain; |
| 305 | 305 | ||
| 306 | static inline int nf_conntrack_register_notifier(struct notifier_block *nb) | 306 | static inline int nf_conntrack_register_notifier(struct notifier_block *nb) |
| 307 | { | 307 | { |
| 308 | return notifier_chain_register(&nf_conntrack_chain, nb); | 308 | return atomic_notifier_chain_register(&nf_conntrack_chain, nb); |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb) | 311 | static inline int nf_conntrack_unregister_notifier(struct notifier_block *nb) |
| 312 | { | 312 | { |
| 313 | return notifier_chain_unregister(&nf_conntrack_chain, nb); | 313 | return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb); |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | static inline int | 316 | static inline int |
| 317 | nf_conntrack_expect_register_notifier(struct notifier_block *nb) | 317 | nf_conntrack_expect_register_notifier(struct notifier_block *nb) |
| 318 | { | 318 | { |
| 319 | return notifier_chain_register(&nf_conntrack_expect_chain, nb); | 319 | return atomic_notifier_chain_register(&nf_conntrack_expect_chain, nb); |
| 320 | } | 320 | } |
| 321 | 321 | ||
| 322 | static inline int | 322 | static inline int |
| 323 | nf_conntrack_expect_unregister_notifier(struct notifier_block *nb) | 323 | nf_conntrack_expect_unregister_notifier(struct notifier_block *nb) |
| 324 | { | 324 | { |
| 325 | return notifier_chain_unregister(&nf_conntrack_expect_chain, nb); | 325 | return atomic_notifier_chain_unregister(&nf_conntrack_expect_chain, |
| 326 | nb); | ||
| 326 | } | 327 | } |
| 327 | 328 | ||
| 328 | extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); | 329 | extern void nf_ct_deliver_cached_events(const struct nf_conn *ct); |
| @@ -347,14 +348,14 @@ static inline void nf_conntrack_event(enum ip_conntrack_events event, | |||
| 347 | struct nf_conn *ct) | 348 | struct nf_conn *ct) |
| 348 | { | 349 | { |
| 349 | if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) | 350 | if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) |
| 350 | notifier_call_chain(&nf_conntrack_chain, event, ct); | 351 | atomic_notifier_call_chain(&nf_conntrack_chain, event, ct); |
| 351 | } | 352 | } |
| 352 | 353 | ||
| 353 | static inline void | 354 | static inline void |
| 354 | nf_conntrack_expect_event(enum ip_conntrack_expect_events event, | 355 | nf_conntrack_expect_event(enum ip_conntrack_expect_events event, |
| 355 | struct nf_conntrack_expect *exp) | 356 | struct nf_conntrack_expect *exp) |
| 356 | { | 357 | { |
| 357 | notifier_call_chain(&nf_conntrack_expect_chain, event, exp); | 358 | atomic_notifier_call_chain(&nf_conntrack_expect_chain, event, exp); |
| 358 | } | 359 | } |
| 359 | #else /* CONFIG_NF_CONNTRACK_EVENTS */ | 360 | #else /* CONFIG_NF_CONNTRACK_EVENTS */ |
| 360 | static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, | 361 | static inline void nf_conntrack_event_cache(enum ip_conntrack_events event, |
diff --git a/include/net/request_sock.h b/include/net/request_sock.h index 11641c9384f7..c5d7f920c352 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h | |||
| @@ -145,7 +145,7 @@ static inline struct request_sock * | |||
| 145 | { | 145 | { |
| 146 | struct request_sock *req = queue->rskq_accept_head; | 146 | struct request_sock *req = queue->rskq_accept_head; |
| 147 | 147 | ||
| 148 | queue->rskq_accept_head = queue->rskq_accept_head = NULL; | 148 | queue->rskq_accept_head = NULL; |
| 149 | return req; | 149 | return req; |
| 150 | } | 150 | } |
| 151 | 151 | ||
diff --git a/include/sound/core.h b/include/sound/core.h index 144bdc2f217f..7f32c12b4a0a 100644 --- a/include/sound/core.h +++ b/include/sound/core.h | |||
| @@ -186,7 +186,7 @@ struct snd_minor { | |||
| 186 | int type; /* SNDRV_DEVICE_TYPE_XXX */ | 186 | int type; /* SNDRV_DEVICE_TYPE_XXX */ |
| 187 | int card; /* card number */ | 187 | int card; /* card number */ |
| 188 | int device; /* device number */ | 188 | int device; /* device number */ |
| 189 | struct file_operations *f_ops; /* file operations */ | 189 | const struct file_operations *f_ops; /* file operations */ |
| 190 | void *private_data; /* private data for f_ops->open */ | 190 | void *private_data; /* private data for f_ops->open */ |
| 191 | char name[0]; /* device name (keep at the end of | 191 | char name[0]; /* device name (keep at the end of |
| 192 | structure) */ | 192 | structure) */ |
| @@ -200,14 +200,14 @@ extern int snd_ecards_limit; | |||
| 200 | void snd_request_card(int card); | 200 | void snd_request_card(int card); |
| 201 | 201 | ||
| 202 | int snd_register_device(int type, struct snd_card *card, int dev, | 202 | int snd_register_device(int type, struct snd_card *card, int dev, |
| 203 | struct file_operations *f_ops, void *private_data, | 203 | const struct file_operations *f_ops, void *private_data, |
| 204 | const char *name); | 204 | const char *name); |
| 205 | int snd_unregister_device(int type, struct snd_card *card, int dev); | 205 | int snd_unregister_device(int type, struct snd_card *card, int dev); |
| 206 | void *snd_lookup_minor_data(unsigned int minor, int type); | 206 | void *snd_lookup_minor_data(unsigned int minor, int type); |
| 207 | 207 | ||
| 208 | #ifdef CONFIG_SND_OSSEMUL | 208 | #ifdef CONFIG_SND_OSSEMUL |
| 209 | int snd_register_oss_device(int type, struct snd_card *card, int dev, | 209 | int snd_register_oss_device(int type, struct snd_card *card, int dev, |
| 210 | struct file_operations *f_ops, void *private_data, | 210 | const struct file_operations *f_ops, void *private_data, |
| 211 | const char *name); | 211 | const char *name); |
| 212 | int snd_unregister_oss_device(int type, struct snd_card *card, int dev); | 212 | int snd_unregister_oss_device(int type, struct snd_card *card, int dev); |
| 213 | void *snd_lookup_oss_minor_data(unsigned int minor, int type); | 213 | void *snd_lookup_oss_minor_data(unsigned int minor, int type); |
diff --git a/init/main.c b/init/main.c index 64466ea1984c..4a2f0898dda1 100644 --- a/init/main.c +++ b/init/main.c | |||
| @@ -341,7 +341,7 @@ static void __init setup_per_cpu_areas(void) | |||
| 341 | #endif | 341 | #endif |
| 342 | ptr = alloc_bootmem(size * nr_possible_cpus); | 342 | ptr = alloc_bootmem(size * nr_possible_cpus); |
| 343 | 343 | ||
| 344 | for_each_cpu(i) { | 344 | for_each_possible_cpu(i) { |
| 345 | __per_cpu_offset[i] = ptr - __per_cpu_start; | 345 | __per_cpu_offset[i] = ptr - __per_cpu_start; |
| 346 | memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); | 346 | memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); |
| 347 | ptr += size; | 347 | ptr += size; |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 532ec3bf18d6..41ecbd440fed 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
| @@ -762,7 +762,7 @@ out_unlock: | |||
| 762 | * The receiver accepts the message and returns without grabbing the queue | 762 | * The receiver accepts the message and returns without grabbing the queue |
| 763 | * spinlock. Therefore an intermediate STATE_PENDING state and memory barriers | 763 | * spinlock. Therefore an intermediate STATE_PENDING state and memory barriers |
| 764 | * are necessary. The same algorithm is used for sysv semaphores, see | 764 | * are necessary. The same algorithm is used for sysv semaphores, see |
| 765 | * ipc/sem.c fore more details. | 765 | * ipc/sem.c for more details. |
| 766 | * | 766 | * |
| 767 | * The same algorithm is used for senders. | 767 | * The same algorithm is used for senders. |
| 768 | */ | 768 | */ |
diff --git a/kernel/Makefile b/kernel/Makefile index ff1c11dc12cf..58908f9d156a 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
| @@ -12,6 +12,9 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \ | |||
| 12 | 12 | ||
| 13 | obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o | 13 | obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o |
| 14 | obj-$(CONFIG_FUTEX) += futex.o | 14 | obj-$(CONFIG_FUTEX) += futex.o |
| 15 | ifeq ($(CONFIG_COMPAT),y) | ||
| 16 | obj-$(CONFIG_FUTEX) += futex_compat.o | ||
| 17 | endif | ||
| 15 | obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o | 18 | obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o |
| 16 | obj-$(CONFIG_SMP) += cpu.o spinlock.o | 19 | obj-$(CONFIG_SMP) += cpu.o spinlock.o |
| 17 | obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o | 20 | obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o |
diff --git a/kernel/compat.c b/kernel/compat.c index b9bdd1271f44..c1601a84f8d8 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <linux/time.h> | 17 | #include <linux/time.h> |
| 18 | #include <linux/signal.h> | 18 | #include <linux/signal.h> |
| 19 | #include <linux/sched.h> /* for MAX_SCHEDULE_TIMEOUT */ | 19 | #include <linux/sched.h> /* for MAX_SCHEDULE_TIMEOUT */ |
| 20 | #include <linux/futex.h> /* for FUTEX_WAIT */ | ||
| 21 | #include <linux/syscalls.h> | 20 | #include <linux/syscalls.h> |
| 22 | #include <linux/unistd.h> | 21 | #include <linux/unistd.h> |
| 23 | #include <linux/security.h> | 22 | #include <linux/security.h> |
| @@ -239,28 +238,6 @@ asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set, | |||
| 239 | return ret; | 238 | return ret; |
| 240 | } | 239 | } |
| 241 | 240 | ||
| 242 | #ifdef CONFIG_FUTEX | ||
| 243 | asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, int val, | ||
| 244 | struct compat_timespec __user *utime, u32 __user *uaddr2, | ||
| 245 | int val3) | ||
| 246 | { | ||
| 247 | struct timespec t; | ||
| 248 | unsigned long timeout = MAX_SCHEDULE_TIMEOUT; | ||
| 249 | int val2 = 0; | ||
| 250 | |||
| 251 | if ((op == FUTEX_WAIT) && utime) { | ||
| 252 | if (get_compat_timespec(&t, utime)) | ||
| 253 | return -EFAULT; | ||
| 254 | timeout = timespec_to_jiffies(&t) + 1; | ||
| 255 | } | ||
| 256 | if (op >= FUTEX_REQUEUE) | ||
| 257 | val2 = (int) (unsigned long) utime; | ||
| 258 | |||
| 259 | return do_futex((unsigned long)uaddr, op, val, timeout, | ||
| 260 | (unsigned long)uaddr2, val2, val3); | ||
| 261 | } | ||
| 262 | #endif | ||
| 263 | |||
| 264 | asmlinkage long compat_sys_setrlimit(unsigned int resource, | 241 | asmlinkage long compat_sys_setrlimit(unsigned int resource, |
| 265 | struct compat_rlimit __user *rlim) | 242 | struct compat_rlimit __user *rlim) |
| 266 | { | 243 | { |
diff --git a/kernel/cpu.c b/kernel/cpu.c index 8be22bd80933..fe2b8d0bfe4c 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | /* This protects CPUs going up and down... */ | 18 | /* This protects CPUs going up and down... */ |
| 19 | static DECLARE_MUTEX(cpucontrol); | 19 | static DECLARE_MUTEX(cpucontrol); |
| 20 | 20 | ||
| 21 | static struct notifier_block *cpu_chain; | 21 | static BLOCKING_NOTIFIER_HEAD(cpu_chain); |
| 22 | 22 | ||
| 23 | #ifdef CONFIG_HOTPLUG_CPU | 23 | #ifdef CONFIG_HOTPLUG_CPU |
| 24 | static struct task_struct *lock_cpu_hotplug_owner; | 24 | static struct task_struct *lock_cpu_hotplug_owner; |
| @@ -71,21 +71,13 @@ EXPORT_SYMBOL_GPL(lock_cpu_hotplug_interruptible); | |||
| 71 | /* Need to know about CPUs going up/down? */ | 71 | /* Need to know about CPUs going up/down? */ |
| 72 | int register_cpu_notifier(struct notifier_block *nb) | 72 | int register_cpu_notifier(struct notifier_block *nb) |
| 73 | { | 73 | { |
| 74 | int ret; | 74 | return blocking_notifier_chain_register(&cpu_chain, nb); |
| 75 | |||
| 76 | if ((ret = lock_cpu_hotplug_interruptible()) != 0) | ||
| 77 | return ret; | ||
| 78 | ret = notifier_chain_register(&cpu_chain, nb); | ||
| 79 | unlock_cpu_hotplug(); | ||
| 80 | return ret; | ||
| 81 | } | 75 | } |
| 82 | EXPORT_SYMBOL(register_cpu_notifier); | 76 | EXPORT_SYMBOL(register_cpu_notifier); |
| 83 | 77 | ||
| 84 | void unregister_cpu_notifier(struct notifier_block *nb) | 78 | void unregister_cpu_notifier(struct notifier_block *nb) |
| 85 | { | 79 | { |
| 86 | lock_cpu_hotplug(); | 80 | blocking_notifier_chain_unregister(&cpu_chain, nb); |
| 87 | notifier_chain_unregister(&cpu_chain, nb); | ||
| 88 | unlock_cpu_hotplug(); | ||
| 89 | } | 81 | } |
| 90 | EXPORT_SYMBOL(unregister_cpu_notifier); | 82 | EXPORT_SYMBOL(unregister_cpu_notifier); |
| 91 | 83 | ||
| @@ -141,7 +133,7 @@ int cpu_down(unsigned int cpu) | |||
| 141 | goto out; | 133 | goto out; |
| 142 | } | 134 | } |
| 143 | 135 | ||
| 144 | err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, | 136 | err = blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, |
| 145 | (void *)(long)cpu); | 137 | (void *)(long)cpu); |
| 146 | if (err == NOTIFY_BAD) { | 138 | if (err == NOTIFY_BAD) { |
| 147 | printk("%s: attempt to take down CPU %u failed\n", | 139 | printk("%s: attempt to take down CPU %u failed\n", |
| @@ -159,7 +151,7 @@ int cpu_down(unsigned int cpu) | |||
| 159 | p = __stop_machine_run(take_cpu_down, NULL, cpu); | 151 | p = __stop_machine_run(take_cpu_down, NULL, cpu); |
| 160 | if (IS_ERR(p)) { | 152 | if (IS_ERR(p)) { |
| 161 | /* CPU didn't die: tell everyone. Can't complain. */ | 153 | /* CPU didn't die: tell everyone. Can't complain. */ |
| 162 | if (notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED, | 154 | if (blocking_notifier_call_chain(&cpu_chain, CPU_DOWN_FAILED, |
| 163 | (void *)(long)cpu) == NOTIFY_BAD) | 155 | (void *)(long)cpu) == NOTIFY_BAD) |
| 164 | BUG(); | 156 | BUG(); |
| 165 | 157 | ||
| @@ -182,8 +174,8 @@ int cpu_down(unsigned int cpu) | |||
| 182 | put_cpu(); | 174 | put_cpu(); |
| 183 | 175 | ||
| 184 | /* CPU is completely dead: tell everyone. Too late to complain. */ | 176 | /* CPU is completely dead: tell everyone. Too late to complain. */ |
| 185 | if (notifier_call_chain(&cpu_chain, CPU_DEAD, (void *)(long)cpu) | 177 | if (blocking_notifier_call_chain(&cpu_chain, CPU_DEAD, |
| 186 | == NOTIFY_BAD) | 178 | (void *)(long)cpu) == NOTIFY_BAD) |
| 187 | BUG(); | 179 | BUG(); |
| 188 | 180 | ||
| 189 | check_for_tasks(cpu); | 181 | check_for_tasks(cpu); |
| @@ -211,7 +203,7 @@ int __devinit cpu_up(unsigned int cpu) | |||
| 211 | goto out; | 203 | goto out; |
| 212 | } | 204 | } |
| 213 | 205 | ||
| 214 | ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); | 206 | ret = blocking_notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); |
| 215 | if (ret == NOTIFY_BAD) { | 207 | if (ret == NOTIFY_BAD) { |
| 216 | printk("%s: attempt to bring up CPU %u failed\n", | 208 | printk("%s: attempt to bring up CPU %u failed\n", |
| 217 | __FUNCTION__, cpu); | 209 | __FUNCTION__, cpu); |
| @@ -226,11 +218,12 @@ int __devinit cpu_up(unsigned int cpu) | |||
| 226 | BUG_ON(!cpu_online(cpu)); | 218 | BUG_ON(!cpu_online(cpu)); |
| 227 | 219 | ||
| 228 | /* Now call notifier in preparation. */ | 220 | /* Now call notifier in preparation. */ |
| 229 | notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu); | 221 | blocking_notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu); |
| 230 | 222 | ||
| 231 | out_notify: | 223 | out_notify: |
| 232 | if (ret != 0) | 224 | if (ret != 0) |
| 233 | notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu); | 225 | blocking_notifier_call_chain(&cpu_chain, |
| 226 | CPU_UP_CANCELED, hcpu); | ||
| 234 | out: | 227 | out: |
| 235 | unlock_cpu_hotplug(); | 228 | unlock_cpu_hotplug(); |
| 236 | return ret; | 229 | return ret; |
diff --git a/kernel/exit.c b/kernel/exit.c index 8037405e136e..a8c7efc7a681 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
| @@ -31,6 +31,8 @@ | |||
| 31 | #include <linux/signal.h> | 31 | #include <linux/signal.h> |
| 32 | #include <linux/cn_proc.h> | 32 | #include <linux/cn_proc.h> |
| 33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
| 34 | #include <linux/futex.h> | ||
| 35 | #include <linux/compat.h> | ||
| 34 | 36 | ||
| 35 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
| 36 | #include <asm/unistd.h> | 38 | #include <asm/unistd.h> |
| @@ -852,6 +854,12 @@ fastcall NORET_TYPE void do_exit(long code) | |||
| 852 | exit_itimers(tsk->signal); | 854 | exit_itimers(tsk->signal); |
| 853 | acct_process(code); | 855 | acct_process(code); |
| 854 | } | 856 | } |
| 857 | if (unlikely(tsk->robust_list)) | ||
| 858 | exit_robust_list(tsk); | ||
| 859 | #ifdef CONFIG_COMPAT | ||
| 860 | if (unlikely(tsk->compat_robust_list)) | ||
| 861 | compat_exit_robust_list(tsk); | ||
| 862 | #endif | ||
| 855 | exit_mm(tsk); | 863 | exit_mm(tsk); |
| 856 | 864 | ||
| 857 | exit_sem(tsk); | 865 | exit_sem(tsk); |
diff --git a/kernel/fork.c b/kernel/fork.c index e0a2b449dea6..c49bd193b058 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -1061,7 +1061,10 @@ static task_t *copy_process(unsigned long clone_flags, | |||
| 1061 | * Clear TID on mm_release()? | 1061 | * Clear TID on mm_release()? |
| 1062 | */ | 1062 | */ |
| 1063 | p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL; | 1063 | p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL; |
| 1064 | 1064 | p->robust_list = NULL; | |
| 1065 | #ifdef CONFIG_COMPAT | ||
| 1066 | p->compat_robust_list = NULL; | ||
| 1067 | #endif | ||
| 1065 | /* | 1068 | /* |
| 1066 | * sigaltstack should be cleared when sharing the same VM | 1069 | * sigaltstack should be cleared when sharing the same VM |
| 1067 | */ | 1070 | */ |
diff --git a/kernel/futex.c b/kernel/futex.c index 5efa2f978032..9c9b2b6b22dd 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
| @@ -8,6 +8,10 @@ | |||
| 8 | * Removed page pinning, fix privately mapped COW pages and other cleanups | 8 | * Removed page pinning, fix privately mapped COW pages and other cleanups |
| 9 | * (C) Copyright 2003, 2004 Jamie Lokier | 9 | * (C) Copyright 2003, 2004 Jamie Lokier |
| 10 | * | 10 | * |
| 11 | * Robust futex support started by Ingo Molnar | ||
| 12 | * (C) Copyright 2006 Red Hat Inc, All Rights Reserved | ||
| 13 | * Thanks to Thomas Gleixner for suggestions, analysis and fixes. | ||
| 14 | * | ||
| 11 | * Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly | 15 | * Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly |
| 12 | * enough at me, Linus for the original (flawed) idea, Matthew | 16 | * enough at me, Linus for the original (flawed) idea, Matthew |
| 13 | * Kirkwood for proof-of-concept implementation. | 17 | * Kirkwood for proof-of-concept implementation. |
| @@ -829,6 +833,172 @@ error: | |||
| 829 | goto out; | 833 | goto out; |
| 830 | } | 834 | } |
| 831 | 835 | ||
| 836 | /* | ||
| 837 | * Support for robust futexes: the kernel cleans up held futexes at | ||
| 838 | * thread exit time. | ||
| 839 | * | ||
| 840 | * Implementation: user-space maintains a per-thread list of locks it | ||
| 841 | * is holding. Upon do_exit(), the kernel carefully walks this list, | ||
| 842 | * and marks all locks that are owned by this thread with the | ||
| 843 | * FUTEX_OWNER_DEAD bit, and wakes up a waiter (if any). The list is | ||
| 844 | * always manipulated with the lock held, so the list is private and | ||
| 845 | * per-thread. Userspace also maintains a per-thread 'list_op_pending' | ||
| 846 | * field, to allow the kernel to clean up if the thread dies after | ||
| 847 | * acquiring the lock, but just before it could have added itself to | ||
| 848 | * the list. There can only be one such pending lock. | ||
| 849 | */ | ||
| 850 | |||
| 851 | /** | ||
| 852 | * sys_set_robust_list - set the robust-futex list head of a task | ||
| 853 | * @head: pointer to the list-head | ||
| 854 | * @len: length of the list-head, as userspace expects | ||
| 855 | */ | ||
| 856 | asmlinkage long | ||
| 857 | sys_set_robust_list(struct robust_list_head __user *head, | ||
| 858 | size_t len) | ||
| 859 | { | ||
| 860 | /* | ||
| 861 | * The kernel knows only one size for now: | ||
| 862 | */ | ||
| 863 | if (unlikely(len != sizeof(*head))) | ||
| 864 | return -EINVAL; | ||
| 865 | |||
| 866 | current->robust_list = head; | ||
| 867 | |||
| 868 | return 0; | ||
| 869 | } | ||
| 870 | |||
| 871 | /** | ||
| 872 | * sys_get_robust_list - get the robust-futex list head of a task | ||
| 873 | * @pid: pid of the process [zero for current task] | ||
| 874 | * @head_ptr: pointer to a list-head pointer, the kernel fills it in | ||
| 875 | * @len_ptr: pointer to a length field, the kernel fills in the header size | ||
| 876 | */ | ||
| 877 | asmlinkage long | ||
| 878 | sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr, | ||
| 879 | size_t __user *len_ptr) | ||
| 880 | { | ||
| 881 | struct robust_list_head *head; | ||
| 882 | unsigned long ret; | ||
| 883 | |||
| 884 | if (!pid) | ||
| 885 | head = current->robust_list; | ||
| 886 | else { | ||
| 887 | struct task_struct *p; | ||
| 888 | |||
| 889 | ret = -ESRCH; | ||
| 890 | read_lock(&tasklist_lock); | ||
| 891 | p = find_task_by_pid(pid); | ||
| 892 | if (!p) | ||
| 893 | goto err_unlock; | ||
| 894 | ret = -EPERM; | ||
| 895 | if ((current->euid != p->euid) && (current->euid != p->uid) && | ||
| 896 | !capable(CAP_SYS_PTRACE)) | ||
| 897 | goto err_unlock; | ||
| 898 | head = p->robust_list; | ||
| 899 | read_unlock(&tasklist_lock); | ||
| 900 | } | ||
| 901 | |||
| 902 | if (put_user(sizeof(*head), len_ptr)) | ||
| 903 | return -EFAULT; | ||
| 904 | return put_user(head, head_ptr); | ||
| 905 | |||
| 906 | err_unlock: | ||
| 907 | read_unlock(&tasklist_lock); | ||
| 908 | |||
| 909 | return ret; | ||
| 910 | } | ||
| 911 | |||
| 912 | /* | ||
| 913 | * Process a futex-list entry, check whether it's owned by the | ||
| 914 | * dying task, and do notification if so: | ||
| 915 | */ | ||
| 916 | int handle_futex_death(u32 __user *uaddr, struct task_struct *curr) | ||
| 917 | { | ||
| 918 | u32 uval; | ||
| 919 | |||
| 920 | retry: | ||
| 921 | if (get_user(uval, uaddr)) | ||
| 922 | return -1; | ||
| 923 | |||
| 924 | if ((uval & FUTEX_TID_MASK) == curr->pid) { | ||
| 925 | /* | ||
| 926 | * Ok, this dying thread is truly holding a futex | ||
| 927 | * of interest. Set the OWNER_DIED bit atomically | ||
| 928 | * via cmpxchg, and if the value had FUTEX_WAITERS | ||
| 929 | * set, wake up a waiter (if any). (We have to do a | ||
| 930 | * futex_wake() even if OWNER_DIED is already set - | ||
| 931 | * to handle the rare but possible case of recursive | ||
| 932 | * thread-death.) The rest of the cleanup is done in | ||
| 933 | * userspace. | ||
| 934 | */ | ||
| 935 | if (futex_atomic_cmpxchg_inatomic(uaddr, uval, | ||
| 936 | uval | FUTEX_OWNER_DIED) != uval) | ||
| 937 | goto retry; | ||
| 938 | |||
| 939 | if (uval & FUTEX_WAITERS) | ||
| 940 | futex_wake((unsigned long)uaddr, 1); | ||
| 941 | } | ||
| 942 | return 0; | ||
| 943 | } | ||
| 944 | |||
| 945 | /* | ||
| 946 | * Walk curr->robust_list (very carefully, it's a userspace list!) | ||
| 947 | * and mark any locks found there dead, and notify any waiters. | ||
| 948 | * | ||
| 949 | * We silently return on any sign of list-walking problem. | ||
| 950 | */ | ||
| 951 | void exit_robust_list(struct task_struct *curr) | ||
| 952 | { | ||
| 953 | struct robust_list_head __user *head = curr->robust_list; | ||
| 954 | struct robust_list __user *entry, *pending; | ||
| 955 | unsigned int limit = ROBUST_LIST_LIMIT; | ||
| 956 | unsigned long futex_offset; | ||
| 957 | |||
| 958 | /* | ||
| 959 | * Fetch the list head (which was registered earlier, via | ||
| 960 | * sys_set_robust_list()): | ||
| 961 | */ | ||
| 962 | if (get_user(entry, &head->list.next)) | ||
| 963 | return; | ||
| 964 | /* | ||
| 965 | * Fetch the relative futex offset: | ||
| 966 | */ | ||
| 967 | if (get_user(futex_offset, &head->futex_offset)) | ||
| 968 | return; | ||
| 969 | /* | ||
| 970 | * Fetch any possibly pending lock-add first, and handle it | ||
| 971 | * if it exists: | ||
| 972 | */ | ||
| 973 | if (get_user(pending, &head->list_op_pending)) | ||
| 974 | return; | ||
| 975 | if (pending) | ||
| 976 | handle_futex_death((void *)pending + futex_offset, curr); | ||
| 977 | |||
| 978 | while (entry != &head->list) { | ||
| 979 | /* | ||
| 980 | * A pending lock might already be on the list, so | ||
| 981 | * dont process it twice: | ||
| 982 | */ | ||
| 983 | if (entry != pending) | ||
| 984 | if (handle_futex_death((void *)entry + futex_offset, | ||
| 985 | curr)) | ||
| 986 | return; | ||
| 987 | /* | ||
| 988 | * Fetch the next entry in the list: | ||
| 989 | */ | ||
| 990 | if (get_user(entry, &entry->next)) | ||
| 991 | return; | ||
| 992 | /* | ||
| 993 | * Avoid excessively long or circular lists: | ||
| 994 | */ | ||
| 995 | if (!--limit) | ||
| 996 | break; | ||
| 997 | |||
| 998 | cond_resched(); | ||
| 999 | } | ||
| 1000 | } | ||
| 1001 | |||
| 832 | long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout, | 1002 | long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout, |
| 833 | unsigned long uaddr2, int val2, int val3) | 1003 | unsigned long uaddr2, int val2, int val3) |
| 834 | { | 1004 | { |
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c new file mode 100644 index 000000000000..54274fc85321 --- /dev/null +++ b/kernel/futex_compat.c | |||
| @@ -0,0 +1,142 @@ | |||
| 1 | /* | ||
| 2 | * linux/kernel/futex_compat.c | ||
| 3 | * | ||
| 4 | * Futex compatibililty routines. | ||
| 5 | * | ||
| 6 | * Copyright 2006, Red Hat, Inc., Ingo Molnar | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/linkage.h> | ||
| 10 | #include <linux/compat.h> | ||
| 11 | #include <linux/futex.h> | ||
| 12 | |||
| 13 | #include <asm/uaccess.h> | ||
| 14 | |||
| 15 | /* | ||
| 16 | * Walk curr->robust_list (very carefully, it's a userspace list!) | ||
| 17 | * and mark any locks found there dead, and notify any waiters. | ||
| 18 | * | ||
| 19 | * We silently return on any sign of list-walking problem. | ||
| 20 | */ | ||
| 21 | void compat_exit_robust_list(struct task_struct *curr) | ||
| 22 | { | ||
| 23 | struct compat_robust_list_head __user *head = curr->compat_robust_list; | ||
| 24 | struct robust_list __user *entry, *pending; | ||
| 25 | compat_uptr_t uentry, upending; | ||
| 26 | unsigned int limit = ROBUST_LIST_LIMIT; | ||
| 27 | compat_long_t futex_offset; | ||
| 28 | |||
| 29 | /* | ||
| 30 | * Fetch the list head (which was registered earlier, via | ||
| 31 | * sys_set_robust_list()): | ||
| 32 | */ | ||
| 33 | if (get_user(uentry, &head->list.next)) | ||
| 34 | return; | ||
| 35 | entry = compat_ptr(uentry); | ||
| 36 | /* | ||
| 37 | * Fetch the relative futex offset: | ||
| 38 | */ | ||
| 39 | if (get_user(futex_offset, &head->futex_offset)) | ||
| 40 | return; | ||
| 41 | /* | ||
| 42 | * Fetch any possibly pending lock-add first, and handle it | ||
| 43 | * if it exists: | ||
| 44 | */ | ||
| 45 | if (get_user(upending, &head->list_op_pending)) | ||
| 46 | return; | ||
| 47 | pending = compat_ptr(upending); | ||
| 48 | if (upending) | ||
| 49 | handle_futex_death((void *)pending + futex_offset, curr); | ||
| 50 | |||
| 51 | while (compat_ptr(uentry) != &head->list) { | ||
| 52 | /* | ||
| 53 | * A pending lock might already be on the list, so | ||
| 54 | * dont process it twice: | ||
| 55 | */ | ||
| 56 | if (entry != pending) | ||
| 57 | if (handle_futex_death((void *)entry + futex_offset, | ||
| 58 | curr)) | ||
| 59 | return; | ||
| 60 | |||
| 61 | /* | ||
| 62 | * Fetch the next entry in the list: | ||
| 63 | */ | ||
| 64 | if (get_user(uentry, (compat_uptr_t *)&entry->next)) | ||
| 65 | return; | ||
| 66 | entry = compat_ptr(uentry); | ||
| 67 | /* | ||
| 68 | * Avoid excessively long or circular lists: | ||
| 69 | */ | ||
| 70 | if (!--limit) | ||
| 71 | break; | ||
| 72 | |||
| 73 | cond_resched(); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | asmlinkage long | ||
| 78 | compat_sys_set_robust_list(struct compat_robust_list_head __user *head, | ||
| 79 | compat_size_t len) | ||
| 80 | { | ||
| 81 | if (unlikely(len != sizeof(*head))) | ||
| 82 | return -EINVAL; | ||
| 83 | |||
| 84 | current->compat_robust_list = head; | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | asmlinkage long | ||
| 90 | compat_sys_get_robust_list(int pid, compat_uptr_t *head_ptr, | ||
| 91 | compat_size_t __user *len_ptr) | ||
| 92 | { | ||
| 93 | struct compat_robust_list_head *head; | ||
| 94 | unsigned long ret; | ||
| 95 | |||
| 96 | if (!pid) | ||
| 97 | head = current->compat_robust_list; | ||
| 98 | else { | ||
| 99 | struct task_struct *p; | ||
| 100 | |||
| 101 | ret = -ESRCH; | ||
| 102 | read_lock(&tasklist_lock); | ||
| 103 | p = find_task_by_pid(pid); | ||
| 104 | if (!p) | ||
| 105 | goto err_unlock; | ||
| 106 | ret = -EPERM; | ||
| 107 | if ((current->euid != p->euid) && (current->euid != p->uid) && | ||
| 108 | !capable(CAP_SYS_PTRACE)) | ||
| 109 | goto err_unlock; | ||
| 110 | head = p->compat_robust_list; | ||
| 111 | read_unlock(&tasklist_lock); | ||
| 112 | } | ||
| 113 | |||
| 114 | if (put_user(sizeof(*head), len_ptr)) | ||
| 115 | return -EFAULT; | ||
| 116 | return put_user(ptr_to_compat(head), head_ptr); | ||
| 117 | |||
| 118 | err_unlock: | ||
| 119 | read_unlock(&tasklist_lock); | ||
| 120 | |||
| 121 | return ret; | ||
| 122 | } | ||
| 123 | |||
| 124 | asmlinkage long compat_sys_futex(u32 __user *uaddr, int op, u32 val, | ||
| 125 | struct compat_timespec __user *utime, u32 __user *uaddr2, | ||
| 126 | u32 val3) | ||
| 127 | { | ||
| 128 | struct timespec t; | ||
| 129 | unsigned long timeout = MAX_SCHEDULE_TIMEOUT; | ||
| 130 | int val2 = 0; | ||
| 131 | |||
| 132 | if ((op == FUTEX_WAIT) && utime) { | ||
| 133 | if (get_compat_timespec(&t, utime)) | ||
| 134 | return -EFAULT; | ||
| 135 | timeout = timespec_to_jiffies(&t) + 1; | ||
| 136 | } | ||
| 137 | if (op >= FUTEX_REQUEUE) | ||
| 138 | val2 = (int) (unsigned long) utime; | ||
| 139 | |||
| 140 | return do_futex((unsigned long)uaddr, op, val, timeout, | ||
| 141 | (unsigned long)uaddr2, val2, val3); | ||
| 142 | } | ||
diff --git a/kernel/module.c b/kernel/module.c index ddfe45ac2fd1..bd088a7c1499 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -64,26 +64,17 @@ static DEFINE_SPINLOCK(modlist_lock); | |||
| 64 | static DEFINE_MUTEX(module_mutex); | 64 | static DEFINE_MUTEX(module_mutex); |
| 65 | static LIST_HEAD(modules); | 65 | static LIST_HEAD(modules); |
| 66 | 66 | ||
| 67 | static DEFINE_MUTEX(notify_mutex); | 67 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); |
| 68 | static struct notifier_block * module_notify_list; | ||
| 69 | 68 | ||
| 70 | int register_module_notifier(struct notifier_block * nb) | 69 | int register_module_notifier(struct notifier_block * nb) |
| 71 | { | 70 | { |
| 72 | int err; | 71 | return blocking_notifier_chain_register(&module_notify_list, nb); |
| 73 | mutex_lock(¬ify_mutex); | ||
| 74 | err = notifier_chain_register(&module_notify_list, nb); | ||
| 75 | mutex_unlock(¬ify_mutex); | ||
| 76 | return err; | ||
| 77 | } | 72 | } |
| 78 | EXPORT_SYMBOL(register_module_notifier); | 73 | EXPORT_SYMBOL(register_module_notifier); |
| 79 | 74 | ||
| 80 | int unregister_module_notifier(struct notifier_block * nb) | 75 | int unregister_module_notifier(struct notifier_block * nb) |
| 81 | { | 76 | { |
| 82 | int err; | 77 | return blocking_notifier_chain_unregister(&module_notify_list, nb); |
| 83 | mutex_lock(¬ify_mutex); | ||
| 84 | err = notifier_chain_unregister(&module_notify_list, nb); | ||
| 85 | mutex_unlock(¬ify_mutex); | ||
| 86 | return err; | ||
| 87 | } | 78 | } |
| 88 | EXPORT_SYMBOL(unregister_module_notifier); | 79 | EXPORT_SYMBOL(unregister_module_notifier); |
| 89 | 80 | ||
| @@ -136,7 +127,7 @@ extern const unsigned long __start___kcrctab_gpl_future[]; | |||
| 136 | #ifndef CONFIG_MODVERSIONS | 127 | #ifndef CONFIG_MODVERSIONS |
| 137 | #define symversion(base, idx) NULL | 128 | #define symversion(base, idx) NULL |
| 138 | #else | 129 | #else |
| 139 | #define symversion(base, idx) ((base) ? ((base) + (idx)) : NULL) | 130 | #define symversion(base, idx) ((base != NULL) ? ((base) + (idx)) : NULL) |
| 140 | #endif | 131 | #endif |
| 141 | 132 | ||
| 142 | /* lookup symbol in given range of kernel_symbols */ | 133 | /* lookup symbol in given range of kernel_symbols */ |
| @@ -1816,9 +1807,8 @@ sys_init_module(void __user *umod, | |||
| 1816 | /* Drop lock so they can recurse */ | 1807 | /* Drop lock so they can recurse */ |
| 1817 | mutex_unlock(&module_mutex); | 1808 | mutex_unlock(&module_mutex); |
| 1818 | 1809 | ||
| 1819 | mutex_lock(¬ify_mutex); | 1810 | blocking_notifier_call_chain(&module_notify_list, |
| 1820 | notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod); | 1811 | MODULE_STATE_COMING, mod); |
| 1821 | mutex_unlock(¬ify_mutex); | ||
| 1822 | 1812 | ||
| 1823 | /* Start the module */ | 1813 | /* Start the module */ |
| 1824 | if (mod->init != NULL) | 1814 | if (mod->init != NULL) |
diff --git a/kernel/panic.c b/kernel/panic.c index acd95adddb93..f895c7c01d5b 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
| @@ -29,7 +29,7 @@ static DEFINE_SPINLOCK(pause_on_oops_lock); | |||
| 29 | int panic_timeout; | 29 | int panic_timeout; |
| 30 | EXPORT_SYMBOL(panic_timeout); | 30 | EXPORT_SYMBOL(panic_timeout); |
| 31 | 31 | ||
| 32 | struct notifier_block *panic_notifier_list; | 32 | ATOMIC_NOTIFIER_HEAD(panic_notifier_list); |
| 33 | 33 | ||
| 34 | EXPORT_SYMBOL(panic_notifier_list); | 34 | EXPORT_SYMBOL(panic_notifier_list); |
| 35 | 35 | ||
| @@ -97,7 +97,7 @@ NORET_TYPE void panic(const char * fmt, ...) | |||
| 97 | smp_send_stop(); | 97 | smp_send_stop(); |
| 98 | #endif | 98 | #endif |
| 99 | 99 | ||
| 100 | notifier_call_chain(&panic_notifier_list, 0, buf); | 100 | atomic_notifier_call_chain(&panic_notifier_list, 0, buf); |
| 101 | 101 | ||
| 102 | if (!panic_blink) | 102 | if (!panic_blink) |
| 103 | panic_blink = no_blink; | 103 | panic_blink = no_blink; |
diff --git a/kernel/params.c b/kernel/params.c index 9de637a5c8bc..af43ecdc8d9b 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #define DEBUGP(fmt, a...) | 31 | #define DEBUGP(fmt, a...) |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | static inline int dash2underscore(char c) | 34 | static inline char dash2underscore(char c) |
| 35 | { | 35 | { |
| 36 | if (c == '-') | 36 | if (c == '-') |
| 37 | return '_'; | 37 | return '_'; |
diff --git a/kernel/profile.c b/kernel/profile.c index ad81f799a9b4..5a730fdb1a2c 100644 --- a/kernel/profile.c +++ b/kernel/profile.c | |||
| @@ -87,72 +87,52 @@ void __init profile_init(void) | |||
| 87 | 87 | ||
| 88 | #ifdef CONFIG_PROFILING | 88 | #ifdef CONFIG_PROFILING |
| 89 | 89 | ||
| 90 | static DECLARE_RWSEM(profile_rwsem); | 90 | static BLOCKING_NOTIFIER_HEAD(task_exit_notifier); |
| 91 | static DEFINE_RWLOCK(handoff_lock); | 91 | static ATOMIC_NOTIFIER_HEAD(task_free_notifier); |
| 92 | static struct notifier_block * task_exit_notifier; | 92 | static BLOCKING_NOTIFIER_HEAD(munmap_notifier); |
| 93 | static struct notifier_block * task_free_notifier; | ||
| 94 | static struct notifier_block * munmap_notifier; | ||
| 95 | 93 | ||
| 96 | void profile_task_exit(struct task_struct * task) | 94 | void profile_task_exit(struct task_struct * task) |
| 97 | { | 95 | { |
| 98 | down_read(&profile_rwsem); | 96 | blocking_notifier_call_chain(&task_exit_notifier, 0, task); |
| 99 | notifier_call_chain(&task_exit_notifier, 0, task); | ||
| 100 | up_read(&profile_rwsem); | ||
| 101 | } | 97 | } |
| 102 | 98 | ||
| 103 | int profile_handoff_task(struct task_struct * task) | 99 | int profile_handoff_task(struct task_struct * task) |
| 104 | { | 100 | { |
| 105 | int ret; | 101 | int ret; |
| 106 | read_lock(&handoff_lock); | 102 | ret = atomic_notifier_call_chain(&task_free_notifier, 0, task); |
| 107 | ret = notifier_call_chain(&task_free_notifier, 0, task); | ||
| 108 | read_unlock(&handoff_lock); | ||
| 109 | return (ret == NOTIFY_OK) ? 1 : 0; | 103 | return (ret == NOTIFY_OK) ? 1 : 0; |
| 110 | } | 104 | } |
| 111 | 105 | ||
| 112 | void profile_munmap(unsigned long addr) | 106 | void profile_munmap(unsigned long addr) |
| 113 | { | 107 | { |
| 114 | down_read(&profile_rwsem); | 108 | blocking_notifier_call_chain(&munmap_notifier, 0, (void *)addr); |
| 115 | notifier_call_chain(&munmap_notifier, 0, (void *)addr); | ||
| 116 | up_read(&profile_rwsem); | ||
| 117 | } | 109 | } |
| 118 | 110 | ||
| 119 | int task_handoff_register(struct notifier_block * n) | 111 | int task_handoff_register(struct notifier_block * n) |
| 120 | { | 112 | { |
| 121 | int err = -EINVAL; | 113 | return atomic_notifier_chain_register(&task_free_notifier, n); |
| 122 | |||
| 123 | write_lock(&handoff_lock); | ||
| 124 | err = notifier_chain_register(&task_free_notifier, n); | ||
| 125 | write_unlock(&handoff_lock); | ||
| 126 | return err; | ||
| 127 | } | 114 | } |
| 128 | 115 | ||
| 129 | int task_handoff_unregister(struct notifier_block * n) | 116 | int task_handoff_unregister(struct notifier_block * n) |
| 130 | { | 117 | { |
| 131 | int err = -EINVAL; | 118 | return atomic_notifier_chain_unregister(&task_free_notifier, n); |
| 132 | |||
| 133 | write_lock(&handoff_lock); | ||
| 134 | err = notifier_chain_unregister(&task_free_notifier, n); | ||
| 135 | write_unlock(&handoff_lock); | ||
| 136 | return err; | ||
| 137 | } | 119 | } |
| 138 | 120 | ||
| 139 | int profile_event_register(enum profile_type type, struct notifier_block * n) | 121 | int profile_event_register(enum profile_type type, struct notifier_block * n) |
| 140 | { | 122 | { |
| 141 | int err = -EINVAL; | 123 | int err = -EINVAL; |
| 142 | 124 | ||
| 143 | down_write(&profile_rwsem); | ||
| 144 | |||
| 145 | switch (type) { | 125 | switch (type) { |
| 146 | case PROFILE_TASK_EXIT: | 126 | case PROFILE_TASK_EXIT: |
| 147 | err = notifier_chain_register(&task_exit_notifier, n); | 127 | err = blocking_notifier_chain_register( |
| 128 | &task_exit_notifier, n); | ||
| 148 | break; | 129 | break; |
| 149 | case PROFILE_MUNMAP: | 130 | case PROFILE_MUNMAP: |
| 150 | err = notifier_chain_register(&munmap_notifier, n); | 131 | err = blocking_notifier_chain_register( |
| 132 | &munmap_notifier, n); | ||
| 151 | break; | 133 | break; |
| 152 | } | 134 | } |
| 153 | 135 | ||
| 154 | up_write(&profile_rwsem); | ||
| 155 | |||
| 156 | return err; | 136 | return err; |
| 157 | } | 137 | } |
| 158 | 138 | ||
| @@ -161,18 +141,17 @@ int profile_event_unregister(enum profile_type type, struct notifier_block * n) | |||
| 161 | { | 141 | { |
| 162 | int err = -EINVAL; | 142 | int err = -EINVAL; |
| 163 | 143 | ||
| 164 | down_write(&profile_rwsem); | ||
| 165 | |||
| 166 | switch (type) { | 144 | switch (type) { |
| 167 | case PROFILE_TASK_EXIT: | 145 | case PROFILE_TASK_EXIT: |
| 168 | err = notifier_chain_unregister(&task_exit_notifier, n); | 146 | err = blocking_notifier_chain_unregister( |
| 147 | &task_exit_notifier, n); | ||
| 169 | break; | 148 | break; |
| 170 | case PROFILE_MUNMAP: | 149 | case PROFILE_MUNMAP: |
| 171 | err = notifier_chain_unregister(&munmap_notifier, n); | 150 | err = blocking_notifier_chain_unregister( |
| 151 | &munmap_notifier, n); | ||
| 172 | break; | 152 | break; |
| 173 | } | 153 | } |
| 174 | 154 | ||
| 175 | up_write(&profile_rwsem); | ||
| 176 | return err; | 155 | return err; |
| 177 | } | 156 | } |
| 178 | 157 | ||
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index b4b362b5baf5..8154e7589d12 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c | |||
| @@ -301,7 +301,7 @@ rcu_torture_printk(char *page) | |||
| 301 | long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 }; | 301 | long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 }; |
| 302 | long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 }; | 302 | long batchsummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 }; |
| 303 | 303 | ||
| 304 | for_each_cpu(cpu) { | 304 | for_each_possible_cpu(cpu) { |
| 305 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { | 305 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { |
| 306 | pipesummary[i] += per_cpu(rcu_torture_count, cpu)[i]; | 306 | pipesummary[i] += per_cpu(rcu_torture_count, cpu)[i]; |
| 307 | batchsummary[i] += per_cpu(rcu_torture_batch, cpu)[i]; | 307 | batchsummary[i] += per_cpu(rcu_torture_batch, cpu)[i]; |
| @@ -535,7 +535,7 @@ rcu_torture_init(void) | |||
| 535 | atomic_set(&n_rcu_torture_error, 0); | 535 | atomic_set(&n_rcu_torture_error, 0); |
| 536 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) | 536 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) |
| 537 | atomic_set(&rcu_torture_wcount[i], 0); | 537 | atomic_set(&rcu_torture_wcount[i], 0); |
| 538 | for_each_cpu(cpu) { | 538 | for_each_possible_cpu(cpu) { |
| 539 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { | 539 | for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { |
| 540 | per_cpu(rcu_torture_count, cpu)[i] = 0; | 540 | per_cpu(rcu_torture_count, cpu)[i] = 0; |
| 541 | per_cpu(rcu_torture_batch, cpu)[i] = 0; | 541 | per_cpu(rcu_torture_batch, cpu)[i] = 0; |
diff --git a/kernel/sched.c b/kernel/sched.c index 78acdefeccca..a9ecac398bb9 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -145,7 +145,8 @@ | |||
| 145 | (v1) * (v2_max) / (v1_max) | 145 | (v1) * (v2_max) / (v1_max) |
| 146 | 146 | ||
| 147 | #define DELTA(p) \ | 147 | #define DELTA(p) \ |
| 148 | (SCALE(TASK_NICE(p), 40, MAX_BONUS) + INTERACTIVE_DELTA) | 148 | (SCALE(TASK_NICE(p) + 20, 40, MAX_BONUS) - 20 * MAX_BONUS / 40 + \ |
| 149 | INTERACTIVE_DELTA) | ||
| 149 | 150 | ||
| 150 | #define TASK_INTERACTIVE(p) \ | 151 | #define TASK_INTERACTIVE(p) \ |
| 151 | ((p)->prio <= (p)->static_prio - DELTA(p)) | 152 | ((p)->prio <= (p)->static_prio - DELTA(p)) |
| @@ -1624,7 +1625,7 @@ unsigned long nr_uninterruptible(void) | |||
| 1624 | { | 1625 | { |
| 1625 | unsigned long i, sum = 0; | 1626 | unsigned long i, sum = 0; |
| 1626 | 1627 | ||
| 1627 | for_each_cpu(i) | 1628 | for_each_possible_cpu(i) |
| 1628 | sum += cpu_rq(i)->nr_uninterruptible; | 1629 | sum += cpu_rq(i)->nr_uninterruptible; |
| 1629 | 1630 | ||
| 1630 | /* | 1631 | /* |
| @@ -1641,7 +1642,7 @@ unsigned long long nr_context_switches(void) | |||
| 1641 | { | 1642 | { |
| 1642 | unsigned long long i, sum = 0; | 1643 | unsigned long long i, sum = 0; |
| 1643 | 1644 | ||
| 1644 | for_each_cpu(i) | 1645 | for_each_possible_cpu(i) |
| 1645 | sum += cpu_rq(i)->nr_switches; | 1646 | sum += cpu_rq(i)->nr_switches; |
| 1646 | 1647 | ||
| 1647 | return sum; | 1648 | return sum; |
| @@ -1651,7 +1652,7 @@ unsigned long nr_iowait(void) | |||
| 1651 | { | 1652 | { |
| 1652 | unsigned long i, sum = 0; | 1653 | unsigned long i, sum = 0; |
| 1653 | 1654 | ||
| 1654 | for_each_cpu(i) | 1655 | for_each_possible_cpu(i) |
| 1655 | sum += atomic_read(&cpu_rq(i)->nr_iowait); | 1656 | sum += atomic_read(&cpu_rq(i)->nr_iowait); |
| 1656 | 1657 | ||
| 1657 | return sum; | 1658 | return sum; |
| @@ -2878,13 +2879,11 @@ asmlinkage void __sched schedule(void) | |||
| 2878 | * schedule() atomically, we ignore that path for now. | 2879 | * schedule() atomically, we ignore that path for now. |
| 2879 | * Otherwise, whine if we are scheduling when we should not be. | 2880 | * Otherwise, whine if we are scheduling when we should not be. |
| 2880 | */ | 2881 | */ |
| 2881 | if (likely(!current->exit_state)) { | 2882 | if (unlikely(in_atomic() && !current->exit_state)) { |
| 2882 | if (unlikely(in_atomic())) { | 2883 | printk(KERN_ERR "BUG: scheduling while atomic: " |
| 2883 | printk(KERN_ERR "BUG: scheduling while atomic: " | 2884 | "%s/0x%08x/%d\n", |
| 2884 | "%s/0x%08x/%d\n", | 2885 | current->comm, preempt_count(), current->pid); |
| 2885 | current->comm, preempt_count(), current->pid); | 2886 | dump_stack(); |
| 2886 | dump_stack(); | ||
| 2887 | } | ||
| 2888 | } | 2887 | } |
| 2889 | profile_hit(SCHED_PROFILING, __builtin_return_address(0)); | 2888 | profile_hit(SCHED_PROFILING, __builtin_return_address(0)); |
| 2890 | 2889 | ||
| @@ -5575,11 +5574,31 @@ static int cpu_to_cpu_group(int cpu) | |||
| 5575 | } | 5574 | } |
| 5576 | #endif | 5575 | #endif |
| 5577 | 5576 | ||
| 5577 | #ifdef CONFIG_SCHED_MC | ||
| 5578 | static DEFINE_PER_CPU(struct sched_domain, core_domains); | ||
| 5579 | static struct sched_group sched_group_core[NR_CPUS]; | ||
| 5580 | #endif | ||
| 5581 | |||
| 5582 | #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT) | ||
| 5583 | static int cpu_to_core_group(int cpu) | ||
| 5584 | { | ||
| 5585 | return first_cpu(cpu_sibling_map[cpu]); | ||
| 5586 | } | ||
| 5587 | #elif defined(CONFIG_SCHED_MC) | ||
| 5588 | static int cpu_to_core_group(int cpu) | ||
| 5589 | { | ||
| 5590 | return cpu; | ||
| 5591 | } | ||
| 5592 | #endif | ||
| 5593 | |||
| 5578 | static DEFINE_PER_CPU(struct sched_domain, phys_domains); | 5594 | static DEFINE_PER_CPU(struct sched_domain, phys_domains); |
| 5579 | static struct sched_group sched_group_phys[NR_CPUS]; | 5595 | static struct sched_group sched_group_phys[NR_CPUS]; |
| 5580 | static int cpu_to_phys_group(int cpu) | 5596 | static int cpu_to_phys_group(int cpu) |
| 5581 | { | 5597 | { |
| 5582 | #ifdef CONFIG_SCHED_SMT | 5598 | #if defined(CONFIG_SCHED_MC) |
| 5599 | cpumask_t mask = cpu_coregroup_map(cpu); | ||
| 5600 | return first_cpu(mask); | ||
| 5601 | #elif defined(CONFIG_SCHED_SMT) | ||
| 5583 | return first_cpu(cpu_sibling_map[cpu]); | 5602 | return first_cpu(cpu_sibling_map[cpu]); |
| 5584 | #else | 5603 | #else |
| 5585 | return cpu; | 5604 | return cpu; |
| @@ -5602,6 +5621,32 @@ static int cpu_to_allnodes_group(int cpu) | |||
| 5602 | { | 5621 | { |
| 5603 | return cpu_to_node(cpu); | 5622 | return cpu_to_node(cpu); |
| 5604 | } | 5623 | } |
| 5624 | static void init_numa_sched_groups_power(struct sched_group *group_head) | ||
| 5625 | { | ||
| 5626 | struct sched_group *sg = group_head; | ||
| 5627 | int j; | ||
| 5628 | |||
| 5629 | if (!sg) | ||
| 5630 | return; | ||
| 5631 | next_sg: | ||
| 5632 | for_each_cpu_mask(j, sg->cpumask) { | ||
| 5633 | struct sched_domain *sd; | ||
| 5634 | |||
| 5635 | sd = &per_cpu(phys_domains, j); | ||
| 5636 | if (j != first_cpu(sd->groups->cpumask)) { | ||
| 5637 | /* | ||
| 5638 | * Only add "power" once for each | ||
| 5639 | * physical package. | ||
| 5640 | */ | ||
| 5641 | continue; | ||
| 5642 | } | ||
| 5643 | |||
| 5644 | sg->cpu_power += sd->groups->cpu_power; | ||
| 5645 | } | ||
| 5646 | sg = sg->next; | ||
| 5647 | if (sg != group_head) | ||
| 5648 | goto next_sg; | ||
| 5649 | } | ||
| 5605 | #endif | 5650 | #endif |
| 5606 | 5651 | ||
| 5607 | /* | 5652 | /* |
| @@ -5677,6 +5722,17 @@ void build_sched_domains(const cpumask_t *cpu_map) | |||
| 5677 | sd->parent = p; | 5722 | sd->parent = p; |
| 5678 | sd->groups = &sched_group_phys[group]; | 5723 | sd->groups = &sched_group_phys[group]; |
| 5679 | 5724 | ||
| 5725 | #ifdef CONFIG_SCHED_MC | ||
| 5726 | p = sd; | ||
| 5727 | sd = &per_cpu(core_domains, i); | ||
| 5728 | group = cpu_to_core_group(i); | ||
| 5729 | *sd = SD_MC_INIT; | ||
| 5730 | sd->span = cpu_coregroup_map(i); | ||
| 5731 | cpus_and(sd->span, sd->span, *cpu_map); | ||
| 5732 | sd->parent = p; | ||
| 5733 | sd->groups = &sched_group_core[group]; | ||
| 5734 | #endif | ||
| 5735 | |||
| 5680 | #ifdef CONFIG_SCHED_SMT | 5736 | #ifdef CONFIG_SCHED_SMT |
| 5681 | p = sd; | 5737 | p = sd; |
| 5682 | sd = &per_cpu(cpu_domains, i); | 5738 | sd = &per_cpu(cpu_domains, i); |
| @@ -5702,6 +5758,19 @@ void build_sched_domains(const cpumask_t *cpu_map) | |||
| 5702 | } | 5758 | } |
| 5703 | #endif | 5759 | #endif |
| 5704 | 5760 | ||
| 5761 | #ifdef CONFIG_SCHED_MC | ||
| 5762 | /* Set up multi-core groups */ | ||
| 5763 | for_each_cpu_mask(i, *cpu_map) { | ||
| 5764 | cpumask_t this_core_map = cpu_coregroup_map(i); | ||
| 5765 | cpus_and(this_core_map, this_core_map, *cpu_map); | ||
| 5766 | if (i != first_cpu(this_core_map)) | ||
| 5767 | continue; | ||
| 5768 | init_sched_build_groups(sched_group_core, this_core_map, | ||
| 5769 | &cpu_to_core_group); | ||
| 5770 | } | ||
| 5771 | #endif | ||
| 5772 | |||
| 5773 | |||
| 5705 | /* Set up physical groups */ | 5774 | /* Set up physical groups */ |
| 5706 | for (i = 0; i < MAX_NUMNODES; i++) { | 5775 | for (i = 0; i < MAX_NUMNODES; i++) { |
| 5707 | cpumask_t nodemask = node_to_cpumask(i); | 5776 | cpumask_t nodemask = node_to_cpumask(i); |
| @@ -5798,51 +5867,38 @@ void build_sched_domains(const cpumask_t *cpu_map) | |||
| 5798 | power = SCHED_LOAD_SCALE; | 5867 | power = SCHED_LOAD_SCALE; |
| 5799 | sd->groups->cpu_power = power; | 5868 | sd->groups->cpu_power = power; |
| 5800 | #endif | 5869 | #endif |
| 5870 | #ifdef CONFIG_SCHED_MC | ||
| 5871 | sd = &per_cpu(core_domains, i); | ||
| 5872 | power = SCHED_LOAD_SCALE + (cpus_weight(sd->groups->cpumask)-1) | ||
| 5873 | * SCHED_LOAD_SCALE / 10; | ||
| 5874 | sd->groups->cpu_power = power; | ||
| 5801 | 5875 | ||
| 5802 | sd = &per_cpu(phys_domains, i); | 5876 | sd = &per_cpu(phys_domains, i); |
| 5877 | |||
| 5878 | /* | ||
| 5879 | * This has to be < 2 * SCHED_LOAD_SCALE | ||
| 5880 | * Lets keep it SCHED_LOAD_SCALE, so that | ||
| 5881 | * while calculating NUMA group's cpu_power | ||
| 5882 | * we can simply do | ||
| 5883 | * numa_group->cpu_power += phys_group->cpu_power; | ||
| 5884 | * | ||
| 5885 | * See "only add power once for each physical pkg" | ||
| 5886 | * comment below | ||
| 5887 | */ | ||
| 5888 | sd->groups->cpu_power = SCHED_LOAD_SCALE; | ||
| 5889 | #else | ||
| 5890 | sd = &per_cpu(phys_domains, i); | ||
| 5803 | power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE * | 5891 | power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE * |
| 5804 | (cpus_weight(sd->groups->cpumask)-1) / 10; | 5892 | (cpus_weight(sd->groups->cpumask)-1) / 10; |
| 5805 | sd->groups->cpu_power = power; | 5893 | sd->groups->cpu_power = power; |
| 5806 | |||
| 5807 | #ifdef CONFIG_NUMA | ||
| 5808 | sd = &per_cpu(allnodes_domains, i); | ||
| 5809 | if (sd->groups) { | ||
| 5810 | power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE * | ||
| 5811 | (cpus_weight(sd->groups->cpumask)-1) / 10; | ||
| 5812 | sd->groups->cpu_power = power; | ||
| 5813 | } | ||
| 5814 | #endif | 5894 | #endif |
| 5815 | } | 5895 | } |
| 5816 | 5896 | ||
| 5817 | #ifdef CONFIG_NUMA | 5897 | #ifdef CONFIG_NUMA |
| 5818 | for (i = 0; i < MAX_NUMNODES; i++) { | 5898 | for (i = 0; i < MAX_NUMNODES; i++) |
| 5819 | struct sched_group *sg = sched_group_nodes[i]; | 5899 | init_numa_sched_groups_power(sched_group_nodes[i]); |
| 5820 | int j; | ||
| 5821 | |||
| 5822 | if (sg == NULL) | ||
| 5823 | continue; | ||
| 5824 | next_sg: | ||
| 5825 | for_each_cpu_mask(j, sg->cpumask) { | ||
| 5826 | struct sched_domain *sd; | ||
| 5827 | int power; | ||
| 5828 | |||
| 5829 | sd = &per_cpu(phys_domains, j); | ||
| 5830 | if (j != first_cpu(sd->groups->cpumask)) { | ||
| 5831 | /* | ||
| 5832 | * Only add "power" once for each | ||
| 5833 | * physical package. | ||
| 5834 | */ | ||
| 5835 | continue; | ||
| 5836 | } | ||
| 5837 | power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE * | ||
| 5838 | (cpus_weight(sd->groups->cpumask)-1) / 10; | ||
| 5839 | 5900 | ||
| 5840 | sg->cpu_power += power; | 5901 | init_numa_sched_groups_power(sched_group_allnodes); |
| 5841 | } | ||
| 5842 | sg = sg->next; | ||
| 5843 | if (sg != sched_group_nodes[i]) | ||
| 5844 | goto next_sg; | ||
| 5845 | } | ||
| 5846 | #endif | 5902 | #endif |
| 5847 | 5903 | ||
| 5848 | /* Attach the domains */ | 5904 | /* Attach the domains */ |
| @@ -5850,6 +5906,8 @@ next_sg: | |||
| 5850 | struct sched_domain *sd; | 5906 | struct sched_domain *sd; |
| 5851 | #ifdef CONFIG_SCHED_SMT | 5907 | #ifdef CONFIG_SCHED_SMT |
| 5852 | sd = &per_cpu(cpu_domains, i); | 5908 | sd = &per_cpu(cpu_domains, i); |
| 5909 | #elif defined(CONFIG_SCHED_MC) | ||
| 5910 | sd = &per_cpu(core_domains, i); | ||
| 5853 | #else | 5911 | #else |
| 5854 | sd = &per_cpu(phys_domains, i); | 5912 | sd = &per_cpu(phys_domains, i); |
| 5855 | #endif | 5913 | #endif |
| @@ -6022,7 +6080,7 @@ void __init sched_init(void) | |||
| 6022 | runqueue_t *rq; | 6080 | runqueue_t *rq; |
| 6023 | int i, j, k; | 6081 | int i, j, k; |
| 6024 | 6082 | ||
| 6025 | for_each_cpu(i) { | 6083 | for_each_possible_cpu(i) { |
| 6026 | prio_array_t *array; | 6084 | prio_array_t *array; |
| 6027 | 6085 | ||
| 6028 | rq = cpu_rq(i); | 6086 | rq = cpu_rq(i); |
diff --git a/kernel/softlockup.c b/kernel/softlockup.c index d9b3d5847ed8..ced91e1ff564 100644 --- a/kernel/softlockup.c +++ b/kernel/softlockup.c | |||
| @@ -152,5 +152,5 @@ __init void spawn_softlockup_task(void) | |||
| 152 | cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); | 152 | cpu_callback(&cpu_nfb, CPU_ONLINE, cpu); |
| 153 | register_cpu_notifier(&cpu_nfb); | 153 | register_cpu_notifier(&cpu_nfb); |
| 154 | 154 | ||
| 155 | notifier_chain_register(&panic_notifier_list, &panic_block); | 155 | atomic_notifier_chain_register(&panic_notifier_list, &panic_block); |
| 156 | } | 156 | } |
diff --git a/kernel/sys.c b/kernel/sys.c index 38bc73ede2ba..c93d37f71aef 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -95,99 +95,304 @@ int cad_pid = 1; | |||
| 95 | * and the like. | 95 | * and the like. |
| 96 | */ | 96 | */ |
| 97 | 97 | ||
| 98 | static struct notifier_block *reboot_notifier_list; | 98 | static BLOCKING_NOTIFIER_HEAD(reboot_notifier_list); |
| 99 | static DEFINE_RWLOCK(notifier_lock); | 99 | |
| 100 | /* | ||
| 101 | * Notifier chain core routines. The exported routines below | ||
| 102 | * are layered on top of these, with appropriate locking added. | ||
| 103 | */ | ||
| 104 | |||
| 105 | static int notifier_chain_register(struct notifier_block **nl, | ||
| 106 | struct notifier_block *n) | ||
| 107 | { | ||
| 108 | while ((*nl) != NULL) { | ||
| 109 | if (n->priority > (*nl)->priority) | ||
| 110 | break; | ||
| 111 | nl = &((*nl)->next); | ||
| 112 | } | ||
| 113 | n->next = *nl; | ||
| 114 | rcu_assign_pointer(*nl, n); | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int notifier_chain_unregister(struct notifier_block **nl, | ||
| 119 | struct notifier_block *n) | ||
| 120 | { | ||
| 121 | while ((*nl) != NULL) { | ||
| 122 | if ((*nl) == n) { | ||
| 123 | rcu_assign_pointer(*nl, n->next); | ||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | nl = &((*nl)->next); | ||
| 127 | } | ||
| 128 | return -ENOENT; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int __kprobes notifier_call_chain(struct notifier_block **nl, | ||
| 132 | unsigned long val, void *v) | ||
| 133 | { | ||
| 134 | int ret = NOTIFY_DONE; | ||
| 135 | struct notifier_block *nb; | ||
| 136 | |||
| 137 | nb = rcu_dereference(*nl); | ||
| 138 | while (nb) { | ||
| 139 | ret = nb->notifier_call(nb, val, v); | ||
| 140 | if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK) | ||
| 141 | break; | ||
| 142 | nb = rcu_dereference(nb->next); | ||
| 143 | } | ||
| 144 | return ret; | ||
| 145 | } | ||
| 146 | |||
| 147 | /* | ||
| 148 | * Atomic notifier chain routines. Registration and unregistration | ||
| 149 | * use a mutex, and call_chain is synchronized by RCU (no locks). | ||
| 150 | */ | ||
| 100 | 151 | ||
| 101 | /** | 152 | /** |
| 102 | * notifier_chain_register - Add notifier to a notifier chain | 153 | * atomic_notifier_chain_register - Add notifier to an atomic notifier chain |
| 103 | * @list: Pointer to root list pointer | 154 | * @nh: Pointer to head of the atomic notifier chain |
| 104 | * @n: New entry in notifier chain | 155 | * @n: New entry in notifier chain |
| 105 | * | 156 | * |
| 106 | * Adds a notifier to a notifier chain. | 157 | * Adds a notifier to an atomic notifier chain. |
| 107 | * | 158 | * |
| 108 | * Currently always returns zero. | 159 | * Currently always returns zero. |
| 109 | */ | 160 | */ |
| 161 | |||
| 162 | int atomic_notifier_chain_register(struct atomic_notifier_head *nh, | ||
| 163 | struct notifier_block *n) | ||
| 164 | { | ||
| 165 | unsigned long flags; | ||
| 166 | int ret; | ||
| 167 | |||
| 168 | spin_lock_irqsave(&nh->lock, flags); | ||
| 169 | ret = notifier_chain_register(&nh->head, n); | ||
| 170 | spin_unlock_irqrestore(&nh->lock, flags); | ||
| 171 | return ret; | ||
| 172 | } | ||
| 173 | |||
| 174 | EXPORT_SYMBOL_GPL(atomic_notifier_chain_register); | ||
| 175 | |||
| 176 | /** | ||
| 177 | * atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain | ||
| 178 | * @nh: Pointer to head of the atomic notifier chain | ||
| 179 | * @n: Entry to remove from notifier chain | ||
| 180 | * | ||
| 181 | * Removes a notifier from an atomic notifier chain. | ||
| 182 | * | ||
| 183 | * Returns zero on success or %-ENOENT on failure. | ||
| 184 | */ | ||
| 185 | int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, | ||
| 186 | struct notifier_block *n) | ||
| 187 | { | ||
| 188 | unsigned long flags; | ||
| 189 | int ret; | ||
| 190 | |||
| 191 | spin_lock_irqsave(&nh->lock, flags); | ||
| 192 | ret = notifier_chain_unregister(&nh->head, n); | ||
| 193 | spin_unlock_irqrestore(&nh->lock, flags); | ||
| 194 | synchronize_rcu(); | ||
| 195 | return ret; | ||
| 196 | } | ||
| 197 | |||
| 198 | EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister); | ||
| 199 | |||
| 200 | /** | ||
| 201 | * atomic_notifier_call_chain - Call functions in an atomic notifier chain | ||
| 202 | * @nh: Pointer to head of the atomic notifier chain | ||
| 203 | * @val: Value passed unmodified to notifier function | ||
| 204 | * @v: Pointer passed unmodified to notifier function | ||
| 205 | * | ||
| 206 | * Calls each function in a notifier chain in turn. The functions | ||
| 207 | * run in an atomic context, so they must not block. | ||
| 208 | * This routine uses RCU to synchronize with changes to the chain. | ||
| 209 | * | ||
| 210 | * If the return value of the notifier can be and'ed | ||
| 211 | * with %NOTIFY_STOP_MASK then atomic_notifier_call_chain | ||
| 212 | * will return immediately, with the return value of | ||
| 213 | * the notifier function which halted execution. | ||
| 214 | * Otherwise the return value is the return value | ||
| 215 | * of the last notifier function called. | ||
| 216 | */ | ||
| 110 | 217 | ||
| 111 | int notifier_chain_register(struct notifier_block **list, struct notifier_block *n) | 218 | int atomic_notifier_call_chain(struct atomic_notifier_head *nh, |
| 219 | unsigned long val, void *v) | ||
| 112 | { | 220 | { |
| 113 | write_lock(¬ifier_lock); | 221 | int ret; |
| 114 | while(*list) | 222 | |
| 115 | { | 223 | rcu_read_lock(); |
| 116 | if(n->priority > (*list)->priority) | 224 | ret = notifier_call_chain(&nh->head, val, v); |
| 117 | break; | 225 | rcu_read_unlock(); |
| 118 | list= &((*list)->next); | 226 | return ret; |
| 119 | } | ||
| 120 | n->next = *list; | ||
| 121 | *list=n; | ||
| 122 | write_unlock(¬ifier_lock); | ||
| 123 | return 0; | ||
| 124 | } | 227 | } |
| 125 | 228 | ||
| 126 | EXPORT_SYMBOL(notifier_chain_register); | 229 | EXPORT_SYMBOL_GPL(atomic_notifier_call_chain); |
| 230 | |||
| 231 | /* | ||
| 232 | * Blocking notifier chain routines. All access to the chain is | ||
| 233 | * synchronized by an rwsem. | ||
| 234 | */ | ||
| 127 | 235 | ||
| 128 | /** | 236 | /** |
| 129 | * notifier_chain_unregister - Remove notifier from a notifier chain | 237 | * blocking_notifier_chain_register - Add notifier to a blocking notifier chain |
| 130 | * @nl: Pointer to root list pointer | 238 | * @nh: Pointer to head of the blocking notifier chain |
| 131 | * @n: New entry in notifier chain | 239 | * @n: New entry in notifier chain |
| 132 | * | 240 | * |
| 133 | * Removes a notifier from a notifier chain. | 241 | * Adds a notifier to a blocking notifier chain. |
| 242 | * Must be called in process context. | ||
| 134 | * | 243 | * |
| 135 | * Returns zero on success, or %-ENOENT on failure. | 244 | * Currently always returns zero. |
| 136 | */ | 245 | */ |
| 137 | 246 | ||
| 138 | int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n) | 247 | int blocking_notifier_chain_register(struct blocking_notifier_head *nh, |
| 248 | struct notifier_block *n) | ||
| 139 | { | 249 | { |
| 140 | write_lock(¬ifier_lock); | 250 | int ret; |
| 141 | while((*nl)!=NULL) | 251 | |
| 142 | { | 252 | /* |
| 143 | if((*nl)==n) | 253 | * This code gets used during boot-up, when task switching is |
| 144 | { | 254 | * not yet working and interrupts must remain disabled. At |
| 145 | *nl=n->next; | 255 | * such times we must not call down_write(). |
| 146 | write_unlock(¬ifier_lock); | 256 | */ |
| 147 | return 0; | 257 | if (unlikely(system_state == SYSTEM_BOOTING)) |
| 148 | } | 258 | return notifier_chain_register(&nh->head, n); |
| 149 | nl=&((*nl)->next); | 259 | |
| 150 | } | 260 | down_write(&nh->rwsem); |
| 151 | write_unlock(¬ifier_lock); | 261 | ret = notifier_chain_register(&nh->head, n); |
| 152 | return -ENOENT; | 262 | up_write(&nh->rwsem); |
| 263 | return ret; | ||
| 153 | } | 264 | } |
| 154 | 265 | ||
| 155 | EXPORT_SYMBOL(notifier_chain_unregister); | 266 | EXPORT_SYMBOL_GPL(blocking_notifier_chain_register); |
| 156 | 267 | ||
| 157 | /** | 268 | /** |
| 158 | * notifier_call_chain - Call functions in a notifier chain | 269 | * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain |
| 159 | * @n: Pointer to root pointer of notifier chain | 270 | * @nh: Pointer to head of the blocking notifier chain |
| 271 | * @n: Entry to remove from notifier chain | ||
| 272 | * | ||
| 273 | * Removes a notifier from a blocking notifier chain. | ||
| 274 | * Must be called from process context. | ||
| 275 | * | ||
| 276 | * Returns zero on success or %-ENOENT on failure. | ||
| 277 | */ | ||
| 278 | int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, | ||
| 279 | struct notifier_block *n) | ||
| 280 | { | ||
| 281 | int ret; | ||
| 282 | |||
| 283 | /* | ||
| 284 | * This code gets used during boot-up, when task switching is | ||
| 285 | * not yet working and interrupts must remain disabled. At | ||
| 286 | * such times we must not call down_write(). | ||
| 287 | */ | ||
| 288 | if (unlikely(system_state == SYSTEM_BOOTING)) | ||
| 289 | return notifier_chain_unregister(&nh->head, n); | ||
| 290 | |||
| 291 | down_write(&nh->rwsem); | ||
| 292 | ret = notifier_chain_unregister(&nh->head, n); | ||
| 293 | up_write(&nh->rwsem); | ||
| 294 | return ret; | ||
| 295 | } | ||
| 296 | |||
| 297 | EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister); | ||
| 298 | |||
| 299 | /** | ||
| 300 | * blocking_notifier_call_chain - Call functions in a blocking notifier chain | ||
| 301 | * @nh: Pointer to head of the blocking notifier chain | ||
| 160 | * @val: Value passed unmodified to notifier function | 302 | * @val: Value passed unmodified to notifier function |
| 161 | * @v: Pointer passed unmodified to notifier function | 303 | * @v: Pointer passed unmodified to notifier function |
| 162 | * | 304 | * |
| 163 | * Calls each function in a notifier chain in turn. | 305 | * Calls each function in a notifier chain in turn. The functions |
| 306 | * run in a process context, so they are allowed to block. | ||
| 164 | * | 307 | * |
| 165 | * If the return value of the notifier can be and'd | 308 | * If the return value of the notifier can be and'ed |
| 166 | * with %NOTIFY_STOP_MASK, then notifier_call_chain | 309 | * with %NOTIFY_STOP_MASK then blocking_notifier_call_chain |
| 167 | * will return immediately, with the return value of | 310 | * will return immediately, with the return value of |
| 168 | * the notifier function which halted execution. | 311 | * the notifier function which halted execution. |
| 169 | * Otherwise, the return value is the return value | 312 | * Otherwise the return value is the return value |
| 170 | * of the last notifier function called. | 313 | * of the last notifier function called. |
| 171 | */ | 314 | */ |
| 172 | 315 | ||
| 173 | int __kprobes notifier_call_chain(struct notifier_block **n, unsigned long val, void *v) | 316 | int blocking_notifier_call_chain(struct blocking_notifier_head *nh, |
| 317 | unsigned long val, void *v) | ||
| 174 | { | 318 | { |
| 175 | int ret=NOTIFY_DONE; | 319 | int ret; |
| 176 | struct notifier_block *nb = *n; | ||
| 177 | 320 | ||
| 178 | while(nb) | 321 | down_read(&nh->rwsem); |
| 179 | { | 322 | ret = notifier_call_chain(&nh->head, val, v); |
| 180 | ret=nb->notifier_call(nb,val,v); | 323 | up_read(&nh->rwsem); |
| 181 | if(ret&NOTIFY_STOP_MASK) | ||
| 182 | { | ||
| 183 | return ret; | ||
| 184 | } | ||
| 185 | nb=nb->next; | ||
| 186 | } | ||
| 187 | return ret; | 324 | return ret; |
| 188 | } | 325 | } |
| 189 | 326 | ||
| 190 | EXPORT_SYMBOL(notifier_call_chain); | 327 | EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); |
| 328 | |||
| 329 | /* | ||
| 330 | * Raw notifier chain routines. There is no protection; | ||
| 331 | * the caller must provide it. Use at your own risk! | ||
| 332 | */ | ||
| 333 | |||
| 334 | /** | ||
| 335 | * raw_notifier_chain_register - Add notifier to a raw notifier chain | ||
| 336 | * @nh: Pointer to head of the raw notifier chain | ||
| 337 | * @n: New entry in notifier chain | ||
| 338 | * | ||
| 339 | * Adds a notifier to a raw notifier chain. | ||
| 340 | * All locking must be provided by the caller. | ||
| 341 | * | ||
| 342 | * Currently always returns zero. | ||
| 343 | */ | ||
| 344 | |||
| 345 | int raw_notifier_chain_register(struct raw_notifier_head *nh, | ||
| 346 | struct notifier_block *n) | ||
| 347 | { | ||
| 348 | return notifier_chain_register(&nh->head, n); | ||
| 349 | } | ||
| 350 | |||
| 351 | EXPORT_SYMBOL_GPL(raw_notifier_chain_register); | ||
| 352 | |||
| 353 | /** | ||
| 354 | * raw_notifier_chain_unregister - Remove notifier from a raw notifier chain | ||
| 355 | * @nh: Pointer to head of the raw notifier chain | ||
| 356 | * @n: Entry to remove from notifier chain | ||
| 357 | * | ||
| 358 | * Removes a notifier from a raw notifier chain. | ||
| 359 | * All locking must be provided by the caller. | ||
| 360 | * | ||
| 361 | * Returns zero on success or %-ENOENT on failure. | ||
| 362 | */ | ||
| 363 | int raw_notifier_chain_unregister(struct raw_notifier_head *nh, | ||
| 364 | struct notifier_block *n) | ||
| 365 | { | ||
| 366 | return notifier_chain_unregister(&nh->head, n); | ||
| 367 | } | ||
| 368 | |||
| 369 | EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister); | ||
| 370 | |||
| 371 | /** | ||
| 372 | * raw_notifier_call_chain - Call functions in a raw notifier chain | ||
| 373 | * @nh: Pointer to head of the raw notifier chain | ||
| 374 | * @val: Value passed unmodified to notifier function | ||
| 375 | * @v: Pointer passed unmodified to notifier function | ||
| 376 | * | ||
| 377 | * Calls each function in a notifier chain in turn. The functions | ||
| 378 | * run in an undefined context. | ||
| 379 | * All locking must be provided by the caller. | ||
| 380 | * | ||
| 381 | * If the return value of the notifier can be and'ed | ||
| 382 | * with %NOTIFY_STOP_MASK then raw_notifier_call_chain | ||
| 383 | * will return immediately, with the return value of | ||
| 384 | * the notifier function which halted execution. | ||
| 385 | * Otherwise the return value is the return value | ||
| 386 | * of the last notifier function called. | ||
| 387 | */ | ||
| 388 | |||
| 389 | int raw_notifier_call_chain(struct raw_notifier_head *nh, | ||
| 390 | unsigned long val, void *v) | ||
| 391 | { | ||
| 392 | return notifier_call_chain(&nh->head, val, v); | ||
| 393 | } | ||
| 394 | |||
| 395 | EXPORT_SYMBOL_GPL(raw_notifier_call_chain); | ||
| 191 | 396 | ||
| 192 | /** | 397 | /** |
| 193 | * register_reboot_notifier - Register function to be called at reboot time | 398 | * register_reboot_notifier - Register function to be called at reboot time |
| @@ -196,13 +401,13 @@ EXPORT_SYMBOL(notifier_call_chain); | |||
| 196 | * Registers a function with the list of functions | 401 | * Registers a function with the list of functions |
| 197 | * to be called at reboot time. | 402 | * to be called at reboot time. |
| 198 | * | 403 | * |
| 199 | * Currently always returns zero, as notifier_chain_register | 404 | * Currently always returns zero, as blocking_notifier_chain_register |
| 200 | * always returns zero. | 405 | * always returns zero. |
| 201 | */ | 406 | */ |
| 202 | 407 | ||
| 203 | int register_reboot_notifier(struct notifier_block * nb) | 408 | int register_reboot_notifier(struct notifier_block * nb) |
| 204 | { | 409 | { |
| 205 | return notifier_chain_register(&reboot_notifier_list, nb); | 410 | return blocking_notifier_chain_register(&reboot_notifier_list, nb); |
| 206 | } | 411 | } |
| 207 | 412 | ||
| 208 | EXPORT_SYMBOL(register_reboot_notifier); | 413 | EXPORT_SYMBOL(register_reboot_notifier); |
| @@ -219,7 +424,7 @@ EXPORT_SYMBOL(register_reboot_notifier); | |||
| 219 | 424 | ||
| 220 | int unregister_reboot_notifier(struct notifier_block * nb) | 425 | int unregister_reboot_notifier(struct notifier_block * nb) |
| 221 | { | 426 | { |
| 222 | return notifier_chain_unregister(&reboot_notifier_list, nb); | 427 | return blocking_notifier_chain_unregister(&reboot_notifier_list, nb); |
| 223 | } | 428 | } |
| 224 | 429 | ||
| 225 | EXPORT_SYMBOL(unregister_reboot_notifier); | 430 | EXPORT_SYMBOL(unregister_reboot_notifier); |
| @@ -380,7 +585,7 @@ EXPORT_SYMBOL_GPL(emergency_restart); | |||
| 380 | 585 | ||
| 381 | void kernel_restart_prepare(char *cmd) | 586 | void kernel_restart_prepare(char *cmd) |
| 382 | { | 587 | { |
| 383 | notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); | 588 | blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); |
| 384 | system_state = SYSTEM_RESTART; | 589 | system_state = SYSTEM_RESTART; |
| 385 | device_shutdown(); | 590 | device_shutdown(); |
| 386 | } | 591 | } |
| @@ -430,7 +635,7 @@ EXPORT_SYMBOL_GPL(kernel_kexec); | |||
| 430 | 635 | ||
| 431 | void kernel_shutdown_prepare(enum system_states state) | 636 | void kernel_shutdown_prepare(enum system_states state) |
| 432 | { | 637 | { |
| 433 | notifier_call_chain(&reboot_notifier_list, | 638 | blocking_notifier_call_chain(&reboot_notifier_list, |
| 434 | (state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL); | 639 | (state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL); |
| 435 | system_state = state; | 640 | system_state = state; |
| 436 | device_shutdown(); | 641 | device_shutdown(); |
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 1067090db6b1..d82864c4a617 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
| @@ -42,6 +42,10 @@ cond_syscall(sys_recvmsg); | |||
| 42 | cond_syscall(sys_socketcall); | 42 | cond_syscall(sys_socketcall); |
| 43 | cond_syscall(sys_futex); | 43 | cond_syscall(sys_futex); |
| 44 | cond_syscall(compat_sys_futex); | 44 | cond_syscall(compat_sys_futex); |
| 45 | cond_syscall(sys_set_robust_list); | ||
| 46 | cond_syscall(compat_sys_set_robust_list); | ||
| 47 | cond_syscall(sys_get_robust_list); | ||
| 48 | cond_syscall(compat_sys_get_robust_list); | ||
| 45 | cond_syscall(sys_epoll_create); | 49 | cond_syscall(sys_epoll_create); |
| 46 | cond_syscall(sys_epoll_ctl); | 50 | cond_syscall(sys_epoll_ctl); |
| 47 | cond_syscall(sys_epoll_wait); | 51 | cond_syscall(sys_epoll_wait); |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 7e70ab13e191..6e8a60f67c7a 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
| @@ -172,7 +172,7 @@ config DEBUG_IOREMAP | |||
| 172 | 172 | ||
| 173 | config DEBUG_FS | 173 | config DEBUG_FS |
| 174 | bool "Debug Filesystem" | 174 | bool "Debug Filesystem" |
| 175 | depends on DEBUG_KERNEL && SYSFS | 175 | depends on SYSFS |
| 176 | help | 176 | help |
| 177 | debugfs is a virtual file system that kernel developers use to put | 177 | debugfs is a virtual file system that kernel developers use to put |
| 178 | debugging files into. Enable this option to be able to read and | 178 | debugging files into. Enable this option to be able to read and |
diff --git a/mm/Makefile b/mm/Makefile index f10c753dce6d..0b8f73f2ed16 100644 --- a/mm/Makefile +++ b/mm/Makefile | |||
| @@ -10,7 +10,7 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \ | |||
| 10 | obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ | 10 | obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ |
| 11 | page_alloc.o page-writeback.o pdflush.o \ | 11 | page_alloc.o page-writeback.o pdflush.o \ |
| 12 | readahead.o swap.o truncate.o vmscan.o \ | 12 | readahead.o swap.o truncate.o vmscan.o \ |
| 13 | prio_tree.o util.o $(mmu-y) | 13 | prio_tree.o util.o mmzone.o $(mmu-y) |
| 14 | 14 | ||
| 15 | obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o | 15 | obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o |
| 16 | obj-$(CONFIG_HUGETLBFS) += hugetlb.o | 16 | obj-$(CONFIG_HUGETLBFS) += hugetlb.o |
diff --git a/mm/bootmem.c b/mm/bootmem.c index b55bd39fc5dd..d3e3bd2ffcea 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
| @@ -33,6 +33,7 @@ EXPORT_SYMBOL(max_pfn); /* This is exported so | |||
| 33 | * dma_get_required_mask(), which uses | 33 | * dma_get_required_mask(), which uses |
| 34 | * it, can be an inline function */ | 34 | * it, can be an inline function */ |
| 35 | 35 | ||
| 36 | static LIST_HEAD(bdata_list); | ||
| 36 | #ifdef CONFIG_CRASH_DUMP | 37 | #ifdef CONFIG_CRASH_DUMP |
| 37 | /* | 38 | /* |
| 38 | * If we have booted due to a crash, max_pfn will be a very low value. We need | 39 | * If we have booted due to a crash, max_pfn will be a very low value. We need |
| @@ -52,6 +53,27 @@ unsigned long __init bootmem_bootmap_pages (unsigned long pages) | |||
| 52 | 53 | ||
| 53 | return mapsize; | 54 | return mapsize; |
| 54 | } | 55 | } |
| 56 | /* | ||
| 57 | * link bdata in order | ||
| 58 | */ | ||
| 59 | static void link_bootmem(bootmem_data_t *bdata) | ||
| 60 | { | ||
| 61 | bootmem_data_t *ent; | ||
| 62 | if (list_empty(&bdata_list)) { | ||
| 63 | list_add(&bdata->list, &bdata_list); | ||
| 64 | return; | ||
| 65 | } | ||
| 66 | /* insert in order */ | ||
| 67 | list_for_each_entry(ent, &bdata_list, list) { | ||
| 68 | if (bdata->node_boot_start < ent->node_boot_start) { | ||
| 69 | list_add_tail(&bdata->list, &ent->list); | ||
| 70 | return; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | list_add_tail(&bdata->list, &bdata_list); | ||
| 74 | return; | ||
| 75 | } | ||
| 76 | |||
| 55 | 77 | ||
| 56 | /* | 78 | /* |
| 57 | * Called once to set up the allocator itself. | 79 | * Called once to set up the allocator itself. |
| @@ -62,13 +84,11 @@ static unsigned long __init init_bootmem_core (pg_data_t *pgdat, | |||
| 62 | bootmem_data_t *bdata = pgdat->bdata; | 84 | bootmem_data_t *bdata = pgdat->bdata; |
| 63 | unsigned long mapsize = ((end - start)+7)/8; | 85 | unsigned long mapsize = ((end - start)+7)/8; |
| 64 | 86 | ||
| 65 | pgdat->pgdat_next = pgdat_list; | ||
| 66 | pgdat_list = pgdat; | ||
| 67 | |||
| 68 | mapsize = ALIGN(mapsize, sizeof(long)); | 87 | mapsize = ALIGN(mapsize, sizeof(long)); |
| 69 | bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT); | 88 | bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT); |
| 70 | bdata->node_boot_start = (start << PAGE_SHIFT); | 89 | bdata->node_boot_start = (start << PAGE_SHIFT); |
| 71 | bdata->node_low_pfn = end; | 90 | bdata->node_low_pfn = end; |
| 91 | link_bootmem(bdata); | ||
| 72 | 92 | ||
| 73 | /* | 93 | /* |
| 74 | * Initially all pages are reserved - setup_arch() has to | 94 | * Initially all pages are reserved - setup_arch() has to |
| @@ -383,12 +403,11 @@ unsigned long __init free_all_bootmem (void) | |||
| 383 | 403 | ||
| 384 | void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal) | 404 | void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal) |
| 385 | { | 405 | { |
| 386 | pg_data_t *pgdat = pgdat_list; | 406 | bootmem_data_t *bdata; |
| 387 | void *ptr; | 407 | void *ptr; |
| 388 | 408 | ||
| 389 | for_each_pgdat(pgdat) | 409 | list_for_each_entry(bdata, &bdata_list, list) |
| 390 | if ((ptr = __alloc_bootmem_core(pgdat->bdata, size, | 410 | if ((ptr = __alloc_bootmem_core(bdata, size, align, goal, 0))) |
| 391 | align, goal, 0))) | ||
| 392 | return(ptr); | 411 | return(ptr); |
| 393 | 412 | ||
| 394 | /* | 413 | /* |
| @@ -416,11 +435,11 @@ void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, unsigne | |||
| 416 | 435 | ||
| 417 | void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, unsigned long goal) | 436 | void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, unsigned long goal) |
| 418 | { | 437 | { |
| 419 | pg_data_t *pgdat = pgdat_list; | 438 | bootmem_data_t *bdata; |
| 420 | void *ptr; | 439 | void *ptr; |
| 421 | 440 | ||
| 422 | for_each_pgdat(pgdat) | 441 | list_for_each_entry(bdata, &bdata_list, list) |
| 423 | if ((ptr = __alloc_bootmem_core(pgdat->bdata, size, | 442 | if ((ptr = __alloc_bootmem_core(bdata, size, |
| 424 | align, goal, LOW32LIMIT))) | 443 | align, goal, LOW32LIMIT))) |
| 425 | return(ptr); | 444 | return(ptr); |
| 426 | 445 | ||
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 4f71cfd29c6f..dec8249e972d 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
| @@ -912,7 +912,7 @@ asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode, | |||
| 912 | /* | 912 | /* |
| 913 | * Check if this process has the right to modify the specified | 913 | * Check if this process has the right to modify the specified |
| 914 | * process. The right exists if the process has administrative | 914 | * process. The right exists if the process has administrative |
| 915 | * capabilities, superuser priviledges or the same | 915 | * capabilities, superuser privileges or the same |
| 916 | * userid as the target process. | 916 | * userid as the target process. |
| 917 | */ | 917 | */ |
| 918 | if ((current->euid != task->suid) && (current->euid != task->uid) && | 918 | if ((current->euid != task->suid) && (current->euid != task->uid) && |
diff --git a/mm/mmzone.c b/mm/mmzone.c new file mode 100644 index 000000000000..b022370e612e --- /dev/null +++ b/mm/mmzone.c | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | /* | ||
| 2 | * linux/mm/mmzone.c | ||
| 3 | * | ||
| 4 | * management codes for pgdats and zones. | ||
| 5 | */ | ||
| 6 | |||
| 7 | |||
| 8 | #include <linux/config.h> | ||
| 9 | #include <linux/stddef.h> | ||
| 10 | #include <linux/mmzone.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | |||
| 13 | struct pglist_data *first_online_pgdat(void) | ||
| 14 | { | ||
| 15 | return NODE_DATA(first_online_node); | ||
| 16 | } | ||
| 17 | |||
| 18 | EXPORT_SYMBOL(first_online_pgdat); | ||
| 19 | |||
| 20 | struct pglist_data *next_online_pgdat(struct pglist_data *pgdat) | ||
| 21 | { | ||
| 22 | int nid = next_online_node(pgdat->node_id); | ||
| 23 | |||
| 24 | if (nid == MAX_NUMNODES) | ||
| 25 | return NULL; | ||
| 26 | return NODE_DATA(nid); | ||
| 27 | } | ||
| 28 | EXPORT_SYMBOL(next_online_pgdat); | ||
| 29 | |||
| 30 | |||
| 31 | /* | ||
| 32 | * next_zone - helper magic for for_each_zone() | ||
| 33 | */ | ||
| 34 | struct zone *next_zone(struct zone *zone) | ||
| 35 | { | ||
| 36 | pg_data_t *pgdat = zone->zone_pgdat; | ||
| 37 | |||
| 38 | if (zone < pgdat->node_zones + MAX_NR_ZONES - 1) | ||
| 39 | zone++; | ||
| 40 | else { | ||
| 41 | pgdat = next_online_pgdat(pgdat); | ||
| 42 | if (pgdat) | ||
| 43 | zone = pgdat->node_zones; | ||
| 44 | else | ||
| 45 | zone = NULL; | ||
| 46 | } | ||
| 47 | return zone; | ||
| 48 | } | ||
| 49 | EXPORT_SYMBOL(next_zone); | ||
| 50 | |||
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 338a02bb004d..dc523a1f270d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -49,7 +49,6 @@ nodemask_t node_online_map __read_mostly = { { [0] = 1UL } }; | |||
| 49 | EXPORT_SYMBOL(node_online_map); | 49 | EXPORT_SYMBOL(node_online_map); |
| 50 | nodemask_t node_possible_map __read_mostly = NODE_MASK_ALL; | 50 | nodemask_t node_possible_map __read_mostly = NODE_MASK_ALL; |
| 51 | EXPORT_SYMBOL(node_possible_map); | 51 | EXPORT_SYMBOL(node_possible_map); |
| 52 | struct pglist_data *pgdat_list __read_mostly; | ||
| 53 | unsigned long totalram_pages __read_mostly; | 52 | unsigned long totalram_pages __read_mostly; |
| 54 | unsigned long totalhigh_pages __read_mostly; | 53 | unsigned long totalhigh_pages __read_mostly; |
| 55 | long nr_swap_pages; | 54 | long nr_swap_pages; |
| @@ -1201,7 +1200,7 @@ unsigned int nr_free_highpages (void) | |||
| 1201 | pg_data_t *pgdat; | 1200 | pg_data_t *pgdat; |
| 1202 | unsigned int pages = 0; | 1201 | unsigned int pages = 0; |
| 1203 | 1202 | ||
| 1204 | for_each_pgdat(pgdat) | 1203 | for_each_online_pgdat(pgdat) |
| 1205 | pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages; | 1204 | pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages; |
| 1206 | 1205 | ||
| 1207 | return pages; | 1206 | return pages; |
| @@ -1343,7 +1342,7 @@ void get_zone_counts(unsigned long *active, | |||
| 1343 | *active = 0; | 1342 | *active = 0; |
| 1344 | *inactive = 0; | 1343 | *inactive = 0; |
| 1345 | *free = 0; | 1344 | *free = 0; |
| 1346 | for_each_pgdat(pgdat) { | 1345 | for_each_online_pgdat(pgdat) { |
| 1347 | unsigned long l, m, n; | 1346 | unsigned long l, m, n; |
| 1348 | __get_zone_counts(&l, &m, &n, pgdat); | 1347 | __get_zone_counts(&l, &m, &n, pgdat); |
| 1349 | *active += l; | 1348 | *active += l; |
| @@ -2042,7 +2041,6 @@ static __meminit void init_currently_empty_zone(struct zone *zone, | |||
| 2042 | zone_wait_table_init(zone, size); | 2041 | zone_wait_table_init(zone, size); |
| 2043 | pgdat->nr_zones = zone_idx(zone) + 1; | 2042 | pgdat->nr_zones = zone_idx(zone) + 1; |
| 2044 | 2043 | ||
| 2045 | zone->zone_mem_map = pfn_to_page(zone_start_pfn); | ||
| 2046 | zone->zone_start_pfn = zone_start_pfn; | 2044 | zone->zone_start_pfn = zone_start_pfn; |
| 2047 | 2045 | ||
| 2048 | memmap_init(size, pgdat->node_id, zone_idx(zone), zone_start_pfn); | 2046 | memmap_init(size, pgdat->node_id, zone_idx(zone), zone_start_pfn); |
| @@ -2170,8 +2168,9 @@ static void *frag_start(struct seq_file *m, loff_t *pos) | |||
| 2170 | { | 2168 | { |
| 2171 | pg_data_t *pgdat; | 2169 | pg_data_t *pgdat; |
| 2172 | loff_t node = *pos; | 2170 | loff_t node = *pos; |
| 2173 | 2171 | for (pgdat = first_online_pgdat(); | |
| 2174 | for (pgdat = pgdat_list; pgdat && node; pgdat = pgdat->pgdat_next) | 2172 | pgdat && node; |
| 2173 | pgdat = next_online_pgdat(pgdat)) | ||
| 2175 | --node; | 2174 | --node; |
| 2176 | 2175 | ||
| 2177 | return pgdat; | 2176 | return pgdat; |
| @@ -2182,7 +2181,7 @@ static void *frag_next(struct seq_file *m, void *arg, loff_t *pos) | |||
| 2182 | pg_data_t *pgdat = (pg_data_t *)arg; | 2181 | pg_data_t *pgdat = (pg_data_t *)arg; |
| 2183 | 2182 | ||
| 2184 | (*pos)++; | 2183 | (*pos)++; |
| 2185 | return pgdat->pgdat_next; | 2184 | return next_online_pgdat(pgdat); |
| 2186 | } | 2185 | } |
| 2187 | 2186 | ||
| 2188 | static void frag_stop(struct seq_file *m, void *arg) | 2187 | static void frag_stop(struct seq_file *m, void *arg) |
| @@ -2483,7 +2482,7 @@ static void setup_per_zone_lowmem_reserve(void) | |||
| 2483 | struct pglist_data *pgdat; | 2482 | struct pglist_data *pgdat; |
| 2484 | int j, idx; | 2483 | int j, idx; |
| 2485 | 2484 | ||
| 2486 | for_each_pgdat(pgdat) { | 2485 | for_each_online_pgdat(pgdat) { |
| 2487 | for (j = 0; j < MAX_NR_ZONES; j++) { | 2486 | for (j = 0; j < MAX_NR_ZONES; j++) { |
| 2488 | struct zone *zone = pgdat->node_zones + j; | 2487 | struct zone *zone = pgdat->node_zones + j; |
| 2489 | unsigned long present_pages = zone->present_pages; | 2488 | unsigned long present_pages = zone->present_pages; |
| @@ -2745,3 +2744,44 @@ void *__init alloc_large_system_hash(const char *tablename, | |||
| 2745 | 2744 | ||
| 2746 | return table; | 2745 | return table; |
| 2747 | } | 2746 | } |
| 2747 | |||
| 2748 | #ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE | ||
| 2749 | /* | ||
| 2750 | * pfn <-> page translation. out-of-line version. | ||
| 2751 | * (see asm-generic/memory_model.h) | ||
| 2752 | */ | ||
| 2753 | #if defined(CONFIG_FLATMEM) | ||
| 2754 | struct page *pfn_to_page(unsigned long pfn) | ||
| 2755 | { | ||
| 2756 | return mem_map + (pfn - ARCH_PFN_OFFSET); | ||
| 2757 | } | ||
| 2758 | unsigned long page_to_pfn(struct page *page) | ||
| 2759 | { | ||
| 2760 | return (page - mem_map) + ARCH_PFN_OFFSET; | ||
| 2761 | } | ||
| 2762 | #elif defined(CONFIG_DISCONTIGMEM) | ||
| 2763 | struct page *pfn_to_page(unsigned long pfn) | ||
| 2764 | { | ||
| 2765 | int nid = arch_pfn_to_nid(pfn); | ||
| 2766 | return NODE_DATA(nid)->node_mem_map + arch_local_page_offset(pfn,nid); | ||
| 2767 | } | ||
| 2768 | unsigned long page_to_pfn(struct page *page) | ||
| 2769 | { | ||
| 2770 | struct pglist_data *pgdat = NODE_DATA(page_to_nid(page)); | ||
| 2771 | return (page - pgdat->node_mem_map) + pgdat->node_start_pfn; | ||
| 2772 | } | ||
| 2773 | #elif defined(CONFIG_SPARSEMEM) | ||
| 2774 | struct page *pfn_to_page(unsigned long pfn) | ||
| 2775 | { | ||
| 2776 | return __section_mem_map_addr(__pfn_to_section(pfn)) + pfn; | ||
| 2777 | } | ||
| 2778 | |||
| 2779 | unsigned long page_to_pfn(struct page *page) | ||
| 2780 | { | ||
| 2781 | long section_id = page_to_section(page); | ||
| 2782 | return page - __section_mem_map_addr(__nr_to_section(section_id)); | ||
| 2783 | } | ||
| 2784 | #endif /* CONFIG_FLATMEM/DISCONTIGMME/SPARSEMEM */ | ||
| 2785 | EXPORT_SYMBOL(pfn_to_page); | ||
| 2786 | EXPORT_SYMBOL(page_to_pfn); | ||
| 2787 | #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */ | ||
| @@ -3311,7 +3311,7 @@ void *__alloc_percpu(size_t size) | |||
| 3311 | * and we have no way of figuring out how to fix the array | 3311 | * and we have no way of figuring out how to fix the array |
| 3312 | * that we have allocated then.... | 3312 | * that we have allocated then.... |
| 3313 | */ | 3313 | */ |
| 3314 | for_each_cpu(i) { | 3314 | for_each_possible_cpu(i) { |
| 3315 | int node = cpu_to_node(i); | 3315 | int node = cpu_to_node(i); |
| 3316 | 3316 | ||
| 3317 | if (node_online(node)) | 3317 | if (node_online(node)) |
| @@ -3398,7 +3398,7 @@ void free_percpu(const void *objp) | |||
| 3398 | /* | 3398 | /* |
| 3399 | * We allocate for all cpus so we cannot use for online cpu here. | 3399 | * We allocate for all cpus so we cannot use for online cpu here. |
| 3400 | */ | 3400 | */ |
| 3401 | for_each_cpu(i) | 3401 | for_each_possible_cpu(i) |
| 3402 | kfree(p->ptrs[i]); | 3402 | kfree(p->ptrs[i]); |
| 3403 | kfree(p); | 3403 | kfree(p); |
| 3404 | } | 3404 | } |
| @@ -512,7 +512,7 @@ long percpu_counter_sum(struct percpu_counter *fbc) | |||
| 512 | 512 | ||
| 513 | spin_lock(&fbc->lock); | 513 | spin_lock(&fbc->lock); |
| 514 | ret = fbc->count; | 514 | ret = fbc->count; |
| 515 | for_each_cpu(cpu) { | 515 | for_each_possible_cpu(cpu) { |
| 516 | long *pcount = per_cpu_ptr(fbc->counters, cpu); | 516 | long *pcount = per_cpu_ptr(fbc->counters, cpu); |
| 517 | ret += *pcount; | 517 | ret += *pcount; |
| 518 | } | 518 | } |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 78865c849f8f..acdf001d6941 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
| @@ -1305,7 +1305,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages) | |||
| 1305 | 1305 | ||
| 1306 | current->reclaim_state = &reclaim_state; | 1306 | current->reclaim_state = &reclaim_state; |
| 1307 | repeat: | 1307 | repeat: |
| 1308 | for_each_pgdat(pgdat) { | 1308 | for_each_online_pgdat(pgdat) { |
| 1309 | unsigned long freed; | 1309 | unsigned long freed; |
| 1310 | 1310 | ||
| 1311 | freed = balance_pgdat(pgdat, nr_to_free, 0); | 1311 | freed = balance_pgdat(pgdat, nr_to_free, 0); |
| @@ -1335,7 +1335,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb, | |||
| 1335 | cpumask_t mask; | 1335 | cpumask_t mask; |
| 1336 | 1336 | ||
| 1337 | if (action == CPU_ONLINE) { | 1337 | if (action == CPU_ONLINE) { |
| 1338 | for_each_pgdat(pgdat) { | 1338 | for_each_online_pgdat(pgdat) { |
| 1339 | mask = node_to_cpumask(pgdat->node_id); | 1339 | mask = node_to_cpumask(pgdat->node_id); |
| 1340 | if (any_online_cpu(mask) != NR_CPUS) | 1340 | if (any_online_cpu(mask) != NR_CPUS) |
| 1341 | /* One of our CPUs online: restore mask */ | 1341 | /* One of our CPUs online: restore mask */ |
| @@ -1351,7 +1351,7 @@ static int __init kswapd_init(void) | |||
| 1351 | pg_data_t *pgdat; | 1351 | pg_data_t *pgdat; |
| 1352 | 1352 | ||
| 1353 | swap_setup(); | 1353 | swap_setup(); |
| 1354 | for_each_pgdat(pgdat) { | 1354 | for_each_online_pgdat(pgdat) { |
| 1355 | pid_t pid; | 1355 | pid_t pid; |
| 1356 | 1356 | ||
| 1357 | pid = kernel_thread(kswapd, pgdat, CLONE_KERNEL); | 1357 | pid = kernel_thread(kswapd, pgdat, CLONE_KERNEL); |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 9106354c781e..a49a6975092d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
| @@ -73,23 +73,23 @@ DEFINE_RWLOCK(hci_cb_list_lock); | |||
| 73 | struct hci_proto *hci_proto[HCI_MAX_PROTO]; | 73 | struct hci_proto *hci_proto[HCI_MAX_PROTO]; |
| 74 | 74 | ||
| 75 | /* HCI notifiers list */ | 75 | /* HCI notifiers list */ |
| 76 | static struct notifier_block *hci_notifier; | 76 | static ATOMIC_NOTIFIER_HEAD(hci_notifier); |
| 77 | 77 | ||
| 78 | /* ---- HCI notifications ---- */ | 78 | /* ---- HCI notifications ---- */ |
| 79 | 79 | ||
| 80 | int hci_register_notifier(struct notifier_block *nb) | 80 | int hci_register_notifier(struct notifier_block *nb) |
| 81 | { | 81 | { |
| 82 | return notifier_chain_register(&hci_notifier, nb); | 82 | return atomic_notifier_chain_register(&hci_notifier, nb); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | int hci_unregister_notifier(struct notifier_block *nb) | 85 | int hci_unregister_notifier(struct notifier_block *nb) |
| 86 | { | 86 | { |
| 87 | return notifier_chain_unregister(&hci_notifier, nb); | 87 | return atomic_notifier_chain_unregister(&hci_notifier, nb); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static void hci_notify(struct hci_dev *hdev, int event) | 90 | static void hci_notify(struct hci_dev *hdev, int event) |
| 91 | { | 91 | { |
| 92 | notifier_call_chain(&hci_notifier, event, hdev); | 92 | atomic_notifier_call_chain(&hci_notifier, event, hdev); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | /* ---- HCI requests ---- */ | 95 | /* ---- HCI requests ---- */ |
diff --git a/net/core/dev.c b/net/core/dev.c index 8e1dc3051222..a3ab11f34153 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -193,7 +193,7 @@ static inline struct hlist_head *dev_index_hash(int ifindex) | |||
| 193 | * Our notifier list | 193 | * Our notifier list |
| 194 | */ | 194 | */ |
| 195 | 195 | ||
| 196 | static struct notifier_block *netdev_chain; | 196 | static BLOCKING_NOTIFIER_HEAD(netdev_chain); |
| 197 | 197 | ||
| 198 | /* | 198 | /* |
| 199 | * Device drivers call our routines to queue packets here. We empty the | 199 | * Device drivers call our routines to queue packets here. We empty the |
| @@ -736,7 +736,8 @@ int dev_change_name(struct net_device *dev, char *newname) | |||
| 736 | if (!err) { | 736 | if (!err) { |
| 737 | hlist_del(&dev->name_hlist); | 737 | hlist_del(&dev->name_hlist); |
| 738 | hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); | 738 | hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); |
| 739 | notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); | 739 | blocking_notifier_call_chain(&netdev_chain, |
| 740 | NETDEV_CHANGENAME, dev); | ||
| 740 | } | 741 | } |
| 741 | 742 | ||
| 742 | return err; | 743 | return err; |
| @@ -750,7 +751,7 @@ int dev_change_name(struct net_device *dev, char *newname) | |||
| 750 | */ | 751 | */ |
| 751 | void netdev_features_change(struct net_device *dev) | 752 | void netdev_features_change(struct net_device *dev) |
| 752 | { | 753 | { |
| 753 | notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev); | 754 | blocking_notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev); |
| 754 | } | 755 | } |
| 755 | EXPORT_SYMBOL(netdev_features_change); | 756 | EXPORT_SYMBOL(netdev_features_change); |
| 756 | 757 | ||
| @@ -765,7 +766,8 @@ EXPORT_SYMBOL(netdev_features_change); | |||
| 765 | void netdev_state_change(struct net_device *dev) | 766 | void netdev_state_change(struct net_device *dev) |
| 766 | { | 767 | { |
| 767 | if (dev->flags & IFF_UP) { | 768 | if (dev->flags & IFF_UP) { |
| 768 | notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev); | 769 | blocking_notifier_call_chain(&netdev_chain, |
| 770 | NETDEV_CHANGE, dev); | ||
| 769 | rtmsg_ifinfo(RTM_NEWLINK, dev, 0); | 771 | rtmsg_ifinfo(RTM_NEWLINK, dev, 0); |
| 770 | } | 772 | } |
| 771 | } | 773 | } |
| @@ -862,7 +864,7 @@ int dev_open(struct net_device *dev) | |||
| 862 | /* | 864 | /* |
| 863 | * ... and announce new interface. | 865 | * ... and announce new interface. |
| 864 | */ | 866 | */ |
| 865 | notifier_call_chain(&netdev_chain, NETDEV_UP, dev); | 867 | blocking_notifier_call_chain(&netdev_chain, NETDEV_UP, dev); |
| 866 | } | 868 | } |
| 867 | return ret; | 869 | return ret; |
| 868 | } | 870 | } |
| @@ -885,7 +887,7 @@ int dev_close(struct net_device *dev) | |||
| 885 | * Tell people we are going down, so that they can | 887 | * Tell people we are going down, so that they can |
| 886 | * prepare to death, when device is still operating. | 888 | * prepare to death, when device is still operating. |
| 887 | */ | 889 | */ |
| 888 | notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev); | 890 | blocking_notifier_call_chain(&netdev_chain, NETDEV_GOING_DOWN, dev); |
| 889 | 891 | ||
| 890 | dev_deactivate(dev); | 892 | dev_deactivate(dev); |
| 891 | 893 | ||
| @@ -922,7 +924,7 @@ int dev_close(struct net_device *dev) | |||
| 922 | /* | 924 | /* |
| 923 | * Tell people we are down | 925 | * Tell people we are down |
| 924 | */ | 926 | */ |
| 925 | notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev); | 927 | blocking_notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev); |
| 926 | 928 | ||
| 927 | return 0; | 929 | return 0; |
| 928 | } | 930 | } |
| @@ -953,7 +955,7 @@ int register_netdevice_notifier(struct notifier_block *nb) | |||
| 953 | int err; | 955 | int err; |
| 954 | 956 | ||
| 955 | rtnl_lock(); | 957 | rtnl_lock(); |
| 956 | err = notifier_chain_register(&netdev_chain, nb); | 958 | err = blocking_notifier_chain_register(&netdev_chain, nb); |
| 957 | if (!err) { | 959 | if (!err) { |
| 958 | for (dev = dev_base; dev; dev = dev->next) { | 960 | for (dev = dev_base; dev; dev = dev->next) { |
| 959 | nb->notifier_call(nb, NETDEV_REGISTER, dev); | 961 | nb->notifier_call(nb, NETDEV_REGISTER, dev); |
| @@ -981,7 +983,7 @@ int unregister_netdevice_notifier(struct notifier_block *nb) | |||
| 981 | int err; | 983 | int err; |
| 982 | 984 | ||
| 983 | rtnl_lock(); | 985 | rtnl_lock(); |
| 984 | err = notifier_chain_unregister(&netdev_chain, nb); | 986 | err = blocking_notifier_chain_unregister(&netdev_chain, nb); |
| 985 | rtnl_unlock(); | 987 | rtnl_unlock(); |
| 986 | return err; | 988 | return err; |
| 987 | } | 989 | } |
| @@ -992,12 +994,12 @@ int unregister_netdevice_notifier(struct notifier_block *nb) | |||
| 992 | * @v: pointer passed unmodified to notifier function | 994 | * @v: pointer passed unmodified to notifier function |
| 993 | * | 995 | * |
| 994 | * Call all network notifier blocks. Parameters and return value | 996 | * Call all network notifier blocks. Parameters and return value |
| 995 | * are as for notifier_call_chain(). | 997 | * are as for blocking_notifier_call_chain(). |
| 996 | */ | 998 | */ |
| 997 | 999 | ||
| 998 | int call_netdevice_notifiers(unsigned long val, void *v) | 1000 | int call_netdevice_notifiers(unsigned long val, void *v) |
| 999 | { | 1001 | { |
| 1000 | return notifier_call_chain(&netdev_chain, val, v); | 1002 | return blocking_notifier_call_chain(&netdev_chain, val, v); |
| 1001 | } | 1003 | } |
| 1002 | 1004 | ||
| 1003 | /* When > 0 there are consumers of rx skb time stamps */ | 1005 | /* When > 0 there are consumers of rx skb time stamps */ |
| @@ -2242,7 +2244,8 @@ int dev_change_flags(struct net_device *dev, unsigned flags) | |||
| 2242 | if (dev->flags & IFF_UP && | 2244 | if (dev->flags & IFF_UP && |
| 2243 | ((old_flags ^ dev->flags) &~ (IFF_UP | IFF_PROMISC | IFF_ALLMULTI | | 2245 | ((old_flags ^ dev->flags) &~ (IFF_UP | IFF_PROMISC | IFF_ALLMULTI | |
| 2244 | IFF_VOLATILE))) | 2246 | IFF_VOLATILE))) |
| 2245 | notifier_call_chain(&netdev_chain, NETDEV_CHANGE, dev); | 2247 | blocking_notifier_call_chain(&netdev_chain, |
| 2248 | NETDEV_CHANGE, dev); | ||
| 2246 | 2249 | ||
| 2247 | if ((flags ^ dev->gflags) & IFF_PROMISC) { | 2250 | if ((flags ^ dev->gflags) & IFF_PROMISC) { |
| 2248 | int inc = (flags & IFF_PROMISC) ? +1 : -1; | 2251 | int inc = (flags & IFF_PROMISC) ? +1 : -1; |
| @@ -2286,8 +2289,8 @@ int dev_set_mtu(struct net_device *dev, int new_mtu) | |||
| 2286 | else | 2289 | else |
| 2287 | dev->mtu = new_mtu; | 2290 | dev->mtu = new_mtu; |
| 2288 | if (!err && dev->flags & IFF_UP) | 2291 | if (!err && dev->flags & IFF_UP) |
| 2289 | notifier_call_chain(&netdev_chain, | 2292 | blocking_notifier_call_chain(&netdev_chain, |
| 2290 | NETDEV_CHANGEMTU, dev); | 2293 | NETDEV_CHANGEMTU, dev); |
| 2291 | return err; | 2294 | return err; |
| 2292 | } | 2295 | } |
| 2293 | 2296 | ||
| @@ -2303,7 +2306,8 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) | |||
| 2303 | return -ENODEV; | 2306 | return -ENODEV; |
| 2304 | err = dev->set_mac_address(dev, sa); | 2307 | err = dev->set_mac_address(dev, sa); |
| 2305 | if (!err) | 2308 | if (!err) |
| 2306 | notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev); | 2309 | blocking_notifier_call_chain(&netdev_chain, |
| 2310 | NETDEV_CHANGEADDR, dev); | ||
| 2307 | return err; | 2311 | return err; |
| 2308 | } | 2312 | } |
| 2309 | 2313 | ||
| @@ -2359,7 +2363,7 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd) | |||
| 2359 | return -EINVAL; | 2363 | return -EINVAL; |
| 2360 | memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, | 2364 | memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, |
| 2361 | min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len)); | 2365 | min(sizeof ifr->ifr_hwaddr.sa_data, (size_t) dev->addr_len)); |
| 2362 | notifier_call_chain(&netdev_chain, | 2366 | blocking_notifier_call_chain(&netdev_chain, |
| 2363 | NETDEV_CHANGEADDR, dev); | 2367 | NETDEV_CHANGEADDR, dev); |
| 2364 | return 0; | 2368 | return 0; |
| 2365 | 2369 | ||
| @@ -2813,7 +2817,7 @@ int register_netdevice(struct net_device *dev) | |||
| 2813 | write_unlock_bh(&dev_base_lock); | 2817 | write_unlock_bh(&dev_base_lock); |
| 2814 | 2818 | ||
| 2815 | /* Notify protocols, that a new device appeared. */ | 2819 | /* Notify protocols, that a new device appeared. */ |
| 2816 | notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev); | 2820 | blocking_notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev); |
| 2817 | 2821 | ||
| 2818 | /* Finish registration after unlock */ | 2822 | /* Finish registration after unlock */ |
| 2819 | net_set_todo(dev); | 2823 | net_set_todo(dev); |
| @@ -2892,7 +2896,7 @@ static void netdev_wait_allrefs(struct net_device *dev) | |||
| 2892 | rtnl_lock(); | 2896 | rtnl_lock(); |
| 2893 | 2897 | ||
| 2894 | /* Rebroadcast unregister notification */ | 2898 | /* Rebroadcast unregister notification */ |
| 2895 | notifier_call_chain(&netdev_chain, | 2899 | blocking_notifier_call_chain(&netdev_chain, |
| 2896 | NETDEV_UNREGISTER, dev); | 2900 | NETDEV_UNREGISTER, dev); |
| 2897 | 2901 | ||
| 2898 | if (test_bit(__LINK_STATE_LINKWATCH_PENDING, | 2902 | if (test_bit(__LINK_STATE_LINKWATCH_PENDING, |
| @@ -3148,7 +3152,7 @@ int unregister_netdevice(struct net_device *dev) | |||
| 3148 | /* Notify protocols, that we are about to destroy | 3152 | /* Notify protocols, that we are about to destroy |
| 3149 | this device. They should clean all the things. | 3153 | this device. They should clean all the things. |
| 3150 | */ | 3154 | */ |
| 3151 | notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); | 3155 | blocking_notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev); |
| 3152 | 3156 | ||
| 3153 | /* | 3157 | /* |
| 3154 | * Flush the multicast chain | 3158 | * Flush the multicast chain |
diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 98f0fc923f91..1e44eda1fda9 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c | |||
| @@ -51,7 +51,7 @@ int reqsk_queue_alloc(struct request_sock_queue *queue, | |||
| 51 | 51 | ||
| 52 | get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); | 52 | get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); |
| 53 | rwlock_init(&queue->syn_wait_lock); | 53 | rwlock_init(&queue->syn_wait_lock); |
| 54 | queue->rskq_accept_head = queue->rskq_accept_head = NULL; | 54 | queue->rskq_accept_head = NULL; |
| 55 | lopt->nr_table_entries = nr_table_entries; | 55 | lopt->nr_table_entries = nr_table_entries; |
| 56 | 56 | ||
| 57 | write_lock_bh(&queue->syn_wait_lock); | 57 | write_lock_bh(&queue->syn_wait_lock); |
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index cc7b9d9255ef..d2ae9893ca17 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c | |||
| @@ -68,7 +68,7 @@ __le16 decnet_address = 0; | |||
| 68 | 68 | ||
| 69 | static DEFINE_RWLOCK(dndev_lock); | 69 | static DEFINE_RWLOCK(dndev_lock); |
| 70 | static struct net_device *decnet_default_device; | 70 | static struct net_device *decnet_default_device; |
| 71 | static struct notifier_block *dnaddr_chain; | 71 | static BLOCKING_NOTIFIER_HEAD(dnaddr_chain); |
| 72 | 72 | ||
| 73 | static struct dn_dev *dn_dev_create(struct net_device *dev, int *err); | 73 | static struct dn_dev *dn_dev_create(struct net_device *dev, int *err); |
| 74 | static void dn_dev_delete(struct net_device *dev); | 74 | static void dn_dev_delete(struct net_device *dev); |
| @@ -446,7 +446,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de | |||
| 446 | } | 446 | } |
| 447 | 447 | ||
| 448 | rtmsg_ifa(RTM_DELADDR, ifa1); | 448 | rtmsg_ifa(RTM_DELADDR, ifa1); |
| 449 | notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1); | 449 | blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1); |
| 450 | if (destroy) { | 450 | if (destroy) { |
| 451 | dn_dev_free_ifa(ifa1); | 451 | dn_dev_free_ifa(ifa1); |
| 452 | 452 | ||
| @@ -481,7 +481,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) | |||
| 481 | dn_db->ifa_list = ifa; | 481 | dn_db->ifa_list = ifa; |
| 482 | 482 | ||
| 483 | rtmsg_ifa(RTM_NEWADDR, ifa); | 483 | rtmsg_ifa(RTM_NEWADDR, ifa); |
| 484 | notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); | 484 | blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); |
| 485 | 485 | ||
| 486 | return 0; | 486 | return 0; |
| 487 | } | 487 | } |
| @@ -1285,12 +1285,12 @@ void dn_dev_devices_on(void) | |||
| 1285 | 1285 | ||
| 1286 | int register_dnaddr_notifier(struct notifier_block *nb) | 1286 | int register_dnaddr_notifier(struct notifier_block *nb) |
| 1287 | { | 1287 | { |
| 1288 | return notifier_chain_register(&dnaddr_chain, nb); | 1288 | return blocking_notifier_chain_register(&dnaddr_chain, nb); |
| 1289 | } | 1289 | } |
| 1290 | 1290 | ||
| 1291 | int unregister_dnaddr_notifier(struct notifier_block *nb) | 1291 | int unregister_dnaddr_notifier(struct notifier_block *nb) |
| 1292 | { | 1292 | { |
| 1293 | return notifier_chain_unregister(&dnaddr_chain, nb); | 1293 | return blocking_notifier_chain_unregister(&dnaddr_chain, nb); |
| 1294 | } | 1294 | } |
| 1295 | 1295 | ||
| 1296 | #ifdef CONFIG_PROC_FS | 1296 | #ifdef CONFIG_PROC_FS |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 44fdf1413e2c..81c2f7885292 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
| @@ -81,7 +81,7 @@ static struct ipv4_devconf ipv4_devconf_dflt = { | |||
| 81 | 81 | ||
| 82 | static void rtmsg_ifa(int event, struct in_ifaddr *); | 82 | static void rtmsg_ifa(int event, struct in_ifaddr *); |
| 83 | 83 | ||
| 84 | static struct notifier_block *inetaddr_chain; | 84 | static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); |
| 85 | static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | 85 | static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, |
| 86 | int destroy); | 86 | int destroy); |
| 87 | #ifdef CONFIG_SYSCTL | 87 | #ifdef CONFIG_SYSCTL |
| @@ -267,7 +267,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
| 267 | *ifap1 = ifa->ifa_next; | 267 | *ifap1 = ifa->ifa_next; |
| 268 | 268 | ||
| 269 | rtmsg_ifa(RTM_DELADDR, ifa); | 269 | rtmsg_ifa(RTM_DELADDR, ifa); |
| 270 | notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); | 270 | blocking_notifier_call_chain(&inetaddr_chain, |
| 271 | NETDEV_DOWN, ifa); | ||
| 271 | inet_free_ifa(ifa); | 272 | inet_free_ifa(ifa); |
| 272 | } else { | 273 | } else { |
| 273 | promote = ifa; | 274 | promote = ifa; |
| @@ -291,7 +292,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
| 291 | So that, this order is correct. | 292 | So that, this order is correct. |
| 292 | */ | 293 | */ |
| 293 | rtmsg_ifa(RTM_DELADDR, ifa1); | 294 | rtmsg_ifa(RTM_DELADDR, ifa1); |
| 294 | notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); | 295 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); |
| 295 | 296 | ||
| 296 | if (promote) { | 297 | if (promote) { |
| 297 | 298 | ||
| @@ -303,7 +304,8 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
| 303 | 304 | ||
| 304 | promote->ifa_flags &= ~IFA_F_SECONDARY; | 305 | promote->ifa_flags &= ~IFA_F_SECONDARY; |
| 305 | rtmsg_ifa(RTM_NEWADDR, promote); | 306 | rtmsg_ifa(RTM_NEWADDR, promote); |
| 306 | notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote); | 307 | blocking_notifier_call_chain(&inetaddr_chain, |
| 308 | NETDEV_UP, promote); | ||
| 307 | for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { | 309 | for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { |
| 308 | if (ifa1->ifa_mask != ifa->ifa_mask || | 310 | if (ifa1->ifa_mask != ifa->ifa_mask || |
| 309 | !inet_ifa_match(ifa1->ifa_address, ifa)) | 311 | !inet_ifa_match(ifa1->ifa_address, ifa)) |
| @@ -366,7 +368,7 @@ static int inet_insert_ifa(struct in_ifaddr *ifa) | |||
| 366 | Notifier will trigger FIB update, so that | 368 | Notifier will trigger FIB update, so that |
| 367 | listeners of netlink will know about new ifaddr */ | 369 | listeners of netlink will know about new ifaddr */ |
| 368 | rtmsg_ifa(RTM_NEWADDR, ifa); | 370 | rtmsg_ifa(RTM_NEWADDR, ifa); |
| 369 | notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); | 371 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); |
| 370 | 372 | ||
| 371 | return 0; | 373 | return 0; |
| 372 | } | 374 | } |
| @@ -938,12 +940,12 @@ u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scop | |||
| 938 | 940 | ||
| 939 | int register_inetaddr_notifier(struct notifier_block *nb) | 941 | int register_inetaddr_notifier(struct notifier_block *nb) |
| 940 | { | 942 | { |
| 941 | return notifier_chain_register(&inetaddr_chain, nb); | 943 | return blocking_notifier_chain_register(&inetaddr_chain, nb); |
| 942 | } | 944 | } |
| 943 | 945 | ||
| 944 | int unregister_inetaddr_notifier(struct notifier_block *nb) | 946 | int unregister_inetaddr_notifier(struct notifier_block *nb) |
| 945 | { | 947 | { |
| 946 | return notifier_chain_unregister(&inetaddr_chain, nb); | 948 | return blocking_notifier_chain_unregister(&inetaddr_chain, nb); |
| 947 | } | 949 | } |
| 948 | 950 | ||
| 949 | /* Rename ifa_labels for a device name change. Make some effort to preserve existing | 951 | /* Rename ifa_labels for a device name change. Make some effort to preserve existing |
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 9e34034729a6..ceaabc18202b 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c | |||
| @@ -80,8 +80,8 @@ static int ip_conntrack_vmalloc; | |||
| 80 | static unsigned int ip_conntrack_next_id; | 80 | static unsigned int ip_conntrack_next_id; |
| 81 | static unsigned int ip_conntrack_expect_next_id; | 81 | static unsigned int ip_conntrack_expect_next_id; |
| 82 | #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS | 82 | #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS |
| 83 | struct notifier_block *ip_conntrack_chain; | 83 | ATOMIC_NOTIFIER_HEAD(ip_conntrack_chain); |
| 84 | struct notifier_block *ip_conntrack_expect_chain; | 84 | ATOMIC_NOTIFIER_HEAD(ip_conntrack_expect_chain); |
| 85 | 85 | ||
| 86 | DEFINE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache); | 86 | DEFINE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache); |
| 87 | 87 | ||
| @@ -92,7 +92,7 @@ __ip_ct_deliver_cached_events(struct ip_conntrack_ecache *ecache) | |||
| 92 | { | 92 | { |
| 93 | DEBUGP("ecache: delivering events for %p\n", ecache->ct); | 93 | DEBUGP("ecache: delivering events for %p\n", ecache->ct); |
| 94 | if (is_confirmed(ecache->ct) && !is_dying(ecache->ct) && ecache->events) | 94 | if (is_confirmed(ecache->ct) && !is_dying(ecache->ct) && ecache->events) |
| 95 | notifier_call_chain(&ip_conntrack_chain, ecache->events, | 95 | atomic_notifier_call_chain(&ip_conntrack_chain, ecache->events, |
| 96 | ecache->ct); | 96 | ecache->ct); |
| 97 | ecache->events = 0; | 97 | ecache->events = 0; |
| 98 | ip_conntrack_put(ecache->ct); | 98 | ip_conntrack_put(ecache->ct); |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 01c62a0d3742..445006ee4522 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -143,7 +143,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
| 143 | struct prefix_info *pinfo); | 143 | struct prefix_info *pinfo); |
| 144 | static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev); | 144 | static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev); |
| 145 | 145 | ||
| 146 | static struct notifier_block *inet6addr_chain; | 146 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); |
| 147 | 147 | ||
| 148 | struct ipv6_devconf ipv6_devconf = { | 148 | struct ipv6_devconf ipv6_devconf = { |
| 149 | .forwarding = 0, | 149 | .forwarding = 0, |
| @@ -593,7 +593,7 @@ out2: | |||
| 593 | read_unlock_bh(&addrconf_lock); | 593 | read_unlock_bh(&addrconf_lock); |
| 594 | 594 | ||
| 595 | if (likely(err == 0)) | 595 | if (likely(err == 0)) |
| 596 | notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); | 596 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); |
| 597 | else { | 597 | else { |
| 598 | kfree(ifa); | 598 | kfree(ifa); |
| 599 | ifa = ERR_PTR(err); | 599 | ifa = ERR_PTR(err); |
| @@ -688,7 +688,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
| 688 | 688 | ||
| 689 | ipv6_ifa_notify(RTM_DELADDR, ifp); | 689 | ipv6_ifa_notify(RTM_DELADDR, ifp); |
| 690 | 690 | ||
| 691 | notifier_call_chain(&inet6addr_chain,NETDEV_DOWN,ifp); | 691 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp); |
| 692 | 692 | ||
| 693 | addrconf_del_timer(ifp); | 693 | addrconf_del_timer(ifp); |
| 694 | 694 | ||
| @@ -3767,12 +3767,12 @@ static void addrconf_sysctl_unregister(struct ipv6_devconf *p) | |||
| 3767 | 3767 | ||
| 3768 | int register_inet6addr_notifier(struct notifier_block *nb) | 3768 | int register_inet6addr_notifier(struct notifier_block *nb) |
| 3769 | { | 3769 | { |
| 3770 | return notifier_chain_register(&inet6addr_chain, nb); | 3770 | return atomic_notifier_chain_register(&inet6addr_chain, nb); |
| 3771 | } | 3771 | } |
| 3772 | 3772 | ||
| 3773 | int unregister_inet6addr_notifier(struct notifier_block *nb) | 3773 | int unregister_inet6addr_notifier(struct notifier_block *nb) |
| 3774 | { | 3774 | { |
| 3775 | return notifier_chain_unregister(&inet6addr_chain,nb); | 3775 | return atomic_notifier_chain_unregister(&inet6addr_chain,nb); |
| 3776 | } | 3776 | } |
| 3777 | 3777 | ||
| 3778 | /* | 3778 | /* |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 028b636687ec..d4cfec3f414e 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
| @@ -228,6 +228,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) | |||
| 228 | 228 | ||
| 229 | t->id.proto = IPPROTO_IPV6; | 229 | t->id.proto = IPPROTO_IPV6; |
| 230 | t->id.spi = xfrm6_tunnel_alloc_spi((xfrm_address_t *)&x->props.saddr); | 230 | t->id.spi = xfrm6_tunnel_alloc_spi((xfrm_address_t *)&x->props.saddr); |
| 231 | if (!t->id.spi) | ||
| 232 | goto error; | ||
| 233 | |||
| 231 | memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr)); | 234 | memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr)); |
| 232 | memcpy(&t->sel, &x->sel, sizeof(t->sel)); | 235 | memcpy(&t->sel, &x->sel, sizeof(t->sel)); |
| 233 | t->props.family = AF_INET6; | 236 | t->props.family = AF_INET6; |
| @@ -243,7 +246,9 @@ out: | |||
| 243 | return t; | 246 | return t; |
| 244 | 247 | ||
| 245 | error: | 248 | error: |
| 249 | t->km.state = XFRM_STATE_DEAD; | ||
| 246 | xfrm_state_put(t); | 250 | xfrm_state_put(t); |
| 251 | t = NULL; | ||
| 247 | goto out; | 252 | goto out; |
| 248 | } | 253 | } |
| 249 | 254 | ||
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 759445648667..627b11342233 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
| @@ -1302,7 +1302,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1302 | if (sk->sk_state != TCP_ESTABLISHED) | 1302 | if (sk->sk_state != TCP_ESTABLISHED) |
| 1303 | return -ENOTCONN; | 1303 | return -ENOTCONN; |
| 1304 | 1304 | ||
| 1305 | /* Check that we don't send out to big frames */ | 1305 | /* Check that we don't send out too big frames */ |
| 1306 | if (len > self->max_data_size) { | 1306 | if (len > self->max_data_size) { |
| 1307 | IRDA_DEBUG(2, "%s(), Chopping frame from %zd to %d bytes!\n", | 1307 | IRDA_DEBUG(2, "%s(), Chopping frame from %zd to %d bytes!\n", |
| 1308 | __FUNCTION__, len, self->max_data_size); | 1308 | __FUNCTION__, len, self->max_data_size); |
| @@ -1546,7 +1546,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
| 1546 | IRDA_ASSERT(self != NULL, return -1;); | 1546 | IRDA_ASSERT(self != NULL, return -1;); |
| 1547 | 1547 | ||
| 1548 | /* | 1548 | /* |
| 1549 | * Check that we don't send out to big frames. This is an unreliable | 1549 | * Check that we don't send out too big frames. This is an unreliable |
| 1550 | * service, so we have no fragmentation and no coalescence | 1550 | * service, so we have no fragmentation and no coalescence |
| 1551 | */ | 1551 | */ |
| 1552 | if (len > self->max_data_size) { | 1552 | if (len > self->max_data_size) { |
| @@ -1642,7 +1642,7 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, | |||
| 1642 | } | 1642 | } |
| 1643 | 1643 | ||
| 1644 | /* | 1644 | /* |
| 1645 | * Check that we don't send out to big frames. This is an unreliable | 1645 | * Check that we don't send out too big frames. This is an unreliable |
| 1646 | * service, so we have no fragmentation and no coalescence | 1646 | * service, so we have no fragmentation and no coalescence |
| 1647 | */ | 1647 | */ |
| 1648 | if (len > self->max_data_size) { | 1648 | if (len > self->max_data_size) { |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 0ae281d9bfc3..56389c83557c 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -90,8 +90,8 @@ static int nf_conntrack_vmalloc; | |||
| 90 | static unsigned int nf_conntrack_next_id; | 90 | static unsigned int nf_conntrack_next_id; |
| 91 | static unsigned int nf_conntrack_expect_next_id; | 91 | static unsigned int nf_conntrack_expect_next_id; |
| 92 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 92 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
| 93 | struct notifier_block *nf_conntrack_chain; | 93 | ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain); |
| 94 | struct notifier_block *nf_conntrack_expect_chain; | 94 | ATOMIC_NOTIFIER_HEAD(nf_conntrack_expect_chain); |
| 95 | 95 | ||
| 96 | DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); | 96 | DEFINE_PER_CPU(struct nf_conntrack_ecache, nf_conntrack_ecache); |
| 97 | 97 | ||
| @@ -103,7 +103,7 @@ __nf_ct_deliver_cached_events(struct nf_conntrack_ecache *ecache) | |||
| 103 | DEBUGP("ecache: delivering events for %p\n", ecache->ct); | 103 | DEBUGP("ecache: delivering events for %p\n", ecache->ct); |
| 104 | if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct) | 104 | if (nf_ct_is_confirmed(ecache->ct) && !nf_ct_is_dying(ecache->ct) |
| 105 | && ecache->events) | 105 | && ecache->events) |
| 106 | notifier_call_chain(&nf_conntrack_chain, ecache->events, | 106 | atomic_notifier_call_chain(&nf_conntrack_chain, ecache->events, |
| 107 | ecache->ct); | 107 | ecache->ct); |
| 108 | 108 | ||
| 109 | ecache->events = 0; | 109 | ecache->events = 0; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d00a9034cb5f..2a233ffcf618 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -123,7 +123,7 @@ static void netlink_destroy_callback(struct netlink_callback *cb); | |||
| 123 | static DEFINE_RWLOCK(nl_table_lock); | 123 | static DEFINE_RWLOCK(nl_table_lock); |
| 124 | static atomic_t nl_table_users = ATOMIC_INIT(0); | 124 | static atomic_t nl_table_users = ATOMIC_INIT(0); |
| 125 | 125 | ||
| 126 | static struct notifier_block *netlink_chain; | 126 | static ATOMIC_NOTIFIER_HEAD(netlink_chain); |
| 127 | 127 | ||
| 128 | static u32 netlink_group_mask(u32 group) | 128 | static u32 netlink_group_mask(u32 group) |
| 129 | { | 129 | { |
| @@ -469,7 +469,8 @@ static int netlink_release(struct socket *sock) | |||
| 469 | .protocol = sk->sk_protocol, | 469 | .protocol = sk->sk_protocol, |
| 470 | .pid = nlk->pid, | 470 | .pid = nlk->pid, |
| 471 | }; | 471 | }; |
| 472 | notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n); | 472 | atomic_notifier_call_chain(&netlink_chain, |
| 473 | NETLINK_URELEASE, &n); | ||
| 473 | } | 474 | } |
| 474 | 475 | ||
| 475 | if (nlk->module) | 476 | if (nlk->module) |
| @@ -1695,12 +1696,12 @@ static struct file_operations netlink_seq_fops = { | |||
| 1695 | 1696 | ||
| 1696 | int netlink_register_notifier(struct notifier_block *nb) | 1697 | int netlink_register_notifier(struct notifier_block *nb) |
| 1697 | { | 1698 | { |
| 1698 | return notifier_chain_register(&netlink_chain, nb); | 1699 | return atomic_notifier_chain_register(&netlink_chain, nb); |
| 1699 | } | 1700 | } |
| 1700 | 1701 | ||
| 1701 | int netlink_unregister_notifier(struct notifier_block *nb) | 1702 | int netlink_unregister_notifier(struct notifier_block *nb) |
| 1702 | { | 1703 | { |
| 1703 | return notifier_chain_unregister(&netlink_chain, nb); | 1704 | return atomic_notifier_chain_unregister(&netlink_chain, nb); |
| 1704 | } | 1705 | } |
| 1705 | 1706 | ||
| 1706 | static const struct proto_ops netlink_ops = { | 1707 | static const struct proto_ops netlink_ops = { |
diff --git a/net/nonet.c b/net/nonet.c index 1230f0ae832e..92e76640c7cd 100644 --- a/net/nonet.c +++ b/net/nonet.c | |||
| @@ -19,7 +19,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare) | |||
| 19 | return -ENXIO; | 19 | return -ENXIO; |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | struct file_operations bad_sock_fops = { | 22 | const struct file_operations bad_sock_fops = { |
| 23 | .owner = THIS_MODULE, | 23 | .owner = THIS_MODULE, |
| 24 | .open = sock_no_open, | 24 | .open = sock_no_open, |
| 25 | }; | 25 | }; |
diff --git a/net/socket.c b/net/socket.c index 5211ba270375..fcd77eac0ccf 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -539,7 +539,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare) | |||
| 539 | return -ENXIO; | 539 | return -ENXIO; |
| 540 | } | 540 | } |
| 541 | 541 | ||
| 542 | struct file_operations bad_sock_fops = { | 542 | const struct file_operations bad_sock_fops = { |
| 543 | .owner = THIS_MODULE, | 543 | .owner = THIS_MODULE, |
| 544 | .open = sock_no_open, | 544 | .open = sock_no_open, |
| 545 | }; | 545 | }; |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 23632d84d8d7..4d7eb9e704da 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
| @@ -78,7 +78,8 @@ struct rsi { | |||
| 78 | 78 | ||
| 79 | static struct cache_head *rsi_table[RSI_HASHMAX]; | 79 | static struct cache_head *rsi_table[RSI_HASHMAX]; |
| 80 | static struct cache_detail rsi_cache; | 80 | static struct cache_detail rsi_cache; |
| 81 | static struct rsi *rsi_lookup(struct rsi *item, int set); | 81 | static struct rsi *rsi_update(struct rsi *new, struct rsi *old); |
| 82 | static struct rsi *rsi_lookup(struct rsi *item); | ||
| 82 | 83 | ||
| 83 | static void rsi_free(struct rsi *rsii) | 84 | static void rsi_free(struct rsi *rsii) |
| 84 | { | 85 | { |
| @@ -88,13 +89,11 @@ static void rsi_free(struct rsi *rsii) | |||
| 88 | kfree(rsii->out_token.data); | 89 | kfree(rsii->out_token.data); |
| 89 | } | 90 | } |
| 90 | 91 | ||
| 91 | static void rsi_put(struct cache_head *item, struct cache_detail *cd) | 92 | static void rsi_put(struct kref *ref) |
| 92 | { | 93 | { |
| 93 | struct rsi *rsii = container_of(item, struct rsi, h); | 94 | struct rsi *rsii = container_of(ref, struct rsi, h.ref); |
| 94 | if (cache_put(item, cd)) { | 95 | rsi_free(rsii); |
| 95 | rsi_free(rsii); | 96 | kfree(rsii); |
| 96 | kfree(rsii); | ||
| 97 | } | ||
| 98 | } | 97 | } |
| 99 | 98 | ||
| 100 | static inline int rsi_hash(struct rsi *item) | 99 | static inline int rsi_hash(struct rsi *item) |
| @@ -103,8 +102,10 @@ static inline int rsi_hash(struct rsi *item) | |||
| 103 | ^ hash_mem(item->in_token.data, item->in_token.len, RSI_HASHBITS); | 102 | ^ hash_mem(item->in_token.data, item->in_token.len, RSI_HASHBITS); |
| 104 | } | 103 | } |
| 105 | 104 | ||
| 106 | static inline int rsi_match(struct rsi *item, struct rsi *tmp) | 105 | static int rsi_match(struct cache_head *a, struct cache_head *b) |
| 107 | { | 106 | { |
| 107 | struct rsi *item = container_of(a, struct rsi, h); | ||
| 108 | struct rsi *tmp = container_of(b, struct rsi, h); | ||
| 108 | return netobj_equal(&item->in_handle, &tmp->in_handle) | 109 | return netobj_equal(&item->in_handle, &tmp->in_handle) |
| 109 | && netobj_equal(&item->in_token, &tmp->in_token); | 110 | && netobj_equal(&item->in_token, &tmp->in_token); |
| 110 | } | 111 | } |
| @@ -125,8 +126,11 @@ static inline int dup_netobj(struct xdr_netobj *dst, struct xdr_netobj *src) | |||
| 125 | return dup_to_netobj(dst, src->data, src->len); | 126 | return dup_to_netobj(dst, src->data, src->len); |
| 126 | } | 127 | } |
| 127 | 128 | ||
| 128 | static inline void rsi_init(struct rsi *new, struct rsi *item) | 129 | static void rsi_init(struct cache_head *cnew, struct cache_head *citem) |
| 129 | { | 130 | { |
| 131 | struct rsi *new = container_of(cnew, struct rsi, h); | ||
| 132 | struct rsi *item = container_of(citem, struct rsi, h); | ||
| 133 | |||
| 130 | new->out_handle.data = NULL; | 134 | new->out_handle.data = NULL; |
| 131 | new->out_handle.len = 0; | 135 | new->out_handle.len = 0; |
| 132 | new->out_token.data = NULL; | 136 | new->out_token.data = NULL; |
| @@ -141,8 +145,11 @@ static inline void rsi_init(struct rsi *new, struct rsi *item) | |||
| 141 | item->in_token.data = NULL; | 145 | item->in_token.data = NULL; |
| 142 | } | 146 | } |
| 143 | 147 | ||
| 144 | static inline void rsi_update(struct rsi *new, struct rsi *item) | 148 | static void update_rsi(struct cache_head *cnew, struct cache_head *citem) |
| 145 | { | 149 | { |
| 150 | struct rsi *new = container_of(cnew, struct rsi, h); | ||
| 151 | struct rsi *item = container_of(citem, struct rsi, h); | ||
| 152 | |||
| 146 | BUG_ON(new->out_handle.data || new->out_token.data); | 153 | BUG_ON(new->out_handle.data || new->out_token.data); |
| 147 | new->out_handle.len = item->out_handle.len; | 154 | new->out_handle.len = item->out_handle.len; |
| 148 | item->out_handle.len = 0; | 155 | item->out_handle.len = 0; |
| @@ -157,6 +164,15 @@ static inline void rsi_update(struct rsi *new, struct rsi *item) | |||
| 157 | new->minor_status = item->minor_status; | 164 | new->minor_status = item->minor_status; |
| 158 | } | 165 | } |
| 159 | 166 | ||
| 167 | static struct cache_head *rsi_alloc(void) | ||
| 168 | { | ||
| 169 | struct rsi *rsii = kmalloc(sizeof(*rsii), GFP_KERNEL); | ||
| 170 | if (rsii) | ||
| 171 | return &rsii->h; | ||
| 172 | else | ||
| 173 | return NULL; | ||
| 174 | } | ||
| 175 | |||
| 160 | static void rsi_request(struct cache_detail *cd, | 176 | static void rsi_request(struct cache_detail *cd, |
| 161 | struct cache_head *h, | 177 | struct cache_head *h, |
| 162 | char **bpp, int *blen) | 178 | char **bpp, int *blen) |
| @@ -198,6 +214,10 @@ static int rsi_parse(struct cache_detail *cd, | |||
| 198 | if (dup_to_netobj(&rsii.in_token, buf, len)) | 214 | if (dup_to_netobj(&rsii.in_token, buf, len)) |
| 199 | goto out; | 215 | goto out; |
| 200 | 216 | ||
| 217 | rsip = rsi_lookup(&rsii); | ||
| 218 | if (!rsip) | ||
| 219 | goto out; | ||
| 220 | |||
| 201 | rsii.h.flags = 0; | 221 | rsii.h.flags = 0; |
| 202 | /* expiry */ | 222 | /* expiry */ |
| 203 | expiry = get_expiry(&mesg); | 223 | expiry = get_expiry(&mesg); |
| @@ -240,12 +260,14 @@ static int rsi_parse(struct cache_detail *cd, | |||
| 240 | goto out; | 260 | goto out; |
| 241 | } | 261 | } |
| 242 | rsii.h.expiry_time = expiry; | 262 | rsii.h.expiry_time = expiry; |
| 243 | rsip = rsi_lookup(&rsii, 1); | 263 | rsip = rsi_update(&rsii, rsip); |
| 244 | status = 0; | 264 | status = 0; |
| 245 | out: | 265 | out: |
| 246 | rsi_free(&rsii); | 266 | rsi_free(&rsii); |
| 247 | if (rsip) | 267 | if (rsip) |
| 248 | rsi_put(&rsip->h, &rsi_cache); | 268 | cache_put(&rsip->h, &rsi_cache); |
| 269 | else | ||
| 270 | status = -ENOMEM; | ||
| 249 | return status; | 271 | return status; |
| 250 | } | 272 | } |
| 251 | 273 | ||
| @@ -257,9 +279,37 @@ static struct cache_detail rsi_cache = { | |||
| 257 | .cache_put = rsi_put, | 279 | .cache_put = rsi_put, |
| 258 | .cache_request = rsi_request, | 280 | .cache_request = rsi_request, |
| 259 | .cache_parse = rsi_parse, | 281 | .cache_parse = rsi_parse, |
| 282 | .match = rsi_match, | ||
| 283 | .init = rsi_init, | ||
| 284 | .update = update_rsi, | ||
| 285 | .alloc = rsi_alloc, | ||
| 260 | }; | 286 | }; |
| 261 | 287 | ||
| 262 | static DefineSimpleCacheLookup(rsi, 0) | 288 | static struct rsi *rsi_lookup(struct rsi *item) |
| 289 | { | ||
| 290 | struct cache_head *ch; | ||
| 291 | int hash = rsi_hash(item); | ||
| 292 | |||
| 293 | ch = sunrpc_cache_lookup(&rsi_cache, &item->h, hash); | ||
| 294 | if (ch) | ||
| 295 | return container_of(ch, struct rsi, h); | ||
| 296 | else | ||
| 297 | return NULL; | ||
| 298 | } | ||
| 299 | |||
| 300 | static struct rsi *rsi_update(struct rsi *new, struct rsi *old) | ||
| 301 | { | ||
| 302 | struct cache_head *ch; | ||
| 303 | int hash = rsi_hash(new); | ||
| 304 | |||
| 305 | ch = sunrpc_cache_update(&rsi_cache, &new->h, | ||
| 306 | &old->h, hash); | ||
| 307 | if (ch) | ||
| 308 | return container_of(ch, struct rsi, h); | ||
| 309 | else | ||
| 310 | return NULL; | ||
| 311 | } | ||
| 312 | |||
| 263 | 313 | ||
| 264 | /* | 314 | /* |
| 265 | * The rpcsec_context cache is used to store a context that is | 315 | * The rpcsec_context cache is used to store a context that is |
| @@ -293,7 +343,8 @@ struct rsc { | |||
| 293 | 343 | ||
| 294 | static struct cache_head *rsc_table[RSC_HASHMAX]; | 344 | static struct cache_head *rsc_table[RSC_HASHMAX]; |
| 295 | static struct cache_detail rsc_cache; | 345 | static struct cache_detail rsc_cache; |
| 296 | static struct rsc *rsc_lookup(struct rsc *item, int set); | 346 | static struct rsc *rsc_update(struct rsc *new, struct rsc *old); |
| 347 | static struct rsc *rsc_lookup(struct rsc *item); | ||
| 297 | 348 | ||
| 298 | static void rsc_free(struct rsc *rsci) | 349 | static void rsc_free(struct rsc *rsci) |
| 299 | { | 350 | { |
| @@ -304,14 +355,12 @@ static void rsc_free(struct rsc *rsci) | |||
| 304 | put_group_info(rsci->cred.cr_group_info); | 355 | put_group_info(rsci->cred.cr_group_info); |
| 305 | } | 356 | } |
| 306 | 357 | ||
| 307 | static void rsc_put(struct cache_head *item, struct cache_detail *cd) | 358 | static void rsc_put(struct kref *ref) |
| 308 | { | 359 | { |
| 309 | struct rsc *rsci = container_of(item, struct rsc, h); | 360 | struct rsc *rsci = container_of(ref, struct rsc, h.ref); |
| 310 | 361 | ||
| 311 | if (cache_put(item, cd)) { | 362 | rsc_free(rsci); |
| 312 | rsc_free(rsci); | 363 | kfree(rsci); |
| 313 | kfree(rsci); | ||
| 314 | } | ||
| 315 | } | 364 | } |
| 316 | 365 | ||
| 317 | static inline int | 366 | static inline int |
| @@ -320,15 +369,21 @@ rsc_hash(struct rsc *rsci) | |||
| 320 | return hash_mem(rsci->handle.data, rsci->handle.len, RSC_HASHBITS); | 369 | return hash_mem(rsci->handle.data, rsci->handle.len, RSC_HASHBITS); |
| 321 | } | 370 | } |
| 322 | 371 | ||
| 323 | static inline int | 372 | static int |
| 324 | rsc_match(struct rsc *new, struct rsc *tmp) | 373 | rsc_match(struct cache_head *a, struct cache_head *b) |
| 325 | { | 374 | { |
| 375 | struct rsc *new = container_of(a, struct rsc, h); | ||
| 376 | struct rsc *tmp = container_of(b, struct rsc, h); | ||
| 377 | |||
| 326 | return netobj_equal(&new->handle, &tmp->handle); | 378 | return netobj_equal(&new->handle, &tmp->handle); |
| 327 | } | 379 | } |
| 328 | 380 | ||
| 329 | static inline void | 381 | static void |
| 330 | rsc_init(struct rsc *new, struct rsc *tmp) | 382 | rsc_init(struct cache_head *cnew, struct cache_head *ctmp) |
| 331 | { | 383 | { |
| 384 | struct rsc *new = container_of(cnew, struct rsc, h); | ||
| 385 | struct rsc *tmp = container_of(ctmp, struct rsc, h); | ||
| 386 | |||
| 332 | new->handle.len = tmp->handle.len; | 387 | new->handle.len = tmp->handle.len; |
| 333 | tmp->handle.len = 0; | 388 | tmp->handle.len = 0; |
| 334 | new->handle.data = tmp->handle.data; | 389 | new->handle.data = tmp->handle.data; |
| @@ -337,9 +392,12 @@ rsc_init(struct rsc *new, struct rsc *tmp) | |||
| 337 | new->cred.cr_group_info = NULL; | 392 | new->cred.cr_group_info = NULL; |
| 338 | } | 393 | } |
| 339 | 394 | ||
| 340 | static inline void | 395 | static void |
| 341 | rsc_update(struct rsc *new, struct rsc *tmp) | 396 | update_rsc(struct cache_head *cnew, struct cache_head *ctmp) |
| 342 | { | 397 | { |
| 398 | struct rsc *new = container_of(cnew, struct rsc, h); | ||
| 399 | struct rsc *tmp = container_of(ctmp, struct rsc, h); | ||
| 400 | |||
| 343 | new->mechctx = tmp->mechctx; | 401 | new->mechctx = tmp->mechctx; |
| 344 | tmp->mechctx = NULL; | 402 | tmp->mechctx = NULL; |
| 345 | memset(&new->seqdata, 0, sizeof(new->seqdata)); | 403 | memset(&new->seqdata, 0, sizeof(new->seqdata)); |
| @@ -348,6 +406,16 @@ rsc_update(struct rsc *new, struct rsc *tmp) | |||
| 348 | tmp->cred.cr_group_info = NULL; | 406 | tmp->cred.cr_group_info = NULL; |
| 349 | } | 407 | } |
| 350 | 408 | ||
| 409 | static struct cache_head * | ||
| 410 | rsc_alloc(void) | ||
| 411 | { | ||
| 412 | struct rsc *rsci = kmalloc(sizeof(*rsci), GFP_KERNEL); | ||
| 413 | if (rsci) | ||
| 414 | return &rsci->h; | ||
| 415 | else | ||
| 416 | return NULL; | ||
| 417 | } | ||
| 418 | |||
| 351 | static int rsc_parse(struct cache_detail *cd, | 419 | static int rsc_parse(struct cache_detail *cd, |
| 352 | char *mesg, int mlen) | 420 | char *mesg, int mlen) |
| 353 | { | 421 | { |
| @@ -373,6 +441,10 @@ static int rsc_parse(struct cache_detail *cd, | |||
| 373 | if (expiry == 0) | 441 | if (expiry == 0) |
| 374 | goto out; | 442 | goto out; |
| 375 | 443 | ||
| 444 | rscp = rsc_lookup(&rsci); | ||
| 445 | if (!rscp) | ||
| 446 | goto out; | ||
| 447 | |||
| 376 | /* uid, or NEGATIVE */ | 448 | /* uid, or NEGATIVE */ |
| 377 | rv = get_int(&mesg, &rsci.cred.cr_uid); | 449 | rv = get_int(&mesg, &rsci.cred.cr_uid); |
| 378 | if (rv == -EINVAL) | 450 | if (rv == -EINVAL) |
| @@ -428,12 +500,14 @@ static int rsc_parse(struct cache_detail *cd, | |||
| 428 | gss_mech_put(gm); | 500 | gss_mech_put(gm); |
| 429 | } | 501 | } |
| 430 | rsci.h.expiry_time = expiry; | 502 | rsci.h.expiry_time = expiry; |
| 431 | rscp = rsc_lookup(&rsci, 1); | 503 | rscp = rsc_update(&rsci, rscp); |
| 432 | status = 0; | 504 | status = 0; |
| 433 | out: | 505 | out: |
| 434 | rsc_free(&rsci); | 506 | rsc_free(&rsci); |
| 435 | if (rscp) | 507 | if (rscp) |
| 436 | rsc_put(&rscp->h, &rsc_cache); | 508 | cache_put(&rscp->h, &rsc_cache); |
| 509 | else | ||
| 510 | status = -ENOMEM; | ||
| 437 | return status; | 511 | return status; |
| 438 | } | 512 | } |
| 439 | 513 | ||
| @@ -444,9 +518,37 @@ static struct cache_detail rsc_cache = { | |||
| 444 | .name = "auth.rpcsec.context", | 518 | .name = "auth.rpcsec.context", |
| 445 | .cache_put = rsc_put, | 519 | .cache_put = rsc_put, |
| 446 | .cache_parse = rsc_parse, | 520 | .cache_parse = rsc_parse, |
| 521 | .match = rsc_match, | ||
| 522 | .init = rsc_init, | ||
| 523 | .update = update_rsc, | ||
| 524 | .alloc = rsc_alloc, | ||
| 447 | }; | 525 | }; |
| 448 | 526 | ||
| 449 | static DefineSimpleCacheLookup(rsc, 0); | 527 | static struct rsc *rsc_lookup(struct rsc *item) |
| 528 | { | ||
| 529 | struct cache_head *ch; | ||
| 530 | int hash = rsc_hash(item); | ||
| 531 | |||
| 532 | ch = sunrpc_cache_lookup(&rsc_cache, &item->h, hash); | ||
| 533 | if (ch) | ||
| 534 | return container_of(ch, struct rsc, h); | ||
| 535 | else | ||
| 536 | return NULL; | ||
| 537 | } | ||
| 538 | |||
| 539 | static struct rsc *rsc_update(struct rsc *new, struct rsc *old) | ||
| 540 | { | ||
| 541 | struct cache_head *ch; | ||
| 542 | int hash = rsc_hash(new); | ||
| 543 | |||
| 544 | ch = sunrpc_cache_update(&rsc_cache, &new->h, | ||
| 545 | &old->h, hash); | ||
| 546 | if (ch) | ||
| 547 | return container_of(ch, struct rsc, h); | ||
| 548 | else | ||
| 549 | return NULL; | ||
| 550 | } | ||
| 551 | |||
| 450 | 552 | ||
| 451 | static struct rsc * | 553 | static struct rsc * |
| 452 | gss_svc_searchbyctx(struct xdr_netobj *handle) | 554 | gss_svc_searchbyctx(struct xdr_netobj *handle) |
| @@ -457,7 +559,7 @@ gss_svc_searchbyctx(struct xdr_netobj *handle) | |||
| 457 | memset(&rsci, 0, sizeof(rsci)); | 559 | memset(&rsci, 0, sizeof(rsci)); |
| 458 | if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) | 560 | if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) |
| 459 | return NULL; | 561 | return NULL; |
| 460 | found = rsc_lookup(&rsci, 0); | 562 | found = rsc_lookup(&rsci); |
| 461 | rsc_free(&rsci); | 563 | rsc_free(&rsci); |
| 462 | if (!found) | 564 | if (!found) |
| 463 | return NULL; | 565 | return NULL; |
| @@ -645,6 +747,8 @@ find_gss_auth_domain(struct gss_ctx *ctx, u32 svc) | |||
| 645 | return auth_domain_find(name); | 747 | return auth_domain_find(name); |
| 646 | } | 748 | } |
| 647 | 749 | ||
| 750 | static struct auth_ops svcauthops_gss; | ||
| 751 | |||
| 648 | int | 752 | int |
| 649 | svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) | 753 | svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) |
| 650 | { | 754 | { |
| @@ -655,20 +759,18 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) | |||
| 655 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 759 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
| 656 | if (!new) | 760 | if (!new) |
| 657 | goto out; | 761 | goto out; |
| 658 | cache_init(&new->h.h); | 762 | kref_init(&new->h.ref); |
| 659 | new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL); | 763 | new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL); |
| 660 | if (!new->h.name) | 764 | if (!new->h.name) |
| 661 | goto out_free_dom; | 765 | goto out_free_dom; |
| 662 | strcpy(new->h.name, name); | 766 | strcpy(new->h.name, name); |
| 663 | new->h.flavour = RPC_AUTH_GSS; | 767 | new->h.flavour = &svcauthops_gss; |
| 664 | new->pseudoflavor = pseudoflavor; | 768 | new->pseudoflavor = pseudoflavor; |
| 665 | new->h.h.expiry_time = NEVER; | ||
| 666 | 769 | ||
| 667 | test = auth_domain_lookup(&new->h, 1); | 770 | test = auth_domain_lookup(name, &new->h); |
| 668 | if (test == &new->h) { | 771 | if (test != &new->h) { /* XXX Duplicate registration? */ |
| 669 | BUG_ON(atomic_dec_and_test(&new->h.h.refcnt)); | ||
| 670 | } else { /* XXX Duplicate registration? */ | ||
| 671 | auth_domain_put(&new->h); | 772 | auth_domain_put(&new->h); |
| 773 | /* dangling ref-count... */ | ||
| 672 | goto out; | 774 | goto out; |
| 673 | } | 775 | } |
| 674 | return 0; | 776 | return 0; |
| @@ -895,7 +997,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp) | |||
| 895 | goto drop; | 997 | goto drop; |
| 896 | } | 998 | } |
| 897 | 999 | ||
| 898 | rsip = rsi_lookup(&rsikey, 0); | 1000 | rsip = rsi_lookup(&rsikey); |
| 899 | rsi_free(&rsikey); | 1001 | rsi_free(&rsikey); |
| 900 | if (!rsip) { | 1002 | if (!rsip) { |
| 901 | goto drop; | 1003 | goto drop; |
| @@ -970,7 +1072,7 @@ drop: | |||
| 970 | ret = SVC_DROP; | 1072 | ret = SVC_DROP; |
| 971 | out: | 1073 | out: |
| 972 | if (rsci) | 1074 | if (rsci) |
| 973 | rsc_put(&rsci->h, &rsc_cache); | 1075 | cache_put(&rsci->h, &rsc_cache); |
| 974 | return ret; | 1076 | return ret; |
| 975 | } | 1077 | } |
| 976 | 1078 | ||
| @@ -1062,7 +1164,7 @@ out_err: | |||
| 1062 | put_group_info(rqstp->rq_cred.cr_group_info); | 1164 | put_group_info(rqstp->rq_cred.cr_group_info); |
| 1063 | rqstp->rq_cred.cr_group_info = NULL; | 1165 | rqstp->rq_cred.cr_group_info = NULL; |
| 1064 | if (gsd->rsci) | 1166 | if (gsd->rsci) |
| 1065 | rsc_put(&gsd->rsci->h, &rsc_cache); | 1167 | cache_put(&gsd->rsci->h, &rsc_cache); |
| 1066 | gsd->rsci = NULL; | 1168 | gsd->rsci = NULL; |
| 1067 | 1169 | ||
| 1068 | return stat; | 1170 | return stat; |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 0acccfeeb284..3ac4193a78ed 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
| @@ -37,16 +37,138 @@ | |||
| 37 | static void cache_defer_req(struct cache_req *req, struct cache_head *item); | 37 | static void cache_defer_req(struct cache_req *req, struct cache_head *item); |
| 38 | static void cache_revisit_request(struct cache_head *item); | 38 | static void cache_revisit_request(struct cache_head *item); |
| 39 | 39 | ||
| 40 | void cache_init(struct cache_head *h) | 40 | static void cache_init(struct cache_head *h) |
| 41 | { | 41 | { |
| 42 | time_t now = get_seconds(); | 42 | time_t now = get_seconds(); |
| 43 | h->next = NULL; | 43 | h->next = NULL; |
| 44 | h->flags = 0; | 44 | h->flags = 0; |
| 45 | atomic_set(&h->refcnt, 1); | 45 | kref_init(&h->ref); |
| 46 | h->expiry_time = now + CACHE_NEW_EXPIRY; | 46 | h->expiry_time = now + CACHE_NEW_EXPIRY; |
| 47 | h->last_refresh = now; | 47 | h->last_refresh = now; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, | ||
| 51 | struct cache_head *key, int hash) | ||
| 52 | { | ||
| 53 | struct cache_head **head, **hp; | ||
| 54 | struct cache_head *new = NULL; | ||
| 55 | |||
| 56 | head = &detail->hash_table[hash]; | ||
| 57 | |||
| 58 | read_lock(&detail->hash_lock); | ||
| 59 | |||
| 60 | for (hp=head; *hp != NULL ; hp = &(*hp)->next) { | ||
| 61 | struct cache_head *tmp = *hp; | ||
| 62 | if (detail->match(tmp, key)) { | ||
| 63 | cache_get(tmp); | ||
| 64 | read_unlock(&detail->hash_lock); | ||
| 65 | return tmp; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | read_unlock(&detail->hash_lock); | ||
| 69 | /* Didn't find anything, insert an empty entry */ | ||
| 70 | |||
| 71 | new = detail->alloc(); | ||
| 72 | if (!new) | ||
| 73 | return NULL; | ||
| 74 | cache_init(new); | ||
| 75 | |||
| 76 | write_lock(&detail->hash_lock); | ||
| 77 | |||
| 78 | /* check if entry appeared while we slept */ | ||
| 79 | for (hp=head; *hp != NULL ; hp = &(*hp)->next) { | ||
| 80 | struct cache_head *tmp = *hp; | ||
| 81 | if (detail->match(tmp, key)) { | ||
| 82 | cache_get(tmp); | ||
| 83 | write_unlock(&detail->hash_lock); | ||
| 84 | cache_put(new, detail); | ||
| 85 | return tmp; | ||
| 86 | } | ||
| 87 | } | ||
| 88 | detail->init(new, key); | ||
| 89 | new->next = *head; | ||
| 90 | *head = new; | ||
| 91 | detail->entries++; | ||
| 92 | cache_get(new); | ||
| 93 | write_unlock(&detail->hash_lock); | ||
| 94 | |||
| 95 | return new; | ||
| 96 | } | ||
| 97 | EXPORT_SYMBOL(sunrpc_cache_lookup); | ||
| 98 | |||
| 99 | |||
| 100 | static void queue_loose(struct cache_detail *detail, struct cache_head *ch); | ||
| 101 | |||
| 102 | static int cache_fresh_locked(struct cache_head *head, time_t expiry) | ||
| 103 | { | ||
| 104 | head->expiry_time = expiry; | ||
| 105 | head->last_refresh = get_seconds(); | ||
| 106 | return !test_and_set_bit(CACHE_VALID, &head->flags); | ||
| 107 | } | ||
| 108 | |||
| 109 | static void cache_fresh_unlocked(struct cache_head *head, | ||
| 110 | struct cache_detail *detail, int new) | ||
| 111 | { | ||
| 112 | if (new) | ||
| 113 | cache_revisit_request(head); | ||
| 114 | if (test_and_clear_bit(CACHE_PENDING, &head->flags)) { | ||
| 115 | cache_revisit_request(head); | ||
| 116 | queue_loose(detail, head); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | struct cache_head *sunrpc_cache_update(struct cache_detail *detail, | ||
| 121 | struct cache_head *new, struct cache_head *old, int hash) | ||
| 122 | { | ||
| 123 | /* The 'old' entry is to be replaced by 'new'. | ||
| 124 | * If 'old' is not VALID, we update it directly, | ||
| 125 | * otherwise we need to replace it | ||
| 126 | */ | ||
| 127 | struct cache_head **head; | ||
| 128 | struct cache_head *tmp; | ||
| 129 | int is_new; | ||
| 130 | |||
| 131 | if (!test_bit(CACHE_VALID, &old->flags)) { | ||
| 132 | write_lock(&detail->hash_lock); | ||
| 133 | if (!test_bit(CACHE_VALID, &old->flags)) { | ||
| 134 | if (test_bit(CACHE_NEGATIVE, &new->flags)) | ||
| 135 | set_bit(CACHE_NEGATIVE, &old->flags); | ||
| 136 | else | ||
| 137 | detail->update(old, new); | ||
| 138 | is_new = cache_fresh_locked(old, new->expiry_time); | ||
| 139 | write_unlock(&detail->hash_lock); | ||
| 140 | cache_fresh_unlocked(old, detail, is_new); | ||
| 141 | return old; | ||
| 142 | } | ||
| 143 | write_unlock(&detail->hash_lock); | ||
| 144 | } | ||
| 145 | /* We need to insert a new entry */ | ||
| 146 | tmp = detail->alloc(); | ||
| 147 | if (!tmp) { | ||
| 148 | cache_put(old, detail); | ||
| 149 | return NULL; | ||
| 150 | } | ||
| 151 | cache_init(tmp); | ||
| 152 | detail->init(tmp, old); | ||
| 153 | head = &detail->hash_table[hash]; | ||
| 154 | |||
| 155 | write_lock(&detail->hash_lock); | ||
| 156 | if (test_bit(CACHE_NEGATIVE, &new->flags)) | ||
| 157 | set_bit(CACHE_NEGATIVE, &tmp->flags); | ||
| 158 | else | ||
| 159 | detail->update(tmp, new); | ||
| 160 | tmp->next = *head; | ||
| 161 | *head = tmp; | ||
| 162 | cache_get(tmp); | ||
| 163 | is_new = cache_fresh_locked(tmp, new->expiry_time); | ||
| 164 | cache_fresh_locked(old, 0); | ||
| 165 | write_unlock(&detail->hash_lock); | ||
| 166 | cache_fresh_unlocked(tmp, detail, is_new); | ||
| 167 | cache_fresh_unlocked(old, detail, 0); | ||
| 168 | cache_put(old, detail); | ||
| 169 | return tmp; | ||
| 170 | } | ||
| 171 | EXPORT_SYMBOL(sunrpc_cache_update); | ||
| 50 | 172 | ||
| 51 | static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h); | 173 | static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h); |
| 52 | /* | 174 | /* |
| @@ -94,7 +216,8 @@ int cache_check(struct cache_detail *detail, | |||
| 94 | clear_bit(CACHE_PENDING, &h->flags); | 216 | clear_bit(CACHE_PENDING, &h->flags); |
| 95 | if (rv == -EAGAIN) { | 217 | if (rv == -EAGAIN) { |
| 96 | set_bit(CACHE_NEGATIVE, &h->flags); | 218 | set_bit(CACHE_NEGATIVE, &h->flags); |
| 97 | cache_fresh(detail, h, get_seconds()+CACHE_NEW_EXPIRY); | 219 | cache_fresh_unlocked(h, detail, |
| 220 | cache_fresh_locked(h, get_seconds()+CACHE_NEW_EXPIRY)); | ||
| 98 | rv = -ENOENT; | 221 | rv = -ENOENT; |
| 99 | } | 222 | } |
| 100 | break; | 223 | break; |
| @@ -110,25 +233,11 @@ int cache_check(struct cache_detail *detail, | |||
| 110 | if (rv == -EAGAIN) | 233 | if (rv == -EAGAIN) |
| 111 | cache_defer_req(rqstp, h); | 234 | cache_defer_req(rqstp, h); |
| 112 | 235 | ||
| 113 | if (rv && h) | 236 | if (rv) |
| 114 | detail->cache_put(h, detail); | 237 | cache_put(h, detail); |
| 115 | return rv; | 238 | return rv; |
| 116 | } | 239 | } |
| 117 | 240 | ||
| 118 | static void queue_loose(struct cache_detail *detail, struct cache_head *ch); | ||
| 119 | |||
| 120 | void cache_fresh(struct cache_detail *detail, | ||
| 121 | struct cache_head *head, time_t expiry) | ||
| 122 | { | ||
| 123 | |||
| 124 | head->expiry_time = expiry; | ||
| 125 | head->last_refresh = get_seconds(); | ||
| 126 | if (!test_and_set_bit(CACHE_VALID, &head->flags)) | ||
| 127 | cache_revisit_request(head); | ||
| 128 | if (test_and_clear_bit(CACHE_PENDING, &head->flags)) | ||
| 129 | queue_loose(detail, head); | ||
| 130 | } | ||
| 131 | |||
| 132 | /* | 241 | /* |
| 133 | * caches need to be periodically cleaned. | 242 | * caches need to be periodically cleaned. |
| 134 | * For this we maintain a list of cache_detail and | 243 | * For this we maintain a list of cache_detail and |
| @@ -322,7 +431,7 @@ static int cache_clean(void) | |||
| 322 | if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) | 431 | if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) |
| 323 | queue_loose(current_detail, ch); | 432 | queue_loose(current_detail, ch); |
| 324 | 433 | ||
| 325 | if (atomic_read(&ch->refcnt) == 1) | 434 | if (atomic_read(&ch->ref.refcount) == 1) |
| 326 | break; | 435 | break; |
| 327 | } | 436 | } |
| 328 | if (ch) { | 437 | if (ch) { |
| @@ -337,7 +446,7 @@ static int cache_clean(void) | |||
| 337 | current_index ++; | 446 | current_index ++; |
| 338 | spin_unlock(&cache_list_lock); | 447 | spin_unlock(&cache_list_lock); |
| 339 | if (ch) | 448 | if (ch) |
| 340 | d->cache_put(ch, d); | 449 | cache_put(ch, d); |
| 341 | } else | 450 | } else |
| 342 | spin_unlock(&cache_list_lock); | 451 | spin_unlock(&cache_list_lock); |
| 343 | 452 | ||
| @@ -453,7 +562,7 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item) | |||
| 453 | /* there was one too many */ | 562 | /* there was one too many */ |
| 454 | dreq->revisit(dreq, 1); | 563 | dreq->revisit(dreq, 1); |
| 455 | } | 564 | } |
| 456 | if (test_bit(CACHE_VALID, &item->flags)) { | 565 | if (!test_bit(CACHE_PENDING, &item->flags)) { |
| 457 | /* must have just been validated... */ | 566 | /* must have just been validated... */ |
| 458 | cache_revisit_request(item); | 567 | cache_revisit_request(item); |
| 459 | } | 568 | } |
| @@ -614,7 +723,7 @@ cache_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) | |||
| 614 | !test_bit(CACHE_PENDING, &rq->item->flags)) { | 723 | !test_bit(CACHE_PENDING, &rq->item->flags)) { |
| 615 | list_del(&rq->q.list); | 724 | list_del(&rq->q.list); |
| 616 | spin_unlock(&queue_lock); | 725 | spin_unlock(&queue_lock); |
| 617 | cd->cache_put(rq->item, cd); | 726 | cache_put(rq->item, cd); |
| 618 | kfree(rq->buf); | 727 | kfree(rq->buf); |
| 619 | kfree(rq); | 728 | kfree(rq); |
| 620 | } else | 729 | } else |
| @@ -794,10 +903,10 @@ static void queue_loose(struct cache_detail *detail, struct cache_head *ch) | |||
| 794 | if (cr->item != ch) | 903 | if (cr->item != ch) |
| 795 | continue; | 904 | continue; |
| 796 | if (cr->readers != 0) | 905 | if (cr->readers != 0) |
| 797 | break; | 906 | continue; |
| 798 | list_del(&cr->q.list); | 907 | list_del(&cr->q.list); |
| 799 | spin_unlock(&queue_lock); | 908 | spin_unlock(&queue_lock); |
| 800 | detail->cache_put(cr->item, detail); | 909 | cache_put(cr->item, detail); |
| 801 | kfree(cr->buf); | 910 | kfree(cr->buf); |
| 802 | kfree(cr); | 911 | kfree(cr); |
| 803 | return; | 912 | return; |
| @@ -1082,8 +1191,8 @@ static int c_show(struct seq_file *m, void *p) | |||
| 1082 | return cd->cache_show(m, cd, NULL); | 1191 | return cd->cache_show(m, cd, NULL); |
| 1083 | 1192 | ||
| 1084 | ifdebug(CACHE) | 1193 | ifdebug(CACHE) |
| 1085 | seq_printf(m, "# expiry=%ld refcnt=%d\n", | 1194 | seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n", |
| 1086 | cp->expiry_time, atomic_read(&cp->refcnt)); | 1195 | cp->expiry_time, atomic_read(&cp->ref.refcount), cp->flags); |
| 1087 | cache_get(cp); | 1196 | cache_get(cp); |
| 1088 | if (cache_check(cd, cp, NULL)) | 1197 | if (cache_check(cd, cp, NULL)) |
| 1089 | /* cache_check does a cache_put on failure */ | 1198 | /* cache_check does a cache_put on failure */ |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index aa4158be9900..cc673dd8433f 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
| @@ -395,7 +395,7 @@ enum { | |||
| 395 | */ | 395 | */ |
| 396 | struct rpc_filelist { | 396 | struct rpc_filelist { |
| 397 | char *name; | 397 | char *name; |
| 398 | struct file_operations *i_fop; | 398 | const struct file_operations *i_fop; |
| 399 | int mode; | 399 | int mode; |
| 400 | }; | 400 | }; |
| 401 | 401 | ||
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 790941e8af4d..dea529666d69 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c | |||
| @@ -225,7 +225,7 @@ EXPORT_SYMBOL(rpc_print_iostats); | |||
| 225 | * Register/unregister RPC proc files | 225 | * Register/unregister RPC proc files |
| 226 | */ | 226 | */ |
| 227 | static inline struct proc_dir_entry * | 227 | static inline struct proc_dir_entry * |
| 228 | do_register(const char *name, void *data, struct file_operations *fops) | 228 | do_register(const char *name, void *data, const struct file_operations *fops) |
| 229 | { | 229 | { |
| 230 | struct proc_dir_entry *ent; | 230 | struct proc_dir_entry *ent; |
| 231 | 231 | ||
| @@ -253,7 +253,7 @@ rpc_proc_unregister(const char *name) | |||
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | struct proc_dir_entry * | 255 | struct proc_dir_entry * |
| 256 | svc_proc_register(struct svc_stat *statp, struct file_operations *fops) | 256 | svc_proc_register(struct svc_stat *statp, const struct file_operations *fops) |
| 257 | { | 257 | { |
| 258 | return do_register(statp->program->pg_name, statp, fops); | 258 | return do_register(statp->program->pg_name, statp, fops); |
| 259 | } | 259 | } |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 9f7373203592..769114f0f886 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
| @@ -105,8 +105,6 @@ EXPORT_SYMBOL(auth_unix_lookup); | |||
| 105 | EXPORT_SYMBOL(cache_check); | 105 | EXPORT_SYMBOL(cache_check); |
| 106 | EXPORT_SYMBOL(cache_flush); | 106 | EXPORT_SYMBOL(cache_flush); |
| 107 | EXPORT_SYMBOL(cache_purge); | 107 | EXPORT_SYMBOL(cache_purge); |
| 108 | EXPORT_SYMBOL(cache_fresh); | ||
| 109 | EXPORT_SYMBOL(cache_init); | ||
| 110 | EXPORT_SYMBOL(cache_register); | 108 | EXPORT_SYMBOL(cache_register); |
| 111 | EXPORT_SYMBOL(cache_unregister); | 109 | EXPORT_SYMBOL(cache_unregister); |
| 112 | EXPORT_SYMBOL(qword_add); | 110 | EXPORT_SYMBOL(qword_add); |
| @@ -142,6 +140,7 @@ EXPORT_SYMBOL(nlm_debug); | |||
| 142 | 140 | ||
| 143 | extern int register_rpc_pipefs(void); | 141 | extern int register_rpc_pipefs(void); |
| 144 | extern void unregister_rpc_pipefs(void); | 142 | extern void unregister_rpc_pipefs(void); |
| 143 | extern struct cache_detail ip_map_cache; | ||
| 145 | 144 | ||
| 146 | static int __init | 145 | static int __init |
| 147 | init_sunrpc(void) | 146 | init_sunrpc(void) |
| @@ -158,7 +157,6 @@ init_sunrpc(void) | |||
| 158 | #ifdef CONFIG_PROC_FS | 157 | #ifdef CONFIG_PROC_FS |
| 159 | rpc_proc_init(); | 158 | rpc_proc_init(); |
| 160 | #endif | 159 | #endif |
| 161 | cache_register(&auth_domain_cache); | ||
| 162 | cache_register(&ip_map_cache); | 160 | cache_register(&ip_map_cache); |
| 163 | out: | 161 | out: |
| 164 | return err; | 162 | return err; |
| @@ -169,8 +167,6 @@ cleanup_sunrpc(void) | |||
| 169 | { | 167 | { |
| 170 | unregister_rpc_pipefs(); | 168 | unregister_rpc_pipefs(); |
| 171 | rpc_destroy_mempool(); | 169 | rpc_destroy_mempool(); |
| 172 | if (cache_unregister(&auth_domain_cache)) | ||
| 173 | printk(KERN_ERR "sunrpc: failed to unregister auth_domain cache\n"); | ||
| 174 | if (cache_unregister(&ip_map_cache)) | 170 | if (cache_unregister(&ip_map_cache)) |
| 175 | printk(KERN_ERR "sunrpc: failed to unregister ip_map cache\n"); | 171 | printk(KERN_ERR "sunrpc: failed to unregister ip_map cache\n"); |
| 176 | #ifdef RPC_DEBUG | 172 | #ifdef RPC_DEBUG |
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c index dda4f0c63511..5b28c6176806 100644 --- a/net/sunrpc/svcauth.c +++ b/net/sunrpc/svcauth.c | |||
| @@ -106,112 +106,56 @@ svc_auth_unregister(rpc_authflavor_t flavor) | |||
| 106 | EXPORT_SYMBOL(svc_auth_unregister); | 106 | EXPORT_SYMBOL(svc_auth_unregister); |
| 107 | 107 | ||
| 108 | /************************************************** | 108 | /************************************************** |
| 109 | * cache for domain name to auth_domain | 109 | * 'auth_domains' are stored in a hash table indexed by name. |
| 110 | * Entries are only added by flavours which will normally | 110 | * When the last reference to an 'auth_domain' is dropped, |
| 111 | * have a structure that 'inherits' from auth_domain. | 111 | * the object is unhashed and freed. |
| 112 | * e.g. when an IP -> domainname is given to auth_unix, | 112 | * If auth_domain_lookup fails to find an entry, it will return |
| 113 | * and the domain name doesn't exist, it will create a | 113 | * it's second argument 'new'. If this is non-null, it will |
| 114 | * auth_unix_domain and add it to this hash table. | 114 | * have been atomically linked into the table. |
| 115 | * If it finds the name does exist, but isn't AUTH_UNIX, | ||
| 116 | * it will complain. | ||
| 117 | */ | 115 | */ |
| 118 | 116 | ||
| 119 | /* | ||
| 120 | * Auth auth_domain cache is somewhat different to other caches, | ||
| 121 | * largely because the entries are possibly of different types: | ||
| 122 | * each auth flavour has it's own type. | ||
| 123 | * One consequence of this that DefineCacheLookup cannot | ||
| 124 | * allocate a new structure as it cannot know the size. | ||
| 125 | * Notice that the "INIT" code fragment is quite different | ||
| 126 | * from other caches. When auth_domain_lookup might be | ||
| 127 | * creating a new domain, the new domain is passed in | ||
| 128 | * complete and it is used as-is rather than being copied into | ||
| 129 | * another structure. | ||
| 130 | */ | ||
| 131 | #define DN_HASHBITS 6 | 117 | #define DN_HASHBITS 6 |
| 132 | #define DN_HASHMAX (1<<DN_HASHBITS) | 118 | #define DN_HASHMAX (1<<DN_HASHBITS) |
| 133 | #define DN_HASHMASK (DN_HASHMAX-1) | 119 | #define DN_HASHMASK (DN_HASHMAX-1) |
| 134 | 120 | ||
| 135 | static struct cache_head *auth_domain_table[DN_HASHMAX]; | 121 | static struct hlist_head auth_domain_table[DN_HASHMAX]; |
| 136 | 122 | static spinlock_t auth_domain_lock = SPIN_LOCK_UNLOCKED; | |
| 137 | static void auth_domain_drop(struct cache_head *item, struct cache_detail *cd) | ||
| 138 | { | ||
| 139 | struct auth_domain *dom = container_of(item, struct auth_domain, h); | ||
| 140 | if (cache_put(item,cd)) | ||
| 141 | authtab[dom->flavour]->domain_release(dom); | ||
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | struct cache_detail auth_domain_cache = { | ||
| 146 | .owner = THIS_MODULE, | ||
| 147 | .hash_size = DN_HASHMAX, | ||
| 148 | .hash_table = auth_domain_table, | ||
| 149 | .name = "auth.domain", | ||
| 150 | .cache_put = auth_domain_drop, | ||
| 151 | }; | ||
| 152 | 123 | ||
| 153 | void auth_domain_put(struct auth_domain *dom) | 124 | void auth_domain_put(struct auth_domain *dom) |
| 154 | { | 125 | { |
| 155 | auth_domain_drop(&dom->h, &auth_domain_cache); | 126 | if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) { |
| 156 | } | 127 | hlist_del(&dom->hash); |
| 157 | 128 | dom->flavour->domain_release(dom); | |
| 158 | static inline int auth_domain_hash(struct auth_domain *item) | 129 | } |
| 159 | { | ||
| 160 | return hash_str(item->name, DN_HASHBITS); | ||
| 161 | } | ||
| 162 | static inline int auth_domain_match(struct auth_domain *tmp, struct auth_domain *item) | ||
| 163 | { | ||
| 164 | return strcmp(tmp->name, item->name) == 0; | ||
| 165 | } | 130 | } |
| 166 | 131 | ||
| 167 | struct auth_domain * | 132 | struct auth_domain * |
| 168 | auth_domain_lookup(struct auth_domain *item, int set) | 133 | auth_domain_lookup(char *name, struct auth_domain *new) |
| 169 | { | 134 | { |
| 170 | struct auth_domain *tmp = NULL; | 135 | struct auth_domain *hp; |
| 171 | struct cache_head **hp, **head; | 136 | struct hlist_head *head; |
| 172 | head = &auth_domain_cache.hash_table[auth_domain_hash(item)]; | 137 | struct hlist_node *np; |
| 173 | 138 | ||
| 174 | if (set) | 139 | head = &auth_domain_table[hash_str(name, DN_HASHBITS)]; |
| 175 | write_lock(&auth_domain_cache.hash_lock); | 140 | |
| 176 | else | 141 | spin_lock(&auth_domain_lock); |
| 177 | read_lock(&auth_domain_cache.hash_lock); | 142 | |
| 178 | for (hp=head; *hp != NULL; hp = &tmp->h.next) { | 143 | hlist_for_each_entry(hp, np, head, hash) { |
| 179 | tmp = container_of(*hp, struct auth_domain, h); | 144 | if (strcmp(hp->name, name)==0) { |
| 180 | if (!auth_domain_match(tmp, item)) | 145 | kref_get(&hp->ref); |
| 181 | continue; | 146 | spin_unlock(&auth_domain_lock); |
| 182 | if (!set) { | 147 | return hp; |
| 183 | cache_get(&tmp->h); | ||
| 184 | goto out_noset; | ||
| 185 | } | 148 | } |
| 186 | *hp = tmp->h.next; | ||
| 187 | tmp->h.next = NULL; | ||
| 188 | auth_domain_drop(&tmp->h, &auth_domain_cache); | ||
| 189 | goto out_set; | ||
| 190 | } | 149 | } |
| 191 | /* Didn't find anything */ | 150 | if (new) { |
| 192 | if (!set) | 151 | hlist_add_head(&new->hash, head); |
| 193 | goto out_nada; | 152 | kref_get(&new->ref); |
| 194 | auth_domain_cache.entries++; | 153 | } |
| 195 | out_set: | 154 | spin_unlock(&auth_domain_lock); |
| 196 | item->h.next = *head; | 155 | return new; |
| 197 | *head = &item->h; | ||
| 198 | cache_get(&item->h); | ||
| 199 | write_unlock(&auth_domain_cache.hash_lock); | ||
| 200 | cache_fresh(&auth_domain_cache, &item->h, item->h.expiry_time); | ||
| 201 | cache_get(&item->h); | ||
| 202 | return item; | ||
| 203 | out_nada: | ||
| 204 | tmp = NULL; | ||
| 205 | out_noset: | ||
| 206 | read_unlock(&auth_domain_cache.hash_lock); | ||
| 207 | return tmp; | ||
| 208 | } | 156 | } |
| 209 | 157 | ||
| 210 | struct auth_domain *auth_domain_find(char *name) | 158 | struct auth_domain *auth_domain_find(char *name) |
| 211 | { | 159 | { |
| 212 | struct auth_domain *rv, ad; | 160 | return auth_domain_lookup(name, NULL); |
| 213 | |||
| 214 | ad.name = name; | ||
| 215 | rv = auth_domain_lookup(&ad, 0); | ||
| 216 | return rv; | ||
| 217 | } | 161 | } |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 3e6c694bbad1..7e5707e2d6b6 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
| @@ -27,41 +27,35 @@ struct unix_domain { | |||
| 27 | /* other stuff later */ | 27 | /* other stuff later */ |
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | extern struct auth_ops svcauth_unix; | ||
| 31 | |||
| 30 | struct auth_domain *unix_domain_find(char *name) | 32 | struct auth_domain *unix_domain_find(char *name) |
| 31 | { | 33 | { |
| 32 | struct auth_domain *rv, ud; | 34 | struct auth_domain *rv; |
| 33 | struct unix_domain *new; | 35 | struct unix_domain *new = NULL; |
| 34 | 36 | ||
| 35 | ud.name = name; | 37 | rv = auth_domain_lookup(name, NULL); |
| 36 | 38 | while(1) { | |
| 37 | rv = auth_domain_lookup(&ud, 0); | 39 | if (rv) { |
| 38 | 40 | if (new && rv != &new->h) | |
| 39 | foundit: | 41 | auth_domain_put(&new->h); |
| 40 | if (rv && rv->flavour != RPC_AUTH_UNIX) { | 42 | |
| 41 | auth_domain_put(rv); | 43 | if (rv->flavour != &svcauth_unix) { |
| 42 | return NULL; | 44 | auth_domain_put(rv); |
| 43 | } | 45 | return NULL; |
| 44 | if (rv) | 46 | } |
| 45 | return rv; | 47 | return rv; |
| 46 | 48 | } | |
| 47 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 49 | |
| 48 | if (new == NULL) | 50 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
| 49 | return NULL; | 51 | if (new == NULL) |
| 50 | cache_init(&new->h.h); | 52 | return NULL; |
| 51 | new->h.name = kstrdup(name, GFP_KERNEL); | 53 | kref_init(&new->h.ref); |
| 52 | new->h.flavour = RPC_AUTH_UNIX; | 54 | new->h.name = kstrdup(name, GFP_KERNEL); |
| 53 | new->addr_changes = 0; | 55 | new->h.flavour = &svcauth_unix; |
| 54 | new->h.h.expiry_time = NEVER; | 56 | new->addr_changes = 0; |
| 55 | 57 | rv = auth_domain_lookup(name, &new->h); | |
| 56 | rv = auth_domain_lookup(&new->h, 2); | ||
| 57 | if (rv == &new->h) { | ||
| 58 | if (atomic_dec_and_test(&new->h.h.refcnt)) BUG(); | ||
| 59 | } else { | ||
| 60 | auth_domain_put(&new->h); | ||
| 61 | goto foundit; | ||
| 62 | } | 58 | } |
| 63 | |||
| 64 | return rv; | ||
| 65 | } | 59 | } |
| 66 | 60 | ||
| 67 | static void svcauth_unix_domain_release(struct auth_domain *dom) | 61 | static void svcauth_unix_domain_release(struct auth_domain *dom) |
| @@ -90,15 +84,15 @@ struct ip_map { | |||
| 90 | }; | 84 | }; |
| 91 | static struct cache_head *ip_table[IP_HASHMAX]; | 85 | static struct cache_head *ip_table[IP_HASHMAX]; |
| 92 | 86 | ||
| 93 | static void ip_map_put(struct cache_head *item, struct cache_detail *cd) | 87 | static void ip_map_put(struct kref *kref) |
| 94 | { | 88 | { |
| 89 | struct cache_head *item = container_of(kref, struct cache_head, ref); | ||
| 95 | struct ip_map *im = container_of(item, struct ip_map,h); | 90 | struct ip_map *im = container_of(item, struct ip_map,h); |
| 96 | if (cache_put(item, cd)) { | 91 | |
| 97 | if (test_bit(CACHE_VALID, &item->flags) && | 92 | if (test_bit(CACHE_VALID, &item->flags) && |
| 98 | !test_bit(CACHE_NEGATIVE, &item->flags)) | 93 | !test_bit(CACHE_NEGATIVE, &item->flags)) |
| 99 | auth_domain_put(&im->m_client->h); | 94 | auth_domain_put(&im->m_client->h); |
| 100 | kfree(im); | 95 | kfree(im); |
| 101 | } | ||
| 102 | } | 96 | } |
| 103 | 97 | ||
| 104 | #if IP_HASHBITS == 8 | 98 | #if IP_HASHBITS == 8 |
| @@ -112,28 +106,38 @@ static inline int hash_ip(unsigned long ip) | |||
| 112 | return (hash ^ (hash>>8)) & 0xff; | 106 | return (hash ^ (hash>>8)) & 0xff; |
| 113 | } | 107 | } |
| 114 | #endif | 108 | #endif |
| 115 | 109 | static int ip_map_match(struct cache_head *corig, struct cache_head *cnew) | |
| 116 | static inline int ip_map_hash(struct ip_map *item) | ||
| 117 | { | ||
| 118 | return hash_str(item->m_class, IP_HASHBITS) ^ | ||
| 119 | hash_ip((unsigned long)item->m_addr.s_addr); | ||
| 120 | } | ||
| 121 | static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp) | ||
| 122 | { | 110 | { |
| 123 | return strcmp(tmp->m_class, item->m_class) == 0 | 111 | struct ip_map *orig = container_of(corig, struct ip_map, h); |
| 124 | && tmp->m_addr.s_addr == item->m_addr.s_addr; | 112 | struct ip_map *new = container_of(cnew, struct ip_map, h); |
| 113 | return strcmp(orig->m_class, new->m_class) == 0 | ||
| 114 | && orig->m_addr.s_addr == new->m_addr.s_addr; | ||
| 125 | } | 115 | } |
| 126 | static inline void ip_map_init(struct ip_map *new, struct ip_map *item) | 116 | static void ip_map_init(struct cache_head *cnew, struct cache_head *citem) |
| 127 | { | 117 | { |
| 118 | struct ip_map *new = container_of(cnew, struct ip_map, h); | ||
| 119 | struct ip_map *item = container_of(citem, struct ip_map, h); | ||
| 120 | |||
| 128 | strcpy(new->m_class, item->m_class); | 121 | strcpy(new->m_class, item->m_class); |
| 129 | new->m_addr.s_addr = item->m_addr.s_addr; | 122 | new->m_addr.s_addr = item->m_addr.s_addr; |
| 130 | } | 123 | } |
| 131 | static inline void ip_map_update(struct ip_map *new, struct ip_map *item) | 124 | static void update(struct cache_head *cnew, struct cache_head *citem) |
| 132 | { | 125 | { |
| 133 | cache_get(&item->m_client->h.h); | 126 | struct ip_map *new = container_of(cnew, struct ip_map, h); |
| 127 | struct ip_map *item = container_of(citem, struct ip_map, h); | ||
| 128 | |||
| 129 | kref_get(&item->m_client->h.ref); | ||
| 134 | new->m_client = item->m_client; | 130 | new->m_client = item->m_client; |
| 135 | new->m_add_change = item->m_add_change; | 131 | new->m_add_change = item->m_add_change; |
| 136 | } | 132 | } |
| 133 | static struct cache_head *ip_map_alloc(void) | ||
| 134 | { | ||
| 135 | struct ip_map *i = kmalloc(sizeof(*i), GFP_KERNEL); | ||
| 136 | if (i) | ||
| 137 | return &i->h; | ||
| 138 | else | ||
| 139 | return NULL; | ||
| 140 | } | ||
| 137 | 141 | ||
| 138 | static void ip_map_request(struct cache_detail *cd, | 142 | static void ip_map_request(struct cache_detail *cd, |
| 139 | struct cache_head *h, | 143 | struct cache_head *h, |
| @@ -154,7 +158,8 @@ static void ip_map_request(struct cache_detail *cd, | |||
| 154 | (*bpp)[-1] = '\n'; | 158 | (*bpp)[-1] = '\n'; |
| 155 | } | 159 | } |
| 156 | 160 | ||
| 157 | static struct ip_map *ip_map_lookup(struct ip_map *, int); | 161 | static struct ip_map *ip_map_lookup(char *class, struct in_addr addr); |
| 162 | static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry); | ||
| 158 | 163 | ||
| 159 | static int ip_map_parse(struct cache_detail *cd, | 164 | static int ip_map_parse(struct cache_detail *cd, |
| 160 | char *mesg, int mlen) | 165 | char *mesg, int mlen) |
| @@ -166,7 +171,11 @@ static int ip_map_parse(struct cache_detail *cd, | |||
| 166 | int len; | 171 | int len; |
| 167 | int b1,b2,b3,b4; | 172 | int b1,b2,b3,b4; |
| 168 | char c; | 173 | char c; |
| 169 | struct ip_map ipm, *ipmp; | 174 | char class[8]; |
| 175 | struct in_addr addr; | ||
| 176 | int err; | ||
| 177 | |||
| 178 | struct ip_map *ipmp; | ||
| 170 | struct auth_domain *dom; | 179 | struct auth_domain *dom; |
| 171 | time_t expiry; | 180 | time_t expiry; |
| 172 | 181 | ||
| @@ -175,7 +184,7 @@ static int ip_map_parse(struct cache_detail *cd, | |||
| 175 | mesg[mlen-1] = 0; | 184 | mesg[mlen-1] = 0; |
| 176 | 185 | ||
| 177 | /* class */ | 186 | /* class */ |
| 178 | len = qword_get(&mesg, ipm.m_class, sizeof(ipm.m_class)); | 187 | len = qword_get(&mesg, class, sizeof(class)); |
| 179 | if (len <= 0) return -EINVAL; | 188 | if (len <= 0) return -EINVAL; |
| 180 | 189 | ||
| 181 | /* ip address */ | 190 | /* ip address */ |
| @@ -200,25 +209,22 @@ static int ip_map_parse(struct cache_detail *cd, | |||
| 200 | } else | 209 | } else |
| 201 | dom = NULL; | 210 | dom = NULL; |
| 202 | 211 | ||
| 203 | ipm.m_addr.s_addr = | 212 | addr.s_addr = |
| 204 | htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4); | 213 | htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4); |
| 205 | ipm.h.flags = 0; | 214 | |
| 206 | if (dom) { | 215 | ipmp = ip_map_lookup(class,addr); |
| 207 | ipm.m_client = container_of(dom, struct unix_domain, h); | 216 | if (ipmp) { |
| 208 | ipm.m_add_change = ipm.m_client->addr_changes; | 217 | err = ip_map_update(ipmp, |
| 218 | container_of(dom, struct unix_domain, h), | ||
| 219 | expiry); | ||
| 209 | } else | 220 | } else |
| 210 | set_bit(CACHE_NEGATIVE, &ipm.h.flags); | 221 | err = -ENOMEM; |
| 211 | ipm.h.expiry_time = expiry; | ||
| 212 | 222 | ||
| 213 | ipmp = ip_map_lookup(&ipm, 1); | ||
| 214 | if (ipmp) | ||
| 215 | ip_map_put(&ipmp->h, &ip_map_cache); | ||
| 216 | if (dom) | 223 | if (dom) |
| 217 | auth_domain_put(dom); | 224 | auth_domain_put(dom); |
| 218 | if (!ipmp) | 225 | |
| 219 | return -ENOMEM; | ||
| 220 | cache_flush(); | 226 | cache_flush(); |
| 221 | return 0; | 227 | return err; |
| 222 | } | 228 | } |
| 223 | 229 | ||
| 224 | static int ip_map_show(struct seq_file *m, | 230 | static int ip_map_show(struct seq_file *m, |
| @@ -262,32 +268,70 @@ struct cache_detail ip_map_cache = { | |||
| 262 | .cache_request = ip_map_request, | 268 | .cache_request = ip_map_request, |
| 263 | .cache_parse = ip_map_parse, | 269 | .cache_parse = ip_map_parse, |
| 264 | .cache_show = ip_map_show, | 270 | .cache_show = ip_map_show, |
| 271 | .match = ip_map_match, | ||
| 272 | .init = ip_map_init, | ||
| 273 | .update = update, | ||
| 274 | .alloc = ip_map_alloc, | ||
| 265 | }; | 275 | }; |
| 266 | 276 | ||
| 267 | static DefineSimpleCacheLookup(ip_map, 0) | 277 | static struct ip_map *ip_map_lookup(char *class, struct in_addr addr) |
| 278 | { | ||
| 279 | struct ip_map ip; | ||
| 280 | struct cache_head *ch; | ||
| 281 | |||
| 282 | strcpy(ip.m_class, class); | ||
| 283 | ip.m_addr = addr; | ||
| 284 | ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h, | ||
| 285 | hash_str(class, IP_HASHBITS) ^ | ||
| 286 | hash_ip((unsigned long)addr.s_addr)); | ||
| 287 | |||
| 288 | if (ch) | ||
| 289 | return container_of(ch, struct ip_map, h); | ||
| 290 | else | ||
| 291 | return NULL; | ||
| 292 | } | ||
| 268 | 293 | ||
| 294 | static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry) | ||
| 295 | { | ||
| 296 | struct ip_map ip; | ||
| 297 | struct cache_head *ch; | ||
| 298 | |||
| 299 | ip.m_client = udom; | ||
| 300 | ip.h.flags = 0; | ||
| 301 | if (!udom) | ||
| 302 | set_bit(CACHE_NEGATIVE, &ip.h.flags); | ||
| 303 | else { | ||
| 304 | ip.m_add_change = udom->addr_changes; | ||
| 305 | /* if this is from the legacy set_client system call, | ||
| 306 | * we need m_add_change to be one higher | ||
| 307 | */ | ||
| 308 | if (expiry == NEVER) | ||
| 309 | ip.m_add_change++; | ||
| 310 | } | ||
| 311 | ip.h.expiry_time = expiry; | ||
| 312 | ch = sunrpc_cache_update(&ip_map_cache, | ||
| 313 | &ip.h, &ipm->h, | ||
| 314 | hash_str(ipm->m_class, IP_HASHBITS) ^ | ||
| 315 | hash_ip((unsigned long)ipm->m_addr.s_addr)); | ||
| 316 | if (!ch) | ||
| 317 | return -ENOMEM; | ||
| 318 | cache_put(ch, &ip_map_cache); | ||
| 319 | return 0; | ||
| 320 | } | ||
| 269 | 321 | ||
| 270 | int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom) | 322 | int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom) |
| 271 | { | 323 | { |
| 272 | struct unix_domain *udom; | 324 | struct unix_domain *udom; |
| 273 | struct ip_map ip, *ipmp; | 325 | struct ip_map *ipmp; |
| 274 | 326 | ||
| 275 | if (dom->flavour != RPC_AUTH_UNIX) | 327 | if (dom->flavour != &svcauth_unix) |
| 276 | return -EINVAL; | 328 | return -EINVAL; |
| 277 | udom = container_of(dom, struct unix_domain, h); | 329 | udom = container_of(dom, struct unix_domain, h); |
| 278 | strcpy(ip.m_class, "nfsd"); | 330 | ipmp = ip_map_lookup("nfsd", addr); |
| 279 | ip.m_addr = addr; | ||
| 280 | ip.m_client = udom; | ||
| 281 | ip.m_add_change = udom->addr_changes+1; | ||
| 282 | ip.h.flags = 0; | ||
| 283 | ip.h.expiry_time = NEVER; | ||
| 284 | |||
| 285 | ipmp = ip_map_lookup(&ip, 1); | ||
| 286 | 331 | ||
| 287 | if (ipmp) { | 332 | if (ipmp) |
| 288 | ip_map_put(&ipmp->h, &ip_map_cache); | 333 | return ip_map_update(ipmp, udom, NEVER); |
| 289 | return 0; | 334 | else |
| 290 | } else | ||
| 291 | return -ENOMEM; | 335 | return -ENOMEM; |
| 292 | } | 336 | } |
| 293 | 337 | ||
| @@ -295,7 +339,7 @@ int auth_unix_forget_old(struct auth_domain *dom) | |||
| 295 | { | 339 | { |
| 296 | struct unix_domain *udom; | 340 | struct unix_domain *udom; |
| 297 | 341 | ||
| 298 | if (dom->flavour != RPC_AUTH_UNIX) | 342 | if (dom->flavour != &svcauth_unix) |
| 299 | return -EINVAL; | 343 | return -EINVAL; |
| 300 | udom = container_of(dom, struct unix_domain, h); | 344 | udom = container_of(dom, struct unix_domain, h); |
| 301 | udom->addr_changes++; | 345 | udom->addr_changes++; |
| @@ -310,7 +354,7 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr) | |||
| 310 | strcpy(key.m_class, "nfsd"); | 354 | strcpy(key.m_class, "nfsd"); |
| 311 | key.m_addr = addr; | 355 | key.m_addr = addr; |
| 312 | 356 | ||
| 313 | ipm = ip_map_lookup(&key, 0); | 357 | ipm = ip_map_lookup("nfsd", addr); |
| 314 | 358 | ||
| 315 | if (!ipm) | 359 | if (!ipm) |
| 316 | return NULL; | 360 | return NULL; |
| @@ -323,31 +367,28 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr) | |||
| 323 | rv = NULL; | 367 | rv = NULL; |
| 324 | } else { | 368 | } else { |
| 325 | rv = &ipm->m_client->h; | 369 | rv = &ipm->m_client->h; |
| 326 | cache_get(&rv->h); | 370 | kref_get(&rv->ref); |
| 327 | } | 371 | } |
| 328 | ip_map_put(&ipm->h, &ip_map_cache); | 372 | cache_put(&ipm->h, &ip_map_cache); |
| 329 | return rv; | 373 | return rv; |
| 330 | } | 374 | } |
| 331 | 375 | ||
| 332 | void svcauth_unix_purge(void) | 376 | void svcauth_unix_purge(void) |
| 333 | { | 377 | { |
| 334 | cache_purge(&ip_map_cache); | 378 | cache_purge(&ip_map_cache); |
| 335 | cache_purge(&auth_domain_cache); | ||
| 336 | } | 379 | } |
| 337 | 380 | ||
| 338 | static int | 381 | static int |
| 339 | svcauth_unix_set_client(struct svc_rqst *rqstp) | 382 | svcauth_unix_set_client(struct svc_rqst *rqstp) |
| 340 | { | 383 | { |
| 341 | struct ip_map key, *ipm; | 384 | struct ip_map *ipm; |
| 342 | 385 | ||
| 343 | rqstp->rq_client = NULL; | 386 | rqstp->rq_client = NULL; |
| 344 | if (rqstp->rq_proc == 0) | 387 | if (rqstp->rq_proc == 0) |
| 345 | return SVC_OK; | 388 | return SVC_OK; |
| 346 | 389 | ||
| 347 | strcpy(key.m_class, rqstp->rq_server->sv_program->pg_class); | 390 | ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class, |
| 348 | key.m_addr = rqstp->rq_addr.sin_addr; | 391 | rqstp->rq_addr.sin_addr); |
| 349 | |||
| 350 | ipm = ip_map_lookup(&key, 0); | ||
| 351 | 392 | ||
| 352 | if (ipm == NULL) | 393 | if (ipm == NULL) |
| 353 | return SVC_DENIED; | 394 | return SVC_DENIED; |
| @@ -361,8 +402,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) | |||
| 361 | return SVC_DENIED; | 402 | return SVC_DENIED; |
| 362 | case 0: | 403 | case 0: |
| 363 | rqstp->rq_client = &ipm->m_client->h; | 404 | rqstp->rq_client = &ipm->m_client->h; |
| 364 | cache_get(&rqstp->rq_client->h); | 405 | kref_get(&rqstp->rq_client->ref); |
| 365 | ip_map_put(&ipm->h, &ip_map_cache); | 406 | cache_put(&ipm->h, &ip_map_cache); |
| 366 | break; | 407 | break; |
| 367 | } | 408 | } |
| 368 | return SVC_OK; | 409 | return SVC_OK; |
diff --git a/sound/core/init.c b/sound/core/init.c index ad68761abba1..5bb8a8b23d51 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
| @@ -223,7 +223,8 @@ int snd_card_disconnect(struct snd_card *card) | |||
| 223 | struct snd_monitor_file *mfile; | 223 | struct snd_monitor_file *mfile; |
| 224 | struct file *file; | 224 | struct file *file; |
| 225 | struct snd_shutdown_f_ops *s_f_ops; | 225 | struct snd_shutdown_f_ops *s_f_ops; |
| 226 | struct file_operations *f_ops, *old_f_ops; | 226 | struct file_operations *f_ops; |
| 227 | const struct file_operations *old_f_ops; | ||
| 227 | int err; | 228 | int err; |
| 228 | 229 | ||
| 229 | spin_lock(&card->files_lock); | 230 | spin_lock(&card->files_lock); |
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 6b7a36774298..87b47c9564f7 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
| @@ -631,7 +631,8 @@ int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, | |||
| 631 | return -EINVAL; | 631 | return -EINVAL; |
| 632 | } | 632 | } |
| 633 | if (params->buffer_size != runtime->buffer_size) { | 633 | if (params->buffer_size != runtime->buffer_size) { |
| 634 | if ((newbuf = (char *) kmalloc(params->buffer_size, GFP_KERNEL)) == NULL) | 634 | newbuf = kmalloc(params->buffer_size, GFP_KERNEL); |
| 635 | if (!newbuf) | ||
| 635 | return -ENOMEM; | 636 | return -ENOMEM; |
| 636 | kfree(runtime->buffer); | 637 | kfree(runtime->buffer); |
| 637 | runtime->buffer = newbuf; | 638 | runtime->buffer = newbuf; |
| @@ -657,7 +658,8 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream, | |||
| 657 | return -EINVAL; | 658 | return -EINVAL; |
| 658 | } | 659 | } |
| 659 | if (params->buffer_size != runtime->buffer_size) { | 660 | if (params->buffer_size != runtime->buffer_size) { |
| 660 | if ((newbuf = (char *) kmalloc(params->buffer_size, GFP_KERNEL)) == NULL) | 661 | newbuf = kmalloc(params->buffer_size, GFP_KERNEL); |
| 662 | if (!newbuf) | ||
| 661 | return -ENOMEM; | 663 | return -ENOMEM; |
| 662 | kfree(runtime->buffer); | 664 | kfree(runtime->buffer); |
| 663 | runtime->buffer = newbuf; | 665 | runtime->buffer = newbuf; |
diff --git a/sound/core/sound.c b/sound/core/sound.c index 4d28e5212611..108e430b5036 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
| @@ -137,7 +137,7 @@ static int snd_open(struct inode *inode, struct file *file) | |||
| 137 | { | 137 | { |
| 138 | unsigned int minor = iminor(inode); | 138 | unsigned int minor = iminor(inode); |
| 139 | struct snd_minor *mptr = NULL; | 139 | struct snd_minor *mptr = NULL; |
| 140 | struct file_operations *old_fops; | 140 | const struct file_operations *old_fops; |
| 141 | int err = 0; | 141 | int err = 0; |
| 142 | 142 | ||
| 143 | if (minor >= ARRAY_SIZE(snd_minors)) | 143 | if (minor >= ARRAY_SIZE(snd_minors)) |
| @@ -240,7 +240,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev) | |||
| 240 | * Retrurns zero if successful, or a negative error code on failure. | 240 | * Retrurns zero if successful, or a negative error code on failure. |
| 241 | */ | 241 | */ |
| 242 | int snd_register_device(int type, struct snd_card *card, int dev, | 242 | int snd_register_device(int type, struct snd_card *card, int dev, |
| 243 | struct file_operations *f_ops, void *private_data, | 243 | const struct file_operations *f_ops, void *private_data, |
| 244 | const char *name) | 244 | const char *name) |
| 245 | { | 245 | { |
| 246 | int minor; | 246 | int minor; |
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 4023d3b406de..9055c6de9587 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c | |||
| @@ -95,7 +95,7 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) | |||
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | int snd_register_oss_device(int type, struct snd_card *card, int dev, | 97 | int snd_register_oss_device(int type, struct snd_card *card, int dev, |
| 98 | struct file_operations *f_ops, void *private_data, | 98 | const struct file_operations *f_ops, void *private_data, |
| 99 | const char *name) | 99 | const char *name) |
| 100 | { | 100 | { |
| 101 | int minor = snd_oss_kernel_minor(type, card, dev); | 101 | int minor = snd_oss_kernel_minor(type, card, dev); |
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 9d10d79e27af..9ea3059a7064 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c | |||
| @@ -59,7 +59,8 @@ module_param_array(irq, int, NULL, 0444); | |||
| 59 | MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device."); | 59 | MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device."); |
| 60 | 60 | ||
| 61 | static struct platform_device *platform_devices[SNDRV_CARDS]; | 61 | static struct platform_device *platform_devices[SNDRV_CARDS]; |
| 62 | static int pnp_registered = 0; | 62 | static int pnp_registered; |
| 63 | static unsigned int snd_mpu401_devices; | ||
| 63 | 64 | ||
| 64 | static int snd_mpu401_create(int dev, struct snd_card **rcard) | 65 | static int snd_mpu401_create(int dev, struct snd_card **rcard) |
| 65 | { | 66 | { |
| @@ -197,6 +198,7 @@ static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev, | |||
| 197 | } | 198 | } |
| 198 | snd_card_set_dev(card, &pnp_dev->dev); | 199 | snd_card_set_dev(card, &pnp_dev->dev); |
| 199 | pnp_set_drvdata(pnp_dev, card); | 200 | pnp_set_drvdata(pnp_dev, card); |
| 201 | snd_mpu401_devices++; | ||
| 200 | ++dev; | 202 | ++dev; |
| 201 | return 0; | 203 | return 0; |
| 202 | } | 204 | } |
| @@ -234,12 +236,11 @@ static void __init_or_module snd_mpu401_unregister_all(void) | |||
| 234 | 236 | ||
| 235 | static int __init alsa_card_mpu401_init(void) | 237 | static int __init alsa_card_mpu401_init(void) |
| 236 | { | 238 | { |
| 237 | int i, err, devices; | 239 | int i, err; |
| 238 | 240 | ||
| 239 | if ((err = platform_driver_register(&snd_mpu401_driver)) < 0) | 241 | if ((err = platform_driver_register(&snd_mpu401_driver)) < 0) |
| 240 | return err; | 242 | return err; |
| 241 | 243 | ||
| 242 | devices = 0; | ||
| 243 | for (i = 0; i < SNDRV_CARDS; i++) { | 244 | for (i = 0; i < SNDRV_CARDS; i++) { |
| 244 | struct platform_device *device; | 245 | struct platform_device *device; |
| 245 | if (! enable[i]) | 246 | if (! enable[i]) |
| @@ -255,14 +256,13 @@ static int __init alsa_card_mpu401_init(void) | |||
| 255 | goto errout; | 256 | goto errout; |
| 256 | } | 257 | } |
| 257 | platform_devices[i] = device; | 258 | platform_devices[i] = device; |
| 258 | devices++; | 259 | snd_mpu401_devices++; |
| 259 | } | 260 | } |
| 260 | if ((err = pnp_register_driver(&snd_mpu401_pnp_driver)) >= 0) { | 261 | err = pnp_register_driver(&snd_mpu401_pnp_driver); |
| 262 | if (!err) | ||
| 261 | pnp_registered = 1; | 263 | pnp_registered = 1; |
| 262 | devices += err; | ||
| 263 | } | ||
| 264 | 264 | ||
| 265 | if (!devices) { | 265 | if (!snd_mpu401_devices) { |
| 266 | #ifdef MODULE | 266 | #ifdef MODULE |
| 267 | printk(KERN_ERR "MPU-401 device not found or device busy\n"); | 267 | printk(KERN_ERR "MPU-401 device not found or device busy\n"); |
| 268 | #endif | 268 | #endif |
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 7051f7798ed7..31f299aed281 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c | |||
| @@ -262,6 +262,8 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard | |||
| 262 | return 0; | 262 | return 0; |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | static unsigned int __devinitdata ad1816a_devices; | ||
| 266 | |||
| 265 | static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card, | 267 | static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card, |
| 266 | const struct pnp_card_device_id *id) | 268 | const struct pnp_card_device_id *id) |
| 267 | { | 269 | { |
| @@ -275,6 +277,7 @@ static int __devinit snd_ad1816a_pnp_detect(struct pnp_card_link *card, | |||
| 275 | if (res < 0) | 277 | if (res < 0) |
| 276 | return res; | 278 | return res; |
| 277 | dev++; | 279 | dev++; |
| 280 | ad1816a_devices++; | ||
| 278 | return 0; | 281 | return 0; |
| 279 | } | 282 | } |
| 280 | return -ENODEV; | 283 | return -ENODEV; |
| @@ -297,10 +300,13 @@ static struct pnp_card_driver ad1816a_pnpc_driver = { | |||
| 297 | 300 | ||
| 298 | static int __init alsa_card_ad1816a_init(void) | 301 | static int __init alsa_card_ad1816a_init(void) |
| 299 | { | 302 | { |
| 300 | int cards; | 303 | int err; |
| 304 | |||
| 305 | err = pnp_register_card_driver(&ad1816a_pnpc_driver); | ||
| 306 | if (err) | ||
| 307 | return err; | ||
| 301 | 308 | ||
| 302 | cards = pnp_register_card_driver(&ad1816a_pnpc_driver); | 309 | if (!ad1816a_devices) { |
| 303 | if (cards <= 0) { | ||
| 304 | pnp_unregister_card_driver(&ad1816a_pnpc_driver); | 310 | pnp_unregister_card_driver(&ad1816a_pnpc_driver); |
| 305 | #ifdef MODULE | 311 | #ifdef MODULE |
| 306 | printk(KERN_ERR "no AD1816A based soundcards found.\n"); | 312 | printk(KERN_ERR "no AD1816A based soundcards found.\n"); |
diff --git a/sound/isa/als100.c b/sound/isa/als100.c index 9b77c17b3f66..a52bd8a14c9b 100644 --- a/sound/isa/als100.c +++ b/sound/isa/als100.c | |||
| @@ -199,7 +199,7 @@ static int __devinit snd_card_als100_pnp(int dev, struct snd_card_als100 *acard, | |||
| 199 | return 0; | 199 | return 0; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | static int __init snd_card_als100_probe(int dev, | 202 | static int __devinit snd_card_als100_probe(int dev, |
| 203 | struct pnp_card_link *pcard, | 203 | struct pnp_card_link *pcard, |
| 204 | const struct pnp_card_device_id *pid) | 204 | const struct pnp_card_device_id *pid) |
| 205 | { | 205 | { |
| @@ -281,6 +281,8 @@ static int __init snd_card_als100_probe(int dev, | |||
| 281 | return 0; | 281 | return 0; |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | static unsigned int __devinitdata als100_devices; | ||
| 285 | |||
| 284 | static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card, | 286 | static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card, |
| 285 | const struct pnp_card_device_id *id) | 287 | const struct pnp_card_device_id *id) |
| 286 | { | 288 | { |
| @@ -294,6 +296,7 @@ static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card, | |||
| 294 | if (res < 0) | 296 | if (res < 0) |
| 295 | return res; | 297 | return res; |
| 296 | dev++; | 298 | dev++; |
| 299 | als100_devices++; | ||
| 297 | return 0; | 300 | return 0; |
| 298 | } | 301 | } |
| 299 | return -ENODEV; | 302 | return -ENODEV; |
| @@ -345,10 +348,13 @@ static struct pnp_card_driver als100_pnpc_driver = { | |||
| 345 | 348 | ||
| 346 | static int __init alsa_card_als100_init(void) | 349 | static int __init alsa_card_als100_init(void) |
| 347 | { | 350 | { |
| 348 | int cards; | 351 | int err; |
| 352 | |||
| 353 | err = pnp_register_card_driver(&als100_pnpc_driver); | ||
| 354 | if (err) | ||
| 355 | return err; | ||
| 349 | 356 | ||
| 350 | cards = pnp_register_card_driver(&als100_pnpc_driver); | 357 | if (!als100_devices) { |
| 351 | if (cards <= 0) { | ||
| 352 | pnp_unregister_card_driver(&als100_pnpc_driver); | 358 | pnp_unregister_card_driver(&als100_pnpc_driver); |
| 353 | #ifdef MODULE | 359 | #ifdef MODULE |
| 354 | snd_printk(KERN_ERR "no ALS100 based soundcards found\n"); | 360 | snd_printk(KERN_ERR "no ALS100 based soundcards found\n"); |
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c index a530691bf4f7..15e59283aac6 100644 --- a/sound/isa/azt2320.c +++ b/sound/isa/azt2320.c | |||
| @@ -310,6 +310,8 @@ static int __devinit snd_card_azt2320_probe(int dev, | |||
| 310 | return 0; | 310 | return 0; |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | static unsigned int __devinitdata azt2320_devices; | ||
| 314 | |||
| 313 | static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card, | 315 | static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card, |
| 314 | const struct pnp_card_device_id *id) | 316 | const struct pnp_card_device_id *id) |
| 315 | { | 317 | { |
| @@ -323,6 +325,7 @@ static int __devinit snd_azt2320_pnp_detect(struct pnp_card_link *card, | |||
| 323 | if (res < 0) | 325 | if (res < 0) |
| 324 | return res; | 326 | return res; |
| 325 | dev++; | 327 | dev++; |
| 328 | azt2320_devices++; | ||
| 326 | return 0; | 329 | return 0; |
| 327 | } | 330 | } |
| 328 | return -ENODEV; | 331 | return -ENODEV; |
| @@ -372,10 +375,13 @@ static struct pnp_card_driver azt2320_pnpc_driver = { | |||
| 372 | 375 | ||
| 373 | static int __init alsa_card_azt2320_init(void) | 376 | static int __init alsa_card_azt2320_init(void) |
| 374 | { | 377 | { |
| 375 | int cards; | 378 | int err; |
| 379 | |||
| 380 | err = pnp_register_card_driver(&azt2320_pnpc_driver); | ||
| 381 | if (err) | ||
| 382 | return err; | ||
| 376 | 383 | ||
| 377 | cards = pnp_register_card_driver(&azt2320_pnpc_driver); | 384 | if (!azt2320_devices) { |
| 378 | if (cards <= 0) { | ||
| 379 | pnp_unregister_card_driver(&azt2320_pnpc_driver); | 385 | pnp_unregister_card_driver(&azt2320_pnpc_driver); |
| 380 | #ifdef MODULE | 386 | #ifdef MODULE |
| 381 | snd_printk(KERN_ERR "no AZT2320 based soundcards found\n"); | 387 | snd_printk(KERN_ERR "no AZT2320 based soundcards found\n"); |
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index fd9bb2575de8..fa63048a8b9d 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c | |||
| @@ -175,7 +175,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids); | |||
| 175 | #endif | 175 | #endif |
| 176 | 176 | ||
| 177 | 177 | ||
| 178 | static struct ad1848_mix_elem snd_cmi8330_controls[] __initdata = { | 178 | static struct ad1848_mix_elem snd_cmi8330_controls[] __devinitdata = { |
| 179 | AD1848_DOUBLE("Master Playback Volume", 0, CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0), | 179 | AD1848_DOUBLE("Master Playback Volume", 0, CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0), |
| 180 | AD1848_SINGLE("Loud Playback Switch", 0, CMI8330_MUTEMUX, 6, 1, 1), | 180 | AD1848_SINGLE("Loud Playback Switch", 0, CMI8330_MUTEMUX, 6, 1, 1), |
| 181 | AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), | 181 | AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), |
| @@ -204,7 +204,7 @@ AD1848_SINGLE(SNDRV_CTL_NAME_IEC958("Input ",PLAYBACK,SWITCH), 0, CMI8330_MUTEMU | |||
| 204 | }; | 204 | }; |
| 205 | 205 | ||
| 206 | #ifdef ENABLE_SB_MIXER | 206 | #ifdef ENABLE_SB_MIXER |
| 207 | static struct sbmix_elem cmi8330_sb_mixers[] __initdata = { | 207 | static struct sbmix_elem cmi8330_sb_mixers[] __devinitdata = { |
| 208 | SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31), | 208 | SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31), |
| 209 | SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15), | 209 | SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15), |
| 210 | SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15), | 210 | SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15), |
| @@ -222,7 +222,7 @@ SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6 | |||
| 222 | SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1), | 222 | SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1), |
| 223 | }; | 223 | }; |
| 224 | 224 | ||
| 225 | static unsigned char cmi8330_sb_init_values[][2] __initdata = { | 225 | static unsigned char cmi8330_sb_init_values[][2] __devinitdata = { |
| 226 | { SB_DSP4_MASTER_DEV + 0, 0 }, | 226 | { SB_DSP4_MASTER_DEV + 0, 0 }, |
| 227 | { SB_DSP4_MASTER_DEV + 1, 0 }, | 227 | { SB_DSP4_MASTER_DEV + 1, 0 }, |
| 228 | { SB_DSP4_PCM_DEV + 0, 0 }, | 228 | { SB_DSP4_PCM_DEV + 0, 0 }, |
| @@ -545,7 +545,7 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) | |||
| 545 | return snd_card_register(card); | 545 | return snd_card_register(card); |
| 546 | } | 546 | } |
| 547 | 547 | ||
| 548 | static int __init snd_cmi8330_nonpnp_probe(struct platform_device *pdev) | 548 | static int __devinit snd_cmi8330_nonpnp_probe(struct platform_device *pdev) |
| 549 | { | 549 | { |
| 550 | struct snd_card *card; | 550 | struct snd_card *card; |
| 551 | int err; | 551 | int err; |
| @@ -607,6 +607,8 @@ static struct platform_driver snd_cmi8330_driver = { | |||
| 607 | 607 | ||
| 608 | 608 | ||
| 609 | #ifdef CONFIG_PNP | 609 | #ifdef CONFIG_PNP |
| 610 | static unsigned int __devinitdata cmi8330_pnp_devices; | ||
| 611 | |||
| 610 | static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, | 612 | static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, |
| 611 | const struct pnp_card_device_id *pid) | 613 | const struct pnp_card_device_id *pid) |
| 612 | { | 614 | { |
| @@ -636,6 +638,7 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard, | |||
| 636 | } | 638 | } |
| 637 | pnp_set_card_drvdata(pcard, card); | 639 | pnp_set_card_drvdata(pcard, card); |
| 638 | dev++; | 640 | dev++; |
| 641 | cmi8330_pnp_devices++; | ||
| 639 | return 0; | 642 | return 0; |
| 640 | } | 643 | } |
| 641 | 644 | ||
| @@ -706,9 +709,9 @@ static int __init alsa_card_cmi8330_init(void) | |||
| 706 | 709 | ||
| 707 | #ifdef CONFIG_PNP | 710 | #ifdef CONFIG_PNP |
| 708 | err = pnp_register_card_driver(&cmi8330_pnpc_driver); | 711 | err = pnp_register_card_driver(&cmi8330_pnpc_driver); |
| 709 | if (err >= 0) { | 712 | if (!err) { |
| 710 | pnp_registered = 1; | 713 | pnp_registered = 1; |
| 711 | cards += err; | 714 | cards += cmi8330_pnp_devices; |
| 712 | } | 715 | } |
| 713 | #endif | 716 | #endif |
| 714 | 717 | ||
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c index 4060918e0327..382bb17ef49f 100644 --- a/sound/isa/cs423x/cs4236.c +++ b/sound/isa/cs423x/cs4236.c | |||
| @@ -133,6 +133,7 @@ static int pnpc_registered; | |||
| 133 | static int pnp_registered; | 133 | static int pnp_registered; |
| 134 | #endif | 134 | #endif |
| 135 | #endif /* CONFIG_PNP */ | 135 | #endif /* CONFIG_PNP */ |
| 136 | static unsigned int snd_cs423x_devices; | ||
| 136 | 137 | ||
| 137 | struct snd_card_cs4236 { | 138 | struct snd_card_cs4236 { |
| 138 | struct snd_cs4231 *chip; | 139 | struct snd_cs4231 *chip; |
| @@ -564,7 +565,7 @@ static int __init snd_cs423x_nonpnp_probe(struct platform_device *pdev) | |||
| 564 | snd_card_free(card); | 565 | snd_card_free(card); |
| 565 | return err; | 566 | return err; |
| 566 | } | 567 | } |
| 567 | 568 | ||
| 568 | platform_set_drvdata(pdev, card); | 569 | platform_set_drvdata(pdev, card); |
| 569 | return 0; | 570 | return 0; |
| 570 | } | 571 | } |
| @@ -650,6 +651,7 @@ static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev, | |||
| 650 | } | 651 | } |
| 651 | pnp_set_drvdata(pdev, card); | 652 | pnp_set_drvdata(pdev, card); |
| 652 | dev++; | 653 | dev++; |
| 654 | snd_cs423x_devices++; | ||
| 653 | return 0; | 655 | return 0; |
| 654 | } | 656 | } |
| 655 | 657 | ||
| @@ -713,6 +715,7 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard, | |||
| 713 | } | 715 | } |
| 714 | pnp_set_card_drvdata(pcard, card); | 716 | pnp_set_card_drvdata(pcard, card); |
| 715 | dev++; | 717 | dev++; |
| 718 | snd_cs423x_devices++; | ||
| 716 | return 0; | 719 | return 0; |
| 717 | } | 720 | } |
| 718 | 721 | ||
| @@ -721,7 +724,7 @@ static void __devexit snd_cs423x_pnpc_remove(struct pnp_card_link * pcard) | |||
| 721 | snd_card_free(pnp_get_card_drvdata(pcard)); | 724 | snd_card_free(pnp_get_card_drvdata(pcard)); |
| 722 | pnp_set_card_drvdata(pcard, NULL); | 725 | pnp_set_card_drvdata(pcard, NULL); |
| 723 | } | 726 | } |
| 724 | 727 | ||
| 725 | #ifdef CONFIG_PM | 728 | #ifdef CONFIG_PM |
| 726 | static int snd_cs423x_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state) | 729 | static int snd_cs423x_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state) |
| 727 | { | 730 | { |
| @@ -766,7 +769,7 @@ static void __init_or_module snd_cs423x_unregister_all(void) | |||
| 766 | 769 | ||
| 767 | static int __init alsa_card_cs423x_init(void) | 770 | static int __init alsa_card_cs423x_init(void) |
| 768 | { | 771 | { |
| 769 | int i, err, cards = 0; | 772 | int i, err; |
| 770 | 773 | ||
| 771 | if ((err = platform_driver_register(&cs423x_nonpnp_driver)) < 0) | 774 | if ((err = platform_driver_register(&cs423x_nonpnp_driver)) < 0) |
| 772 | return err; | 775 | return err; |
| @@ -782,24 +785,20 @@ static int __init alsa_card_cs423x_init(void) | |||
| 782 | goto errout; | 785 | goto errout; |
| 783 | } | 786 | } |
| 784 | platform_devices[i] = device; | 787 | platform_devices[i] = device; |
| 785 | cards++; | 788 | snd_cs423x_devices++; |
| 786 | } | 789 | } |
| 787 | #ifdef CONFIG_PNP | 790 | #ifdef CONFIG_PNP |
| 788 | #ifdef CS4232 | 791 | #ifdef CS4232 |
| 789 | i = pnp_register_driver(&cs4232_pnp_driver); | 792 | err = pnp_register_driver(&cs4232_pnp_driver); |
| 790 | if (i >= 0) { | 793 | if (!err) |
| 791 | pnp_registered = 1; | 794 | pnp_registered = 1; |
| 792 | cards += i; | ||
| 793 | } | ||
| 794 | #endif | 795 | #endif |
| 795 | i = pnp_register_card_driver(&cs423x_pnpc_driver); | 796 | err = pnp_register_card_driver(&cs423x_pnpc_driver); |
| 796 | if (i >= 0) { | 797 | if (!err) |
| 797 | pnpc_registered = 1; | 798 | pnpc_registered = 1; |
| 798 | cards += i; | ||
| 799 | } | ||
| 800 | #endif /* CONFIG_PNP */ | 799 | #endif /* CONFIG_PNP */ |
| 801 | 800 | ||
| 802 | if (!cards) { | 801 | if (!snd_cs423x_devices) { |
| 803 | #ifdef MODULE | 802 | #ifdef MODULE |
| 804 | printk(KERN_ERR IDENT " soundcard not found or device busy\n"); | 803 | printk(KERN_ERR IDENT " soundcard not found or device busy\n"); |
| 805 | #endif | 804 | #endif |
diff --git a/sound/isa/dt019x.c b/sound/isa/dt019x.c index 50e7bc5ef561..0acb4e5da47f 100644 --- a/sound/isa/dt019x.c +++ b/sound/isa/dt019x.c | |||
| @@ -272,6 +272,8 @@ static int __devinit snd_card_dt019x_probe(int dev, struct pnp_card_link *pcard, | |||
| 272 | return 0; | 272 | return 0; |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | static unsigned int __devinitdata dt019x_devices; | ||
| 276 | |||
| 275 | static int __devinit snd_dt019x_pnp_probe(struct pnp_card_link *card, | 277 | static int __devinit snd_dt019x_pnp_probe(struct pnp_card_link *card, |
| 276 | const struct pnp_card_device_id *pid) | 278 | const struct pnp_card_device_id *pid) |
| 277 | { | 279 | { |
| @@ -285,6 +287,7 @@ static int __devinit snd_dt019x_pnp_probe(struct pnp_card_link *card, | |||
| 285 | if (res < 0) | 287 | if (res < 0) |
| 286 | return res; | 288 | return res; |
| 287 | dev++; | 289 | dev++; |
| 290 | dt019x_devices++; | ||
| 288 | return 0; | 291 | return 0; |
| 289 | } | 292 | } |
| 290 | return -ENODEV; | 293 | return -ENODEV; |
| @@ -336,10 +339,13 @@ static struct pnp_card_driver dt019x_pnpc_driver = { | |||
| 336 | 339 | ||
| 337 | static int __init alsa_card_dt019x_init(void) | 340 | static int __init alsa_card_dt019x_init(void) |
| 338 | { | 341 | { |
| 339 | int cards = 0; | 342 | int err; |
| 343 | |||
| 344 | err = pnp_register_card_driver(&dt019x_pnpc_driver); | ||
| 345 | if (err) | ||
| 346 | return err; | ||
| 340 | 347 | ||
| 341 | cards = pnp_register_card_driver(&dt019x_pnpc_driver); | 348 | if (!dt019x_devices) { |
| 342 | if (cards <= 0) { | ||
| 343 | pnp_unregister_card_driver(&dt019x_pnpc_driver); | 349 | pnp_unregister_card_driver(&dt019x_pnpc_driver); |
| 344 | #ifdef MODULE | 350 | #ifdef MODULE |
| 345 | snd_printk(KERN_ERR "no DT-019X / ALS-007 based soundcards found\n"); | 351 | snd_printk(KERN_ERR "no DT-019X / ALS-007 based soundcards found\n"); |
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 721955d26194..9fbc185b4cc2 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c | |||
| @@ -2204,7 +2204,7 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev) | |||
| 2204 | return snd_card_register(card); | 2204 | return snd_card_register(card); |
| 2205 | } | 2205 | } |
| 2206 | 2206 | ||
| 2207 | static int __init snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devptr) | 2207 | static int __devinit snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devptr) |
| 2208 | { | 2208 | { |
| 2209 | struct snd_card *card; | 2209 | struct snd_card *card; |
| 2210 | int err; | 2210 | int err; |
| @@ -2221,7 +2221,7 @@ static int __init snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devp | |||
| 2221 | return 0; | 2221 | return 0; |
| 2222 | } | 2222 | } |
| 2223 | 2223 | ||
| 2224 | static int __init snd_es18xx_nonpnp_probe(struct platform_device *pdev) | 2224 | static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev) |
| 2225 | { | 2225 | { |
| 2226 | int dev = pdev->id; | 2226 | int dev = pdev->id; |
| 2227 | int err; | 2227 | int err; |
| @@ -2297,6 +2297,8 @@ static struct platform_driver snd_es18xx_nonpnp_driver = { | |||
| 2297 | 2297 | ||
| 2298 | 2298 | ||
| 2299 | #ifdef CONFIG_PNP | 2299 | #ifdef CONFIG_PNP |
| 2300 | static unsigned int __devinitdata es18xx_pnp_devices; | ||
| 2301 | |||
| 2300 | static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard, | 2302 | static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard, |
| 2301 | const struct pnp_card_device_id *pid) | 2303 | const struct pnp_card_device_id *pid) |
| 2302 | { | 2304 | { |
| @@ -2327,6 +2329,7 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard, | |||
| 2327 | 2329 | ||
| 2328 | pnp_set_card_drvdata(pcard, card); | 2330 | pnp_set_card_drvdata(pcard, card); |
| 2329 | dev++; | 2331 | dev++; |
| 2332 | es18xx_pnp_devices++; | ||
| 2330 | return 0; | 2333 | return 0; |
| 2331 | } | 2334 | } |
| 2332 | 2335 | ||
| @@ -2397,10 +2400,10 @@ static int __init alsa_card_es18xx_init(void) | |||
| 2397 | } | 2400 | } |
| 2398 | 2401 | ||
| 2399 | #ifdef CONFIG_PNP | 2402 | #ifdef CONFIG_PNP |
| 2400 | i = pnp_register_card_driver(&es18xx_pnpc_driver); | 2403 | err = pnp_register_card_driver(&es18xx_pnpc_driver); |
| 2401 | if (i >= 0) { | 2404 | if (!err) { |
| 2402 | pnp_registered = 1; | 2405 | pnp_registered = 1; |
| 2403 | cards += i; | 2406 | cards += es18xx_pnp_devices; |
| 2404 | } | 2407 | } |
| 2405 | #endif | 2408 | #endif |
| 2406 | 2409 | ||
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 2cacd0fa6871..de71b7a99c83 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c | |||
| @@ -791,7 +791,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev) | |||
| 791 | return 0; | 791 | return 0; |
| 792 | } | 792 | } |
| 793 | 793 | ||
| 794 | static int __init snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr) | 794 | static int __devinit snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr) |
| 795 | { | 795 | { |
| 796 | struct snd_card *card; | 796 | struct snd_card *card; |
| 797 | int err; | 797 | int err; |
| @@ -809,7 +809,7 @@ static int __init snd_interwave_nonpnp_probe1(int dev, struct platform_device *d | |||
| 809 | return 0; | 809 | return 0; |
| 810 | } | 810 | } |
| 811 | 811 | ||
| 812 | static int __init snd_interwave_nonpnp_probe(struct platform_device *pdev) | 812 | static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev) |
| 813 | { | 813 | { |
| 814 | int dev = pdev->id; | 814 | int dev = pdev->id; |
| 815 | int err; | 815 | int err; |
| @@ -867,6 +867,7 @@ static struct platform_driver snd_interwave_driver = { | |||
| 867 | }; | 867 | }; |
| 868 | 868 | ||
| 869 | #ifdef CONFIG_PNP | 869 | #ifdef CONFIG_PNP |
| 870 | static unsigned int __devinitdata interwave_pnp_devices; | ||
| 870 | 871 | ||
| 871 | static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, | 872 | static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, |
| 872 | const struct pnp_card_device_id *pid) | 873 | const struct pnp_card_device_id *pid) |
| @@ -897,6 +898,7 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard, | |||
| 897 | } | 898 | } |
| 898 | pnp_set_card_drvdata(pcard, card); | 899 | pnp_set_card_drvdata(pcard, card); |
| 899 | dev++; | 900 | dev++; |
| 901 | interwave_pnp_devices++; | ||
| 900 | return 0; | 902 | return 0; |
| 901 | } | 903 | } |
| 902 | 904 | ||
| @@ -954,10 +956,10 @@ static int __init alsa_card_interwave_init(void) | |||
| 954 | } | 956 | } |
| 955 | 957 | ||
| 956 | /* ISA PnP cards */ | 958 | /* ISA PnP cards */ |
| 957 | i = pnp_register_card_driver(&interwave_pnpc_driver); | 959 | err = pnp_register_card_driver(&interwave_pnpc_driver); |
| 958 | if (i >= 0) { | 960 | if (!err) { |
| 959 | pnp_registered = 1; | 961 | pnp_registered = 1; |
| 960 | cards += i; | 962 | cards += interwave_pnp_devices;; |
| 961 | } | 963 | } |
| 962 | 964 | ||
| 963 | if (!cards) { | 965 | if (!cards) { |
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 56fcd8a946a4..c906e205d7d5 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c | |||
| @@ -95,6 +95,7 @@ static struct platform_device *platform_devices[SNDRV_CARDS]; | |||
| 95 | static int pnp_registered; | 95 | static int pnp_registered; |
| 96 | static int pnpc_registered; | 96 | static int pnpc_registered; |
| 97 | #endif | 97 | #endif |
| 98 | static unsigned int snd_opl3sa2_devices; | ||
| 98 | 99 | ||
| 99 | /* control ports */ | 100 | /* control ports */ |
| 100 | #define OPL3SA2_PM_CTRL 0x01 | 101 | #define OPL3SA2_PM_CTRL 0x01 |
| @@ -760,6 +761,7 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev, | |||
| 760 | } | 761 | } |
| 761 | pnp_set_drvdata(pdev, card); | 762 | pnp_set_drvdata(pdev, card); |
| 762 | dev++; | 763 | dev++; |
| 764 | snd_opl3sa2_devices++; | ||
| 763 | return 0; | 765 | return 0; |
| 764 | } | 766 | } |
| 765 | 767 | ||
| @@ -826,6 +828,7 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard, | |||
| 826 | } | 828 | } |
| 827 | pnp_set_card_drvdata(pcard, card); | 829 | pnp_set_card_drvdata(pcard, card); |
| 828 | dev++; | 830 | dev++; |
| 831 | snd_opl3sa2_devices++; | ||
| 829 | return 0; | 832 | return 0; |
| 830 | } | 833 | } |
| 831 | 834 | ||
| @@ -944,7 +947,7 @@ static void __init_or_module snd_opl3sa2_unregister_all(void) | |||
| 944 | 947 | ||
| 945 | static int __init alsa_card_opl3sa2_init(void) | 948 | static int __init alsa_card_opl3sa2_init(void) |
| 946 | { | 949 | { |
| 947 | int i, err, cards = 0; | 950 | int i, err; |
| 948 | 951 | ||
| 949 | if ((err = platform_driver_register(&snd_opl3sa2_nonpnp_driver)) < 0) | 952 | if ((err = platform_driver_register(&snd_opl3sa2_nonpnp_driver)) < 0) |
| 950 | return err; | 953 | return err; |
| @@ -964,23 +967,19 @@ static int __init alsa_card_opl3sa2_init(void) | |||
| 964 | goto errout; | 967 | goto errout; |
| 965 | } | 968 | } |
| 966 | platform_devices[i] = device; | 969 | platform_devices[i] = device; |
| 967 | cards++; | 970 | snd_opl3sa2_devices++; |
| 968 | } | 971 | } |
| 969 | 972 | ||
| 970 | #ifdef CONFIG_PNP | 973 | #ifdef CONFIG_PNP |
| 971 | err = pnp_register_driver(&opl3sa2_pnp_driver); | 974 | err = pnp_register_driver(&opl3sa2_pnp_driver); |
| 972 | if (err >= 0) { | 975 | if (!err) |
| 973 | pnp_registered = 1; | 976 | pnp_registered = 1; |
| 974 | cards += err; | ||
| 975 | } | ||
| 976 | err = pnp_register_card_driver(&opl3sa2_pnpc_driver); | 977 | err = pnp_register_card_driver(&opl3sa2_pnpc_driver); |
| 977 | if (err >= 0) { | 978 | if (!err) |
| 978 | pnpc_registered = 1; | 979 | pnpc_registered = 1; |
| 979 | cards += err; | ||
| 980 | } | ||
| 981 | #endif | 980 | #endif |
| 982 | 981 | ||
| 983 | if (!cards) { | 982 | if (!snd_opl3sa2_devices) { |
| 984 | #ifdef MODULE | 983 | #ifdef MODULE |
| 985 | snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n"); | 984 | snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n"); |
| 986 | #endif | 985 | #endif |
diff --git a/sound/isa/sb/es968.c b/sound/isa/sb/es968.c index 9da80bfa3027..d4d65b84265a 100644 --- a/sound/isa/sb/es968.c +++ b/sound/isa/sb/es968.c | |||
| @@ -124,7 +124,7 @@ static int __devinit snd_card_es968_pnp(int dev, struct snd_card_es968 *acard, | |||
| 124 | return 0; | 124 | return 0; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static int __init snd_card_es968_probe(int dev, | 127 | static int __devinit snd_card_es968_probe(int dev, |
| 128 | struct pnp_card_link *pcard, | 128 | struct pnp_card_link *pcard, |
| 129 | const struct pnp_card_device_id *pid) | 129 | const struct pnp_card_device_id *pid) |
| 130 | { | 130 | { |
| @@ -182,6 +182,8 @@ static int __init snd_card_es968_probe(int dev, | |||
| 182 | return 0; | 182 | return 0; |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | static unsigned int __devinitdata es968_devices; | ||
| 186 | |||
| 185 | static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card, | 187 | static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card, |
| 186 | const struct pnp_card_device_id *id) | 188 | const struct pnp_card_device_id *id) |
| 187 | { | 189 | { |
| @@ -195,6 +197,7 @@ static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card, | |||
| 195 | if (res < 0) | 197 | if (res < 0) |
| 196 | return res; | 198 | return res; |
| 197 | dev++; | 199 | dev++; |
| 200 | es968_devices++; | ||
| 198 | return 0; | 201 | return 0; |
| 199 | } | 202 | } |
| 200 | return -ENODEV; | 203 | return -ENODEV; |
| @@ -246,8 +249,11 @@ static struct pnp_card_driver es968_pnpc_driver = { | |||
| 246 | 249 | ||
| 247 | static int __init alsa_card_es968_init(void) | 250 | static int __init alsa_card_es968_init(void) |
| 248 | { | 251 | { |
| 249 | int cards = pnp_register_card_driver(&es968_pnpc_driver); | 252 | int err = pnp_register_card_driver(&es968_pnpc_driver); |
| 250 | if (cards <= 0) { | 253 | if (err) |
| 254 | return err; | ||
| 255 | |||
| 256 | if (!es968_devices) { | ||
| 251 | pnp_unregister_card_driver(&es968_pnpc_driver); | 257 | pnp_unregister_card_driver(&es968_pnpc_driver); |
| 252 | #ifdef MODULE | 258 | #ifdef MODULE |
| 253 | snd_printk(KERN_ERR "no ES968 based soundcards found\n"); | 259 | snd_printk(KERN_ERR "no ES968 based soundcards found\n"); |
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 5737ab76160c..21ea65925a9e 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c | |||
| @@ -369,7 +369,7 @@ static struct snd_card *snd_sb16_card_new(int dev) | |||
| 369 | return card; | 369 | return card; |
| 370 | } | 370 | } |
| 371 | 371 | ||
| 372 | static int __init snd_sb16_probe(struct snd_card *card, int dev) | 372 | static int __devinit snd_sb16_probe(struct snd_card *card, int dev) |
| 373 | { | 373 | { |
| 374 | int xirq, xdma8, xdma16; | 374 | int xirq, xdma8, xdma16; |
| 375 | struct snd_sb *chip; | 375 | struct snd_sb *chip; |
| @@ -518,7 +518,7 @@ static int snd_sb16_resume(struct snd_card *card) | |||
| 518 | } | 518 | } |
| 519 | #endif | 519 | #endif |
| 520 | 520 | ||
| 521 | static int __init snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr) | 521 | static int __devinit snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr) |
| 522 | { | 522 | { |
| 523 | struct snd_card_sb16 *acard; | 523 | struct snd_card_sb16 *acard; |
| 524 | struct snd_card *card; | 524 | struct snd_card *card; |
| @@ -548,7 +548,7 @@ static int __init snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr | |||
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | 550 | ||
| 551 | static int __init snd_sb16_nonpnp_probe(struct platform_device *pdev) | 551 | static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev) |
| 552 | { | 552 | { |
| 553 | int dev = pdev->id; | 553 | int dev = pdev->id; |
| 554 | int err; | 554 | int err; |
| @@ -629,6 +629,7 @@ static struct platform_driver snd_sb16_nonpnp_driver = { | |||
| 629 | 629 | ||
| 630 | 630 | ||
| 631 | #ifdef CONFIG_PNP | 631 | #ifdef CONFIG_PNP |
| 632 | static unsigned int __devinitdata sb16_pnp_devices; | ||
| 632 | 633 | ||
| 633 | static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, | 634 | static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, |
| 634 | const struct pnp_card_device_id *pid) | 635 | const struct pnp_card_device_id *pid) |
| @@ -651,6 +652,7 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard, | |||
| 651 | } | 652 | } |
| 652 | pnp_set_card_drvdata(pcard, card); | 653 | pnp_set_card_drvdata(pcard, card); |
| 653 | dev++; | 654 | dev++; |
| 655 | sb16_pnp_devices++; | ||
| 654 | return 0; | 656 | return 0; |
| 655 | } | 657 | } |
| 656 | 658 | ||
| @@ -727,10 +729,10 @@ static int __init alsa_card_sb16_init(void) | |||
| 727 | } | 729 | } |
| 728 | #ifdef CONFIG_PNP | 730 | #ifdef CONFIG_PNP |
| 729 | /* PnP cards at last */ | 731 | /* PnP cards at last */ |
| 730 | i = pnp_register_card_driver(&sb16_pnpc_driver); | 732 | err = pnp_register_card_driver(&sb16_pnpc_driver); |
| 731 | if (i >= 0) { | 733 | if (!err) { |
| 732 | pnp_registered = 1; | 734 | pnp_registered = 1; |
| 733 | cards += i; | 735 | cards += sb16_pnp_devices; |
| 734 | } | 736 | } |
| 735 | #endif | 737 | #endif |
| 736 | 738 | ||
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 29bba8cc3ef3..48e5552d3444 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c | |||
| @@ -1255,7 +1255,7 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp) | |||
| 1255 | } | 1255 | } |
| 1256 | 1256 | ||
| 1257 | 1257 | ||
| 1258 | static int __init snd_sscape_probe(struct platform_device *pdev) | 1258 | static int __devinit snd_sscape_probe(struct platform_device *pdev) |
| 1259 | { | 1259 | { |
| 1260 | int dev = pdev->id; | 1260 | int dev = pdev->id; |
| 1261 | struct snd_card *card; | 1261 | struct snd_card *card; |
| @@ -1469,7 +1469,7 @@ static int __init sscape_init(void) | |||
| 1469 | if (ret < 0) | 1469 | if (ret < 0) |
| 1470 | return ret; | 1470 | return ret; |
| 1471 | #ifdef CONFIG_PNP | 1471 | #ifdef CONFIG_PNP |
| 1472 | if (pnp_register_card_driver(&sscape_pnpc_driver) >= 0) | 1472 | if (pnp_register_card_driver(&sscape_pnpc_driver) == 0) |
| 1473 | pnp_registered = 1; | 1473 | pnp_registered = 1; |
| 1474 | #endif | 1474 | #endif |
| 1475 | return 0; | 1475 | return 0; |
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index c0115bf9065e..2f13cd5d4dcb 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c | |||
| @@ -589,7 +589,7 @@ snd_wavefront_probe (struct snd_card *card, int dev) | |||
| 589 | return snd_card_register(card); | 589 | return snd_card_register(card); |
| 590 | } | 590 | } |
| 591 | 591 | ||
| 592 | static int __init snd_wavefront_nonpnp_probe(struct platform_device *pdev) | 592 | static int __devinit snd_wavefront_nonpnp_probe(struct platform_device *pdev) |
| 593 | { | 593 | { |
| 594 | int dev = pdev->id; | 594 | int dev = pdev->id; |
| 595 | struct snd_card *card; | 595 | struct snd_card *card; |
| @@ -637,6 +637,7 @@ static struct platform_driver snd_wavefront_driver = { | |||
| 637 | 637 | ||
| 638 | 638 | ||
| 639 | #ifdef CONFIG_PNP | 639 | #ifdef CONFIG_PNP |
| 640 | static unsigned int __devinitdata wavefront_pnp_devices; | ||
| 640 | 641 | ||
| 641 | static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, | 642 | static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, |
| 642 | const struct pnp_card_device_id *pid) | 643 | const struct pnp_card_device_id *pid) |
| @@ -670,6 +671,7 @@ static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard, | |||
| 670 | 671 | ||
| 671 | pnp_set_card_drvdata(pcard, card); | 672 | pnp_set_card_drvdata(pcard, card); |
| 672 | dev++; | 673 | dev++; |
| 674 | wavefront_pnp_devices++; | ||
| 673 | return 0; | 675 | return 0; |
| 674 | } | 676 | } |
| 675 | 677 | ||
| @@ -729,10 +731,10 @@ static int __init alsa_card_wavefront_init(void) | |||
| 729 | } | 731 | } |
| 730 | 732 | ||
| 731 | #ifdef CONFIG_PNP | 733 | #ifdef CONFIG_PNP |
| 732 | i = pnp_register_card_driver(&wavefront_pnpc_driver); | 734 | err = pnp_register_card_driver(&wavefront_pnpc_driver); |
| 733 | if (i >= 0) { | 735 | if (!err) { |
| 734 | pnp_registered = 1; | 736 | pnp_registered = 1; |
| 735 | cards += i; | 737 | cards += wavefront_pnp_devices; |
| 736 | } | 738 | } |
| 737 | #endif | 739 | #endif |
| 738 | 740 | ||
diff --git a/sound/oss/cs4232.c b/sound/oss/cs4232.c index 7c59e2d4003a..c7f86f09c28d 100644 --- a/sound/oss/cs4232.c +++ b/sound/oss/cs4232.c | |||
| @@ -360,6 +360,8 @@ static int __initdata synthio = -1; | |||
| 360 | static int __initdata synthirq = -1; | 360 | static int __initdata synthirq = -1; |
| 361 | static int __initdata isapnp = 1; | 361 | static int __initdata isapnp = 1; |
| 362 | 362 | ||
| 363 | static unsigned int cs4232_devices; | ||
| 364 | |||
| 363 | MODULE_DESCRIPTION("CS4232 based soundcard driver"); | 365 | MODULE_DESCRIPTION("CS4232 based soundcard driver"); |
| 364 | MODULE_AUTHOR("Hannu Savolainen, Paul Barton-Davis"); | 366 | MODULE_AUTHOR("Hannu Savolainen, Paul Barton-Davis"); |
| 365 | MODULE_LICENSE("GPL"); | 367 | MODULE_LICENSE("GPL"); |
| @@ -421,6 +423,7 @@ static int cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev | |||
| 421 | return -ENODEV; | 423 | return -ENODEV; |
| 422 | } | 424 | } |
| 423 | pnp_set_drvdata(dev,isapnpcfg); | 425 | pnp_set_drvdata(dev,isapnpcfg); |
| 426 | cs4232_devices++; | ||
| 424 | return 0; | 427 | return 0; |
| 425 | } | 428 | } |
| 426 | 429 | ||
| @@ -455,10 +458,11 @@ static int __init init_cs4232(void) | |||
| 455 | #endif | 458 | #endif |
| 456 | cfg.irq = -1; | 459 | cfg.irq = -1; |
| 457 | 460 | ||
| 458 | if (isapnp && | 461 | if (isapnp) { |
| 459 | (pnp_register_driver(&cs4232_driver) > 0) | 462 | pnp_register_driver(&cs4232_driver); |
| 460 | ) | 463 | if (cs4232_devices) |
| 461 | return 0; | 464 | return 0; |
| 465 | } | ||
| 462 | 466 | ||
| 463 | if(io==-1||irq==-1||dma==-1) | 467 | if(io==-1||irq==-1||dma==-1) |
| 464 | { | 468 | { |
| @@ -503,7 +507,8 @@ static int __init setup_cs4232(char *str) | |||
| 503 | int ints[7]; | 507 | int ints[7]; |
| 504 | 508 | ||
| 505 | /* If we have isapnp cards, no need for options */ | 509 | /* If we have isapnp cards, no need for options */ |
| 506 | if (pnp_register_driver(&cs4232_driver) > 0) | 510 | pnp_register_driver(&cs4232_driver); |
| 511 | if (cs4232_devices) | ||
| 507 | return 1; | 512 | return 1; |
| 508 | 513 | ||
| 509 | str = get_options(str, ARRAY_SIZE(ints), ints); | 514 | str = get_options(str, ARRAY_SIZE(ints), ints); |
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c index 6ba8d6f45fe8..3bbc8105e9f1 100644 --- a/sound/oss/dmasound/dmasound_awacs.c +++ b/sound/oss/dmasound/dmasound_awacs.c | |||
| @@ -2798,7 +2798,7 @@ __init setup_beep(void) | |||
| 2798 | DBDMA_ALIGN(beep_dbdma_cmd_space); | 2798 | DBDMA_ALIGN(beep_dbdma_cmd_space); |
| 2799 | /* set up emergency dbdma cmd */ | 2799 | /* set up emergency dbdma cmd */ |
| 2800 | emergency_dbdma_cmd = beep_dbdma_cmd+1 ; | 2800 | emergency_dbdma_cmd = beep_dbdma_cmd+1 ; |
| 2801 | beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); | 2801 | beep_buf = kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); |
| 2802 | if (beep_buf == NULL) { | 2802 | if (beep_buf == NULL) { |
| 2803 | printk(KERN_ERR "dmasound_pmac: no memory for beep buffer\n"); | 2803 | printk(KERN_ERR "dmasound_pmac: no memory for beep buffer\n"); |
| 2804 | kfree(beep_dbdma_cmd_space) ; | 2804 | kfree(beep_dbdma_cmd_space) ; |
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c index 959a96794dba..25ae8e4a488d 100644 --- a/sound/oss/emu10k1/midi.c +++ b/sound/oss/emu10k1/midi.c | |||
| @@ -65,7 +65,8 @@ static int midiin_add_buffer(struct emu10k1_mididevice *midi_dev, struct midi_hd | |||
| 65 | 65 | ||
| 66 | init_midi_hdr(midihdr); | 66 | init_midi_hdr(midihdr); |
| 67 | 67 | ||
| 68 | if ((midihdr->data = (u8 *) kmalloc(MIDIIN_BUFLEN, GFP_KERNEL)) == NULL) { | 68 | midihdr->data = kmalloc(MIDIIN_BUFLEN, GFP_KERNEL); |
| 69 | if (!midihdr->data) { | ||
| 69 | ERROR(); | 70 | ERROR(); |
| 70 | kfree(midihdr); | 71 | kfree(midihdr); |
| 71 | return -1; | 72 | return -1; |
| @@ -334,7 +335,8 @@ static ssize_t emu10k1_midi_write(struct file *file, const char __user *buffer, | |||
| 334 | midihdr->bytesrecorded = 0; | 335 | midihdr->bytesrecorded = 0; |
| 335 | midihdr->flags = 0; | 336 | midihdr->flags = 0; |
| 336 | 337 | ||
| 337 | if ((midihdr->data = (u8 *) kmalloc(count, GFP_KERNEL)) == NULL) { | 338 | midihdr->data = kmalloc(count, GFP_KERNEL); |
| 339 | if (!midihdr->data) { | ||
| 338 | ERROR(); | 340 | ERROR(); |
| 339 | kfree(midihdr); | 341 | kfree(midihdr); |
| 340 | return -EINVAL; | 342 | return -EINVAL; |
| @@ -545,7 +547,8 @@ int emu10k1_seq_midi_out(int dev, unsigned char midi_byte) | |||
| 545 | midihdr->bytesrecorded = 0; | 547 | midihdr->bytesrecorded = 0; |
| 546 | midihdr->flags = 0; | 548 | midihdr->flags = 0; |
| 547 | 549 | ||
| 548 | if ((midihdr->data = (u8 *) kmalloc(1, GFP_KERNEL)) == NULL) { | 550 | midihdr->data = kmalloc(1, GFP_KERNEL); |
| 551 | if (!midihdr->data) { | ||
| 549 | ERROR(); | 552 | ERROR(); |
| 550 | kfree(midihdr); | 553 | kfree(midihdr); |
| 551 | return -EINVAL; | 554 | return -EINVAL; |
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c index 78d3e29ce968..6861563d7525 100644 --- a/sound/oss/esssolo1.c +++ b/sound/oss/esssolo1.c | |||
| @@ -2348,7 +2348,7 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device | |||
| 2348 | /* Recording requires 24-bit DMA, so attempt to set dma mask | 2348 | /* Recording requires 24-bit DMA, so attempt to set dma mask |
| 2349 | * to 24 bits first, then 32 bits (playback only) if that fails. | 2349 | * to 24 bits first, then 32 bits (playback only) if that fails. |
| 2350 | */ | 2350 | */ |
| 2351 | if (pci_set_dma_mask(pcidev, 0x00ffffff) && | 2351 | if (pci_set_dma_mask(pcidev, DMA_24BIT_MASK) && |
| 2352 | pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) { | 2352 | pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) { |
| 2353 | printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n"); | 2353 | printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n"); |
| 2354 | return -ENODEV; | 2354 | return -ENODEV; |
diff --git a/sound/oss/maestro3.c b/sound/oss/maestro3.c index 66044aff2586..4a5e4237a110 100644 --- a/sound/oss/maestro3.c +++ b/sound/oss/maestro3.c | |||
| @@ -2582,15 +2582,9 @@ static int alloc_dsp_suspendmem(struct m3_card *card) | |||
| 2582 | 2582 | ||
| 2583 | return 0; | 2583 | return 0; |
| 2584 | } | 2584 | } |
| 2585 | static void free_dsp_suspendmem(struct m3_card *card) | ||
| 2586 | { | ||
| 2587 | if(card->suspend_mem) | ||
| 2588 | vfree(card->suspend_mem); | ||
| 2589 | } | ||
| 2590 | 2585 | ||
| 2591 | #else | 2586 | #else |
| 2592 | #define alloc_dsp_suspendmem(args...) 0 | 2587 | #define alloc_dsp_suspendmem(args...) 0 |
| 2593 | #define free_dsp_suspendmem(args...) | ||
| 2594 | #endif | 2588 | #endif |
| 2595 | 2589 | ||
| 2596 | /* | 2590 | /* |
| @@ -2717,7 +2711,7 @@ out: | |||
| 2717 | if(ret) { | 2711 | if(ret) { |
| 2718 | if(card->iobase) | 2712 | if(card->iobase) |
| 2719 | release_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); | 2713 | release_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); |
| 2720 | free_dsp_suspendmem(card); | 2714 | vfree(card->suspend_mem); |
| 2721 | if(card->ac97) { | 2715 | if(card->ac97) { |
| 2722 | unregister_sound_mixer(card->ac97->dev_mixer); | 2716 | unregister_sound_mixer(card->ac97->dev_mixer); |
| 2723 | kfree(card->ac97); | 2717 | kfree(card->ac97); |
| @@ -2760,7 +2754,7 @@ static void m3_remove(struct pci_dev *pci_dev) | |||
| 2760 | } | 2754 | } |
| 2761 | 2755 | ||
| 2762 | release_region(card->iobase, 256); | 2756 | release_region(card->iobase, 256); |
| 2763 | free_dsp_suspendmem(card); | 2757 | vfree(card->suspend_mem); |
| 2764 | kfree(card); | 2758 | kfree(card); |
| 2765 | } | 2759 | } |
| 2766 | devs = NULL; | 2760 | devs = NULL; |
diff --git a/sound/oss/msnd.c b/sound/oss/msnd.c index a7ad2b0a2ac0..5dbfc0f9c3c7 100644 --- a/sound/oss/msnd.c +++ b/sound/oss/msnd.c | |||
| @@ -95,10 +95,8 @@ void msnd_fifo_init(msnd_fifo *f) | |||
| 95 | 95 | ||
| 96 | void msnd_fifo_free(msnd_fifo *f) | 96 | void msnd_fifo_free(msnd_fifo *f) |
| 97 | { | 97 | { |
| 98 | if (f->data) { | 98 | vfree(f->data); |
| 99 | vfree(f->data); | 99 | f->data = NULL; |
| 100 | f->data = NULL; | ||
| 101 | } | ||
| 102 | } | 100 | } |
| 103 | 101 | ||
| 104 | int msnd_fifo_alloc(msnd_fifo *f, size_t n) | 102 | int msnd_fifo_alloc(msnd_fifo *f, size_t n) |
diff --git a/sound/oss/sb_card.c b/sound/oss/sb_card.c index 680b82e15298..4708cbdc3149 100644 --- a/sound/oss/sb_card.c +++ b/sound/oss/sb_card.c | |||
| @@ -52,6 +52,7 @@ static int __initdata sm_games = 0; /* Logitech soundman games? */ | |||
| 52 | static struct sb_card_config *legacy = NULL; | 52 | static struct sb_card_config *legacy = NULL; |
| 53 | 53 | ||
| 54 | #ifdef CONFIG_PNP | 54 | #ifdef CONFIG_PNP |
| 55 | static int pnp_registered; | ||
| 55 | static int __initdata pnp = 1; | 56 | static int __initdata pnp = 1; |
| 56 | /* | 57 | /* |
| 57 | static int __initdata uart401 = 0; | 58 | static int __initdata uart401 = 0; |
| @@ -133,7 +134,7 @@ static void sb_unload(struct sb_card_config *scc) | |||
| 133 | } | 134 | } |
| 134 | 135 | ||
| 135 | /* Register legacy card with OSS subsystem */ | 136 | /* Register legacy card with OSS subsystem */ |
| 136 | static int sb_init_legacy(void) | 137 | static int __init sb_init_legacy(void) |
| 137 | { | 138 | { |
| 138 | struct sb_module_options sbmo = {0}; | 139 | struct sb_module_options sbmo = {0}; |
| 139 | 140 | ||
| @@ -234,6 +235,8 @@ static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc) | |||
| 234 | } | 235 | } |
| 235 | } | 236 | } |
| 236 | 237 | ||
| 238 | static unsigned int sb_pnp_devices; | ||
| 239 | |||
| 237 | /* Probe callback function for the PnP API */ | 240 | /* Probe callback function for the PnP API */ |
| 238 | static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_device_id *card_id) | 241 | static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_device_id *card_id) |
| 239 | { | 242 | { |
| @@ -264,6 +267,7 @@ static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_device | |||
| 264 | scc->conf.dma, scc->conf.dma2); | 267 | scc->conf.dma, scc->conf.dma2); |
| 265 | 268 | ||
| 266 | pnp_set_card_drvdata(card, scc); | 269 | pnp_set_card_drvdata(card, scc); |
| 270 | sb_pnp_devices++; | ||
| 267 | 271 | ||
| 268 | return sb_register_oss(scc, &sbmo); | 272 | return sb_register_oss(scc, &sbmo); |
| 269 | } | 273 | } |
| @@ -289,6 +293,14 @@ static struct pnp_card_driver sb_pnp_driver = { | |||
| 289 | MODULE_DEVICE_TABLE(pnp_card, sb_pnp_card_table); | 293 | MODULE_DEVICE_TABLE(pnp_card, sb_pnp_card_table); |
| 290 | #endif /* CONFIG_PNP */ | 294 | #endif /* CONFIG_PNP */ |
| 291 | 295 | ||
| 296 | static void __init_or_module sb_unregister_all(void) | ||
| 297 | { | ||
| 298 | #ifdef CONFIG_PNP | ||
| 299 | if (pnp_registered) | ||
| 300 | pnp_unregister_card_driver(&sb_pnp_driver); | ||
| 301 | #endif | ||
| 302 | } | ||
| 303 | |||
| 292 | static int __init sb_init(void) | 304 | static int __init sb_init(void) |
| 293 | { | 305 | { |
| 294 | int lres = 0; | 306 | int lres = 0; |
| @@ -307,17 +319,18 @@ static int __init sb_init(void) | |||
| 307 | 319 | ||
| 308 | #ifdef CONFIG_PNP | 320 | #ifdef CONFIG_PNP |
| 309 | if(pnp) { | 321 | if(pnp) { |
| 310 | pres = pnp_register_card_driver(&sb_pnp_driver); | 322 | int err = pnp_register_card_driver(&sb_pnp_driver); |
| 323 | if (!err) | ||
| 324 | pnp_registered = 1; | ||
| 325 | pres = sb_pnp_devices; | ||
| 311 | } | 326 | } |
| 312 | #endif | 327 | #endif |
| 313 | printk(KERN_INFO "sb: Init: Done\n"); | 328 | printk(KERN_INFO "sb: Init: Done\n"); |
| 314 | 329 | ||
| 315 | /* If either PnP or Legacy registered a card then return | 330 | /* If either PnP or Legacy registered a card then return |
| 316 | * success */ | 331 | * success */ |
| 317 | if (pres <= 0 && lres <= 0) { | 332 | if (pres == 0 && lres <= 0) { |
| 318 | #ifdef CONFIG_PNP | 333 | sb_unregister_all(); |
| 319 | pnp_unregister_card_driver(&sb_pnp_driver); | ||
| 320 | #endif | ||
| 321 | return -ENODEV; | 334 | return -ENODEV; |
| 322 | } | 335 | } |
| 323 | return 0; | 336 | return 0; |
| @@ -333,14 +346,10 @@ static void __exit sb_exit(void) | |||
| 333 | sb_unload(legacy); | 346 | sb_unload(legacy); |
| 334 | } | 347 | } |
| 335 | 348 | ||
| 336 | #ifdef CONFIG_PNP | 349 | sb_unregister_all(); |
| 337 | pnp_unregister_card_driver(&sb_pnp_driver); | ||
| 338 | #endif | ||
| 339 | 350 | ||
| 340 | if (smw_free) { | 351 | vfree(smw_free); |
| 341 | vfree(smw_free); | 352 | smw_free = NULL; |
| 342 | smw_free = NULL; | ||
| 343 | } | ||
| 344 | } | 353 | } |
| 345 | 354 | ||
| 346 | module_init(sb_init); | 355 | module_init(sb_init); |
diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c index 347cd79c2502..6815c30e0bc1 100644 --- a/sound/oss/sequencer.c +++ b/sound/oss/sequencer.c | |||
| @@ -1671,14 +1671,7 @@ void sequencer_init(void) | |||
| 1671 | 1671 | ||
| 1672 | void sequencer_unload(void) | 1672 | void sequencer_unload(void) |
| 1673 | { | 1673 | { |
| 1674 | if(queue) | 1674 | vfree(queue); |
| 1675 | { | 1675 | vfree(iqueue); |
| 1676 | vfree(queue); | 1676 | queue = iqueue = NULL; |
| 1677 | queue=NULL; | ||
| 1678 | } | ||
| 1679 | if(iqueue) | ||
| 1680 | { | ||
| 1681 | vfree(iqueue); | ||
| 1682 | iqueue=NULL; | ||
| 1683 | } | ||
| 1684 | } | 1677 | } |
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c index 8a9917c919c2..3f7427cd195a 100644 --- a/sound/oss/sh_dac_audio.c +++ b/sound/oss/sh_dac_audio.c | |||
| @@ -289,7 +289,7 @@ static int __init dac_audio_init(void) | |||
| 289 | 289 | ||
| 290 | in_use = 0; | 290 | in_use = 0; |
| 291 | 291 | ||
| 292 | data_buffer = (char *)kmalloc(BUFFER_SIZE, GFP_KERNEL); | 292 | data_buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL); |
| 293 | if (data_buffer == NULL) | 293 | if (data_buffer == NULL) |
| 294 | return -ENOMEM; | 294 | return -ENOMEM; |
| 295 | 295 | ||
diff --git a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c index 4471757b7985..42bd276cfc39 100644 --- a/sound/oss/sonicvibes.c +++ b/sound/oss/sonicvibes.c | |||
| @@ -116,6 +116,7 @@ | |||
| 116 | #include <linux/spinlock.h> | 116 | #include <linux/spinlock.h> |
| 117 | #include <linux/smp_lock.h> | 117 | #include <linux/smp_lock.h> |
| 118 | #include <linux/gameport.h> | 118 | #include <linux/gameport.h> |
| 119 | #include <linux/dma-mapping.h> | ||
| 119 | #include <linux/mutex.h> | 120 | #include <linux/mutex.h> |
| 120 | 121 | ||
| 121 | 122 | ||
| @@ -2535,7 +2536,7 @@ static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id | |||
| 2535 | return -ENODEV; | 2536 | return -ENODEV; |
| 2536 | if (pcidev->irq == 0) | 2537 | if (pcidev->irq == 0) |
| 2537 | return -ENODEV; | 2538 | return -ENODEV; |
| 2538 | if (pci_set_dma_mask(pcidev, 0x00ffffff)) { | 2539 | if (pci_set_dma_mask(pcidev, DMA_24BIT_MASK)) { |
| 2539 | printk(KERN_WARNING "sonicvibes: architecture does not support 24bit PCI busmaster DMA\n"); | 2540 | printk(KERN_WARNING "sonicvibes: architecture does not support 24bit PCI busmaster DMA\n"); |
| 2540 | return -ENODEV; | 2541 | return -ENODEV; |
| 2541 | } | 2542 | } |
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index 2aa5a7fdb6e0..c6c8333acc62 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
| 40 | #include <linux/compiler.h> | 40 | #include <linux/compiler.h> |
| 41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
| 42 | #include <linux/dma-mapping.h> | ||
| 42 | 43 | ||
| 43 | #include <sound/driver.h> | 44 | #include <sound/driver.h> |
| 44 | #include <sound/core.h> | 45 | #include <sound/core.h> |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index e264136e8fb4..fc92b6896c24 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
| 36 | #include <linux/dma-mapping.h> | ||
| 36 | #include <sound/core.h> | 37 | #include <sound/core.h> |
| 37 | #include <sound/pcm.h> | 38 | #include <sound/pcm.h> |
| 38 | #include <sound/info.h> | 39 | #include <sound/info.h> |
| @@ -2220,8 +2221,8 @@ static int __devinit snd_ali_create(struct snd_card *card, | |||
| 2220 | if ((err = pci_enable_device(pci)) < 0) | 2221 | if ((err = pci_enable_device(pci)) < 0) |
| 2221 | return err; | 2222 | return err; |
| 2222 | /* check, if we can restrict PCI DMA transfers to 31 bits */ | 2223 | /* check, if we can restrict PCI DMA transfers to 31 bits */ |
| 2223 | if (pci_set_dma_mask(pci, 0x7fffffff) < 0 || | 2224 | if (pci_set_dma_mask(pci, DMA_31BIT_MASK) < 0 || |
| 2224 | pci_set_consistent_dma_mask(pci, 0x7fffffff) < 0) { | 2225 | pci_set_consistent_dma_mask(pci, DMA_31BIT_MASK) < 0) { |
| 2225 | snd_printk(KERN_ERR "architecture does not support 31bit PCI busmaster DMA\n"); | 2226 | snd_printk(KERN_ERR "architecture does not support 31bit PCI busmaster DMA\n"); |
| 2226 | pci_disable_device(pci); | 2227 | pci_disable_device(pci); |
| 2227 | return -ENXIO; | 2228 | return -ENXIO; |
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 7b2ff5f4672e..100d8127a411 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
| @@ -70,6 +70,7 @@ | |||
| 70 | #include <linux/slab.h> | 70 | #include <linux/slab.h> |
| 71 | #include <linux/gameport.h> | 71 | #include <linux/gameport.h> |
| 72 | #include <linux/moduleparam.h> | 72 | #include <linux/moduleparam.h> |
| 73 | #include <linux/dma-mapping.h> | ||
| 73 | #include <sound/core.h> | 74 | #include <sound/core.h> |
| 74 | #include <sound/pcm.h> | 75 | #include <sound/pcm.h> |
| 75 | #include <sound/rawmidi.h> | 76 | #include <sound/rawmidi.h> |
| @@ -688,8 +689,8 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, | |||
| 688 | return err; | 689 | return err; |
| 689 | } | 690 | } |
| 690 | /* check, if we can restrict PCI DMA transfers to 24 bits */ | 691 | /* check, if we can restrict PCI DMA transfers to 24 bits */ |
| 691 | if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || | 692 | if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 || |
| 692 | pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { | 693 | pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) { |
| 693 | snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); | 694 | snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); |
| 694 | pci_disable_device(pci); | 695 | pci_disable_device(pci); |
| 695 | return -ENXIO; | 696 | return -ENXIO; |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index e077eb3fbe2f..680077e1e057 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
| @@ -104,6 +104,7 @@ | |||
| 104 | #include <linux/slab.h> | 104 | #include <linux/slab.h> |
| 105 | #include <linux/gameport.h> | 105 | #include <linux/gameport.h> |
| 106 | #include <linux/moduleparam.h> | 106 | #include <linux/moduleparam.h> |
| 107 | #include <linux/dma-mapping.h> | ||
| 107 | #include <sound/core.h> | 108 | #include <sound/core.h> |
| 108 | #include <sound/control.h> | 109 | #include <sound/control.h> |
| 109 | #include <sound/pcm.h> | 110 | #include <sound/pcm.h> |
| @@ -1669,8 +1670,8 @@ snd_azf3328_create(struct snd_card *card, | |||
| 1669 | chip->irq = -1; | 1670 | chip->irq = -1; |
| 1670 | 1671 | ||
| 1671 | /* check if we can restrict PCI DMA transfers to 24 bits */ | 1672 | /* check if we can restrict PCI DMA transfers to 24 bits */ |
| 1672 | if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || | 1673 | if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 || |
| 1673 | pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { | 1674 | pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) { |
| 1674 | snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); | 1675 | snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); |
| 1675 | err = -ENXIO; | 1676 | err = -ENXIO; |
| 1676 | goto out_err; | 1677 | goto out_err; |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 2208dbd48be9..3e332f398162 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/dma-mapping.h> | 36 | #include <linux/dma-mapping.h> |
| 37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
| 38 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
| 39 | #include <linux/dma-mapping.h> | ||
| 39 | #include <sound/core.h> | 40 | #include <sound/core.h> |
| 40 | #include <sound/initval.h> | 41 | #include <sound/initval.h> |
| 41 | #include <sound/pcm.h> | 42 | #include <sound/pcm.h> |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 0d556b09ad04..4d62fe439177 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
| @@ -55,6 +55,7 @@ | |||
| 55 | #include <linux/gameport.h> | 55 | #include <linux/gameport.h> |
| 56 | #include <linux/moduleparam.h> | 56 | #include <linux/moduleparam.h> |
| 57 | #include <linux/delay.h> | 57 | #include <linux/delay.h> |
| 58 | #include <linux/dma-mapping.h> | ||
| 58 | #include <sound/core.h> | 59 | #include <sound/core.h> |
| 59 | #include <sound/control.h> | 60 | #include <sound/control.h> |
| 60 | #include <sound/pcm.h> | 61 | #include <sound/pcm.h> |
| @@ -1517,8 +1518,8 @@ static int __devinit snd_es1938_create(struct snd_card *card, | |||
| 1517 | if ((err = pci_enable_device(pci)) < 0) | 1518 | if ((err = pci_enable_device(pci)) < 0) |
| 1518 | return err; | 1519 | return err; |
| 1519 | /* check, if we can restrict PCI DMA transfers to 24 bits */ | 1520 | /* check, if we can restrict PCI DMA transfers to 24 bits */ |
| 1520 | if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || | 1521 | if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 || |
| 1521 | pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { | 1522 | pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) { |
| 1522 | snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); | 1523 | snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); |
| 1523 | pci_disable_device(pci); | 1524 | pci_disable_device(pci); |
| 1524 | return -ENXIO; | 1525 | return -ENXIO; |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index dd465a186e11..e3ad17f53c29 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
| @@ -104,6 +104,7 @@ | |||
| 104 | #include <linux/slab.h> | 104 | #include <linux/slab.h> |
| 105 | #include <linux/gameport.h> | 105 | #include <linux/gameport.h> |
| 106 | #include <linux/moduleparam.h> | 106 | #include <linux/moduleparam.h> |
| 107 | #include <linux/dma-mapping.h> | ||
| 107 | #include <linux/mutex.h> | 108 | #include <linux/mutex.h> |
| 108 | 109 | ||
| 109 | #include <sound/core.h> | 110 | #include <sound/core.h> |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 672e198317e1..b88eeba2f5d1 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
| @@ -56,7 +56,9 @@ | |||
| 56 | #include <linux/dma-mapping.h> | 56 | #include <linux/dma-mapping.h> |
| 57 | #include <linux/slab.h> | 57 | #include <linux/slab.h> |
| 58 | #include <linux/moduleparam.h> | 58 | #include <linux/moduleparam.h> |
| 59 | #include <linux/dma-mapping.h> | ||
| 59 | #include <linux/mutex.h> | 60 | #include <linux/mutex.h> |
| 61 | |||
| 60 | #include <sound/core.h> | 62 | #include <sound/core.h> |
| 61 | #include <sound/cs8427.h> | 63 | #include <sound/cs8427.h> |
| 62 | #include <sound/info.h> | 64 | #include <sound/info.h> |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 8bc084956c28..44393e190929 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
| 42 | #include <linux/vmalloc.h> | 42 | #include <linux/vmalloc.h> |
| 43 | #include <linux/moduleparam.h> | 43 | #include <linux/moduleparam.h> |
| 44 | #include <linux/dma-mapping.h> | ||
| 44 | #include <sound/core.h> | 45 | #include <sound/core.h> |
| 45 | #include <sound/info.h> | 46 | #include <sound/info.h> |
| 46 | #include <sound/control.h> | 47 | #include <sound/control.h> |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 43ee3b2b948f..b5a095052d4c 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
| 29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
| 30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
| 31 | #include <linux/dma-mapping.h> | ||
| 32 | |||
| 31 | #include <sound/core.h> | 33 | #include <sound/core.h> |
| 32 | #include <sound/initval.h> | 34 | #include <sound/initval.h> |
| 33 | #include <sound/info.h> | 35 | #include <sound/info.h> |
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index f679779d96e3..35875c8aa299 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
| 31 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
| 32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
| 33 | #include <linux/dma-mapping.h> | ||
| 33 | 34 | ||
| 34 | #include <sound/core.h> | 35 | #include <sound/core.h> |
| 35 | #include <sound/initval.h> | 36 | #include <sound/initval.h> |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 0cbef5fe6c63..ab78544bf042 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
| @@ -313,7 +313,7 @@ static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int chann | |||
| 313 | } | 313 | } |
| 314 | 314 | ||
| 315 | /* | 315 | /* |
| 316 | * SPDIF I/O capabilites (half-duplex mode) | 316 | * SPDIF I/O capabilities (half-duplex mode) |
| 317 | */ | 317 | */ |
| 318 | static struct snd_pcm_hardware snd_rme32_spdif_info = { | 318 | static struct snd_pcm_hardware snd_rme32_spdif_info = { |
| 319 | .info = (SNDRV_PCM_INFO_MMAP_IOMEM | | 319 | .info = (SNDRV_PCM_INFO_MMAP_IOMEM | |
| @@ -339,7 +339,7 @@ static struct snd_pcm_hardware snd_rme32_spdif_info = { | |||
| 339 | }; | 339 | }; |
| 340 | 340 | ||
| 341 | /* | 341 | /* |
| 342 | * ADAT I/O capabilites (half-duplex mode) | 342 | * ADAT I/O capabilities (half-duplex mode) |
| 343 | */ | 343 | */ |
| 344 | static struct snd_pcm_hardware snd_rme32_adat_info = | 344 | static struct snd_pcm_hardware snd_rme32_adat_info = |
| 345 | { | 345 | { |
| @@ -364,7 +364,7 @@ static struct snd_pcm_hardware snd_rme32_adat_info = | |||
| 364 | }; | 364 | }; |
| 365 | 365 | ||
| 366 | /* | 366 | /* |
| 367 | * SPDIF I/O capabilites (full-duplex mode) | 367 | * SPDIF I/O capabilities (full-duplex mode) |
| 368 | */ | 368 | */ |
| 369 | static struct snd_pcm_hardware snd_rme32_spdif_fd_info = { | 369 | static struct snd_pcm_hardware snd_rme32_spdif_fd_info = { |
| 370 | .info = (SNDRV_PCM_INFO_MMAP | | 370 | .info = (SNDRV_PCM_INFO_MMAP | |
| @@ -390,7 +390,7 @@ static struct snd_pcm_hardware snd_rme32_spdif_fd_info = { | |||
| 390 | }; | 390 | }; |
| 391 | 391 | ||
| 392 | /* | 392 | /* |
| 393 | * ADAT I/O capabilites (full-duplex mode) | 393 | * ADAT I/O capabilities (full-duplex mode) |
| 394 | */ | 394 | */ |
| 395 | static struct snd_pcm_hardware snd_rme32_adat_fd_info = | 395 | static struct snd_pcm_hardware snd_rme32_adat_fd_info = |
| 396 | { | 396 | { |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 0e694b011dcc..6c2a9f4a7659 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
| @@ -359,7 +359,7 @@ snd_rme96_capture_copy(struct snd_pcm_substream *substream, | |||
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | /* | 361 | /* |
| 362 | * Digital output capabilites (S/PDIF) | 362 | * Digital output capabilities (S/PDIF) |
| 363 | */ | 363 | */ |
| 364 | static struct snd_pcm_hardware snd_rme96_playback_spdif_info = | 364 | static struct snd_pcm_hardware snd_rme96_playback_spdif_info = |
| 365 | { | 365 | { |
| @@ -388,7 +388,7 @@ static struct snd_pcm_hardware snd_rme96_playback_spdif_info = | |||
| 388 | }; | 388 | }; |
| 389 | 389 | ||
| 390 | /* | 390 | /* |
| 391 | * Digital input capabilites (S/PDIF) | 391 | * Digital input capabilities (S/PDIF) |
| 392 | */ | 392 | */ |
| 393 | static struct snd_pcm_hardware snd_rme96_capture_spdif_info = | 393 | static struct snd_pcm_hardware snd_rme96_capture_spdif_info = |
| 394 | { | 394 | { |
| @@ -417,7 +417,7 @@ static struct snd_pcm_hardware snd_rme96_capture_spdif_info = | |||
| 417 | }; | 417 | }; |
| 418 | 418 | ||
| 419 | /* | 419 | /* |
| 420 | * Digital output capabilites (ADAT) | 420 | * Digital output capabilities (ADAT) |
| 421 | */ | 421 | */ |
| 422 | static struct snd_pcm_hardware snd_rme96_playback_adat_info = | 422 | static struct snd_pcm_hardware snd_rme96_playback_adat_info = |
| 423 | { | 423 | { |
| @@ -442,7 +442,7 @@ static struct snd_pcm_hardware snd_rme96_playback_adat_info = | |||
| 442 | }; | 442 | }; |
| 443 | 443 | ||
| 444 | /* | 444 | /* |
| 445 | * Digital input capabilites (ADAT) | 445 | * Digital input capabilities (ADAT) |
| 446 | */ | 446 | */ |
| 447 | static struct snd_pcm_hardware snd_rme96_capture_adat_info = | 447 | static struct snd_pcm_hardware snd_rme96_capture_adat_info = |
| 448 | { | 448 | { |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 980b9cd689dd..b5538efd146b 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
| @@ -2256,7 +2256,7 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm | |||
| 2256 | } | 2256 | } |
| 2257 | 2257 | ||
| 2258 | /* Channel playback mixer as default control | 2258 | /* Channel playback mixer as default control |
| 2259 | Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats to big for any alsamixer | 2259 | Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer |
| 2260 | they are accesible via special IOCTL on hwdep | 2260 | they are accesible via special IOCTL on hwdep |
| 2261 | and the mixer 2dimensional mixer control */ | 2261 | and the mixer 2dimensional mixer control */ |
| 2262 | 2262 | ||
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 7bbea3738b8a..2d66a09fe5ee 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | #include <linux/gameport.h> | 31 | #include <linux/gameport.h> |
| 32 | #include <linux/moduleparam.h> | 32 | #include <linux/moduleparam.h> |
| 33 | #include <linux/dma-mapping.h> | ||
| 33 | 34 | ||
| 34 | #include <sound/core.h> | 35 | #include <sound/core.h> |
| 35 | #include <sound/pcm.h> | 36 | #include <sound/pcm.h> |
| @@ -1227,8 +1228,8 @@ static int __devinit snd_sonicvibes_create(struct snd_card *card, | |||
| 1227 | if ((err = pci_enable_device(pci)) < 0) | 1228 | if ((err = pci_enable_device(pci)) < 0) |
| 1228 | return err; | 1229 | return err; |
| 1229 | /* check, if we can restrict PCI DMA transfers to 24 bits */ | 1230 | /* check, if we can restrict PCI DMA transfers to 24 bits */ |
| 1230 | if (pci_set_dma_mask(pci, 0x00ffffff) < 0 || | 1231 | if (pci_set_dma_mask(pci, DMA_24BIT_MASK) < 0 || |
| 1231 | pci_set_consistent_dma_mask(pci, 0x00ffffff) < 0) { | 1232 | pci_set_consistent_dma_mask(pci, DMA_24BIT_MASK) < 0) { |
| 1232 | snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); | 1233 | snd_printk(KERN_ERR "architecture does not support 24bit PCI busmaster DMA\n"); |
| 1233 | pci_disable_device(pci); | 1234 | pci_disable_device(pci); |
| 1234 | return -ENXIO; | 1235 | return -ENXIO; |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 83b7d8aba9e6..52178b8ad49d 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 36 | #include <linux/vmalloc.h> | 36 | #include <linux/vmalloc.h> |
| 37 | #include <linux/gameport.h> | 37 | #include <linux/gameport.h> |
| 38 | #include <linux/dma-mapping.h> | ||
| 38 | 39 | ||
| 39 | #include <sound/core.h> | 40 | #include <sound/core.h> |
| 40 | #include <sound/info.h> | 41 | #include <sound/info.h> |
| @@ -3554,8 +3555,8 @@ int __devinit snd_trident_create(struct snd_card *card, | |||
| 3554 | if ((err = pci_enable_device(pci)) < 0) | 3555 | if ((err = pci_enable_device(pci)) < 0) |
| 3555 | return err; | 3556 | return err; |
| 3556 | /* check, if we can restrict PCI DMA transfers to 30 bits */ | 3557 | /* check, if we can restrict PCI DMA transfers to 30 bits */ |
| 3557 | if (pci_set_dma_mask(pci, 0x3fffffff) < 0 || | 3558 | if (pci_set_dma_mask(pci, DMA_30BIT_MASK) < 0 || |
| 3558 | pci_set_consistent_dma_mask(pci, 0x3fffffff) < 0) { | 3559 | pci_set_consistent_dma_mask(pci, DMA_30BIT_MASK) < 0) { |
| 3559 | snd_printk(KERN_ERR "architecture does not support 30bit PCI busmaster DMA\n"); | 3560 | snd_printk(KERN_ERR "architecture does not support 30bit PCI busmaster DMA\n"); |
| 3560 | pci_disable_device(pci); | 3561 | pci_disable_device(pci); |
| 3561 | return -ENXIO; | 3562 | return -ENXIO; |
diff --git a/sound/sound_core.c b/sound/sound_core.c index 394b53e20cb8..6f849720aef3 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c | |||
| @@ -53,7 +53,7 @@ | |||
| 53 | struct sound_unit | 53 | struct sound_unit |
| 54 | { | 54 | { |
| 55 | int unit_minor; | 55 | int unit_minor; |
| 56 | struct file_operations *unit_fops; | 56 | const struct file_operations *unit_fops; |
| 57 | struct sound_unit *next; | 57 | struct sound_unit *next; |
| 58 | char name[32]; | 58 | char name[32]; |
| 59 | }; | 59 | }; |
| @@ -73,7 +73,7 @@ EXPORT_SYMBOL(sound_class); | |||
| 73 | * join into it. Called with the lock asserted | 73 | * join into it. Called with the lock asserted |
| 74 | */ | 74 | */ |
| 75 | 75 | ||
| 76 | static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, struct file_operations *fops, int index, int low, int top) | 76 | static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, const struct file_operations *fops, int index, int low, int top) |
| 77 | { | 77 | { |
| 78 | int n=low; | 78 | int n=low; |
| 79 | 79 | ||
| @@ -153,7 +153,7 @@ static DEFINE_SPINLOCK(sound_loader_lock); | |||
| 153 | * list. Acquires locks as needed | 153 | * list. Acquires locks as needed |
| 154 | */ | 154 | */ |
| 155 | 155 | ||
| 156 | static int sound_insert_unit(struct sound_unit **list, struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode, struct device *dev) | 156 | static int sound_insert_unit(struct sound_unit **list, const struct file_operations *fops, int index, int low, int top, const char *name, umode_t mode, struct device *dev) |
| 157 | { | 157 | { |
| 158 | struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL); | 158 | struct sound_unit *s = kmalloc(sizeof(*s), GFP_KERNEL); |
| 159 | int r; | 159 | int r; |
| @@ -237,7 +237,7 @@ static struct sound_unit *chains[SOUND_STEP]; | |||
| 237 | * a negative error code is returned. | 237 | * a negative error code is returned. |
| 238 | */ | 238 | */ |
| 239 | 239 | ||
| 240 | int register_sound_special_device(struct file_operations *fops, int unit, | 240 | int register_sound_special_device(const struct file_operations *fops, int unit, |
| 241 | struct device *dev) | 241 | struct device *dev) |
| 242 | { | 242 | { |
| 243 | const int chain = unit % SOUND_STEP; | 243 | const int chain = unit % SOUND_STEP; |
| @@ -301,7 +301,7 @@ int register_sound_special_device(struct file_operations *fops, int unit, | |||
| 301 | 301 | ||
| 302 | EXPORT_SYMBOL(register_sound_special_device); | 302 | EXPORT_SYMBOL(register_sound_special_device); |
| 303 | 303 | ||
| 304 | int register_sound_special(struct file_operations *fops, int unit) | 304 | int register_sound_special(const struct file_operations *fops, int unit) |
| 305 | { | 305 | { |
| 306 | return register_sound_special_device(fops, unit, NULL); | 306 | return register_sound_special_device(fops, unit, NULL); |
| 307 | } | 307 | } |
| @@ -318,7 +318,7 @@ EXPORT_SYMBOL(register_sound_special); | |||
| 318 | * number is returned, on failure a negative error code is returned. | 318 | * number is returned, on failure a negative error code is returned. |
| 319 | */ | 319 | */ |
| 320 | 320 | ||
| 321 | int register_sound_mixer(struct file_operations *fops, int dev) | 321 | int register_sound_mixer(const struct file_operations *fops, int dev) |
| 322 | { | 322 | { |
| 323 | return sound_insert_unit(&chains[0], fops, dev, 0, 128, | 323 | return sound_insert_unit(&chains[0], fops, dev, 0, 128, |
| 324 | "mixer", S_IRUSR | S_IWUSR, NULL); | 324 | "mixer", S_IRUSR | S_IWUSR, NULL); |
| @@ -336,7 +336,7 @@ EXPORT_SYMBOL(register_sound_mixer); | |||
| 336 | * number is returned, on failure a negative error code is returned. | 336 | * number is returned, on failure a negative error code is returned. |
| 337 | */ | 337 | */ |
| 338 | 338 | ||
| 339 | int register_sound_midi(struct file_operations *fops, int dev) | 339 | int register_sound_midi(const struct file_operations *fops, int dev) |
| 340 | { | 340 | { |
| 341 | return sound_insert_unit(&chains[2], fops, dev, 2, 130, | 341 | return sound_insert_unit(&chains[2], fops, dev, 2, 130, |
| 342 | "midi", S_IRUSR | S_IWUSR, NULL); | 342 | "midi", S_IRUSR | S_IWUSR, NULL); |
| @@ -362,7 +362,7 @@ EXPORT_SYMBOL(register_sound_midi); | |||
| 362 | * and will always allocate them as a matching pair - eg dsp3/audio3 | 362 | * and will always allocate them as a matching pair - eg dsp3/audio3 |
| 363 | */ | 363 | */ |
| 364 | 364 | ||
| 365 | int register_sound_dsp(struct file_operations *fops, int dev) | 365 | int register_sound_dsp(const struct file_operations *fops, int dev) |
| 366 | { | 366 | { |
| 367 | return sound_insert_unit(&chains[3], fops, dev, 3, 131, | 367 | return sound_insert_unit(&chains[3], fops, dev, 3, 131, |
| 368 | "dsp", S_IWUSR | S_IRUSR, NULL); | 368 | "dsp", S_IWUSR | S_IRUSR, NULL); |
| @@ -381,7 +381,7 @@ EXPORT_SYMBOL(register_sound_dsp); | |||
| 381 | */ | 381 | */ |
| 382 | 382 | ||
| 383 | 383 | ||
| 384 | int register_sound_synth(struct file_operations *fops, int dev) | 384 | int register_sound_synth(const struct file_operations *fops, int dev) |
| 385 | { | 385 | { |
| 386 | return sound_insert_unit(&chains[9], fops, dev, 9, 137, | 386 | return sound_insert_unit(&chains[9], fops, dev, 9, 137, |
| 387 | "synth", S_IRUSR | S_IWUSR, NULL); | 387 | "synth", S_IRUSR | S_IWUSR, NULL); |
| @@ -501,7 +501,7 @@ int soundcore_open(struct inode *inode, struct file *file) | |||
| 501 | int chain; | 501 | int chain; |
| 502 | int unit = iminor(inode); | 502 | int unit = iminor(inode); |
| 503 | struct sound_unit *s; | 503 | struct sound_unit *s; |
| 504 | struct file_operations *new_fops = NULL; | 504 | const struct file_operations *new_fops = NULL; |
| 505 | 505 | ||
| 506 | chain=unit&0x0F; | 506 | chain=unit&0x0F; |
| 507 | if(chain==4 || chain==5) /* dsp/audio/dsp16 */ | 507 | if(chain==4 || chain==5) /* dsp/audio/dsp16 */ |
| @@ -540,7 +540,7 @@ int soundcore_open(struct inode *inode, struct file *file) | |||
| 540 | * switching ->f_op in the first place. | 540 | * switching ->f_op in the first place. |
| 541 | */ | 541 | */ |
| 542 | int err = 0; | 542 | int err = 0; |
| 543 | struct file_operations *old_fops = file->f_op; | 543 | const struct file_operations *old_fops = file->f_op; |
| 544 | file->f_op = new_fops; | 544 | file->f_op = new_fops; |
| 545 | spin_unlock(&sound_loader_lock); | 545 | spin_unlock(&sound_loader_lock); |
| 546 | if(file->f_op->open) | 546 | if(file->f_op->open) |
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 315855082fe1..fe67a92e2a1a 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c | |||
| @@ -404,7 +404,7 @@ static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs) | |||
| 404 | struct usX2Ydev * usX2Y = subs->usX2Y; | 404 | struct usX2Ydev * usX2Y = subs->usX2Y; |
| 405 | usX2Y->prepare_subs = subs; | 405 | usX2Y->prepare_subs = subs; |
| 406 | subs->urb[0]->start_frame = -1; | 406 | subs->urb[0]->start_frame = -1; |
| 407 | smp_wmb(); // Make shure above modifications are seen by i_usX2Y_subs_startup() | 407 | smp_wmb(); // Make sure above modifications are seen by i_usX2Y_subs_startup() |
| 408 | usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup); | 408 | usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup); |
| 409 | } | 409 | } |
| 410 | 410 | ||
