diff options
357 files changed, 13335 insertions, 5051 deletions
diff --git a/.gitignore b/.gitignore index 8d14531846b9..8363e48cdcdc 100644 --- a/.gitignore +++ b/.gitignore | |||
@@ -17,6 +17,7 @@ | |||
17 | *.i | 17 | *.i |
18 | *.lst | 18 | *.lst |
19 | *.symtypes | 19 | *.symtypes |
20 | *.order | ||
20 | 21 | ||
21 | # | 22 | # |
22 | # Top-level generic files | 23 | # Top-level generic files |
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index 6a4adcae9f9a..560f88dc7090 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt | |||
@@ -86,9 +86,21 @@ Alex is working on a new set of patches right now. | |||
86 | When mounting an ext4 filesystem, the following option are accepted: | 86 | When mounting an ext4 filesystem, the following option are accepted: |
87 | (*) == default | 87 | (*) == default |
88 | 88 | ||
89 | extents ext4 will use extents to address file data. The | 89 | extents (*) ext4 will use extents to address file data. The |
90 | file system will no longer be mountable by ext3. | 90 | file system will no longer be mountable by ext3. |
91 | 91 | ||
92 | noextents ext4 will not use extents for newly created files | ||
93 | |||
94 | journal_checksum Enable checksumming of the journal transactions. | ||
95 | This will allow the recovery code in e2fsck and the | ||
96 | kernel to detect corruption in the kernel. It is a | ||
97 | compatible change and will be ignored by older kernels. | ||
98 | |||
99 | journal_async_commit Commit block can be written to disk without waiting | ||
100 | for descriptor blocks. If enabled older kernels cannot | ||
101 | mount the device. This will enable 'journal_checksum' | ||
102 | internally. | ||
103 | |||
92 | journal=update Update the ext4 file system's journal to the current | 104 | journal=update Update the ext4 file system's journal to the current |
93 | format. | 105 | format. |
94 | 106 | ||
@@ -196,6 +208,12 @@ nobh (a) cache disk block mapping information | |||
196 | "nobh" option tries to avoid associating buffer | 208 | "nobh" option tries to avoid associating buffer |
197 | heads (supported only for "writeback" mode). | 209 | heads (supported only for "writeback" mode). |
198 | 210 | ||
211 | mballoc (*) Use the multiple block allocator for block allocation | ||
212 | nomballoc disabled multiple block allocator for block allocation. | ||
213 | stripe=n Number of filesystem blocks that mballoc will try | ||
214 | to use for allocation size and alignment. For RAID5/6 | ||
215 | systems this should be the number of data | ||
216 | disks * RAID chunk size in file system blocks. | ||
199 | 217 | ||
200 | Data Mode | 218 | Data Mode |
201 | --------- | 219 | --------- |
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index dec99455321f..4413a2d4646f 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt | |||
@@ -857,6 +857,45 @@ CPUs. | |||
857 | The "procs_blocked" line gives the number of processes currently blocked, | 857 | The "procs_blocked" line gives the number of processes currently blocked, |
858 | waiting for I/O to complete. | 858 | waiting for I/O to complete. |
859 | 859 | ||
860 | 1.9 Ext4 file system parameters | ||
861 | ------------------------------ | ||
862 | Ext4 file system have one directory per partition under /proc/fs/ext4/ | ||
863 | # ls /proc/fs/ext4/hdc/ | ||
864 | group_prealloc max_to_scan mb_groups mb_history min_to_scan order2_req | ||
865 | stats stream_req | ||
866 | |||
867 | mb_groups: | ||
868 | This file gives the details of mutiblock allocator buddy cache of free blocks | ||
869 | |||
870 | mb_history: | ||
871 | Multiblock allocation history. | ||
872 | |||
873 | stats: | ||
874 | This file indicate whether the multiblock allocator should start collecting | ||
875 | statistics. The statistics are shown during unmount | ||
876 | |||
877 | group_prealloc: | ||
878 | The multiblock allocator normalize the block allocation request to | ||
879 | group_prealloc filesystem blocks if we don't have strip value set. | ||
880 | The stripe value can be specified at mount time or during mke2fs. | ||
881 | |||
882 | max_to_scan: | ||
883 | How long multiblock allocator can look for a best extent (in found extents) | ||
884 | |||
885 | min_to_scan: | ||
886 | How long multiblock allocator must look for a best extent | ||
887 | |||
888 | order2_req: | ||
889 | Multiblock allocator use 2^N search using buddies only for requests greater | ||
890 | than or equal to order2_req. The request size is specfied in file system | ||
891 | blocks. A value of 2 indicate only if the requests are greater than or equal | ||
892 | to 4 blocks. | ||
893 | |||
894 | stream_req: | ||
895 | Files smaller than stream_req are served by the stream allocator, whose | ||
896 | purpose is to pack requests as close each to other as possible to | ||
897 | produce smooth I/O traffic. Avalue of 16 indicate that file smaller than 16 | ||
898 | filesystem block size will use group based preallocation. | ||
860 | 899 | ||
861 | ------------------------------------------------------------------------------ | 900 | ------------------------------------------------------------------------------ |
862 | Summary | 901 | Summary |
diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt index 616043a6da99..649cb8799890 100644 --- a/Documentation/kbuild/kconfig-language.txt +++ b/Documentation/kbuild/kconfig-language.txt | |||
@@ -24,7 +24,7 @@ visible if its parent entry is also visible. | |||
24 | Menu entries | 24 | Menu entries |
25 | ------------ | 25 | ------------ |
26 | 26 | ||
27 | Most entries define a config option, all other entries help to organize | 27 | Most entries define a config option; all other entries help to organize |
28 | them. A single configuration option is defined like this: | 28 | them. A single configuration option is defined like this: |
29 | 29 | ||
30 | config MODVERSIONS | 30 | config MODVERSIONS |
@@ -50,7 +50,7 @@ applicable everywhere (see syntax). | |||
50 | 50 | ||
51 | - type definition: "bool"/"tristate"/"string"/"hex"/"int" | 51 | - type definition: "bool"/"tristate"/"string"/"hex"/"int" |
52 | Every config option must have a type. There are only two basic types: | 52 | Every config option must have a type. There are only two basic types: |
53 | tristate and string, the other types are based on these two. The type | 53 | tristate and string; the other types are based on these two. The type |
54 | definition optionally accepts an input prompt, so these two examples | 54 | definition optionally accepts an input prompt, so these two examples |
55 | are equivalent: | 55 | are equivalent: |
56 | 56 | ||
@@ -108,7 +108,7 @@ applicable everywhere (see syntax). | |||
108 | equal to 'y' without visiting the dependencies. So abusing | 108 | equal to 'y' without visiting the dependencies. So abusing |
109 | select you are able to select a symbol FOO even if FOO depends | 109 | select you are able to select a symbol FOO even if FOO depends |
110 | on BAR that is not set. In general use select only for | 110 | on BAR that is not set. In general use select only for |
111 | non-visible symbols (no promts anywhere) and for symbols with | 111 | non-visible symbols (no prompts anywhere) and for symbols with |
112 | no dependencies. That will limit the usefulness but on the | 112 | no dependencies. That will limit the usefulness but on the |
113 | other hand avoid the illegal configurations all over. kconfig | 113 | other hand avoid the illegal configurations all over. kconfig |
114 | should one day warn about such things. | 114 | should one day warn about such things. |
@@ -127,6 +127,27 @@ applicable everywhere (see syntax). | |||
127 | used to help visually separate configuration logic from help within | 127 | used to help visually separate configuration logic from help within |
128 | the file as an aid to developers. | 128 | the file as an aid to developers. |
129 | 129 | ||
130 | - misc options: "option" <symbol>[=<value>] | ||
131 | Various less common options can be defined via this option syntax, | ||
132 | which can modify the behaviour of the menu entry and its config | ||
133 | symbol. These options are currently possible: | ||
134 | |||
135 | - "defconfig_list" | ||
136 | This declares a list of default entries which can be used when | ||
137 | looking for the default configuration (which is used when the main | ||
138 | .config doesn't exists yet.) | ||
139 | |||
140 | - "modules" | ||
141 | This declares the symbol to be used as the MODULES symbol, which | ||
142 | enables the third modular state for all config symbols. | ||
143 | |||
144 | - "env"=<value> | ||
145 | This imports the environment variable into Kconfig. It behaves like | ||
146 | a default, except that the value comes from the environment, this | ||
147 | also means that the behaviour when mixing it with normal defaults is | ||
148 | undefined at this point. The symbol is currently not exported back | ||
149 | to the build environment (if this is desired, it can be done via | ||
150 | another symbol). | ||
130 | 151 | ||
131 | Menu dependencies | 152 | Menu dependencies |
132 | ----------------- | 153 | ----------------- |
@@ -162,9 +183,9 @@ An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2 | |||
162 | respectively for calculations). A menu entry becomes visible when it's | 183 | respectively for calculations). A menu entry becomes visible when it's |
163 | expression evaluates to 'm' or 'y'. | 184 | expression evaluates to 'm' or 'y'. |
164 | 185 | ||
165 | There are two types of symbols: constant and nonconstant symbols. | 186 | There are two types of symbols: constant and non-constant symbols. |
166 | Nonconstant symbols are the most common ones and are defined with the | 187 | Non-constant symbols are the most common ones and are defined with the |
167 | 'config' statement. Nonconstant symbols consist entirely of alphanumeric | 188 | 'config' statement. Non-constant symbols consist entirely of alphanumeric |
168 | characters or underscores. | 189 | characters or underscores. |
169 | Constant symbols are only part of expressions. Constant symbols are | 190 | Constant symbols are only part of expressions. Constant symbols are |
170 | always surrounded by single or double quotes. Within the quote, any | 191 | always surrounded by single or double quotes. Within the quote, any |
@@ -301,3 +322,81 @@ mainmenu: | |||
301 | 322 | ||
302 | This sets the config program's title bar if the config program chooses | 323 | This sets the config program's title bar if the config program chooses |
303 | to use it. | 324 | to use it. |
325 | |||
326 | |||
327 | Kconfig hints | ||
328 | ------------- | ||
329 | This is a collection of Kconfig tips, most of which aren't obvious at | ||
330 | first glance and most of which have become idioms in several Kconfig | ||
331 | files. | ||
332 | |||
333 | Adding common features and make the usage configurable | ||
334 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
335 | It is a common idiom to implement a feature/functionality that are | ||
336 | relevant for some architectures but not all. | ||
337 | The recommended way to do so is to use a config variable named HAVE_* | ||
338 | that is defined in a common Kconfig file and selected by the relevant | ||
339 | architectures. | ||
340 | An example is the generic IOMAP functionality. | ||
341 | |||
342 | We would in lib/Kconfig see: | ||
343 | |||
344 | # Generic IOMAP is used to ... | ||
345 | config HAVE_GENERIC_IOMAP | ||
346 | |||
347 | config GENERIC_IOMAP | ||
348 | depends on HAVE_GENERIC_IOMAP && FOO | ||
349 | |||
350 | And in lib/Makefile we would see: | ||
351 | obj-$(CONFIG_GENERIC_IOMAP) += iomap.o | ||
352 | |||
353 | For each architecture using the generic IOMAP functionality we would see: | ||
354 | |||
355 | config X86 | ||
356 | select ... | ||
357 | select HAVE_GENERIC_IOMAP | ||
358 | select ... | ||
359 | |||
360 | Note: we use the existing config option and avoid creating a new | ||
361 | config variable to select HAVE_GENERIC_IOMAP. | ||
362 | |||
363 | Note: the use of the internal config variable HAVE_GENERIC_IOMAP, it is | ||
364 | introduced to overcome the limitation of select which will force a | ||
365 | config option to 'y' no matter the dependencies. | ||
366 | The dependencies are moved to the symbol GENERIC_IOMAP and we avoid the | ||
367 | situation where select forces a symbol equals to 'y'. | ||
368 | |||
369 | Build as module only | ||
370 | ~~~~~~~~~~~~~~~~~~~~ | ||
371 | To restrict a component build to module-only, qualify its config symbol | ||
372 | with "depends on m". E.g.: | ||
373 | |||
374 | config FOO | ||
375 | depends on BAR && m | ||
376 | |||
377 | limits FOO to module (=m) or disabled (=n). | ||
378 | |||
379 | |||
380 | Build limited by a third config symbol which may be =y or =m | ||
381 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
382 | A common idiom that we see (and sometimes have problems with) is this: | ||
383 | |||
384 | When option C in B (module or subsystem) uses interfaces from A (module | ||
385 | or subsystem), and both A and B are tristate (could be =y or =m if they | ||
386 | were independent of each other, but they aren't), then we need to limit | ||
387 | C such that it cannot be built statically if A is built as a loadable | ||
388 | module. (C already depends on B, so there is no dependency issue to | ||
389 | take care of here.) | ||
390 | |||
391 | If A is linked statically into the kernel image, C can be built | ||
392 | statically or as loadable module(s). However, if A is built as loadable | ||
393 | module(s), then C must be restricted to loadable module(s) also. This | ||
394 | can be expressed in kconfig language as: | ||
395 | |||
396 | config C | ||
397 | depends on A = y || A = B | ||
398 | |||
399 | or for real examples, use this command in a kernel tree: | ||
400 | |||
401 | $ find . -name Kconfig\* | xargs grep -ns "depends on.*=.*||.*=" | grep -v orig | ||
402 | |||
diff --git a/Documentation/mips/00-INDEX b/Documentation/mips/00-INDEX index 3f13bf8043d2..8ae9cffc2262 100644 --- a/Documentation/mips/00-INDEX +++ b/Documentation/mips/00-INDEX | |||
@@ -2,5 +2,3 @@ | |||
2 | - this file. | 2 | - this file. |
3 | AU1xxx_IDE.README | 3 | AU1xxx_IDE.README |
4 | - README for MIPS AU1XXX IDE driver. | 4 | - README for MIPS AU1XXX IDE driver. |
5 | GT64120.README | ||
6 | - README for dir with info on MIPS boards using GT-64120 or GT-64120A. | ||
diff --git a/Documentation/mips/GT64120.README b/Documentation/mips/GT64120.README deleted file mode 100644 index 2d0eec91dc59..000000000000 --- a/Documentation/mips/GT64120.README +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | README for arch/mips/gt64120 directory and subdirectories | ||
2 | |||
3 | Jun Sun, jsun@mvista.com or jsun@junsun.net | ||
4 | 01/27, 2001 | ||
5 | |||
6 | MOTIVATION | ||
7 | ---------- | ||
8 | |||
9 | Many MIPS boards share the same system controller (or CPU companian chip), | ||
10 | such as GT-64120. It is highly desirable to let these boards share | ||
11 | the same controller code instead of duplicating them. | ||
12 | |||
13 | This directory is meant to hold all MIPS boards that use GT-64120 or GT-64120A. | ||
14 | |||
15 | |||
16 | HOW TO ADD A BOARD | ||
17 | ------------------ | ||
18 | |||
19 | . Create a subdirectory include/asm/gt64120/<board>. | ||
20 | |||
21 | . Create a file called gt64120_dep.h under that directory. | ||
22 | |||
23 | . Modify include/asm/gt64120/gt64120.h file to include the new gt64120_dep.h | ||
24 | based on config options. The board-dep section is at the end of | ||
25 | include/asm/gt64120/gt64120.h file. There you can find all required | ||
26 | definitions include/asm/gt64120/<board>/gt64120_dep.h file must supply. | ||
27 | |||
28 | . Create a subdirectory arch/mips/gt64120/<board> directory to hold | ||
29 | board specific routines. | ||
30 | |||
31 | . The GT-64120 common code is supplied under arch/mips/gt64120/common directory. | ||
32 | It includes: | ||
33 | 1) arch/mips/gt64120/pci.c - | ||
34 | common PCI routine, include the top-level pcibios_init() | ||
35 | 2) arch/mips/gt64120/irq.c - | ||
36 | common IRQ routine, include the top-level do_IRQ() | ||
37 | [This part really belongs to arch/mips/kernel. jsun] | ||
38 | 3) arch/mips/gt64120/gt_irq.c - | ||
39 | common IRQ routines for GT-64120 chip. Currently it only handles | ||
40 | the timer interrupt. | ||
41 | |||
42 | . Board-specific routines are supplied under arch/mips/gt64120/<board> dir. | ||
43 | 1) arch/mips/gt64120/<board>/pci.c - it provides bus fixup routine | ||
44 | 2) arch/mips/gt64120/<board>/irq.c - it provides enable/disable irqs | ||
45 | and board irq setup routine (irq_setup) | ||
46 | 3) arch/mips/gt64120/<board>/int-handler.S - | ||
47 | The first-level interrupt dispatching routine. | ||
48 | 4) a bunch of other "normal" stuff (setup, prom, dbg_io, reset, etc) | ||
49 | |||
50 | . Follow other "normal" procedure to modify configuration files, etc. | ||
51 | |||
52 | |||
53 | TO-DO LIST | ||
54 | ---------- | ||
55 | |||
56 | . Expand arch/mips/gt64120/gt_irq.c to handle all GT-64120 interrupts. | ||
57 | We probably need to introduce GT_IRQ_BASE in board-dep header file, | ||
58 | which is used the starting irq_nr for all GT irqs. | ||
59 | |||
60 | A function, gt64120_handle_irq(), will be added so that the first-level | ||
61 | irq dispatcher will call this function if it detects an interrupt | ||
62 | from GT-64120. | ||
63 | |||
64 | . More support for GT-64120 PCI features (2nd PCI bus, perhaps) | ||
65 | |||
@@ -520,6 +520,11 @@ KBUILD_CFLAGS += -g | |||
520 | KBUILD_AFLAGS += -gdwarf-2 | 520 | KBUILD_AFLAGS += -gdwarf-2 |
521 | endif | 521 | endif |
522 | 522 | ||
523 | # We trigger additional mismatches with less inlining | ||
524 | ifdef CONFIG_DEBUG_SECTION_MISMATCH | ||
525 | KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once) | ||
526 | endif | ||
527 | |||
523 | # Force gcc to behave correct even for buggy distributions | 528 | # Force gcc to behave correct even for buggy distributions |
524 | KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) | 529 | KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) |
525 | 530 | ||
@@ -793,7 +798,7 @@ define rule_vmlinux-modpost | |||
793 | endef | 798 | endef |
794 | 799 | ||
795 | # vmlinux image - including updated kernel symbols | 800 | # vmlinux image - including updated kernel symbols |
796 | vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) vmlinux.o FORCE | 801 | vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o $(kallsyms.o) FORCE |
797 | ifdef CONFIG_HEADERS_CHECK | 802 | ifdef CONFIG_HEADERS_CHECK |
798 | $(Q)$(MAKE) -f $(srctree)/Makefile headers_check | 803 | $(Q)$(MAKE) -f $(srctree)/Makefile headers_check |
799 | endif | 804 | endif |
@@ -804,7 +809,9 @@ endif | |||
804 | $(call if_changed_rule,vmlinux__) | 809 | $(call if_changed_rule,vmlinux__) |
805 | $(Q)rm -f .old_version | 810 | $(Q)rm -f .old_version |
806 | 811 | ||
807 | vmlinux.o: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE | 812 | # build vmlinux.o first to catch section mismatch errors early |
813 | $(kallsyms.o): vmlinux.o | ||
814 | vmlinux.o: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE | ||
808 | $(call if_changed_rule,vmlinux-modpost) | 815 | $(call if_changed_rule,vmlinux-modpost) |
809 | 816 | ||
810 | # The actual objects are generated when descending, | 817 | # The actual objects are generated when descending, |
@@ -1021,9 +1028,14 @@ ifdef CONFIG_MODULES | |||
1021 | all: modules | 1028 | all: modules |
1022 | 1029 | ||
1023 | # Build modules | 1030 | # Build modules |
1031 | # | ||
1032 | # A module can be listed more than once in obj-m resulting in | ||
1033 | # duplicate lines in modules.order files. Those are removed | ||
1034 | # using awk while concatenating to the final file. | ||
1024 | 1035 | ||
1025 | PHONY += modules | 1036 | PHONY += modules |
1026 | modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) | 1037 | modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) |
1038 | $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order | ||
1027 | @echo ' Building modules, stage 2.'; | 1039 | @echo ' Building modules, stage 2.'; |
1028 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost | 1040 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost |
1029 | 1041 | ||
@@ -1051,6 +1063,7 @@ _modinst_: | |||
1051 | rm -f $(MODLIB)/build ; \ | 1063 | rm -f $(MODLIB)/build ; \ |
1052 | ln -s $(objtree) $(MODLIB)/build ; \ | 1064 | ln -s $(objtree) $(MODLIB)/build ; \ |
1053 | fi | 1065 | fi |
1066 | @cp -f $(objtree)/modules.order $(MODLIB)/ | ||
1054 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst | 1067 | $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst |
1055 | 1068 | ||
1056 | # This depmod is only for convenience to give the initial | 1069 | # This depmod is only for convenience to give the initial |
@@ -1110,7 +1123,7 @@ clean: archclean $(clean-dirs) | |||
1110 | @find . $(RCS_FIND_IGNORE) \ | 1123 | @find . $(RCS_FIND_IGNORE) \ |
1111 | \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ | 1124 | \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ |
1112 | -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ | 1125 | -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ |
1113 | -o -name '*.symtypes' \) \ | 1126 | -o -name '*.symtypes' -o -name 'modules.order' \) \ |
1114 | -type f -print | xargs rm -f | 1127 | -type f -print | xargs rm -f |
1115 | 1128 | ||
1116 | # mrproper - Delete all generated files, including .config | 1129 | # mrproper - Delete all generated files, including .config |
@@ -1175,7 +1188,7 @@ help: | |||
1175 | @echo ' dir/ - Build all files in dir and below' | 1188 | @echo ' dir/ - Build all files in dir and below' |
1176 | @echo ' dir/file.[ois] - Build specified target only' | 1189 | @echo ' dir/file.[ois] - Build specified target only' |
1177 | @echo ' dir/file.ko - Build module including final link' | 1190 | @echo ' dir/file.ko - Build module including final link' |
1178 | @echo ' rpm - Build a kernel as an RPM package' | 1191 | @echo ' prepare - Set up for building external modules' |
1179 | @echo ' tags/TAGS - Generate tags file for editors' | 1192 | @echo ' tags/TAGS - Generate tags file for editors' |
1180 | @echo ' cscope - Generate cscope index' | 1193 | @echo ' cscope - Generate cscope index' |
1181 | @echo ' kernelrelease - Output the release version string' | 1194 | @echo ' kernelrelease - Output the release version string' |
@@ -1188,6 +1201,8 @@ help: | |||
1188 | @echo 'Static analysers' | 1201 | @echo 'Static analysers' |
1189 | @echo ' checkstack - Generate a list of stack hogs' | 1202 | @echo ' checkstack - Generate a list of stack hogs' |
1190 | @echo ' namespacecheck - Name space analysis on compiled kernel' | 1203 | @echo ' namespacecheck - Name space analysis on compiled kernel' |
1204 | @echo ' versioncheck - Sanity check on version.h usage' | ||
1205 | @echo ' includecheck - Check for duplicate included header files' | ||
1191 | @echo ' export_report - List the usages of all exported symbols' | 1206 | @echo ' export_report - List the usages of all exported symbols' |
1192 | @if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \ | 1207 | @if [ -r $(srctree)/include/asm-$(SRCARCH)/Kbuild ]; then \ |
1193 | echo ' headers_check - Sanity check on exported headers'; \ | 1208 | echo ' headers_check - Sanity check on exported headers'; \ |
@@ -1371,6 +1386,7 @@ define xtags | |||
1371 | if $1 --version 2>&1 | grep -iq exuberant; then \ | 1386 | if $1 --version 2>&1 | grep -iq exuberant; then \ |
1372 | $(all-sources) | xargs $1 -a \ | 1387 | $(all-sources) | xargs $1 -a \ |
1373 | -I __initdata,__exitdata,__acquires,__releases \ | 1388 | -I __initdata,__exitdata,__acquires,__releases \ |
1389 | -I __read_mostly,____cacheline_aligned,____cacheline_aligned_in_smp,____cacheline_internodealigned_in_smp \ | ||
1374 | -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \ | 1390 | -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \ |
1375 | --extra=+f --c-kinds=+px \ | 1391 | --extra=+f --c-kinds=+px \ |
1376 | --regex-asm='/^ENTRY\(([^)]*)\).*/\1/'; \ | 1392 | --regex-asm='/^ENTRY\(([^)]*)\).*/\1/'; \ |
@@ -1428,12 +1444,12 @@ tags: FORCE | |||
1428 | includecheck: | 1444 | includecheck: |
1429 | find * $(RCS_FIND_IGNORE) \ | 1445 | find * $(RCS_FIND_IGNORE) \ |
1430 | -name '*.[hcS]' -type f -print | sort \ | 1446 | -name '*.[hcS]' -type f -print | sort \ |
1431 | | xargs $(PERL) -w scripts/checkincludes.pl | 1447 | | xargs $(PERL) -w $(srctree)/scripts/checkincludes.pl |
1432 | 1448 | ||
1433 | versioncheck: | 1449 | versioncheck: |
1434 | find * $(RCS_FIND_IGNORE) \ | 1450 | find * $(RCS_FIND_IGNORE) \ |
1435 | -name '*.[hcS]' -type f -print | sort \ | 1451 | -name '*.[hcS]' -type f -print | sort \ |
1436 | | xargs $(PERL) -w scripts/checkversion.pl | 1452 | | xargs $(PERL) -w $(srctree)/scripts/checkversion.pl |
1437 | 1453 | ||
1438 | namespacecheck: | 1454 | namespacecheck: |
1439 | $(PERL) $(srctree)/scripts/namespace.pl | 1455 | $(PERL) $(srctree)/scripts/namespace.pl |
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S index 55c05b511f4c..f13249be17c5 100644 --- a/arch/alpha/kernel/vmlinux.lds.S +++ b/arch/alpha/kernel/vmlinux.lds.S | |||
@@ -46,11 +46,11 @@ SECTIONS | |||
46 | __init_begin = .; | 46 | __init_begin = .; |
47 | .init.text : { | 47 | .init.text : { |
48 | _sinittext = .; | 48 | _sinittext = .; |
49 | *(.init.text) | 49 | INIT_TEXT |
50 | _einittext = .; | 50 | _einittext = .; |
51 | } | 51 | } |
52 | .init.data : { | 52 | .init.data : { |
53 | *(.init.data) | 53 | INIT_DATA |
54 | } | 54 | } |
55 | 55 | ||
56 | . = ALIGN(16); | 56 | . = ALIGN(16); |
@@ -136,8 +136,8 @@ SECTIONS | |||
136 | 136 | ||
137 | /* Sections to be discarded */ | 137 | /* Sections to be discarded */ |
138 | /DISCARD/ : { | 138 | /DISCARD/ : { |
139 | *(.exit.text) | 139 | EXIT_TEXT |
140 | *(.exit.data) | 140 | EXIT_DATA |
141 | *(.exitcall.exit) | 141 | *(.exitcall.exit) |
142 | } | 142 | } |
143 | 143 | ||
diff --git a/arch/alpha/lib/dec_and_lock.c b/arch/alpha/lib/dec_and_lock.c index 6ae2500a9d9e..0f5520d2f45f 100644 --- a/arch/alpha/lib/dec_and_lock.c +++ b/arch/alpha/lib/dec_and_lock.c | |||
@@ -30,8 +30,7 @@ _atomic_dec_and_lock: \n\ | |||
30 | .previous \n\ | 30 | .previous \n\ |
31 | .end _atomic_dec_and_lock"); | 31 | .end _atomic_dec_and_lock"); |
32 | 32 | ||
33 | static int __attribute_used__ | 33 | static int __used atomic_dec_and_lock_1(atomic_t *atomic, spinlock_t *lock) |
34 | atomic_dec_and_lock_1(atomic_t *atomic, spinlock_t *lock) | ||
35 | { | 34 | { |
36 | /* Slow path */ | 35 | /* Slow path */ |
37 | spin_lock(lock); | 36 | spin_lock(lock); |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index 30f732c7fdb5..4898bdcfe7dd 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -30,7 +30,7 @@ SECTIONS | |||
30 | } | 30 | } |
31 | 31 | ||
32 | .init : { /* Init code and data */ | 32 | .init : { /* Init code and data */ |
33 | *(.init.text) | 33 | INIT_TEXT |
34 | _einittext = .; | 34 | _einittext = .; |
35 | __proc_info_begin = .; | 35 | __proc_info_begin = .; |
36 | *(.proc.info.init) | 36 | *(.proc.info.init) |
@@ -70,15 +70,15 @@ SECTIONS | |||
70 | __per_cpu_end = .; | 70 | __per_cpu_end = .; |
71 | #ifndef CONFIG_XIP_KERNEL | 71 | #ifndef CONFIG_XIP_KERNEL |
72 | __init_begin = _stext; | 72 | __init_begin = _stext; |
73 | *(.init.data) | 73 | INIT_DATA |
74 | . = ALIGN(4096); | 74 | . = ALIGN(4096); |
75 | __init_end = .; | 75 | __init_end = .; |
76 | #endif | 76 | #endif |
77 | } | 77 | } |
78 | 78 | ||
79 | /DISCARD/ : { /* Exit code and data */ | 79 | /DISCARD/ : { /* Exit code and data */ |
80 | *(.exit.text) | 80 | EXIT_TEXT |
81 | *(.exit.data) | 81 | EXIT_DATA |
82 | *(.exitcall.exit) | 82 | *(.exitcall.exit) |
83 | #ifndef CONFIG_MMU | 83 | #ifndef CONFIG_MMU |
84 | *(.fixup) | 84 | *(.fixup) |
@@ -130,7 +130,7 @@ SECTIONS | |||
130 | #ifdef CONFIG_XIP_KERNEL | 130 | #ifdef CONFIG_XIP_KERNEL |
131 | . = ALIGN(4096); | 131 | . = ALIGN(4096); |
132 | __init_begin = .; | 132 | __init_begin = .; |
133 | *(.init.data) | 133 | INIT_DATA |
134 | . = ALIGN(4096); | 134 | . = ALIGN(4096); |
135 | __init_end = .; | 135 | __init_end = .; |
136 | #endif | 136 | #endif |
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 02272aa36e90..88d5e61a2e13 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile | |||
@@ -1,9 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
3 | # | 3 | # |
4 | # Note! Dependencies are done automagically by 'make dep', which also | ||
5 | # removes any old dependencies. DON'T put your own dependencies here | ||
6 | # unless it's something special (ie not a .c file). | ||
7 | 4 | ||
8 | # Object file lists. | 5 | # Object file lists. |
9 | 6 | ||
diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile index 18785ff37657..7ce4ba9eb242 100644 --- a/arch/arm/mach-netx/Makefile +++ b/arch/arm/mach-netx/Makefile | |||
@@ -1,9 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
3 | # | 3 | # |
4 | # Note! Dependencies are done automagically by 'make dep', which also | ||
5 | # removes any old dependencies. DON'T put your own dependencies here | ||
6 | # unless it's something special (ie not a .c file). | ||
7 | 4 | ||
8 | # Object file lists. | 5 | # Object file lists. |
9 | 6 | ||
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S index 11f08e35a2eb..481cfd40c053 100644 --- a/arch/avr32/kernel/vmlinux.lds.S +++ b/arch/avr32/kernel/vmlinux.lds.S | |||
@@ -27,19 +27,19 @@ SECTIONS | |||
27 | __init_begin = .; | 27 | __init_begin = .; |
28 | _sinittext = .; | 28 | _sinittext = .; |
29 | *(.text.reset) | 29 | *(.text.reset) |
30 | *(.init.text) | 30 | INIT_TEXT |
31 | /* | 31 | /* |
32 | * .exit.text is discarded at runtime, not | 32 | * .exit.text is discarded at runtime, not |
33 | * link time, to deal with references from | 33 | * link time, to deal with references from |
34 | * __bug_table | 34 | * __bug_table |
35 | */ | 35 | */ |
36 | *(.exit.text) | 36 | EXIT_TEXT |
37 | _einittext = .; | 37 | _einittext = .; |
38 | . = ALIGN(4); | 38 | . = ALIGN(4); |
39 | __tagtable_begin = .; | 39 | __tagtable_begin = .; |
40 | *(.taglist.init) | 40 | *(.taglist.init) |
41 | __tagtable_end = .; | 41 | __tagtable_end = .; |
42 | *(.init.data) | 42 | INIT_DATA |
43 | . = ALIGN(16); | 43 | . = ALIGN(16); |
44 | __setup_start = .; | 44 | __setup_start = .; |
45 | *(.init.setup) | 45 | *(.init.setup) |
@@ -135,7 +135,7 @@ SECTIONS | |||
135 | * thrown away, as cleanup code is never called unless it's a module. | 135 | * thrown away, as cleanup code is never called unless it's a module. |
136 | */ | 136 | */ |
137 | /DISCARD/ : { | 137 | /DISCARD/ : { |
138 | *(.exit.data) | 138 | EXIT_DATA |
139 | *(.exitcall.exit) | 139 | *(.exitcall.exit) |
140 | } | 140 | } |
141 | 141 | ||
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index 9b75bc83c71f..858722421b40 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S | |||
@@ -91,13 +91,13 @@ SECTIONS | |||
91 | { | 91 | { |
92 | . = ALIGN(PAGE_SIZE); | 92 | . = ALIGN(PAGE_SIZE); |
93 | __sinittext = .; | 93 | __sinittext = .; |
94 | *(.init.text) | 94 | INIT_TEXT |
95 | __einittext = .; | 95 | __einittext = .; |
96 | } | 96 | } |
97 | .init.data : | 97 | .init.data : |
98 | { | 98 | { |
99 | . = ALIGN(16); | 99 | . = ALIGN(16); |
100 | *(.init.data) | 100 | INIT_DATA |
101 | } | 101 | } |
102 | .init.setup : | 102 | .init.setup : |
103 | { | 103 | { |
@@ -198,8 +198,8 @@ SECTIONS | |||
198 | 198 | ||
199 | /DISCARD/ : | 199 | /DISCARD/ : |
200 | { | 200 | { |
201 | *(.exit.text) | 201 | EXIT_TEXT |
202 | *(.exit.data) | 202 | EXIT_DATA |
203 | *(.exitcall.exit) | 203 | *(.exitcall.exit) |
204 | } | 204 | } |
205 | } | 205 | } |
diff --git a/arch/cris/arch-v10/vmlinux.lds.S b/arch/cris/arch-v10/vmlinux.lds.S index 97a7876ed681..93c9f0ea286b 100644 --- a/arch/cris/arch-v10/vmlinux.lds.S +++ b/arch/cris/arch-v10/vmlinux.lds.S | |||
@@ -57,10 +57,10 @@ SECTIONS | |||
57 | __init_begin = .; | 57 | __init_begin = .; |
58 | .init.text : { | 58 | .init.text : { |
59 | _sinittext = .; | 59 | _sinittext = .; |
60 | *(.init.text) | 60 | INIT_TEXT |
61 | _einittext = .; | 61 | _einittext = .; |
62 | } | 62 | } |
63 | .init.data : { *(.init.data) } | 63 | .init.data : { INIT_DATA } |
64 | . = ALIGN(16); | 64 | . = ALIGN(16); |
65 | __setup_start = .; | 65 | __setup_start = .; |
66 | .init.setup : { *(.init.setup) } | 66 | .init.setup : { *(.init.setup) } |
@@ -109,8 +109,8 @@ SECTIONS | |||
109 | 109 | ||
110 | /* Sections to be discarded */ | 110 | /* Sections to be discarded */ |
111 | /DISCARD/ : { | 111 | /DISCARD/ : { |
112 | *(.text.exit) | 112 | EXIT_TEXT |
113 | *(.data.exit) | 113 | EXIT_DATA |
114 | *(.exitcall.exit) | 114 | *(.exitcall.exit) |
115 | } | 115 | } |
116 | 116 | ||
diff --git a/arch/cris/arch-v32/boot/compressed/Makefile b/arch/cris/arch-v32/boot/compressed/Makefile index 9f77eda914ba..609692f9d5eb 100644 --- a/arch/cris/arch-v32/boot/compressed/Makefile +++ b/arch/cris/arch-v32/boot/compressed/Makefile | |||
@@ -7,7 +7,7 @@ | |||
7 | target = $(target_compressed_dir) | 7 | target = $(target_compressed_dir) |
8 | src = $(src_compressed_dir) | 8 | src = $(src_compressed_dir) |
9 | 9 | ||
10 | CC = gcc-cris -mlinux -march=v32 -I $(TOPDIR)/include | 10 | CC = gcc-cris -mlinux -march=v32 $(LINUXINCLUDE) |
11 | CFLAGS = -O2 | 11 | CFLAGS = -O2 |
12 | LD = gcc-cris -mlinux -march=v32 -nostdlib | 12 | LD = gcc-cris -mlinux -march=v32 -nostdlib |
13 | OBJCOPY = objcopy-cris | 13 | OBJCOPY = objcopy-cris |
diff --git a/arch/cris/arch-v32/vmlinux.lds.S b/arch/cris/arch-v32/vmlinux.lds.S index b076c134c0bb..fead8c59ea63 100644 --- a/arch/cris/arch-v32/vmlinux.lds.S +++ b/arch/cris/arch-v32/vmlinux.lds.S | |||
@@ -61,10 +61,10 @@ SECTIONS | |||
61 | __init_begin = .; | 61 | __init_begin = .; |
62 | .init.text : { | 62 | .init.text : { |
63 | _sinittext = .; | 63 | _sinittext = .; |
64 | *(.init.text) | 64 | INIT_TEXT |
65 | _einittext = .; | 65 | _einittext = .; |
66 | } | 66 | } |
67 | .init.data : { *(.init.data) } | 67 | .init.data : { INIT_DATA } |
68 | . = ALIGN(16); | 68 | . = ALIGN(16); |
69 | __setup_start = .; | 69 | __setup_start = .; |
70 | .init.setup : { *(.init.setup) } | 70 | .init.setup : { *(.init.setup) } |
@@ -124,8 +124,8 @@ SECTIONS | |||
124 | 124 | ||
125 | /* Sections to be discarded */ | 125 | /* Sections to be discarded */ |
126 | /DISCARD/ : { | 126 | /DISCARD/ : { |
127 | *(.text.exit) | 127 | EXIT_TEXT |
128 | *(.data.exit) | 128 | EXIT_DATA |
129 | *(.exitcall.exit) | 129 | *(.exitcall.exit) |
130 | } | 130 | } |
131 | 131 | ||
diff --git a/arch/frv/boot/Makefile b/arch/frv/boot/Makefile index dc6f03824423..6ae3254da019 100644 --- a/arch/frv/boot/Makefile +++ b/arch/frv/boot/Makefile | |||
@@ -10,7 +10,7 @@ | |||
10 | 10 | ||
11 | targets := Image zImage bootpImage | 11 | targets := Image zImage bootpImage |
12 | 12 | ||
13 | SYSTEM =$(TOPDIR)/$(LINUX) | 13 | SYSTEM =$(LINUX) |
14 | 14 | ||
15 | ZTEXTADDR = 0x02080000 | 15 | ZTEXTADDR = 0x02080000 |
16 | PARAMS_PHYS = 0x0207c000 | 16 | PARAMS_PHYS = 0x0207c000 |
@@ -45,7 +45,7 @@ zImage: $(CONFIGURE) compressed/$(LINUX) | |||
45 | bootpImage: bootp/bootp | 45 | bootpImage: bootp/bootp |
46 | $(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@ | 46 | $(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@ |
47 | 47 | ||
48 | compressed/$(LINUX): $(TOPDIR)/$(LINUX) dep | 48 | compressed/$(LINUX): $(LINUX) dep |
49 | @$(MAKE) -C compressed $(LINUX) | 49 | @$(MAKE) -C compressed $(LINUX) |
50 | 50 | ||
51 | bootp/bootp: zImage initrd | 51 | bootp/bootp: zImage initrd |
@@ -59,10 +59,10 @@ initrd: | |||
59 | # installation | 59 | # installation |
60 | # | 60 | # |
61 | install: $(CONFIGURE) Image | 61 | install: $(CONFIGURE) Image |
62 | sh ./install.sh $(KERNELRELEASE) Image $(TOPDIR)/System.map "$(INSTALL_PATH)" | 62 | sh ./install.sh $(KERNELRELEASE) Image System.map "$(INSTALL_PATH)" |
63 | 63 | ||
64 | zinstall: $(CONFIGURE) zImage | 64 | zinstall: $(CONFIGURE) zImage |
65 | sh ./install.sh $(KERNELRELEASE) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)" | 65 | sh ./install.sh $(KERNELRELEASE) zImage System.map "$(INSTALL_PATH)" |
66 | 66 | ||
67 | # | 67 | # |
68 | # miscellany | 68 | # miscellany |
diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c index e89cad1192a9..48a0393e7cee 100644 --- a/arch/frv/kernel/gdb-stub.c +++ b/arch/frv/kernel/gdb-stub.c | |||
@@ -87,7 +87,7 @@ | |||
87 | * Example: | 87 | * Example: |
88 | * $ cd ~/linux | 88 | * $ cd ~/linux |
89 | * $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging> | 89 | * $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging> |
90 | * $ make dep; make vmlinux | 90 | * $ make vmlinux |
91 | * | 91 | * |
92 | * Step 3: | 92 | * Step 3: |
93 | * Download the kernel to the remote target and start | 93 | * Download the kernel to the remote target and start |
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S index a17a81d58bf6..f42b328b1dd0 100644 --- a/arch/frv/kernel/vmlinux.lds.S +++ b/arch/frv/kernel/vmlinux.lds.S | |||
@@ -28,14 +28,14 @@ SECTIONS | |||
28 | .init.text : { | 28 | .init.text : { |
29 | *(.text.head) | 29 | *(.text.head) |
30 | #ifndef CONFIG_DEBUG_INFO | 30 | #ifndef CONFIG_DEBUG_INFO |
31 | *(.init.text) | 31 | INIT_TEXT |
32 | *(.exit.text) | 32 | EXIT_TEXT |
33 | *(.exit.data) | 33 | EXIT_DATA |
34 | *(.exitcall.exit) | 34 | *(.exitcall.exit) |
35 | #endif | 35 | #endif |
36 | } | 36 | } |
37 | _einittext = .; | 37 | _einittext = .; |
38 | .init.data : { *(.init.data) } | 38 | .init.data : { INIT_DATA } |
39 | 39 | ||
40 | . = ALIGN(8); | 40 | . = ALIGN(8); |
41 | __setup_start = .; | 41 | __setup_start = .; |
@@ -106,8 +106,8 @@ SECTIONS | |||
106 | LOCK_TEXT | 106 | LOCK_TEXT |
107 | #ifdef CONFIG_DEBUG_INFO | 107 | #ifdef CONFIG_DEBUG_INFO |
108 | *( | 108 | *( |
109 | .init.text | 109 | INIT_TEXT |
110 | .exit.text | 110 | EXIT_TEXT |
111 | .exitcall.exit | 111 | .exitcall.exit |
112 | ) | 112 | ) |
113 | #endif | 113 | #endif |
@@ -138,7 +138,7 @@ SECTIONS | |||
138 | .data : { /* Data */ | 138 | .data : { /* Data */ |
139 | DATA_DATA | 139 | DATA_DATA |
140 | *(.data.*) | 140 | *(.data.*) |
141 | *(.exit.data) | 141 | EXIT_DATA |
142 | CONSTRUCTORS | 142 | CONSTRUCTORS |
143 | } | 143 | } |
144 | 144 | ||
diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S index a2e72d495551..43a87b9085b6 100644 --- a/arch/h8300/kernel/vmlinux.lds.S +++ b/arch/h8300/kernel/vmlinux.lds.S | |||
@@ -110,9 +110,9 @@ SECTIONS | |||
110 | . = ALIGN(0x4) ; | 110 | . = ALIGN(0x4) ; |
111 | ___init_begin = .; | 111 | ___init_begin = .; |
112 | __sinittext = .; | 112 | __sinittext = .; |
113 | *(.init.text) | 113 | INIT_TEXT |
114 | __einittext = .; | 114 | __einittext = .; |
115 | *(.init.data) | 115 | INIT_DATA |
116 | . = ALIGN(0x4) ; | 116 | . = ALIGN(0x4) ; |
117 | ___setup_start = .; | 117 | ___setup_start = .; |
118 | *(.init.setup) | 118 | *(.init.setup) |
@@ -124,8 +124,8 @@ SECTIONS | |||
124 | ___con_initcall_start = .; | 124 | ___con_initcall_start = .; |
125 | *(.con_initcall.init) | 125 | *(.con_initcall.init) |
126 | ___con_initcall_end = .; | 126 | ___con_initcall_end = .; |
127 | *(.exit.text) | 127 | EXIT_TEXT |
128 | *(.exit.data) | 128 | EXIT_DATA |
129 | #if defined(CONFIG_BLK_DEV_INITRD) | 129 | #if defined(CONFIG_BLK_DEV_INITRD) |
130 | . = ALIGN(4); | 130 | . = ALIGN(4); |
131 | ___initramfs_start = .; | 131 | ___initramfs_start = .; |
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index 757e419ebcf8..80622acc95de 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S | |||
@@ -27,8 +27,8 @@ SECTIONS | |||
27 | { | 27 | { |
28 | /* Sections to be discarded */ | 28 | /* Sections to be discarded */ |
29 | /DISCARD/ : { | 29 | /DISCARD/ : { |
30 | *(.exit.text) | 30 | EXIT_TEXT |
31 | *(.exit.data) | 31 | EXIT_DATA |
32 | *(.exitcall.exit) | 32 | *(.exitcall.exit) |
33 | *(.IA_64.unwind.exit.text) | 33 | *(.IA_64.unwind.exit.text) |
34 | *(.IA_64.unwind_info.exit.text) | 34 | *(.IA_64.unwind_info.exit.text) |
@@ -119,12 +119,12 @@ SECTIONS | |||
119 | .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) | 119 | .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) |
120 | { | 120 | { |
121 | _sinittext = .; | 121 | _sinittext = .; |
122 | *(.init.text) | 122 | INIT_TEXT |
123 | _einittext = .; | 123 | _einittext = .; |
124 | } | 124 | } |
125 | 125 | ||
126 | .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) | 126 | .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) |
127 | { *(.init.data) } | 127 | { INIT_DATA } |
128 | 128 | ||
129 | #ifdef CONFIG_BLK_DEV_INITRD | 129 | #ifdef CONFIG_BLK_DEV_INITRD |
130 | .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) | 130 | .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) |
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S index 942a8c7a4417..41b07854fcc6 100644 --- a/arch/m32r/kernel/vmlinux.lds.S +++ b/arch/m32r/kernel/vmlinux.lds.S | |||
@@ -76,10 +76,10 @@ SECTIONS | |||
76 | __init_begin = .; | 76 | __init_begin = .; |
77 | .init.text : { | 77 | .init.text : { |
78 | _sinittext = .; | 78 | _sinittext = .; |
79 | *(.init.text) | 79 | INIT_TEXT |
80 | _einittext = .; | 80 | _einittext = .; |
81 | } | 81 | } |
82 | .init.data : { *(.init.data) } | 82 | .init.data : { INIT_DATA } |
83 | . = ALIGN(16); | 83 | . = ALIGN(16); |
84 | __setup_start = .; | 84 | __setup_start = .; |
85 | .init.setup : { *(.init.setup) } | 85 | .init.setup : { *(.init.setup) } |
@@ -100,8 +100,8 @@ SECTIONS | |||
100 | .altinstr_replacement : { *(.altinstr_replacement) } | 100 | .altinstr_replacement : { *(.altinstr_replacement) } |
101 | /* .exit.text is discard at runtime, not link time, to deal with references | 101 | /* .exit.text is discard at runtime, not link time, to deal with references |
102 | from .altinstructions and .eh_frame */ | 102 | from .altinstructions and .eh_frame */ |
103 | .exit.text : { *(.exit.text) } | 103 | .exit.text : { EXIT_TEXT } |
104 | .exit.data : { *(.exit.data) } | 104 | .exit.data : { EXIT_DATA } |
105 | 105 | ||
106 | #ifdef CONFIG_BLK_DEV_INITRD | 106 | #ifdef CONFIG_BLK_DEV_INITRD |
107 | . = ALIGN(4096); | 107 | . = ALIGN(4096); |
@@ -124,8 +124,8 @@ SECTIONS | |||
124 | 124 | ||
125 | /* Sections to be discarded */ | 125 | /* Sections to be discarded */ |
126 | /DISCARD/ : { | 126 | /DISCARD/ : { |
127 | *(.exit.text) | 127 | EXIT_TEXT |
128 | *(.exit.data) | 128 | EXIT_DATA |
129 | *(.exitcall.exit) | 129 | *(.exitcall.exit) |
130 | } | 130 | } |
131 | 131 | ||
diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds index 59fe285865ec..7537cc5e6159 100644 --- a/arch/m68k/kernel/vmlinux-std.lds +++ b/arch/m68k/kernel/vmlinux-std.lds | |||
@@ -45,10 +45,10 @@ SECTIONS | |||
45 | __init_begin = .; | 45 | __init_begin = .; |
46 | .init.text : { | 46 | .init.text : { |
47 | _sinittext = .; | 47 | _sinittext = .; |
48 | *(.init.text) | 48 | INIT_TEXT |
49 | _einittext = .; | 49 | _einittext = .; |
50 | } | 50 | } |
51 | .init.data : { *(.init.data) } | 51 | .init.data : { INIT_DATA } |
52 | . = ALIGN(16); | 52 | . = ALIGN(16); |
53 | __setup_start = .; | 53 | __setup_start = .; |
54 | .init.setup : { *(.init.setup) } | 54 | .init.setup : { *(.init.setup) } |
@@ -82,8 +82,8 @@ SECTIONS | |||
82 | 82 | ||
83 | /* Sections to be discarded */ | 83 | /* Sections to be discarded */ |
84 | /DISCARD/ : { | 84 | /DISCARD/ : { |
85 | *(.exit.text) | 85 | EXIT_TEXT |
86 | *(.exit.data) | 86 | EXIT_DATA |
87 | *(.exitcall.exit) | 87 | *(.exitcall.exit) |
88 | } | 88 | } |
89 | 89 | ||
diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds index 4adffefb5c48..cdc313e7c299 100644 --- a/arch/m68k/kernel/vmlinux-sun3.lds +++ b/arch/m68k/kernel/vmlinux-sun3.lds | |||
@@ -38,10 +38,10 @@ SECTIONS | |||
38 | __init_begin = .; | 38 | __init_begin = .; |
39 | .init.text : { | 39 | .init.text : { |
40 | _sinittext = .; | 40 | _sinittext = .; |
41 | *(.init.text) | 41 | INIT_TEXT |
42 | _einittext = .; | 42 | _einittext = .; |
43 | } | 43 | } |
44 | .init.data : { *(.init.data) } | 44 | .init.data : { INIT_DATA } |
45 | . = ALIGN(16); | 45 | . = ALIGN(16); |
46 | __setup_start = .; | 46 | __setup_start = .; |
47 | .init.setup : { *(.init.setup) } | 47 | .init.setup : { *(.init.setup) } |
@@ -77,8 +77,8 @@ __init_begin = .; | |||
77 | 77 | ||
78 | /* Sections to be discarded */ | 78 | /* Sections to be discarded */ |
79 | /DISCARD/ : { | 79 | /DISCARD/ : { |
80 | *(.exit.text) | 80 | EXIT_TEXT |
81 | *(.exit.data) | 81 | EXIT_DATA |
82 | *(.exitcall.exit) | 82 | *(.exitcall.exit) |
83 | } | 83 | } |
84 | 84 | ||
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S index 07a0055602f4..b44edb08e212 100644 --- a/arch/m68knommu/kernel/vmlinux.lds.S +++ b/arch/m68knommu/kernel/vmlinux.lds.S | |||
@@ -143,9 +143,9 @@ SECTIONS { | |||
143 | . = ALIGN(4096); | 143 | . = ALIGN(4096); |
144 | __init_begin = .; | 144 | __init_begin = .; |
145 | _sinittext = .; | 145 | _sinittext = .; |
146 | *(.init.text) | 146 | INIT_TEXT |
147 | _einittext = .; | 147 | _einittext = .; |
148 | *(.init.data) | 148 | INIT_DATA |
149 | . = ALIGN(16); | 149 | . = ALIGN(16); |
150 | __setup_start = .; | 150 | __setup_start = .; |
151 | *(.init.setup) | 151 | *(.init.setup) |
@@ -170,8 +170,8 @@ SECTIONS { | |||
170 | } > INIT | 170 | } > INIT |
171 | 171 | ||
172 | /DISCARD/ : { | 172 | /DISCARD/ : { |
173 | *(.exit.text) | 173 | EXIT_TEXT |
174 | *(.exit.data) | 174 | EXIT_DATA |
175 | *(.exitcall.exit) | 175 | *(.exitcall.exit) |
176 | } | 176 | } |
177 | 177 | ||
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index b22c043b6ef8..6b0f85f02c79 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -37,16 +37,6 @@ config BASLER_EXCITE | |||
37 | The eXcite is a smart camera platform manufactured by | 37 | The eXcite is a smart camera platform manufactured by |
38 | Basler Vision Technologies AG. | 38 | Basler Vision Technologies AG. |
39 | 39 | ||
40 | config BASLER_EXCITE_PROTOTYPE | ||
41 | bool "Support for pre-release units" | ||
42 | depends on BASLER_EXCITE | ||
43 | default n | ||
44 | help | ||
45 | Pre-series (prototype) units are different from later ones in | ||
46 | some ways. Select this option if you have one of these. Please | ||
47 | note that a kernel built with this option selected will not be | ||
48 | able to run on normal units. | ||
49 | |||
50 | config BCM47XX | 40 | config BCM47XX |
51 | bool "BCM47XX based boards" | 41 | bool "BCM47XX based boards" |
52 | select CEVT_R4K | 42 | select CEVT_R4K |
@@ -82,7 +72,7 @@ config MIPS_COBALT | |||
82 | select SYS_HAS_CPU_NEVADA | 72 | select SYS_HAS_CPU_NEVADA |
83 | select SYS_HAS_EARLY_PRINTK | 73 | select SYS_HAS_EARLY_PRINTK |
84 | select SYS_SUPPORTS_32BIT_KERNEL | 74 | select SYS_SUPPORTS_32BIT_KERNEL |
85 | select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL | 75 | select SYS_SUPPORTS_64BIT_KERNEL |
86 | select SYS_SUPPORTS_LITTLE_ENDIAN | 76 | select SYS_SUPPORTS_LITTLE_ENDIAN |
87 | select GENERIC_HARDIRQS_NO__DO_IRQ | 77 | select GENERIC_HARDIRQS_NO__DO_IRQ |
88 | 78 | ||
@@ -91,6 +81,9 @@ config MACH_DECSTATION | |||
91 | select BOOT_ELF32 | 81 | select BOOT_ELF32 |
92 | select CEVT_R4K | 82 | select CEVT_R4K |
93 | select CSRC_R4K | 83 | select CSRC_R4K |
84 | select CPU_DADDI_WORKAROUNDS if 64BIT | ||
85 | select CPU_R4000_WORKAROUNDS if 64BIT | ||
86 | select CPU_R4400_WORKAROUNDS if 64BIT | ||
94 | select DMA_NONCOHERENT | 87 | select DMA_NONCOHERENT |
95 | select NO_IOPORT | 88 | select NO_IOPORT |
96 | select IRQ_CPU | 89 | select IRQ_CPU |
@@ -124,12 +117,12 @@ config MACH_JAZZ | |||
124 | select ARCH_MAY_HAVE_PC_FDC | 117 | select ARCH_MAY_HAVE_PC_FDC |
125 | select CEVT_R4K | 118 | select CEVT_R4K |
126 | select CSRC_R4K | 119 | select CSRC_R4K |
120 | select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN | ||
127 | select GENERIC_ISA_DMA | 121 | select GENERIC_ISA_DMA |
128 | select IRQ_CPU | 122 | select IRQ_CPU |
129 | select I8253 | 123 | select I8253 |
130 | select I8259 | 124 | select I8259 |
131 | select ISA | 125 | select ISA |
132 | select PCSPEAKER | ||
133 | select SYS_HAS_CPU_R4X00 | 126 | select SYS_HAS_CPU_R4X00 |
134 | select SYS_SUPPORTS_32BIT_KERNEL | 127 | select SYS_SUPPORTS_32BIT_KERNEL |
135 | select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL | 128 | select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL |
@@ -187,6 +180,7 @@ config LEMOTE_FULONG | |||
187 | config MIPS_ATLAS | 180 | config MIPS_ATLAS |
188 | bool "MIPS Atlas board" | 181 | bool "MIPS Atlas board" |
189 | select BOOT_ELF32 | 182 | select BOOT_ELF32 |
183 | select BOOT_RAW | ||
190 | select CEVT_R4K | 184 | select CEVT_R4K |
191 | select CSRC_R4K | 185 | select CSRC_R4K |
192 | select DMA_NONCOHERENT | 186 | select DMA_NONCOHERENT |
@@ -219,6 +213,7 @@ config MIPS_MALTA | |||
219 | bool "MIPS Malta board" | 213 | bool "MIPS Malta board" |
220 | select ARCH_MAY_HAVE_PC_FDC | 214 | select ARCH_MAY_HAVE_PC_FDC |
221 | select BOOT_ELF32 | 215 | select BOOT_ELF32 |
216 | select BOOT_RAW | ||
222 | select CEVT_R4K | 217 | select CEVT_R4K |
223 | select CSRC_R4K | 218 | select CSRC_R4K |
224 | select DMA_NONCOHERENT | 219 | select DMA_NONCOHERENT |
@@ -364,35 +359,6 @@ config PMC_YOSEMITE | |||
364 | Yosemite is an evaluation board for the RM9000x2 processor | 359 | Yosemite is an evaluation board for the RM9000x2 processor |
365 | manufactured by PMC-Sierra. | 360 | manufactured by PMC-Sierra. |
366 | 361 | ||
367 | config QEMU | ||
368 | bool "Qemu" | ||
369 | select CEVT_R4K | ||
370 | select CSRC_R4K | ||
371 | select DMA_COHERENT | ||
372 | select GENERIC_ISA_DMA | ||
373 | select HAVE_STD_PC_SERIAL_PORT | ||
374 | select I8253 | ||
375 | select I8259 | ||
376 | select IRQ_CPU | ||
377 | select ISA | ||
378 | select PCSPEAKER | ||
379 | select SWAP_IO_SPACE | ||
380 | select SYS_HAS_CPU_MIPS32_R1 | ||
381 | select SYS_HAS_EARLY_PRINTK | ||
382 | select SYS_SUPPORTS_32BIT_KERNEL | ||
383 | select SYS_SUPPORTS_BIG_ENDIAN | ||
384 | select SYS_SUPPORTS_LITTLE_ENDIAN | ||
385 | select GENERIC_HARDIRQS_NO__DO_IRQ | ||
386 | select NR_CPUS_DEFAULT_1 | ||
387 | select SYS_SUPPORTS_SMP | ||
388 | help | ||
389 | Qemu is a software emulator which among other architectures also | ||
390 | can simulate a MIPS32 4Kc system. This patch adds support for the | ||
391 | system architecture that currently is being simulated by Qemu. It | ||
392 | will eventually be removed again when Qemu has the capability to | ||
393 | simulate actual MIPS hardware platforms. More information on Qemu | ||
394 | can be found at http://www.linux-mips.org/wiki/Qemu. | ||
395 | |||
396 | config SGI_IP22 | 362 | config SGI_IP22 |
397 | bool "SGI IP22 (Indy/Indigo2)" | 363 | bool "SGI IP22 (Indy/Indigo2)" |
398 | select ARC | 364 | select ARC |
@@ -400,6 +366,7 @@ config SGI_IP22 | |||
400 | select BOOT_ELF32 | 366 | select BOOT_ELF32 |
401 | select CEVT_R4K | 367 | select CEVT_R4K |
402 | select CSRC_R4K | 368 | select CSRC_R4K |
369 | select DEFAULT_SGI_PARTITION | ||
403 | select DMA_NONCOHERENT | 370 | select DMA_NONCOHERENT |
404 | select HW_HAS_EISA | 371 | select HW_HAS_EISA |
405 | select I8253 | 372 | select I8253 |
@@ -407,6 +374,12 @@ config SGI_IP22 | |||
407 | select IP22_CPU_SCACHE | 374 | select IP22_CPU_SCACHE |
408 | select IRQ_CPU | 375 | select IRQ_CPU |
409 | select GENERIC_ISA_DMA_SUPPORT_BROKEN | 376 | select GENERIC_ISA_DMA_SUPPORT_BROKEN |
377 | select SGI_HAS_DS1286 | ||
378 | select SGI_HAS_I8042 | ||
379 | select SGI_HAS_INDYDOG | ||
380 | select SGI_HAS_SEEQ | ||
381 | select SGI_HAS_WD93 | ||
382 | select SGI_HAS_ZILOG | ||
410 | select SWAP_IO_SPACE | 383 | select SWAP_IO_SPACE |
411 | select SYS_HAS_CPU_R4X00 | 384 | select SYS_HAS_CPU_R4X00 |
412 | select SYS_HAS_CPU_R5000 | 385 | select SYS_HAS_CPU_R5000 |
@@ -424,6 +397,7 @@ config SGI_IP27 | |||
424 | select ARC | 397 | select ARC |
425 | select ARC64 | 398 | select ARC64 |
426 | select BOOT_ELF64 | 399 | select BOOT_ELF64 |
400 | select DEFAULT_SGI_PARTITION | ||
427 | select DMA_IP27 | 401 | select DMA_IP27 |
428 | select SYS_HAS_EARLY_PRINTK | 402 | select SYS_HAS_EARLY_PRINTK |
429 | select HW_HAS_PCI | 403 | select HW_HAS_PCI |
@@ -440,6 +414,36 @@ config SGI_IP27 | |||
440 | workstations. To compile a Linux kernel that runs on these, say Y | 414 | workstations. To compile a Linux kernel that runs on these, say Y |
441 | here. | 415 | here. |
442 | 416 | ||
417 | config SGI_IP28 | ||
418 | bool "SGI IP28 (Indigo2 R10k) (EXPERIMENTAL)" | ||
419 | depends on EXPERIMENTAL | ||
420 | select ARC | ||
421 | select ARC64 | ||
422 | select BOOT_ELF64 | ||
423 | select CEVT_R4K | ||
424 | select CSRC_R4K | ||
425 | select DEFAULT_SGI_PARTITION | ||
426 | select DMA_NONCOHERENT | ||
427 | select GENERIC_ISA_DMA_SUPPORT_BROKEN | ||
428 | select IRQ_CPU | ||
429 | select HW_HAS_EISA | ||
430 | select I8253 | ||
431 | select I8259 | ||
432 | select SGI_HAS_DS1286 | ||
433 | select SGI_HAS_I8042 | ||
434 | select SGI_HAS_INDYDOG | ||
435 | select SGI_HAS_SEEQ | ||
436 | select SGI_HAS_WD93 | ||
437 | select SGI_HAS_ZILOG | ||
438 | select SWAP_IO_SPACE | ||
439 | select SYS_HAS_CPU_R10000 | ||
440 | select SYS_HAS_EARLY_PRINTK | ||
441 | select SYS_SUPPORTS_64BIT_KERNEL | ||
442 | select SYS_SUPPORTS_BIG_ENDIAN | ||
443 | help | ||
444 | This is the SGI Indigo2 with R10000 processor. To compile a Linux | ||
445 | kernel that runs on these, say Y here. | ||
446 | |||
443 | config SGI_IP32 | 447 | config SGI_IP32 |
444 | bool "SGI IP32 (O2)" | 448 | bool "SGI IP32 (O2)" |
445 | select ARC | 449 | select ARC |
@@ -545,19 +549,6 @@ config SIBYTE_SENTOSA | |||
545 | select SYS_SUPPORTS_BIG_ENDIAN | 549 | select SYS_SUPPORTS_BIG_ENDIAN |
546 | select SYS_SUPPORTS_LITTLE_ENDIAN | 550 | select SYS_SUPPORTS_LITTLE_ENDIAN |
547 | 551 | ||
548 | config SIBYTE_PTSWARM | ||
549 | bool "Sibyte BCM91250PT-PTSWARM" | ||
550 | depends on EXPERIMENTAL | ||
551 | select BOOT_ELF32 | ||
552 | select DMA_COHERENT | ||
553 | select NR_CPUS_DEFAULT_2 | ||
554 | select SIBYTE_SB1250 | ||
555 | select SWAP_IO_SPACE | ||
556 | select SYS_HAS_CPU_SB1 | ||
557 | select SYS_SUPPORTS_BIG_ENDIAN | ||
558 | select SYS_SUPPORTS_HIGHMEM | ||
559 | select SYS_SUPPORTS_LITTLE_ENDIAN | ||
560 | |||
561 | config SIBYTE_BIGSUR | 552 | config SIBYTE_BIGSUR |
562 | bool "Sibyte BCM91480B-BigSur" | 553 | bool "Sibyte BCM91480B-BigSur" |
563 | select BOOT_ELF32 | 554 | select BOOT_ELF32 |
@@ -575,10 +566,12 @@ config SNI_RM | |||
575 | bool "SNI RM200/300/400" | 566 | bool "SNI RM200/300/400" |
576 | select ARC if CPU_LITTLE_ENDIAN | 567 | select ARC if CPU_LITTLE_ENDIAN |
577 | select ARC32 if CPU_LITTLE_ENDIAN | 568 | select ARC32 if CPU_LITTLE_ENDIAN |
569 | select SNIPROM if CPU_BIG_ENDIAN | ||
578 | select ARCH_MAY_HAVE_PC_FDC | 570 | select ARCH_MAY_HAVE_PC_FDC |
579 | select BOOT_ELF32 | 571 | select BOOT_ELF32 |
580 | select CEVT_R4K | 572 | select CEVT_R4K |
581 | select CSRC_R4K | 573 | select CSRC_R4K |
574 | select DEFAULT_SGI_PARTITION if CPU_BIG_ENDIAN | ||
582 | select DMA_NONCOHERENT | 575 | select DMA_NONCOHERENT |
583 | select GENERIC_ISA_DMA | 576 | select GENERIC_ISA_DMA |
584 | select HW_HAS_EISA | 577 | select HW_HAS_EISA |
@@ -587,7 +580,6 @@ config SNI_RM | |||
587 | select I8253 | 580 | select I8253 |
588 | select I8259 | 581 | select I8259 |
589 | select ISA | 582 | select ISA |
590 | select PCSPEAKER | ||
591 | select SWAP_IO_SPACE if CPU_BIG_ENDIAN | 583 | select SWAP_IO_SPACE if CPU_BIG_ENDIAN |
592 | select SYS_HAS_CPU_R4X00 | 584 | select SYS_HAS_CPU_R4X00 |
593 | select SYS_HAS_CPU_R5000 | 585 | select SYS_HAS_CPU_R5000 |
@@ -690,6 +682,7 @@ config WR_PPMC | |||
690 | endchoice | 682 | endchoice |
691 | 683 | ||
692 | source "arch/mips/au1000/Kconfig" | 684 | source "arch/mips/au1000/Kconfig" |
685 | source "arch/mips/basler/excite/Kconfig" | ||
693 | source "arch/mips/jazz/Kconfig" | 686 | source "arch/mips/jazz/Kconfig" |
694 | source "arch/mips/lasat/Kconfig" | 687 | source "arch/mips/lasat/Kconfig" |
695 | source "arch/mips/pmc-sierra/Kconfig" | 688 | source "arch/mips/pmc-sierra/Kconfig" |
@@ -797,10 +790,6 @@ config DMA_COHERENT | |||
797 | config DMA_IP27 | 790 | config DMA_IP27 |
798 | bool | 791 | bool |
799 | 792 | ||
800 | config DMA_IP32 | ||
801 | bool | ||
802 | select DMA_NEED_PCI_MAP_STATE | ||
803 | |||
804 | config DMA_NONCOHERENT | 793 | config DMA_NONCOHERENT |
805 | bool | 794 | bool |
806 | select DMA_NEED_PCI_MAP_STATE | 795 | select DMA_NEED_PCI_MAP_STATE |
@@ -956,16 +945,40 @@ config EMMA2RH | |||
956 | config SERIAL_RM9000 | 945 | config SERIAL_RM9000 |
957 | bool | 946 | bool |
958 | 947 | ||
948 | config SGI_HAS_DS1286 | ||
949 | bool | ||
950 | |||
951 | config SGI_HAS_INDYDOG | ||
952 | bool | ||
953 | |||
954 | config SGI_HAS_SEEQ | ||
955 | bool | ||
956 | |||
957 | config SGI_HAS_WD93 | ||
958 | bool | ||
959 | |||
960 | config SGI_HAS_ZILOG | ||
961 | bool | ||
962 | |||
963 | config SGI_HAS_I8042 | ||
964 | bool | ||
965 | |||
966 | config DEFAULT_SGI_PARTITION | ||
967 | bool | ||
968 | |||
959 | config ARC32 | 969 | config ARC32 |
960 | bool | 970 | bool |
961 | 971 | ||
972 | config SNIPROM | ||
973 | bool | ||
974 | |||
962 | config BOOT_ELF32 | 975 | config BOOT_ELF32 |
963 | bool | 976 | bool |
964 | 977 | ||
965 | config MIPS_L1_CACHE_SHIFT | 978 | config MIPS_L1_CACHE_SHIFT |
966 | int | 979 | int |
967 | default "4" if MACH_DECSTATION | 980 | default "4" if MACH_DECSTATION |
968 | default "7" if SGI_IP27 || SNI_RM | 981 | default "7" if SGI_IP27 || SGI_IP28 || SNI_RM |
969 | default "4" if PMC_MSP4200_EVAL | 982 | default "4" if PMC_MSP4200_EVAL |
970 | default "5" | 983 | default "5" |
971 | 984 | ||
@@ -974,7 +987,7 @@ config HAVE_STD_PC_SERIAL_PORT | |||
974 | 987 | ||
975 | config ARC_CONSOLE | 988 | config ARC_CONSOLE |
976 | bool "ARC console support" | 989 | bool "ARC console support" |
977 | depends on SGI_IP22 || (SNI_RM && CPU_LITTLE_ENDIAN) | 990 | depends on SGI_IP22 || SGI_IP28 || (SNI_RM && CPU_LITTLE_ENDIAN) |
978 | 991 | ||
979 | config ARC_MEMORY | 992 | config ARC_MEMORY |
980 | bool | 993 | bool |
@@ -983,7 +996,7 @@ config ARC_MEMORY | |||
983 | 996 | ||
984 | config ARC_PROMLIB | 997 | config ARC_PROMLIB |
985 | bool | 998 | bool |
986 | depends on MACH_JAZZ || SNI_RM || SGI_IP22 || SGI_IP32 | 999 | depends on MACH_JAZZ || SNI_RM || SGI_IP22 || SGI_IP28 || SGI_IP32 |
987 | default y | 1000 | default y |
988 | 1001 | ||
989 | config ARC64 | 1002 | config ARC64 |
@@ -1443,7 +1456,9 @@ config MIPS_MT_SMP | |||
1443 | select MIPS_MT | 1456 | select MIPS_MT |
1444 | select NR_CPUS_DEFAULT_2 | 1457 | select NR_CPUS_DEFAULT_2 |
1445 | select SMP | 1458 | select SMP |
1459 | select SYS_SUPPORTS_SCHED_SMT if SMP | ||
1446 | select SYS_SUPPORTS_SMP | 1460 | select SYS_SUPPORTS_SMP |
1461 | select SMP_UP | ||
1447 | help | 1462 | help |
1448 | This is a kernel model which is also known a VSMP or lately | 1463 | This is a kernel model which is also known a VSMP or lately |
1449 | has been marketesed into SMVP. | 1464 | has been marketesed into SMVP. |
@@ -1460,6 +1475,7 @@ config MIPS_MT_SMTC | |||
1460 | select NR_CPUS_DEFAULT_8 | 1475 | select NR_CPUS_DEFAULT_8 |
1461 | select SMP | 1476 | select SMP |
1462 | select SYS_SUPPORTS_SMP | 1477 | select SYS_SUPPORTS_SMP |
1478 | select SMP_UP | ||
1463 | help | 1479 | help |
1464 | This is a kernel model which is known a SMTC or lately has been | 1480 | This is a kernel model which is known a SMTC or lately has been |
1465 | marketesed into SMVP. | 1481 | marketesed into SMVP. |
@@ -1469,6 +1485,19 @@ endchoice | |||
1469 | config MIPS_MT | 1485 | config MIPS_MT |
1470 | bool | 1486 | bool |
1471 | 1487 | ||
1488 | config SCHED_SMT | ||
1489 | bool "SMT (multithreading) scheduler support" | ||
1490 | depends on SYS_SUPPORTS_SCHED_SMT | ||
1491 | default n | ||
1492 | help | ||
1493 | SMT scheduler support improves the CPU scheduler's decision making | ||
1494 | when dealing with MIPS MT enabled cores at a cost of slightly | ||
1495 | increased overhead in some places. If unsure say N here. | ||
1496 | |||
1497 | config SYS_SUPPORTS_SCHED_SMT | ||
1498 | bool | ||
1499 | |||
1500 | |||
1472 | config SYS_SUPPORTS_MULTITHREADING | 1501 | config SYS_SUPPORTS_MULTITHREADING |
1473 | bool | 1502 | bool |
1474 | 1503 | ||
@@ -1589,15 +1618,6 @@ config CPU_HAS_SMARTMIPS | |||
1589 | config CPU_HAS_WB | 1618 | config CPU_HAS_WB |
1590 | bool | 1619 | bool |
1591 | 1620 | ||
1592 | config 64BIT_CONTEXT | ||
1593 | bool "Save 64bit integer registers" | ||
1594 | depends on 32BIT && CPU_LOONGSON2 | ||
1595 | help | ||
1596 | Loongson2 CPU is 64bit , when used in 32BIT mode, its integer | ||
1597 | registers can still be accessed as 64bit, mainly for multimedia | ||
1598 | instructions. We must have all 64bit save/restored to make sure | ||
1599 | those instructions to get correct result. | ||
1600 | |||
1601 | # | 1621 | # |
1602 | # Vectored interrupt mode is an R2 feature | 1622 | # Vectored interrupt mode is an R2 feature |
1603 | # | 1623 | # |
@@ -1619,6 +1639,19 @@ config GENERIC_CLOCKEVENTS_BROADCAST | |||
1619 | bool | 1639 | bool |
1620 | 1640 | ||
1621 | # | 1641 | # |
1642 | # CPU non-features | ||
1643 | # | ||
1644 | config CPU_DADDI_WORKAROUNDS | ||
1645 | bool | ||
1646 | |||
1647 | config CPU_R4000_WORKAROUNDS | ||
1648 | bool | ||
1649 | select CPU_R4400_WORKAROUNDS | ||
1650 | |||
1651 | config CPU_R4400_WORKAROUNDS | ||
1652 | bool | ||
1653 | |||
1654 | # | ||
1622 | # Use the generic interrupt handling code in kernel/irq/: | 1655 | # Use the generic interrupt handling code in kernel/irq/: |
1623 | # | 1656 | # |
1624 | config GENERIC_HARDIRQS | 1657 | config GENERIC_HARDIRQS |
@@ -1721,6 +1754,9 @@ config SMP | |||
1721 | 1754 | ||
1722 | If you don't know what to do here, say N. | 1755 | If you don't know what to do here, say N. |
1723 | 1756 | ||
1757 | config SMP_UP | ||
1758 | bool | ||
1759 | |||
1724 | config SYS_SUPPORTS_SMP | 1760 | config SYS_SUPPORTS_SMP |
1725 | bool | 1761 | bool |
1726 | 1762 | ||
@@ -1978,9 +2014,6 @@ config MMU | |||
1978 | config I8253 | 2014 | config I8253 |
1979 | bool | 2015 | bool |
1980 | 2016 | ||
1981 | config PCSPEAKER | ||
1982 | bool | ||
1983 | |||
1984 | config ZONE_DMA32 | 2017 | config ZONE_DMA32 |
1985 | bool | 2018 | bool |
1986 | 2019 | ||
diff --git a/arch/mips/Makefile b/arch/mips/Makefile index a1f8d8b96b03..3fb7f3065c92 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile | |||
@@ -141,6 +141,10 @@ cflags-$(CONFIG_CPU_R8000) += -march=r8000 -Wa,--trap | |||
141 | cflags-$(CONFIG_CPU_R10000) += $(call cc-option,-march=r10000,-march=r8000) \ | 141 | cflags-$(CONFIG_CPU_R10000) += $(call cc-option,-march=r10000,-march=r8000) \ |
142 | -Wa,--trap | 142 | -Wa,--trap |
143 | 143 | ||
144 | cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,) | ||
145 | cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,) | ||
146 | cflags-$(CONFIG_CPU_DADDI_WORKAROUNDS) += $(call cc-option,-mno-daddi,) | ||
147 | |||
144 | ifdef CONFIG_CPU_SB1 | 148 | ifdef CONFIG_CPU_SB1 |
145 | ifdef CONFIG_SB1_PASS_1_WORKAROUNDS | 149 | ifdef CONFIG_SB1_PASS_1_WORKAROUNDS |
146 | MODFLAGS += -msb1-pass1-workarounds | 150 | MODFLAGS += -msb1-pass1-workarounds |
@@ -152,6 +156,8 @@ endif | |||
152 | # | 156 | # |
153 | libs-$(CONFIG_ARC) += arch/mips/fw/arc/ | 157 | libs-$(CONFIG_ARC) += arch/mips/fw/arc/ |
154 | libs-$(CONFIG_CFE) += arch/mips/fw/cfe/ | 158 | libs-$(CONFIG_CFE) += arch/mips/fw/cfe/ |
159 | libs-$(CONFIG_SNIPROM) += arch/mips/fw/sni/ | ||
160 | libs-y += arch/mips/fw/lib/ | ||
155 | libs-$(CONFIG_SIBYTE_CFE) += arch/mips/sibyte/cfe/ | 161 | libs-$(CONFIG_SIBYTE_CFE) += arch/mips/sibyte/cfe/ |
156 | 162 | ||
157 | # | 163 | # |
@@ -308,7 +314,7 @@ core-$(CONFIG_MIPS_ATLAS) += arch/mips/mips-boards/atlas/ | |||
308 | cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-atlas | 314 | cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-atlas |
309 | cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-mips | 315 | cflags-$(CONFIG_MIPS_ATLAS) += -Iinclude/asm-mips/mach-mips |
310 | load-$(CONFIG_MIPS_ATLAS) += 0xffffffff80100000 | 316 | load-$(CONFIG_MIPS_ATLAS) += 0xffffffff80100000 |
311 | all-$(CONFIG_MIPS_ATLAS) := vmlinux.srec | 317 | all-$(CONFIG_MIPS_ATLAS) := vmlinux.bin |
312 | 318 | ||
313 | # | 319 | # |
314 | # MIPS Malta board | 320 | # MIPS Malta board |
@@ -316,7 +322,7 @@ all-$(CONFIG_MIPS_ATLAS) := vmlinux.srec | |||
316 | core-$(CONFIG_MIPS_MALTA) += arch/mips/mips-boards/malta/ | 322 | core-$(CONFIG_MIPS_MALTA) += arch/mips/mips-boards/malta/ |
317 | cflags-$(CONFIG_MIPS_MALTA) += -Iinclude/asm-mips/mach-mips | 323 | cflags-$(CONFIG_MIPS_MALTA) += -Iinclude/asm-mips/mach-mips |
318 | load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 | 324 | load-$(CONFIG_MIPS_MALTA) += 0xffffffff80100000 |
319 | all-$(CONFIG_MIPS_MALTA) := vmlinux.srec | 325 | all-$(CONFIG_MIPS_MALTA) := vmlinux.bin |
320 | 326 | ||
321 | # | 327 | # |
322 | # MIPS SEAD board | 328 | # MIPS SEAD board |
@@ -349,14 +355,6 @@ cflags-$(CONFIG_PMC_YOSEMITE) += -Iinclude/asm-mips/mach-yosemite | |||
349 | load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000 | 355 | load-$(CONFIG_PMC_YOSEMITE) += 0xffffffff80100000 |
350 | 356 | ||
351 | # | 357 | # |
352 | # Qemu simulating MIPS32 4Kc | ||
353 | # | ||
354 | core-$(CONFIG_QEMU) += arch/mips/qemu/ | ||
355 | cflags-$(CONFIG_QEMU) += -Iinclude/asm-mips/mach-qemu | ||
356 | load-$(CONFIG_QEMU) += 0xffffffff80010000 | ||
357 | all-$(CONFIG_QEMU) := vmlinux.bin | ||
358 | |||
359 | # | ||
360 | # Basler eXcite | 358 | # Basler eXcite |
361 | # | 359 | # |
362 | core-$(CONFIG_BASLER_EXCITE) += arch/mips/basler/excite/ | 360 | core-$(CONFIG_BASLER_EXCITE) += arch/mips/basler/excite/ |
@@ -475,6 +473,20 @@ endif | |||
475 | endif | 473 | endif |
476 | 474 | ||
477 | # | 475 | # |
476 | # SGI IP28 (Indigo2 R10k) | ||
477 | # | ||
478 | # Set the load address to >= 0xa800000020080000 if you want to leave space for | ||
479 | # symmon, 0xa800000020004000 for production kernels ? Note that the value must | ||
480 | # be 16kb aligned or the handling of the current variable will break. | ||
481 | # Simplified: what IP22 does at 128MB+ in ksegN, IP28 does at 512MB+ in xkphys | ||
482 | # | ||
483 | #core-$(CONFIG_SGI_IP28) += arch/mips/sgi-ip22/ arch/mips/arc/arc_con.o | ||
484 | core-$(CONFIG_SGI_IP28) += arch/mips/sgi-ip22/ | ||
485 | cflags-$(CONFIG_SGI_IP28) += -mr10k-cache-barrier=1 -Iinclude/asm-mips/mach-ip28 | ||
486 | #cflags-$(CONFIG_SGI_IP28) += -Iinclude/asm-mips/mach-ip28 | ||
487 | load-$(CONFIG_SGI_IP28) += 0xa800000020004000 | ||
488 | |||
489 | # | ||
478 | # SGI-IP32 (O2) | 490 | # SGI-IP32 (O2) |
479 | # | 491 | # |
480 | # Set the load address to >= 80069000 if you want to leave space for symmon, | 492 | # Set the load address to >= 80069000 if you want to leave space for symmon, |
@@ -602,9 +614,11 @@ ifdef CONFIG_64BIT | |||
602 | endif | 614 | endif |
603 | endif | 615 | endif |
604 | 616 | ||
605 | ifeq ($(KBUILD_SYM32), y) | 617 | ifeq ($(KBUILD_SYM32)$(call cc-option-yn,-msym32), yy) |
606 | ifeq ($(call cc-option-yn,-msym32), y) | 618 | cflags-y += -msym32 -DKBUILD_64BIT_SYM32 |
607 | cflags-y += -msym32 -DKBUILD_64BIT_SYM32 | 619 | else |
620 | ifeq ($(CONFIG_CPU_DADDI_WORKAROUNDS), y) | ||
621 | $(error CONFIG_CPU_DADDI_WORKAROUNDS unsupported without -msym32) | ||
608 | endif | 622 | endif |
609 | endif | 623 | endif |
610 | endif | 624 | endif |
diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c index 98a4e34b0248..37a10a01de9d 100644 --- a/arch/mips/au1000/common/au1xxx_irqmap.c +++ b/arch/mips/au1000/common/au1xxx_irqmap.c | |||
@@ -25,27 +25,10 @@ | |||
25 | * with this program; if not, write to the Free Software Foundation, Inc., | 25 | * with this program; if not, write to the Free Software Foundation, Inc., |
26 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 26 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
27 | */ | 27 | */ |
28 | #include <linux/errno.h> | ||
29 | #include <linux/init.h> | 28 | #include <linux/init.h> |
30 | #include <linux/irq.h> | 29 | #include <linux/kernel.h> |
31 | #include <linux/kernel_stat.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/signal.h> | ||
34 | #include <linux/sched.h> | ||
35 | #include <linux/types.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/ioport.h> | ||
38 | #include <linux/timex.h> | ||
39 | #include <linux/slab.h> | ||
40 | #include <linux/random.h> | ||
41 | #include <linux/delay.h> | ||
42 | #include <linux/bitops.h> | ||
43 | 30 | ||
44 | #include <asm/bootinfo.h> | 31 | #include <au1000.h> |
45 | #include <asm/io.h> | ||
46 | #include <asm/mipsregs.h> | ||
47 | #include <asm/system.h> | ||
48 | #include <asm/mach-au1x00/au1000.h> | ||
49 | 32 | ||
50 | /* The IC0 interrupt table. This is processor, rather than | 33 | /* The IC0 interrupt table. This is processor, rather than |
51 | * board dependent, so no reason to keep this info in the board | 34 | * board dependent, so no reason to keep this info in the board |
diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c index edf91f41a786..428ed275a0f6 100644 --- a/arch/mips/au1000/common/dbdma.c +++ b/arch/mips/au1000/common/dbdma.c | |||
@@ -179,7 +179,7 @@ static dbdev_tab_t dbdev_tab[] = { | |||
179 | { 0, 0, 0, 0, 0, 0, 0 }, | 179 | { 0, 0, 0, 0, 0, 0, 0 }, |
180 | }; | 180 | }; |
181 | 181 | ||
182 | #define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t)) | 182 | #define DBDEV_TAB_SIZE ARRAY_SIZE(dbdev_tab) |
183 | 183 | ||
184 | static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS]; | 184 | static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS]; |
185 | 185 | ||
diff --git a/arch/mips/au1000/db1x00/init.c b/arch/mips/au1000/db1x00/init.c index 43298fd9459c..e822c123eab8 100644 --- a/arch/mips/au1000/db1x00/init.c +++ b/arch/mips/au1000/db1x00/init.c | |||
@@ -57,17 +57,6 @@ void __init prom_init(void) | |||
57 | prom_argv = (char **) fw_arg1; | 57 | prom_argv = (char **) fw_arg1; |
58 | prom_envp = (char **) fw_arg2; | 58 | prom_envp = (char **) fw_arg2; |
59 | 59 | ||
60 | /* Set the platform # */ | ||
61 | #if defined(CONFIG_MIPS_DB1550) | ||
62 | mips_machtype = MACH_DB1550; | ||
63 | #elif defined(CONFIG_MIPS_DB1500) | ||
64 | mips_machtype = MACH_DB1500; | ||
65 | #elif defined(CONFIG_MIPS_DB1100) | ||
66 | mips_machtype = MACH_DB1100; | ||
67 | #else | ||
68 | mips_machtype = MACH_DB1000; | ||
69 | #endif | ||
70 | |||
71 | prom_init_cmdline(); | 60 | prom_init_cmdline(); |
72 | 61 | ||
73 | memsize_str = prom_getenv("memsize"); | 62 | memsize_str = prom_getenv("memsize"); |
diff --git a/arch/mips/au1000/mtx-1/init.c b/arch/mips/au1000/mtx-1/init.c index cdeae3212a2d..e700fd312a24 100644 --- a/arch/mips/au1000/mtx-1/init.c +++ b/arch/mips/au1000/mtx-1/init.c | |||
@@ -54,8 +54,6 @@ void __init prom_init(void) | |||
54 | prom_argv = (char **) fw_arg1; | 54 | prom_argv = (char **) fw_arg1; |
55 | prom_envp = (char **) fw_arg2; | 55 | prom_envp = (char **) fw_arg2; |
56 | 56 | ||
57 | mips_machtype = MACH_MTX1; /* set the platform # */ | ||
58 | |||
59 | prom_init_cmdline(); | 57 | prom_init_cmdline(); |
60 | 58 | ||
61 | memsize_str = prom_getenv("memsize"); | 59 | memsize_str = prom_getenv("memsize"); |
diff --git a/arch/mips/au1000/mtx-1/platform.c b/arch/mips/au1000/mtx-1/platform.c index 49c0fb409fea..ce8637b3afa9 100644 --- a/arch/mips/au1000/mtx-1/platform.c +++ b/arch/mips/au1000/mtx-1/platform.c | |||
@@ -22,9 +22,32 @@ | |||
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/leds.h> | 24 | #include <linux/leds.h> |
25 | #include <linux/gpio_keys.h> | ||
26 | #include <linux/input.h> | ||
25 | 27 | ||
26 | #include <asm/gpio.h> | 28 | #include <asm/gpio.h> |
27 | 29 | ||
30 | static struct gpio_keys_button mtx1_gpio_button[] = { | ||
31 | { | ||
32 | .gpio = 207, | ||
33 | .code = BTN_0, | ||
34 | .desc = "System button", | ||
35 | } | ||
36 | }; | ||
37 | |||
38 | static struct gpio_keys_platform_data mtx1_buttons_data = { | ||
39 | .buttons = mtx1_gpio_button, | ||
40 | .nbuttons = ARRAY_SIZE(mtx1_gpio_button), | ||
41 | }; | ||
42 | |||
43 | static struct platform_device mtx1_button = { | ||
44 | .name = "gpio-keys", | ||
45 | .id = -1, | ||
46 | .dev = { | ||
47 | .platform_data = &mtx1_buttons_data, | ||
48 | } | ||
49 | }; | ||
50 | |||
28 | static struct resource mtx1_wdt_res[] = { | 51 | static struct resource mtx1_wdt_res[] = { |
29 | [0] = { | 52 | [0] = { |
30 | .start = 15, | 53 | .start = 15, |
@@ -66,11 +89,13 @@ static struct platform_device mtx1_gpio_leds = { | |||
66 | 89 | ||
67 | static struct __initdata platform_device * mtx1_devs[] = { | 90 | static struct __initdata platform_device * mtx1_devs[] = { |
68 | &mtx1_gpio_leds, | 91 | &mtx1_gpio_leds, |
69 | &mtx1_wdt | 92 | &mtx1_wdt, |
93 | &mtx1_button | ||
70 | }; | 94 | }; |
71 | 95 | ||
72 | static int __init mtx1_register_devices(void) | 96 | static int __init mtx1_register_devices(void) |
73 | { | 97 | { |
98 | gpio_direction_input(207); | ||
74 | return platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs)); | 99 | return platform_add_devices(mtx1_devs, ARRAY_SIZE(mtx1_devs)); |
75 | } | 100 | } |
76 | 101 | ||
diff --git a/arch/mips/au1000/pb1000/init.c b/arch/mips/au1000/pb1000/init.c index ddccaf6997d0..2515b9fb24af 100644 --- a/arch/mips/au1000/pb1000/init.c +++ b/arch/mips/au1000/pb1000/init.c | |||
@@ -52,8 +52,6 @@ void __init prom_init(void) | |||
52 | prom_argv = (char **) fw_arg1; | 52 | prom_argv = (char **) fw_arg1; |
53 | prom_envp = (char **) fw_arg2; | 53 | prom_envp = (char **) fw_arg2; |
54 | 54 | ||
55 | mips_machtype = MACH_PB1000; | ||
56 | |||
57 | prom_init_cmdline(); | 55 | prom_init_cmdline(); |
58 | memsize_str = prom_getenv("memsize"); | 56 | memsize_str = prom_getenv("memsize"); |
59 | if (!memsize_str) { | 57 | if (!memsize_str) { |
diff --git a/arch/mips/au1000/pb1100/init.c b/arch/mips/au1000/pb1100/init.c index c93fd39b4aba..490c3801c275 100644 --- a/arch/mips/au1000/pb1100/init.c +++ b/arch/mips/au1000/pb1100/init.c | |||
@@ -53,8 +53,6 @@ void __init prom_init(void) | |||
53 | prom_argv = (char **) fw_arg1; | 53 | prom_argv = (char **) fw_arg1; |
54 | prom_envp = (char **) fw_arg3; | 54 | prom_envp = (char **) fw_arg3; |
55 | 55 | ||
56 | mips_machtype = MACH_PB1100; | ||
57 | |||
58 | prom_init_cmdline(); | 56 | prom_init_cmdline(); |
59 | 57 | ||
60 | memsize_str = prom_getenv("memsize"); | 58 | memsize_str = prom_getenv("memsize"); |
diff --git a/arch/mips/au1000/pb1200/init.c b/arch/mips/au1000/pb1200/init.c index c251570749ee..069ed45f04f2 100644 --- a/arch/mips/au1000/pb1200/init.c +++ b/arch/mips/au1000/pb1200/init.c | |||
@@ -53,8 +53,6 @@ void __init prom_init(void) | |||
53 | prom_argv = (char **) fw_arg1; | 53 | prom_argv = (char **) fw_arg1; |
54 | prom_envp = (char **) fw_arg2; | 54 | prom_envp = (char **) fw_arg2; |
55 | 55 | ||
56 | mips_machtype = MACH_PB1200; | ||
57 | |||
58 | prom_init_cmdline(); | 56 | prom_init_cmdline(); |
59 | memsize_str = prom_getenv("memsize"); | 57 | memsize_str = prom_getenv("memsize"); |
60 | if (!memsize_str) { | 58 | if (!memsize_str) { |
diff --git a/arch/mips/au1000/pb1500/init.c b/arch/mips/au1000/pb1500/init.c index 507d4b204161..db558c967048 100644 --- a/arch/mips/au1000/pb1500/init.c +++ b/arch/mips/au1000/pb1500/init.c | |||
@@ -53,8 +53,6 @@ void __init prom_init(void) | |||
53 | prom_argv = (char **) fw_arg1; | 53 | prom_argv = (char **) fw_arg1; |
54 | prom_envp = (char **) fw_arg2; | 54 | prom_envp = (char **) fw_arg2; |
55 | 55 | ||
56 | mips_machtype = MACH_PB1500; | ||
57 | |||
58 | prom_init_cmdline(); | 56 | prom_init_cmdline(); |
59 | memsize_str = prom_getenv("memsize"); | 57 | memsize_str = prom_getenv("memsize"); |
60 | if (!memsize_str) { | 58 | if (!memsize_str) { |
diff --git a/arch/mips/au1000/pb1550/init.c b/arch/mips/au1000/pb1550/init.c index b03eee601e36..b716363ea564 100644 --- a/arch/mips/au1000/pb1550/init.c +++ b/arch/mips/au1000/pb1550/init.c | |||
@@ -53,8 +53,6 @@ void __init prom_init(void) | |||
53 | prom_argv = (char **) fw_arg1; | 53 | prom_argv = (char **) fw_arg1; |
54 | prom_envp = (char **) fw_arg2; | 54 | prom_envp = (char **) fw_arg2; |
55 | 55 | ||
56 | mips_machtype = MACH_PB1550; | ||
57 | |||
58 | prom_init_cmdline(); | 56 | prom_init_cmdline(); |
59 | memsize_str = prom_getenv("memsize"); | 57 | memsize_str = prom_getenv("memsize"); |
60 | if (!memsize_str) { | 58 | if (!memsize_str) { |
diff --git a/arch/mips/au1000/xxs1500/init.c b/arch/mips/au1000/xxs1500/init.c index 6532939f377a..7e6878c1b0a5 100644 --- a/arch/mips/au1000/xxs1500/init.c +++ b/arch/mips/au1000/xxs1500/init.c | |||
@@ -52,8 +52,6 @@ void __init prom_init(void) | |||
52 | prom_argv = (char **) fw_arg1; | 52 | prom_argv = (char **) fw_arg1; |
53 | prom_envp = (char **) fw_arg2; | 53 | prom_envp = (char **) fw_arg2; |
54 | 54 | ||
55 | mips_machtype = MACH_XXS1500; /* set the platform # */ | ||
56 | |||
57 | prom_init_cmdline(); | 55 | prom_init_cmdline(); |
58 | 56 | ||
59 | memsize_str = prom_getenv("memsize"); | 57 | memsize_str = prom_getenv("memsize"); |
diff --git a/arch/mips/basler/excite/Kconfig b/arch/mips/basler/excite/Kconfig new file mode 100644 index 000000000000..ba506075608b --- /dev/null +++ b/arch/mips/basler/excite/Kconfig | |||
@@ -0,0 +1,9 @@ | |||
1 | config BASLER_EXCITE_PROTOTYPE | ||
2 | bool "Support for pre-release units" | ||
3 | depends on BASLER_EXCITE | ||
4 | default n | ||
5 | help | ||
6 | Pre-series (prototype) units are different from later ones in | ||
7 | some ways. Select this option if you have one of these. Please | ||
8 | note that a kernel built with this option selected will not be | ||
9 | able to run on normal units. | ||
diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c index 6af0b21ebc32..476d20e08d0e 100644 --- a/arch/mips/basler/excite/excite_iodev.c +++ b/arch/mips/basler/excite/excite_iodev.c | |||
@@ -48,7 +48,7 @@ static DECLARE_WAIT_QUEUE_HEAD(wq); | |||
48 | 48 | ||
49 | 49 | ||
50 | 50 | ||
51 | static struct file_operations fops = | 51 | static const struct file_operations fops = |
52 | { | 52 | { |
53 | .owner = THIS_MODULE, | 53 | .owner = THIS_MODULE, |
54 | .open = iodev_open, | 54 | .open = iodev_open, |
diff --git a/arch/mips/basler/excite/excite_prom.c b/arch/mips/basler/excite/excite_prom.c index 2d752c2f6e59..68d8bc597e34 100644 --- a/arch/mips/basler/excite/excite_prom.c +++ b/arch/mips/basler/excite/excite_prom.c | |||
@@ -135,8 +135,6 @@ void __init prom_init(void) | |||
135 | #ifdef CONFIG_64BIT | 135 | #ifdef CONFIG_64BIT |
136 | # error 64 bit support not implemented | 136 | # error 64 bit support not implemented |
137 | #endif /* CONFIG_64BIT */ | 137 | #endif /* CONFIG_64BIT */ |
138 | |||
139 | mips_machtype = MACH_TITAN_EXCITE; | ||
140 | } | 138 | } |
141 | 139 | ||
142 | /* This is called from free_initmem(), so we need to provide it */ | 140 | /* This is called from free_initmem(), so we need to provide it */ |
diff --git a/arch/mips/cobalt/reset.c b/arch/mips/cobalt/reset.c index 71eb4ccc4bc1..516b4428df4e 100644 --- a/arch/mips/cobalt/reset.c +++ b/arch/mips/cobalt/reset.c | |||
@@ -10,9 +10,10 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/io.h> | 12 | #include <linux/io.h> |
13 | #include <linux/jiffies.h> | ||
14 | #include <linux/leds.h> | 13 | #include <linux/leds.h> |
15 | 14 | ||
15 | #include <asm/processor.h> | ||
16 | |||
16 | #include <cobalt.h> | 17 | #include <cobalt.h> |
17 | 18 | ||
18 | #define RESET_PORT ((void __iomem *)CKSEG1ADDR(0x1c000000)) | 19 | #define RESET_PORT ((void __iomem *)CKSEG1ADDR(0x1c000000)) |
@@ -29,28 +30,15 @@ device_initcall(ledtrig_power_off_init); | |||
29 | 30 | ||
30 | void cobalt_machine_halt(void) | 31 | void cobalt_machine_halt(void) |
31 | { | 32 | { |
32 | int state, last, diff; | ||
33 | unsigned long mark; | ||
34 | |||
35 | /* | 33 | /* |
36 | * turn on power off LED on RaQ | 34 | * turn on power off LED on RaQ |
37 | * | ||
38 | * restart if ENTER and SELECT are pressed | ||
39 | */ | 35 | */ |
40 | |||
41 | last = COBALT_KEY_PORT; | ||
42 | |||
43 | led_trigger_event(power_off_led_trigger, LED_FULL); | 36 | led_trigger_event(power_off_led_trigger, LED_FULL); |
44 | 37 | ||
45 | for (state = 0;;) { | 38 | local_irq_disable(); |
46 | diff = COBALT_KEY_PORT ^ last; | 39 | while (1) { |
47 | last ^= diff; | 40 | if (cpu_wait) |
48 | 41 | cpu_wait(); | |
49 | if((diff & (COBALT_KEY_ENTER | COBALT_KEY_SELECT)) && !(~last & (COBALT_KEY_ENTER | COBALT_KEY_SELECT))) | ||
50 | writeb(RESET, RESET_PORT); | ||
51 | |||
52 | for (mark = jiffies; jiffies - mark < HZ;) | ||
53 | ; | ||
54 | } | 42 | } |
55 | } | 43 | } |
56 | 44 | ||
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig index 62bcc887f2ca..3443f6cd57bb 100644 --- a/arch/mips/configs/atlas_defconfig +++ b/arch/mips/configs/atlas_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_MIPS_ATLAS=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_MIPS_ATLAS=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index 3c70c9d16d01..abf70d74e9d7 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_ZONE_DMA=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_SIBYTE_BIGSUR=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig index 8ecbbb226c76..a94f14b5c8fa 100644 --- a/arch/mips/configs/capcella_defconfig +++ b/arch/mips/configs/capcella_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MACH_VR41XX=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MACH_VR41XX=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig index 36c13039e237..b7295e988381 100644 --- a/arch/mips/configs/cobalt_defconfig +++ b/arch/mips/configs/cobalt_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MIPS_COBALT=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MIPS_COBALT=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig index 5a8b7acb7dd7..36578968d386 100644 --- a/arch/mips/configs/db1000_defconfig +++ b/arch/mips/configs/db1000_defconfig | |||
@@ -38,7 +38,6 @@ CONFIG_MIPS_DB1000=y | |||
38 | # CONFIG_PNX8550_STB810 is not set | 38 | # CONFIG_PNX8550_STB810 is not set |
39 | # CONFIG_MACH_VR41XX is not set | 39 | # CONFIG_MACH_VR41XX is not set |
40 | # CONFIG_PMC_YOSEMITE is not set | 40 | # CONFIG_PMC_YOSEMITE is not set |
41 | # CONFIG_QEMU is not set | ||
42 | # CONFIG_MARKEINS is not set | 41 | # CONFIG_MARKEINS is not set |
43 | # CONFIG_SGI_IP22 is not set | 42 | # CONFIG_SGI_IP22 is not set |
44 | # CONFIG_SGI_IP27 is not set | 43 | # CONFIG_SGI_IP27 is not set |
@@ -48,7 +47,6 @@ CONFIG_MIPS_DB1000=y | |||
48 | # CONFIG_SIBYTE_SENTOSA is not set | 47 | # CONFIG_SIBYTE_SENTOSA is not set |
49 | # CONFIG_SIBYTE_RHONE is not set | 48 | # CONFIG_SIBYTE_RHONE is not set |
50 | # CONFIG_SIBYTE_CARMEL is not set | 49 | # CONFIG_SIBYTE_CARMEL is not set |
51 | # CONFIG_SIBYTE_PTSWARM is not set | ||
52 | # CONFIG_SIBYTE_LITTLESUR is not set | 50 | # CONFIG_SIBYTE_LITTLESUR is not set |
53 | # CONFIG_SIBYTE_CRHINE is not set | 51 | # CONFIG_SIBYTE_CRHINE is not set |
54 | # CONFIG_SIBYTE_CRHONE is not set | 52 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig index d4ed90bca269..5a90740c363a 100644 --- a/arch/mips/configs/db1100_defconfig +++ b/arch/mips/configs/db1100_defconfig | |||
@@ -38,7 +38,6 @@ CONFIG_MIPS_DB1100=y | |||
38 | # CONFIG_PNX8550_STB810 is not set | 38 | # CONFIG_PNX8550_STB810 is not set |
39 | # CONFIG_MACH_VR41XX is not set | 39 | # CONFIG_MACH_VR41XX is not set |
40 | # CONFIG_PMC_YOSEMITE is not set | 40 | # CONFIG_PMC_YOSEMITE is not set |
41 | # CONFIG_QEMU is not set | ||
42 | # CONFIG_MARKEINS is not set | 41 | # CONFIG_MARKEINS is not set |
43 | # CONFIG_SGI_IP22 is not set | 42 | # CONFIG_SGI_IP22 is not set |
44 | # CONFIG_SGI_IP27 is not set | 43 | # CONFIG_SGI_IP27 is not set |
@@ -48,7 +47,6 @@ CONFIG_MIPS_DB1100=y | |||
48 | # CONFIG_SIBYTE_SENTOSA is not set | 47 | # CONFIG_SIBYTE_SENTOSA is not set |
49 | # CONFIG_SIBYTE_RHONE is not set | 48 | # CONFIG_SIBYTE_RHONE is not set |
50 | # CONFIG_SIBYTE_CARMEL is not set | 49 | # CONFIG_SIBYTE_CARMEL is not set |
51 | # CONFIG_SIBYTE_PTSWARM is not set | ||
52 | # CONFIG_SIBYTE_LITTLESUR is not set | 50 | # CONFIG_SIBYTE_LITTLESUR is not set |
53 | # CONFIG_SIBYTE_CRHINE is not set | 51 | # CONFIG_SIBYTE_CRHINE is not set |
54 | # CONFIG_SIBYTE_CRHONE is not set | 52 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig index a055657e6983..76f37a1159fe 100644 --- a/arch/mips/configs/db1200_defconfig +++ b/arch/mips/configs/db1200_defconfig | |||
@@ -38,7 +38,6 @@ CONFIG_MIPS_DB1200=y | |||
38 | # CONFIG_PNX8550_STB810 is not set | 38 | # CONFIG_PNX8550_STB810 is not set |
39 | # CONFIG_MACH_VR41XX is not set | 39 | # CONFIG_MACH_VR41XX is not set |
40 | # CONFIG_PMC_YOSEMITE is not set | 40 | # CONFIG_PMC_YOSEMITE is not set |
41 | # CONFIG_QEMU is not set | ||
42 | # CONFIG_MARKEINS is not set | 41 | # CONFIG_MARKEINS is not set |
43 | # CONFIG_SGI_IP22 is not set | 42 | # CONFIG_SGI_IP22 is not set |
44 | # CONFIG_SGI_IP27 is not set | 43 | # CONFIG_SGI_IP27 is not set |
@@ -48,7 +47,6 @@ CONFIG_MIPS_DB1200=y | |||
48 | # CONFIG_SIBYTE_SENTOSA is not set | 47 | # CONFIG_SIBYTE_SENTOSA is not set |
49 | # CONFIG_SIBYTE_RHONE is not set | 48 | # CONFIG_SIBYTE_RHONE is not set |
50 | # CONFIG_SIBYTE_CARMEL is not set | 49 | # CONFIG_SIBYTE_CARMEL is not set |
51 | # CONFIG_SIBYTE_PTSWARM is not set | ||
52 | # CONFIG_SIBYTE_LITTLESUR is not set | 50 | # CONFIG_SIBYTE_LITTLESUR is not set |
53 | # CONFIG_SIBYTE_CRHINE is not set | 51 | # CONFIG_SIBYTE_CRHINE is not set |
54 | # CONFIG_SIBYTE_CRHONE is not set | 52 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig index 0ad08cf446ec..508c91944f30 100644 --- a/arch/mips/configs/db1500_defconfig +++ b/arch/mips/configs/db1500_defconfig | |||
@@ -38,7 +38,6 @@ CONFIG_MIPS_DB1500=y | |||
38 | # CONFIG_PNX8550_STB810 is not set | 38 | # CONFIG_PNX8550_STB810 is not set |
39 | # CONFIG_MACH_VR41XX is not set | 39 | # CONFIG_MACH_VR41XX is not set |
40 | # CONFIG_PMC_YOSEMITE is not set | 40 | # CONFIG_PMC_YOSEMITE is not set |
41 | # CONFIG_QEMU is not set | ||
42 | # CONFIG_MARKEINS is not set | 41 | # CONFIG_MARKEINS is not set |
43 | # CONFIG_SGI_IP22 is not set | 42 | # CONFIG_SGI_IP22 is not set |
44 | # CONFIG_SGI_IP27 is not set | 43 | # CONFIG_SGI_IP27 is not set |
@@ -48,7 +47,6 @@ CONFIG_MIPS_DB1500=y | |||
48 | # CONFIG_SIBYTE_SENTOSA is not set | 47 | # CONFIG_SIBYTE_SENTOSA is not set |
49 | # CONFIG_SIBYTE_RHONE is not set | 48 | # CONFIG_SIBYTE_RHONE is not set |
50 | # CONFIG_SIBYTE_CARMEL is not set | 49 | # CONFIG_SIBYTE_CARMEL is not set |
51 | # CONFIG_SIBYTE_PTSWARM is not set | ||
52 | # CONFIG_SIBYTE_LITTLESUR is not set | 50 | # CONFIG_SIBYTE_LITTLESUR is not set |
53 | # CONFIG_SIBYTE_CRHINE is not set | 51 | # CONFIG_SIBYTE_CRHINE is not set |
54 | # CONFIG_SIBYTE_CRHONE is not set | 52 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig index 057c7d429c80..0c2c70d21db9 100644 --- a/arch/mips/configs/db1550_defconfig +++ b/arch/mips/configs/db1550_defconfig | |||
@@ -38,7 +38,6 @@ CONFIG_MIPS_DB1550=y | |||
38 | # CONFIG_PNX8550_STB810 is not set | 38 | # CONFIG_PNX8550_STB810 is not set |
39 | # CONFIG_MACH_VR41XX is not set | 39 | # CONFIG_MACH_VR41XX is not set |
40 | # CONFIG_PMC_YOSEMITE is not set | 40 | # CONFIG_PMC_YOSEMITE is not set |
41 | # CONFIG_QEMU is not set | ||
42 | # CONFIG_MARKEINS is not set | 41 | # CONFIG_MARKEINS is not set |
43 | # CONFIG_SGI_IP22 is not set | 42 | # CONFIG_SGI_IP22 is not set |
44 | # CONFIG_SGI_IP27 is not set | 43 | # CONFIG_SGI_IP27 is not set |
@@ -48,7 +47,6 @@ CONFIG_MIPS_DB1550=y | |||
48 | # CONFIG_SIBYTE_SENTOSA is not set | 47 | # CONFIG_SIBYTE_SENTOSA is not set |
49 | # CONFIG_SIBYTE_RHONE is not set | 48 | # CONFIG_SIBYTE_RHONE is not set |
50 | # CONFIG_SIBYTE_CARMEL is not set | 49 | # CONFIG_SIBYTE_CARMEL is not set |
51 | # CONFIG_SIBYTE_PTSWARM is not set | ||
52 | # CONFIG_SIBYTE_LITTLESUR is not set | 50 | # CONFIG_SIBYTE_LITTLESUR is not set |
53 | # CONFIG_SIBYTE_CRHINE is not set | 51 | # CONFIG_SIBYTE_CRHINE is not set |
54 | # CONFIG_SIBYTE_CRHONE is not set | 52 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig index 2fb350432669..58c2cd68c3a7 100644 --- a/arch/mips/configs/decstation_defconfig +++ b/arch/mips/configs/decstation_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_MACH_DECSTATION=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_MACH_DECSTATION=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig index d0d07faeb844..90d81f5dcebc 100644 --- a/arch/mips/configs/e55_defconfig +++ b/arch/mips/configs/e55_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MACH_VR41XX=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MACH_VR41XX=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig index d73d965f7615..f9a003c2b3a1 100644 --- a/arch/mips/configs/emma2rh_defconfig +++ b/arch/mips/configs/emma2rh_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_ZONE_DMA=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | CONFIG_MARKEINS=y | 40 | CONFIG_MARKEINS=y |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_MARKEINS=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig index 17a866057fd4..15efacc75d73 100644 --- a/arch/mips/configs/excite_defconfig +++ b/arch/mips/configs/excite_defconfig | |||
@@ -38,7 +38,6 @@ CONFIG_BASLER_EXCITE=y | |||
38 | # CONFIG_PNX8550_STB810 is not set | 38 | # CONFIG_PNX8550_STB810 is not set |
39 | # CONFIG_MACH_VR41XX is not set | 39 | # CONFIG_MACH_VR41XX is not set |
40 | # CONFIG_PMC_YOSEMITE is not set | 40 | # CONFIG_PMC_YOSEMITE is not set |
41 | # CONFIG_QEMU is not set | ||
42 | # CONFIG_MARKEINS is not set | 41 | # CONFIG_MARKEINS is not set |
43 | # CONFIG_SGI_IP22 is not set | 42 | # CONFIG_SGI_IP22 is not set |
44 | # CONFIG_SGI_IP27 is not set | 43 | # CONFIG_SGI_IP27 is not set |
@@ -48,7 +47,6 @@ CONFIG_BASLER_EXCITE=y | |||
48 | # CONFIG_SIBYTE_SENTOSA is not set | 47 | # CONFIG_SIBYTE_SENTOSA is not set |
49 | # CONFIG_SIBYTE_RHONE is not set | 48 | # CONFIG_SIBYTE_RHONE is not set |
50 | # CONFIG_SIBYTE_CARMEL is not set | 49 | # CONFIG_SIBYTE_CARMEL is not set |
51 | # CONFIG_SIBYTE_PTSWARM is not set | ||
52 | # CONFIG_SIBYTE_LITTLESUR is not set | 50 | # CONFIG_SIBYTE_LITTLESUR is not set |
53 | # CONFIG_SIBYTE_CRHINE is not set | 51 | # CONFIG_SIBYTE_CRHINE is not set |
54 | # CONFIG_SIBYTE_CRHONE is not set | 52 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/fulong_defconfig b/arch/mips/configs/fulong_defconfig index 4ef39a0527cc..5887a1735fba 100644 --- a/arch/mips/configs/fulong_defconfig +++ b/arch/mips/configs/fulong_defconfig | |||
@@ -23,7 +23,6 @@ CONFIG_LEMOTE_FULONG=y | |||
23 | # CONFIG_PNX8550_STB810 is not set | 23 | # CONFIG_PNX8550_STB810 is not set |
24 | # CONFIG_MACH_VR41XX is not set | 24 | # CONFIG_MACH_VR41XX is not set |
25 | # CONFIG_PMC_YOSEMITE is not set | 25 | # CONFIG_PMC_YOSEMITE is not set |
26 | # CONFIG_QEMU is not set | ||
27 | # CONFIG_MARKEINS is not set | 26 | # CONFIG_MARKEINS is not set |
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
@@ -33,7 +32,6 @@ CONFIG_LEMOTE_FULONG=y | |||
33 | # CONFIG_SIBYTE_SENTOSA is not set | 32 | # CONFIG_SIBYTE_SENTOSA is not set |
34 | # CONFIG_SIBYTE_RHONE is not set | 33 | # CONFIG_SIBYTE_RHONE is not set |
35 | # CONFIG_SIBYTE_CARMEL is not set | 34 | # CONFIG_SIBYTE_CARMEL is not set |
36 | # CONFIG_SIBYTE_PTSWARM is not set | ||
37 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
38 | # CONFIG_SIBYTE_CRHINE is not set | 36 | # CONFIG_SIBYTE_CRHINE is not set |
39 | # CONFIG_SIBYTE_CRHONE is not set | 37 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig index 670039bb1a7c..4f5e56c9335e 100644 --- a/arch/mips/configs/ip22_defconfig +++ b/arch/mips/configs/ip22_defconfig | |||
@@ -25,7 +25,6 @@ CONFIG_ZONE_DMA=y | |||
25 | # CONFIG_PNX8550_STB810 is not set | 25 | # CONFIG_PNX8550_STB810 is not set |
26 | # CONFIG_PMC_MSP is not set | 26 | # CONFIG_PMC_MSP is not set |
27 | # CONFIG_PMC_YOSEMITE is not set | 27 | # CONFIG_PMC_YOSEMITE is not set |
28 | # CONFIG_QEMU is not set | ||
29 | CONFIG_SGI_IP22=y | 28 | CONFIG_SGI_IP22=y |
30 | # CONFIG_SGI_IP27 is not set | 29 | # CONFIG_SGI_IP27 is not set |
31 | # CONFIG_SGI_IP32 is not set | 30 | # CONFIG_SGI_IP32 is not set |
@@ -36,7 +35,6 @@ CONFIG_SGI_IP22=y | |||
36 | # CONFIG_SIBYTE_SWARM is not set | 35 | # CONFIG_SIBYTE_SWARM is not set |
37 | # CONFIG_SIBYTE_LITTLESUR is not set | 36 | # CONFIG_SIBYTE_LITTLESUR is not set |
38 | # CONFIG_SIBYTE_SENTOSA is not set | 37 | # CONFIG_SIBYTE_SENTOSA is not set |
39 | # CONFIG_SIBYTE_PTSWARM is not set | ||
40 | # CONFIG_SIBYTE_BIGSUR is not set | 38 | # CONFIG_SIBYTE_BIGSUR is not set |
41 | # CONFIG_SNI_RM is not set | 39 | # CONFIG_SNI_RM is not set |
42 | # CONFIG_TOSHIBA_JMR3927 is not set | 40 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index 892d4c38fd0d..f40e437bd9e5 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MIPS=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | CONFIG_SGI_IP27=y | 28 | CONFIG_SGI_IP27=y |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_SGI_IP27=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index 47f49b60c5d6..2c5c624c5d42 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_ZONE_DMA=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_SGI_IP32=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig index fa655e247ecc..56148745e8f2 100644 --- a/arch/mips/configs/jazz_defconfig +++ b/arch/mips/configs/jazz_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_MACH_JAZZ=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_MACH_JAZZ=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig index eb96791c33ea..a7cd67753aac 100644 --- a/arch/mips/configs/jmr3927_defconfig +++ b/arch/mips/configs/jmr3927_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MIPS=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MIPS=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | CONFIG_TOSHIBA_JMR3927=y | 39 | CONFIG_TOSHIBA_JMR3927=y |
@@ -464,7 +462,6 @@ CONFIG_SERIAL_TXX9_STDSERIAL=y | |||
464 | CONFIG_LEGACY_PTYS=y | 462 | CONFIG_LEGACY_PTYS=y |
465 | CONFIG_LEGACY_PTY_COUNT=256 | 463 | CONFIG_LEGACY_PTY_COUNT=256 |
466 | # CONFIG_IPMI_HANDLER is not set | 464 | # CONFIG_IPMI_HANDLER is not set |
467 | # CONFIG_WATCHDOG is not set | ||
468 | # CONFIG_HW_RANDOM is not set | 465 | # CONFIG_HW_RANDOM is not set |
469 | # CONFIG_RTC is not set | 466 | # CONFIG_RTC is not set |
470 | # CONFIG_R3964 is not set | 467 | # CONFIG_R3964 is not set |
@@ -482,6 +479,20 @@ CONFIG_DEVPORT=y | |||
482 | # CONFIG_W1 is not set | 479 | # CONFIG_W1 is not set |
483 | # CONFIG_POWER_SUPPLY is not set | 480 | # CONFIG_POWER_SUPPLY is not set |
484 | # CONFIG_HWMON is not set | 481 | # CONFIG_HWMON is not set |
482 | CONFIG_WATCHDOG=y | ||
483 | # CONFIG_WATCHDOG_NOWAYOUT is not set | ||
484 | |||
485 | # | ||
486 | # Watchdog Device Drivers | ||
487 | # | ||
488 | # CONFIG_SOFT_WATCHDOG is not set | ||
489 | CONFIG_TXX9_WDT=y | ||
490 | |||
491 | # | ||
492 | # PCI-based Watchdog Cards | ||
493 | # | ||
494 | # CONFIG_PCIPCWATCHDOG is not set | ||
495 | # CONFIG_WDTPCI is not set | ||
485 | 496 | ||
486 | # | 497 | # |
487 | # Multifunction device drivers | 498 | # Multifunction device drivers |
diff --git a/arch/mips/configs/lasat_defconfig b/arch/mips/configs/lasat_defconfig index 2c665fcef089..e6aef999854c 100644 --- a/arch/mips/configs/lasat_defconfig +++ b/arch/mips/configs/lasat_defconfig | |||
@@ -25,7 +25,6 @@ CONFIG_LASAT=y | |||
25 | # CONFIG_PNX8550_STB810 is not set | 25 | # CONFIG_PNX8550_STB810 is not set |
26 | # CONFIG_PMC_MSP is not set | 26 | # CONFIG_PMC_MSP is not set |
27 | # CONFIG_PMC_YOSEMITE is not set | 27 | # CONFIG_PMC_YOSEMITE is not set |
28 | # CONFIG_QEMU is not set | ||
29 | # CONFIG_SGI_IP22 is not set | 28 | # CONFIG_SGI_IP22 is not set |
30 | # CONFIG_SGI_IP27 is not set | 29 | # CONFIG_SGI_IP27 is not set |
31 | # CONFIG_SGI_IP32 is not set | 30 | # CONFIG_SGI_IP32 is not set |
@@ -36,7 +35,6 @@ CONFIG_LASAT=y | |||
36 | # CONFIG_SIBYTE_SWARM is not set | 35 | # CONFIG_SIBYTE_SWARM is not set |
37 | # CONFIG_SIBYTE_LITTLESUR is not set | 36 | # CONFIG_SIBYTE_LITTLESUR is not set |
38 | # CONFIG_SIBYTE_SENTOSA is not set | 37 | # CONFIG_SIBYTE_SENTOSA is not set |
39 | # CONFIG_SIBYTE_PTSWARM is not set | ||
40 | # CONFIG_SIBYTE_BIGSUR is not set | 38 | # CONFIG_SIBYTE_BIGSUR is not set |
41 | # CONFIG_SNI_RM is not set | 39 | # CONFIG_SNI_RM is not set |
42 | # CONFIG_TOSHIBA_JMR3927 is not set | 40 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig index 4b7e43c9f69a..3d0da952811c 100644 --- a/arch/mips/configs/malta_defconfig +++ b/arch/mips/configs/malta_defconfig | |||
@@ -25,7 +25,6 @@ CONFIG_MIPS_MALTA=y | |||
25 | # CONFIG_PNX8550_STB810 is not set | 25 | # CONFIG_PNX8550_STB810 is not set |
26 | # CONFIG_PMC_MSP is not set | 26 | # CONFIG_PMC_MSP is not set |
27 | # CONFIG_PMC_YOSEMITE is not set | 27 | # CONFIG_PMC_YOSEMITE is not set |
28 | # CONFIG_QEMU is not set | ||
29 | # CONFIG_SGI_IP22 is not set | 28 | # CONFIG_SGI_IP22 is not set |
30 | # CONFIG_SGI_IP27 is not set | 29 | # CONFIG_SGI_IP27 is not set |
31 | # CONFIG_SGI_IP32 is not set | 30 | # CONFIG_SGI_IP32 is not set |
@@ -36,7 +35,6 @@ CONFIG_MIPS_MALTA=y | |||
36 | # CONFIG_SIBYTE_SWARM is not set | 35 | # CONFIG_SIBYTE_SWARM is not set |
37 | # CONFIG_SIBYTE_LITTLESUR is not set | 36 | # CONFIG_SIBYTE_LITTLESUR is not set |
38 | # CONFIG_SIBYTE_SENTOSA is not set | 37 | # CONFIG_SIBYTE_SENTOSA is not set |
39 | # CONFIG_SIBYTE_PTSWARM is not set | ||
40 | # CONFIG_SIBYTE_BIGSUR is not set | 38 | # CONFIG_SIBYTE_BIGSUR is not set |
41 | # CONFIG_SNI_RM is not set | 39 | # CONFIG_SNI_RM is not set |
42 | # CONFIG_TOSHIBA_JMR3927 is not set | 40 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig index 61b72f5a953e..6db0bdaefb27 100644 --- a/arch/mips/configs/mipssim_defconfig +++ b/arch/mips/configs/mipssim_defconfig | |||
@@ -26,7 +26,6 @@ CONFIG_MIPS_SIM=y | |||
26 | # CONFIG_PNX8550_STB810 is not set | 26 | # CONFIG_PNX8550_STB810 is not set |
27 | # CONFIG_PMC_MSP is not set | 27 | # CONFIG_PMC_MSP is not set |
28 | # CONFIG_PMC_YOSEMITE is not set | 28 | # CONFIG_PMC_YOSEMITE is not set |
29 | # CONFIG_QEMU is not set | ||
30 | # CONFIG_SGI_IP22 is not set | 29 | # CONFIG_SGI_IP22 is not set |
31 | # CONFIG_SGI_IP27 is not set | 30 | # CONFIG_SGI_IP27 is not set |
32 | # CONFIG_SGI_IP32 is not set | 31 | # CONFIG_SGI_IP32 is not set |
@@ -37,7 +36,6 @@ CONFIG_MIPS_SIM=y | |||
37 | # CONFIG_SIBYTE_SWARM is not set | 36 | # CONFIG_SIBYTE_SWARM is not set |
38 | # CONFIG_SIBYTE_LITTLESUR is not set | 37 | # CONFIG_SIBYTE_LITTLESUR is not set |
39 | # CONFIG_SIBYTE_SENTOSA is not set | 38 | # CONFIG_SIBYTE_SENTOSA is not set |
40 | # CONFIG_SIBYTE_PTSWARM is not set | ||
41 | # CONFIG_SIBYTE_BIGSUR is not set | 39 | # CONFIG_SIBYTE_BIGSUR is not set |
42 | # CONFIG_SNI_RM is not set | 40 | # CONFIG_SNI_RM is not set |
43 | # CONFIG_TOSHIBA_JMR3927 is not set | 41 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig index 8334350d7229..27e23fc9363a 100644 --- a/arch/mips/configs/mpc30x_defconfig +++ b/arch/mips/configs/mpc30x_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MACH_VR41XX=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MACH_VR41XX=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/msp71xx_defconfig b/arch/mips/configs/msp71xx_defconfig index 69278999c9a2..b12b73f6d74f 100644 --- a/arch/mips/configs/msp71xx_defconfig +++ b/arch/mips/configs/msp71xx_defconfig | |||
@@ -38,7 +38,6 @@ CONFIG_ZONE_DMA=y | |||
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | CONFIG_PMC_MSP=y | 39 | CONFIG_PMC_MSP=y |
40 | # CONFIG_PMC_YOSEMITE is not set | 40 | # CONFIG_PMC_YOSEMITE is not set |
41 | # CONFIG_QEMU is not set | ||
42 | # CONFIG_MARKEINS is not set | 41 | # CONFIG_MARKEINS is not set |
43 | # CONFIG_SGI_IP22 is not set | 42 | # CONFIG_SGI_IP22 is not set |
44 | # CONFIG_SGI_IP27 is not set | 43 | # CONFIG_SGI_IP27 is not set |
@@ -48,7 +47,6 @@ CONFIG_PMC_MSP=y | |||
48 | # CONFIG_SIBYTE_SENTOSA is not set | 47 | # CONFIG_SIBYTE_SENTOSA is not set |
49 | # CONFIG_SIBYTE_RHONE is not set | 48 | # CONFIG_SIBYTE_RHONE is not set |
50 | # CONFIG_SIBYTE_CARMEL is not set | 49 | # CONFIG_SIBYTE_CARMEL is not set |
51 | # CONFIG_SIBYTE_PTSWARM is not set | ||
52 | # CONFIG_SIBYTE_LITTLESUR is not set | 50 | # CONFIG_SIBYTE_LITTLESUR is not set |
53 | # CONFIG_SIBYTE_CRHINE is not set | 51 | # CONFIG_SIBYTE_CRHINE is not set |
54 | # CONFIG_SIBYTE_CRHONE is not set | 52 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig index b536d7c63790..fa3aa3919448 100644 --- a/arch/mips/configs/mtx1_defconfig +++ b/arch/mips/configs/mtx1_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MACH_ALCHEMY=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MACH_ALCHEMY=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
@@ -1617,6 +1615,7 @@ CONFIG_INPUT_EVBUG=m | |||
1617 | # | 1615 | # |
1618 | CONFIG_INPUT_KEYBOARD=y | 1616 | CONFIG_INPUT_KEYBOARD=y |
1619 | CONFIG_KEYBOARD_ATKBD=y | 1617 | CONFIG_KEYBOARD_ATKBD=y |
1618 | CONFIG_KEYBOARD_GPIO=y | ||
1620 | CONFIG_KEYBOARD_SUNKBD=m | 1619 | CONFIG_KEYBOARD_SUNKBD=m |
1621 | CONFIG_KEYBOARD_LKKBD=m | 1620 | CONFIG_KEYBOARD_LKKBD=m |
1622 | CONFIG_KEYBOARD_XTKBD=m | 1621 | CONFIG_KEYBOARD_XTKBD=m |
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig index 703d28db05b9..1d0157d3a5bb 100644 --- a/arch/mips/configs/pb1100_defconfig +++ b/arch/mips/configs/pb1100_defconfig | |||
@@ -38,7 +38,6 @@ CONFIG_MIPS_PB1100=y | |||
38 | # CONFIG_PNX8550_STB810 is not set | 38 | # CONFIG_PNX8550_STB810 is not set |
39 | # CONFIG_MACH_VR41XX is not set | 39 | # CONFIG_MACH_VR41XX is not set |
40 | # CONFIG_PMC_YOSEMITE is not set | 40 | # CONFIG_PMC_YOSEMITE is not set |
41 | # CONFIG_QEMU is not set | ||
42 | # CONFIG_MARKEINS is not set | 41 | # CONFIG_MARKEINS is not set |
43 | # CONFIG_SGI_IP22 is not set | 42 | # CONFIG_SGI_IP22 is not set |
44 | # CONFIG_SGI_IP27 is not set | 43 | # CONFIG_SGI_IP27 is not set |
@@ -48,7 +47,6 @@ CONFIG_MIPS_PB1100=y | |||
48 | # CONFIG_SIBYTE_SENTOSA is not set | 47 | # CONFIG_SIBYTE_SENTOSA is not set |
49 | # CONFIG_SIBYTE_RHONE is not set | 48 | # CONFIG_SIBYTE_RHONE is not set |
50 | # CONFIG_SIBYTE_CARMEL is not set | 49 | # CONFIG_SIBYTE_CARMEL is not set |
51 | # CONFIG_SIBYTE_PTSWARM is not set | ||
52 | # CONFIG_SIBYTE_LITTLESUR is not set | 50 | # CONFIG_SIBYTE_LITTLESUR is not set |
53 | # CONFIG_SIBYTE_CRHINE is not set | 51 | # CONFIG_SIBYTE_CRHINE is not set |
54 | # CONFIG_SIBYTE_CRHONE is not set | 52 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig index 82f0c5cee0dc..d0491a05ee58 100644 --- a/arch/mips/configs/pb1500_defconfig +++ b/arch/mips/configs/pb1500_defconfig | |||
@@ -38,7 +38,6 @@ CONFIG_MIPS_PB1500=y | |||
38 | # CONFIG_PNX8550_STB810 is not set | 38 | # CONFIG_PNX8550_STB810 is not set |
39 | # CONFIG_MACH_VR41XX is not set | 39 | # CONFIG_MACH_VR41XX is not set |
40 | # CONFIG_PMC_YOSEMITE is not set | 40 | # CONFIG_PMC_YOSEMITE is not set |
41 | # CONFIG_QEMU is not set | ||
42 | # CONFIG_MARKEINS is not set | 41 | # CONFIG_MARKEINS is not set |
43 | # CONFIG_SGI_IP22 is not set | 42 | # CONFIG_SGI_IP22 is not set |
44 | # CONFIG_SGI_IP27 is not set | 43 | # CONFIG_SGI_IP27 is not set |
@@ -48,7 +47,6 @@ CONFIG_MIPS_PB1500=y | |||
48 | # CONFIG_SIBYTE_SENTOSA is not set | 47 | # CONFIG_SIBYTE_SENTOSA is not set |
49 | # CONFIG_SIBYTE_RHONE is not set | 48 | # CONFIG_SIBYTE_RHONE is not set |
50 | # CONFIG_SIBYTE_CARMEL is not set | 49 | # CONFIG_SIBYTE_CARMEL is not set |
51 | # CONFIG_SIBYTE_PTSWARM is not set | ||
52 | # CONFIG_SIBYTE_LITTLESUR is not set | 50 | # CONFIG_SIBYTE_LITTLESUR is not set |
53 | # CONFIG_SIBYTE_CRHINE is not set | 51 | # CONFIG_SIBYTE_CRHINE is not set |
54 | # CONFIG_SIBYTE_CRHONE is not set | 52 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig index 147a4fc7fdd8..16d78d3cd2aa 100644 --- a/arch/mips/configs/pb1550_defconfig +++ b/arch/mips/configs/pb1550_defconfig | |||
@@ -38,7 +38,6 @@ CONFIG_MIPS_PB1550=y | |||
38 | # CONFIG_PNX8550_STB810 is not set | 38 | # CONFIG_PNX8550_STB810 is not set |
39 | # CONFIG_MACH_VR41XX is not set | 39 | # CONFIG_MACH_VR41XX is not set |
40 | # CONFIG_PMC_YOSEMITE is not set | 40 | # CONFIG_PMC_YOSEMITE is not set |
41 | # CONFIG_QEMU is not set | ||
42 | # CONFIG_MARKEINS is not set | 41 | # CONFIG_MARKEINS is not set |
43 | # CONFIG_SGI_IP22 is not set | 42 | # CONFIG_SGI_IP22 is not set |
44 | # CONFIG_SGI_IP27 is not set | 43 | # CONFIG_SGI_IP27 is not set |
@@ -48,7 +47,6 @@ CONFIG_MIPS_PB1550=y | |||
48 | # CONFIG_SIBYTE_SENTOSA is not set | 47 | # CONFIG_SIBYTE_SENTOSA is not set |
49 | # CONFIG_SIBYTE_RHONE is not set | 48 | # CONFIG_SIBYTE_RHONE is not set |
50 | # CONFIG_SIBYTE_CARMEL is not set | 49 | # CONFIG_SIBYTE_CARMEL is not set |
51 | # CONFIG_SIBYTE_PTSWARM is not set | ||
52 | # CONFIG_SIBYTE_LITTLESUR is not set | 50 | # CONFIG_SIBYTE_LITTLESUR is not set |
53 | # CONFIG_SIBYTE_CRHINE is not set | 51 | # CONFIG_SIBYTE_CRHINE is not set |
54 | # CONFIG_SIBYTE_CRHONE is not set | 52 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig index f6906b069e04..518a60892b78 100644 --- a/arch/mips/configs/pnx8550-jbs_defconfig +++ b/arch/mips/configs/pnx8550-jbs_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_PNX8550_JBS=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_PNX8550_JBS=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/pnx8550-stb810_defconfig b/arch/mips/configs/pnx8550-stb810_defconfig index b741f81696fb..68351eb81bc8 100644 --- a/arch/mips/configs/pnx8550-stb810_defconfig +++ b/arch/mips/configs/pnx8550-stb810_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_ZONE_DMA=y | |||
37 | CONFIG_PNX8550_STB810=y | 37 | CONFIG_PNX8550_STB810=y |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_PNX8550_STB810=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig index b3caf5125c15..72ca147f9422 100644 --- a/arch/mips/configs/qemu_defconfig +++ b/arch/mips/configs/qemu_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_ZONE_DMA=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | CONFIG_QEMU=y | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_QEMU=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/rbhma4200_defconfig b/arch/mips/configs/rbhma4200_defconfig index 9383a598094b..470f6f4d3ea2 100644 --- a/arch/mips/configs/rbhma4200_defconfig +++ b/arch/mips/configs/rbhma4200_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MIPS=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MIPS=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
@@ -431,7 +429,6 @@ CONFIG_UNIX98_PTYS=y | |||
431 | CONFIG_LEGACY_PTYS=y | 429 | CONFIG_LEGACY_PTYS=y |
432 | CONFIG_LEGACY_PTY_COUNT=256 | 430 | CONFIG_LEGACY_PTY_COUNT=256 |
433 | # CONFIG_IPMI_HANDLER is not set | 431 | # CONFIG_IPMI_HANDLER is not set |
434 | # CONFIG_WATCHDOG is not set | ||
435 | # CONFIG_HW_RANDOM is not set | 432 | # CONFIG_HW_RANDOM is not set |
436 | # CONFIG_RTC is not set | 433 | # CONFIG_RTC is not set |
437 | # CONFIG_R3964 is not set | 434 | # CONFIG_R3964 is not set |
@@ -449,6 +446,20 @@ CONFIG_DEVPORT=y | |||
449 | # CONFIG_W1 is not set | 446 | # CONFIG_W1 is not set |
450 | # CONFIG_POWER_SUPPLY is not set | 447 | # CONFIG_POWER_SUPPLY is not set |
451 | # CONFIG_HWMON is not set | 448 | # CONFIG_HWMON is not set |
449 | CONFIG_WATCHDOG=y | ||
450 | # CONFIG_WATCHDOG_NOWAYOUT is not set | ||
451 | |||
452 | # | ||
453 | # Watchdog Device Drivers | ||
454 | # | ||
455 | # CONFIG_SOFT_WATCHDOG is not set | ||
456 | CONFIG_TXX9_WDT=m | ||
457 | |||
458 | # | ||
459 | # PCI-based Watchdog Cards | ||
460 | # | ||
461 | # CONFIG_PCIPCWATCHDOG is not set | ||
462 | # CONFIG_WDTPCI is not set | ||
452 | 463 | ||
453 | # | 464 | # |
454 | # Multifunction device drivers | 465 | # Multifunction device drivers |
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig index d1b56cc0fd7c..5a39f56b175e 100644 --- a/arch/mips/configs/rbhma4500_defconfig +++ b/arch/mips/configs/rbhma4500_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MIPS=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MIPS=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
@@ -450,7 +448,6 @@ CONFIG_UNIX98_PTYS=y | |||
450 | CONFIG_LEGACY_PTYS=y | 448 | CONFIG_LEGACY_PTYS=y |
451 | CONFIG_LEGACY_PTY_COUNT=256 | 449 | CONFIG_LEGACY_PTY_COUNT=256 |
452 | # CONFIG_IPMI_HANDLER is not set | 450 | # CONFIG_IPMI_HANDLER is not set |
453 | # CONFIG_WATCHDOG is not set | ||
454 | # CONFIG_HW_RANDOM is not set | 451 | # CONFIG_HW_RANDOM is not set |
455 | # CONFIG_RTC is not set | 452 | # CONFIG_RTC is not set |
456 | # CONFIG_R3964 is not set | 453 | # CONFIG_R3964 is not set |
@@ -479,6 +476,20 @@ CONFIG_SPI_AT25=y | |||
479 | # CONFIG_W1 is not set | 476 | # CONFIG_W1 is not set |
480 | # CONFIG_POWER_SUPPLY is not set | 477 | # CONFIG_POWER_SUPPLY is not set |
481 | # CONFIG_HWMON is not set | 478 | # CONFIG_HWMON is not set |
479 | CONFIG_WATCHDOG=y | ||
480 | # CONFIG_WATCHDOG_NOWAYOUT is not set | ||
481 | |||
482 | # | ||
483 | # Watchdog Device Drivers | ||
484 | # | ||
485 | # CONFIG_SOFT_WATCHDOG is not set | ||
486 | CONFIG_TXX9_WDT=m | ||
487 | |||
488 | # | ||
489 | # PCI-based Watchdog Cards | ||
490 | # | ||
491 | # CONFIG_PCIPCWATCHDOG is not set | ||
492 | # CONFIG_WDTPCI is not set | ||
482 | 493 | ||
483 | # | 494 | # |
484 | # Multifunction device drivers | 495 | # Multifunction device drivers |
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig index fc388118b114..56371b860eb0 100644 --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_ZONE_DMA=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_ZONE_DMA=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig index c2798229cbfb..117470b60e34 100644 --- a/arch/mips/configs/sb1250-swarm_defconfig +++ b/arch/mips/configs/sb1250-swarm_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_ZONE_DMA=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_SIBYTE_SWARM=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig index 2b6282d132a8..3ee75b15c0b0 100644 --- a/arch/mips/configs/sead_defconfig +++ b/arch/mips/configs/sead_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_MIPS_SEAD=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_MIPS_SEAD=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/tb0219_defconfig b/arch/mips/configs/tb0219_defconfig index 326aa7aa40ea..af82e1a1823c 100644 --- a/arch/mips/configs/tb0219_defconfig +++ b/arch/mips/configs/tb0219_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MACH_VR41XX=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MACH_VR41XX=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig index 9fd0faeacf53..a95385b24546 100644 --- a/arch/mips/configs/tb0226_defconfig +++ b/arch/mips/configs/tb0226_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MACH_VR41XX=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MACH_VR41XX=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig index 499b6bd7ee68..40d4a40a970e 100644 --- a/arch/mips/configs/tb0287_defconfig +++ b/arch/mips/configs/tb0287_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MACH_VR41XX=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MACH_VR41XX=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig index b52256ca0b53..edf90b321fe6 100644 --- a/arch/mips/configs/workpad_defconfig +++ b/arch/mips/configs/workpad_defconfig | |||
@@ -24,7 +24,6 @@ CONFIG_MACH_VR41XX=y | |||
24 | # CONFIG_PNX8550_STB810 is not set | 24 | # CONFIG_PNX8550_STB810 is not set |
25 | # CONFIG_PMC_MSP is not set | 25 | # CONFIG_PMC_MSP is not set |
26 | # CONFIG_PMC_YOSEMITE is not set | 26 | # CONFIG_PMC_YOSEMITE is not set |
27 | # CONFIG_QEMU is not set | ||
28 | # CONFIG_SGI_IP22 is not set | 27 | # CONFIG_SGI_IP22 is not set |
29 | # CONFIG_SGI_IP27 is not set | 28 | # CONFIG_SGI_IP27 is not set |
30 | # CONFIG_SGI_IP32 is not set | 29 | # CONFIG_SGI_IP32 is not set |
@@ -35,7 +34,6 @@ CONFIG_MACH_VR41XX=y | |||
35 | # CONFIG_SIBYTE_SWARM is not set | 34 | # CONFIG_SIBYTE_SWARM is not set |
36 | # CONFIG_SIBYTE_LITTLESUR is not set | 35 | # CONFIG_SIBYTE_LITTLESUR is not set |
37 | # CONFIG_SIBYTE_SENTOSA is not set | 36 | # CONFIG_SIBYTE_SENTOSA is not set |
38 | # CONFIG_SIBYTE_PTSWARM is not set | ||
39 | # CONFIG_SIBYTE_BIGSUR is not set | 37 | # CONFIG_SIBYTE_BIGSUR is not set |
40 | # CONFIG_SNI_RM is not set | 38 | # CONFIG_SNI_RM is not set |
41 | # CONFIG_TOSHIBA_JMR3927 is not set | 39 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig index 7e410e10fed7..2e3c683b2052 100644 --- a/arch/mips/configs/wrppmc_defconfig +++ b/arch/mips/configs/wrppmc_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_WR_PPMC=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | # CONFIG_PMC_YOSEMITE is not set | 39 | # CONFIG_PMC_YOSEMITE is not set |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_WR_PPMC=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig index acaf0e21bb00..b6178ffbc523 100644 --- a/arch/mips/configs/yosemite_defconfig +++ b/arch/mips/configs/yosemite_defconfig | |||
@@ -37,7 +37,6 @@ CONFIG_ZONE_DMA=y | |||
37 | # CONFIG_PNX8550_STB810 is not set | 37 | # CONFIG_PNX8550_STB810 is not set |
38 | # CONFIG_MACH_VR41XX is not set | 38 | # CONFIG_MACH_VR41XX is not set |
39 | CONFIG_PMC_YOSEMITE=y | 39 | CONFIG_PMC_YOSEMITE=y |
40 | # CONFIG_QEMU is not set | ||
41 | # CONFIG_MARKEINS is not set | 40 | # CONFIG_MARKEINS is not set |
42 | # CONFIG_SGI_IP22 is not set | 41 | # CONFIG_SGI_IP22 is not set |
43 | # CONFIG_SGI_IP27 is not set | 42 | # CONFIG_SGI_IP27 is not set |
@@ -47,7 +46,6 @@ CONFIG_PMC_YOSEMITE=y | |||
47 | # CONFIG_SIBYTE_SENTOSA is not set | 46 | # CONFIG_SIBYTE_SENTOSA is not set |
48 | # CONFIG_SIBYTE_RHONE is not set | 47 | # CONFIG_SIBYTE_RHONE is not set |
49 | # CONFIG_SIBYTE_CARMEL is not set | 48 | # CONFIG_SIBYTE_CARMEL is not set |
50 | # CONFIG_SIBYTE_PTSWARM is not set | ||
51 | # CONFIG_SIBYTE_LITTLESUR is not set | 49 | # CONFIG_SIBYTE_LITTLESUR is not set |
52 | # CONFIG_SIBYTE_CRHINE is not set | 50 | # CONFIG_SIBYTE_CRHINE is not set |
53 | # CONFIG_SIBYTE_CRHONE is not set | 51 | # CONFIG_SIBYTE_CRHONE is not set |
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index 820e5331205f..60349062595a 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c | |||
@@ -161,7 +161,6 @@ static cycle_t dec_ioasic_hpt_read(void) | |||
161 | 161 | ||
162 | void __init plat_time_init(void) | 162 | void __init plat_time_init(void) |
163 | { | 163 | { |
164 | mips_timer_state = dec_timer_state; | ||
165 | mips_timer_ack = dec_timer_ack; | 164 | mips_timer_ack = dec_timer_ack; |
166 | 165 | ||
167 | if (!cpu_has_counter && IOASIC) | 166 | if (!cpu_has_counter && IOASIC) |
diff --git a/arch/mips/defconfig b/arch/mips/defconfig index 670039bb1a7c..4f5e56c9335e 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig | |||
@@ -25,7 +25,6 @@ CONFIG_ZONE_DMA=y | |||
25 | # CONFIG_PNX8550_STB810 is not set | 25 | # CONFIG_PNX8550_STB810 is not set |
26 | # CONFIG_PMC_MSP is not set | 26 | # CONFIG_PMC_MSP is not set |
27 | # CONFIG_PMC_YOSEMITE is not set | 27 | # CONFIG_PMC_YOSEMITE is not set |
28 | # CONFIG_QEMU is not set | ||
29 | CONFIG_SGI_IP22=y | 28 | CONFIG_SGI_IP22=y |
30 | # CONFIG_SGI_IP27 is not set | 29 | # CONFIG_SGI_IP27 is not set |
31 | # CONFIG_SGI_IP32 is not set | 30 | # CONFIG_SGI_IP32 is not set |
@@ -36,7 +35,6 @@ CONFIG_SGI_IP22=y | |||
36 | # CONFIG_SIBYTE_SWARM is not set | 35 | # CONFIG_SIBYTE_SWARM is not set |
37 | # CONFIG_SIBYTE_LITTLESUR is not set | 36 | # CONFIG_SIBYTE_LITTLESUR is not set |
38 | # CONFIG_SIBYTE_SENTOSA is not set | 37 | # CONFIG_SIBYTE_SENTOSA is not set |
39 | # CONFIG_SIBYTE_PTSWARM is not set | ||
40 | # CONFIG_SIBYTE_BIGSUR is not set | 38 | # CONFIG_SIBYTE_BIGSUR is not set |
41 | # CONFIG_SNI_RM is not set | 39 | # CONFIG_SNI_RM is not set |
42 | # CONFIG_TOSHIBA_JMR3927 is not set | 40 | # CONFIG_TOSHIBA_JMR3927 is not set |
diff --git a/arch/mips/fw/arc/cmdline.c b/arch/mips/fw/arc/cmdline.c index fd604ef28823..4ca4eef934a5 100644 --- a/arch/mips/fw/arc/cmdline.c +++ b/arch/mips/fw/arc/cmdline.c | |||
@@ -52,7 +52,7 @@ static char * __init move_firmware_args(char* cp) | |||
52 | strcat(cp, used_arc[i][1]); | 52 | strcat(cp, used_arc[i][1]); |
53 | cp += strlen(used_arc[i][1]); | 53 | cp += strlen(used_arc[i][1]); |
54 | /* ... and now the argument */ | 54 | /* ... and now the argument */ |
55 | s = strstr(prom_argv(actr), "="); | 55 | s = strchr(prom_argv(actr), '='); |
56 | if (s) { | 56 | if (s) { |
57 | s++; | 57 | s++; |
58 | strcpy(cp, s); | 58 | strcpy(cp, s); |
diff --git a/arch/mips/fw/arc/init.c b/arch/mips/fw/arc/init.c index e2f75b13312f..3ad8788b6eaa 100644 --- a/arch/mips/fw/arc/init.c +++ b/arch/mips/fw/arc/init.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <asm/bootinfo.h> | 13 | #include <asm/bootinfo.h> |
14 | #include <asm/sgialib.h> | 14 | #include <asm/sgialib.h> |
15 | #include <asm/smp-ops.h> | ||
15 | 16 | ||
16 | #undef DEBUG_PROM_INIT | 17 | #undef DEBUG_PROM_INIT |
17 | 18 | ||
@@ -48,4 +49,11 @@ void __init prom_init(void) | |||
48 | ArcRead(0, &c, 1, &cnt); | 49 | ArcRead(0, &c, 1, &cnt); |
49 | ArcEnterInteractiveMode(); | 50 | ArcEnterInteractiveMode(); |
50 | #endif | 51 | #endif |
52 | #ifdef CONFIG_SGI_IP27 | ||
53 | { | ||
54 | extern struct plat_smp_ops ip27_smp_ops; | ||
55 | |||
56 | register_smp_ops(&ip27_smp_ops); | ||
57 | } | ||
58 | #endif | ||
51 | } | 59 | } |
diff --git a/arch/mips/fw/cfe/cfe_api.c b/arch/mips/fw/cfe/cfe_api.c index a9f69e4e40ac..717db74f7c6e 100644 --- a/arch/mips/fw/cfe/cfe_api.c +++ b/arch/mips/fw/cfe/cfe_api.c | |||
@@ -16,19 +16,16 @@ | |||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | /* ********************************************************************* | 19 | /* |
20 | * | 20 | * |
21 | * Broadcom Common Firmware Environment (CFE) | 21 | * Broadcom Common Firmware Environment (CFE) |
22 | * | 22 | * |
23 | * Device Function stubs File: cfe_api.c | 23 | * This module contains device function stubs (small routines to |
24 | * | 24 | * call the standard "iocb" interface entry point to CFE). |
25 | * This module contains device function stubs (small routines to | 25 | * There should be one routine here per iocb function call. |
26 | * call the standard "iocb" interface entry point to CFE). | 26 | * |
27 | * There should be one routine here per iocb function call. | 27 | * Authors: Mitch Lichtenberg, Chris Demetriou |
28 | * | 28 | */ |
29 | * Authors: Mitch Lichtenberg, Chris Demetriou | ||
30 | * | ||
31 | ********************************************************************* */ | ||
32 | 29 | ||
33 | #include <asm/fw/cfe/cfe_api.h> | 30 | #include <asm/fw/cfe/cfe_api.h> |
34 | #include "cfe_api_int.h" | 31 | #include "cfe_api_int.h" |
@@ -37,12 +34,8 @@ | |||
37 | #define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n)) | 34 | #define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n)) |
38 | #define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x)) | 35 | #define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x)) |
39 | 36 | ||
40 | #ifdef CFE_API_IMPL_NAMESPACE | 37 | int cfe_iocb_dispatch(struct cfe_xiocb *xiocb); |
41 | #define cfe_iocb_dispatch(a) __cfe_iocb_dispatch(a) | ||
42 | #endif | ||
43 | int cfe_iocb_dispatch(cfe_xiocb_t * xiocb); | ||
44 | 38 | ||
45 | #if defined(CFE_API_common) || defined(CFE_API_ALL) | ||
46 | /* | 39 | /* |
47 | * Declare the dispatch function with args of "intptr_t". | 40 | * Declare the dispatch function with args of "intptr_t". |
48 | * This makes sure whatever model we're compiling in | 41 | * This makes sure whatever model we're compiling in |
@@ -53,27 +46,25 @@ int cfe_iocb_dispatch(cfe_xiocb_t * xiocb); | |||
53 | */ | 46 | */ |
54 | 47 | ||
55 | static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb) = 0; | 48 | static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb) = 0; |
56 | static cfe_xuint_t cfe_handle = 0; | 49 | static u64 cfe_handle = 0; |
57 | 50 | ||
58 | int cfe_init(cfe_xuint_t handle, cfe_xuint_t ept) | 51 | int cfe_init(u64 handle, u64 ept) |
59 | { | 52 | { |
60 | cfe_dispfunc = NATIVE_FROM_XPTR(ept); | 53 | cfe_dispfunc = NATIVE_FROM_XPTR(ept); |
61 | cfe_handle = handle; | 54 | cfe_handle = handle; |
62 | return 0; | 55 | return 0; |
63 | } | 56 | } |
64 | 57 | ||
65 | int cfe_iocb_dispatch(cfe_xiocb_t * xiocb) | 58 | int cfe_iocb_dispatch(struct cfe_xiocb * xiocb) |
66 | { | 59 | { |
67 | if (!cfe_dispfunc) | 60 | if (!cfe_dispfunc) |
68 | return -1; | 61 | return -1; |
69 | return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb); | 62 | return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb); |
70 | } | 63 | } |
71 | #endif /* CFE_API_common || CFE_API_ALL */ | ||
72 | 64 | ||
73 | #if defined(CFE_API_close) || defined(CFE_API_ALL) | ||
74 | int cfe_close(int handle) | 65 | int cfe_close(int handle) |
75 | { | 66 | { |
76 | cfe_xiocb_t xiocb; | 67 | struct cfe_xiocb xiocb; |
77 | 68 | ||
78 | xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE; | 69 | xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE; |
79 | xiocb.xiocb_status = 0; | 70 | xiocb.xiocb_status = 0; |
@@ -86,18 +77,16 @@ int cfe_close(int handle) | |||
86 | return xiocb.xiocb_status; | 77 | return xiocb.xiocb_status; |
87 | 78 | ||
88 | } | 79 | } |
89 | #endif /* CFE_API_close || CFE_API_ALL */ | ||
90 | 80 | ||
91 | #if defined(CFE_API_cpu_start) || defined(CFE_API_ALL) | ||
92 | int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1) | 81 | int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1) |
93 | { | 82 | { |
94 | cfe_xiocb_t xiocb; | 83 | struct cfe_xiocb xiocb; |
95 | 84 | ||
96 | xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL; | 85 | xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL; |
97 | xiocb.xiocb_status = 0; | 86 | xiocb.xiocb_status = 0; |
98 | xiocb.xiocb_handle = 0; | 87 | xiocb.xiocb_handle = 0; |
99 | xiocb.xiocb_flags = 0; | 88 | xiocb.xiocb_flags = 0; |
100 | xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t); | 89 | xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl); |
101 | xiocb.plist.xiocb_cpuctl.cpu_number = cpu; | 90 | xiocb.plist.xiocb_cpuctl.cpu_number = cpu; |
102 | xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START; | 91 | xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START; |
103 | xiocb.plist.xiocb_cpuctl.gp_val = gp; | 92 | xiocb.plist.xiocb_cpuctl.gp_val = gp; |
@@ -109,18 +98,16 @@ int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1) | |||
109 | 98 | ||
110 | return xiocb.xiocb_status; | 99 | return xiocb.xiocb_status; |
111 | } | 100 | } |
112 | #endif /* CFE_API_cpu_start || CFE_API_ALL */ | ||
113 | 101 | ||
114 | #if defined(CFE_API_cpu_stop) || defined(CFE_API_ALL) | ||
115 | int cfe_cpu_stop(int cpu) | 102 | int cfe_cpu_stop(int cpu) |
116 | { | 103 | { |
117 | cfe_xiocb_t xiocb; | 104 | struct cfe_xiocb xiocb; |
118 | 105 | ||
119 | xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL; | 106 | xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL; |
120 | xiocb.xiocb_status = 0; | 107 | xiocb.xiocb_status = 0; |
121 | xiocb.xiocb_handle = 0; | 108 | xiocb.xiocb_handle = 0; |
122 | xiocb.xiocb_flags = 0; | 109 | xiocb.xiocb_flags = 0; |
123 | xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t); | 110 | xiocb.xiocb_psize = sizeof(struct xiocb_cpuctl); |
124 | xiocb.plist.xiocb_cpuctl.cpu_number = cpu; | 111 | xiocb.plist.xiocb_cpuctl.cpu_number = cpu; |
125 | xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP; | 112 | xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP; |
126 | 113 | ||
@@ -128,18 +115,16 @@ int cfe_cpu_stop(int cpu) | |||
128 | 115 | ||
129 | return xiocb.xiocb_status; | 116 | return xiocb.xiocb_status; |
130 | } | 117 | } |
131 | #endif /* CFE_API_cpu_stop || CFE_API_ALL */ | ||
132 | 118 | ||
133 | #if defined(CFE_API_enumenv) || defined(CFE_API_ALL) | ||
134 | int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen) | 119 | int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen) |
135 | { | 120 | { |
136 | cfe_xiocb_t xiocb; | 121 | struct cfe_xiocb xiocb; |
137 | 122 | ||
138 | xiocb.xiocb_fcode = CFE_CMD_ENV_SET; | 123 | xiocb.xiocb_fcode = CFE_CMD_ENV_SET; |
139 | xiocb.xiocb_status = 0; | 124 | xiocb.xiocb_status = 0; |
140 | xiocb.xiocb_handle = 0; | 125 | xiocb.xiocb_handle = 0; |
141 | xiocb.xiocb_flags = 0; | 126 | xiocb.xiocb_flags = 0; |
142 | xiocb.xiocb_psize = sizeof(xiocb_envbuf_t); | 127 | xiocb.xiocb_psize = sizeof(struct xiocb_envbuf); |
143 | xiocb.plist.xiocb_envbuf.enum_idx = idx; | 128 | xiocb.plist.xiocb_envbuf.enum_idx = idx; |
144 | xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name); | 129 | xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name); |
145 | xiocb.plist.xiocb_envbuf.name_length = namelen; | 130 | xiocb.plist.xiocb_envbuf.name_length = namelen; |
@@ -150,20 +135,17 @@ int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen) | |||
150 | 135 | ||
151 | return xiocb.xiocb_status; | 136 | return xiocb.xiocb_status; |
152 | } | 137 | } |
153 | #endif /* CFE_API_enumenv || CFE_API_ALL */ | ||
154 | 138 | ||
155 | #if defined(CFE_API_enummem) || defined(CFE_API_ALL) | ||
156 | int | 139 | int |
157 | cfe_enummem(int idx, int flags, cfe_xuint_t * start, cfe_xuint_t * length, | 140 | cfe_enummem(int idx, int flags, u64 *start, u64 *length, u64 *type) |
158 | cfe_xuint_t * type) | ||
159 | { | 141 | { |
160 | cfe_xiocb_t xiocb; | 142 | struct cfe_xiocb xiocb; |
161 | 143 | ||
162 | xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM; | 144 | xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM; |
163 | xiocb.xiocb_status = 0; | 145 | xiocb.xiocb_status = 0; |
164 | xiocb.xiocb_handle = 0; | 146 | xiocb.xiocb_handle = 0; |
165 | xiocb.xiocb_flags = flags; | 147 | xiocb.xiocb_flags = flags; |
166 | xiocb.xiocb_psize = sizeof(xiocb_meminfo_t); | 148 | xiocb.xiocb_psize = sizeof(struct xiocb_meminfo); |
167 | xiocb.plist.xiocb_meminfo.mi_idx = idx; | 149 | xiocb.plist.xiocb_meminfo.mi_idx = idx; |
168 | 150 | ||
169 | cfe_iocb_dispatch(&xiocb); | 151 | cfe_iocb_dispatch(&xiocb); |
@@ -177,30 +159,26 @@ cfe_enummem(int idx, int flags, cfe_xuint_t * start, cfe_xuint_t * length, | |||
177 | 159 | ||
178 | return 0; | 160 | return 0; |
179 | } | 161 | } |
180 | #endif /* CFE_API_enummem || CFE_API_ALL */ | ||
181 | 162 | ||
182 | #if defined(CFE_API_exit) || defined(CFE_API_ALL) | ||
183 | int cfe_exit(int warm, int status) | 163 | int cfe_exit(int warm, int status) |
184 | { | 164 | { |
185 | cfe_xiocb_t xiocb; | 165 | struct cfe_xiocb xiocb; |
186 | 166 | ||
187 | xiocb.xiocb_fcode = CFE_CMD_FW_RESTART; | 167 | xiocb.xiocb_fcode = CFE_CMD_FW_RESTART; |
188 | xiocb.xiocb_status = 0; | 168 | xiocb.xiocb_status = 0; |
189 | xiocb.xiocb_handle = 0; | 169 | xiocb.xiocb_handle = 0; |
190 | xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0; | 170 | xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0; |
191 | xiocb.xiocb_psize = sizeof(xiocb_exitstat_t); | 171 | xiocb.xiocb_psize = sizeof(struct xiocb_exitstat); |
192 | xiocb.plist.xiocb_exitstat.status = status; | 172 | xiocb.plist.xiocb_exitstat.status = status; |
193 | 173 | ||
194 | cfe_iocb_dispatch(&xiocb); | 174 | cfe_iocb_dispatch(&xiocb); |
195 | 175 | ||
196 | return xiocb.xiocb_status; | 176 | return xiocb.xiocb_status; |
197 | } | 177 | } |
198 | #endif /* CFE_API_exit || CFE_API_ALL */ | ||
199 | 178 | ||
200 | #if defined(CFE_API_flushcache) || defined(CFE_API_ALL) | ||
201 | int cfe_flushcache(int flg) | 179 | int cfe_flushcache(int flg) |
202 | { | 180 | { |
203 | cfe_xiocb_t xiocb; | 181 | struct cfe_xiocb xiocb; |
204 | 182 | ||
205 | xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE; | 183 | xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE; |
206 | xiocb.xiocb_status = 0; | 184 | xiocb.xiocb_status = 0; |
@@ -212,34 +190,30 @@ int cfe_flushcache(int flg) | |||
212 | 190 | ||
213 | return xiocb.xiocb_status; | 191 | return xiocb.xiocb_status; |
214 | } | 192 | } |
215 | #endif /* CFE_API_flushcache || CFE_API_ALL */ | ||
216 | 193 | ||
217 | #if defined(CFE_API_getdevinfo) || defined(CFE_API_ALL) | ||
218 | int cfe_getdevinfo(char *name) | 194 | int cfe_getdevinfo(char *name) |
219 | { | 195 | { |
220 | cfe_xiocb_t xiocb; | 196 | struct cfe_xiocb xiocb; |
221 | 197 | ||
222 | xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO; | 198 | xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO; |
223 | xiocb.xiocb_status = 0; | 199 | xiocb.xiocb_status = 0; |
224 | xiocb.xiocb_handle = 0; | 200 | xiocb.xiocb_handle = 0; |
225 | xiocb.xiocb_flags = 0; | 201 | xiocb.xiocb_flags = 0; |
226 | xiocb.xiocb_psize = sizeof(xiocb_buffer_t); | 202 | xiocb.xiocb_psize = sizeof(struct xiocb_buffer); |
227 | xiocb.plist.xiocb_buffer.buf_offset = 0; | 203 | xiocb.plist.xiocb_buffer.buf_offset = 0; |
228 | xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name); | 204 | xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name); |
229 | xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name); | 205 | xiocb.plist.xiocb_buffer.buf_length = strlen(name); |
230 | 206 | ||
231 | cfe_iocb_dispatch(&xiocb); | 207 | cfe_iocb_dispatch(&xiocb); |
232 | 208 | ||
233 | if (xiocb.xiocb_status < 0) | 209 | if (xiocb.xiocb_status < 0) |
234 | return xiocb.xiocb_status; | 210 | return xiocb.xiocb_status; |
235 | return xiocb.plist.xiocb_buffer.buf_devflags; | 211 | return xiocb.plist.xiocb_buffer.buf_ioctlcmd; |
236 | } | 212 | } |
237 | #endif /* CFE_API_getdevinfo || CFE_API_ALL */ | ||
238 | 213 | ||
239 | #if defined(CFE_API_getenv) || defined(CFE_API_ALL) | ||
240 | int cfe_getenv(char *name, char *dest, int destlen) | 214 | int cfe_getenv(char *name, char *dest, int destlen) |
241 | { | 215 | { |
242 | cfe_xiocb_t xiocb; | 216 | struct cfe_xiocb xiocb; |
243 | 217 | ||
244 | *dest = 0; | 218 | *dest = 0; |
245 | 219 | ||
@@ -247,10 +221,10 @@ int cfe_getenv(char *name, char *dest, int destlen) | |||
247 | xiocb.xiocb_status = 0; | 221 | xiocb.xiocb_status = 0; |
248 | xiocb.xiocb_handle = 0; | 222 | xiocb.xiocb_handle = 0; |
249 | xiocb.xiocb_flags = 0; | 223 | xiocb.xiocb_flags = 0; |
250 | xiocb.xiocb_psize = sizeof(xiocb_envbuf_t); | 224 | xiocb.xiocb_psize = sizeof(struct xiocb_envbuf); |
251 | xiocb.plist.xiocb_envbuf.enum_idx = 0; | 225 | xiocb.plist.xiocb_envbuf.enum_idx = 0; |
252 | xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name); | 226 | xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name); |
253 | xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name); | 227 | xiocb.plist.xiocb_envbuf.name_length = strlen(name); |
254 | xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest); | 228 | xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest); |
255 | xiocb.plist.xiocb_envbuf.val_length = destlen; | 229 | xiocb.plist.xiocb_envbuf.val_length = destlen; |
256 | 230 | ||
@@ -258,18 +232,16 @@ int cfe_getenv(char *name, char *dest, int destlen) | |||
258 | 232 | ||
259 | return xiocb.xiocb_status; | 233 | return xiocb.xiocb_status; |
260 | } | 234 | } |
261 | #endif /* CFE_API_getenv || CFE_API_ALL */ | ||
262 | 235 | ||
263 | #if defined(CFE_API_getfwinfo) || defined(CFE_API_ALL) | ||
264 | int cfe_getfwinfo(cfe_fwinfo_t * info) | 236 | int cfe_getfwinfo(cfe_fwinfo_t * info) |
265 | { | 237 | { |
266 | cfe_xiocb_t xiocb; | 238 | struct cfe_xiocb xiocb; |
267 | 239 | ||
268 | xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO; | 240 | xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO; |
269 | xiocb.xiocb_status = 0; | 241 | xiocb.xiocb_status = 0; |
270 | xiocb.xiocb_handle = 0; | 242 | xiocb.xiocb_handle = 0; |
271 | xiocb.xiocb_flags = 0; | 243 | xiocb.xiocb_flags = 0; |
272 | xiocb.xiocb_psize = sizeof(xiocb_fwinfo_t); | 244 | xiocb.xiocb_psize = sizeof(struct xiocb_fwinfo); |
273 | 245 | ||
274 | cfe_iocb_dispatch(&xiocb); | 246 | cfe_iocb_dispatch(&xiocb); |
275 | 247 | ||
@@ -292,12 +264,10 @@ int cfe_getfwinfo(cfe_fwinfo_t * info) | |||
292 | 264 | ||
293 | return 0; | 265 | return 0; |
294 | } | 266 | } |
295 | #endif /* CFE_API_getfwinfo || CFE_API_ALL */ | ||
296 | 267 | ||
297 | #if defined(CFE_API_getstdhandle) || defined(CFE_API_ALL) | ||
298 | int cfe_getstdhandle(int flg) | 268 | int cfe_getstdhandle(int flg) |
299 | { | 269 | { |
300 | cfe_xiocb_t xiocb; | 270 | struct cfe_xiocb xiocb; |
301 | 271 | ||
302 | xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE; | 272 | xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE; |
303 | xiocb.xiocb_status = 0; | 273 | xiocb.xiocb_status = 0; |
@@ -311,23 +281,17 @@ int cfe_getstdhandle(int flg) | |||
311 | return xiocb.xiocb_status; | 281 | return xiocb.xiocb_status; |
312 | return xiocb.xiocb_handle; | 282 | return xiocb.xiocb_handle; |
313 | } | 283 | } |
314 | #endif /* CFE_API_getstdhandle || CFE_API_ALL */ | ||
315 | 284 | ||
316 | #if defined(CFE_API_getticks) || defined(CFE_API_ALL) | ||
317 | int64_t | 285 | int64_t |
318 | #ifdef CFE_API_IMPL_NAMESPACE | ||
319 | __cfe_getticks(void) | ||
320 | #else | ||
321 | cfe_getticks(void) | 286 | cfe_getticks(void) |
322 | #endif | ||
323 | { | 287 | { |
324 | cfe_xiocb_t xiocb; | 288 | struct cfe_xiocb xiocb; |
325 | 289 | ||
326 | xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME; | 290 | xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME; |
327 | xiocb.xiocb_status = 0; | 291 | xiocb.xiocb_status = 0; |
328 | xiocb.xiocb_handle = 0; | 292 | xiocb.xiocb_handle = 0; |
329 | xiocb.xiocb_flags = 0; | 293 | xiocb.xiocb_flags = 0; |
330 | xiocb.xiocb_psize = sizeof(xiocb_time_t); | 294 | xiocb.xiocb_psize = sizeof(struct xiocb_time); |
331 | xiocb.plist.xiocb_time.ticks = 0; | 295 | xiocb.plist.xiocb_time.ticks = 0; |
332 | 296 | ||
333 | cfe_iocb_dispatch(&xiocb); | 297 | cfe_iocb_dispatch(&xiocb); |
@@ -335,18 +299,16 @@ cfe_getticks(void) | |||
335 | return xiocb.plist.xiocb_time.ticks; | 299 | return xiocb.plist.xiocb_time.ticks; |
336 | 300 | ||
337 | } | 301 | } |
338 | #endif /* CFE_API_getticks || CFE_API_ALL */ | ||
339 | 302 | ||
340 | #if defined(CFE_API_inpstat) || defined(CFE_API_ALL) | ||
341 | int cfe_inpstat(int handle) | 303 | int cfe_inpstat(int handle) |
342 | { | 304 | { |
343 | cfe_xiocb_t xiocb; | 305 | struct cfe_xiocb xiocb; |
344 | 306 | ||
345 | xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT; | 307 | xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT; |
346 | xiocb.xiocb_status = 0; | 308 | xiocb.xiocb_status = 0; |
347 | xiocb.xiocb_handle = handle; | 309 | xiocb.xiocb_handle = handle; |
348 | xiocb.xiocb_flags = 0; | 310 | xiocb.xiocb_flags = 0; |
349 | xiocb.xiocb_psize = sizeof(xiocb_inpstat_t); | 311 | xiocb.xiocb_psize = sizeof(struct xiocb_inpstat); |
350 | xiocb.plist.xiocb_inpstat.inp_status = 0; | 312 | xiocb.plist.xiocb_inpstat.inp_status = 0; |
351 | 313 | ||
352 | cfe_iocb_dispatch(&xiocb); | 314 | cfe_iocb_dispatch(&xiocb); |
@@ -355,20 +317,18 @@ int cfe_inpstat(int handle) | |||
355 | return xiocb.xiocb_status; | 317 | return xiocb.xiocb_status; |
356 | return xiocb.plist.xiocb_inpstat.inp_status; | 318 | return xiocb.plist.xiocb_inpstat.inp_status; |
357 | } | 319 | } |
358 | #endif /* CFE_API_inpstat || CFE_API_ALL */ | ||
359 | 320 | ||
360 | #if defined(CFE_API_ioctl) || defined(CFE_API_ALL) | ||
361 | int | 321 | int |
362 | cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer, | 322 | cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer, |
363 | int length, int *retlen, cfe_xuint_t offset) | 323 | int length, int *retlen, u64 offset) |
364 | { | 324 | { |
365 | cfe_xiocb_t xiocb; | 325 | struct cfe_xiocb xiocb; |
366 | 326 | ||
367 | xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL; | 327 | xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL; |
368 | xiocb.xiocb_status = 0; | 328 | xiocb.xiocb_status = 0; |
369 | xiocb.xiocb_handle = handle; | 329 | xiocb.xiocb_handle = handle; |
370 | xiocb.xiocb_flags = 0; | 330 | xiocb.xiocb_flags = 0; |
371 | xiocb.xiocb_psize = sizeof(xiocb_buffer_t); | 331 | xiocb.xiocb_psize = sizeof(struct xiocb_buffer); |
372 | xiocb.plist.xiocb_buffer.buf_offset = offset; | 332 | xiocb.plist.xiocb_buffer.buf_offset = offset; |
373 | xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum; | 333 | xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum; |
374 | xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); | 334 | xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); |
@@ -380,21 +340,19 @@ cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer, | |||
380 | *retlen = xiocb.plist.xiocb_buffer.buf_retlen; | 340 | *retlen = xiocb.plist.xiocb_buffer.buf_retlen; |
381 | return xiocb.xiocb_status; | 341 | return xiocb.xiocb_status; |
382 | } | 342 | } |
383 | #endif /* CFE_API_ioctl || CFE_API_ALL */ | ||
384 | 343 | ||
385 | #if defined(CFE_API_open) || defined(CFE_API_ALL) | ||
386 | int cfe_open(char *name) | 344 | int cfe_open(char *name) |
387 | { | 345 | { |
388 | cfe_xiocb_t xiocb; | 346 | struct cfe_xiocb xiocb; |
389 | 347 | ||
390 | xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN; | 348 | xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN; |
391 | xiocb.xiocb_status = 0; | 349 | xiocb.xiocb_status = 0; |
392 | xiocb.xiocb_handle = 0; | 350 | xiocb.xiocb_handle = 0; |
393 | xiocb.xiocb_flags = 0; | 351 | xiocb.xiocb_flags = 0; |
394 | xiocb.xiocb_psize = sizeof(xiocb_buffer_t); | 352 | xiocb.xiocb_psize = sizeof(struct xiocb_buffer); |
395 | xiocb.plist.xiocb_buffer.buf_offset = 0; | 353 | xiocb.plist.xiocb_buffer.buf_offset = 0; |
396 | xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name); | 354 | xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name); |
397 | xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name); | 355 | xiocb.plist.xiocb_buffer.buf_length = strlen(name); |
398 | 356 | ||
399 | cfe_iocb_dispatch(&xiocb); | 357 | cfe_iocb_dispatch(&xiocb); |
400 | 358 | ||
@@ -402,27 +360,21 @@ int cfe_open(char *name) | |||
402 | return xiocb.xiocb_status; | 360 | return xiocb.xiocb_status; |
403 | return xiocb.xiocb_handle; | 361 | return xiocb.xiocb_handle; |
404 | } | 362 | } |
405 | #endif /* CFE_API_open || CFE_API_ALL */ | ||
406 | 363 | ||
407 | #if defined(CFE_API_read) || defined(CFE_API_ALL) | ||
408 | int cfe_read(int handle, unsigned char *buffer, int length) | 364 | int cfe_read(int handle, unsigned char *buffer, int length) |
409 | { | 365 | { |
410 | return cfe_readblk(handle, 0, buffer, length); | 366 | return cfe_readblk(handle, 0, buffer, length); |
411 | } | 367 | } |
412 | #endif /* CFE_API_read || CFE_API_ALL */ | ||
413 | 368 | ||
414 | #if defined(CFE_API_readblk) || defined(CFE_API_ALL) | 369 | int cfe_readblk(int handle, s64 offset, unsigned char *buffer, int length) |
415 | int | ||
416 | cfe_readblk(int handle, cfe_xint_t offset, unsigned char *buffer, | ||
417 | int length) | ||
418 | { | 370 | { |
419 | cfe_xiocb_t xiocb; | 371 | struct cfe_xiocb xiocb; |
420 | 372 | ||
421 | xiocb.xiocb_fcode = CFE_CMD_DEV_READ; | 373 | xiocb.xiocb_fcode = CFE_CMD_DEV_READ; |
422 | xiocb.xiocb_status = 0; | 374 | xiocb.xiocb_status = 0; |
423 | xiocb.xiocb_handle = handle; | 375 | xiocb.xiocb_handle = handle; |
424 | xiocb.xiocb_flags = 0; | 376 | xiocb.xiocb_flags = 0; |
425 | xiocb.xiocb_psize = sizeof(xiocb_buffer_t); | 377 | xiocb.xiocb_psize = sizeof(struct xiocb_buffer); |
426 | xiocb.plist.xiocb_buffer.buf_offset = offset; | 378 | xiocb.plist.xiocb_buffer.buf_offset = offset; |
427 | xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); | 379 | xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); |
428 | xiocb.plist.xiocb_buffer.buf_length = length; | 380 | xiocb.plist.xiocb_buffer.buf_length = length; |
@@ -433,62 +385,41 @@ cfe_readblk(int handle, cfe_xint_t offset, unsigned char *buffer, | |||
433 | return xiocb.xiocb_status; | 385 | return xiocb.xiocb_status; |
434 | return xiocb.plist.xiocb_buffer.buf_retlen; | 386 | return xiocb.plist.xiocb_buffer.buf_retlen; |
435 | } | 387 | } |
436 | #endif /* CFE_API_readblk || CFE_API_ALL */ | ||
437 | 388 | ||
438 | #if defined(CFE_API_setenv) || defined(CFE_API_ALL) | ||
439 | int cfe_setenv(char *name, char *val) | 389 | int cfe_setenv(char *name, char *val) |
440 | { | 390 | { |
441 | cfe_xiocb_t xiocb; | 391 | struct cfe_xiocb xiocb; |
442 | 392 | ||
443 | xiocb.xiocb_fcode = CFE_CMD_ENV_SET; | 393 | xiocb.xiocb_fcode = CFE_CMD_ENV_SET; |
444 | xiocb.xiocb_status = 0; | 394 | xiocb.xiocb_status = 0; |
445 | xiocb.xiocb_handle = 0; | 395 | xiocb.xiocb_handle = 0; |
446 | xiocb.xiocb_flags = 0; | 396 | xiocb.xiocb_flags = 0; |
447 | xiocb.xiocb_psize = sizeof(xiocb_envbuf_t); | 397 | xiocb.xiocb_psize = sizeof(struct xiocb_envbuf); |
448 | xiocb.plist.xiocb_envbuf.enum_idx = 0; | 398 | xiocb.plist.xiocb_envbuf.enum_idx = 0; |
449 | xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name); | 399 | xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name); |
450 | xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name); | 400 | xiocb.plist.xiocb_envbuf.name_length = strlen(name); |
451 | xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val); | 401 | xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val); |
452 | xiocb.plist.xiocb_envbuf.val_length = cfe_strlen(val); | 402 | xiocb.plist.xiocb_envbuf.val_length = strlen(val); |
453 | 403 | ||
454 | cfe_iocb_dispatch(&xiocb); | 404 | cfe_iocb_dispatch(&xiocb); |
455 | 405 | ||
456 | return xiocb.xiocb_status; | 406 | return xiocb.xiocb_status; |
457 | } | 407 | } |
458 | #endif /* CFE_API_setenv || CFE_API_ALL */ | ||
459 | |||
460 | #if (defined(CFE_API_strlen) || defined(CFE_API_ALL)) \ | ||
461 | && !defined(CFE_API_STRLEN_CUSTOM) | ||
462 | int cfe_strlen(char *name) | ||
463 | { | ||
464 | int count = 0; | ||
465 | |||
466 | while (*name++) | ||
467 | count++; | ||
468 | 408 | ||
469 | return count; | ||
470 | } | ||
471 | #endif /* CFE_API_strlen || CFE_API_ALL */ | ||
472 | |||
473 | #if defined(CFE_API_write) || defined(CFE_API_ALL) | ||
474 | int cfe_write(int handle, unsigned char *buffer, int length) | 409 | int cfe_write(int handle, unsigned char *buffer, int length) |
475 | { | 410 | { |
476 | return cfe_writeblk(handle, 0, buffer, length); | 411 | return cfe_writeblk(handle, 0, buffer, length); |
477 | } | 412 | } |
478 | #endif /* CFE_API_write || CFE_API_ALL */ | ||
479 | 413 | ||
480 | #if defined(CFE_API_writeblk) || defined(CFE_API_ALL) | 414 | int cfe_writeblk(int handle, s64 offset, unsigned char *buffer, int length) |
481 | int | ||
482 | cfe_writeblk(int handle, cfe_xint_t offset, unsigned char *buffer, | ||
483 | int length) | ||
484 | { | 415 | { |
485 | cfe_xiocb_t xiocb; | 416 | struct cfe_xiocb xiocb; |
486 | 417 | ||
487 | xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE; | 418 | xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE; |
488 | xiocb.xiocb_status = 0; | 419 | xiocb.xiocb_status = 0; |
489 | xiocb.xiocb_handle = handle; | 420 | xiocb.xiocb_handle = handle; |
490 | xiocb.xiocb_flags = 0; | 421 | xiocb.xiocb_flags = 0; |
491 | xiocb.xiocb_psize = sizeof(xiocb_buffer_t); | 422 | xiocb.xiocb_psize = sizeof(struct xiocb_buffer); |
492 | xiocb.plist.xiocb_buffer.buf_offset = offset; | 423 | xiocb.plist.xiocb_buffer.buf_offset = offset; |
493 | xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); | 424 | xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); |
494 | xiocb.plist.xiocb_buffer.buf_length = length; | 425 | xiocb.plist.xiocb_buffer.buf_length = length; |
@@ -499,4 +430,3 @@ cfe_writeblk(int handle, cfe_xint_t offset, unsigned char *buffer, | |||
499 | return xiocb.xiocb_status; | 430 | return xiocb.xiocb_status; |
500 | return xiocb.plist.xiocb_buffer.buf_retlen; | 431 | return xiocb.plist.xiocb_buffer.buf_retlen; |
501 | } | 432 | } |
502 | #endif /* CFE_API_writeblk || CFE_API_ALL */ | ||
diff --git a/arch/mips/fw/cfe/cfe_api_int.h b/arch/mips/fw/cfe/cfe_api_int.h index f7e5a64b55f3..d9759e646956 100644 --- a/arch/mips/fw/cfe/cfe_api_int.h +++ b/arch/mips/fw/cfe/cfe_api_int.h | |||
@@ -15,28 +15,12 @@ | |||
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | */ | 17 | */ |
18 | |||
19 | /* ********************************************************************* | ||
20 | * | ||
21 | * Broadcom Common Firmware Environment (CFE) | ||
22 | * | ||
23 | * Device function prototypes File: cfe_api_int.h | ||
24 | * | ||
25 | * This header defines all internal types and macros for the | ||
26 | * library. This is stuff that's not exported to an app | ||
27 | * using the library. | ||
28 | * | ||
29 | * Authors: Mitch Lichtenberg, Chris Demetriou | ||
30 | * | ||
31 | ********************************************************************* */ | ||
32 | |||
33 | #ifndef CFE_API_INT_H | 18 | #ifndef CFE_API_INT_H |
34 | #define CFE_API_INT_H | 19 | #define CFE_API_INT_H |
35 | 20 | ||
36 | /* ********************************************************************* | 21 | /* |
37 | * Constants | 22 | * Constants. |
38 | ********************************************************************* */ | 23 | */ |
39 | |||
40 | #define CFE_CMD_FW_GETINFO 0 | 24 | #define CFE_CMD_FW_GETINFO 0 |
41 | #define CFE_CMD_FW_RESTART 1 | 25 | #define CFE_CMD_FW_RESTART 1 |
42 | #define CFE_CMD_FW_BOOT 2 | 26 | #define CFE_CMD_FW_BOOT 2 |
@@ -64,89 +48,101 @@ | |||
64 | 48 | ||
65 | #define CFE_CMD_VENDOR_USE 0x8000 /* codes above this are for customer use */ | 49 | #define CFE_CMD_VENDOR_USE 0x8000 /* codes above this are for customer use */ |
66 | 50 | ||
67 | /* ********************************************************************* | 51 | /* |
68 | * Structures | 52 | * Structures. |
69 | ********************************************************************* */ | 53 | */ |
70 | 54 | ||
71 | typedef uint64_t cfe_xuint_t; | 55 | /* eeek, signed "pointers" */ |
72 | typedef int64_t cfe_xint_t; | 56 | typedef s64 cfe_xptr_t; |
73 | typedef int64_t cfe_xptr_t; | ||
74 | 57 | ||
75 | typedef struct xiocb_buffer_s { | 58 | struct xiocb_buffer { |
76 | cfe_xuint_t buf_offset; /* offset on device (bytes) */ | 59 | u64 buf_offset; /* offset on device (bytes) */ |
77 | cfe_xptr_t buf_ptr; /* pointer to a buffer */ | 60 | cfe_xptr_t buf_ptr; /* pointer to a buffer */ |
78 | cfe_xuint_t buf_length; /* length of this buffer */ | 61 | u64 buf_length; /* length of this buffer */ |
79 | cfe_xuint_t buf_retlen; /* returned length (for read ops) */ | 62 | u64 buf_retlen; /* returned length (for read ops) */ |
80 | cfe_xuint_t buf_ioctlcmd; /* IOCTL command (used only for IOCTLs) */ | 63 | u64 buf_ioctlcmd; /* IOCTL command (used only for IOCTLs) */ |
81 | } xiocb_buffer_t; | 64 | }; |
82 | |||
83 | #define buf_devflags buf_ioctlcmd /* returned device info flags */ | ||
84 | 65 | ||
85 | typedef struct xiocb_inpstat_s { | 66 | struct xiocb_inpstat { |
86 | cfe_xuint_t inp_status; /* 1 means input available */ | 67 | u64 inp_status; /* 1 means input available */ |
87 | } xiocb_inpstat_t; | 68 | }; |
88 | 69 | ||
89 | typedef struct xiocb_envbuf_s { | 70 | struct xiocb_envbuf { |
90 | cfe_xint_t enum_idx; /* 0-based enumeration index */ | 71 | s64 enum_idx; /* 0-based enumeration index */ |
91 | cfe_xptr_t name_ptr; /* name string buffer */ | 72 | cfe_xptr_t name_ptr; /* name string buffer */ |
92 | cfe_xint_t name_length; /* size of name buffer */ | 73 | s64 name_length; /* size of name buffer */ |
93 | cfe_xptr_t val_ptr; /* value string buffer */ | 74 | cfe_xptr_t val_ptr; /* value string buffer */ |
94 | cfe_xint_t val_length; /* size of value string buffer */ | 75 | s64 val_length; /* size of value string buffer */ |
95 | } xiocb_envbuf_t; | 76 | }; |
96 | 77 | ||
97 | typedef struct xiocb_cpuctl_s { | 78 | struct xiocb_cpuctl { |
98 | cfe_xuint_t cpu_number; /* cpu number to control */ | 79 | u64 cpu_number; /* cpu number to control */ |
99 | cfe_xuint_t cpu_command; /* command to issue to CPU */ | 80 | u64 cpu_command; /* command to issue to CPU */ |
100 | cfe_xuint_t start_addr; /* CPU start address */ | 81 | u64 start_addr; /* CPU start address */ |
101 | cfe_xuint_t gp_val; /* starting GP value */ | 82 | u64 gp_val; /* starting GP value */ |
102 | cfe_xuint_t sp_val; /* starting SP value */ | 83 | u64 sp_val; /* starting SP value */ |
103 | cfe_xuint_t a1_val; /* starting A1 value */ | 84 | u64 a1_val; /* starting A1 value */ |
104 | } xiocb_cpuctl_t; | 85 | }; |
105 | 86 | ||
106 | typedef struct xiocb_time_s { | 87 | struct xiocb_time { |
107 | cfe_xint_t ticks; /* current time in ticks */ | 88 | s64 ticks; /* current time in ticks */ |
108 | } xiocb_time_t; | 89 | }; |
109 | 90 | ||
110 | typedef struct xiocb_exitstat_s { | 91 | struct xiocb_exitstat{ |
111 | cfe_xint_t status; | 92 | s64 status; |
112 | } xiocb_exitstat_t; | 93 | }; |
113 | 94 | ||
114 | typedef struct xiocb_meminfo_s { | 95 | struct xiocb_meminfo { |
115 | cfe_xint_t mi_idx; /* 0-based enumeration index */ | 96 | s64 mi_idx; /* 0-based enumeration index */ |
116 | cfe_xint_t mi_type; /* type of memory block */ | 97 | s64 mi_type; /* type of memory block */ |
117 | cfe_xuint_t mi_addr; /* physical start address */ | 98 | u64 mi_addr; /* physical start address */ |
118 | cfe_xuint_t mi_size; /* block size */ | 99 | u64 mi_size; /* block size */ |
119 | } xiocb_meminfo_t; | 100 | }; |
120 | 101 | ||
121 | typedef struct xiocb_fwinfo_s { | 102 | struct xiocb_fwinfo { |
122 | cfe_xint_t fwi_version; /* major, minor, eco version */ | 103 | s64 fwi_version; /* major, minor, eco version */ |
123 | cfe_xint_t fwi_totalmem; /* total installed mem */ | 104 | s64 fwi_totalmem; /* total installed mem */ |
124 | cfe_xint_t fwi_flags; /* various flags */ | 105 | s64 fwi_flags; /* various flags */ |
125 | cfe_xint_t fwi_boardid; /* board ID */ | 106 | s64 fwi_boardid; /* board ID */ |
126 | cfe_xint_t fwi_bootarea_va; /* VA of boot area */ | 107 | s64 fwi_bootarea_va; /* VA of boot area */ |
127 | cfe_xint_t fwi_bootarea_pa; /* PA of boot area */ | 108 | s64 fwi_bootarea_pa; /* PA of boot area */ |
128 | cfe_xint_t fwi_bootarea_size; /* size of boot area */ | 109 | s64 fwi_bootarea_size; /* size of boot area */ |
129 | cfe_xint_t fwi_reserved1; | 110 | s64 fwi_reserved1; |
130 | cfe_xint_t fwi_reserved2; | 111 | s64 fwi_reserved2; |
131 | cfe_xint_t fwi_reserved3; | 112 | s64 fwi_reserved3; |
132 | } xiocb_fwinfo_t; | 113 | }; |
133 | 114 | ||
134 | typedef struct cfe_xiocb_s { | 115 | struct cfe_xiocb { |
135 | cfe_xuint_t xiocb_fcode; /* IOCB function code */ | 116 | u64 xiocb_fcode; /* IOCB function code */ |
136 | cfe_xint_t xiocb_status; /* return status */ | 117 | s64 xiocb_status; /* return status */ |
137 | cfe_xint_t xiocb_handle; /* file/device handle */ | 118 | s64 xiocb_handle; /* file/device handle */ |
138 | cfe_xuint_t xiocb_flags; /* flags for this IOCB */ | 119 | u64 xiocb_flags; /* flags for this IOCB */ |
139 | cfe_xuint_t xiocb_psize; /* size of parameter list */ | 120 | u64 xiocb_psize; /* size of parameter list */ |
140 | union { | 121 | union { |
141 | xiocb_buffer_t xiocb_buffer; /* buffer parameters */ | 122 | /* buffer parameters */ |
142 | xiocb_inpstat_t xiocb_inpstat; /* input status parameters */ | 123 | struct xiocb_buffer xiocb_buffer; |
143 | xiocb_envbuf_t xiocb_envbuf; /* environment function parameters */ | 124 | |
144 | xiocb_cpuctl_t xiocb_cpuctl; /* CPU control parameters */ | 125 | /* input status parameters */ |
145 | xiocb_time_t xiocb_time; /* timer parameters */ | 126 | struct xiocb_inpstat xiocb_inpstat; |
146 | xiocb_meminfo_t xiocb_meminfo; /* memory arena info parameters */ | 127 | |
147 | xiocb_fwinfo_t xiocb_fwinfo; /* firmware information */ | 128 | /* environment function parameters */ |
148 | xiocb_exitstat_t xiocb_exitstat; /* Exit Status */ | 129 | struct xiocb_envbuf xiocb_envbuf; |
130 | |||
131 | /* CPU control parameters */ | ||
132 | struct xiocb_cpuctl xiocb_cpuctl; | ||
133 | |||
134 | /* timer parameters */ | ||
135 | struct xiocb_time xiocb_time; | ||
136 | |||
137 | /* memory arena info parameters */ | ||
138 | struct xiocb_meminfo xiocb_meminfo; | ||
139 | |||
140 | /* firmware information */ | ||
141 | struct xiocb_fwinfo xiocb_fwinfo; | ||
142 | |||
143 | /* Exit Status */ | ||
144 | struct xiocb_exitstat xiocb_exitstat; | ||
149 | } plist; | 145 | } plist; |
150 | } cfe_xiocb_t; | 146 | }; |
151 | 147 | ||
152 | #endif /* CFE_API_INT_H */ | 148 | #endif /* CFE_API_INT_H */ |
diff --git a/arch/mips/fw/lib/Makefile b/arch/mips/fw/lib/Makefile new file mode 100644 index 000000000000..84befc968fc4 --- /dev/null +++ b/arch/mips/fw/lib/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for generic prom monitor library routines under Linux. | ||
3 | # | ||
4 | |||
5 | lib-$(CONFIG_64BIT) += call_o32.o | ||
diff --git a/arch/mips/fw/lib/call_o32.S b/arch/mips/fw/lib/call_o32.S new file mode 100644 index 000000000000..bdf7d1d4081a --- /dev/null +++ b/arch/mips/fw/lib/call_o32.S | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * arch/mips/dec/prom/call_o32.S | ||
3 | * | ||
4 | * O32 interface for the 64 (or N32) ABI. | ||
5 | * | ||
6 | * Copyright (C) 2002 Maciej W. Rozycki | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <asm/asm.h> | ||
15 | #include <asm/regdef.h> | ||
16 | |||
17 | /* Maximum number of arguments supported. Must be even! */ | ||
18 | #define O32_ARGC 32 | ||
19 | /* Number of static registers we save. */ | ||
20 | #define O32_STATC 11 | ||
21 | /* Frame size for static register */ | ||
22 | #define O32_FRAMESZ (SZREG * O32_STATC) | ||
23 | /* Frame size on new stack */ | ||
24 | #define O32_FRAMESZ_NEW (SZREG + 4 * O32_ARGC) | ||
25 | |||
26 | .text | ||
27 | |||
28 | /* | ||
29 | * O32 function call dispatcher, for interfacing 32-bit ROM routines. | ||
30 | * | ||
31 | * The standard 64 (N32) calling sequence is supported, with a0 | ||
32 | * holding a function pointer, a1 a new stack pointer, a2-a7 -- its | ||
33 | * first six arguments and the stack -- remaining ones (up to O32_ARGC, | ||
34 | * including a2-a7). Static registers, gp and fp are preserved, v0 holds | ||
35 | * a result. This code relies on the called o32 function for sp and ra | ||
36 | * restoration and this dispatcher has to be placed in a KSEGx (or KUSEG) | ||
37 | * address space. Any pointers passed have to point to addresses within | ||
38 | * one of these spaces as well. | ||
39 | */ | ||
40 | NESTED(call_o32, O32_FRAMESZ, ra) | ||
41 | REG_SUBU sp,O32_FRAMESZ | ||
42 | |||
43 | REG_S ra,O32_FRAMESZ-1*SZREG(sp) | ||
44 | REG_S fp,O32_FRAMESZ-2*SZREG(sp) | ||
45 | REG_S gp,O32_FRAMESZ-3*SZREG(sp) | ||
46 | REG_S s7,O32_FRAMESZ-4*SZREG(sp) | ||
47 | REG_S s6,O32_FRAMESZ-5*SZREG(sp) | ||
48 | REG_S s5,O32_FRAMESZ-6*SZREG(sp) | ||
49 | REG_S s4,O32_FRAMESZ-7*SZREG(sp) | ||
50 | REG_S s3,O32_FRAMESZ-8*SZREG(sp) | ||
51 | REG_S s2,O32_FRAMESZ-9*SZREG(sp) | ||
52 | REG_S s1,O32_FRAMESZ-10*SZREG(sp) | ||
53 | REG_S s0,O32_FRAMESZ-11*SZREG(sp) | ||
54 | |||
55 | move jp,a0 | ||
56 | REG_SUBU s0,a1,O32_FRAMESZ_NEW | ||
57 | REG_S sp,O32_FRAMESZ_NEW-1*SZREG(s0) | ||
58 | |||
59 | sll a0,a2,zero | ||
60 | sll a1,a3,zero | ||
61 | sll a2,a4,zero | ||
62 | sll a3,a5,zero | ||
63 | sw a6,0x10(s0) | ||
64 | sw a7,0x14(s0) | ||
65 | |||
66 | PTR_LA t0,O32_FRAMESZ(sp) | ||
67 | PTR_LA t1,0x18(s0) | ||
68 | li t2,O32_ARGC-6 | ||
69 | 1: | ||
70 | lw t3,(t0) | ||
71 | REG_ADDU t0,SZREG | ||
72 | sw t3,(t1) | ||
73 | REG_SUBU t2,1 | ||
74 | REG_ADDU t1,4 | ||
75 | bnez t2,1b | ||
76 | |||
77 | move sp,s0 | ||
78 | |||
79 | jalr jp | ||
80 | |||
81 | REG_L sp,O32_FRAMESZ_NEW-1*SZREG(sp) | ||
82 | |||
83 | REG_L s0,O32_FRAMESZ-11*SZREG(sp) | ||
84 | REG_L s1,O32_FRAMESZ-10*SZREG(sp) | ||
85 | REG_L s2,O32_FRAMESZ-9*SZREG(sp) | ||
86 | REG_L s3,O32_FRAMESZ-8*SZREG(sp) | ||
87 | REG_L s4,O32_FRAMESZ-7*SZREG(sp) | ||
88 | REG_L s5,O32_FRAMESZ-6*SZREG(sp) | ||
89 | REG_L s6,O32_FRAMESZ-5*SZREG(sp) | ||
90 | REG_L s7,O32_FRAMESZ-4*SZREG(sp) | ||
91 | REG_L gp,O32_FRAMESZ-3*SZREG(sp) | ||
92 | REG_L fp,O32_FRAMESZ-2*SZREG(sp) | ||
93 | REG_L ra,O32_FRAMESZ-1*SZREG(sp) | ||
94 | |||
95 | REG_ADDU sp,O32_FRAMESZ | ||
96 | jr ra | ||
97 | END(call_o32) | ||
diff --git a/arch/mips/fw/sni/Makefile b/arch/mips/fw/sni/Makefile new file mode 100644 index 000000000000..d9740a3788e2 --- /dev/null +++ b/arch/mips/fw/sni/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for the SNI prom monitor routines under Linux. | ||
3 | # | ||
4 | |||
5 | lib-$(CONFIG_SNIPROM) += sniprom.o | ||
diff --git a/arch/mips/fw/sni/sniprom.c b/arch/mips/fw/sni/sniprom.c new file mode 100644 index 000000000000..96ba99202758 --- /dev/null +++ b/arch/mips/fw/sni/sniprom.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * Big Endian PROM code for SNI RM machines | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 2005-2006 Florian Lohoff (flo@rfc822.org) | ||
9 | * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <linux/console.h> | ||
16 | |||
17 | #include <asm/addrspace.h> | ||
18 | #include <asm/sni.h> | ||
19 | #include <asm/mipsprom.h> | ||
20 | #include <asm/mipsregs.h> | ||
21 | #include <asm/bootinfo.h> | ||
22 | |||
23 | /* special SNI prom calls */ | ||
24 | /* | ||
25 | * This does not exist in all proms - SINIX compares | ||
26 | * the prom env variable "version" against "2.0008" | ||
27 | * or greater. If lesser it tries to probe interesting | ||
28 | * registers | ||
29 | */ | ||
30 | #define PROM_GET_MEMCONF 58 | ||
31 | #define PROM_GET_HWCONF 61 | ||
32 | |||
33 | #define PROM_VEC (u64 *)CKSEG1ADDR(0x1fc00000) | ||
34 | #define PROM_ENTRY(x) (PROM_VEC + (x)) | ||
35 | |||
36 | #define ___prom_putchar ((int *(*)(int))PROM_ENTRY(PROM_PUTCHAR)) | ||
37 | #define ___prom_getenv ((char *(*)(char *))PROM_ENTRY(PROM_GETENV)) | ||
38 | #define ___prom_get_memconf ((void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF)) | ||
39 | #define ___prom_get_hwconf ((u32 (*)(void))PROM_ENTRY(PROM_GET_HWCONF)) | ||
40 | |||
41 | #ifdef CONFIG_64BIT | ||
42 | |||
43 | static u8 o32_stk[16384]; | ||
44 | #define O32_STK &o32_stk[sizeof(o32_stk)] | ||
45 | |||
46 | #define __PROM_O32(fun, arg) fun arg __asm__(#fun); \ | ||
47 | __asm__(#fun " = call_o32") | ||
48 | |||
49 | int __PROM_O32(__prom_putchar, (int *(*)(int), void *, int)); | ||
50 | char *__PROM_O32(__prom_getenv, (char *(*)(char *), void *, char *)); | ||
51 | void __PROM_O32(__prom_get_memconf, (void (*)(void *), void *, void *)); | ||
52 | u32 __PROM_O32(__prom_get_hwconf, (u32 (*)(void), void *)); | ||
53 | |||
54 | #define _prom_putchar(x) __prom_putchar(___prom_putchar, O32_STK, x) | ||
55 | #define _prom_getenv(x) __prom_getenv(___prom_getenv, O32_STK, x) | ||
56 | #define _prom_get_memconf(x) __prom_get_memconf(___prom_get_memconf, O32_STK, x) | ||
57 | #define _prom_get_hwconf() __prom_get_hwconf(___prom_get_hwconf, O32_STK) | ||
58 | |||
59 | #else | ||
60 | #define _prom_putchar(x) ___prom_putchar(x) | ||
61 | #define _prom_getenv(x) ___prom_getenv(x) | ||
62 | #define _prom_get_memconf(x) ___prom_get_memconf(x) | ||
63 | #define _prom_get_hwconf(x) ___prom_get_hwconf(x) | ||
64 | #endif | ||
65 | |||
66 | void prom_putchar(char c) | ||
67 | { | ||
68 | _prom_putchar(c); | ||
69 | } | ||
70 | |||
71 | |||
72 | char *prom_getenv(char *s) | ||
73 | { | ||
74 | return _prom_getenv(s); | ||
75 | } | ||
76 | |||
77 | void *prom_get_hwconf(void) | ||
78 | { | ||
79 | u32 hwconf = _prom_get_hwconf(); | ||
80 | |||
81 | if (hwconf == 0xffffffff) | ||
82 | return NULL; | ||
83 | |||
84 | return (void *)CKSEG1ADDR(hwconf); | ||
85 | } | ||
86 | |||
87 | void __init prom_free_prom_memory(void) | ||
88 | { | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * /proc/cpuinfo system type | ||
93 | * | ||
94 | */ | ||
95 | char *system_type = "Unknown"; | ||
96 | const char *get_system_type(void) | ||
97 | { | ||
98 | return system_type; | ||
99 | } | ||
100 | |||
101 | static void __init sni_mem_init(void) | ||
102 | { | ||
103 | int i, memsize; | ||
104 | struct membank { | ||
105 | u32 size; | ||
106 | u32 base; | ||
107 | u32 size2; | ||
108 | u32 pad1; | ||
109 | u32 pad2; | ||
110 | } memconf[8]; | ||
111 | int brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE; | ||
112 | |||
113 | |||
114 | /* MemSIZE from prom in 16MByte chunks */ | ||
115 | memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16; | ||
116 | |||
117 | pr_debug("IDProm memsize: %u MByte\n", memsize); | ||
118 | |||
119 | /* get memory bank layout from prom */ | ||
120 | _prom_get_memconf(&memconf); | ||
121 | |||
122 | pr_debug("prom_get_mem_conf memory configuration:\n"); | ||
123 | for (i = 0; i < 8 && memconf[i].size; i++) { | ||
124 | if (brd_type == SNI_BRD_PCI_TOWER || | ||
125 | brd_type == SNI_BRD_PCI_TOWER_CPLUS) { | ||
126 | if (memconf[i].base >= 0x20000000 && | ||
127 | memconf[i].base < 0x30000000) | ||
128 | memconf[i].base -= 0x20000000; | ||
129 | } | ||
130 | pr_debug("Bank%d: %08x @ %08x\n", i, | ||
131 | memconf[i].size, memconf[i].base); | ||
132 | add_memory_region(memconf[i].base, memconf[i].size, | ||
133 | BOOT_MEM_RAM); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | void __init prom_init(void) | ||
138 | { | ||
139 | int argc = fw_arg0; | ||
140 | u32 *argv = (u32 *)CKSEG0ADDR(fw_arg1); | ||
141 | int i; | ||
142 | |||
143 | sni_mem_init(); | ||
144 | |||
145 | /* copy prom cmdline parameters to kernel cmdline */ | ||
146 | for (i = 1; i < argc; i++) { | ||
147 | strcat(arcs_cmdline, (char *)CKSEG0ADDR(argv[i])); | ||
148 | if (i < (argc - 1)) | ||
149 | strcat(arcs_cmdline, " "); | ||
150 | } | ||
151 | } | ||
diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c index 51f6b7862460..728ef6a80edd 100644 --- a/arch/mips/gt64120/wrppmc/setup.c +++ b/arch/mips/gt64120/wrppmc/setup.c | |||
@@ -121,8 +121,6 @@ const char *get_system_type(void) | |||
121 | */ | 121 | */ |
122 | void __init prom_init(void) | 122 | void __init prom_init(void) |
123 | { | 123 | { |
124 | mips_machtype = MACH_WRPPMC; | ||
125 | |||
126 | add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM); | 124 | add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM); |
127 | add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA); | 125 | add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA); |
128 | 126 | ||
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c index a7857973ca03..a7947199c99b 100644 --- a/arch/mips/jazz/setup.c +++ b/arch/mips/jazz/setup.c | |||
@@ -200,12 +200,19 @@ static struct platform_device jazz_cmos_pdev = { | |||
200 | .resource = jazz_cmos_rsrc | 200 | .resource = jazz_cmos_rsrc |
201 | }; | 201 | }; |
202 | 202 | ||
203 | static struct platform_device pcspeaker_pdev = { | ||
204 | .name = "pcspkr", | ||
205 | .id = -1, | ||
206 | }; | ||
207 | |||
203 | static int __init jazz_setup_devinit(void) | 208 | static int __init jazz_setup_devinit(void) |
204 | { | 209 | { |
205 | platform_device_register(&jazz_serial8250_device); | 210 | platform_device_register(&jazz_serial8250_device); |
206 | platform_device_register(&jazz_esp_pdev); | 211 | platform_device_register(&jazz_esp_pdev); |
207 | platform_device_register(&jazz_sonic_pdev); | 212 | platform_device_register(&jazz_sonic_pdev); |
208 | platform_device_register(&jazz_cmos_pdev); | 213 | platform_device_register(&jazz_cmos_pdev); |
214 | platform_device_register(&pcspeaker_pdev); | ||
215 | |||
209 | return 0; | 216 | return 0; |
210 | } | 217 | } |
211 | 218 | ||
diff --git a/arch/mips/jmr3927/rbhma3100/init.c b/arch/mips/jmr3927/rbhma3100/init.c index b643f75ec9a5..700b9cf8eb9d 100644 --- a/arch/mips/jmr3927/rbhma3100/init.c +++ b/arch/mips/jmr3927/rbhma3100/init.c | |||
@@ -52,10 +52,6 @@ void __init prom_init(void) | |||
52 | puts("Warning: TX3927 TLB off\n"); | 52 | puts("Warning: TX3927 TLB off\n"); |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | #ifdef CONFIG_TOSHIBA_JMR3927 | ||
56 | mips_machtype = MACH_TOSHIBA_JMR3927; | ||
57 | #endif | ||
58 | |||
59 | prom_init_cmdline(); | 55 | prom_init_cmdline(); |
60 | add_memory_region(0, JMR3927_SDRAM_SIZE, BOOT_MEM_RAM); | 56 | add_memory_region(0, JMR3927_SDRAM_SIZE, BOOT_MEM_RAM); |
61 | } | 57 | } |
diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c index 06e01c8f4e3a..c886d804d303 100644 --- a/arch/mips/jmr3927/rbhma3100/setup.c +++ b/arch/mips/jmr3927/rbhma3100/setup.c | |||
@@ -29,21 +29,17 @@ | |||
29 | 29 | ||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/kdev_t.h> | ||
33 | #include <linux/types.h> | 32 | #include <linux/types.h> |
34 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
35 | #include <linux/ide.h> | ||
36 | #include <linux/ioport.h> | 34 | #include <linux/ioport.h> |
37 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
38 | #include <linux/pm.h> | 36 | #include <linux/pm.h> |
39 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
38 | #include <linux/clk.h> | ||
40 | #ifdef CONFIG_SERIAL_TXX9 | 39 | #ifdef CONFIG_SERIAL_TXX9 |
41 | #include <linux/tty.h> | ||
42 | #include <linux/serial.h> | ||
43 | #include <linux/serial_core.h> | 40 | #include <linux/serial_core.h> |
44 | #endif | 41 | #endif |
45 | 42 | ||
46 | #include <asm/addrspace.h> | ||
47 | #include <asm/txx9tmr.h> | 43 | #include <asm/txx9tmr.h> |
48 | #include <asm/reboot.h> | 44 | #include <asm/reboot.h> |
49 | #include <asm/jmr3927/jmr3927.h> | 45 | #include <asm/jmr3927/jmr3927.h> |
@@ -238,6 +234,8 @@ static void __init tx3927_setup(void) | |||
238 | tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_BEOW; | 234 | tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_BEOW; |
239 | /* Disable PCI snoop */ | 235 | /* Disable PCI snoop */ |
240 | tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_PSNP; | 236 | tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_PSNP; |
237 | /* do reset on watchdog */ | ||
238 | tx3927_ccfgptr->ccfg |= TX3927_CCFG_WR; | ||
241 | 239 | ||
242 | #ifdef DO_WRITE_THROUGH | 240 | #ifdef DO_WRITE_THROUGH |
243 | /* Enable PCI SNOOP - with write through only */ | 241 | /* Enable PCI SNOOP - with write through only */ |
@@ -388,3 +386,55 @@ static int __init jmr3927_rtc_init(void) | |||
388 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; | 386 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; |
389 | } | 387 | } |
390 | device_initcall(jmr3927_rtc_init); | 388 | device_initcall(jmr3927_rtc_init); |
389 | |||
390 | /* Watchdog support */ | ||
391 | |||
392 | static int __init txx9_wdt_init(unsigned long base) | ||
393 | { | ||
394 | struct resource res = { | ||
395 | .start = base, | ||
396 | .end = base + 0x100 - 1, | ||
397 | .flags = IORESOURCE_MEM, | ||
398 | }; | ||
399 | struct platform_device *dev = | ||
400 | platform_device_register_simple("txx9wdt", -1, &res, 1); | ||
401 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; | ||
402 | } | ||
403 | |||
404 | static int __init jmr3927_wdt_init(void) | ||
405 | { | ||
406 | return txx9_wdt_init(TX3927_TMR_REG(2)); | ||
407 | } | ||
408 | device_initcall(jmr3927_wdt_init); | ||
409 | |||
410 | /* Minimum CLK support */ | ||
411 | |||
412 | struct clk *clk_get(struct device *dev, const char *id) | ||
413 | { | ||
414 | if (!strcmp(id, "imbus_clk")) | ||
415 | return (struct clk *)JMR3927_IMCLK; | ||
416 | return ERR_PTR(-ENOENT); | ||
417 | } | ||
418 | EXPORT_SYMBOL(clk_get); | ||
419 | |||
420 | int clk_enable(struct clk *clk) | ||
421 | { | ||
422 | return 0; | ||
423 | } | ||
424 | EXPORT_SYMBOL(clk_enable); | ||
425 | |||
426 | void clk_disable(struct clk *clk) | ||
427 | { | ||
428 | } | ||
429 | EXPORT_SYMBOL(clk_disable); | ||
430 | |||
431 | unsigned long clk_get_rate(struct clk *clk) | ||
432 | { | ||
433 | return (unsigned long)clk; | ||
434 | } | ||
435 | EXPORT_SYMBOL(clk_get_rate); | ||
436 | |||
437 | void clk_put(struct clk *clk) | ||
438 | { | ||
439 | } | ||
440 | EXPORT_SYMBOL(clk_put); | ||
diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index af78456d4138..417bb3e336ac 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c | |||
@@ -18,6 +18,15 @@ | |||
18 | #include <asm/mipsregs.h> | 18 | #include <asm/mipsregs.h> |
19 | #include <asm/system.h> | 19 | #include <asm/system.h> |
20 | 20 | ||
21 | static char bug64hit[] __initdata = | ||
22 | "reliable operation impossible!\n%s"; | ||
23 | static char nowar[] __initdata = | ||
24 | "Please report to <linux-mips@linux-mips.org>."; | ||
25 | static char r4kwar[] __initdata = | ||
26 | "Enable CPU_R4000_WORKAROUNDS to rectify."; | ||
27 | static char daddiwar[] __initdata = | ||
28 | "Enable CPU_DADDI_WORKAROUNDS to rectify."; | ||
29 | |||
21 | static inline void align_mod(const int align, const int mod) | 30 | static inline void align_mod(const int align, const int mod) |
22 | { | 31 | { |
23 | asm volatile( | 32 | asm volatile( |
@@ -155,13 +164,7 @@ static inline void check_mult_sh(void) | |||
155 | } | 164 | } |
156 | 165 | ||
157 | printk("no.\n"); | 166 | printk("no.\n"); |
158 | panic("Reliable operation impossible!\n" | 167 | panic(bug64hit, !R4000_WAR ? r4kwar : nowar); |
159 | #ifndef CONFIG_CPU_R4000 | ||
160 | "Configure for R4000 to enable the workaround." | ||
161 | #else | ||
162 | "Please report to <linux-mips@linux-mips.org>." | ||
163 | #endif | ||
164 | ); | ||
165 | } | 168 | } |
166 | 169 | ||
167 | static volatile int daddi_ov __initdata = 0; | 170 | static volatile int daddi_ov __initdata = 0; |
@@ -233,15 +236,11 @@ static inline void check_daddi(void) | |||
233 | } | 236 | } |
234 | 237 | ||
235 | printk("no.\n"); | 238 | printk("no.\n"); |
236 | panic("Reliable operation impossible!\n" | 239 | panic(bug64hit, !DADDI_WAR ? daddiwar : nowar); |
237 | #if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400) | ||
238 | "Configure for R4000 or R4400 to enable the workaround." | ||
239 | #else | ||
240 | "Please report to <linux-mips@linux-mips.org>." | ||
241 | #endif | ||
242 | ); | ||
243 | } | 240 | } |
244 | 241 | ||
242 | int daddiu_bug __initdata = -1; | ||
243 | |||
245 | static inline void check_daddiu(void) | 244 | static inline void check_daddiu(void) |
246 | { | 245 | { |
247 | long v, w, tmp; | 246 | long v, w, tmp; |
@@ -281,7 +280,9 @@ static inline void check_daddiu(void) | |||
281 | : "=&r" (v), "=&r" (w), "=&r" (tmp) | 280 | : "=&r" (v), "=&r" (w), "=&r" (tmp) |
282 | : "I" (0xffffffffffffdb9aUL), "I" (0x1234)); | 281 | : "I" (0xffffffffffffdb9aUL), "I" (0x1234)); |
283 | 282 | ||
284 | if (v == w) { | 283 | daddiu_bug = v != w; |
284 | |||
285 | if (!daddiu_bug) { | ||
285 | printk("no.\n"); | 286 | printk("no.\n"); |
286 | return; | 287 | return; |
287 | } | 288 | } |
@@ -303,18 +304,16 @@ static inline void check_daddiu(void) | |||
303 | } | 304 | } |
304 | 305 | ||
305 | printk("no.\n"); | 306 | printk("no.\n"); |
306 | panic("Reliable operation impossible!\n" | 307 | panic(bug64hit, !DADDI_WAR ? daddiwar : nowar); |
307 | #if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400) | ||
308 | "Configure for R4000 or R4400 to enable the workaround." | ||
309 | #else | ||
310 | "Please report to <linux-mips@linux-mips.org>." | ||
311 | #endif | ||
312 | ); | ||
313 | } | 308 | } |
314 | 309 | ||
315 | void __init check_bugs64(void) | 310 | void __init check_bugs64_early(void) |
316 | { | 311 | { |
317 | check_mult_sh(); | 312 | check_mult_sh(); |
318 | check_daddi(); | ||
319 | check_daddiu(); | 313 | check_daddiu(); |
320 | } | 314 | } |
315 | |||
316 | void __init check_bugs64(void) | ||
317 | { | ||
318 | check_daddi(); | ||
319 | } | ||
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 5c2794391bf5..5861a432a52f 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c | |||
@@ -188,6 +188,8 @@ static inline void check_wait(void) | |||
188 | case CPU_AU1500: | 188 | case CPU_AU1500: |
189 | case CPU_AU1550: | 189 | case CPU_AU1550: |
190 | case CPU_AU1200: | 190 | case CPU_AU1200: |
191 | case CPU_AU1210: | ||
192 | case CPU_AU1250: | ||
191 | if (allow_au1k_wait) | 193 | if (allow_au1k_wait) |
192 | cpu_wait = au1k_wait; | 194 | cpu_wait = au1k_wait; |
193 | break; | 195 | break; |
@@ -733,6 +735,11 @@ static inline void cpu_probe_alchemy(struct cpuinfo_mips *c) | |||
733 | break; | 735 | break; |
734 | case 4: | 736 | case 4: |
735 | c->cputype = CPU_AU1200; | 737 | c->cputype = CPU_AU1200; |
738 | if (2 == (c->processor_id & 0xff)) | ||
739 | c->cputype = CPU_AU1250; | ||
740 | break; | ||
741 | case 5: | ||
742 | c->cputype = CPU_AU1210; | ||
736 | break; | 743 | break; |
737 | default: | 744 | default: |
738 | panic("Unknown Au Core!"); | 745 | panic("Unknown Au Core!"); |
@@ -858,6 +865,8 @@ static __init const char *cpu_to_name(struct cpuinfo_mips *c) | |||
858 | case CPU_AU1100: name = "Au1100"; break; | 865 | case CPU_AU1100: name = "Au1100"; break; |
859 | case CPU_AU1550: name = "Au1550"; break; | 866 | case CPU_AU1550: name = "Au1550"; break; |
860 | case CPU_AU1200: name = "Au1200"; break; | 867 | case CPU_AU1200: name = "Au1200"; break; |
868 | case CPU_AU1210: name = "Au1210"; break; | ||
869 | case CPU_AU1250: name = "Au1250"; break; | ||
861 | case CPU_4KEC: name = "MIPS 4KEc"; break; | 870 | case CPU_4KEC: name = "MIPS 4KEc"; break; |
862 | case CPU_4KSC: name = "MIPS 4KSc"; break; | 871 | case CPU_4KSC: name = "MIPS 4KSc"; break; |
863 | case CPU_VR41XX: name = "NEC Vr41xx"; break; | 872 | case CPU_VR41XX: name = "NEC Vr41xx"; break; |
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S index e76a76bf0b3d..c6ada98ee042 100644 --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S | |||
@@ -6,7 +6,7 @@ | |||
6 | * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle | 6 | * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle |
7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
8 | * Copyright (C) 2001 MIPS Technologies, Inc. | 8 | * Copyright (C) 2001 MIPS Technologies, Inc. |
9 | * Copyright (C) 2002 Maciej W. Rozycki | 9 | * Copyright (C) 2002, 2007 Maciej W. Rozycki |
10 | */ | 10 | */ |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | 12 | ||
@@ -471,7 +471,13 @@ NESTED(nmi_handler, PT_SIZE, sp) | |||
471 | jr k0 | 471 | jr k0 |
472 | rfe | 472 | rfe |
473 | #else | 473 | #else |
474 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS | ||
474 | LONG_ADDIU k0, 4 /* stall on $k0 */ | 475 | LONG_ADDIU k0, 4 /* stall on $k0 */ |
476 | #else | ||
477 | .set at=v1 | ||
478 | LONG_ADDIU k0, 4 | ||
479 | .set noat | ||
480 | #endif | ||
475 | MTC0 k0, CP0_EPC | 481 | MTC0 k0, CP0_EPC |
476 | /* I hope three instructions between MTC0 and ERET are enough... */ | 482 | /* I hope three instructions between MTC0 and ERET are enough... */ |
477 | ori k1, _THREAD_MASK | 483 | ori k1, _THREAD_MASK |
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index d2c2e00e5864..f6704ab16306 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c | |||
@@ -161,8 +161,7 @@ static unsigned int translate_open_flags(int flags) | |||
161 | int i; | 161 | int i; |
162 | unsigned int ret = 0; | 162 | unsigned int ret = 0; |
163 | 163 | ||
164 | for (i = 0; i < (sizeof(open_flags_table) / sizeof(struct apsp_table)); | 164 | for (i = 0; i < ARRAY_SIZE(open_flags_table); i++) { |
165 | i++) { | ||
166 | if( (flags & open_flags_table[i].sp) ) { | 165 | if( (flags & open_flags_table[i].sp) ) { |
167 | ret |= open_flags_table[i].ap; | 166 | ret |= open_flags_table[i].ap; |
168 | } | 167 | } |
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 2b8ec1102e86..65af3cc90abb 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
@@ -174,36 +174,16 @@ struct rlimit32 { | |||
174 | int rlim_max; | 174 | int rlim_max; |
175 | }; | 175 | }; |
176 | 176 | ||
177 | #ifdef __MIPSEB__ | 177 | asmlinkage long sys32_truncate64(const char __user * path, |
178 | asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy, | 178 | unsigned long __dummy, int a2, int a3) |
179 | int length_hi, int length_lo) | ||
180 | #endif | ||
181 | #ifdef __MIPSEL__ | ||
182 | asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy, | ||
183 | int length_lo, int length_hi) | ||
184 | #endif | ||
185 | { | 179 | { |
186 | loff_t length; | 180 | return sys_truncate(path, merge_64(a2, a3)); |
187 | |||
188 | length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo; | ||
189 | |||
190 | return sys_truncate(path, length); | ||
191 | } | 181 | } |
192 | 182 | ||
193 | #ifdef __MIPSEB__ | ||
194 | asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, | 183 | asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, |
195 | int length_hi, int length_lo) | 184 | int a2, int a3) |
196 | #endif | ||
197 | #ifdef __MIPSEL__ | ||
198 | asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, | ||
199 | int length_lo, int length_hi) | ||
200 | #endif | ||
201 | { | 185 | { |
202 | loff_t length; | 186 | return sys_ftruncate(fd, merge_64(a2, a3)); |
203 | |||
204 | length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo; | ||
205 | |||
206 | return sys_ftruncate(fd, length); | ||
207 | } | 187 | } |
208 | 188 | ||
209 | static inline long | 189 | static inline long |
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c index 3d6b1ec1f328..640fb0cc6e39 100644 --- a/arch/mips/kernel/mips-mt.c +++ b/arch/mips/kernel/mips-mt.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <asm/system.h> | 17 | #include <asm/system.h> |
18 | #include <asm/hardirq.h> | 18 | #include <asm/hardirq.h> |
19 | #include <asm/mmu_context.h> | 19 | #include <asm/mmu_context.h> |
20 | #include <asm/smp.h> | ||
21 | #include <asm/mipsmtregs.h> | 20 | #include <asm/mipsmtregs.h> |
22 | #include <asm/r4kcache.h> | 21 | #include <asm/r4kcache.h> |
23 | #include <asm/cacheflush.h> | 22 | #include <asm/cacheflush.h> |
diff --git a/arch/mips/kernel/pcspeaker.c b/arch/mips/kernel/pcspeaker.c deleted file mode 100644 index 475df6904219..000000000000 --- a/arch/mips/kernel/pcspeaker.c +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2006 IBM Corporation | ||
3 | * | ||
4 | * Implements device information for i8253 timer chip | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation | ||
9 | */ | ||
10 | |||
11 | #include <linux/platform_device.h> | ||
12 | |||
13 | static __init int add_pcspkr(void) | ||
14 | { | ||
15 | struct platform_device *pd; | ||
16 | int ret; | ||
17 | |||
18 | pd = platform_device_alloc("pcspkr", -1); | ||
19 | if (!pd) | ||
20 | return -ENOMEM; | ||
21 | |||
22 | ret = platform_device_add(pd); | ||
23 | if (ret) | ||
24 | platform_device_put(pd); | ||
25 | |||
26 | return ret; | ||
27 | } | ||
28 | device_initcall(add_pcspkr); | ||
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c index 6e6e947cce1e..36f065398243 100644 --- a/arch/mips/kernel/proc.c +++ b/arch/mips/kernel/proc.c | |||
@@ -62,6 +62,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
62 | ); | 62 | ); |
63 | seq_printf(m, "shadow register sets\t: %d\n", | 63 | seq_printf(m, "shadow register sets\t: %d\n", |
64 | cpu_data[n].srsets); | 64 | cpu_data[n].srsets); |
65 | seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); | ||
65 | 66 | ||
66 | sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", | 67 | sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", |
67 | cpu_has_vce ? "%u" : "not available"); | 68 | cpu_has_vce ? "%u" : "not available"); |
@@ -89,7 +90,7 @@ static void c_stop(struct seq_file *m, void *v) | |||
89 | { | 90 | { |
90 | } | 91 | } |
91 | 92 | ||
92 | struct seq_operations cpuinfo_op = { | 93 | const struct seq_operations cpuinfo_op = { |
93 | .start = c_start, | 94 | .start = c_start, |
94 | .next = c_next, | 95 | .next = c_next, |
95 | .stop = c_stop, | 96 | .stop = c_stop, |
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 1ba00c15505b..0233798f7155 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <asm/atomic.h> | 40 | #include <asm/atomic.h> |
41 | #include <asm/cpu.h> | 41 | #include <asm/cpu.h> |
42 | #include <asm/processor.h> | 42 | #include <asm/processor.h> |
43 | #include <asm/mips_mt.h> | ||
44 | #include <asm/system.h> | 43 | #include <asm/system.h> |
45 | #include <asm/vpe.h> | 44 | #include <asm/vpe.h> |
46 | #include <asm/rtlx.h> | 45 | #include <asm/rtlx.h> |
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index f8a535afce39..269c252d956f 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 Ralf Baechle | 8 | * Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02, 03 Ralf Baechle |
9 | * Copyright (C) 1996 Stoned Elipot | 9 | * Copyright (C) 1996 Stoned Elipot |
10 | * Copyright (C) 1999 Silicon Graphics, Inc. | 10 | * Copyright (C) 1999 Silicon Graphics, Inc. |
11 | * Copyright (C) 2000 2001, 2002 Maciej W. Rozycki | 11 | * Copyright (C) 2000, 2001, 2002, 2007 Maciej W. Rozycki |
12 | */ | 12 | */ |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/ioport.h> | 14 | #include <linux/ioport.h> |
@@ -24,10 +24,12 @@ | |||
24 | 24 | ||
25 | #include <asm/addrspace.h> | 25 | #include <asm/addrspace.h> |
26 | #include <asm/bootinfo.h> | 26 | #include <asm/bootinfo.h> |
27 | #include <asm/bugs.h> | ||
27 | #include <asm/cache.h> | 28 | #include <asm/cache.h> |
28 | #include <asm/cpu.h> | 29 | #include <asm/cpu.h> |
29 | #include <asm/sections.h> | 30 | #include <asm/sections.h> |
30 | #include <asm/setup.h> | 31 | #include <asm/setup.h> |
32 | #include <asm/smp-ops.h> | ||
31 | #include <asm/system.h> | 33 | #include <asm/system.h> |
32 | 34 | ||
33 | struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly; | 35 | struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly; |
@@ -561,6 +563,7 @@ void __init setup_arch(char **cmdline_p) | |||
561 | } | 563 | } |
562 | #endif | 564 | #endif |
563 | cpu_report(); | 565 | cpu_report(); |
566 | check_bugs_early(); | ||
564 | 567 | ||
565 | #if defined(CONFIG_VT) | 568 | #if defined(CONFIG_VT) |
566 | #if defined(CONFIG_VGA_CONSOLE) | 569 | #if defined(CONFIG_VGA_CONSOLE) |
@@ -573,9 +576,7 @@ void __init setup_arch(char **cmdline_p) | |||
573 | arch_mem_init(cmdline_p); | 576 | arch_mem_init(cmdline_p); |
574 | 577 | ||
575 | resource_init(); | 578 | resource_init(); |
576 | #ifdef CONFIG_SMP | ||
577 | plat_smp_setup(); | 579 | plat_smp_setup(); |
578 | #endif | ||
579 | } | 580 | } |
580 | 581 | ||
581 | static int __init fpu_disable(char *s) | 582 | static int __init fpu_disable(char *s) |
diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index 94e210cc6cb6..89e6f6aa5166 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/cpumask.h> | 22 | #include <linux/cpumask.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/compiler.h> | 24 | #include <linux/compiler.h> |
25 | #include <linux/smp.h> | ||
25 | 26 | ||
26 | #include <asm/atomic.h> | 27 | #include <asm/atomic.h> |
27 | #include <asm/cacheflush.h> | 28 | #include <asm/cacheflush.h> |
@@ -30,7 +31,6 @@ | |||
30 | #include <asm/system.h> | 31 | #include <asm/system.h> |
31 | #include <asm/hardirq.h> | 32 | #include <asm/hardirq.h> |
32 | #include <asm/mmu_context.h> | 33 | #include <asm/mmu_context.h> |
33 | #include <asm/smp.h> | ||
34 | #include <asm/time.h> | 34 | #include <asm/time.h> |
35 | #include <asm/mipsregs.h> | 35 | #include <asm/mipsregs.h> |
36 | #include <asm/mipsmtregs.h> | 36 | #include <asm/mipsmtregs.h> |
@@ -215,68 +215,67 @@ static void __init smp_tc_init(unsigned int tc, unsigned int mvpconf0) | |||
215 | write_tc_c0_tchalt(TCHALT_H); | 215 | write_tc_c0_tchalt(TCHALT_H); |
216 | } | 216 | } |
217 | 217 | ||
218 | /* | 218 | static void vsmp_send_ipi_single(int cpu, unsigned int action) |
219 | * Common setup before any secondaries are started | ||
220 | * Make sure all CPU's are in a sensible state before we boot any of the | ||
221 | * secondarys | ||
222 | */ | ||
223 | void __init plat_smp_setup(void) | ||
224 | { | 219 | { |
225 | unsigned int mvpconf0, ntc, tc, ncpu = 0; | 220 | int i; |
226 | 221 | unsigned long flags; | |
227 | #ifdef CONFIG_MIPS_MT_FPAFF | 222 | int vpflags; |
228 | /* If we have an FPU, enroll ourselves in the FPU-full mask */ | ||
229 | if (cpu_has_fpu) | ||
230 | cpu_set(0, mt_fpu_cpumask); | ||
231 | #endif /* CONFIG_MIPS_MT_FPAFF */ | ||
232 | if (!cpu_has_mipsmt) | ||
233 | return; | ||
234 | |||
235 | /* disable MT so we can configure */ | ||
236 | dvpe(); | ||
237 | dmt(); | ||
238 | 223 | ||
239 | /* Put MVPE's into 'configuration state' */ | 224 | local_irq_save(flags); |
240 | set_c0_mvpcontrol(MVPCONTROL_VPC); | ||
241 | 225 | ||
242 | mvpconf0 = read_c0_mvpconf0(); | 226 | vpflags = dvpe(); /* cant access the other CPU's registers whilst MVPE enabled */ |
243 | ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT; | ||
244 | 227 | ||
245 | /* we'll always have more TC's than VPE's, so loop setting everything | 228 | switch (action) { |
246 | to a sensible state */ | 229 | case SMP_CALL_FUNCTION: |
247 | for (tc = 0; tc <= ntc; tc++) { | 230 | i = C_SW1; |
248 | settc(tc); | 231 | break; |
249 | 232 | ||
250 | smp_tc_init(tc, mvpconf0); | 233 | case SMP_RESCHEDULE_YOURSELF: |
251 | ncpu = smp_vpe_init(tc, mvpconf0, ncpu); | 234 | default: |
235 | i = C_SW0; | ||
236 | break; | ||
252 | } | 237 | } |
253 | 238 | ||
254 | /* Release config state */ | 239 | /* 1:1 mapping of vpe and tc... */ |
255 | clear_c0_mvpcontrol(MVPCONTROL_VPC); | 240 | settc(cpu); |
241 | write_vpe_c0_cause(read_vpe_c0_cause() | i); | ||
242 | evpe(vpflags); | ||
256 | 243 | ||
257 | /* We'll wait until starting the secondaries before starting MVPE */ | 244 | local_irq_restore(flags); |
245 | } | ||
258 | 246 | ||
259 | printk(KERN_INFO "Detected %i available secondary CPU(s)\n", ncpu); | 247 | static void vsmp_send_ipi_mask(cpumask_t mask, unsigned int action) |
248 | { | ||
249 | unsigned int i; | ||
250 | |||
251 | for_each_cpu_mask(i, mask) | ||
252 | vsmp_send_ipi_single(i, action); | ||
260 | } | 253 | } |
261 | 254 | ||
262 | void __init plat_prepare_cpus(unsigned int max_cpus) | 255 | static void __cpuinit vsmp_init_secondary(void) |
263 | { | 256 | { |
264 | mips_mt_set_cpuoptions(); | 257 | /* Enable per-cpu interrupts */ |
265 | 258 | ||
266 | /* set up ipi interrupts */ | 259 | /* This is Malta specific: IPI,performance and timer inetrrupts */ |
267 | if (cpu_has_vint) { | 260 | write_c0_status((read_c0_status() & ~ST0_IM ) | |
268 | set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); | 261 | (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7)); |
269 | set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); | 262 | } |
270 | } | ||
271 | 263 | ||
272 | cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ; | 264 | static void __cpuinit vsmp_smp_finish(void) |
273 | cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ; | 265 | { |
266 | write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ)); | ||
274 | 267 | ||
275 | setup_irq(cpu_ipi_resched_irq, &irq_resched); | 268 | #ifdef CONFIG_MIPS_MT_FPAFF |
276 | setup_irq(cpu_ipi_call_irq, &irq_call); | 269 | /* If we have an FPU, enroll ourselves in the FPU-full mask */ |
270 | if (cpu_has_fpu) | ||
271 | cpu_set(smp_processor_id(), mt_fpu_cpumask); | ||
272 | #endif /* CONFIG_MIPS_MT_FPAFF */ | ||
277 | 273 | ||
278 | set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq); | 274 | local_irq_enable(); |
279 | set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq); | 275 | } |
276 | |||
277 | static void vsmp_cpus_done(void) | ||
278 | { | ||
280 | } | 279 | } |
281 | 280 | ||
282 | /* | 281 | /* |
@@ -287,7 +286,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus) | |||
287 | * (unsigned long)idle->thread_info the gp | 286 | * (unsigned long)idle->thread_info the gp |
288 | * assumes a 1:1 mapping of TC => VPE | 287 | * assumes a 1:1 mapping of TC => VPE |
289 | */ | 288 | */ |
290 | void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) | 289 | static void __cpuinit vsmp_boot_secondary(int cpu, struct task_struct *idle) |
291 | { | 290 | { |
292 | struct thread_info *gp = task_thread_info(idle); | 291 | struct thread_info *gp = task_thread_info(idle); |
293 | dvpe(); | 292 | dvpe(); |
@@ -321,57 +320,81 @@ void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) | |||
321 | evpe(EVPE_ENABLE); | 320 | evpe(EVPE_ENABLE); |
322 | } | 321 | } |
323 | 322 | ||
324 | void __cpuinit prom_init_secondary(void) | 323 | /* |
325 | { | 324 | * Common setup before any secondaries are started |
326 | /* Enable per-cpu interrupts */ | 325 | * Make sure all CPU's are in a sensible state before we boot any of the |
327 | 326 | * secondarys | |
328 | /* This is Malta specific: IPI,performance and timer inetrrupts */ | 327 | */ |
329 | write_c0_status((read_c0_status() & ~ST0_IM ) | | 328 | static void __init vsmp_smp_setup(void) |
330 | (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP6 | STATUSF_IP7)); | ||
331 | } | ||
332 | |||
333 | void __cpuinit prom_smp_finish(void) | ||
334 | { | 329 | { |
335 | write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ)); | 330 | unsigned int mvpconf0, ntc, tc, ncpu = 0; |
331 | unsigned int nvpe; | ||
336 | 332 | ||
337 | #ifdef CONFIG_MIPS_MT_FPAFF | 333 | #ifdef CONFIG_MIPS_MT_FPAFF |
338 | /* If we have an FPU, enroll ourselves in the FPU-full mask */ | 334 | /* If we have an FPU, enroll ourselves in the FPU-full mask */ |
339 | if (cpu_has_fpu) | 335 | if (cpu_has_fpu) |
340 | cpu_set(smp_processor_id(), mt_fpu_cpumask); | 336 | cpu_set(0, mt_fpu_cpumask); |
341 | #endif /* CONFIG_MIPS_MT_FPAFF */ | 337 | #endif /* CONFIG_MIPS_MT_FPAFF */ |
338 | if (!cpu_has_mipsmt) | ||
339 | return; | ||
342 | 340 | ||
343 | local_irq_enable(); | 341 | /* disable MT so we can configure */ |
344 | } | 342 | dvpe(); |
343 | dmt(); | ||
345 | 344 | ||
346 | void prom_cpus_done(void) | 345 | /* Put MVPE's into 'configuration state' */ |
347 | { | 346 | set_c0_mvpcontrol(MVPCONTROL_VPC); |
348 | } | ||
349 | 347 | ||
350 | void core_send_ipi(int cpu, unsigned int action) | 348 | mvpconf0 = read_c0_mvpconf0(); |
351 | { | 349 | ntc = (mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT; |
352 | int i; | ||
353 | unsigned long flags; | ||
354 | int vpflags; | ||
355 | 350 | ||
356 | local_irq_save(flags); | 351 | nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1; |
352 | smp_num_siblings = nvpe; | ||
357 | 353 | ||
358 | vpflags = dvpe(); /* cant access the other CPU's registers whilst MVPE enabled */ | 354 | /* we'll always have more TC's than VPE's, so loop setting everything |
355 | to a sensible state */ | ||
356 | for (tc = 0; tc <= ntc; tc++) { | ||
357 | settc(tc); | ||
359 | 358 | ||
360 | switch (action) { | 359 | smp_tc_init(tc, mvpconf0); |
361 | case SMP_CALL_FUNCTION: | 360 | ncpu = smp_vpe_init(tc, mvpconf0, ncpu); |
362 | i = C_SW1; | 361 | } |
363 | break; | ||
364 | 362 | ||
365 | case SMP_RESCHEDULE_YOURSELF: | 363 | /* Release config state */ |
366 | default: | 364 | clear_c0_mvpcontrol(MVPCONTROL_VPC); |
367 | i = C_SW0; | 365 | |
368 | break; | 366 | /* We'll wait until starting the secondaries before starting MVPE */ |
367 | |||
368 | printk(KERN_INFO "Detected %i available secondary CPU(s)\n", ncpu); | ||
369 | } | ||
370 | |||
371 | static void __init vsmp_prepare_cpus(unsigned int max_cpus) | ||
372 | { | ||
373 | mips_mt_set_cpuoptions(); | ||
374 | |||
375 | /* set up ipi interrupts */ | ||
376 | if (cpu_has_vint) { | ||
377 | set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch); | ||
378 | set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch); | ||
369 | } | 379 | } |
370 | 380 | ||
371 | /* 1:1 mapping of vpe and tc... */ | 381 | cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ; |
372 | settc(cpu); | 382 | cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ; |
373 | write_vpe_c0_cause(read_vpe_c0_cause() | i); | ||
374 | evpe(vpflags); | ||
375 | 383 | ||
376 | local_irq_restore(flags); | 384 | setup_irq(cpu_ipi_resched_irq, &irq_resched); |
385 | setup_irq(cpu_ipi_call_irq, &irq_call); | ||
386 | |||
387 | set_irq_handler(cpu_ipi_resched_irq, handle_percpu_irq); | ||
388 | set_irq_handler(cpu_ipi_call_irq, handle_percpu_irq); | ||
377 | } | 389 | } |
390 | |||
391 | struct plat_smp_ops vsmp_smp_ops = { | ||
392 | .send_ipi_single = vsmp_send_ipi_single, | ||
393 | .send_ipi_mask = vsmp_send_ipi_mask, | ||
394 | .init_secondary = vsmp_init_secondary, | ||
395 | .smp_finish = vsmp_smp_finish, | ||
396 | .cpus_done = vsmp_cpus_done, | ||
397 | .boot_secondary = vsmp_boot_secondary, | ||
398 | .smp_setup = vsmp_smp_setup, | ||
399 | .prepare_cpus = vsmp_prepare_cpus, | ||
400 | }; | ||
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 63989e9df4f9..1e5dfc28294a 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <asm/processor.h> | 37 | #include <asm/processor.h> |
38 | #include <asm/system.h> | 38 | #include <asm/system.h> |
39 | #include <asm/mmu_context.h> | 39 | #include <asm/mmu_context.h> |
40 | #include <asm/smp.h> | ||
41 | #include <asm/time.h> | 40 | #include <asm/time.h> |
42 | 41 | ||
43 | #ifdef CONFIG_MIPS_MT_SMTC | 42 | #ifdef CONFIG_MIPS_MT_SMTC |
@@ -56,6 +55,44 @@ EXPORT_SYMBOL(cpu_online_map); | |||
56 | extern void __init calibrate_delay(void); | 55 | extern void __init calibrate_delay(void); |
57 | extern void cpu_idle(void); | 56 | extern void cpu_idle(void); |
58 | 57 | ||
58 | /* Number of TCs (or siblings in Intel speak) per CPU core */ | ||
59 | int smp_num_siblings = 1; | ||
60 | EXPORT_SYMBOL(smp_num_siblings); | ||
61 | |||
62 | /* representing the TCs (or siblings in Intel speak) of each logical CPU */ | ||
63 | cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; | ||
64 | EXPORT_SYMBOL(cpu_sibling_map); | ||
65 | |||
66 | /* representing cpus for which sibling maps can be computed */ | ||
67 | static cpumask_t cpu_sibling_setup_map; | ||
68 | |||
69 | static inline void set_cpu_sibling_map(int cpu) | ||
70 | { | ||
71 | int i; | ||
72 | |||
73 | cpu_set(cpu, cpu_sibling_setup_map); | ||
74 | |||
75 | if (smp_num_siblings > 1) { | ||
76 | for_each_cpu_mask(i, cpu_sibling_setup_map) { | ||
77 | if (cpu_data[cpu].core == cpu_data[i].core) { | ||
78 | cpu_set(i, cpu_sibling_map[cpu]); | ||
79 | cpu_set(cpu, cpu_sibling_map[i]); | ||
80 | } | ||
81 | } | ||
82 | } else | ||
83 | cpu_set(cpu, cpu_sibling_map[cpu]); | ||
84 | } | ||
85 | |||
86 | struct plat_smp_ops *mp_ops; | ||
87 | |||
88 | __cpuinit void register_smp_ops(struct plat_smp_ops *ops) | ||
89 | { | ||
90 | if (ops) | ||
91 | printk(KERN_WARNING "Overriding previous set SMP ops\n"); | ||
92 | |||
93 | mp_ops = ops; | ||
94 | } | ||
95 | |||
59 | /* | 96 | /* |
60 | * First C code run on the secondary CPUs after being started up by | 97 | * First C code run on the secondary CPUs after being started up by |
61 | * the master. | 98 | * the master. |
@@ -72,7 +109,7 @@ asmlinkage __cpuinit void start_secondary(void) | |||
72 | cpu_report(); | 109 | cpu_report(); |
73 | per_cpu_trap_init(); | 110 | per_cpu_trap_init(); |
74 | mips_clockevent_init(); | 111 | mips_clockevent_init(); |
75 | prom_init_secondary(); | 112 | mp_ops->init_secondary(); |
76 | 113 | ||
77 | /* | 114 | /* |
78 | * XXX parity protection should be folded in here when it's converted | 115 | * XXX parity protection should be folded in here when it's converted |
@@ -84,7 +121,8 @@ asmlinkage __cpuinit void start_secondary(void) | |||
84 | cpu = smp_processor_id(); | 121 | cpu = smp_processor_id(); |
85 | cpu_data[cpu].udelay_val = loops_per_jiffy; | 122 | cpu_data[cpu].udelay_val = loops_per_jiffy; |
86 | 123 | ||
87 | prom_smp_finish(); | 124 | mp_ops->smp_finish(); |
125 | set_cpu_sibling_map(cpu); | ||
88 | 126 | ||
89 | cpu_set(cpu, cpu_callin_map); | 127 | cpu_set(cpu, cpu_callin_map); |
90 | 128 | ||
@@ -155,7 +193,7 @@ int smp_call_function_mask(cpumask_t mask, void (*func) (void *info), | |||
155 | smp_mb(); | 193 | smp_mb(); |
156 | 194 | ||
157 | /* Send a message to all other CPUs and wait for them to respond */ | 195 | /* Send a message to all other CPUs and wait for them to respond */ |
158 | core_send_ipi_mask(mask, SMP_CALL_FUNCTION); | 196 | mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION); |
159 | 197 | ||
160 | /* Wait for response */ | 198 | /* Wait for response */ |
161 | /* FIXME: lock-up detection, backtrace on lock-up */ | 199 | /* FIXME: lock-up detection, backtrace on lock-up */ |
@@ -249,7 +287,7 @@ void smp_send_stop(void) | |||
249 | 287 | ||
250 | void __init smp_cpus_done(unsigned int max_cpus) | 288 | void __init smp_cpus_done(unsigned int max_cpus) |
251 | { | 289 | { |
252 | prom_cpus_done(); | 290 | mp_ops->cpus_done(); |
253 | } | 291 | } |
254 | 292 | ||
255 | /* called from main before smp_init() */ | 293 | /* called from main before smp_init() */ |
@@ -257,7 +295,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
257 | { | 295 | { |
258 | init_new_context(current, &init_mm); | 296 | init_new_context(current, &init_mm); |
259 | current_thread_info()->cpu = 0; | 297 | current_thread_info()->cpu = 0; |
260 | plat_prepare_cpus(max_cpus); | 298 | mp_ops->prepare_cpus(max_cpus); |
299 | set_cpu_sibling_map(0); | ||
261 | #ifndef CONFIG_HOTPLUG_CPU | 300 | #ifndef CONFIG_HOTPLUG_CPU |
262 | cpu_present_map = cpu_possible_map; | 301 | cpu_present_map = cpu_possible_map; |
263 | #endif | 302 | #endif |
@@ -295,7 +334,7 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
295 | if (IS_ERR(idle)) | 334 | if (IS_ERR(idle)) |
296 | panic(KERN_ERR "Fork failed for CPU %d", cpu); | 335 | panic(KERN_ERR "Fork failed for CPU %d", cpu); |
297 | 336 | ||
298 | prom_boot_secondary(cpu, idle); | 337 | mp_ops->boot_secondary(cpu, idle); |
299 | 338 | ||
300 | /* | 339 | /* |
301 | * Trust is futile. We should really have timeouts ... | 340 | * Trust is futile. We should really have timeouts ... |
diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c index 6f3709996172..fe256559c997 100644 --- a/arch/mips/kernel/smtc-proc.c +++ b/arch/mips/kernel/smtc-proc.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <asm/system.h> | 14 | #include <asm/system.h> |
15 | #include <asm/hardirq.h> | 15 | #include <asm/hardirq.h> |
16 | #include <asm/mmu_context.h> | 16 | #include <asm/mmu_context.h> |
17 | #include <asm/smp.h> | ||
18 | #include <asm/mipsregs.h> | 17 | #include <asm/mipsregs.h> |
19 | #include <asm/cacheflush.h> | 18 | #include <asm/cacheflush.h> |
20 | #include <linux/proc_fs.h> | 19 | #include <linux/proc_fs.h> |
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 9c92d42996cb..85f700e58131 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <asm/hazards.h> | 16 | #include <asm/hazards.h> |
17 | #include <asm/irq.h> | 17 | #include <asm/irq.h> |
18 | #include <asm/mmu_context.h> | 18 | #include <asm/mmu_context.h> |
19 | #include <asm/smp.h> | ||
20 | #include <asm/mipsregs.h> | 19 | #include <asm/mipsregs.h> |
21 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
22 | #include <asm/time.h> | 21 | #include <asm/time.h> |
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c index 2995be1ab3ca..9f85d4cecc5b 100644 --- a/arch/mips/kernel/time.c +++ b/arch/mips/kernel/time.c | |||
@@ -50,8 +50,6 @@ int update_persistent_clock(struct timespec now) | |||
50 | return rtc_mips_set_mmss(now.tv_sec); | 50 | return rtc_mips_set_mmss(now.tv_sec); |
51 | } | 51 | } |
52 | 52 | ||
53 | int (*mips_timer_state)(void); | ||
54 | |||
55 | int null_perf_irq(void) | 53 | int null_perf_irq(void) |
56 | { | 54 | { |
57 | return 0; | 55 | return 0; |
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 5fc2398bdb76..b5470ceb418b 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S | |||
@@ -114,11 +114,11 @@ SECTIONS | |||
114 | __init_begin = .; | 114 | __init_begin = .; |
115 | .init.text : { | 115 | .init.text : { |
116 | _sinittext = .; | 116 | _sinittext = .; |
117 | *(.init.text) | 117 | INIT_TEXT |
118 | _einittext = .; | 118 | _einittext = .; |
119 | } | 119 | } |
120 | .init.data : { | 120 | .init.data : { |
121 | *(.init.data) | 121 | INIT_DATA |
122 | } | 122 | } |
123 | . = ALIGN(16); | 123 | . = ALIGN(16); |
124 | .init.setup : { | 124 | .init.setup : { |
@@ -144,10 +144,10 @@ SECTIONS | |||
144 | * references from .rodata | 144 | * references from .rodata |
145 | */ | 145 | */ |
146 | .exit.text : { | 146 | .exit.text : { |
147 | *(.exit.text) | 147 | EXIT_TEXT |
148 | } | 148 | } |
149 | .exit.data : { | 149 | .exit.data : { |
150 | *(.exit.data) | 150 | EXIT_DATA |
151 | } | 151 | } |
152 | #if defined(CONFIG_BLK_DEV_INITRD) | 152 | #if defined(CONFIG_BLK_DEV_INITRD) |
153 | . = ALIGN(_PAGE_SIZE); | 153 | . = ALIGN(_PAGE_SIZE); |
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index c06eb812a95e..eed2dc4273e0 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c | |||
@@ -53,7 +53,6 @@ | |||
53 | #include <asm/system.h> | 53 | #include <asm/system.h> |
54 | #include <asm/vpe.h> | 54 | #include <asm/vpe.h> |
55 | #include <asm/kspd.h> | 55 | #include <asm/kspd.h> |
56 | #include <asm/mips_mt.h> | ||
57 | 56 | ||
58 | typedef void *vpe_handle; | 57 | typedef void *vpe_handle; |
59 | 58 | ||
diff --git a/arch/mips/lasat/picvue.c b/arch/mips/lasat/picvue.c index 6471d0663fd8..d3d04c392e25 100644 --- a/arch/mips/lasat/picvue.c +++ b/arch/mips/lasat/picvue.c | |||
@@ -22,8 +22,6 @@ | |||
22 | 22 | ||
23 | struct pvc_defs *picvue; | 23 | struct pvc_defs *picvue; |
24 | 24 | ||
25 | DECLARE_MUTEX(pvc_sem); | ||
26 | |||
27 | static void pvc_reg_write(u32 val) | 25 | static void pvc_reg_write(u32 val) |
28 | { | 26 | { |
29 | *picvue->reg = val; | 27 | *picvue->reg = val; |
diff --git a/arch/mips/lasat/picvue.h b/arch/mips/lasat/picvue.h index 2a96bf971897..91df55371127 100644 --- a/arch/mips/lasat/picvue.h +++ b/arch/mips/lasat/picvue.h | |||
@@ -4,8 +4,6 @@ | |||
4 | * Brian Murphy <brian.murphy@eicon.com> | 4 | * Brian Murphy <brian.murphy@eicon.com> |
5 | * | 5 | * |
6 | */ | 6 | */ |
7 | #include <asm/semaphore.h> | ||
8 | |||
9 | struct pvc_defs { | 7 | struct pvc_defs { |
10 | volatile u32 *reg; | 8 | volatile u32 *reg; |
11 | u32 data_shift; | 9 | u32 data_shift; |
@@ -45,4 +43,3 @@ void pvc_move(u8 cmd); | |||
45 | void pvc_clear(void); | 43 | void pvc_clear(void); |
46 | void pvc_home(void); | 44 | void pvc_home(void); |
47 | 45 | ||
48 | extern struct semaphore pvc_sem; | ||
diff --git a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c index 9947c1525822..0bb6037afba3 100644 --- a/arch/mips/lasat/picvue_proc.c +++ b/arch/mips/lasat/picvue_proc.c | |||
@@ -13,9 +13,11 @@ | |||
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | 14 | ||
15 | #include <linux/timer.h> | 15 | #include <linux/timer.h> |
16 | #include <linux/mutex.h> | ||
16 | 17 | ||
17 | #include "picvue.h" | 18 | #include "picvue.h" |
18 | 19 | ||
20 | static DEFINE_MUTEX(pvc_mutex); | ||
19 | static char pvc_lines[PVC_NLINES][PVC_LINELEN+1]; | 21 | static char pvc_lines[PVC_NLINES][PVC_LINELEN+1]; |
20 | static int pvc_linedata[PVC_NLINES]; | 22 | static int pvc_linedata[PVC_NLINES]; |
21 | static struct proc_dir_entry *pvc_display_dir; | 23 | static struct proc_dir_entry *pvc_display_dir; |
@@ -48,9 +50,9 @@ static int pvc_proc_read_line(char *page, char **start, | |||
48 | return 0; | 50 | return 0; |
49 | } | 51 | } |
50 | 52 | ||
51 | down(&pvc_sem); | 53 | mutex_lock(&pvc_mutex); |
52 | page += sprintf(page, "%s\n", pvc_lines[lineno]); | 54 | page += sprintf(page, "%s\n", pvc_lines[lineno]); |
53 | up(&pvc_sem); | 55 | mutex_unlock(&pvc_mutex); |
54 | 56 | ||
55 | return page - origpage; | 57 | return page - origpage; |
56 | } | 58 | } |
@@ -73,10 +75,10 @@ static int pvc_proc_write_line(struct file *file, const char *buffer, | |||
73 | if (buffer[count-1] == '\n') | 75 | if (buffer[count-1] == '\n') |
74 | count--; | 76 | count--; |
75 | 77 | ||
76 | down(&pvc_sem); | 78 | mutex_lock(&pvc_mutex); |
77 | strncpy(pvc_lines[lineno], buffer, count); | 79 | strncpy(pvc_lines[lineno], buffer, count); |
78 | pvc_lines[lineno][count] = '\0'; | 80 | pvc_lines[lineno][count] = '\0'; |
79 | up(&pvc_sem); | 81 | mutex_unlock(&pvc_mutex); |
80 | 82 | ||
81 | tasklet_schedule(&pvc_display_tasklet); | 83 | tasklet_schedule(&pvc_display_tasklet); |
82 | 84 | ||
@@ -89,7 +91,7 @@ static int pvc_proc_write_scroll(struct file *file, const char *buffer, | |||
89 | int origcount = count; | 91 | int origcount = count; |
90 | int cmd = simple_strtol(buffer, NULL, 10); | 92 | int cmd = simple_strtol(buffer, NULL, 10); |
91 | 93 | ||
92 | down(&pvc_sem); | 94 | mutex_lock(&pvc_mutex); |
93 | if (scroll_interval != 0) | 95 | if (scroll_interval != 0) |
94 | del_timer(&timer); | 96 | del_timer(&timer); |
95 | 97 | ||
@@ -106,7 +108,7 @@ static int pvc_proc_write_scroll(struct file *file, const char *buffer, | |||
106 | } | 108 | } |
107 | add_timer(&timer); | 109 | add_timer(&timer); |
108 | } | 110 | } |
109 | up(&pvc_sem); | 111 | mutex_unlock(&pvc_mutex); |
110 | 112 | ||
111 | return origcount; | 113 | return origcount; |
112 | } | 114 | } |
@@ -117,9 +119,9 @@ static int pvc_proc_read_scroll(char *page, char **start, | |||
117 | { | 119 | { |
118 | char *origpage = page; | 120 | char *origpage = page; |
119 | 121 | ||
120 | down(&pvc_sem); | 122 | mutex_lock(&pvc_mutex); |
121 | page += sprintf(page, "%d\n", scroll_dir * scroll_interval); | 123 | page += sprintf(page, "%d\n", scroll_dir * scroll_interval); |
122 | up(&pvc_sem); | 124 | mutex_unlock(&pvc_mutex); |
123 | 125 | ||
124 | return page - origpage; | 126 | return page - origpage; |
125 | } | 127 | } |
diff --git a/arch/mips/lemote/lm2e/pci.c b/arch/mips/lemote/lm2e/pci.c index 1ade1cef3899..c1e41f15cc7e 100644 --- a/arch/mips/lemote/lm2e/pci.c +++ b/arch/mips/lemote/lm2e/pci.c | |||
@@ -81,9 +81,6 @@ static void __init ict_pcimap(void) | |||
81 | 81 | ||
82 | static int __init pcibios_init(void) | 82 | static int __init pcibios_init(void) |
83 | { | 83 | { |
84 | extern int pci_probe_only; | ||
85 | pci_probe_only = 0; | ||
86 | |||
87 | ict_pcimap(); | 84 | ict_pcimap(); |
88 | register_pci_controller(&loongson2e_pci_controller); | 85 | register_pci_controller(&loongson2e_pci_controller); |
89 | 86 | ||
diff --git a/arch/mips/lemote/lm2e/prom.c b/arch/mips/lemote/lm2e/prom.c index 824336812198..7edc15dfed6c 100644 --- a/arch/mips/lemote/lm2e/prom.c +++ b/arch/mips/lemote/lm2e/prom.c | |||
@@ -57,8 +57,6 @@ void __init prom_init(void) | |||
57 | arg = (int *)fw_arg1; | 57 | arg = (int *)fw_arg1; |
58 | env = (int *)fw_arg2; | 58 | env = (int *)fw_arg2; |
59 | 59 | ||
60 | mips_machtype = MACH_LEMOTE_FULONG; | ||
61 | |||
62 | prom_init_cmdline(); | 60 | prom_init_cmdline(); |
63 | 61 | ||
64 | if ((strstr(arcs_cmdline, "console=")) == NULL) | 62 | if ((strstr(arcs_cmdline, "console=")) == NULL) |
diff --git a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S index c0a77fe038be..8d7784122c14 100644 --- a/arch/mips/lib/csum_partial.S +++ b/arch/mips/lib/csum_partial.S | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright (C) 1998, 1999 Ralf Baechle | 8 | * Copyright (C) 1998, 1999 Ralf Baechle |
9 | * Copyright (C) 1999 Silicon Graphics, Inc. | 9 | * Copyright (C) 1999 Silicon Graphics, Inc. |
10 | * Copyright (C) 2007 Maciej W. Rozycki | ||
10 | */ | 11 | */ |
11 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
12 | #include <asm/asm.h> | 13 | #include <asm/asm.h> |
@@ -52,9 +53,12 @@ | |||
52 | #define UNIT(unit) ((unit)*NBYTES) | 53 | #define UNIT(unit) ((unit)*NBYTES) |
53 | 54 | ||
54 | #define ADDC(sum,reg) \ | 55 | #define ADDC(sum,reg) \ |
56 | .set push; \ | ||
57 | .set noat; \ | ||
55 | ADD sum, reg; \ | 58 | ADD sum, reg; \ |
56 | sltu v1, sum, reg; \ | 59 | sltu v1, sum, reg; \ |
57 | ADD sum, v1 | 60 | ADD sum, v1; \ |
61 | .set pop | ||
58 | 62 | ||
59 | #define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \ | 63 | #define CSUM_BIGCHUNK1(src, offset, sum, _t0, _t1, _t2, _t3) \ |
60 | LOAD _t0, (offset + UNIT(0))(src); \ | 64 | LOAD _t0, (offset + UNIT(0))(src); \ |
@@ -92,13 +96,13 @@ LEAF(csum_partial) | |||
92 | move t7, zero | 96 | move t7, zero |
93 | 97 | ||
94 | sltiu t8, a1, 0x8 | 98 | sltiu t8, a1, 0x8 |
95 | bnez t8, small_csumcpy /* < 8 bytes to copy */ | 99 | bnez t8, .Lsmall_csumcpy /* < 8 bytes to copy */ |
96 | move t2, a1 | 100 | move t2, a1 |
97 | 101 | ||
98 | andi t7, src, 0x1 /* odd buffer? */ | 102 | andi t7, src, 0x1 /* odd buffer? */ |
99 | 103 | ||
100 | hword_align: | 104 | .Lhword_align: |
101 | beqz t7, word_align | 105 | beqz t7, .Lword_align |
102 | andi t8, src, 0x2 | 106 | andi t8, src, 0x2 |
103 | 107 | ||
104 | lbu t0, (src) | 108 | lbu t0, (src) |
@@ -110,8 +114,8 @@ hword_align: | |||
110 | PTR_ADDU src, src, 0x1 | 114 | PTR_ADDU src, src, 0x1 |
111 | andi t8, src, 0x2 | 115 | andi t8, src, 0x2 |
112 | 116 | ||
113 | word_align: | 117 | .Lword_align: |
114 | beqz t8, dword_align | 118 | beqz t8, .Ldword_align |
115 | sltiu t8, a1, 56 | 119 | sltiu t8, a1, 56 |
116 | 120 | ||
117 | lhu t0, (src) | 121 | lhu t0, (src) |
@@ -120,12 +124,12 @@ word_align: | |||
120 | sltiu t8, a1, 56 | 124 | sltiu t8, a1, 56 |
121 | PTR_ADDU src, src, 0x2 | 125 | PTR_ADDU src, src, 0x2 |
122 | 126 | ||
123 | dword_align: | 127 | .Ldword_align: |
124 | bnez t8, do_end_words | 128 | bnez t8, .Ldo_end_words |
125 | move t8, a1 | 129 | move t8, a1 |
126 | 130 | ||
127 | andi t8, src, 0x4 | 131 | andi t8, src, 0x4 |
128 | beqz t8, qword_align | 132 | beqz t8, .Lqword_align |
129 | andi t8, src, 0x8 | 133 | andi t8, src, 0x8 |
130 | 134 | ||
131 | lw t0, 0x00(src) | 135 | lw t0, 0x00(src) |
@@ -134,8 +138,8 @@ dword_align: | |||
134 | PTR_ADDU src, src, 0x4 | 138 | PTR_ADDU src, src, 0x4 |
135 | andi t8, src, 0x8 | 139 | andi t8, src, 0x8 |
136 | 140 | ||
137 | qword_align: | 141 | .Lqword_align: |
138 | beqz t8, oword_align | 142 | beqz t8, .Loword_align |
139 | andi t8, src, 0x10 | 143 | andi t8, src, 0x10 |
140 | 144 | ||
141 | #ifdef USE_DOUBLE | 145 | #ifdef USE_DOUBLE |
@@ -152,8 +156,8 @@ qword_align: | |||
152 | PTR_ADDU src, src, 0x8 | 156 | PTR_ADDU src, src, 0x8 |
153 | andi t8, src, 0x10 | 157 | andi t8, src, 0x10 |
154 | 158 | ||
155 | oword_align: | 159 | .Loword_align: |
156 | beqz t8, begin_movement | 160 | beqz t8, .Lbegin_movement |
157 | LONG_SRL t8, a1, 0x7 | 161 | LONG_SRL t8, a1, 0x7 |
158 | 162 | ||
159 | #ifdef USE_DOUBLE | 163 | #ifdef USE_DOUBLE |
@@ -168,51 +172,55 @@ oword_align: | |||
168 | PTR_ADDU src, src, 0x10 | 172 | PTR_ADDU src, src, 0x10 |
169 | LONG_SRL t8, a1, 0x7 | 173 | LONG_SRL t8, a1, 0x7 |
170 | 174 | ||
171 | begin_movement: | 175 | .Lbegin_movement: |
172 | beqz t8, 1f | 176 | beqz t8, 1f |
173 | andi t2, a1, 0x40 | 177 | andi t2, a1, 0x40 |
174 | 178 | ||
175 | move_128bytes: | 179 | .Lmove_128bytes: |
176 | CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) | 180 | CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) |
177 | CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4) | 181 | CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4) |
178 | CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4) | 182 | CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4) |
179 | CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4) | 183 | CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4) |
180 | LONG_SUBU t8, t8, 0x01 | 184 | LONG_SUBU t8, t8, 0x01 |
181 | bnez t8, move_128bytes | 185 | .set reorder /* DADDI_WAR */ |
182 | PTR_ADDU src, src, 0x80 | 186 | PTR_ADDU src, src, 0x80 |
187 | bnez t8, .Lmove_128bytes | ||
188 | .set noreorder | ||
183 | 189 | ||
184 | 1: | 190 | 1: |
185 | beqz t2, 1f | 191 | beqz t2, 1f |
186 | andi t2, a1, 0x20 | 192 | andi t2, a1, 0x20 |
187 | 193 | ||
188 | move_64bytes: | 194 | .Lmove_64bytes: |
189 | CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) | 195 | CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) |
190 | CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4) | 196 | CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4) |
191 | PTR_ADDU src, src, 0x40 | 197 | PTR_ADDU src, src, 0x40 |
192 | 198 | ||
193 | 1: | 199 | 1: |
194 | beqz t2, do_end_words | 200 | beqz t2, .Ldo_end_words |
195 | andi t8, a1, 0x1c | 201 | andi t8, a1, 0x1c |
196 | 202 | ||
197 | move_32bytes: | 203 | .Lmove_32bytes: |
198 | CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) | 204 | CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4) |
199 | andi t8, a1, 0x1c | 205 | andi t8, a1, 0x1c |
200 | PTR_ADDU src, src, 0x20 | 206 | PTR_ADDU src, src, 0x20 |
201 | 207 | ||
202 | do_end_words: | 208 | .Ldo_end_words: |
203 | beqz t8, small_csumcpy | 209 | beqz t8, .Lsmall_csumcpy |
204 | andi t2, a1, 0x3 | 210 | andi t2, a1, 0x3 |
205 | LONG_SRL t8, t8, 0x2 | 211 | LONG_SRL t8, t8, 0x2 |
206 | 212 | ||
207 | end_words: | 213 | .Lend_words: |
208 | lw t0, (src) | 214 | lw t0, (src) |
209 | LONG_SUBU t8, t8, 0x1 | 215 | LONG_SUBU t8, t8, 0x1 |
210 | ADDC(sum, t0) | 216 | ADDC(sum, t0) |
211 | bnez t8, end_words | 217 | .set reorder /* DADDI_WAR */ |
212 | PTR_ADDU src, src, 0x4 | 218 | PTR_ADDU src, src, 0x4 |
219 | bnez t8, .Lend_words | ||
220 | .set noreorder | ||
213 | 221 | ||
214 | /* unknown src alignment and < 8 bytes to go */ | 222 | /* unknown src alignment and < 8 bytes to go */ |
215 | small_csumcpy: | 223 | .Lsmall_csumcpy: |
216 | move a1, t2 | 224 | move a1, t2 |
217 | 225 | ||
218 | andi t0, a1, 4 | 226 | andi t0, a1, 4 |
@@ -246,6 +254,8 @@ small_csumcpy: | |||
246 | 1: ADDC(sum, t1) | 254 | 1: ADDC(sum, t1) |
247 | 255 | ||
248 | /* fold checksum */ | 256 | /* fold checksum */ |
257 | .set push | ||
258 | .set noat | ||
249 | #ifdef USE_DOUBLE | 259 | #ifdef USE_DOUBLE |
250 | dsll32 v1, sum, 0 | 260 | dsll32 v1, sum, 0 |
251 | daddu sum, v1 | 261 | daddu sum, v1 |
@@ -266,6 +276,7 @@ small_csumcpy: | |||
266 | srl sum, sum, 8 | 276 | srl sum, sum, 8 |
267 | or sum, v1 | 277 | or sum, v1 |
268 | andi sum, 0xffff | 278 | andi sum, 0xffff |
279 | .set pop | ||
269 | 1: | 280 | 1: |
270 | .set reorder | 281 | .set reorder |
271 | /* Add the passed partial csum. */ | 282 | /* Add the passed partial csum. */ |
@@ -373,7 +384,11 @@ small_csumcpy: | |||
373 | 384 | ||
374 | #define ADDRMASK (NBYTES-1) | 385 | #define ADDRMASK (NBYTES-1) |
375 | 386 | ||
387 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS | ||
376 | .set noat | 388 | .set noat |
389 | #else | ||
390 | .set at=v1 | ||
391 | #endif | ||
377 | 392 | ||
378 | LEAF(__csum_partial_copy_user) | 393 | LEAF(__csum_partial_copy_user) |
379 | PTR_ADDU AT, src, len /* See (1) above. */ | 394 | PTR_ADDU AT, src, len /* See (1) above. */ |
@@ -398,95 +413,101 @@ FEXPORT(csum_partial_copy_nocheck) | |||
398 | */ | 413 | */ |
399 | sltu t2, len, NBYTES | 414 | sltu t2, len, NBYTES |
400 | and t1, dst, ADDRMASK | 415 | and t1, dst, ADDRMASK |
401 | bnez t2, copy_bytes_checklen | 416 | bnez t2, .Lcopy_bytes_checklen |
402 | and t0, src, ADDRMASK | 417 | and t0, src, ADDRMASK |
403 | andi odd, dst, 0x1 /* odd buffer? */ | 418 | andi odd, dst, 0x1 /* odd buffer? */ |
404 | bnez t1, dst_unaligned | 419 | bnez t1, .Ldst_unaligned |
405 | nop | 420 | nop |
406 | bnez t0, src_unaligned_dst_aligned | 421 | bnez t0, .Lsrc_unaligned_dst_aligned |
407 | /* | 422 | /* |
408 | * use delay slot for fall-through | 423 | * use delay slot for fall-through |
409 | * src and dst are aligned; need to compute rem | 424 | * src and dst are aligned; need to compute rem |
410 | */ | 425 | */ |
411 | both_aligned: | 426 | .Lboth_aligned: |
412 | SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter | 427 | SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter |
413 | beqz t0, cleanup_both_aligned # len < 8*NBYTES | 428 | beqz t0, .Lcleanup_both_aligned # len < 8*NBYTES |
414 | nop | 429 | nop |
415 | SUB len, 8*NBYTES # subtract here for bgez loop | 430 | SUB len, 8*NBYTES # subtract here for bgez loop |
416 | .align 4 | 431 | .align 4 |
417 | 1: | 432 | 1: |
418 | EXC( LOAD t0, UNIT(0)(src), l_exc) | 433 | EXC( LOAD t0, UNIT(0)(src), .Ll_exc) |
419 | EXC( LOAD t1, UNIT(1)(src), l_exc_copy) | 434 | EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) |
420 | EXC( LOAD t2, UNIT(2)(src), l_exc_copy) | 435 | EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) |
421 | EXC( LOAD t3, UNIT(3)(src), l_exc_copy) | 436 | EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) |
422 | EXC( LOAD t4, UNIT(4)(src), l_exc_copy) | 437 | EXC( LOAD t4, UNIT(4)(src), .Ll_exc_copy) |
423 | EXC( LOAD t5, UNIT(5)(src), l_exc_copy) | 438 | EXC( LOAD t5, UNIT(5)(src), .Ll_exc_copy) |
424 | EXC( LOAD t6, UNIT(6)(src), l_exc_copy) | 439 | EXC( LOAD t6, UNIT(6)(src), .Ll_exc_copy) |
425 | EXC( LOAD t7, UNIT(7)(src), l_exc_copy) | 440 | EXC( LOAD t7, UNIT(7)(src), .Ll_exc_copy) |
426 | SUB len, len, 8*NBYTES | 441 | SUB len, len, 8*NBYTES |
427 | ADD src, src, 8*NBYTES | 442 | ADD src, src, 8*NBYTES |
428 | EXC( STORE t0, UNIT(0)(dst), s_exc) | 443 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc) |
429 | ADDC(sum, t0) | 444 | ADDC(sum, t0) |
430 | EXC( STORE t1, UNIT(1)(dst), s_exc) | 445 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc) |
431 | ADDC(sum, t1) | 446 | ADDC(sum, t1) |
432 | EXC( STORE t2, UNIT(2)(dst), s_exc) | 447 | EXC( STORE t2, UNIT(2)(dst), .Ls_exc) |
433 | ADDC(sum, t2) | 448 | ADDC(sum, t2) |
434 | EXC( STORE t3, UNIT(3)(dst), s_exc) | 449 | EXC( STORE t3, UNIT(3)(dst), .Ls_exc) |
435 | ADDC(sum, t3) | 450 | ADDC(sum, t3) |
436 | EXC( STORE t4, UNIT(4)(dst), s_exc) | 451 | EXC( STORE t4, UNIT(4)(dst), .Ls_exc) |
437 | ADDC(sum, t4) | 452 | ADDC(sum, t4) |
438 | EXC( STORE t5, UNIT(5)(dst), s_exc) | 453 | EXC( STORE t5, UNIT(5)(dst), .Ls_exc) |
439 | ADDC(sum, t5) | 454 | ADDC(sum, t5) |
440 | EXC( STORE t6, UNIT(6)(dst), s_exc) | 455 | EXC( STORE t6, UNIT(6)(dst), .Ls_exc) |
441 | ADDC(sum, t6) | 456 | ADDC(sum, t6) |
442 | EXC( STORE t7, UNIT(7)(dst), s_exc) | 457 | EXC( STORE t7, UNIT(7)(dst), .Ls_exc) |
443 | ADDC(sum, t7) | 458 | ADDC(sum, t7) |
459 | .set reorder /* DADDI_WAR */ | ||
460 | ADD dst, dst, 8*NBYTES | ||
444 | bgez len, 1b | 461 | bgez len, 1b |
445 | ADD dst, dst, 8*NBYTES | 462 | .set noreorder |
446 | ADD len, 8*NBYTES # revert len (see above) | 463 | ADD len, 8*NBYTES # revert len (see above) |
447 | 464 | ||
448 | /* | 465 | /* |
449 | * len == the number of bytes left to copy < 8*NBYTES | 466 | * len == the number of bytes left to copy < 8*NBYTES |
450 | */ | 467 | */ |
451 | cleanup_both_aligned: | 468 | .Lcleanup_both_aligned: |
452 | #define rem t7 | 469 | #define rem t7 |
453 | beqz len, done | 470 | beqz len, .Ldone |
454 | sltu t0, len, 4*NBYTES | 471 | sltu t0, len, 4*NBYTES |
455 | bnez t0, less_than_4units | 472 | bnez t0, .Lless_than_4units |
456 | and rem, len, (NBYTES-1) # rem = len % NBYTES | 473 | and rem, len, (NBYTES-1) # rem = len % NBYTES |
457 | /* | 474 | /* |
458 | * len >= 4*NBYTES | 475 | * len >= 4*NBYTES |
459 | */ | 476 | */ |
460 | EXC( LOAD t0, UNIT(0)(src), l_exc) | 477 | EXC( LOAD t0, UNIT(0)(src), .Ll_exc) |
461 | EXC( LOAD t1, UNIT(1)(src), l_exc_copy) | 478 | EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) |
462 | EXC( LOAD t2, UNIT(2)(src), l_exc_copy) | 479 | EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) |
463 | EXC( LOAD t3, UNIT(3)(src), l_exc_copy) | 480 | EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) |
464 | SUB len, len, 4*NBYTES | 481 | SUB len, len, 4*NBYTES |
465 | ADD src, src, 4*NBYTES | 482 | ADD src, src, 4*NBYTES |
466 | EXC( STORE t0, UNIT(0)(dst), s_exc) | 483 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc) |
467 | ADDC(sum, t0) | 484 | ADDC(sum, t0) |
468 | EXC( STORE t1, UNIT(1)(dst), s_exc) | 485 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc) |
469 | ADDC(sum, t1) | 486 | ADDC(sum, t1) |
470 | EXC( STORE t2, UNIT(2)(dst), s_exc) | 487 | EXC( STORE t2, UNIT(2)(dst), .Ls_exc) |
471 | ADDC(sum, t2) | 488 | ADDC(sum, t2) |
472 | EXC( STORE t3, UNIT(3)(dst), s_exc) | 489 | EXC( STORE t3, UNIT(3)(dst), .Ls_exc) |
473 | ADDC(sum, t3) | 490 | ADDC(sum, t3) |
474 | beqz len, done | 491 | .set reorder /* DADDI_WAR */ |
475 | ADD dst, dst, 4*NBYTES | 492 | ADD dst, dst, 4*NBYTES |
476 | less_than_4units: | 493 | beqz len, .Ldone |
494 | .set noreorder | ||
495 | .Lless_than_4units: | ||
477 | /* | 496 | /* |
478 | * rem = len % NBYTES | 497 | * rem = len % NBYTES |
479 | */ | 498 | */ |
480 | beq rem, len, copy_bytes | 499 | beq rem, len, .Lcopy_bytes |
481 | nop | 500 | nop |
482 | 1: | 501 | 1: |
483 | EXC( LOAD t0, 0(src), l_exc) | 502 | EXC( LOAD t0, 0(src), .Ll_exc) |
484 | ADD src, src, NBYTES | 503 | ADD src, src, NBYTES |
485 | SUB len, len, NBYTES | 504 | SUB len, len, NBYTES |
486 | EXC( STORE t0, 0(dst), s_exc) | 505 | EXC( STORE t0, 0(dst), .Ls_exc) |
487 | ADDC(sum, t0) | 506 | ADDC(sum, t0) |
507 | .set reorder /* DADDI_WAR */ | ||
508 | ADD dst, dst, NBYTES | ||
488 | bne rem, len, 1b | 509 | bne rem, len, 1b |
489 | ADD dst, dst, NBYTES | 510 | .set noreorder |
490 | 511 | ||
491 | /* | 512 | /* |
492 | * src and dst are aligned, need to copy rem bytes (rem < NBYTES) | 513 | * src and dst are aligned, need to copy rem bytes (rem < NBYTES) |
@@ -500,20 +521,20 @@ EXC( STORE t0, 0(dst), s_exc) | |||
500 | * more instruction-level parallelism. | 521 | * more instruction-level parallelism. |
501 | */ | 522 | */ |
502 | #define bits t2 | 523 | #define bits t2 |
503 | beqz len, done | 524 | beqz len, .Ldone |
504 | ADD t1, dst, len # t1 is just past last byte of dst | 525 | ADD t1, dst, len # t1 is just past last byte of dst |
505 | li bits, 8*NBYTES | 526 | li bits, 8*NBYTES |
506 | SLL rem, len, 3 # rem = number of bits to keep | 527 | SLL rem, len, 3 # rem = number of bits to keep |
507 | EXC( LOAD t0, 0(src), l_exc) | 528 | EXC( LOAD t0, 0(src), .Ll_exc) |
508 | SUB bits, bits, rem # bits = number of bits to discard | 529 | SUB bits, bits, rem # bits = number of bits to discard |
509 | SHIFT_DISCARD t0, t0, bits | 530 | SHIFT_DISCARD t0, t0, bits |
510 | EXC( STREST t0, -1(t1), s_exc) | 531 | EXC( STREST t0, -1(t1), .Ls_exc) |
511 | SHIFT_DISCARD_REVERT t0, t0, bits | 532 | SHIFT_DISCARD_REVERT t0, t0, bits |
512 | .set reorder | 533 | .set reorder |
513 | ADDC(sum, t0) | 534 | ADDC(sum, t0) |
514 | b done | 535 | b .Ldone |
515 | .set noreorder | 536 | .set noreorder |
516 | dst_unaligned: | 537 | .Ldst_unaligned: |
517 | /* | 538 | /* |
518 | * dst is unaligned | 539 | * dst is unaligned |
519 | * t0 = src & ADDRMASK | 540 | * t0 = src & ADDRMASK |
@@ -524,25 +545,25 @@ dst_unaligned: | |||
524 | * Set match = (src and dst have same alignment) | 545 | * Set match = (src and dst have same alignment) |
525 | */ | 546 | */ |
526 | #define match rem | 547 | #define match rem |
527 | EXC( LDFIRST t3, FIRST(0)(src), l_exc) | 548 | EXC( LDFIRST t3, FIRST(0)(src), .Ll_exc) |
528 | ADD t2, zero, NBYTES | 549 | ADD t2, zero, NBYTES |
529 | EXC( LDREST t3, REST(0)(src), l_exc_copy) | 550 | EXC( LDREST t3, REST(0)(src), .Ll_exc_copy) |
530 | SUB t2, t2, t1 # t2 = number of bytes copied | 551 | SUB t2, t2, t1 # t2 = number of bytes copied |
531 | xor match, t0, t1 | 552 | xor match, t0, t1 |
532 | EXC( STFIRST t3, FIRST(0)(dst), s_exc) | 553 | EXC( STFIRST t3, FIRST(0)(dst), .Ls_exc) |
533 | SLL t4, t1, 3 # t4 = number of bits to discard | 554 | SLL t4, t1, 3 # t4 = number of bits to discard |
534 | SHIFT_DISCARD t3, t3, t4 | 555 | SHIFT_DISCARD t3, t3, t4 |
535 | /* no SHIFT_DISCARD_REVERT to handle odd buffer properly */ | 556 | /* no SHIFT_DISCARD_REVERT to handle odd buffer properly */ |
536 | ADDC(sum, t3) | 557 | ADDC(sum, t3) |
537 | beq len, t2, done | 558 | beq len, t2, .Ldone |
538 | SUB len, len, t2 | 559 | SUB len, len, t2 |
539 | ADD dst, dst, t2 | 560 | ADD dst, dst, t2 |
540 | beqz match, both_aligned | 561 | beqz match, .Lboth_aligned |
541 | ADD src, src, t2 | 562 | ADD src, src, t2 |
542 | 563 | ||
543 | src_unaligned_dst_aligned: | 564 | .Lsrc_unaligned_dst_aligned: |
544 | SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter | 565 | SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter |
545 | beqz t0, cleanup_src_unaligned | 566 | beqz t0, .Lcleanup_src_unaligned |
546 | and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES | 567 | and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES |
547 | 1: | 568 | 1: |
548 | /* | 569 | /* |
@@ -551,49 +572,53 @@ src_unaligned_dst_aligned: | |||
551 | * It's OK to load FIRST(N+1) before REST(N) because the two addresses | 572 | * It's OK to load FIRST(N+1) before REST(N) because the two addresses |
552 | * are to the same unit (unless src is aligned, but it's not). | 573 | * are to the same unit (unless src is aligned, but it's not). |
553 | */ | 574 | */ |
554 | EXC( LDFIRST t0, FIRST(0)(src), l_exc) | 575 | EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) |
555 | EXC( LDFIRST t1, FIRST(1)(src), l_exc_copy) | 576 | EXC( LDFIRST t1, FIRST(1)(src), .Ll_exc_copy) |
556 | SUB len, len, 4*NBYTES | 577 | SUB len, len, 4*NBYTES |
557 | EXC( LDREST t0, REST(0)(src), l_exc_copy) | 578 | EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) |
558 | EXC( LDREST t1, REST(1)(src), l_exc_copy) | 579 | EXC( LDREST t1, REST(1)(src), .Ll_exc_copy) |
559 | EXC( LDFIRST t2, FIRST(2)(src), l_exc_copy) | 580 | EXC( LDFIRST t2, FIRST(2)(src), .Ll_exc_copy) |
560 | EXC( LDFIRST t3, FIRST(3)(src), l_exc_copy) | 581 | EXC( LDFIRST t3, FIRST(3)(src), .Ll_exc_copy) |
561 | EXC( LDREST t2, REST(2)(src), l_exc_copy) | 582 | EXC( LDREST t2, REST(2)(src), .Ll_exc_copy) |
562 | EXC( LDREST t3, REST(3)(src), l_exc_copy) | 583 | EXC( LDREST t3, REST(3)(src), .Ll_exc_copy) |
563 | ADD src, src, 4*NBYTES | 584 | ADD src, src, 4*NBYTES |
564 | #ifdef CONFIG_CPU_SB1 | 585 | #ifdef CONFIG_CPU_SB1 |
565 | nop # improves slotting | 586 | nop # improves slotting |
566 | #endif | 587 | #endif |
567 | EXC( STORE t0, UNIT(0)(dst), s_exc) | 588 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc) |
568 | ADDC(sum, t0) | 589 | ADDC(sum, t0) |
569 | EXC( STORE t1, UNIT(1)(dst), s_exc) | 590 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc) |
570 | ADDC(sum, t1) | 591 | ADDC(sum, t1) |
571 | EXC( STORE t2, UNIT(2)(dst), s_exc) | 592 | EXC( STORE t2, UNIT(2)(dst), .Ls_exc) |
572 | ADDC(sum, t2) | 593 | ADDC(sum, t2) |
573 | EXC( STORE t3, UNIT(3)(dst), s_exc) | 594 | EXC( STORE t3, UNIT(3)(dst), .Ls_exc) |
574 | ADDC(sum, t3) | 595 | ADDC(sum, t3) |
596 | .set reorder /* DADDI_WAR */ | ||
597 | ADD dst, dst, 4*NBYTES | ||
575 | bne len, rem, 1b | 598 | bne len, rem, 1b |
576 | ADD dst, dst, 4*NBYTES | 599 | .set noreorder |
577 | 600 | ||
578 | cleanup_src_unaligned: | 601 | .Lcleanup_src_unaligned: |
579 | beqz len, done | 602 | beqz len, .Ldone |
580 | and rem, len, NBYTES-1 # rem = len % NBYTES | 603 | and rem, len, NBYTES-1 # rem = len % NBYTES |
581 | beq rem, len, copy_bytes | 604 | beq rem, len, .Lcopy_bytes |
582 | nop | 605 | nop |
583 | 1: | 606 | 1: |
584 | EXC( LDFIRST t0, FIRST(0)(src), l_exc) | 607 | EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) |
585 | EXC( LDREST t0, REST(0)(src), l_exc_copy) | 608 | EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) |
586 | ADD src, src, NBYTES | 609 | ADD src, src, NBYTES |
587 | SUB len, len, NBYTES | 610 | SUB len, len, NBYTES |
588 | EXC( STORE t0, 0(dst), s_exc) | 611 | EXC( STORE t0, 0(dst), .Ls_exc) |
589 | ADDC(sum, t0) | 612 | ADDC(sum, t0) |
613 | .set reorder /* DADDI_WAR */ | ||
614 | ADD dst, dst, NBYTES | ||
590 | bne len, rem, 1b | 615 | bne len, rem, 1b |
591 | ADD dst, dst, NBYTES | 616 | .set noreorder |
592 | 617 | ||
593 | copy_bytes_checklen: | 618 | .Lcopy_bytes_checklen: |
594 | beqz len, done | 619 | beqz len, .Ldone |
595 | nop | 620 | nop |
596 | copy_bytes: | 621 | .Lcopy_bytes: |
597 | /* 0 < len < NBYTES */ | 622 | /* 0 < len < NBYTES */ |
598 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | 623 | #ifdef CONFIG_CPU_LITTLE_ENDIAN |
599 | #define SHIFT_START 0 | 624 | #define SHIFT_START 0 |
@@ -604,14 +629,14 @@ copy_bytes: | |||
604 | #endif | 629 | #endif |
605 | move t2, zero # partial word | 630 | move t2, zero # partial word |
606 | li t3, SHIFT_START # shift | 631 | li t3, SHIFT_START # shift |
607 | /* use l_exc_copy here to return correct sum on fault */ | 632 | /* use .Ll_exc_copy here to return correct sum on fault */ |
608 | #define COPY_BYTE(N) \ | 633 | #define COPY_BYTE(N) \ |
609 | EXC( lbu t0, N(src), l_exc_copy); \ | 634 | EXC( lbu t0, N(src), .Ll_exc_copy); \ |
610 | SUB len, len, 1; \ | 635 | SUB len, len, 1; \ |
611 | EXC( sb t0, N(dst), s_exc); \ | 636 | EXC( sb t0, N(dst), .Ls_exc); \ |
612 | SLLV t0, t0, t3; \ | 637 | SLLV t0, t0, t3; \ |
613 | addu t3, SHIFT_INC; \ | 638 | addu t3, SHIFT_INC; \ |
614 | beqz len, copy_bytes_done; \ | 639 | beqz len, .Lcopy_bytes_done; \ |
615 | or t2, t0 | 640 | or t2, t0 |
616 | 641 | ||
617 | COPY_BYTE(0) | 642 | COPY_BYTE(0) |
@@ -622,15 +647,17 @@ EXC( sb t0, N(dst), s_exc); \ | |||
622 | COPY_BYTE(4) | 647 | COPY_BYTE(4) |
623 | COPY_BYTE(5) | 648 | COPY_BYTE(5) |
624 | #endif | 649 | #endif |
625 | EXC( lbu t0, NBYTES-2(src), l_exc_copy) | 650 | EXC( lbu t0, NBYTES-2(src), .Ll_exc_copy) |
626 | SUB len, len, 1 | 651 | SUB len, len, 1 |
627 | EXC( sb t0, NBYTES-2(dst), s_exc) | 652 | EXC( sb t0, NBYTES-2(dst), .Ls_exc) |
628 | SLLV t0, t0, t3 | 653 | SLLV t0, t0, t3 |
629 | or t2, t0 | 654 | or t2, t0 |
630 | copy_bytes_done: | 655 | .Lcopy_bytes_done: |
631 | ADDC(sum, t2) | 656 | ADDC(sum, t2) |
632 | done: | 657 | .Ldone: |
633 | /* fold checksum */ | 658 | /* fold checksum */ |
659 | .set push | ||
660 | .set noat | ||
634 | #ifdef USE_DOUBLE | 661 | #ifdef USE_DOUBLE |
635 | dsll32 v1, sum, 0 | 662 | dsll32 v1, sum, 0 |
636 | daddu sum, v1 | 663 | daddu sum, v1 |
@@ -651,13 +678,14 @@ done: | |||
651 | srl sum, sum, 8 | 678 | srl sum, sum, 8 |
652 | or sum, v1 | 679 | or sum, v1 |
653 | andi sum, 0xffff | 680 | andi sum, 0xffff |
681 | .set pop | ||
654 | 1: | 682 | 1: |
655 | .set reorder | 683 | .set reorder |
656 | ADDC(sum, psum) | 684 | ADDC(sum, psum) |
657 | jr ra | 685 | jr ra |
658 | .set noreorder | 686 | .set noreorder |
659 | 687 | ||
660 | l_exc_copy: | 688 | .Ll_exc_copy: |
661 | /* | 689 | /* |
662 | * Copy bytes from src until faulting load address (or until a | 690 | * Copy bytes from src until faulting load address (or until a |
663 | * lb faults) | 691 | * lb faults) |
@@ -672,15 +700,17 @@ l_exc_copy: | |||
672 | li t2, SHIFT_START | 700 | li t2, SHIFT_START |
673 | LOAD t0, THREAD_BUADDR(t0) | 701 | LOAD t0, THREAD_BUADDR(t0) |
674 | 1: | 702 | 1: |
675 | EXC( lbu t1, 0(src), l_exc) | 703 | EXC( lbu t1, 0(src), .Ll_exc) |
676 | ADD src, src, 1 | 704 | ADD src, src, 1 |
677 | sb t1, 0(dst) # can't fault -- we're copy_from_user | 705 | sb t1, 0(dst) # can't fault -- we're copy_from_user |
678 | SLLV t1, t1, t2 | 706 | SLLV t1, t1, t2 |
679 | addu t2, SHIFT_INC | 707 | addu t2, SHIFT_INC |
680 | ADDC(sum, t1) | 708 | ADDC(sum, t1) |
709 | .set reorder /* DADDI_WAR */ | ||
710 | ADD dst, dst, 1 | ||
681 | bne src, t0, 1b | 711 | bne src, t0, 1b |
682 | ADD dst, dst, 1 | 712 | .set noreorder |
683 | l_exc: | 713 | .Ll_exc: |
684 | LOAD t0, TI_TASK($28) | 714 | LOAD t0, TI_TASK($28) |
685 | nop | 715 | nop |
686 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address | 716 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address |
@@ -697,19 +727,30 @@ l_exc: | |||
697 | * Clear len bytes starting at dst. Can't call __bzero because it | 727 | * Clear len bytes starting at dst. Can't call __bzero because it |
698 | * might modify len. An inefficient loop for these rare times... | 728 | * might modify len. An inefficient loop for these rare times... |
699 | */ | 729 | */ |
700 | beqz len, done | 730 | .set reorder /* DADDI_WAR */ |
701 | SUB src, len, 1 | 731 | SUB src, len, 1 |
732 | beqz len, .Ldone | ||
733 | .set noreorder | ||
702 | 1: sb zero, 0(dst) | 734 | 1: sb zero, 0(dst) |
703 | ADD dst, dst, 1 | 735 | ADD dst, dst, 1 |
736 | .set push | ||
737 | .set noat | ||
738 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS | ||
704 | bnez src, 1b | 739 | bnez src, 1b |
705 | SUB src, src, 1 | 740 | SUB src, src, 1 |
741 | #else | ||
742 | li v1, 1 | ||
743 | bnez src, 1b | ||
744 | SUB src, src, v1 | ||
745 | #endif | ||
706 | li v1, -EFAULT | 746 | li v1, -EFAULT |
707 | b done | 747 | b .Ldone |
708 | sw v1, (errptr) | 748 | sw v1, (errptr) |
709 | 749 | ||
710 | s_exc: | 750 | .Ls_exc: |
711 | li v0, -1 /* invalid checksum */ | 751 | li v0, -1 /* invalid checksum */ |
712 | li v1, -EFAULT | 752 | li v1, -EFAULT |
713 | jr ra | 753 | jr ra |
714 | sw v1, (errptr) | 754 | sw v1, (errptr) |
755 | .set pop | ||
715 | END(__csum_partial_copy_user) | 756 | END(__csum_partial_copy_user) |
diff --git a/arch/mips/lib/memcpy-inatomic.S b/arch/mips/lib/memcpy-inatomic.S index 3a534b2baa0f..736d0fb56a94 100644 --- a/arch/mips/lib/memcpy-inatomic.S +++ b/arch/mips/lib/memcpy-inatomic.S | |||
@@ -9,6 +9,7 @@ | |||
9 | * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc. | 9 | * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc. |
10 | * Copyright (C) 2002 Broadcom, Inc. | 10 | * Copyright (C) 2002 Broadcom, Inc. |
11 | * memcpy/copy_user author: Mark Vandevoorde | 11 | * memcpy/copy_user author: Mark Vandevoorde |
12 | * Copyright (C) 2007 Maciej W. Rozycki | ||
12 | * | 13 | * |
13 | * Mnemonic names for arguments to memcpy/__copy_user | 14 | * Mnemonic names for arguments to memcpy/__copy_user |
14 | */ | 15 | */ |
@@ -175,7 +176,11 @@ | |||
175 | 176 | ||
176 | .text | 177 | .text |
177 | .set noreorder | 178 | .set noreorder |
179 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS | ||
178 | .set noat | 180 | .set noat |
181 | #else | ||
182 | .set at=v1 | ||
183 | #endif | ||
179 | 184 | ||
180 | /* | 185 | /* |
181 | * A combined memcpy/__copy_user | 186 | * A combined memcpy/__copy_user |
@@ -204,36 +209,36 @@ LEAF(__copy_user_inatomic) | |||
204 | and t1, dst, ADDRMASK | 209 | and t1, dst, ADDRMASK |
205 | PREF( 0, 1*32(src) ) | 210 | PREF( 0, 1*32(src) ) |
206 | PREF( 1, 1*32(dst) ) | 211 | PREF( 1, 1*32(dst) ) |
207 | bnez t2, copy_bytes_checklen | 212 | bnez t2, .Lcopy_bytes_checklen |
208 | and t0, src, ADDRMASK | 213 | and t0, src, ADDRMASK |
209 | PREF( 0, 2*32(src) ) | 214 | PREF( 0, 2*32(src) ) |
210 | PREF( 1, 2*32(dst) ) | 215 | PREF( 1, 2*32(dst) ) |
211 | bnez t1, dst_unaligned | 216 | bnez t1, .Ldst_unaligned |
212 | nop | 217 | nop |
213 | bnez t0, src_unaligned_dst_aligned | 218 | bnez t0, .Lsrc_unaligned_dst_aligned |
214 | /* | 219 | /* |
215 | * use delay slot for fall-through | 220 | * use delay slot for fall-through |
216 | * src and dst are aligned; need to compute rem | 221 | * src and dst are aligned; need to compute rem |
217 | */ | 222 | */ |
218 | both_aligned: | 223 | .Lboth_aligned: |
219 | SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter | 224 | SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter |
220 | beqz t0, cleanup_both_aligned # len < 8*NBYTES | 225 | beqz t0, .Lcleanup_both_aligned # len < 8*NBYTES |
221 | and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES) | 226 | and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES) |
222 | PREF( 0, 3*32(src) ) | 227 | PREF( 0, 3*32(src) ) |
223 | PREF( 1, 3*32(dst) ) | 228 | PREF( 1, 3*32(dst) ) |
224 | .align 4 | 229 | .align 4 |
225 | 1: | 230 | 1: |
226 | EXC( LOAD t0, UNIT(0)(src), l_exc) | 231 | EXC( LOAD t0, UNIT(0)(src), .Ll_exc) |
227 | EXC( LOAD t1, UNIT(1)(src), l_exc_copy) | 232 | EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) |
228 | EXC( LOAD t2, UNIT(2)(src), l_exc_copy) | 233 | EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) |
229 | EXC( LOAD t3, UNIT(3)(src), l_exc_copy) | 234 | EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) |
230 | SUB len, len, 8*NBYTES | 235 | SUB len, len, 8*NBYTES |
231 | EXC( LOAD t4, UNIT(4)(src), l_exc_copy) | 236 | EXC( LOAD t4, UNIT(4)(src), .Ll_exc_copy) |
232 | EXC( LOAD t7, UNIT(5)(src), l_exc_copy) | 237 | EXC( LOAD t7, UNIT(5)(src), .Ll_exc_copy) |
233 | STORE t0, UNIT(0)(dst) | 238 | STORE t0, UNIT(0)(dst) |
234 | STORE t1, UNIT(1)(dst) | 239 | STORE t1, UNIT(1)(dst) |
235 | EXC( LOAD t0, UNIT(6)(src), l_exc_copy) | 240 | EXC( LOAD t0, UNIT(6)(src), .Ll_exc_copy) |
236 | EXC( LOAD t1, UNIT(7)(src), l_exc_copy) | 241 | EXC( LOAD t1, UNIT(7)(src), .Ll_exc_copy) |
237 | ADD src, src, 8*NBYTES | 242 | ADD src, src, 8*NBYTES |
238 | ADD dst, dst, 8*NBYTES | 243 | ADD dst, dst, 8*NBYTES |
239 | STORE t2, UNIT(-6)(dst) | 244 | STORE t2, UNIT(-6)(dst) |
@@ -250,39 +255,43 @@ EXC( LOAD t1, UNIT(7)(src), l_exc_copy) | |||
250 | /* | 255 | /* |
251 | * len == rem == the number of bytes left to copy < 8*NBYTES | 256 | * len == rem == the number of bytes left to copy < 8*NBYTES |
252 | */ | 257 | */ |
253 | cleanup_both_aligned: | 258 | .Lcleanup_both_aligned: |
254 | beqz len, done | 259 | beqz len, .Ldone |
255 | sltu t0, len, 4*NBYTES | 260 | sltu t0, len, 4*NBYTES |
256 | bnez t0, less_than_4units | 261 | bnez t0, .Lless_than_4units |
257 | and rem, len, (NBYTES-1) # rem = len % NBYTES | 262 | and rem, len, (NBYTES-1) # rem = len % NBYTES |
258 | /* | 263 | /* |
259 | * len >= 4*NBYTES | 264 | * len >= 4*NBYTES |
260 | */ | 265 | */ |
261 | EXC( LOAD t0, UNIT(0)(src), l_exc) | 266 | EXC( LOAD t0, UNIT(0)(src), .Ll_exc) |
262 | EXC( LOAD t1, UNIT(1)(src), l_exc_copy) | 267 | EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) |
263 | EXC( LOAD t2, UNIT(2)(src), l_exc_copy) | 268 | EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) |
264 | EXC( LOAD t3, UNIT(3)(src), l_exc_copy) | 269 | EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) |
265 | SUB len, len, 4*NBYTES | 270 | SUB len, len, 4*NBYTES |
266 | ADD src, src, 4*NBYTES | 271 | ADD src, src, 4*NBYTES |
267 | STORE t0, UNIT(0)(dst) | 272 | STORE t0, UNIT(0)(dst) |
268 | STORE t1, UNIT(1)(dst) | 273 | STORE t1, UNIT(1)(dst) |
269 | STORE t2, UNIT(2)(dst) | 274 | STORE t2, UNIT(2)(dst) |
270 | STORE t3, UNIT(3)(dst) | 275 | STORE t3, UNIT(3)(dst) |
271 | beqz len, done | 276 | .set reorder /* DADDI_WAR */ |
272 | ADD dst, dst, 4*NBYTES | 277 | ADD dst, dst, 4*NBYTES |
273 | less_than_4units: | 278 | beqz len, .Ldone |
279 | .set noreorder | ||
280 | .Lless_than_4units: | ||
274 | /* | 281 | /* |
275 | * rem = len % NBYTES | 282 | * rem = len % NBYTES |
276 | */ | 283 | */ |
277 | beq rem, len, copy_bytes | 284 | beq rem, len, .Lcopy_bytes |
278 | nop | 285 | nop |
279 | 1: | 286 | 1: |
280 | EXC( LOAD t0, 0(src), l_exc) | 287 | EXC( LOAD t0, 0(src), .Ll_exc) |
281 | ADD src, src, NBYTES | 288 | ADD src, src, NBYTES |
282 | SUB len, len, NBYTES | 289 | SUB len, len, NBYTES |
283 | STORE t0, 0(dst) | 290 | STORE t0, 0(dst) |
291 | .set reorder /* DADDI_WAR */ | ||
292 | ADD dst, dst, NBYTES | ||
284 | bne rem, len, 1b | 293 | bne rem, len, 1b |
285 | ADD dst, dst, NBYTES | 294 | .set noreorder |
286 | 295 | ||
287 | /* | 296 | /* |
288 | * src and dst are aligned, need to copy rem bytes (rem < NBYTES) | 297 | * src and dst are aligned, need to copy rem bytes (rem < NBYTES) |
@@ -296,17 +305,17 @@ EXC( LOAD t0, 0(src), l_exc) | |||
296 | * more instruction-level parallelism. | 305 | * more instruction-level parallelism. |
297 | */ | 306 | */ |
298 | #define bits t2 | 307 | #define bits t2 |
299 | beqz len, done | 308 | beqz len, .Ldone |
300 | ADD t1, dst, len # t1 is just past last byte of dst | 309 | ADD t1, dst, len # t1 is just past last byte of dst |
301 | li bits, 8*NBYTES | 310 | li bits, 8*NBYTES |
302 | SLL rem, len, 3 # rem = number of bits to keep | 311 | SLL rem, len, 3 # rem = number of bits to keep |
303 | EXC( LOAD t0, 0(src), l_exc) | 312 | EXC( LOAD t0, 0(src), .Ll_exc) |
304 | SUB bits, bits, rem # bits = number of bits to discard | 313 | SUB bits, bits, rem # bits = number of bits to discard |
305 | SHIFT_DISCARD t0, t0, bits | 314 | SHIFT_DISCARD t0, t0, bits |
306 | STREST t0, -1(t1) | 315 | STREST t0, -1(t1) |
307 | jr ra | 316 | jr ra |
308 | move len, zero | 317 | move len, zero |
309 | dst_unaligned: | 318 | .Ldst_unaligned: |
310 | /* | 319 | /* |
311 | * dst is unaligned | 320 | * dst is unaligned |
312 | * t0 = src & ADDRMASK | 321 | * t0 = src & ADDRMASK |
@@ -317,22 +326,22 @@ dst_unaligned: | |||
317 | * Set match = (src and dst have same alignment) | 326 | * Set match = (src and dst have same alignment) |
318 | */ | 327 | */ |
319 | #define match rem | 328 | #define match rem |
320 | EXC( LDFIRST t3, FIRST(0)(src), l_exc) | 329 | EXC( LDFIRST t3, FIRST(0)(src), .Ll_exc) |
321 | ADD t2, zero, NBYTES | 330 | ADD t2, zero, NBYTES |
322 | EXC( LDREST t3, REST(0)(src), l_exc_copy) | 331 | EXC( LDREST t3, REST(0)(src), .Ll_exc_copy) |
323 | SUB t2, t2, t1 # t2 = number of bytes copied | 332 | SUB t2, t2, t1 # t2 = number of bytes copied |
324 | xor match, t0, t1 | 333 | xor match, t0, t1 |
325 | STFIRST t3, FIRST(0)(dst) | 334 | STFIRST t3, FIRST(0)(dst) |
326 | beq len, t2, done | 335 | beq len, t2, .Ldone |
327 | SUB len, len, t2 | 336 | SUB len, len, t2 |
328 | ADD dst, dst, t2 | 337 | ADD dst, dst, t2 |
329 | beqz match, both_aligned | 338 | beqz match, .Lboth_aligned |
330 | ADD src, src, t2 | 339 | ADD src, src, t2 |
331 | 340 | ||
332 | src_unaligned_dst_aligned: | 341 | .Lsrc_unaligned_dst_aligned: |
333 | SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter | 342 | SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter |
334 | PREF( 0, 3*32(src) ) | 343 | PREF( 0, 3*32(src) ) |
335 | beqz t0, cleanup_src_unaligned | 344 | beqz t0, .Lcleanup_src_unaligned |
336 | and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES | 345 | and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES |
337 | PREF( 1, 3*32(dst) ) | 346 | PREF( 1, 3*32(dst) ) |
338 | 1: | 347 | 1: |
@@ -342,15 +351,15 @@ src_unaligned_dst_aligned: | |||
342 | * It's OK to load FIRST(N+1) before REST(N) because the two addresses | 351 | * It's OK to load FIRST(N+1) before REST(N) because the two addresses |
343 | * are to the same unit (unless src is aligned, but it's not). | 352 | * are to the same unit (unless src is aligned, but it's not). |
344 | */ | 353 | */ |
345 | EXC( LDFIRST t0, FIRST(0)(src), l_exc) | 354 | EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) |
346 | EXC( LDFIRST t1, FIRST(1)(src), l_exc_copy) | 355 | EXC( LDFIRST t1, FIRST(1)(src), .Ll_exc_copy) |
347 | SUB len, len, 4*NBYTES | 356 | SUB len, len, 4*NBYTES |
348 | EXC( LDREST t0, REST(0)(src), l_exc_copy) | 357 | EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) |
349 | EXC( LDREST t1, REST(1)(src), l_exc_copy) | 358 | EXC( LDREST t1, REST(1)(src), .Ll_exc_copy) |
350 | EXC( LDFIRST t2, FIRST(2)(src), l_exc_copy) | 359 | EXC( LDFIRST t2, FIRST(2)(src), .Ll_exc_copy) |
351 | EXC( LDFIRST t3, FIRST(3)(src), l_exc_copy) | 360 | EXC( LDFIRST t3, FIRST(3)(src), .Ll_exc_copy) |
352 | EXC( LDREST t2, REST(2)(src), l_exc_copy) | 361 | EXC( LDREST t2, REST(2)(src), .Ll_exc_copy) |
353 | EXC( LDREST t3, REST(3)(src), l_exc_copy) | 362 | EXC( LDREST t3, REST(3)(src), .Ll_exc_copy) |
354 | PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed) | 363 | PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed) |
355 | ADD src, src, 4*NBYTES | 364 | ADD src, src, 4*NBYTES |
356 | #ifdef CONFIG_CPU_SB1 | 365 | #ifdef CONFIG_CPU_SB1 |
@@ -361,32 +370,36 @@ EXC( LDREST t3, REST(3)(src), l_exc_copy) | |||
361 | STORE t2, UNIT(2)(dst) | 370 | STORE t2, UNIT(2)(dst) |
362 | STORE t3, UNIT(3)(dst) | 371 | STORE t3, UNIT(3)(dst) |
363 | PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed) | 372 | PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed) |
373 | .set reorder /* DADDI_WAR */ | ||
374 | ADD dst, dst, 4*NBYTES | ||
364 | bne len, rem, 1b | 375 | bne len, rem, 1b |
365 | ADD dst, dst, 4*NBYTES | 376 | .set noreorder |
366 | 377 | ||
367 | cleanup_src_unaligned: | 378 | .Lcleanup_src_unaligned: |
368 | beqz len, done | 379 | beqz len, .Ldone |
369 | and rem, len, NBYTES-1 # rem = len % NBYTES | 380 | and rem, len, NBYTES-1 # rem = len % NBYTES |
370 | beq rem, len, copy_bytes | 381 | beq rem, len, .Lcopy_bytes |
371 | nop | 382 | nop |
372 | 1: | 383 | 1: |
373 | EXC( LDFIRST t0, FIRST(0)(src), l_exc) | 384 | EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) |
374 | EXC( LDREST t0, REST(0)(src), l_exc_copy) | 385 | EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) |
375 | ADD src, src, NBYTES | 386 | ADD src, src, NBYTES |
376 | SUB len, len, NBYTES | 387 | SUB len, len, NBYTES |
377 | STORE t0, 0(dst) | 388 | STORE t0, 0(dst) |
389 | .set reorder /* DADDI_WAR */ | ||
390 | ADD dst, dst, NBYTES | ||
378 | bne len, rem, 1b | 391 | bne len, rem, 1b |
379 | ADD dst, dst, NBYTES | 392 | .set noreorder |
380 | 393 | ||
381 | copy_bytes_checklen: | 394 | .Lcopy_bytes_checklen: |
382 | beqz len, done | 395 | beqz len, .Ldone |
383 | nop | 396 | nop |
384 | copy_bytes: | 397 | .Lcopy_bytes: |
385 | /* 0 < len < NBYTES */ | 398 | /* 0 < len < NBYTES */ |
386 | #define COPY_BYTE(N) \ | 399 | #define COPY_BYTE(N) \ |
387 | EXC( lb t0, N(src), l_exc); \ | 400 | EXC( lb t0, N(src), .Ll_exc); \ |
388 | SUB len, len, 1; \ | 401 | SUB len, len, 1; \ |
389 | beqz len, done; \ | 402 | beqz len, .Ldone; \ |
390 | sb t0, N(dst) | 403 | sb t0, N(dst) |
391 | 404 | ||
392 | COPY_BYTE(0) | 405 | COPY_BYTE(0) |
@@ -397,16 +410,16 @@ EXC( lb t0, N(src), l_exc); \ | |||
397 | COPY_BYTE(4) | 410 | COPY_BYTE(4) |
398 | COPY_BYTE(5) | 411 | COPY_BYTE(5) |
399 | #endif | 412 | #endif |
400 | EXC( lb t0, NBYTES-2(src), l_exc) | 413 | EXC( lb t0, NBYTES-2(src), .Ll_exc) |
401 | SUB len, len, 1 | 414 | SUB len, len, 1 |
402 | jr ra | 415 | jr ra |
403 | sb t0, NBYTES-2(dst) | 416 | sb t0, NBYTES-2(dst) |
404 | done: | 417 | .Ldone: |
405 | jr ra | 418 | jr ra |
406 | nop | 419 | nop |
407 | END(__copy_user_inatomic) | 420 | END(__copy_user_inatomic) |
408 | 421 | ||
409 | l_exc_copy: | 422 | .Ll_exc_copy: |
410 | /* | 423 | /* |
411 | * Copy bytes from src until faulting load address (or until a | 424 | * Copy bytes from src until faulting load address (or until a |
412 | * lb faults) | 425 | * lb faults) |
@@ -421,12 +434,14 @@ l_exc_copy: | |||
421 | nop | 434 | nop |
422 | LOAD t0, THREAD_BUADDR(t0) | 435 | LOAD t0, THREAD_BUADDR(t0) |
423 | 1: | 436 | 1: |
424 | EXC( lb t1, 0(src), l_exc) | 437 | EXC( lb t1, 0(src), .Ll_exc) |
425 | ADD src, src, 1 | 438 | ADD src, src, 1 |
426 | sb t1, 0(dst) # can't fault -- we're copy_from_user | 439 | sb t1, 0(dst) # can't fault -- we're copy_from_user |
440 | .set reorder /* DADDI_WAR */ | ||
441 | ADD dst, dst, 1 | ||
427 | bne src, t0, 1b | 442 | bne src, t0, 1b |
428 | ADD dst, dst, 1 | 443 | .set noreorder |
429 | l_exc: | 444 | .Ll_exc: |
430 | LOAD t0, TI_TASK($28) | 445 | LOAD t0, TI_TASK($28) |
431 | nop | 446 | nop |
432 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address | 447 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address |
diff --git a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S index a526c62cb76a..c06cccf60bec 100644 --- a/arch/mips/lib/memcpy.S +++ b/arch/mips/lib/memcpy.S | |||
@@ -9,6 +9,7 @@ | |||
9 | * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc. | 9 | * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc. |
10 | * Copyright (C) 2002 Broadcom, Inc. | 10 | * Copyright (C) 2002 Broadcom, Inc. |
11 | * memcpy/copy_user author: Mark Vandevoorde | 11 | * memcpy/copy_user author: Mark Vandevoorde |
12 | * Copyright (C) 2007 Maciej W. Rozycki | ||
12 | * | 13 | * |
13 | * Mnemonic names for arguments to memcpy/__copy_user | 14 | * Mnemonic names for arguments to memcpy/__copy_user |
14 | */ | 15 | */ |
@@ -175,7 +176,11 @@ | |||
175 | 176 | ||
176 | .text | 177 | .text |
177 | .set noreorder | 178 | .set noreorder |
179 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS | ||
178 | .set noat | 180 | .set noat |
181 | #else | ||
182 | .set at=v1 | ||
183 | #endif | ||
179 | 184 | ||
180 | /* | 185 | /* |
181 | * A combined memcpy/__copy_user | 186 | * A combined memcpy/__copy_user |
@@ -186,7 +191,7 @@ | |||
186 | .align 5 | 191 | .align 5 |
187 | LEAF(memcpy) /* a0=dst a1=src a2=len */ | 192 | LEAF(memcpy) /* a0=dst a1=src a2=len */ |
188 | move v0, dst /* return value */ | 193 | move v0, dst /* return value */ |
189 | __memcpy: | 194 | .L__memcpy: |
190 | FEXPORT(__copy_user) | 195 | FEXPORT(__copy_user) |
191 | /* | 196 | /* |
192 | * Note: dst & src may be unaligned, len may be 0 | 197 | * Note: dst & src may be unaligned, len may be 0 |
@@ -194,6 +199,7 @@ FEXPORT(__copy_user) | |||
194 | */ | 199 | */ |
195 | #define rem t8 | 200 | #define rem t8 |
196 | 201 | ||
202 | R10KCBARRIER(0(ra)) | ||
197 | /* | 203 | /* |
198 | * The "issue break"s below are very approximate. | 204 | * The "issue break"s below are very approximate. |
199 | * Issue delays for dcache fills will perturb the schedule, as will | 205 | * Issue delays for dcache fills will perturb the schedule, as will |
@@ -207,44 +213,45 @@ FEXPORT(__copy_user) | |||
207 | and t1, dst, ADDRMASK | 213 | and t1, dst, ADDRMASK |
208 | PREF( 0, 1*32(src) ) | 214 | PREF( 0, 1*32(src) ) |
209 | PREF( 1, 1*32(dst) ) | 215 | PREF( 1, 1*32(dst) ) |
210 | bnez t2, copy_bytes_checklen | 216 | bnez t2, .Lcopy_bytes_checklen |
211 | and t0, src, ADDRMASK | 217 | and t0, src, ADDRMASK |
212 | PREF( 0, 2*32(src) ) | 218 | PREF( 0, 2*32(src) ) |
213 | PREF( 1, 2*32(dst) ) | 219 | PREF( 1, 2*32(dst) ) |
214 | bnez t1, dst_unaligned | 220 | bnez t1, .Ldst_unaligned |
215 | nop | 221 | nop |
216 | bnez t0, src_unaligned_dst_aligned | 222 | bnez t0, .Lsrc_unaligned_dst_aligned |
217 | /* | 223 | /* |
218 | * use delay slot for fall-through | 224 | * use delay slot for fall-through |
219 | * src and dst are aligned; need to compute rem | 225 | * src and dst are aligned; need to compute rem |
220 | */ | 226 | */ |
221 | both_aligned: | 227 | .Lboth_aligned: |
222 | SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter | 228 | SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter |
223 | beqz t0, cleanup_both_aligned # len < 8*NBYTES | 229 | beqz t0, .Lcleanup_both_aligned # len < 8*NBYTES |
224 | and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES) | 230 | and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES) |
225 | PREF( 0, 3*32(src) ) | 231 | PREF( 0, 3*32(src) ) |
226 | PREF( 1, 3*32(dst) ) | 232 | PREF( 1, 3*32(dst) ) |
227 | .align 4 | 233 | .align 4 |
228 | 1: | 234 | 1: |
229 | EXC( LOAD t0, UNIT(0)(src), l_exc) | 235 | R10KCBARRIER(0(ra)) |
230 | EXC( LOAD t1, UNIT(1)(src), l_exc_copy) | 236 | EXC( LOAD t0, UNIT(0)(src), .Ll_exc) |
231 | EXC( LOAD t2, UNIT(2)(src), l_exc_copy) | 237 | EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) |
232 | EXC( LOAD t3, UNIT(3)(src), l_exc_copy) | 238 | EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) |
239 | EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) | ||
233 | SUB len, len, 8*NBYTES | 240 | SUB len, len, 8*NBYTES |
234 | EXC( LOAD t4, UNIT(4)(src), l_exc_copy) | 241 | EXC( LOAD t4, UNIT(4)(src), .Ll_exc_copy) |
235 | EXC( LOAD t7, UNIT(5)(src), l_exc_copy) | 242 | EXC( LOAD t7, UNIT(5)(src), .Ll_exc_copy) |
236 | EXC( STORE t0, UNIT(0)(dst), s_exc_p8u) | 243 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc_p8u) |
237 | EXC( STORE t1, UNIT(1)(dst), s_exc_p7u) | 244 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc_p7u) |
238 | EXC( LOAD t0, UNIT(6)(src), l_exc_copy) | 245 | EXC( LOAD t0, UNIT(6)(src), .Ll_exc_copy) |
239 | EXC( LOAD t1, UNIT(7)(src), l_exc_copy) | 246 | EXC( LOAD t1, UNIT(7)(src), .Ll_exc_copy) |
240 | ADD src, src, 8*NBYTES | 247 | ADD src, src, 8*NBYTES |
241 | ADD dst, dst, 8*NBYTES | 248 | ADD dst, dst, 8*NBYTES |
242 | EXC( STORE t2, UNIT(-6)(dst), s_exc_p6u) | 249 | EXC( STORE t2, UNIT(-6)(dst), .Ls_exc_p6u) |
243 | EXC( STORE t3, UNIT(-5)(dst), s_exc_p5u) | 250 | EXC( STORE t3, UNIT(-5)(dst), .Ls_exc_p5u) |
244 | EXC( STORE t4, UNIT(-4)(dst), s_exc_p4u) | 251 | EXC( STORE t4, UNIT(-4)(dst), .Ls_exc_p4u) |
245 | EXC( STORE t7, UNIT(-3)(dst), s_exc_p3u) | 252 | EXC( STORE t7, UNIT(-3)(dst), .Ls_exc_p3u) |
246 | EXC( STORE t0, UNIT(-2)(dst), s_exc_p2u) | 253 | EXC( STORE t0, UNIT(-2)(dst), .Ls_exc_p2u) |
247 | EXC( STORE t1, UNIT(-1)(dst), s_exc_p1u) | 254 | EXC( STORE t1, UNIT(-1)(dst), .Ls_exc_p1u) |
248 | PREF( 0, 8*32(src) ) | 255 | PREF( 0, 8*32(src) ) |
249 | PREF( 1, 8*32(dst) ) | 256 | PREF( 1, 8*32(dst) ) |
250 | bne len, rem, 1b | 257 | bne len, rem, 1b |
@@ -253,39 +260,45 @@ EXC( STORE t1, UNIT(-1)(dst), s_exc_p1u) | |||
253 | /* | 260 | /* |
254 | * len == rem == the number of bytes left to copy < 8*NBYTES | 261 | * len == rem == the number of bytes left to copy < 8*NBYTES |
255 | */ | 262 | */ |
256 | cleanup_both_aligned: | 263 | .Lcleanup_both_aligned: |
257 | beqz len, done | 264 | beqz len, .Ldone |
258 | sltu t0, len, 4*NBYTES | 265 | sltu t0, len, 4*NBYTES |
259 | bnez t0, less_than_4units | 266 | bnez t0, .Lless_than_4units |
260 | and rem, len, (NBYTES-1) # rem = len % NBYTES | 267 | and rem, len, (NBYTES-1) # rem = len % NBYTES |
261 | /* | 268 | /* |
262 | * len >= 4*NBYTES | 269 | * len >= 4*NBYTES |
263 | */ | 270 | */ |
264 | EXC( LOAD t0, UNIT(0)(src), l_exc) | 271 | EXC( LOAD t0, UNIT(0)(src), .Ll_exc) |
265 | EXC( LOAD t1, UNIT(1)(src), l_exc_copy) | 272 | EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy) |
266 | EXC( LOAD t2, UNIT(2)(src), l_exc_copy) | 273 | EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy) |
267 | EXC( LOAD t3, UNIT(3)(src), l_exc_copy) | 274 | EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy) |
268 | SUB len, len, 4*NBYTES | 275 | SUB len, len, 4*NBYTES |
269 | ADD src, src, 4*NBYTES | 276 | ADD src, src, 4*NBYTES |
270 | EXC( STORE t0, UNIT(0)(dst), s_exc_p4u) | 277 | R10KCBARRIER(0(ra)) |
271 | EXC( STORE t1, UNIT(1)(dst), s_exc_p3u) | 278 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc_p4u) |
272 | EXC( STORE t2, UNIT(2)(dst), s_exc_p2u) | 279 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc_p3u) |
273 | EXC( STORE t3, UNIT(3)(dst), s_exc_p1u) | 280 | EXC( STORE t2, UNIT(2)(dst), .Ls_exc_p2u) |
274 | beqz len, done | 281 | EXC( STORE t3, UNIT(3)(dst), .Ls_exc_p1u) |
275 | ADD dst, dst, 4*NBYTES | 282 | .set reorder /* DADDI_WAR */ |
276 | less_than_4units: | 283 | ADD dst, dst, 4*NBYTES |
284 | beqz len, .Ldone | ||
285 | .set noreorder | ||
286 | .Lless_than_4units: | ||
277 | /* | 287 | /* |
278 | * rem = len % NBYTES | 288 | * rem = len % NBYTES |
279 | */ | 289 | */ |
280 | beq rem, len, copy_bytes | 290 | beq rem, len, .Lcopy_bytes |
281 | nop | 291 | nop |
282 | 1: | 292 | 1: |
283 | EXC( LOAD t0, 0(src), l_exc) | 293 | R10KCBARRIER(0(ra)) |
294 | EXC( LOAD t0, 0(src), .Ll_exc) | ||
284 | ADD src, src, NBYTES | 295 | ADD src, src, NBYTES |
285 | SUB len, len, NBYTES | 296 | SUB len, len, NBYTES |
286 | EXC( STORE t0, 0(dst), s_exc_p1u) | 297 | EXC( STORE t0, 0(dst), .Ls_exc_p1u) |
298 | .set reorder /* DADDI_WAR */ | ||
299 | ADD dst, dst, NBYTES | ||
287 | bne rem, len, 1b | 300 | bne rem, len, 1b |
288 | ADD dst, dst, NBYTES | 301 | .set noreorder |
289 | 302 | ||
290 | /* | 303 | /* |
291 | * src and dst are aligned, need to copy rem bytes (rem < NBYTES) | 304 | * src and dst are aligned, need to copy rem bytes (rem < NBYTES) |
@@ -299,17 +312,17 @@ EXC( STORE t0, 0(dst), s_exc_p1u) | |||
299 | * more instruction-level parallelism. | 312 | * more instruction-level parallelism. |
300 | */ | 313 | */ |
301 | #define bits t2 | 314 | #define bits t2 |
302 | beqz len, done | 315 | beqz len, .Ldone |
303 | ADD t1, dst, len # t1 is just past last byte of dst | 316 | ADD t1, dst, len # t1 is just past last byte of dst |
304 | li bits, 8*NBYTES | 317 | li bits, 8*NBYTES |
305 | SLL rem, len, 3 # rem = number of bits to keep | 318 | SLL rem, len, 3 # rem = number of bits to keep |
306 | EXC( LOAD t0, 0(src), l_exc) | 319 | EXC( LOAD t0, 0(src), .Ll_exc) |
307 | SUB bits, bits, rem # bits = number of bits to discard | 320 | SUB bits, bits, rem # bits = number of bits to discard |
308 | SHIFT_DISCARD t0, t0, bits | 321 | SHIFT_DISCARD t0, t0, bits |
309 | EXC( STREST t0, -1(t1), s_exc) | 322 | EXC( STREST t0, -1(t1), .Ls_exc) |
310 | jr ra | 323 | jr ra |
311 | move len, zero | 324 | move len, zero |
312 | dst_unaligned: | 325 | .Ldst_unaligned: |
313 | /* | 326 | /* |
314 | * dst is unaligned | 327 | * dst is unaligned |
315 | * t0 = src & ADDRMASK | 328 | * t0 = src & ADDRMASK |
@@ -320,22 +333,23 @@ dst_unaligned: | |||
320 | * Set match = (src and dst have same alignment) | 333 | * Set match = (src and dst have same alignment) |
321 | */ | 334 | */ |
322 | #define match rem | 335 | #define match rem |
323 | EXC( LDFIRST t3, FIRST(0)(src), l_exc) | 336 | EXC( LDFIRST t3, FIRST(0)(src), .Ll_exc) |
324 | ADD t2, zero, NBYTES | 337 | ADD t2, zero, NBYTES |
325 | EXC( LDREST t3, REST(0)(src), l_exc_copy) | 338 | EXC( LDREST t3, REST(0)(src), .Ll_exc_copy) |
326 | SUB t2, t2, t1 # t2 = number of bytes copied | 339 | SUB t2, t2, t1 # t2 = number of bytes copied |
327 | xor match, t0, t1 | 340 | xor match, t0, t1 |
328 | EXC( STFIRST t3, FIRST(0)(dst), s_exc) | 341 | R10KCBARRIER(0(ra)) |
329 | beq len, t2, done | 342 | EXC( STFIRST t3, FIRST(0)(dst), .Ls_exc) |
343 | beq len, t2, .Ldone | ||
330 | SUB len, len, t2 | 344 | SUB len, len, t2 |
331 | ADD dst, dst, t2 | 345 | ADD dst, dst, t2 |
332 | beqz match, both_aligned | 346 | beqz match, .Lboth_aligned |
333 | ADD src, src, t2 | 347 | ADD src, src, t2 |
334 | 348 | ||
335 | src_unaligned_dst_aligned: | 349 | .Lsrc_unaligned_dst_aligned: |
336 | SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter | 350 | SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter |
337 | PREF( 0, 3*32(src) ) | 351 | PREF( 0, 3*32(src) ) |
338 | beqz t0, cleanup_src_unaligned | 352 | beqz t0, .Lcleanup_src_unaligned |
339 | and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES | 353 | and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES |
340 | PREF( 1, 3*32(dst) ) | 354 | PREF( 1, 3*32(dst) ) |
341 | 1: | 355 | 1: |
@@ -345,52 +359,59 @@ src_unaligned_dst_aligned: | |||
345 | * It's OK to load FIRST(N+1) before REST(N) because the two addresses | 359 | * It's OK to load FIRST(N+1) before REST(N) because the two addresses |
346 | * are to the same unit (unless src is aligned, but it's not). | 360 | * are to the same unit (unless src is aligned, but it's not). |
347 | */ | 361 | */ |
348 | EXC( LDFIRST t0, FIRST(0)(src), l_exc) | 362 | R10KCBARRIER(0(ra)) |
349 | EXC( LDFIRST t1, FIRST(1)(src), l_exc_copy) | 363 | EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) |
364 | EXC( LDFIRST t1, FIRST(1)(src), .Ll_exc_copy) | ||
350 | SUB len, len, 4*NBYTES | 365 | SUB len, len, 4*NBYTES |
351 | EXC( LDREST t0, REST(0)(src), l_exc_copy) | 366 | EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) |
352 | EXC( LDREST t1, REST(1)(src), l_exc_copy) | 367 | EXC( LDREST t1, REST(1)(src), .Ll_exc_copy) |
353 | EXC( LDFIRST t2, FIRST(2)(src), l_exc_copy) | 368 | EXC( LDFIRST t2, FIRST(2)(src), .Ll_exc_copy) |
354 | EXC( LDFIRST t3, FIRST(3)(src), l_exc_copy) | 369 | EXC( LDFIRST t3, FIRST(3)(src), .Ll_exc_copy) |
355 | EXC( LDREST t2, REST(2)(src), l_exc_copy) | 370 | EXC( LDREST t2, REST(2)(src), .Ll_exc_copy) |
356 | EXC( LDREST t3, REST(3)(src), l_exc_copy) | 371 | EXC( LDREST t3, REST(3)(src), .Ll_exc_copy) |
357 | PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed) | 372 | PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed) |
358 | ADD src, src, 4*NBYTES | 373 | ADD src, src, 4*NBYTES |
359 | #ifdef CONFIG_CPU_SB1 | 374 | #ifdef CONFIG_CPU_SB1 |
360 | nop # improves slotting | 375 | nop # improves slotting |
361 | #endif | 376 | #endif |
362 | EXC( STORE t0, UNIT(0)(dst), s_exc_p4u) | 377 | EXC( STORE t0, UNIT(0)(dst), .Ls_exc_p4u) |
363 | EXC( STORE t1, UNIT(1)(dst), s_exc_p3u) | 378 | EXC( STORE t1, UNIT(1)(dst), .Ls_exc_p3u) |
364 | EXC( STORE t2, UNIT(2)(dst), s_exc_p2u) | 379 | EXC( STORE t2, UNIT(2)(dst), .Ls_exc_p2u) |
365 | EXC( STORE t3, UNIT(3)(dst), s_exc_p1u) | 380 | EXC( STORE t3, UNIT(3)(dst), .Ls_exc_p1u) |
366 | PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed) | 381 | PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed) |
382 | .set reorder /* DADDI_WAR */ | ||
383 | ADD dst, dst, 4*NBYTES | ||
367 | bne len, rem, 1b | 384 | bne len, rem, 1b |
368 | ADD dst, dst, 4*NBYTES | 385 | .set noreorder |
369 | 386 | ||
370 | cleanup_src_unaligned: | 387 | .Lcleanup_src_unaligned: |
371 | beqz len, done | 388 | beqz len, .Ldone |
372 | and rem, len, NBYTES-1 # rem = len % NBYTES | 389 | and rem, len, NBYTES-1 # rem = len % NBYTES |
373 | beq rem, len, copy_bytes | 390 | beq rem, len, .Lcopy_bytes |
374 | nop | 391 | nop |
375 | 1: | 392 | 1: |
376 | EXC( LDFIRST t0, FIRST(0)(src), l_exc) | 393 | R10KCBARRIER(0(ra)) |
377 | EXC( LDREST t0, REST(0)(src), l_exc_copy) | 394 | EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc) |
395 | EXC( LDREST t0, REST(0)(src), .Ll_exc_copy) | ||
378 | ADD src, src, NBYTES | 396 | ADD src, src, NBYTES |
379 | SUB len, len, NBYTES | 397 | SUB len, len, NBYTES |
380 | EXC( STORE t0, 0(dst), s_exc_p1u) | 398 | EXC( STORE t0, 0(dst), .Ls_exc_p1u) |
399 | .set reorder /* DADDI_WAR */ | ||
400 | ADD dst, dst, NBYTES | ||
381 | bne len, rem, 1b | 401 | bne len, rem, 1b |
382 | ADD dst, dst, NBYTES | 402 | .set noreorder |
383 | 403 | ||
384 | copy_bytes_checklen: | 404 | .Lcopy_bytes_checklen: |
385 | beqz len, done | 405 | beqz len, .Ldone |
386 | nop | 406 | nop |
387 | copy_bytes: | 407 | .Lcopy_bytes: |
388 | /* 0 < len < NBYTES */ | 408 | /* 0 < len < NBYTES */ |
409 | R10KCBARRIER(0(ra)) | ||
389 | #define COPY_BYTE(N) \ | 410 | #define COPY_BYTE(N) \ |
390 | EXC( lb t0, N(src), l_exc); \ | 411 | EXC( lb t0, N(src), .Ll_exc); \ |
391 | SUB len, len, 1; \ | 412 | SUB len, len, 1; \ |
392 | beqz len, done; \ | 413 | beqz len, .Ldone; \ |
393 | EXC( sb t0, N(dst), s_exc_p1) | 414 | EXC( sb t0, N(dst), .Ls_exc_p1) |
394 | 415 | ||
395 | COPY_BYTE(0) | 416 | COPY_BYTE(0) |
396 | COPY_BYTE(1) | 417 | COPY_BYTE(1) |
@@ -400,16 +421,16 @@ EXC( sb t0, N(dst), s_exc_p1) | |||
400 | COPY_BYTE(4) | 421 | COPY_BYTE(4) |
401 | COPY_BYTE(5) | 422 | COPY_BYTE(5) |
402 | #endif | 423 | #endif |
403 | EXC( lb t0, NBYTES-2(src), l_exc) | 424 | EXC( lb t0, NBYTES-2(src), .Ll_exc) |
404 | SUB len, len, 1 | 425 | SUB len, len, 1 |
405 | jr ra | 426 | jr ra |
406 | EXC( sb t0, NBYTES-2(dst), s_exc_p1) | 427 | EXC( sb t0, NBYTES-2(dst), .Ls_exc_p1) |
407 | done: | 428 | .Ldone: |
408 | jr ra | 429 | jr ra |
409 | nop | 430 | nop |
410 | END(memcpy) | 431 | END(memcpy) |
411 | 432 | ||
412 | l_exc_copy: | 433 | .Ll_exc_copy: |
413 | /* | 434 | /* |
414 | * Copy bytes from src until faulting load address (or until a | 435 | * Copy bytes from src until faulting load address (or until a |
415 | * lb faults) | 436 | * lb faults) |
@@ -424,12 +445,14 @@ l_exc_copy: | |||
424 | nop | 445 | nop |
425 | LOAD t0, THREAD_BUADDR(t0) | 446 | LOAD t0, THREAD_BUADDR(t0) |
426 | 1: | 447 | 1: |
427 | EXC( lb t1, 0(src), l_exc) | 448 | EXC( lb t1, 0(src), .Ll_exc) |
428 | ADD src, src, 1 | 449 | ADD src, src, 1 |
429 | sb t1, 0(dst) # can't fault -- we're copy_from_user | 450 | sb t1, 0(dst) # can't fault -- we're copy_from_user |
451 | .set reorder /* DADDI_WAR */ | ||
452 | ADD dst, dst, 1 | ||
430 | bne src, t0, 1b | 453 | bne src, t0, 1b |
431 | ADD dst, dst, 1 | 454 | .set noreorder |
432 | l_exc: | 455 | .Ll_exc: |
433 | LOAD t0, TI_TASK($28) | 456 | LOAD t0, TI_TASK($28) |
434 | nop | 457 | nop |
435 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address | 458 | LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address |
@@ -446,20 +469,33 @@ l_exc: | |||
446 | * Clear len bytes starting at dst. Can't call __bzero because it | 469 | * Clear len bytes starting at dst. Can't call __bzero because it |
447 | * might modify len. An inefficient loop for these rare times... | 470 | * might modify len. An inefficient loop for these rare times... |
448 | */ | 471 | */ |
449 | beqz len, done | 472 | .set reorder /* DADDI_WAR */ |
450 | SUB src, len, 1 | 473 | SUB src, len, 1 |
474 | beqz len, .Ldone | ||
475 | .set noreorder | ||
451 | 1: sb zero, 0(dst) | 476 | 1: sb zero, 0(dst) |
452 | ADD dst, dst, 1 | 477 | ADD dst, dst, 1 |
478 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS | ||
453 | bnez src, 1b | 479 | bnez src, 1b |
454 | SUB src, src, 1 | 480 | SUB src, src, 1 |
481 | #else | ||
482 | .set push | ||
483 | .set noat | ||
484 | li v1, 1 | ||
485 | bnez src, 1b | ||
486 | SUB src, src, v1 | ||
487 | .set pop | ||
488 | #endif | ||
455 | jr ra | 489 | jr ra |
456 | nop | 490 | nop |
457 | 491 | ||
458 | 492 | ||
459 | #define SEXC(n) \ | 493 | #define SEXC(n) \ |
460 | s_exc_p ## n ## u: \ | 494 | .set reorder; /* DADDI_WAR */ \ |
461 | jr ra; \ | 495 | .Ls_exc_p ## n ## u: \ |
462 | ADD len, len, n*NBYTES | 496 | ADD len, len, n*NBYTES; \ |
497 | jr ra; \ | ||
498 | .set noreorder | ||
463 | 499 | ||
464 | SEXC(8) | 500 | SEXC(8) |
465 | SEXC(7) | 501 | SEXC(7) |
@@ -470,10 +506,12 @@ SEXC(3) | |||
470 | SEXC(2) | 506 | SEXC(2) |
471 | SEXC(1) | 507 | SEXC(1) |
472 | 508 | ||
473 | s_exc_p1: | 509 | .Ls_exc_p1: |
510 | .set reorder /* DADDI_WAR */ | ||
511 | ADD len, len, 1 | ||
474 | jr ra | 512 | jr ra |
475 | ADD len, len, 1 | 513 | .set noreorder |
476 | s_exc: | 514 | .Ls_exc: |
477 | jr ra | 515 | jr ra |
478 | nop | 516 | nop |
479 | 517 | ||
@@ -484,38 +522,44 @@ LEAF(memmove) | |||
484 | sltu t0, a1, t0 # dst + len <= src -> memcpy | 522 | sltu t0, a1, t0 # dst + len <= src -> memcpy |
485 | sltu t1, a0, t1 # dst >= src + len -> memcpy | 523 | sltu t1, a0, t1 # dst >= src + len -> memcpy |
486 | and t0, t1 | 524 | and t0, t1 |
487 | beqz t0, __memcpy | 525 | beqz t0, .L__memcpy |
488 | move v0, a0 /* return value */ | 526 | move v0, a0 /* return value */ |
489 | beqz a2, r_out | 527 | beqz a2, .Lr_out |
490 | END(memmove) | 528 | END(memmove) |
491 | 529 | ||
492 | /* fall through to __rmemcpy */ | 530 | /* fall through to __rmemcpy */ |
493 | LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ | 531 | LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ |
494 | sltu t0, a1, a0 | 532 | sltu t0, a1, a0 |
495 | beqz t0, r_end_bytes_up # src >= dst | 533 | beqz t0, .Lr_end_bytes_up # src >= dst |
496 | nop | 534 | nop |
497 | ADD a0, a2 # dst = dst + len | 535 | ADD a0, a2 # dst = dst + len |
498 | ADD a1, a2 # src = src + len | 536 | ADD a1, a2 # src = src + len |
499 | 537 | ||
500 | r_end_bytes: | 538 | .Lr_end_bytes: |
539 | R10KCBARRIER(0(ra)) | ||
501 | lb t0, -1(a1) | 540 | lb t0, -1(a1) |
502 | SUB a2, a2, 0x1 | 541 | SUB a2, a2, 0x1 |
503 | sb t0, -1(a0) | 542 | sb t0, -1(a0) |
504 | SUB a1, a1, 0x1 | 543 | SUB a1, a1, 0x1 |
505 | bnez a2, r_end_bytes | 544 | .set reorder /* DADDI_WAR */ |
506 | SUB a0, a0, 0x1 | 545 | SUB a0, a0, 0x1 |
546 | bnez a2, .Lr_end_bytes | ||
547 | .set noreorder | ||
507 | 548 | ||
508 | r_out: | 549 | .Lr_out: |
509 | jr ra | 550 | jr ra |
510 | move a2, zero | 551 | move a2, zero |
511 | 552 | ||
512 | r_end_bytes_up: | 553 | .Lr_end_bytes_up: |
554 | R10KCBARRIER(0(ra)) | ||
513 | lb t0, (a1) | 555 | lb t0, (a1) |
514 | SUB a2, a2, 0x1 | 556 | SUB a2, a2, 0x1 |
515 | sb t0, (a0) | 557 | sb t0, (a0) |
516 | ADD a1, a1, 0x1 | 558 | ADD a1, a1, 0x1 |
517 | bnez a2, r_end_bytes_up | 559 | .set reorder /* DADDI_WAR */ |
518 | ADD a0, a0, 0x1 | 560 | ADD a0, a0, 0x1 |
561 | bnez a2, .Lr_end_bytes_up | ||
562 | .set noreorder | ||
519 | 563 | ||
520 | jr ra | 564 | jr ra |
521 | move a2, zero | 565 | move a2, zero |
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S index 3f8b8b3d0b23..77dc3b20110a 100644 --- a/arch/mips/lib/memset.S +++ b/arch/mips/lib/memset.S | |||
@@ -5,6 +5,7 @@ | |||
5 | * | 5 | * |
6 | * Copyright (C) 1998, 1999, 2000 by Ralf Baechle | 6 | * Copyright (C) 1998, 1999, 2000 by Ralf Baechle |
7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
8 | * Copyright (C) 2007 Maciej W. Rozycki | ||
8 | */ | 9 | */ |
9 | #include <asm/asm.h> | 10 | #include <asm/asm.h> |
10 | #include <asm/asm-offsets.h> | 11 | #include <asm/asm-offsets.h> |
@@ -71,34 +72,45 @@ LEAF(memset) | |||
71 | 72 | ||
72 | FEXPORT(__bzero) | 73 | FEXPORT(__bzero) |
73 | sltiu t0, a2, LONGSIZE /* very small region? */ | 74 | sltiu t0, a2, LONGSIZE /* very small region? */ |
74 | bnez t0, small_memset | 75 | bnez t0, .Lsmall_memset |
75 | andi t0, a0, LONGMASK /* aligned? */ | 76 | andi t0, a0, LONGMASK /* aligned? */ |
76 | 77 | ||
78 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS | ||
77 | beqz t0, 1f | 79 | beqz t0, 1f |
78 | PTR_SUBU t0, LONGSIZE /* alignment in bytes */ | 80 | PTR_SUBU t0, LONGSIZE /* alignment in bytes */ |
81 | #else | ||
82 | .set noat | ||
83 | li AT, LONGSIZE | ||
84 | beqz t0, 1f | ||
85 | PTR_SUBU t0, AT /* alignment in bytes */ | ||
86 | .set at | ||
87 | #endif | ||
79 | 88 | ||
89 | R10KCBARRIER(0(ra)) | ||
80 | #ifdef __MIPSEB__ | 90 | #ifdef __MIPSEB__ |
81 | EX(LONG_S_L, a1, (a0), first_fixup) /* make word/dword aligned */ | 91 | EX(LONG_S_L, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */ |
82 | #endif | 92 | #endif |
83 | #ifdef __MIPSEL__ | 93 | #ifdef __MIPSEL__ |
84 | EX(LONG_S_R, a1, (a0), first_fixup) /* make word/dword aligned */ | 94 | EX(LONG_S_R, a1, (a0), .Lfirst_fixup) /* make word/dword aligned */ |
85 | #endif | 95 | #endif |
86 | PTR_SUBU a0, t0 /* long align ptr */ | 96 | PTR_SUBU a0, t0 /* long align ptr */ |
87 | PTR_ADDU a2, t0 /* correct size */ | 97 | PTR_ADDU a2, t0 /* correct size */ |
88 | 98 | ||
89 | 1: ori t1, a2, 0x3f /* # of full blocks */ | 99 | 1: ori t1, a2, 0x3f /* # of full blocks */ |
90 | xori t1, 0x3f | 100 | xori t1, 0x3f |
91 | beqz t1, memset_partial /* no block to fill */ | 101 | beqz t1, .Lmemset_partial /* no block to fill */ |
92 | andi t0, a2, 0x40-LONGSIZE | 102 | andi t0, a2, 0x40-LONGSIZE |
93 | 103 | ||
94 | PTR_ADDU t1, a0 /* end address */ | 104 | PTR_ADDU t1, a0 /* end address */ |
95 | .set reorder | 105 | .set reorder |
96 | 1: PTR_ADDIU a0, 64 | 106 | 1: PTR_ADDIU a0, 64 |
97 | f_fill64 a0, -64, a1, fwd_fixup | 107 | R10KCBARRIER(0(ra)) |
108 | f_fill64 a0, -64, a1, .Lfwd_fixup | ||
98 | bne t1, a0, 1b | 109 | bne t1, a0, 1b |
99 | .set noreorder | 110 | .set noreorder |
100 | 111 | ||
101 | memset_partial: | 112 | .Lmemset_partial: |
113 | R10KCBARRIER(0(ra)) | ||
102 | PTR_LA t1, 2f /* where to start */ | 114 | PTR_LA t1, 2f /* where to start */ |
103 | #if LONGSIZE == 4 | 115 | #if LONGSIZE == 4 |
104 | PTR_SUBU t1, t0 | 116 | PTR_SUBU t1, t0 |
@@ -106,7 +118,7 @@ memset_partial: | |||
106 | .set noat | 118 | .set noat |
107 | LONG_SRL AT, t0, 1 | 119 | LONG_SRL AT, t0, 1 |
108 | PTR_SUBU t1, AT | 120 | PTR_SUBU t1, AT |
109 | .set noat | 121 | .set at |
110 | #endif | 122 | #endif |
111 | jr t1 | 123 | jr t1 |
112 | PTR_ADDU a0, t0 /* dest ptr */ | 124 | PTR_ADDU a0, t0 /* dest ptr */ |
@@ -114,26 +126,28 @@ memset_partial: | |||
114 | .set push | 126 | .set push |
115 | .set noreorder | 127 | .set noreorder |
116 | .set nomacro | 128 | .set nomacro |
117 | f_fill64 a0, -64, a1, partial_fixup /* ... but first do longs ... */ | 129 | f_fill64 a0, -64, a1, .Lpartial_fixup /* ... but first do longs ... */ |
118 | 2: .set pop | 130 | 2: .set pop |
119 | andi a2, LONGMASK /* At most one long to go */ | 131 | andi a2, LONGMASK /* At most one long to go */ |
120 | 132 | ||
121 | beqz a2, 1f | 133 | beqz a2, 1f |
122 | PTR_ADDU a0, a2 /* What's left */ | 134 | PTR_ADDU a0, a2 /* What's left */ |
135 | R10KCBARRIER(0(ra)) | ||
123 | #ifdef __MIPSEB__ | 136 | #ifdef __MIPSEB__ |
124 | EX(LONG_S_R, a1, -1(a0), last_fixup) | 137 | EX(LONG_S_R, a1, -1(a0), .Llast_fixup) |
125 | #endif | 138 | #endif |
126 | #ifdef __MIPSEL__ | 139 | #ifdef __MIPSEL__ |
127 | EX(LONG_S_L, a1, -1(a0), last_fixup) | 140 | EX(LONG_S_L, a1, -1(a0), .Llast_fixup) |
128 | #endif | 141 | #endif |
129 | 1: jr ra | 142 | 1: jr ra |
130 | move a2, zero | 143 | move a2, zero |
131 | 144 | ||
132 | small_memset: | 145 | .Lsmall_memset: |
133 | beqz a2, 2f | 146 | beqz a2, 2f |
134 | PTR_ADDU t1, a0, a2 | 147 | PTR_ADDU t1, a0, a2 |
135 | 148 | ||
136 | 1: PTR_ADDIU a0, 1 /* fill bytewise */ | 149 | 1: PTR_ADDIU a0, 1 /* fill bytewise */ |
150 | R10KCBARRIER(0(ra)) | ||
137 | bne t1, a0, 1b | 151 | bne t1, a0, 1b |
138 | sb a1, -1(a0) | 152 | sb a1, -1(a0) |
139 | 153 | ||
@@ -141,11 +155,11 @@ small_memset: | |||
141 | move a2, zero | 155 | move a2, zero |
142 | END(memset) | 156 | END(memset) |
143 | 157 | ||
144 | first_fixup: | 158 | .Lfirst_fixup: |
145 | jr ra | 159 | jr ra |
146 | nop | 160 | nop |
147 | 161 | ||
148 | fwd_fixup: | 162 | .Lfwd_fixup: |
149 | PTR_L t0, TI_TASK($28) | 163 | PTR_L t0, TI_TASK($28) |
150 | LONG_L t0, THREAD_BUADDR(t0) | 164 | LONG_L t0, THREAD_BUADDR(t0) |
151 | andi a2, 0x3f | 165 | andi a2, 0x3f |
@@ -153,7 +167,7 @@ fwd_fixup: | |||
153 | jr ra | 167 | jr ra |
154 | LONG_SUBU a2, t0 | 168 | LONG_SUBU a2, t0 |
155 | 169 | ||
156 | partial_fixup: | 170 | .Lpartial_fixup: |
157 | PTR_L t0, TI_TASK($28) | 171 | PTR_L t0, TI_TASK($28) |
158 | LONG_L t0, THREAD_BUADDR(t0) | 172 | LONG_L t0, THREAD_BUADDR(t0) |
159 | andi a2, LONGMASK | 173 | andi a2, LONGMASK |
@@ -161,6 +175,6 @@ partial_fixup: | |||
161 | jr ra | 175 | jr ra |
162 | LONG_SUBU a2, t0 | 176 | LONG_SUBU a2, t0 |
163 | 177 | ||
164 | last_fixup: | 178 | .Llast_fixup: |
165 | jr ra | 179 | jr ra |
166 | andi v1, a2, LONGMASK | 180 | andi v1, a2, LONGMASK |
diff --git a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S index eca558d83a37..fdbb970f670d 100644 --- a/arch/mips/lib/strlen_user.S +++ b/arch/mips/lib/strlen_user.S | |||
@@ -24,16 +24,16 @@ | |||
24 | LEAF(__strlen_user_asm) | 24 | LEAF(__strlen_user_asm) |
25 | LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? | 25 | LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? |
26 | and v0, a0 | 26 | and v0, a0 |
27 | bnez v0, fault | 27 | bnez v0, .Lfault |
28 | 28 | ||
29 | FEXPORT(__strlen_user_nocheck_asm) | 29 | FEXPORT(__strlen_user_nocheck_asm) |
30 | move v0, a0 | 30 | move v0, a0 |
31 | 1: EX(lb, t0, (v0), fault) | 31 | 1: EX(lb, t0, (v0), .Lfault) |
32 | PTR_ADDIU v0, 1 | 32 | PTR_ADDIU v0, 1 |
33 | bnez t0, 1b | 33 | bnez t0, 1b |
34 | PTR_SUBU v0, a0 | 34 | PTR_SUBU v0, a0 |
35 | jr ra | 35 | jr ra |
36 | END(__strlen_user_asm) | 36 | END(__strlen_user_asm) |
37 | 37 | ||
38 | fault: move v0, zero | 38 | .Lfault: move v0, zero |
39 | jr ra | 39 | jr ra |
diff --git a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S index d16c76fbfac7..7201b2ff08c8 100644 --- a/arch/mips/lib/strncpy_user.S +++ b/arch/mips/lib/strncpy_user.S | |||
@@ -30,29 +30,30 @@ | |||
30 | LEAF(__strncpy_from_user_asm) | 30 | LEAF(__strncpy_from_user_asm) |
31 | LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? | 31 | LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? |
32 | and v0, a1 | 32 | and v0, a1 |
33 | bnez v0, fault | 33 | bnez v0, .Lfault |
34 | 34 | ||
35 | FEXPORT(__strncpy_from_user_nocheck_asm) | 35 | FEXPORT(__strncpy_from_user_nocheck_asm) |
36 | move v0, zero | 36 | move v0, zero |
37 | move v1, a1 | 37 | move v1, a1 |
38 | .set noreorder | 38 | .set noreorder |
39 | 1: EX(lbu, t0, (v1), fault) | 39 | 1: EX(lbu, t0, (v1), .Lfault) |
40 | PTR_ADDIU v1, 1 | 40 | PTR_ADDIU v1, 1 |
41 | R10KCBARRIER(0(ra)) | ||
41 | beqz t0, 2f | 42 | beqz t0, 2f |
42 | sb t0, (a0) | 43 | sb t0, (a0) |
43 | PTR_ADDIU v0, 1 | 44 | PTR_ADDIU v0, 1 |
44 | bne v0, a2, 1b | ||
45 | PTR_ADDIU a0, 1 | ||
46 | .set reorder | 45 | .set reorder |
46 | PTR_ADDIU a0, 1 | ||
47 | bne v0, a2, 1b | ||
47 | 2: PTR_ADDU t0, a1, v0 | 48 | 2: PTR_ADDU t0, a1, v0 |
48 | xor t0, a1 | 49 | xor t0, a1 |
49 | bltz t0, fault | 50 | bltz t0, .Lfault |
50 | jr ra # return n | 51 | jr ra # return n |
51 | END(__strncpy_from_user_asm) | 52 | END(__strncpy_from_user_asm) |
52 | 53 | ||
53 | fault: li v0, -EFAULT | 54 | .Lfault: li v0, -EFAULT |
54 | jr ra | 55 | jr ra |
55 | 56 | ||
56 | .section __ex_table,"a" | 57 | .section __ex_table,"a" |
57 | PTR 1b, fault | 58 | PTR 1b, .Lfault |
58 | .previous | 59 | .previous |
diff --git a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S index c0ea15194a0e..c768e3000616 100644 --- a/arch/mips/lib/strnlen_user.S +++ b/arch/mips/lib/strnlen_user.S | |||
@@ -28,18 +28,19 @@ | |||
28 | LEAF(__strnlen_user_asm) | 28 | LEAF(__strnlen_user_asm) |
29 | LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? | 29 | LONG_L v0, TI_ADDR_LIMIT($28) # pointer ok? |
30 | and v0, a0 | 30 | and v0, a0 |
31 | bnez v0, fault | 31 | bnez v0, .Lfault |
32 | 32 | ||
33 | FEXPORT(__strnlen_user_nocheck_asm) | 33 | FEXPORT(__strnlen_user_nocheck_asm) |
34 | move v0, a0 | 34 | move v0, a0 |
35 | PTR_ADDU a1, a0 # stop pointer | 35 | PTR_ADDU a1, a0 # stop pointer |
36 | 1: beq v0, a1, 1f # limit reached? | 36 | 1: beq v0, a1, 1f # limit reached? |
37 | EX(lb, t0, (v0), fault) | 37 | EX(lb, t0, (v0), .Lfault) |
38 | PTR_ADDU v0, 1 | 38 | PTR_ADDU v0, 1 |
39 | bnez t0, 1b | 39 | bnez t0, 1b |
40 | 1: PTR_SUBU v0, a0 | 40 | 1: PTR_SUBU v0, a0 |
41 | jr ra | 41 | jr ra |
42 | END(__strnlen_user_asm) | 42 | END(__strnlen_user_asm) |
43 | 43 | ||
44 | fault: move v0, zero | 44 | .Lfault: |
45 | move v0, zero | ||
45 | jr ra | 46 | jr ra |
diff --git a/arch/mips/lib/uncached.c b/arch/mips/lib/uncached.c index 58d14f4d9349..27b012d4341c 100644 --- a/arch/mips/lib/uncached.c +++ b/arch/mips/lib/uncached.c | |||
@@ -46,9 +46,9 @@ unsigned long __init run_uncached(void *func) | |||
46 | if (sp >= (long)CKSEG0 && sp < (long)CKSEG2) | 46 | if (sp >= (long)CKSEG0 && sp < (long)CKSEG2) |
47 | usp = CKSEG1ADDR(sp); | 47 | usp = CKSEG1ADDR(sp); |
48 | #ifdef CONFIG_64BIT | 48 | #ifdef CONFIG_64BIT |
49 | else if ((long long)sp >= (long long)PHYS_TO_XKPHYS(0LL, 0) && | 49 | else if ((long long)sp >= (long long)PHYS_TO_XKPHYS(0, 0) && |
50 | (long long)sp < (long long)PHYS_TO_XKPHYS(8LL, 0)) | 50 | (long long)sp < (long long)PHYS_TO_XKPHYS(8, 0)) |
51 | usp = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED, | 51 | usp = PHYS_TO_XKPHYS(K_CALG_UNCACHED, |
52 | XKPHYS_TO_PHYS((long long)sp)); | 52 | XKPHYS_TO_PHYS((long long)sp)); |
53 | #endif | 53 | #endif |
54 | else { | 54 | else { |
@@ -58,9 +58,9 @@ unsigned long __init run_uncached(void *func) | |||
58 | if (lfunc >= (long)CKSEG0 && lfunc < (long)CKSEG2) | 58 | if (lfunc >= (long)CKSEG0 && lfunc < (long)CKSEG2) |
59 | ufunc = CKSEG1ADDR(lfunc); | 59 | ufunc = CKSEG1ADDR(lfunc); |
60 | #ifdef CONFIG_64BIT | 60 | #ifdef CONFIG_64BIT |
61 | else if ((long long)lfunc >= (long long)PHYS_TO_XKPHYS(0LL, 0) && | 61 | else if ((long long)lfunc >= (long long)PHYS_TO_XKPHYS(0, 0) && |
62 | (long long)lfunc < (long long)PHYS_TO_XKPHYS(8LL, 0)) | 62 | (long long)lfunc < (long long)PHYS_TO_XKPHYS(8, 0)) |
63 | ufunc = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED, | 63 | ufunc = PHYS_TO_XKPHYS(K_CALG_UNCACHED, |
64 | XKPHYS_TO_PHYS((long long)lfunc)); | 64 | XKPHYS_TO_PHYS((long long)lfunc)); |
65 | #endif | 65 | #endif |
66 | else { | 66 | else { |
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c index e405d112a067..5c500802271e 100644 --- a/arch/mips/mips-boards/atlas/atlas_setup.c +++ b/arch/mips/mips-boards/atlas/atlas_setup.c | |||
@@ -34,12 +34,6 @@ | |||
34 | #include <asm/time.h> | 34 | #include <asm/time.h> |
35 | #include <asm/traps.h> | 35 | #include <asm/traps.h> |
36 | 36 | ||
37 | extern void mips_reboot_setup(void); | ||
38 | |||
39 | #ifdef CONFIG_KGDB | ||
40 | extern void kgdb_config(void); | ||
41 | #endif | ||
42 | |||
43 | static void __init serial_init(void); | 37 | static void __init serial_init(void); |
44 | 38 | ||
45 | const char *get_system_type(void) | 39 | const char *get_system_type(void) |
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c index 30f1f54cb68b..1695dca5506b 100644 --- a/arch/mips/mips-boards/generic/init.c +++ b/arch/mips/mips-boards/generic/init.c | |||
@@ -250,6 +250,8 @@ void __init mips_ejtag_setup(void) | |||
250 | flush_icache_range((unsigned long)base, (unsigned long)base + 0x80); | 250 | flush_icache_range((unsigned long)base, (unsigned long)base + 0x80); |
251 | } | 251 | } |
252 | 252 | ||
253 | extern struct plat_smp_ops msmtc_smp_ops; | ||
254 | |||
253 | void __init prom_init(void) | 255 | void __init prom_init(void) |
254 | { | 256 | { |
255 | prom_argc = fw_arg0; | 257 | prom_argc = fw_arg0; |
@@ -416,4 +418,10 @@ void __init prom_init(void) | |||
416 | #ifdef CONFIG_SERIAL_8250_CONSOLE | 418 | #ifdef CONFIG_SERIAL_8250_CONSOLE |
417 | console_config(); | 419 | console_config(); |
418 | #endif | 420 | #endif |
421 | #ifdef CONFIG_MIPS_MT_SMP | ||
422 | register_smp_ops(&vsmp_smp_ops); | ||
423 | #endif | ||
424 | #ifdef CONFIG_MIPS_MT_SMTC | ||
425 | register_smp_ops(&msmtc_smp_ops); | ||
426 | #endif | ||
419 | } | 427 | } |
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c index f010261b75d8..dbe60eb55e29 100644 --- a/arch/mips/mips-boards/malta/malta_int.c +++ b/arch/mips/mips-boards/malta/malta_int.c | |||
@@ -26,13 +26,13 @@ | |||
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/io.h> | ||
29 | #include <linux/kernel_stat.h> | 30 | #include <linux/kernel_stat.h> |
30 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
31 | #include <linux/random.h> | 32 | #include <linux/random.h> |
32 | 33 | ||
33 | #include <asm/i8259.h> | 34 | #include <asm/i8259.h> |
34 | #include <asm/irq_cpu.h> | 35 | #include <asm/irq_cpu.h> |
35 | #include <asm/io.h> | ||
36 | #include <asm/irq_regs.h> | 36 | #include <asm/irq_regs.h> |
37 | #include <asm/mips-boards/malta.h> | 37 | #include <asm/mips-boards/malta.h> |
38 | #include <asm/mips-boards/maltaint.h> | 38 | #include <asm/mips-boards/maltaint.h> |
@@ -47,7 +47,7 @@ static DEFINE_SPINLOCK(mips_irq_lock); | |||
47 | static inline int mips_pcibios_iack(void) | 47 | static inline int mips_pcibios_iack(void) |
48 | { | 48 | { |
49 | int irq; | 49 | int irq; |
50 | u32 dummy; | 50 | u32 dummy; |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * Determine highest priority pending interrupt by performing | 53 | * Determine highest priority pending interrupt by performing |
@@ -58,7 +58,7 @@ static inline int mips_pcibios_iack(void) | |||
58 | case MIPS_REVISION_SCON_ROCIT: | 58 | case MIPS_REVISION_SCON_ROCIT: |
59 | case MIPS_REVISION_SCON_SOCITSC: | 59 | case MIPS_REVISION_SCON_SOCITSC: |
60 | case MIPS_REVISION_SCON_SOCITSCP: | 60 | case MIPS_REVISION_SCON_SOCITSCP: |
61 | MSC_READ(MSC01_PCI_IACK, irq); | 61 | MSC_READ(MSC01_PCI_IACK, irq); |
62 | irq &= 0xff; | 62 | irq &= 0xff; |
63 | break; | 63 | break; |
64 | case MIPS_REVISION_SCON_GT64120: | 64 | case MIPS_REVISION_SCON_GT64120: |
@@ -83,7 +83,7 @@ static inline int mips_pcibios_iack(void) | |||
83 | BONITO_PCIMAP_CFG = 0; | 83 | BONITO_PCIMAP_CFG = 0; |
84 | break; | 84 | break; |
85 | default: | 85 | default: |
86 | printk("Unknown system controller.\n"); | 86 | printk(KERN_WARNING "Unknown system controller.\n"); |
87 | return -1; | 87 | return -1; |
88 | } | 88 | } |
89 | return irq; | 89 | return irq; |
@@ -114,7 +114,8 @@ static void malta_hw0_irqdispatch(void) | |||
114 | 114 | ||
115 | irq = get_int(); | 115 | irq = get_int(); |
116 | if (irq < 0) { | 116 | if (irq < 0) { |
117 | return; /* interrupt has already been cleared */ | 117 | /* interrupt has already been cleared */ |
118 | return; | ||
118 | } | 119 | } |
119 | 120 | ||
120 | do_IRQ(MALTA_INT_BASE + irq); | 121 | do_IRQ(MALTA_INT_BASE + irq); |
@@ -123,15 +124,15 @@ static void malta_hw0_irqdispatch(void) | |||
123 | static void corehi_irqdispatch(void) | 124 | static void corehi_irqdispatch(void) |
124 | { | 125 | { |
125 | unsigned int intedge, intsteer, pcicmd, pcibadaddr; | 126 | unsigned int intedge, intsteer, pcicmd, pcibadaddr; |
126 | unsigned int pcimstat, intisr, inten, intpol; | 127 | unsigned int pcimstat, intisr, inten, intpol; |
127 | unsigned int intrcause, datalo, datahi; | 128 | unsigned int intrcause, datalo, datahi; |
128 | struct pt_regs *regs = get_irq_regs(); | 129 | struct pt_regs *regs = get_irq_regs(); |
129 | 130 | ||
130 | printk("CoreHI interrupt, shouldn't happen, so we die here!!!\n"); | 131 | printk(KERN_EMERG "CoreHI interrupt, shouldn't happen, we die here!\n"); |
131 | printk("epc : %08lx\nStatus: %08lx\n" | 132 | printk(KERN_EMERG "epc : %08lx\nStatus: %08lx\n" |
132 | "Cause : %08lx\nbadVaddr : %08lx\n", | 133 | "Cause : %08lx\nbadVaddr : %08lx\n", |
133 | regs->cp0_epc, regs->cp0_status, | 134 | regs->cp0_epc, regs->cp0_status, |
134 | regs->cp0_cause, regs->cp0_badvaddr); | 135 | regs->cp0_cause, regs->cp0_badvaddr); |
135 | 136 | ||
136 | /* Read all the registers and then print them as there is a | 137 | /* Read all the registers and then print them as there is a |
137 | problem with interspersed printk's upsetting the Bonito controller. | 138 | problem with interspersed printk's upsetting the Bonito controller. |
@@ -139,41 +140,41 @@ static void corehi_irqdispatch(void) | |||
139 | */ | 140 | */ |
140 | 141 | ||
141 | switch (mips_revision_sconid) { | 142 | switch (mips_revision_sconid) { |
142 | case MIPS_REVISION_SCON_SOCIT: | 143 | case MIPS_REVISION_SCON_SOCIT: |
143 | case MIPS_REVISION_SCON_ROCIT: | 144 | case MIPS_REVISION_SCON_ROCIT: |
144 | case MIPS_REVISION_SCON_SOCITSC: | 145 | case MIPS_REVISION_SCON_SOCITSC: |
145 | case MIPS_REVISION_SCON_SOCITSCP: | 146 | case MIPS_REVISION_SCON_SOCITSCP: |
146 | ll_msc_irq(); | 147 | ll_msc_irq(); |
147 | break; | 148 | break; |
148 | case MIPS_REVISION_SCON_GT64120: | 149 | case MIPS_REVISION_SCON_GT64120: |
149 | intrcause = GT_READ(GT_INTRCAUSE_OFS); | 150 | intrcause = GT_READ(GT_INTRCAUSE_OFS); |
150 | datalo = GT_READ(GT_CPUERR_ADDRLO_OFS); | 151 | datalo = GT_READ(GT_CPUERR_ADDRLO_OFS); |
151 | datahi = GT_READ(GT_CPUERR_ADDRHI_OFS); | 152 | datahi = GT_READ(GT_CPUERR_ADDRHI_OFS); |
152 | printk("GT_INTRCAUSE = %08x\n", intrcause); | 153 | printk(KERN_EMERG "GT_INTRCAUSE = %08x\n", intrcause); |
153 | printk("GT_CPUERR_ADDR = %02x%08x\n", datahi, datalo); | 154 | printk(KERN_EMERG "GT_CPUERR_ADDR = %02x%08x\n", |
154 | break; | 155 | datahi, datalo); |
155 | case MIPS_REVISION_SCON_BONITO: | 156 | break; |
156 | pcibadaddr = BONITO_PCIBADADDR; | 157 | case MIPS_REVISION_SCON_BONITO: |
157 | pcimstat = BONITO_PCIMSTAT; | 158 | pcibadaddr = BONITO_PCIBADADDR; |
158 | intisr = BONITO_INTISR; | 159 | pcimstat = BONITO_PCIMSTAT; |
159 | inten = BONITO_INTEN; | 160 | intisr = BONITO_INTISR; |
160 | intpol = BONITO_INTPOL; | 161 | inten = BONITO_INTEN; |
161 | intedge = BONITO_INTEDGE; | 162 | intpol = BONITO_INTPOL; |
162 | intsteer = BONITO_INTSTEER; | 163 | intedge = BONITO_INTEDGE; |
163 | pcicmd = BONITO_PCICMD; | 164 | intsteer = BONITO_INTSTEER; |
164 | printk("BONITO_INTISR = %08x\n", intisr); | 165 | pcicmd = BONITO_PCICMD; |
165 | printk("BONITO_INTEN = %08x\n", inten); | 166 | printk(KERN_EMERG "BONITO_INTISR = %08x\n", intisr); |
166 | printk("BONITO_INTPOL = %08x\n", intpol); | 167 | printk(KERN_EMERG "BONITO_INTEN = %08x\n", inten); |
167 | printk("BONITO_INTEDGE = %08x\n", intedge); | 168 | printk(KERN_EMERG "BONITO_INTPOL = %08x\n", intpol); |
168 | printk("BONITO_INTSTEER = %08x\n", intsteer); | 169 | printk(KERN_EMERG "BONITO_INTEDGE = %08x\n", intedge); |
169 | printk("BONITO_PCICMD = %08x\n", pcicmd); | 170 | printk(KERN_EMERG "BONITO_INTSTEER = %08x\n", intsteer); |
170 | printk("BONITO_PCIBADADDR = %08x\n", pcibadaddr); | 171 | printk(KERN_EMERG "BONITO_PCICMD = %08x\n", pcicmd); |
171 | printk("BONITO_PCIMSTAT = %08x\n", pcimstat); | 172 | printk(KERN_EMERG "BONITO_PCIBADADDR = %08x\n", pcibadaddr); |
172 | break; | 173 | printk(KERN_EMERG "BONITO_PCIMSTAT = %08x\n", pcimstat); |
173 | } | 174 | break; |
174 | 175 | } | |
175 | /* We die here*/ | 176 | |
176 | die("CoreHi interrupt", regs); | 177 | die("CoreHi interrupt", regs); |
177 | } | 178 | } |
178 | 179 | ||
179 | static inline int clz(unsigned long x) | 180 | static inline int clz(unsigned long x) |
@@ -214,9 +215,9 @@ static inline unsigned int irq_ffs(unsigned int pending) | |||
214 | 215 | ||
215 | t0 = pending & 0x8000; | 216 | t0 = pending & 0x8000; |
216 | t0 = t0 < 1; | 217 | t0 = t0 < 1; |
217 | //t0 = t0 << 2; | 218 | /* t0 = t0 << 2; */ |
218 | a0 = a0 - t0; | 219 | a0 = a0 - t0; |
219 | //pending = pending << t0; | 220 | /* pending = pending << t0; */ |
220 | 221 | ||
221 | return a0; | 222 | return a0; |
222 | #endif | 223 | #endif |
@@ -299,21 +300,29 @@ void __init arch_init_irq(void) | |||
299 | if (!cpu_has_veic) | 300 | if (!cpu_has_veic) |
300 | mips_cpu_irq_init(); | 301 | mips_cpu_irq_init(); |
301 | 302 | ||
302 | switch(mips_revision_sconid) { | 303 | switch (mips_revision_sconid) { |
303 | case MIPS_REVISION_SCON_SOCIT: | 304 | case MIPS_REVISION_SCON_SOCIT: |
304 | case MIPS_REVISION_SCON_ROCIT: | 305 | case MIPS_REVISION_SCON_ROCIT: |
305 | if (cpu_has_veic) | 306 | if (cpu_has_veic) |
306 | init_msc_irqs(MIPS_MSC01_IC_REG_BASE, MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs); | 307 | init_msc_irqs(MIPS_MSC01_IC_REG_BASE, |
308 | MSC01E_INT_BASE, msc_eicirqmap, | ||
309 | msc_nr_eicirqs); | ||
307 | else | 310 | else |
308 | init_msc_irqs(MIPS_MSC01_IC_REG_BASE, MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs); | 311 | init_msc_irqs(MIPS_MSC01_IC_REG_BASE, |
312 | MSC01C_INT_BASE, msc_irqmap, | ||
313 | msc_nr_irqs); | ||
309 | break; | 314 | break; |
310 | 315 | ||
311 | case MIPS_REVISION_SCON_SOCITSC: | 316 | case MIPS_REVISION_SCON_SOCITSC: |
312 | case MIPS_REVISION_SCON_SOCITSCP: | 317 | case MIPS_REVISION_SCON_SOCITSCP: |
313 | if (cpu_has_veic) | 318 | if (cpu_has_veic) |
314 | init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE, MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs); | 319 | init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE, |
320 | MSC01E_INT_BASE, msc_eicirqmap, | ||
321 | msc_nr_eicirqs); | ||
315 | else | 322 | else |
316 | init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE, MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs); | 323 | init_msc_irqs(MIPS_SOCITSC_IC_REG_BASE, |
324 | MSC01C_INT_BASE, msc_irqmap, | ||
325 | msc_nr_irqs); | ||
317 | } | 326 | } |
318 | 327 | ||
319 | if (cpu_has_veic) { | 328 | if (cpu_has_veic) { |
@@ -321,8 +330,7 @@ void __init arch_init_irq(void) | |||
321 | set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch); | 330 | set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch); |
322 | setup_irq(MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq); | 331 | setup_irq(MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq); |
323 | setup_irq(MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction); | 332 | setup_irq(MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction); |
324 | } | 333 | } else if (cpu_has_vint) { |
325 | else if (cpu_has_vint) { | ||
326 | set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch); | 334 | set_vi_handler(MIPSCPU_INT_I8259A, malta_hw0_irqdispatch); |
327 | set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch); | 335 | set_vi_handler(MIPSCPU_INT_COREHI, corehi_irqdispatch); |
328 | #ifdef CONFIG_MIPS_MT_SMTC | 336 | #ifdef CONFIG_MIPS_MT_SMTC |
@@ -344,11 +352,12 @@ void __init arch_init_irq(void) | |||
344 | } | 352 | } |
345 | #else /* Not SMTC */ | 353 | #else /* Not SMTC */ |
346 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); | 354 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); |
347 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); | 355 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, |
356 | &corehi_irqaction); | ||
348 | #endif /* CONFIG_MIPS_MT_SMTC */ | 357 | #endif /* CONFIG_MIPS_MT_SMTC */ |
349 | } | 358 | } else { |
350 | else { | ||
351 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); | 359 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_I8259A, &i8259irq); |
352 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); | 360 | setup_irq(MIPS_CPU_IRQ_BASE+MIPSCPU_INT_COREHI, |
361 | &corehi_irqaction); | ||
353 | } | 362 | } |
354 | } | 363 | } |
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c index bc43a5c2224d..2cd8f5734b36 100644 --- a/arch/mips/mips-boards/malta/malta_setup.c +++ b/arch/mips/mips-boards/malta/malta_setup.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Carsten Langgaard, carstenl@mips.com | 2 | * Carsten Langgaard, carstenl@mips.com |
3 | * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. | 3 | * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. |
4 | * Copyright (C) Dmitri Vorobiev | ||
4 | * | 5 | * |
5 | * This program is free software; you can distribute it and/or modify it | 6 | * This program is free software; you can distribute it and/or modify it |
6 | * under the terms of the GNU General Public License (Version 2) as | 7 | * under the terms of the GNU General Public License (Version 2) as |
@@ -15,39 +16,57 @@ | |||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | 16 | * with this program; if not, write to the Free Software Foundation, Inc., |
16 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | 17 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. |
17 | */ | 18 | */ |
19 | #include <linux/cpu.h> | ||
18 | #include <linux/init.h> | 20 | #include <linux/init.h> |
19 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
20 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
23 | #include <linux/irq.h> | ||
21 | #include <linux/pci.h> | 24 | #include <linux/pci.h> |
22 | #include <linux/screen_info.h> | 25 | #include <linux/screen_info.h> |
26 | #include <linux/time.h> | ||
23 | 27 | ||
24 | #include <asm/cpu.h> | ||
25 | #include <asm/bootinfo.h> | 28 | #include <asm/bootinfo.h> |
26 | #include <asm/irq.h> | ||
27 | #include <asm/mips-boards/generic.h> | 29 | #include <asm/mips-boards/generic.h> |
28 | #include <asm/mips-boards/prom.h> | 30 | #include <asm/mips-boards/prom.h> |
29 | #include <asm/mips-boards/malta.h> | 31 | #include <asm/mips-boards/malta.h> |
30 | #include <asm/mips-boards/maltaint.h> | 32 | #include <asm/mips-boards/maltaint.h> |
31 | #include <asm/dma.h> | 33 | #include <asm/dma.h> |
32 | #include <asm/time.h> | ||
33 | #include <asm/traps.h> | 34 | #include <asm/traps.h> |
34 | #ifdef CONFIG_VT | 35 | #ifdef CONFIG_VT |
35 | #include <linux/console.h> | 36 | #include <linux/console.h> |
36 | #endif | 37 | #endif |
37 | 38 | ||
38 | extern void mips_reboot_setup(void); | ||
39 | extern unsigned long mips_rtc_get_time(void); | ||
40 | |||
41 | #ifdef CONFIG_KGDB | ||
42 | extern void kgdb_config(void); | ||
43 | #endif | ||
44 | |||
45 | struct resource standard_io_resources[] = { | 39 | struct resource standard_io_resources[] = { |
46 | { .name = "dma1", .start = 0x00, .end = 0x1f, .flags = IORESOURCE_BUSY }, | 40 | { |
47 | { .name = "timer", .start = 0x40, .end = 0x5f, .flags = IORESOURCE_BUSY }, | 41 | .name = "dma1", |
48 | { .name = "keyboard", .start = 0x60, .end = 0x6f, .flags = IORESOURCE_BUSY }, | 42 | .start = 0x00, |
49 | { .name = "dma page reg", .start = 0x80, .end = 0x8f, .flags = IORESOURCE_BUSY }, | 43 | .end = 0x1f, |
50 | { .name = "dma2", .start = 0xc0, .end = 0xdf, .flags = IORESOURCE_BUSY }, | 44 | .flags = IORESOURCE_BUSY |
45 | }, | ||
46 | { | ||
47 | .name = "timer", | ||
48 | .start = 0x40, | ||
49 | .end = 0x5f, | ||
50 | .flags = IORESOURCE_BUSY | ||
51 | }, | ||
52 | { | ||
53 | .name = "keyboard", | ||
54 | .start = 0x60, | ||
55 | .end = 0x6f, | ||
56 | .flags = IORESOURCE_BUSY | ||
57 | }, | ||
58 | { | ||
59 | .name = "dma page reg", | ||
60 | .start = 0x80, | ||
61 | .end = 0x8f, | ||
62 | .flags = IORESOURCE_BUSY | ||
63 | }, | ||
64 | { | ||
65 | .name = "dma2", | ||
66 | .start = 0xc0, | ||
67 | .end = 0xdf, | ||
68 | .flags = IORESOURCE_BUSY | ||
69 | }, | ||
51 | }; | 70 | }; |
52 | 71 | ||
53 | const char *get_system_type(void) | 72 | const char *get_system_type(void) |
@@ -62,7 +81,7 @@ const char display_string[] = " LINUX ON MALTA "; | |||
62 | #endif /* CONFIG_MIPS_MT_SMTC */ | 81 | #endif /* CONFIG_MIPS_MT_SMTC */ |
63 | 82 | ||
64 | #ifdef CONFIG_BLK_DEV_FD | 83 | #ifdef CONFIG_BLK_DEV_FD |
65 | void __init fd_activate(void) | 84 | static void __init fd_activate(void) |
66 | { | 85 | { |
67 | /* | 86 | /* |
68 | * Activate Floppy Controller in the SMSC FDC37M817 Super I/O | 87 | * Activate Floppy Controller in the SMSC FDC37M817 Super I/O |
@@ -83,6 +102,85 @@ void __init fd_activate(void) | |||
83 | } | 102 | } |
84 | #endif | 103 | #endif |
85 | 104 | ||
105 | #ifdef CONFIG_BLK_DEV_IDE | ||
106 | static void __init pci_clock_check(void) | ||
107 | { | ||
108 | unsigned int __iomem *jmpr_p = | ||
109 | (unsigned int *) ioremap(MALTA_JMPRS_REG, sizeof(unsigned int)); | ||
110 | int jmpr = (__raw_readl(jmpr_p) >> 2) & 0x07; | ||
111 | static const int pciclocks[] __initdata = { | ||
112 | 33, 20, 25, 30, 12, 16, 37, 10 | ||
113 | }; | ||
114 | int pciclock = pciclocks[jmpr]; | ||
115 | char *argptr = prom_getcmdline(); | ||
116 | |||
117 | if (pciclock != 33 && !strstr(argptr, "idebus=")) { | ||
118 | printk(KERN_WARNING "WARNING: PCI clock is %dMHz, " | ||
119 | "setting idebus\n", pciclock); | ||
120 | argptr += strlen(argptr); | ||
121 | sprintf(argptr, " idebus=%d", pciclock); | ||
122 | if (pciclock < 20 || pciclock > 66) | ||
123 | printk(KERN_WARNING "WARNING: IDE timing " | ||
124 | "calculations will be incorrect\n"); | ||
125 | } | ||
126 | } | ||
127 | #endif | ||
128 | |||
129 | #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) | ||
130 | static void __init screen_info_setup(void) | ||
131 | { | ||
132 | screen_info = (struct screen_info) { | ||
133 | .orig_x = 0, | ||
134 | .orig_y = 25, | ||
135 | .ext_mem_k = 0, | ||
136 | .orig_video_page = 0, | ||
137 | .orig_video_mode = 0, | ||
138 | .orig_video_cols = 80, | ||
139 | .unused2 = 0, | ||
140 | .orig_video_ega_bx = 0, | ||
141 | .unused3 = 0, | ||
142 | .orig_video_lines = 25, | ||
143 | .orig_video_isVGA = VIDEO_TYPE_VGAC, | ||
144 | .orig_video_points = 16 | ||
145 | }; | ||
146 | } | ||
147 | #endif | ||
148 | |||
149 | static void __init bonito_quirks_setup(void) | ||
150 | { | ||
151 | char *argptr; | ||
152 | |||
153 | argptr = prom_getcmdline(); | ||
154 | if (strstr(argptr, "debug")) { | ||
155 | BONITO_BONGENCFG |= BONITO_BONGENCFG_DEBUGMODE; | ||
156 | printk(KERN_INFO "Enabled Bonito debug mode\n"); | ||
157 | } else | ||
158 | BONITO_BONGENCFG &= ~BONITO_BONGENCFG_DEBUGMODE; | ||
159 | |||
160 | #ifdef CONFIG_DMA_COHERENT | ||
161 | if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) { | ||
162 | BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN; | ||
163 | printk(KERN_INFO "Enabled Bonito CPU coherency\n"); | ||
164 | |||
165 | argptr = prom_getcmdline(); | ||
166 | if (strstr(argptr, "iobcuncached")) { | ||
167 | BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN; | ||
168 | BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG & | ||
169 | ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | | ||
170 | BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); | ||
171 | printk(KERN_INFO "Disabled Bonito IOBC coherency\n"); | ||
172 | } else { | ||
173 | BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN; | ||
174 | BONITO_PCIMEMBASECFG |= | ||
175 | (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | | ||
176 | BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); | ||
177 | printk(KERN_INFO "Enabled Bonito IOBC coherency\n"); | ||
178 | } | ||
179 | } else | ||
180 | panic("Hardware DMA cache coherency not supported"); | ||
181 | #endif | ||
182 | } | ||
183 | |||
86 | void __init plat_mem_setup(void) | 184 | void __init plat_mem_setup(void) |
87 | { | 185 | { |
88 | unsigned int i; | 186 | unsigned int i; |
@@ -102,86 +200,24 @@ void __init plat_mem_setup(void) | |||
102 | kgdb_config(); | 200 | kgdb_config(); |
103 | #endif | 201 | #endif |
104 | 202 | ||
105 | if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) { | ||
106 | char *argptr; | ||
107 | |||
108 | argptr = prom_getcmdline(); | ||
109 | if (strstr(argptr, "debug")) { | ||
110 | BONITO_BONGENCFG |= BONITO_BONGENCFG_DEBUGMODE; | ||
111 | printk("Enabled Bonito debug mode\n"); | ||
112 | } | ||
113 | else | ||
114 | BONITO_BONGENCFG &= ~BONITO_BONGENCFG_DEBUGMODE; | ||
115 | |||
116 | #ifdef CONFIG_DMA_COHERENT | ||
117 | if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) { | ||
118 | BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN; | ||
119 | printk("Enabled Bonito CPU coherency\n"); | ||
120 | |||
121 | argptr = prom_getcmdline(); | ||
122 | if (strstr(argptr, "iobcuncached")) { | ||
123 | BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN; | ||
124 | BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG & | ||
125 | ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | | ||
126 | BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); | ||
127 | printk("Disabled Bonito IOBC coherency\n"); | ||
128 | } | ||
129 | else { | ||
130 | BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN; | ||
131 | BONITO_PCIMEMBASECFG |= | ||
132 | (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | | ||
133 | BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); | ||
134 | printk("Enabled Bonito IOBC coherency\n"); | ||
135 | } | ||
136 | } | ||
137 | else | ||
138 | panic("Hardware DMA cache coherency not supported"); | ||
139 | |||
140 | #endif | ||
141 | } | ||
142 | #ifdef CONFIG_DMA_COHERENT | 203 | #ifdef CONFIG_DMA_COHERENT |
143 | else { | 204 | if (mips_revision_sconid != MIPS_REVISION_SCON_BONITO) |
144 | panic("Hardware DMA cache coherency not supported"); | 205 | panic("Hardware DMA cache coherency not supported"); |
145 | } | ||
146 | #endif | 206 | #endif |
147 | 207 | ||
208 | if (mips_revision_sconid == MIPS_REVISION_SCON_BONITO) | ||
209 | bonito_quirks_setup(); | ||
210 | |||
148 | #ifdef CONFIG_BLK_DEV_IDE | 211 | #ifdef CONFIG_BLK_DEV_IDE |
149 | /* Check PCI clock */ | 212 | pci_clock_check(); |
150 | { | ||
151 | unsigned int __iomem *jmpr_p = (unsigned int *) ioremap(MALTA_JMPRS_REG, sizeof(unsigned int)); | ||
152 | int jmpr = (__raw_readl(jmpr_p) >> 2) & 0x07; | ||
153 | static const int pciclocks[] __initdata = { | ||
154 | 33, 20, 25, 30, 12, 16, 37, 10 | ||
155 | }; | ||
156 | int pciclock = pciclocks[jmpr]; | ||
157 | char *argptr = prom_getcmdline(); | ||
158 | |||
159 | if (pciclock != 33 && !strstr (argptr, "idebus=")) { | ||
160 | printk("WARNING: PCI clock is %dMHz, setting idebus\n", pciclock); | ||
161 | argptr += strlen(argptr); | ||
162 | sprintf(argptr, " idebus=%d", pciclock); | ||
163 | if (pciclock < 20 || pciclock > 66) | ||
164 | printk("WARNING: IDE timing calculations will be incorrect\n"); | ||
165 | } | ||
166 | } | ||
167 | #endif | 213 | #endif |
214 | |||
168 | #ifdef CONFIG_BLK_DEV_FD | 215 | #ifdef CONFIG_BLK_DEV_FD |
169 | fd_activate(); | 216 | fd_activate(); |
170 | #endif | 217 | #endif |
171 | #ifdef CONFIG_VT | 218 | |
172 | #if defined(CONFIG_VGA_CONSOLE) | 219 | #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) |
173 | screen_info = (struct screen_info) { | 220 | screen_info_setup(); |
174 | 0, 25, /* orig-x, orig-y */ | ||
175 | 0, /* unused */ | ||
176 | 0, /* orig-video-page */ | ||
177 | 0, /* orig-video-mode */ | ||
178 | 80, /* orig-video-cols */ | ||
179 | 0, 0, 0, /* ega_ax, ega_bx, ega_cx */ | ||
180 | 25, /* orig-video-lines */ | ||
181 | VIDEO_TYPE_VGAC, /* orig-video-isVGA */ | ||
182 | 16 /* orig-video-points */ | ||
183 | }; | ||
184 | #endif | ||
185 | #endif | 221 | #endif |
186 | mips_reboot_setup(); | 222 | mips_reboot_setup(); |
187 | } | 223 | } |
diff --git a/arch/mips/mips-boards/malta/malta_smtc.c b/arch/mips/mips-boards/malta/malta_smtc.c index 5c980f4a48fe..5ea705e49454 100644 --- a/arch/mips/mips-boards/malta/malta_smtc.c +++ b/arch/mips/mips-boards/malta/malta_smtc.c | |||
@@ -15,28 +15,26 @@ | |||
15 | * Cause the specified action to be performed on a targeted "CPU" | 15 | * Cause the specified action to be performed on a targeted "CPU" |
16 | */ | 16 | */ |
17 | 17 | ||
18 | void core_send_ipi(int cpu, unsigned int action) | 18 | static void msmtc_send_ipi_single(int cpu, unsigned int action) |
19 | { | 19 | { |
20 | /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ | 20 | /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ |
21 | smtc_send_ipi(cpu, LINUX_SMP_IPI, action); | 21 | smtc_send_ipi(cpu, LINUX_SMP_IPI, action); |
22 | } | 22 | } |
23 | 23 | ||
24 | /* | 24 | static void msmtc_send_ipi_mask(cpumask_t mask, unsigned int action) |
25 | * Platform "CPU" startup hook | ||
26 | */ | ||
27 | |||
28 | void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) | ||
29 | { | 25 | { |
30 | smtc_boot_secondary(cpu, idle); | 26 | unsigned int i; |
27 | |||
28 | for_each_cpu_mask(i, mask) | ||
29 | msmtc_send_ipi_single(i, action); | ||
31 | } | 30 | } |
32 | 31 | ||
33 | /* | 32 | /* |
34 | * Post-config but pre-boot cleanup entry point | 33 | * Post-config but pre-boot cleanup entry point |
35 | */ | 34 | */ |
36 | 35 | static void __cpuinit msmtc_init_secondary(void) | |
37 | void __cpuinit prom_init_secondary(void) | ||
38 | { | 36 | { |
39 | void smtc_init_secondary(void); | 37 | void smtc_init_secondary(void); |
40 | int myvpe; | 38 | int myvpe; |
41 | 39 | ||
42 | /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */ | 40 | /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */ |
@@ -50,45 +48,61 @@ void __cpuinit prom_init_secondary(void) | |||
50 | set_c0_status(0x100 << cp0_perfcount_irq); | 48 | set_c0_status(0x100 << cp0_perfcount_irq); |
51 | } | 49 | } |
52 | 50 | ||
53 | smtc_init_secondary(); | 51 | smtc_init_secondary(); |
54 | } | 52 | } |
55 | 53 | ||
56 | /* | 54 | /* |
57 | * Platform SMP pre-initialization | 55 | * Platform "CPU" startup hook |
58 | * | ||
59 | * As noted above, we can assume a single CPU for now | ||
60 | * but it may be multithreaded. | ||
61 | */ | 56 | */ |
62 | 57 | static void __cpuinit msmtc_boot_secondary(int cpu, struct task_struct *idle) | |
63 | void __cpuinit plat_smp_setup(void) | ||
64 | { | 58 | { |
65 | if (read_c0_config3() & (1<<2)) | 59 | smtc_boot_secondary(cpu, idle); |
66 | mipsmt_build_cpu_map(0); | ||
67 | } | 60 | } |
68 | 61 | ||
69 | void __init plat_prepare_cpus(unsigned int max_cpus) | 62 | /* |
63 | * SMP initialization finalization entry point | ||
64 | */ | ||
65 | static void __cpuinit msmtc_smp_finish(void) | ||
70 | { | 66 | { |
71 | if (read_c0_config3() & (1<<2)) | 67 | smtc_smp_finish(); |
72 | mipsmt_prepare_cpus(); | ||
73 | } | 68 | } |
74 | 69 | ||
75 | /* | 70 | /* |
76 | * SMP initialization finalization entry point | 71 | * Hook for after all CPUs are online |
77 | */ | 72 | */ |
78 | 73 | ||
79 | void __cpuinit prom_smp_finish(void) | 74 | static void msmtc_cpus_done(void) |
80 | { | 75 | { |
81 | smtc_smp_finish(); | ||
82 | } | 76 | } |
83 | 77 | ||
84 | /* | 78 | /* |
85 | * Hook for after all CPUs are online | 79 | * Platform SMP pre-initialization |
80 | * | ||
81 | * As noted above, we can assume a single CPU for now | ||
82 | * but it may be multithreaded. | ||
86 | */ | 83 | */ |
87 | 84 | ||
88 | void prom_cpus_done(void) | 85 | static void __init msmtc_smp_setup(void) |
89 | { | 86 | { |
87 | mipsmt_build_cpu_map(0); | ||
90 | } | 88 | } |
91 | 89 | ||
90 | static void __init msmtc_prepare_cpus(unsigned int max_cpus) | ||
91 | { | ||
92 | mipsmt_prepare_cpus(); | ||
93 | } | ||
94 | |||
95 | struct plat_smp_ops msmtc_smp_ops = { | ||
96 | .send_ipi_single = msmtc_send_ipi_single, | ||
97 | .send_ipi_mask = msmtc_send_ipi_mask, | ||
98 | .init_secondary = msmtc_init_secondary, | ||
99 | .smp_finish = msmtc_smp_finish, | ||
100 | .cpus_done = msmtc_cpus_done, | ||
101 | .boot_secondary = msmtc_boot_secondary, | ||
102 | .smp_setup = msmtc_smp_setup, | ||
103 | .prepare_cpus = msmtc_prepare_cpus, | ||
104 | }; | ||
105 | |||
92 | #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF | 106 | #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF |
93 | /* | 107 | /* |
94 | * IRQ affinity hook | 108 | * IRQ affinity hook |
diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c index 1fb61b852304..8aa8e5b7b074 100644 --- a/arch/mips/mips-boards/sead/sead_setup.c +++ b/arch/mips/mips-boards/sead/sead_setup.c | |||
@@ -34,8 +34,6 @@ | |||
34 | #include <asm/mips-boards/seadint.h> | 34 | #include <asm/mips-boards/seadint.h> |
35 | #include <asm/time.h> | 35 | #include <asm/time.h> |
36 | 36 | ||
37 | extern void mips_reboot_setup(void); | ||
38 | |||
39 | static void __init serial_init(void); | 37 | static void __init serial_init(void); |
40 | 38 | ||
41 | const char *get_system_type(void) | 39 | const char *get_system_type(void) |
diff --git a/arch/mips/mipssim/Makefile b/arch/mips/mipssim/Makefile index 75568b584df4..57f43c1c7882 100644 --- a/arch/mips/mipssim/Makefile +++ b/arch/mips/mipssim/Makefile | |||
@@ -21,6 +21,6 @@ obj-y := sim_platform.o sim_setup.o sim_mem.o sim_time.o sim_int.o \ | |||
21 | sim_cmdline.o | 21 | sim_cmdline.o |
22 | 22 | ||
23 | obj-$(CONFIG_EARLY_PRINTK) += sim_console.o | 23 | obj-$(CONFIG_EARLY_PRINTK) += sim_console.o |
24 | obj-$(CONFIG_SMP) += sim_smp.o | 24 | obj-$(CONFIG_MIPS_MT_SMTC) += sim_smtc.o |
25 | 25 | ||
26 | EXTRA_CFLAGS += -Werror | 26 | EXTRA_CFLAGS += -Werror |
diff --git a/arch/mips/mipssim/sim_setup.c b/arch/mips/mipssim/sim_setup.c index 452c129d02c1..d49fe73426b7 100644 --- a/arch/mips/mipssim/sim_setup.c +++ b/arch/mips/mipssim/sim_setup.c | |||
@@ -60,6 +60,8 @@ void __init plat_mem_setup(void) | |||
60 | #endif | 60 | #endif |
61 | } | 61 | } |
62 | 62 | ||
63 | extern struct plat_smp_ops ssmtc_smp_ops; | ||
64 | |||
63 | void __init prom_init(void) | 65 | void __init prom_init(void) |
64 | { | 66 | { |
65 | set_io_port_base(0xbfd00000); | 67 | set_io_port_base(0xbfd00000); |
@@ -67,8 +69,20 @@ void __init prom_init(void) | |||
67 | pr_info("\nLINUX started...\n"); | 69 | pr_info("\nLINUX started...\n"); |
68 | prom_init_cmdline(); | 70 | prom_init_cmdline(); |
69 | prom_meminit(); | 71 | prom_meminit(); |
70 | } | ||
71 | 72 | ||
73 | #ifdef CONFIG_MIPS_MT_SMP | ||
74 | if (cpu_has_mipsmt) | ||
75 | register_smp_ops(&vsmp_smp_ops); | ||
76 | else | ||
77 | register_smp_ops(&up_smp_ops); | ||
78 | #endif | ||
79 | #ifdef CONFIG_MIPS_MT_SMTC | ||
80 | if (cpu_has_mipsmt) | ||
81 | register_smp_ops(&ssmtc_smp_ops); | ||
82 | else | ||
83 | register_smp_ops(&up_smp_ops); | ||
84 | #endif | ||
85 | } | ||
72 | 86 | ||
73 | static void __init serial_init(void) | 87 | static void __init serial_init(void) |
74 | { | 88 | { |
diff --git a/arch/mips/mipssim/sim_smp.c b/arch/mips/mipssim/sim_smtc.c index ccbbccac23ef..d6e4f656ad14 100644 --- a/arch/mips/mipssim/sim_smp.c +++ b/arch/mips/mipssim/sim_smtc.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * | 16 | * |
17 | */ | 17 | */ |
18 | /* | 18 | /* |
19 | * Simulator Platform-specific hooks for SMP operation | 19 | * Simulator Platform-specific hooks for SMTC operation |
20 | */ | 20 | */ |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
@@ -29,65 +29,72 @@ | |||
29 | #include <asm/processor.h> | 29 | #include <asm/processor.h> |
30 | #include <asm/system.h> | 30 | #include <asm/system.h> |
31 | #include <asm/mmu_context.h> | 31 | #include <asm/mmu_context.h> |
32 | #ifdef CONFIG_MIPS_MT_SMTC | ||
33 | #include <asm/smtc_ipi.h> | 32 | #include <asm/smtc_ipi.h> |
34 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
35 | 33 | ||
36 | /* VPE/SMP Prototype implements platform interfaces directly */ | 34 | /* VPE/SMP Prototype implements platform interfaces directly */ |
37 | #if !defined(CONFIG_MIPS_MT_SMP) | ||
38 | 35 | ||
39 | /* | 36 | /* |
40 | * Cause the specified action to be performed on a targeted "CPU" | 37 | * Cause the specified action to be performed on a targeted "CPU" |
41 | */ | 38 | */ |
42 | 39 | ||
43 | void core_send_ipi(int cpu, unsigned int action) | 40 | static void ssmtc_send_ipi_single(int cpu, unsigned int action) |
44 | { | 41 | { |
45 | #ifdef CONFIG_MIPS_MT_SMTC | ||
46 | smtc_send_ipi(cpu, LINUX_SMP_IPI, action); | 42 | smtc_send_ipi(cpu, LINUX_SMP_IPI, action); |
47 | #endif /* CONFIG_MIPS_MT_SMTC */ | 43 | /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ |
48 | /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */ | 44 | } |
45 | |||
46 | static inline void ssmtc_send_ipi_mask(cpumask_t mask, unsigned int action) | ||
47 | { | ||
48 | unsigned int i; | ||
49 | 49 | ||
50 | for_each_cpu_mask(i, mask) | ||
51 | ssmtc_send_ipi_single(i, action); | ||
50 | } | 52 | } |
51 | 53 | ||
52 | /* | 54 | /* |
53 | * Platform "CPU" startup hook | 55 | * Post-config but pre-boot cleanup entry point |
54 | */ | 56 | */ |
55 | 57 | static void __cpuinit ssmtc_init_secondary(void) | |
56 | void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) | ||
57 | { | 58 | { |
58 | #ifdef CONFIG_MIPS_MT_SMTC | 59 | void smtc_init_secondary(void); |
59 | smtc_boot_secondary(cpu, idle); | 60 | |
60 | #endif /* CONFIG_MIPS_MT_SMTC */ | 61 | smtc_init_secondary(); |
61 | } | 62 | } |
62 | 63 | ||
63 | /* | 64 | /* |
64 | * Post-config but pre-boot cleanup entry point | 65 | * SMP initialization finalization entry point |
65 | */ | 66 | */ |
67 | static void __cpuinit ssmtc_smp_finish(void) | ||
68 | { | ||
69 | smtc_smp_finish(); | ||
70 | } | ||
66 | 71 | ||
67 | void __cpuinit prom_init_secondary(void) | 72 | /* |
73 | * Hook for after all CPUs are online | ||
74 | */ | ||
75 | static void ssmtc_cpus_done(void) | ||
68 | { | 76 | { |
69 | #ifdef CONFIG_MIPS_MT_SMTC | 77 | } |
70 | void smtc_init_secondary(void); | ||
71 | 78 | ||
72 | smtc_init_secondary(); | 79 | /* |
73 | #endif /* CONFIG_MIPS_MT_SMTC */ | 80 | * Platform "CPU" startup hook |
81 | */ | ||
82 | static void __cpuinit ssmtc_boot_secondary(int cpu, struct task_struct *idle) | ||
83 | { | ||
84 | smtc_boot_secondary(cpu, idle); | ||
74 | } | 85 | } |
75 | 86 | ||
76 | void plat_smp_setup(void) | 87 | static void __init ssmtc_smp_setup(void) |
77 | { | 88 | { |
78 | #ifdef CONFIG_MIPS_MT_SMTC | ||
79 | if (read_c0_config3() & (1 << 2)) | 89 | if (read_c0_config3() & (1 << 2)) |
80 | mipsmt_build_cpu_map(0); | 90 | mipsmt_build_cpu_map(0); |
81 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
82 | } | 91 | } |
83 | 92 | ||
84 | /* | 93 | /* |
85 | * Platform SMP pre-initialization | 94 | * Platform SMP pre-initialization |
86 | */ | 95 | */ |
87 | 96 | static void ssmtc_prepare_cpus(unsigned int max_cpus) | |
88 | void plat_prepare_cpus(unsigned int max_cpus) | ||
89 | { | 97 | { |
90 | #ifdef CONFIG_MIPS_MT_SMTC | ||
91 | /* | 98 | /* |
92 | * As noted above, we can assume a single CPU for now | 99 | * As noted above, we can assume a single CPU for now |
93 | * but it may be multithreaded. | 100 | * but it may be multithreaded. |
@@ -96,28 +103,15 @@ void plat_prepare_cpus(unsigned int max_cpus) | |||
96 | if (read_c0_config3() & (1 << 2)) { | 103 | if (read_c0_config3() & (1 << 2)) { |
97 | mipsmt_prepare_cpus(); | 104 | mipsmt_prepare_cpus(); |
98 | } | 105 | } |
99 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
100 | } | 106 | } |
101 | 107 | ||
102 | /* | 108 | struct plat_smp_ops ssmtc_smp_ops = { |
103 | * SMP initialization finalization entry point | 109 | .send_ipi_single = ssmtc_send_ipi_single, |
104 | */ | 110 | .send_ipi_mask = ssmtc_send_ipi_mask, |
105 | 111 | .init_secondary = ssmtc_init_secondary, | |
106 | void __cpuinit prom_smp_finish(void) | 112 | .smp_finish = ssmtc_smp_finish, |
107 | { | 113 | .cpus_done = ssmtc_cpus_done, |
108 | #ifdef CONFIG_MIPS_MT_SMTC | 114 | .boot_secondary = ssmtc_boot_secondary, |
109 | smtc_smp_finish(); | 115 | .smp_setup = ssmtc_smp_setup, |
110 | #endif /* CONFIG_MIPS_MT_SMTC */ | 116 | .prepare_cpus = ssmtc_prepare_cpus, |
111 | } | 117 | }; |
112 | |||
113 | /* | ||
114 | * Hook for after all CPUs are online | ||
115 | */ | ||
116 | |||
117 | void prom_cpus_done(void) | ||
118 | { | ||
119 | #ifdef CONFIG_MIPS_MT_SMTC | ||
120 | |||
121 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
122 | } | ||
123 | #endif /* CONFIG_MIPS32R2_MT_SMP */ | ||
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 9355f1c9325f..02bd180f0e02 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c | |||
@@ -449,7 +449,7 @@ static inline void local_r4k_flush_cache_page(void *args) | |||
449 | * If the page isn't marked valid, the page cannot possibly be | 449 | * If the page isn't marked valid, the page cannot possibly be |
450 | * in the cache. | 450 | * in the cache. |
451 | */ | 451 | */ |
452 | if (!(pte_val(*ptep) & _PAGE_PRESENT)) | 452 | if (!(pte_present(*ptep))) |
453 | return; | 453 | return; |
454 | 454 | ||
455 | if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) | 455 | if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) |
@@ -468,8 +468,6 @@ static inline void local_r4k_flush_cache_page(void *args) | |||
468 | 468 | ||
469 | if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { | 469 | if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) { |
470 | r4k_blast_dcache_page(addr); | 470 | r4k_blast_dcache_page(addr); |
471 | if (exec && !cpu_icache_snoops_remote_store) | ||
472 | r4k_blast_scache_page(addr); | ||
473 | } | 471 | } |
474 | if (exec) { | 472 | if (exec) { |
475 | if (vaddr && cpu_has_vtag_icache && mm == current->active_mm) { | 473 | if (vaddr && cpu_has_vtag_icache && mm == current->active_mm) { |
@@ -533,13 +531,6 @@ static inline void local_r4k_flush_icache_range(void *args) | |||
533 | R4600_HIT_CACHEOP_WAR_IMPL; | 531 | R4600_HIT_CACHEOP_WAR_IMPL; |
534 | protected_blast_dcache_range(start, end); | 532 | protected_blast_dcache_range(start, end); |
535 | } | 533 | } |
536 | |||
537 | if (!cpu_icache_snoops_remote_store && scache_size) { | ||
538 | if (end - start > scache_size) | ||
539 | r4k_blast_scache(); | ||
540 | else | ||
541 | protected_blast_scache_range(start, end); | ||
542 | } | ||
543 | } | 534 | } |
544 | 535 | ||
545 | if (end - start > icache_size) | 536 | if (end - start > icache_size) |
@@ -598,7 +589,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) | |||
598 | if (size >= scache_size) | 589 | if (size >= scache_size) |
599 | r4k_blast_scache(); | 590 | r4k_blast_scache(); |
600 | else | 591 | else |
601 | blast_scache_range(addr, addr + size); | 592 | blast_inv_scache_range(addr, addr + size); |
602 | return; | 593 | return; |
603 | } | 594 | } |
604 | 595 | ||
@@ -606,7 +597,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) | |||
606 | r4k_blast_dcache(); | 597 | r4k_blast_dcache(); |
607 | } else { | 598 | } else { |
608 | R4600_HIT_CACHEOP_WAR_IMPL; | 599 | R4600_HIT_CACHEOP_WAR_IMPL; |
609 | blast_dcache_range(addr, addr + size); | 600 | blast_inv_dcache_range(addr, addr + size); |
610 | } | 601 | } |
611 | 602 | ||
612 | bc_inv(addr, size); | 603 | bc_inv(addr, size); |
@@ -989,6 +980,8 @@ static void __init probe_pcache(void) | |||
989 | case CPU_AU1100: | 980 | case CPU_AU1100: |
990 | case CPU_AU1550: | 981 | case CPU_AU1550: |
991 | case CPU_AU1200: | 982 | case CPU_AU1200: |
983 | case CPU_AU1210: | ||
984 | case CPU_AU1250: | ||
992 | c->icache.flags |= MIPS_CACHE_IC_F_DC; | 985 | c->icache.flags |= MIPS_CACHE_IC_F_DC; |
993 | break; | 986 | break; |
994 | } | 987 | } |
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 810535dd091b..ae39dd88b9aa 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c | |||
@@ -383,7 +383,7 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size, | |||
383 | BUG_ON(direction == DMA_NONE); | 383 | BUG_ON(direction == DMA_NONE); |
384 | 384 | ||
385 | if (!plat_device_is_coherent(dev)) | 385 | if (!plat_device_is_coherent(dev)) |
386 | dma_cache_wback_inv((unsigned long)vaddr, size); | 386 | __dma_sync((unsigned long)vaddr, size, direction); |
387 | } | 387 | } |
388 | 388 | ||
389 | EXPORT_SYMBOL(dma_cache_sync); | 389 | EXPORT_SYMBOL(dma_cache_sync); |
diff --git a/arch/mips/mm/pg-r4k.c b/arch/mips/mm/pg-r4k.c index 4f770ac885ce..9185fbf37c0d 100644 --- a/arch/mips/mm/pg-r4k.c +++ b/arch/mips/mm/pg-r4k.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2003, 04, 05 Ralf Baechle (ralf@linux-mips.org) | 6 | * Copyright (C) 2003, 04, 05 Ralf Baechle (ralf@linux-mips.org) |
7 | * Copyright (C) 2007 Maciej W. Rozycki | ||
7 | */ | 8 | */ |
8 | #include <linux/init.h> | 9 | #include <linux/init.h> |
9 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
@@ -12,6 +13,7 @@ | |||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/proc_fs.h> | 14 | #include <linux/proc_fs.h> |
14 | 15 | ||
16 | #include <asm/bugs.h> | ||
15 | #include <asm/cacheops.h> | 17 | #include <asm/cacheops.h> |
16 | #include <asm/inst.h> | 18 | #include <asm/inst.h> |
17 | #include <asm/io.h> | 19 | #include <asm/io.h> |
@@ -255,64 +257,58 @@ static inline void build_store_reg(int reg) | |||
255 | __build_store_reg(reg); | 257 | __build_store_reg(reg); |
256 | } | 258 | } |
257 | 259 | ||
258 | static inline void build_addiu_a2_a0(unsigned long offset) | 260 | static inline void build_addiu_rt_rs(unsigned int rt, unsigned int rs, |
261 | unsigned long offset) | ||
259 | { | 262 | { |
260 | union mips_instruction mi; | 263 | union mips_instruction mi; |
261 | 264 | ||
262 | BUG_ON(offset > 0x7fff); | 265 | BUG_ON(offset > 0x7fff); |
263 | 266 | ||
264 | mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; | 267 | if (cpu_has_64bit_gp_regs && DADDI_WAR && r4k_daddiu_bug()) { |
265 | mi.i_format.rs = 4; /* $a0 */ | 268 | mi.i_format.opcode = addiu_op; |
266 | mi.i_format.rt = 6; /* $a2 */ | 269 | mi.i_format.rs = 0; /* $zero */ |
267 | mi.i_format.simmediate = offset; | 270 | mi.i_format.rt = 25; /* $t9 */ |
271 | mi.i_format.simmediate = offset; | ||
272 | emit_instruction(mi); | ||
268 | 273 | ||
274 | mi.r_format.opcode = spec_op; | ||
275 | mi.r_format.rs = rs; | ||
276 | mi.r_format.rt = 25; /* $t9 */ | ||
277 | mi.r_format.rd = rt; | ||
278 | mi.r_format.re = 0; | ||
279 | mi.r_format.func = daddu_op; | ||
280 | } else { | ||
281 | mi.i_format.opcode = cpu_has_64bit_gp_regs ? | ||
282 | daddiu_op : addiu_op; | ||
283 | mi.i_format.rs = rs; | ||
284 | mi.i_format.rt = rt; | ||
285 | mi.i_format.simmediate = offset; | ||
286 | } | ||
269 | emit_instruction(mi); | 287 | emit_instruction(mi); |
270 | } | 288 | } |
271 | 289 | ||
272 | static inline void build_addiu_a2(unsigned long offset) | 290 | static inline void build_addiu_a2_a0(unsigned long offset) |
273 | { | 291 | { |
274 | union mips_instruction mi; | 292 | build_addiu_rt_rs(6, 4, offset); /* $a2, $a0, offset */ |
275 | 293 | } | |
276 | BUG_ON(offset > 0x7fff); | ||
277 | |||
278 | mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; | ||
279 | mi.i_format.rs = 6; /* $a2 */ | ||
280 | mi.i_format.rt = 6; /* $a2 */ | ||
281 | mi.i_format.simmediate = offset; | ||
282 | 294 | ||
283 | emit_instruction(mi); | 295 | static inline void build_addiu_a2(unsigned long offset) |
296 | { | ||
297 | build_addiu_rt_rs(6, 6, offset); /* $a2, $a2, offset */ | ||
284 | } | 298 | } |
285 | 299 | ||
286 | static inline void build_addiu_a1(unsigned long offset) | 300 | static inline void build_addiu_a1(unsigned long offset) |
287 | { | 301 | { |
288 | union mips_instruction mi; | 302 | build_addiu_rt_rs(5, 5, offset); /* $a1, $a1, offset */ |
289 | |||
290 | BUG_ON(offset > 0x7fff); | ||
291 | |||
292 | mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; | ||
293 | mi.i_format.rs = 5; /* $a1 */ | ||
294 | mi.i_format.rt = 5; /* $a1 */ | ||
295 | mi.i_format.simmediate = offset; | ||
296 | 303 | ||
297 | load_offset -= offset; | 304 | load_offset -= offset; |
298 | |||
299 | emit_instruction(mi); | ||
300 | } | 305 | } |
301 | 306 | ||
302 | static inline void build_addiu_a0(unsigned long offset) | 307 | static inline void build_addiu_a0(unsigned long offset) |
303 | { | 308 | { |
304 | union mips_instruction mi; | 309 | build_addiu_rt_rs(4, 4, offset); /* $a0, $a0, offset */ |
305 | |||
306 | BUG_ON(offset > 0x7fff); | ||
307 | |||
308 | mi.i_format.opcode = cpu_has_64bit_gp_regs ? daddiu_op : addiu_op; | ||
309 | mi.i_format.rs = 4; /* $a0 */ | ||
310 | mi.i_format.rt = 4; /* $a0 */ | ||
311 | mi.i_format.simmediate = offset; | ||
312 | 310 | ||
313 | store_offset -= offset; | 311 | store_offset -= offset; |
314 | |||
315 | emit_instruction(mi); | ||
316 | } | 312 | } |
317 | 313 | ||
318 | static inline void build_bne(unsigned int *dest) | 314 | static inline void build_bne(unsigned int *dest) |
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index a61246d3533d..d026302e0ecc 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Synthesize TLB refill handlers at runtime. | 6 | * Synthesize TLB refill handlers at runtime. |
7 | * | 7 | * |
8 | * Copyright (C) 2004,2005,2006 by Thiemo Seufer | 8 | * Copyright (C) 2004,2005,2006 by Thiemo Seufer |
9 | * Copyright (C) 2005 Maciej W. Rozycki | 9 | * Copyright (C) 2005, 2007 Maciej W. Rozycki |
10 | * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) | 10 | * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) |
11 | * | 11 | * |
12 | * ... and the days got worse and worse and now you see | 12 | * ... and the days got worse and worse and now you see |
@@ -19,20 +19,15 @@ | |||
19 | * (Condolences to Napoleon XIV) | 19 | * (Condolences to Napoleon XIV) |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <stdarg.h> | ||
23 | |||
24 | #include <linux/mm.h> | ||
25 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
26 | #include <linux/types.h> | 23 | #include <linux/types.h> |
27 | #include <linux/string.h> | 24 | #include <linux/string.h> |
28 | #include <linux/init.h> | 25 | #include <linux/init.h> |
29 | 26 | ||
30 | #include <asm/pgtable.h> | 27 | #include <asm/bugs.h> |
31 | #include <asm/cacheflush.h> | ||
32 | #include <asm/mmu_context.h> | 28 | #include <asm/mmu_context.h> |
33 | #include <asm/inst.h> | 29 | #include <asm/inst.h> |
34 | #include <asm/elf.h> | 30 | #include <asm/elf.h> |
35 | #include <asm/smp.h> | ||
36 | #include <asm/war.h> | 31 | #include <asm/war.h> |
37 | 32 | ||
38 | static inline int r45k_bvahwbug(void) | 33 | static inline int r45k_bvahwbug(void) |
@@ -66,7 +61,7 @@ static inline int __maybe_unused r10000_llsc_war(void) | |||
66 | * why; it's not an issue caused by the core RTL. | 61 | * why; it's not an issue caused by the core RTL. |
67 | * | 62 | * |
68 | */ | 63 | */ |
69 | static __init int __attribute__((unused)) m4kc_tlbp_war(void) | 64 | static int __init m4kc_tlbp_war(void) |
70 | { | 65 | { |
71 | return (current_cpu_data.processor_id & 0xffff00) == | 66 | return (current_cpu_data.processor_id & 0xffff00) == |
72 | (PRID_COMP_MIPS | PRID_IMP_4KC); | 67 | (PRID_COMP_MIPS | PRID_IMP_4KC); |
@@ -140,7 +135,7 @@ struct insn { | |||
140 | | (e) << RE_SH \ | 135 | | (e) << RE_SH \ |
141 | | (f) << FUNC_SH) | 136 | | (f) << FUNC_SH) |
142 | 137 | ||
143 | static __initdata struct insn insn_table[] = { | 138 | static struct insn insn_table[] __initdata = { |
144 | { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, | 139 | { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, |
145 | { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD }, | 140 | { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD }, |
146 | { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD }, | 141 | { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD }, |
@@ -193,7 +188,7 @@ static __initdata struct insn insn_table[] = { | |||
193 | 188 | ||
194 | #undef M | 189 | #undef M |
195 | 190 | ||
196 | static __init u32 build_rs(u32 arg) | 191 | static u32 __init build_rs(u32 arg) |
197 | { | 192 | { |
198 | if (arg & ~RS_MASK) | 193 | if (arg & ~RS_MASK) |
199 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); | 194 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); |
@@ -201,7 +196,7 @@ static __init u32 build_rs(u32 arg) | |||
201 | return (arg & RS_MASK) << RS_SH; | 196 | return (arg & RS_MASK) << RS_SH; |
202 | } | 197 | } |
203 | 198 | ||
204 | static __init u32 build_rt(u32 arg) | 199 | static u32 __init build_rt(u32 arg) |
205 | { | 200 | { |
206 | if (arg & ~RT_MASK) | 201 | if (arg & ~RT_MASK) |
207 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); | 202 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); |
@@ -209,7 +204,7 @@ static __init u32 build_rt(u32 arg) | |||
209 | return (arg & RT_MASK) << RT_SH; | 204 | return (arg & RT_MASK) << RT_SH; |
210 | } | 205 | } |
211 | 206 | ||
212 | static __init u32 build_rd(u32 arg) | 207 | static u32 __init build_rd(u32 arg) |
213 | { | 208 | { |
214 | if (arg & ~RD_MASK) | 209 | if (arg & ~RD_MASK) |
215 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); | 210 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); |
@@ -217,7 +212,7 @@ static __init u32 build_rd(u32 arg) | |||
217 | return (arg & RD_MASK) << RD_SH; | 212 | return (arg & RD_MASK) << RD_SH; |
218 | } | 213 | } |
219 | 214 | ||
220 | static __init u32 build_re(u32 arg) | 215 | static u32 __init build_re(u32 arg) |
221 | { | 216 | { |
222 | if (arg & ~RE_MASK) | 217 | if (arg & ~RE_MASK) |
223 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); | 218 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); |
@@ -225,7 +220,7 @@ static __init u32 build_re(u32 arg) | |||
225 | return (arg & RE_MASK) << RE_SH; | 220 | return (arg & RE_MASK) << RE_SH; |
226 | } | 221 | } |
227 | 222 | ||
228 | static __init u32 build_simm(s32 arg) | 223 | static u32 __init build_simm(s32 arg) |
229 | { | 224 | { |
230 | if (arg > 0x7fff || arg < -0x8000) | 225 | if (arg > 0x7fff || arg < -0x8000) |
231 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); | 226 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); |
@@ -233,7 +228,7 @@ static __init u32 build_simm(s32 arg) | |||
233 | return arg & 0xffff; | 228 | return arg & 0xffff; |
234 | } | 229 | } |
235 | 230 | ||
236 | static __init u32 build_uimm(u32 arg) | 231 | static u32 __init build_uimm(u32 arg) |
237 | { | 232 | { |
238 | if (arg & ~IMM_MASK) | 233 | if (arg & ~IMM_MASK) |
239 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); | 234 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); |
@@ -241,7 +236,7 @@ static __init u32 build_uimm(u32 arg) | |||
241 | return arg & IMM_MASK; | 236 | return arg & IMM_MASK; |
242 | } | 237 | } |
243 | 238 | ||
244 | static __init u32 build_bimm(s32 arg) | 239 | static u32 __init build_bimm(s32 arg) |
245 | { | 240 | { |
246 | if (arg > 0x1ffff || arg < -0x20000) | 241 | if (arg > 0x1ffff || arg < -0x20000) |
247 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); | 242 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); |
@@ -252,7 +247,7 @@ static __init u32 build_bimm(s32 arg) | |||
252 | return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff); | 247 | return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff); |
253 | } | 248 | } |
254 | 249 | ||
255 | static __init u32 build_jimm(u32 arg) | 250 | static u32 __init build_jimm(u32 arg) |
256 | { | 251 | { |
257 | if (arg & ~((JIMM_MASK) << 2)) | 252 | if (arg & ~((JIMM_MASK) << 2)) |
258 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); | 253 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); |
@@ -260,7 +255,7 @@ static __init u32 build_jimm(u32 arg) | |||
260 | return (arg >> 2) & JIMM_MASK; | 255 | return (arg >> 2) & JIMM_MASK; |
261 | } | 256 | } |
262 | 257 | ||
263 | static __init u32 build_func(u32 arg) | 258 | static u32 __init build_func(u32 arg) |
264 | { | 259 | { |
265 | if (arg & ~FUNC_MASK) | 260 | if (arg & ~FUNC_MASK) |
266 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); | 261 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); |
@@ -268,7 +263,7 @@ static __init u32 build_func(u32 arg) | |||
268 | return arg & FUNC_MASK; | 263 | return arg & FUNC_MASK; |
269 | } | 264 | } |
270 | 265 | ||
271 | static __init u32 build_set(u32 arg) | 266 | static u32 __init build_set(u32 arg) |
272 | { | 267 | { |
273 | if (arg & ~SET_MASK) | 268 | if (arg & ~SET_MASK) |
274 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); | 269 | printk(KERN_WARNING "TLB synthesizer field overflow\n"); |
@@ -293,7 +288,7 @@ static void __init build_insn(u32 **buf, enum opcode opc, ...) | |||
293 | break; | 288 | break; |
294 | } | 289 | } |
295 | 290 | ||
296 | if (!ip) | 291 | if (!ip || (opc == insn_daddiu && r4k_daddiu_bug())) |
297 | panic("Unsupported TLB synthesizer instruction %d", opc); | 292 | panic("Unsupported TLB synthesizer instruction %d", opc); |
298 | 293 | ||
299 | op = ip->match; | 294 | op = ip->match; |
@@ -315,69 +310,69 @@ static void __init build_insn(u32 **buf, enum opcode opc, ...) | |||
315 | } | 310 | } |
316 | 311 | ||
317 | #define I_u1u2u3(op) \ | 312 | #define I_u1u2u3(op) \ |
318 | static inline void __init i##op(u32 **buf, unsigned int a, \ | 313 | static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \ |
319 | unsigned int b, unsigned int c) \ | 314 | unsigned int b, unsigned int c) \ |
320 | { \ | 315 | { \ |
321 | build_insn(buf, insn##op, a, b, c); \ | 316 | build_insn(buf, insn##op, a, b, c); \ |
322 | } | 317 | } |
323 | 318 | ||
324 | #define I_u2u1u3(op) \ | 319 | #define I_u2u1u3(op) \ |
325 | static inline void __init i##op(u32 **buf, unsigned int a, \ | 320 | static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \ |
326 | unsigned int b, unsigned int c) \ | 321 | unsigned int b, unsigned int c) \ |
327 | { \ | 322 | { \ |
328 | build_insn(buf, insn##op, b, a, c); \ | 323 | build_insn(buf, insn##op, b, a, c); \ |
329 | } | 324 | } |
330 | 325 | ||
331 | #define I_u3u1u2(op) \ | 326 | #define I_u3u1u2(op) \ |
332 | static inline void __init i##op(u32 **buf, unsigned int a, \ | 327 | static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \ |
333 | unsigned int b, unsigned int c) \ | 328 | unsigned int b, unsigned int c) \ |
334 | { \ | 329 | { \ |
335 | build_insn(buf, insn##op, b, c, a); \ | 330 | build_insn(buf, insn##op, b, c, a); \ |
336 | } | 331 | } |
337 | 332 | ||
338 | #define I_u1u2s3(op) \ | 333 | #define I_u1u2s3(op) \ |
339 | static inline void __init i##op(u32 **buf, unsigned int a, \ | 334 | static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \ |
340 | unsigned int b, signed int c) \ | 335 | unsigned int b, signed int c) \ |
341 | { \ | 336 | { \ |
342 | build_insn(buf, insn##op, a, b, c); \ | 337 | build_insn(buf, insn##op, a, b, c); \ |
343 | } | 338 | } |
344 | 339 | ||
345 | #define I_u2s3u1(op) \ | 340 | #define I_u2s3u1(op) \ |
346 | static inline void __init i##op(u32 **buf, unsigned int a, \ | 341 | static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \ |
347 | signed int b, unsigned int c) \ | 342 | signed int b, unsigned int c) \ |
348 | { \ | 343 | { \ |
349 | build_insn(buf, insn##op, c, a, b); \ | 344 | build_insn(buf, insn##op, c, a, b); \ |
350 | } | 345 | } |
351 | 346 | ||
352 | #define I_u2u1s3(op) \ | 347 | #define I_u2u1s3(op) \ |
353 | static inline void __init i##op(u32 **buf, unsigned int a, \ | 348 | static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \ |
354 | unsigned int b, signed int c) \ | 349 | unsigned int b, signed int c) \ |
355 | { \ | 350 | { \ |
356 | build_insn(buf, insn##op, b, a, c); \ | 351 | build_insn(buf, insn##op, b, a, c); \ |
357 | } | 352 | } |
358 | 353 | ||
359 | #define I_u1u2(op) \ | 354 | #define I_u1u2(op) \ |
360 | static inline void __init i##op(u32 **buf, unsigned int a, \ | 355 | static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \ |
361 | unsigned int b) \ | 356 | unsigned int b) \ |
362 | { \ | 357 | { \ |
363 | build_insn(buf, insn##op, a, b); \ | 358 | build_insn(buf, insn##op, a, b); \ |
364 | } | 359 | } |
365 | 360 | ||
366 | #define I_u1s2(op) \ | 361 | #define I_u1s2(op) \ |
367 | static inline void __init i##op(u32 **buf, unsigned int a, \ | 362 | static void __init __maybe_unused i##op(u32 **buf, unsigned int a, \ |
368 | signed int b) \ | 363 | signed int b) \ |
369 | { \ | 364 | { \ |
370 | build_insn(buf, insn##op, a, b); \ | 365 | build_insn(buf, insn##op, a, b); \ |
371 | } | 366 | } |
372 | 367 | ||
373 | #define I_u1(op) \ | 368 | #define I_u1(op) \ |
374 | static inline void __init i##op(u32 **buf, unsigned int a) \ | 369 | static void __init __maybe_unused i##op(u32 **buf, unsigned int a) \ |
375 | { \ | 370 | { \ |
376 | build_insn(buf, insn##op, a); \ | 371 | build_insn(buf, insn##op, a); \ |
377 | } | 372 | } |
378 | 373 | ||
379 | #define I_0(op) \ | 374 | #define I_0(op) \ |
380 | static inline void __init i##op(u32 **buf) \ | 375 | static void __init __maybe_unused i##op(u32 **buf) \ |
381 | { \ | 376 | { \ |
382 | build_insn(buf, insn##op); \ | 377 | build_insn(buf, insn##op); \ |
383 | } | 378 | } |
@@ -457,7 +452,7 @@ struct label { | |||
457 | enum label_id lab; | 452 | enum label_id lab; |
458 | }; | 453 | }; |
459 | 454 | ||
460 | static __init void build_label(struct label **lab, u32 *addr, | 455 | static void __init build_label(struct label **lab, u32 *addr, |
461 | enum label_id l) | 456 | enum label_id l) |
462 | { | 457 | { |
463 | (*lab)->addr = addr; | 458 | (*lab)->addr = addr; |
@@ -466,7 +461,7 @@ static __init void build_label(struct label **lab, u32 *addr, | |||
466 | } | 461 | } |
467 | 462 | ||
468 | #define L_LA(lb) \ | 463 | #define L_LA(lb) \ |
469 | static inline void l##lb(struct label **lab, u32 *addr) \ | 464 | static inline void __init l##lb(struct label **lab, u32 *addr) \ |
470 | { \ | 465 | { \ |
471 | build_label(lab, addr, label##lb); \ | 466 | build_label(lab, addr, label##lb); \ |
472 | } | 467 | } |
@@ -525,37 +520,46 @@ L_LA(_r3000_write_probe_fail) | |||
525 | #define i_ssnop(buf) i_sll(buf, 0, 0, 1) | 520 | #define i_ssnop(buf) i_sll(buf, 0, 0, 1) |
526 | #define i_ehb(buf) i_sll(buf, 0, 0, 3) | 521 | #define i_ehb(buf) i_sll(buf, 0, 0, 3) |
527 | 522 | ||
528 | #ifdef CONFIG_64BIT | 523 | static int __init __maybe_unused in_compat_space_p(long addr) |
529 | static __init int __maybe_unused in_compat_space_p(long addr) | ||
530 | { | 524 | { |
531 | /* Is this address in 32bit compat space? */ | 525 | /* Is this address in 32bit compat space? */ |
526 | #ifdef CONFIG_64BIT | ||
532 | return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L); | 527 | return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L); |
528 | #else | ||
529 | return 1; | ||
530 | #endif | ||
533 | } | 531 | } |
534 | 532 | ||
535 | static __init int __maybe_unused rel_highest(long val) | 533 | static int __init __maybe_unused rel_highest(long val) |
536 | { | 534 | { |
535 | #ifdef CONFIG_64BIT | ||
537 | return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000; | 536 | return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000; |
537 | #else | ||
538 | return 0; | ||
539 | #endif | ||
538 | } | 540 | } |
539 | 541 | ||
540 | static __init int __maybe_unused rel_higher(long val) | 542 | static int __init __maybe_unused rel_higher(long val) |
541 | { | 543 | { |
544 | #ifdef CONFIG_64BIT | ||
542 | return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000; | 545 | return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000; |
543 | } | 546 | #else |
547 | return 0; | ||
544 | #endif | 548 | #endif |
549 | } | ||
545 | 550 | ||
546 | static __init int rel_hi(long val) | 551 | static int __init rel_hi(long val) |
547 | { | 552 | { |
548 | return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000; | 553 | return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000; |
549 | } | 554 | } |
550 | 555 | ||
551 | static __init int rel_lo(long val) | 556 | static int __init rel_lo(long val) |
552 | { | 557 | { |
553 | return ((val & 0xffff) ^ 0x8000) - 0x8000; | 558 | return ((val & 0xffff) ^ 0x8000) - 0x8000; |
554 | } | 559 | } |
555 | 560 | ||
556 | static __init void i_LA_mostly(u32 **buf, unsigned int rs, long addr) | 561 | static void __init i_LA_mostly(u32 **buf, unsigned int rs, long addr) |
557 | { | 562 | { |
558 | #ifdef CONFIG_64BIT | ||
559 | if (!in_compat_space_p(addr)) { | 563 | if (!in_compat_space_p(addr)) { |
560 | i_lui(buf, rs, rel_highest(addr)); | 564 | i_lui(buf, rs, rel_highest(addr)); |
561 | if (rel_higher(addr)) | 565 | if (rel_higher(addr)) |
@@ -567,16 +571,18 @@ static __init void i_LA_mostly(u32 **buf, unsigned int rs, long addr) | |||
567 | } else | 571 | } else |
568 | i_dsll32(buf, rs, rs, 0); | 572 | i_dsll32(buf, rs, rs, 0); |
569 | } else | 573 | } else |
570 | #endif | ||
571 | i_lui(buf, rs, rel_hi(addr)); | 574 | i_lui(buf, rs, rel_hi(addr)); |
572 | } | 575 | } |
573 | 576 | ||
574 | static __init void __maybe_unused i_LA(u32 **buf, unsigned int rs, | 577 | static void __init __maybe_unused i_LA(u32 **buf, unsigned int rs, long addr) |
575 | long addr) | ||
576 | { | 578 | { |
577 | i_LA_mostly(buf, rs, addr); | 579 | i_LA_mostly(buf, rs, addr); |
578 | if (rel_lo(addr)) | 580 | if (rel_lo(addr)) { |
579 | i_ADDIU(buf, rs, rs, rel_lo(addr)); | 581 | if (!in_compat_space_p(addr)) |
582 | i_daddiu(buf, rs, rs, rel_lo(addr)); | ||
583 | else | ||
584 | i_addiu(buf, rs, rs, rel_lo(addr)); | ||
585 | } | ||
580 | } | 586 | } |
581 | 587 | ||
582 | /* | 588 | /* |
@@ -589,7 +595,7 @@ struct reloc { | |||
589 | enum label_id lab; | 595 | enum label_id lab; |
590 | }; | 596 | }; |
591 | 597 | ||
592 | static __init void r_mips_pc16(struct reloc **rel, u32 *addr, | 598 | static void __init r_mips_pc16(struct reloc **rel, u32 *addr, |
593 | enum label_id l) | 599 | enum label_id l) |
594 | { | 600 | { |
595 | (*rel)->addr = addr; | 601 | (*rel)->addr = addr; |
@@ -614,7 +620,7 @@ static inline void __resolve_relocs(struct reloc *rel, struct label *lab) | |||
614 | } | 620 | } |
615 | } | 621 | } |
616 | 622 | ||
617 | static __init void resolve_relocs(struct reloc *rel, struct label *lab) | 623 | static void __init resolve_relocs(struct reloc *rel, struct label *lab) |
618 | { | 624 | { |
619 | struct label *l; | 625 | struct label *l; |
620 | 626 | ||
@@ -624,7 +630,7 @@ static __init void resolve_relocs(struct reloc *rel, struct label *lab) | |||
624 | __resolve_relocs(rel, l); | 630 | __resolve_relocs(rel, l); |
625 | } | 631 | } |
626 | 632 | ||
627 | static __init void move_relocs(struct reloc *rel, u32 *first, u32 *end, | 633 | static void __init move_relocs(struct reloc *rel, u32 *first, u32 *end, |
628 | long off) | 634 | long off) |
629 | { | 635 | { |
630 | for (; rel->lab != label_invalid; rel++) | 636 | for (; rel->lab != label_invalid; rel++) |
@@ -632,7 +638,7 @@ static __init void move_relocs(struct reloc *rel, u32 *first, u32 *end, | |||
632 | rel->addr += off; | 638 | rel->addr += off; |
633 | } | 639 | } |
634 | 640 | ||
635 | static __init void move_labels(struct label *lab, u32 *first, u32 *end, | 641 | static void __init move_labels(struct label *lab, u32 *first, u32 *end, |
636 | long off) | 642 | long off) |
637 | { | 643 | { |
638 | for (; lab->lab != label_invalid; lab++) | 644 | for (; lab->lab != label_invalid; lab++) |
@@ -640,7 +646,7 @@ static __init void move_labels(struct label *lab, u32 *first, u32 *end, | |||
640 | lab->addr += off; | 646 | lab->addr += off; |
641 | } | 647 | } |
642 | 648 | ||
643 | static __init void copy_handler(struct reloc *rel, struct label *lab, | 649 | static void __init copy_handler(struct reloc *rel, struct label *lab, |
644 | u32 *first, u32 *end, u32 *target) | 650 | u32 *first, u32 *end, u32 *target) |
645 | { | 651 | { |
646 | long off = (long)(target - first); | 652 | long off = (long)(target - first); |
@@ -651,7 +657,7 @@ static __init void copy_handler(struct reloc *rel, struct label *lab, | |||
651 | move_labels(lab, first, end, off); | 657 | move_labels(lab, first, end, off); |
652 | } | 658 | } |
653 | 659 | ||
654 | static __init int __maybe_unused insn_has_bdelay(struct reloc *rel, | 660 | static int __init __maybe_unused insn_has_bdelay(struct reloc *rel, |
655 | u32 *addr) | 661 | u32 *addr) |
656 | { | 662 | { |
657 | for (; rel->lab != label_invalid; rel++) { | 663 | for (; rel->lab != label_invalid; rel++) { |
@@ -714,6 +720,22 @@ il_bgez(u32 **p, struct reloc **r, unsigned int reg, enum label_id l) | |||
714 | i_bgez(p, reg, 0); | 720 | i_bgez(p, reg, 0); |
715 | } | 721 | } |
716 | 722 | ||
723 | /* | ||
724 | * For debug purposes. | ||
725 | */ | ||
726 | static inline void dump_handler(const u32 *handler, int count) | ||
727 | { | ||
728 | int i; | ||
729 | |||
730 | pr_debug("\t.set push\n"); | ||
731 | pr_debug("\t.set noreorder\n"); | ||
732 | |||
733 | for (i = 0; i < count; i++) | ||
734 | pr_debug("\t%p\t.word 0x%08x\n", &handler[i], handler[i]); | ||
735 | |||
736 | pr_debug("\t.set pop\n"); | ||
737 | } | ||
738 | |||
717 | /* The only general purpose registers allowed in TLB handlers. */ | 739 | /* The only general purpose registers allowed in TLB handlers. */ |
718 | #define K0 26 | 740 | #define K0 26 |
719 | #define K1 27 | 741 | #define K1 27 |
@@ -743,11 +765,11 @@ il_bgez(u32 **p, struct reloc **r, unsigned int reg, enum label_id l) | |||
743 | * We deliberately chose a buffer size of 128, so we won't scribble | 765 | * We deliberately chose a buffer size of 128, so we won't scribble |
744 | * over anything important on overflow before we panic. | 766 | * over anything important on overflow before we panic. |
745 | */ | 767 | */ |
746 | static __initdata u32 tlb_handler[128]; | 768 | static u32 tlb_handler[128] __initdata; |
747 | 769 | ||
748 | /* simply assume worst case size for labels and relocs */ | 770 | /* simply assume worst case size for labels and relocs */ |
749 | static __initdata struct label labels[128]; | 771 | static struct label labels[128] __initdata; |
750 | static __initdata struct reloc relocs[128]; | 772 | static struct reloc relocs[128] __initdata; |
751 | 773 | ||
752 | /* | 774 | /* |
753 | * The R3000 TLB handler is simple. | 775 | * The R3000 TLB handler is simple. |
@@ -756,7 +778,6 @@ static void __init build_r3000_tlb_refill_handler(void) | |||
756 | { | 778 | { |
757 | long pgdc = (long)pgd_current; | 779 | long pgdc = (long)pgd_current; |
758 | u32 *p; | 780 | u32 *p; |
759 | int i; | ||
760 | 781 | ||
761 | memset(tlb_handler, 0, sizeof(tlb_handler)); | 782 | memset(tlb_handler, 0, sizeof(tlb_handler)); |
762 | p = tlb_handler; | 783 | p = tlb_handler; |
@@ -785,13 +806,9 @@ static void __init build_r3000_tlb_refill_handler(void) | |||
785 | pr_info("Synthesized TLB refill handler (%u instructions).\n", | 806 | pr_info("Synthesized TLB refill handler (%u instructions).\n", |
786 | (unsigned int)(p - tlb_handler)); | 807 | (unsigned int)(p - tlb_handler)); |
787 | 808 | ||
788 | pr_debug("\t.set push\n"); | ||
789 | pr_debug("\t.set noreorder\n"); | ||
790 | for (i = 0; i < (p - tlb_handler); i++) | ||
791 | pr_debug("\t.word 0x%08x\n", tlb_handler[i]); | ||
792 | pr_debug("\t.set pop\n"); | ||
793 | |||
794 | memcpy((void *)ebase, tlb_handler, 0x80); | 809 | memcpy((void *)ebase, tlb_handler, 0x80); |
810 | |||
811 | dump_handler((u32 *)ebase, 32); | ||
795 | } | 812 | } |
796 | 813 | ||
797 | /* | 814 | /* |
@@ -801,7 +818,7 @@ static void __init build_r3000_tlb_refill_handler(void) | |||
801 | * other one.To keep things simple, we first assume linear space, | 818 | * other one.To keep things simple, we first assume linear space, |
802 | * then we relocate it to the final handler layout as needed. | 819 | * then we relocate it to the final handler layout as needed. |
803 | */ | 820 | */ |
804 | static __initdata u32 final_handler[64]; | 821 | static u32 final_handler[64] __initdata; |
805 | 822 | ||
806 | /* | 823 | /* |
807 | * Hazards | 824 | * Hazards |
@@ -825,7 +842,7 @@ static __initdata u32 final_handler[64]; | |||
825 | * | 842 | * |
826 | * As if we MIPS hackers wouldn't know how to nop pipelines happy ... | 843 | * As if we MIPS hackers wouldn't know how to nop pipelines happy ... |
827 | */ | 844 | */ |
828 | static __init void __maybe_unused build_tlb_probe_entry(u32 **p) | 845 | static void __init __maybe_unused build_tlb_probe_entry(u32 **p) |
829 | { | 846 | { |
830 | switch (current_cpu_type()) { | 847 | switch (current_cpu_type()) { |
831 | /* Found by experiment: R4600 v2.0 needs this, too. */ | 848 | /* Found by experiment: R4600 v2.0 needs this, too. */ |
@@ -849,7 +866,7 @@ static __init void __maybe_unused build_tlb_probe_entry(u32 **p) | |||
849 | */ | 866 | */ |
850 | enum tlb_write_entry { tlb_random, tlb_indexed }; | 867 | enum tlb_write_entry { tlb_random, tlb_indexed }; |
851 | 868 | ||
852 | static __init void build_tlb_write_entry(u32 **p, struct label **l, | 869 | static void __init build_tlb_write_entry(u32 **p, struct label **l, |
853 | struct reloc **r, | 870 | struct reloc **r, |
854 | enum tlb_write_entry wmode) | 871 | enum tlb_write_entry wmode) |
855 | { | 872 | { |
@@ -860,6 +877,12 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l, | |||
860 | case tlb_indexed: tlbw = i_tlbwi; break; | 877 | case tlb_indexed: tlbw = i_tlbwi; break; |
861 | } | 878 | } |
862 | 879 | ||
880 | if (cpu_has_mips_r2) { | ||
881 | i_ehb(p); | ||
882 | tlbw(p); | ||
883 | return; | ||
884 | } | ||
885 | |||
863 | switch (current_cpu_type()) { | 886 | switch (current_cpu_type()) { |
864 | case CPU_R4000PC: | 887 | case CPU_R4000PC: |
865 | case CPU_R4000SC: | 888 | case CPU_R4000SC: |
@@ -894,6 +917,8 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l, | |||
894 | case CPU_AU1500: | 917 | case CPU_AU1500: |
895 | case CPU_AU1550: | 918 | case CPU_AU1550: |
896 | case CPU_AU1200: | 919 | case CPU_AU1200: |
920 | case CPU_AU1210: | ||
921 | case CPU_AU1250: | ||
897 | case CPU_PR4450: | 922 | case CPU_PR4450: |
898 | i_nop(p); | 923 | i_nop(p); |
899 | tlbw(p); | 924 | tlbw(p); |
@@ -935,14 +960,6 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l, | |||
935 | tlbw(p); | 960 | tlbw(p); |
936 | break; | 961 | break; |
937 | 962 | ||
938 | case CPU_4KEC: | ||
939 | case CPU_24K: | ||
940 | case CPU_34K: | ||
941 | case CPU_74K: | ||
942 | i_ehb(p); | ||
943 | tlbw(p); | ||
944 | break; | ||
945 | |||
946 | case CPU_RM9000: | 963 | case CPU_RM9000: |
947 | /* | 964 | /* |
948 | * When the JTLB is updated by tlbwi or tlbwr, a subsequent | 965 | * When the JTLB is updated by tlbwi or tlbwr, a subsequent |
@@ -993,7 +1010,7 @@ static __init void build_tlb_write_entry(u32 **p, struct label **l, | |||
993 | * TMP and PTR are scratch. | 1010 | * TMP and PTR are scratch. |
994 | * TMP will be clobbered, PTR will hold the pmd entry. | 1011 | * TMP will be clobbered, PTR will hold the pmd entry. |
995 | */ | 1012 | */ |
996 | static __init void | 1013 | static void __init |
997 | build_get_pmde64(u32 **p, struct label **l, struct reloc **r, | 1014 | build_get_pmde64(u32 **p, struct label **l, struct reloc **r, |
998 | unsigned int tmp, unsigned int ptr) | 1015 | unsigned int tmp, unsigned int ptr) |
999 | { | 1016 | { |
@@ -1054,7 +1071,7 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r, | |||
1054 | * BVADDR is the faulting address, PTR is scratch. | 1071 | * BVADDR is the faulting address, PTR is scratch. |
1055 | * PTR will hold the pgd for vmalloc. | 1072 | * PTR will hold the pgd for vmalloc. |
1056 | */ | 1073 | */ |
1057 | static __init void | 1074 | static void __init |
1058 | build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r, | 1075 | build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r, |
1059 | unsigned int bvaddr, unsigned int ptr) | 1076 | unsigned int bvaddr, unsigned int ptr) |
1060 | { | 1077 | { |
@@ -1087,7 +1104,10 @@ build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r, | |||
1087 | } else { | 1104 | } else { |
1088 | i_LA_mostly(p, ptr, modd); | 1105 | i_LA_mostly(p, ptr, modd); |
1089 | il_b(p, r, label_vmalloc_done); | 1106 | il_b(p, r, label_vmalloc_done); |
1090 | i_daddiu(p, ptr, ptr, rel_lo(modd)); | 1107 | if (in_compat_space_p(modd)) |
1108 | i_addiu(p, ptr, ptr, rel_lo(modd)); | ||
1109 | else | ||
1110 | i_daddiu(p, ptr, ptr, rel_lo(modd)); | ||
1091 | } | 1111 | } |
1092 | 1112 | ||
1093 | l_vmalloc(l, *p); | 1113 | l_vmalloc(l, *p); |
@@ -1108,7 +1128,10 @@ build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r, | |||
1108 | } else { | 1128 | } else { |
1109 | i_LA_mostly(p, ptr, swpd); | 1129 | i_LA_mostly(p, ptr, swpd); |
1110 | il_b(p, r, label_vmalloc_done); | 1130 | il_b(p, r, label_vmalloc_done); |
1111 | i_daddiu(p, ptr, ptr, rel_lo(swpd)); | 1131 | if (in_compat_space_p(swpd)) |
1132 | i_addiu(p, ptr, ptr, rel_lo(swpd)); | ||
1133 | else | ||
1134 | i_daddiu(p, ptr, ptr, rel_lo(swpd)); | ||
1112 | } | 1135 | } |
1113 | } | 1136 | } |
1114 | 1137 | ||
@@ -1118,7 +1141,7 @@ build_get_pgd_vmalloc64(u32 **p, struct label **l, struct reloc **r, | |||
1118 | * TMP and PTR are scratch. | 1141 | * TMP and PTR are scratch. |
1119 | * TMP will be clobbered, PTR will hold the pgd entry. | 1142 | * TMP will be clobbered, PTR will hold the pgd entry. |
1120 | */ | 1143 | */ |
1121 | static __init void __maybe_unused | 1144 | static void __init __maybe_unused |
1122 | build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) | 1145 | build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) |
1123 | { | 1146 | { |
1124 | long pgdc = (long)pgd_current; | 1147 | long pgdc = (long)pgd_current; |
@@ -1153,7 +1176,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) | |||
1153 | 1176 | ||
1154 | #endif /* !CONFIG_64BIT */ | 1177 | #endif /* !CONFIG_64BIT */ |
1155 | 1178 | ||
1156 | static __init void build_adjust_context(u32 **p, unsigned int ctx) | 1179 | static void __init build_adjust_context(u32 **p, unsigned int ctx) |
1157 | { | 1180 | { |
1158 | unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12; | 1181 | unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12; |
1159 | unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); | 1182 | unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); |
@@ -1179,7 +1202,7 @@ static __init void build_adjust_context(u32 **p, unsigned int ctx) | |||
1179 | i_andi(p, ctx, ctx, mask); | 1202 | i_andi(p, ctx, ctx, mask); |
1180 | } | 1203 | } |
1181 | 1204 | ||
1182 | static __init void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) | 1205 | static void __init build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) |
1183 | { | 1206 | { |
1184 | /* | 1207 | /* |
1185 | * Bug workaround for the Nevada. It seems as if under certain | 1208 | * Bug workaround for the Nevada. It seems as if under certain |
@@ -1204,7 +1227,7 @@ static __init void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) | |||
1204 | i_ADDU(p, ptr, ptr, tmp); /* add in offset */ | 1227 | i_ADDU(p, ptr, ptr, tmp); /* add in offset */ |
1205 | } | 1228 | } |
1206 | 1229 | ||
1207 | static __init void build_update_entries(u32 **p, unsigned int tmp, | 1230 | static void __init build_update_entries(u32 **p, unsigned int tmp, |
1208 | unsigned int ptep) | 1231 | unsigned int ptep) |
1209 | { | 1232 | { |
1210 | /* | 1233 | /* |
@@ -1254,7 +1277,6 @@ static void __init build_r4000_tlb_refill_handler(void) | |||
1254 | struct reloc *r = relocs; | 1277 | struct reloc *r = relocs; |
1255 | u32 *f; | 1278 | u32 *f; |
1256 | unsigned int final_len; | 1279 | unsigned int final_len; |
1257 | int i; | ||
1258 | 1280 | ||
1259 | memset(tlb_handler, 0, sizeof(tlb_handler)); | 1281 | memset(tlb_handler, 0, sizeof(tlb_handler)); |
1260 | memset(labels, 0, sizeof(labels)); | 1282 | memset(labels, 0, sizeof(labels)); |
@@ -1356,20 +1378,9 @@ static void __init build_r4000_tlb_refill_handler(void) | |||
1356 | pr_info("Synthesized TLB refill handler (%u instructions).\n", | 1378 | pr_info("Synthesized TLB refill handler (%u instructions).\n", |
1357 | final_len); | 1379 | final_len); |
1358 | 1380 | ||
1359 | f = final_handler; | ||
1360 | #if defined(CONFIG_64BIT) && !defined(CONFIG_CPU_LOONGSON2) | ||
1361 | if (final_len > 32) | ||
1362 | final_len = 64; | ||
1363 | else | ||
1364 | f = final_handler + 32; | ||
1365 | #endif /* CONFIG_64BIT */ | ||
1366 | pr_debug("\t.set push\n"); | ||
1367 | pr_debug("\t.set noreorder\n"); | ||
1368 | for (i = 0; i < final_len; i++) | ||
1369 | pr_debug("\t.word 0x%08x\n", f[i]); | ||
1370 | pr_debug("\t.set pop\n"); | ||
1371 | |||
1372 | memcpy((void *)ebase, final_handler, 0x100); | 1381 | memcpy((void *)ebase, final_handler, 0x100); |
1382 | |||
1383 | dump_handler((u32 *)ebase, 64); | ||
1373 | } | 1384 | } |
1374 | 1385 | ||
1375 | /* | 1386 | /* |
@@ -1381,18 +1392,15 @@ static void __init build_r4000_tlb_refill_handler(void) | |||
1381 | extern void tlb_do_page_fault_0(void); | 1392 | extern void tlb_do_page_fault_0(void); |
1382 | extern void tlb_do_page_fault_1(void); | 1393 | extern void tlb_do_page_fault_1(void); |
1383 | 1394 | ||
1384 | #define __tlb_handler_align \ | ||
1385 | __attribute__((__aligned__(1 << CONFIG_MIPS_L1_CACHE_SHIFT))) | ||
1386 | |||
1387 | /* | 1395 | /* |
1388 | * 128 instructions for the fastpath handler is generous and should | 1396 | * 128 instructions for the fastpath handler is generous and should |
1389 | * never be exceeded. | 1397 | * never be exceeded. |
1390 | */ | 1398 | */ |
1391 | #define FASTPATH_SIZE 128 | 1399 | #define FASTPATH_SIZE 128 |
1392 | 1400 | ||
1393 | u32 __tlb_handler_align handle_tlbl[FASTPATH_SIZE]; | 1401 | u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned; |
1394 | u32 __tlb_handler_align handle_tlbs[FASTPATH_SIZE]; | 1402 | u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned; |
1395 | u32 __tlb_handler_align handle_tlbm[FASTPATH_SIZE]; | 1403 | u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned; |
1396 | 1404 | ||
1397 | static void __init | 1405 | static void __init |
1398 | iPTE_LW(u32 **p, struct label **l, unsigned int pte, unsigned int ptr) | 1406 | iPTE_LW(u32 **p, struct label **l, unsigned int pte, unsigned int ptr) |
@@ -1600,7 +1608,6 @@ static void __init build_r3000_tlb_load_handler(void) | |||
1600 | u32 *p = handle_tlbl; | 1608 | u32 *p = handle_tlbl; |
1601 | struct label *l = labels; | 1609 | struct label *l = labels; |
1602 | struct reloc *r = relocs; | 1610 | struct reloc *r = relocs; |
1603 | int i; | ||
1604 | 1611 | ||
1605 | memset(handle_tlbl, 0, sizeof(handle_tlbl)); | 1612 | memset(handle_tlbl, 0, sizeof(handle_tlbl)); |
1606 | memset(labels, 0, sizeof(labels)); | 1613 | memset(labels, 0, sizeof(labels)); |
@@ -1623,11 +1630,7 @@ static void __init build_r3000_tlb_load_handler(void) | |||
1623 | pr_info("Synthesized TLB load handler fastpath (%u instructions).\n", | 1630 | pr_info("Synthesized TLB load handler fastpath (%u instructions).\n", |
1624 | (unsigned int)(p - handle_tlbl)); | 1631 | (unsigned int)(p - handle_tlbl)); |
1625 | 1632 | ||
1626 | pr_debug("\t.set push\n"); | 1633 | dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); |
1627 | pr_debug("\t.set noreorder\n"); | ||
1628 | for (i = 0; i < (p - handle_tlbl); i++) | ||
1629 | pr_debug("\t.word 0x%08x\n", handle_tlbl[i]); | ||
1630 | pr_debug("\t.set pop\n"); | ||
1631 | } | 1634 | } |
1632 | 1635 | ||
1633 | static void __init build_r3000_tlb_store_handler(void) | 1636 | static void __init build_r3000_tlb_store_handler(void) |
@@ -1635,7 +1638,6 @@ static void __init build_r3000_tlb_store_handler(void) | |||
1635 | u32 *p = handle_tlbs; | 1638 | u32 *p = handle_tlbs; |
1636 | struct label *l = labels; | 1639 | struct label *l = labels; |
1637 | struct reloc *r = relocs; | 1640 | struct reloc *r = relocs; |
1638 | int i; | ||
1639 | 1641 | ||
1640 | memset(handle_tlbs, 0, sizeof(handle_tlbs)); | 1642 | memset(handle_tlbs, 0, sizeof(handle_tlbs)); |
1641 | memset(labels, 0, sizeof(labels)); | 1643 | memset(labels, 0, sizeof(labels)); |
@@ -1658,11 +1660,7 @@ static void __init build_r3000_tlb_store_handler(void) | |||
1658 | pr_info("Synthesized TLB store handler fastpath (%u instructions).\n", | 1660 | pr_info("Synthesized TLB store handler fastpath (%u instructions).\n", |
1659 | (unsigned int)(p - handle_tlbs)); | 1661 | (unsigned int)(p - handle_tlbs)); |
1660 | 1662 | ||
1661 | pr_debug("\t.set push\n"); | 1663 | dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); |
1662 | pr_debug("\t.set noreorder\n"); | ||
1663 | for (i = 0; i < (p - handle_tlbs); i++) | ||
1664 | pr_debug("\t.word 0x%08x\n", handle_tlbs[i]); | ||
1665 | pr_debug("\t.set pop\n"); | ||
1666 | } | 1664 | } |
1667 | 1665 | ||
1668 | static void __init build_r3000_tlb_modify_handler(void) | 1666 | static void __init build_r3000_tlb_modify_handler(void) |
@@ -1670,7 +1668,6 @@ static void __init build_r3000_tlb_modify_handler(void) | |||
1670 | u32 *p = handle_tlbm; | 1668 | u32 *p = handle_tlbm; |
1671 | struct label *l = labels; | 1669 | struct label *l = labels; |
1672 | struct reloc *r = relocs; | 1670 | struct reloc *r = relocs; |
1673 | int i; | ||
1674 | 1671 | ||
1675 | memset(handle_tlbm, 0, sizeof(handle_tlbm)); | 1672 | memset(handle_tlbm, 0, sizeof(handle_tlbm)); |
1676 | memset(labels, 0, sizeof(labels)); | 1673 | memset(labels, 0, sizeof(labels)); |
@@ -1693,11 +1690,7 @@ static void __init build_r3000_tlb_modify_handler(void) | |||
1693 | pr_info("Synthesized TLB modify handler fastpath (%u instructions).\n", | 1690 | pr_info("Synthesized TLB modify handler fastpath (%u instructions).\n", |
1694 | (unsigned int)(p - handle_tlbm)); | 1691 | (unsigned int)(p - handle_tlbm)); |
1695 | 1692 | ||
1696 | pr_debug("\t.set push\n"); | 1693 | dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); |
1697 | pr_debug("\t.set noreorder\n"); | ||
1698 | for (i = 0; i < (p - handle_tlbm); i++) | ||
1699 | pr_debug("\t.word 0x%08x\n", handle_tlbm[i]); | ||
1700 | pr_debug("\t.set pop\n"); | ||
1701 | } | 1694 | } |
1702 | 1695 | ||
1703 | /* | 1696 | /* |
@@ -1750,7 +1743,6 @@ static void __init build_r4000_tlb_load_handler(void) | |||
1750 | u32 *p = handle_tlbl; | 1743 | u32 *p = handle_tlbl; |
1751 | struct label *l = labels; | 1744 | struct label *l = labels; |
1752 | struct reloc *r = relocs; | 1745 | struct reloc *r = relocs; |
1753 | int i; | ||
1754 | 1746 | ||
1755 | memset(handle_tlbl, 0, sizeof(handle_tlbl)); | 1747 | memset(handle_tlbl, 0, sizeof(handle_tlbl)); |
1756 | memset(labels, 0, sizeof(labels)); | 1748 | memset(labels, 0, sizeof(labels)); |
@@ -1783,11 +1775,7 @@ static void __init build_r4000_tlb_load_handler(void) | |||
1783 | pr_info("Synthesized TLB load handler fastpath (%u instructions).\n", | 1775 | pr_info("Synthesized TLB load handler fastpath (%u instructions).\n", |
1784 | (unsigned int)(p - handle_tlbl)); | 1776 | (unsigned int)(p - handle_tlbl)); |
1785 | 1777 | ||
1786 | pr_debug("\t.set push\n"); | 1778 | dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); |
1787 | pr_debug("\t.set noreorder\n"); | ||
1788 | for (i = 0; i < (p - handle_tlbl); i++) | ||
1789 | pr_debug("\t.word 0x%08x\n", handle_tlbl[i]); | ||
1790 | pr_debug("\t.set pop\n"); | ||
1791 | } | 1779 | } |
1792 | 1780 | ||
1793 | static void __init build_r4000_tlb_store_handler(void) | 1781 | static void __init build_r4000_tlb_store_handler(void) |
@@ -1795,7 +1783,6 @@ static void __init build_r4000_tlb_store_handler(void) | |||
1795 | u32 *p = handle_tlbs; | 1783 | u32 *p = handle_tlbs; |
1796 | struct label *l = labels; | 1784 | struct label *l = labels; |
1797 | struct reloc *r = relocs; | 1785 | struct reloc *r = relocs; |
1798 | int i; | ||
1799 | 1786 | ||
1800 | memset(handle_tlbs, 0, sizeof(handle_tlbs)); | 1787 | memset(handle_tlbs, 0, sizeof(handle_tlbs)); |
1801 | memset(labels, 0, sizeof(labels)); | 1788 | memset(labels, 0, sizeof(labels)); |
@@ -1819,11 +1806,7 @@ static void __init build_r4000_tlb_store_handler(void) | |||
1819 | pr_info("Synthesized TLB store handler fastpath (%u instructions).\n", | 1806 | pr_info("Synthesized TLB store handler fastpath (%u instructions).\n", |
1820 | (unsigned int)(p - handle_tlbs)); | 1807 | (unsigned int)(p - handle_tlbs)); |
1821 | 1808 | ||
1822 | pr_debug("\t.set push\n"); | 1809 | dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); |
1823 | pr_debug("\t.set noreorder\n"); | ||
1824 | for (i = 0; i < (p - handle_tlbs); i++) | ||
1825 | pr_debug("\t.word 0x%08x\n", handle_tlbs[i]); | ||
1826 | pr_debug("\t.set pop\n"); | ||
1827 | } | 1810 | } |
1828 | 1811 | ||
1829 | static void __init build_r4000_tlb_modify_handler(void) | 1812 | static void __init build_r4000_tlb_modify_handler(void) |
@@ -1831,7 +1814,6 @@ static void __init build_r4000_tlb_modify_handler(void) | |||
1831 | u32 *p = handle_tlbm; | 1814 | u32 *p = handle_tlbm; |
1832 | struct label *l = labels; | 1815 | struct label *l = labels; |
1833 | struct reloc *r = relocs; | 1816 | struct reloc *r = relocs; |
1834 | int i; | ||
1835 | 1817 | ||
1836 | memset(handle_tlbm, 0, sizeof(handle_tlbm)); | 1818 | memset(handle_tlbm, 0, sizeof(handle_tlbm)); |
1837 | memset(labels, 0, sizeof(labels)); | 1819 | memset(labels, 0, sizeof(labels)); |
@@ -1856,11 +1838,7 @@ static void __init build_r4000_tlb_modify_handler(void) | |||
1856 | pr_info("Synthesized TLB modify handler fastpath (%u instructions).\n", | 1838 | pr_info("Synthesized TLB modify handler fastpath (%u instructions).\n", |
1857 | (unsigned int)(p - handle_tlbm)); | 1839 | (unsigned int)(p - handle_tlbm)); |
1858 | 1840 | ||
1859 | pr_debug("\t.set push\n"); | 1841 | dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); |
1860 | pr_debug("\t.set noreorder\n"); | ||
1861 | for (i = 0; i < (p - handle_tlbm); i++) | ||
1862 | pr_debug("\t.word 0x%08x\n", handle_tlbm[i]); | ||
1863 | pr_debug("\t.set pop\n"); | ||
1864 | } | 1842 | } |
1865 | 1843 | ||
1866 | void __init build_tlb_refill_handler(void) | 1844 | void __init build_tlb_refill_handler(void) |
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c index bdfa07aecd97..ccbea229a0e6 100644 --- a/arch/mips/oprofile/op_model_mipsxx.c +++ b/arch/mips/oprofile/op_model_mipsxx.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #define M_PERFCTL_SUPERVISOR (1UL << 2) | 19 | #define M_PERFCTL_SUPERVISOR (1UL << 2) |
20 | #define M_PERFCTL_USER (1UL << 3) | 20 | #define M_PERFCTL_USER (1UL << 3) |
21 | #define M_PERFCTL_INTERRUPT_ENABLE (1UL << 4) | 21 | #define M_PERFCTL_INTERRUPT_ENABLE (1UL << 4) |
22 | #define M_PERFCTL_EVENT(event) (((event) & 0x3f) << 5) | 22 | #define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5) |
23 | #define M_PERFCTL_VPEID(vpe) ((vpe) << 16) | 23 | #define M_PERFCTL_VPEID(vpe) ((vpe) << 16) |
24 | #define M_PERFCTL_MT_EN(filter) ((filter) << 20) | 24 | #define M_PERFCTL_MT_EN(filter) ((filter) << 20) |
25 | #define M_TC_EN_ALL M_PERFCTL_MT_EN(0) | 25 | #define M_TC_EN_ALL M_PERFCTL_MT_EN(0) |
diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c index 47f316c86ab1..30ed36125bcd 100644 --- a/arch/mips/pci/pci-bcm1480.c +++ b/arch/mips/pci/pci-bcm1480.c | |||
@@ -178,8 +178,8 @@ struct pci_ops bcm1480_pci_ops = { | |||
178 | 178 | ||
179 | static struct resource bcm1480_mem_resource = { | 179 | static struct resource bcm1480_mem_resource = { |
180 | .name = "BCM1480 PCI MEM", | 180 | .name = "BCM1480 PCI MEM", |
181 | .start = 0x30000000UL, | 181 | .start = A_BCM1480_PHYS_PCI_MEM_MATCH_BYTES, |
182 | .end = 0x3fffffffUL, | 182 | .end = A_BCM1480_PHYS_PCI_MEM_MATCH_BYTES + 0xfffffffUL, |
183 | .flags = IORESOURCE_MEM, | 183 | .flags = IORESOURCE_MEM, |
184 | }; | 184 | }; |
185 | 185 | ||
diff --git a/arch/mips/pci/pci-bcm1480ht.c b/arch/mips/pci/pci-bcm1480ht.c index a63e3bd6b0ac..005e7fecab08 100644 --- a/arch/mips/pci/pci-bcm1480ht.c +++ b/arch/mips/pci/pci-bcm1480ht.c | |||
@@ -173,8 +173,8 @@ struct pci_ops bcm1480ht_pci_ops = { | |||
173 | 173 | ||
174 | static struct resource bcm1480ht_mem_resource = { | 174 | static struct resource bcm1480ht_mem_resource = { |
175 | .name = "BCM1480 HT MEM", | 175 | .name = "BCM1480 HT MEM", |
176 | .start = 0x40000000UL, | 176 | .start = A_BCM1480_PHYS_HT_MEM_MATCH_BYTES, |
177 | .end = 0x5fffffffUL, | 177 | .end = A_BCM1480_PHYS_HT_MEM_MATCH_BYTES + 0x1fffffffUL, |
178 | .flags = IORESOURCE_MEM, | 178 | .flags = IORESOURCE_MEM, |
179 | }; | 179 | }; |
180 | 180 | ||
diff --git a/arch/mips/philips/pnx8550/common/setup.c b/arch/mips/philips/pnx8550/common/setup.c index 2ce298f4d19a..92d764c97701 100644 --- a/arch/mips/philips/pnx8550/common/setup.c +++ b/arch/mips/philips/pnx8550/common/setup.c | |||
@@ -74,7 +74,7 @@ struct resource standard_io_resources[] = { | |||
74 | }, | 74 | }, |
75 | }; | 75 | }; |
76 | 76 | ||
77 | #define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource)) | 77 | #define STANDARD_IO_RESOURCES ARRAY_SIZE(standard_io_resources) |
78 | 78 | ||
79 | extern struct resource pci_io_resource; | 79 | extern struct resource pci_io_resource; |
80 | extern struct resource pci_mem_resource; | 80 | extern struct resource pci_mem_resource; |
diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c index 6d494e0de3d9..62f495b57f93 100644 --- a/arch/mips/philips/pnx8550/common/time.c +++ b/arch/mips/philips/pnx8550/common/time.c | |||
@@ -47,11 +47,6 @@ static struct clocksource pnx_clocksource = { | |||
47 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 47 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
48 | }; | 48 | }; |
49 | 49 | ||
50 | static void timer_ack(void) | ||
51 | { | ||
52 | write_c0_compare(cpj); | ||
53 | } | ||
54 | |||
55 | static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id) | 50 | static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id) |
56 | { | 51 | { |
57 | struct clock_event_device *c = dev_id; | 52 | struct clock_event_device *c = dev_id; |
@@ -94,30 +89,22 @@ static struct clock_event_device pnx8xxx_clockevent = { | |||
94 | .set_next_event = pnx8xxx_set_next_event, | 89 | .set_next_event = pnx8xxx_set_next_event, |
95 | }; | 90 | }; |
96 | 91 | ||
97 | /* | 92 | static inline void timer_ack(void) |
98 | * plat_time_init() - it does the following things: | 93 | { |
99 | * | 94 | write_c0_compare(cpj); |
100 | * 1) plat_time_init() - | 95 | } |
101 | * a) (optional) set up RTC routines, | ||
102 | * b) (optional) calibrate and set the mips_hpt_frequency | ||
103 | * (only needed if you intended to use cpu counter as timer interrupt | ||
104 | * source) | ||
105 | */ | ||
106 | 96 | ||
107 | __init void plat_time_init(void) | 97 | __init void plat_time_init(void) |
108 | { | 98 | { |
109 | unsigned int configPR; | 99 | unsigned int configPR; |
110 | unsigned int n; | 100 | unsigned int n; |
111 | unsigned int m; | 101 | unsigned int m; |
112 | unsigned int p; | 102 | unsigned int p; |
113 | unsigned int pow2p; | 103 | unsigned int pow2p; |
114 | 104 | ||
115 | clockevents_register_device(&pnx8xxx_clockevent); | 105 | clockevents_register_device(&pnx8xxx_clockevent); |
116 | clocksource_register(&pnx_clocksource); | 106 | clocksource_register(&pnx_clocksource); |
117 | 107 | ||
118 | setup_irq(PNX8550_INT_TIMER1, &pnx8xxx_timer_irq); | ||
119 | setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction); | ||
120 | |||
121 | /* Timer 1 start */ | 108 | /* Timer 1 start */ |
122 | configPR = read_c0_config7(); | 109 | configPR = read_c0_config7(); |
123 | configPR &= ~0x00000008; | 110 | configPR &= ~0x00000008; |
@@ -158,6 +145,6 @@ __init void plat_time_init(void) | |||
158 | write_c0_count2(0); | 145 | write_c0_count2(0); |
159 | write_c0_compare2(0xffffffff); | 146 | write_c0_compare2(0xffffffff); |
160 | 147 | ||
148 | setup_irq(PNX8550_INT_TIMER1, &pnx8xxx_timer_irq); | ||
149 | setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction); | ||
161 | } | 150 | } |
162 | |||
163 | |||
diff --git a/arch/mips/philips/pnx8550/jbs/init.c b/arch/mips/philips/pnx8550/jbs/init.c index cfd90fa3d799..90b4d35f3ece 100644 --- a/arch/mips/philips/pnx8550/jbs/init.c +++ b/arch/mips/philips/pnx8550/jbs/init.c | |||
@@ -45,11 +45,8 @@ const char *get_system_type(void) | |||
45 | 45 | ||
46 | void __init prom_init(void) | 46 | void __init prom_init(void) |
47 | { | 47 | { |
48 | |||
49 | unsigned long memsize; | 48 | unsigned long memsize; |
50 | 49 | ||
51 | mips_machtype = MACH_PHILIPS_JBS; | ||
52 | |||
53 | //memsize = 0x02800000; /* Trimedia uses memory above */ | 50 | //memsize = 0x02800000; /* Trimedia uses memory above */ |
54 | memsize = 0x08000000; /* Trimedia uses memory above */ | 51 | memsize = 0x08000000; /* Trimedia uses memory above */ |
55 | add_memory_region(0, memsize, BOOT_MEM_RAM); | 52 | add_memory_region(0, memsize, BOOT_MEM_RAM); |
diff --git a/arch/mips/philips/pnx8550/stb810/prom_init.c b/arch/mips/philips/pnx8550/stb810/prom_init.c index fdb33ed089b9..832dd60b0a7a 100644 --- a/arch/mips/philips/pnx8550/stb810/prom_init.c +++ b/arch/mips/philips/pnx8550/stb810/prom_init.c | |||
@@ -41,8 +41,6 @@ void __init prom_init(void) | |||
41 | 41 | ||
42 | prom_init_cmdline(); | 42 | prom_init_cmdline(); |
43 | 43 | ||
44 | mips_machtype = MACH_PHILIPS_STB810; | ||
45 | |||
46 | memsize = 0x08000000; /* Trimedia uses memory above */ | 44 | memsize = 0x08000000; /* Trimedia uses memory above */ |
47 | add_memory_region(0, memsize, BOOT_MEM_RAM); | 45 | add_memory_region(0, memsize, BOOT_MEM_RAM); |
48 | } | 46 | } |
diff --git a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h b/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h deleted file mode 100644 index 31c5523276fa..000000000000 --- a/arch/mips/pmc-sierra/yosemite/i2c-yosemite.h +++ /dev/null | |||
@@ -1,96 +0,0 @@ | |||
1 | /* | ||
2 | * arch/mips/pmc-sierra/yosemite/i2c-yosemite.h | ||
3 | * | ||
4 | * Copyright (C) 2003 PMC-Sierra Inc. | ||
5 | * Author: Manish Lachwani (lachwani@pmc-sierra.com) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
13 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
14 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
15 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
16 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
17 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
18 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
19 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
20 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
21 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License along | ||
24 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
25 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __I2C_YOSEMITE_H | ||
29 | #define __I2C_YOSEMITE_H | ||
30 | |||
31 | /* Read and Write operations to the chip */ | ||
32 | |||
33 | #define TITAN_I2C_BASE 0xbb000000 /* XXX Needs to change */ | ||
34 | |||
35 | #define TITAN_I2C_WRITE(offset, data) \ | ||
36 | *(volatile unsigned long *)(TITAN_I2C_BASE + offset) = data | ||
37 | |||
38 | #define TITAN_I2C_READ(offset) *(volatile unsigned long *)(TITAN_I2C_BASE + offset) | ||
39 | |||
40 | |||
41 | /* Local constansts*/ | ||
42 | #define TITAN_I2C_MAX_FILTER 15 | ||
43 | #define TITAN_I2C_MAX_CLK 1023 | ||
44 | #define TITAN_I2C_MAX_ARBF 15 | ||
45 | #define TITAN_I2C_MAX_NAK 15 | ||
46 | #define TITAN_I2C_MAX_MASTERCODE 7 | ||
47 | #define TITAN_I2C_MAX_WORDS_PER_RW 4 | ||
48 | #define TITAN_I2C_MAX_POLL 100 | ||
49 | |||
50 | /* Registers used for I2C work */ | ||
51 | #define TITAN_I2C_SCMB_CONTROL 0x0180 /* SCMB Control */ | ||
52 | #define TITAN_I2C_SCMB_CLOCK_A 0x0184 /* SCMB Clock A */ | ||
53 | #define TITAN_I2C_SCMB_CLOCK_B 0x0188 /* SCMB Clock B */ | ||
54 | #define TITAN_I2C_CONFIG 0x01A0 /* I2C Config */ | ||
55 | #define TITAN_I2C_COMMAND 0x01A4 /* I2C Command */ | ||
56 | #define TITAN_I2C_SLAVE_ADDRESS 0x01A8 /* I2C Slave Address */ | ||
57 | #define TITAN_I2C_DATA 0x01AC /* I2C Data [15:0] */ | ||
58 | #define TITAN_I2C_INTERRUPTS 0x01BC /* I2C Interrupts */ | ||
59 | |||
60 | /* Error */ | ||
61 | #define TITAN_I2C_ERR_ARB_LOST (-9220) | ||
62 | #define TITAN_I2C_ERR_NO_RESP (-9221) | ||
63 | #define TITAN_I2C_ERR_DATA_COLLISION (-9222) | ||
64 | #define TITAN_I2C_ERR_TIMEOUT (-9223) | ||
65 | #define TITAN_I2C_ERR_OK 0 | ||
66 | |||
67 | /* I2C Command Type */ | ||
68 | typedef enum { | ||
69 | TITAN_I2C_CMD_WRITE = 0, | ||
70 | TITAN_I2C_CMD_READ = 1, | ||
71 | TITAN_I2C_CMD_READ_WRITE = 2 | ||
72 | } titan_i2c_cmd_type; | ||
73 | |||
74 | /* I2C structures */ | ||
75 | typedef struct { | ||
76 | int filtera; /* Register 0x0184, bits 15 - 12 */ | ||
77 | int clka; /* Register 0x0184, bits 9 - 0 */ | ||
78 | int filterb; /* Register 0x0188, bits 15 - 12 */ | ||
79 | int clkb; /* Register 0x0188, bits 9 - 0 */ | ||
80 | } titan_i2c_config; | ||
81 | |||
82 | /* I2C command type */ | ||
83 | typedef struct { | ||
84 | titan_i2c_cmd_type type; /* Type of command */ | ||
85 | int num_arb; /* Register 0x01a0, bits 15 - 12 */ | ||
86 | int num_nak; /* Register 0x01a0, bits 11 - 8 */ | ||
87 | int addr_size; /* Register 0x01a0, bit 7 */ | ||
88 | int mst_code; /* Register 0x01a0, bits 6 - 4 */ | ||
89 | int arb_en; /* Register 0x01a0, bit 1 */ | ||
90 | int speed; /* Register 0x01a0, bit 0 */ | ||
91 | int slave_addr; /* Register 0x01a8 */ | ||
92 | int write_size; /* Register 0x01a4, bits 10 - 8 */ | ||
93 | unsigned int *data; /* Register 0x01ac */ | ||
94 | } titan_i2c_command; | ||
95 | |||
96 | #endif /* __I2C_YOSEMITE_H */ | ||
diff --git a/arch/mips/pmc-sierra/yosemite/prom.c b/arch/mips/pmc-sierra/yosemite/prom.c index 9b9936de6589..35dc435846a6 100644 --- a/arch/mips/pmc-sierra/yosemite/prom.c +++ b/arch/mips/pmc-sierra/yosemite/prom.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/pgtable.h> | 19 | #include <asm/pgtable.h> |
20 | #include <asm/processor.h> | 20 | #include <asm/processor.h> |
21 | #include <asm/reboot.h> | 21 | #include <asm/reboot.h> |
22 | #include <asm/smp-ops.h> | ||
22 | #include <asm/system.h> | 23 | #include <asm/system.h> |
23 | #include <asm/bootinfo.h> | 24 | #include <asm/bootinfo.h> |
24 | #include <asm/pmon.h> | 25 | #include <asm/pmon.h> |
@@ -78,6 +79,8 @@ static void prom_halt(void) | |||
78 | __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0"); | 79 | __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0"); |
79 | } | 80 | } |
80 | 81 | ||
82 | extern struct plat_smp_ops yos_smp_ops; | ||
83 | |||
81 | /* | 84 | /* |
82 | * Init routine which accepts the variables from PMON | 85 | * Init routine which accepts the variables from PMON |
83 | */ | 86 | */ |
@@ -126,9 +129,9 @@ void __init prom_init(void) | |||
126 | env++; | 129 | env++; |
127 | } | 130 | } |
128 | 131 | ||
129 | mips_machtype = MACH_TITAN_YOSEMITE; | ||
130 | |||
131 | prom_grab_secondary(); | 132 | prom_grab_secondary(); |
133 | |||
134 | register_smp_ops(&yos_smp_ops); | ||
132 | } | 135 | } |
133 | 136 | ||
134 | void __init prom_free_prom_memory(void) | 137 | void __init prom_free_prom_memory(void) |
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index b0f12cd2968a..653f3ec61cab 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c | |||
@@ -42,70 +42,6 @@ void __init prom_grab_secondary(void) | |||
42 | launchstack + LAUNCHSTACK_SIZE, 0); | 42 | launchstack + LAUNCHSTACK_SIZE, 0); |
43 | } | 43 | } |
44 | 44 | ||
45 | /* | ||
46 | * Detect available CPUs, populate phys_cpu_present_map before smp_init | ||
47 | * | ||
48 | * We don't want to start the secondary CPU yet nor do we have a nice probing | ||
49 | * feature in PMON so we just assume presence of the secondary core. | ||
50 | */ | ||
51 | void __init plat_smp_setup(void) | ||
52 | { | ||
53 | int i; | ||
54 | |||
55 | cpus_clear(phys_cpu_present_map); | ||
56 | |||
57 | for (i = 0; i < 2; i++) { | ||
58 | cpu_set(i, phys_cpu_present_map); | ||
59 | __cpu_number_map[i] = i; | ||
60 | __cpu_logical_map[i] = i; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | void __init plat_prepare_cpus(unsigned int max_cpus) | ||
65 | { | ||
66 | /* | ||
67 | * Be paranoid. Enable the IPI only if we're really about to go SMP. | ||
68 | */ | ||
69 | if (cpus_weight(cpu_possible_map)) | ||
70 | set_c0_status(STATUSF_IP5); | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Firmware CPU startup hook | ||
75 | * Complicated by PMON's weird interface which tries to minimic the UNIX fork. | ||
76 | * It launches the next * available CPU and copies some information on the | ||
77 | * stack so the first thing we do is throw away that stuff and load useful | ||
78 | * values into the registers ... | ||
79 | */ | ||
80 | void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) | ||
81 | { | ||
82 | unsigned long gp = (unsigned long) task_thread_info(idle); | ||
83 | unsigned long sp = __KSTK_TOS(idle); | ||
84 | |||
85 | secondary_sp = sp; | ||
86 | secondary_gp = gp; | ||
87 | |||
88 | spin_unlock(&launch_lock); | ||
89 | } | ||
90 | |||
91 | /* Hook for after all CPUs are online */ | ||
92 | void prom_cpus_done(void) | ||
93 | { | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * After we've done initial boot, this function is called to allow the | ||
98 | * board code to clean up state, if needed | ||
99 | */ | ||
100 | void __cpuinit prom_init_secondary(void) | ||
101 | { | ||
102 | set_c0_status(ST0_CO | ST0_IE | ST0_IM); | ||
103 | } | ||
104 | |||
105 | void __cpuinit prom_smp_finish(void) | ||
106 | { | ||
107 | } | ||
108 | |||
109 | void titan_mailbox_irq(void) | 45 | void titan_mailbox_irq(void) |
110 | { | 46 | { |
111 | int cpu = smp_processor_id(); | 47 | int cpu = smp_processor_id(); |
@@ -133,7 +69,7 @@ void titan_mailbox_irq(void) | |||
133 | /* | 69 | /* |
134 | * Send inter-processor interrupt | 70 | * Send inter-processor interrupt |
135 | */ | 71 | */ |
136 | void core_send_ipi(int cpu, unsigned int action) | 72 | static void yos_send_ipi_single(int cpu, unsigned int action) |
137 | { | 73 | { |
138 | /* | 74 | /* |
139 | * Generate an INTMSG so that it can be sent over to the | 75 | * Generate an INTMSG so that it can be sent over to the |
@@ -159,3 +95,86 @@ void core_send_ipi(int cpu, unsigned int action) | |||
159 | break; | 95 | break; |
160 | } | 96 | } |
161 | } | 97 | } |
98 | |||
99 | static void yos_send_ipi_mask(cpumask_t mask, unsigned int action) | ||
100 | { | ||
101 | unsigned int i; | ||
102 | |||
103 | for_each_cpu_mask(i, mask) | ||
104 | yos_send_ipi_single(i, action); | ||
105 | } | ||
106 | |||
107 | /* | ||
108 | * After we've done initial boot, this function is called to allow the | ||
109 | * board code to clean up state, if needed | ||
110 | */ | ||
111 | static void __cpuinit yos_init_secondary(void) | ||
112 | { | ||
113 | set_c0_status(ST0_CO | ST0_IE | ST0_IM); | ||
114 | } | ||
115 | |||
116 | static void __cpuinit yos_smp_finish(void) | ||
117 | { | ||
118 | } | ||
119 | |||
120 | /* Hook for after all CPUs are online */ | ||
121 | static void yos_cpus_done(void) | ||
122 | { | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * Firmware CPU startup hook | ||
127 | * Complicated by PMON's weird interface which tries to minimic the UNIX fork. | ||
128 | * It launches the next * available CPU and copies some information on the | ||
129 | * stack so the first thing we do is throw away that stuff and load useful | ||
130 | * values into the registers ... | ||
131 | */ | ||
132 | static void __cpuinit yos_boot_secondary(int cpu, struct task_struct *idle) | ||
133 | { | ||
134 | unsigned long gp = (unsigned long) task_thread_info(idle); | ||
135 | unsigned long sp = __KSTK_TOS(idle); | ||
136 | |||
137 | secondary_sp = sp; | ||
138 | secondary_gp = gp; | ||
139 | |||
140 | spin_unlock(&launch_lock); | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * Detect available CPUs, populate phys_cpu_present_map before smp_init | ||
145 | * | ||
146 | * We don't want to start the secondary CPU yet nor do we have a nice probing | ||
147 | * feature in PMON so we just assume presence of the secondary core. | ||
148 | */ | ||
149 | static void __init yos_smp_setup(void) | ||
150 | { | ||
151 | int i; | ||
152 | |||
153 | cpus_clear(phys_cpu_present_map); | ||
154 | |||
155 | for (i = 0; i < 2; i++) { | ||
156 | cpu_set(i, phys_cpu_present_map); | ||
157 | __cpu_number_map[i] = i; | ||
158 | __cpu_logical_map[i] = i; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static void __init yos_prepare_cpus(unsigned int max_cpus) | ||
163 | { | ||
164 | /* | ||
165 | * Be paranoid. Enable the IPI only if we're really about to go SMP. | ||
166 | */ | ||
167 | if (cpus_weight(cpu_possible_map)) | ||
168 | set_c0_status(STATUSF_IP5); | ||
169 | } | ||
170 | |||
171 | struct plat_smp_ops yos_smp_ops = { | ||
172 | .send_ipi_single = yos_send_ipi_single, | ||
173 | .send_ipi_mask = yos_send_ipi_mask, | ||
174 | .init_secondary = yos_init_secondary, | ||
175 | .smp_finish = yos_smp_finish, | ||
176 | .cpus_done = yos_cpus_done, | ||
177 | .boot_secondary = yos_boot_secondary, | ||
178 | .smp_setup = yos_smp_setup, | ||
179 | .prepare_cpus = yos_prepare_cpus, | ||
180 | }; | ||
diff --git a/arch/mips/qemu/Makefile b/arch/mips/qemu/Makefile deleted file mode 100644 index 2ba4ef34b4a7..000000000000 --- a/arch/mips/qemu/Makefile +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for Qemu specific kernel interface routines under Linux. | ||
3 | # | ||
4 | |||
5 | obj-y = q-firmware.o q-irq.o q-mem.o q-setup.o q-reset.o | ||
6 | |||
7 | obj-$(CONFIG_EARLY_PRINTK) += q-console.o | ||
8 | obj-$(CONFIG_SMP) += q-smp.o | ||
9 | |||
10 | EXTRA_CFLAGS += -Werror | ||
diff --git a/arch/mips/qemu/q-console.c b/arch/mips/qemu/q-console.c deleted file mode 100644 index 81101ae5017a..000000000000 --- a/arch/mips/qemu/q-console.c +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | #include <linux/console.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <linux/serial_reg.h> | ||
4 | #include <asm/io.h> | ||
5 | |||
6 | #define PORT(offset) (0x3f8 + (offset)) | ||
7 | |||
8 | static inline unsigned int serial_in(int offset) | ||
9 | { | ||
10 | return inb(PORT(offset)); | ||
11 | } | ||
12 | |||
13 | static inline void serial_out(int offset, int value) | ||
14 | { | ||
15 | outb(value, PORT(offset)); | ||
16 | } | ||
17 | |||
18 | int prom_putchar(char c) | ||
19 | { | ||
20 | while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0) | ||
21 | ; | ||
22 | |||
23 | serial_out(UART_TX, c); | ||
24 | |||
25 | return 1; | ||
26 | } | ||
diff --git a/arch/mips/qemu/q-firmware.c b/arch/mips/qemu/q-firmware.c deleted file mode 100644 index 3ed43f416cd1..000000000000 --- a/arch/mips/qemu/q-firmware.c +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/string.h> | ||
3 | #include <asm/addrspace.h> | ||
4 | #include <asm/bootinfo.h> | ||
5 | #include <asm/io.h> | ||
6 | |||
7 | #define QEMU_PORT_BASE 0xb4000000 | ||
8 | |||
9 | void __init prom_init(void) | ||
10 | { | ||
11 | int *cmdline; | ||
12 | |||
13 | cmdline = (int *) (CKSEG0 + (0x10 << 20) - 260); | ||
14 | if (*cmdline == 0x12345678) { | ||
15 | if (*(char *)(cmdline + 1)) | ||
16 | strcpy(arcs_cmdline, (char *)(cmdline + 1)); | ||
17 | add_memory_region(0x0<<20, cmdline[-1], BOOT_MEM_RAM); | ||
18 | } else { | ||
19 | add_memory_region(0x0<<20, 0x10<<20, BOOT_MEM_RAM); | ||
20 | } | ||
21 | |||
22 | |||
23 | set_io_port_base(QEMU_PORT_BASE); | ||
24 | } | ||
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c deleted file mode 100644 index 7df36dbe65c7..000000000000 --- a/arch/mips/qemu/q-irq.c +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | #include <linux/init.h> | ||
2 | #include <linux/interrupt.h> | ||
3 | #include <linux/linkage.h> | ||
4 | |||
5 | #include <asm/i8259.h> | ||
6 | #include <asm/irq_cpu.h> | ||
7 | #include <asm/mipsregs.h> | ||
8 | #include <asm/qemu.h> | ||
9 | #include <asm/system.h> | ||
10 | #include <asm/time.h> | ||
11 | |||
12 | asmlinkage void plat_irq_dispatch(void) | ||
13 | { | ||
14 | unsigned int pending = read_c0_status() & read_c0_cause(); | ||
15 | |||
16 | if (pending & 0x8000) { | ||
17 | do_IRQ(Q_COUNT_COMPARE_IRQ); | ||
18 | return; | ||
19 | } | ||
20 | if (pending & 0x0400) { | ||
21 | int irq = i8259_irq(); | ||
22 | |||
23 | if (likely(irq >= 0)) | ||
24 | do_IRQ(irq); | ||
25 | |||
26 | return; | ||
27 | } | ||
28 | } | ||
29 | |||
30 | void __init arch_init_irq(void) | ||
31 | { | ||
32 | mips_hpt_frequency = QEMU_C0_COUNTER_CLOCK; /* 100MHz */ | ||
33 | |||
34 | mips_cpu_irq_init(); | ||
35 | init_i8259_irqs(); | ||
36 | set_c0_status(0x400); | ||
37 | } | ||
diff --git a/arch/mips/qemu/q-mem.c b/arch/mips/qemu/q-mem.c deleted file mode 100644 index dae39b59de15..000000000000 --- a/arch/mips/qemu/q-mem.c +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | #include <linux/init.h> | ||
2 | |||
3 | void __init prom_free_prom_memory(void) | ||
4 | { | ||
5 | } | ||
diff --git a/arch/mips/qemu/q-reset.c b/arch/mips/qemu/q-reset.c deleted file mode 100644 index dbbe44ad7e89..000000000000 --- a/arch/mips/qemu/q-reset.c +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | |||
2 | #include <asm/io.h> | ||
3 | #include <asm/reboot.h> | ||
4 | #include <asm/cacheflush.h> | ||
5 | #include <asm/qemu.h> | ||
6 | |||
7 | static void qemu_machine_restart(char *command) | ||
8 | { | ||
9 | volatile unsigned int *reg = (unsigned int *)QEMU_RESTART_REG; | ||
10 | |||
11 | set_c0_status(ST0_BEV | ST0_ERL); | ||
12 | change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); | ||
13 | flush_cache_all(); | ||
14 | write_c0_wired(0); | ||
15 | *reg = 42; | ||
16 | while (1) | ||
17 | cpu_wait(); | ||
18 | } | ||
19 | |||
20 | static void qemu_machine_halt(void) | ||
21 | { | ||
22 | volatile unsigned int *reg = (unsigned int *)QEMU_HALT_REG; | ||
23 | |||
24 | *reg = 42; | ||
25 | while (1) | ||
26 | cpu_wait(); | ||
27 | } | ||
28 | |||
29 | void qemu_reboot_setup(void) | ||
30 | { | ||
31 | _machine_restart = qemu_machine_restart; | ||
32 | _machine_halt = qemu_machine_halt; | ||
33 | } | ||
diff --git a/arch/mips/qemu/q-setup.c b/arch/mips/qemu/q-setup.c deleted file mode 100644 index 969cedc8d8b9..000000000000 --- a/arch/mips/qemu/q-setup.c +++ /dev/null | |||
@@ -1,22 +0,0 @@ | |||
1 | #include <linux/init.h> | ||
2 | |||
3 | #include <asm/i8253.h> | ||
4 | #include <asm/io.h> | ||
5 | #include <asm/time.h> | ||
6 | |||
7 | extern void qemu_reboot_setup(void); | ||
8 | |||
9 | const char *get_system_type(void) | ||
10 | { | ||
11 | return "Qemu"; | ||
12 | } | ||
13 | |||
14 | void __init plat_time_init(void) | ||
15 | { | ||
16 | setup_pit_timer(); | ||
17 | } | ||
18 | |||
19 | void __init plat_mem_setup(void) | ||
20 | { | ||
21 | qemu_reboot_setup(); | ||
22 | } | ||
diff --git a/arch/mips/qemu/q-smp.c b/arch/mips/qemu/q-smp.c deleted file mode 100644 index 4b0178d0df0b..000000000000 --- a/arch/mips/qemu/q-smp.c +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2006 by Ralf Baechle (ralf@linux-mips.org) | ||
7 | * | ||
8 | * Symmetric Uniprocessor (TM) Support | ||
9 | */ | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/sched.h> | ||
12 | |||
13 | /* | ||
14 | * Send inter-processor interrupt | ||
15 | */ | ||
16 | void core_send_ipi(int cpu, unsigned int action) | ||
17 | { | ||
18 | panic(KERN_ERR "%s called", __FUNCTION__); | ||
19 | } | ||
20 | |||
21 | /* | ||
22 | * After we've done initial boot, this function is called to allow the | ||
23 | * board code to clean up state, if needed | ||
24 | */ | ||
25 | void __cpuinit prom_init_secondary(void) | ||
26 | { | ||
27 | } | ||
28 | |||
29 | void __cpuinit prom_smp_finish(void) | ||
30 | { | ||
31 | } | ||
32 | |||
33 | /* Hook for after all CPUs are online */ | ||
34 | void prom_cpus_done(void) | ||
35 | { | ||
36 | } | ||
37 | |||
38 | void __init prom_prepare_cpus(unsigned int max_cpus) | ||
39 | { | ||
40 | cpus_clear(phys_cpu_present_map); | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | * Firmware CPU startup hook | ||
45 | */ | ||
46 | void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) | ||
47 | { | ||
48 | } | ||
49 | |||
50 | void __init plat_smp_setup(void) | ||
51 | { | ||
52 | } | ||
53 | void __init plat_prepare_cpus(unsigned int max_cpus) | ||
54 | { | ||
55 | } | ||
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile index e3acb51b70b5..ef1564e40c8d 100644 --- a/arch/mips/sgi-ip22/Makefile +++ b/arch/mips/sgi-ip22/Makefile | |||
@@ -3,9 +3,11 @@ | |||
3 | # under Linux. | 3 | # under Linux. |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \ | 6 | obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-time.o ip22-nvram.o \ |
7 | ip22-time.o ip22-nvram.o ip22-platform.o ip22-reset.o ip22-setup.o | 7 | ip22-platform.o ip22-reset.o ip22-setup.o |
8 | 8 | ||
9 | obj-$(CONFIG_SGI_IP22) += ip22-berr.o | ||
10 | obj-$(CONFIG_SGI_IP28) += ip28-berr.o | ||
9 | obj-$(CONFIG_EISA) += ip22-eisa.o | 11 | obj-$(CONFIG_EISA) += ip22-eisa.o |
10 | 12 | ||
11 | EXTRA_CFLAGS += -Werror | 13 | # EXTRA_CFLAGS += -Werror |
diff --git a/arch/mips/sgi-ip22/ip22-mc.c b/arch/mips/sgi-ip22/ip22-mc.c index 01a805dcc67c..3f35d6367bec 100644 --- a/arch/mips/sgi-ip22/ip22-mc.c +++ b/arch/mips/sgi-ip22/ip22-mc.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) | 4 | * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) |
5 | * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes | 5 | * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes |
6 | * Copyright (C) 2003 Ladislav Michl (ladis@linux-mips.org) | 6 | * Copyright (C) 2003 Ladislav Michl (ladis@linux-mips.org) |
7 | * Copyright (C) 2004 Peter Fuerst (pf@net.alphadv.de) - IP28 | ||
7 | */ | 8 | */ |
8 | 9 | ||
9 | #include <linux/init.h> | 10 | #include <linux/init.h> |
@@ -137,9 +138,12 @@ void __init sgimc_init(void) | |||
137 | /* Step 2: Enable all parity checking in cpu control register | 138 | /* Step 2: Enable all parity checking in cpu control register |
138 | * zero. | 139 | * zero. |
139 | */ | 140 | */ |
141 | /* don't touch parity settings for IP28 */ | ||
142 | #ifndef CONFIG_SGI_IP28 | ||
140 | tmp = sgimc->cpuctrl0; | 143 | tmp = sgimc->cpuctrl0; |
141 | tmp |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM | | 144 | tmp |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM | |
142 | SGIMC_CCTRL0_R4KNOCHKPARR); | 145 | SGIMC_CCTRL0_R4KNOCHKPARR); |
146 | #endif | ||
143 | sgimc->cpuctrl0 = tmp; | 147 | sgimc->cpuctrl0 = tmp; |
144 | 148 | ||
145 | /* Step 3: Setup the MC write buffer depth, this is controlled | 149 | /* Step 3: Setup the MC write buffer depth, this is controlled |
diff --git a/arch/mips/sgi-ip22/ip28-berr.c b/arch/mips/sgi-ip22/ip28-berr.c new file mode 100644 index 000000000000..30e12e2ec4b5 --- /dev/null +++ b/arch/mips/sgi-ip22/ip28-berr.c | |||
@@ -0,0 +1,502 @@ | |||
1 | /* | ||
2 | * ip28-berr.c: Bus error handling. | ||
3 | * | ||
4 | * Copyright (C) 2002, 2003 Ladislav Michl (ladis@linux-mips.org) | ||
5 | * Copyright (C) 2005 Peter Fuerst (pf@net.alphadv.de) - IP28 | ||
6 | */ | ||
7 | |||
8 | #include <linux/init.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/seq_file.h> | ||
12 | |||
13 | #include <asm/addrspace.h> | ||
14 | #include <asm/system.h> | ||
15 | #include <asm/traps.h> | ||
16 | #include <asm/branch.h> | ||
17 | #include <asm/irq_regs.h> | ||
18 | #include <asm/sgi/mc.h> | ||
19 | #include <asm/sgi/hpc3.h> | ||
20 | #include <asm/sgi/ioc.h> | ||
21 | #include <asm/sgi/ip22.h> | ||
22 | #include <asm/r4kcache.h> | ||
23 | #include <asm/uaccess.h> | ||
24 | #include <asm/bootinfo.h> | ||
25 | |||
26 | static unsigned int count_be_is_fixup; | ||
27 | static unsigned int count_be_handler; | ||
28 | static unsigned int count_be_interrupt; | ||
29 | static int debug_be_interrupt; | ||
30 | |||
31 | static unsigned int cpu_err_stat; /* Status reg for CPU */ | ||
32 | static unsigned int gio_err_stat; /* Status reg for GIO */ | ||
33 | static unsigned int cpu_err_addr; /* Error address reg for CPU */ | ||
34 | static unsigned int gio_err_addr; /* Error address reg for GIO */ | ||
35 | static unsigned int extio_stat; | ||
36 | static unsigned int hpc3_berr_stat; /* Bus error interrupt status */ | ||
37 | |||
38 | struct hpc3_stat { | ||
39 | unsigned long addr; | ||
40 | unsigned int ctrl; | ||
41 | unsigned int cbp; | ||
42 | unsigned int ndptr; | ||
43 | }; | ||
44 | |||
45 | static struct { | ||
46 | struct hpc3_stat pbdma[8]; | ||
47 | struct hpc3_stat scsi[2]; | ||
48 | struct hpc3_stat ethrx, ethtx; | ||
49 | } hpc3; | ||
50 | |||
51 | static struct { | ||
52 | unsigned long err_addr; | ||
53 | struct { | ||
54 | u32 lo; | ||
55 | u32 hi; | ||
56 | } tags[1][2], tagd[4][2], tagi[4][2]; /* Way 0/1 */ | ||
57 | } cache_tags; | ||
58 | |||
59 | static inline void save_cache_tags(unsigned busaddr) | ||
60 | { | ||
61 | unsigned long addr = CAC_BASE | busaddr; | ||
62 | int i; | ||
63 | cache_tags.err_addr = addr; | ||
64 | |||
65 | /* | ||
66 | * Starting with a bus-address, save secondary cache (indexed by | ||
67 | * PA[23..18:7..6]) tags first. | ||
68 | */ | ||
69 | addr &= ~1L; | ||
70 | #define tag cache_tags.tags[0] | ||
71 | cache_op(Index_Load_Tag_S, addr); | ||
72 | tag[0].lo = read_c0_taglo(); /* PA[35:18], VA[13:12] */ | ||
73 | tag[0].hi = read_c0_taghi(); /* PA[39:36] */ | ||
74 | cache_op(Index_Load_Tag_S, addr | 1L); | ||
75 | tag[1].lo = read_c0_taglo(); /* PA[35:18], VA[13:12] */ | ||
76 | tag[1].hi = read_c0_taghi(); /* PA[39:36] */ | ||
77 | #undef tag | ||
78 | |||
79 | /* | ||
80 | * Save all primary data cache (indexed by VA[13:5]) tags which | ||
81 | * might fit to this bus-address, knowing that VA[11:0] == PA[11:0]. | ||
82 | * Saving all tags and evaluating them later is easier and safer | ||
83 | * than relying on VA[13:12] from the secondary cache tags to pick | ||
84 | * matching primary tags here already. | ||
85 | */ | ||
86 | addr &= (0xffL << 56) | ((1 << 12) - 1); | ||
87 | #define tag cache_tags.tagd[i] | ||
88 | for (i = 0; i < 4; ++i, addr += (1 << 12)) { | ||
89 | cache_op(Index_Load_Tag_D, addr); | ||
90 | tag[0].lo = read_c0_taglo(); /* PA[35:12] */ | ||
91 | tag[0].hi = read_c0_taghi(); /* PA[39:36] */ | ||
92 | cache_op(Index_Load_Tag_D, addr | 1L); | ||
93 | tag[1].lo = read_c0_taglo(); /* PA[35:12] */ | ||
94 | tag[1].hi = read_c0_taghi(); /* PA[39:36] */ | ||
95 | } | ||
96 | #undef tag | ||
97 | |||
98 | /* | ||
99 | * Save primary instruction cache (indexed by VA[13:6]) tags | ||
100 | * the same way. | ||
101 | */ | ||
102 | addr &= (0xffL << 56) | ((1 << 12) - 1); | ||
103 | #define tag cache_tags.tagi[i] | ||
104 | for (i = 0; i < 4; ++i, addr += (1 << 12)) { | ||
105 | cache_op(Index_Load_Tag_I, addr); | ||
106 | tag[0].lo = read_c0_taglo(); /* PA[35:12] */ | ||
107 | tag[0].hi = read_c0_taghi(); /* PA[39:36] */ | ||
108 | cache_op(Index_Load_Tag_I, addr | 1L); | ||
109 | tag[1].lo = read_c0_taglo(); /* PA[35:12] */ | ||
110 | tag[1].hi = read_c0_taghi(); /* PA[39:36] */ | ||
111 | } | ||
112 | #undef tag | ||
113 | } | ||
114 | |||
115 | #define GIO_ERRMASK 0xff00 | ||
116 | #define CPU_ERRMASK 0x3f00 | ||
117 | |||
118 | static void save_and_clear_buserr(void) | ||
119 | { | ||
120 | int i; | ||
121 | |||
122 | /* save status registers */ | ||
123 | cpu_err_addr = sgimc->cerr; | ||
124 | cpu_err_stat = sgimc->cstat; | ||
125 | gio_err_addr = sgimc->gerr; | ||
126 | gio_err_stat = sgimc->gstat; | ||
127 | extio_stat = sgioc->extio; | ||
128 | hpc3_berr_stat = hpc3c0->bestat; | ||
129 | |||
130 | hpc3.scsi[0].addr = (unsigned long)&hpc3c0->scsi_chan0; | ||
131 | hpc3.scsi[0].ctrl = hpc3c0->scsi_chan0.ctrl; /* HPC3_SCTRL_ACTIVE ? */ | ||
132 | hpc3.scsi[0].cbp = hpc3c0->scsi_chan0.cbptr; | ||
133 | hpc3.scsi[0].ndptr = hpc3c0->scsi_chan0.ndptr; | ||
134 | |||
135 | hpc3.scsi[1].addr = (unsigned long)&hpc3c0->scsi_chan1; | ||
136 | hpc3.scsi[1].ctrl = hpc3c0->scsi_chan1.ctrl; /* HPC3_SCTRL_ACTIVE ? */ | ||
137 | hpc3.scsi[1].cbp = hpc3c0->scsi_chan1.cbptr; | ||
138 | hpc3.scsi[1].ndptr = hpc3c0->scsi_chan1.ndptr; | ||
139 | |||
140 | hpc3.ethrx.addr = (unsigned long)&hpc3c0->ethregs.rx_cbptr; | ||
141 | hpc3.ethrx.ctrl = hpc3c0->ethregs.rx_ctrl; /* HPC3_ERXCTRL_ACTIVE ? */ | ||
142 | hpc3.ethrx.cbp = hpc3c0->ethregs.rx_cbptr; | ||
143 | hpc3.ethrx.ndptr = hpc3c0->ethregs.rx_ndptr; | ||
144 | |||
145 | hpc3.ethtx.addr = (unsigned long)&hpc3c0->ethregs.tx_cbptr; | ||
146 | hpc3.ethtx.ctrl = hpc3c0->ethregs.tx_ctrl; /* HPC3_ETXCTRL_ACTIVE ? */ | ||
147 | hpc3.ethtx.cbp = hpc3c0->ethregs.tx_cbptr; | ||
148 | hpc3.ethtx.ndptr = hpc3c0->ethregs.tx_ndptr; | ||
149 | |||
150 | for (i = 0; i < 8; ++i) { | ||
151 | /* HPC3_PDMACTRL_ISACT ? */ | ||
152 | hpc3.pbdma[i].addr = (unsigned long)&hpc3c0->pbdma[i]; | ||
153 | hpc3.pbdma[i].ctrl = hpc3c0->pbdma[i].pbdma_ctrl; | ||
154 | hpc3.pbdma[i].cbp = hpc3c0->pbdma[i].pbdma_bptr; | ||
155 | hpc3.pbdma[i].ndptr = hpc3c0->pbdma[i].pbdma_dptr; | ||
156 | } | ||
157 | i = 0; | ||
158 | if (gio_err_stat & CPU_ERRMASK) | ||
159 | i = gio_err_addr; | ||
160 | if (cpu_err_stat & CPU_ERRMASK) | ||
161 | i = cpu_err_addr; | ||
162 | save_cache_tags(i); | ||
163 | |||
164 | sgimc->cstat = sgimc->gstat = 0; | ||
165 | } | ||
166 | |||
167 | static void print_cache_tags(void) | ||
168 | { | ||
169 | u32 scb, scw; | ||
170 | int i; | ||
171 | |||
172 | printk(KERN_ERR "Cache tags @ %08x:\n", (unsigned)cache_tags.err_addr); | ||
173 | |||
174 | /* PA[31:12] shifted to PTag0 (PA[35:12]) format */ | ||
175 | scw = (cache_tags.err_addr >> 4) & 0x0fffff00; | ||
176 | |||
177 | scb = cache_tags.err_addr & ((1 << 12) - 1) & ~((1 << 5) - 1); | ||
178 | for (i = 0; i < 4; ++i) { /* for each possible VA[13:12] value */ | ||
179 | if ((cache_tags.tagd[i][0].lo & 0x0fffff00) != scw && | ||
180 | (cache_tags.tagd[i][1].lo & 0x0fffff00) != scw) | ||
181 | continue; | ||
182 | printk(KERN_ERR | ||
183 | "D: 0: %08x %08x, 1: %08x %08x (VA[13:5] %04x)\n", | ||
184 | cache_tags.tagd[i][0].hi, cache_tags.tagd[i][0].lo, | ||
185 | cache_tags.tagd[i][1].hi, cache_tags.tagd[i][1].lo, | ||
186 | scb | (1 << 12)*i); | ||
187 | } | ||
188 | scb = cache_tags.err_addr & ((1 << 12) - 1) & ~((1 << 6) - 1); | ||
189 | for (i = 0; i < 4; ++i) { /* for each possible VA[13:12] value */ | ||
190 | if ((cache_tags.tagi[i][0].lo & 0x0fffff00) != scw && | ||
191 | (cache_tags.tagi[i][1].lo & 0x0fffff00) != scw) | ||
192 | continue; | ||
193 | printk(KERN_ERR | ||
194 | "I: 0: %08x %08x, 1: %08x %08x (VA[13:6] %04x)\n", | ||
195 | cache_tags.tagi[i][0].hi, cache_tags.tagi[i][0].lo, | ||
196 | cache_tags.tagi[i][1].hi, cache_tags.tagi[i][1].lo, | ||
197 | scb | (1 << 12)*i); | ||
198 | } | ||
199 | i = read_c0_config(); | ||
200 | scb = i & (1 << 13) ? 7:6; /* scblksize = 2^[7..6] */ | ||
201 | scw = ((i >> 16) & 7) + 19 - 1; /* scwaysize = 2^[24..19] / 2 */ | ||
202 | |||
203 | i = ((1 << scw) - 1) & ~((1 << scb) - 1); | ||
204 | printk(KERN_ERR "S: 0: %08x %08x, 1: %08x %08x (PA[%u:%u] %05x)\n", | ||
205 | cache_tags.tags[0][0].hi, cache_tags.tags[0][0].lo, | ||
206 | cache_tags.tags[0][1].hi, cache_tags.tags[0][1].lo, | ||
207 | scw-1, scb, i & (unsigned)cache_tags.err_addr); | ||
208 | } | ||
209 | |||
210 | static inline const char *cause_excode_text(int cause) | ||
211 | { | ||
212 | static const char *txt[32] = | ||
213 | { "Interrupt", | ||
214 | "TLB modification", | ||
215 | "TLB (load or instruction fetch)", | ||
216 | "TLB (store)", | ||
217 | "Address error (load or instruction fetch)", | ||
218 | "Address error (store)", | ||
219 | "Bus error (instruction fetch)", | ||
220 | "Bus error (data: load or store)", | ||
221 | "Syscall", | ||
222 | "Breakpoint", | ||
223 | "Reserved instruction", | ||
224 | "Coprocessor unusable", | ||
225 | "Arithmetic Overflow", | ||
226 | "Trap", | ||
227 | "14", | ||
228 | "Floating-Point", | ||
229 | "16", "17", "18", "19", "20", "21", "22", | ||
230 | "Watch Hi/Lo", | ||
231 | "24", "25", "26", "27", "28", "29", "30", "31", | ||
232 | }; | ||
233 | return txt[(cause & 0x7c) >> 2]; | ||
234 | } | ||
235 | |||
236 | static void print_buserr(const struct pt_regs *regs) | ||
237 | { | ||
238 | const int field = 2 * sizeof(unsigned long); | ||
239 | int error = 0; | ||
240 | |||
241 | if (extio_stat & EXTIO_MC_BUSERR) { | ||
242 | printk(KERN_ERR "MC Bus Error\n"); | ||
243 | error |= 1; | ||
244 | } | ||
245 | if (extio_stat & EXTIO_HPC3_BUSERR) { | ||
246 | printk(KERN_ERR "HPC3 Bus Error 0x%x:<id=0x%x,%s,lane=0x%x>\n", | ||
247 | hpc3_berr_stat, | ||
248 | (hpc3_berr_stat & HPC3_BESTAT_PIDMASK) >> | ||
249 | HPC3_BESTAT_PIDSHIFT, | ||
250 | (hpc3_berr_stat & HPC3_BESTAT_CTYPE) ? "PIO" : "DMA", | ||
251 | hpc3_berr_stat & HPC3_BESTAT_BLMASK); | ||
252 | error |= 2; | ||
253 | } | ||
254 | if (extio_stat & EXTIO_EISA_BUSERR) { | ||
255 | printk(KERN_ERR "EISA Bus Error\n"); | ||
256 | error |= 4; | ||
257 | } | ||
258 | if (cpu_err_stat & CPU_ERRMASK) { | ||
259 | printk(KERN_ERR "CPU error 0x%x<%s%s%s%s%s%s> @ 0x%08x\n", | ||
260 | cpu_err_stat, | ||
261 | cpu_err_stat & SGIMC_CSTAT_RD ? "RD " : "", | ||
262 | cpu_err_stat & SGIMC_CSTAT_PAR ? "PAR " : "", | ||
263 | cpu_err_stat & SGIMC_CSTAT_ADDR ? "ADDR " : "", | ||
264 | cpu_err_stat & SGIMC_CSTAT_SYSAD_PAR ? "SYSAD " : "", | ||
265 | cpu_err_stat & SGIMC_CSTAT_SYSCMD_PAR ? "SYSCMD " : "", | ||
266 | cpu_err_stat & SGIMC_CSTAT_BAD_DATA ? "BAD_DATA " : "", | ||
267 | cpu_err_addr); | ||
268 | error |= 8; | ||
269 | } | ||
270 | if (gio_err_stat & GIO_ERRMASK) { | ||
271 | printk(KERN_ERR "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x%08x\n", | ||
272 | gio_err_stat, | ||
273 | gio_err_stat & SGIMC_GSTAT_RD ? "RD " : "", | ||
274 | gio_err_stat & SGIMC_GSTAT_WR ? "WR " : "", | ||
275 | gio_err_stat & SGIMC_GSTAT_TIME ? "TIME " : "", | ||
276 | gio_err_stat & SGIMC_GSTAT_PROM ? "PROM " : "", | ||
277 | gio_err_stat & SGIMC_GSTAT_ADDR ? "ADDR " : "", | ||
278 | gio_err_stat & SGIMC_GSTAT_BC ? "BC " : "", | ||
279 | gio_err_stat & SGIMC_GSTAT_PIO_RD ? "PIO_RD " : "", | ||
280 | gio_err_stat & SGIMC_GSTAT_PIO_WR ? "PIO_WR " : "", | ||
281 | gio_err_addr); | ||
282 | error |= 16; | ||
283 | } | ||
284 | if (!error) | ||
285 | printk(KERN_ERR "MC: Hmm, didn't find any error condition.\n"); | ||
286 | else { | ||
287 | printk(KERN_ERR "CP0: config %08x, " | ||
288 | "MC: cpuctrl0/1: %08x/%05x, giopar: %04x\n" | ||
289 | "MC: cpu/gio_memacc: %08x/%05x, memcfg0/1: %08x/%08x\n", | ||
290 | read_c0_config(), | ||
291 | sgimc->cpuctrl0, sgimc->cpuctrl0, sgimc->giopar, | ||
292 | sgimc->cmacc, sgimc->gmacc, | ||
293 | sgimc->mconfig0, sgimc->mconfig1); | ||
294 | print_cache_tags(); | ||
295 | } | ||
296 | printk(KERN_ALERT "%s, epc == %0*lx, ra == %0*lx\n", | ||
297 | cause_excode_text(regs->cp0_cause), | ||
298 | field, regs->cp0_epc, field, regs->regs[31]); | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | * Check, whether MC's (virtual) DMA address caused the bus error. | ||
303 | * See "Virtual DMA Specification", Draft 1.5, Feb 13 1992, SGI | ||
304 | */ | ||
305 | |||
306 | static int addr_is_ram(unsigned long addr, unsigned sz) | ||
307 | { | ||
308 | int i; | ||
309 | |||
310 | for (i = 0; i < boot_mem_map.nr_map; i++) { | ||
311 | unsigned long a = boot_mem_map.map[i].addr; | ||
312 | if (a <= addr && addr+sz <= a+boot_mem_map.map[i].size) | ||
313 | return 1; | ||
314 | } | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int check_microtlb(u32 hi, u32 lo, unsigned long vaddr) | ||
319 | { | ||
320 | /* This is likely rather similar to correct code ;-) */ | ||
321 | |||
322 | vaddr &= 0x7fffffff; /* Doc. states that top bit is ignored */ | ||
323 | |||
324 | /* If tlb-entry is valid and VPN-high (bits [30:21] ?) matches... */ | ||
325 | if ((lo & 2) && (vaddr >> 21) == ((hi<<1) >> 22)) { | ||
326 | u32 ctl = sgimc->dma_ctrl; | ||
327 | if (ctl & 1) { | ||
328 | unsigned int pgsz = (ctl & 2) ? 14:12; /* 16k:4k */ | ||
329 | /* PTEIndex is VPN-low (bits [22:14]/[20:12] ?) */ | ||
330 | unsigned long pte = (lo >> 6) << 12; /* PTEBase */ | ||
331 | pte += 8*((vaddr >> pgsz) & 0x1ff); | ||
332 | if (addr_is_ram(pte, 8)) { | ||
333 | /* | ||
334 | * Note: Since DMA hardware does look up | ||
335 | * translation on its own, this PTE *must* | ||
336 | * match the TLB/EntryLo-register format ! | ||
337 | */ | ||
338 | unsigned long a = *(unsigned long *) | ||
339 | PHYS_TO_XKSEG_UNCACHED(pte); | ||
340 | a = (a & 0x3f) << 6; /* PFN */ | ||
341 | a += vaddr & ((1 << pgsz) - 1); | ||
342 | return (cpu_err_addr == a); | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int check_vdma_memaddr(void) | ||
350 | { | ||
351 | if (cpu_err_stat & CPU_ERRMASK) { | ||
352 | u32 a = sgimc->maddronly; | ||
353 | |||
354 | if (!(sgimc->dma_ctrl & 0x100)) /* Xlate-bit clear ? */ | ||
355 | return (cpu_err_addr == a); | ||
356 | |||
357 | if (check_microtlb(sgimc->dtlb_hi0, sgimc->dtlb_lo0, a) || | ||
358 | check_microtlb(sgimc->dtlb_hi1, sgimc->dtlb_lo1, a) || | ||
359 | check_microtlb(sgimc->dtlb_hi2, sgimc->dtlb_lo2, a) || | ||
360 | check_microtlb(sgimc->dtlb_hi3, sgimc->dtlb_lo3, a)) | ||
361 | return 1; | ||
362 | } | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static int check_vdma_gioaddr(void) | ||
367 | { | ||
368 | if (gio_err_stat & GIO_ERRMASK) { | ||
369 | u32 a = sgimc->gio_dma_trans; | ||
370 | a = (sgimc->gmaddronly & ~a) | (sgimc->gio_dma_sbits & a); | ||
371 | return (gio_err_addr == a); | ||
372 | } | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | /* | ||
377 | * MC sends an interrupt whenever bus or parity errors occur. In addition, | ||
378 | * if the error happened during a CPU read, it also asserts the bus error | ||
379 | * pin on the R4K. Code in bus error handler save the MC bus error registers | ||
380 | * and then clear the interrupt when this happens. | ||
381 | */ | ||
382 | |||
383 | static int ip28_be_interrupt(const struct pt_regs *regs) | ||
384 | { | ||
385 | int i; | ||
386 | |||
387 | save_and_clear_buserr(); | ||
388 | /* | ||
389 | * Try to find out, whether we got here by a mispredicted speculative | ||
390 | * load/store operation. If so, it's not fatal, we can go on. | ||
391 | */ | ||
392 | /* Any cause other than "Interrupt" (ExcCode 0) is fatal. */ | ||
393 | if (regs->cp0_cause & CAUSEF_EXCCODE) | ||
394 | goto mips_be_fatal; | ||
395 | |||
396 | /* Any cause other than "Bus error interrupt" (IP6) is weird. */ | ||
397 | if ((regs->cp0_cause & CAUSEF_IP6) != CAUSEF_IP6) | ||
398 | goto mips_be_fatal; | ||
399 | |||
400 | if (extio_stat & (EXTIO_HPC3_BUSERR | EXTIO_EISA_BUSERR)) | ||
401 | goto mips_be_fatal; | ||
402 | |||
403 | /* Any state other than "Memory bus error" is fatal. */ | ||
404 | if (cpu_err_stat & CPU_ERRMASK & ~SGIMC_CSTAT_ADDR) | ||
405 | goto mips_be_fatal; | ||
406 | |||
407 | /* GIO errors other than timeouts are fatal */ | ||
408 | if (gio_err_stat & GIO_ERRMASK & ~SGIMC_GSTAT_TIME) | ||
409 | goto mips_be_fatal; | ||
410 | |||
411 | /* | ||
412 | * Now we have an asynchronous bus error, speculatively or DMA caused. | ||
413 | * Need to search all DMA descriptors for the error address. | ||
414 | */ | ||
415 | for (i = 0; i < sizeof(hpc3)/sizeof(struct hpc3_stat); ++i) { | ||
416 | struct hpc3_stat *hp = (struct hpc3_stat *)&hpc3 + i; | ||
417 | if ((cpu_err_stat & CPU_ERRMASK) && | ||
418 | (cpu_err_addr == hp->ndptr || cpu_err_addr == hp->cbp)) | ||
419 | break; | ||
420 | if ((gio_err_stat & GIO_ERRMASK) && | ||
421 | (gio_err_addr == hp->ndptr || gio_err_addr == hp->cbp)) | ||
422 | break; | ||
423 | } | ||
424 | if (i < sizeof(hpc3)/sizeof(struct hpc3_stat)) { | ||
425 | struct hpc3_stat *hp = (struct hpc3_stat *)&hpc3 + i; | ||
426 | printk(KERN_ERR "at DMA addresses: HPC3 @ %08lx:" | ||
427 | " ctl %08x, ndp %08x, cbp %08x\n", | ||
428 | CPHYSADDR(hp->addr), hp->ctrl, hp->ndptr, hp->cbp); | ||
429 | goto mips_be_fatal; | ||
430 | } | ||
431 | /* Check MC's virtual DMA stuff. */ | ||
432 | if (check_vdma_memaddr()) { | ||
433 | printk(KERN_ERR "at GIO DMA: mem address 0x%08x.\n", | ||
434 | sgimc->maddronly); | ||
435 | goto mips_be_fatal; | ||
436 | } | ||
437 | if (check_vdma_gioaddr()) { | ||
438 | printk(KERN_ERR "at GIO DMA: gio address 0x%08x.\n", | ||
439 | sgimc->gmaddronly); | ||
440 | goto mips_be_fatal; | ||
441 | } | ||
442 | /* A speculative bus error... */ | ||
443 | if (debug_be_interrupt) { | ||
444 | print_buserr(regs); | ||
445 | printk(KERN_ERR "discarded!\n"); | ||
446 | } | ||
447 | return MIPS_BE_DISCARD; | ||
448 | |||
449 | mips_be_fatal: | ||
450 | print_buserr(regs); | ||
451 | return MIPS_BE_FATAL; | ||
452 | } | ||
453 | |||
454 | void ip22_be_interrupt(int irq) | ||
455 | { | ||
456 | const struct pt_regs *regs = get_irq_regs(); | ||
457 | |||
458 | count_be_interrupt++; | ||
459 | |||
460 | if (ip28_be_interrupt(regs) != MIPS_BE_DISCARD) { | ||
461 | /* Assume it would be too dangerous to continue ... */ | ||
462 | die_if_kernel("Oops", regs); | ||
463 | force_sig(SIGBUS, current); | ||
464 | } else if (debug_be_interrupt) | ||
465 | show_regs((struct pt_regs *)regs); | ||
466 | } | ||
467 | |||
468 | static int ip28_be_handler(struct pt_regs *regs, int is_fixup) | ||
469 | { | ||
470 | /* | ||
471 | * We arrive here only in the unusual case of do_be() invocation, | ||
472 | * i.e. by a bus error exception without a bus error interrupt. | ||
473 | */ | ||
474 | if (is_fixup) { | ||
475 | count_be_is_fixup++; | ||
476 | save_and_clear_buserr(); | ||
477 | return MIPS_BE_FIXUP; | ||
478 | } | ||
479 | count_be_handler++; | ||
480 | return ip28_be_interrupt(regs); | ||
481 | } | ||
482 | |||
483 | void __init ip22_be_init(void) | ||
484 | { | ||
485 | board_be_handler = ip28_be_handler; | ||
486 | } | ||
487 | |||
488 | int ip28_show_be_info(struct seq_file *m) | ||
489 | { | ||
490 | seq_printf(m, "IP28 be fixups\t\t: %u\n", count_be_is_fixup); | ||
491 | seq_printf(m, "IP28 be interrupts\t: %u\n", count_be_interrupt); | ||
492 | seq_printf(m, "IP28 be handler\t\t: %u\n", count_be_handler); | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static int __init debug_be_setup(char *str) | ||
498 | { | ||
499 | debug_be_interrupt++; | ||
500 | return 1; | ||
501 | } | ||
502 | __setup("ip28_debug_be", debug_be_setup); | ||
diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 3305fa9ae66d..a49e7c85f724 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <asm/sn/hub.h> | 27 | #include <asm/sn/hub.h> |
28 | #include <asm/sn/intr.h> | 28 | #include <asm/sn/intr.h> |
29 | #include <asm/current.h> | 29 | #include <asm/current.h> |
30 | #include <asm/smp.h> | ||
31 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
32 | #include <asm/mmu_context.h> | 31 | #include <asm/mmu_context.h> |
33 | #include <asm/thread_info.h> | 32 | #include <asm/thread_info.h> |
diff --git a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c index f10d9839006d..48932ce1d730 100644 --- a/arch/mips/sgi-ip27/ip27-klnuma.c +++ b/arch/mips/sgi-ip27/ip27-klnuma.c | |||
@@ -11,7 +11,6 @@ | |||
11 | 11 | ||
12 | #include <asm/page.h> | 12 | #include <asm/page.h> |
13 | #include <asm/sections.h> | 13 | #include <asm/sections.h> |
14 | #include <asm/smp.h> | ||
15 | #include <asm/sn/types.h> | 14 | #include <asm/sn/types.h> |
16 | #include <asm/sn/arch.h> | 15 | #include <asm/sn/arch.h> |
17 | #include <asm/sn/gda.h> | 16 | #include <asm/sn/gda.h> |
diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index a70656d42191..f15fc93d6b35 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c | |||
@@ -140,30 +140,51 @@ static __init void intr_clear_all(nasid_t nasid) | |||
140 | REMOTE_HUB_CLR_INTR(nasid, i); | 140 | REMOTE_HUB_CLR_INTR(nasid, i); |
141 | } | 141 | } |
142 | 142 | ||
143 | void __init plat_smp_setup(void) | 143 | static void ip27_send_ipi_single(int destid, unsigned int action) |
144 | { | 144 | { |
145 | cnodeid_t cnode; | 145 | int irq; |
146 | 146 | ||
147 | for_each_online_node(cnode) { | 147 | switch (action) { |
148 | if (cnode == 0) | 148 | case SMP_RESCHEDULE_YOURSELF: |
149 | continue; | 149 | irq = CPU_RESCHED_A_IRQ; |
150 | intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); | 150 | break; |
151 | case SMP_CALL_FUNCTION: | ||
152 | irq = CPU_CALL_A_IRQ; | ||
153 | break; | ||
154 | default: | ||
155 | panic("sendintr"); | ||
151 | } | 156 | } |
152 | 157 | ||
153 | replicate_kernel_text(); | 158 | irq += cputoslice(destid); |
154 | 159 | ||
155 | /* | 160 | /* |
156 | * Assumption to be fixed: we're always booted on logical / physical | 161 | * Convert the compact hub number to the NASID to get the correct |
157 | * processor 0. While we're always running on logical processor 0 | 162 | * part of the address space. Then set the interrupt bit associated |
158 | * this still means this is physical processor zero; it might for | 163 | * with the CPU we want to send the interrupt to. |
159 | * example be disabled in the firwware. | ||
160 | */ | 164 | */ |
161 | alloc_cpupda(0, 0); | 165 | REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cpu_to_node(destid)), irq); |
162 | } | 166 | } |
163 | 167 | ||
164 | void __init plat_prepare_cpus(unsigned int max_cpus) | 168 | static void ip27_send_ipi_mask(cpumask_t mask, unsigned int action) |
169 | { | ||
170 | unsigned int i; | ||
171 | |||
172 | for_each_cpu_mask(i, mask) | ||
173 | ip27_send_ipi_single(i, action); | ||
174 | } | ||
175 | |||
176 | static void __cpuinit ip27_init_secondary(void) | ||
177 | { | ||
178 | per_cpu_init(); | ||
179 | local_irq_enable(); | ||
180 | } | ||
181 | |||
182 | static void __cpuinit ip27_smp_finish(void) | ||
183 | { | ||
184 | } | ||
185 | |||
186 | static void __init ip27_cpus_done(void) | ||
165 | { | 187 | { |
166 | /* We already did everything necessary earlier */ | ||
167 | } | 188 | } |
168 | 189 | ||
169 | /* | 190 | /* |
@@ -171,7 +192,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus) | |||
171 | * set sp to the kernel stack of the newly created idle process, gp to the proc | 192 | * set sp to the kernel stack of the newly created idle process, gp to the proc |
172 | * struct so that current_thread_info() will work. | 193 | * struct so that current_thread_info() will work. |
173 | */ | 194 | */ |
174 | void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) | 195 | static void __cpuinit ip27_boot_secondary(int cpu, struct task_struct *idle) |
175 | { | 196 | { |
176 | unsigned long gp = (unsigned long)task_thread_info(idle); | 197 | unsigned long gp = (unsigned long)task_thread_info(idle); |
177 | unsigned long sp = __KSTK_TOS(idle); | 198 | unsigned long sp = __KSTK_TOS(idle); |
@@ -181,41 +202,39 @@ void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) | |||
181 | 0, (void *) sp, (void *) gp); | 202 | 0, (void *) sp, (void *) gp); |
182 | } | 203 | } |
183 | 204 | ||
184 | void __cpuinit prom_init_secondary(void) | 205 | static void __init ip27_smp_setup(void) |
185 | { | 206 | { |
186 | per_cpu_init(); | 207 | cnodeid_t cnode; |
187 | local_irq_enable(); | ||
188 | } | ||
189 | |||
190 | void __init prom_cpus_done(void) | ||
191 | { | ||
192 | } | ||
193 | |||
194 | void __cpuinit prom_smp_finish(void) | ||
195 | { | ||
196 | } | ||
197 | |||
198 | void core_send_ipi(int destid, unsigned int action) | ||
199 | { | ||
200 | int irq; | ||
201 | 208 | ||
202 | switch (action) { | 209 | for_each_online_node(cnode) { |
203 | case SMP_RESCHEDULE_YOURSELF: | 210 | if (cnode == 0) |
204 | irq = CPU_RESCHED_A_IRQ; | 211 | continue; |
205 | break; | 212 | intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); |
206 | case SMP_CALL_FUNCTION: | ||
207 | irq = CPU_CALL_A_IRQ; | ||
208 | break; | ||
209 | default: | ||
210 | panic("sendintr"); | ||
211 | } | 213 | } |
212 | 214 | ||
213 | irq += cputoslice(destid); | 215 | replicate_kernel_text(); |
214 | 216 | ||
215 | /* | 217 | /* |
216 | * Convert the compact hub number to the NASID to get the correct | 218 | * Assumption to be fixed: we're always booted on logical / physical |
217 | * part of the address space. Then set the interrupt bit associated | 219 | * processor 0. While we're always running on logical processor 0 |
218 | * with the CPU we want to send the interrupt to. | 220 | * this still means this is physical processor zero; it might for |
221 | * example be disabled in the firwware. | ||
219 | */ | 222 | */ |
220 | REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cpu_to_node(destid)), irq); | 223 | alloc_cpupda(0, 0); |
221 | } | 224 | } |
225 | |||
226 | static void __init ip27_prepare_cpus(unsigned int max_cpus) | ||
227 | { | ||
228 | /* We already did everything necessary earlier */ | ||
229 | } | ||
230 | |||
231 | struct plat_smp_ops ip27_smp_ops = { | ||
232 | .send_ipi_single = ip27_send_ipi_single, | ||
233 | .send_ipi_mask = ip27_send_ipi_mask, | ||
234 | .init_secondary = ip27_init_secondary, | ||
235 | .smp_finish = ip27_smp_finish, | ||
236 | .cpus_done = ip27_cpus_done, | ||
237 | .boot_secondary = ip27_boot_secondary, | ||
238 | .smp_setup = ip27_smp_setup, | ||
239 | .prepare_cpus = ip27_prepare_cpus, | ||
240 | }; | ||
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index 436ba78359ab..183c460b9ca1 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include <asm/mmu_context.h> | 24 | #include <asm/mmu_context.h> |
25 | #include <asm/io.h> | 25 | #include <asm/io.h> |
26 | #include <asm/fw/cfe/cfe_api.h> | ||
26 | #include <asm/sibyte/sb1250.h> | 27 | #include <asm/sibyte/sb1250.h> |
27 | #include <asm/sibyte/bcm1480_regs.h> | 28 | #include <asm/sibyte/bcm1480_regs.h> |
28 | #include <asm/sibyte/bcm1480_int.h> | 29 | #include <asm/sibyte/bcm1480_int.h> |
@@ -67,28 +68,114 @@ void __cpuinit bcm1480_smp_init(void) | |||
67 | change_c0_status(ST0_IM, imask); | 68 | change_c0_status(ST0_IM, imask); |
68 | } | 69 | } |
69 | 70 | ||
70 | void __cpuinit bcm1480_smp_finish(void) | 71 | /* |
72 | * These are routines for dealing with the sb1250 smp capabilities | ||
73 | * independent of board/firmware | ||
74 | */ | ||
75 | |||
76 | /* | ||
77 | * Simple enough; everything is set up, so just poke the appropriate mailbox | ||
78 | * register, and we should be set | ||
79 | */ | ||
80 | static void bcm1480_send_ipi_single(int cpu, unsigned int action) | ||
81 | { | ||
82 | __raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]); | ||
83 | } | ||
84 | |||
85 | static void bcm1480_send_ipi_mask(cpumask_t mask, unsigned int action) | ||
86 | { | ||
87 | unsigned int i; | ||
88 | |||
89 | for_each_cpu_mask(i, mask) | ||
90 | bcm1480_send_ipi_single(i, action); | ||
91 | } | ||
92 | |||
93 | /* | ||
94 | * Code to run on secondary just after probing the CPU | ||
95 | */ | ||
96 | static void __cpuinit bcm1480_init_secondary(void) | ||
97 | { | ||
98 | extern void bcm1480_smp_init(void); | ||
99 | |||
100 | bcm1480_smp_init(); | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Do any tidying up before marking online and running the idle | ||
105 | * loop | ||
106 | */ | ||
107 | static void __cpuinit bcm1480_smp_finish(void) | ||
71 | { | 108 | { |
72 | extern void sb1480_clockevent_init(void); | 109 | extern void sb1480_clockevent_init(void); |
73 | 110 | ||
74 | sb1480_clockevent_init(); | 111 | sb1480_clockevent_init(); |
75 | local_irq_enable(); | 112 | local_irq_enable(); |
113 | bcm1480_smp_finish(); | ||
76 | } | 114 | } |
77 | 115 | ||
78 | /* | 116 | /* |
79 | * These are routines for dealing with the sb1250 smp capabilities | 117 | * Final cleanup after all secondaries booted |
80 | * independent of board/firmware | ||
81 | */ | 118 | */ |
119 | static void bcm1480_cpus_done(void) | ||
120 | { | ||
121 | } | ||
82 | 122 | ||
83 | /* | 123 | /* |
84 | * Simple enough; everything is set up, so just poke the appropriate mailbox | 124 | * Setup the PC, SP, and GP of a secondary processor and start it |
85 | * register, and we should be set | 125 | * running! |
86 | */ | 126 | */ |
87 | void core_send_ipi(int cpu, unsigned int action) | 127 | static void __cpuinit bcm1480_boot_secondary(int cpu, struct task_struct *idle) |
88 | { | 128 | { |
89 | __raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]); | 129 | int retval; |
130 | |||
131 | retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap, | ||
132 | __KSTK_TOS(idle), | ||
133 | (unsigned long)task_thread_info(idle), 0); | ||
134 | if (retval != 0) | ||
135 | printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); | ||
90 | } | 136 | } |
91 | 137 | ||
138 | /* | ||
139 | * Use CFE to find out how many CPUs are available, setting up | ||
140 | * phys_cpu_present_map and the logical/physical mappings. | ||
141 | * XXXKW will the boot CPU ever not be physical 0? | ||
142 | * | ||
143 | * Common setup before any secondaries are started | ||
144 | */ | ||
145 | static void __init bcm1480_smp_setup(void) | ||
146 | { | ||
147 | int i, num; | ||
148 | |||
149 | cpus_clear(phys_cpu_present_map); | ||
150 | cpu_set(0, phys_cpu_present_map); | ||
151 | __cpu_number_map[0] = 0; | ||
152 | __cpu_logical_map[0] = 0; | ||
153 | |||
154 | for (i = 1, num = 0; i < NR_CPUS; i++) { | ||
155 | if (cfe_cpu_stop(i) == 0) { | ||
156 | cpu_set(i, phys_cpu_present_map); | ||
157 | __cpu_number_map[i] = ++num; | ||
158 | __cpu_logical_map[num] = i; | ||
159 | } | ||
160 | } | ||
161 | printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); | ||
162 | } | ||
163 | |||
164 | static void __init bcm1480_prepare_cpus(unsigned int max_cpus) | ||
165 | { | ||
166 | } | ||
167 | |||
168 | struct plat_smp_ops bcm1480_smp_ops = { | ||
169 | .send_ipi_single = bcm1480_send_ipi_single, | ||
170 | .send_ipi_mask = bcm1480_send_ipi_mask, | ||
171 | .init_secondary = bcm1480_init_secondary, | ||
172 | .smp_finish = bcm1480_smp_finish, | ||
173 | .cpus_done = bcm1480_cpus_done, | ||
174 | .boot_secondary = bcm1480_boot_secondary, | ||
175 | .smp_setup = bcm1480_smp_setup, | ||
176 | .prepare_cpus = bcm1480_prepare_cpus, | ||
177 | }; | ||
178 | |||
92 | void bcm1480_mailbox_interrupt(void) | 179 | void bcm1480_mailbox_interrupt(void) |
93 | { | 180 | { |
94 | int cpu = smp_processor_id(); | 181 | int cpu = smp_processor_id(); |
diff --git a/arch/mips/sibyte/cfe/Makefile b/arch/mips/sibyte/cfe/Makefile index a1214937b705..02b32e142adf 100644 --- a/arch/mips/sibyte/cfe/Makefile +++ b/arch/mips/sibyte/cfe/Makefile | |||
@@ -1,3 +1,2 @@ | |||
1 | lib-y = setup.o | 1 | lib-y = setup.o |
2 | lib-$(CONFIG_SMP) += smp.o | ||
3 | lib-$(CONFIG_SIBYTE_CFE_CONSOLE) += console.o | 2 | lib-$(CONFIG_SIBYTE_CFE_CONSOLE) += console.o |
diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/cfe/setup.c index dbd6e6fdd3f9..33fce826f8bf 100644 --- a/arch/mips/sibyte/cfe/setup.c +++ b/arch/mips/sibyte/cfe/setup.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/bootinfo.h> | 28 | #include <asm/bootinfo.h> |
29 | #include <asm/reboot.h> | 29 | #include <asm/reboot.h> |
30 | #include <asm/sibyte/board.h> | 30 | #include <asm/sibyte/board.h> |
31 | #include <asm/smp-ops.h> | ||
31 | 32 | ||
32 | #include <asm/fw/cfe/cfe_api.h> | 33 | #include <asm/fw/cfe/cfe_api.h> |
33 | #include <asm/fw/cfe/cfe_error.h> | 34 | #include <asm/fw/cfe/cfe_error.h> |
@@ -232,6 +233,9 @@ static int __init initrd_setup(char *str) | |||
232 | 233 | ||
233 | #endif | 234 | #endif |
234 | 235 | ||
236 | extern struct plat_smp_ops sb_smp_ops; | ||
237 | extern struct plat_smp_ops bcm1480_smp_ops; | ||
238 | |||
235 | /* | 239 | /* |
236 | * prom_init is called just after the cpu type is determined, from setup_arch() | 240 | * prom_init is called just after the cpu type is determined, from setup_arch() |
237 | */ | 241 | */ |
@@ -297,9 +301,6 @@ void __init prom_init(void) | |||
297 | * command line | 301 | * command line |
298 | */ | 302 | */ |
299 | strcpy(arcs_cmdline, "root=/dev/ram0 "); | 303 | strcpy(arcs_cmdline, "root=/dev/ram0 "); |
300 | #ifdef CONFIG_SIBYTE_PTSWARM | ||
301 | strcat(arcs_cmdline, "console=ttyS0,115200 "); | ||
302 | #endif | ||
303 | } else { | 304 | } else { |
304 | /* The loader should have set the command line */ | 305 | /* The loader should have set the command line */ |
305 | /* too early for panic to do any good */ | 306 | /* too early for panic to do any good */ |
@@ -340,6 +341,13 @@ void __init prom_init(void) | |||
340 | arcs_cmdline[CL_SIZE-1] = 0; | 341 | arcs_cmdline[CL_SIZE-1] = 0; |
341 | 342 | ||
342 | prom_meminit(); | 343 | prom_meminit(); |
344 | |||
345 | #if defined(CONFIG_SIBYTE_BCM112X) || defined(CONFIG_SIBYTE_SB1250) | ||
346 | register_smp_ops(&sb_smp_ops); | ||
347 | #endif | ||
348 | #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) | ||
349 | register_smp_ops(&bcm1480_smp_ops); | ||
350 | #endif | ||
343 | } | 351 | } |
344 | 352 | ||
345 | void __init prom_free_prom_memory(void) | 353 | void __init prom_free_prom_memory(void) |
diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c deleted file mode 100644 index 534a62912f21..000000000000 --- a/arch/mips/sibyte/cfe/smp.c +++ /dev/null | |||
@@ -1,110 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version 2 | ||
7 | * of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | */ | ||
18 | |||
19 | #include <linux/init.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/smp.h> | ||
22 | #include <asm/processor.h> | ||
23 | |||
24 | #include <asm/fw/cfe/cfe_api.h> | ||
25 | #include <asm/fw/cfe/cfe_error.h> | ||
26 | |||
27 | /* | ||
28 | * Use CFE to find out how many CPUs are available, setting up | ||
29 | * phys_cpu_present_map and the logical/physical mappings. | ||
30 | * XXXKW will the boot CPU ever not be physical 0? | ||
31 | * | ||
32 | * Common setup before any secondaries are started | ||
33 | */ | ||
34 | void __init plat_smp_setup(void) | ||
35 | { | ||
36 | int i, num; | ||
37 | |||
38 | cpus_clear(phys_cpu_present_map); | ||
39 | cpu_set(0, phys_cpu_present_map); | ||
40 | __cpu_number_map[0] = 0; | ||
41 | __cpu_logical_map[0] = 0; | ||
42 | |||
43 | for (i = 1, num = 0; i < NR_CPUS; i++) { | ||
44 | if (cfe_cpu_stop(i) == 0) { | ||
45 | cpu_set(i, phys_cpu_present_map); | ||
46 | __cpu_number_map[i] = ++num; | ||
47 | __cpu_logical_map[num] = i; | ||
48 | } | ||
49 | } | ||
50 | printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); | ||
51 | } | ||
52 | |||
53 | void __init plat_prepare_cpus(unsigned int max_cpus) | ||
54 | { | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * Setup the PC, SP, and GP of a secondary processor and start it | ||
59 | * running! | ||
60 | */ | ||
61 | void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle) | ||
62 | { | ||
63 | int retval; | ||
64 | |||
65 | retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap, | ||
66 | __KSTK_TOS(idle), | ||
67 | (unsigned long)task_thread_info(idle), 0); | ||
68 | if (retval != 0) | ||
69 | printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); | ||
70 | } | ||
71 | |||
72 | /* | ||
73 | * Code to run on secondary just after probing the CPU | ||
74 | */ | ||
75 | void __cpuinit prom_init_secondary(void) | ||
76 | { | ||
77 | #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) | ||
78 | extern void bcm1480_smp_init(void); | ||
79 | bcm1480_smp_init(); | ||
80 | #elif defined(CONFIG_SIBYTE_SB1250) | ||
81 | extern void sb1250_smp_init(void); | ||
82 | sb1250_smp_init(); | ||
83 | #else | ||
84 | #error invalid SMP configuration | ||
85 | #endif | ||
86 | } | ||
87 | |||
88 | /* | ||
89 | * Do any tidying up before marking online and running the idle | ||
90 | * loop | ||
91 | */ | ||
92 | void __cpuinit prom_smp_finish(void) | ||
93 | { | ||
94 | #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) | ||
95 | extern void bcm1480_smp_finish(void); | ||
96 | bcm1480_smp_finish(); | ||
97 | #elif defined(CONFIG_SIBYTE_SB1250) | ||
98 | extern void sb1250_smp_finish(void); | ||
99 | sb1250_smp_finish(); | ||
100 | #else | ||
101 | #error invalid SMP configuration | ||
102 | #endif | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | * Final cleanup after all secondaries booted | ||
107 | */ | ||
108 | void prom_cpus_done(void) | ||
109 | { | ||
110 | } | ||
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index 3f52c95a4eb8..0734b933e969 100644 --- a/arch/mips/sibyte/sb1250/smp.c +++ b/arch/mips/sibyte/sb1250/smp.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <asm/mmu_context.h> | 25 | #include <asm/mmu_context.h> |
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | #include <asm/fw/cfe/cfe_api.h> | ||
27 | #include <asm/sibyte/sb1250.h> | 28 | #include <asm/sibyte/sb1250.h> |
28 | #include <asm/sibyte/sb1250_regs.h> | 29 | #include <asm/sibyte/sb1250_regs.h> |
29 | #include <asm/sibyte/sb1250_int.h> | 30 | #include <asm/sibyte/sb1250_int.h> |
@@ -55,7 +56,43 @@ void __cpuinit sb1250_smp_init(void) | |||
55 | change_c0_status(ST0_IM, imask); | 56 | change_c0_status(ST0_IM, imask); |
56 | } | 57 | } |
57 | 58 | ||
58 | void __cpuinit sb1250_smp_finish(void) | 59 | /* |
60 | * These are routines for dealing with the sb1250 smp capabilities | ||
61 | * independent of board/firmware | ||
62 | */ | ||
63 | |||
64 | /* | ||
65 | * Simple enough; everything is set up, so just poke the appropriate mailbox | ||
66 | * register, and we should be set | ||
67 | */ | ||
68 | static void sb1250_send_ipi_single(int cpu, unsigned int action) | ||
69 | { | ||
70 | __raw_writeq((((u64)action) << 48), mailbox_set_regs[cpu]); | ||
71 | } | ||
72 | |||
73 | static inline void sb1250_send_ipi_mask(cpumask_t mask, unsigned int action) | ||
74 | { | ||
75 | unsigned int i; | ||
76 | |||
77 | for_each_cpu_mask(i, mask) | ||
78 | sb1250_send_ipi_single(i, action); | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * Code to run on secondary just after probing the CPU | ||
83 | */ | ||
84 | static void __cpuinit sb1250_init_secondary(void) | ||
85 | { | ||
86 | extern void sb1250_smp_init(void); | ||
87 | |||
88 | sb1250_smp_init(); | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * Do any tidying up before marking online and running the idle | ||
93 | * loop | ||
94 | */ | ||
95 | static void __cpuinit sb1250_smp_finish(void) | ||
59 | { | 96 | { |
60 | extern void sb1250_clockevent_init(void); | 97 | extern void sb1250_clockevent_init(void); |
61 | 98 | ||
@@ -64,19 +101,68 @@ void __cpuinit sb1250_smp_finish(void) | |||
64 | } | 101 | } |
65 | 102 | ||
66 | /* | 103 | /* |
67 | * These are routines for dealing with the sb1250 smp capabilities | 104 | * Final cleanup after all secondaries booted |
68 | * independent of board/firmware | ||
69 | */ | 105 | */ |
106 | static void sb1250_cpus_done(void) | ||
107 | { | ||
108 | } | ||
70 | 109 | ||
71 | /* | 110 | /* |
72 | * Simple enough; everything is set up, so just poke the appropriate mailbox | 111 | * Setup the PC, SP, and GP of a secondary processor and start it |
73 | * register, and we should be set | 112 | * running! |
74 | */ | 113 | */ |
75 | void core_send_ipi(int cpu, unsigned int action) | 114 | static void __cpuinit sb1250_boot_secondary(int cpu, struct task_struct *idle) |
76 | { | 115 | { |
77 | __raw_writeq((((u64)action) << 48), mailbox_set_regs[cpu]); | 116 | int retval; |
117 | |||
118 | retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap, | ||
119 | __KSTK_TOS(idle), | ||
120 | (unsigned long)task_thread_info(idle), 0); | ||
121 | if (retval != 0) | ||
122 | printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); | ||
78 | } | 123 | } |
79 | 124 | ||
125 | /* | ||
126 | * Use CFE to find out how many CPUs are available, setting up | ||
127 | * phys_cpu_present_map and the logical/physical mappings. | ||
128 | * XXXKW will the boot CPU ever not be physical 0? | ||
129 | * | ||
130 | * Common setup before any secondaries are started | ||
131 | */ | ||
132 | static void __init sb1250_smp_setup(void) | ||
133 | { | ||
134 | int i, num; | ||
135 | |||
136 | cpus_clear(phys_cpu_present_map); | ||
137 | cpu_set(0, phys_cpu_present_map); | ||
138 | __cpu_number_map[0] = 0; | ||
139 | __cpu_logical_map[0] = 0; | ||
140 | |||
141 | for (i = 1, num = 0; i < NR_CPUS; i++) { | ||
142 | if (cfe_cpu_stop(i) == 0) { | ||
143 | cpu_set(i, phys_cpu_present_map); | ||
144 | __cpu_number_map[i] = ++num; | ||
145 | __cpu_logical_map[num] = i; | ||
146 | } | ||
147 | } | ||
148 | printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); | ||
149 | } | ||
150 | |||
151 | static void __init sb1250_prepare_cpus(unsigned int max_cpus) | ||
152 | { | ||
153 | } | ||
154 | |||
155 | struct plat_smp_ops sb_smp_ops = { | ||
156 | .send_ipi_single = sb1250_send_ipi_single, | ||
157 | .send_ipi_mask = sb1250_send_ipi_mask, | ||
158 | .init_secondary = sb1250_init_secondary, | ||
159 | .smp_finish = sb1250_smp_finish, | ||
160 | .cpus_done = sb1250_cpus_done, | ||
161 | .boot_secondary = sb1250_boot_secondary, | ||
162 | .smp_setup = sb1250_smp_setup, | ||
163 | .prepare_cpus = sb1250_prepare_cpus, | ||
164 | }; | ||
165 | |||
80 | void sb1250_mailbox_interrupt(void) | 166 | void sb1250_mailbox_interrupt(void) |
81 | { | 167 | { |
82 | int cpu = smp_processor_id(); | 168 | int cpu = smp_processor_id(); |
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile index 3a99cd62c0bd..a7dbeebe7fe6 100644 --- a/arch/mips/sni/Makefile +++ b/arch/mips/sni/Makefile | |||
@@ -3,6 +3,6 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += irq.o reset.o setup.o a20r.o rm200.o pcimt.o pcit.o time.o | 5 | obj-y += irq.o reset.o setup.o a20r.o rm200.o pcimt.o pcit.o time.o |
6 | obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o | 6 | obj-$(CONFIG_EISA) += eisa.o |
7 | 7 | ||
8 | EXTRA_CFLAGS += -Werror | 8 | EXTRA_CFLAGS += -Werror |
diff --git a/arch/mips/sni/a20r.c b/arch/mips/sni/a20r.c index b74607599971..3f8cf5eb2f06 100644 --- a/arch/mips/sni/a20r.c +++ b/arch/mips/sni/a20r.c | |||
@@ -117,10 +117,19 @@ static struct resource sc26xx_rsrc[] = { | |||
117 | } | 117 | } |
118 | }; | 118 | }; |
119 | 119 | ||
120 | static unsigned int sc26xx_data[2] = { | ||
121 | /* DTR | RTS | DSR | CTS | DCD | RI */ | ||
122 | (8 << 0) | (4 << 4) | (6 << 8) | (0 << 12) | (6 << 16) | (0 << 20), | ||
123 | (3 << 0) | (2 << 4) | (1 << 8) | (2 << 12) | (3 << 16) | (4 << 20) | ||
124 | }; | ||
125 | |||
120 | static struct platform_device sc26xx_pdev = { | 126 | static struct platform_device sc26xx_pdev = { |
121 | .name = "SC26xx", | 127 | .name = "SC26xx", |
122 | .num_resources = ARRAY_SIZE(sc26xx_rsrc), | 128 | .num_resources = ARRAY_SIZE(sc26xx_rsrc), |
123 | .resource = sc26xx_rsrc | 129 | .resource = sc26xx_rsrc, |
130 | .dev = { | ||
131 | .platform_data = sc26xx_data, | ||
132 | } | ||
124 | }; | 133 | }; |
125 | 134 | ||
126 | static u32 a20r_ack_hwint(void) | 135 | static u32 a20r_ack_hwint(void) |
@@ -231,9 +240,9 @@ static int __init snirm_a20r_setup_devinit(void) | |||
231 | platform_device_register(&sc26xx_pdev); | 240 | platform_device_register(&sc26xx_pdev); |
232 | platform_device_register(&a20r_serial8250_device); | 241 | platform_device_register(&a20r_serial8250_device); |
233 | platform_device_register(&a20r_ds1216_device); | 242 | platform_device_register(&a20r_ds1216_device); |
243 | sni_eisa_root_init(); | ||
234 | break; | 244 | break; |
235 | } | 245 | } |
236 | |||
237 | return 0; | 246 | return 0; |
238 | } | 247 | } |
239 | 248 | ||
diff --git a/arch/mips/sni/eisa.c b/arch/mips/sni/eisa.c new file mode 100644 index 000000000000..7396cd719900 --- /dev/null +++ b/arch/mips/sni/eisa.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * Virtual EISA root driver. | ||
3 | * Acts as a placeholder if we don't have a proper EISA bridge. | ||
4 | * | ||
5 | * (C) 2003 Marc Zyngier <maz@wild-wind.fr.eu.org> | ||
6 | * modified for SNI usage by Thomas Bogendoerfer | ||
7 | * | ||
8 | * This code is released under the GPL version 2. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/eisa.h> | ||
14 | #include <linux/init.h> | ||
15 | |||
16 | /* The default EISA device parent (virtual root device). | ||
17 | * Now use a platform device, since that's the obvious choice. */ | ||
18 | |||
19 | static struct platform_device eisa_root_dev = { | ||
20 | .name = "eisa", | ||
21 | .id = 0, | ||
22 | }; | ||
23 | |||
24 | static struct eisa_root_device eisa_bus_root = { | ||
25 | .dev = &eisa_root_dev.dev, | ||
26 | .bus_base_addr = 0, | ||
27 | .res = &ioport_resource, | ||
28 | .slots = EISA_MAX_SLOTS, | ||
29 | .dma_mask = 0xffffffff, | ||
30 | .force_probe = 1, | ||
31 | }; | ||
32 | |||
33 | int __init sni_eisa_root_init(void) | ||
34 | { | ||
35 | int r; | ||
36 | |||
37 | r = platform_device_register(&eisa_root_dev); | ||
38 | if (!r) | ||
39 | return r; | ||
40 | |||
41 | eisa_root_dev.dev.driver_data = &eisa_bus_root; | ||
42 | |||
43 | if (eisa_root_register(&eisa_bus_root)) { | ||
44 | /* A real bridge may have been registered before | ||
45 | * us. So quietly unregister. */ | ||
46 | platform_device_unregister(&eisa_root_dev); | ||
47 | return -1; | ||
48 | } | ||
49 | return 0; | ||
50 | } | ||
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c index 9ccffdfb8289..e8e72bb3a9af 100644 --- a/arch/mips/sni/irq.c +++ b/arch/mips/sni/irq.c | |||
@@ -35,14 +35,14 @@ static irqreturn_t sni_isa_irq_handler(int dummy, void *p) | |||
35 | if (unlikely(irq < 0)) | 35 | if (unlikely(irq < 0)) |
36 | return IRQ_NONE; | 36 | return IRQ_NONE; |
37 | 37 | ||
38 | do_IRQ(irq); | 38 | generic_handle_irq(irq); |
39 | return IRQ_HANDLED; | 39 | return IRQ_HANDLED; |
40 | } | 40 | } |
41 | 41 | ||
42 | struct irqaction sni_isa_irq = { | 42 | struct irqaction sni_isa_irq = { |
43 | .handler = sni_isa_irq_handler, | 43 | .handler = sni_isa_irq_handler, |
44 | .name = "ISA", | 44 | .name = "ISA", |
45 | .flags = IRQF_SHARED | 45 | .flags = IRQF_SHARED | IRQF_DISABLED |
46 | }; | 46 | }; |
47 | 47 | ||
48 | /* | 48 | /* |
diff --git a/arch/mips/sni/pcit.c b/arch/mips/sni/pcit.c index 416f397c768b..e5f12cf96e8e 100644 --- a/arch/mips/sni/pcit.c +++ b/arch/mips/sni/pcit.c | |||
@@ -76,6 +76,11 @@ static struct platform_device pcit_cmos_device = { | |||
76 | .resource = pcit_cmos_rsrc | 76 | .resource = pcit_cmos_rsrc |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static struct platform_device pcit_pcspeaker_pdev = { | ||
80 | .name = "pcspkr", | ||
81 | .id = -1, | ||
82 | }; | ||
83 | |||
79 | static struct resource sni_io_resource = { | 84 | static struct resource sni_io_resource = { |
80 | .start = 0x00000000UL, | 85 | .start = 0x00000000UL, |
81 | .end = 0x03bfffffUL, | 86 | .end = 0x03bfffffUL, |
@@ -277,11 +282,13 @@ static int __init snirm_pcit_setup_devinit(void) | |||
277 | case SNI_BRD_PCI_TOWER: | 282 | case SNI_BRD_PCI_TOWER: |
278 | platform_device_register(&pcit_serial8250_device); | 283 | platform_device_register(&pcit_serial8250_device); |
279 | platform_device_register(&pcit_cmos_device); | 284 | platform_device_register(&pcit_cmos_device); |
285 | platform_device_register(&pcit_pcspeaker_pdev); | ||
280 | break; | 286 | break; |
281 | 287 | ||
282 | case SNI_BRD_PCI_TOWER_CPLUS: | 288 | case SNI_BRD_PCI_TOWER_CPLUS: |
283 | platform_device_register(&pcit_cplus_serial8250_device); | 289 | platform_device_register(&pcit_cplus_serial8250_device); |
284 | platform_device_register(&pcit_cmos_device); | 290 | platform_device_register(&pcit_cmos_device); |
291 | platform_device_register(&pcit_pcspeaker_pdev); | ||
285 | break; | 292 | break; |
286 | } | 293 | } |
287 | return 0; | 294 | return 0; |
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c index 67b061eef6cd..5310aa75afa4 100644 --- a/arch/mips/sni/rm200.c +++ b/arch/mips/sni/rm200.c | |||
@@ -5,30 +5,36 @@ | |||
5 | * License. See the file "COPYING" in the main directory of this archive | 5 | * License. See the file "COPYING" in the main directory of this archive |
6 | * for more details. | 6 | * for more details. |
7 | * | 7 | * |
8 | * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) | 8 | * Copyright (C) 2006,2007 Thomas Bogendoerfer (tsbogend@alpha.franken.de) |
9 | * | ||
10 | * i8259 parts ripped out of arch/mips/kernel/i8259.c | ||
9 | */ | 11 | */ |
10 | 12 | ||
13 | #include <linux/delay.h> | ||
11 | #include <linux/init.h> | 14 | #include <linux/init.h> |
12 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
13 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
14 | #include <linux/serial_8250.h> | 17 | #include <linux/serial_8250.h> |
18 | #include <linux/io.h> | ||
15 | 19 | ||
16 | #include <asm/sni.h> | 20 | #include <asm/sni.h> |
17 | #include <asm/time.h> | 21 | #include <asm/time.h> |
18 | #include <asm/irq_cpu.h> | 22 | #include <asm/irq_cpu.h> |
19 | 23 | ||
20 | #define PORT(_base,_irq) \ | 24 | #define RM200_I8259A_IRQ_BASE 32 |
25 | |||
26 | #define MEMPORT(_base,_irq) \ | ||
21 | { \ | 27 | { \ |
22 | .iobase = _base, \ | 28 | .mapbase = _base, \ |
23 | .irq = _irq, \ | 29 | .irq = _irq, \ |
24 | .uartclk = 1843200, \ | 30 | .uartclk = 1843200, \ |
25 | .iotype = UPIO_PORT, \ | 31 | .iotype = UPIO_MEM, \ |
26 | .flags = UPF_BOOT_AUTOCONF, \ | 32 | .flags = UPF_BOOT_AUTOCONF|UPF_IOREMAP, \ |
27 | } | 33 | } |
28 | 34 | ||
29 | static struct plat_serial8250_port rm200_data[] = { | 35 | static struct plat_serial8250_port rm200_data[] = { |
30 | PORT(0x3f8, 4), | 36 | MEMPORT(0x160003f8, RM200_I8259A_IRQ_BASE + 4), |
31 | PORT(0x2f8, 3), | 37 | MEMPORT(0x160002f8, RM200_I8259A_IRQ_BASE + 3), |
32 | { }, | 38 | { }, |
33 | }; | 39 | }; |
34 | 40 | ||
@@ -112,15 +118,311 @@ static int __init snirm_setup_devinit(void) | |||
112 | platform_device_register(&rm200_ds1216_device); | 118 | platform_device_register(&rm200_ds1216_device); |
113 | platform_device_register(&snirm_82596_rm200_pdev); | 119 | platform_device_register(&snirm_82596_rm200_pdev); |
114 | platform_device_register(&snirm_53c710_rm200_pdev); | 120 | platform_device_register(&snirm_53c710_rm200_pdev); |
121 | sni_eisa_root_init(); | ||
115 | } | 122 | } |
116 | return 0; | 123 | return 0; |
117 | } | 124 | } |
118 | 125 | ||
119 | device_initcall(snirm_setup_devinit); | 126 | device_initcall(snirm_setup_devinit); |
120 | 127 | ||
128 | /* | ||
129 | * RM200 has an ISA and an EISA bus. The iSA bus is only used | ||
130 | * for onboard devices and also has twi i8259 PICs. Since these | ||
131 | * PICs are no accessible via inb/outb the following code uses | ||
132 | * readb/writeb to access them | ||
133 | */ | ||
134 | |||
135 | DEFINE_SPINLOCK(sni_rm200_i8259A_lock); | ||
136 | #define PIC_CMD 0x00 | ||
137 | #define PIC_IMR 0x01 | ||
138 | #define PIC_ISR PIC_CMD | ||
139 | #define PIC_POLL PIC_ISR | ||
140 | #define PIC_OCW3 PIC_ISR | ||
141 | |||
142 | /* i8259A PIC related value */ | ||
143 | #define PIC_CASCADE_IR 2 | ||
144 | #define MASTER_ICW4_DEFAULT 0x01 | ||
145 | #define SLAVE_ICW4_DEFAULT 0x01 | ||
146 | |||
147 | /* | ||
148 | * This contains the irq mask for both 8259A irq controllers, | ||
149 | */ | ||
150 | static unsigned int rm200_cached_irq_mask = 0xffff; | ||
151 | static __iomem u8 *rm200_pic_master; | ||
152 | static __iomem u8 *rm200_pic_slave; | ||
153 | |||
154 | #define cached_master_mask (rm200_cached_irq_mask) | ||
155 | #define cached_slave_mask (rm200_cached_irq_mask >> 8) | ||
156 | |||
157 | static void sni_rm200_disable_8259A_irq(unsigned int irq) | ||
158 | { | ||
159 | unsigned int mask; | ||
160 | unsigned long flags; | ||
161 | |||
162 | irq -= RM200_I8259A_IRQ_BASE; | ||
163 | mask = 1 << irq; | ||
164 | spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); | ||
165 | rm200_cached_irq_mask |= mask; | ||
166 | if (irq & 8) | ||
167 | writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR); | ||
168 | else | ||
169 | writeb(cached_master_mask, rm200_pic_master + PIC_IMR); | ||
170 | spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags); | ||
171 | } | ||
172 | |||
173 | static void sni_rm200_enable_8259A_irq(unsigned int irq) | ||
174 | { | ||
175 | unsigned int mask; | ||
176 | unsigned long flags; | ||
177 | |||
178 | irq -= RM200_I8259A_IRQ_BASE; | ||
179 | mask = ~(1 << irq); | ||
180 | spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); | ||
181 | rm200_cached_irq_mask &= mask; | ||
182 | if (irq & 8) | ||
183 | writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR); | ||
184 | else | ||
185 | writeb(cached_master_mask, rm200_pic_master + PIC_IMR); | ||
186 | spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags); | ||
187 | } | ||
188 | |||
189 | static inline int sni_rm200_i8259A_irq_real(unsigned int irq) | ||
190 | { | ||
191 | int value; | ||
192 | int irqmask = 1 << irq; | ||
193 | |||
194 | if (irq < 8) { | ||
195 | writeb(0x0B, rm200_pic_master + PIC_CMD); | ||
196 | value = readb(rm200_pic_master + PIC_CMD) & irqmask; | ||
197 | writeb(0x0A, rm200_pic_master + PIC_CMD); | ||
198 | return value; | ||
199 | } | ||
200 | writeb(0x0B, rm200_pic_slave + PIC_CMD); /* ISR register */ | ||
201 | value = readb(rm200_pic_slave + PIC_CMD) & (irqmask >> 8); | ||
202 | writeb(0x0A, rm200_pic_slave + PIC_CMD); | ||
203 | return value; | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * Careful! The 8259A is a fragile beast, it pretty | ||
208 | * much _has_ to be done exactly like this (mask it | ||
209 | * first, _then_ send the EOI, and the order of EOI | ||
210 | * to the two 8259s is important! | ||
211 | */ | ||
212 | void sni_rm200_mask_and_ack_8259A(unsigned int irq) | ||
213 | { | ||
214 | unsigned int irqmask; | ||
215 | unsigned long flags; | ||
216 | |||
217 | irq -= RM200_I8259A_IRQ_BASE; | ||
218 | irqmask = 1 << irq; | ||
219 | spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); | ||
220 | /* | ||
221 | * Lightweight spurious IRQ detection. We do not want | ||
222 | * to overdo spurious IRQ handling - it's usually a sign | ||
223 | * of hardware problems, so we only do the checks we can | ||
224 | * do without slowing down good hardware unnecessarily. | ||
225 | * | ||
226 | * Note that IRQ7 and IRQ15 (the two spurious IRQs | ||
227 | * usually resulting from the 8259A-1|2 PICs) occur | ||
228 | * even if the IRQ is masked in the 8259A. Thus we | ||
229 | * can check spurious 8259A IRQs without doing the | ||
230 | * quite slow i8259A_irq_real() call for every IRQ. | ||
231 | * This does not cover 100% of spurious interrupts, | ||
232 | * but should be enough to warn the user that there | ||
233 | * is something bad going on ... | ||
234 | */ | ||
235 | if (rm200_cached_irq_mask & irqmask) | ||
236 | goto spurious_8259A_irq; | ||
237 | rm200_cached_irq_mask |= irqmask; | ||
238 | |||
239 | handle_real_irq: | ||
240 | if (irq & 8) { | ||
241 | readb(rm200_pic_slave + PIC_IMR); | ||
242 | writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR); | ||
243 | writeb(0x60+(irq & 7), rm200_pic_slave + PIC_CMD); | ||
244 | writeb(0x60+PIC_CASCADE_IR, rm200_pic_master + PIC_CMD); | ||
245 | } else { | ||
246 | readb(rm200_pic_master + PIC_IMR); | ||
247 | writeb(cached_master_mask, rm200_pic_master + PIC_IMR); | ||
248 | writeb(0x60+irq, rm200_pic_master + PIC_CMD); | ||
249 | } | ||
250 | spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags); | ||
251 | return; | ||
252 | |||
253 | spurious_8259A_irq: | ||
254 | /* | ||
255 | * this is the slow path - should happen rarely. | ||
256 | */ | ||
257 | if (sni_rm200_i8259A_irq_real(irq)) | ||
258 | /* | ||
259 | * oops, the IRQ _is_ in service according to the | ||
260 | * 8259A - not spurious, go handle it. | ||
261 | */ | ||
262 | goto handle_real_irq; | ||
263 | |||
264 | { | ||
265 | static int spurious_irq_mask; | ||
266 | /* | ||
267 | * At this point we can be sure the IRQ is spurious, | ||
268 | * lets ACK and report it. [once per IRQ] | ||
269 | */ | ||
270 | if (!(spurious_irq_mask & irqmask)) { | ||
271 | printk(KERN_DEBUG | ||
272 | "spurious RM200 8259A interrupt: IRQ%d.\n", irq); | ||
273 | spurious_irq_mask |= irqmask; | ||
274 | } | ||
275 | atomic_inc(&irq_err_count); | ||
276 | /* | ||
277 | * Theoretically we do not have to handle this IRQ, | ||
278 | * but in Linux this does not cause problems and is | ||
279 | * simpler for us. | ||
280 | */ | ||
281 | goto handle_real_irq; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | static struct irq_chip sni_rm200_i8259A_chip = { | ||
286 | .name = "RM200-XT-PIC", | ||
287 | .mask = sni_rm200_disable_8259A_irq, | ||
288 | .unmask = sni_rm200_enable_8259A_irq, | ||
289 | .mask_ack = sni_rm200_mask_and_ack_8259A, | ||
290 | }; | ||
291 | |||
292 | /* | ||
293 | * Do the traditional i8259 interrupt polling thing. This is for the few | ||
294 | * cases where no better interrupt acknowledge method is available and we | ||
295 | * absolutely must touch the i8259. | ||
296 | */ | ||
297 | static inline int sni_rm200_i8259_irq(void) | ||
298 | { | ||
299 | int irq; | ||
300 | |||
301 | spin_lock(&sni_rm200_i8259A_lock); | ||
302 | |||
303 | /* Perform an interrupt acknowledge cycle on controller 1. */ | ||
304 | writeb(0x0C, rm200_pic_master + PIC_CMD); /* prepare for poll */ | ||
305 | irq = readb(rm200_pic_master + PIC_CMD) & 7; | ||
306 | if (irq == PIC_CASCADE_IR) { | ||
307 | /* | ||
308 | * Interrupt is cascaded so perform interrupt | ||
309 | * acknowledge on controller 2. | ||
310 | */ | ||
311 | writeb(0x0C, rm200_pic_slave + PIC_CMD); /* prepare for poll */ | ||
312 | irq = (readb(rm200_pic_slave + PIC_CMD) & 7) + 8; | ||
313 | } | ||
314 | |||
315 | if (unlikely(irq == 7)) { | ||
316 | /* | ||
317 | * This may be a spurious interrupt. | ||
318 | * | ||
319 | * Read the interrupt status register (ISR). If the most | ||
320 | * significant bit is not set then there is no valid | ||
321 | * interrupt. | ||
322 | */ | ||
323 | writeb(0x0B, rm200_pic_master + PIC_ISR); /* ISR register */ | ||
324 | if (~readb(rm200_pic_master + PIC_ISR) & 0x80) | ||
325 | irq = -1; | ||
326 | } | ||
327 | |||
328 | spin_unlock(&sni_rm200_i8259A_lock); | ||
329 | |||
330 | return likely(irq >= 0) ? irq + RM200_I8259A_IRQ_BASE : irq; | ||
331 | } | ||
332 | |||
333 | void sni_rm200_init_8259A(void) | ||
334 | { | ||
335 | unsigned long flags; | ||
336 | |||
337 | spin_lock_irqsave(&sni_rm200_i8259A_lock, flags); | ||
338 | |||
339 | writeb(0xff, rm200_pic_master + PIC_IMR); | ||
340 | writeb(0xff, rm200_pic_slave + PIC_IMR); | ||
341 | |||
342 | writeb(0x11, rm200_pic_master + PIC_CMD); | ||
343 | writeb(0, rm200_pic_master + PIC_IMR); | ||
344 | writeb(1U << PIC_CASCADE_IR, rm200_pic_master + PIC_IMR); | ||
345 | writeb(MASTER_ICW4_DEFAULT, rm200_pic_master + PIC_IMR); | ||
346 | writeb(0x11, rm200_pic_slave + PIC_CMD); | ||
347 | writeb(8, rm200_pic_slave + PIC_IMR); | ||
348 | writeb(PIC_CASCADE_IR, rm200_pic_slave + PIC_IMR); | ||
349 | writeb(SLAVE_ICW4_DEFAULT, rm200_pic_slave + PIC_IMR); | ||
350 | udelay(100); /* wait for 8259A to initialize */ | ||
351 | |||
352 | writeb(cached_master_mask, rm200_pic_master + PIC_IMR); | ||
353 | writeb(cached_slave_mask, rm200_pic_slave + PIC_IMR); | ||
354 | |||
355 | spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags); | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | * IRQ2 is cascade interrupt to second interrupt controller | ||
360 | */ | ||
361 | static struct irqaction sni_rm200_irq2 = { | ||
362 | no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL | ||
363 | }; | ||
364 | |||
365 | static struct resource sni_rm200_pic1_resource = { | ||
366 | .name = "onboard ISA pic1", | ||
367 | .start = 0x16000020, | ||
368 | .end = 0x16000023, | ||
369 | .flags = IORESOURCE_BUSY | ||
370 | }; | ||
371 | |||
372 | static struct resource sni_rm200_pic2_resource = { | ||
373 | .name = "onboard ISA pic2", | ||
374 | .start = 0x160000a0, | ||
375 | .end = 0x160000a3, | ||
376 | .flags = IORESOURCE_BUSY | ||
377 | }; | ||
378 | |||
379 | /* ISA irq handler */ | ||
380 | static irqreturn_t sni_rm200_i8259A_irq_handler(int dummy, void *p) | ||
381 | { | ||
382 | int irq; | ||
383 | |||
384 | irq = sni_rm200_i8259_irq(); | ||
385 | if (unlikely(irq < 0)) | ||
386 | return IRQ_NONE; | ||
387 | |||
388 | do_IRQ(irq); | ||
389 | return IRQ_HANDLED; | ||
390 | } | ||
391 | |||
392 | struct irqaction sni_rm200_i8259A_irq = { | ||
393 | .handler = sni_rm200_i8259A_irq_handler, | ||
394 | .name = "onboard ISA", | ||
395 | .flags = IRQF_SHARED | ||
396 | }; | ||
397 | |||
398 | void __init sni_rm200_i8259_irqs(void) | ||
399 | { | ||
400 | int i; | ||
401 | |||
402 | rm200_pic_master = ioremap_nocache(0x16000020, 4); | ||
403 | if (!rm200_pic_master) | ||
404 | return; | ||
405 | rm200_pic_slave = ioremap_nocache(0x160000a0, 4); | ||
406 | if (!rm200_pic_master) { | ||
407 | iounmap(rm200_pic_master); | ||
408 | return; | ||
409 | } | ||
410 | |||
411 | insert_resource(&iomem_resource, &sni_rm200_pic1_resource); | ||
412 | insert_resource(&iomem_resource, &sni_rm200_pic2_resource); | ||
413 | |||
414 | sni_rm200_init_8259A(); | ||
415 | |||
416 | for (i = RM200_I8259A_IRQ_BASE; i < RM200_I8259A_IRQ_BASE + 16; i++) | ||
417 | set_irq_chip_and_handler(i, &sni_rm200_i8259A_chip, | ||
418 | handle_level_irq); | ||
419 | |||
420 | setup_irq(RM200_I8259A_IRQ_BASE + PIC_CASCADE_IR, &sni_rm200_irq2); | ||
421 | } | ||
422 | |||
121 | 423 | ||
122 | #define SNI_RM200_INT_STAT_REG 0xbc000000 | 424 | #define SNI_RM200_INT_STAT_REG CKSEG1ADDR(0xbc000000) |
123 | #define SNI_RM200_INT_ENA_REG 0xbc080000 | 425 | #define SNI_RM200_INT_ENA_REG CKSEG1ADDR(0xbc080000) |
124 | 426 | ||
125 | #define SNI_RM200_INT_START 24 | 427 | #define SNI_RM200_INT_START 24 |
126 | #define SNI_RM200_INT_END 28 | 428 | #define SNI_RM200_INT_END 28 |
@@ -181,17 +483,17 @@ void __init sni_rm200_irq_init(void) | |||
181 | 483 | ||
182 | * (volatile u8 *)SNI_RM200_INT_ENA_REG = 0x1f; | 484 | * (volatile u8 *)SNI_RM200_INT_ENA_REG = 0x1f; |
183 | 485 | ||
486 | sni_rm200_i8259_irqs(); | ||
184 | mips_cpu_irq_init(); | 487 | mips_cpu_irq_init(); |
185 | /* Actually we've got more interrupts to handle ... */ | 488 | /* Actually we've got more interrupts to handle ... */ |
186 | for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++) | 489 | for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++) |
187 | set_irq_chip(i, &rm200_irq_type); | 490 | set_irq_chip(i, &rm200_irq_type); |
188 | sni_hwint = sni_rm200_hwint; | 491 | sni_hwint = sni_rm200_hwint; |
189 | change_c0_status(ST0_IM, IE_IRQ0); | 492 | change_c0_status(ST0_IM, IE_IRQ0); |
190 | setup_irq(SNI_RM200_INT_START + 0, &sni_isa_irq); | 493 | setup_irq(SNI_RM200_INT_START + 0, &sni_rm200_i8259A_irq); |
494 | setup_irq(SNI_RM200_INT_START + 1, &sni_isa_irq); | ||
191 | } | 495 | } |
192 | 496 | ||
193 | void __init sni_rm200_init(void) | 497 | void __init sni_rm200_init(void) |
194 | { | 498 | { |
195 | set_io_port_base(SNI_PORT_BASE + 0x02000000); | ||
196 | ioport_resource.end += 0x02000000; | ||
197 | } | 499 | } |
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c index e8b26bdee24c..5484e1c62054 100644 --- a/arch/mips/sni/setup.c +++ b/arch/mips/sni/setup.c | |||
@@ -19,11 +19,17 @@ | |||
19 | #include <asm/sgialib.h> | 19 | #include <asm/sgialib.h> |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #ifdef CONFIG_SNIPROM | ||
23 | #include <asm/mipsprom.h> | ||
24 | #endif | ||
25 | |||
26 | #include <asm/bootinfo.h> | ||
22 | #include <asm/io.h> | 27 | #include <asm/io.h> |
23 | #include <asm/reboot.h> | 28 | #include <asm/reboot.h> |
24 | #include <asm/sni.h> | 29 | #include <asm/sni.h> |
25 | 30 | ||
26 | unsigned int sni_brd_type; | 31 | unsigned int sni_brd_type; |
32 | EXPORT_SYMBOL(sni_brd_type); | ||
27 | 33 | ||
28 | extern void sni_machine_restart(char *command); | 34 | extern void sni_machine_restart(char *command); |
29 | extern void sni_machine_power_off(void); | 35 | extern void sni_machine_power_off(void); |
@@ -47,20 +53,152 @@ static void __init sni_display_setup(void) | |||
47 | #endif | 53 | #endif |
48 | } | 54 | } |
49 | 55 | ||
56 | static void __init sni_console_setup(void) | ||
57 | { | ||
58 | #ifndef CONFIG_ARC | ||
59 | char *ctype; | ||
60 | char *cdev; | ||
61 | char *baud; | ||
62 | int port; | ||
63 | static char options[8]; | ||
64 | |||
65 | cdev = prom_getenv("console_dev"); | ||
66 | if (strncmp(cdev, "tty", 3) == 0) { | ||
67 | ctype = prom_getenv("console"); | ||
68 | switch (*ctype) { | ||
69 | default: | ||
70 | case 'l': | ||
71 | port = 0; | ||
72 | baud = prom_getenv("lbaud"); | ||
73 | break; | ||
74 | case 'r': | ||
75 | port = 1; | ||
76 | baud = prom_getenv("rbaud"); | ||
77 | break; | ||
78 | } | ||
79 | if (baud) | ||
80 | strcpy(options, baud); | ||
81 | if (strncmp(cdev, "tty552", 6) == 0) | ||
82 | add_preferred_console("ttyS", port, | ||
83 | baud ? options : NULL); | ||
84 | else | ||
85 | add_preferred_console("ttySC", port, | ||
86 | baud ? options : NULL); | ||
87 | } | ||
88 | #endif | ||
89 | } | ||
90 | |||
91 | #ifdef DEBUG | ||
92 | static void __init sni_idprom_dump(void) | ||
93 | { | ||
94 | int i; | ||
95 | |||
96 | pr_debug("SNI IDProm dump:\n"); | ||
97 | for (i = 0; i < 256; i++) { | ||
98 | if (i%16 == 0) | ||
99 | pr_debug("%04x ", i); | ||
100 | |||
101 | printk("%02x ", *(unsigned char *) (SNI_IDPROM_BASE + i)); | ||
102 | |||
103 | if (i % 16 == 15) | ||
104 | printk("\n"); | ||
105 | } | ||
106 | } | ||
107 | #endif | ||
50 | 108 | ||
51 | void __init plat_mem_setup(void) | 109 | void __init plat_mem_setup(void) |
52 | { | 110 | { |
111 | int cputype; | ||
112 | |||
53 | set_io_port_base(SNI_PORT_BASE); | 113 | set_io_port_base(SNI_PORT_BASE); |
54 | // ioport_resource.end = sni_io_resource.end; | 114 | // ioport_resource.end = sni_io_resource.end; |
55 | 115 | ||
56 | /* | 116 | /* |
57 | * Setup (E)ISA I/O memory access stuff | 117 | * Setup (E)ISA I/O memory access stuff |
58 | */ | 118 | */ |
59 | isa_slot_offset = 0xb0000000; | 119 | isa_slot_offset = CKSEG1ADDR(0xb0000000); |
60 | #ifdef CONFIG_EISA | 120 | #ifdef CONFIG_EISA |
61 | EISA_bus = 1; | 121 | EISA_bus = 1; |
62 | #endif | 122 | #endif |
63 | 123 | ||
124 | sni_brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE; | ||
125 | cputype = *(unsigned char *)SNI_IDPROM_CPUTYPE; | ||
126 | switch (sni_brd_type) { | ||
127 | case SNI_BRD_TOWER_OASIC: | ||
128 | switch (cputype) { | ||
129 | case SNI_CPU_M8030: | ||
130 | system_type = "RM400-330"; | ||
131 | break; | ||
132 | case SNI_CPU_M8031: | ||
133 | system_type = "RM400-430"; | ||
134 | break; | ||
135 | case SNI_CPU_M8037: | ||
136 | system_type = "RM400-530"; | ||
137 | break; | ||
138 | case SNI_CPU_M8034: | ||
139 | system_type = "RM400-730"; | ||
140 | break; | ||
141 | default: | ||
142 | system_type = "RM400-xxx"; | ||
143 | break; | ||
144 | } | ||
145 | break; | ||
146 | case SNI_BRD_MINITOWER: | ||
147 | switch (cputype) { | ||
148 | case SNI_CPU_M8021: | ||
149 | case SNI_CPU_M8043: | ||
150 | system_type = "RM400-120"; | ||
151 | break; | ||
152 | case SNI_CPU_M8040: | ||
153 | system_type = "RM400-220"; | ||
154 | break; | ||
155 | case SNI_CPU_M8053: | ||
156 | system_type = "RM400-225"; | ||
157 | break; | ||
158 | case SNI_CPU_M8050: | ||
159 | system_type = "RM400-420"; | ||
160 | break; | ||
161 | default: | ||
162 | system_type = "RM400-xxx"; | ||
163 | break; | ||
164 | } | ||
165 | break; | ||
166 | case SNI_BRD_PCI_TOWER: | ||
167 | system_type = "RM400-Cxx"; | ||
168 | break; | ||
169 | case SNI_BRD_RM200: | ||
170 | system_type = "RM200-xxx"; | ||
171 | break; | ||
172 | case SNI_BRD_PCI_MTOWER: | ||
173 | system_type = "RM300-Cxx"; | ||
174 | break; | ||
175 | case SNI_BRD_PCI_DESKTOP: | ||
176 | switch (read_c0_prid() & 0xff00) { | ||
177 | case PRID_IMP_R4600: | ||
178 | case PRID_IMP_R4700: | ||
179 | system_type = "RM200-C20"; | ||
180 | break; | ||
181 | case PRID_IMP_R5000: | ||
182 | system_type = "RM200-C40"; | ||
183 | break; | ||
184 | default: | ||
185 | system_type = "RM200-Cxx"; | ||
186 | break; | ||
187 | } | ||
188 | break; | ||
189 | case SNI_BRD_PCI_TOWER_CPLUS: | ||
190 | system_type = "RM400-Exx"; | ||
191 | break; | ||
192 | case SNI_BRD_PCI_MTOWER_CPLUS: | ||
193 | system_type = "RM300-Exx"; | ||
194 | break; | ||
195 | } | ||
196 | pr_debug("Found SNI brdtype %02x name %s\n", sni_brd_type, system_type); | ||
197 | |||
198 | #ifdef DEBUG | ||
199 | sni_idprom_dump(); | ||
200 | #endif | ||
201 | |||
64 | switch (sni_brd_type) { | 202 | switch (sni_brd_type) { |
65 | case SNI_BRD_10: | 203 | case SNI_BRD_10: |
66 | case SNI_BRD_10NEW: | 204 | case SNI_BRD_10NEW: |
@@ -89,9 +227,10 @@ void __init plat_mem_setup(void) | |||
89 | pm_power_off = sni_machine_power_off; | 227 | pm_power_off = sni_machine_power_off; |
90 | 228 | ||
91 | sni_display_setup(); | 229 | sni_display_setup(); |
230 | sni_console_setup(); | ||
92 | } | 231 | } |
93 | 232 | ||
94 | #if CONFIG_PCI | 233 | #ifdef CONFIG_PCI |
95 | 234 | ||
96 | #include <linux/pci.h> | 235 | #include <linux/pci.h> |
97 | #include <video/vga.h> | 236 | #include <video/vga.h> |
diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c deleted file mode 100644 index eff4b89d7b75..000000000000 --- a/arch/mips/sni/sniprom.c +++ /dev/null | |||
@@ -1,251 +0,0 @@ | |||
1 | /* | ||
2 | * Big Endian PROM code for SNI RM machines | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 2005-2006 Florian Lohoff (flo@rfc822.org) | ||
9 | * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) | ||
10 | */ | ||
11 | |||
12 | #define DEBUG | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/console.h> | ||
18 | |||
19 | #include <asm/addrspace.h> | ||
20 | #include <asm/sni.h> | ||
21 | #include <asm/mipsprom.h> | ||
22 | #include <asm/mipsregs.h> | ||
23 | #include <asm/bootinfo.h> | ||
24 | |||
25 | /* special SNI prom calls */ | ||
26 | /* | ||
27 | * This does not exist in all proms - SINIX compares | ||
28 | * the prom env variable "version" against "2.0008" | ||
29 | * or greater. If lesser it tries to probe interesting | ||
30 | * registers | ||
31 | */ | ||
32 | #define PROM_GET_MEMCONF 58 | ||
33 | |||
34 | #define PROM_VEC (u64 *)CKSEG1ADDR(0x1fc00000) | ||
35 | #define PROM_ENTRY(x) (PROM_VEC + (x)) | ||
36 | |||
37 | |||
38 | static int *(*__prom_putchar)(int) = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR); | ||
39 | |||
40 | void prom_putchar(char c) | ||
41 | { | ||
42 | __prom_putchar(c); | ||
43 | } | ||
44 | |||
45 | static char *(*__prom_getenv)(char *) = (char *(*)(char *))PROM_ENTRY(PROM_GETENV); | ||
46 | static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF); | ||
47 | |||
48 | char *prom_getenv(char *s) | ||
49 | { | ||
50 | return __prom_getenv(s); | ||
51 | } | ||
52 | |||
53 | void __init prom_free_prom_memory(void) | ||
54 | { | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * /proc/cpuinfo system type | ||
59 | * | ||
60 | */ | ||
61 | static const char *systype = "Unknown"; | ||
62 | const char *get_system_type(void) | ||
63 | { | ||
64 | return systype; | ||
65 | } | ||
66 | |||
67 | #define SNI_IDPROM_BASE 0xbff00000 | ||
68 | #define SNI_IDPROM_MEMSIZE (SNI_IDPROM_BASE+0x28) /* Memsize in 16MB quantities */ | ||
69 | #define SNI_IDPROM_BRDTYPE (SNI_IDPROM_BASE+0x29) /* Board Type */ | ||
70 | #define SNI_IDPROM_CPUTYPE (SNI_IDPROM_BASE+0x30) /* CPU Type */ | ||
71 | |||
72 | #define SNI_IDPROM_SIZE 0x1000 | ||
73 | |||
74 | #ifdef DEBUG | ||
75 | static void __init sni_idprom_dump(void) | ||
76 | { | ||
77 | int i; | ||
78 | |||
79 | pr_debug("SNI IDProm dump:\n"); | ||
80 | for (i = 0; i < 256; i++) { | ||
81 | if (i%16 == 0) | ||
82 | pr_debug("%04x ", i); | ||
83 | |||
84 | printk("%02x ", *(unsigned char *) (SNI_IDPROM_BASE + i)); | ||
85 | |||
86 | if (i % 16 == 15) | ||
87 | printk("\n"); | ||
88 | } | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | static void __init sni_mem_init(void ) | ||
93 | { | ||
94 | int i, memsize; | ||
95 | struct membank { | ||
96 | u32 size; | ||
97 | u32 base; | ||
98 | u32 size2; | ||
99 | u32 pad1; | ||
100 | u32 pad2; | ||
101 | } memconf[8]; | ||
102 | |||
103 | /* MemSIZE from prom in 16MByte chunks */ | ||
104 | memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16; | ||
105 | |||
106 | pr_debug("IDProm memsize: %lu MByte\n", memsize); | ||
107 | |||
108 | /* get memory bank layout from prom */ | ||
109 | __prom_get_memconf(&memconf); | ||
110 | |||
111 | pr_debug("prom_get_mem_conf memory configuration:\n"); | ||
112 | for (i = 0;i < 8 && memconf[i].size; i++) { | ||
113 | if (sni_brd_type == SNI_BRD_PCI_TOWER || | ||
114 | sni_brd_type == SNI_BRD_PCI_TOWER_CPLUS) { | ||
115 | if (memconf[i].base >= 0x20000000 && | ||
116 | memconf[i].base < 0x30000000) { | ||
117 | memconf[i].base -= 0x20000000; | ||
118 | } | ||
119 | } | ||
120 | pr_debug("Bank%d: %08x @ %08x\n", i, | ||
121 | memconf[i].size, memconf[i].base); | ||
122 | add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static void __init sni_console_setup(void) | ||
127 | { | ||
128 | char *ctype; | ||
129 | char *cdev; | ||
130 | char *baud; | ||
131 | int port; | ||
132 | static char options[8]; | ||
133 | |||
134 | cdev = prom_getenv("console_dev"); | ||
135 | if (strncmp (cdev, "tty", 3) == 0) { | ||
136 | ctype = prom_getenv("console"); | ||
137 | switch (*ctype) { | ||
138 | default: | ||
139 | case 'l': | ||
140 | port = 0; | ||
141 | baud = prom_getenv("lbaud"); | ||
142 | break; | ||
143 | case 'r': | ||
144 | port = 1; | ||
145 | baud = prom_getenv("rbaud"); | ||
146 | break; | ||
147 | } | ||
148 | if (baud) | ||
149 | strcpy(options, baud); | ||
150 | if (strncmp (cdev, "tty552", 6) == 0) | ||
151 | add_preferred_console("ttyS", port, baud ? options : NULL); | ||
152 | else | ||
153 | add_preferred_console("ttySC", port, baud ? options : NULL); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | void __init prom_init(void) | ||
158 | { | ||
159 | int argc = fw_arg0; | ||
160 | char **argv = (void *)fw_arg1; | ||
161 | int i; | ||
162 | int cputype; | ||
163 | |||
164 | sni_brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE; | ||
165 | cputype = *(unsigned char *)SNI_IDPROM_CPUTYPE; | ||
166 | switch (sni_brd_type) { | ||
167 | case SNI_BRD_TOWER_OASIC: | ||
168 | switch (cputype) { | ||
169 | case SNI_CPU_M8030: | ||
170 | systype = "RM400-330"; | ||
171 | break; | ||
172 | case SNI_CPU_M8031: | ||
173 | systype = "RM400-430"; | ||
174 | break; | ||
175 | case SNI_CPU_M8037: | ||
176 | systype = "RM400-530"; | ||
177 | break; | ||
178 | case SNI_CPU_M8034: | ||
179 | systype = "RM400-730"; | ||
180 | break; | ||
181 | default: | ||
182 | systype = "RM400-xxx"; | ||
183 | break; | ||
184 | } | ||
185 | break; | ||
186 | case SNI_BRD_MINITOWER: | ||
187 | switch (cputype) { | ||
188 | case SNI_CPU_M8021: | ||
189 | case SNI_CPU_M8043: | ||
190 | systype = "RM400-120"; | ||
191 | break; | ||
192 | case SNI_CPU_M8040: | ||
193 | systype = "RM400-220"; | ||
194 | break; | ||
195 | case SNI_CPU_M8053: | ||
196 | systype = "RM400-225"; | ||
197 | break; | ||
198 | case SNI_CPU_M8050: | ||
199 | systype = "RM400-420"; | ||
200 | break; | ||
201 | default: | ||
202 | systype = "RM400-xxx"; | ||
203 | break; | ||
204 | } | ||
205 | break; | ||
206 | case SNI_BRD_PCI_TOWER: | ||
207 | systype = "RM400-Cxx"; | ||
208 | break; | ||
209 | case SNI_BRD_RM200: | ||
210 | systype = "RM200-xxx"; | ||
211 | break; | ||
212 | case SNI_BRD_PCI_MTOWER: | ||
213 | systype = "RM300-Cxx"; | ||
214 | break; | ||
215 | case SNI_BRD_PCI_DESKTOP: | ||
216 | switch (read_c0_prid() & 0xff00) { | ||
217 | case PRID_IMP_R4600: | ||
218 | case PRID_IMP_R4700: | ||
219 | systype = "RM200-C20"; | ||
220 | break; | ||
221 | case PRID_IMP_R5000: | ||
222 | systype = "RM200-C40"; | ||
223 | break; | ||
224 | default: | ||
225 | systype = "RM200-Cxx"; | ||
226 | break; | ||
227 | } | ||
228 | break; | ||
229 | case SNI_BRD_PCI_TOWER_CPLUS: | ||
230 | systype = "RM400-Exx"; | ||
231 | break; | ||
232 | case SNI_BRD_PCI_MTOWER_CPLUS: | ||
233 | systype = "RM300-Exx"; | ||
234 | break; | ||
235 | } | ||
236 | pr_debug("Found SNI brdtype %02x name %s\n", sni_brd_type, systype); | ||
237 | |||
238 | #ifdef DEBUG | ||
239 | sni_idprom_dump(); | ||
240 | #endif | ||
241 | sni_mem_init(); | ||
242 | sni_console_setup(); | ||
243 | |||
244 | /* copy prom cmdline parameters to kernel cmdline */ | ||
245 | for (i = 1; i < argc; i++) { | ||
246 | strcat(arcs_cmdline, argv[i]); | ||
247 | if (i < (argc - 1)) | ||
248 | strcat(arcs_cmdline, " "); | ||
249 | } | ||
250 | } | ||
251 | |||
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c index 6f339af08d22..796e3ce28720 100644 --- a/arch/mips/sni/time.c +++ b/arch/mips/sni/time.c | |||
@@ -178,6 +178,7 @@ void __init plat_time_init(void) | |||
178 | sni_a20r_timer_setup(); | 178 | sni_a20r_timer_setup(); |
179 | break; | 179 | break; |
180 | } | 180 | } |
181 | setup_pit_timer(); | ||
181 | } | 182 | } |
182 | 183 | ||
183 | unsigned long read_persistent_clock(void) | 184 | unsigned long read_persistent_clock(void) |
diff --git a/arch/mips/tx4927/common/Makefile b/arch/mips/tx4927/common/Makefile index 18375787e094..a7fe76a64964 100644 --- a/arch/mips/tx4927/common/Makefile +++ b/arch/mips/tx4927/common/Makefile | |||
@@ -1,12 +1,8 @@ | |||
1 | # | 1 | # |
2 | # Makefile for common code for Toshiba TX4927 based systems | 2 | # Makefile for common code for Toshiba TX4927 based systems |
3 | # | 3 | # |
4 | # Note! Dependencies are done automagically by 'make dep', which also | ||
5 | # removes any old dependencies. DON'T put your own dependencies here | ||
6 | # unless it's something special (ie not a .c file). | ||
7 | # | ||
8 | 4 | ||
9 | obj-y += tx4927_prom.o tx4927_setup.o tx4927_irq.o | 5 | obj-y += tx4927_prom.o tx4927_irq.o |
10 | 6 | ||
11 | obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o | 7 | obj-$(CONFIG_TOSHIBA_FPCIB0) += smsc_fdc37m81x.o |
12 | obj-$(CONFIG_KGDB) += tx4927_dbgio.o | 8 | obj-$(CONFIG_KGDB) += tx4927_dbgio.o |
diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c deleted file mode 100644 index 36c5f200eb3d..000000000000 --- a/arch/mips/tx4927/common/tx4927_setup.c +++ /dev/null | |||
@@ -1,186 +0,0 @@ | |||
1 | /* | ||
2 | * Author: MontaVista Software, Inc. | ||
3 | * source@mvista.com | ||
4 | * | ||
5 | * Copyright 2001-2002 MontaVista Software Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
13 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
14 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
15 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
16 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | ||
17 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | ||
18 | * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
19 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
20 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
21 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License along | ||
24 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
25 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/kernel_stat.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/signal.h> | ||
32 | #include <linux/sched.h> | ||
33 | #include <linux/types.h> | ||
34 | #include <linux/interrupt.h> | ||
35 | #include <linux/ioport.h> | ||
36 | #include <linux/timex.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/random.h> | ||
39 | #include <linux/irq.h> | ||
40 | #include <linux/bitops.h> | ||
41 | #include <asm/bootinfo.h> | ||
42 | #include <asm/io.h> | ||
43 | #include <asm/irq.h> | ||
44 | #include <asm/mipsregs.h> | ||
45 | #include <asm/system.h> | ||
46 | #include <asm/time.h> | ||
47 | #include <asm/tx4927/tx4927.h> | ||
48 | |||
49 | |||
50 | #undef DEBUG | ||
51 | |||
52 | void dump_cp0(char *key); | ||
53 | |||
54 | |||
55 | void __init plat_mem_setup(void) | ||
56 | { | ||
57 | #ifdef CONFIG_TOSHIBA_RBTX4927 | ||
58 | { | ||
59 | extern void toshiba_rbtx4927_setup(void); | ||
60 | toshiba_rbtx4927_setup(); | ||
61 | } | ||
62 | #endif | ||
63 | } | ||
64 | |||
65 | void __init plat_time_init(void) | ||
66 | { | ||
67 | #ifdef CONFIG_TOSHIBA_RBTX4927 | ||
68 | { | ||
69 | extern void toshiba_rbtx4927_time_init(void); | ||
70 | toshiba_rbtx4927_time_init(); | ||
71 | } | ||
72 | #endif | ||
73 | } | ||
74 | |||
75 | #ifdef DEBUG | ||
76 | void print_cp0(char *key, int num, char *name, u32 val) | ||
77 | { | ||
78 | printk("%s cp0:%02d:%s=0x%08x\n", key, num, name, val); | ||
79 | return; | ||
80 | } | ||
81 | |||
82 | void | ||
83 | dump_cp0(char *key) | ||
84 | { | ||
85 | if (key == NULL) | ||
86 | key = ""; | ||
87 | |||
88 | print_cp0(key, 0, "INDEX ", read_c0_index()); | ||
89 | print_cp0(key, 2, "ENTRYLO1", read_c0_entrylo0()); | ||
90 | print_cp0(key, 3, "ENTRYLO2", read_c0_entrylo1()); | ||
91 | print_cp0(key, 4, "CONTEXT ", read_c0_context()); | ||
92 | print_cp0(key, 5, "PAGEMASK", read_c0_pagemask()); | ||
93 | print_cp0(key, 6, "WIRED ", read_c0_wired()); | ||
94 | //print_cp0(key, 8, "BADVADDR", read_c0_badvaddr()); | ||
95 | print_cp0(key, 9, "COUNT ", read_c0_count()); | ||
96 | print_cp0(key, 10, "ENTRYHI ", read_c0_entryhi()); | ||
97 | print_cp0(key, 11, "COMPARE ", read_c0_compare()); | ||
98 | print_cp0(key, 12, "STATUS ", read_c0_status()); | ||
99 | print_cp0(key, 13, "CAUSE ", read_c0_cause() & 0xffff87ff); | ||
100 | print_cp0(key, 16, "CONFIG ", read_c0_config()); | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | void print_pic(char *key, unsigned long reg, char *name) | ||
105 | { | ||
106 | printk(KERN_INFO "%s pic:0x%08lx:%s=0x%08x\n", key, reg, name, | ||
107 | __raw_readl((void __iomem *)reg)); | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | |||
112 | void dump_pic(char *key) | ||
113 | { | ||
114 | if (key == NULL) | ||
115 | key = ""; | ||
116 | |||
117 | print_pic(key, 0xff1ff600, "IRDEN "); | ||
118 | print_pic(key, 0xff1ff604, "IRDM0 "); | ||
119 | print_pic(key, 0xff1ff608, "IRDM1 "); | ||
120 | |||
121 | print_pic(key, 0xff1ff610, "IRLVL0 "); | ||
122 | print_pic(key, 0xff1ff614, "IRLVL1 "); | ||
123 | print_pic(key, 0xff1ff618, "IRLVL2 "); | ||
124 | print_pic(key, 0xff1ff61c, "IRLVL3 "); | ||
125 | print_pic(key, 0xff1ff620, "IRLVL4 "); | ||
126 | print_pic(key, 0xff1ff624, "IRLVL5 "); | ||
127 | print_pic(key, 0xff1ff628, "IRLVL6 "); | ||
128 | print_pic(key, 0xff1ff62c, "IRLVL7 "); | ||
129 | |||
130 | print_pic(key, 0xff1ff640, "IRMSK "); | ||
131 | print_pic(key, 0xff1ff660, "IREDC "); | ||
132 | print_pic(key, 0xff1ff680, "IRPND "); | ||
133 | print_pic(key, 0xff1ff6a0, "IRCS "); | ||
134 | |||
135 | print_pic(key, 0xff1ff514, "IRFLAG1 "); /* don't read IRLAG0 -- it hangs system */ | ||
136 | |||
137 | print_pic(key, 0xff1ff518, "IRPOL "); | ||
138 | print_pic(key, 0xff1ff51c, "IRRCNT "); | ||
139 | print_pic(key, 0xff1ff520, "IRMASKINT"); | ||
140 | print_pic(key, 0xff1ff524, "IRMASKEXT"); | ||
141 | |||
142 | return; | ||
143 | } | ||
144 | |||
145 | |||
146 | void print_addr(char *hdr, char *key, unsigned long addr) | ||
147 | { | ||
148 | printk(KERN_INFO "%s %s:0x%08lx=0x%08x\n", hdr, key, addr, | ||
149 | __raw_readl((void __iomem *)addr)); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | |||
154 | void dump_180(char *key) | ||
155 | { | ||
156 | u32 i; | ||
157 | |||
158 | for (i = 0x80000180; i < 0x80000180 + 0x80; i += 4) { | ||
159 | print_addr("180", key, i); | ||
160 | } | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | |||
165 | void dump_eh0(char *key) | ||
166 | { | ||
167 | int i; | ||
168 | extern unsigned long exception_handlers[]; | ||
169 | |||
170 | for (i = (int) exception_handlers; | ||
171 | i < (int) (exception_handlers + 20); i += 4) { | ||
172 | print_addr("eh0", key, i); | ||
173 | } | ||
174 | |||
175 | return; | ||
176 | } | ||
177 | |||
178 | void pk0(void) | ||
179 | { | ||
180 | volatile u32 val; | ||
181 | |||
182 | __asm__ __volatile__("ori %0, $26, 0":"=r"(val) | ||
183 | ); | ||
184 | printk("k0=[0x%08x]\n", val); | ||
185 | } | ||
186 | #endif | ||
diff --git a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c index 0299595ce1c4..e466e5e711d8 100644 --- a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c | |||
@@ -45,27 +45,19 @@ | |||
45 | #include <linux/init.h> | 45 | #include <linux/init.h> |
46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
47 | #include <linux/types.h> | 47 | #include <linux/types.h> |
48 | #include <linux/mm.h> | ||
49 | #include <linux/swap.h> | ||
50 | #include <linux/ioport.h> | 48 | #include <linux/ioport.h> |
51 | #include <linux/sched.h> | ||
52 | #include <linux/interrupt.h> | 49 | #include <linux/interrupt.h> |
53 | #include <linux/pci.h> | 50 | #include <linux/pci.h> |
54 | #include <linux/timex.h> | ||
55 | #include <linux/pm.h> | 51 | #include <linux/pm.h> |
56 | #include <linux/platform_device.h> | 52 | #include <linux/platform_device.h> |
53 | #include <linux/clk.h> | ||
57 | 54 | ||
58 | #include <asm/bootinfo.h> | 55 | #include <asm/bootinfo.h> |
59 | #include <asm/page.h> | ||
60 | #include <asm/io.h> | 56 | #include <asm/io.h> |
61 | #include <asm/irq.h> | ||
62 | #include <asm/irq_regs.h> | ||
63 | #include <asm/processor.h> | 57 | #include <asm/processor.h> |
64 | #include <asm/reboot.h> | 58 | #include <asm/reboot.h> |
65 | #include <asm/time.h> | 59 | #include <asm/time.h> |
66 | #include <asm/txx9tmr.h> | 60 | #include <asm/txx9tmr.h> |
67 | #include <linux/bootmem.h> | ||
68 | #include <linux/blkdev.h> | ||
69 | #ifdef CONFIG_TOSHIBA_FPCIB0 | 61 | #ifdef CONFIG_TOSHIBA_FPCIB0 |
70 | #include <asm/tx4927/smsc_fdc37m81x.h> | 62 | #include <asm/tx4927/smsc_fdc37m81x.h> |
71 | #endif | 63 | #endif |
@@ -73,42 +65,26 @@ | |||
73 | #ifdef CONFIG_PCI | 65 | #ifdef CONFIG_PCI |
74 | #include <asm/tx4927/tx4927_pci.h> | 66 | #include <asm/tx4927/tx4927_pci.h> |
75 | #endif | 67 | #endif |
76 | #ifdef CONFIG_BLK_DEV_IDEPCI | ||
77 | #include <linux/hdreg.h> | ||
78 | #include <linux/ide.h> | ||
79 | #endif | ||
80 | #ifdef CONFIG_SERIAL_TXX9 | 68 | #ifdef CONFIG_SERIAL_TXX9 |
81 | #include <linux/tty.h> | ||
82 | #include <linux/serial.h> | ||
83 | #include <linux/serial_core.h> | 69 | #include <linux/serial_core.h> |
84 | #endif | 70 | #endif |
85 | 71 | ||
86 | #undef TOSHIBA_RBTX4927_SETUP_DEBUG | 72 | #undef TOSHIBA_RBTX4927_SETUP_DEBUG |
87 | 73 | ||
88 | #ifdef TOSHIBA_RBTX4927_SETUP_DEBUG | 74 | #ifdef TOSHIBA_RBTX4927_SETUP_DEBUG |
89 | #define TOSHIBA_RBTX4927_SETUP_NONE 0x00000000 | ||
90 | |||
91 | #define TOSHIBA_RBTX4927_SETUP_INFO ( 1 << 0 ) | ||
92 | #define TOSHIBA_RBTX4927_SETUP_WARN ( 1 << 1 ) | ||
93 | #define TOSHIBA_RBTX4927_SETUP_EROR ( 1 << 2 ) | ||
94 | |||
95 | #define TOSHIBA_RBTX4927_SETUP_EFWFU ( 1 << 3 ) | ||
96 | #define TOSHIBA_RBTX4927_SETUP_SETUP ( 1 << 4 ) | 75 | #define TOSHIBA_RBTX4927_SETUP_SETUP ( 1 << 4 ) |
97 | #define TOSHIBA_RBTX4927_SETUP_PCIBIOS ( 1 << 7 ) | 76 | #define TOSHIBA_RBTX4927_SETUP_PCIBIOS ( 1 << 7 ) |
98 | #define TOSHIBA_RBTX4927_SETUP_PCI1 ( 1 << 8 ) | 77 | #define TOSHIBA_RBTX4927_SETUP_PCI1 ( 1 << 8 ) |
99 | #define TOSHIBA_RBTX4927_SETUP_PCI2 ( 1 << 9 ) | 78 | #define TOSHIBA_RBTX4927_SETUP_PCI2 ( 1 << 9 ) |
100 | #define TOSHIBA_RBTX4927_SETUP_PCI66 ( 1 << 10 ) | ||
101 | 79 | ||
102 | #define TOSHIBA_RBTX4927_SETUP_ALL 0xffffffff | 80 | #define TOSHIBA_RBTX4927_SETUP_ALL 0xffffffff |
103 | #endif | 81 | #endif |
104 | 82 | ||
105 | #ifdef TOSHIBA_RBTX4927_SETUP_DEBUG | 83 | #ifdef TOSHIBA_RBTX4927_SETUP_DEBUG |
106 | static const u32 toshiba_rbtx4927_setup_debug_flag = | 84 | static const u32 toshiba_rbtx4927_setup_debug_flag = |
107 | (TOSHIBA_RBTX4927_SETUP_NONE | TOSHIBA_RBTX4927_SETUP_INFO | | 85 | (TOSHIBA_RBTX4927_SETUP_SETUP | |
108 | TOSHIBA_RBTX4927_SETUP_WARN | TOSHIBA_RBTX4927_SETUP_EROR | | ||
109 | TOSHIBA_RBTX4927_SETUP_EFWFU | TOSHIBA_RBTX4927_SETUP_SETUP | | ||
110 | | TOSHIBA_RBTX4927_SETUP_PCIBIOS | TOSHIBA_RBTX4927_SETUP_PCI1 | | 86 | | TOSHIBA_RBTX4927_SETUP_PCIBIOS | TOSHIBA_RBTX4927_SETUP_PCI1 | |
111 | TOSHIBA_RBTX4927_SETUP_PCI2 | TOSHIBA_RBTX4927_SETUP_PCI66); | 87 | TOSHIBA_RBTX4927_SETUP_PCI2); |
112 | #endif | 88 | #endif |
113 | 89 | ||
114 | #ifdef TOSHIBA_RBTX4927_SETUP_DEBUG | 90 | #ifdef TOSHIBA_RBTX4927_SETUP_DEBUG |
@@ -718,7 +694,7 @@ void toshiba_rbtx4927_power_off(void) | |||
718 | /* no return */ | 694 | /* no return */ |
719 | } | 695 | } |
720 | 696 | ||
721 | void __init toshiba_rbtx4927_setup(void) | 697 | void __init plat_mem_setup(void) |
722 | { | 698 | { |
723 | int i; | 699 | int i; |
724 | u32 cp0_config; | 700 | u32 cp0_config; |
@@ -741,13 +717,6 @@ void __init toshiba_rbtx4927_setup(void) | |||
741 | cp0_config = cp0_config & ~(TX49_CONF_IC | TX49_CONF_DC); | 717 | cp0_config = cp0_config & ~(TX49_CONF_IC | TX49_CONF_DC); |
742 | write_c0_config(cp0_config); | 718 | write_c0_config(cp0_config); |
743 | 719 | ||
744 | #ifdef TOSHIBA_RBTX4927_SETUP_DEBUG | ||
745 | { | ||
746 | extern void dump_cp0(char *); | ||
747 | dump_cp0("toshiba_rbtx4927_early_fw_fixup"); | ||
748 | } | ||
749 | #endif | ||
750 | |||
751 | set_io_port_base(KSEG1 + TBTX4927_ISA_IO_OFFSET); | 720 | set_io_port_base(KSEG1 + TBTX4927_ISA_IO_OFFSET); |
752 | TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, | 721 | TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, |
753 | ":mips_io_port_base=0x%08lx\n", | 722 | ":mips_io_port_base=0x%08lx\n", |
@@ -835,6 +804,8 @@ void __init toshiba_rbtx4927_setup(void) | |||
835 | } | 804 | } |
836 | 805 | ||
837 | /* CCFG */ | 806 | /* CCFG */ |
807 | /* do reset on watchdog */ | ||
808 | tx4927_ccfgptr->ccfg |= TX4927_CCFG_WR; | ||
838 | /* enable Timeout BusError */ | 809 | /* enable Timeout BusError */ |
839 | if (tx4927_ccfg_toeon) | 810 | if (tx4927_ccfg_toeon) |
840 | tx4927_ccfgptr->ccfg |= TX4927_CCFG_TOE; | 811 | tx4927_ccfgptr->ccfg |= TX4927_CCFG_TOE; |
@@ -936,8 +907,7 @@ void __init toshiba_rbtx4927_setup(void) | |||
936 | "+\n"); | 907 | "+\n"); |
937 | } | 908 | } |
938 | 909 | ||
939 | void __init | 910 | void __init plat_time_init(void) |
940 | toshiba_rbtx4927_time_init(void) | ||
941 | { | 911 | { |
942 | mips_hpt_frequency = tx4927_cpu_clock / 2; | 912 | mips_hpt_frequency = tx4927_cpu_clock / 2; |
943 | if (tx4927_ccfgptr->ccfg & TX4927_CCFG_TINTDIS) | 913 | if (tx4927_ccfgptr->ccfg & TX4927_CCFG_TINTDIS) |
@@ -977,3 +947,55 @@ static int __init rbtx4927_ne_init(void) | |||
977 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; | 947 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; |
978 | } | 948 | } |
979 | device_initcall(rbtx4927_ne_init); | 949 | device_initcall(rbtx4927_ne_init); |
950 | |||
951 | /* Watchdog support */ | ||
952 | |||
953 | static int __init txx9_wdt_init(unsigned long base) | ||
954 | { | ||
955 | struct resource res = { | ||
956 | .start = base, | ||
957 | .end = base + 0x100 - 1, | ||
958 | .flags = IORESOURCE_MEM, | ||
959 | }; | ||
960 | struct platform_device *dev = | ||
961 | platform_device_register_simple("txx9wdt", -1, &res, 1); | ||
962 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; | ||
963 | } | ||
964 | |||
965 | static int __init rbtx4927_wdt_init(void) | ||
966 | { | ||
967 | return txx9_wdt_init(TX4927_TMR_REG(2) & 0xfffffffffULL); | ||
968 | } | ||
969 | device_initcall(rbtx4927_wdt_init); | ||
970 | |||
971 | /* Minimum CLK support */ | ||
972 | |||
973 | struct clk *clk_get(struct device *dev, const char *id) | ||
974 | { | ||
975 | if (!strcmp(id, "imbus_clk")) | ||
976 | return (struct clk *)50000000; | ||
977 | return ERR_PTR(-ENOENT); | ||
978 | } | ||
979 | EXPORT_SYMBOL(clk_get); | ||
980 | |||
981 | int clk_enable(struct clk *clk) | ||
982 | { | ||
983 | return 0; | ||
984 | } | ||
985 | EXPORT_SYMBOL(clk_enable); | ||
986 | |||
987 | void clk_disable(struct clk *clk) | ||
988 | { | ||
989 | } | ||
990 | EXPORT_SYMBOL(clk_disable); | ||
991 | |||
992 | unsigned long clk_get_rate(struct clk *clk) | ||
993 | { | ||
994 | return (unsigned long)clk; | ||
995 | } | ||
996 | EXPORT_SYMBOL(clk_get_rate); | ||
997 | |||
998 | void clk_put(struct clk *clk) | ||
999 | { | ||
1000 | } | ||
1001 | EXPORT_SYMBOL(clk_put); | ||
diff --git a/arch/mips/tx4938/common/Makefile b/arch/mips/tx4938/common/Makefile index 8352eca67906..56aa1ed1ee0c 100644 --- a/arch/mips/tx4938/common/Makefile +++ b/arch/mips/tx4938/common/Makefile | |||
@@ -1,12 +1,8 @@ | |||
1 | # | 1 | # |
2 | # Makefile for common code for Toshiba TX4927 based systems | 2 | # Makefile for common code for Toshiba TX4927 based systems |
3 | # | 3 | # |
4 | # Note! Dependencies are done automagically by 'make dep', which also | ||
5 | # removes any old dependencies. DON'T put your own dependencies here | ||
6 | # unless it's something special (ie not a .c file). | ||
7 | # | ||
8 | 4 | ||
9 | obj-y += prom.o setup.o irq.o | 5 | obj-y += prom.o irq.o |
10 | obj-$(CONFIG_KGDB) += dbgio.o | 6 | obj-$(CONFIG_KGDB) += dbgio.o |
11 | 7 | ||
12 | EXTRA_CFLAGS += -Werror | 8 | EXTRA_CFLAGS += -Werror |
diff --git a/arch/mips/tx4938/common/setup.c b/arch/mips/tx4938/common/setup.c deleted file mode 100644 index 3ba4101d141e..000000000000 --- a/arch/mips/tx4938/common/setup.c +++ /dev/null | |||
@@ -1,45 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/mips/tx4938/common/setup.c | ||
3 | * | ||
4 | * common tx4938 setup routines | ||
5 | * | ||
6 | * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the | ||
7 | * terms of the GNU General Public License version 2. This program is | ||
8 | * licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | * | ||
11 | * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com) | ||
12 | */ | ||
13 | |||
14 | #include <linux/errno.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel_stat.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/signal.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/timex.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/random.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/bitops.h> | ||
28 | #include <asm/bootinfo.h> | ||
29 | #include <asm/io.h> | ||
30 | #include <asm/irq.h> | ||
31 | #include <asm/mipsregs.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/time.h> | ||
34 | #include <asm/tx4938/rbtx4938.h> | ||
35 | |||
36 | extern void toshiba_rbtx4938_setup(void); | ||
37 | |||
38 | void __init tx4938_setup(void); | ||
39 | void dump_cp0(char *key); | ||
40 | |||
41 | void __init | ||
42 | plat_mem_setup(void) | ||
43 | { | ||
44 | toshiba_rbtx4938_setup(); | ||
45 | } | ||
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/Makefile b/arch/mips/tx4938/toshiba_rbtx4938/Makefile index 675bb1c3e40c..2316dd7dd1bd 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/Makefile +++ b/arch/mips/tx4938/toshiba_rbtx4938/Makefile | |||
@@ -1,10 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for common code for Toshiba TX4927 based systems | 2 | # Makefile for common code for Toshiba TX4927 based systems |
3 | # | 3 | # |
4 | # Note! Dependencies are done automagically by 'make dep', which also | ||
5 | # removes any old dependencies. DON'T put your own dependencies here | ||
6 | # unless it's something special (ie not a .c file). | ||
7 | # | ||
8 | 4 | ||
9 | obj-y += prom.o setup.o irq.o spi_eeprom.o | 5 | obj-y += prom.o setup.o irq.o spi_eeprom.o |
10 | 6 | ||
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/prom.c b/arch/mips/tx4938/toshiba_rbtx4938/prom.c index 69f21c1b7942..1644bffa501a 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/prom.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/prom.c | |||
@@ -47,7 +47,6 @@ void __init prom_init(void) | |||
47 | #ifndef CONFIG_TX4938_NAND_BOOT | 47 | #ifndef CONFIG_TX4938_NAND_BOOT |
48 | prom_init_cmdline(); | 48 | prom_init_cmdline(); |
49 | #endif | 49 | #endif |
50 | mips_machtype = MACH_TOSHIBA_RBTX4938; | ||
51 | 50 | ||
52 | msize = tx4938_get_mem_size(); | 51 | msize = tx4938_get_mem_size(); |
53 | add_memory_region(0, msize << 20, BOOT_MEM_RAM); | 52 | add_memory_region(0, msize << 20, BOOT_MEM_RAM); |
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c index 632e5d201353..61249f049cd6 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c | |||
@@ -24,16 +24,12 @@ | |||
24 | 24 | ||
25 | #include <asm/wbflush.h> | 25 | #include <asm/wbflush.h> |
26 | #include <asm/reboot.h> | 26 | #include <asm/reboot.h> |
27 | #include <asm/irq.h> | ||
28 | #include <asm/time.h> | 27 | #include <asm/time.h> |
29 | #include <asm/txx9tmr.h> | 28 | #include <asm/txx9tmr.h> |
30 | #include <asm/uaccess.h> | ||
31 | #include <asm/io.h> | 29 | #include <asm/io.h> |
32 | #include <asm/bootinfo.h> | 30 | #include <asm/bootinfo.h> |
33 | #include <asm/tx4938/rbtx4938.h> | 31 | #include <asm/tx4938/rbtx4938.h> |
34 | #ifdef CONFIG_SERIAL_TXX9 | 32 | #ifdef CONFIG_SERIAL_TXX9 |
35 | #include <linux/tty.h> | ||
36 | #include <linux/serial.h> | ||
37 | #include <linux/serial_core.h> | 33 | #include <linux/serial_core.h> |
38 | #endif | 34 | #endif |
39 | #include <linux/spi/spi.h> | 35 | #include <linux/spi/spi.h> |
@@ -728,6 +724,8 @@ void __init tx4938_board_setup(void) | |||
728 | /* CCFG */ | 724 | /* CCFG */ |
729 | /* clear WatchDogReset,BusErrorOnWrite flag (W1C) */ | 725 | /* clear WatchDogReset,BusErrorOnWrite flag (W1C) */ |
730 | tx4938_ccfgptr->ccfg |= TX4938_CCFG_WDRST | TX4938_CCFG_BEOW; | 726 | tx4938_ccfgptr->ccfg |= TX4938_CCFG_WDRST | TX4938_CCFG_BEOW; |
727 | /* do reset on watchdog */ | ||
728 | tx4938_ccfgptr->ccfg |= TX4938_CCFG_WR; | ||
731 | /* clear PCIC1 reset */ | 729 | /* clear PCIC1 reset */ |
732 | if (tx4938_ccfgptr->clkctr & TX4938_CLKCTR_PCIC1RST) | 730 | if (tx4938_ccfgptr->clkctr & TX4938_CLKCTR_PCIC1RST) |
733 | tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIC1RST; | 731 | tx4938_ccfgptr->clkctr &= ~TX4938_CLKCTR_PCIC1RST; |
@@ -855,7 +853,7 @@ void __init plat_time_init(void) | |||
855 | txx9_gbus_clock / 2); | 853 | txx9_gbus_clock / 2); |
856 | } | 854 | } |
857 | 855 | ||
858 | void __init toshiba_rbtx4938_setup(void) | 856 | void __init plat_mem_setup(void) |
859 | { | 857 | { |
860 | unsigned long long pcfg; | 858 | unsigned long long pcfg; |
861 | char *argptr; | 859 | char *argptr; |
@@ -1125,12 +1123,35 @@ static int __init rbtx4938_spi_init(void) | |||
1125 | } | 1123 | } |
1126 | arch_initcall(rbtx4938_spi_init); | 1124 | arch_initcall(rbtx4938_spi_init); |
1127 | 1125 | ||
1126 | /* Watchdog support */ | ||
1127 | |||
1128 | static int __init txx9_wdt_init(unsigned long base) | ||
1129 | { | ||
1130 | struct resource res = { | ||
1131 | .start = base, | ||
1132 | .end = base + 0x100 - 1, | ||
1133 | .flags = IORESOURCE_MEM, | ||
1134 | .parent = &tx4938_reg_resource, | ||
1135 | }; | ||
1136 | struct platform_device *dev = | ||
1137 | platform_device_register_simple("txx9wdt", -1, &res, 1); | ||
1138 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; | ||
1139 | } | ||
1140 | |||
1141 | static int __init rbtx4938_wdt_init(void) | ||
1142 | { | ||
1143 | return txx9_wdt_init(TX4938_TMR_REG(2) & 0xfffffffffULL); | ||
1144 | } | ||
1145 | device_initcall(rbtx4938_wdt_init); | ||
1146 | |||
1128 | /* Minimum CLK support */ | 1147 | /* Minimum CLK support */ |
1129 | 1148 | ||
1130 | struct clk *clk_get(struct device *dev, const char *id) | 1149 | struct clk *clk_get(struct device *dev, const char *id) |
1131 | { | 1150 | { |
1132 | if (!strcmp(id, "spi-baseclk")) | 1151 | if (!strcmp(id, "spi-baseclk")) |
1133 | return (struct clk *)(txx9_gbus_clock / 2 / 4); | 1152 | return (struct clk *)(txx9_gbus_clock / 2 / 4); |
1153 | if (!strcmp(id, "imbus_clk")) | ||
1154 | return (struct clk *)(txx9_gbus_clock / 2); | ||
1134 | return ERR_PTR(-ENOENT); | 1155 | return ERR_PTR(-ENOENT); |
1135 | } | 1156 | } |
1136 | EXPORT_SYMBOL(clk_get); | 1157 | EXPORT_SYMBOL(clk_get); |
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c index 8d760df686c4..76d4b5ed3fc0 100644 --- a/arch/mips/vr41xx/common/init.c +++ b/arch/mips/vr41xx/common/init.c | |||
@@ -40,6 +40,8 @@ void __init plat_time_init(void) | |||
40 | { | 40 | { |
41 | unsigned long tclock; | 41 | unsigned long tclock; |
42 | 42 | ||
43 | vr41xx_calculate_clock_frequency(); | ||
44 | |||
43 | tclock = vr41xx_get_tclock_frequency(); | 45 | tclock = vr41xx_get_tclock_frequency(); |
44 | if (current_cpu_data.processor_id == PRID_VR4131_REV2_0 || | 46 | if (current_cpu_data.processor_id == PRID_VR4131_REV2_0 || |
45 | current_cpu_data.processor_id == PRID_VR4131_REV2_1) | 47 | current_cpu_data.processor_id == PRID_VR4131_REV2_1) |
@@ -50,8 +52,6 @@ void __init plat_time_init(void) | |||
50 | 52 | ||
51 | void __init plat_mem_setup(void) | 53 | void __init plat_mem_setup(void) |
52 | { | 54 | { |
53 | vr41xx_calculate_clock_frequency(); | ||
54 | |||
55 | iomem_resource_init(); | 55 | iomem_resource_init(); |
56 | } | 56 | } |
57 | 57 | ||
diff --git a/arch/mips/vr41xx/nec-cmbvr4133/setup.c b/arch/mips/vr41xx/nec-cmbvr4133/setup.c index 58e47686b499..7723d2011b08 100644 --- a/arch/mips/vr41xx/nec-cmbvr4133/setup.c +++ b/arch/mips/vr41xx/nec-cmbvr4133/setup.c | |||
@@ -50,7 +50,7 @@ static struct mtd_partition cmbvr4133_mtd_parts[] = { | |||
50 | } | 50 | } |
51 | }; | 51 | }; |
52 | 52 | ||
53 | #define number_partitions (sizeof(cmbvr4133_mtd_parts)/sizeof(struct mtd_partition)) | 53 | #define number_partitions ARRAY_SIZE(cmbvr4133_mtd_parts) |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | extern void i8259_init(void); | 56 | extern void i8259_init(void); |
@@ -64,8 +64,6 @@ static void __init nec_cmbvr4133_setup(void) | |||
64 | #endif | 64 | #endif |
65 | set_io_port_base(KSEG1ADDR(0x16000000)); | 65 | set_io_port_base(KSEG1ADDR(0x16000000)); |
66 | 66 | ||
67 | mips_machtype = MACH_NEC_CMBVR4133; | ||
68 | |||
69 | #ifdef CONFIG_PCI | 67 | #ifdef CONFIG_PCI |
70 | #ifdef CONFIG_ROCKHOPPER | 68 | #ifdef CONFIG_ROCKHOPPER |
71 | ali_m5229_preinit(); | 69 | ali_m5229_preinit(); |
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index 40d0ff9b81ab..50b4a3a25d0a 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S | |||
@@ -172,11 +172,11 @@ SECTIONS | |||
172 | __init_begin = .; | 172 | __init_begin = .; |
173 | .init.text : { | 173 | .init.text : { |
174 | _sinittext = .; | 174 | _sinittext = .; |
175 | *(.init.text) | 175 | INIT_TEXT |
176 | _einittext = .; | 176 | _einittext = .; |
177 | } | 177 | } |
178 | .init.data : { | 178 | .init.data : { |
179 | *(.init.data) | 179 | INIT_DATA |
180 | } | 180 | } |
181 | . = ALIGN(16); | 181 | . = ALIGN(16); |
182 | .init.setup : { | 182 | .init.setup : { |
@@ -215,10 +215,10 @@ SECTIONS | |||
215 | * from .altinstructions and .eh_frame | 215 | * from .altinstructions and .eh_frame |
216 | */ | 216 | */ |
217 | .exit.text : { | 217 | .exit.text : { |
218 | *(.exit.text) | 218 | EXIT_TEXT |
219 | } | 219 | } |
220 | .exit.data : { | 220 | .exit.data : { |
221 | *(.exit.data) | 221 | EXIT_DATA |
222 | } | 222 | } |
223 | #ifdef CONFIG_BLK_DEV_INITRD | 223 | #ifdef CONFIG_BLK_DEV_INITRD |
224 | . = ALIGN(PAGE_SIZE); | 224 | . = ALIGN(PAGE_SIZE); |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 18e32719d0ed..4b1d98b8135e 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -65,7 +65,7 @@ obj-wlib := $(addsuffix .o, $(basename $(addprefix $(obj)/, $(src-wlib)))) | |||
65 | obj-plat := $(addsuffix .o, $(basename $(addprefix $(obj)/, $(src-plat)))) | 65 | obj-plat := $(addsuffix .o, $(basename $(addprefix $(obj)/, $(src-plat)))) |
66 | 66 | ||
67 | quiet_cmd_copy_zlib = COPY $@ | 67 | quiet_cmd_copy_zlib = COPY $@ |
68 | cmd_copy_zlib = sed "s@__attribute_used__@@;s@<linux/\([^>]*\).*@\"\1\"@" $< > $@ | 68 | cmd_copy_zlib = sed "s@__used@@;s@<linux/\([^>]*\).*@\"\1\"@" $< > $@ |
69 | 69 | ||
70 | quiet_cmd_copy_zlibheader = COPY $@ | 70 | quiet_cmd_copy_zlibheader = COPY $@ |
71 | cmd_copy_zlibheader = sed "s@<linux/\([^>]*\).*@\"\1\"@" $< > $@ | 71 | cmd_copy_zlibheader = sed "s@<linux/\([^>]*\).*@\"\1\"@" $< > $@ |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 25d9a96484dd..c8127f832df0 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -158,7 +158,7 @@ static ssize_t show_##NAME(struct sys_device *dev, char *buf) \ | |||
158 | unsigned long val = run_on_cpu(cpu->sysdev.id, read_##NAME, 0); \ | 158 | unsigned long val = run_on_cpu(cpu->sysdev.id, read_##NAME, 0); \ |
159 | return sprintf(buf, "%lx\n", val); \ | 159 | return sprintf(buf, "%lx\n", val); \ |
160 | } \ | 160 | } \ |
161 | static ssize_t __attribute_used__ \ | 161 | static ssize_t __used \ |
162 | store_##NAME(struct sys_device *dev, const char *buf, size_t count) \ | 162 | store_##NAME(struct sys_device *dev, const char *buf, size_t count) \ |
163 | { \ | 163 | { \ |
164 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); \ | 164 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); \ |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index f66fa5d966b0..0afb9e31d2a0 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
@@ -23,7 +23,7 @@ SECTIONS | |||
23 | /* Sections to be discarded. */ | 23 | /* Sections to be discarded. */ |
24 | /DISCARD/ : { | 24 | /DISCARD/ : { |
25 | *(.exitcall.exit) | 25 | *(.exitcall.exit) |
26 | *(.exit.data) | 26 | EXIT_DATA |
27 | } | 27 | } |
28 | 28 | ||
29 | . = KERNELBASE; | 29 | . = KERNELBASE; |
@@ -76,17 +76,19 @@ SECTIONS | |||
76 | 76 | ||
77 | .init.text : { | 77 | .init.text : { |
78 | _sinittext = .; | 78 | _sinittext = .; |
79 | *(.init.text) | 79 | INIT_TEXT |
80 | _einittext = .; | 80 | _einittext = .; |
81 | } | 81 | } |
82 | 82 | ||
83 | /* .exit.text is discarded at runtime, not link time, | 83 | /* .exit.text is discarded at runtime, not link time, |
84 | * to deal with references from __bug_table | 84 | * to deal with references from __bug_table |
85 | */ | 85 | */ |
86 | .exit.text : { *(.exit.text) } | 86 | .exit.text : { |
87 | EXIT_TEXT | ||
88 | } | ||
87 | 89 | ||
88 | .init.data : { | 90 | .init.data : { |
89 | *(.init.data); | 91 | INIT_DATA |
90 | __vtop_table_begin = .; | 92 | __vtop_table_begin = .; |
91 | *(.vtop_fixup); | 93 | *(.vtop_fixup); |
92 | __vtop_table_end = .; | 94 | __vtop_table_end = .; |
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index cddc250a6a5c..446a8bbb847b 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c | |||
@@ -172,15 +172,15 @@ static void power4_stop(void) | |||
172 | } | 172 | } |
173 | 173 | ||
174 | /* Fake functions used by canonicalize_pc */ | 174 | /* Fake functions used by canonicalize_pc */ |
175 | static void __attribute_used__ hypervisor_bucket(void) | 175 | static void __used hypervisor_bucket(void) |
176 | { | 176 | { |
177 | } | 177 | } |
178 | 178 | ||
179 | static void __attribute_used__ rtas_bucket(void) | 179 | static void __used rtas_bucket(void) |
180 | { | 180 | { |
181 | } | 181 | } |
182 | 182 | ||
183 | static void __attribute_used__ kernel_unknown_bucket(void) | 183 | static void __used kernel_unknown_bucket(void) |
184 | { | 184 | { |
185 | } | 185 | } |
186 | 186 | ||
diff --git a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S index 98c1212674f6..52b64fcbdfc5 100644 --- a/arch/ppc/kernel/vmlinux.lds.S +++ b/arch/ppc/kernel/vmlinux.lds.S | |||
@@ -97,14 +97,14 @@ SECTIONS | |||
97 | __init_begin = .; | 97 | __init_begin = .; |
98 | .init.text : { | 98 | .init.text : { |
99 | _sinittext = .; | 99 | _sinittext = .; |
100 | *(.init.text) | 100 | INIT_TEXT |
101 | _einittext = .; | 101 | _einittext = .; |
102 | } | 102 | } |
103 | /* .exit.text is discarded at runtime, not link time, | 103 | /* .exit.text is discarded at runtime, not link time, |
104 | to deal with references from __bug_table */ | 104 | to deal with references from __bug_table */ |
105 | .exit.text : { *(.exit.text) } | 105 | .exit.text : { EXIT_TEXT } |
106 | .init.data : { | 106 | .init.data : { |
107 | *(.init.data); | 107 | INIT_DATA |
108 | __vtop_table_begin = .; | 108 | __vtop_table_begin = .; |
109 | *(.vtop_fixup); | 109 | *(.vtop_fixup); |
110 | __vtop_table_end = .; | 110 | __vtop_table_end = .; |
@@ -164,6 +164,6 @@ SECTIONS | |||
164 | /* Sections to be discarded. */ | 164 | /* Sections to be discarded. */ |
165 | /DISCARD/ : { | 165 | /DISCARD/ : { |
166 | *(.exitcall.exit) | 166 | *(.exitcall.exit) |
167 | *(.exit.data) | 167 | EXIT_DATA |
168 | } | 168 | } |
169 | } | 169 | } |
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 936159199346..7d43c3cd3ef3 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S | |||
@@ -97,7 +97,7 @@ SECTIONS | |||
97 | __init_begin = .; | 97 | __init_begin = .; |
98 | .init.text : { | 98 | .init.text : { |
99 | _sinittext = .; | 99 | _sinittext = .; |
100 | *(.init.text) | 100 | INIT_TEXT |
101 | _einittext = .; | 101 | _einittext = .; |
102 | } | 102 | } |
103 | /* | 103 | /* |
@@ -105,11 +105,11 @@ SECTIONS | |||
105 | * to deal with references from __bug_table | 105 | * to deal with references from __bug_table |
106 | */ | 106 | */ |
107 | .exit.text : { | 107 | .exit.text : { |
108 | *(.exit.text) | 108 | EXIT_TEXT |
109 | } | 109 | } |
110 | 110 | ||
111 | .init.data : { | 111 | .init.data : { |
112 | *(.init.data) | 112 | INIT_DATA |
113 | } | 113 | } |
114 | . = ALIGN(0x100); | 114 | . = ALIGN(0x100); |
115 | .init.setup : { | 115 | .init.setup : { |
@@ -156,7 +156,7 @@ SECTIONS | |||
156 | 156 | ||
157 | /* Sections to be discarded */ | 157 | /* Sections to be discarded */ |
158 | /DISCARD/ : { | 158 | /DISCARD/ : { |
159 | *(.exit.data) | 159 | EXIT_DATA |
160 | *(.exitcall.exit) | 160 | *(.exitcall.exit) |
161 | } | 161 | } |
162 | 162 | ||
diff --git a/arch/sh/kernel/vmlinux_32.lds.S b/arch/sh/kernel/vmlinux_32.lds.S index d549fac6d3e7..c7113786ecd4 100644 --- a/arch/sh/kernel/vmlinux_32.lds.S +++ b/arch/sh/kernel/vmlinux_32.lds.S | |||
@@ -84,9 +84,9 @@ SECTIONS | |||
84 | . = ALIGN(PAGE_SIZE); /* Init code and data */ | 84 | . = ALIGN(PAGE_SIZE); /* Init code and data */ |
85 | __init_begin = .; | 85 | __init_begin = .; |
86 | _sinittext = .; | 86 | _sinittext = .; |
87 | .init.text : { *(.init.text) } | 87 | .init.text : { INIT_TEXT } |
88 | _einittext = .; | 88 | _einittext = .; |
89 | .init.data : { *(.init.data) } | 89 | .init.data : { INIT_DATA } |
90 | 90 | ||
91 | . = ALIGN(16); | 91 | . = ALIGN(16); |
92 | __setup_start = .; | 92 | __setup_start = .; |
@@ -122,8 +122,8 @@ SECTIONS | |||
122 | * .exit.text is discarded at runtime, not link time, to deal with | 122 | * .exit.text is discarded at runtime, not link time, to deal with |
123 | * references from __bug_table | 123 | * references from __bug_table |
124 | */ | 124 | */ |
125 | .exit.text : { *(.exit.text) } | 125 | .exit.text : { EXIT_TEXT } |
126 | .exit.data : { *(.exit.data) } | 126 | .exit.data : { EXIT_DATA } |
127 | 127 | ||
128 | . = ALIGN(PAGE_SIZE); | 128 | . = ALIGN(PAGE_SIZE); |
129 | .bss : { | 129 | .bss : { |
diff --git a/arch/sh/kernel/vmlinux_64.lds.S b/arch/sh/kernel/vmlinux_64.lds.S index 2fd0f7401484..3f1bd6392bb3 100644 --- a/arch/sh/kernel/vmlinux_64.lds.S +++ b/arch/sh/kernel/vmlinux_64.lds.S | |||
@@ -96,9 +96,9 @@ SECTIONS | |||
96 | . = ALIGN(PAGE_SIZE); /* Init code and data */ | 96 | . = ALIGN(PAGE_SIZE); /* Init code and data */ |
97 | __init_begin = .; | 97 | __init_begin = .; |
98 | _sinittext = .; | 98 | _sinittext = .; |
99 | .init.text : C_PHYS(.init.text) { *(.init.text) } | 99 | .init.text : C_PHYS(.init.text) { INIT_TEXT } |
100 | _einittext = .; | 100 | _einittext = .; |
101 | .init.data : C_PHYS(.init.data) { *(.init.data) } | 101 | .init.data : C_PHYS(.init.data) { INIT_DATA } |
102 | . = ALIGN(L1_CACHE_BYTES); /* Better if Cache Line aligned */ | 102 | . = ALIGN(L1_CACHE_BYTES); /* Better if Cache Line aligned */ |
103 | __setup_start = .; | 103 | __setup_start = .; |
104 | .init.setup : C_PHYS(.init.setup) { *(.init.setup) } | 104 | .init.setup : C_PHYS(.init.setup) { *(.init.setup) } |
@@ -134,8 +134,8 @@ SECTIONS | |||
134 | * .exit.text is discarded at runtime, not link time, to deal with | 134 | * .exit.text is discarded at runtime, not link time, to deal with |
135 | * references from __bug_table | 135 | * references from __bug_table |
136 | */ | 136 | */ |
137 | .exit.text : C_PHYS(.exit.text) { *(.exit.text) } | 137 | .exit.text : C_PHYS(.exit.text) { EXIT_TEXT } |
138 | .exit.data : C_PHYS(.exit.data) { *(.exit.data) } | 138 | .exit.data : C_PHYS(.exit.data) { EXIT_DATA } |
139 | 139 | ||
140 | . = ALIGN(PAGE_SIZE); | 140 | . = ALIGN(PAGE_SIZE); |
141 | .bss : C_PHYS(.bss) { | 141 | .bss : C_PHYS(.bss) { |
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index a8b4200f9cc3..216147d6e61f 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S | |||
@@ -48,12 +48,12 @@ SECTIONS | |||
48 | __init_begin = .; | 48 | __init_begin = .; |
49 | .init.text : { | 49 | .init.text : { |
50 | _sinittext = .; | 50 | _sinittext = .; |
51 | *(.init.text) | 51 | INIT_TEXT |
52 | _einittext = .; | 52 | _einittext = .; |
53 | } | 53 | } |
54 | __init_text_end = .; | 54 | __init_text_end = .; |
55 | .init.data : { | 55 | .init.data : { |
56 | *(.init.data) | 56 | INIT_DATA |
57 | } | 57 | } |
58 | . = ALIGN(16); | 58 | . = ALIGN(16); |
59 | .init.setup : { | 59 | .init.setup : { |
@@ -102,8 +102,8 @@ SECTIONS | |||
102 | _end = . ; | 102 | _end = . ; |
103 | PROVIDE (end = .); | 103 | PROVIDE (end = .); |
104 | /DISCARD/ : { | 104 | /DISCARD/ : { |
105 | *(.exit.text) | 105 | EXIT_TEXT |
106 | *(.exit.data) | 106 | EXIT_DATA |
107 | *(.exitcall.exit) | 107 | *(.exitcall.exit) |
108 | } | 108 | } |
109 | 109 | ||
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index 953be816fa25..dc7bf1b6321c 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c | |||
@@ -175,7 +175,7 @@ unsigned long compute_effective_address(struct pt_regs *regs, | |||
175 | } | 175 | } |
176 | 176 | ||
177 | /* This is just to make gcc think die_if_kernel does return... */ | 177 | /* This is just to make gcc think die_if_kernel does return... */ |
178 | static void __attribute_used__ unaligned_panic(char *str, struct pt_regs *regs) | 178 | static void __used unaligned_panic(char *str, struct pt_regs *regs) |
179 | { | 179 | { |
180 | die_if_kernel(str, regs); | 180 | die_if_kernel(str, regs); |
181 | } | 181 | } |
diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S index 9fcd503bc04a..01f809617e5e 100644 --- a/arch/sparc64/kernel/vmlinux.lds.S +++ b/arch/sparc64/kernel/vmlinux.lds.S | |||
@@ -56,11 +56,11 @@ SECTIONS | |||
56 | .init.text : { | 56 | .init.text : { |
57 | __init_begin = .; | 57 | __init_begin = .; |
58 | _sinittext = .; | 58 | _sinittext = .; |
59 | *(.init.text) | 59 | INIT_TEXT |
60 | _einittext = .; | 60 | _einittext = .; |
61 | } | 61 | } |
62 | .init.data : { | 62 | .init.data : { |
63 | *(.init.data) | 63 | INIT_DATA |
64 | } | 64 | } |
65 | . = ALIGN(16); | 65 | . = ALIGN(16); |
66 | .init.setup : { | 66 | .init.setup : { |
@@ -137,8 +137,8 @@ SECTIONS | |||
137 | PROVIDE (end = .); | 137 | PROVIDE (end = .); |
138 | 138 | ||
139 | /DISCARD/ : { | 139 | /DISCARD/ : { |
140 | *(.exit.text) | 140 | EXIT_TEXT |
141 | *(.exit.data) | 141 | EXIT_DATA |
142 | *(.exitcall.exit) | 142 | *(.exitcall.exit) |
143 | } | 143 | } |
144 | 144 | ||
diff --git a/arch/um/include/init.h b/arch/um/include/init.h index d4de7c0120ce..cebc6cae9190 100644 --- a/arch/um/include/init.h +++ b/arch/um/include/init.h | |||
@@ -42,15 +42,15 @@ typedef void (*exitcall_t)(void); | |||
42 | 42 | ||
43 | /* These are for everybody (although not all archs will actually | 43 | /* These are for everybody (although not all archs will actually |
44 | discard it in modules) */ | 44 | discard it in modules) */ |
45 | #define __init __attribute__ ((__section__ (".init.text"))) | 45 | #define __init __section(.init.text) |
46 | #define __initdata __attribute__ ((__section__ (".init.data"))) | 46 | #define __initdata __section(.init.data) |
47 | #define __exitdata __attribute__ ((__section__(".exit.data"))) | 47 | #define __exitdata __section(.exit.data) |
48 | #define __exit_call __attribute_used__ __attribute__ ((__section__ (".exitcall.exit"))) | 48 | #define __exit_call __used __section(.exitcall.exit) |
49 | 49 | ||
50 | #ifdef MODULE | 50 | #ifdef MODULE |
51 | #define __exit __attribute__ ((__section__(".exit.text"))) | 51 | #define __exit __section(.exit.text) |
52 | #else | 52 | #else |
53 | #define __exit __attribute_used__ __attribute__ ((__section__(".exit.text"))) | 53 | #define __exit __used __section(.exit.text) |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | #endif | 56 | #endif |
@@ -103,16 +103,16 @@ extern struct uml_param __uml_setup_start, __uml_setup_end; | |||
103 | * Mark functions and data as being only used at initialization | 103 | * Mark functions and data as being only used at initialization |
104 | * or exit time. | 104 | * or exit time. |
105 | */ | 105 | */ |
106 | #define __uml_init_setup __attribute_used__ __attribute__ ((__section__ (".uml.setup.init"))) | 106 | #define __uml_init_setup __used __section(.uml.setup.init) |
107 | #define __uml_setup_help __attribute_used__ __attribute__ ((__section__ (".uml.help.init"))) | 107 | #define __uml_setup_help __used __section(.uml.help.init) |
108 | #define __uml_init_call __attribute_used__ __attribute__ ((__section__ (".uml.initcall.init"))) | 108 | #define __uml_init_call __used __section(.uml.initcall.init) |
109 | #define __uml_postsetup_call __attribute_used__ __attribute__ ((__section__ (".uml.postsetup.init"))) | 109 | #define __uml_postsetup_call __used __section(.uml.postsetup.init) |
110 | #define __uml_exit_call __attribute_used__ __attribute__ ((__section__ (".uml.exitcall.exit"))) | 110 | #define __uml_exit_call __used __section(.uml.exitcall.exit) |
111 | 111 | ||
112 | #ifndef __KERNEL__ | 112 | #ifndef __KERNEL__ |
113 | 113 | ||
114 | #define __define_initcall(level,fn) \ | 114 | #define __define_initcall(level,fn) \ |
115 | static initcall_t __initcall_##fn __attribute_used__ \ | 115 | static initcall_t __initcall_##fn __used \ |
116 | __attribute__((__section__(".initcall" level ".init"))) = fn | 116 | __attribute__((__section__(".initcall" level ".init"))) = fn |
117 | 117 | ||
118 | /* Userspace initcalls shouldn't depend on anything in the kernel, so we'll | 118 | /* Userspace initcalls shouldn't depend on anything in the kernel, so we'll |
@@ -122,7 +122,7 @@ extern struct uml_param __uml_setup_start, __uml_setup_end; | |||
122 | 122 | ||
123 | #define __exitcall(fn) static exitcall_t __exitcall_##fn __exit_call = fn | 123 | #define __exitcall(fn) static exitcall_t __exitcall_##fn __exit_call = fn |
124 | 124 | ||
125 | #define __init_call __attribute_used__ __attribute__ ((__section__ (".initcall.init"))) | 125 | #define __init_call __used __section(.initcall.init) |
126 | 126 | ||
127 | #endif | 127 | #endif |
128 | 128 | ||
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 3866f4960f04..26090b7f323e 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S | |||
@@ -17,7 +17,7 @@ SECTIONS | |||
17 | __init_begin = .; | 17 | __init_begin = .; |
18 | .init.text : { | 18 | .init.text : { |
19 | _sinittext = .; | 19 | _sinittext = .; |
20 | *(.init.text) | 20 | INIT_TEXT |
21 | _einittext = .; | 21 | _einittext = .; |
22 | } | 22 | } |
23 | 23 | ||
@@ -84,7 +84,7 @@ SECTIONS | |||
84 | 84 | ||
85 | #include "asm/common.lds.S" | 85 | #include "asm/common.lds.S" |
86 | 86 | ||
87 | init.data : { *(.init.data) } | 87 | init.data : { INIT_DATA } |
88 | 88 | ||
89 | /* Ensure the __preinit_array_start label is properly aligned. We | 89 | /* Ensure the __preinit_array_start label is properly aligned. We |
90 | could instead move the label definition inside the section, but | 90 | could instead move the label definition inside the section, but |
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 13df191e2b41..5828c1d54505 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S | |||
@@ -23,7 +23,7 @@ SECTIONS | |||
23 | __init_begin = .; | 23 | __init_begin = .; |
24 | .init.text : { | 24 | .init.text : { |
25 | _sinittext = .; | 25 | _sinittext = .; |
26 | *(.init.text) | 26 | INIT_TEXT |
27 | _einittext = .; | 27 | _einittext = .; |
28 | } | 28 | } |
29 | . = ALIGN(4096); | 29 | . = ALIGN(4096); |
@@ -48,7 +48,7 @@ SECTIONS | |||
48 | 48 | ||
49 | #include "asm/common.lds.S" | 49 | #include "asm/common.lds.S" |
50 | 50 | ||
51 | init.data : { *(init.data) } | 51 | init.data : { INIT_DATA } |
52 | .data : | 52 | .data : |
53 | { | 53 | { |
54 | . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ | 54 | . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ |
diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S index 6172599b4ce2..d08cd1d27f27 100644 --- a/arch/v850/kernel/vmlinux.lds.S +++ b/arch/v850/kernel/vmlinux.lds.S | |||
@@ -114,7 +114,7 @@ | |||
114 | #define DATA_CONTENTS \ | 114 | #define DATA_CONTENTS \ |
115 | __sdata = . ; \ | 115 | __sdata = . ; \ |
116 | DATA_DATA \ | 116 | DATA_DATA \ |
117 | *(.exit.data) /* 2.5 convention */ \ | 117 | EXIT_DATA /* 2.5 convention */ \ |
118 | *(.data.exit) /* 2.4 convention */ \ | 118 | *(.data.exit) /* 2.4 convention */ \ |
119 | . = ALIGN (16) ; \ | 119 | . = ALIGN (16) ; \ |
120 | *(.data.cacheline_aligned) \ | 120 | *(.data.cacheline_aligned) \ |
@@ -157,9 +157,9 @@ | |||
157 | . = ALIGN (4096) ; \ | 157 | . = ALIGN (4096) ; \ |
158 | __init_start = . ; \ | 158 | __init_start = . ; \ |
159 | __sinittext = .; \ | 159 | __sinittext = .; \ |
160 | *(.init.text) /* 2.5 convention */ \ | 160 | INIT_TEXT /* 2.5 convention */ \ |
161 | __einittext = .; \ | 161 | __einittext = .; \ |
162 | *(.init.data) \ | 162 | INIT_DATA \ |
163 | *(.text.init) /* 2.4 convention */ \ | 163 | *(.text.init) /* 2.4 convention */ \ |
164 | *(.data.init) \ | 164 | *(.data.init) \ |
165 | INITCALL_CONTENTS \ | 165 | INITCALL_CONTENTS \ |
@@ -170,7 +170,7 @@ | |||
170 | #define ROMK_INIT_RAM_CONTENTS \ | 170 | #define ROMK_INIT_RAM_CONTENTS \ |
171 | . = ALIGN (4096) ; \ | 171 | . = ALIGN (4096) ; \ |
172 | __init_start = . ; \ | 172 | __init_start = . ; \ |
173 | *(.init.data) /* 2.5 convention */ \ | 173 | INIT_DATA /* 2.5 convention */ \ |
174 | *(.data.init) /* 2.4 convention */ \ | 174 | *(.data.init) /* 2.4 convention */ \ |
175 | __init_end = . ; \ | 175 | __init_end = . ; \ |
176 | . = ALIGN (4096) ; | 176 | . = ALIGN (4096) ; |
@@ -179,7 +179,7 @@ | |||
179 | should go into ROM. */ | 179 | should go into ROM. */ |
180 | #define ROMK_INIT_ROM_CONTENTS \ | 180 | #define ROMK_INIT_ROM_CONTENTS \ |
181 | _sinittext = .; \ | 181 | _sinittext = .; \ |
182 | *(.init.text) /* 2.5 convention */ \ | 182 | INIT_TEXT /* 2.5 convention */ \ |
183 | _einittext = .; \ | 183 | _einittext = .; \ |
184 | *(.text.init) /* 2.4 convention */ \ | 184 | *(.text.init) /* 2.4 convention */ \ |
185 | INITCALL_CONTENTS \ | 185 | INITCALL_CONTENTS \ |
diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S index 7d72cce00529..84c913f38f98 100644 --- a/arch/x86/kernel/vmlinux_32.lds.S +++ b/arch/x86/kernel/vmlinux_32.lds.S | |||
@@ -131,10 +131,12 @@ SECTIONS | |||
131 | .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { | 131 | .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { |
132 | __init_begin = .; | 132 | __init_begin = .; |
133 | _sinittext = .; | 133 | _sinittext = .; |
134 | *(.init.text) | 134 | INIT_TEXT |
135 | _einittext = .; | 135 | _einittext = .; |
136 | } | 136 | } |
137 | .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) } | 137 | .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { |
138 | INIT_DATA | ||
139 | } | ||
138 | . = ALIGN(16); | 140 | . = ALIGN(16); |
139 | .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { | 141 | .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { |
140 | __setup_start = .; | 142 | __setup_start = .; |
@@ -169,8 +171,12 @@ SECTIONS | |||
169 | } | 171 | } |
170 | /* .exit.text is discard at runtime, not link time, to deal with references | 172 | /* .exit.text is discard at runtime, not link time, to deal with references |
171 | from .altinstructions and .eh_frame */ | 173 | from .altinstructions and .eh_frame */ |
172 | .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) } | 174 | .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { |
173 | .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) } | 175 | EXIT_TEXT |
176 | } | ||
177 | .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { | ||
178 | EXIT_DATA | ||
179 | } | ||
174 | #if defined(CONFIG_BLK_DEV_INITRD) | 180 | #if defined(CONFIG_BLK_DEV_INITRD) |
175 | . = ALIGN(4096); | 181 | . = ALIGN(4096); |
176 | .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { | 182 | .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { |
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index ba8ea97abd21..ea5386944e67 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S | |||
@@ -155,12 +155,15 @@ SECTIONS | |||
155 | __init_begin = .; | 155 | __init_begin = .; |
156 | .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { | 156 | .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { |
157 | _sinittext = .; | 157 | _sinittext = .; |
158 | *(.init.text) | 158 | INIT_TEXT |
159 | _einittext = .; | 159 | _einittext = .; |
160 | } | 160 | } |
161 | __initdata_begin = .; | 161 | .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { |
162 | .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) } | 162 | __initdata_begin = .; |
163 | __initdata_end = .; | 163 | INIT_DATA |
164 | __initdata_end = .; | ||
165 | } | ||
166 | |||
164 | . = ALIGN(16); | 167 | . = ALIGN(16); |
165 | __setup_start = .; | 168 | __setup_start = .; |
166 | .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) } | 169 | .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) } |
@@ -187,8 +190,12 @@ SECTIONS | |||
187 | } | 190 | } |
188 | /* .exit.text is discard at runtime, not link time, to deal with references | 191 | /* .exit.text is discard at runtime, not link time, to deal with references |
189 | from .altinstructions and .eh_frame */ | 192 | from .altinstructions and .eh_frame */ |
190 | .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) } | 193 | .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { |
191 | .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) } | 194 | EXIT_TEXT |
195 | } | ||
196 | .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { | ||
197 | EXIT_DATA | ||
198 | } | ||
192 | 199 | ||
193 | /* vdso blob that is mapped into user space */ | 200 | /* vdso blob that is mapped into user space */ |
194 | vdso_start = . ; | 201 | vdso_start = . ; |
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index ac4ed52034db..7d0f55a4982d 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S | |||
@@ -136,13 +136,13 @@ SECTIONS | |||
136 | __init_begin = .; | 136 | __init_begin = .; |
137 | .init.text : { | 137 | .init.text : { |
138 | _sinittext = .; | 138 | _sinittext = .; |
139 | *(.init.literal) *(.init.text) | 139 | *(.init.literal) INIT_TEXT |
140 | _einittext = .; | 140 | _einittext = .; |
141 | } | 141 | } |
142 | 142 | ||
143 | .init.data : | 143 | .init.data : |
144 | { | 144 | { |
145 | *(.init.data) | 145 | INIT_DATA |
146 | . = ALIGN(0x4); | 146 | . = ALIGN(0x4); |
147 | __tagtable_begin = .; | 147 | __tagtable_begin = .; |
148 | *(.taglist) | 148 | *(.taglist) |
@@ -278,8 +278,9 @@ SECTIONS | |||
278 | /* Sections to be discarded */ | 278 | /* Sections to be discarded */ |
279 | /DISCARD/ : | 279 | /DISCARD/ : |
280 | { | 280 | { |
281 | *(.exit.literal .exit.text) | 281 | *(.exit.literal) |
282 | *(.exit.data) | 282 | EXIT_TEXT |
283 | EXIT_DATA | ||
283 | *(.exitcall.exit) | 284 | *(.exitcall.exit) |
284 | } | 285 | } |
285 | 286 | ||
diff --git a/arch/xtensa/mm/Makefile b/arch/xtensa/mm/Makefile index 10aec22a8f98..64e304a2f884 100644 --- a/arch/xtensa/mm/Makefile +++ b/arch/xtensa/mm/Makefile | |||
@@ -1,9 +1,5 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the Linux/Xtensa-specific parts of the memory manager. | 2 | # Makefile for the Linux/Xtensa-specific parts of the memory manager. |
3 | # | 3 | # |
4 | # Note! Dependencies are done automagically by 'make dep', which also | ||
5 | # removes any old dependencies. DON'T put your own dependencies here | ||
6 | # unless it's something special (ie not a .c file). | ||
7 | # | ||
8 | 4 | ||
9 | obj-y := init.o fault.o tlb.o misc.o cache.o | 5 | obj-y := init.o fault.o tlb.o misc.o cache.o |
diff --git a/arch/xtensa/platform-iss/Makefile b/arch/xtensa/platform-iss/Makefile index 5b394e9620e5..af96e314d71f 100644 --- a/arch/xtensa/platform-iss/Makefile +++ b/arch/xtensa/platform-iss/Makefile | |||
@@ -3,11 +3,6 @@ | |||
3 | # Makefile for the Xtensa Instruction Set Simulator (ISS) | 3 | # Makefile for the Xtensa Instruction Set Simulator (ISS) |
4 | # "prom monitor" library routines under Linux. | 4 | # "prom monitor" library routines under Linux. |
5 | # | 5 | # |
6 | # Note! Dependencies are done automagically by 'make dep', which also | ||
7 | # removes any old dependencies. DON'T put your own dependencies here | ||
8 | # unless it's something special (ie not a .c file). | ||
9 | # | ||
10 | # Note 2! The CFLAGS definitions are in the main makefile... | ||
11 | 6 | ||
12 | obj-y = io.o console.o setup.o network.o | 7 | obj-y = io.o console.o setup.o network.o |
13 | 8 | ||
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile index 06a86fe6a78d..de28dfd3b96c 100644 --- a/drivers/base/power/Makefile +++ b/drivers/base/power/Makefile | |||
@@ -2,9 +2,5 @@ obj-$(CONFIG_PM) += sysfs.o | |||
2 | obj-$(CONFIG_PM_SLEEP) += main.o | 2 | obj-$(CONFIG_PM_SLEEP) += main.o |
3 | obj-$(CONFIG_PM_TRACE) += trace.o | 3 | obj-$(CONFIG_PM_TRACE) += trace.o |
4 | 4 | ||
5 | ifeq ($(CONFIG_DEBUG_DRIVER),y) | 5 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG |
6 | EXTRA_CFLAGS += -DDEBUG | 6 | ccflags-$(CONFIG_PM_VERBOSE) += -DDEBUG |
7 | endif | ||
8 | ifeq ($(CONFIG_PM_VERBOSE),y) | ||
9 | EXTRA_CFLAGS += -DDEBUG | ||
10 | endif | ||
diff --git a/drivers/infiniband/hw/cxgb3/Makefile b/drivers/infiniband/hw/cxgb3/Makefile index 36b98989b15e..7e7b5a66f042 100644 --- a/drivers/infiniband/hw/cxgb3/Makefile +++ b/drivers/infiniband/hw/cxgb3/Makefile | |||
@@ -1,5 +1,4 @@ | |||
1 | EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3 \ | 1 | EXTRA_CFLAGS += -Idrivers/net/cxgb3 |
2 | -I$(TOPDIR)/drivers/infiniband/hw/cxgb3/core | ||
3 | 2 | ||
4 | obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o | 3 | obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o |
5 | 4 | ||
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h index b242cee656e7..80e3f03b5041 100644 --- a/drivers/rapidio/rio.h +++ b/drivers/rapidio/rio.h | |||
@@ -31,8 +31,8 @@ extern struct rio_route_ops __end_rio_route_ops[]; | |||
31 | 31 | ||
32 | /* Helpers internal to the RIO core code */ | 32 | /* Helpers internal to the RIO core code */ |
33 | #define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \ | 33 | #define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \ |
34 | static struct rio_route_ops __rio_route_ops __attribute_used__ \ | 34 | static struct rio_route_ops __rio_route_ops __used \ |
35 | __attribute__((__section__(#section))) = { vid, did, add_hook, get_hook }; | 35 | __section(section)= { vid, did, add_hook, get_hook }; |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * DECLARE_RIO_ROUTE_OPS - Registers switch routing operations | 38 | * DECLARE_RIO_ROUTE_OPS - Registers switch routing operations |
diff --git a/fs/Kconfig b/fs/Kconfig index 9656139d2e99..219ec06a8c7e 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -236,6 +236,7 @@ config JBD_DEBUG | |||
236 | 236 | ||
237 | config JBD2 | 237 | config JBD2 |
238 | tristate | 238 | tristate |
239 | select CRC32 | ||
239 | help | 240 | help |
240 | This is a generic journaling layer for block devices that support | 241 | This is a generic journaling layer for block devices that support |
241 | both 32-bit and 64-bit block numbers. It is currently used by | 242 | both 32-bit and 64-bit block numbers. It is currently used by |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 33fe39ad4e03..0cc3597c1197 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -546,11 +546,11 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | |||
546 | dentry->d_op = &afs_fs_dentry_operations; | 546 | dentry->d_op = &afs_fs_dentry_operations; |
547 | 547 | ||
548 | d_add(dentry, inode); | 548 | d_add(dentry, inode); |
549 | _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%lu }", | 549 | _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%llu }", |
550 | fid.vnode, | 550 | fid.vnode, |
551 | fid.unique, | 551 | fid.unique, |
552 | dentry->d_inode->i_ino, | 552 | dentry->d_inode->i_ino, |
553 | dentry->d_inode->i_version); | 553 | (unsigned long long)dentry->d_inode->i_version); |
554 | 554 | ||
555 | return NULL; | 555 | return NULL; |
556 | } | 556 | } |
@@ -630,9 +630,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
630 | * been deleted and replaced, and the original vnode ID has | 630 | * been deleted and replaced, and the original vnode ID has |
631 | * been reused */ | 631 | * been reused */ |
632 | if (fid.unique != vnode->fid.unique) { | 632 | if (fid.unique != vnode->fid.unique) { |
633 | _debug("%s: file deleted (uq %u -> %u I:%lu)", | 633 | _debug("%s: file deleted (uq %u -> %u I:%llu)", |
634 | dentry->d_name.name, fid.unique, | 634 | dentry->d_name.name, fid.unique, |
635 | vnode->fid.unique, dentry->d_inode->i_version); | 635 | vnode->fid.unique, |
636 | (unsigned long long)dentry->d_inode->i_version); | ||
636 | spin_lock(&vnode->lock); | 637 | spin_lock(&vnode->lock); |
637 | set_bit(AFS_VNODE_DELETED, &vnode->flags); | 638 | set_bit(AFS_VNODE_DELETED, &vnode->flags); |
638 | spin_unlock(&vnode->lock); | 639 | spin_unlock(&vnode->lock); |
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index d196840127c6..84750c8e9f95 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c | |||
@@ -301,7 +301,8 @@ int afs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
301 | 301 | ||
302 | inode = dentry->d_inode; | 302 | inode = dentry->d_inode; |
303 | 303 | ||
304 | _enter("{ ino=%lu v=%lu }", inode->i_ino, inode->i_version); | 304 | _enter("{ ino=%lu v=%llu }", inode->i_ino, |
305 | (unsigned long long)inode->i_version); | ||
305 | 306 | ||
306 | generic_fillattr(inode, stat); | 307 | generic_fillattr(inode, stat); |
307 | return 0; | 308 | return 0; |
diff --git a/fs/buffer.c b/fs/buffer.c index 7249e014819e..456c9ab7705b 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -3213,6 +3213,50 @@ static int buffer_cpu_notify(struct notifier_block *self, | |||
3213 | return NOTIFY_OK; | 3213 | return NOTIFY_OK; |
3214 | } | 3214 | } |
3215 | 3215 | ||
3216 | /** | ||
3217 | * bh_uptodate_or_lock: Test whether the buffer is uptodate | ||
3218 | * @bh: struct buffer_head | ||
3219 | * | ||
3220 | * Return true if the buffer is up-to-date and false, | ||
3221 | * with the buffer locked, if not. | ||
3222 | */ | ||
3223 | int bh_uptodate_or_lock(struct buffer_head *bh) | ||
3224 | { | ||
3225 | if (!buffer_uptodate(bh)) { | ||
3226 | lock_buffer(bh); | ||
3227 | if (!buffer_uptodate(bh)) | ||
3228 | return 0; | ||
3229 | unlock_buffer(bh); | ||
3230 | } | ||
3231 | return 1; | ||
3232 | } | ||
3233 | EXPORT_SYMBOL(bh_uptodate_or_lock); | ||
3234 | |||
3235 | /** | ||
3236 | * bh_submit_read: Submit a locked buffer for reading | ||
3237 | * @bh: struct buffer_head | ||
3238 | * | ||
3239 | * Returns zero on success and -EIO on error. | ||
3240 | */ | ||
3241 | int bh_submit_read(struct buffer_head *bh) | ||
3242 | { | ||
3243 | BUG_ON(!buffer_locked(bh)); | ||
3244 | |||
3245 | if (buffer_uptodate(bh)) { | ||
3246 | unlock_buffer(bh); | ||
3247 | return 0; | ||
3248 | } | ||
3249 | |||
3250 | get_bh(bh); | ||
3251 | bh->b_end_io = end_buffer_read_sync; | ||
3252 | submit_bh(READ, bh); | ||
3253 | wait_on_buffer(bh); | ||
3254 | if (buffer_uptodate(bh)) | ||
3255 | return 0; | ||
3256 | return -EIO; | ||
3257 | } | ||
3258 | EXPORT_SYMBOL(bh_submit_read); | ||
3259 | |||
3216 | void __init buffer_init(void) | 3260 | void __init buffer_init(void) |
3217 | { | 3261 | { |
3218 | int nrpages; | 3262 | int nrpages; |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index da8cb3b3592c..ffdc022cae64 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -1376,7 +1376,7 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) | |||
1376 | return -EINVAL; | 1376 | return -EINVAL; |
1377 | } | 1377 | } |
1378 | 1378 | ||
1379 | static __attribute_used__ int | 1379 | static __used int |
1380 | ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) | 1380 | ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) |
1381 | { | 1381 | { |
1382 | return -EINVAL; | 1382 | return -EINVAL; |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 154e25f13d77..6abaf75163f0 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -680,11 +680,31 @@ static int ext2_check_descriptors (struct super_block * sb) | |||
680 | static loff_t ext2_max_size(int bits) | 680 | static loff_t ext2_max_size(int bits) |
681 | { | 681 | { |
682 | loff_t res = EXT2_NDIR_BLOCKS; | 682 | loff_t res = EXT2_NDIR_BLOCKS; |
683 | /* This constant is calculated to be the largest file size for a | 683 | int meta_blocks; |
684 | * dense, 4k-blocksize file such that the total number of | 684 | loff_t upper_limit; |
685 | |||
686 | /* This is calculated to be the largest file size for a | ||
687 | * dense, file such that the total number of | ||
685 | * sectors in the file, including data and all indirect blocks, | 688 | * sectors in the file, including data and all indirect blocks, |
686 | * does not exceed 2^32. */ | 689 | * does not exceed 2^32 -1 |
687 | const loff_t upper_limit = 0x1ff7fffd000LL; | 690 | * __u32 i_blocks representing the total number of |
691 | * 512 bytes blocks of the file | ||
692 | */ | ||
693 | upper_limit = (1LL << 32) - 1; | ||
694 | |||
695 | /* total blocks in file system block size */ | ||
696 | upper_limit >>= (bits - 9); | ||
697 | |||
698 | |||
699 | /* indirect blocks */ | ||
700 | meta_blocks = 1; | ||
701 | /* double indirect blocks */ | ||
702 | meta_blocks += 1 + (1LL << (bits-2)); | ||
703 | /* tripple indirect blocks */ | ||
704 | meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2))); | ||
705 | |||
706 | upper_limit -= meta_blocks; | ||
707 | upper_limit <<= bits; | ||
688 | 708 | ||
689 | res += 1LL << (bits-2); | 709 | res += 1LL << (bits-2); |
690 | res += 1LL << (2*(bits-2)); | 710 | res += 1LL << (2*(bits-2)); |
@@ -692,6 +712,10 @@ static loff_t ext2_max_size(int bits) | |||
692 | res <<= bits; | 712 | res <<= bits; |
693 | if (res > upper_limit) | 713 | if (res > upper_limit) |
694 | res = upper_limit; | 714 | res = upper_limit; |
715 | |||
716 | if (res > MAX_LFS_FILESIZE) | ||
717 | res = MAX_LFS_FILESIZE; | ||
718 | |||
695 | return res; | 719 | return res; |
696 | } | 720 | } |
697 | 721 | ||
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index cb14de1502c3..f3675cc630e9 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -1436,11 +1436,31 @@ static void ext3_orphan_cleanup (struct super_block * sb, | |||
1436 | static loff_t ext3_max_size(int bits) | 1436 | static loff_t ext3_max_size(int bits) |
1437 | { | 1437 | { |
1438 | loff_t res = EXT3_NDIR_BLOCKS; | 1438 | loff_t res = EXT3_NDIR_BLOCKS; |
1439 | /* This constant is calculated to be the largest file size for a | 1439 | int meta_blocks; |
1440 | * dense, 4k-blocksize file such that the total number of | 1440 | loff_t upper_limit; |
1441 | |||
1442 | /* This is calculated to be the largest file size for a | ||
1443 | * dense, file such that the total number of | ||
1441 | * sectors in the file, including data and all indirect blocks, | 1444 | * sectors in the file, including data and all indirect blocks, |
1442 | * does not exceed 2^32. */ | 1445 | * does not exceed 2^32 -1 |
1443 | const loff_t upper_limit = 0x1ff7fffd000LL; | 1446 | * __u32 i_blocks representing the total number of |
1447 | * 512 bytes blocks of the file | ||
1448 | */ | ||
1449 | upper_limit = (1LL << 32) - 1; | ||
1450 | |||
1451 | /* total blocks in file system block size */ | ||
1452 | upper_limit >>= (bits - 9); | ||
1453 | |||
1454 | |||
1455 | /* indirect blocks */ | ||
1456 | meta_blocks = 1; | ||
1457 | /* double indirect blocks */ | ||
1458 | meta_blocks += 1 + (1LL << (bits-2)); | ||
1459 | /* tripple indirect blocks */ | ||
1460 | meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2))); | ||
1461 | |||
1462 | upper_limit -= meta_blocks; | ||
1463 | upper_limit <<= bits; | ||
1444 | 1464 | ||
1445 | res += 1LL << (bits-2); | 1465 | res += 1LL << (bits-2); |
1446 | res += 1LL << (2*(bits-2)); | 1466 | res += 1LL << (2*(bits-2)); |
@@ -1448,6 +1468,10 @@ static loff_t ext3_max_size(int bits) | |||
1448 | res <<= bits; | 1468 | res <<= bits; |
1449 | if (res > upper_limit) | 1469 | if (res > upper_limit) |
1450 | res = upper_limit; | 1470 | res = upper_limit; |
1471 | |||
1472 | if (res > MAX_LFS_FILESIZE) | ||
1473 | res = MAX_LFS_FILESIZE; | ||
1474 | |||
1451 | return res; | 1475 | return res; |
1452 | } | 1476 | } |
1453 | 1477 | ||
diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile index ae6e7e502ac9..ac6fa8ca0a2f 100644 --- a/fs/ext4/Makefile +++ b/fs/ext4/Makefile | |||
@@ -6,7 +6,7 @@ obj-$(CONFIG_EXT4DEV_FS) += ext4dev.o | |||
6 | 6 | ||
7 | ext4dev-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ | 7 | ext4dev-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ |
8 | ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ | 8 | ioctl.o namei.o super.o symlink.o hash.o resize.o extents.o \ |
9 | ext4_jbd2.o | 9 | ext4_jbd2.o migrate.o mballoc.o |
10 | 10 | ||
11 | ext4dev-$(CONFIG_EXT4DEV_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o | 11 | ext4dev-$(CONFIG_EXT4DEV_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o |
12 | ext4dev-$(CONFIG_EXT4DEV_FS_POSIX_ACL) += acl.o | 12 | ext4dev-$(CONFIG_EXT4DEV_FS_POSIX_ACL) += acl.o |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 71ee95e534fd..ac75ea953d83 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -29,7 +29,7 @@ | |||
29 | * Calculate the block group number and offset, given a block number | 29 | * Calculate the block group number and offset, given a block number |
30 | */ | 30 | */ |
31 | void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, | 31 | void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, |
32 | unsigned long *blockgrpp, ext4_grpblk_t *offsetp) | 32 | ext4_group_t *blockgrpp, ext4_grpblk_t *offsetp) |
33 | { | 33 | { |
34 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | 34 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; |
35 | ext4_grpblk_t offset; | 35 | ext4_grpblk_t offset; |
@@ -46,7 +46,7 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr, | |||
46 | /* Initializes an uninitialized block bitmap if given, and returns the | 46 | /* Initializes an uninitialized block bitmap if given, and returns the |
47 | * number of blocks free in the group. */ | 47 | * number of blocks free in the group. */ |
48 | unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | 48 | unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, |
49 | int block_group, struct ext4_group_desc *gdp) | 49 | ext4_group_t block_group, struct ext4_group_desc *gdp) |
50 | { | 50 | { |
51 | unsigned long start; | 51 | unsigned long start; |
52 | int bit, bit_max; | 52 | int bit, bit_max; |
@@ -60,7 +60,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
60 | * essentially implementing a per-group read-only flag. */ | 60 | * essentially implementing a per-group read-only flag. */ |
61 | if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { | 61 | if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { |
62 | ext4_error(sb, __FUNCTION__, | 62 | ext4_error(sb, __FUNCTION__, |
63 | "Checksum bad for group %u\n", block_group); | 63 | "Checksum bad for group %lu\n", block_group); |
64 | gdp->bg_free_blocks_count = 0; | 64 | gdp->bg_free_blocks_count = 0; |
65 | gdp->bg_free_inodes_count = 0; | 65 | gdp->bg_free_inodes_count = 0; |
66 | gdp->bg_itable_unused = 0; | 66 | gdp->bg_itable_unused = 0; |
@@ -153,7 +153,7 @@ unsigned ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
153 | * group descriptor | 153 | * group descriptor |
154 | */ | 154 | */ |
155 | struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, | 155 | struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, |
156 | unsigned int block_group, | 156 | ext4_group_t block_group, |
157 | struct buffer_head ** bh) | 157 | struct buffer_head ** bh) |
158 | { | 158 | { |
159 | unsigned long group_desc; | 159 | unsigned long group_desc; |
@@ -164,7 +164,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, | |||
164 | if (block_group >= sbi->s_groups_count) { | 164 | if (block_group >= sbi->s_groups_count) { |
165 | ext4_error (sb, "ext4_get_group_desc", | 165 | ext4_error (sb, "ext4_get_group_desc", |
166 | "block_group >= groups_count - " | 166 | "block_group >= groups_count - " |
167 | "block_group = %d, groups_count = %lu", | 167 | "block_group = %lu, groups_count = %lu", |
168 | block_group, sbi->s_groups_count); | 168 | block_group, sbi->s_groups_count); |
169 | 169 | ||
170 | return NULL; | 170 | return NULL; |
@@ -176,7 +176,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, | |||
176 | if (!sbi->s_group_desc[group_desc]) { | 176 | if (!sbi->s_group_desc[group_desc]) { |
177 | ext4_error (sb, "ext4_get_group_desc", | 177 | ext4_error (sb, "ext4_get_group_desc", |
178 | "Group descriptor not loaded - " | 178 | "Group descriptor not loaded - " |
179 | "block_group = %d, group_desc = %lu, desc = %lu", | 179 | "block_group = %lu, group_desc = %lu, desc = %lu", |
180 | block_group, group_desc, offset); | 180 | block_group, group_desc, offset); |
181 | return NULL; | 181 | return NULL; |
182 | } | 182 | } |
@@ -189,18 +189,70 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, | |||
189 | return desc; | 189 | return desc; |
190 | } | 190 | } |
191 | 191 | ||
192 | static int ext4_valid_block_bitmap(struct super_block *sb, | ||
193 | struct ext4_group_desc *desc, | ||
194 | unsigned int block_group, | ||
195 | struct buffer_head *bh) | ||
196 | { | ||
197 | ext4_grpblk_t offset; | ||
198 | ext4_grpblk_t next_zero_bit; | ||
199 | ext4_fsblk_t bitmap_blk; | ||
200 | ext4_fsblk_t group_first_block; | ||
201 | |||
202 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) { | ||
203 | /* with FLEX_BG, the inode/block bitmaps and itable | ||
204 | * blocks may not be in the group at all | ||
205 | * so the bitmap validation will be skipped for those groups | ||
206 | * or it has to also read the block group where the bitmaps | ||
207 | * are located to verify they are set. | ||
208 | */ | ||
209 | return 1; | ||
210 | } | ||
211 | group_first_block = ext4_group_first_block_no(sb, block_group); | ||
212 | |||
213 | /* check whether block bitmap block number is set */ | ||
214 | bitmap_blk = ext4_block_bitmap(sb, desc); | ||
215 | offset = bitmap_blk - group_first_block; | ||
216 | if (!ext4_test_bit(offset, bh->b_data)) | ||
217 | /* bad block bitmap */ | ||
218 | goto err_out; | ||
219 | |||
220 | /* check whether the inode bitmap block number is set */ | ||
221 | bitmap_blk = ext4_inode_bitmap(sb, desc); | ||
222 | offset = bitmap_blk - group_first_block; | ||
223 | if (!ext4_test_bit(offset, bh->b_data)) | ||
224 | /* bad block bitmap */ | ||
225 | goto err_out; | ||
226 | |||
227 | /* check whether the inode table block number is set */ | ||
228 | bitmap_blk = ext4_inode_table(sb, desc); | ||
229 | offset = bitmap_blk - group_first_block; | ||
230 | next_zero_bit = ext4_find_next_zero_bit(bh->b_data, | ||
231 | offset + EXT4_SB(sb)->s_itb_per_group, | ||
232 | offset); | ||
233 | if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group) | ||
234 | /* good bitmap for inode tables */ | ||
235 | return 1; | ||
236 | |||
237 | err_out: | ||
238 | ext4_error(sb, __FUNCTION__, | ||
239 | "Invalid block bitmap - " | ||
240 | "block_group = %d, block = %llu", | ||
241 | block_group, bitmap_blk); | ||
242 | return 0; | ||
243 | } | ||
192 | /** | 244 | /** |
193 | * read_block_bitmap() | 245 | * read_block_bitmap() |
194 | * @sb: super block | 246 | * @sb: super block |
195 | * @block_group: given block group | 247 | * @block_group: given block group |
196 | * | 248 | * |
197 | * Read the bitmap for a given block_group, reading into the specified | 249 | * Read the bitmap for a given block_group,and validate the |
198 | * slot in the superblock's bitmap cache. | 250 | * bits for block/inode/inode tables are set in the bitmaps |
199 | * | 251 | * |
200 | * Return buffer_head on success or NULL in case of failure. | 252 | * Return buffer_head on success or NULL in case of failure. |
201 | */ | 253 | */ |
202 | struct buffer_head * | 254 | struct buffer_head * |
203 | read_block_bitmap(struct super_block *sb, unsigned int block_group) | 255 | read_block_bitmap(struct super_block *sb, ext4_group_t block_group) |
204 | { | 256 | { |
205 | struct ext4_group_desc * desc; | 257 | struct ext4_group_desc * desc; |
206 | struct buffer_head * bh = NULL; | 258 | struct buffer_head * bh = NULL; |
@@ -210,25 +262,36 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group) | |||
210 | if (!desc) | 262 | if (!desc) |
211 | return NULL; | 263 | return NULL; |
212 | bitmap_blk = ext4_block_bitmap(sb, desc); | 264 | bitmap_blk = ext4_block_bitmap(sb, desc); |
265 | bh = sb_getblk(sb, bitmap_blk); | ||
266 | if (unlikely(!bh)) { | ||
267 | ext4_error(sb, __FUNCTION__, | ||
268 | "Cannot read block bitmap - " | ||
269 | "block_group = %d, block_bitmap = %llu", | ||
270 | (int)block_group, (unsigned long long)bitmap_blk); | ||
271 | return NULL; | ||
272 | } | ||
273 | if (bh_uptodate_or_lock(bh)) | ||
274 | return bh; | ||
275 | |||
213 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 276 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { |
214 | bh = sb_getblk(sb, bitmap_blk); | 277 | ext4_init_block_bitmap(sb, bh, block_group, desc); |
215 | if (!buffer_uptodate(bh)) { | 278 | set_buffer_uptodate(bh); |
216 | lock_buffer(bh); | 279 | unlock_buffer(bh); |
217 | if (!buffer_uptodate(bh)) { | 280 | return bh; |
218 | ext4_init_block_bitmap(sb, bh, block_group, | ||
219 | desc); | ||
220 | set_buffer_uptodate(bh); | ||
221 | } | ||
222 | unlock_buffer(bh); | ||
223 | } | ||
224 | } else { | ||
225 | bh = sb_bread(sb, bitmap_blk); | ||
226 | } | 281 | } |
227 | if (!bh) | 282 | if (bh_submit_read(bh) < 0) { |
228 | ext4_error (sb, __FUNCTION__, | 283 | put_bh(bh); |
284 | ext4_error(sb, __FUNCTION__, | ||
229 | "Cannot read block bitmap - " | 285 | "Cannot read block bitmap - " |
230 | "block_group = %d, block_bitmap = %llu", | 286 | "block_group = %d, block_bitmap = %llu", |
231 | block_group, bitmap_blk); | 287 | (int)block_group, (unsigned long long)bitmap_blk); |
288 | return NULL; | ||
289 | } | ||
290 | if (!ext4_valid_block_bitmap(sb, desc, block_group, bh)) { | ||
291 | put_bh(bh); | ||
292 | return NULL; | ||
293 | } | ||
294 | |||
232 | return bh; | 295 | return bh; |
233 | } | 296 | } |
234 | /* | 297 | /* |
@@ -320,7 +383,7 @@ restart: | |||
320 | */ | 383 | */ |
321 | static int | 384 | static int |
322 | goal_in_my_reservation(struct ext4_reserve_window *rsv, ext4_grpblk_t grp_goal, | 385 | goal_in_my_reservation(struct ext4_reserve_window *rsv, ext4_grpblk_t grp_goal, |
323 | unsigned int group, struct super_block * sb) | 386 | ext4_group_t group, struct super_block *sb) |
324 | { | 387 | { |
325 | ext4_fsblk_t group_first_block, group_last_block; | 388 | ext4_fsblk_t group_first_block, group_last_block; |
326 | 389 | ||
@@ -463,7 +526,7 @@ static inline int rsv_is_empty(struct ext4_reserve_window *rsv) | |||
463 | * when setting the reservation window size through ioctl before the file | 526 | * when setting the reservation window size through ioctl before the file |
464 | * is open for write (needs block allocation). | 527 | * is open for write (needs block allocation). |
465 | * | 528 | * |
466 | * Needs truncate_mutex protection prior to call this function. | 529 | * Needs down_write(i_data_sem) protection prior to call this function. |
467 | */ | 530 | */ |
468 | void ext4_init_block_alloc_info(struct inode *inode) | 531 | void ext4_init_block_alloc_info(struct inode *inode) |
469 | { | 532 | { |
@@ -514,6 +577,8 @@ void ext4_discard_reservation(struct inode *inode) | |||
514 | struct ext4_reserve_window_node *rsv; | 577 | struct ext4_reserve_window_node *rsv; |
515 | spinlock_t *rsv_lock = &EXT4_SB(inode->i_sb)->s_rsv_window_lock; | 578 | spinlock_t *rsv_lock = &EXT4_SB(inode->i_sb)->s_rsv_window_lock; |
516 | 579 | ||
580 | ext4_mb_discard_inode_preallocations(inode); | ||
581 | |||
517 | if (!block_i) | 582 | if (!block_i) |
518 | return; | 583 | return; |
519 | 584 | ||
@@ -540,7 +605,7 @@ void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb, | |||
540 | { | 605 | { |
541 | struct buffer_head *bitmap_bh = NULL; | 606 | struct buffer_head *bitmap_bh = NULL; |
542 | struct buffer_head *gd_bh; | 607 | struct buffer_head *gd_bh; |
543 | unsigned long block_group; | 608 | ext4_group_t block_group; |
544 | ext4_grpblk_t bit; | 609 | ext4_grpblk_t bit; |
545 | unsigned long i; | 610 | unsigned long i; |
546 | unsigned long overflow; | 611 | unsigned long overflow; |
@@ -587,11 +652,13 @@ do_more: | |||
587 | in_range(ext4_inode_bitmap(sb, desc), block, count) || | 652 | in_range(ext4_inode_bitmap(sb, desc), block, count) || |
588 | in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) || | 653 | in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) || |
589 | in_range(block + count - 1, ext4_inode_table(sb, desc), | 654 | in_range(block + count - 1, ext4_inode_table(sb, desc), |
590 | sbi->s_itb_per_group)) | 655 | sbi->s_itb_per_group)) { |
591 | ext4_error (sb, "ext4_free_blocks", | 656 | ext4_error (sb, "ext4_free_blocks", |
592 | "Freeing blocks in system zones - " | 657 | "Freeing blocks in system zones - " |
593 | "Block = %llu, count = %lu", | 658 | "Block = %llu, count = %lu", |
594 | block, count); | 659 | block, count); |
660 | goto error_return; | ||
661 | } | ||
595 | 662 | ||
596 | /* | 663 | /* |
597 | * We are about to start releasing blocks in the bitmap, | 664 | * We are about to start releasing blocks in the bitmap, |
@@ -720,19 +787,29 @@ error_return: | |||
720 | * @inode: inode | 787 | * @inode: inode |
721 | * @block: start physical block to free | 788 | * @block: start physical block to free |
722 | * @count: number of blocks to count | 789 | * @count: number of blocks to count |
790 | * @metadata: Are these metadata blocks | ||
723 | */ | 791 | */ |
724 | void ext4_free_blocks(handle_t *handle, struct inode *inode, | 792 | void ext4_free_blocks(handle_t *handle, struct inode *inode, |
725 | ext4_fsblk_t block, unsigned long count) | 793 | ext4_fsblk_t block, unsigned long count, |
794 | int metadata) | ||
726 | { | 795 | { |
727 | struct super_block * sb; | 796 | struct super_block * sb; |
728 | unsigned long dquot_freed_blocks; | 797 | unsigned long dquot_freed_blocks; |
729 | 798 | ||
799 | /* this isn't the right place to decide whether block is metadata | ||
800 | * inode.c/extents.c knows better, but for safety ... */ | ||
801 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode) || | ||
802 | ext4_should_journal_data(inode)) | ||
803 | metadata = 1; | ||
804 | |||
730 | sb = inode->i_sb; | 805 | sb = inode->i_sb; |
731 | if (!sb) { | 806 | |
732 | printk ("ext4_free_blocks: nonexistent device"); | 807 | if (!test_opt(sb, MBALLOC) || !EXT4_SB(sb)->s_group_info) |
733 | return; | 808 | ext4_free_blocks_sb(handle, sb, block, count, |
734 | } | 809 | &dquot_freed_blocks); |
735 | ext4_free_blocks_sb(handle, sb, block, count, &dquot_freed_blocks); | 810 | else |
811 | ext4_mb_free_blocks(handle, inode, block, count, | ||
812 | metadata, &dquot_freed_blocks); | ||
736 | if (dquot_freed_blocks) | 813 | if (dquot_freed_blocks) |
737 | DQUOT_FREE_BLOCK(inode, dquot_freed_blocks); | 814 | DQUOT_FREE_BLOCK(inode, dquot_freed_blocks); |
738 | return; | 815 | return; |
@@ -920,9 +997,10 @@ claim_block(spinlock_t *lock, ext4_grpblk_t block, struct buffer_head *bh) | |||
920 | * ext4_journal_release_buffer(), else we'll run out of credits. | 997 | * ext4_journal_release_buffer(), else we'll run out of credits. |
921 | */ | 998 | */ |
922 | static ext4_grpblk_t | 999 | static ext4_grpblk_t |
923 | ext4_try_to_allocate(struct super_block *sb, handle_t *handle, int group, | 1000 | ext4_try_to_allocate(struct super_block *sb, handle_t *handle, |
924 | struct buffer_head *bitmap_bh, ext4_grpblk_t grp_goal, | 1001 | ext4_group_t group, struct buffer_head *bitmap_bh, |
925 | unsigned long *count, struct ext4_reserve_window *my_rsv) | 1002 | ext4_grpblk_t grp_goal, unsigned long *count, |
1003 | struct ext4_reserve_window *my_rsv) | ||
926 | { | 1004 | { |
927 | ext4_fsblk_t group_first_block; | 1005 | ext4_fsblk_t group_first_block; |
928 | ext4_grpblk_t start, end; | 1006 | ext4_grpblk_t start, end; |
@@ -1156,7 +1234,7 @@ static int find_next_reservable_window( | |||
1156 | */ | 1234 | */ |
1157 | static int alloc_new_reservation(struct ext4_reserve_window_node *my_rsv, | 1235 | static int alloc_new_reservation(struct ext4_reserve_window_node *my_rsv, |
1158 | ext4_grpblk_t grp_goal, struct super_block *sb, | 1236 | ext4_grpblk_t grp_goal, struct super_block *sb, |
1159 | unsigned int group, struct buffer_head *bitmap_bh) | 1237 | ext4_group_t group, struct buffer_head *bitmap_bh) |
1160 | { | 1238 | { |
1161 | struct ext4_reserve_window_node *search_head; | 1239 | struct ext4_reserve_window_node *search_head; |
1162 | ext4_fsblk_t group_first_block, group_end_block, start_block; | 1240 | ext4_fsblk_t group_first_block, group_end_block, start_block; |
@@ -1354,7 +1432,7 @@ static void try_to_extend_reservation(struct ext4_reserve_window_node *my_rsv, | |||
1354 | */ | 1432 | */ |
1355 | static ext4_grpblk_t | 1433 | static ext4_grpblk_t |
1356 | ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, | 1434 | ext4_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, |
1357 | unsigned int group, struct buffer_head *bitmap_bh, | 1435 | ext4_group_t group, struct buffer_head *bitmap_bh, |
1358 | ext4_grpblk_t grp_goal, | 1436 | ext4_grpblk_t grp_goal, |
1359 | struct ext4_reserve_window_node * my_rsv, | 1437 | struct ext4_reserve_window_node * my_rsv, |
1360 | unsigned long *count, int *errp) | 1438 | unsigned long *count, int *errp) |
@@ -1510,7 +1588,7 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries) | |||
1510 | } | 1588 | } |
1511 | 1589 | ||
1512 | /** | 1590 | /** |
1513 | * ext4_new_blocks() -- core block(s) allocation function | 1591 | * ext4_new_blocks_old() -- core block(s) allocation function |
1514 | * @handle: handle to this transaction | 1592 | * @handle: handle to this transaction |
1515 | * @inode: file inode | 1593 | * @inode: file inode |
1516 | * @goal: given target block(filesystem wide) | 1594 | * @goal: given target block(filesystem wide) |
@@ -1523,17 +1601,17 @@ int ext4_should_retry_alloc(struct super_block *sb, int *retries) | |||
1523 | * any specific goal block. | 1601 | * any specific goal block. |
1524 | * | 1602 | * |
1525 | */ | 1603 | */ |
1526 | ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode, | 1604 | ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode, |
1527 | ext4_fsblk_t goal, unsigned long *count, int *errp) | 1605 | ext4_fsblk_t goal, unsigned long *count, int *errp) |
1528 | { | 1606 | { |
1529 | struct buffer_head *bitmap_bh = NULL; | 1607 | struct buffer_head *bitmap_bh = NULL; |
1530 | struct buffer_head *gdp_bh; | 1608 | struct buffer_head *gdp_bh; |
1531 | unsigned long group_no; | 1609 | ext4_group_t group_no; |
1532 | int goal_group; | 1610 | ext4_group_t goal_group; |
1533 | ext4_grpblk_t grp_target_blk; /* blockgroup relative goal block */ | 1611 | ext4_grpblk_t grp_target_blk; /* blockgroup relative goal block */ |
1534 | ext4_grpblk_t grp_alloc_blk; /* blockgroup-relative allocated block*/ | 1612 | ext4_grpblk_t grp_alloc_blk; /* blockgroup-relative allocated block*/ |
1535 | ext4_fsblk_t ret_block; /* filesyetem-wide allocated block */ | 1613 | ext4_fsblk_t ret_block; /* filesyetem-wide allocated block */ |
1536 | int bgi; /* blockgroup iteration index */ | 1614 | ext4_group_t bgi; /* blockgroup iteration index */ |
1537 | int fatal = 0, err; | 1615 | int fatal = 0, err; |
1538 | int performed_allocation = 0; | 1616 | int performed_allocation = 0; |
1539 | ext4_grpblk_t free_blocks; /* number of free blocks in a group */ | 1617 | ext4_grpblk_t free_blocks; /* number of free blocks in a group */ |
@@ -1544,10 +1622,7 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode, | |||
1544 | struct ext4_reserve_window_node *my_rsv = NULL; | 1622 | struct ext4_reserve_window_node *my_rsv = NULL; |
1545 | struct ext4_block_alloc_info *block_i; | 1623 | struct ext4_block_alloc_info *block_i; |
1546 | unsigned short windowsz = 0; | 1624 | unsigned short windowsz = 0; |
1547 | #ifdef EXT4FS_DEBUG | 1625 | ext4_group_t ngroups; |
1548 | static int goal_hits, goal_attempts; | ||
1549 | #endif | ||
1550 | unsigned long ngroups; | ||
1551 | unsigned long num = *count; | 1626 | unsigned long num = *count; |
1552 | 1627 | ||
1553 | *errp = -ENOSPC; | 1628 | *errp = -ENOSPC; |
@@ -1567,7 +1642,7 @@ ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode, | |||
1567 | 1642 | ||
1568 | sbi = EXT4_SB(sb); | 1643 | sbi = EXT4_SB(sb); |
1569 | es = EXT4_SB(sb)->s_es; | 1644 | es = EXT4_SB(sb)->s_es; |
1570 | ext4_debug("goal=%lu.\n", goal); | 1645 | ext4_debug("goal=%llu.\n", goal); |
1571 | /* | 1646 | /* |
1572 | * Allocate a block from reservation only when | 1647 | * Allocate a block from reservation only when |
1573 | * filesystem is mounted with reservation(default,-o reservation), and | 1648 | * filesystem is mounted with reservation(default,-o reservation), and |
@@ -1677,7 +1752,7 @@ retry_alloc: | |||
1677 | 1752 | ||
1678 | allocated: | 1753 | allocated: |
1679 | 1754 | ||
1680 | ext4_debug("using block group %d(%d)\n", | 1755 | ext4_debug("using block group %lu(%d)\n", |
1681 | group_no, gdp->bg_free_blocks_count); | 1756 | group_no, gdp->bg_free_blocks_count); |
1682 | 1757 | ||
1683 | BUFFER_TRACE(gdp_bh, "get_write_access"); | 1758 | BUFFER_TRACE(gdp_bh, "get_write_access"); |
@@ -1692,11 +1767,13 @@ allocated: | |||
1692 | in_range(ret_block, ext4_inode_table(sb, gdp), | 1767 | in_range(ret_block, ext4_inode_table(sb, gdp), |
1693 | EXT4_SB(sb)->s_itb_per_group) || | 1768 | EXT4_SB(sb)->s_itb_per_group) || |
1694 | in_range(ret_block + num - 1, ext4_inode_table(sb, gdp), | 1769 | in_range(ret_block + num - 1, ext4_inode_table(sb, gdp), |
1695 | EXT4_SB(sb)->s_itb_per_group)) | 1770 | EXT4_SB(sb)->s_itb_per_group)) { |
1696 | ext4_error(sb, "ext4_new_block", | 1771 | ext4_error(sb, "ext4_new_block", |
1697 | "Allocating block in system zone - " | 1772 | "Allocating block in system zone - " |
1698 | "blocks from %llu, length %lu", | 1773 | "blocks from %llu, length %lu", |
1699 | ret_block, num); | 1774 | ret_block, num); |
1775 | goto out; | ||
1776 | } | ||
1700 | 1777 | ||
1701 | performed_allocation = 1; | 1778 | performed_allocation = 1; |
1702 | 1779 | ||
@@ -1743,9 +1820,6 @@ allocated: | |||
1743 | * list of some description. We don't know in advance whether | 1820 | * list of some description. We don't know in advance whether |
1744 | * the caller wants to use it as metadata or data. | 1821 | * the caller wants to use it as metadata or data. |
1745 | */ | 1822 | */ |
1746 | ext4_debug("allocating block %lu. Goal hits %d of %d.\n", | ||
1747 | ret_block, goal_hits, goal_attempts); | ||
1748 | |||
1749 | spin_lock(sb_bgl_lock(sbi, group_no)); | 1823 | spin_lock(sb_bgl_lock(sbi, group_no)); |
1750 | if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) | 1824 | if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) |
1751 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); | 1825 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); |
@@ -1787,13 +1861,46 @@ out: | |||
1787 | } | 1861 | } |
1788 | 1862 | ||
1789 | ext4_fsblk_t ext4_new_block(handle_t *handle, struct inode *inode, | 1863 | ext4_fsblk_t ext4_new_block(handle_t *handle, struct inode *inode, |
1790 | ext4_fsblk_t goal, int *errp) | 1864 | ext4_fsblk_t goal, int *errp) |
1791 | { | 1865 | { |
1792 | unsigned long count = 1; | 1866 | struct ext4_allocation_request ar; |
1867 | ext4_fsblk_t ret; | ||
1793 | 1868 | ||
1794 | return ext4_new_blocks(handle, inode, goal, &count, errp); | 1869 | if (!test_opt(inode->i_sb, MBALLOC)) { |
1870 | unsigned long count = 1; | ||
1871 | ret = ext4_new_blocks_old(handle, inode, goal, &count, errp); | ||
1872 | return ret; | ||
1873 | } | ||
1874 | |||
1875 | memset(&ar, 0, sizeof(ar)); | ||
1876 | ar.inode = inode; | ||
1877 | ar.goal = goal; | ||
1878 | ar.len = 1; | ||
1879 | ret = ext4_mb_new_blocks(handle, &ar, errp); | ||
1880 | return ret; | ||
1881 | } | ||
1882 | |||
1883 | ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode, | ||
1884 | ext4_fsblk_t goal, unsigned long *count, int *errp) | ||
1885 | { | ||
1886 | struct ext4_allocation_request ar; | ||
1887 | ext4_fsblk_t ret; | ||
1888 | |||
1889 | if (!test_opt(inode->i_sb, MBALLOC)) { | ||
1890 | ret = ext4_new_blocks_old(handle, inode, goal, count, errp); | ||
1891 | return ret; | ||
1892 | } | ||
1893 | |||
1894 | memset(&ar, 0, sizeof(ar)); | ||
1895 | ar.inode = inode; | ||
1896 | ar.goal = goal; | ||
1897 | ar.len = *count; | ||
1898 | ret = ext4_mb_new_blocks(handle, &ar, errp); | ||
1899 | *count = ar.len; | ||
1900 | return ret; | ||
1795 | } | 1901 | } |
1796 | 1902 | ||
1903 | |||
1797 | /** | 1904 | /** |
1798 | * ext4_count_free_blocks() -- count filesystem free blocks | 1905 | * ext4_count_free_blocks() -- count filesystem free blocks |
1799 | * @sb: superblock | 1906 | * @sb: superblock |
@@ -1804,8 +1911,8 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb) | |||
1804 | { | 1911 | { |
1805 | ext4_fsblk_t desc_count; | 1912 | ext4_fsblk_t desc_count; |
1806 | struct ext4_group_desc *gdp; | 1913 | struct ext4_group_desc *gdp; |
1807 | int i; | 1914 | ext4_group_t i; |
1808 | unsigned long ngroups = EXT4_SB(sb)->s_groups_count; | 1915 | ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; |
1809 | #ifdef EXT4FS_DEBUG | 1916 | #ifdef EXT4FS_DEBUG |
1810 | struct ext4_super_block *es; | 1917 | struct ext4_super_block *es; |
1811 | ext4_fsblk_t bitmap_count; | 1918 | ext4_fsblk_t bitmap_count; |
@@ -1829,14 +1936,14 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb) | |||
1829 | continue; | 1936 | continue; |
1830 | 1937 | ||
1831 | x = ext4_count_free(bitmap_bh, sb->s_blocksize); | 1938 | x = ext4_count_free(bitmap_bh, sb->s_blocksize); |
1832 | printk("group %d: stored = %d, counted = %lu\n", | 1939 | printk(KERN_DEBUG "group %lu: stored = %d, counted = %lu\n", |
1833 | i, le16_to_cpu(gdp->bg_free_blocks_count), x); | 1940 | i, le16_to_cpu(gdp->bg_free_blocks_count), x); |
1834 | bitmap_count += x; | 1941 | bitmap_count += x; |
1835 | } | 1942 | } |
1836 | brelse(bitmap_bh); | 1943 | brelse(bitmap_bh); |
1837 | printk("ext4_count_free_blocks: stored = %llu" | 1944 | printk("ext4_count_free_blocks: stored = %llu" |
1838 | ", computed = %llu, %llu\n", | 1945 | ", computed = %llu, %llu\n", |
1839 | EXT4_FREE_BLOCKS_COUNT(es), | 1946 | ext4_free_blocks_count(es), |
1840 | desc_count, bitmap_count); | 1947 | desc_count, bitmap_count); |
1841 | return bitmap_count; | 1948 | return bitmap_count; |
1842 | #else | 1949 | #else |
@@ -1853,7 +1960,7 @@ ext4_fsblk_t ext4_count_free_blocks(struct super_block *sb) | |||
1853 | #endif | 1960 | #endif |
1854 | } | 1961 | } |
1855 | 1962 | ||
1856 | static inline int test_root(int a, int b) | 1963 | static inline int test_root(ext4_group_t a, int b) |
1857 | { | 1964 | { |
1858 | int num = b; | 1965 | int num = b; |
1859 | 1966 | ||
@@ -1862,7 +1969,7 @@ static inline int test_root(int a, int b) | |||
1862 | return num == a; | 1969 | return num == a; |
1863 | } | 1970 | } |
1864 | 1971 | ||
1865 | static int ext4_group_sparse(int group) | 1972 | static int ext4_group_sparse(ext4_group_t group) |
1866 | { | 1973 | { |
1867 | if (group <= 1) | 1974 | if (group <= 1) |
1868 | return 1; | 1975 | return 1; |
@@ -1880,7 +1987,7 @@ static int ext4_group_sparse(int group) | |||
1880 | * Return the number of blocks used by the superblock (primary or backup) | 1987 | * Return the number of blocks used by the superblock (primary or backup) |
1881 | * in this group. Currently this will be only 0 or 1. | 1988 | * in this group. Currently this will be only 0 or 1. |
1882 | */ | 1989 | */ |
1883 | int ext4_bg_has_super(struct super_block *sb, int group) | 1990 | int ext4_bg_has_super(struct super_block *sb, ext4_group_t group) |
1884 | { | 1991 | { |
1885 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 1992 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, |
1886 | EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) && | 1993 | EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) && |
@@ -1889,18 +1996,20 @@ int ext4_bg_has_super(struct super_block *sb, int group) | |||
1889 | return 1; | 1996 | return 1; |
1890 | } | 1997 | } |
1891 | 1998 | ||
1892 | static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb, int group) | 1999 | static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb, |
2000 | ext4_group_t group) | ||
1893 | { | 2001 | { |
1894 | unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb); | 2002 | unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb); |
1895 | unsigned long first = metagroup * EXT4_DESC_PER_BLOCK(sb); | 2003 | ext4_group_t first = metagroup * EXT4_DESC_PER_BLOCK(sb); |
1896 | unsigned long last = first + EXT4_DESC_PER_BLOCK(sb) - 1; | 2004 | ext4_group_t last = first + EXT4_DESC_PER_BLOCK(sb) - 1; |
1897 | 2005 | ||
1898 | if (group == first || group == first + 1 || group == last) | 2006 | if (group == first || group == first + 1 || group == last) |
1899 | return 1; | 2007 | return 1; |
1900 | return 0; | 2008 | return 0; |
1901 | } | 2009 | } |
1902 | 2010 | ||
1903 | static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb, int group) | 2011 | static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb, |
2012 | ext4_group_t group) | ||
1904 | { | 2013 | { |
1905 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | 2014 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, |
1906 | EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) && | 2015 | EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) && |
@@ -1918,7 +2027,7 @@ static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb, int group) | |||
1918 | * (primary or backup) in this group. In the future there may be a | 2027 | * (primary or backup) in this group. In the future there may be a |
1919 | * different number of descriptor blocks in each group. | 2028 | * different number of descriptor blocks in each group. |
1920 | */ | 2029 | */ |
1921 | unsigned long ext4_bg_num_gdb(struct super_block *sb, int group) | 2030 | unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group) |
1922 | { | 2031 | { |
1923 | unsigned long first_meta_bg = | 2032 | unsigned long first_meta_bg = |
1924 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg); | 2033 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg); |
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index f612bef98315..33888bb58144 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
@@ -67,7 +67,7 @@ int ext4_check_dir_entry (const char * function, struct inode * dir, | |||
67 | unsigned long offset) | 67 | unsigned long offset) |
68 | { | 68 | { |
69 | const char * error_msg = NULL; | 69 | const char * error_msg = NULL; |
70 | const int rlen = le16_to_cpu(de->rec_len); | 70 | const int rlen = ext4_rec_len_from_disk(de->rec_len); |
71 | 71 | ||
72 | if (rlen < EXT4_DIR_REC_LEN(1)) | 72 | if (rlen < EXT4_DIR_REC_LEN(1)) |
73 | error_msg = "rec_len is smaller than minimal"; | 73 | error_msg = "rec_len is smaller than minimal"; |
@@ -124,7 +124,7 @@ static int ext4_readdir(struct file * filp, | |||
124 | offset = filp->f_pos & (sb->s_blocksize - 1); | 124 | offset = filp->f_pos & (sb->s_blocksize - 1); |
125 | 125 | ||
126 | while (!error && !stored && filp->f_pos < inode->i_size) { | 126 | while (!error && !stored && filp->f_pos < inode->i_size) { |
127 | unsigned long blk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb); | 127 | ext4_lblk_t blk = filp->f_pos >> EXT4_BLOCK_SIZE_BITS(sb); |
128 | struct buffer_head map_bh; | 128 | struct buffer_head map_bh; |
129 | struct buffer_head *bh = NULL; | 129 | struct buffer_head *bh = NULL; |
130 | 130 | ||
@@ -172,10 +172,10 @@ revalidate: | |||
172 | * least that it is non-zero. A | 172 | * least that it is non-zero. A |
173 | * failure will be detected in the | 173 | * failure will be detected in the |
174 | * dirent test below. */ | 174 | * dirent test below. */ |
175 | if (le16_to_cpu(de->rec_len) < | 175 | if (ext4_rec_len_from_disk(de->rec_len) |
176 | EXT4_DIR_REC_LEN(1)) | 176 | < EXT4_DIR_REC_LEN(1)) |
177 | break; | 177 | break; |
178 | i += le16_to_cpu(de->rec_len); | 178 | i += ext4_rec_len_from_disk(de->rec_len); |
179 | } | 179 | } |
180 | offset = i; | 180 | offset = i; |
181 | filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) | 181 | filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1)) |
@@ -197,7 +197,7 @@ revalidate: | |||
197 | ret = stored; | 197 | ret = stored; |
198 | goto out; | 198 | goto out; |
199 | } | 199 | } |
200 | offset += le16_to_cpu(de->rec_len); | 200 | offset += ext4_rec_len_from_disk(de->rec_len); |
201 | if (le32_to_cpu(de->inode)) { | 201 | if (le32_to_cpu(de->inode)) { |
202 | /* We might block in the next section | 202 | /* We might block in the next section |
203 | * if the data destination is | 203 | * if the data destination is |
@@ -219,7 +219,7 @@ revalidate: | |||
219 | goto revalidate; | 219 | goto revalidate; |
220 | stored ++; | 220 | stored ++; |
221 | } | 221 | } |
222 | filp->f_pos += le16_to_cpu(de->rec_len); | 222 | filp->f_pos += ext4_rec_len_from_disk(de->rec_len); |
223 | } | 223 | } |
224 | offset = 0; | 224 | offset = 0; |
225 | brelse (bh); | 225 | brelse (bh); |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 85287742f2ae..bc7081f1fbe8 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -61,7 +61,7 @@ static ext4_fsblk_t ext_pblock(struct ext4_extent *ex) | |||
61 | * idx_pblock: | 61 | * idx_pblock: |
62 | * combine low and high parts of a leaf physical block number into ext4_fsblk_t | 62 | * combine low and high parts of a leaf physical block number into ext4_fsblk_t |
63 | */ | 63 | */ |
64 | static ext4_fsblk_t idx_pblock(struct ext4_extent_idx *ix) | 64 | ext4_fsblk_t idx_pblock(struct ext4_extent_idx *ix) |
65 | { | 65 | { |
66 | ext4_fsblk_t block; | 66 | ext4_fsblk_t block; |
67 | 67 | ||
@@ -75,7 +75,7 @@ static ext4_fsblk_t idx_pblock(struct ext4_extent_idx *ix) | |||
75 | * stores a large physical block number into an extent struct, | 75 | * stores a large physical block number into an extent struct, |
76 | * breaking it into parts | 76 | * breaking it into parts |
77 | */ | 77 | */ |
78 | static void ext4_ext_store_pblock(struct ext4_extent *ex, ext4_fsblk_t pb) | 78 | void ext4_ext_store_pblock(struct ext4_extent *ex, ext4_fsblk_t pb) |
79 | { | 79 | { |
80 | ex->ee_start_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff)); | 80 | ex->ee_start_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff)); |
81 | ex->ee_start_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff); | 81 | ex->ee_start_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff); |
@@ -144,7 +144,7 @@ static int ext4_ext_dirty(handle_t *handle, struct inode *inode, | |||
144 | 144 | ||
145 | static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode, | 145 | static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode, |
146 | struct ext4_ext_path *path, | 146 | struct ext4_ext_path *path, |
147 | ext4_fsblk_t block) | 147 | ext4_lblk_t block) |
148 | { | 148 | { |
149 | struct ext4_inode_info *ei = EXT4_I(inode); | 149 | struct ext4_inode_info *ei = EXT4_I(inode); |
150 | ext4_fsblk_t bg_start; | 150 | ext4_fsblk_t bg_start; |
@@ -367,13 +367,14 @@ static void ext4_ext_drop_refs(struct ext4_ext_path *path) | |||
367 | * the header must be checked before calling this | 367 | * the header must be checked before calling this |
368 | */ | 368 | */ |
369 | static void | 369 | static void |
370 | ext4_ext_binsearch_idx(struct inode *inode, struct ext4_ext_path *path, int block) | 370 | ext4_ext_binsearch_idx(struct inode *inode, |
371 | struct ext4_ext_path *path, ext4_lblk_t block) | ||
371 | { | 372 | { |
372 | struct ext4_extent_header *eh = path->p_hdr; | 373 | struct ext4_extent_header *eh = path->p_hdr; |
373 | struct ext4_extent_idx *r, *l, *m; | 374 | struct ext4_extent_idx *r, *l, *m; |
374 | 375 | ||
375 | 376 | ||
376 | ext_debug("binsearch for %d(idx): ", block); | 377 | ext_debug("binsearch for %u(idx): ", block); |
377 | 378 | ||
378 | l = EXT_FIRST_INDEX(eh) + 1; | 379 | l = EXT_FIRST_INDEX(eh) + 1; |
379 | r = EXT_LAST_INDEX(eh); | 380 | r = EXT_LAST_INDEX(eh); |
@@ -425,7 +426,8 @@ ext4_ext_binsearch_idx(struct inode *inode, struct ext4_ext_path *path, int bloc | |||
425 | * the header must be checked before calling this | 426 | * the header must be checked before calling this |
426 | */ | 427 | */ |
427 | static void | 428 | static void |
428 | ext4_ext_binsearch(struct inode *inode, struct ext4_ext_path *path, int block) | 429 | ext4_ext_binsearch(struct inode *inode, |
430 | struct ext4_ext_path *path, ext4_lblk_t block) | ||
429 | { | 431 | { |
430 | struct ext4_extent_header *eh = path->p_hdr; | 432 | struct ext4_extent_header *eh = path->p_hdr; |
431 | struct ext4_extent *r, *l, *m; | 433 | struct ext4_extent *r, *l, *m; |
@@ -438,7 +440,7 @@ ext4_ext_binsearch(struct inode *inode, struct ext4_ext_path *path, int block) | |||
438 | return; | 440 | return; |
439 | } | 441 | } |
440 | 442 | ||
441 | ext_debug("binsearch for %d: ", block); | 443 | ext_debug("binsearch for %u: ", block); |
442 | 444 | ||
443 | l = EXT_FIRST_EXTENT(eh) + 1; | 445 | l = EXT_FIRST_EXTENT(eh) + 1; |
444 | r = EXT_LAST_EXTENT(eh); | 446 | r = EXT_LAST_EXTENT(eh); |
@@ -494,7 +496,8 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode) | |||
494 | } | 496 | } |
495 | 497 | ||
496 | struct ext4_ext_path * | 498 | struct ext4_ext_path * |
497 | ext4_ext_find_extent(struct inode *inode, int block, struct ext4_ext_path *path) | 499 | ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, |
500 | struct ext4_ext_path *path) | ||
498 | { | 501 | { |
499 | struct ext4_extent_header *eh; | 502 | struct ext4_extent_header *eh; |
500 | struct buffer_head *bh; | 503 | struct buffer_head *bh; |
@@ -763,7 +766,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
763 | while (k--) { | 766 | while (k--) { |
764 | oldblock = newblock; | 767 | oldblock = newblock; |
765 | newblock = ablocks[--a]; | 768 | newblock = ablocks[--a]; |
766 | bh = sb_getblk(inode->i_sb, (ext4_fsblk_t)newblock); | 769 | bh = sb_getblk(inode->i_sb, newblock); |
767 | if (!bh) { | 770 | if (!bh) { |
768 | err = -EIO; | 771 | err = -EIO; |
769 | goto cleanup; | 772 | goto cleanup; |
@@ -783,9 +786,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
783 | fidx->ei_block = border; | 786 | fidx->ei_block = border; |
784 | ext4_idx_store_pblock(fidx, oldblock); | 787 | ext4_idx_store_pblock(fidx, oldblock); |
785 | 788 | ||
786 | ext_debug("int.index at %d (block %llu): %lu -> %llu\n", i, | 789 | ext_debug("int.index at %d (block %llu): %u -> %llu\n", |
787 | newblock, (unsigned long) le32_to_cpu(border), | 790 | i, newblock, le32_to_cpu(border), oldblock); |
788 | oldblock); | ||
789 | /* copy indexes */ | 791 | /* copy indexes */ |
790 | m = 0; | 792 | m = 0; |
791 | path[i].p_idx++; | 793 | path[i].p_idx++; |
@@ -851,7 +853,7 @@ cleanup: | |||
851 | for (i = 0; i < depth; i++) { | 853 | for (i = 0; i < depth; i++) { |
852 | if (!ablocks[i]) | 854 | if (!ablocks[i]) |
853 | continue; | 855 | continue; |
854 | ext4_free_blocks(handle, inode, ablocks[i], 1); | 856 | ext4_free_blocks(handle, inode, ablocks[i], 1, 1); |
855 | } | 857 | } |
856 | } | 858 | } |
857 | kfree(ablocks); | 859 | kfree(ablocks); |
@@ -979,8 +981,8 @@ repeat: | |||
979 | /* refill path */ | 981 | /* refill path */ |
980 | ext4_ext_drop_refs(path); | 982 | ext4_ext_drop_refs(path); |
981 | path = ext4_ext_find_extent(inode, | 983 | path = ext4_ext_find_extent(inode, |
982 | le32_to_cpu(newext->ee_block), | 984 | (ext4_lblk_t)le32_to_cpu(newext->ee_block), |
983 | path); | 985 | path); |
984 | if (IS_ERR(path)) | 986 | if (IS_ERR(path)) |
985 | err = PTR_ERR(path); | 987 | err = PTR_ERR(path); |
986 | } else { | 988 | } else { |
@@ -992,8 +994,8 @@ repeat: | |||
992 | /* refill path */ | 994 | /* refill path */ |
993 | ext4_ext_drop_refs(path); | 995 | ext4_ext_drop_refs(path); |
994 | path = ext4_ext_find_extent(inode, | 996 | path = ext4_ext_find_extent(inode, |
995 | le32_to_cpu(newext->ee_block), | 997 | (ext4_lblk_t)le32_to_cpu(newext->ee_block), |
996 | path); | 998 | path); |
997 | if (IS_ERR(path)) { | 999 | if (IS_ERR(path)) { |
998 | err = PTR_ERR(path); | 1000 | err = PTR_ERR(path); |
999 | goto out; | 1001 | goto out; |
@@ -1015,13 +1017,157 @@ out: | |||
1015 | } | 1017 | } |
1016 | 1018 | ||
1017 | /* | 1019 | /* |
1020 | * search the closest allocated block to the left for *logical | ||
1021 | * and returns it at @logical + it's physical address at @phys | ||
1022 | * if *logical is the smallest allocated block, the function | ||
1023 | * returns 0 at @phys | ||
1024 | * return value contains 0 (success) or error code | ||
1025 | */ | ||
1026 | int | ||
1027 | ext4_ext_search_left(struct inode *inode, struct ext4_ext_path *path, | ||
1028 | ext4_lblk_t *logical, ext4_fsblk_t *phys) | ||
1029 | { | ||
1030 | struct ext4_extent_idx *ix; | ||
1031 | struct ext4_extent *ex; | ||
1032 | int depth, ee_len; | ||
1033 | |||
1034 | BUG_ON(path == NULL); | ||
1035 | depth = path->p_depth; | ||
1036 | *phys = 0; | ||
1037 | |||
1038 | if (depth == 0 && path->p_ext == NULL) | ||
1039 | return 0; | ||
1040 | |||
1041 | /* usually extent in the path covers blocks smaller | ||
1042 | * then *logical, but it can be that extent is the | ||
1043 | * first one in the file */ | ||
1044 | |||
1045 | ex = path[depth].p_ext; | ||
1046 | ee_len = ext4_ext_get_actual_len(ex); | ||
1047 | if (*logical < le32_to_cpu(ex->ee_block)) { | ||
1048 | BUG_ON(EXT_FIRST_EXTENT(path[depth].p_hdr) != ex); | ||
1049 | while (--depth >= 0) { | ||
1050 | ix = path[depth].p_idx; | ||
1051 | BUG_ON(ix != EXT_FIRST_INDEX(path[depth].p_hdr)); | ||
1052 | } | ||
1053 | return 0; | ||
1054 | } | ||
1055 | |||
1056 | BUG_ON(*logical < (le32_to_cpu(ex->ee_block) + ee_len)); | ||
1057 | |||
1058 | *logical = le32_to_cpu(ex->ee_block) + ee_len - 1; | ||
1059 | *phys = ext_pblock(ex) + ee_len - 1; | ||
1060 | return 0; | ||
1061 | } | ||
1062 | |||
1063 | /* | ||
1064 | * search the closest allocated block to the right for *logical | ||
1065 | * and returns it at @logical + it's physical address at @phys | ||
1066 | * if *logical is the smallest allocated block, the function | ||
1067 | * returns 0 at @phys | ||
1068 | * return value contains 0 (success) or error code | ||
1069 | */ | ||
1070 | int | ||
1071 | ext4_ext_search_right(struct inode *inode, struct ext4_ext_path *path, | ||
1072 | ext4_lblk_t *logical, ext4_fsblk_t *phys) | ||
1073 | { | ||
1074 | struct buffer_head *bh = NULL; | ||
1075 | struct ext4_extent_header *eh; | ||
1076 | struct ext4_extent_idx *ix; | ||
1077 | struct ext4_extent *ex; | ||
1078 | ext4_fsblk_t block; | ||
1079 | int depth, ee_len; | ||
1080 | |||
1081 | BUG_ON(path == NULL); | ||
1082 | depth = path->p_depth; | ||
1083 | *phys = 0; | ||
1084 | |||
1085 | if (depth == 0 && path->p_ext == NULL) | ||
1086 | return 0; | ||
1087 | |||
1088 | /* usually extent in the path covers blocks smaller | ||
1089 | * then *logical, but it can be that extent is the | ||
1090 | * first one in the file */ | ||
1091 | |||
1092 | ex = path[depth].p_ext; | ||
1093 | ee_len = ext4_ext_get_actual_len(ex); | ||
1094 | if (*logical < le32_to_cpu(ex->ee_block)) { | ||
1095 | BUG_ON(EXT_FIRST_EXTENT(path[depth].p_hdr) != ex); | ||
1096 | while (--depth >= 0) { | ||
1097 | ix = path[depth].p_idx; | ||
1098 | BUG_ON(ix != EXT_FIRST_INDEX(path[depth].p_hdr)); | ||
1099 | } | ||
1100 | *logical = le32_to_cpu(ex->ee_block); | ||
1101 | *phys = ext_pblock(ex); | ||
1102 | return 0; | ||
1103 | } | ||
1104 | |||
1105 | BUG_ON(*logical < (le32_to_cpu(ex->ee_block) + ee_len)); | ||
1106 | |||
1107 | if (ex != EXT_LAST_EXTENT(path[depth].p_hdr)) { | ||
1108 | /* next allocated block in this leaf */ | ||
1109 | ex++; | ||
1110 | *logical = le32_to_cpu(ex->ee_block); | ||
1111 | *phys = ext_pblock(ex); | ||
1112 | return 0; | ||
1113 | } | ||
1114 | |||
1115 | /* go up and search for index to the right */ | ||
1116 | while (--depth >= 0) { | ||
1117 | ix = path[depth].p_idx; | ||
1118 | if (ix != EXT_LAST_INDEX(path[depth].p_hdr)) | ||
1119 | break; | ||
1120 | } | ||
1121 | |||
1122 | if (depth < 0) { | ||
1123 | /* we've gone up to the root and | ||
1124 | * found no index to the right */ | ||
1125 | return 0; | ||
1126 | } | ||
1127 | |||
1128 | /* we've found index to the right, let's | ||
1129 | * follow it and find the closest allocated | ||
1130 | * block to the right */ | ||
1131 | ix++; | ||
1132 | block = idx_pblock(ix); | ||
1133 | while (++depth < path->p_depth) { | ||
1134 | bh = sb_bread(inode->i_sb, block); | ||
1135 | if (bh == NULL) | ||
1136 | return -EIO; | ||
1137 | eh = ext_block_hdr(bh); | ||
1138 | if (ext4_ext_check_header(inode, eh, depth)) { | ||
1139 | put_bh(bh); | ||
1140 | return -EIO; | ||
1141 | } | ||
1142 | ix = EXT_FIRST_INDEX(eh); | ||
1143 | block = idx_pblock(ix); | ||
1144 | put_bh(bh); | ||
1145 | } | ||
1146 | |||
1147 | bh = sb_bread(inode->i_sb, block); | ||
1148 | if (bh == NULL) | ||
1149 | return -EIO; | ||
1150 | eh = ext_block_hdr(bh); | ||
1151 | if (ext4_ext_check_header(inode, eh, path->p_depth - depth)) { | ||
1152 | put_bh(bh); | ||
1153 | return -EIO; | ||
1154 | } | ||
1155 | ex = EXT_FIRST_EXTENT(eh); | ||
1156 | *logical = le32_to_cpu(ex->ee_block); | ||
1157 | *phys = ext_pblock(ex); | ||
1158 | put_bh(bh); | ||
1159 | return 0; | ||
1160 | |||
1161 | } | ||
1162 | |||
1163 | /* | ||
1018 | * ext4_ext_next_allocated_block: | 1164 | * ext4_ext_next_allocated_block: |
1019 | * returns allocated block in subsequent extent or EXT_MAX_BLOCK. | 1165 | * returns allocated block in subsequent extent or EXT_MAX_BLOCK. |
1020 | * NOTE: it considers block number from index entry as | 1166 | * NOTE: it considers block number from index entry as |
1021 | * allocated block. Thus, index entries have to be consistent | 1167 | * allocated block. Thus, index entries have to be consistent |
1022 | * with leaves. | 1168 | * with leaves. |
1023 | */ | 1169 | */ |
1024 | static unsigned long | 1170 | static ext4_lblk_t |
1025 | ext4_ext_next_allocated_block(struct ext4_ext_path *path) | 1171 | ext4_ext_next_allocated_block(struct ext4_ext_path *path) |
1026 | { | 1172 | { |
1027 | int depth; | 1173 | int depth; |
@@ -1054,7 +1200,7 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path) | |||
1054 | * ext4_ext_next_leaf_block: | 1200 | * ext4_ext_next_leaf_block: |
1055 | * returns first allocated block from next leaf or EXT_MAX_BLOCK | 1201 | * returns first allocated block from next leaf or EXT_MAX_BLOCK |
1056 | */ | 1202 | */ |
1057 | static unsigned ext4_ext_next_leaf_block(struct inode *inode, | 1203 | static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, |
1058 | struct ext4_ext_path *path) | 1204 | struct ext4_ext_path *path) |
1059 | { | 1205 | { |
1060 | int depth; | 1206 | int depth; |
@@ -1072,7 +1218,8 @@ static unsigned ext4_ext_next_leaf_block(struct inode *inode, | |||
1072 | while (depth >= 0) { | 1218 | while (depth >= 0) { |
1073 | if (path[depth].p_idx != | 1219 | if (path[depth].p_idx != |
1074 | EXT_LAST_INDEX(path[depth].p_hdr)) | 1220 | EXT_LAST_INDEX(path[depth].p_hdr)) |
1075 | return le32_to_cpu(path[depth].p_idx[1].ei_block); | 1221 | return (ext4_lblk_t) |
1222 | le32_to_cpu(path[depth].p_idx[1].ei_block); | ||
1076 | depth--; | 1223 | depth--; |
1077 | } | 1224 | } |
1078 | 1225 | ||
@@ -1085,7 +1232,7 @@ static unsigned ext4_ext_next_leaf_block(struct inode *inode, | |||
1085 | * then we have to correct all indexes above. | 1232 | * then we have to correct all indexes above. |
1086 | * TODO: do we need to correct tree in all cases? | 1233 | * TODO: do we need to correct tree in all cases? |
1087 | */ | 1234 | */ |
1088 | int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode, | 1235 | static int ext4_ext_correct_indexes(handle_t *handle, struct inode *inode, |
1089 | struct ext4_ext_path *path) | 1236 | struct ext4_ext_path *path) |
1090 | { | 1237 | { |
1091 | struct ext4_extent_header *eh; | 1238 | struct ext4_extent_header *eh; |
@@ -1171,7 +1318,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, | |||
1171 | if (ext1_ee_len + ext2_ee_len > max_len) | 1318 | if (ext1_ee_len + ext2_ee_len > max_len) |
1172 | return 0; | 1319 | return 0; |
1173 | #ifdef AGGRESSIVE_TEST | 1320 | #ifdef AGGRESSIVE_TEST |
1174 | if (le16_to_cpu(ex1->ee_len) >= 4) | 1321 | if (ext1_ee_len >= 4) |
1175 | return 0; | 1322 | return 0; |
1176 | #endif | 1323 | #endif |
1177 | 1324 | ||
@@ -1239,7 +1386,7 @@ unsigned int ext4_ext_check_overlap(struct inode *inode, | |||
1239 | struct ext4_extent *newext, | 1386 | struct ext4_extent *newext, |
1240 | struct ext4_ext_path *path) | 1387 | struct ext4_ext_path *path) |
1241 | { | 1388 | { |
1242 | unsigned long b1, b2; | 1389 | ext4_lblk_t b1, b2; |
1243 | unsigned int depth, len1; | 1390 | unsigned int depth, len1; |
1244 | unsigned int ret = 0; | 1391 | unsigned int ret = 0; |
1245 | 1392 | ||
@@ -1260,7 +1407,7 @@ unsigned int ext4_ext_check_overlap(struct inode *inode, | |||
1260 | goto out; | 1407 | goto out; |
1261 | } | 1408 | } |
1262 | 1409 | ||
1263 | /* check for wrap through zero */ | 1410 | /* check for wrap through zero on extent logical start block*/ |
1264 | if (b1 + len1 < b1) { | 1411 | if (b1 + len1 < b1) { |
1265 | len1 = EXT_MAX_BLOCK - b1; | 1412 | len1 = EXT_MAX_BLOCK - b1; |
1266 | newext->ee_len = cpu_to_le16(len1); | 1413 | newext->ee_len = cpu_to_le16(len1); |
@@ -1290,7 +1437,8 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, | |||
1290 | struct ext4_extent *ex, *fex; | 1437 | struct ext4_extent *ex, *fex; |
1291 | struct ext4_extent *nearex; /* nearest extent */ | 1438 | struct ext4_extent *nearex; /* nearest extent */ |
1292 | struct ext4_ext_path *npath = NULL; | 1439 | struct ext4_ext_path *npath = NULL; |
1293 | int depth, len, err, next; | 1440 | int depth, len, err; |
1441 | ext4_lblk_t next; | ||
1294 | unsigned uninitialized = 0; | 1442 | unsigned uninitialized = 0; |
1295 | 1443 | ||
1296 | BUG_ON(ext4_ext_get_actual_len(newext) == 0); | 1444 | BUG_ON(ext4_ext_get_actual_len(newext) == 0); |
@@ -1435,114 +1583,8 @@ cleanup: | |||
1435 | return err; | 1583 | return err; |
1436 | } | 1584 | } |
1437 | 1585 | ||
1438 | int ext4_ext_walk_space(struct inode *inode, unsigned long block, | ||
1439 | unsigned long num, ext_prepare_callback func, | ||
1440 | void *cbdata) | ||
1441 | { | ||
1442 | struct ext4_ext_path *path = NULL; | ||
1443 | struct ext4_ext_cache cbex; | ||
1444 | struct ext4_extent *ex; | ||
1445 | unsigned long next, start = 0, end = 0; | ||
1446 | unsigned long last = block + num; | ||
1447 | int depth, exists, err = 0; | ||
1448 | |||
1449 | BUG_ON(func == NULL); | ||
1450 | BUG_ON(inode == NULL); | ||
1451 | |||
1452 | while (block < last && block != EXT_MAX_BLOCK) { | ||
1453 | num = last - block; | ||
1454 | /* find extent for this block */ | ||
1455 | path = ext4_ext_find_extent(inode, block, path); | ||
1456 | if (IS_ERR(path)) { | ||
1457 | err = PTR_ERR(path); | ||
1458 | path = NULL; | ||
1459 | break; | ||
1460 | } | ||
1461 | |||
1462 | depth = ext_depth(inode); | ||
1463 | BUG_ON(path[depth].p_hdr == NULL); | ||
1464 | ex = path[depth].p_ext; | ||
1465 | next = ext4_ext_next_allocated_block(path); | ||
1466 | |||
1467 | exists = 0; | ||
1468 | if (!ex) { | ||
1469 | /* there is no extent yet, so try to allocate | ||
1470 | * all requested space */ | ||
1471 | start = block; | ||
1472 | end = block + num; | ||
1473 | } else if (le32_to_cpu(ex->ee_block) > block) { | ||
1474 | /* need to allocate space before found extent */ | ||
1475 | start = block; | ||
1476 | end = le32_to_cpu(ex->ee_block); | ||
1477 | if (block + num < end) | ||
1478 | end = block + num; | ||
1479 | } else if (block >= le32_to_cpu(ex->ee_block) | ||
1480 | + ext4_ext_get_actual_len(ex)) { | ||
1481 | /* need to allocate space after found extent */ | ||
1482 | start = block; | ||
1483 | end = block + num; | ||
1484 | if (end >= next) | ||
1485 | end = next; | ||
1486 | } else if (block >= le32_to_cpu(ex->ee_block)) { | ||
1487 | /* | ||
1488 | * some part of requested space is covered | ||
1489 | * by found extent | ||
1490 | */ | ||
1491 | start = block; | ||
1492 | end = le32_to_cpu(ex->ee_block) | ||
1493 | + ext4_ext_get_actual_len(ex); | ||
1494 | if (block + num < end) | ||
1495 | end = block + num; | ||
1496 | exists = 1; | ||
1497 | } else { | ||
1498 | BUG(); | ||
1499 | } | ||
1500 | BUG_ON(end <= start); | ||
1501 | |||
1502 | if (!exists) { | ||
1503 | cbex.ec_block = start; | ||
1504 | cbex.ec_len = end - start; | ||
1505 | cbex.ec_start = 0; | ||
1506 | cbex.ec_type = EXT4_EXT_CACHE_GAP; | ||
1507 | } else { | ||
1508 | cbex.ec_block = le32_to_cpu(ex->ee_block); | ||
1509 | cbex.ec_len = ext4_ext_get_actual_len(ex); | ||
1510 | cbex.ec_start = ext_pblock(ex); | ||
1511 | cbex.ec_type = EXT4_EXT_CACHE_EXTENT; | ||
1512 | } | ||
1513 | |||
1514 | BUG_ON(cbex.ec_len == 0); | ||
1515 | err = func(inode, path, &cbex, cbdata); | ||
1516 | ext4_ext_drop_refs(path); | ||
1517 | |||
1518 | if (err < 0) | ||
1519 | break; | ||
1520 | if (err == EXT_REPEAT) | ||
1521 | continue; | ||
1522 | else if (err == EXT_BREAK) { | ||
1523 | err = 0; | ||
1524 | break; | ||
1525 | } | ||
1526 | |||
1527 | if (ext_depth(inode) != depth) { | ||
1528 | /* depth was changed. we have to realloc path */ | ||
1529 | kfree(path); | ||
1530 | path = NULL; | ||
1531 | } | ||
1532 | |||
1533 | block = cbex.ec_block + cbex.ec_len; | ||
1534 | } | ||
1535 | |||
1536 | if (path) { | ||
1537 | ext4_ext_drop_refs(path); | ||
1538 | kfree(path); | ||
1539 | } | ||
1540 | |||
1541 | return err; | ||
1542 | } | ||
1543 | |||
1544 | static void | 1586 | static void |
1545 | ext4_ext_put_in_cache(struct inode *inode, __u32 block, | 1587 | ext4_ext_put_in_cache(struct inode *inode, ext4_lblk_t block, |
1546 | __u32 len, ext4_fsblk_t start, int type) | 1588 | __u32 len, ext4_fsblk_t start, int type) |
1547 | { | 1589 | { |
1548 | struct ext4_ext_cache *cex; | 1590 | struct ext4_ext_cache *cex; |
@@ -1561,10 +1603,11 @@ ext4_ext_put_in_cache(struct inode *inode, __u32 block, | |||
1561 | */ | 1603 | */ |
1562 | static void | 1604 | static void |
1563 | ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, | 1605 | ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, |
1564 | unsigned long block) | 1606 | ext4_lblk_t block) |
1565 | { | 1607 | { |
1566 | int depth = ext_depth(inode); | 1608 | int depth = ext_depth(inode); |
1567 | unsigned long lblock, len; | 1609 | unsigned long len; |
1610 | ext4_lblk_t lblock; | ||
1568 | struct ext4_extent *ex; | 1611 | struct ext4_extent *ex; |
1569 | 1612 | ||
1570 | ex = path[depth].p_ext; | 1613 | ex = path[depth].p_ext; |
@@ -1576,32 +1619,34 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, | |||
1576 | } else if (block < le32_to_cpu(ex->ee_block)) { | 1619 | } else if (block < le32_to_cpu(ex->ee_block)) { |
1577 | lblock = block; | 1620 | lblock = block; |
1578 | len = le32_to_cpu(ex->ee_block) - block; | 1621 | len = le32_to_cpu(ex->ee_block) - block; |
1579 | ext_debug("cache gap(before): %lu [%lu:%lu]", | 1622 | ext_debug("cache gap(before): %u [%u:%u]", |
1580 | (unsigned long) block, | 1623 | block, |
1581 | (unsigned long) le32_to_cpu(ex->ee_block), | 1624 | le32_to_cpu(ex->ee_block), |
1582 | (unsigned long) ext4_ext_get_actual_len(ex)); | 1625 | ext4_ext_get_actual_len(ex)); |
1583 | } else if (block >= le32_to_cpu(ex->ee_block) | 1626 | } else if (block >= le32_to_cpu(ex->ee_block) |
1584 | + ext4_ext_get_actual_len(ex)) { | 1627 | + ext4_ext_get_actual_len(ex)) { |
1628 | ext4_lblk_t next; | ||
1585 | lblock = le32_to_cpu(ex->ee_block) | 1629 | lblock = le32_to_cpu(ex->ee_block) |
1586 | + ext4_ext_get_actual_len(ex); | 1630 | + ext4_ext_get_actual_len(ex); |
1587 | len = ext4_ext_next_allocated_block(path); | 1631 | |
1588 | ext_debug("cache gap(after): [%lu:%lu] %lu", | 1632 | next = ext4_ext_next_allocated_block(path); |
1589 | (unsigned long) le32_to_cpu(ex->ee_block), | 1633 | ext_debug("cache gap(after): [%u:%u] %u", |
1590 | (unsigned long) ext4_ext_get_actual_len(ex), | 1634 | le32_to_cpu(ex->ee_block), |
1591 | (unsigned long) block); | 1635 | ext4_ext_get_actual_len(ex), |
1592 | BUG_ON(len == lblock); | 1636 | block); |
1593 | len = len - lblock; | 1637 | BUG_ON(next == lblock); |
1638 | len = next - lblock; | ||
1594 | } else { | 1639 | } else { |
1595 | lblock = len = 0; | 1640 | lblock = len = 0; |
1596 | BUG(); | 1641 | BUG(); |
1597 | } | 1642 | } |
1598 | 1643 | ||
1599 | ext_debug(" -> %lu:%lu\n", (unsigned long) lblock, len); | 1644 | ext_debug(" -> %u:%lu\n", lblock, len); |
1600 | ext4_ext_put_in_cache(inode, lblock, len, 0, EXT4_EXT_CACHE_GAP); | 1645 | ext4_ext_put_in_cache(inode, lblock, len, 0, EXT4_EXT_CACHE_GAP); |
1601 | } | 1646 | } |
1602 | 1647 | ||
1603 | static int | 1648 | static int |
1604 | ext4_ext_in_cache(struct inode *inode, unsigned long block, | 1649 | ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block, |
1605 | struct ext4_extent *ex) | 1650 | struct ext4_extent *ex) |
1606 | { | 1651 | { |
1607 | struct ext4_ext_cache *cex; | 1652 | struct ext4_ext_cache *cex; |
@@ -1618,11 +1663,9 @@ ext4_ext_in_cache(struct inode *inode, unsigned long block, | |||
1618 | ex->ee_block = cpu_to_le32(cex->ec_block); | 1663 | ex->ee_block = cpu_to_le32(cex->ec_block); |
1619 | ext4_ext_store_pblock(ex, cex->ec_start); | 1664 | ext4_ext_store_pblock(ex, cex->ec_start); |
1620 | ex->ee_len = cpu_to_le16(cex->ec_len); | 1665 | ex->ee_len = cpu_to_le16(cex->ec_len); |
1621 | ext_debug("%lu cached by %lu:%lu:%llu\n", | 1666 | ext_debug("%u cached by %u:%u:%llu\n", |
1622 | (unsigned long) block, | 1667 | block, |
1623 | (unsigned long) cex->ec_block, | 1668 | cex->ec_block, cex->ec_len, cex->ec_start); |
1624 | (unsigned long) cex->ec_len, | ||
1625 | cex->ec_start); | ||
1626 | return cex->ec_type; | 1669 | return cex->ec_type; |
1627 | } | 1670 | } |
1628 | 1671 | ||
@@ -1636,7 +1679,7 @@ ext4_ext_in_cache(struct inode *inode, unsigned long block, | |||
1636 | * It's used in truncate case only, thus all requests are for | 1679 | * It's used in truncate case only, thus all requests are for |
1637 | * last index in the block only. | 1680 | * last index in the block only. |
1638 | */ | 1681 | */ |
1639 | int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, | 1682 | static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, |
1640 | struct ext4_ext_path *path) | 1683 | struct ext4_ext_path *path) |
1641 | { | 1684 | { |
1642 | struct buffer_head *bh; | 1685 | struct buffer_head *bh; |
@@ -1657,7 +1700,7 @@ int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, | |||
1657 | ext_debug("index is empty, remove it, free block %llu\n", leaf); | 1700 | ext_debug("index is empty, remove it, free block %llu\n", leaf); |
1658 | bh = sb_find_get_block(inode->i_sb, leaf); | 1701 | bh = sb_find_get_block(inode->i_sb, leaf); |
1659 | ext4_forget(handle, 1, inode, bh, leaf); | 1702 | ext4_forget(handle, 1, inode, bh, leaf); |
1660 | ext4_free_blocks(handle, inode, leaf, 1); | 1703 | ext4_free_blocks(handle, inode, leaf, 1, 1); |
1661 | return err; | 1704 | return err; |
1662 | } | 1705 | } |
1663 | 1706 | ||
@@ -1666,7 +1709,7 @@ int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, | |||
1666 | * This routine returns max. credits that the extent tree can consume. | 1709 | * This routine returns max. credits that the extent tree can consume. |
1667 | * It should be OK for low-performance paths like ->writepage() | 1710 | * It should be OK for low-performance paths like ->writepage() |
1668 | * To allow many writing processes to fit into a single transaction, | 1711 | * To allow many writing processes to fit into a single transaction, |
1669 | * the caller should calculate credits under truncate_mutex and | 1712 | * the caller should calculate credits under i_data_sem and |
1670 | * pass the actual path. | 1713 | * pass the actual path. |
1671 | */ | 1714 | */ |
1672 | int ext4_ext_calc_credits_for_insert(struct inode *inode, | 1715 | int ext4_ext_calc_credits_for_insert(struct inode *inode, |
@@ -1714,12 +1757,14 @@ int ext4_ext_calc_credits_for_insert(struct inode *inode, | |||
1714 | 1757 | ||
1715 | static int ext4_remove_blocks(handle_t *handle, struct inode *inode, | 1758 | static int ext4_remove_blocks(handle_t *handle, struct inode *inode, |
1716 | struct ext4_extent *ex, | 1759 | struct ext4_extent *ex, |
1717 | unsigned long from, unsigned long to) | 1760 | ext4_lblk_t from, ext4_lblk_t to) |
1718 | { | 1761 | { |
1719 | struct buffer_head *bh; | 1762 | struct buffer_head *bh; |
1720 | unsigned short ee_len = ext4_ext_get_actual_len(ex); | 1763 | unsigned short ee_len = ext4_ext_get_actual_len(ex); |
1721 | int i; | 1764 | int i, metadata = 0; |
1722 | 1765 | ||
1766 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | ||
1767 | metadata = 1; | ||
1723 | #ifdef EXTENTS_STATS | 1768 | #ifdef EXTENTS_STATS |
1724 | { | 1769 | { |
1725 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 1770 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
@@ -1738,42 +1783,45 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, | |||
1738 | if (from >= le32_to_cpu(ex->ee_block) | 1783 | if (from >= le32_to_cpu(ex->ee_block) |
1739 | && to == le32_to_cpu(ex->ee_block) + ee_len - 1) { | 1784 | && to == le32_to_cpu(ex->ee_block) + ee_len - 1) { |
1740 | /* tail removal */ | 1785 | /* tail removal */ |
1741 | unsigned long num; | 1786 | ext4_lblk_t num; |
1742 | ext4_fsblk_t start; | 1787 | ext4_fsblk_t start; |
1788 | |||
1743 | num = le32_to_cpu(ex->ee_block) + ee_len - from; | 1789 | num = le32_to_cpu(ex->ee_block) + ee_len - from; |
1744 | start = ext_pblock(ex) + ee_len - num; | 1790 | start = ext_pblock(ex) + ee_len - num; |
1745 | ext_debug("free last %lu blocks starting %llu\n", num, start); | 1791 | ext_debug("free last %u blocks starting %llu\n", num, start); |
1746 | for (i = 0; i < num; i++) { | 1792 | for (i = 0; i < num; i++) { |
1747 | bh = sb_find_get_block(inode->i_sb, start + i); | 1793 | bh = sb_find_get_block(inode->i_sb, start + i); |
1748 | ext4_forget(handle, 0, inode, bh, start + i); | 1794 | ext4_forget(handle, 0, inode, bh, start + i); |
1749 | } | 1795 | } |
1750 | ext4_free_blocks(handle, inode, start, num); | 1796 | ext4_free_blocks(handle, inode, start, num, metadata); |
1751 | } else if (from == le32_to_cpu(ex->ee_block) | 1797 | } else if (from == le32_to_cpu(ex->ee_block) |
1752 | && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { | 1798 | && to <= le32_to_cpu(ex->ee_block) + ee_len - 1) { |
1753 | printk("strange request: removal %lu-%lu from %u:%u\n", | 1799 | printk(KERN_INFO "strange request: removal %u-%u from %u:%u\n", |
1754 | from, to, le32_to_cpu(ex->ee_block), ee_len); | 1800 | from, to, le32_to_cpu(ex->ee_block), ee_len); |
1755 | } else { | 1801 | } else { |
1756 | printk("strange request: removal(2) %lu-%lu from %u:%u\n", | 1802 | printk(KERN_INFO "strange request: removal(2) " |
1757 | from, to, le32_to_cpu(ex->ee_block), ee_len); | 1803 | "%u-%u from %u:%u\n", |
1804 | from, to, le32_to_cpu(ex->ee_block), ee_len); | ||
1758 | } | 1805 | } |
1759 | return 0; | 1806 | return 0; |
1760 | } | 1807 | } |
1761 | 1808 | ||
1762 | static int | 1809 | static int |
1763 | ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | 1810 | ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, |
1764 | struct ext4_ext_path *path, unsigned long start) | 1811 | struct ext4_ext_path *path, ext4_lblk_t start) |
1765 | { | 1812 | { |
1766 | int err = 0, correct_index = 0; | 1813 | int err = 0, correct_index = 0; |
1767 | int depth = ext_depth(inode), credits; | 1814 | int depth = ext_depth(inode), credits; |
1768 | struct ext4_extent_header *eh; | 1815 | struct ext4_extent_header *eh; |
1769 | unsigned a, b, block, num; | 1816 | ext4_lblk_t a, b, block; |
1770 | unsigned long ex_ee_block; | 1817 | unsigned num; |
1818 | ext4_lblk_t ex_ee_block; | ||
1771 | unsigned short ex_ee_len; | 1819 | unsigned short ex_ee_len; |
1772 | unsigned uninitialized = 0; | 1820 | unsigned uninitialized = 0; |
1773 | struct ext4_extent *ex; | 1821 | struct ext4_extent *ex; |
1774 | 1822 | ||
1775 | /* the header must be checked already in ext4_ext_remove_space() */ | 1823 | /* the header must be checked already in ext4_ext_remove_space() */ |
1776 | ext_debug("truncate since %lu in leaf\n", start); | 1824 | ext_debug("truncate since %u in leaf\n", start); |
1777 | if (!path[depth].p_hdr) | 1825 | if (!path[depth].p_hdr) |
1778 | path[depth].p_hdr = ext_block_hdr(path[depth].p_bh); | 1826 | path[depth].p_hdr = ext_block_hdr(path[depth].p_bh); |
1779 | eh = path[depth].p_hdr; | 1827 | eh = path[depth].p_hdr; |
@@ -1904,7 +1952,7 @@ ext4_ext_more_to_rm(struct ext4_ext_path *path) | |||
1904 | return 1; | 1952 | return 1; |
1905 | } | 1953 | } |
1906 | 1954 | ||
1907 | int ext4_ext_remove_space(struct inode *inode, unsigned long start) | 1955 | static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start) |
1908 | { | 1956 | { |
1909 | struct super_block *sb = inode->i_sb; | 1957 | struct super_block *sb = inode->i_sb; |
1910 | int depth = ext_depth(inode); | 1958 | int depth = ext_depth(inode); |
@@ -1912,7 +1960,7 @@ int ext4_ext_remove_space(struct inode *inode, unsigned long start) | |||
1912 | handle_t *handle; | 1960 | handle_t *handle; |
1913 | int i = 0, err = 0; | 1961 | int i = 0, err = 0; |
1914 | 1962 | ||
1915 | ext_debug("truncate since %lu\n", start); | 1963 | ext_debug("truncate since %u\n", start); |
1916 | 1964 | ||
1917 | /* probably first extent we're gonna free will be last in block */ | 1965 | /* probably first extent we're gonna free will be last in block */ |
1918 | handle = ext4_journal_start(inode, depth + 1); | 1966 | handle = ext4_journal_start(inode, depth + 1); |
@@ -2094,17 +2142,19 @@ void ext4_ext_release(struct super_block *sb) | |||
2094 | * b> Splits in two extents: Write is happening at either end of the extent | 2142 | * b> Splits in two extents: Write is happening at either end of the extent |
2095 | * c> Splits in three extents: Somone is writing in middle of the extent | 2143 | * c> Splits in three extents: Somone is writing in middle of the extent |
2096 | */ | 2144 | */ |
2097 | int ext4_ext_convert_to_initialized(handle_t *handle, struct inode *inode, | 2145 | static int ext4_ext_convert_to_initialized(handle_t *handle, |
2098 | struct ext4_ext_path *path, | 2146 | struct inode *inode, |
2099 | ext4_fsblk_t iblock, | 2147 | struct ext4_ext_path *path, |
2100 | unsigned long max_blocks) | 2148 | ext4_lblk_t iblock, |
2149 | unsigned long max_blocks) | ||
2101 | { | 2150 | { |
2102 | struct ext4_extent *ex, newex; | 2151 | struct ext4_extent *ex, newex; |
2103 | struct ext4_extent *ex1 = NULL; | 2152 | struct ext4_extent *ex1 = NULL; |
2104 | struct ext4_extent *ex2 = NULL; | 2153 | struct ext4_extent *ex2 = NULL; |
2105 | struct ext4_extent *ex3 = NULL; | 2154 | struct ext4_extent *ex3 = NULL; |
2106 | struct ext4_extent_header *eh; | 2155 | struct ext4_extent_header *eh; |
2107 | unsigned int allocated, ee_block, ee_len, depth; | 2156 | ext4_lblk_t ee_block; |
2157 | unsigned int allocated, ee_len, depth; | ||
2108 | ext4_fsblk_t newblock; | 2158 | ext4_fsblk_t newblock; |
2109 | int err = 0; | 2159 | int err = 0; |
2110 | int ret = 0; | 2160 | int ret = 0; |
@@ -2225,8 +2275,13 @@ out: | |||
2225 | return err ? err : allocated; | 2275 | return err ? err : allocated; |
2226 | } | 2276 | } |
2227 | 2277 | ||
2278 | /* | ||
2279 | * Need to be called with | ||
2280 | * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system block | ||
2281 | * (ie, create is zero). Otherwise down_write(&EXT4_I(inode)->i_data_sem) | ||
2282 | */ | ||
2228 | int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | 2283 | int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, |
2229 | ext4_fsblk_t iblock, | 2284 | ext4_lblk_t iblock, |
2230 | unsigned long max_blocks, struct buffer_head *bh_result, | 2285 | unsigned long max_blocks, struct buffer_head *bh_result, |
2231 | int create, int extend_disksize) | 2286 | int create, int extend_disksize) |
2232 | { | 2287 | { |
@@ -2236,11 +2291,11 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2236 | ext4_fsblk_t goal, newblock; | 2291 | ext4_fsblk_t goal, newblock; |
2237 | int err = 0, depth, ret; | 2292 | int err = 0, depth, ret; |
2238 | unsigned long allocated = 0; | 2293 | unsigned long allocated = 0; |
2294 | struct ext4_allocation_request ar; | ||
2239 | 2295 | ||
2240 | __clear_bit(BH_New, &bh_result->b_state); | 2296 | __clear_bit(BH_New, &bh_result->b_state); |
2241 | ext_debug("blocks %d/%lu requested for inode %u\n", (int) iblock, | 2297 | ext_debug("blocks %u/%lu requested for inode %u\n", |
2242 | max_blocks, (unsigned) inode->i_ino); | 2298 | iblock, max_blocks, inode->i_ino); |
2243 | mutex_lock(&EXT4_I(inode)->truncate_mutex); | ||
2244 | 2299 | ||
2245 | /* check in cache */ | 2300 | /* check in cache */ |
2246 | goal = ext4_ext_in_cache(inode, iblock, &newex); | 2301 | goal = ext4_ext_in_cache(inode, iblock, &newex); |
@@ -2260,7 +2315,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2260 | - le32_to_cpu(newex.ee_block) | 2315 | - le32_to_cpu(newex.ee_block) |
2261 | + ext_pblock(&newex); | 2316 | + ext_pblock(&newex); |
2262 | /* number of remaining blocks in the extent */ | 2317 | /* number of remaining blocks in the extent */ |
2263 | allocated = le16_to_cpu(newex.ee_len) - | 2318 | allocated = ext4_ext_get_actual_len(&newex) - |
2264 | (iblock - le32_to_cpu(newex.ee_block)); | 2319 | (iblock - le32_to_cpu(newex.ee_block)); |
2265 | goto out; | 2320 | goto out; |
2266 | } else { | 2321 | } else { |
@@ -2288,7 +2343,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2288 | 2343 | ||
2289 | ex = path[depth].p_ext; | 2344 | ex = path[depth].p_ext; |
2290 | if (ex) { | 2345 | if (ex) { |
2291 | unsigned long ee_block = le32_to_cpu(ex->ee_block); | 2346 | ext4_lblk_t ee_block = le32_to_cpu(ex->ee_block); |
2292 | ext4_fsblk_t ee_start = ext_pblock(ex); | 2347 | ext4_fsblk_t ee_start = ext_pblock(ex); |
2293 | unsigned short ee_len; | 2348 | unsigned short ee_len; |
2294 | 2349 | ||
@@ -2302,7 +2357,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2302 | newblock = iblock - ee_block + ee_start; | 2357 | newblock = iblock - ee_block + ee_start; |
2303 | /* number of remaining blocks in the extent */ | 2358 | /* number of remaining blocks in the extent */ |
2304 | allocated = ee_len - (iblock - ee_block); | 2359 | allocated = ee_len - (iblock - ee_block); |
2305 | ext_debug("%d fit into %lu:%d -> %llu\n", (int) iblock, | 2360 | ext_debug("%u fit into %lu:%d -> %llu\n", iblock, |
2306 | ee_block, ee_len, newblock); | 2361 | ee_block, ee_len, newblock); |
2307 | 2362 | ||
2308 | /* Do not put uninitialized extent in the cache */ | 2363 | /* Do not put uninitialized extent in the cache */ |
@@ -2320,9 +2375,10 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2320 | ret = ext4_ext_convert_to_initialized(handle, inode, | 2375 | ret = ext4_ext_convert_to_initialized(handle, inode, |
2321 | path, iblock, | 2376 | path, iblock, |
2322 | max_blocks); | 2377 | max_blocks); |
2323 | if (ret <= 0) | 2378 | if (ret <= 0) { |
2379 | err = ret; | ||
2324 | goto out2; | 2380 | goto out2; |
2325 | else | 2381 | } else |
2326 | allocated = ret; | 2382 | allocated = ret; |
2327 | goto outnew; | 2383 | goto outnew; |
2328 | } | 2384 | } |
@@ -2347,8 +2403,15 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2347 | if (S_ISREG(inode->i_mode) && (!EXT4_I(inode)->i_block_alloc_info)) | 2403 | if (S_ISREG(inode->i_mode) && (!EXT4_I(inode)->i_block_alloc_info)) |
2348 | ext4_init_block_alloc_info(inode); | 2404 | ext4_init_block_alloc_info(inode); |
2349 | 2405 | ||
2350 | /* allocate new block */ | 2406 | /* find neighbour allocated blocks */ |
2351 | goal = ext4_ext_find_goal(inode, path, iblock); | 2407 | ar.lleft = iblock; |
2408 | err = ext4_ext_search_left(inode, path, &ar.lleft, &ar.pleft); | ||
2409 | if (err) | ||
2410 | goto out2; | ||
2411 | ar.lright = iblock; | ||
2412 | err = ext4_ext_search_right(inode, path, &ar.lright, &ar.pright); | ||
2413 | if (err) | ||
2414 | goto out2; | ||
2352 | 2415 | ||
2353 | /* | 2416 | /* |
2354 | * See if request is beyond maximum number of blocks we can have in | 2417 | * See if request is beyond maximum number of blocks we can have in |
@@ -2368,10 +2431,21 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2368 | newex.ee_len = cpu_to_le16(max_blocks); | 2431 | newex.ee_len = cpu_to_le16(max_blocks); |
2369 | err = ext4_ext_check_overlap(inode, &newex, path); | 2432 | err = ext4_ext_check_overlap(inode, &newex, path); |
2370 | if (err) | 2433 | if (err) |
2371 | allocated = le16_to_cpu(newex.ee_len); | 2434 | allocated = ext4_ext_get_actual_len(&newex); |
2372 | else | 2435 | else |
2373 | allocated = max_blocks; | 2436 | allocated = max_blocks; |
2374 | newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err); | 2437 | |
2438 | /* allocate new block */ | ||
2439 | ar.inode = inode; | ||
2440 | ar.goal = ext4_ext_find_goal(inode, path, iblock); | ||
2441 | ar.logical = iblock; | ||
2442 | ar.len = allocated; | ||
2443 | if (S_ISREG(inode->i_mode)) | ||
2444 | ar.flags = EXT4_MB_HINT_DATA; | ||
2445 | else | ||
2446 | /* disable in-core preallocation for non-regular files */ | ||
2447 | ar.flags = 0; | ||
2448 | newblock = ext4_mb_new_blocks(handle, &ar, &err); | ||
2375 | if (!newblock) | 2449 | if (!newblock) |
2376 | goto out2; | 2450 | goto out2; |
2377 | ext_debug("allocate new block: goal %llu, found %llu/%lu\n", | 2451 | ext_debug("allocate new block: goal %llu, found %llu/%lu\n", |
@@ -2379,14 +2453,17 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2379 | 2453 | ||
2380 | /* try to insert new extent into found leaf and return */ | 2454 | /* try to insert new extent into found leaf and return */ |
2381 | ext4_ext_store_pblock(&newex, newblock); | 2455 | ext4_ext_store_pblock(&newex, newblock); |
2382 | newex.ee_len = cpu_to_le16(allocated); | 2456 | newex.ee_len = cpu_to_le16(ar.len); |
2383 | if (create == EXT4_CREATE_UNINITIALIZED_EXT) /* Mark uninitialized */ | 2457 | if (create == EXT4_CREATE_UNINITIALIZED_EXT) /* Mark uninitialized */ |
2384 | ext4_ext_mark_uninitialized(&newex); | 2458 | ext4_ext_mark_uninitialized(&newex); |
2385 | err = ext4_ext_insert_extent(handle, inode, path, &newex); | 2459 | err = ext4_ext_insert_extent(handle, inode, path, &newex); |
2386 | if (err) { | 2460 | if (err) { |
2387 | /* free data blocks we just allocated */ | 2461 | /* free data blocks we just allocated */ |
2462 | /* not a good idea to call discard here directly, | ||
2463 | * but otherwise we'd need to call it every free() */ | ||
2464 | ext4_mb_discard_inode_preallocations(inode); | ||
2388 | ext4_free_blocks(handle, inode, ext_pblock(&newex), | 2465 | ext4_free_blocks(handle, inode, ext_pblock(&newex), |
2389 | le16_to_cpu(newex.ee_len)); | 2466 | ext4_ext_get_actual_len(&newex), 0); |
2390 | goto out2; | 2467 | goto out2; |
2391 | } | 2468 | } |
2392 | 2469 | ||
@@ -2395,6 +2472,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | |||
2395 | 2472 | ||
2396 | /* previous routine could use block we allocated */ | 2473 | /* previous routine could use block we allocated */ |
2397 | newblock = ext_pblock(&newex); | 2474 | newblock = ext_pblock(&newex); |
2475 | allocated = ext4_ext_get_actual_len(&newex); | ||
2398 | outnew: | 2476 | outnew: |
2399 | __set_bit(BH_New, &bh_result->b_state); | 2477 | __set_bit(BH_New, &bh_result->b_state); |
2400 | 2478 | ||
@@ -2414,8 +2492,6 @@ out2: | |||
2414 | ext4_ext_drop_refs(path); | 2492 | ext4_ext_drop_refs(path); |
2415 | kfree(path); | 2493 | kfree(path); |
2416 | } | 2494 | } |
2417 | mutex_unlock(&EXT4_I(inode)->truncate_mutex); | ||
2418 | |||
2419 | return err ? err : allocated; | 2495 | return err ? err : allocated; |
2420 | } | 2496 | } |
2421 | 2497 | ||
@@ -2423,7 +2499,7 @@ void ext4_ext_truncate(struct inode * inode, struct page *page) | |||
2423 | { | 2499 | { |
2424 | struct address_space *mapping = inode->i_mapping; | 2500 | struct address_space *mapping = inode->i_mapping; |
2425 | struct super_block *sb = inode->i_sb; | 2501 | struct super_block *sb = inode->i_sb; |
2426 | unsigned long last_block; | 2502 | ext4_lblk_t last_block; |
2427 | handle_t *handle; | 2503 | handle_t *handle; |
2428 | int err = 0; | 2504 | int err = 0; |
2429 | 2505 | ||
@@ -2445,9 +2521,11 @@ void ext4_ext_truncate(struct inode * inode, struct page *page) | |||
2445 | if (page) | 2521 | if (page) |
2446 | ext4_block_truncate_page(handle, page, mapping, inode->i_size); | 2522 | ext4_block_truncate_page(handle, page, mapping, inode->i_size); |
2447 | 2523 | ||
2448 | mutex_lock(&EXT4_I(inode)->truncate_mutex); | 2524 | down_write(&EXT4_I(inode)->i_data_sem); |
2449 | ext4_ext_invalidate_cache(inode); | 2525 | ext4_ext_invalidate_cache(inode); |
2450 | 2526 | ||
2527 | ext4_mb_discard_inode_preallocations(inode); | ||
2528 | |||
2451 | /* | 2529 | /* |
2452 | * TODO: optimization is possible here. | 2530 | * TODO: optimization is possible here. |
2453 | * Probably we need not scan at all, | 2531 | * Probably we need not scan at all, |
@@ -2481,7 +2559,7 @@ out_stop: | |||
2481 | if (inode->i_nlink) | 2559 | if (inode->i_nlink) |
2482 | ext4_orphan_del(handle, inode); | 2560 | ext4_orphan_del(handle, inode); |
2483 | 2561 | ||
2484 | mutex_unlock(&EXT4_I(inode)->truncate_mutex); | 2562 | up_write(&EXT4_I(inode)->i_data_sem); |
2485 | ext4_journal_stop(handle); | 2563 | ext4_journal_stop(handle); |
2486 | } | 2564 | } |
2487 | 2565 | ||
@@ -2516,7 +2594,8 @@ int ext4_ext_writepage_trans_blocks(struct inode *inode, int num) | |||
2516 | long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) | 2594 | long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) |
2517 | { | 2595 | { |
2518 | handle_t *handle; | 2596 | handle_t *handle; |
2519 | ext4_fsblk_t block, max_blocks; | 2597 | ext4_lblk_t block; |
2598 | unsigned long max_blocks; | ||
2520 | ext4_fsblk_t nblocks = 0; | 2599 | ext4_fsblk_t nblocks = 0; |
2521 | int ret = 0; | 2600 | int ret = 0; |
2522 | int ret2 = 0; | 2601 | int ret2 = 0; |
@@ -2544,6 +2623,7 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len) | |||
2544 | * modify 1 super block, 1 block bitmap and 1 group descriptor. | 2623 | * modify 1 super block, 1 block bitmap and 1 group descriptor. |
2545 | */ | 2624 | */ |
2546 | credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + 3; | 2625 | credits = EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + 3; |
2626 | down_write((&EXT4_I(inode)->i_data_sem)); | ||
2547 | retry: | 2627 | retry: |
2548 | while (ret >= 0 && ret < max_blocks) { | 2628 | while (ret >= 0 && ret < max_blocks) { |
2549 | block = block + ret; | 2629 | block = block + ret; |
@@ -2557,12 +2637,12 @@ retry: | |||
2557 | ret = ext4_ext_get_blocks(handle, inode, block, | 2637 | ret = ext4_ext_get_blocks(handle, inode, block, |
2558 | max_blocks, &map_bh, | 2638 | max_blocks, &map_bh, |
2559 | EXT4_CREATE_UNINITIALIZED_EXT, 0); | 2639 | EXT4_CREATE_UNINITIALIZED_EXT, 0); |
2560 | WARN_ON(!ret); | 2640 | WARN_ON(ret <= 0); |
2561 | if (!ret) { | 2641 | if (ret <= 0) { |
2562 | ext4_error(inode->i_sb, "ext4_fallocate", | 2642 | ext4_error(inode->i_sb, "ext4_fallocate", |
2563 | "ext4_ext_get_blocks returned 0! inode#%lu" | 2643 | "ext4_ext_get_blocks returned error: " |
2564 | ", block=%llu, max_blocks=%llu", | 2644 | "inode#%lu, block=%u, max_blocks=%lu", |
2565 | inode->i_ino, block, max_blocks); | 2645 | inode->i_ino, block, max_blocks); |
2566 | ret = -EIO; | 2646 | ret = -EIO; |
2567 | ext4_mark_inode_dirty(handle, inode); | 2647 | ext4_mark_inode_dirty(handle, inode); |
2568 | ret2 = ext4_journal_stop(handle); | 2648 | ret2 = ext4_journal_stop(handle); |
@@ -2600,6 +2680,7 @@ retry: | |||
2600 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) | 2680 | if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) |
2601 | goto retry; | 2681 | goto retry; |
2602 | 2682 | ||
2683 | up_write((&EXT4_I(inode)->i_data_sem)); | ||
2603 | /* | 2684 | /* |
2604 | * Time to update the file size. | 2685 | * Time to update the file size. |
2605 | * Update only when preallocation was requested beyond the file size. | 2686 | * Update only when preallocation was requested beyond the file size. |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 1a81cd66d63b..ac35ec58db55 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -37,9 +37,9 @@ static int ext4_release_file (struct inode * inode, struct file * filp) | |||
37 | if ((filp->f_mode & FMODE_WRITE) && | 37 | if ((filp->f_mode & FMODE_WRITE) && |
38 | (atomic_read(&inode->i_writecount) == 1)) | 38 | (atomic_read(&inode->i_writecount) == 1)) |
39 | { | 39 | { |
40 | mutex_lock(&EXT4_I(inode)->truncate_mutex); | 40 | down_write(&EXT4_I(inode)->i_data_sem); |
41 | ext4_discard_reservation(inode); | 41 | ext4_discard_reservation(inode); |
42 | mutex_unlock(&EXT4_I(inode)->truncate_mutex); | 42 | up_write(&EXT4_I(inode)->i_data_sem); |
43 | } | 43 | } |
44 | if (is_dx(inode) && filp->private_data) | 44 | if (is_dx(inode) && filp->private_data) |
45 | ext4_htree_free_dir_info(filp->private_data); | 45 | ext4_htree_free_dir_info(filp->private_data); |
@@ -56,8 +56,25 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
56 | ssize_t ret; | 56 | ssize_t ret; |
57 | int err; | 57 | int err; |
58 | 58 | ||
59 | ret = generic_file_aio_write(iocb, iov, nr_segs, pos); | 59 | /* |
60 | * If we have encountered a bitmap-format file, the size limit | ||
61 | * is smaller than s_maxbytes, which is for extent-mapped files. | ||
62 | */ | ||
63 | |||
64 | if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) { | ||
65 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||
66 | size_t length = iov_length(iov, nr_segs); | ||
60 | 67 | ||
68 | if (pos > sbi->s_bitmap_maxbytes) | ||
69 | return -EFBIG; | ||
70 | |||
71 | if (pos + length > sbi->s_bitmap_maxbytes) { | ||
72 | nr_segs = iov_shorten((struct iovec *)iov, nr_segs, | ||
73 | sbi->s_bitmap_maxbytes - pos); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | ret = generic_file_aio_write(iocb, iov, nr_segs, pos); | ||
61 | /* | 78 | /* |
62 | * Skip flushing if there was an error, or if nothing was written. | 79 | * Skip flushing if there was an error, or if nothing was written. |
63 | */ | 80 | */ |
diff --git a/fs/ext4/group.h b/fs/ext4/group.h index 1577910bb58b..7eb0604e7eea 100644 --- a/fs/ext4/group.h +++ b/fs/ext4/group.h | |||
@@ -14,14 +14,16 @@ extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group, | |||
14 | extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group, | 14 | extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group, |
15 | struct ext4_group_desc *gdp); | 15 | struct ext4_group_desc *gdp); |
16 | struct buffer_head *read_block_bitmap(struct super_block *sb, | 16 | struct buffer_head *read_block_bitmap(struct super_block *sb, |
17 | unsigned int block_group); | 17 | ext4_group_t block_group); |
18 | extern unsigned ext4_init_block_bitmap(struct super_block *sb, | 18 | extern unsigned ext4_init_block_bitmap(struct super_block *sb, |
19 | struct buffer_head *bh, int group, | 19 | struct buffer_head *bh, |
20 | ext4_group_t group, | ||
20 | struct ext4_group_desc *desc); | 21 | struct ext4_group_desc *desc); |
21 | #define ext4_free_blocks_after_init(sb, group, desc) \ | 22 | #define ext4_free_blocks_after_init(sb, group, desc) \ |
22 | ext4_init_block_bitmap(sb, NULL, group, desc) | 23 | ext4_init_block_bitmap(sb, NULL, group, desc) |
23 | extern unsigned ext4_init_inode_bitmap(struct super_block *sb, | 24 | extern unsigned ext4_init_inode_bitmap(struct super_block *sb, |
24 | struct buffer_head *bh, int group, | 25 | struct buffer_head *bh, |
26 | ext4_group_t group, | ||
25 | struct ext4_group_desc *desc); | 27 | struct ext4_group_desc *desc); |
26 | extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap); | 28 | extern void mark_bitmap_end(int start_bit, int end_bit, char *bitmap); |
27 | #endif /* _LINUX_EXT4_GROUP_H */ | 29 | #endif /* _LINUX_EXT4_GROUP_H */ |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index c61f37fd3f05..575b5215c808 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -64,8 +64,8 @@ void mark_bitmap_end(int start_bit, int end_bit, char *bitmap) | |||
64 | } | 64 | } |
65 | 65 | ||
66 | /* Initializes an uninitialized inode bitmap */ | 66 | /* Initializes an uninitialized inode bitmap */ |
67 | unsigned ext4_init_inode_bitmap(struct super_block *sb, | 67 | unsigned ext4_init_inode_bitmap(struct super_block *sb, struct buffer_head *bh, |
68 | struct buffer_head *bh, int block_group, | 68 | ext4_group_t block_group, |
69 | struct ext4_group_desc *gdp) | 69 | struct ext4_group_desc *gdp) |
70 | { | 70 | { |
71 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 71 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
@@ -75,7 +75,7 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb, | |||
75 | /* If checksum is bad mark all blocks and inodes use to prevent | 75 | /* If checksum is bad mark all blocks and inodes use to prevent |
76 | * allocation, essentially implementing a per-group read-only flag. */ | 76 | * allocation, essentially implementing a per-group read-only flag. */ |
77 | if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { | 77 | if (!ext4_group_desc_csum_verify(sbi, block_group, gdp)) { |
78 | ext4_error(sb, __FUNCTION__, "Checksum bad for group %u\n", | 78 | ext4_error(sb, __FUNCTION__, "Checksum bad for group %lu\n", |
79 | block_group); | 79 | block_group); |
80 | gdp->bg_free_blocks_count = 0; | 80 | gdp->bg_free_blocks_count = 0; |
81 | gdp->bg_free_inodes_count = 0; | 81 | gdp->bg_free_inodes_count = 0; |
@@ -98,7 +98,7 @@ unsigned ext4_init_inode_bitmap(struct super_block *sb, | |||
98 | * Return buffer_head of bitmap on success or NULL. | 98 | * Return buffer_head of bitmap on success or NULL. |
99 | */ | 99 | */ |
100 | static struct buffer_head * | 100 | static struct buffer_head * |
101 | read_inode_bitmap(struct super_block * sb, unsigned long block_group) | 101 | read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) |
102 | { | 102 | { |
103 | struct ext4_group_desc *desc; | 103 | struct ext4_group_desc *desc; |
104 | struct buffer_head *bh = NULL; | 104 | struct buffer_head *bh = NULL; |
@@ -152,7 +152,7 @@ void ext4_free_inode (handle_t *handle, struct inode * inode) | |||
152 | unsigned long ino; | 152 | unsigned long ino; |
153 | struct buffer_head *bitmap_bh = NULL; | 153 | struct buffer_head *bitmap_bh = NULL; |
154 | struct buffer_head *bh2; | 154 | struct buffer_head *bh2; |
155 | unsigned long block_group; | 155 | ext4_group_t block_group; |
156 | unsigned long bit; | 156 | unsigned long bit; |
157 | struct ext4_group_desc * gdp; | 157 | struct ext4_group_desc * gdp; |
158 | struct ext4_super_block * es; | 158 | struct ext4_super_block * es; |
@@ -260,12 +260,14 @@ error_return: | |||
260 | * For other inodes, search forward from the parent directory\'s block | 260 | * For other inodes, search forward from the parent directory\'s block |
261 | * group to find a free inode. | 261 | * group to find a free inode. |
262 | */ | 262 | */ |
263 | static int find_group_dir(struct super_block *sb, struct inode *parent) | 263 | static int find_group_dir(struct super_block *sb, struct inode *parent, |
264 | ext4_group_t *best_group) | ||
264 | { | 265 | { |
265 | int ngroups = EXT4_SB(sb)->s_groups_count; | 266 | ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; |
266 | unsigned int freei, avefreei; | 267 | unsigned int freei, avefreei; |
267 | struct ext4_group_desc *desc, *best_desc = NULL; | 268 | struct ext4_group_desc *desc, *best_desc = NULL; |
268 | int group, best_group = -1; | 269 | ext4_group_t group; |
270 | int ret = -1; | ||
269 | 271 | ||
270 | freei = percpu_counter_read_positive(&EXT4_SB(sb)->s_freeinodes_counter); | 272 | freei = percpu_counter_read_positive(&EXT4_SB(sb)->s_freeinodes_counter); |
271 | avefreei = freei / ngroups; | 273 | avefreei = freei / ngroups; |
@@ -279,11 +281,12 @@ static int find_group_dir(struct super_block *sb, struct inode *parent) | |||
279 | if (!best_desc || | 281 | if (!best_desc || |
280 | (le16_to_cpu(desc->bg_free_blocks_count) > | 282 | (le16_to_cpu(desc->bg_free_blocks_count) > |
281 | le16_to_cpu(best_desc->bg_free_blocks_count))) { | 283 | le16_to_cpu(best_desc->bg_free_blocks_count))) { |
282 | best_group = group; | 284 | *best_group = group; |
283 | best_desc = desc; | 285 | best_desc = desc; |
286 | ret = 0; | ||
284 | } | 287 | } |
285 | } | 288 | } |
286 | return best_group; | 289 | return ret; |
287 | } | 290 | } |
288 | 291 | ||
289 | /* | 292 | /* |
@@ -314,12 +317,13 @@ static int find_group_dir(struct super_block *sb, struct inode *parent) | |||
314 | #define INODE_COST 64 | 317 | #define INODE_COST 64 |
315 | #define BLOCK_COST 256 | 318 | #define BLOCK_COST 256 |
316 | 319 | ||
317 | static int find_group_orlov(struct super_block *sb, struct inode *parent) | 320 | static int find_group_orlov(struct super_block *sb, struct inode *parent, |
321 | ext4_group_t *group) | ||
318 | { | 322 | { |
319 | int parent_group = EXT4_I(parent)->i_block_group; | 323 | ext4_group_t parent_group = EXT4_I(parent)->i_block_group; |
320 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 324 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
321 | struct ext4_super_block *es = sbi->s_es; | 325 | struct ext4_super_block *es = sbi->s_es; |
322 | int ngroups = sbi->s_groups_count; | 326 | ext4_group_t ngroups = sbi->s_groups_count; |
323 | int inodes_per_group = EXT4_INODES_PER_GROUP(sb); | 327 | int inodes_per_group = EXT4_INODES_PER_GROUP(sb); |
324 | unsigned int freei, avefreei; | 328 | unsigned int freei, avefreei; |
325 | ext4_fsblk_t freeb, avefreeb; | 329 | ext4_fsblk_t freeb, avefreeb; |
@@ -327,7 +331,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) | |||
327 | unsigned int ndirs; | 331 | unsigned int ndirs; |
328 | int max_debt, max_dirs, min_inodes; | 332 | int max_debt, max_dirs, min_inodes; |
329 | ext4_grpblk_t min_blocks; | 333 | ext4_grpblk_t min_blocks; |
330 | int group = -1, i; | 334 | ext4_group_t i; |
331 | struct ext4_group_desc *desc; | 335 | struct ext4_group_desc *desc; |
332 | 336 | ||
333 | freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); | 337 | freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); |
@@ -340,13 +344,14 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) | |||
340 | if ((parent == sb->s_root->d_inode) || | 344 | if ((parent == sb->s_root->d_inode) || |
341 | (EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL)) { | 345 | (EXT4_I(parent)->i_flags & EXT4_TOPDIR_FL)) { |
342 | int best_ndir = inodes_per_group; | 346 | int best_ndir = inodes_per_group; |
343 | int best_group = -1; | 347 | ext4_group_t grp; |
348 | int ret = -1; | ||
344 | 349 | ||
345 | get_random_bytes(&group, sizeof(group)); | 350 | get_random_bytes(&grp, sizeof(grp)); |
346 | parent_group = (unsigned)group % ngroups; | 351 | parent_group = (unsigned)grp % ngroups; |
347 | for (i = 0; i < ngroups; i++) { | 352 | for (i = 0; i < ngroups; i++) { |
348 | group = (parent_group + i) % ngroups; | 353 | grp = (parent_group + i) % ngroups; |
349 | desc = ext4_get_group_desc (sb, group, NULL); | 354 | desc = ext4_get_group_desc(sb, grp, NULL); |
350 | if (!desc || !desc->bg_free_inodes_count) | 355 | if (!desc || !desc->bg_free_inodes_count) |
351 | continue; | 356 | continue; |
352 | if (le16_to_cpu(desc->bg_used_dirs_count) >= best_ndir) | 357 | if (le16_to_cpu(desc->bg_used_dirs_count) >= best_ndir) |
@@ -355,11 +360,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) | |||
355 | continue; | 360 | continue; |
356 | if (le16_to_cpu(desc->bg_free_blocks_count) < avefreeb) | 361 | if (le16_to_cpu(desc->bg_free_blocks_count) < avefreeb) |
357 | continue; | 362 | continue; |
358 | best_group = group; | 363 | *group = grp; |
364 | ret = 0; | ||
359 | best_ndir = le16_to_cpu(desc->bg_used_dirs_count); | 365 | best_ndir = le16_to_cpu(desc->bg_used_dirs_count); |
360 | } | 366 | } |
361 | if (best_group >= 0) | 367 | if (ret == 0) |
362 | return best_group; | 368 | return ret; |
363 | goto fallback; | 369 | goto fallback; |
364 | } | 370 | } |
365 | 371 | ||
@@ -380,8 +386,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) | |||
380 | max_debt = 1; | 386 | max_debt = 1; |
381 | 387 | ||
382 | for (i = 0; i < ngroups; i++) { | 388 | for (i = 0; i < ngroups; i++) { |
383 | group = (parent_group + i) % ngroups; | 389 | *group = (parent_group + i) % ngroups; |
384 | desc = ext4_get_group_desc (sb, group, NULL); | 390 | desc = ext4_get_group_desc(sb, *group, NULL); |
385 | if (!desc || !desc->bg_free_inodes_count) | 391 | if (!desc || !desc->bg_free_inodes_count) |
386 | continue; | 392 | continue; |
387 | if (le16_to_cpu(desc->bg_used_dirs_count) >= max_dirs) | 393 | if (le16_to_cpu(desc->bg_used_dirs_count) >= max_dirs) |
@@ -390,17 +396,16 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent) | |||
390 | continue; | 396 | continue; |
391 | if (le16_to_cpu(desc->bg_free_blocks_count) < min_blocks) | 397 | if (le16_to_cpu(desc->bg_free_blocks_count) < min_blocks) |
392 | continue; | 398 | continue; |
393 | return group; | 399 | return 0; |
394 | } | 400 | } |
395 | 401 | ||
396 | fallback: | 402 | fallback: |
397 | for (i = 0; i < ngroups; i++) { | 403 | for (i = 0; i < ngroups; i++) { |
398 | group = (parent_group + i) % ngroups; | 404 | *group = (parent_group + i) % ngroups; |
399 | desc = ext4_get_group_desc (sb, group, NULL); | 405 | desc = ext4_get_group_desc(sb, *group, NULL); |
400 | if (!desc || !desc->bg_free_inodes_count) | 406 | if (desc && desc->bg_free_inodes_count && |
401 | continue; | 407 | le16_to_cpu(desc->bg_free_inodes_count) >= avefreei) |
402 | if (le16_to_cpu(desc->bg_free_inodes_count) >= avefreei) | 408 | return 0; |
403 | return group; | ||
404 | } | 409 | } |
405 | 410 | ||
406 | if (avefreei) { | 411 | if (avefreei) { |
@@ -415,21 +420,22 @@ fallback: | |||
415 | return -1; | 420 | return -1; |
416 | } | 421 | } |
417 | 422 | ||
418 | static int find_group_other(struct super_block *sb, struct inode *parent) | 423 | static int find_group_other(struct super_block *sb, struct inode *parent, |
424 | ext4_group_t *group) | ||
419 | { | 425 | { |
420 | int parent_group = EXT4_I(parent)->i_block_group; | 426 | ext4_group_t parent_group = EXT4_I(parent)->i_block_group; |
421 | int ngroups = EXT4_SB(sb)->s_groups_count; | 427 | ext4_group_t ngroups = EXT4_SB(sb)->s_groups_count; |
422 | struct ext4_group_desc *desc; | 428 | struct ext4_group_desc *desc; |
423 | int group, i; | 429 | ext4_group_t i; |
424 | 430 | ||
425 | /* | 431 | /* |
426 | * Try to place the inode in its parent directory | 432 | * Try to place the inode in its parent directory |
427 | */ | 433 | */ |
428 | group = parent_group; | 434 | *group = parent_group; |
429 | desc = ext4_get_group_desc (sb, group, NULL); | 435 | desc = ext4_get_group_desc(sb, *group, NULL); |
430 | if (desc && le16_to_cpu(desc->bg_free_inodes_count) && | 436 | if (desc && le16_to_cpu(desc->bg_free_inodes_count) && |
431 | le16_to_cpu(desc->bg_free_blocks_count)) | 437 | le16_to_cpu(desc->bg_free_blocks_count)) |
432 | return group; | 438 | return 0; |
433 | 439 | ||
434 | /* | 440 | /* |
435 | * We're going to place this inode in a different blockgroup from its | 441 | * We're going to place this inode in a different blockgroup from its |
@@ -440,33 +446,33 @@ static int find_group_other(struct super_block *sb, struct inode *parent) | |||
440 | * | 446 | * |
441 | * So add our directory's i_ino into the starting point for the hash. | 447 | * So add our directory's i_ino into the starting point for the hash. |
442 | */ | 448 | */ |
443 | group = (group + parent->i_ino) % ngroups; | 449 | *group = (*group + parent->i_ino) % ngroups; |
444 | 450 | ||
445 | /* | 451 | /* |
446 | * Use a quadratic hash to find a group with a free inode and some free | 452 | * Use a quadratic hash to find a group with a free inode and some free |
447 | * blocks. | 453 | * blocks. |
448 | */ | 454 | */ |
449 | for (i = 1; i < ngroups; i <<= 1) { | 455 | for (i = 1; i < ngroups; i <<= 1) { |
450 | group += i; | 456 | *group += i; |
451 | if (group >= ngroups) | 457 | if (*group >= ngroups) |
452 | group -= ngroups; | 458 | *group -= ngroups; |
453 | desc = ext4_get_group_desc (sb, group, NULL); | 459 | desc = ext4_get_group_desc(sb, *group, NULL); |
454 | if (desc && le16_to_cpu(desc->bg_free_inodes_count) && | 460 | if (desc && le16_to_cpu(desc->bg_free_inodes_count) && |
455 | le16_to_cpu(desc->bg_free_blocks_count)) | 461 | le16_to_cpu(desc->bg_free_blocks_count)) |
456 | return group; | 462 | return 0; |
457 | } | 463 | } |
458 | 464 | ||
459 | /* | 465 | /* |
460 | * That failed: try linear search for a free inode, even if that group | 466 | * That failed: try linear search for a free inode, even if that group |
461 | * has no free blocks. | 467 | * has no free blocks. |
462 | */ | 468 | */ |
463 | group = parent_group; | 469 | *group = parent_group; |
464 | for (i = 0; i < ngroups; i++) { | 470 | for (i = 0; i < ngroups; i++) { |
465 | if (++group >= ngroups) | 471 | if (++*group >= ngroups) |
466 | group = 0; | 472 | *group = 0; |
467 | desc = ext4_get_group_desc (sb, group, NULL); | 473 | desc = ext4_get_group_desc(sb, *group, NULL); |
468 | if (desc && le16_to_cpu(desc->bg_free_inodes_count)) | 474 | if (desc && le16_to_cpu(desc->bg_free_inodes_count)) |
469 | return group; | 475 | return 0; |
470 | } | 476 | } |
471 | 477 | ||
472 | return -1; | 478 | return -1; |
@@ -487,16 +493,17 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode) | |||
487 | struct super_block *sb; | 493 | struct super_block *sb; |
488 | struct buffer_head *bitmap_bh = NULL; | 494 | struct buffer_head *bitmap_bh = NULL; |
489 | struct buffer_head *bh2; | 495 | struct buffer_head *bh2; |
490 | int group; | 496 | ext4_group_t group = 0; |
491 | unsigned long ino = 0; | 497 | unsigned long ino = 0; |
492 | struct inode * inode; | 498 | struct inode * inode; |
493 | struct ext4_group_desc * gdp = NULL; | 499 | struct ext4_group_desc * gdp = NULL; |
494 | struct ext4_super_block * es; | 500 | struct ext4_super_block * es; |
495 | struct ext4_inode_info *ei; | 501 | struct ext4_inode_info *ei; |
496 | struct ext4_sb_info *sbi; | 502 | struct ext4_sb_info *sbi; |
497 | int err = 0; | 503 | int ret2, err = 0; |
498 | struct inode *ret; | 504 | struct inode *ret; |
499 | int i, free = 0; | 505 | ext4_group_t i; |
506 | int free = 0; | ||
500 | 507 | ||
501 | /* Cannot create files in a deleted directory */ | 508 | /* Cannot create files in a deleted directory */ |
502 | if (!dir || !dir->i_nlink) | 509 | if (!dir || !dir->i_nlink) |
@@ -512,14 +519,14 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode * dir, int mode) | |||
512 | es = sbi->s_es; | 519 | es = sbi->s_es; |
513 | if (S_ISDIR(mode)) { | 520 | if (S_ISDIR(mode)) { |
514 | if (test_opt (sb, OLDALLOC)) | 521 | if (test_opt (sb, OLDALLOC)) |
515 | group = find_group_dir(sb, dir); | 522 | ret2 = find_group_dir(sb, dir, &group); |
516 | else | 523 | else |
517 | group = find_group_orlov(sb, dir); | 524 | ret2 = find_group_orlov(sb, dir, &group); |
518 | } else | 525 | } else |
519 | group = find_group_other(sb, dir); | 526 | ret2 = find_group_other(sb, dir, &group); |
520 | 527 | ||
521 | err = -ENOSPC; | 528 | err = -ENOSPC; |
522 | if (group == -1) | 529 | if (ret2 == -1) |
523 | goto out; | 530 | goto out; |
524 | 531 | ||
525 | for (i = 0; i < sbi->s_groups_count; i++) { | 532 | for (i = 0; i < sbi->s_groups_count; i++) { |
@@ -583,7 +590,7 @@ got: | |||
583 | ino > EXT4_INODES_PER_GROUP(sb)) { | 590 | ino > EXT4_INODES_PER_GROUP(sb)) { |
584 | ext4_error(sb, __FUNCTION__, | 591 | ext4_error(sb, __FUNCTION__, |
585 | "reserved inode or inode > inodes count - " | 592 | "reserved inode or inode > inodes count - " |
586 | "block_group = %d, inode=%lu", group, | 593 | "block_group = %lu, inode=%lu", group, |
587 | ino + group * EXT4_INODES_PER_GROUP(sb)); | 594 | ino + group * EXT4_INODES_PER_GROUP(sb)); |
588 | err = -EIO; | 595 | err = -EIO; |
589 | goto fail; | 596 | goto fail; |
@@ -702,7 +709,6 @@ got: | |||
702 | if (!S_ISDIR(mode)) | 709 | if (!S_ISDIR(mode)) |
703 | ei->i_flags &= ~EXT4_DIRSYNC_FL; | 710 | ei->i_flags &= ~EXT4_DIRSYNC_FL; |
704 | ei->i_file_acl = 0; | 711 | ei->i_file_acl = 0; |
705 | ei->i_dir_acl = 0; | ||
706 | ei->i_dtime = 0; | 712 | ei->i_dtime = 0; |
707 | ei->i_block_alloc_info = NULL; | 713 | ei->i_block_alloc_info = NULL; |
708 | ei->i_block_group = group; | 714 | ei->i_block_group = group; |
@@ -741,13 +747,10 @@ got: | |||
741 | if (test_opt(sb, EXTENTS)) { | 747 | if (test_opt(sb, EXTENTS)) { |
742 | EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL; | 748 | EXT4_I(inode)->i_flags |= EXT4_EXTENTS_FL; |
743 | ext4_ext_tree_init(handle, inode); | 749 | ext4_ext_tree_init(handle, inode); |
744 | if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) { | 750 | err = ext4_update_incompat_feature(handle, sb, |
745 | err = ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh); | 751 | EXT4_FEATURE_INCOMPAT_EXTENTS); |
746 | if (err) goto fail; | 752 | if (err) |
747 | EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS); | 753 | goto fail; |
748 | BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "call ext4_journal_dirty_metadata"); | ||
749 | err = ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh); | ||
750 | } | ||
751 | } | 754 | } |
752 | 755 | ||
753 | ext4_debug("allocating inode %lu\n", inode->i_ino); | 756 | ext4_debug("allocating inode %lu\n", inode->i_ino); |
@@ -777,7 +780,7 @@ fail_drop: | |||
777 | struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) | 780 | struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino) |
778 | { | 781 | { |
779 | unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count); | 782 | unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count); |
780 | unsigned long block_group; | 783 | ext4_group_t block_group; |
781 | int bit; | 784 | int bit; |
782 | struct buffer_head *bitmap_bh = NULL; | 785 | struct buffer_head *bitmap_bh = NULL; |
783 | struct inode *inode = NULL; | 786 | struct inode *inode = NULL; |
@@ -833,7 +836,7 @@ unsigned long ext4_count_free_inodes (struct super_block * sb) | |||
833 | { | 836 | { |
834 | unsigned long desc_count; | 837 | unsigned long desc_count; |
835 | struct ext4_group_desc *gdp; | 838 | struct ext4_group_desc *gdp; |
836 | int i; | 839 | ext4_group_t i; |
837 | #ifdef EXT4FS_DEBUG | 840 | #ifdef EXT4FS_DEBUG |
838 | struct ext4_super_block *es; | 841 | struct ext4_super_block *es; |
839 | unsigned long bitmap_count, x; | 842 | unsigned long bitmap_count, x; |
@@ -854,7 +857,7 @@ unsigned long ext4_count_free_inodes (struct super_block * sb) | |||
854 | continue; | 857 | continue; |
855 | 858 | ||
856 | x = ext4_count_free(bitmap_bh, EXT4_INODES_PER_GROUP(sb) / 8); | 859 | x = ext4_count_free(bitmap_bh, EXT4_INODES_PER_GROUP(sb) / 8); |
857 | printk("group %d: stored = %d, counted = %lu\n", | 860 | printk(KERN_DEBUG "group %lu: stored = %d, counted = %lu\n", |
858 | i, le16_to_cpu(gdp->bg_free_inodes_count), x); | 861 | i, le16_to_cpu(gdp->bg_free_inodes_count), x); |
859 | bitmap_count += x; | 862 | bitmap_count += x; |
860 | } | 863 | } |
@@ -879,7 +882,7 @@ unsigned long ext4_count_free_inodes (struct super_block * sb) | |||
879 | unsigned long ext4_count_dirs (struct super_block * sb) | 882 | unsigned long ext4_count_dirs (struct super_block * sb) |
880 | { | 883 | { |
881 | unsigned long count = 0; | 884 | unsigned long count = 0; |
882 | int i; | 885 | ext4_group_t i; |
883 | 886 | ||
884 | for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) { | 887 | for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) { |
885 | struct ext4_group_desc *gdp = ext4_get_group_desc (sb, i, NULL); | 888 | struct ext4_group_desc *gdp = ext4_get_group_desc (sb, i, NULL); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 5489703d9573..bb717cbb749c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -105,7 +105,7 @@ int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, | |||
105 | */ | 105 | */ |
106 | static unsigned long blocks_for_truncate(struct inode *inode) | 106 | static unsigned long blocks_for_truncate(struct inode *inode) |
107 | { | 107 | { |
108 | unsigned long needed; | 108 | ext4_lblk_t needed; |
109 | 109 | ||
110 | needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9); | 110 | needed = inode->i_blocks >> (inode->i_sb->s_blocksize_bits - 9); |
111 | 111 | ||
@@ -243,13 +243,6 @@ static inline void add_chain(Indirect *p, struct buffer_head *bh, __le32 *v) | |||
243 | p->bh = bh; | 243 | p->bh = bh; |
244 | } | 244 | } |
245 | 245 | ||
246 | static int verify_chain(Indirect *from, Indirect *to) | ||
247 | { | ||
248 | while (from <= to && from->key == *from->p) | ||
249 | from++; | ||
250 | return (from > to); | ||
251 | } | ||
252 | |||
253 | /** | 246 | /** |
254 | * ext4_block_to_path - parse the block number into array of offsets | 247 | * ext4_block_to_path - parse the block number into array of offsets |
255 | * @inode: inode in question (we are only interested in its superblock) | 248 | * @inode: inode in question (we are only interested in its superblock) |
@@ -282,7 +275,8 @@ static int verify_chain(Indirect *from, Indirect *to) | |||
282 | */ | 275 | */ |
283 | 276 | ||
284 | static int ext4_block_to_path(struct inode *inode, | 277 | static int ext4_block_to_path(struct inode *inode, |
285 | long i_block, int offsets[4], int *boundary) | 278 | ext4_lblk_t i_block, |
279 | ext4_lblk_t offsets[4], int *boundary) | ||
286 | { | 280 | { |
287 | int ptrs = EXT4_ADDR_PER_BLOCK(inode->i_sb); | 281 | int ptrs = EXT4_ADDR_PER_BLOCK(inode->i_sb); |
288 | int ptrs_bits = EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb); | 282 | int ptrs_bits = EXT4_ADDR_PER_BLOCK_BITS(inode->i_sb); |
@@ -313,7 +307,10 @@ static int ext4_block_to_path(struct inode *inode, | |||
313 | offsets[n++] = i_block & (ptrs - 1); | 307 | offsets[n++] = i_block & (ptrs - 1); |
314 | final = ptrs; | 308 | final = ptrs; |
315 | } else { | 309 | } else { |
316 | ext4_warning(inode->i_sb, "ext4_block_to_path", "block > big"); | 310 | ext4_warning(inode->i_sb, "ext4_block_to_path", |
311 | "block %lu > max", | ||
312 | i_block + direct_blocks + | ||
313 | indirect_blocks + double_blocks); | ||
317 | } | 314 | } |
318 | if (boundary) | 315 | if (boundary) |
319 | *boundary = final - 1 - (i_block & (ptrs - 1)); | 316 | *boundary = final - 1 - (i_block & (ptrs - 1)); |
@@ -344,12 +341,14 @@ static int ext4_block_to_path(struct inode *inode, | |||
344 | * (pointer to last triple returned, *@err == 0) | 341 | * (pointer to last triple returned, *@err == 0) |
345 | * or when it gets an IO error reading an indirect block | 342 | * or when it gets an IO error reading an indirect block |
346 | * (ditto, *@err == -EIO) | 343 | * (ditto, *@err == -EIO) |
347 | * or when it notices that chain had been changed while it was reading | ||
348 | * (ditto, *@err == -EAGAIN) | ||
349 | * or when it reads all @depth-1 indirect blocks successfully and finds | 344 | * or when it reads all @depth-1 indirect blocks successfully and finds |
350 | * the whole chain, all way to the data (returns %NULL, *err == 0). | 345 | * the whole chain, all way to the data (returns %NULL, *err == 0). |
346 | * | ||
347 | * Need to be called with | ||
348 | * down_read(&EXT4_I(inode)->i_data_sem) | ||
351 | */ | 349 | */ |
352 | static Indirect *ext4_get_branch(struct inode *inode, int depth, int *offsets, | 350 | static Indirect *ext4_get_branch(struct inode *inode, int depth, |
351 | ext4_lblk_t *offsets, | ||
353 | Indirect chain[4], int *err) | 352 | Indirect chain[4], int *err) |
354 | { | 353 | { |
355 | struct super_block *sb = inode->i_sb; | 354 | struct super_block *sb = inode->i_sb; |
@@ -365,9 +364,6 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth, int *offsets, | |||
365 | bh = sb_bread(sb, le32_to_cpu(p->key)); | 364 | bh = sb_bread(sb, le32_to_cpu(p->key)); |
366 | if (!bh) | 365 | if (!bh) |
367 | goto failure; | 366 | goto failure; |
368 | /* Reader: pointers */ | ||
369 | if (!verify_chain(chain, p)) | ||
370 | goto changed; | ||
371 | add_chain(++p, bh, (__le32*)bh->b_data + *++offsets); | 367 | add_chain(++p, bh, (__le32*)bh->b_data + *++offsets); |
372 | /* Reader: end */ | 368 | /* Reader: end */ |
373 | if (!p->key) | 369 | if (!p->key) |
@@ -375,10 +371,6 @@ static Indirect *ext4_get_branch(struct inode *inode, int depth, int *offsets, | |||
375 | } | 371 | } |
376 | return NULL; | 372 | return NULL; |
377 | 373 | ||
378 | changed: | ||
379 | brelse(bh); | ||
380 | *err = -EAGAIN; | ||
381 | goto no_block; | ||
382 | failure: | 374 | failure: |
383 | *err = -EIO; | 375 | *err = -EIO; |
384 | no_block: | 376 | no_block: |
@@ -445,7 +437,7 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind) | |||
445 | * stores it in *@goal and returns zero. | 437 | * stores it in *@goal and returns zero. |
446 | */ | 438 | */ |
447 | 439 | ||
448 | static ext4_fsblk_t ext4_find_goal(struct inode *inode, long block, | 440 | static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block, |
449 | Indirect chain[4], Indirect *partial) | 441 | Indirect chain[4], Indirect *partial) |
450 | { | 442 | { |
451 | struct ext4_block_alloc_info *block_i; | 443 | struct ext4_block_alloc_info *block_i; |
@@ -559,7 +551,7 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode, | |||
559 | return ret; | 551 | return ret; |
560 | failed_out: | 552 | failed_out: |
561 | for (i = 0; i <index; i++) | 553 | for (i = 0; i <index; i++) |
562 | ext4_free_blocks(handle, inode, new_blocks[i], 1); | 554 | ext4_free_blocks(handle, inode, new_blocks[i], 1, 0); |
563 | return ret; | 555 | return ret; |
564 | } | 556 | } |
565 | 557 | ||
@@ -590,7 +582,7 @@ failed_out: | |||
590 | */ | 582 | */ |
591 | static int ext4_alloc_branch(handle_t *handle, struct inode *inode, | 583 | static int ext4_alloc_branch(handle_t *handle, struct inode *inode, |
592 | int indirect_blks, int *blks, ext4_fsblk_t goal, | 584 | int indirect_blks, int *blks, ext4_fsblk_t goal, |
593 | int *offsets, Indirect *branch) | 585 | ext4_lblk_t *offsets, Indirect *branch) |
594 | { | 586 | { |
595 | int blocksize = inode->i_sb->s_blocksize; | 587 | int blocksize = inode->i_sb->s_blocksize; |
596 | int i, n = 0; | 588 | int i, n = 0; |
@@ -658,9 +650,9 @@ failed: | |||
658 | ext4_journal_forget(handle, branch[i].bh); | 650 | ext4_journal_forget(handle, branch[i].bh); |
659 | } | 651 | } |
660 | for (i = 0; i <indirect_blks; i++) | 652 | for (i = 0; i <indirect_blks; i++) |
661 | ext4_free_blocks(handle, inode, new_blocks[i], 1); | 653 | ext4_free_blocks(handle, inode, new_blocks[i], 1, 0); |
662 | 654 | ||
663 | ext4_free_blocks(handle, inode, new_blocks[i], num); | 655 | ext4_free_blocks(handle, inode, new_blocks[i], num, 0); |
664 | 656 | ||
665 | return err; | 657 | return err; |
666 | } | 658 | } |
@@ -680,7 +672,7 @@ failed: | |||
680 | * chain to new block and return 0. | 672 | * chain to new block and return 0. |
681 | */ | 673 | */ |
682 | static int ext4_splice_branch(handle_t *handle, struct inode *inode, | 674 | static int ext4_splice_branch(handle_t *handle, struct inode *inode, |
683 | long block, Indirect *where, int num, int blks) | 675 | ext4_lblk_t block, Indirect *where, int num, int blks) |
684 | { | 676 | { |
685 | int i; | 677 | int i; |
686 | int err = 0; | 678 | int err = 0; |
@@ -757,9 +749,10 @@ err_out: | |||
757 | for (i = 1; i <= num; i++) { | 749 | for (i = 1; i <= num; i++) { |
758 | BUFFER_TRACE(where[i].bh, "call jbd2_journal_forget"); | 750 | BUFFER_TRACE(where[i].bh, "call jbd2_journal_forget"); |
759 | ext4_journal_forget(handle, where[i].bh); | 751 | ext4_journal_forget(handle, where[i].bh); |
760 | ext4_free_blocks(handle,inode,le32_to_cpu(where[i-1].key),1); | 752 | ext4_free_blocks(handle, inode, |
753 | le32_to_cpu(where[i-1].key), 1, 0); | ||
761 | } | 754 | } |
762 | ext4_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks); | 755 | ext4_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks, 0); |
763 | 756 | ||
764 | return err; | 757 | return err; |
765 | } | 758 | } |
@@ -782,14 +775,19 @@ err_out: | |||
782 | * return > 0, # of blocks mapped or allocated. | 775 | * return > 0, # of blocks mapped or allocated. |
783 | * return = 0, if plain lookup failed. | 776 | * return = 0, if plain lookup failed. |
784 | * return < 0, error case. | 777 | * return < 0, error case. |
778 | * | ||
779 | * | ||
780 | * Need to be called with | ||
781 | * down_read(&EXT4_I(inode)->i_data_sem) if not allocating file system block | ||
782 | * (ie, create is zero). Otherwise down_write(&EXT4_I(inode)->i_data_sem) | ||
785 | */ | 783 | */ |
786 | int ext4_get_blocks_handle(handle_t *handle, struct inode *inode, | 784 | int ext4_get_blocks_handle(handle_t *handle, struct inode *inode, |
787 | sector_t iblock, unsigned long maxblocks, | 785 | ext4_lblk_t iblock, unsigned long maxblocks, |
788 | struct buffer_head *bh_result, | 786 | struct buffer_head *bh_result, |
789 | int create, int extend_disksize) | 787 | int create, int extend_disksize) |
790 | { | 788 | { |
791 | int err = -EIO; | 789 | int err = -EIO; |
792 | int offsets[4]; | 790 | ext4_lblk_t offsets[4]; |
793 | Indirect chain[4]; | 791 | Indirect chain[4]; |
794 | Indirect *partial; | 792 | Indirect *partial; |
795 | ext4_fsblk_t goal; | 793 | ext4_fsblk_t goal; |
@@ -803,7 +801,8 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode, | |||
803 | 801 | ||
804 | J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)); | 802 | J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)); |
805 | J_ASSERT(handle != NULL || create == 0); | 803 | J_ASSERT(handle != NULL || create == 0); |
806 | depth = ext4_block_to_path(inode,iblock,offsets,&blocks_to_boundary); | 804 | depth = ext4_block_to_path(inode, iblock, offsets, |
805 | &blocks_to_boundary); | ||
807 | 806 | ||
808 | if (depth == 0) | 807 | if (depth == 0) |
809 | goto out; | 808 | goto out; |
@@ -819,18 +818,6 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode, | |||
819 | while (count < maxblocks && count <= blocks_to_boundary) { | 818 | while (count < maxblocks && count <= blocks_to_boundary) { |
820 | ext4_fsblk_t blk; | 819 | ext4_fsblk_t blk; |
821 | 820 | ||
822 | if (!verify_chain(chain, partial)) { | ||
823 | /* | ||
824 | * Indirect block might be removed by | ||
825 | * truncate while we were reading it. | ||
826 | * Handling of that case: forget what we've | ||
827 | * got now. Flag the err as EAGAIN, so it | ||
828 | * will reread. | ||
829 | */ | ||
830 | err = -EAGAIN; | ||
831 | count = 0; | ||
832 | break; | ||
833 | } | ||
834 | blk = le32_to_cpu(*(chain[depth-1].p + count)); | 821 | blk = le32_to_cpu(*(chain[depth-1].p + count)); |
835 | 822 | ||
836 | if (blk == first_block + count) | 823 | if (blk == first_block + count) |
@@ -838,44 +825,13 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode, | |||
838 | else | 825 | else |
839 | break; | 826 | break; |
840 | } | 827 | } |
841 | if (err != -EAGAIN) | 828 | goto got_it; |
842 | goto got_it; | ||
843 | } | 829 | } |
844 | 830 | ||
845 | /* Next simple case - plain lookup or failed read of indirect block */ | 831 | /* Next simple case - plain lookup or failed read of indirect block */ |
846 | if (!create || err == -EIO) | 832 | if (!create || err == -EIO) |
847 | goto cleanup; | 833 | goto cleanup; |
848 | 834 | ||
849 | mutex_lock(&ei->truncate_mutex); | ||
850 | |||
851 | /* | ||
852 | * If the indirect block is missing while we are reading | ||
853 | * the chain(ext4_get_branch() returns -EAGAIN err), or | ||
854 | * if the chain has been changed after we grab the semaphore, | ||
855 | * (either because another process truncated this branch, or | ||
856 | * another get_block allocated this branch) re-grab the chain to see if | ||
857 | * the request block has been allocated or not. | ||
858 | * | ||
859 | * Since we already block the truncate/other get_block | ||
860 | * at this point, we will have the current copy of the chain when we | ||
861 | * splice the branch into the tree. | ||
862 | */ | ||
863 | if (err == -EAGAIN || !verify_chain(chain, partial)) { | ||
864 | while (partial > chain) { | ||
865 | brelse(partial->bh); | ||
866 | partial--; | ||
867 | } | ||
868 | partial = ext4_get_branch(inode, depth, offsets, chain, &err); | ||
869 | if (!partial) { | ||
870 | count++; | ||
871 | mutex_unlock(&ei->truncate_mutex); | ||
872 | if (err) | ||
873 | goto cleanup; | ||
874 | clear_buffer_new(bh_result); | ||
875 | goto got_it; | ||
876 | } | ||
877 | } | ||
878 | |||
879 | /* | 835 | /* |
880 | * Okay, we need to do block allocation. Lazily initialize the block | 836 | * Okay, we need to do block allocation. Lazily initialize the block |
881 | * allocation info here if necessary | 837 | * allocation info here if necessary |
@@ -911,13 +867,12 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode, | |||
911 | err = ext4_splice_branch(handle, inode, iblock, | 867 | err = ext4_splice_branch(handle, inode, iblock, |
912 | partial, indirect_blks, count); | 868 | partial, indirect_blks, count); |
913 | /* | 869 | /* |
914 | * i_disksize growing is protected by truncate_mutex. Don't forget to | 870 | * i_disksize growing is protected by i_data_sem. Don't forget to |
915 | * protect it if you're about to implement concurrent | 871 | * protect it if you're about to implement concurrent |
916 | * ext4_get_block() -bzzz | 872 | * ext4_get_block() -bzzz |
917 | */ | 873 | */ |
918 | if (!err && extend_disksize && inode->i_size > ei->i_disksize) | 874 | if (!err && extend_disksize && inode->i_size > ei->i_disksize) |
919 | ei->i_disksize = inode->i_size; | 875 | ei->i_disksize = inode->i_size; |
920 | mutex_unlock(&ei->truncate_mutex); | ||
921 | if (err) | 876 | if (err) |
922 | goto cleanup; | 877 | goto cleanup; |
923 | 878 | ||
@@ -942,6 +897,47 @@ out: | |||
942 | 897 | ||
943 | #define DIO_CREDITS (EXT4_RESERVE_TRANS_BLOCKS + 32) | 898 | #define DIO_CREDITS (EXT4_RESERVE_TRANS_BLOCKS + 32) |
944 | 899 | ||
900 | int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | ||
901 | unsigned long max_blocks, struct buffer_head *bh, | ||
902 | int create, int extend_disksize) | ||
903 | { | ||
904 | int retval; | ||
905 | /* | ||
906 | * Try to see if we can get the block without requesting | ||
907 | * for new file system block. | ||
908 | */ | ||
909 | down_read((&EXT4_I(inode)->i_data_sem)); | ||
910 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { | ||
911 | retval = ext4_ext_get_blocks(handle, inode, block, max_blocks, | ||
912 | bh, 0, 0); | ||
913 | } else { | ||
914 | retval = ext4_get_blocks_handle(handle, | ||
915 | inode, block, max_blocks, bh, 0, 0); | ||
916 | } | ||
917 | up_read((&EXT4_I(inode)->i_data_sem)); | ||
918 | if (!create || (retval > 0)) | ||
919 | return retval; | ||
920 | |||
921 | /* | ||
922 | * We need to allocate new blocks which will result | ||
923 | * in i_data update | ||
924 | */ | ||
925 | down_write((&EXT4_I(inode)->i_data_sem)); | ||
926 | /* | ||
927 | * We need to check for EXT4 here because migrate | ||
928 | * could have changed the inode type in between | ||
929 | */ | ||
930 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { | ||
931 | retval = ext4_ext_get_blocks(handle, inode, block, max_blocks, | ||
932 | bh, create, extend_disksize); | ||
933 | } else { | ||
934 | retval = ext4_get_blocks_handle(handle, inode, block, | ||
935 | max_blocks, bh, create, extend_disksize); | ||
936 | } | ||
937 | up_write((&EXT4_I(inode)->i_data_sem)); | ||
938 | return retval; | ||
939 | } | ||
940 | |||
945 | static int ext4_get_block(struct inode *inode, sector_t iblock, | 941 | static int ext4_get_block(struct inode *inode, sector_t iblock, |
946 | struct buffer_head *bh_result, int create) | 942 | struct buffer_head *bh_result, int create) |
947 | { | 943 | { |
@@ -996,7 +992,7 @@ get_block: | |||
996 | * `handle' can be NULL if create is zero | 992 | * `handle' can be NULL if create is zero |
997 | */ | 993 | */ |
998 | struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode, | 994 | struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode, |
999 | long block, int create, int *errp) | 995 | ext4_lblk_t block, int create, int *errp) |
1000 | { | 996 | { |
1001 | struct buffer_head dummy; | 997 | struct buffer_head dummy; |
1002 | int fatal = 0, err; | 998 | int fatal = 0, err; |
@@ -1063,7 +1059,7 @@ err: | |||
1063 | } | 1059 | } |
1064 | 1060 | ||
1065 | struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, | 1061 | struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, |
1066 | int block, int create, int *err) | 1062 | ext4_lblk_t block, int create, int *err) |
1067 | { | 1063 | { |
1068 | struct buffer_head * bh; | 1064 | struct buffer_head * bh; |
1069 | 1065 | ||
@@ -1446,7 +1442,7 @@ static int jbd2_journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh) | |||
1446 | * ext4_file_write() -> generic_file_write() -> __alloc_pages() -> ... | 1442 | * ext4_file_write() -> generic_file_write() -> __alloc_pages() -> ... |
1447 | * | 1443 | * |
1448 | * Same applies to ext4_get_block(). We will deadlock on various things like | 1444 | * Same applies to ext4_get_block(). We will deadlock on various things like |
1449 | * lock_journal and i_truncate_mutex. | 1445 | * lock_journal and i_data_sem |
1450 | * | 1446 | * |
1451 | * Setting PF_MEMALLOC here doesn't work - too many internal memory | 1447 | * Setting PF_MEMALLOC here doesn't work - too many internal memory |
1452 | * allocations fail. | 1448 | * allocations fail. |
@@ -1828,7 +1824,8 @@ int ext4_block_truncate_page(handle_t *handle, struct page *page, | |||
1828 | { | 1824 | { |
1829 | ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT; | 1825 | ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT; |
1830 | unsigned offset = from & (PAGE_CACHE_SIZE-1); | 1826 | unsigned offset = from & (PAGE_CACHE_SIZE-1); |
1831 | unsigned blocksize, iblock, length, pos; | 1827 | unsigned blocksize, length, pos; |
1828 | ext4_lblk_t iblock; | ||
1832 | struct inode *inode = mapping->host; | 1829 | struct inode *inode = mapping->host; |
1833 | struct buffer_head *bh; | 1830 | struct buffer_head *bh; |
1834 | int err = 0; | 1831 | int err = 0; |
@@ -1964,7 +1961,7 @@ static inline int all_zeroes(__le32 *p, __le32 *q) | |||
1964 | * (no partially truncated stuff there). */ | 1961 | * (no partially truncated stuff there). */ |
1965 | 1962 | ||
1966 | static Indirect *ext4_find_shared(struct inode *inode, int depth, | 1963 | static Indirect *ext4_find_shared(struct inode *inode, int depth, |
1967 | int offsets[4], Indirect chain[4], __le32 *top) | 1964 | ext4_lblk_t offsets[4], Indirect chain[4], __le32 *top) |
1968 | { | 1965 | { |
1969 | Indirect *partial, *p; | 1966 | Indirect *partial, *p; |
1970 | int k, err; | 1967 | int k, err; |
@@ -2048,15 +2045,15 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode, | |||
2048 | for (p = first; p < last; p++) { | 2045 | for (p = first; p < last; p++) { |
2049 | u32 nr = le32_to_cpu(*p); | 2046 | u32 nr = le32_to_cpu(*p); |
2050 | if (nr) { | 2047 | if (nr) { |
2051 | struct buffer_head *bh; | 2048 | struct buffer_head *tbh; |
2052 | 2049 | ||
2053 | *p = 0; | 2050 | *p = 0; |
2054 | bh = sb_find_get_block(inode->i_sb, nr); | 2051 | tbh = sb_find_get_block(inode->i_sb, nr); |
2055 | ext4_forget(handle, 0, inode, bh, nr); | 2052 | ext4_forget(handle, 0, inode, tbh, nr); |
2056 | } | 2053 | } |
2057 | } | 2054 | } |
2058 | 2055 | ||
2059 | ext4_free_blocks(handle, inode, block_to_free, count); | 2056 | ext4_free_blocks(handle, inode, block_to_free, count, 0); |
2060 | } | 2057 | } |
2061 | 2058 | ||
2062 | /** | 2059 | /** |
@@ -2229,7 +2226,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, | |||
2229 | ext4_journal_test_restart(handle, inode); | 2226 | ext4_journal_test_restart(handle, inode); |
2230 | } | 2227 | } |
2231 | 2228 | ||
2232 | ext4_free_blocks(handle, inode, nr, 1); | 2229 | ext4_free_blocks(handle, inode, nr, 1, 1); |
2233 | 2230 | ||
2234 | if (parent_bh) { | 2231 | if (parent_bh) { |
2235 | /* | 2232 | /* |
@@ -2289,12 +2286,12 @@ void ext4_truncate(struct inode *inode) | |||
2289 | __le32 *i_data = ei->i_data; | 2286 | __le32 *i_data = ei->i_data; |
2290 | int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb); | 2287 | int addr_per_block = EXT4_ADDR_PER_BLOCK(inode->i_sb); |
2291 | struct address_space *mapping = inode->i_mapping; | 2288 | struct address_space *mapping = inode->i_mapping; |
2292 | int offsets[4]; | 2289 | ext4_lblk_t offsets[4]; |
2293 | Indirect chain[4]; | 2290 | Indirect chain[4]; |
2294 | Indirect *partial; | 2291 | Indirect *partial; |
2295 | __le32 nr = 0; | 2292 | __le32 nr = 0; |
2296 | int n; | 2293 | int n; |
2297 | long last_block; | 2294 | ext4_lblk_t last_block; |
2298 | unsigned blocksize = inode->i_sb->s_blocksize; | 2295 | unsigned blocksize = inode->i_sb->s_blocksize; |
2299 | struct page *page; | 2296 | struct page *page; |
2300 | 2297 | ||
@@ -2320,8 +2317,10 @@ void ext4_truncate(struct inode *inode) | |||
2320 | return; | 2317 | return; |
2321 | } | 2318 | } |
2322 | 2319 | ||
2323 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) | 2320 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { |
2324 | return ext4_ext_truncate(inode, page); | 2321 | ext4_ext_truncate(inode, page); |
2322 | return; | ||
2323 | } | ||
2325 | 2324 | ||
2326 | handle = start_transaction(inode); | 2325 | handle = start_transaction(inode); |
2327 | if (IS_ERR(handle)) { | 2326 | if (IS_ERR(handle)) { |
@@ -2369,7 +2368,7 @@ void ext4_truncate(struct inode *inode) | |||
2369 | * From here we block out all ext4_get_block() callers who want to | 2368 | * From here we block out all ext4_get_block() callers who want to |
2370 | * modify the block allocation tree. | 2369 | * modify the block allocation tree. |
2371 | */ | 2370 | */ |
2372 | mutex_lock(&ei->truncate_mutex); | 2371 | down_write(&ei->i_data_sem); |
2373 | 2372 | ||
2374 | if (n == 1) { /* direct blocks */ | 2373 | if (n == 1) { /* direct blocks */ |
2375 | ext4_free_data(handle, inode, NULL, i_data+offsets[0], | 2374 | ext4_free_data(handle, inode, NULL, i_data+offsets[0], |
@@ -2433,7 +2432,7 @@ do_indirects: | |||
2433 | 2432 | ||
2434 | ext4_discard_reservation(inode); | 2433 | ext4_discard_reservation(inode); |
2435 | 2434 | ||
2436 | mutex_unlock(&ei->truncate_mutex); | 2435 | up_write(&ei->i_data_sem); |
2437 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); | 2436 | inode->i_mtime = inode->i_ctime = ext4_current_time(inode); |
2438 | ext4_mark_inode_dirty(handle, inode); | 2437 | ext4_mark_inode_dirty(handle, inode); |
2439 | 2438 | ||
@@ -2460,7 +2459,8 @@ out_stop: | |||
2460 | static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb, | 2459 | static ext4_fsblk_t ext4_get_inode_block(struct super_block *sb, |
2461 | unsigned long ino, struct ext4_iloc *iloc) | 2460 | unsigned long ino, struct ext4_iloc *iloc) |
2462 | { | 2461 | { |
2463 | unsigned long desc, group_desc, block_group; | 2462 | unsigned long desc, group_desc; |
2463 | ext4_group_t block_group; | ||
2464 | unsigned long offset; | 2464 | unsigned long offset; |
2465 | ext4_fsblk_t block; | 2465 | ext4_fsblk_t block; |
2466 | struct buffer_head *bh; | 2466 | struct buffer_head *bh; |
@@ -2547,7 +2547,7 @@ static int __ext4_get_inode_loc(struct inode *inode, | |||
2547 | struct ext4_group_desc *desc; | 2547 | struct ext4_group_desc *desc; |
2548 | int inodes_per_buffer; | 2548 | int inodes_per_buffer; |
2549 | int inode_offset, i; | 2549 | int inode_offset, i; |
2550 | int block_group; | 2550 | ext4_group_t block_group; |
2551 | int start; | 2551 | int start; |
2552 | 2552 | ||
2553 | block_group = (inode->i_ino - 1) / | 2553 | block_group = (inode->i_ino - 1) / |
@@ -2660,6 +2660,28 @@ void ext4_get_inode_flags(struct ext4_inode_info *ei) | |||
2660 | if (flags & S_DIRSYNC) | 2660 | if (flags & S_DIRSYNC) |
2661 | ei->i_flags |= EXT4_DIRSYNC_FL; | 2661 | ei->i_flags |= EXT4_DIRSYNC_FL; |
2662 | } | 2662 | } |
2663 | static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, | ||
2664 | struct ext4_inode_info *ei) | ||
2665 | { | ||
2666 | blkcnt_t i_blocks ; | ||
2667 | struct inode *inode = &(ei->vfs_inode); | ||
2668 | struct super_block *sb = inode->i_sb; | ||
2669 | |||
2670 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, | ||
2671 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { | ||
2672 | /* we are using combined 48 bit field */ | ||
2673 | i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 | | ||
2674 | le32_to_cpu(raw_inode->i_blocks_lo); | ||
2675 | if (ei->i_flags & EXT4_HUGE_FILE_FL) { | ||
2676 | /* i_blocks represent file system block size */ | ||
2677 | return i_blocks << (inode->i_blkbits - 9); | ||
2678 | } else { | ||
2679 | return i_blocks; | ||
2680 | } | ||
2681 | } else { | ||
2682 | return le32_to_cpu(raw_inode->i_blocks_lo); | ||
2683 | } | ||
2684 | } | ||
2663 | 2685 | ||
2664 | void ext4_read_inode(struct inode * inode) | 2686 | void ext4_read_inode(struct inode * inode) |
2665 | { | 2687 | { |
@@ -2687,7 +2709,6 @@ void ext4_read_inode(struct inode * inode) | |||
2687 | inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; | 2709 | inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16; |
2688 | } | 2710 | } |
2689 | inode->i_nlink = le16_to_cpu(raw_inode->i_links_count); | 2711 | inode->i_nlink = le16_to_cpu(raw_inode->i_links_count); |
2690 | inode->i_size = le32_to_cpu(raw_inode->i_size); | ||
2691 | 2712 | ||
2692 | ei->i_state = 0; | 2713 | ei->i_state = 0; |
2693 | ei->i_dir_start_lookup = 0; | 2714 | ei->i_dir_start_lookup = 0; |
@@ -2709,19 +2730,15 @@ void ext4_read_inode(struct inode * inode) | |||
2709 | * recovery code: that's fine, we're about to complete | 2730 | * recovery code: that's fine, we're about to complete |
2710 | * the process of deleting those. */ | 2731 | * the process of deleting those. */ |
2711 | } | 2732 | } |
2712 | inode->i_blocks = le32_to_cpu(raw_inode->i_blocks); | ||
2713 | ei->i_flags = le32_to_cpu(raw_inode->i_flags); | 2733 | ei->i_flags = le32_to_cpu(raw_inode->i_flags); |
2714 | ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl); | 2734 | inode->i_blocks = ext4_inode_blocks(raw_inode, ei); |
2735 | ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl_lo); | ||
2715 | if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != | 2736 | if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != |
2716 | cpu_to_le32(EXT4_OS_HURD)) | 2737 | cpu_to_le32(EXT4_OS_HURD)) { |
2717 | ei->i_file_acl |= | 2738 | ei->i_file_acl |= |
2718 | ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32; | 2739 | ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32; |
2719 | if (!S_ISREG(inode->i_mode)) { | ||
2720 | ei->i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl); | ||
2721 | } else { | ||
2722 | inode->i_size |= | ||
2723 | ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32; | ||
2724 | } | 2740 | } |
2741 | inode->i_size = ext4_isize(raw_inode); | ||
2725 | ei->i_disksize = inode->i_size; | 2742 | ei->i_disksize = inode->i_size; |
2726 | inode->i_generation = le32_to_cpu(raw_inode->i_generation); | 2743 | inode->i_generation = le32_to_cpu(raw_inode->i_generation); |
2727 | ei->i_block_group = iloc.block_group; | 2744 | ei->i_block_group = iloc.block_group; |
@@ -2765,6 +2782,13 @@ void ext4_read_inode(struct inode * inode) | |||
2765 | EXT4_INODE_GET_XTIME(i_atime, inode, raw_inode); | 2782 | EXT4_INODE_GET_XTIME(i_atime, inode, raw_inode); |
2766 | EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode); | 2783 | EXT4_EINODE_GET_XTIME(i_crtime, ei, raw_inode); |
2767 | 2784 | ||
2785 | inode->i_version = le32_to_cpu(raw_inode->i_disk_version); | ||
2786 | if (EXT4_INODE_SIZE(inode->i_sb) > EXT4_GOOD_OLD_INODE_SIZE) { | ||
2787 | if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi)) | ||
2788 | inode->i_version |= | ||
2789 | (__u64)(le32_to_cpu(raw_inode->i_version_hi)) << 32; | ||
2790 | } | ||
2791 | |||
2768 | if (S_ISREG(inode->i_mode)) { | 2792 | if (S_ISREG(inode->i_mode)) { |
2769 | inode->i_op = &ext4_file_inode_operations; | 2793 | inode->i_op = &ext4_file_inode_operations; |
2770 | inode->i_fop = &ext4_file_operations; | 2794 | inode->i_fop = &ext4_file_operations; |
@@ -2797,6 +2821,55 @@ bad_inode: | |||
2797 | return; | 2821 | return; |
2798 | } | 2822 | } |
2799 | 2823 | ||
2824 | static int ext4_inode_blocks_set(handle_t *handle, | ||
2825 | struct ext4_inode *raw_inode, | ||
2826 | struct ext4_inode_info *ei) | ||
2827 | { | ||
2828 | struct inode *inode = &(ei->vfs_inode); | ||
2829 | u64 i_blocks = inode->i_blocks; | ||
2830 | struct super_block *sb = inode->i_sb; | ||
2831 | int err = 0; | ||
2832 | |||
2833 | if (i_blocks <= ~0U) { | ||
2834 | /* | ||
2835 | * i_blocks can be represnted in a 32 bit variable | ||
2836 | * as multiple of 512 bytes | ||
2837 | */ | ||
2838 | raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); | ||
2839 | raw_inode->i_blocks_high = 0; | ||
2840 | ei->i_flags &= ~EXT4_HUGE_FILE_FL; | ||
2841 | } else if (i_blocks <= 0xffffffffffffULL) { | ||
2842 | /* | ||
2843 | * i_blocks can be represented in a 48 bit variable | ||
2844 | * as multiple of 512 bytes | ||
2845 | */ | ||
2846 | err = ext4_update_rocompat_feature(handle, sb, | ||
2847 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE); | ||
2848 | if (err) | ||
2849 | goto err_out; | ||
2850 | /* i_block is stored in the split 48 bit fields */ | ||
2851 | raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); | ||
2852 | raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32); | ||
2853 | ei->i_flags &= ~EXT4_HUGE_FILE_FL; | ||
2854 | } else { | ||
2855 | /* | ||
2856 | * i_blocks should be represented in a 48 bit variable | ||
2857 | * as multiple of file system block size | ||
2858 | */ | ||
2859 | err = ext4_update_rocompat_feature(handle, sb, | ||
2860 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE); | ||
2861 | if (err) | ||
2862 | goto err_out; | ||
2863 | ei->i_flags |= EXT4_HUGE_FILE_FL; | ||
2864 | /* i_block is stored in file system block size */ | ||
2865 | i_blocks = i_blocks >> (inode->i_blkbits - 9); | ||
2866 | raw_inode->i_blocks_lo = cpu_to_le32(i_blocks); | ||
2867 | raw_inode->i_blocks_high = cpu_to_le16(i_blocks >> 32); | ||
2868 | } | ||
2869 | err_out: | ||
2870 | return err; | ||
2871 | } | ||
2872 | |||
2800 | /* | 2873 | /* |
2801 | * Post the struct inode info into an on-disk inode location in the | 2874 | * Post the struct inode info into an on-disk inode location in the |
2802 | * buffer-cache. This gobbles the caller's reference to the | 2875 | * buffer-cache. This gobbles the caller's reference to the |
@@ -2845,47 +2918,42 @@ static int ext4_do_update_inode(handle_t *handle, | |||
2845 | raw_inode->i_gid_high = 0; | 2918 | raw_inode->i_gid_high = 0; |
2846 | } | 2919 | } |
2847 | raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); | 2920 | raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); |
2848 | raw_inode->i_size = cpu_to_le32(ei->i_disksize); | ||
2849 | 2921 | ||
2850 | EXT4_INODE_SET_XTIME(i_ctime, inode, raw_inode); | 2922 | EXT4_INODE_SET_XTIME(i_ctime, inode, raw_inode); |
2851 | EXT4_INODE_SET_XTIME(i_mtime, inode, raw_inode); | 2923 | EXT4_INODE_SET_XTIME(i_mtime, inode, raw_inode); |
2852 | EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode); | 2924 | EXT4_INODE_SET_XTIME(i_atime, inode, raw_inode); |
2853 | EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode); | 2925 | EXT4_EINODE_SET_XTIME(i_crtime, ei, raw_inode); |
2854 | 2926 | ||
2855 | raw_inode->i_blocks = cpu_to_le32(inode->i_blocks); | 2927 | if (ext4_inode_blocks_set(handle, raw_inode, ei)) |
2928 | goto out_brelse; | ||
2856 | raw_inode->i_dtime = cpu_to_le32(ei->i_dtime); | 2929 | raw_inode->i_dtime = cpu_to_le32(ei->i_dtime); |
2857 | raw_inode->i_flags = cpu_to_le32(ei->i_flags); | 2930 | raw_inode->i_flags = cpu_to_le32(ei->i_flags); |
2858 | if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != | 2931 | if (EXT4_SB(inode->i_sb)->s_es->s_creator_os != |
2859 | cpu_to_le32(EXT4_OS_HURD)) | 2932 | cpu_to_le32(EXT4_OS_HURD)) |
2860 | raw_inode->i_file_acl_high = | 2933 | raw_inode->i_file_acl_high = |
2861 | cpu_to_le16(ei->i_file_acl >> 32); | 2934 | cpu_to_le16(ei->i_file_acl >> 32); |
2862 | raw_inode->i_file_acl = cpu_to_le32(ei->i_file_acl); | 2935 | raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl); |
2863 | if (!S_ISREG(inode->i_mode)) { | 2936 | ext4_isize_set(raw_inode, ei->i_disksize); |
2864 | raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl); | 2937 | if (ei->i_disksize > 0x7fffffffULL) { |
2865 | } else { | 2938 | struct super_block *sb = inode->i_sb; |
2866 | raw_inode->i_size_high = | 2939 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, |
2867 | cpu_to_le32(ei->i_disksize >> 32); | 2940 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE) || |
2868 | if (ei->i_disksize > 0x7fffffffULL) { | 2941 | EXT4_SB(sb)->s_es->s_rev_level == |
2869 | struct super_block *sb = inode->i_sb; | 2942 | cpu_to_le32(EXT4_GOOD_OLD_REV)) { |
2870 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, | 2943 | /* If this is the first large file |
2871 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE) || | 2944 | * created, add a flag to the superblock. |
2872 | EXT4_SB(sb)->s_es->s_rev_level == | 2945 | */ |
2873 | cpu_to_le32(EXT4_GOOD_OLD_REV)) { | 2946 | err = ext4_journal_get_write_access(handle, |
2874 | /* If this is the first large file | 2947 | EXT4_SB(sb)->s_sbh); |
2875 | * created, add a flag to the superblock. | 2948 | if (err) |
2876 | */ | 2949 | goto out_brelse; |
2877 | err = ext4_journal_get_write_access(handle, | 2950 | ext4_update_dynamic_rev(sb); |
2878 | EXT4_SB(sb)->s_sbh); | 2951 | EXT4_SET_RO_COMPAT_FEATURE(sb, |
2879 | if (err) | ||
2880 | goto out_brelse; | ||
2881 | ext4_update_dynamic_rev(sb); | ||
2882 | EXT4_SET_RO_COMPAT_FEATURE(sb, | ||
2883 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE); | 2952 | EXT4_FEATURE_RO_COMPAT_LARGE_FILE); |
2884 | sb->s_dirt = 1; | 2953 | sb->s_dirt = 1; |
2885 | handle->h_sync = 1; | 2954 | handle->h_sync = 1; |
2886 | err = ext4_journal_dirty_metadata(handle, | 2955 | err = ext4_journal_dirty_metadata(handle, |
2887 | EXT4_SB(sb)->s_sbh); | 2956 | EXT4_SB(sb)->s_sbh); |
2888 | } | ||
2889 | } | 2957 | } |
2890 | } | 2958 | } |
2891 | raw_inode->i_generation = cpu_to_le32(inode->i_generation); | 2959 | raw_inode->i_generation = cpu_to_le32(inode->i_generation); |
@@ -2903,8 +2971,14 @@ static int ext4_do_update_inode(handle_t *handle, | |||
2903 | } else for (block = 0; block < EXT4_N_BLOCKS; block++) | 2971 | } else for (block = 0; block < EXT4_N_BLOCKS; block++) |
2904 | raw_inode->i_block[block] = ei->i_data[block]; | 2972 | raw_inode->i_block[block] = ei->i_data[block]; |
2905 | 2973 | ||
2906 | if (ei->i_extra_isize) | 2974 | raw_inode->i_disk_version = cpu_to_le32(inode->i_version); |
2975 | if (ei->i_extra_isize) { | ||
2976 | if (EXT4_FITS_IN_INODE(raw_inode, ei, i_version_hi)) | ||
2977 | raw_inode->i_version_hi = | ||
2978 | cpu_to_le32(inode->i_version >> 32); | ||
2907 | raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); | 2979 | raw_inode->i_extra_isize = cpu_to_le16(ei->i_extra_isize); |
2980 | } | ||
2981 | |||
2908 | 2982 | ||
2909 | BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata"); | 2983 | BUFFER_TRACE(bh, "call ext4_journal_dirty_metadata"); |
2910 | rc = ext4_journal_dirty_metadata(handle, bh); | 2984 | rc = ext4_journal_dirty_metadata(handle, bh); |
@@ -3024,6 +3098,17 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) | |||
3024 | ext4_journal_stop(handle); | 3098 | ext4_journal_stop(handle); |
3025 | } | 3099 | } |
3026 | 3100 | ||
3101 | if (attr->ia_valid & ATTR_SIZE) { | ||
3102 | if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) { | ||
3103 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | ||
3104 | |||
3105 | if (attr->ia_size > sbi->s_bitmap_maxbytes) { | ||
3106 | error = -EFBIG; | ||
3107 | goto err_out; | ||
3108 | } | ||
3109 | } | ||
3110 | } | ||
3111 | |||
3027 | if (S_ISREG(inode->i_mode) && | 3112 | if (S_ISREG(inode->i_mode) && |
3028 | attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) { | 3113 | attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) { |
3029 | handle_t *handle; | 3114 | handle_t *handle; |
@@ -3120,6 +3205,9 @@ int ext4_mark_iloc_dirty(handle_t *handle, | |||
3120 | { | 3205 | { |
3121 | int err = 0; | 3206 | int err = 0; |
3122 | 3207 | ||
3208 | if (test_opt(inode->i_sb, I_VERSION)) | ||
3209 | inode_inc_iversion(inode); | ||
3210 | |||
3123 | /* the do_update_inode consumes one bh->b_count */ | 3211 | /* the do_update_inode consumes one bh->b_count */ |
3124 | get_bh(iloc->bh); | 3212 | get_bh(iloc->bh); |
3125 | 3213 | ||
@@ -3158,8 +3246,10 @@ ext4_reserve_inode_write(handle_t *handle, struct inode *inode, | |||
3158 | * Expand an inode by new_extra_isize bytes. | 3246 | * Expand an inode by new_extra_isize bytes. |
3159 | * Returns 0 on success or negative error number on failure. | 3247 | * Returns 0 on success or negative error number on failure. |
3160 | */ | 3248 | */ |
3161 | int ext4_expand_extra_isize(struct inode *inode, unsigned int new_extra_isize, | 3249 | static int ext4_expand_extra_isize(struct inode *inode, |
3162 | struct ext4_iloc iloc, handle_t *handle) | 3250 | unsigned int new_extra_isize, |
3251 | struct ext4_iloc iloc, | ||
3252 | handle_t *handle) | ||
3163 | { | 3253 | { |
3164 | struct ext4_inode *raw_inode; | 3254 | struct ext4_inode *raw_inode; |
3165 | struct ext4_xattr_ibody_header *header; | 3255 | struct ext4_xattr_ibody_header *header; |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index e7f894bdb420..2ed7c37f897e 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -199,7 +199,7 @@ flags_err: | |||
199 | * need to allocate reservation structure for this inode | 199 | * need to allocate reservation structure for this inode |
200 | * before set the window size | 200 | * before set the window size |
201 | */ | 201 | */ |
202 | mutex_lock(&ei->truncate_mutex); | 202 | down_write(&ei->i_data_sem); |
203 | if (!ei->i_block_alloc_info) | 203 | if (!ei->i_block_alloc_info) |
204 | ext4_init_block_alloc_info(inode); | 204 | ext4_init_block_alloc_info(inode); |
205 | 205 | ||
@@ -207,7 +207,7 @@ flags_err: | |||
207 | struct ext4_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node; | 207 | struct ext4_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node; |
208 | rsv->rsv_goal_size = rsv_window_size; | 208 | rsv->rsv_goal_size = rsv_window_size; |
209 | } | 209 | } |
210 | mutex_unlock(&ei->truncate_mutex); | 210 | up_write(&ei->i_data_sem); |
211 | return 0; | 211 | return 0; |
212 | } | 212 | } |
213 | case EXT4_IOC_GROUP_EXTEND: { | 213 | case EXT4_IOC_GROUP_EXTEND: { |
@@ -254,6 +254,9 @@ flags_err: | |||
254 | return err; | 254 | return err; |
255 | } | 255 | } |
256 | 256 | ||
257 | case EXT4_IOC_MIGRATE: | ||
258 | return ext4_ext_migrate(inode, filp, cmd, arg); | ||
259 | |||
257 | default: | 260 | default: |
258 | return -ENOTTY; | 261 | return -ENOTTY; |
259 | } | 262 | } |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c new file mode 100644 index 000000000000..76e5fedc0a0b --- /dev/null +++ b/fs/ext4/mballoc.c | |||
@@ -0,0 +1,4552 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2003-2006, Cluster File Systems, Inc, info@clusterfs.com | ||
3 | * Written by Alex Tomas <alex@clusterfs.com> | ||
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 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public Licens | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111- | ||
17 | */ | ||
18 | |||
19 | |||
20 | /* | ||
21 | * mballoc.c contains the multiblocks allocation routines | ||
22 | */ | ||
23 | |||
24 | #include <linux/time.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/namei.h> | ||
27 | #include <linux/ext4_jbd2.h> | ||
28 | #include <linux/ext4_fs.h> | ||
29 | #include <linux/quotaops.h> | ||
30 | #include <linux/buffer_head.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/swap.h> | ||
33 | #include <linux/proc_fs.h> | ||
34 | #include <linux/pagemap.h> | ||
35 | #include <linux/seq_file.h> | ||
36 | #include <linux/version.h> | ||
37 | #include "group.h" | ||
38 | |||
39 | /* | ||
40 | * MUSTDO: | ||
41 | * - test ext4_ext_search_left() and ext4_ext_search_right() | ||
42 | * - search for metadata in few groups | ||
43 | * | ||
44 | * TODO v4: | ||
45 | * - normalization should take into account whether file is still open | ||
46 | * - discard preallocations if no free space left (policy?) | ||
47 | * - don't normalize tails | ||
48 | * - quota | ||
49 | * - reservation for superuser | ||
50 | * | ||
51 | * TODO v3: | ||
52 | * - bitmap read-ahead (proposed by Oleg Drokin aka green) | ||
53 | * - track min/max extents in each group for better group selection | ||
54 | * - mb_mark_used() may allocate chunk right after splitting buddy | ||
55 | * - tree of groups sorted by number of free blocks | ||
56 | * - error handling | ||
57 | */ | ||
58 | |||
59 | /* | ||
60 | * The allocation request involve request for multiple number of blocks | ||
61 | * near to the goal(block) value specified. | ||
62 | * | ||
63 | * During initialization phase of the allocator we decide to use the group | ||
64 | * preallocation or inode preallocation depending on the size file. The | ||
65 | * size of the file could be the resulting file size we would have after | ||
66 | * allocation or the current file size which ever is larger. If the size is | ||
67 | * less that sbi->s_mb_stream_request we select the group | ||
68 | * preallocation. The default value of s_mb_stream_request is 16 | ||
69 | * blocks. This can also be tuned via | ||
70 | * /proc/fs/ext4/<partition>/stream_req. The value is represented in terms | ||
71 | * of number of blocks. | ||
72 | * | ||
73 | * The main motivation for having small file use group preallocation is to | ||
74 | * ensure that we have small file closer in the disk. | ||
75 | * | ||
76 | * First stage the allocator looks at the inode prealloc list | ||
77 | * ext4_inode_info->i_prealloc_list contain list of prealloc spaces for | ||
78 | * this particular inode. The inode prealloc space is represented as: | ||
79 | * | ||
80 | * pa_lstart -> the logical start block for this prealloc space | ||
81 | * pa_pstart -> the physical start block for this prealloc space | ||
82 | * pa_len -> lenght for this prealloc space | ||
83 | * pa_free -> free space available in this prealloc space | ||
84 | * | ||
85 | * The inode preallocation space is used looking at the _logical_ start | ||
86 | * block. If only the logical file block falls within the range of prealloc | ||
87 | * space we will consume the particular prealloc space. This make sure that | ||
88 | * that the we have contiguous physical blocks representing the file blocks | ||
89 | * | ||
90 | * The important thing to be noted in case of inode prealloc space is that | ||
91 | * we don't modify the values associated to inode prealloc space except | ||
92 | * pa_free. | ||
93 | * | ||
94 | * If we are not able to find blocks in the inode prealloc space and if we | ||
95 | * have the group allocation flag set then we look at the locality group | ||
96 | * prealloc space. These are per CPU prealloc list repreasented as | ||
97 | * | ||
98 | * ext4_sb_info.s_locality_groups[smp_processor_id()] | ||
99 | * | ||
100 | * The reason for having a per cpu locality group is to reduce the contention | ||
101 | * between CPUs. It is possible to get scheduled at this point. | ||
102 | * | ||
103 | * The locality group prealloc space is used looking at whether we have | ||
104 | * enough free space (pa_free) withing the prealloc space. | ||
105 | * | ||
106 | * If we can't allocate blocks via inode prealloc or/and locality group | ||
107 | * prealloc then we look at the buddy cache. The buddy cache is represented | ||
108 | * by ext4_sb_info.s_buddy_cache (struct inode) whose file offset gets | ||
109 | * mapped to the buddy and bitmap information regarding different | ||
110 | * groups. The buddy information is attached to buddy cache inode so that | ||
111 | * we can access them through the page cache. The information regarding | ||
112 | * each group is loaded via ext4_mb_load_buddy. The information involve | ||
113 | * block bitmap and buddy information. The information are stored in the | ||
114 | * inode as: | ||
115 | * | ||
116 | * { page } | ||
117 | * [ group 0 buddy][ group 0 bitmap] [group 1][ group 1]... | ||
118 | * | ||
119 | * | ||
120 | * one block each for bitmap and buddy information. So for each group we | ||
121 | * take up 2 blocks. A page can contain blocks_per_page (PAGE_CACHE_SIZE / | ||
122 | * blocksize) blocks. So it can have information regarding groups_per_page | ||
123 | * which is blocks_per_page/2 | ||
124 | * | ||
125 | * The buddy cache inode is not stored on disk. The inode is thrown | ||
126 | * away when the filesystem is unmounted. | ||
127 | * | ||
128 | * We look for count number of blocks in the buddy cache. If we were able | ||
129 | * to locate that many free blocks we return with additional information | ||
130 | * regarding rest of the contiguous physical block available | ||
131 | * | ||
132 | * Before allocating blocks via buddy cache we normalize the request | ||
133 | * blocks. This ensure we ask for more blocks that we needed. The extra | ||
134 | * blocks that we get after allocation is added to the respective prealloc | ||
135 | * list. In case of inode preallocation we follow a list of heuristics | ||
136 | * based on file size. This can be found in ext4_mb_normalize_request. If | ||
137 | * we are doing a group prealloc we try to normalize the request to | ||
138 | * sbi->s_mb_group_prealloc. Default value of s_mb_group_prealloc is set to | ||
139 | * 512 blocks. This can be tuned via | ||
140 | * /proc/fs/ext4/<partition/group_prealloc. The value is represented in | ||
141 | * terms of number of blocks. If we have mounted the file system with -O | ||
142 | * stripe=<value> option the group prealloc request is normalized to the | ||
143 | * stripe value (sbi->s_stripe) | ||
144 | * | ||
145 | * The regular allocator(using the buddy cache) support few tunables. | ||
146 | * | ||
147 | * /proc/fs/ext4/<partition>/min_to_scan | ||
148 | * /proc/fs/ext4/<partition>/max_to_scan | ||
149 | * /proc/fs/ext4/<partition>/order2_req | ||
150 | * | ||
151 | * The regular allocator use buddy scan only if the request len is power of | ||
152 | * 2 blocks and the order of allocation is >= sbi->s_mb_order2_reqs. The | ||
153 | * value of s_mb_order2_reqs can be tuned via | ||
154 | * /proc/fs/ext4/<partition>/order2_req. If the request len is equal to | ||
155 | * stripe size (sbi->s_stripe), we try to search for contigous block in | ||
156 | * stripe size. This should result in better allocation on RAID setup. If | ||
157 | * not we search in the specific group using bitmap for best extents. The | ||
158 | * tunable min_to_scan and max_to_scan controll the behaviour here. | ||
159 | * min_to_scan indicate how long the mballoc __must__ look for a best | ||
160 | * extent and max_to_scanindicate how long the mballoc __can__ look for a | ||
161 | * best extent in the found extents. Searching for the blocks starts with | ||
162 | * the group specified as the goal value in allocation context via | ||
163 | * ac_g_ex. Each group is first checked based on the criteria whether it | ||
164 | * can used for allocation. ext4_mb_good_group explains how the groups are | ||
165 | * checked. | ||
166 | * | ||
167 | * Both the prealloc space are getting populated as above. So for the first | ||
168 | * request we will hit the buddy cache which will result in this prealloc | ||
169 | * space getting filled. The prealloc space is then later used for the | ||
170 | * subsequent request. | ||
171 | */ | ||
172 | |||
173 | /* | ||
174 | * mballoc operates on the following data: | ||
175 | * - on-disk bitmap | ||
176 | * - in-core buddy (actually includes buddy and bitmap) | ||
177 | * - preallocation descriptors (PAs) | ||
178 | * | ||
179 | * there are two types of preallocations: | ||
180 | * - inode | ||
181 | * assiged to specific inode and can be used for this inode only. | ||
182 | * it describes part of inode's space preallocated to specific | ||
183 | * physical blocks. any block from that preallocated can be used | ||
184 | * independent. the descriptor just tracks number of blocks left | ||
185 | * unused. so, before taking some block from descriptor, one must | ||
186 | * make sure corresponded logical block isn't allocated yet. this | ||
187 | * also means that freeing any block within descriptor's range | ||
188 | * must discard all preallocated blocks. | ||
189 | * - locality group | ||
190 | * assigned to specific locality group which does not translate to | ||
191 | * permanent set of inodes: inode can join and leave group. space | ||
192 | * from this type of preallocation can be used for any inode. thus | ||
193 | * it's consumed from the beginning to the end. | ||
194 | * | ||
195 | * relation between them can be expressed as: | ||
196 | * in-core buddy = on-disk bitmap + preallocation descriptors | ||
197 | * | ||
198 | * this mean blocks mballoc considers used are: | ||
199 | * - allocated blocks (persistent) | ||
200 | * - preallocated blocks (non-persistent) | ||
201 | * | ||
202 | * consistency in mballoc world means that at any time a block is either | ||
203 | * free or used in ALL structures. notice: "any time" should not be read | ||
204 | * literally -- time is discrete and delimited by locks. | ||
205 | * | ||
206 | * to keep it simple, we don't use block numbers, instead we count number of | ||
207 | * blocks: how many blocks marked used/free in on-disk bitmap, buddy and PA. | ||
208 | * | ||
209 | * all operations can be expressed as: | ||
210 | * - init buddy: buddy = on-disk + PAs | ||
211 | * - new PA: buddy += N; PA = N | ||
212 | * - use inode PA: on-disk += N; PA -= N | ||
213 | * - discard inode PA buddy -= on-disk - PA; PA = 0 | ||
214 | * - use locality group PA on-disk += N; PA -= N | ||
215 | * - discard locality group PA buddy -= PA; PA = 0 | ||
216 | * note: 'buddy -= on-disk - PA' is used to show that on-disk bitmap | ||
217 | * is used in real operation because we can't know actual used | ||
218 | * bits from PA, only from on-disk bitmap | ||
219 | * | ||
220 | * if we follow this strict logic, then all operations above should be atomic. | ||
221 | * given some of them can block, we'd have to use something like semaphores | ||
222 | * killing performance on high-end SMP hardware. let's try to relax it using | ||
223 | * the following knowledge: | ||
224 | * 1) if buddy is referenced, it's already initialized | ||
225 | * 2) while block is used in buddy and the buddy is referenced, | ||
226 | * nobody can re-allocate that block | ||
227 | * 3) we work on bitmaps and '+' actually means 'set bits'. if on-disk has | ||
228 | * bit set and PA claims same block, it's OK. IOW, one can set bit in | ||
229 | * on-disk bitmap if buddy has same bit set or/and PA covers corresponded | ||
230 | * block | ||
231 | * | ||
232 | * so, now we're building a concurrency table: | ||
233 | * - init buddy vs. | ||
234 | * - new PA | ||
235 | * blocks for PA are allocated in the buddy, buddy must be referenced | ||
236 | * until PA is linked to allocation group to avoid concurrent buddy init | ||
237 | * - use inode PA | ||
238 | * we need to make sure that either on-disk bitmap or PA has uptodate data | ||
239 | * given (3) we care that PA-=N operation doesn't interfere with init | ||
240 | * - discard inode PA | ||
241 | * the simplest way would be to have buddy initialized by the discard | ||
242 | * - use locality group PA | ||
243 | * again PA-=N must be serialized with init | ||
244 | * - discard locality group PA | ||
245 | * the simplest way would be to have buddy initialized by the discard | ||
246 | * - new PA vs. | ||
247 | * - use inode PA | ||
248 | * i_data_sem serializes them | ||
249 | * - discard inode PA | ||
250 | * discard process must wait until PA isn't used by another process | ||
251 | * - use locality group PA | ||
252 | * some mutex should serialize them | ||
253 | * - discard locality group PA | ||
254 | * discard process must wait until PA isn't used by another process | ||
255 | * - use inode PA | ||
256 | * - use inode PA | ||
257 | * i_data_sem or another mutex should serializes them | ||
258 | * - discard inode PA | ||
259 | * discard process must wait until PA isn't used by another process | ||
260 | * - use locality group PA | ||
261 | * nothing wrong here -- they're different PAs covering different blocks | ||
262 | * - discard locality group PA | ||
263 | * discard process must wait until PA isn't used by another process | ||
264 | * | ||
265 | * now we're ready to make few consequences: | ||
266 | * - PA is referenced and while it is no discard is possible | ||
267 | * - PA is referenced until block isn't marked in on-disk bitmap | ||
268 | * - PA changes only after on-disk bitmap | ||
269 | * - discard must not compete with init. either init is done before | ||
270 | * any discard or they're serialized somehow | ||
271 | * - buddy init as sum of on-disk bitmap and PAs is done atomically | ||
272 | * | ||
273 | * a special case when we've used PA to emptiness. no need to modify buddy | ||
274 | * in this case, but we should care about concurrent init | ||
275 | * | ||
276 | */ | ||
277 | |||
278 | /* | ||
279 | * Logic in few words: | ||
280 | * | ||
281 | * - allocation: | ||
282 | * load group | ||
283 | * find blocks | ||
284 | * mark bits in on-disk bitmap | ||
285 | * release group | ||
286 | * | ||
287 | * - use preallocation: | ||
288 | * find proper PA (per-inode or group) | ||
289 | * load group | ||
290 | * mark bits in on-disk bitmap | ||
291 | * release group | ||
292 | * release PA | ||
293 | * | ||
294 | * - free: | ||
295 | * load group | ||
296 | * mark bits in on-disk bitmap | ||
297 | * release group | ||
298 | * | ||
299 | * - discard preallocations in group: | ||
300 | * mark PAs deleted | ||
301 | * move them onto local list | ||
302 | * load on-disk bitmap | ||
303 | * load group | ||
304 | * remove PA from object (inode or locality group) | ||
305 | * mark free blocks in-core | ||
306 | * | ||
307 | * - discard inode's preallocations: | ||
308 | */ | ||
309 | |||
310 | /* | ||
311 | * Locking rules | ||
312 | * | ||
313 | * Locks: | ||
314 | * - bitlock on a group (group) | ||
315 | * - object (inode/locality) (object) | ||
316 | * - per-pa lock (pa) | ||
317 | * | ||
318 | * Paths: | ||
319 | * - new pa | ||
320 | * object | ||
321 | * group | ||
322 | * | ||
323 | * - find and use pa: | ||
324 | * pa | ||
325 | * | ||
326 | * - release consumed pa: | ||
327 | * pa | ||
328 | * group | ||
329 | * object | ||
330 | * | ||
331 | * - generate in-core bitmap: | ||
332 | * group | ||
333 | * pa | ||
334 | * | ||
335 | * - discard all for given object (inode, locality group): | ||
336 | * object | ||
337 | * pa | ||
338 | * group | ||
339 | * | ||
340 | * - discard all for given group: | ||
341 | * group | ||
342 | * pa | ||
343 | * group | ||
344 | * object | ||
345 | * | ||
346 | */ | ||
347 | |||
348 | /* | ||
349 | * with AGGRESSIVE_CHECK allocator runs consistency checks over | ||
350 | * structures. these checks slow things down a lot | ||
351 | */ | ||
352 | #define AGGRESSIVE_CHECK__ | ||
353 | |||
354 | /* | ||
355 | * with DOUBLE_CHECK defined mballoc creates persistent in-core | ||
356 | * bitmaps, maintains and uses them to check for double allocations | ||
357 | */ | ||
358 | #define DOUBLE_CHECK__ | ||
359 | |||
360 | /* | ||
361 | */ | ||
362 | #define MB_DEBUG__ | ||
363 | #ifdef MB_DEBUG | ||
364 | #define mb_debug(fmt, a...) printk(fmt, ##a) | ||
365 | #else | ||
366 | #define mb_debug(fmt, a...) | ||
367 | #endif | ||
368 | |||
369 | /* | ||
370 | * with EXT4_MB_HISTORY mballoc stores last N allocations in memory | ||
371 | * and you can monitor it in /proc/fs/ext4/<dev>/mb_history | ||
372 | */ | ||
373 | #define EXT4_MB_HISTORY | ||
374 | #define EXT4_MB_HISTORY_ALLOC 1 /* allocation */ | ||
375 | #define EXT4_MB_HISTORY_PREALLOC 2 /* preallocated blocks used */ | ||
376 | #define EXT4_MB_HISTORY_DISCARD 4 /* preallocation discarded */ | ||
377 | #define EXT4_MB_HISTORY_FREE 8 /* free */ | ||
378 | |||
379 | #define EXT4_MB_HISTORY_DEFAULT (EXT4_MB_HISTORY_ALLOC | \ | ||
380 | EXT4_MB_HISTORY_PREALLOC) | ||
381 | |||
382 | /* | ||
383 | * How long mballoc can look for a best extent (in found extents) | ||
384 | */ | ||
385 | #define MB_DEFAULT_MAX_TO_SCAN 200 | ||
386 | |||
387 | /* | ||
388 | * How long mballoc must look for a best extent | ||
389 | */ | ||
390 | #define MB_DEFAULT_MIN_TO_SCAN 10 | ||
391 | |||
392 | /* | ||
393 | * How many groups mballoc will scan looking for the best chunk | ||
394 | */ | ||
395 | #define MB_DEFAULT_MAX_GROUPS_TO_SCAN 5 | ||
396 | |||
397 | /* | ||
398 | * with 'ext4_mb_stats' allocator will collect stats that will be | ||
399 | * shown at umount. The collecting costs though! | ||
400 | */ | ||
401 | #define MB_DEFAULT_STATS 1 | ||
402 | |||
403 | /* | ||
404 | * files smaller than MB_DEFAULT_STREAM_THRESHOLD are served | ||
405 | * by the stream allocator, which purpose is to pack requests | ||
406 | * as close each to other as possible to produce smooth I/O traffic | ||
407 | * We use locality group prealloc space for stream request. | ||
408 | * We can tune the same via /proc/fs/ext4/<parition>/stream_req | ||
409 | */ | ||
410 | #define MB_DEFAULT_STREAM_THRESHOLD 16 /* 64K */ | ||
411 | |||
412 | /* | ||
413 | * for which requests use 2^N search using buddies | ||
414 | */ | ||
415 | #define MB_DEFAULT_ORDER2_REQS 2 | ||
416 | |||
417 | /* | ||
418 | * default group prealloc size 512 blocks | ||
419 | */ | ||
420 | #define MB_DEFAULT_GROUP_PREALLOC 512 | ||
421 | |||
422 | static struct kmem_cache *ext4_pspace_cachep; | ||
423 | |||
424 | #ifdef EXT4_BB_MAX_BLOCKS | ||
425 | #undef EXT4_BB_MAX_BLOCKS | ||
426 | #endif | ||
427 | #define EXT4_BB_MAX_BLOCKS 30 | ||
428 | |||
429 | struct ext4_free_metadata { | ||
430 | ext4_group_t group; | ||
431 | unsigned short num; | ||
432 | ext4_grpblk_t blocks[EXT4_BB_MAX_BLOCKS]; | ||
433 | struct list_head list; | ||
434 | }; | ||
435 | |||
436 | struct ext4_group_info { | ||
437 | unsigned long bb_state; | ||
438 | unsigned long bb_tid; | ||
439 | struct ext4_free_metadata *bb_md_cur; | ||
440 | unsigned short bb_first_free; | ||
441 | unsigned short bb_free; | ||
442 | unsigned short bb_fragments; | ||
443 | struct list_head bb_prealloc_list; | ||
444 | #ifdef DOUBLE_CHECK | ||
445 | void *bb_bitmap; | ||
446 | #endif | ||
447 | unsigned short bb_counters[]; | ||
448 | }; | ||
449 | |||
450 | #define EXT4_GROUP_INFO_NEED_INIT_BIT 0 | ||
451 | #define EXT4_GROUP_INFO_LOCKED_BIT 1 | ||
452 | |||
453 | #define EXT4_MB_GRP_NEED_INIT(grp) \ | ||
454 | (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state))) | ||
455 | |||
456 | |||
457 | struct ext4_prealloc_space { | ||
458 | struct list_head pa_inode_list; | ||
459 | struct list_head pa_group_list; | ||
460 | union { | ||
461 | struct list_head pa_tmp_list; | ||
462 | struct rcu_head pa_rcu; | ||
463 | } u; | ||
464 | spinlock_t pa_lock; | ||
465 | atomic_t pa_count; | ||
466 | unsigned pa_deleted; | ||
467 | ext4_fsblk_t pa_pstart; /* phys. block */ | ||
468 | ext4_lblk_t pa_lstart; /* log. block */ | ||
469 | unsigned short pa_len; /* len of preallocated chunk */ | ||
470 | unsigned short pa_free; /* how many blocks are free */ | ||
471 | unsigned short pa_linear; /* consumed in one direction | ||
472 | * strictly, for grp prealloc */ | ||
473 | spinlock_t *pa_obj_lock; | ||
474 | struct inode *pa_inode; /* hack, for history only */ | ||
475 | }; | ||
476 | |||
477 | |||
478 | struct ext4_free_extent { | ||
479 | ext4_lblk_t fe_logical; | ||
480 | ext4_grpblk_t fe_start; | ||
481 | ext4_group_t fe_group; | ||
482 | int fe_len; | ||
483 | }; | ||
484 | |||
485 | /* | ||
486 | * Locality group: | ||
487 | * we try to group all related changes together | ||
488 | * so that writeback can flush/allocate them together as well | ||
489 | */ | ||
490 | struct ext4_locality_group { | ||
491 | /* for allocator */ | ||
492 | struct mutex lg_mutex; /* to serialize allocates */ | ||
493 | struct list_head lg_prealloc_list;/* list of preallocations */ | ||
494 | spinlock_t lg_prealloc_lock; | ||
495 | }; | ||
496 | |||
497 | struct ext4_allocation_context { | ||
498 | struct inode *ac_inode; | ||
499 | struct super_block *ac_sb; | ||
500 | |||
501 | /* original request */ | ||
502 | struct ext4_free_extent ac_o_ex; | ||
503 | |||
504 | /* goal request (after normalization) */ | ||
505 | struct ext4_free_extent ac_g_ex; | ||
506 | |||
507 | /* the best found extent */ | ||
508 | struct ext4_free_extent ac_b_ex; | ||
509 | |||
510 | /* copy of the bext found extent taken before preallocation efforts */ | ||
511 | struct ext4_free_extent ac_f_ex; | ||
512 | |||
513 | /* number of iterations done. we have to track to limit searching */ | ||
514 | unsigned long ac_ex_scanned; | ||
515 | __u16 ac_groups_scanned; | ||
516 | __u16 ac_found; | ||
517 | __u16 ac_tail; | ||
518 | __u16 ac_buddy; | ||
519 | __u16 ac_flags; /* allocation hints */ | ||
520 | __u8 ac_status; | ||
521 | __u8 ac_criteria; | ||
522 | __u8 ac_repeats; | ||
523 | __u8 ac_2order; /* if request is to allocate 2^N blocks and | ||
524 | * N > 0, the field stores N, otherwise 0 */ | ||
525 | __u8 ac_op; /* operation, for history only */ | ||
526 | struct page *ac_bitmap_page; | ||
527 | struct page *ac_buddy_page; | ||
528 | struct ext4_prealloc_space *ac_pa; | ||
529 | struct ext4_locality_group *ac_lg; | ||
530 | }; | ||
531 | |||
532 | #define AC_STATUS_CONTINUE 1 | ||
533 | #define AC_STATUS_FOUND 2 | ||
534 | #define AC_STATUS_BREAK 3 | ||
535 | |||
536 | struct ext4_mb_history { | ||
537 | struct ext4_free_extent orig; /* orig allocation */ | ||
538 | struct ext4_free_extent goal; /* goal allocation */ | ||
539 | struct ext4_free_extent result; /* result allocation */ | ||
540 | unsigned pid; | ||
541 | unsigned ino; | ||
542 | __u16 found; /* how many extents have been found */ | ||
543 | __u16 groups; /* how many groups have been scanned */ | ||
544 | __u16 tail; /* what tail broke some buddy */ | ||
545 | __u16 buddy; /* buddy the tail ^^^ broke */ | ||
546 | __u16 flags; | ||
547 | __u8 cr:3; /* which phase the result extent was found at */ | ||
548 | __u8 op:4; | ||
549 | __u8 merged:1; | ||
550 | }; | ||
551 | |||
552 | struct ext4_buddy { | ||
553 | struct page *bd_buddy_page; | ||
554 | void *bd_buddy; | ||
555 | struct page *bd_bitmap_page; | ||
556 | void *bd_bitmap; | ||
557 | struct ext4_group_info *bd_info; | ||
558 | struct super_block *bd_sb; | ||
559 | __u16 bd_blkbits; | ||
560 | ext4_group_t bd_group; | ||
561 | }; | ||
562 | #define EXT4_MB_BITMAP(e4b) ((e4b)->bd_bitmap) | ||
563 | #define EXT4_MB_BUDDY(e4b) ((e4b)->bd_buddy) | ||
564 | |||
565 | #ifndef EXT4_MB_HISTORY | ||
566 | static inline void ext4_mb_store_history(struct ext4_allocation_context *ac) | ||
567 | { | ||
568 | return; | ||
569 | } | ||
570 | #else | ||
571 | static void ext4_mb_store_history(struct ext4_allocation_context *ac); | ||
572 | #endif | ||
573 | |||
574 | #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) | ||
575 | |||
576 | static struct proc_dir_entry *proc_root_ext4; | ||
577 | struct buffer_head *read_block_bitmap(struct super_block *, ext4_group_t); | ||
578 | ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode, | ||
579 | ext4_fsblk_t goal, unsigned long *count, int *errp); | ||
580 | |||
581 | static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, | ||
582 | ext4_group_t group); | ||
583 | static void ext4_mb_poll_new_transaction(struct super_block *, handle_t *); | ||
584 | static void ext4_mb_free_committed_blocks(struct super_block *); | ||
585 | static void ext4_mb_return_to_preallocation(struct inode *inode, | ||
586 | struct ext4_buddy *e4b, sector_t block, | ||
587 | int count); | ||
588 | static void ext4_mb_put_pa(struct ext4_allocation_context *, | ||
589 | struct super_block *, struct ext4_prealloc_space *pa); | ||
590 | static int ext4_mb_init_per_dev_proc(struct super_block *sb); | ||
591 | static int ext4_mb_destroy_per_dev_proc(struct super_block *sb); | ||
592 | |||
593 | |||
594 | static inline void ext4_lock_group(struct super_block *sb, ext4_group_t group) | ||
595 | { | ||
596 | struct ext4_group_info *grinfo = ext4_get_group_info(sb, group); | ||
597 | |||
598 | bit_spin_lock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state)); | ||
599 | } | ||
600 | |||
601 | static inline void ext4_unlock_group(struct super_block *sb, | ||
602 | ext4_group_t group) | ||
603 | { | ||
604 | struct ext4_group_info *grinfo = ext4_get_group_info(sb, group); | ||
605 | |||
606 | bit_spin_unlock(EXT4_GROUP_INFO_LOCKED_BIT, &(grinfo->bb_state)); | ||
607 | } | ||
608 | |||
609 | static inline int ext4_is_group_locked(struct super_block *sb, | ||
610 | ext4_group_t group) | ||
611 | { | ||
612 | struct ext4_group_info *grinfo = ext4_get_group_info(sb, group); | ||
613 | |||
614 | return bit_spin_is_locked(EXT4_GROUP_INFO_LOCKED_BIT, | ||
615 | &(grinfo->bb_state)); | ||
616 | } | ||
617 | |||
618 | static ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb, | ||
619 | struct ext4_free_extent *fex) | ||
620 | { | ||
621 | ext4_fsblk_t block; | ||
622 | |||
623 | block = (ext4_fsblk_t) fex->fe_group * EXT4_BLOCKS_PER_GROUP(sb) | ||
624 | + fex->fe_start | ||
625 | + le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); | ||
626 | return block; | ||
627 | } | ||
628 | |||
629 | #if BITS_PER_LONG == 64 | ||
630 | #define mb_correct_addr_and_bit(bit, addr) \ | ||
631 | { \ | ||
632 | bit += ((unsigned long) addr & 7UL) << 3; \ | ||
633 | addr = (void *) ((unsigned long) addr & ~7UL); \ | ||
634 | } | ||
635 | #elif BITS_PER_LONG == 32 | ||
636 | #define mb_correct_addr_and_bit(bit, addr) \ | ||
637 | { \ | ||
638 | bit += ((unsigned long) addr & 3UL) << 3; \ | ||
639 | addr = (void *) ((unsigned long) addr & ~3UL); \ | ||
640 | } | ||
641 | #else | ||
642 | #error "how many bits you are?!" | ||
643 | #endif | ||
644 | |||
645 | static inline int mb_test_bit(int bit, void *addr) | ||
646 | { | ||
647 | /* | ||
648 | * ext4_test_bit on architecture like powerpc | ||
649 | * needs unsigned long aligned address | ||
650 | */ | ||
651 | mb_correct_addr_and_bit(bit, addr); | ||
652 | return ext4_test_bit(bit, addr); | ||
653 | } | ||
654 | |||
655 | static inline void mb_set_bit(int bit, void *addr) | ||
656 | { | ||
657 | mb_correct_addr_and_bit(bit, addr); | ||
658 | ext4_set_bit(bit, addr); | ||
659 | } | ||
660 | |||
661 | static inline void mb_set_bit_atomic(spinlock_t *lock, int bit, void *addr) | ||
662 | { | ||
663 | mb_correct_addr_and_bit(bit, addr); | ||
664 | ext4_set_bit_atomic(lock, bit, addr); | ||
665 | } | ||
666 | |||
667 | static inline void mb_clear_bit(int bit, void *addr) | ||
668 | { | ||
669 | mb_correct_addr_and_bit(bit, addr); | ||
670 | ext4_clear_bit(bit, addr); | ||
671 | } | ||
672 | |||
673 | static inline void mb_clear_bit_atomic(spinlock_t *lock, int bit, void *addr) | ||
674 | { | ||
675 | mb_correct_addr_and_bit(bit, addr); | ||
676 | ext4_clear_bit_atomic(lock, bit, addr); | ||
677 | } | ||
678 | |||
679 | static void *mb_find_buddy(struct ext4_buddy *e4b, int order, int *max) | ||
680 | { | ||
681 | char *bb; | ||
682 | |||
683 | /* FIXME!! is this needed */ | ||
684 | BUG_ON(EXT4_MB_BITMAP(e4b) == EXT4_MB_BUDDY(e4b)); | ||
685 | BUG_ON(max == NULL); | ||
686 | |||
687 | if (order > e4b->bd_blkbits + 1) { | ||
688 | *max = 0; | ||
689 | return NULL; | ||
690 | } | ||
691 | |||
692 | /* at order 0 we see each particular block */ | ||
693 | *max = 1 << (e4b->bd_blkbits + 3); | ||
694 | if (order == 0) | ||
695 | return EXT4_MB_BITMAP(e4b); | ||
696 | |||
697 | bb = EXT4_MB_BUDDY(e4b) + EXT4_SB(e4b->bd_sb)->s_mb_offsets[order]; | ||
698 | *max = EXT4_SB(e4b->bd_sb)->s_mb_maxs[order]; | ||
699 | |||
700 | return bb; | ||
701 | } | ||
702 | |||
703 | #ifdef DOUBLE_CHECK | ||
704 | static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b, | ||
705 | int first, int count) | ||
706 | { | ||
707 | int i; | ||
708 | struct super_block *sb = e4b->bd_sb; | ||
709 | |||
710 | if (unlikely(e4b->bd_info->bb_bitmap == NULL)) | ||
711 | return; | ||
712 | BUG_ON(!ext4_is_group_locked(sb, e4b->bd_group)); | ||
713 | for (i = 0; i < count; i++) { | ||
714 | if (!mb_test_bit(first + i, e4b->bd_info->bb_bitmap)) { | ||
715 | ext4_fsblk_t blocknr; | ||
716 | blocknr = e4b->bd_group * EXT4_BLOCKS_PER_GROUP(sb); | ||
717 | blocknr += first + i; | ||
718 | blocknr += | ||
719 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); | ||
720 | |||
721 | ext4_error(sb, __FUNCTION__, "double-free of inode" | ||
722 | " %lu's block %llu(bit %u in group %lu)\n", | ||
723 | inode ? inode->i_ino : 0, blocknr, | ||
724 | first + i, e4b->bd_group); | ||
725 | } | ||
726 | mb_clear_bit(first + i, e4b->bd_info->bb_bitmap); | ||
727 | } | ||
728 | } | ||
729 | |||
730 | static void mb_mark_used_double(struct ext4_buddy *e4b, int first, int count) | ||
731 | { | ||
732 | int i; | ||
733 | |||
734 | if (unlikely(e4b->bd_info->bb_bitmap == NULL)) | ||
735 | return; | ||
736 | BUG_ON(!ext4_is_group_locked(e4b->bd_sb, e4b->bd_group)); | ||
737 | for (i = 0; i < count; i++) { | ||
738 | BUG_ON(mb_test_bit(first + i, e4b->bd_info->bb_bitmap)); | ||
739 | mb_set_bit(first + i, e4b->bd_info->bb_bitmap); | ||
740 | } | ||
741 | } | ||
742 | |||
743 | static void mb_cmp_bitmaps(struct ext4_buddy *e4b, void *bitmap) | ||
744 | { | ||
745 | if (memcmp(e4b->bd_info->bb_bitmap, bitmap, e4b->bd_sb->s_blocksize)) { | ||
746 | unsigned char *b1, *b2; | ||
747 | int i; | ||
748 | b1 = (unsigned char *) e4b->bd_info->bb_bitmap; | ||
749 | b2 = (unsigned char *) bitmap; | ||
750 | for (i = 0; i < e4b->bd_sb->s_blocksize; i++) { | ||
751 | if (b1[i] != b2[i]) { | ||
752 | printk("corruption in group %lu at byte %u(%u):" | ||
753 | " %x in copy != %x on disk/prealloc\n", | ||
754 | e4b->bd_group, i, i * 8, b1[i], b2[i]); | ||
755 | BUG(); | ||
756 | } | ||
757 | } | ||
758 | } | ||
759 | } | ||
760 | |||
761 | #else | ||
762 | static inline void mb_free_blocks_double(struct inode *inode, | ||
763 | struct ext4_buddy *e4b, int first, int count) | ||
764 | { | ||
765 | return; | ||
766 | } | ||
767 | static inline void mb_mark_used_double(struct ext4_buddy *e4b, | ||
768 | int first, int count) | ||
769 | { | ||
770 | return; | ||
771 | } | ||
772 | static inline void mb_cmp_bitmaps(struct ext4_buddy *e4b, void *bitmap) | ||
773 | { | ||
774 | return; | ||
775 | } | ||
776 | #endif | ||
777 | |||
778 | #ifdef AGGRESSIVE_CHECK | ||
779 | |||
780 | #define MB_CHECK_ASSERT(assert) \ | ||
781 | do { \ | ||
782 | if (!(assert)) { \ | ||
783 | printk(KERN_EMERG \ | ||
784 | "Assertion failure in %s() at %s:%d: \"%s\"\n", \ | ||
785 | function, file, line, # assert); \ | ||
786 | BUG(); \ | ||
787 | } \ | ||
788 | } while (0) | ||
789 | |||
790 | static int __mb_check_buddy(struct ext4_buddy *e4b, char *file, | ||
791 | const char *function, int line) | ||
792 | { | ||
793 | struct super_block *sb = e4b->bd_sb; | ||
794 | int order = e4b->bd_blkbits + 1; | ||
795 | int max; | ||
796 | int max2; | ||
797 | int i; | ||
798 | int j; | ||
799 | int k; | ||
800 | int count; | ||
801 | struct ext4_group_info *grp; | ||
802 | int fragments = 0; | ||
803 | int fstart; | ||
804 | struct list_head *cur; | ||
805 | void *buddy; | ||
806 | void *buddy2; | ||
807 | |||
808 | if (!test_opt(sb, MBALLOC)) | ||
809 | return 0; | ||
810 | |||
811 | { | ||
812 | static int mb_check_counter; | ||
813 | if (mb_check_counter++ % 100 != 0) | ||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | while (order > 1) { | ||
818 | buddy = mb_find_buddy(e4b, order, &max); | ||
819 | MB_CHECK_ASSERT(buddy); | ||
820 | buddy2 = mb_find_buddy(e4b, order - 1, &max2); | ||
821 | MB_CHECK_ASSERT(buddy2); | ||
822 | MB_CHECK_ASSERT(buddy != buddy2); | ||
823 | MB_CHECK_ASSERT(max * 2 == max2); | ||
824 | |||
825 | count = 0; | ||
826 | for (i = 0; i < max; i++) { | ||
827 | |||
828 | if (mb_test_bit(i, buddy)) { | ||
829 | /* only single bit in buddy2 may be 1 */ | ||
830 | if (!mb_test_bit(i << 1, buddy2)) { | ||
831 | MB_CHECK_ASSERT( | ||
832 | mb_test_bit((i<<1)+1, buddy2)); | ||
833 | } else if (!mb_test_bit((i << 1) + 1, buddy2)) { | ||
834 | MB_CHECK_ASSERT( | ||
835 | mb_test_bit(i << 1, buddy2)); | ||
836 | } | ||
837 | continue; | ||
838 | } | ||
839 | |||
840 | /* both bits in buddy2 must be 0 */ | ||
841 | MB_CHECK_ASSERT(mb_test_bit(i << 1, buddy2)); | ||
842 | MB_CHECK_ASSERT(mb_test_bit((i << 1) + 1, buddy2)); | ||
843 | |||
844 | for (j = 0; j < (1 << order); j++) { | ||
845 | k = (i * (1 << order)) + j; | ||
846 | MB_CHECK_ASSERT( | ||
847 | !mb_test_bit(k, EXT4_MB_BITMAP(e4b))); | ||
848 | } | ||
849 | count++; | ||
850 | } | ||
851 | MB_CHECK_ASSERT(e4b->bd_info->bb_counters[order] == count); | ||
852 | order--; | ||
853 | } | ||
854 | |||
855 | fstart = -1; | ||
856 | buddy = mb_find_buddy(e4b, 0, &max); | ||
857 | for (i = 0; i < max; i++) { | ||
858 | if (!mb_test_bit(i, buddy)) { | ||
859 | MB_CHECK_ASSERT(i >= e4b->bd_info->bb_first_free); | ||
860 | if (fstart == -1) { | ||
861 | fragments++; | ||
862 | fstart = i; | ||
863 | } | ||
864 | continue; | ||
865 | } | ||
866 | fstart = -1; | ||
867 | /* check used bits only */ | ||
868 | for (j = 0; j < e4b->bd_blkbits + 1; j++) { | ||
869 | buddy2 = mb_find_buddy(e4b, j, &max2); | ||
870 | k = i >> j; | ||
871 | MB_CHECK_ASSERT(k < max2); | ||
872 | MB_CHECK_ASSERT(mb_test_bit(k, buddy2)); | ||
873 | } | ||
874 | } | ||
875 | MB_CHECK_ASSERT(!EXT4_MB_GRP_NEED_INIT(e4b->bd_info)); | ||
876 | MB_CHECK_ASSERT(e4b->bd_info->bb_fragments == fragments); | ||
877 | |||
878 | grp = ext4_get_group_info(sb, e4b->bd_group); | ||
879 | buddy = mb_find_buddy(e4b, 0, &max); | ||
880 | list_for_each(cur, &grp->bb_prealloc_list) { | ||
881 | ext4_group_t groupnr; | ||
882 | struct ext4_prealloc_space *pa; | ||
883 | pa = list_entry(cur, struct ext4_prealloc_space, group_list); | ||
884 | ext4_get_group_no_and_offset(sb, pa->pstart, &groupnr, &k); | ||
885 | MB_CHECK_ASSERT(groupnr == e4b->bd_group); | ||
886 | for (i = 0; i < pa->len; i++) | ||
887 | MB_CHECK_ASSERT(mb_test_bit(k + i, buddy)); | ||
888 | } | ||
889 | return 0; | ||
890 | } | ||
891 | #undef MB_CHECK_ASSERT | ||
892 | #define mb_check_buddy(e4b) __mb_check_buddy(e4b, \ | ||
893 | __FILE__, __FUNCTION__, __LINE__) | ||
894 | #else | ||
895 | #define mb_check_buddy(e4b) | ||
896 | #endif | ||
897 | |||
898 | /* FIXME!! need more doc */ | ||
899 | static void ext4_mb_mark_free_simple(struct super_block *sb, | ||
900 | void *buddy, unsigned first, int len, | ||
901 | struct ext4_group_info *grp) | ||
902 | { | ||
903 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
904 | unsigned short min; | ||
905 | unsigned short max; | ||
906 | unsigned short chunk; | ||
907 | unsigned short border; | ||
908 | |||
909 | BUG_ON(len >= EXT4_BLOCKS_PER_GROUP(sb)); | ||
910 | |||
911 | border = 2 << sb->s_blocksize_bits; | ||
912 | |||
913 | while (len > 0) { | ||
914 | /* find how many blocks can be covered since this position */ | ||
915 | max = ffs(first | border) - 1; | ||
916 | |||
917 | /* find how many blocks of power 2 we need to mark */ | ||
918 | min = fls(len) - 1; | ||
919 | |||
920 | if (max < min) | ||
921 | min = max; | ||
922 | chunk = 1 << min; | ||
923 | |||
924 | /* mark multiblock chunks only */ | ||
925 | grp->bb_counters[min]++; | ||
926 | if (min > 0) | ||
927 | mb_clear_bit(first >> min, | ||
928 | buddy + sbi->s_mb_offsets[min]); | ||
929 | |||
930 | len -= chunk; | ||
931 | first += chunk; | ||
932 | } | ||
933 | } | ||
934 | |||
935 | static void ext4_mb_generate_buddy(struct super_block *sb, | ||
936 | void *buddy, void *bitmap, ext4_group_t group) | ||
937 | { | ||
938 | struct ext4_group_info *grp = ext4_get_group_info(sb, group); | ||
939 | unsigned short max = EXT4_BLOCKS_PER_GROUP(sb); | ||
940 | unsigned short i = 0; | ||
941 | unsigned short first; | ||
942 | unsigned short len; | ||
943 | unsigned free = 0; | ||
944 | unsigned fragments = 0; | ||
945 | unsigned long long period = get_cycles(); | ||
946 | |||
947 | /* initialize buddy from bitmap which is aggregation | ||
948 | * of on-disk bitmap and preallocations */ | ||
949 | i = ext4_find_next_zero_bit(bitmap, max, 0); | ||
950 | grp->bb_first_free = i; | ||
951 | while (i < max) { | ||
952 | fragments++; | ||
953 | first = i; | ||
954 | i = ext4_find_next_bit(bitmap, max, i); | ||
955 | len = i - first; | ||
956 | free += len; | ||
957 | if (len > 1) | ||
958 | ext4_mb_mark_free_simple(sb, buddy, first, len, grp); | ||
959 | else | ||
960 | grp->bb_counters[0]++; | ||
961 | if (i < max) | ||
962 | i = ext4_find_next_zero_bit(bitmap, max, i); | ||
963 | } | ||
964 | grp->bb_fragments = fragments; | ||
965 | |||
966 | if (free != grp->bb_free) { | ||
967 | printk(KERN_DEBUG | ||
968 | "EXT4-fs: group %lu: %u blocks in bitmap, %u in gd\n", | ||
969 | group, free, grp->bb_free); | ||
970 | grp->bb_free = free; | ||
971 | } | ||
972 | |||
973 | clear_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &(grp->bb_state)); | ||
974 | |||
975 | period = get_cycles() - period; | ||
976 | spin_lock(&EXT4_SB(sb)->s_bal_lock); | ||
977 | EXT4_SB(sb)->s_mb_buddies_generated++; | ||
978 | EXT4_SB(sb)->s_mb_generation_time += period; | ||
979 | spin_unlock(&EXT4_SB(sb)->s_bal_lock); | ||
980 | } | ||
981 | |||
982 | /* The buddy information is attached the buddy cache inode | ||
983 | * for convenience. The information regarding each group | ||
984 | * is loaded via ext4_mb_load_buddy. The information involve | ||
985 | * block bitmap and buddy information. The information are | ||
986 | * stored in the inode as | ||
987 | * | ||
988 | * { page } | ||
989 | * [ group 0 buddy][ group 0 bitmap] [group 1][ group 1]... | ||
990 | * | ||
991 | * | ||
992 | * one block each for bitmap and buddy information. | ||
993 | * So for each group we take up 2 blocks. A page can | ||
994 | * contain blocks_per_page (PAGE_CACHE_SIZE / blocksize) blocks. | ||
995 | * So it can have information regarding groups_per_page which | ||
996 | * is blocks_per_page/2 | ||
997 | */ | ||
998 | |||
999 | static int ext4_mb_init_cache(struct page *page, char *incore) | ||
1000 | { | ||
1001 | int blocksize; | ||
1002 | int blocks_per_page; | ||
1003 | int groups_per_page; | ||
1004 | int err = 0; | ||
1005 | int i; | ||
1006 | ext4_group_t first_group; | ||
1007 | int first_block; | ||
1008 | struct super_block *sb; | ||
1009 | struct buffer_head *bhs; | ||
1010 | struct buffer_head **bh; | ||
1011 | struct inode *inode; | ||
1012 | char *data; | ||
1013 | char *bitmap; | ||
1014 | |||
1015 | mb_debug("init page %lu\n", page->index); | ||
1016 | |||
1017 | inode = page->mapping->host; | ||
1018 | sb = inode->i_sb; | ||
1019 | blocksize = 1 << inode->i_blkbits; | ||
1020 | blocks_per_page = PAGE_CACHE_SIZE / blocksize; | ||
1021 | |||
1022 | groups_per_page = blocks_per_page >> 1; | ||
1023 | if (groups_per_page == 0) | ||
1024 | groups_per_page = 1; | ||
1025 | |||
1026 | /* allocate buffer_heads to read bitmaps */ | ||
1027 | if (groups_per_page > 1) { | ||
1028 | err = -ENOMEM; | ||
1029 | i = sizeof(struct buffer_head *) * groups_per_page; | ||
1030 | bh = kzalloc(i, GFP_NOFS); | ||
1031 | if (bh == NULL) | ||
1032 | goto out; | ||
1033 | } else | ||
1034 | bh = &bhs; | ||
1035 | |||
1036 | first_group = page->index * blocks_per_page / 2; | ||
1037 | |||
1038 | /* read all groups the page covers into the cache */ | ||
1039 | for (i = 0; i < groups_per_page; i++) { | ||
1040 | struct ext4_group_desc *desc; | ||
1041 | |||
1042 | if (first_group + i >= EXT4_SB(sb)->s_groups_count) | ||
1043 | break; | ||
1044 | |||
1045 | err = -EIO; | ||
1046 | desc = ext4_get_group_desc(sb, first_group + i, NULL); | ||
1047 | if (desc == NULL) | ||
1048 | goto out; | ||
1049 | |||
1050 | err = -ENOMEM; | ||
1051 | bh[i] = sb_getblk(sb, ext4_block_bitmap(sb, desc)); | ||
1052 | if (bh[i] == NULL) | ||
1053 | goto out; | ||
1054 | |||
1055 | if (bh_uptodate_or_lock(bh[i])) | ||
1056 | continue; | ||
1057 | |||
1058 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | ||
1059 | ext4_init_block_bitmap(sb, bh[i], | ||
1060 | first_group + i, desc); | ||
1061 | set_buffer_uptodate(bh[i]); | ||
1062 | unlock_buffer(bh[i]); | ||
1063 | continue; | ||
1064 | } | ||
1065 | get_bh(bh[i]); | ||
1066 | bh[i]->b_end_io = end_buffer_read_sync; | ||
1067 | submit_bh(READ, bh[i]); | ||
1068 | mb_debug("read bitmap for group %lu\n", first_group + i); | ||
1069 | } | ||
1070 | |||
1071 | /* wait for I/O completion */ | ||
1072 | for (i = 0; i < groups_per_page && bh[i]; i++) | ||
1073 | wait_on_buffer(bh[i]); | ||
1074 | |||
1075 | err = -EIO; | ||
1076 | for (i = 0; i < groups_per_page && bh[i]; i++) | ||
1077 | if (!buffer_uptodate(bh[i])) | ||
1078 | goto out; | ||
1079 | |||
1080 | first_block = page->index * blocks_per_page; | ||
1081 | for (i = 0; i < blocks_per_page; i++) { | ||
1082 | int group; | ||
1083 | struct ext4_group_info *grinfo; | ||
1084 | |||
1085 | group = (first_block + i) >> 1; | ||
1086 | if (group >= EXT4_SB(sb)->s_groups_count) | ||
1087 | break; | ||
1088 | |||
1089 | /* | ||
1090 | * data carry information regarding this | ||
1091 | * particular group in the format specified | ||
1092 | * above | ||
1093 | * | ||
1094 | */ | ||
1095 | data = page_address(page) + (i * blocksize); | ||
1096 | bitmap = bh[group - first_group]->b_data; | ||
1097 | |||
1098 | /* | ||
1099 | * We place the buddy block and bitmap block | ||
1100 | * close together | ||
1101 | */ | ||
1102 | if ((first_block + i) & 1) { | ||
1103 | /* this is block of buddy */ | ||
1104 | BUG_ON(incore == NULL); | ||
1105 | mb_debug("put buddy for group %u in page %lu/%x\n", | ||
1106 | group, page->index, i * blocksize); | ||
1107 | memset(data, 0xff, blocksize); | ||
1108 | grinfo = ext4_get_group_info(sb, group); | ||
1109 | grinfo->bb_fragments = 0; | ||
1110 | memset(grinfo->bb_counters, 0, | ||
1111 | sizeof(unsigned short)*(sb->s_blocksize_bits+2)); | ||
1112 | /* | ||
1113 | * incore got set to the group block bitmap below | ||
1114 | */ | ||
1115 | ext4_mb_generate_buddy(sb, data, incore, group); | ||
1116 | incore = NULL; | ||
1117 | } else { | ||
1118 | /* this is block of bitmap */ | ||
1119 | BUG_ON(incore != NULL); | ||
1120 | mb_debug("put bitmap for group %u in page %lu/%x\n", | ||
1121 | group, page->index, i * blocksize); | ||
1122 | |||
1123 | /* see comments in ext4_mb_put_pa() */ | ||
1124 | ext4_lock_group(sb, group); | ||
1125 | memcpy(data, bitmap, blocksize); | ||
1126 | |||
1127 | /* mark all preallocated blks used in in-core bitmap */ | ||
1128 | ext4_mb_generate_from_pa(sb, data, group); | ||
1129 | ext4_unlock_group(sb, group); | ||
1130 | |||
1131 | /* set incore so that the buddy information can be | ||
1132 | * generated using this | ||
1133 | */ | ||
1134 | incore = data; | ||
1135 | } | ||
1136 | } | ||
1137 | SetPageUptodate(page); | ||
1138 | |||
1139 | out: | ||
1140 | if (bh) { | ||
1141 | for (i = 0; i < groups_per_page && bh[i]; i++) | ||
1142 | brelse(bh[i]); | ||
1143 | if (bh != &bhs) | ||
1144 | kfree(bh); | ||
1145 | } | ||
1146 | return err; | ||
1147 | } | ||
1148 | |||
1149 | static int ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group, | ||
1150 | struct ext4_buddy *e4b) | ||
1151 | { | ||
1152 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
1153 | struct inode *inode = sbi->s_buddy_cache; | ||
1154 | int blocks_per_page; | ||
1155 | int block; | ||
1156 | int pnum; | ||
1157 | int poff; | ||
1158 | struct page *page; | ||
1159 | |||
1160 | mb_debug("load group %lu\n", group); | ||
1161 | |||
1162 | blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; | ||
1163 | |||
1164 | e4b->bd_blkbits = sb->s_blocksize_bits; | ||
1165 | e4b->bd_info = ext4_get_group_info(sb, group); | ||
1166 | e4b->bd_sb = sb; | ||
1167 | e4b->bd_group = group; | ||
1168 | e4b->bd_buddy_page = NULL; | ||
1169 | e4b->bd_bitmap_page = NULL; | ||
1170 | |||
1171 | /* | ||
1172 | * the buddy cache inode stores the block bitmap | ||
1173 | * and buddy information in consecutive blocks. | ||
1174 | * So for each group we need two blocks. | ||
1175 | */ | ||
1176 | block = group * 2; | ||
1177 | pnum = block / blocks_per_page; | ||
1178 | poff = block % blocks_per_page; | ||
1179 | |||
1180 | /* we could use find_or_create_page(), but it locks page | ||
1181 | * what we'd like to avoid in fast path ... */ | ||
1182 | page = find_get_page(inode->i_mapping, pnum); | ||
1183 | if (page == NULL || !PageUptodate(page)) { | ||
1184 | if (page) | ||
1185 | page_cache_release(page); | ||
1186 | page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS); | ||
1187 | if (page) { | ||
1188 | BUG_ON(page->mapping != inode->i_mapping); | ||
1189 | if (!PageUptodate(page)) { | ||
1190 | ext4_mb_init_cache(page, NULL); | ||
1191 | mb_cmp_bitmaps(e4b, page_address(page) + | ||
1192 | (poff * sb->s_blocksize)); | ||
1193 | } | ||
1194 | unlock_page(page); | ||
1195 | } | ||
1196 | } | ||
1197 | if (page == NULL || !PageUptodate(page)) | ||
1198 | goto err; | ||
1199 | e4b->bd_bitmap_page = page; | ||
1200 | e4b->bd_bitmap = page_address(page) + (poff * sb->s_blocksize); | ||
1201 | mark_page_accessed(page); | ||
1202 | |||
1203 | block++; | ||
1204 | pnum = block / blocks_per_page; | ||
1205 | poff = block % blocks_per_page; | ||
1206 | |||
1207 | page = find_get_page(inode->i_mapping, pnum); | ||
1208 | if (page == NULL || !PageUptodate(page)) { | ||
1209 | if (page) | ||
1210 | page_cache_release(page); | ||
1211 | page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS); | ||
1212 | if (page) { | ||
1213 | BUG_ON(page->mapping != inode->i_mapping); | ||
1214 | if (!PageUptodate(page)) | ||
1215 | ext4_mb_init_cache(page, e4b->bd_bitmap); | ||
1216 | |||
1217 | unlock_page(page); | ||
1218 | } | ||
1219 | } | ||
1220 | if (page == NULL || !PageUptodate(page)) | ||
1221 | goto err; | ||
1222 | e4b->bd_buddy_page = page; | ||
1223 | e4b->bd_buddy = page_address(page) + (poff * sb->s_blocksize); | ||
1224 | mark_page_accessed(page); | ||
1225 | |||
1226 | BUG_ON(e4b->bd_bitmap_page == NULL); | ||
1227 | BUG_ON(e4b->bd_buddy_page == NULL); | ||
1228 | |||
1229 | return 0; | ||
1230 | |||
1231 | err: | ||
1232 | if (e4b->bd_bitmap_page) | ||
1233 | page_cache_release(e4b->bd_bitmap_page); | ||
1234 | if (e4b->bd_buddy_page) | ||
1235 | page_cache_release(e4b->bd_buddy_page); | ||
1236 | e4b->bd_buddy = NULL; | ||
1237 | e4b->bd_bitmap = NULL; | ||
1238 | return -EIO; | ||
1239 | } | ||
1240 | |||
1241 | static void ext4_mb_release_desc(struct ext4_buddy *e4b) | ||
1242 | { | ||
1243 | if (e4b->bd_bitmap_page) | ||
1244 | page_cache_release(e4b->bd_bitmap_page); | ||
1245 | if (e4b->bd_buddy_page) | ||
1246 | page_cache_release(e4b->bd_buddy_page); | ||
1247 | } | ||
1248 | |||
1249 | |||
1250 | static int mb_find_order_for_block(struct ext4_buddy *e4b, int block) | ||
1251 | { | ||
1252 | int order = 1; | ||
1253 | void *bb; | ||
1254 | |||
1255 | BUG_ON(EXT4_MB_BITMAP(e4b) == EXT4_MB_BUDDY(e4b)); | ||
1256 | BUG_ON(block >= (1 << (e4b->bd_blkbits + 3))); | ||
1257 | |||
1258 | bb = EXT4_MB_BUDDY(e4b); | ||
1259 | while (order <= e4b->bd_blkbits + 1) { | ||
1260 | block = block >> 1; | ||
1261 | if (!mb_test_bit(block, bb)) { | ||
1262 | /* this block is part of buddy of order 'order' */ | ||
1263 | return order; | ||
1264 | } | ||
1265 | bb += 1 << (e4b->bd_blkbits - order); | ||
1266 | order++; | ||
1267 | } | ||
1268 | return 0; | ||
1269 | } | ||
1270 | |||
1271 | static void mb_clear_bits(spinlock_t *lock, void *bm, int cur, int len) | ||
1272 | { | ||
1273 | __u32 *addr; | ||
1274 | |||
1275 | len = cur + len; | ||
1276 | while (cur < len) { | ||
1277 | if ((cur & 31) == 0 && (len - cur) >= 32) { | ||
1278 | /* fast path: clear whole word at once */ | ||
1279 | addr = bm + (cur >> 3); | ||
1280 | *addr = 0; | ||
1281 | cur += 32; | ||
1282 | continue; | ||
1283 | } | ||
1284 | mb_clear_bit_atomic(lock, cur, bm); | ||
1285 | cur++; | ||
1286 | } | ||
1287 | } | ||
1288 | |||
1289 | static void mb_set_bits(spinlock_t *lock, void *bm, int cur, int len) | ||
1290 | { | ||
1291 | __u32 *addr; | ||
1292 | |||
1293 | len = cur + len; | ||
1294 | while (cur < len) { | ||
1295 | if ((cur & 31) == 0 && (len - cur) >= 32) { | ||
1296 | /* fast path: set whole word at once */ | ||
1297 | addr = bm + (cur >> 3); | ||
1298 | *addr = 0xffffffff; | ||
1299 | cur += 32; | ||
1300 | continue; | ||
1301 | } | ||
1302 | mb_set_bit_atomic(lock, cur, bm); | ||
1303 | cur++; | ||
1304 | } | ||
1305 | } | ||
1306 | |||
1307 | static int mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, | ||
1308 | int first, int count) | ||
1309 | { | ||
1310 | int block = 0; | ||
1311 | int max = 0; | ||
1312 | int order; | ||
1313 | void *buddy; | ||
1314 | void *buddy2; | ||
1315 | struct super_block *sb = e4b->bd_sb; | ||
1316 | |||
1317 | BUG_ON(first + count > (sb->s_blocksize << 3)); | ||
1318 | BUG_ON(!ext4_is_group_locked(sb, e4b->bd_group)); | ||
1319 | mb_check_buddy(e4b); | ||
1320 | mb_free_blocks_double(inode, e4b, first, count); | ||
1321 | |||
1322 | e4b->bd_info->bb_free += count; | ||
1323 | if (first < e4b->bd_info->bb_first_free) | ||
1324 | e4b->bd_info->bb_first_free = first; | ||
1325 | |||
1326 | /* let's maintain fragments counter */ | ||
1327 | if (first != 0) | ||
1328 | block = !mb_test_bit(first - 1, EXT4_MB_BITMAP(e4b)); | ||
1329 | if (first + count < EXT4_SB(sb)->s_mb_maxs[0]) | ||
1330 | max = !mb_test_bit(first + count, EXT4_MB_BITMAP(e4b)); | ||
1331 | if (block && max) | ||
1332 | e4b->bd_info->bb_fragments--; | ||
1333 | else if (!block && !max) | ||
1334 | e4b->bd_info->bb_fragments++; | ||
1335 | |||
1336 | /* let's maintain buddy itself */ | ||
1337 | while (count-- > 0) { | ||
1338 | block = first++; | ||
1339 | order = 0; | ||
1340 | |||
1341 | if (!mb_test_bit(block, EXT4_MB_BITMAP(e4b))) { | ||
1342 | ext4_fsblk_t blocknr; | ||
1343 | blocknr = e4b->bd_group * EXT4_BLOCKS_PER_GROUP(sb); | ||
1344 | blocknr += block; | ||
1345 | blocknr += | ||
1346 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); | ||
1347 | |||
1348 | ext4_error(sb, __FUNCTION__, "double-free of inode" | ||
1349 | " %lu's block %llu(bit %u in group %lu)\n", | ||
1350 | inode ? inode->i_ino : 0, blocknr, block, | ||
1351 | e4b->bd_group); | ||
1352 | } | ||
1353 | mb_clear_bit(block, EXT4_MB_BITMAP(e4b)); | ||
1354 | e4b->bd_info->bb_counters[order]++; | ||
1355 | |||
1356 | /* start of the buddy */ | ||
1357 | buddy = mb_find_buddy(e4b, order, &max); | ||
1358 | |||
1359 | do { | ||
1360 | block &= ~1UL; | ||
1361 | if (mb_test_bit(block, buddy) || | ||
1362 | mb_test_bit(block + 1, buddy)) | ||
1363 | break; | ||
1364 | |||
1365 | /* both the buddies are free, try to coalesce them */ | ||
1366 | buddy2 = mb_find_buddy(e4b, order + 1, &max); | ||
1367 | |||
1368 | if (!buddy2) | ||
1369 | break; | ||
1370 | |||
1371 | if (order > 0) { | ||
1372 | /* for special purposes, we don't set | ||
1373 | * free bits in bitmap */ | ||
1374 | mb_set_bit(block, buddy); | ||
1375 | mb_set_bit(block + 1, buddy); | ||
1376 | } | ||
1377 | e4b->bd_info->bb_counters[order]--; | ||
1378 | e4b->bd_info->bb_counters[order]--; | ||
1379 | |||
1380 | block = block >> 1; | ||
1381 | order++; | ||
1382 | e4b->bd_info->bb_counters[order]++; | ||
1383 | |||
1384 | mb_clear_bit(block, buddy2); | ||
1385 | buddy = buddy2; | ||
1386 | } while (1); | ||
1387 | } | ||
1388 | mb_check_buddy(e4b); | ||
1389 | |||
1390 | return 0; | ||
1391 | } | ||
1392 | |||
1393 | static int mb_find_extent(struct ext4_buddy *e4b, int order, int block, | ||
1394 | int needed, struct ext4_free_extent *ex) | ||
1395 | { | ||
1396 | int next = block; | ||
1397 | int max; | ||
1398 | int ord; | ||
1399 | void *buddy; | ||
1400 | |||
1401 | BUG_ON(!ext4_is_group_locked(e4b->bd_sb, e4b->bd_group)); | ||
1402 | BUG_ON(ex == NULL); | ||
1403 | |||
1404 | buddy = mb_find_buddy(e4b, order, &max); | ||
1405 | BUG_ON(buddy == NULL); | ||
1406 | BUG_ON(block >= max); | ||
1407 | if (mb_test_bit(block, buddy)) { | ||
1408 | ex->fe_len = 0; | ||
1409 | ex->fe_start = 0; | ||
1410 | ex->fe_group = 0; | ||
1411 | return 0; | ||
1412 | } | ||
1413 | |||
1414 | /* FIXME dorp order completely ? */ | ||
1415 | if (likely(order == 0)) { | ||
1416 | /* find actual order */ | ||
1417 | order = mb_find_order_for_block(e4b, block); | ||
1418 | block = block >> order; | ||
1419 | } | ||
1420 | |||
1421 | ex->fe_len = 1 << order; | ||
1422 | ex->fe_start = block << order; | ||
1423 | ex->fe_group = e4b->bd_group; | ||
1424 | |||
1425 | /* calc difference from given start */ | ||
1426 | next = next - ex->fe_start; | ||
1427 | ex->fe_len -= next; | ||
1428 | ex->fe_start += next; | ||
1429 | |||
1430 | while (needed > ex->fe_len && | ||
1431 | (buddy = mb_find_buddy(e4b, order, &max))) { | ||
1432 | |||
1433 | if (block + 1 >= max) | ||
1434 | break; | ||
1435 | |||
1436 | next = (block + 1) * (1 << order); | ||
1437 | if (mb_test_bit(next, EXT4_MB_BITMAP(e4b))) | ||
1438 | break; | ||
1439 | |||
1440 | ord = mb_find_order_for_block(e4b, next); | ||
1441 | |||
1442 | order = ord; | ||
1443 | block = next >> order; | ||
1444 | ex->fe_len += 1 << order; | ||
1445 | } | ||
1446 | |||
1447 | BUG_ON(ex->fe_start + ex->fe_len > (1 << (e4b->bd_blkbits + 3))); | ||
1448 | return ex->fe_len; | ||
1449 | } | ||
1450 | |||
1451 | static int mb_mark_used(struct ext4_buddy *e4b, struct ext4_free_extent *ex) | ||
1452 | { | ||
1453 | int ord; | ||
1454 | int mlen = 0; | ||
1455 | int max = 0; | ||
1456 | int cur; | ||
1457 | int start = ex->fe_start; | ||
1458 | int len = ex->fe_len; | ||
1459 | unsigned ret = 0; | ||
1460 | int len0 = len; | ||
1461 | void *buddy; | ||
1462 | |||
1463 | BUG_ON(start + len > (e4b->bd_sb->s_blocksize << 3)); | ||
1464 | BUG_ON(e4b->bd_group != ex->fe_group); | ||
1465 | BUG_ON(!ext4_is_group_locked(e4b->bd_sb, e4b->bd_group)); | ||
1466 | mb_check_buddy(e4b); | ||
1467 | mb_mark_used_double(e4b, start, len); | ||
1468 | |||
1469 | e4b->bd_info->bb_free -= len; | ||
1470 | if (e4b->bd_info->bb_first_free == start) | ||
1471 | e4b->bd_info->bb_first_free += len; | ||
1472 | |||
1473 | /* let's maintain fragments counter */ | ||
1474 | if (start != 0) | ||
1475 | mlen = !mb_test_bit(start - 1, EXT4_MB_BITMAP(e4b)); | ||
1476 | if (start + len < EXT4_SB(e4b->bd_sb)->s_mb_maxs[0]) | ||
1477 | max = !mb_test_bit(start + len, EXT4_MB_BITMAP(e4b)); | ||
1478 | if (mlen && max) | ||
1479 | e4b->bd_info->bb_fragments++; | ||
1480 | else if (!mlen && !max) | ||
1481 | e4b->bd_info->bb_fragments--; | ||
1482 | |||
1483 | /* let's maintain buddy itself */ | ||
1484 | while (len) { | ||
1485 | ord = mb_find_order_for_block(e4b, start); | ||
1486 | |||
1487 | if (((start >> ord) << ord) == start && len >= (1 << ord)) { | ||
1488 | /* the whole chunk may be allocated at once! */ | ||
1489 | mlen = 1 << ord; | ||
1490 | buddy = mb_find_buddy(e4b, ord, &max); | ||
1491 | BUG_ON((start >> ord) >= max); | ||
1492 | mb_set_bit(start >> ord, buddy); | ||
1493 | e4b->bd_info->bb_counters[ord]--; | ||
1494 | start += mlen; | ||
1495 | len -= mlen; | ||
1496 | BUG_ON(len < 0); | ||
1497 | continue; | ||
1498 | } | ||
1499 | |||
1500 | /* store for history */ | ||
1501 | if (ret == 0) | ||
1502 | ret = len | (ord << 16); | ||
1503 | |||
1504 | /* we have to split large buddy */ | ||
1505 | BUG_ON(ord <= 0); | ||
1506 | buddy = mb_find_buddy(e4b, ord, &max); | ||
1507 | mb_set_bit(start >> ord, buddy); | ||
1508 | e4b->bd_info->bb_counters[ord]--; | ||
1509 | |||
1510 | ord--; | ||
1511 | cur = (start >> ord) & ~1U; | ||
1512 | buddy = mb_find_buddy(e4b, ord, &max); | ||
1513 | mb_clear_bit(cur, buddy); | ||
1514 | mb_clear_bit(cur + 1, buddy); | ||
1515 | e4b->bd_info->bb_counters[ord]++; | ||
1516 | e4b->bd_info->bb_counters[ord]++; | ||
1517 | } | ||
1518 | |||
1519 | mb_set_bits(sb_bgl_lock(EXT4_SB(e4b->bd_sb), ex->fe_group), | ||
1520 | EXT4_MB_BITMAP(e4b), ex->fe_start, len0); | ||
1521 | mb_check_buddy(e4b); | ||
1522 | |||
1523 | return ret; | ||
1524 | } | ||
1525 | |||
1526 | /* | ||
1527 | * Must be called under group lock! | ||
1528 | */ | ||
1529 | static void ext4_mb_use_best_found(struct ext4_allocation_context *ac, | ||
1530 | struct ext4_buddy *e4b) | ||
1531 | { | ||
1532 | struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); | ||
1533 | int ret; | ||
1534 | |||
1535 | BUG_ON(ac->ac_b_ex.fe_group != e4b->bd_group); | ||
1536 | BUG_ON(ac->ac_status == AC_STATUS_FOUND); | ||
1537 | |||
1538 | ac->ac_b_ex.fe_len = min(ac->ac_b_ex.fe_len, ac->ac_g_ex.fe_len); | ||
1539 | ac->ac_b_ex.fe_logical = ac->ac_g_ex.fe_logical; | ||
1540 | ret = mb_mark_used(e4b, &ac->ac_b_ex); | ||
1541 | |||
1542 | /* preallocation can change ac_b_ex, thus we store actually | ||
1543 | * allocated blocks for history */ | ||
1544 | ac->ac_f_ex = ac->ac_b_ex; | ||
1545 | |||
1546 | ac->ac_status = AC_STATUS_FOUND; | ||
1547 | ac->ac_tail = ret & 0xffff; | ||
1548 | ac->ac_buddy = ret >> 16; | ||
1549 | |||
1550 | /* XXXXXXX: SUCH A HORRIBLE **CK */ | ||
1551 | /*FIXME!! Why ? */ | ||
1552 | ac->ac_bitmap_page = e4b->bd_bitmap_page; | ||
1553 | get_page(ac->ac_bitmap_page); | ||
1554 | ac->ac_buddy_page = e4b->bd_buddy_page; | ||
1555 | get_page(ac->ac_buddy_page); | ||
1556 | |||
1557 | /* store last allocated for subsequent stream allocation */ | ||
1558 | if ((ac->ac_flags & EXT4_MB_HINT_DATA)) { | ||
1559 | spin_lock(&sbi->s_md_lock); | ||
1560 | sbi->s_mb_last_group = ac->ac_f_ex.fe_group; | ||
1561 | sbi->s_mb_last_start = ac->ac_f_ex.fe_start; | ||
1562 | spin_unlock(&sbi->s_md_lock); | ||
1563 | } | ||
1564 | } | ||
1565 | |||
1566 | /* | ||
1567 | * regular allocator, for general purposes allocation | ||
1568 | */ | ||
1569 | |||
1570 | static void ext4_mb_check_limits(struct ext4_allocation_context *ac, | ||
1571 | struct ext4_buddy *e4b, | ||
1572 | int finish_group) | ||
1573 | { | ||
1574 | struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); | ||
1575 | struct ext4_free_extent *bex = &ac->ac_b_ex; | ||
1576 | struct ext4_free_extent *gex = &ac->ac_g_ex; | ||
1577 | struct ext4_free_extent ex; | ||
1578 | int max; | ||
1579 | |||
1580 | /* | ||
1581 | * We don't want to scan for a whole year | ||
1582 | */ | ||
1583 | if (ac->ac_found > sbi->s_mb_max_to_scan && | ||
1584 | !(ac->ac_flags & EXT4_MB_HINT_FIRST)) { | ||
1585 | ac->ac_status = AC_STATUS_BREAK; | ||
1586 | return; | ||
1587 | } | ||
1588 | |||
1589 | /* | ||
1590 | * Haven't found good chunk so far, let's continue | ||
1591 | */ | ||
1592 | if (bex->fe_len < gex->fe_len) | ||
1593 | return; | ||
1594 | |||
1595 | if ((finish_group || ac->ac_found > sbi->s_mb_min_to_scan) | ||
1596 | && bex->fe_group == e4b->bd_group) { | ||
1597 | /* recheck chunk's availability - we don't know | ||
1598 | * when it was found (within this lock-unlock | ||
1599 | * period or not) */ | ||
1600 | max = mb_find_extent(e4b, 0, bex->fe_start, gex->fe_len, &ex); | ||
1601 | if (max >= gex->fe_len) { | ||
1602 | ext4_mb_use_best_found(ac, e4b); | ||
1603 | return; | ||
1604 | } | ||
1605 | } | ||
1606 | } | ||
1607 | |||
1608 | /* | ||
1609 | * The routine checks whether found extent is good enough. If it is, | ||
1610 | * then the extent gets marked used and flag is set to the context | ||
1611 | * to stop scanning. Otherwise, the extent is compared with the | ||
1612 | * previous found extent and if new one is better, then it's stored | ||
1613 | * in the context. Later, the best found extent will be used, if | ||
1614 | * mballoc can't find good enough extent. | ||
1615 | * | ||
1616 | * FIXME: real allocation policy is to be designed yet! | ||
1617 | */ | ||
1618 | static void ext4_mb_measure_extent(struct ext4_allocation_context *ac, | ||
1619 | struct ext4_free_extent *ex, | ||
1620 | struct ext4_buddy *e4b) | ||
1621 | { | ||
1622 | struct ext4_free_extent *bex = &ac->ac_b_ex; | ||
1623 | struct ext4_free_extent *gex = &ac->ac_g_ex; | ||
1624 | |||
1625 | BUG_ON(ex->fe_len <= 0); | ||
1626 | BUG_ON(ex->fe_len >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); | ||
1627 | BUG_ON(ex->fe_start >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); | ||
1628 | BUG_ON(ac->ac_status != AC_STATUS_CONTINUE); | ||
1629 | |||
1630 | ac->ac_found++; | ||
1631 | |||
1632 | /* | ||
1633 | * The special case - take what you catch first | ||
1634 | */ | ||
1635 | if (unlikely(ac->ac_flags & EXT4_MB_HINT_FIRST)) { | ||
1636 | *bex = *ex; | ||
1637 | ext4_mb_use_best_found(ac, e4b); | ||
1638 | return; | ||
1639 | } | ||
1640 | |||
1641 | /* | ||
1642 | * Let's check whether the chuck is good enough | ||
1643 | */ | ||
1644 | if (ex->fe_len == gex->fe_len) { | ||
1645 | *bex = *ex; | ||
1646 | ext4_mb_use_best_found(ac, e4b); | ||
1647 | return; | ||
1648 | } | ||
1649 | |||
1650 | /* | ||
1651 | * If this is first found extent, just store it in the context | ||
1652 | */ | ||
1653 | if (bex->fe_len == 0) { | ||
1654 | *bex = *ex; | ||
1655 | return; | ||
1656 | } | ||
1657 | |||
1658 | /* | ||
1659 | * If new found extent is better, store it in the context | ||
1660 | */ | ||
1661 | if (bex->fe_len < gex->fe_len) { | ||
1662 | /* if the request isn't satisfied, any found extent | ||
1663 | * larger than previous best one is better */ | ||
1664 | if (ex->fe_len > bex->fe_len) | ||
1665 | *bex = *ex; | ||
1666 | } else if (ex->fe_len > gex->fe_len) { | ||
1667 | /* if the request is satisfied, then we try to find | ||
1668 | * an extent that still satisfy the request, but is | ||
1669 | * smaller than previous one */ | ||
1670 | if (ex->fe_len < bex->fe_len) | ||
1671 | *bex = *ex; | ||
1672 | } | ||
1673 | |||
1674 | ext4_mb_check_limits(ac, e4b, 0); | ||
1675 | } | ||
1676 | |||
1677 | static int ext4_mb_try_best_found(struct ext4_allocation_context *ac, | ||
1678 | struct ext4_buddy *e4b) | ||
1679 | { | ||
1680 | struct ext4_free_extent ex = ac->ac_b_ex; | ||
1681 | ext4_group_t group = ex.fe_group; | ||
1682 | int max; | ||
1683 | int err; | ||
1684 | |||
1685 | BUG_ON(ex.fe_len <= 0); | ||
1686 | err = ext4_mb_load_buddy(ac->ac_sb, group, e4b); | ||
1687 | if (err) | ||
1688 | return err; | ||
1689 | |||
1690 | ext4_lock_group(ac->ac_sb, group); | ||
1691 | max = mb_find_extent(e4b, 0, ex.fe_start, ex.fe_len, &ex); | ||
1692 | |||
1693 | if (max > 0) { | ||
1694 | ac->ac_b_ex = ex; | ||
1695 | ext4_mb_use_best_found(ac, e4b); | ||
1696 | } | ||
1697 | |||
1698 | ext4_unlock_group(ac->ac_sb, group); | ||
1699 | ext4_mb_release_desc(e4b); | ||
1700 | |||
1701 | return 0; | ||
1702 | } | ||
1703 | |||
1704 | static int ext4_mb_find_by_goal(struct ext4_allocation_context *ac, | ||
1705 | struct ext4_buddy *e4b) | ||
1706 | { | ||
1707 | ext4_group_t group = ac->ac_g_ex.fe_group; | ||
1708 | int max; | ||
1709 | int err; | ||
1710 | struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); | ||
1711 | struct ext4_super_block *es = sbi->s_es; | ||
1712 | struct ext4_free_extent ex; | ||
1713 | |||
1714 | if (!(ac->ac_flags & EXT4_MB_HINT_TRY_GOAL)) | ||
1715 | return 0; | ||
1716 | |||
1717 | err = ext4_mb_load_buddy(ac->ac_sb, group, e4b); | ||
1718 | if (err) | ||
1719 | return err; | ||
1720 | |||
1721 | ext4_lock_group(ac->ac_sb, group); | ||
1722 | max = mb_find_extent(e4b, 0, ac->ac_g_ex.fe_start, | ||
1723 | ac->ac_g_ex.fe_len, &ex); | ||
1724 | |||
1725 | if (max >= ac->ac_g_ex.fe_len && ac->ac_g_ex.fe_len == sbi->s_stripe) { | ||
1726 | ext4_fsblk_t start; | ||
1727 | |||
1728 | start = (e4b->bd_group * EXT4_BLOCKS_PER_GROUP(ac->ac_sb)) + | ||
1729 | ex.fe_start + le32_to_cpu(es->s_first_data_block); | ||
1730 | /* use do_div to get remainder (would be 64-bit modulo) */ | ||
1731 | if (do_div(start, sbi->s_stripe) == 0) { | ||
1732 | ac->ac_found++; | ||
1733 | ac->ac_b_ex = ex; | ||
1734 | ext4_mb_use_best_found(ac, e4b); | ||
1735 | } | ||
1736 | } else if (max >= ac->ac_g_ex.fe_len) { | ||
1737 | BUG_ON(ex.fe_len <= 0); | ||
1738 | BUG_ON(ex.fe_group != ac->ac_g_ex.fe_group); | ||
1739 | BUG_ON(ex.fe_start != ac->ac_g_ex.fe_start); | ||
1740 | ac->ac_found++; | ||
1741 | ac->ac_b_ex = ex; | ||
1742 | ext4_mb_use_best_found(ac, e4b); | ||
1743 | } else if (max > 0 && (ac->ac_flags & EXT4_MB_HINT_MERGE)) { | ||
1744 | /* Sometimes, caller may want to merge even small | ||
1745 | * number of blocks to an existing extent */ | ||
1746 | BUG_ON(ex.fe_len <= 0); | ||
1747 | BUG_ON(ex.fe_group != ac->ac_g_ex.fe_group); | ||
1748 | BUG_ON(ex.fe_start != ac->ac_g_ex.fe_start); | ||
1749 | ac->ac_found++; | ||
1750 | ac->ac_b_ex = ex; | ||
1751 | ext4_mb_use_best_found(ac, e4b); | ||
1752 | } | ||
1753 | ext4_unlock_group(ac->ac_sb, group); | ||
1754 | ext4_mb_release_desc(e4b); | ||
1755 | |||
1756 | return 0; | ||
1757 | } | ||
1758 | |||
1759 | /* | ||
1760 | * The routine scans buddy structures (not bitmap!) from given order | ||
1761 | * to max order and tries to find big enough chunk to satisfy the req | ||
1762 | */ | ||
1763 | static void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac, | ||
1764 | struct ext4_buddy *e4b) | ||
1765 | { | ||
1766 | struct super_block *sb = ac->ac_sb; | ||
1767 | struct ext4_group_info *grp = e4b->bd_info; | ||
1768 | void *buddy; | ||
1769 | int i; | ||
1770 | int k; | ||
1771 | int max; | ||
1772 | |||
1773 | BUG_ON(ac->ac_2order <= 0); | ||
1774 | for (i = ac->ac_2order; i <= sb->s_blocksize_bits + 1; i++) { | ||
1775 | if (grp->bb_counters[i] == 0) | ||
1776 | continue; | ||
1777 | |||
1778 | buddy = mb_find_buddy(e4b, i, &max); | ||
1779 | BUG_ON(buddy == NULL); | ||
1780 | |||
1781 | k = ext4_find_next_zero_bit(buddy, max, 0); | ||
1782 | BUG_ON(k >= max); | ||
1783 | |||
1784 | ac->ac_found++; | ||
1785 | |||
1786 | ac->ac_b_ex.fe_len = 1 << i; | ||
1787 | ac->ac_b_ex.fe_start = k << i; | ||
1788 | ac->ac_b_ex.fe_group = e4b->bd_group; | ||
1789 | |||
1790 | ext4_mb_use_best_found(ac, e4b); | ||
1791 | |||
1792 | BUG_ON(ac->ac_b_ex.fe_len != ac->ac_g_ex.fe_len); | ||
1793 | |||
1794 | if (EXT4_SB(sb)->s_mb_stats) | ||
1795 | atomic_inc(&EXT4_SB(sb)->s_bal_2orders); | ||
1796 | |||
1797 | break; | ||
1798 | } | ||
1799 | } | ||
1800 | |||
1801 | /* | ||
1802 | * The routine scans the group and measures all found extents. | ||
1803 | * In order to optimize scanning, caller must pass number of | ||
1804 | * free blocks in the group, so the routine can know upper limit. | ||
1805 | */ | ||
1806 | static void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | ||
1807 | struct ext4_buddy *e4b) | ||
1808 | { | ||
1809 | struct super_block *sb = ac->ac_sb; | ||
1810 | void *bitmap = EXT4_MB_BITMAP(e4b); | ||
1811 | struct ext4_free_extent ex; | ||
1812 | int i; | ||
1813 | int free; | ||
1814 | |||
1815 | free = e4b->bd_info->bb_free; | ||
1816 | BUG_ON(free <= 0); | ||
1817 | |||
1818 | i = e4b->bd_info->bb_first_free; | ||
1819 | |||
1820 | while (free && ac->ac_status == AC_STATUS_CONTINUE) { | ||
1821 | i = ext4_find_next_zero_bit(bitmap, | ||
1822 | EXT4_BLOCKS_PER_GROUP(sb), i); | ||
1823 | if (i >= EXT4_BLOCKS_PER_GROUP(sb)) { | ||
1824 | BUG_ON(free != 0); | ||
1825 | break; | ||
1826 | } | ||
1827 | |||
1828 | mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex); | ||
1829 | BUG_ON(ex.fe_len <= 0); | ||
1830 | BUG_ON(free < ex.fe_len); | ||
1831 | |||
1832 | ext4_mb_measure_extent(ac, &ex, e4b); | ||
1833 | |||
1834 | i += ex.fe_len; | ||
1835 | free -= ex.fe_len; | ||
1836 | } | ||
1837 | |||
1838 | ext4_mb_check_limits(ac, e4b, 1); | ||
1839 | } | ||
1840 | |||
1841 | /* | ||
1842 | * This is a special case for storages like raid5 | ||
1843 | * we try to find stripe-aligned chunks for stripe-size requests | ||
1844 | * XXX should do so at least for multiples of stripe size as well | ||
1845 | */ | ||
1846 | static void ext4_mb_scan_aligned(struct ext4_allocation_context *ac, | ||
1847 | struct ext4_buddy *e4b) | ||
1848 | { | ||
1849 | struct super_block *sb = ac->ac_sb; | ||
1850 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
1851 | void *bitmap = EXT4_MB_BITMAP(e4b); | ||
1852 | struct ext4_free_extent ex; | ||
1853 | ext4_fsblk_t first_group_block; | ||
1854 | ext4_fsblk_t a; | ||
1855 | ext4_grpblk_t i; | ||
1856 | int max; | ||
1857 | |||
1858 | BUG_ON(sbi->s_stripe == 0); | ||
1859 | |||
1860 | /* find first stripe-aligned block in group */ | ||
1861 | first_group_block = e4b->bd_group * EXT4_BLOCKS_PER_GROUP(sb) | ||
1862 | + le32_to_cpu(sbi->s_es->s_first_data_block); | ||
1863 | a = first_group_block + sbi->s_stripe - 1; | ||
1864 | do_div(a, sbi->s_stripe); | ||
1865 | i = (a * sbi->s_stripe) - first_group_block; | ||
1866 | |||
1867 | while (i < EXT4_BLOCKS_PER_GROUP(sb)) { | ||
1868 | if (!mb_test_bit(i, bitmap)) { | ||
1869 | max = mb_find_extent(e4b, 0, i, sbi->s_stripe, &ex); | ||
1870 | if (max >= sbi->s_stripe) { | ||
1871 | ac->ac_found++; | ||
1872 | ac->ac_b_ex = ex; | ||
1873 | ext4_mb_use_best_found(ac, e4b); | ||
1874 | break; | ||
1875 | } | ||
1876 | } | ||
1877 | i += sbi->s_stripe; | ||
1878 | } | ||
1879 | } | ||
1880 | |||
1881 | static int ext4_mb_good_group(struct ext4_allocation_context *ac, | ||
1882 | ext4_group_t group, int cr) | ||
1883 | { | ||
1884 | unsigned free, fragments; | ||
1885 | unsigned i, bits; | ||
1886 | struct ext4_group_desc *desc; | ||
1887 | struct ext4_group_info *grp = ext4_get_group_info(ac->ac_sb, group); | ||
1888 | |||
1889 | BUG_ON(cr < 0 || cr >= 4); | ||
1890 | BUG_ON(EXT4_MB_GRP_NEED_INIT(grp)); | ||
1891 | |||
1892 | free = grp->bb_free; | ||
1893 | fragments = grp->bb_fragments; | ||
1894 | if (free == 0) | ||
1895 | return 0; | ||
1896 | if (fragments == 0) | ||
1897 | return 0; | ||
1898 | |||
1899 | switch (cr) { | ||
1900 | case 0: | ||
1901 | BUG_ON(ac->ac_2order == 0); | ||
1902 | /* If this group is uninitialized, skip it initially */ | ||
1903 | desc = ext4_get_group_desc(ac->ac_sb, group, NULL); | ||
1904 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) | ||
1905 | return 0; | ||
1906 | |||
1907 | bits = ac->ac_sb->s_blocksize_bits + 1; | ||
1908 | for (i = ac->ac_2order; i <= bits; i++) | ||
1909 | if (grp->bb_counters[i] > 0) | ||
1910 | return 1; | ||
1911 | break; | ||
1912 | case 1: | ||
1913 | if ((free / fragments) >= ac->ac_g_ex.fe_len) | ||
1914 | return 1; | ||
1915 | break; | ||
1916 | case 2: | ||
1917 | if (free >= ac->ac_g_ex.fe_len) | ||
1918 | return 1; | ||
1919 | break; | ||
1920 | case 3: | ||
1921 | return 1; | ||
1922 | default: | ||
1923 | BUG(); | ||
1924 | } | ||
1925 | |||
1926 | return 0; | ||
1927 | } | ||
1928 | |||
1929 | static int ext4_mb_regular_allocator(struct ext4_allocation_context *ac) | ||
1930 | { | ||
1931 | ext4_group_t group; | ||
1932 | ext4_group_t i; | ||
1933 | int cr; | ||
1934 | int err = 0; | ||
1935 | int bsbits; | ||
1936 | struct ext4_sb_info *sbi; | ||
1937 | struct super_block *sb; | ||
1938 | struct ext4_buddy e4b; | ||
1939 | loff_t size, isize; | ||
1940 | |||
1941 | sb = ac->ac_sb; | ||
1942 | sbi = EXT4_SB(sb); | ||
1943 | BUG_ON(ac->ac_status == AC_STATUS_FOUND); | ||
1944 | |||
1945 | /* first, try the goal */ | ||
1946 | err = ext4_mb_find_by_goal(ac, &e4b); | ||
1947 | if (err || ac->ac_status == AC_STATUS_FOUND) | ||
1948 | goto out; | ||
1949 | |||
1950 | if (unlikely(ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY)) | ||
1951 | goto out; | ||
1952 | |||
1953 | /* | ||
1954 | * ac->ac2_order is set only if the fe_len is a power of 2 | ||
1955 | * if ac2_order is set we also set criteria to 0 so that we | ||
1956 | * try exact allocation using buddy. | ||
1957 | */ | ||
1958 | i = fls(ac->ac_g_ex.fe_len); | ||
1959 | ac->ac_2order = 0; | ||
1960 | /* | ||
1961 | * We search using buddy data only if the order of the request | ||
1962 | * is greater than equal to the sbi_s_mb_order2_reqs | ||
1963 | * You can tune it via /proc/fs/ext4/<partition>/order2_req | ||
1964 | */ | ||
1965 | if (i >= sbi->s_mb_order2_reqs) { | ||
1966 | /* | ||
1967 | * This should tell if fe_len is exactly power of 2 | ||
1968 | */ | ||
1969 | if ((ac->ac_g_ex.fe_len & (~(1 << (i - 1)))) == 0) | ||
1970 | ac->ac_2order = i - 1; | ||
1971 | } | ||
1972 | |||
1973 | bsbits = ac->ac_sb->s_blocksize_bits; | ||
1974 | /* if stream allocation is enabled, use global goal */ | ||
1975 | size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len; | ||
1976 | isize = i_size_read(ac->ac_inode) >> bsbits; | ||
1977 | if (size < isize) | ||
1978 | size = isize; | ||
1979 | |||
1980 | if (size < sbi->s_mb_stream_request && | ||
1981 | (ac->ac_flags & EXT4_MB_HINT_DATA)) { | ||
1982 | /* TBD: may be hot point */ | ||
1983 | spin_lock(&sbi->s_md_lock); | ||
1984 | ac->ac_g_ex.fe_group = sbi->s_mb_last_group; | ||
1985 | ac->ac_g_ex.fe_start = sbi->s_mb_last_start; | ||
1986 | spin_unlock(&sbi->s_md_lock); | ||
1987 | } | ||
1988 | |||
1989 | /* searching for the right group start from the goal value specified */ | ||
1990 | group = ac->ac_g_ex.fe_group; | ||
1991 | |||
1992 | /* Let's just scan groups to find more-less suitable blocks */ | ||
1993 | cr = ac->ac_2order ? 0 : 1; | ||
1994 | /* | ||
1995 | * cr == 0 try to get exact allocation, | ||
1996 | * cr == 3 try to get anything | ||
1997 | */ | ||
1998 | repeat: | ||
1999 | for (; cr < 4 && ac->ac_status == AC_STATUS_CONTINUE; cr++) { | ||
2000 | ac->ac_criteria = cr; | ||
2001 | for (i = 0; i < EXT4_SB(sb)->s_groups_count; group++, i++) { | ||
2002 | struct ext4_group_info *grp; | ||
2003 | struct ext4_group_desc *desc; | ||
2004 | |||
2005 | if (group == EXT4_SB(sb)->s_groups_count) | ||
2006 | group = 0; | ||
2007 | |||
2008 | /* quick check to skip empty groups */ | ||
2009 | grp = ext4_get_group_info(ac->ac_sb, group); | ||
2010 | if (grp->bb_free == 0) | ||
2011 | continue; | ||
2012 | |||
2013 | /* | ||
2014 | * if the group is already init we check whether it is | ||
2015 | * a good group and if not we don't load the buddy | ||
2016 | */ | ||
2017 | if (EXT4_MB_GRP_NEED_INIT(grp)) { | ||
2018 | /* | ||
2019 | * we need full data about the group | ||
2020 | * to make a good selection | ||
2021 | */ | ||
2022 | err = ext4_mb_load_buddy(sb, group, &e4b); | ||
2023 | if (err) | ||
2024 | goto out; | ||
2025 | ext4_mb_release_desc(&e4b); | ||
2026 | } | ||
2027 | |||
2028 | /* | ||
2029 | * If the particular group doesn't satisfy our | ||
2030 | * criteria we continue with the next group | ||
2031 | */ | ||
2032 | if (!ext4_mb_good_group(ac, group, cr)) | ||
2033 | continue; | ||
2034 | |||
2035 | err = ext4_mb_load_buddy(sb, group, &e4b); | ||
2036 | if (err) | ||
2037 | goto out; | ||
2038 | |||
2039 | ext4_lock_group(sb, group); | ||
2040 | if (!ext4_mb_good_group(ac, group, cr)) { | ||
2041 | /* someone did allocation from this group */ | ||
2042 | ext4_unlock_group(sb, group); | ||
2043 | ext4_mb_release_desc(&e4b); | ||
2044 | continue; | ||
2045 | } | ||
2046 | |||
2047 | ac->ac_groups_scanned++; | ||
2048 | desc = ext4_get_group_desc(sb, group, NULL); | ||
2049 | if (cr == 0 || (desc->bg_flags & | ||
2050 | cpu_to_le16(EXT4_BG_BLOCK_UNINIT) && | ||
2051 | ac->ac_2order != 0)) | ||
2052 | ext4_mb_simple_scan_group(ac, &e4b); | ||
2053 | else if (cr == 1 && | ||
2054 | ac->ac_g_ex.fe_len == sbi->s_stripe) | ||
2055 | ext4_mb_scan_aligned(ac, &e4b); | ||
2056 | else | ||
2057 | ext4_mb_complex_scan_group(ac, &e4b); | ||
2058 | |||
2059 | ext4_unlock_group(sb, group); | ||
2060 | ext4_mb_release_desc(&e4b); | ||
2061 | |||
2062 | if (ac->ac_status != AC_STATUS_CONTINUE) | ||
2063 | break; | ||
2064 | } | ||
2065 | } | ||
2066 | |||
2067 | if (ac->ac_b_ex.fe_len > 0 && ac->ac_status != AC_STATUS_FOUND && | ||
2068 | !(ac->ac_flags & EXT4_MB_HINT_FIRST)) { | ||
2069 | /* | ||
2070 | * We've been searching too long. Let's try to allocate | ||
2071 | * the best chunk we've found so far | ||
2072 | */ | ||
2073 | |||
2074 | ext4_mb_try_best_found(ac, &e4b); | ||
2075 | if (ac->ac_status != AC_STATUS_FOUND) { | ||
2076 | /* | ||
2077 | * Someone more lucky has already allocated it. | ||
2078 | * The only thing we can do is just take first | ||
2079 | * found block(s) | ||
2080 | printk(KERN_DEBUG "EXT4-fs: someone won our chunk\n"); | ||
2081 | */ | ||
2082 | ac->ac_b_ex.fe_group = 0; | ||
2083 | ac->ac_b_ex.fe_start = 0; | ||
2084 | ac->ac_b_ex.fe_len = 0; | ||
2085 | ac->ac_status = AC_STATUS_CONTINUE; | ||
2086 | ac->ac_flags |= EXT4_MB_HINT_FIRST; | ||
2087 | cr = 3; | ||
2088 | atomic_inc(&sbi->s_mb_lost_chunks); | ||
2089 | goto repeat; | ||
2090 | } | ||
2091 | } | ||
2092 | out: | ||
2093 | return err; | ||
2094 | } | ||
2095 | |||
2096 | #ifdef EXT4_MB_HISTORY | ||
2097 | struct ext4_mb_proc_session { | ||
2098 | struct ext4_mb_history *history; | ||
2099 | struct super_block *sb; | ||
2100 | int start; | ||
2101 | int max; | ||
2102 | }; | ||
2103 | |||
2104 | static void *ext4_mb_history_skip_empty(struct ext4_mb_proc_session *s, | ||
2105 | struct ext4_mb_history *hs, | ||
2106 | int first) | ||
2107 | { | ||
2108 | if (hs == s->history + s->max) | ||
2109 | hs = s->history; | ||
2110 | if (!first && hs == s->history + s->start) | ||
2111 | return NULL; | ||
2112 | while (hs->orig.fe_len == 0) { | ||
2113 | hs++; | ||
2114 | if (hs == s->history + s->max) | ||
2115 | hs = s->history; | ||
2116 | if (hs == s->history + s->start) | ||
2117 | return NULL; | ||
2118 | } | ||
2119 | return hs; | ||
2120 | } | ||
2121 | |||
2122 | static void *ext4_mb_seq_history_start(struct seq_file *seq, loff_t *pos) | ||
2123 | { | ||
2124 | struct ext4_mb_proc_session *s = seq->private; | ||
2125 | struct ext4_mb_history *hs; | ||
2126 | int l = *pos; | ||
2127 | |||
2128 | if (l == 0) | ||
2129 | return SEQ_START_TOKEN; | ||
2130 | hs = ext4_mb_history_skip_empty(s, s->history + s->start, 1); | ||
2131 | if (!hs) | ||
2132 | return NULL; | ||
2133 | while (--l && (hs = ext4_mb_history_skip_empty(s, ++hs, 0)) != NULL); | ||
2134 | return hs; | ||
2135 | } | ||
2136 | |||
2137 | static void *ext4_mb_seq_history_next(struct seq_file *seq, void *v, | ||
2138 | loff_t *pos) | ||
2139 | { | ||
2140 | struct ext4_mb_proc_session *s = seq->private; | ||
2141 | struct ext4_mb_history *hs = v; | ||
2142 | |||
2143 | ++*pos; | ||
2144 | if (v == SEQ_START_TOKEN) | ||
2145 | return ext4_mb_history_skip_empty(s, s->history + s->start, 1); | ||
2146 | else | ||
2147 | return ext4_mb_history_skip_empty(s, ++hs, 0); | ||
2148 | } | ||
2149 | |||
2150 | static int ext4_mb_seq_history_show(struct seq_file *seq, void *v) | ||
2151 | { | ||
2152 | char buf[25], buf2[25], buf3[25], *fmt; | ||
2153 | struct ext4_mb_history *hs = v; | ||
2154 | |||
2155 | if (v == SEQ_START_TOKEN) { | ||
2156 | seq_printf(seq, "%-5s %-8s %-23s %-23s %-23s %-5s " | ||
2157 | "%-5s %-2s %-5s %-5s %-5s %-6s\n", | ||
2158 | "pid", "inode", "original", "goal", "result", "found", | ||
2159 | "grps", "cr", "flags", "merge", "tail", "broken"); | ||
2160 | return 0; | ||
2161 | } | ||
2162 | |||
2163 | if (hs->op == EXT4_MB_HISTORY_ALLOC) { | ||
2164 | fmt = "%-5u %-8u %-23s %-23s %-23s %-5u %-5u %-2u " | ||
2165 | "%-5u %-5s %-5u %-6u\n"; | ||
2166 | sprintf(buf2, "%lu/%d/%u@%u", hs->result.fe_group, | ||
2167 | hs->result.fe_start, hs->result.fe_len, | ||
2168 | hs->result.fe_logical); | ||
2169 | sprintf(buf, "%lu/%d/%u@%u", hs->orig.fe_group, | ||
2170 | hs->orig.fe_start, hs->orig.fe_len, | ||
2171 | hs->orig.fe_logical); | ||
2172 | sprintf(buf3, "%lu/%d/%u@%u", hs->goal.fe_group, | ||
2173 | hs->goal.fe_start, hs->goal.fe_len, | ||
2174 | hs->goal.fe_logical); | ||
2175 | seq_printf(seq, fmt, hs->pid, hs->ino, buf, buf3, buf2, | ||
2176 | hs->found, hs->groups, hs->cr, hs->flags, | ||
2177 | hs->merged ? "M" : "", hs->tail, | ||
2178 | hs->buddy ? 1 << hs->buddy : 0); | ||
2179 | } else if (hs->op == EXT4_MB_HISTORY_PREALLOC) { | ||
2180 | fmt = "%-5u %-8u %-23s %-23s %-23s\n"; | ||
2181 | sprintf(buf2, "%lu/%d/%u@%u", hs->result.fe_group, | ||
2182 | hs->result.fe_start, hs->result.fe_len, | ||
2183 | hs->result.fe_logical); | ||
2184 | sprintf(buf, "%lu/%d/%u@%u", hs->orig.fe_group, | ||
2185 | hs->orig.fe_start, hs->orig.fe_len, | ||
2186 | hs->orig.fe_logical); | ||
2187 | seq_printf(seq, fmt, hs->pid, hs->ino, buf, "", buf2); | ||
2188 | } else if (hs->op == EXT4_MB_HISTORY_DISCARD) { | ||
2189 | sprintf(buf2, "%lu/%d/%u", hs->result.fe_group, | ||
2190 | hs->result.fe_start, hs->result.fe_len); | ||
2191 | seq_printf(seq, "%-5u %-8u %-23s discard\n", | ||
2192 | hs->pid, hs->ino, buf2); | ||
2193 | } else if (hs->op == EXT4_MB_HISTORY_FREE) { | ||
2194 | sprintf(buf2, "%lu/%d/%u", hs->result.fe_group, | ||
2195 | hs->result.fe_start, hs->result.fe_len); | ||
2196 | seq_printf(seq, "%-5u %-8u %-23s free\n", | ||
2197 | hs->pid, hs->ino, buf2); | ||
2198 | } | ||
2199 | return 0; | ||
2200 | } | ||
2201 | |||
2202 | static void ext4_mb_seq_history_stop(struct seq_file *seq, void *v) | ||
2203 | { | ||
2204 | } | ||
2205 | |||
2206 | static struct seq_operations ext4_mb_seq_history_ops = { | ||
2207 | .start = ext4_mb_seq_history_start, | ||
2208 | .next = ext4_mb_seq_history_next, | ||
2209 | .stop = ext4_mb_seq_history_stop, | ||
2210 | .show = ext4_mb_seq_history_show, | ||
2211 | }; | ||
2212 | |||
2213 | static int ext4_mb_seq_history_open(struct inode *inode, struct file *file) | ||
2214 | { | ||
2215 | struct super_block *sb = PDE(inode)->data; | ||
2216 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
2217 | struct ext4_mb_proc_session *s; | ||
2218 | int rc; | ||
2219 | int size; | ||
2220 | |||
2221 | s = kmalloc(sizeof(*s), GFP_KERNEL); | ||
2222 | if (s == NULL) | ||
2223 | return -ENOMEM; | ||
2224 | s->sb = sb; | ||
2225 | size = sizeof(struct ext4_mb_history) * sbi->s_mb_history_max; | ||
2226 | s->history = kmalloc(size, GFP_KERNEL); | ||
2227 | if (s->history == NULL) { | ||
2228 | kfree(s); | ||
2229 | return -ENOMEM; | ||
2230 | } | ||
2231 | |||
2232 | spin_lock(&sbi->s_mb_history_lock); | ||
2233 | memcpy(s->history, sbi->s_mb_history, size); | ||
2234 | s->max = sbi->s_mb_history_max; | ||
2235 | s->start = sbi->s_mb_history_cur % s->max; | ||
2236 | spin_unlock(&sbi->s_mb_history_lock); | ||
2237 | |||
2238 | rc = seq_open(file, &ext4_mb_seq_history_ops); | ||
2239 | if (rc == 0) { | ||
2240 | struct seq_file *m = (struct seq_file *)file->private_data; | ||
2241 | m->private = s; | ||
2242 | } else { | ||
2243 | kfree(s->history); | ||
2244 | kfree(s); | ||
2245 | } | ||
2246 | return rc; | ||
2247 | |||
2248 | } | ||
2249 | |||
2250 | static int ext4_mb_seq_history_release(struct inode *inode, struct file *file) | ||
2251 | { | ||
2252 | struct seq_file *seq = (struct seq_file *)file->private_data; | ||
2253 | struct ext4_mb_proc_session *s = seq->private; | ||
2254 | kfree(s->history); | ||
2255 | kfree(s); | ||
2256 | return seq_release(inode, file); | ||
2257 | } | ||
2258 | |||
2259 | static ssize_t ext4_mb_seq_history_write(struct file *file, | ||
2260 | const char __user *buffer, | ||
2261 | size_t count, loff_t *ppos) | ||
2262 | { | ||
2263 | struct seq_file *seq = (struct seq_file *)file->private_data; | ||
2264 | struct ext4_mb_proc_session *s = seq->private; | ||
2265 | struct super_block *sb = s->sb; | ||
2266 | char str[32]; | ||
2267 | int value; | ||
2268 | |||
2269 | if (count >= sizeof(str)) { | ||
2270 | printk(KERN_ERR "EXT4-fs: %s string too long, max %u bytes\n", | ||
2271 | "mb_history", (int)sizeof(str)); | ||
2272 | return -EOVERFLOW; | ||
2273 | } | ||
2274 | |||
2275 | if (copy_from_user(str, buffer, count)) | ||
2276 | return -EFAULT; | ||
2277 | |||
2278 | value = simple_strtol(str, NULL, 0); | ||
2279 | if (value < 0) | ||
2280 | return -ERANGE; | ||
2281 | EXT4_SB(sb)->s_mb_history_filter = value; | ||
2282 | |||
2283 | return count; | ||
2284 | } | ||
2285 | |||
2286 | static struct file_operations ext4_mb_seq_history_fops = { | ||
2287 | .owner = THIS_MODULE, | ||
2288 | .open = ext4_mb_seq_history_open, | ||
2289 | .read = seq_read, | ||
2290 | .write = ext4_mb_seq_history_write, | ||
2291 | .llseek = seq_lseek, | ||
2292 | .release = ext4_mb_seq_history_release, | ||
2293 | }; | ||
2294 | |||
2295 | static void *ext4_mb_seq_groups_start(struct seq_file *seq, loff_t *pos) | ||
2296 | { | ||
2297 | struct super_block *sb = seq->private; | ||
2298 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
2299 | ext4_group_t group; | ||
2300 | |||
2301 | if (*pos < 0 || *pos >= sbi->s_groups_count) | ||
2302 | return NULL; | ||
2303 | |||
2304 | group = *pos + 1; | ||
2305 | return (void *) group; | ||
2306 | } | ||
2307 | |||
2308 | static void *ext4_mb_seq_groups_next(struct seq_file *seq, void *v, loff_t *pos) | ||
2309 | { | ||
2310 | struct super_block *sb = seq->private; | ||
2311 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
2312 | ext4_group_t group; | ||
2313 | |||
2314 | ++*pos; | ||
2315 | if (*pos < 0 || *pos >= sbi->s_groups_count) | ||
2316 | return NULL; | ||
2317 | group = *pos + 1; | ||
2318 | return (void *) group;; | ||
2319 | } | ||
2320 | |||
2321 | static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v) | ||
2322 | { | ||
2323 | struct super_block *sb = seq->private; | ||
2324 | long group = (long) v; | ||
2325 | int i; | ||
2326 | int err; | ||
2327 | struct ext4_buddy e4b; | ||
2328 | struct sg { | ||
2329 | struct ext4_group_info info; | ||
2330 | unsigned short counters[16]; | ||
2331 | } sg; | ||
2332 | |||
2333 | group--; | ||
2334 | if (group == 0) | ||
2335 | seq_printf(seq, "#%-5s: %-5s %-5s %-5s " | ||
2336 | "[ %-5s %-5s %-5s %-5s %-5s %-5s %-5s " | ||
2337 | "%-5s %-5s %-5s %-5s %-5s %-5s %-5s ]\n", | ||
2338 | "group", "free", "frags", "first", | ||
2339 | "2^0", "2^1", "2^2", "2^3", "2^4", "2^5", "2^6", | ||
2340 | "2^7", "2^8", "2^9", "2^10", "2^11", "2^12", "2^13"); | ||
2341 | |||
2342 | i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) + | ||
2343 | sizeof(struct ext4_group_info); | ||
2344 | err = ext4_mb_load_buddy(sb, group, &e4b); | ||
2345 | if (err) { | ||
2346 | seq_printf(seq, "#%-5lu: I/O error\n", group); | ||
2347 | return 0; | ||
2348 | } | ||
2349 | ext4_lock_group(sb, group); | ||
2350 | memcpy(&sg, ext4_get_group_info(sb, group), i); | ||
2351 | ext4_unlock_group(sb, group); | ||
2352 | ext4_mb_release_desc(&e4b); | ||
2353 | |||
2354 | seq_printf(seq, "#%-5lu: %-5u %-5u %-5u [", group, sg.info.bb_free, | ||
2355 | sg.info.bb_fragments, sg.info.bb_first_free); | ||
2356 | for (i = 0; i <= 13; i++) | ||
2357 | seq_printf(seq, " %-5u", i <= sb->s_blocksize_bits + 1 ? | ||
2358 | sg.info.bb_counters[i] : 0); | ||
2359 | seq_printf(seq, " ]\n"); | ||
2360 | |||
2361 | return 0; | ||
2362 | } | ||
2363 | |||
2364 | static void ext4_mb_seq_groups_stop(struct seq_file *seq, void *v) | ||
2365 | { | ||
2366 | } | ||
2367 | |||
2368 | static struct seq_operations ext4_mb_seq_groups_ops = { | ||
2369 | .start = ext4_mb_seq_groups_start, | ||
2370 | .next = ext4_mb_seq_groups_next, | ||
2371 | .stop = ext4_mb_seq_groups_stop, | ||
2372 | .show = ext4_mb_seq_groups_show, | ||
2373 | }; | ||
2374 | |||
2375 | static int ext4_mb_seq_groups_open(struct inode *inode, struct file *file) | ||
2376 | { | ||
2377 | struct super_block *sb = PDE(inode)->data; | ||
2378 | int rc; | ||
2379 | |||
2380 | rc = seq_open(file, &ext4_mb_seq_groups_ops); | ||
2381 | if (rc == 0) { | ||
2382 | struct seq_file *m = (struct seq_file *)file->private_data; | ||
2383 | m->private = sb; | ||
2384 | } | ||
2385 | return rc; | ||
2386 | |||
2387 | } | ||
2388 | |||
2389 | static struct file_operations ext4_mb_seq_groups_fops = { | ||
2390 | .owner = THIS_MODULE, | ||
2391 | .open = ext4_mb_seq_groups_open, | ||
2392 | .read = seq_read, | ||
2393 | .llseek = seq_lseek, | ||
2394 | .release = seq_release, | ||
2395 | }; | ||
2396 | |||
2397 | static void ext4_mb_history_release(struct super_block *sb) | ||
2398 | { | ||
2399 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
2400 | |||
2401 | remove_proc_entry("mb_groups", sbi->s_mb_proc); | ||
2402 | remove_proc_entry("mb_history", sbi->s_mb_proc); | ||
2403 | |||
2404 | kfree(sbi->s_mb_history); | ||
2405 | } | ||
2406 | |||
2407 | static void ext4_mb_history_init(struct super_block *sb) | ||
2408 | { | ||
2409 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
2410 | int i; | ||
2411 | |||
2412 | if (sbi->s_mb_proc != NULL) { | ||
2413 | struct proc_dir_entry *p; | ||
2414 | p = create_proc_entry("mb_history", S_IRUGO, sbi->s_mb_proc); | ||
2415 | if (p) { | ||
2416 | p->proc_fops = &ext4_mb_seq_history_fops; | ||
2417 | p->data = sb; | ||
2418 | } | ||
2419 | p = create_proc_entry("mb_groups", S_IRUGO, sbi->s_mb_proc); | ||
2420 | if (p) { | ||
2421 | p->proc_fops = &ext4_mb_seq_groups_fops; | ||
2422 | p->data = sb; | ||
2423 | } | ||
2424 | } | ||
2425 | |||
2426 | sbi->s_mb_history_max = 1000; | ||
2427 | sbi->s_mb_history_cur = 0; | ||
2428 | spin_lock_init(&sbi->s_mb_history_lock); | ||
2429 | i = sbi->s_mb_history_max * sizeof(struct ext4_mb_history); | ||
2430 | sbi->s_mb_history = kmalloc(i, GFP_KERNEL); | ||
2431 | if (likely(sbi->s_mb_history != NULL)) | ||
2432 | memset(sbi->s_mb_history, 0, i); | ||
2433 | /* if we can't allocate history, then we simple won't use it */ | ||
2434 | } | ||
2435 | |||
2436 | static void ext4_mb_store_history(struct ext4_allocation_context *ac) | ||
2437 | { | ||
2438 | struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); | ||
2439 | struct ext4_mb_history h; | ||
2440 | |||
2441 | if (unlikely(sbi->s_mb_history == NULL)) | ||
2442 | return; | ||
2443 | |||
2444 | if (!(ac->ac_op & sbi->s_mb_history_filter)) | ||
2445 | return; | ||
2446 | |||
2447 | h.op = ac->ac_op; | ||
2448 | h.pid = current->pid; | ||
2449 | h.ino = ac->ac_inode ? ac->ac_inode->i_ino : 0; | ||
2450 | h.orig = ac->ac_o_ex; | ||
2451 | h.result = ac->ac_b_ex; | ||
2452 | h.flags = ac->ac_flags; | ||
2453 | h.found = ac->ac_found; | ||
2454 | h.groups = ac->ac_groups_scanned; | ||
2455 | h.cr = ac->ac_criteria; | ||
2456 | h.tail = ac->ac_tail; | ||
2457 | h.buddy = ac->ac_buddy; | ||
2458 | h.merged = 0; | ||
2459 | if (ac->ac_op == EXT4_MB_HISTORY_ALLOC) { | ||
2460 | if (ac->ac_g_ex.fe_start == ac->ac_b_ex.fe_start && | ||
2461 | ac->ac_g_ex.fe_group == ac->ac_b_ex.fe_group) | ||
2462 | h.merged = 1; | ||
2463 | h.goal = ac->ac_g_ex; | ||
2464 | h.result = ac->ac_f_ex; | ||
2465 | } | ||
2466 | |||
2467 | spin_lock(&sbi->s_mb_history_lock); | ||
2468 | memcpy(sbi->s_mb_history + sbi->s_mb_history_cur, &h, sizeof(h)); | ||
2469 | if (++sbi->s_mb_history_cur >= sbi->s_mb_history_max) | ||
2470 | sbi->s_mb_history_cur = 0; | ||
2471 | spin_unlock(&sbi->s_mb_history_lock); | ||
2472 | } | ||
2473 | |||
2474 | #else | ||
2475 | #define ext4_mb_history_release(sb) | ||
2476 | #define ext4_mb_history_init(sb) | ||
2477 | #endif | ||
2478 | |||
2479 | static int ext4_mb_init_backend(struct super_block *sb) | ||
2480 | { | ||
2481 | ext4_group_t i; | ||
2482 | int j, len, metalen; | ||
2483 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
2484 | int num_meta_group_infos = | ||
2485 | (sbi->s_groups_count + EXT4_DESC_PER_BLOCK(sb) - 1) >> | ||
2486 | EXT4_DESC_PER_BLOCK_BITS(sb); | ||
2487 | struct ext4_group_info **meta_group_info; | ||
2488 | |||
2489 | /* An 8TB filesystem with 64-bit pointers requires a 4096 byte | ||
2490 | * kmalloc. A 128kb malloc should suffice for a 256TB filesystem. | ||
2491 | * So a two level scheme suffices for now. */ | ||
2492 | sbi->s_group_info = kmalloc(sizeof(*sbi->s_group_info) * | ||
2493 | num_meta_group_infos, GFP_KERNEL); | ||
2494 | if (sbi->s_group_info == NULL) { | ||
2495 | printk(KERN_ERR "EXT4-fs: can't allocate buddy meta group\n"); | ||
2496 | return -ENOMEM; | ||
2497 | } | ||
2498 | sbi->s_buddy_cache = new_inode(sb); | ||
2499 | if (sbi->s_buddy_cache == NULL) { | ||
2500 | printk(KERN_ERR "EXT4-fs: can't get new inode\n"); | ||
2501 | goto err_freesgi; | ||
2502 | } | ||
2503 | EXT4_I(sbi->s_buddy_cache)->i_disksize = 0; | ||
2504 | |||
2505 | metalen = sizeof(*meta_group_info) << EXT4_DESC_PER_BLOCK_BITS(sb); | ||
2506 | for (i = 0; i < num_meta_group_infos; i++) { | ||
2507 | if ((i + 1) == num_meta_group_infos) | ||
2508 | metalen = sizeof(*meta_group_info) * | ||
2509 | (sbi->s_groups_count - | ||
2510 | (i << EXT4_DESC_PER_BLOCK_BITS(sb))); | ||
2511 | meta_group_info = kmalloc(metalen, GFP_KERNEL); | ||
2512 | if (meta_group_info == NULL) { | ||
2513 | printk(KERN_ERR "EXT4-fs: can't allocate mem for a " | ||
2514 | "buddy group\n"); | ||
2515 | goto err_freemeta; | ||
2516 | } | ||
2517 | sbi->s_group_info[i] = meta_group_info; | ||
2518 | } | ||
2519 | |||
2520 | /* | ||
2521 | * calculate needed size. if change bb_counters size, | ||
2522 | * don't forget about ext4_mb_generate_buddy() | ||
2523 | */ | ||
2524 | len = sizeof(struct ext4_group_info); | ||
2525 | len += sizeof(unsigned short) * (sb->s_blocksize_bits + 2); | ||
2526 | for (i = 0; i < sbi->s_groups_count; i++) { | ||
2527 | struct ext4_group_desc *desc; | ||
2528 | |||
2529 | meta_group_info = | ||
2530 | sbi->s_group_info[i >> EXT4_DESC_PER_BLOCK_BITS(sb)]; | ||
2531 | j = i & (EXT4_DESC_PER_BLOCK(sb) - 1); | ||
2532 | |||
2533 | meta_group_info[j] = kzalloc(len, GFP_KERNEL); | ||
2534 | if (meta_group_info[j] == NULL) { | ||
2535 | printk(KERN_ERR "EXT4-fs: can't allocate buddy mem\n"); | ||
2536 | i--; | ||
2537 | goto err_freebuddy; | ||
2538 | } | ||
2539 | desc = ext4_get_group_desc(sb, i, NULL); | ||
2540 | if (desc == NULL) { | ||
2541 | printk(KERN_ERR | ||
2542 | "EXT4-fs: can't read descriptor %lu\n", i); | ||
2543 | goto err_freebuddy; | ||
2544 | } | ||
2545 | memset(meta_group_info[j], 0, len); | ||
2546 | set_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, | ||
2547 | &(meta_group_info[j]->bb_state)); | ||
2548 | |||
2549 | /* | ||
2550 | * initialize bb_free to be able to skip | ||
2551 | * empty groups without initialization | ||
2552 | */ | ||
2553 | if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | ||
2554 | meta_group_info[j]->bb_free = | ||
2555 | ext4_free_blocks_after_init(sb, i, desc); | ||
2556 | } else { | ||
2557 | meta_group_info[j]->bb_free = | ||
2558 | le16_to_cpu(desc->bg_free_blocks_count); | ||
2559 | } | ||
2560 | |||
2561 | INIT_LIST_HEAD(&meta_group_info[j]->bb_prealloc_list); | ||
2562 | |||
2563 | #ifdef DOUBLE_CHECK | ||
2564 | { | ||
2565 | struct buffer_head *bh; | ||
2566 | meta_group_info[j]->bb_bitmap = | ||
2567 | kmalloc(sb->s_blocksize, GFP_KERNEL); | ||
2568 | BUG_ON(meta_group_info[j]->bb_bitmap == NULL); | ||
2569 | bh = read_block_bitmap(sb, i); | ||
2570 | BUG_ON(bh == NULL); | ||
2571 | memcpy(meta_group_info[j]->bb_bitmap, bh->b_data, | ||
2572 | sb->s_blocksize); | ||
2573 | put_bh(bh); | ||
2574 | } | ||
2575 | #endif | ||
2576 | |||
2577 | } | ||
2578 | |||
2579 | return 0; | ||
2580 | |||
2581 | err_freebuddy: | ||
2582 | while (i >= 0) { | ||
2583 | kfree(ext4_get_group_info(sb, i)); | ||
2584 | i--; | ||
2585 | } | ||
2586 | i = num_meta_group_infos; | ||
2587 | err_freemeta: | ||
2588 | while (--i >= 0) | ||
2589 | kfree(sbi->s_group_info[i]); | ||
2590 | iput(sbi->s_buddy_cache); | ||
2591 | err_freesgi: | ||
2592 | kfree(sbi->s_group_info); | ||
2593 | return -ENOMEM; | ||
2594 | } | ||
2595 | |||
2596 | int ext4_mb_init(struct super_block *sb, int needs_recovery) | ||
2597 | { | ||
2598 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
2599 | unsigned i; | ||
2600 | unsigned offset; | ||
2601 | unsigned max; | ||
2602 | |||
2603 | if (!test_opt(sb, MBALLOC)) | ||
2604 | return 0; | ||
2605 | |||
2606 | i = (sb->s_blocksize_bits + 2) * sizeof(unsigned short); | ||
2607 | |||
2608 | sbi->s_mb_offsets = kmalloc(i, GFP_KERNEL); | ||
2609 | if (sbi->s_mb_offsets == NULL) { | ||
2610 | clear_opt(sbi->s_mount_opt, MBALLOC); | ||
2611 | return -ENOMEM; | ||
2612 | } | ||
2613 | sbi->s_mb_maxs = kmalloc(i, GFP_KERNEL); | ||
2614 | if (sbi->s_mb_maxs == NULL) { | ||
2615 | clear_opt(sbi->s_mount_opt, MBALLOC); | ||
2616 | kfree(sbi->s_mb_maxs); | ||
2617 | return -ENOMEM; | ||
2618 | } | ||
2619 | |||
2620 | /* order 0 is regular bitmap */ | ||
2621 | sbi->s_mb_maxs[0] = sb->s_blocksize << 3; | ||
2622 | sbi->s_mb_offsets[0] = 0; | ||
2623 | |||
2624 | i = 1; | ||
2625 | offset = 0; | ||
2626 | max = sb->s_blocksize << 2; | ||
2627 | do { | ||
2628 | sbi->s_mb_offsets[i] = offset; | ||
2629 | sbi->s_mb_maxs[i] = max; | ||
2630 | offset += 1 << (sb->s_blocksize_bits - i); | ||
2631 | max = max >> 1; | ||
2632 | i++; | ||
2633 | } while (i <= sb->s_blocksize_bits + 1); | ||
2634 | |||
2635 | /* init file for buddy data */ | ||
2636 | i = ext4_mb_init_backend(sb); | ||
2637 | if (i) { | ||
2638 | clear_opt(sbi->s_mount_opt, MBALLOC); | ||
2639 | kfree(sbi->s_mb_offsets); | ||
2640 | kfree(sbi->s_mb_maxs); | ||
2641 | return i; | ||
2642 | } | ||
2643 | |||
2644 | spin_lock_init(&sbi->s_md_lock); | ||
2645 | INIT_LIST_HEAD(&sbi->s_active_transaction); | ||
2646 | INIT_LIST_HEAD(&sbi->s_closed_transaction); | ||
2647 | INIT_LIST_HEAD(&sbi->s_committed_transaction); | ||
2648 | spin_lock_init(&sbi->s_bal_lock); | ||
2649 | |||
2650 | sbi->s_mb_max_to_scan = MB_DEFAULT_MAX_TO_SCAN; | ||
2651 | sbi->s_mb_min_to_scan = MB_DEFAULT_MIN_TO_SCAN; | ||
2652 | sbi->s_mb_stats = MB_DEFAULT_STATS; | ||
2653 | sbi->s_mb_stream_request = MB_DEFAULT_STREAM_THRESHOLD; | ||
2654 | sbi->s_mb_order2_reqs = MB_DEFAULT_ORDER2_REQS; | ||
2655 | sbi->s_mb_history_filter = EXT4_MB_HISTORY_DEFAULT; | ||
2656 | sbi->s_mb_group_prealloc = MB_DEFAULT_GROUP_PREALLOC; | ||
2657 | |||
2658 | i = sizeof(struct ext4_locality_group) * NR_CPUS; | ||
2659 | sbi->s_locality_groups = kmalloc(i, GFP_KERNEL); | ||
2660 | if (sbi->s_locality_groups == NULL) { | ||
2661 | clear_opt(sbi->s_mount_opt, MBALLOC); | ||
2662 | kfree(sbi->s_mb_offsets); | ||
2663 | kfree(sbi->s_mb_maxs); | ||
2664 | return -ENOMEM; | ||
2665 | } | ||
2666 | for (i = 0; i < NR_CPUS; i++) { | ||
2667 | struct ext4_locality_group *lg; | ||
2668 | lg = &sbi->s_locality_groups[i]; | ||
2669 | mutex_init(&lg->lg_mutex); | ||
2670 | INIT_LIST_HEAD(&lg->lg_prealloc_list); | ||
2671 | spin_lock_init(&lg->lg_prealloc_lock); | ||
2672 | } | ||
2673 | |||
2674 | ext4_mb_init_per_dev_proc(sb); | ||
2675 | ext4_mb_history_init(sb); | ||
2676 | |||
2677 | printk("EXT4-fs: mballoc enabled\n"); | ||
2678 | return 0; | ||
2679 | } | ||
2680 | |||
2681 | /* need to called with ext4 group lock (ext4_lock_group) */ | ||
2682 | static void ext4_mb_cleanup_pa(struct ext4_group_info *grp) | ||
2683 | { | ||
2684 | struct ext4_prealloc_space *pa; | ||
2685 | struct list_head *cur, *tmp; | ||
2686 | int count = 0; | ||
2687 | |||
2688 | list_for_each_safe(cur, tmp, &grp->bb_prealloc_list) { | ||
2689 | pa = list_entry(cur, struct ext4_prealloc_space, pa_group_list); | ||
2690 | list_del(&pa->pa_group_list); | ||
2691 | count++; | ||
2692 | kfree(pa); | ||
2693 | } | ||
2694 | if (count) | ||
2695 | mb_debug("mballoc: %u PAs left\n", count); | ||
2696 | |||
2697 | } | ||
2698 | |||
2699 | int ext4_mb_release(struct super_block *sb) | ||
2700 | { | ||
2701 | ext4_group_t i; | ||
2702 | int num_meta_group_infos; | ||
2703 | struct ext4_group_info *grinfo; | ||
2704 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
2705 | |||
2706 | if (!test_opt(sb, MBALLOC)) | ||
2707 | return 0; | ||
2708 | |||
2709 | /* release freed, non-committed blocks */ | ||
2710 | spin_lock(&sbi->s_md_lock); | ||
2711 | list_splice_init(&sbi->s_closed_transaction, | ||
2712 | &sbi->s_committed_transaction); | ||
2713 | list_splice_init(&sbi->s_active_transaction, | ||
2714 | &sbi->s_committed_transaction); | ||
2715 | spin_unlock(&sbi->s_md_lock); | ||
2716 | ext4_mb_free_committed_blocks(sb); | ||
2717 | |||
2718 | if (sbi->s_group_info) { | ||
2719 | for (i = 0; i < sbi->s_groups_count; i++) { | ||
2720 | grinfo = ext4_get_group_info(sb, i); | ||
2721 | #ifdef DOUBLE_CHECK | ||
2722 | kfree(grinfo->bb_bitmap); | ||
2723 | #endif | ||
2724 | ext4_lock_group(sb, i); | ||
2725 | ext4_mb_cleanup_pa(grinfo); | ||
2726 | ext4_unlock_group(sb, i); | ||
2727 | kfree(grinfo); | ||
2728 | } | ||
2729 | num_meta_group_infos = (sbi->s_groups_count + | ||
2730 | EXT4_DESC_PER_BLOCK(sb) - 1) >> | ||
2731 | EXT4_DESC_PER_BLOCK_BITS(sb); | ||
2732 | for (i = 0; i < num_meta_group_infos; i++) | ||
2733 | kfree(sbi->s_group_info[i]); | ||
2734 | kfree(sbi->s_group_info); | ||
2735 | } | ||
2736 | kfree(sbi->s_mb_offsets); | ||
2737 | kfree(sbi->s_mb_maxs); | ||
2738 | if (sbi->s_buddy_cache) | ||
2739 | iput(sbi->s_buddy_cache); | ||
2740 | if (sbi->s_mb_stats) { | ||
2741 | printk(KERN_INFO | ||
2742 | "EXT4-fs: mballoc: %u blocks %u reqs (%u success)\n", | ||
2743 | atomic_read(&sbi->s_bal_allocated), | ||
2744 | atomic_read(&sbi->s_bal_reqs), | ||
2745 | atomic_read(&sbi->s_bal_success)); | ||
2746 | printk(KERN_INFO | ||
2747 | "EXT4-fs: mballoc: %u extents scanned, %u goal hits, " | ||
2748 | "%u 2^N hits, %u breaks, %u lost\n", | ||
2749 | atomic_read(&sbi->s_bal_ex_scanned), | ||
2750 | atomic_read(&sbi->s_bal_goals), | ||
2751 | atomic_read(&sbi->s_bal_2orders), | ||
2752 | atomic_read(&sbi->s_bal_breaks), | ||
2753 | atomic_read(&sbi->s_mb_lost_chunks)); | ||
2754 | printk(KERN_INFO | ||
2755 | "EXT4-fs: mballoc: %lu generated and it took %Lu\n", | ||
2756 | sbi->s_mb_buddies_generated++, | ||
2757 | sbi->s_mb_generation_time); | ||
2758 | printk(KERN_INFO | ||
2759 | "EXT4-fs: mballoc: %u preallocated, %u discarded\n", | ||
2760 | atomic_read(&sbi->s_mb_preallocated), | ||
2761 | atomic_read(&sbi->s_mb_discarded)); | ||
2762 | } | ||
2763 | |||
2764 | kfree(sbi->s_locality_groups); | ||
2765 | |||
2766 | ext4_mb_history_release(sb); | ||
2767 | ext4_mb_destroy_per_dev_proc(sb); | ||
2768 | |||
2769 | return 0; | ||
2770 | } | ||
2771 | |||
2772 | static void ext4_mb_free_committed_blocks(struct super_block *sb) | ||
2773 | { | ||
2774 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
2775 | int err; | ||
2776 | int i; | ||
2777 | int count = 0; | ||
2778 | int count2 = 0; | ||
2779 | struct ext4_free_metadata *md; | ||
2780 | struct ext4_buddy e4b; | ||
2781 | |||
2782 | if (list_empty(&sbi->s_committed_transaction)) | ||
2783 | return; | ||
2784 | |||
2785 | /* there is committed blocks to be freed yet */ | ||
2786 | do { | ||
2787 | /* get next array of blocks */ | ||
2788 | md = NULL; | ||
2789 | spin_lock(&sbi->s_md_lock); | ||
2790 | if (!list_empty(&sbi->s_committed_transaction)) { | ||
2791 | md = list_entry(sbi->s_committed_transaction.next, | ||
2792 | struct ext4_free_metadata, list); | ||
2793 | list_del(&md->list); | ||
2794 | } | ||
2795 | spin_unlock(&sbi->s_md_lock); | ||
2796 | |||
2797 | if (md == NULL) | ||
2798 | break; | ||
2799 | |||
2800 | mb_debug("gonna free %u blocks in group %lu (0x%p):", | ||
2801 | md->num, md->group, md); | ||
2802 | |||
2803 | err = ext4_mb_load_buddy(sb, md->group, &e4b); | ||
2804 | /* we expect to find existing buddy because it's pinned */ | ||
2805 | BUG_ON(err != 0); | ||
2806 | |||
2807 | /* there are blocks to put in buddy to make them really free */ | ||
2808 | count += md->num; | ||
2809 | count2++; | ||
2810 | ext4_lock_group(sb, md->group); | ||
2811 | for (i = 0; i < md->num; i++) { | ||
2812 | mb_debug(" %u", md->blocks[i]); | ||
2813 | err = mb_free_blocks(NULL, &e4b, md->blocks[i], 1); | ||
2814 | BUG_ON(err != 0); | ||
2815 | } | ||
2816 | mb_debug("\n"); | ||
2817 | ext4_unlock_group(sb, md->group); | ||
2818 | |||
2819 | /* balance refcounts from ext4_mb_free_metadata() */ | ||
2820 | page_cache_release(e4b.bd_buddy_page); | ||
2821 | page_cache_release(e4b.bd_bitmap_page); | ||
2822 | |||
2823 | kfree(md); | ||
2824 | ext4_mb_release_desc(&e4b); | ||
2825 | |||
2826 | } while (md); | ||
2827 | |||
2828 | mb_debug("freed %u blocks in %u structures\n", count, count2); | ||
2829 | } | ||
2830 | |||
2831 | #define EXT4_ROOT "ext4" | ||
2832 | #define EXT4_MB_STATS_NAME "stats" | ||
2833 | #define EXT4_MB_MAX_TO_SCAN_NAME "max_to_scan" | ||
2834 | #define EXT4_MB_MIN_TO_SCAN_NAME "min_to_scan" | ||
2835 | #define EXT4_MB_ORDER2_REQ "order2_req" | ||
2836 | #define EXT4_MB_STREAM_REQ "stream_req" | ||
2837 | #define EXT4_MB_GROUP_PREALLOC "group_prealloc" | ||
2838 | |||
2839 | |||
2840 | |||
2841 | #define MB_PROC_VALUE_READ(name) \ | ||
2842 | static int ext4_mb_read_##name(char *page, char **start, \ | ||
2843 | off_t off, int count, int *eof, void *data) \ | ||
2844 | { \ | ||
2845 | struct ext4_sb_info *sbi = data; \ | ||
2846 | int len; \ | ||
2847 | *eof = 1; \ | ||
2848 | if (off != 0) \ | ||
2849 | return 0; \ | ||
2850 | len = sprintf(page, "%ld\n", sbi->s_mb_##name); \ | ||
2851 | *start = page; \ | ||
2852 | return len; \ | ||
2853 | } | ||
2854 | |||
2855 | #define MB_PROC_VALUE_WRITE(name) \ | ||
2856 | static int ext4_mb_write_##name(struct file *file, \ | ||
2857 | const char __user *buf, unsigned long cnt, void *data) \ | ||
2858 | { \ | ||
2859 | struct ext4_sb_info *sbi = data; \ | ||
2860 | char str[32]; \ | ||
2861 | long value; \ | ||
2862 | if (cnt >= sizeof(str)) \ | ||
2863 | return -EINVAL; \ | ||
2864 | if (copy_from_user(str, buf, cnt)) \ | ||
2865 | return -EFAULT; \ | ||
2866 | value = simple_strtol(str, NULL, 0); \ | ||
2867 | if (value <= 0) \ | ||
2868 | return -ERANGE; \ | ||
2869 | sbi->s_mb_##name = value; \ | ||
2870 | return cnt; \ | ||
2871 | } | ||
2872 | |||
2873 | MB_PROC_VALUE_READ(stats); | ||
2874 | MB_PROC_VALUE_WRITE(stats); | ||
2875 | MB_PROC_VALUE_READ(max_to_scan); | ||
2876 | MB_PROC_VALUE_WRITE(max_to_scan); | ||
2877 | MB_PROC_VALUE_READ(min_to_scan); | ||
2878 | MB_PROC_VALUE_WRITE(min_to_scan); | ||
2879 | MB_PROC_VALUE_READ(order2_reqs); | ||
2880 | MB_PROC_VALUE_WRITE(order2_reqs); | ||
2881 | MB_PROC_VALUE_READ(stream_request); | ||
2882 | MB_PROC_VALUE_WRITE(stream_request); | ||
2883 | MB_PROC_VALUE_READ(group_prealloc); | ||
2884 | MB_PROC_VALUE_WRITE(group_prealloc); | ||
2885 | |||
2886 | #define MB_PROC_HANDLER(name, var) \ | ||
2887 | do { \ | ||
2888 | proc = create_proc_entry(name, mode, sbi->s_mb_proc); \ | ||
2889 | if (proc == NULL) { \ | ||
2890 | printk(KERN_ERR "EXT4-fs: can't to create %s\n", name); \ | ||
2891 | goto err_out; \ | ||
2892 | } \ | ||
2893 | proc->data = sbi; \ | ||
2894 | proc->read_proc = ext4_mb_read_##var ; \ | ||
2895 | proc->write_proc = ext4_mb_write_##var; \ | ||
2896 | } while (0) | ||
2897 | |||
2898 | static int ext4_mb_init_per_dev_proc(struct super_block *sb) | ||
2899 | { | ||
2900 | mode_t mode = S_IFREG | S_IRUGO | S_IWUSR; | ||
2901 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
2902 | struct proc_dir_entry *proc; | ||
2903 | char devname[64]; | ||
2904 | |||
2905 | snprintf(devname, sizeof(devname) - 1, "%s", | ||
2906 | bdevname(sb->s_bdev, devname)); | ||
2907 | sbi->s_mb_proc = proc_mkdir(devname, proc_root_ext4); | ||
2908 | |||
2909 | MB_PROC_HANDLER(EXT4_MB_STATS_NAME, stats); | ||
2910 | MB_PROC_HANDLER(EXT4_MB_MAX_TO_SCAN_NAME, max_to_scan); | ||
2911 | MB_PROC_HANDLER(EXT4_MB_MIN_TO_SCAN_NAME, min_to_scan); | ||
2912 | MB_PROC_HANDLER(EXT4_MB_ORDER2_REQ, order2_reqs); | ||
2913 | MB_PROC_HANDLER(EXT4_MB_STREAM_REQ, stream_request); | ||
2914 | MB_PROC_HANDLER(EXT4_MB_GROUP_PREALLOC, group_prealloc); | ||
2915 | |||
2916 | return 0; | ||
2917 | |||
2918 | err_out: | ||
2919 | printk(KERN_ERR "EXT4-fs: Unable to create %s\n", devname); | ||
2920 | remove_proc_entry(EXT4_MB_GROUP_PREALLOC, sbi->s_mb_proc); | ||
2921 | remove_proc_entry(EXT4_MB_STREAM_REQ, sbi->s_mb_proc); | ||
2922 | remove_proc_entry(EXT4_MB_ORDER2_REQ, sbi->s_mb_proc); | ||
2923 | remove_proc_entry(EXT4_MB_MIN_TO_SCAN_NAME, sbi->s_mb_proc); | ||
2924 | remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_mb_proc); | ||
2925 | remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_mb_proc); | ||
2926 | remove_proc_entry(devname, proc_root_ext4); | ||
2927 | sbi->s_mb_proc = NULL; | ||
2928 | |||
2929 | return -ENOMEM; | ||
2930 | } | ||
2931 | |||
2932 | static int ext4_mb_destroy_per_dev_proc(struct super_block *sb) | ||
2933 | { | ||
2934 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
2935 | char devname[64]; | ||
2936 | |||
2937 | if (sbi->s_mb_proc == NULL) | ||
2938 | return -EINVAL; | ||
2939 | |||
2940 | snprintf(devname, sizeof(devname) - 1, "%s", | ||
2941 | bdevname(sb->s_bdev, devname)); | ||
2942 | remove_proc_entry(EXT4_MB_GROUP_PREALLOC, sbi->s_mb_proc); | ||
2943 | remove_proc_entry(EXT4_MB_STREAM_REQ, sbi->s_mb_proc); | ||
2944 | remove_proc_entry(EXT4_MB_ORDER2_REQ, sbi->s_mb_proc); | ||
2945 | remove_proc_entry(EXT4_MB_MIN_TO_SCAN_NAME, sbi->s_mb_proc); | ||
2946 | remove_proc_entry(EXT4_MB_MAX_TO_SCAN_NAME, sbi->s_mb_proc); | ||
2947 | remove_proc_entry(EXT4_MB_STATS_NAME, sbi->s_mb_proc); | ||
2948 | remove_proc_entry(devname, proc_root_ext4); | ||
2949 | |||
2950 | return 0; | ||
2951 | } | ||
2952 | |||
2953 | int __init init_ext4_mballoc(void) | ||
2954 | { | ||
2955 | ext4_pspace_cachep = | ||
2956 | kmem_cache_create("ext4_prealloc_space", | ||
2957 | sizeof(struct ext4_prealloc_space), | ||
2958 | 0, SLAB_RECLAIM_ACCOUNT, NULL); | ||
2959 | if (ext4_pspace_cachep == NULL) | ||
2960 | return -ENOMEM; | ||
2961 | |||
2962 | #ifdef CONFIG_PROC_FS | ||
2963 | proc_root_ext4 = proc_mkdir(EXT4_ROOT, proc_root_fs); | ||
2964 | if (proc_root_ext4 == NULL) | ||
2965 | printk(KERN_ERR "EXT4-fs: Unable to create %s\n", EXT4_ROOT); | ||
2966 | #endif | ||
2967 | |||
2968 | return 0; | ||
2969 | } | ||
2970 | |||
2971 | void exit_ext4_mballoc(void) | ||
2972 | { | ||
2973 | /* XXX: synchronize_rcu(); */ | ||
2974 | kmem_cache_destroy(ext4_pspace_cachep); | ||
2975 | #ifdef CONFIG_PROC_FS | ||
2976 | remove_proc_entry(EXT4_ROOT, proc_root_fs); | ||
2977 | #endif | ||
2978 | } | ||
2979 | |||
2980 | |||
2981 | /* | ||
2982 | * Check quota and mark choosed space (ac->ac_b_ex) non-free in bitmaps | ||
2983 | * Returns 0 if success or error code | ||
2984 | */ | ||
2985 | static int ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | ||
2986 | handle_t *handle) | ||
2987 | { | ||
2988 | struct buffer_head *bitmap_bh = NULL; | ||
2989 | struct ext4_super_block *es; | ||
2990 | struct ext4_group_desc *gdp; | ||
2991 | struct buffer_head *gdp_bh; | ||
2992 | struct ext4_sb_info *sbi; | ||
2993 | struct super_block *sb; | ||
2994 | ext4_fsblk_t block; | ||
2995 | int err; | ||
2996 | |||
2997 | BUG_ON(ac->ac_status != AC_STATUS_FOUND); | ||
2998 | BUG_ON(ac->ac_b_ex.fe_len <= 0); | ||
2999 | |||
3000 | sb = ac->ac_sb; | ||
3001 | sbi = EXT4_SB(sb); | ||
3002 | es = sbi->s_es; | ||
3003 | |||
3004 | ext4_debug("using block group %lu(%d)\n", ac->ac_b_ex.fe_group, | ||
3005 | gdp->bg_free_blocks_count); | ||
3006 | |||
3007 | err = -EIO; | ||
3008 | bitmap_bh = read_block_bitmap(sb, ac->ac_b_ex.fe_group); | ||
3009 | if (!bitmap_bh) | ||
3010 | goto out_err; | ||
3011 | |||
3012 | err = ext4_journal_get_write_access(handle, bitmap_bh); | ||
3013 | if (err) | ||
3014 | goto out_err; | ||
3015 | |||
3016 | err = -EIO; | ||
3017 | gdp = ext4_get_group_desc(sb, ac->ac_b_ex.fe_group, &gdp_bh); | ||
3018 | if (!gdp) | ||
3019 | goto out_err; | ||
3020 | |||
3021 | err = ext4_journal_get_write_access(handle, gdp_bh); | ||
3022 | if (err) | ||
3023 | goto out_err; | ||
3024 | |||
3025 | block = ac->ac_b_ex.fe_group * EXT4_BLOCKS_PER_GROUP(sb) | ||
3026 | + ac->ac_b_ex.fe_start | ||
3027 | + le32_to_cpu(es->s_first_data_block); | ||
3028 | |||
3029 | if (block == ext4_block_bitmap(sb, gdp) || | ||
3030 | block == ext4_inode_bitmap(sb, gdp) || | ||
3031 | in_range(block, ext4_inode_table(sb, gdp), | ||
3032 | EXT4_SB(sb)->s_itb_per_group)) { | ||
3033 | |||
3034 | ext4_error(sb, __FUNCTION__, | ||
3035 | "Allocating block in system zone - block = %llu", | ||
3036 | block); | ||
3037 | } | ||
3038 | #ifdef AGGRESSIVE_CHECK | ||
3039 | { | ||
3040 | int i; | ||
3041 | for (i = 0; i < ac->ac_b_ex.fe_len; i++) { | ||
3042 | BUG_ON(mb_test_bit(ac->ac_b_ex.fe_start + i, | ||
3043 | bitmap_bh->b_data)); | ||
3044 | } | ||
3045 | } | ||
3046 | #endif | ||
3047 | mb_set_bits(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group), bitmap_bh->b_data, | ||
3048 | ac->ac_b_ex.fe_start, ac->ac_b_ex.fe_len); | ||
3049 | |||
3050 | spin_lock(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group)); | ||
3051 | if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | ||
3052 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); | ||
3053 | gdp->bg_free_blocks_count = | ||
3054 | cpu_to_le16(ext4_free_blocks_after_init(sb, | ||
3055 | ac->ac_b_ex.fe_group, | ||
3056 | gdp)); | ||
3057 | } | ||
3058 | gdp->bg_free_blocks_count = | ||
3059 | cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) | ||
3060 | - ac->ac_b_ex.fe_len); | ||
3061 | gdp->bg_checksum = ext4_group_desc_csum(sbi, ac->ac_b_ex.fe_group, gdp); | ||
3062 | spin_unlock(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group)); | ||
3063 | percpu_counter_sub(&sbi->s_freeblocks_counter, ac->ac_b_ex.fe_len); | ||
3064 | |||
3065 | err = ext4_journal_dirty_metadata(handle, bitmap_bh); | ||
3066 | if (err) | ||
3067 | goto out_err; | ||
3068 | err = ext4_journal_dirty_metadata(handle, gdp_bh); | ||
3069 | |||
3070 | out_err: | ||
3071 | sb->s_dirt = 1; | ||
3072 | put_bh(bitmap_bh); | ||
3073 | return err; | ||
3074 | } | ||
3075 | |||
3076 | /* | ||
3077 | * here we normalize request for locality group | ||
3078 | * Group request are normalized to s_strip size if we set the same via mount | ||
3079 | * option. If not we set it to s_mb_group_prealloc which can be configured via | ||
3080 | * /proc/fs/ext4/<partition>/group_prealloc | ||
3081 | * | ||
3082 | * XXX: should we try to preallocate more than the group has now? | ||
3083 | */ | ||
3084 | static void ext4_mb_normalize_group_request(struct ext4_allocation_context *ac) | ||
3085 | { | ||
3086 | struct super_block *sb = ac->ac_sb; | ||
3087 | struct ext4_locality_group *lg = ac->ac_lg; | ||
3088 | |||
3089 | BUG_ON(lg == NULL); | ||
3090 | if (EXT4_SB(sb)->s_stripe) | ||
3091 | ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_stripe; | ||
3092 | else | ||
3093 | ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc; | ||
3094 | mb_debug("#%u: goal %lu blocks for locality group\n", | ||
3095 | current->pid, ac->ac_g_ex.fe_len); | ||
3096 | } | ||
3097 | |||
3098 | /* | ||
3099 | * Normalization means making request better in terms of | ||
3100 | * size and alignment | ||
3101 | */ | ||
3102 | static void ext4_mb_normalize_request(struct ext4_allocation_context *ac, | ||
3103 | struct ext4_allocation_request *ar) | ||
3104 | { | ||
3105 | int bsbits, max; | ||
3106 | ext4_lblk_t end; | ||
3107 | struct list_head *cur; | ||
3108 | loff_t size, orig_size, start_off; | ||
3109 | ext4_lblk_t start, orig_start; | ||
3110 | struct ext4_inode_info *ei = EXT4_I(ac->ac_inode); | ||
3111 | |||
3112 | /* do normalize only data requests, metadata requests | ||
3113 | do not need preallocation */ | ||
3114 | if (!(ac->ac_flags & EXT4_MB_HINT_DATA)) | ||
3115 | return; | ||
3116 | |||
3117 | /* sometime caller may want exact blocks */ | ||
3118 | if (unlikely(ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY)) | ||
3119 | return; | ||
3120 | |||
3121 | /* caller may indicate that preallocation isn't | ||
3122 | * required (it's a tail, for example) */ | ||
3123 | if (ac->ac_flags & EXT4_MB_HINT_NOPREALLOC) | ||
3124 | return; | ||
3125 | |||
3126 | if (ac->ac_flags & EXT4_MB_HINT_GROUP_ALLOC) { | ||
3127 | ext4_mb_normalize_group_request(ac); | ||
3128 | return ; | ||
3129 | } | ||
3130 | |||
3131 | bsbits = ac->ac_sb->s_blocksize_bits; | ||
3132 | |||
3133 | /* first, let's learn actual file size | ||
3134 | * given current request is allocated */ | ||
3135 | size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len; | ||
3136 | size = size << bsbits; | ||
3137 | if (size < i_size_read(ac->ac_inode)) | ||
3138 | size = i_size_read(ac->ac_inode); | ||
3139 | |||
3140 | /* max available blocks in a free group */ | ||
3141 | max = EXT4_BLOCKS_PER_GROUP(ac->ac_sb) - 1 - 1 - | ||
3142 | EXT4_SB(ac->ac_sb)->s_itb_per_group; | ||
3143 | |||
3144 | #define NRL_CHECK_SIZE(req, size, max,bits) \ | ||
3145 | (req <= (size) || max <= ((size) >> bits)) | ||
3146 | |||
3147 | /* first, try to predict filesize */ | ||
3148 | /* XXX: should this table be tunable? */ | ||
3149 | start_off = 0; | ||
3150 | if (size <= 16 * 1024) { | ||
3151 | size = 16 * 1024; | ||
3152 | } else if (size <= 32 * 1024) { | ||
3153 | size = 32 * 1024; | ||
3154 | } else if (size <= 64 * 1024) { | ||
3155 | size = 64 * 1024; | ||
3156 | } else if (size <= 128 * 1024) { | ||
3157 | size = 128 * 1024; | ||
3158 | } else if (size <= 256 * 1024) { | ||
3159 | size = 256 * 1024; | ||
3160 | } else if (size <= 512 * 1024) { | ||
3161 | size = 512 * 1024; | ||
3162 | } else if (size <= 1024 * 1024) { | ||
3163 | size = 1024 * 1024; | ||
3164 | } else if (NRL_CHECK_SIZE(size, 4 * 1024 * 1024, max, bsbits)) { | ||
3165 | start_off = ((loff_t)ac->ac_o_ex.fe_logical >> | ||
3166 | (20 - bsbits)) << 20; | ||
3167 | size = 1024 * 1024; | ||
3168 | } else if (NRL_CHECK_SIZE(size, 8 * 1024 * 1024, max, bsbits)) { | ||
3169 | start_off = ((loff_t)ac->ac_o_ex.fe_logical >> | ||
3170 | (22 - bsbits)) << 22; | ||
3171 | size = 4 * 1024 * 1024; | ||
3172 | } else if (NRL_CHECK_SIZE(ac->ac_o_ex.fe_len, | ||
3173 | (8<<20)>>bsbits, max, bsbits)) { | ||
3174 | start_off = ((loff_t)ac->ac_o_ex.fe_logical >> | ||
3175 | (23 - bsbits)) << 23; | ||
3176 | size = 8 * 1024 * 1024; | ||
3177 | } else { | ||
3178 | start_off = (loff_t)ac->ac_o_ex.fe_logical << bsbits; | ||
3179 | size = ac->ac_o_ex.fe_len << bsbits; | ||
3180 | } | ||
3181 | orig_size = size = size >> bsbits; | ||
3182 | orig_start = start = start_off >> bsbits; | ||
3183 | |||
3184 | /* don't cover already allocated blocks in selected range */ | ||
3185 | if (ar->pleft && start <= ar->lleft) { | ||
3186 | size -= ar->lleft + 1 - start; | ||
3187 | start = ar->lleft + 1; | ||
3188 | } | ||
3189 | if (ar->pright && start + size - 1 >= ar->lright) | ||
3190 | size -= start + size - ar->lright; | ||
3191 | |||
3192 | end = start + size; | ||
3193 | |||
3194 | /* check we don't cross already preallocated blocks */ | ||
3195 | rcu_read_lock(); | ||
3196 | list_for_each_rcu(cur, &ei->i_prealloc_list) { | ||
3197 | struct ext4_prealloc_space *pa; | ||
3198 | unsigned long pa_end; | ||
3199 | |||
3200 | pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list); | ||
3201 | |||
3202 | if (pa->pa_deleted) | ||
3203 | continue; | ||
3204 | spin_lock(&pa->pa_lock); | ||
3205 | if (pa->pa_deleted) { | ||
3206 | spin_unlock(&pa->pa_lock); | ||
3207 | continue; | ||
3208 | } | ||
3209 | |||
3210 | pa_end = pa->pa_lstart + pa->pa_len; | ||
3211 | |||
3212 | /* PA must not overlap original request */ | ||
3213 | BUG_ON(!(ac->ac_o_ex.fe_logical >= pa_end || | ||
3214 | ac->ac_o_ex.fe_logical < pa->pa_lstart)); | ||
3215 | |||
3216 | /* skip PA normalized request doesn't overlap with */ | ||
3217 | if (pa->pa_lstart >= end) { | ||
3218 | spin_unlock(&pa->pa_lock); | ||
3219 | continue; | ||
3220 | } | ||
3221 | if (pa_end <= start) { | ||
3222 | spin_unlock(&pa->pa_lock); | ||
3223 | continue; | ||
3224 | } | ||
3225 | BUG_ON(pa->pa_lstart <= start && pa_end >= end); | ||
3226 | |||
3227 | if (pa_end <= ac->ac_o_ex.fe_logical) { | ||
3228 | BUG_ON(pa_end < start); | ||
3229 | start = pa_end; | ||
3230 | } | ||
3231 | |||
3232 | if (pa->pa_lstart > ac->ac_o_ex.fe_logical) { | ||
3233 | BUG_ON(pa->pa_lstart > end); | ||
3234 | end = pa->pa_lstart; | ||
3235 | } | ||
3236 | spin_unlock(&pa->pa_lock); | ||
3237 | } | ||
3238 | rcu_read_unlock(); | ||
3239 | size = end - start; | ||
3240 | |||
3241 | /* XXX: extra loop to check we really don't overlap preallocations */ | ||
3242 | rcu_read_lock(); | ||
3243 | list_for_each_rcu(cur, &ei->i_prealloc_list) { | ||
3244 | struct ext4_prealloc_space *pa; | ||
3245 | unsigned long pa_end; | ||
3246 | pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list); | ||
3247 | spin_lock(&pa->pa_lock); | ||
3248 | if (pa->pa_deleted == 0) { | ||
3249 | pa_end = pa->pa_lstart + pa->pa_len; | ||
3250 | BUG_ON(!(start >= pa_end || end <= pa->pa_lstart)); | ||
3251 | } | ||
3252 | spin_unlock(&pa->pa_lock); | ||
3253 | } | ||
3254 | rcu_read_unlock(); | ||
3255 | |||
3256 | if (start + size <= ac->ac_o_ex.fe_logical && | ||
3257 | start > ac->ac_o_ex.fe_logical) { | ||
3258 | printk(KERN_ERR "start %lu, size %lu, fe_logical %lu\n", | ||
3259 | (unsigned long) start, (unsigned long) size, | ||
3260 | (unsigned long) ac->ac_o_ex.fe_logical); | ||
3261 | } | ||
3262 | BUG_ON(start + size <= ac->ac_o_ex.fe_logical && | ||
3263 | start > ac->ac_o_ex.fe_logical); | ||
3264 | BUG_ON(size <= 0 || size >= EXT4_BLOCKS_PER_GROUP(ac->ac_sb)); | ||
3265 | |||
3266 | /* now prepare goal request */ | ||
3267 | |||
3268 | /* XXX: is it better to align blocks WRT to logical | ||
3269 | * placement or satisfy big request as is */ | ||
3270 | ac->ac_g_ex.fe_logical = start; | ||
3271 | ac->ac_g_ex.fe_len = size; | ||
3272 | |||
3273 | /* define goal start in order to merge */ | ||
3274 | if (ar->pright && (ar->lright == (start + size))) { | ||
3275 | /* merge to the right */ | ||
3276 | ext4_get_group_no_and_offset(ac->ac_sb, ar->pright - size, | ||
3277 | &ac->ac_f_ex.fe_group, | ||
3278 | &ac->ac_f_ex.fe_start); | ||
3279 | ac->ac_flags |= EXT4_MB_HINT_TRY_GOAL; | ||
3280 | } | ||
3281 | if (ar->pleft && (ar->lleft + 1 == start)) { | ||
3282 | /* merge to the left */ | ||
3283 | ext4_get_group_no_and_offset(ac->ac_sb, ar->pleft + 1, | ||
3284 | &ac->ac_f_ex.fe_group, | ||
3285 | &ac->ac_f_ex.fe_start); | ||
3286 | ac->ac_flags |= EXT4_MB_HINT_TRY_GOAL; | ||
3287 | } | ||
3288 | |||
3289 | mb_debug("goal: %u(was %u) blocks at %u\n", (unsigned) size, | ||
3290 | (unsigned) orig_size, (unsigned) start); | ||
3291 | } | ||
3292 | |||
3293 | static void ext4_mb_collect_stats(struct ext4_allocation_context *ac) | ||
3294 | { | ||
3295 | struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); | ||
3296 | |||
3297 | if (sbi->s_mb_stats && ac->ac_g_ex.fe_len > 1) { | ||
3298 | atomic_inc(&sbi->s_bal_reqs); | ||
3299 | atomic_add(ac->ac_b_ex.fe_len, &sbi->s_bal_allocated); | ||
3300 | if (ac->ac_o_ex.fe_len >= ac->ac_g_ex.fe_len) | ||
3301 | atomic_inc(&sbi->s_bal_success); | ||
3302 | atomic_add(ac->ac_found, &sbi->s_bal_ex_scanned); | ||
3303 | if (ac->ac_g_ex.fe_start == ac->ac_b_ex.fe_start && | ||
3304 | ac->ac_g_ex.fe_group == ac->ac_b_ex.fe_group) | ||
3305 | atomic_inc(&sbi->s_bal_goals); | ||
3306 | if (ac->ac_found > sbi->s_mb_max_to_scan) | ||
3307 | atomic_inc(&sbi->s_bal_breaks); | ||
3308 | } | ||
3309 | |||
3310 | ext4_mb_store_history(ac); | ||
3311 | } | ||
3312 | |||
3313 | /* | ||
3314 | * use blocks preallocated to inode | ||
3315 | */ | ||
3316 | static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac, | ||
3317 | struct ext4_prealloc_space *pa) | ||
3318 | { | ||
3319 | ext4_fsblk_t start; | ||
3320 | ext4_fsblk_t end; | ||
3321 | int len; | ||
3322 | |||
3323 | /* found preallocated blocks, use them */ | ||
3324 | start = pa->pa_pstart + (ac->ac_o_ex.fe_logical - pa->pa_lstart); | ||
3325 | end = min(pa->pa_pstart + pa->pa_len, start + ac->ac_o_ex.fe_len); | ||
3326 | len = end - start; | ||
3327 | ext4_get_group_no_and_offset(ac->ac_sb, start, &ac->ac_b_ex.fe_group, | ||
3328 | &ac->ac_b_ex.fe_start); | ||
3329 | ac->ac_b_ex.fe_len = len; | ||
3330 | ac->ac_status = AC_STATUS_FOUND; | ||
3331 | ac->ac_pa = pa; | ||
3332 | |||
3333 | BUG_ON(start < pa->pa_pstart); | ||
3334 | BUG_ON(start + len > pa->pa_pstart + pa->pa_len); | ||
3335 | BUG_ON(pa->pa_free < len); | ||
3336 | pa->pa_free -= len; | ||
3337 | |||
3338 | mb_debug("use %llu/%lu from inode pa %p\n", start, len, pa); | ||
3339 | } | ||
3340 | |||
3341 | /* | ||
3342 | * use blocks preallocated to locality group | ||
3343 | */ | ||
3344 | static void ext4_mb_use_group_pa(struct ext4_allocation_context *ac, | ||
3345 | struct ext4_prealloc_space *pa) | ||
3346 | { | ||
3347 | unsigned len = ac->ac_o_ex.fe_len; | ||
3348 | |||
3349 | ext4_get_group_no_and_offset(ac->ac_sb, pa->pa_pstart, | ||
3350 | &ac->ac_b_ex.fe_group, | ||
3351 | &ac->ac_b_ex.fe_start); | ||
3352 | ac->ac_b_ex.fe_len = len; | ||
3353 | ac->ac_status = AC_STATUS_FOUND; | ||
3354 | ac->ac_pa = pa; | ||
3355 | |||
3356 | /* we don't correct pa_pstart or pa_plen here to avoid | ||
3357 | * possible race when tte group is being loaded concurrently | ||
3358 | * instead we correct pa later, after blocks are marked | ||
3359 | * in on-disk bitmap -- see ext4_mb_release_context() */ | ||
3360 | /* | ||
3361 | * FIXME!! but the other CPUs can look at this particular | ||
3362 | * pa and think that it have enought free blocks if we | ||
3363 | * don't update pa_free here right ? | ||
3364 | */ | ||
3365 | mb_debug("use %u/%u from group pa %p\n", pa->pa_lstart-len, len, pa); | ||
3366 | } | ||
3367 | |||
3368 | /* | ||
3369 | * search goal blocks in preallocated space | ||
3370 | */ | ||
3371 | static int ext4_mb_use_preallocated(struct ext4_allocation_context *ac) | ||
3372 | { | ||
3373 | struct ext4_inode_info *ei = EXT4_I(ac->ac_inode); | ||
3374 | struct ext4_locality_group *lg; | ||
3375 | struct ext4_prealloc_space *pa; | ||
3376 | struct list_head *cur; | ||
3377 | |||
3378 | /* only data can be preallocated */ | ||
3379 | if (!(ac->ac_flags & EXT4_MB_HINT_DATA)) | ||
3380 | return 0; | ||
3381 | |||
3382 | /* first, try per-file preallocation */ | ||
3383 | rcu_read_lock(); | ||
3384 | list_for_each_rcu(cur, &ei->i_prealloc_list) { | ||
3385 | pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list); | ||
3386 | |||
3387 | /* all fields in this condition don't change, | ||
3388 | * so we can skip locking for them */ | ||
3389 | if (ac->ac_o_ex.fe_logical < pa->pa_lstart || | ||
3390 | ac->ac_o_ex.fe_logical >= pa->pa_lstart + pa->pa_len) | ||
3391 | continue; | ||
3392 | |||
3393 | /* found preallocated blocks, use them */ | ||
3394 | spin_lock(&pa->pa_lock); | ||
3395 | if (pa->pa_deleted == 0 && pa->pa_free) { | ||
3396 | atomic_inc(&pa->pa_count); | ||
3397 | ext4_mb_use_inode_pa(ac, pa); | ||
3398 | spin_unlock(&pa->pa_lock); | ||
3399 | ac->ac_criteria = 10; | ||
3400 | rcu_read_unlock(); | ||
3401 | return 1; | ||
3402 | } | ||
3403 | spin_unlock(&pa->pa_lock); | ||
3404 | } | ||
3405 | rcu_read_unlock(); | ||
3406 | |||
3407 | /* can we use group allocation? */ | ||
3408 | if (!(ac->ac_flags & EXT4_MB_HINT_GROUP_ALLOC)) | ||
3409 | return 0; | ||
3410 | |||
3411 | /* inode may have no locality group for some reason */ | ||
3412 | lg = ac->ac_lg; | ||
3413 | if (lg == NULL) | ||
3414 | return 0; | ||
3415 | |||
3416 | rcu_read_lock(); | ||
3417 | list_for_each_rcu(cur, &lg->lg_prealloc_list) { | ||
3418 | pa = list_entry(cur, struct ext4_prealloc_space, pa_inode_list); | ||
3419 | spin_lock(&pa->pa_lock); | ||
3420 | if (pa->pa_deleted == 0 && pa->pa_free >= ac->ac_o_ex.fe_len) { | ||
3421 | atomic_inc(&pa->pa_count); | ||
3422 | ext4_mb_use_group_pa(ac, pa); | ||
3423 | spin_unlock(&pa->pa_lock); | ||
3424 | ac->ac_criteria = 20; | ||
3425 | rcu_read_unlock(); | ||
3426 | return 1; | ||
3427 | } | ||
3428 | spin_unlock(&pa->pa_lock); | ||
3429 | } | ||
3430 | rcu_read_unlock(); | ||
3431 | |||
3432 | return 0; | ||
3433 | } | ||
3434 | |||
3435 | /* | ||
3436 | * the function goes through all preallocation in this group and marks them | ||
3437 | * used in in-core bitmap. buddy must be generated from this bitmap | ||
3438 | * Need to be called with ext4 group lock (ext4_lock_group) | ||
3439 | */ | ||
3440 | static void ext4_mb_generate_from_pa(struct super_block *sb, void *bitmap, | ||
3441 | ext4_group_t group) | ||
3442 | { | ||
3443 | struct ext4_group_info *grp = ext4_get_group_info(sb, group); | ||
3444 | struct ext4_prealloc_space *pa; | ||
3445 | struct list_head *cur; | ||
3446 | ext4_group_t groupnr; | ||
3447 | ext4_grpblk_t start; | ||
3448 | int preallocated = 0; | ||
3449 | int count = 0; | ||
3450 | int len; | ||
3451 | |||
3452 | /* all form of preallocation discards first load group, | ||
3453 | * so the only competing code is preallocation use. | ||
3454 | * we don't need any locking here | ||
3455 | * notice we do NOT ignore preallocations with pa_deleted | ||
3456 | * otherwise we could leave used blocks available for | ||
3457 | * allocation in buddy when concurrent ext4_mb_put_pa() | ||
3458 | * is dropping preallocation | ||
3459 | */ | ||
3460 | list_for_each(cur, &grp->bb_prealloc_list) { | ||
3461 | pa = list_entry(cur, struct ext4_prealloc_space, pa_group_list); | ||
3462 | spin_lock(&pa->pa_lock); | ||
3463 | ext4_get_group_no_and_offset(sb, pa->pa_pstart, | ||
3464 | &groupnr, &start); | ||
3465 | len = pa->pa_len; | ||
3466 | spin_unlock(&pa->pa_lock); | ||
3467 | if (unlikely(len == 0)) | ||
3468 | continue; | ||
3469 | BUG_ON(groupnr != group); | ||
3470 | mb_set_bits(sb_bgl_lock(EXT4_SB(sb), group), | ||
3471 | bitmap, start, len); | ||
3472 | preallocated += len; | ||
3473 | count++; | ||
3474 | } | ||
3475 | mb_debug("prellocated %u for group %lu\n", preallocated, group); | ||
3476 | } | ||
3477 | |||
3478 | static void ext4_mb_pa_callback(struct rcu_head *head) | ||
3479 | { | ||
3480 | struct ext4_prealloc_space *pa; | ||
3481 | pa = container_of(head, struct ext4_prealloc_space, u.pa_rcu); | ||
3482 | kmem_cache_free(ext4_pspace_cachep, pa); | ||
3483 | } | ||
3484 | |||
3485 | /* | ||
3486 | * drops a reference to preallocated space descriptor | ||
3487 | * if this was the last reference and the space is consumed | ||
3488 | */ | ||
3489 | static void ext4_mb_put_pa(struct ext4_allocation_context *ac, | ||
3490 | struct super_block *sb, struct ext4_prealloc_space *pa) | ||
3491 | { | ||
3492 | unsigned long grp; | ||
3493 | |||
3494 | if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) | ||
3495 | return; | ||
3496 | |||
3497 | /* in this short window concurrent discard can set pa_deleted */ | ||
3498 | spin_lock(&pa->pa_lock); | ||
3499 | if (pa->pa_deleted == 1) { | ||
3500 | spin_unlock(&pa->pa_lock); | ||
3501 | return; | ||
3502 | } | ||
3503 | |||
3504 | pa->pa_deleted = 1; | ||
3505 | spin_unlock(&pa->pa_lock); | ||
3506 | |||
3507 | /* -1 is to protect from crossing allocation group */ | ||
3508 | ext4_get_group_no_and_offset(sb, pa->pa_pstart - 1, &grp, NULL); | ||
3509 | |||
3510 | /* | ||
3511 | * possible race: | ||
3512 | * | ||
3513 | * P1 (buddy init) P2 (regular allocation) | ||
3514 | * find block B in PA | ||
3515 | * copy on-disk bitmap to buddy | ||
3516 | * mark B in on-disk bitmap | ||
3517 | * drop PA from group | ||
3518 | * mark all PAs in buddy | ||
3519 | * | ||
3520 | * thus, P1 initializes buddy with B available. to prevent this | ||
3521 | * we make "copy" and "mark all PAs" atomic and serialize "drop PA" | ||
3522 | * against that pair | ||
3523 | */ | ||
3524 | ext4_lock_group(sb, grp); | ||
3525 | list_del(&pa->pa_group_list); | ||
3526 | ext4_unlock_group(sb, grp); | ||
3527 | |||
3528 | spin_lock(pa->pa_obj_lock); | ||
3529 | list_del_rcu(&pa->pa_inode_list); | ||
3530 | spin_unlock(pa->pa_obj_lock); | ||
3531 | |||
3532 | call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback); | ||
3533 | } | ||
3534 | |||
3535 | /* | ||
3536 | * creates new preallocated space for given inode | ||
3537 | */ | ||
3538 | static int ext4_mb_new_inode_pa(struct ext4_allocation_context *ac) | ||
3539 | { | ||
3540 | struct super_block *sb = ac->ac_sb; | ||
3541 | struct ext4_prealloc_space *pa; | ||
3542 | struct ext4_group_info *grp; | ||
3543 | struct ext4_inode_info *ei; | ||
3544 | |||
3545 | /* preallocate only when found space is larger then requested */ | ||
3546 | BUG_ON(ac->ac_o_ex.fe_len >= ac->ac_b_ex.fe_len); | ||
3547 | BUG_ON(ac->ac_status != AC_STATUS_FOUND); | ||
3548 | BUG_ON(!S_ISREG(ac->ac_inode->i_mode)); | ||
3549 | |||
3550 | pa = kmem_cache_alloc(ext4_pspace_cachep, GFP_NOFS); | ||
3551 | if (pa == NULL) | ||
3552 | return -ENOMEM; | ||
3553 | |||
3554 | if (ac->ac_b_ex.fe_len < ac->ac_g_ex.fe_len) { | ||
3555 | int winl; | ||
3556 | int wins; | ||
3557 | int win; | ||
3558 | int offs; | ||
3559 | |||
3560 | /* we can't allocate as much as normalizer wants. | ||
3561 | * so, found space must get proper lstart | ||
3562 | * to cover original request */ | ||
3563 | BUG_ON(ac->ac_g_ex.fe_logical > ac->ac_o_ex.fe_logical); | ||
3564 | BUG_ON(ac->ac_g_ex.fe_len < ac->ac_o_ex.fe_len); | ||
3565 | |||
3566 | /* we're limited by original request in that | ||
3567 | * logical block must be covered any way | ||
3568 | * winl is window we can move our chunk within */ | ||
3569 | winl = ac->ac_o_ex.fe_logical - ac->ac_g_ex.fe_logical; | ||
3570 | |||
3571 | /* also, we should cover whole original request */ | ||
3572 | wins = ac->ac_b_ex.fe_len - ac->ac_o_ex.fe_len; | ||
3573 | |||
3574 | /* the smallest one defines real window */ | ||
3575 | win = min(winl, wins); | ||
3576 | |||
3577 | offs = ac->ac_o_ex.fe_logical % ac->ac_b_ex.fe_len; | ||
3578 | if (offs && offs < win) | ||
3579 | win = offs; | ||
3580 | |||
3581 | ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical - win; | ||
3582 | BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical); | ||
3583 | BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len); | ||
3584 | } | ||
3585 | |||
3586 | /* preallocation can change ac_b_ex, thus we store actually | ||
3587 | * allocated blocks for history */ | ||
3588 | ac->ac_f_ex = ac->ac_b_ex; | ||
3589 | |||
3590 | pa->pa_lstart = ac->ac_b_ex.fe_logical; | ||
3591 | pa->pa_pstart = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); | ||
3592 | pa->pa_len = ac->ac_b_ex.fe_len; | ||
3593 | pa->pa_free = pa->pa_len; | ||
3594 | atomic_set(&pa->pa_count, 1); | ||
3595 | spin_lock_init(&pa->pa_lock); | ||
3596 | pa->pa_deleted = 0; | ||
3597 | pa->pa_linear = 0; | ||
3598 | |||
3599 | mb_debug("new inode pa %p: %llu/%u for %u\n", pa, | ||
3600 | pa->pa_pstart, pa->pa_len, pa->pa_lstart); | ||
3601 | |||
3602 | ext4_mb_use_inode_pa(ac, pa); | ||
3603 | atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated); | ||
3604 | |||
3605 | ei = EXT4_I(ac->ac_inode); | ||
3606 | grp = ext4_get_group_info(sb, ac->ac_b_ex.fe_group); | ||
3607 | |||
3608 | pa->pa_obj_lock = &ei->i_prealloc_lock; | ||
3609 | pa->pa_inode = ac->ac_inode; | ||
3610 | |||
3611 | ext4_lock_group(sb, ac->ac_b_ex.fe_group); | ||
3612 | list_add(&pa->pa_group_list, &grp->bb_prealloc_list); | ||
3613 | ext4_unlock_group(sb, ac->ac_b_ex.fe_group); | ||
3614 | |||
3615 | spin_lock(pa->pa_obj_lock); | ||
3616 | list_add_rcu(&pa->pa_inode_list, &ei->i_prealloc_list); | ||
3617 | spin_unlock(pa->pa_obj_lock); | ||
3618 | |||
3619 | return 0; | ||
3620 | } | ||
3621 | |||
3622 | /* | ||
3623 | * creates new preallocated space for locality group inodes belongs to | ||
3624 | */ | ||
3625 | static int ext4_mb_new_group_pa(struct ext4_allocation_context *ac) | ||
3626 | { | ||
3627 | struct super_block *sb = ac->ac_sb; | ||
3628 | struct ext4_locality_group *lg; | ||
3629 | struct ext4_prealloc_space *pa; | ||
3630 | struct ext4_group_info *grp; | ||
3631 | |||
3632 | /* preallocate only when found space is larger then requested */ | ||
3633 | BUG_ON(ac->ac_o_ex.fe_len >= ac->ac_b_ex.fe_len); | ||
3634 | BUG_ON(ac->ac_status != AC_STATUS_FOUND); | ||
3635 | BUG_ON(!S_ISREG(ac->ac_inode->i_mode)); | ||
3636 | |||
3637 | BUG_ON(ext4_pspace_cachep == NULL); | ||
3638 | pa = kmem_cache_alloc(ext4_pspace_cachep, GFP_NOFS); | ||
3639 | if (pa == NULL) | ||
3640 | return -ENOMEM; | ||
3641 | |||
3642 | /* preallocation can change ac_b_ex, thus we store actually | ||
3643 | * allocated blocks for history */ | ||
3644 | ac->ac_f_ex = ac->ac_b_ex; | ||
3645 | |||
3646 | pa->pa_pstart = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); | ||
3647 | pa->pa_lstart = pa->pa_pstart; | ||
3648 | pa->pa_len = ac->ac_b_ex.fe_len; | ||
3649 | pa->pa_free = pa->pa_len; | ||
3650 | atomic_set(&pa->pa_count, 1); | ||
3651 | spin_lock_init(&pa->pa_lock); | ||
3652 | pa->pa_deleted = 0; | ||
3653 | pa->pa_linear = 1; | ||
3654 | |||
3655 | mb_debug("new group pa %p: %llu/%u for %u\n", pa, | ||
3656 | pa->pa_pstart, pa->pa_len, pa->pa_lstart); | ||
3657 | |||
3658 | ext4_mb_use_group_pa(ac, pa); | ||
3659 | atomic_add(pa->pa_free, &EXT4_SB(sb)->s_mb_preallocated); | ||
3660 | |||
3661 | grp = ext4_get_group_info(sb, ac->ac_b_ex.fe_group); | ||
3662 | lg = ac->ac_lg; | ||
3663 | BUG_ON(lg == NULL); | ||
3664 | |||
3665 | pa->pa_obj_lock = &lg->lg_prealloc_lock; | ||
3666 | pa->pa_inode = NULL; | ||
3667 | |||
3668 | ext4_lock_group(sb, ac->ac_b_ex.fe_group); | ||
3669 | list_add(&pa->pa_group_list, &grp->bb_prealloc_list); | ||
3670 | ext4_unlock_group(sb, ac->ac_b_ex.fe_group); | ||
3671 | |||
3672 | spin_lock(pa->pa_obj_lock); | ||
3673 | list_add_tail_rcu(&pa->pa_inode_list, &lg->lg_prealloc_list); | ||
3674 | spin_unlock(pa->pa_obj_lock); | ||
3675 | |||
3676 | return 0; | ||
3677 | } | ||
3678 | |||
3679 | static int ext4_mb_new_preallocation(struct ext4_allocation_context *ac) | ||
3680 | { | ||
3681 | int err; | ||
3682 | |||
3683 | if (ac->ac_flags & EXT4_MB_HINT_GROUP_ALLOC) | ||
3684 | err = ext4_mb_new_group_pa(ac); | ||
3685 | else | ||
3686 | err = ext4_mb_new_inode_pa(ac); | ||
3687 | return err; | ||
3688 | } | ||
3689 | |||
3690 | /* | ||
3691 | * finds all unused blocks in on-disk bitmap, frees them in | ||
3692 | * in-core bitmap and buddy. | ||
3693 | * @pa must be unlinked from inode and group lists, so that | ||
3694 | * nobody else can find/use it. | ||
3695 | * the caller MUST hold group/inode locks. | ||
3696 | * TODO: optimize the case when there are no in-core structures yet | ||
3697 | */ | ||
3698 | static int ext4_mb_release_inode_pa(struct ext4_buddy *e4b, | ||
3699 | struct buffer_head *bitmap_bh, | ||
3700 | struct ext4_prealloc_space *pa) | ||
3701 | { | ||
3702 | struct ext4_allocation_context ac; | ||
3703 | struct super_block *sb = e4b->bd_sb; | ||
3704 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
3705 | unsigned long end; | ||
3706 | unsigned long next; | ||
3707 | ext4_group_t group; | ||
3708 | ext4_grpblk_t bit; | ||
3709 | sector_t start; | ||
3710 | int err = 0; | ||
3711 | int free = 0; | ||
3712 | |||
3713 | BUG_ON(pa->pa_deleted == 0); | ||
3714 | ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit); | ||
3715 | BUG_ON(group != e4b->bd_group && pa->pa_len != 0); | ||
3716 | end = bit + pa->pa_len; | ||
3717 | |||
3718 | ac.ac_sb = sb; | ||
3719 | ac.ac_inode = pa->pa_inode; | ||
3720 | ac.ac_op = EXT4_MB_HISTORY_DISCARD; | ||
3721 | |||
3722 | while (bit < end) { | ||
3723 | bit = ext4_find_next_zero_bit(bitmap_bh->b_data, end, bit); | ||
3724 | if (bit >= end) | ||
3725 | break; | ||
3726 | next = ext4_find_next_bit(bitmap_bh->b_data, end, bit); | ||
3727 | if (next > end) | ||
3728 | next = end; | ||
3729 | start = group * EXT4_BLOCKS_PER_GROUP(sb) + bit + | ||
3730 | le32_to_cpu(sbi->s_es->s_first_data_block); | ||
3731 | mb_debug(" free preallocated %u/%u in group %u\n", | ||
3732 | (unsigned) start, (unsigned) next - bit, | ||
3733 | (unsigned) group); | ||
3734 | free += next - bit; | ||
3735 | |||
3736 | ac.ac_b_ex.fe_group = group; | ||
3737 | ac.ac_b_ex.fe_start = bit; | ||
3738 | ac.ac_b_ex.fe_len = next - bit; | ||
3739 | ac.ac_b_ex.fe_logical = 0; | ||
3740 | ext4_mb_store_history(&ac); | ||
3741 | |||
3742 | mb_free_blocks(pa->pa_inode, e4b, bit, next - bit); | ||
3743 | bit = next + 1; | ||
3744 | } | ||
3745 | if (free != pa->pa_free) { | ||
3746 | printk(KERN_ERR "pa %p: logic %lu, phys. %lu, len %lu\n", | ||
3747 | pa, (unsigned long) pa->pa_lstart, | ||
3748 | (unsigned long) pa->pa_pstart, | ||
3749 | (unsigned long) pa->pa_len); | ||
3750 | printk(KERN_ERR "free %u, pa_free %u\n", free, pa->pa_free); | ||
3751 | } | ||
3752 | BUG_ON(free != pa->pa_free); | ||
3753 | atomic_add(free, &sbi->s_mb_discarded); | ||
3754 | |||
3755 | return err; | ||
3756 | } | ||
3757 | |||
3758 | static int ext4_mb_release_group_pa(struct ext4_buddy *e4b, | ||
3759 | struct ext4_prealloc_space *pa) | ||
3760 | { | ||
3761 | struct ext4_allocation_context ac; | ||
3762 | struct super_block *sb = e4b->bd_sb; | ||
3763 | ext4_group_t group; | ||
3764 | ext4_grpblk_t bit; | ||
3765 | |||
3766 | ac.ac_op = EXT4_MB_HISTORY_DISCARD; | ||
3767 | |||
3768 | BUG_ON(pa->pa_deleted == 0); | ||
3769 | ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit); | ||
3770 | BUG_ON(group != e4b->bd_group && pa->pa_len != 0); | ||
3771 | mb_free_blocks(pa->pa_inode, e4b, bit, pa->pa_len); | ||
3772 | atomic_add(pa->pa_len, &EXT4_SB(sb)->s_mb_discarded); | ||
3773 | |||
3774 | ac.ac_sb = sb; | ||
3775 | ac.ac_inode = NULL; | ||
3776 | ac.ac_b_ex.fe_group = group; | ||
3777 | ac.ac_b_ex.fe_start = bit; | ||
3778 | ac.ac_b_ex.fe_len = pa->pa_len; | ||
3779 | ac.ac_b_ex.fe_logical = 0; | ||
3780 | ext4_mb_store_history(&ac); | ||
3781 | |||
3782 | return 0; | ||
3783 | } | ||
3784 | |||
3785 | /* | ||
3786 | * releases all preallocations in given group | ||
3787 | * | ||
3788 | * first, we need to decide discard policy: | ||
3789 | * - when do we discard | ||
3790 | * 1) ENOSPC | ||
3791 | * - how many do we discard | ||
3792 | * 1) how many requested | ||
3793 | */ | ||
3794 | static int ext4_mb_discard_group_preallocations(struct super_block *sb, | ||
3795 | ext4_group_t group, int needed) | ||
3796 | { | ||
3797 | struct ext4_group_info *grp = ext4_get_group_info(sb, group); | ||
3798 | struct buffer_head *bitmap_bh = NULL; | ||
3799 | struct ext4_prealloc_space *pa, *tmp; | ||
3800 | struct list_head list; | ||
3801 | struct ext4_buddy e4b; | ||
3802 | int err; | ||
3803 | int busy = 0; | ||
3804 | int free = 0; | ||
3805 | |||
3806 | mb_debug("discard preallocation for group %lu\n", group); | ||
3807 | |||
3808 | if (list_empty(&grp->bb_prealloc_list)) | ||
3809 | return 0; | ||
3810 | |||
3811 | bitmap_bh = read_block_bitmap(sb, group); | ||
3812 | if (bitmap_bh == NULL) { | ||
3813 | /* error handling here */ | ||
3814 | ext4_mb_release_desc(&e4b); | ||
3815 | BUG_ON(bitmap_bh == NULL); | ||
3816 | } | ||
3817 | |||
3818 | err = ext4_mb_load_buddy(sb, group, &e4b); | ||
3819 | BUG_ON(err != 0); /* error handling here */ | ||
3820 | |||
3821 | if (needed == 0) | ||
3822 | needed = EXT4_BLOCKS_PER_GROUP(sb) + 1; | ||
3823 | |||
3824 | grp = ext4_get_group_info(sb, group); | ||
3825 | INIT_LIST_HEAD(&list); | ||
3826 | |||
3827 | repeat: | ||
3828 | ext4_lock_group(sb, group); | ||
3829 | list_for_each_entry_safe(pa, tmp, | ||
3830 | &grp->bb_prealloc_list, pa_group_list) { | ||
3831 | spin_lock(&pa->pa_lock); | ||
3832 | if (atomic_read(&pa->pa_count)) { | ||
3833 | spin_unlock(&pa->pa_lock); | ||
3834 | busy = 1; | ||
3835 | continue; | ||
3836 | } | ||
3837 | if (pa->pa_deleted) { | ||
3838 | spin_unlock(&pa->pa_lock); | ||
3839 | continue; | ||
3840 | } | ||
3841 | |||
3842 | /* seems this one can be freed ... */ | ||
3843 | pa->pa_deleted = 1; | ||
3844 | |||
3845 | /* we can trust pa_free ... */ | ||
3846 | free += pa->pa_free; | ||
3847 | |||
3848 | spin_unlock(&pa->pa_lock); | ||
3849 | |||
3850 | list_del(&pa->pa_group_list); | ||
3851 | list_add(&pa->u.pa_tmp_list, &list); | ||
3852 | } | ||
3853 | |||
3854 | /* if we still need more blocks and some PAs were used, try again */ | ||
3855 | if (free < needed && busy) { | ||
3856 | busy = 0; | ||
3857 | ext4_unlock_group(sb, group); | ||
3858 | /* | ||
3859 | * Yield the CPU here so that we don't get soft lockup | ||
3860 | * in non preempt case. | ||
3861 | */ | ||
3862 | yield(); | ||
3863 | goto repeat; | ||
3864 | } | ||
3865 | |||
3866 | /* found anything to free? */ | ||
3867 | if (list_empty(&list)) { | ||
3868 | BUG_ON(free != 0); | ||
3869 | goto out; | ||
3870 | } | ||
3871 | |||
3872 | /* now free all selected PAs */ | ||
3873 | list_for_each_entry_safe(pa, tmp, &list, u.pa_tmp_list) { | ||
3874 | |||
3875 | /* remove from object (inode or locality group) */ | ||
3876 | spin_lock(pa->pa_obj_lock); | ||
3877 | list_del_rcu(&pa->pa_inode_list); | ||
3878 | spin_unlock(pa->pa_obj_lock); | ||
3879 | |||
3880 | if (pa->pa_linear) | ||
3881 | ext4_mb_release_group_pa(&e4b, pa); | ||
3882 | else | ||
3883 | ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa); | ||
3884 | |||
3885 | list_del(&pa->u.pa_tmp_list); | ||
3886 | call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback); | ||
3887 | } | ||
3888 | |||
3889 | out: | ||
3890 | ext4_unlock_group(sb, group); | ||
3891 | ext4_mb_release_desc(&e4b); | ||
3892 | put_bh(bitmap_bh); | ||
3893 | return free; | ||
3894 | } | ||
3895 | |||
3896 | /* | ||
3897 | * releases all non-used preallocated blocks for given inode | ||
3898 | * | ||
3899 | * It's important to discard preallocations under i_data_sem | ||
3900 | * We don't want another block to be served from the prealloc | ||
3901 | * space when we are discarding the inode prealloc space. | ||
3902 | * | ||
3903 | * FIXME!! Make sure it is valid at all the call sites | ||
3904 | */ | ||
3905 | void ext4_mb_discard_inode_preallocations(struct inode *inode) | ||
3906 | { | ||
3907 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
3908 | struct super_block *sb = inode->i_sb; | ||
3909 | struct buffer_head *bitmap_bh = NULL; | ||
3910 | struct ext4_prealloc_space *pa, *tmp; | ||
3911 | ext4_group_t group = 0; | ||
3912 | struct list_head list; | ||
3913 | struct ext4_buddy e4b; | ||
3914 | int err; | ||
3915 | |||
3916 | if (!test_opt(sb, MBALLOC) || !S_ISREG(inode->i_mode)) { | ||
3917 | /*BUG_ON(!list_empty(&ei->i_prealloc_list));*/ | ||
3918 | return; | ||
3919 | } | ||
3920 | |||
3921 | mb_debug("discard preallocation for inode %lu\n", inode->i_ino); | ||
3922 | |||
3923 | INIT_LIST_HEAD(&list); | ||
3924 | |||
3925 | repeat: | ||
3926 | /* first, collect all pa's in the inode */ | ||
3927 | spin_lock(&ei->i_prealloc_lock); | ||
3928 | while (!list_empty(&ei->i_prealloc_list)) { | ||
3929 | pa = list_entry(ei->i_prealloc_list.next, | ||
3930 | struct ext4_prealloc_space, pa_inode_list); | ||
3931 | BUG_ON(pa->pa_obj_lock != &ei->i_prealloc_lock); | ||
3932 | spin_lock(&pa->pa_lock); | ||
3933 | if (atomic_read(&pa->pa_count)) { | ||
3934 | /* this shouldn't happen often - nobody should | ||
3935 | * use preallocation while we're discarding it */ | ||
3936 | spin_unlock(&pa->pa_lock); | ||
3937 | spin_unlock(&ei->i_prealloc_lock); | ||
3938 | printk(KERN_ERR "uh-oh! used pa while discarding\n"); | ||
3939 | WARN_ON(1); | ||
3940 | schedule_timeout_uninterruptible(HZ); | ||
3941 | goto repeat; | ||
3942 | |||
3943 | } | ||
3944 | if (pa->pa_deleted == 0) { | ||
3945 | pa->pa_deleted = 1; | ||
3946 | spin_unlock(&pa->pa_lock); | ||
3947 | list_del_rcu(&pa->pa_inode_list); | ||
3948 | list_add(&pa->u.pa_tmp_list, &list); | ||
3949 | continue; | ||
3950 | } | ||
3951 | |||
3952 | /* someone is deleting pa right now */ | ||
3953 | spin_unlock(&pa->pa_lock); | ||
3954 | spin_unlock(&ei->i_prealloc_lock); | ||
3955 | |||
3956 | /* we have to wait here because pa_deleted | ||
3957 | * doesn't mean pa is already unlinked from | ||
3958 | * the list. as we might be called from | ||
3959 | * ->clear_inode() the inode will get freed | ||
3960 | * and concurrent thread which is unlinking | ||
3961 | * pa from inode's list may access already | ||
3962 | * freed memory, bad-bad-bad */ | ||
3963 | |||
3964 | /* XXX: if this happens too often, we can | ||
3965 | * add a flag to force wait only in case | ||
3966 | * of ->clear_inode(), but not in case of | ||
3967 | * regular truncate */ | ||
3968 | schedule_timeout_uninterruptible(HZ); | ||
3969 | goto repeat; | ||
3970 | } | ||
3971 | spin_unlock(&ei->i_prealloc_lock); | ||
3972 | |||
3973 | list_for_each_entry_safe(pa, tmp, &list, u.pa_tmp_list) { | ||
3974 | BUG_ON(pa->pa_linear != 0); | ||
3975 | ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, NULL); | ||
3976 | |||
3977 | err = ext4_mb_load_buddy(sb, group, &e4b); | ||
3978 | BUG_ON(err != 0); /* error handling here */ | ||
3979 | |||
3980 | bitmap_bh = read_block_bitmap(sb, group); | ||
3981 | if (bitmap_bh == NULL) { | ||
3982 | /* error handling here */ | ||
3983 | ext4_mb_release_desc(&e4b); | ||
3984 | BUG_ON(bitmap_bh == NULL); | ||
3985 | } | ||
3986 | |||
3987 | ext4_lock_group(sb, group); | ||
3988 | list_del(&pa->pa_group_list); | ||
3989 | ext4_mb_release_inode_pa(&e4b, bitmap_bh, pa); | ||
3990 | ext4_unlock_group(sb, group); | ||
3991 | |||
3992 | ext4_mb_release_desc(&e4b); | ||
3993 | put_bh(bitmap_bh); | ||
3994 | |||
3995 | list_del(&pa->u.pa_tmp_list); | ||
3996 | call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback); | ||
3997 | } | ||
3998 | } | ||
3999 | |||
4000 | /* | ||
4001 | * finds all preallocated spaces and return blocks being freed to them | ||
4002 | * if preallocated space becomes full (no block is used from the space) | ||
4003 | * then the function frees space in buddy | ||
4004 | * XXX: at the moment, truncate (which is the only way to free blocks) | ||
4005 | * discards all preallocations | ||
4006 | */ | ||
4007 | static void ext4_mb_return_to_preallocation(struct inode *inode, | ||
4008 | struct ext4_buddy *e4b, | ||
4009 | sector_t block, int count) | ||
4010 | { | ||
4011 | BUG_ON(!list_empty(&EXT4_I(inode)->i_prealloc_list)); | ||
4012 | } | ||
4013 | #ifdef MB_DEBUG | ||
4014 | static void ext4_mb_show_ac(struct ext4_allocation_context *ac) | ||
4015 | { | ||
4016 | struct super_block *sb = ac->ac_sb; | ||
4017 | ext4_group_t i; | ||
4018 | |||
4019 | printk(KERN_ERR "EXT4-fs: Can't allocate:" | ||
4020 | " Allocation context details:\n"); | ||
4021 | printk(KERN_ERR "EXT4-fs: status %d flags %d\n", | ||
4022 | ac->ac_status, ac->ac_flags); | ||
4023 | printk(KERN_ERR "EXT4-fs: orig %lu/%lu/%lu@%lu, goal %lu/%lu/%lu@%lu, " | ||
4024 | "best %lu/%lu/%lu@%lu cr %d\n", | ||
4025 | (unsigned long)ac->ac_o_ex.fe_group, | ||
4026 | (unsigned long)ac->ac_o_ex.fe_start, | ||
4027 | (unsigned long)ac->ac_o_ex.fe_len, | ||
4028 | (unsigned long)ac->ac_o_ex.fe_logical, | ||
4029 | (unsigned long)ac->ac_g_ex.fe_group, | ||
4030 | (unsigned long)ac->ac_g_ex.fe_start, | ||
4031 | (unsigned long)ac->ac_g_ex.fe_len, | ||
4032 | (unsigned long)ac->ac_g_ex.fe_logical, | ||
4033 | (unsigned long)ac->ac_b_ex.fe_group, | ||
4034 | (unsigned long)ac->ac_b_ex.fe_start, | ||
4035 | (unsigned long)ac->ac_b_ex.fe_len, | ||
4036 | (unsigned long)ac->ac_b_ex.fe_logical, | ||
4037 | (int)ac->ac_criteria); | ||
4038 | printk(KERN_ERR "EXT4-fs: %lu scanned, %d found\n", ac->ac_ex_scanned, | ||
4039 | ac->ac_found); | ||
4040 | printk(KERN_ERR "EXT4-fs: groups: \n"); | ||
4041 | for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) { | ||
4042 | struct ext4_group_info *grp = ext4_get_group_info(sb, i); | ||
4043 | struct ext4_prealloc_space *pa; | ||
4044 | ext4_grpblk_t start; | ||
4045 | struct list_head *cur; | ||
4046 | ext4_lock_group(sb, i); | ||
4047 | list_for_each(cur, &grp->bb_prealloc_list) { | ||
4048 | pa = list_entry(cur, struct ext4_prealloc_space, | ||
4049 | pa_group_list); | ||
4050 | spin_lock(&pa->pa_lock); | ||
4051 | ext4_get_group_no_and_offset(sb, pa->pa_pstart, | ||
4052 | NULL, &start); | ||
4053 | spin_unlock(&pa->pa_lock); | ||
4054 | printk(KERN_ERR "PA:%lu:%d:%u \n", i, | ||
4055 | start, pa->pa_len); | ||
4056 | } | ||
4057 | ext4_lock_group(sb, i); | ||
4058 | |||
4059 | if (grp->bb_free == 0) | ||
4060 | continue; | ||
4061 | printk(KERN_ERR "%lu: %d/%d \n", | ||
4062 | i, grp->bb_free, grp->bb_fragments); | ||
4063 | } | ||
4064 | printk(KERN_ERR "\n"); | ||
4065 | } | ||
4066 | #else | ||
4067 | static inline void ext4_mb_show_ac(struct ext4_allocation_context *ac) | ||
4068 | { | ||
4069 | return; | ||
4070 | } | ||
4071 | #endif | ||
4072 | |||
4073 | /* | ||
4074 | * We use locality group preallocation for small size file. The size of the | ||
4075 | * file is determined by the current size or the resulting size after | ||
4076 | * allocation which ever is larger | ||
4077 | * | ||
4078 | * One can tune this size via /proc/fs/ext4/<partition>/stream_req | ||
4079 | */ | ||
4080 | static void ext4_mb_group_or_file(struct ext4_allocation_context *ac) | ||
4081 | { | ||
4082 | struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); | ||
4083 | int bsbits = ac->ac_sb->s_blocksize_bits; | ||
4084 | loff_t size, isize; | ||
4085 | |||
4086 | if (!(ac->ac_flags & EXT4_MB_HINT_DATA)) | ||
4087 | return; | ||
4088 | |||
4089 | size = ac->ac_o_ex.fe_logical + ac->ac_o_ex.fe_len; | ||
4090 | isize = i_size_read(ac->ac_inode) >> bsbits; | ||
4091 | size = max(size, isize); | ||
4092 | |||
4093 | /* don't use group allocation for large files */ | ||
4094 | if (size >= sbi->s_mb_stream_request) | ||
4095 | return; | ||
4096 | |||
4097 | if (unlikely(ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY)) | ||
4098 | return; | ||
4099 | |||
4100 | BUG_ON(ac->ac_lg != NULL); | ||
4101 | /* | ||
4102 | * locality group prealloc space are per cpu. The reason for having | ||
4103 | * per cpu locality group is to reduce the contention between block | ||
4104 | * request from multiple CPUs. | ||
4105 | */ | ||
4106 | ac->ac_lg = &sbi->s_locality_groups[get_cpu()]; | ||
4107 | put_cpu(); | ||
4108 | |||
4109 | /* we're going to use group allocation */ | ||
4110 | ac->ac_flags |= EXT4_MB_HINT_GROUP_ALLOC; | ||
4111 | |||
4112 | /* serialize all allocations in the group */ | ||
4113 | mutex_lock(&ac->ac_lg->lg_mutex); | ||
4114 | } | ||
4115 | |||
4116 | static int ext4_mb_initialize_context(struct ext4_allocation_context *ac, | ||
4117 | struct ext4_allocation_request *ar) | ||
4118 | { | ||
4119 | struct super_block *sb = ar->inode->i_sb; | ||
4120 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
4121 | struct ext4_super_block *es = sbi->s_es; | ||
4122 | ext4_group_t group; | ||
4123 | unsigned long len; | ||
4124 | unsigned long goal; | ||
4125 | ext4_grpblk_t block; | ||
4126 | |||
4127 | /* we can't allocate > group size */ | ||
4128 | len = ar->len; | ||
4129 | |||
4130 | /* just a dirty hack to filter too big requests */ | ||
4131 | if (len >= EXT4_BLOCKS_PER_GROUP(sb) - 10) | ||
4132 | len = EXT4_BLOCKS_PER_GROUP(sb) - 10; | ||
4133 | |||
4134 | /* start searching from the goal */ | ||
4135 | goal = ar->goal; | ||
4136 | if (goal < le32_to_cpu(es->s_first_data_block) || | ||
4137 | goal >= ext4_blocks_count(es)) | ||
4138 | goal = le32_to_cpu(es->s_first_data_block); | ||
4139 | ext4_get_group_no_and_offset(sb, goal, &group, &block); | ||
4140 | |||
4141 | /* set up allocation goals */ | ||
4142 | ac->ac_b_ex.fe_logical = ar->logical; | ||
4143 | ac->ac_b_ex.fe_group = 0; | ||
4144 | ac->ac_b_ex.fe_start = 0; | ||
4145 | ac->ac_b_ex.fe_len = 0; | ||
4146 | ac->ac_status = AC_STATUS_CONTINUE; | ||
4147 | ac->ac_groups_scanned = 0; | ||
4148 | ac->ac_ex_scanned = 0; | ||
4149 | ac->ac_found = 0; | ||
4150 | ac->ac_sb = sb; | ||
4151 | ac->ac_inode = ar->inode; | ||
4152 | ac->ac_o_ex.fe_logical = ar->logical; | ||
4153 | ac->ac_o_ex.fe_group = group; | ||
4154 | ac->ac_o_ex.fe_start = block; | ||
4155 | ac->ac_o_ex.fe_len = len; | ||
4156 | ac->ac_g_ex.fe_logical = ar->logical; | ||
4157 | ac->ac_g_ex.fe_group = group; | ||
4158 | ac->ac_g_ex.fe_start = block; | ||
4159 | ac->ac_g_ex.fe_len = len; | ||
4160 | ac->ac_f_ex.fe_len = 0; | ||
4161 | ac->ac_flags = ar->flags; | ||
4162 | ac->ac_2order = 0; | ||
4163 | ac->ac_criteria = 0; | ||
4164 | ac->ac_pa = NULL; | ||
4165 | ac->ac_bitmap_page = NULL; | ||
4166 | ac->ac_buddy_page = NULL; | ||
4167 | ac->ac_lg = NULL; | ||
4168 | |||
4169 | /* we have to define context: we'll we work with a file or | ||
4170 | * locality group. this is a policy, actually */ | ||
4171 | ext4_mb_group_or_file(ac); | ||
4172 | |||
4173 | mb_debug("init ac: %u blocks @ %u, goal %u, flags %x, 2^%d, " | ||
4174 | "left: %u/%u, right %u/%u to %swritable\n", | ||
4175 | (unsigned) ar->len, (unsigned) ar->logical, | ||
4176 | (unsigned) ar->goal, ac->ac_flags, ac->ac_2order, | ||
4177 | (unsigned) ar->lleft, (unsigned) ar->pleft, | ||
4178 | (unsigned) ar->lright, (unsigned) ar->pright, | ||
4179 | atomic_read(&ar->inode->i_writecount) ? "" : "non-"); | ||
4180 | return 0; | ||
4181 | |||
4182 | } | ||
4183 | |||
4184 | /* | ||
4185 | * release all resource we used in allocation | ||
4186 | */ | ||
4187 | static int ext4_mb_release_context(struct ext4_allocation_context *ac) | ||
4188 | { | ||
4189 | if (ac->ac_pa) { | ||
4190 | if (ac->ac_pa->pa_linear) { | ||
4191 | /* see comment in ext4_mb_use_group_pa() */ | ||
4192 | spin_lock(&ac->ac_pa->pa_lock); | ||
4193 | ac->ac_pa->pa_pstart += ac->ac_b_ex.fe_len; | ||
4194 | ac->ac_pa->pa_lstart += ac->ac_b_ex.fe_len; | ||
4195 | ac->ac_pa->pa_free -= ac->ac_b_ex.fe_len; | ||
4196 | ac->ac_pa->pa_len -= ac->ac_b_ex.fe_len; | ||
4197 | spin_unlock(&ac->ac_pa->pa_lock); | ||
4198 | } | ||
4199 | ext4_mb_put_pa(ac, ac->ac_sb, ac->ac_pa); | ||
4200 | } | ||
4201 | if (ac->ac_bitmap_page) | ||
4202 | page_cache_release(ac->ac_bitmap_page); | ||
4203 | if (ac->ac_buddy_page) | ||
4204 | page_cache_release(ac->ac_buddy_page); | ||
4205 | if (ac->ac_flags & EXT4_MB_HINT_GROUP_ALLOC) | ||
4206 | mutex_unlock(&ac->ac_lg->lg_mutex); | ||
4207 | ext4_mb_collect_stats(ac); | ||
4208 | return 0; | ||
4209 | } | ||
4210 | |||
4211 | static int ext4_mb_discard_preallocations(struct super_block *sb, int needed) | ||
4212 | { | ||
4213 | ext4_group_t i; | ||
4214 | int ret; | ||
4215 | int freed = 0; | ||
4216 | |||
4217 | for (i = 0; i < EXT4_SB(sb)->s_groups_count && needed > 0; i++) { | ||
4218 | ret = ext4_mb_discard_group_preallocations(sb, i, needed); | ||
4219 | freed += ret; | ||
4220 | needed -= ret; | ||
4221 | } | ||
4222 | |||
4223 | return freed; | ||
4224 | } | ||
4225 | |||
4226 | /* | ||
4227 | * Main entry point into mballoc to allocate blocks | ||
4228 | * it tries to use preallocation first, then falls back | ||
4229 | * to usual allocation | ||
4230 | */ | ||
4231 | ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | ||
4232 | struct ext4_allocation_request *ar, int *errp) | ||
4233 | { | ||
4234 | struct ext4_allocation_context ac; | ||
4235 | struct ext4_sb_info *sbi; | ||
4236 | struct super_block *sb; | ||
4237 | ext4_fsblk_t block = 0; | ||
4238 | int freed; | ||
4239 | int inquota; | ||
4240 | |||
4241 | sb = ar->inode->i_sb; | ||
4242 | sbi = EXT4_SB(sb); | ||
4243 | |||
4244 | if (!test_opt(sb, MBALLOC)) { | ||
4245 | block = ext4_new_blocks_old(handle, ar->inode, ar->goal, | ||
4246 | &(ar->len), errp); | ||
4247 | return block; | ||
4248 | } | ||
4249 | |||
4250 | while (ar->len && DQUOT_ALLOC_BLOCK(ar->inode, ar->len)) { | ||
4251 | ar->flags |= EXT4_MB_HINT_NOPREALLOC; | ||
4252 | ar->len--; | ||
4253 | } | ||
4254 | if (ar->len == 0) { | ||
4255 | *errp = -EDQUOT; | ||
4256 | return 0; | ||
4257 | } | ||
4258 | inquota = ar->len; | ||
4259 | |||
4260 | ext4_mb_poll_new_transaction(sb, handle); | ||
4261 | |||
4262 | *errp = ext4_mb_initialize_context(&ac, ar); | ||
4263 | if (*errp) { | ||
4264 | ar->len = 0; | ||
4265 | goto out; | ||
4266 | } | ||
4267 | |||
4268 | ac.ac_op = EXT4_MB_HISTORY_PREALLOC; | ||
4269 | if (!ext4_mb_use_preallocated(&ac)) { | ||
4270 | |||
4271 | ac.ac_op = EXT4_MB_HISTORY_ALLOC; | ||
4272 | ext4_mb_normalize_request(&ac, ar); | ||
4273 | |||
4274 | repeat: | ||
4275 | /* allocate space in core */ | ||
4276 | ext4_mb_regular_allocator(&ac); | ||
4277 | |||
4278 | /* as we've just preallocated more space than | ||
4279 | * user requested orinally, we store allocated | ||
4280 | * space in a special descriptor */ | ||
4281 | if (ac.ac_status == AC_STATUS_FOUND && | ||
4282 | ac.ac_o_ex.fe_len < ac.ac_b_ex.fe_len) | ||
4283 | ext4_mb_new_preallocation(&ac); | ||
4284 | } | ||
4285 | |||
4286 | if (likely(ac.ac_status == AC_STATUS_FOUND)) { | ||
4287 | ext4_mb_mark_diskspace_used(&ac, handle); | ||
4288 | *errp = 0; | ||
4289 | block = ext4_grp_offs_to_block(sb, &ac.ac_b_ex); | ||
4290 | ar->len = ac.ac_b_ex.fe_len; | ||
4291 | } else { | ||
4292 | freed = ext4_mb_discard_preallocations(sb, ac.ac_o_ex.fe_len); | ||
4293 | if (freed) | ||
4294 | goto repeat; | ||
4295 | *errp = -ENOSPC; | ||
4296 | ac.ac_b_ex.fe_len = 0; | ||
4297 | ar->len = 0; | ||
4298 | ext4_mb_show_ac(&ac); | ||
4299 | } | ||
4300 | |||
4301 | ext4_mb_release_context(&ac); | ||
4302 | |||
4303 | out: | ||
4304 | if (ar->len < inquota) | ||
4305 | DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len); | ||
4306 | |||
4307 | return block; | ||
4308 | } | ||
4309 | static void ext4_mb_poll_new_transaction(struct super_block *sb, | ||
4310 | handle_t *handle) | ||
4311 | { | ||
4312 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
4313 | |||
4314 | if (sbi->s_last_transaction == handle->h_transaction->t_tid) | ||
4315 | return; | ||
4316 | |||
4317 | /* new transaction! time to close last one and free blocks for | ||
4318 | * committed transaction. we know that only transaction can be | ||
4319 | * active, so previos transaction can be being logged and we | ||
4320 | * know that transaction before previous is known to be already | ||
4321 | * logged. this means that now we may free blocks freed in all | ||
4322 | * transactions before previous one. hope I'm clear enough ... */ | ||
4323 | |||
4324 | spin_lock(&sbi->s_md_lock); | ||
4325 | if (sbi->s_last_transaction != handle->h_transaction->t_tid) { | ||
4326 | mb_debug("new transaction %lu, old %lu\n", | ||
4327 | (unsigned long) handle->h_transaction->t_tid, | ||
4328 | (unsigned long) sbi->s_last_transaction); | ||
4329 | list_splice_init(&sbi->s_closed_transaction, | ||
4330 | &sbi->s_committed_transaction); | ||
4331 | list_splice_init(&sbi->s_active_transaction, | ||
4332 | &sbi->s_closed_transaction); | ||
4333 | sbi->s_last_transaction = handle->h_transaction->t_tid; | ||
4334 | } | ||
4335 | spin_unlock(&sbi->s_md_lock); | ||
4336 | |||
4337 | ext4_mb_free_committed_blocks(sb); | ||
4338 | } | ||
4339 | |||
4340 | static int ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, | ||
4341 | ext4_group_t group, ext4_grpblk_t block, int count) | ||
4342 | { | ||
4343 | struct ext4_group_info *db = e4b->bd_info; | ||
4344 | struct super_block *sb = e4b->bd_sb; | ||
4345 | struct ext4_sb_info *sbi = EXT4_SB(sb); | ||
4346 | struct ext4_free_metadata *md; | ||
4347 | int i; | ||
4348 | |||
4349 | BUG_ON(e4b->bd_bitmap_page == NULL); | ||
4350 | BUG_ON(e4b->bd_buddy_page == NULL); | ||
4351 | |||
4352 | ext4_lock_group(sb, group); | ||
4353 | for (i = 0; i < count; i++) { | ||
4354 | md = db->bb_md_cur; | ||
4355 | if (md && db->bb_tid != handle->h_transaction->t_tid) { | ||
4356 | db->bb_md_cur = NULL; | ||
4357 | md = NULL; | ||
4358 | } | ||
4359 | |||
4360 | if (md == NULL) { | ||
4361 | ext4_unlock_group(sb, group); | ||
4362 | md = kmalloc(sizeof(*md), GFP_NOFS); | ||
4363 | if (md == NULL) | ||
4364 | return -ENOMEM; | ||
4365 | md->num = 0; | ||
4366 | md->group = group; | ||
4367 | |||
4368 | ext4_lock_group(sb, group); | ||
4369 | if (db->bb_md_cur == NULL) { | ||
4370 | spin_lock(&sbi->s_md_lock); | ||
4371 | list_add(&md->list, &sbi->s_active_transaction); | ||
4372 | spin_unlock(&sbi->s_md_lock); | ||
4373 | /* protect buddy cache from being freed, | ||
4374 | * otherwise we'll refresh it from | ||
4375 | * on-disk bitmap and lose not-yet-available | ||
4376 | * blocks */ | ||
4377 | page_cache_get(e4b->bd_buddy_page); | ||
4378 | page_cache_get(e4b->bd_bitmap_page); | ||
4379 | db->bb_md_cur = md; | ||
4380 | db->bb_tid = handle->h_transaction->t_tid; | ||
4381 | mb_debug("new md 0x%p for group %lu\n", | ||
4382 | md, md->group); | ||
4383 | } else { | ||
4384 | kfree(md); | ||
4385 | md = db->bb_md_cur; | ||
4386 | } | ||
4387 | } | ||
4388 | |||
4389 | BUG_ON(md->num >= EXT4_BB_MAX_BLOCKS); | ||
4390 | md->blocks[md->num] = block + i; | ||
4391 | md->num++; | ||
4392 | if (md->num == EXT4_BB_MAX_BLOCKS) { | ||
4393 | /* no more space, put full container on a sb's list */ | ||
4394 | db->bb_md_cur = NULL; | ||
4395 | } | ||
4396 | } | ||
4397 | ext4_unlock_group(sb, group); | ||
4398 | return 0; | ||
4399 | } | ||
4400 | |||
4401 | /* | ||
4402 | * Main entry point into mballoc to free blocks | ||
4403 | */ | ||
4404 | void ext4_mb_free_blocks(handle_t *handle, struct inode *inode, | ||
4405 | unsigned long block, unsigned long count, | ||
4406 | int metadata, unsigned long *freed) | ||
4407 | { | ||
4408 | struct buffer_head *bitmap_bh = 0; | ||
4409 | struct super_block *sb = inode->i_sb; | ||
4410 | struct ext4_allocation_context ac; | ||
4411 | struct ext4_group_desc *gdp; | ||
4412 | struct ext4_super_block *es; | ||
4413 | unsigned long overflow; | ||
4414 | ext4_grpblk_t bit; | ||
4415 | struct buffer_head *gd_bh; | ||
4416 | ext4_group_t block_group; | ||
4417 | struct ext4_sb_info *sbi; | ||
4418 | struct ext4_buddy e4b; | ||
4419 | int err = 0; | ||
4420 | int ret; | ||
4421 | |||
4422 | *freed = 0; | ||
4423 | |||
4424 | ext4_mb_poll_new_transaction(sb, handle); | ||
4425 | |||
4426 | sbi = EXT4_SB(sb); | ||
4427 | es = EXT4_SB(sb)->s_es; | ||
4428 | if (block < le32_to_cpu(es->s_first_data_block) || | ||
4429 | block + count < block || | ||
4430 | block + count > ext4_blocks_count(es)) { | ||
4431 | ext4_error(sb, __FUNCTION__, | ||
4432 | "Freeing blocks not in datazone - " | ||
4433 | "block = %lu, count = %lu", block, count); | ||
4434 | goto error_return; | ||
4435 | } | ||
4436 | |||
4437 | ext4_debug("freeing block %lu\n", block); | ||
4438 | |||
4439 | ac.ac_op = EXT4_MB_HISTORY_FREE; | ||
4440 | ac.ac_inode = inode; | ||
4441 | ac.ac_sb = sb; | ||
4442 | |||
4443 | do_more: | ||
4444 | overflow = 0; | ||
4445 | ext4_get_group_no_and_offset(sb, block, &block_group, &bit); | ||
4446 | |||
4447 | /* | ||
4448 | * Check to see if we are freeing blocks across a group | ||
4449 | * boundary. | ||
4450 | */ | ||
4451 | if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) { | ||
4452 | overflow = bit + count - EXT4_BLOCKS_PER_GROUP(sb); | ||
4453 | count -= overflow; | ||
4454 | } | ||
4455 | bitmap_bh = read_block_bitmap(sb, block_group); | ||
4456 | if (!bitmap_bh) | ||
4457 | goto error_return; | ||
4458 | gdp = ext4_get_group_desc(sb, block_group, &gd_bh); | ||
4459 | if (!gdp) | ||
4460 | goto error_return; | ||
4461 | |||
4462 | if (in_range(ext4_block_bitmap(sb, gdp), block, count) || | ||
4463 | in_range(ext4_inode_bitmap(sb, gdp), block, count) || | ||
4464 | in_range(block, ext4_inode_table(sb, gdp), | ||
4465 | EXT4_SB(sb)->s_itb_per_group) || | ||
4466 | in_range(block + count - 1, ext4_inode_table(sb, gdp), | ||
4467 | EXT4_SB(sb)->s_itb_per_group)) { | ||
4468 | |||
4469 | ext4_error(sb, __FUNCTION__, | ||
4470 | "Freeing blocks in system zone - " | ||
4471 | "Block = %lu, count = %lu", block, count); | ||
4472 | } | ||
4473 | |||
4474 | BUFFER_TRACE(bitmap_bh, "getting write access"); | ||
4475 | err = ext4_journal_get_write_access(handle, bitmap_bh); | ||
4476 | if (err) | ||
4477 | goto error_return; | ||
4478 | |||
4479 | /* | ||
4480 | * We are about to modify some metadata. Call the journal APIs | ||
4481 | * to unshare ->b_data if a currently-committing transaction is | ||
4482 | * using it | ||
4483 | */ | ||
4484 | BUFFER_TRACE(gd_bh, "get_write_access"); | ||
4485 | err = ext4_journal_get_write_access(handle, gd_bh); | ||
4486 | if (err) | ||
4487 | goto error_return; | ||
4488 | |||
4489 | err = ext4_mb_load_buddy(sb, block_group, &e4b); | ||
4490 | if (err) | ||
4491 | goto error_return; | ||
4492 | |||
4493 | #ifdef AGGRESSIVE_CHECK | ||
4494 | { | ||
4495 | int i; | ||
4496 | for (i = 0; i < count; i++) | ||
4497 | BUG_ON(!mb_test_bit(bit + i, bitmap_bh->b_data)); | ||
4498 | } | ||
4499 | #endif | ||
4500 | mb_clear_bits(sb_bgl_lock(sbi, block_group), bitmap_bh->b_data, | ||
4501 | bit, count); | ||
4502 | |||
4503 | /* We dirtied the bitmap block */ | ||
4504 | BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); | ||
4505 | err = ext4_journal_dirty_metadata(handle, bitmap_bh); | ||
4506 | |||
4507 | ac.ac_b_ex.fe_group = block_group; | ||
4508 | ac.ac_b_ex.fe_start = bit; | ||
4509 | ac.ac_b_ex.fe_len = count; | ||
4510 | ext4_mb_store_history(&ac); | ||
4511 | |||
4512 | if (metadata) { | ||
4513 | /* blocks being freed are metadata. these blocks shouldn't | ||
4514 | * be used until this transaction is committed */ | ||
4515 | ext4_mb_free_metadata(handle, &e4b, block_group, bit, count); | ||
4516 | } else { | ||
4517 | ext4_lock_group(sb, block_group); | ||
4518 | err = mb_free_blocks(inode, &e4b, bit, count); | ||
4519 | ext4_mb_return_to_preallocation(inode, &e4b, block, count); | ||
4520 | ext4_unlock_group(sb, block_group); | ||
4521 | BUG_ON(err != 0); | ||
4522 | } | ||
4523 | |||
4524 | spin_lock(sb_bgl_lock(sbi, block_group)); | ||
4525 | gdp->bg_free_blocks_count = | ||
4526 | cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) + count); | ||
4527 | gdp->bg_checksum = ext4_group_desc_csum(sbi, block_group, gdp); | ||
4528 | spin_unlock(sb_bgl_lock(sbi, block_group)); | ||
4529 | percpu_counter_add(&sbi->s_freeblocks_counter, count); | ||
4530 | |||
4531 | ext4_mb_release_desc(&e4b); | ||
4532 | |||
4533 | *freed += count; | ||
4534 | |||
4535 | /* And the group descriptor block */ | ||
4536 | BUFFER_TRACE(gd_bh, "dirtied group descriptor block"); | ||
4537 | ret = ext4_journal_dirty_metadata(handle, gd_bh); | ||
4538 | if (!err) | ||
4539 | err = ret; | ||
4540 | |||
4541 | if (overflow && !err) { | ||
4542 | block += count; | ||
4543 | count = overflow; | ||
4544 | put_bh(bitmap_bh); | ||
4545 | goto do_more; | ||
4546 | } | ||
4547 | sb->s_dirt = 1; | ||
4548 | error_return: | ||
4549 | brelse(bitmap_bh); | ||
4550 | ext4_std_error(sb, err); | ||
4551 | return; | ||
4552 | } | ||
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c new file mode 100644 index 000000000000..3ebc2332f52e --- /dev/null +++ b/fs/ext4/migrate.c | |||
@@ -0,0 +1,560 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corporation, 2007 | ||
3 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2.1 of the GNU Lesser General Public License | ||
7 | * as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/ext4_jbd2.h> | ||
17 | #include <linux/ext4_fs_extents.h> | ||
18 | |||
19 | /* | ||
20 | * The contiguous blocks details which can be | ||
21 | * represented by a single extent | ||
22 | */ | ||
23 | struct list_blocks_struct { | ||
24 | ext4_lblk_t first_block, last_block; | ||
25 | ext4_fsblk_t first_pblock, last_pblock; | ||
26 | }; | ||
27 | |||
28 | static int finish_range(handle_t *handle, struct inode *inode, | ||
29 | struct list_blocks_struct *lb) | ||
30 | |||
31 | { | ||
32 | int retval = 0, needed; | ||
33 | struct ext4_extent newext; | ||
34 | struct ext4_ext_path *path; | ||
35 | if (lb->first_pblock == 0) | ||
36 | return 0; | ||
37 | |||
38 | /* Add the extent to temp inode*/ | ||
39 | newext.ee_block = cpu_to_le32(lb->first_block); | ||
40 | newext.ee_len = cpu_to_le16(lb->last_block - lb->first_block + 1); | ||
41 | ext4_ext_store_pblock(&newext, lb->first_pblock); | ||
42 | path = ext4_ext_find_extent(inode, lb->first_block, NULL); | ||
43 | |||
44 | if (IS_ERR(path)) { | ||
45 | retval = PTR_ERR(path); | ||
46 | goto err_out; | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | * Calculate the credit needed to inserting this extent | ||
51 | * Since we are doing this in loop we may accumalate extra | ||
52 | * credit. But below we try to not accumalate too much | ||
53 | * of them by restarting the journal. | ||
54 | */ | ||
55 | needed = ext4_ext_calc_credits_for_insert(inode, path); | ||
56 | |||
57 | /* | ||
58 | * Make sure the credit we accumalated is not really high | ||
59 | */ | ||
60 | if (needed && handle->h_buffer_credits >= EXT4_RESERVE_TRANS_BLOCKS) { | ||
61 | retval = ext4_journal_restart(handle, needed); | ||
62 | if (retval) | ||
63 | goto err_out; | ||
64 | } | ||
65 | if (needed) { | ||
66 | retval = ext4_journal_extend(handle, needed); | ||
67 | if (retval != 0) { | ||
68 | /* | ||
69 | * IF not able to extend the journal restart the journal | ||
70 | */ | ||
71 | retval = ext4_journal_restart(handle, needed); | ||
72 | if (retval) | ||
73 | goto err_out; | ||
74 | } | ||
75 | } | ||
76 | retval = ext4_ext_insert_extent(handle, inode, path, &newext); | ||
77 | err_out: | ||
78 | lb->first_pblock = 0; | ||
79 | return retval; | ||
80 | } | ||
81 | |||
82 | static int update_extent_range(handle_t *handle, struct inode *inode, | ||
83 | ext4_fsblk_t pblock, ext4_lblk_t blk_num, | ||
84 | struct list_blocks_struct *lb) | ||
85 | { | ||
86 | int retval; | ||
87 | /* | ||
88 | * See if we can add on to the existing range (if it exists) | ||
89 | */ | ||
90 | if (lb->first_pblock && | ||
91 | (lb->last_pblock+1 == pblock) && | ||
92 | (lb->last_block+1 == blk_num)) { | ||
93 | lb->last_pblock = pblock; | ||
94 | lb->last_block = blk_num; | ||
95 | return 0; | ||
96 | } | ||
97 | /* | ||
98 | * Start a new range. | ||
99 | */ | ||
100 | retval = finish_range(handle, inode, lb); | ||
101 | lb->first_pblock = lb->last_pblock = pblock; | ||
102 | lb->first_block = lb->last_block = blk_num; | ||
103 | |||
104 | return retval; | ||
105 | } | ||
106 | |||
107 | static int update_ind_extent_range(handle_t *handle, struct inode *inode, | ||
108 | ext4_fsblk_t pblock, ext4_lblk_t *blk_nump, | ||
109 | struct list_blocks_struct *lb) | ||
110 | { | ||
111 | struct buffer_head *bh; | ||
112 | __le32 *i_data; | ||
113 | int i, retval = 0; | ||
114 | ext4_lblk_t blk_count = *blk_nump; | ||
115 | unsigned long max_entries = inode->i_sb->s_blocksize >> 2; | ||
116 | |||
117 | if (!pblock) { | ||
118 | /* Only update the file block number */ | ||
119 | *blk_nump += max_entries; | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | bh = sb_bread(inode->i_sb, pblock); | ||
124 | if (!bh) | ||
125 | return -EIO; | ||
126 | |||
127 | i_data = (__le32 *)bh->b_data; | ||
128 | for (i = 0; i < max_entries; i++, blk_count++) { | ||
129 | if (i_data[i]) { | ||
130 | retval = update_extent_range(handle, inode, | ||
131 | le32_to_cpu(i_data[i]), | ||
132 | blk_count, lb); | ||
133 | if (retval) | ||
134 | break; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | /* Update the file block number */ | ||
139 | *blk_nump = blk_count; | ||
140 | put_bh(bh); | ||
141 | return retval; | ||
142 | |||
143 | } | ||
144 | |||
145 | static int update_dind_extent_range(handle_t *handle, struct inode *inode, | ||
146 | ext4_fsblk_t pblock, ext4_lblk_t *blk_nump, | ||
147 | struct list_blocks_struct *lb) | ||
148 | { | ||
149 | struct buffer_head *bh; | ||
150 | __le32 *i_data; | ||
151 | int i, retval = 0; | ||
152 | ext4_lblk_t blk_count = *blk_nump; | ||
153 | unsigned long max_entries = inode->i_sb->s_blocksize >> 2; | ||
154 | |||
155 | if (!pblock) { | ||
156 | /* Only update the file block number */ | ||
157 | *blk_nump += max_entries * max_entries; | ||
158 | return 0; | ||
159 | } | ||
160 | bh = sb_bread(inode->i_sb, pblock); | ||
161 | if (!bh) | ||
162 | return -EIO; | ||
163 | |||
164 | i_data = (__le32 *)bh->b_data; | ||
165 | for (i = 0; i < max_entries; i++) { | ||
166 | if (i_data[i]) { | ||
167 | retval = update_ind_extent_range(handle, inode, | ||
168 | le32_to_cpu(i_data[i]), | ||
169 | &blk_count, lb); | ||
170 | if (retval) | ||
171 | break; | ||
172 | } else { | ||
173 | /* Only update the file block number */ | ||
174 | blk_count += max_entries; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /* Update the file block number */ | ||
179 | *blk_nump = blk_count; | ||
180 | put_bh(bh); | ||
181 | return retval; | ||
182 | |||
183 | } | ||
184 | |||
185 | static int update_tind_extent_range(handle_t *handle, struct inode *inode, | ||
186 | ext4_fsblk_t pblock, ext4_lblk_t *blk_nump, | ||
187 | struct list_blocks_struct *lb) | ||
188 | { | ||
189 | struct buffer_head *bh; | ||
190 | __le32 *i_data; | ||
191 | int i, retval = 0; | ||
192 | ext4_lblk_t blk_count = *blk_nump; | ||
193 | unsigned long max_entries = inode->i_sb->s_blocksize >> 2; | ||
194 | |||
195 | if (!pblock) { | ||
196 | /* Only update the file block number */ | ||
197 | *blk_nump += max_entries * max_entries * max_entries; | ||
198 | return 0; | ||
199 | } | ||
200 | bh = sb_bread(inode->i_sb, pblock); | ||
201 | if (!bh) | ||
202 | return -EIO; | ||
203 | |||
204 | i_data = (__le32 *)bh->b_data; | ||
205 | for (i = 0; i < max_entries; i++) { | ||
206 | if (i_data[i]) { | ||
207 | retval = update_dind_extent_range(handle, inode, | ||
208 | le32_to_cpu(i_data[i]), | ||
209 | &blk_count, lb); | ||
210 | if (retval) | ||
211 | break; | ||
212 | } else | ||
213 | /* Only update the file block number */ | ||
214 | blk_count += max_entries * max_entries; | ||
215 | } | ||
216 | /* Update the file block number */ | ||
217 | *blk_nump = blk_count; | ||
218 | put_bh(bh); | ||
219 | return retval; | ||
220 | |||
221 | } | ||
222 | |||
223 | static int free_dind_blocks(handle_t *handle, | ||
224 | struct inode *inode, __le32 i_data) | ||
225 | { | ||
226 | int i; | ||
227 | __le32 *tmp_idata; | ||
228 | struct buffer_head *bh; | ||
229 | unsigned long max_entries = inode->i_sb->s_blocksize >> 2; | ||
230 | |||
231 | bh = sb_bread(inode->i_sb, le32_to_cpu(i_data)); | ||
232 | if (!bh) | ||
233 | return -EIO; | ||
234 | |||
235 | tmp_idata = (__le32 *)bh->b_data; | ||
236 | for (i = 0; i < max_entries; i++) { | ||
237 | if (tmp_idata[i]) | ||
238 | ext4_free_blocks(handle, inode, | ||
239 | le32_to_cpu(tmp_idata[i]), 1, 1); | ||
240 | } | ||
241 | put_bh(bh); | ||
242 | ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int free_tind_blocks(handle_t *handle, | ||
247 | struct inode *inode, __le32 i_data) | ||
248 | { | ||
249 | int i, retval = 0; | ||
250 | __le32 *tmp_idata; | ||
251 | struct buffer_head *bh; | ||
252 | unsigned long max_entries = inode->i_sb->s_blocksize >> 2; | ||
253 | |||
254 | bh = sb_bread(inode->i_sb, le32_to_cpu(i_data)); | ||
255 | if (!bh) | ||
256 | return -EIO; | ||
257 | |||
258 | tmp_idata = (__le32 *)bh->b_data; | ||
259 | for (i = 0; i < max_entries; i++) { | ||
260 | if (tmp_idata[i]) { | ||
261 | retval = free_dind_blocks(handle, | ||
262 | inode, tmp_idata[i]); | ||
263 | if (retval) { | ||
264 | put_bh(bh); | ||
265 | return retval; | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | put_bh(bh); | ||
270 | ext4_free_blocks(handle, inode, le32_to_cpu(i_data), 1, 1); | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int free_ind_block(handle_t *handle, struct inode *inode) | ||
275 | { | ||
276 | int retval; | ||
277 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
278 | |||
279 | if (ei->i_data[EXT4_IND_BLOCK]) | ||
280 | ext4_free_blocks(handle, inode, | ||
281 | le32_to_cpu(ei->i_data[EXT4_IND_BLOCK]), 1, 1); | ||
282 | |||
283 | if (ei->i_data[EXT4_DIND_BLOCK]) { | ||
284 | retval = free_dind_blocks(handle, inode, | ||
285 | ei->i_data[EXT4_DIND_BLOCK]); | ||
286 | if (retval) | ||
287 | return retval; | ||
288 | } | ||
289 | |||
290 | if (ei->i_data[EXT4_TIND_BLOCK]) { | ||
291 | retval = free_tind_blocks(handle, inode, | ||
292 | ei->i_data[EXT4_TIND_BLOCK]); | ||
293 | if (retval) | ||
294 | return retval; | ||
295 | } | ||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode, | ||
300 | struct inode *tmp_inode, int retval) | ||
301 | { | ||
302 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
303 | struct ext4_inode_info *tmp_ei = EXT4_I(tmp_inode); | ||
304 | |||
305 | retval = free_ind_block(handle, inode); | ||
306 | if (retval) | ||
307 | goto err_out; | ||
308 | |||
309 | /* | ||
310 | * One credit accounted for writing the | ||
311 | * i_data field of the original inode | ||
312 | */ | ||
313 | retval = ext4_journal_extend(handle, 1); | ||
314 | if (retval != 0) { | ||
315 | retval = ext4_journal_restart(handle, 1); | ||
316 | if (retval) | ||
317 | goto err_out; | ||
318 | } | ||
319 | |||
320 | /* | ||
321 | * We have the extent map build with the tmp inode. | ||
322 | * Now copy the i_data across | ||
323 | */ | ||
324 | ei->i_flags |= EXT4_EXTENTS_FL; | ||
325 | memcpy(ei->i_data, tmp_ei->i_data, sizeof(ei->i_data)); | ||
326 | |||
327 | /* | ||
328 | * Update i_blocks with the new blocks that got | ||
329 | * allocated while adding extents for extent index | ||
330 | * blocks. | ||
331 | * | ||
332 | * While converting to extents we need not | ||
333 | * update the orignal inode i_blocks for extent blocks | ||
334 | * via quota APIs. The quota update happened via tmp_inode already. | ||
335 | */ | ||
336 | spin_lock(&inode->i_lock); | ||
337 | inode->i_blocks += tmp_inode->i_blocks; | ||
338 | spin_unlock(&inode->i_lock); | ||
339 | |||
340 | ext4_mark_inode_dirty(handle, inode); | ||
341 | err_out: | ||
342 | return retval; | ||
343 | } | ||
344 | |||
345 | static int free_ext_idx(handle_t *handle, struct inode *inode, | ||
346 | struct ext4_extent_idx *ix) | ||
347 | { | ||
348 | int i, retval = 0; | ||
349 | ext4_fsblk_t block; | ||
350 | struct buffer_head *bh; | ||
351 | struct ext4_extent_header *eh; | ||
352 | |||
353 | block = idx_pblock(ix); | ||
354 | bh = sb_bread(inode->i_sb, block); | ||
355 | if (!bh) | ||
356 | return -EIO; | ||
357 | |||
358 | eh = (struct ext4_extent_header *)bh->b_data; | ||
359 | if (eh->eh_depth != 0) { | ||
360 | ix = EXT_FIRST_INDEX(eh); | ||
361 | for (i = 0; i < le16_to_cpu(eh->eh_entries); i++, ix++) { | ||
362 | retval = free_ext_idx(handle, inode, ix); | ||
363 | if (retval) | ||
364 | break; | ||
365 | } | ||
366 | } | ||
367 | put_bh(bh); | ||
368 | ext4_free_blocks(handle, inode, block, 1, 1); | ||
369 | return retval; | ||
370 | } | ||
371 | |||
372 | /* | ||
373 | * Free the extent meta data blocks only | ||
374 | */ | ||
375 | static int free_ext_block(handle_t *handle, struct inode *inode) | ||
376 | { | ||
377 | int i, retval = 0; | ||
378 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
379 | struct ext4_extent_header *eh = (struct ext4_extent_header *)ei->i_data; | ||
380 | struct ext4_extent_idx *ix; | ||
381 | if (eh->eh_depth == 0) | ||
382 | /* | ||
383 | * No extra blocks allocated for extent meta data | ||
384 | */ | ||
385 | return 0; | ||
386 | ix = EXT_FIRST_INDEX(eh); | ||
387 | for (i = 0; i < le16_to_cpu(eh->eh_entries); i++, ix++) { | ||
388 | retval = free_ext_idx(handle, inode, ix); | ||
389 | if (retval) | ||
390 | return retval; | ||
391 | } | ||
392 | return retval; | ||
393 | |||
394 | } | ||
395 | |||
396 | int ext4_ext_migrate(struct inode *inode, struct file *filp, | ||
397 | unsigned int cmd, unsigned long arg) | ||
398 | { | ||
399 | handle_t *handle; | ||
400 | int retval = 0, i; | ||
401 | __le32 *i_data; | ||
402 | ext4_lblk_t blk_count = 0; | ||
403 | struct ext4_inode_info *ei; | ||
404 | struct inode *tmp_inode = NULL; | ||
405 | struct list_blocks_struct lb; | ||
406 | unsigned long max_entries; | ||
407 | |||
408 | if (!test_opt(inode->i_sb, EXTENTS)) | ||
409 | /* | ||
410 | * if mounted with noextents we don't allow the migrate | ||
411 | */ | ||
412 | return -EINVAL; | ||
413 | |||
414 | if ((EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) | ||
415 | return -EINVAL; | ||
416 | |||
417 | down_write(&EXT4_I(inode)->i_data_sem); | ||
418 | handle = ext4_journal_start(inode, | ||
419 | EXT4_DATA_TRANS_BLOCKS(inode->i_sb) + | ||
420 | EXT4_INDEX_EXTRA_TRANS_BLOCKS + 3 + | ||
421 | 2 * EXT4_QUOTA_INIT_BLOCKS(inode->i_sb) | ||
422 | + 1); | ||
423 | if (IS_ERR(handle)) { | ||
424 | retval = PTR_ERR(handle); | ||
425 | goto err_out; | ||
426 | } | ||
427 | tmp_inode = ext4_new_inode(handle, | ||
428 | inode->i_sb->s_root->d_inode, | ||
429 | S_IFREG); | ||
430 | if (IS_ERR(tmp_inode)) { | ||
431 | retval = -ENOMEM; | ||
432 | ext4_journal_stop(handle); | ||
433 | tmp_inode = NULL; | ||
434 | goto err_out; | ||
435 | } | ||
436 | i_size_write(tmp_inode, i_size_read(inode)); | ||
437 | /* | ||
438 | * We don't want the inode to be reclaimed | ||
439 | * if we got interrupted in between. We have | ||
440 | * this tmp inode carrying reference to the | ||
441 | * data blocks of the original file. We set | ||
442 | * the i_nlink to zero at the last stage after | ||
443 | * switching the original file to extent format | ||
444 | */ | ||
445 | tmp_inode->i_nlink = 1; | ||
446 | |||
447 | ext4_ext_tree_init(handle, tmp_inode); | ||
448 | ext4_orphan_add(handle, tmp_inode); | ||
449 | ext4_journal_stop(handle); | ||
450 | |||
451 | ei = EXT4_I(inode); | ||
452 | i_data = ei->i_data; | ||
453 | memset(&lb, 0, sizeof(lb)); | ||
454 | |||
455 | /* 32 bit block address 4 bytes */ | ||
456 | max_entries = inode->i_sb->s_blocksize >> 2; | ||
457 | |||
458 | /* | ||
459 | * start with one credit accounted for | ||
460 | * superblock modification. | ||
461 | * | ||
462 | * For the tmp_inode we already have commited the | ||
463 | * trascation that created the inode. Later as and | ||
464 | * when we add extents we extent the journal | ||
465 | */ | ||
466 | handle = ext4_journal_start(inode, 1); | ||
467 | for (i = 0; i < EXT4_NDIR_BLOCKS; i++, blk_count++) { | ||
468 | if (i_data[i]) { | ||
469 | retval = update_extent_range(handle, tmp_inode, | ||
470 | le32_to_cpu(i_data[i]), | ||
471 | blk_count, &lb); | ||
472 | if (retval) | ||
473 | goto err_out; | ||
474 | } | ||
475 | } | ||
476 | if (i_data[EXT4_IND_BLOCK]) { | ||
477 | retval = update_ind_extent_range(handle, tmp_inode, | ||
478 | le32_to_cpu(i_data[EXT4_IND_BLOCK]), | ||
479 | &blk_count, &lb); | ||
480 | if (retval) | ||
481 | goto err_out; | ||
482 | } else | ||
483 | blk_count += max_entries; | ||
484 | if (i_data[EXT4_DIND_BLOCK]) { | ||
485 | retval = update_dind_extent_range(handle, tmp_inode, | ||
486 | le32_to_cpu(i_data[EXT4_DIND_BLOCK]), | ||
487 | &blk_count, &lb); | ||
488 | if (retval) | ||
489 | goto err_out; | ||
490 | } else | ||
491 | blk_count += max_entries * max_entries; | ||
492 | if (i_data[EXT4_TIND_BLOCK]) { | ||
493 | retval = update_tind_extent_range(handle, tmp_inode, | ||
494 | le32_to_cpu(i_data[EXT4_TIND_BLOCK]), | ||
495 | &blk_count, &lb); | ||
496 | if (retval) | ||
497 | goto err_out; | ||
498 | } | ||
499 | /* | ||
500 | * Build the last extent | ||
501 | */ | ||
502 | retval = finish_range(handle, tmp_inode, &lb); | ||
503 | err_out: | ||
504 | /* | ||
505 | * We are either freeing extent information or indirect | ||
506 | * blocks. During this we touch superblock, group descriptor | ||
507 | * and block bitmap. Later we mark the tmp_inode dirty | ||
508 | * via ext4_ext_tree_init. So allocate a credit of 4 | ||
509 | * We may update quota (user and group). | ||
510 | * | ||
511 | * FIXME!! we may be touching bitmaps in different block groups. | ||
512 | */ | ||
513 | if (ext4_journal_extend(handle, | ||
514 | 4 + 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb)) != 0) | ||
515 | ext4_journal_restart(handle, | ||
516 | 4 + 2*EXT4_QUOTA_TRANS_BLOCKS(inode->i_sb)); | ||
517 | if (retval) | ||
518 | /* | ||
519 | * Failure case delete the extent information with the | ||
520 | * tmp_inode | ||
521 | */ | ||
522 | free_ext_block(handle, tmp_inode); | ||
523 | else | ||
524 | retval = ext4_ext_swap_inode_data(handle, inode, | ||
525 | tmp_inode, retval); | ||
526 | |||
527 | /* | ||
528 | * Mark the tmp_inode as of size zero | ||
529 | */ | ||
530 | i_size_write(tmp_inode, 0); | ||
531 | |||
532 | /* | ||
533 | * set the i_blocks count to zero | ||
534 | * so that the ext4_delete_inode does the | ||
535 | * right job | ||
536 | * | ||
537 | * We don't need to take the i_lock because | ||
538 | * the inode is not visible to user space. | ||
539 | */ | ||
540 | tmp_inode->i_blocks = 0; | ||
541 | |||
542 | /* Reset the extent details */ | ||
543 | ext4_ext_tree_init(handle, tmp_inode); | ||
544 | |||
545 | /* | ||
546 | * Set the i_nlink to zero so that | ||
547 | * generic_drop_inode really deletes the | ||
548 | * inode | ||
549 | */ | ||
550 | tmp_inode->i_nlink = 0; | ||
551 | |||
552 | ext4_journal_stop(handle); | ||
553 | |||
554 | up_write(&EXT4_I(inode)->i_data_sem); | ||
555 | |||
556 | if (tmp_inode) | ||
557 | iput(tmp_inode); | ||
558 | |||
559 | return retval; | ||
560 | } | ||
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 94ee6f315dc1..67b6d8a1ceff 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -51,7 +51,7 @@ | |||
51 | 51 | ||
52 | static struct buffer_head *ext4_append(handle_t *handle, | 52 | static struct buffer_head *ext4_append(handle_t *handle, |
53 | struct inode *inode, | 53 | struct inode *inode, |
54 | u32 *block, int *err) | 54 | ext4_lblk_t *block, int *err) |
55 | { | 55 | { |
56 | struct buffer_head *bh; | 56 | struct buffer_head *bh; |
57 | 57 | ||
@@ -144,8 +144,8 @@ struct dx_map_entry | |||
144 | u16 size; | 144 | u16 size; |
145 | }; | 145 | }; |
146 | 146 | ||
147 | static inline unsigned dx_get_block (struct dx_entry *entry); | 147 | static inline ext4_lblk_t dx_get_block(struct dx_entry *entry); |
148 | static void dx_set_block (struct dx_entry *entry, unsigned value); | 148 | static void dx_set_block(struct dx_entry *entry, ext4_lblk_t value); |
149 | static inline unsigned dx_get_hash (struct dx_entry *entry); | 149 | static inline unsigned dx_get_hash (struct dx_entry *entry); |
150 | static void dx_set_hash (struct dx_entry *entry, unsigned value); | 150 | static void dx_set_hash (struct dx_entry *entry, unsigned value); |
151 | static unsigned dx_get_count (struct dx_entry *entries); | 151 | static unsigned dx_get_count (struct dx_entry *entries); |
@@ -166,7 +166,8 @@ static void dx_sort_map(struct dx_map_entry *map, unsigned count); | |||
166 | static struct ext4_dir_entry_2 *dx_move_dirents (char *from, char *to, | 166 | static struct ext4_dir_entry_2 *dx_move_dirents (char *from, char *to, |
167 | struct dx_map_entry *offsets, int count); | 167 | struct dx_map_entry *offsets, int count); |
168 | static struct ext4_dir_entry_2* dx_pack_dirents (char *base, int size); | 168 | static struct ext4_dir_entry_2* dx_pack_dirents (char *base, int size); |
169 | static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); | 169 | static void dx_insert_block(struct dx_frame *frame, |
170 | u32 hash, ext4_lblk_t block); | ||
170 | static int ext4_htree_next_block(struct inode *dir, __u32 hash, | 171 | static int ext4_htree_next_block(struct inode *dir, __u32 hash, |
171 | struct dx_frame *frame, | 172 | struct dx_frame *frame, |
172 | struct dx_frame *frames, | 173 | struct dx_frame *frames, |
@@ -181,12 +182,12 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
181 | * Mask them off for now. | 182 | * Mask them off for now. |
182 | */ | 183 | */ |
183 | 184 | ||
184 | static inline unsigned dx_get_block (struct dx_entry *entry) | 185 | static inline ext4_lblk_t dx_get_block(struct dx_entry *entry) |
185 | { | 186 | { |
186 | return le32_to_cpu(entry->block) & 0x00ffffff; | 187 | return le32_to_cpu(entry->block) & 0x00ffffff; |
187 | } | 188 | } |
188 | 189 | ||
189 | static inline void dx_set_block (struct dx_entry *entry, unsigned value) | 190 | static inline void dx_set_block(struct dx_entry *entry, ext4_lblk_t value) |
190 | { | 191 | { |
191 | entry->block = cpu_to_le32(value); | 192 | entry->block = cpu_to_le32(value); |
192 | } | 193 | } |
@@ -243,8 +244,8 @@ static void dx_show_index (char * label, struct dx_entry *entries) | |||
243 | int i, n = dx_get_count (entries); | 244 | int i, n = dx_get_count (entries); |
244 | printk("%s index ", label); | 245 | printk("%s index ", label); |
245 | for (i = 0; i < n; i++) { | 246 | for (i = 0; i < n; i++) { |
246 | printk("%x->%u ", i? dx_get_hash(entries + i) : | 247 | printk("%x->%lu ", i? dx_get_hash(entries + i) : |
247 | 0, dx_get_block(entries + i)); | 248 | 0, (unsigned long)dx_get_block(entries + i)); |
248 | } | 249 | } |
249 | printk("\n"); | 250 | printk("\n"); |
250 | } | 251 | } |
@@ -280,7 +281,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext4_dir_ent | |||
280 | space += EXT4_DIR_REC_LEN(de->name_len); | 281 | space += EXT4_DIR_REC_LEN(de->name_len); |
281 | names++; | 282 | names++; |
282 | } | 283 | } |
283 | de = (struct ext4_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); | 284 | de = ext4_next_entry(de); |
284 | } | 285 | } |
285 | printk("(%i)\n", names); | 286 | printk("(%i)\n", names); |
286 | return (struct stats) { names, space, 1 }; | 287 | return (struct stats) { names, space, 1 }; |
@@ -297,7 +298,8 @@ struct stats dx_show_entries(struct dx_hash_info *hinfo, struct inode *dir, | |||
297 | printk("%i indexed blocks...\n", count); | 298 | printk("%i indexed blocks...\n", count); |
298 | for (i = 0; i < count; i++, entries++) | 299 | for (i = 0; i < count; i++, entries++) |
299 | { | 300 | { |
300 | u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0; | 301 | ext4_lblk_t block = dx_get_block(entries); |
302 | ext4_lblk_t hash = i ? dx_get_hash(entries): 0; | ||
301 | u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash; | 303 | u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash; |
302 | struct stats stats; | 304 | struct stats stats; |
303 | printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range); | 305 | printk("%s%3u:%03u hash %8x/%8x ",levels?"":" ", i, block, hash, range); |
@@ -551,7 +553,8 @@ static int ext4_htree_next_block(struct inode *dir, __u32 hash, | |||
551 | */ | 553 | */ |
552 | static inline struct ext4_dir_entry_2 *ext4_next_entry(struct ext4_dir_entry_2 *p) | 554 | static inline struct ext4_dir_entry_2 *ext4_next_entry(struct ext4_dir_entry_2 *p) |
553 | { | 555 | { |
554 | return (struct ext4_dir_entry_2 *)((char*)p + le16_to_cpu(p->rec_len)); | 556 | return (struct ext4_dir_entry_2 *)((char *)p + |
557 | ext4_rec_len_from_disk(p->rec_len)); | ||
555 | } | 558 | } |
556 | 559 | ||
557 | /* | 560 | /* |
@@ -560,7 +563,7 @@ static inline struct ext4_dir_entry_2 *ext4_next_entry(struct ext4_dir_entry_2 * | |||
560 | * into the tree. If there is an error it is returned in err. | 563 | * into the tree. If there is an error it is returned in err. |
561 | */ | 564 | */ |
562 | static int htree_dirblock_to_tree(struct file *dir_file, | 565 | static int htree_dirblock_to_tree(struct file *dir_file, |
563 | struct inode *dir, int block, | 566 | struct inode *dir, ext4_lblk_t block, |
564 | struct dx_hash_info *hinfo, | 567 | struct dx_hash_info *hinfo, |
565 | __u32 start_hash, __u32 start_minor_hash) | 568 | __u32 start_hash, __u32 start_minor_hash) |
566 | { | 569 | { |
@@ -568,7 +571,8 @@ static int htree_dirblock_to_tree(struct file *dir_file, | |||
568 | struct ext4_dir_entry_2 *de, *top; | 571 | struct ext4_dir_entry_2 *de, *top; |
569 | int err, count = 0; | 572 | int err, count = 0; |
570 | 573 | ||
571 | dxtrace(printk("In htree dirblock_to_tree: block %d\n", block)); | 574 | dxtrace(printk(KERN_INFO "In htree dirblock_to_tree: block %lu\n", |
575 | (unsigned long)block)); | ||
572 | if (!(bh = ext4_bread (NULL, dir, block, 0, &err))) | 576 | if (!(bh = ext4_bread (NULL, dir, block, 0, &err))) |
573 | return err; | 577 | return err; |
574 | 578 | ||
@@ -620,9 +624,9 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, | |||
620 | struct ext4_dir_entry_2 *de; | 624 | struct ext4_dir_entry_2 *de; |
621 | struct dx_frame frames[2], *frame; | 625 | struct dx_frame frames[2], *frame; |
622 | struct inode *dir; | 626 | struct inode *dir; |
623 | int block, err; | 627 | ext4_lblk_t block; |
624 | int count = 0; | 628 | int count = 0; |
625 | int ret; | 629 | int ret, err; |
626 | __u32 hashval; | 630 | __u32 hashval; |
627 | 631 | ||
628 | dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash, | 632 | dxtrace(printk("In htree_fill_tree, start hash: %x:%x\n", start_hash, |
@@ -720,7 +724,7 @@ static int dx_make_map (struct ext4_dir_entry_2 *de, int size, | |||
720 | cond_resched(); | 724 | cond_resched(); |
721 | } | 725 | } |
722 | /* XXX: do we need to check rec_len == 0 case? -Chris */ | 726 | /* XXX: do we need to check rec_len == 0 case? -Chris */ |
723 | de = (struct ext4_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); | 727 | de = ext4_next_entry(de); |
724 | } | 728 | } |
725 | return count; | 729 | return count; |
726 | } | 730 | } |
@@ -752,7 +756,7 @@ static void dx_sort_map (struct dx_map_entry *map, unsigned count) | |||
752 | } while(more); | 756 | } while(more); |
753 | } | 757 | } |
754 | 758 | ||
755 | static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block) | 759 | static void dx_insert_block(struct dx_frame *frame, u32 hash, ext4_lblk_t block) |
756 | { | 760 | { |
757 | struct dx_entry *entries = frame->entries; | 761 | struct dx_entry *entries = frame->entries; |
758 | struct dx_entry *old = frame->at, *new = old + 1; | 762 | struct dx_entry *old = frame->at, *new = old + 1; |
@@ -820,7 +824,7 @@ static inline int search_dirblock(struct buffer_head * bh, | |||
820 | return 1; | 824 | return 1; |
821 | } | 825 | } |
822 | /* prevent looping on a bad block */ | 826 | /* prevent looping on a bad block */ |
823 | de_len = le16_to_cpu(de->rec_len); | 827 | de_len = ext4_rec_len_from_disk(de->rec_len); |
824 | if (de_len <= 0) | 828 | if (de_len <= 0) |
825 | return -1; | 829 | return -1; |
826 | offset += de_len; | 830 | offset += de_len; |
@@ -847,23 +851,20 @@ static struct buffer_head * ext4_find_entry (struct dentry *dentry, | |||
847 | struct super_block * sb; | 851 | struct super_block * sb; |
848 | struct buffer_head * bh_use[NAMEI_RA_SIZE]; | 852 | struct buffer_head * bh_use[NAMEI_RA_SIZE]; |
849 | struct buffer_head * bh, *ret = NULL; | 853 | struct buffer_head * bh, *ret = NULL; |
850 | unsigned long start, block, b; | 854 | ext4_lblk_t start, block, b; |
851 | int ra_max = 0; /* Number of bh's in the readahead | 855 | int ra_max = 0; /* Number of bh's in the readahead |
852 | buffer, bh_use[] */ | 856 | buffer, bh_use[] */ |
853 | int ra_ptr = 0; /* Current index into readahead | 857 | int ra_ptr = 0; /* Current index into readahead |
854 | buffer */ | 858 | buffer */ |
855 | int num = 0; | 859 | int num = 0; |
856 | int nblocks, i, err; | 860 | ext4_lblk_t nblocks; |
861 | int i, err; | ||
857 | struct inode *dir = dentry->d_parent->d_inode; | 862 | struct inode *dir = dentry->d_parent->d_inode; |
858 | int namelen; | 863 | int namelen; |
859 | const u8 *name; | ||
860 | unsigned blocksize; | ||
861 | 864 | ||
862 | *res_dir = NULL; | 865 | *res_dir = NULL; |
863 | sb = dir->i_sb; | 866 | sb = dir->i_sb; |
864 | blocksize = sb->s_blocksize; | ||
865 | namelen = dentry->d_name.len; | 867 | namelen = dentry->d_name.len; |
866 | name = dentry->d_name.name; | ||
867 | if (namelen > EXT4_NAME_LEN) | 868 | if (namelen > EXT4_NAME_LEN) |
868 | return NULL; | 869 | return NULL; |
869 | if (is_dx(dir)) { | 870 | if (is_dx(dir)) { |
@@ -914,7 +915,8 @@ restart: | |||
914 | if (!buffer_uptodate(bh)) { | 915 | if (!buffer_uptodate(bh)) { |
915 | /* read error, skip block & hope for the best */ | 916 | /* read error, skip block & hope for the best */ |
916 | ext4_error(sb, __FUNCTION__, "reading directory #%lu " | 917 | ext4_error(sb, __FUNCTION__, "reading directory #%lu " |
917 | "offset %lu", dir->i_ino, block); | 918 | "offset %lu", dir->i_ino, |
919 | (unsigned long)block); | ||
918 | brelse(bh); | 920 | brelse(bh); |
919 | goto next; | 921 | goto next; |
920 | } | 922 | } |
@@ -961,7 +963,7 @@ static struct buffer_head * ext4_dx_find_entry(struct dentry *dentry, | |||
961 | struct dx_frame frames[2], *frame; | 963 | struct dx_frame frames[2], *frame; |
962 | struct ext4_dir_entry_2 *de, *top; | 964 | struct ext4_dir_entry_2 *de, *top; |
963 | struct buffer_head *bh; | 965 | struct buffer_head *bh; |
964 | unsigned long block; | 966 | ext4_lblk_t block; |
965 | int retval; | 967 | int retval; |
966 | int namelen = dentry->d_name.len; | 968 | int namelen = dentry->d_name.len; |
967 | const u8 *name = dentry->d_name.name; | 969 | const u8 *name = dentry->d_name.name; |
@@ -1128,7 +1130,7 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) | |||
1128 | rec_len = EXT4_DIR_REC_LEN(de->name_len); | 1130 | rec_len = EXT4_DIR_REC_LEN(de->name_len); |
1129 | memcpy (to, de, rec_len); | 1131 | memcpy (to, de, rec_len); |
1130 | ((struct ext4_dir_entry_2 *) to)->rec_len = | 1132 | ((struct ext4_dir_entry_2 *) to)->rec_len = |
1131 | cpu_to_le16(rec_len); | 1133 | ext4_rec_len_to_disk(rec_len); |
1132 | de->inode = 0; | 1134 | de->inode = 0; |
1133 | map++; | 1135 | map++; |
1134 | to += rec_len; | 1136 | to += rec_len; |
@@ -1147,13 +1149,12 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size) | |||
1147 | 1149 | ||
1148 | prev = to = de; | 1150 | prev = to = de; |
1149 | while ((char*)de < base + size) { | 1151 | while ((char*)de < base + size) { |
1150 | next = (struct ext4_dir_entry_2 *) ((char *) de + | 1152 | next = ext4_next_entry(de); |
1151 | le16_to_cpu(de->rec_len)); | ||
1152 | if (de->inode && de->name_len) { | 1153 | if (de->inode && de->name_len) { |
1153 | rec_len = EXT4_DIR_REC_LEN(de->name_len); | 1154 | rec_len = EXT4_DIR_REC_LEN(de->name_len); |
1154 | if (de > to) | 1155 | if (de > to) |
1155 | memmove(to, de, rec_len); | 1156 | memmove(to, de, rec_len); |
1156 | to->rec_len = cpu_to_le16(rec_len); | 1157 | to->rec_len = ext4_rec_len_to_disk(rec_len); |
1157 | prev = to; | 1158 | prev = to; |
1158 | to = (struct ext4_dir_entry_2 *) (((char *) to) + rec_len); | 1159 | to = (struct ext4_dir_entry_2 *) (((char *) to) + rec_len); |
1159 | } | 1160 | } |
@@ -1174,7 +1175,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | |||
1174 | unsigned blocksize = dir->i_sb->s_blocksize; | 1175 | unsigned blocksize = dir->i_sb->s_blocksize; |
1175 | unsigned count, continued; | 1176 | unsigned count, continued; |
1176 | struct buffer_head *bh2; | 1177 | struct buffer_head *bh2; |
1177 | u32 newblock; | 1178 | ext4_lblk_t newblock; |
1178 | u32 hash2; | 1179 | u32 hash2; |
1179 | struct dx_map_entry *map; | 1180 | struct dx_map_entry *map; |
1180 | char *data1 = (*bh)->b_data, *data2; | 1181 | char *data1 = (*bh)->b_data, *data2; |
@@ -1221,14 +1222,15 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir, | |||
1221 | split = count - move; | 1222 | split = count - move; |
1222 | hash2 = map[split].hash; | 1223 | hash2 = map[split].hash; |
1223 | continued = hash2 == map[split - 1].hash; | 1224 | continued = hash2 == map[split - 1].hash; |
1224 | dxtrace(printk("Split block %i at %x, %i/%i\n", | 1225 | dxtrace(printk(KERN_INFO "Split block %lu at %x, %i/%i\n", |
1225 | dx_get_block(frame->at), hash2, split, count-split)); | 1226 | (unsigned long)dx_get_block(frame->at), |
1227 | hash2, split, count-split)); | ||
1226 | 1228 | ||
1227 | /* Fancy dance to stay within two buffers */ | 1229 | /* Fancy dance to stay within two buffers */ |
1228 | de2 = dx_move_dirents(data1, data2, map + split, count - split); | 1230 | de2 = dx_move_dirents(data1, data2, map + split, count - split); |
1229 | de = dx_pack_dirents(data1,blocksize); | 1231 | de = dx_pack_dirents(data1,blocksize); |
1230 | de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); | 1232 | de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de); |
1231 | de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2); | 1233 | de2->rec_len = ext4_rec_len_to_disk(data2 + blocksize - (char *) de2); |
1232 | dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1)); | 1234 | dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data1, blocksize, 1)); |
1233 | dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1)); | 1235 | dxtrace(dx_show_leaf (hinfo, (struct ext4_dir_entry_2 *) data2, blocksize, 1)); |
1234 | 1236 | ||
@@ -1297,7 +1299,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1297 | return -EEXIST; | 1299 | return -EEXIST; |
1298 | } | 1300 | } |
1299 | nlen = EXT4_DIR_REC_LEN(de->name_len); | 1301 | nlen = EXT4_DIR_REC_LEN(de->name_len); |
1300 | rlen = le16_to_cpu(de->rec_len); | 1302 | rlen = ext4_rec_len_from_disk(de->rec_len); |
1301 | if ((de->inode? rlen - nlen: rlen) >= reclen) | 1303 | if ((de->inode? rlen - nlen: rlen) >= reclen) |
1302 | break; | 1304 | break; |
1303 | de = (struct ext4_dir_entry_2 *)((char *)de + rlen); | 1305 | de = (struct ext4_dir_entry_2 *)((char *)de + rlen); |
@@ -1316,11 +1318,11 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1316 | 1318 | ||
1317 | /* By now the buffer is marked for journaling */ | 1319 | /* By now the buffer is marked for journaling */ |
1318 | nlen = EXT4_DIR_REC_LEN(de->name_len); | 1320 | nlen = EXT4_DIR_REC_LEN(de->name_len); |
1319 | rlen = le16_to_cpu(de->rec_len); | 1321 | rlen = ext4_rec_len_from_disk(de->rec_len); |
1320 | if (de->inode) { | 1322 | if (de->inode) { |
1321 | struct ext4_dir_entry_2 *de1 = (struct ext4_dir_entry_2 *)((char *)de + nlen); | 1323 | struct ext4_dir_entry_2 *de1 = (struct ext4_dir_entry_2 *)((char *)de + nlen); |
1322 | de1->rec_len = cpu_to_le16(rlen - nlen); | 1324 | de1->rec_len = ext4_rec_len_to_disk(rlen - nlen); |
1323 | de->rec_len = cpu_to_le16(nlen); | 1325 | de->rec_len = ext4_rec_len_to_disk(nlen); |
1324 | de = de1; | 1326 | de = de1; |
1325 | } | 1327 | } |
1326 | de->file_type = EXT4_FT_UNKNOWN; | 1328 | de->file_type = EXT4_FT_UNKNOWN; |
@@ -1374,7 +1376,7 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1374 | int retval; | 1376 | int retval; |
1375 | unsigned blocksize; | 1377 | unsigned blocksize; |
1376 | struct dx_hash_info hinfo; | 1378 | struct dx_hash_info hinfo; |
1377 | u32 block; | 1379 | ext4_lblk_t block; |
1378 | struct fake_dirent *fde; | 1380 | struct fake_dirent *fde; |
1379 | 1381 | ||
1380 | blocksize = dir->i_sb->s_blocksize; | 1382 | blocksize = dir->i_sb->s_blocksize; |
@@ -1397,17 +1399,18 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry, | |||
1397 | 1399 | ||
1398 | /* The 0th block becomes the root, move the dirents out */ | 1400 | /* The 0th block becomes the root, move the dirents out */ |
1399 | fde = &root->dotdot; | 1401 | fde = &root->dotdot; |
1400 | de = (struct ext4_dir_entry_2 *)((char *)fde + le16_to_cpu(fde->rec_len)); | 1402 | de = (struct ext4_dir_entry_2 *)((char *)fde + |
1403 | ext4_rec_len_from_disk(fde->rec_len)); | ||
1401 | len = ((char *) root) + blocksize - (char *) de; | 1404 | len = ((char *) root) + blocksize - (char *) de; |
1402 | memcpy (data1, de, len); | 1405 | memcpy (data1, de, len); |
1403 | de = (struct ext4_dir_entry_2 *) data1; | 1406 | de = (struct ext4_dir_entry_2 *) data1; |
1404 | top = data1 + len; | 1407 | top = data1 + len; |
1405 | while ((char *)(de2=(void*)de+le16_to_cpu(de->rec_len)) < top) | 1408 | while ((char *)(de2 = ext4_next_entry(de)) < top) |
1406 | de = de2; | 1409 | de = de2; |
1407 | de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de); | 1410 | de->rec_len = ext4_rec_len_to_disk(data1 + blocksize - (char *) de); |
1408 | /* Initialize the root; the dot dirents already exist */ | 1411 | /* Initialize the root; the dot dirents already exist */ |
1409 | de = (struct ext4_dir_entry_2 *) (&root->dotdot); | 1412 | de = (struct ext4_dir_entry_2 *) (&root->dotdot); |
1410 | de->rec_len = cpu_to_le16(blocksize - EXT4_DIR_REC_LEN(2)); | 1413 | de->rec_len = ext4_rec_len_to_disk(blocksize - EXT4_DIR_REC_LEN(2)); |
1411 | memset (&root->info, 0, sizeof(root->info)); | 1414 | memset (&root->info, 0, sizeof(root->info)); |
1412 | root->info.info_length = sizeof(root->info); | 1415 | root->info.info_length = sizeof(root->info); |
1413 | root->info.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version; | 1416 | root->info.hash_version = EXT4_SB(dir->i_sb)->s_def_hash_version; |
@@ -1454,7 +1457,7 @@ static int ext4_add_entry (handle_t *handle, struct dentry *dentry, | |||
1454 | int retval; | 1457 | int retval; |
1455 | int dx_fallback=0; | 1458 | int dx_fallback=0; |
1456 | unsigned blocksize; | 1459 | unsigned blocksize; |
1457 | u32 block, blocks; | 1460 | ext4_lblk_t block, blocks; |
1458 | 1461 | ||
1459 | sb = dir->i_sb; | 1462 | sb = dir->i_sb; |
1460 | blocksize = sb->s_blocksize; | 1463 | blocksize = sb->s_blocksize; |
@@ -1487,7 +1490,7 @@ static int ext4_add_entry (handle_t *handle, struct dentry *dentry, | |||
1487 | return retval; | 1490 | return retval; |
1488 | de = (struct ext4_dir_entry_2 *) bh->b_data; | 1491 | de = (struct ext4_dir_entry_2 *) bh->b_data; |
1489 | de->inode = 0; | 1492 | de->inode = 0; |
1490 | de->rec_len = cpu_to_le16(blocksize); | 1493 | de->rec_len = ext4_rec_len_to_disk(blocksize); |
1491 | return add_dirent_to_buf(handle, dentry, inode, de, bh); | 1494 | return add_dirent_to_buf(handle, dentry, inode, de, bh); |
1492 | } | 1495 | } |
1493 | 1496 | ||
@@ -1531,7 +1534,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
1531 | dx_get_count(entries), dx_get_limit(entries))); | 1534 | dx_get_count(entries), dx_get_limit(entries))); |
1532 | /* Need to split index? */ | 1535 | /* Need to split index? */ |
1533 | if (dx_get_count(entries) == dx_get_limit(entries)) { | 1536 | if (dx_get_count(entries) == dx_get_limit(entries)) { |
1534 | u32 newblock; | 1537 | ext4_lblk_t newblock; |
1535 | unsigned icount = dx_get_count(entries); | 1538 | unsigned icount = dx_get_count(entries); |
1536 | int levels = frame - frames; | 1539 | int levels = frame - frames; |
1537 | struct dx_entry *entries2; | 1540 | struct dx_entry *entries2; |
@@ -1550,7 +1553,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
1550 | goto cleanup; | 1553 | goto cleanup; |
1551 | node2 = (struct dx_node *)(bh2->b_data); | 1554 | node2 = (struct dx_node *)(bh2->b_data); |
1552 | entries2 = node2->entries; | 1555 | entries2 = node2->entries; |
1553 | node2->fake.rec_len = cpu_to_le16(sb->s_blocksize); | 1556 | node2->fake.rec_len = ext4_rec_len_to_disk(sb->s_blocksize); |
1554 | node2->fake.inode = 0; | 1557 | node2->fake.inode = 0; |
1555 | BUFFER_TRACE(frame->bh, "get_write_access"); | 1558 | BUFFER_TRACE(frame->bh, "get_write_access"); |
1556 | err = ext4_journal_get_write_access(handle, frame->bh); | 1559 | err = ext4_journal_get_write_access(handle, frame->bh); |
@@ -1648,9 +1651,9 @@ static int ext4_delete_entry (handle_t *handle, | |||
1648 | BUFFER_TRACE(bh, "get_write_access"); | 1651 | BUFFER_TRACE(bh, "get_write_access"); |
1649 | ext4_journal_get_write_access(handle, bh); | 1652 | ext4_journal_get_write_access(handle, bh); |
1650 | if (pde) | 1653 | if (pde) |
1651 | pde->rec_len = | 1654 | pde->rec_len = ext4_rec_len_to_disk( |
1652 | cpu_to_le16(le16_to_cpu(pde->rec_len) + | 1655 | ext4_rec_len_from_disk(pde->rec_len) + |
1653 | le16_to_cpu(de->rec_len)); | 1656 | ext4_rec_len_from_disk(de->rec_len)); |
1654 | else | 1657 | else |
1655 | de->inode = 0; | 1658 | de->inode = 0; |
1656 | dir->i_version++; | 1659 | dir->i_version++; |
@@ -1658,10 +1661,9 @@ static int ext4_delete_entry (handle_t *handle, | |||
1658 | ext4_journal_dirty_metadata(handle, bh); | 1661 | ext4_journal_dirty_metadata(handle, bh); |
1659 | return 0; | 1662 | return 0; |
1660 | } | 1663 | } |
1661 | i += le16_to_cpu(de->rec_len); | 1664 | i += ext4_rec_len_from_disk(de->rec_len); |
1662 | pde = de; | 1665 | pde = de; |
1663 | de = (struct ext4_dir_entry_2 *) | 1666 | de = ext4_next_entry(de); |
1664 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1665 | } | 1667 | } |
1666 | return -ENOENT; | 1668 | return -ENOENT; |
1667 | } | 1669 | } |
@@ -1824,13 +1826,13 @@ retry: | |||
1824 | de = (struct ext4_dir_entry_2 *) dir_block->b_data; | 1826 | de = (struct ext4_dir_entry_2 *) dir_block->b_data; |
1825 | de->inode = cpu_to_le32(inode->i_ino); | 1827 | de->inode = cpu_to_le32(inode->i_ino); |
1826 | de->name_len = 1; | 1828 | de->name_len = 1; |
1827 | de->rec_len = cpu_to_le16(EXT4_DIR_REC_LEN(de->name_len)); | 1829 | de->rec_len = ext4_rec_len_to_disk(EXT4_DIR_REC_LEN(de->name_len)); |
1828 | strcpy (de->name, "."); | 1830 | strcpy (de->name, "."); |
1829 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); | 1831 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); |
1830 | de = (struct ext4_dir_entry_2 *) | 1832 | de = ext4_next_entry(de); |
1831 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1832 | de->inode = cpu_to_le32(dir->i_ino); | 1833 | de->inode = cpu_to_le32(dir->i_ino); |
1833 | de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize-EXT4_DIR_REC_LEN(1)); | 1834 | de->rec_len = ext4_rec_len_to_disk(inode->i_sb->s_blocksize - |
1835 | EXT4_DIR_REC_LEN(1)); | ||
1834 | de->name_len = 2; | 1836 | de->name_len = 2; |
1835 | strcpy (de->name, ".."); | 1837 | strcpy (de->name, ".."); |
1836 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); | 1838 | ext4_set_de_type(dir->i_sb, de, S_IFDIR); |
@@ -1882,8 +1884,7 @@ static int empty_dir (struct inode * inode) | |||
1882 | return 1; | 1884 | return 1; |
1883 | } | 1885 | } |
1884 | de = (struct ext4_dir_entry_2 *) bh->b_data; | 1886 | de = (struct ext4_dir_entry_2 *) bh->b_data; |
1885 | de1 = (struct ext4_dir_entry_2 *) | 1887 | de1 = ext4_next_entry(de); |
1886 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1887 | if (le32_to_cpu(de->inode) != inode->i_ino || | 1888 | if (le32_to_cpu(de->inode) != inode->i_ino || |
1888 | !le32_to_cpu(de1->inode) || | 1889 | !le32_to_cpu(de1->inode) || |
1889 | strcmp (".", de->name) || | 1890 | strcmp (".", de->name) || |
@@ -1894,9 +1895,9 @@ static int empty_dir (struct inode * inode) | |||
1894 | brelse (bh); | 1895 | brelse (bh); |
1895 | return 1; | 1896 | return 1; |
1896 | } | 1897 | } |
1897 | offset = le16_to_cpu(de->rec_len) + le16_to_cpu(de1->rec_len); | 1898 | offset = ext4_rec_len_from_disk(de->rec_len) + |
1898 | de = (struct ext4_dir_entry_2 *) | 1899 | ext4_rec_len_from_disk(de1->rec_len); |
1899 | ((char *) de1 + le16_to_cpu(de1->rec_len)); | 1900 | de = ext4_next_entry(de1); |
1900 | while (offset < inode->i_size ) { | 1901 | while (offset < inode->i_size ) { |
1901 | if (!bh || | 1902 | if (!bh || |
1902 | (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { | 1903 | (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { |
@@ -1925,9 +1926,8 @@ static int empty_dir (struct inode * inode) | |||
1925 | brelse (bh); | 1926 | brelse (bh); |
1926 | return 0; | 1927 | return 0; |
1927 | } | 1928 | } |
1928 | offset += le16_to_cpu(de->rec_len); | 1929 | offset += ext4_rec_len_from_disk(de->rec_len); |
1929 | de = (struct ext4_dir_entry_2 *) | 1930 | de = ext4_next_entry(de); |
1930 | ((char *) de + le16_to_cpu(de->rec_len)); | ||
1931 | } | 1931 | } |
1932 | brelse (bh); | 1932 | brelse (bh); |
1933 | return 1; | 1933 | return 1; |
@@ -2282,8 +2282,7 @@ retry: | |||
2282 | } | 2282 | } |
2283 | 2283 | ||
2284 | #define PARENT_INO(buffer) \ | 2284 | #define PARENT_INO(buffer) \ |
2285 | ((struct ext4_dir_entry_2 *) ((char *) buffer + \ | 2285 | (ext4_next_entry((struct ext4_dir_entry_2 *)(buffer))->inode) |
2286 | le16_to_cpu(((struct ext4_dir_entry_2 *) buffer)->rec_len)))->inode | ||
2287 | 2286 | ||
2288 | /* | 2287 | /* |
2289 | * Anybody can rename anything with this: the permission checks are left to the | 2288 | * Anybody can rename anything with this: the permission checks are left to the |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index bd8a52bb3999..4fbba60816f4 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -28,7 +28,7 @@ static int verify_group_input(struct super_block *sb, | |||
28 | struct ext4_super_block *es = sbi->s_es; | 28 | struct ext4_super_block *es = sbi->s_es; |
29 | ext4_fsblk_t start = ext4_blocks_count(es); | 29 | ext4_fsblk_t start = ext4_blocks_count(es); |
30 | ext4_fsblk_t end = start + input->blocks_count; | 30 | ext4_fsblk_t end = start + input->blocks_count; |
31 | unsigned group = input->group; | 31 | ext4_group_t group = input->group; |
32 | ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group; | 32 | ext4_fsblk_t itend = input->inode_table + sbi->s_itb_per_group; |
33 | unsigned overhead = ext4_bg_has_super(sb, group) ? | 33 | unsigned overhead = ext4_bg_has_super(sb, group) ? |
34 | (1 + ext4_bg_num_gdb(sb, group) + | 34 | (1 + ext4_bg_num_gdb(sb, group) + |
@@ -206,7 +206,7 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
206 | } | 206 | } |
207 | 207 | ||
208 | if (ext4_bg_has_super(sb, input->group)) { | 208 | if (ext4_bg_has_super(sb, input->group)) { |
209 | ext4_debug("mark backup superblock %#04lx (+0)\n", start); | 209 | ext4_debug("mark backup superblock %#04llx (+0)\n", start); |
210 | ext4_set_bit(0, bh->b_data); | 210 | ext4_set_bit(0, bh->b_data); |
211 | } | 211 | } |
212 | 212 | ||
@@ -215,7 +215,7 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
215 | i < gdblocks; i++, block++, bit++) { | 215 | i < gdblocks; i++, block++, bit++) { |
216 | struct buffer_head *gdb; | 216 | struct buffer_head *gdb; |
217 | 217 | ||
218 | ext4_debug("update backup group %#04lx (+%d)\n", block, bit); | 218 | ext4_debug("update backup group %#04llx (+%d)\n", block, bit); |
219 | 219 | ||
220 | if ((err = extend_or_restart_transaction(handle, 1, bh))) | 220 | if ((err = extend_or_restart_transaction(handle, 1, bh))) |
221 | goto exit_bh; | 221 | goto exit_bh; |
@@ -243,7 +243,7 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
243 | i < reserved_gdb; i++, block++, bit++) { | 243 | i < reserved_gdb; i++, block++, bit++) { |
244 | struct buffer_head *gdb; | 244 | struct buffer_head *gdb; |
245 | 245 | ||
246 | ext4_debug("clear reserved block %#04lx (+%d)\n", block, bit); | 246 | ext4_debug("clear reserved block %#04llx (+%d)\n", block, bit); |
247 | 247 | ||
248 | if ((err = extend_or_restart_transaction(handle, 1, bh))) | 248 | if ((err = extend_or_restart_transaction(handle, 1, bh))) |
249 | goto exit_bh; | 249 | goto exit_bh; |
@@ -256,10 +256,10 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
256 | ext4_set_bit(bit, bh->b_data); | 256 | ext4_set_bit(bit, bh->b_data); |
257 | brelse(gdb); | 257 | brelse(gdb); |
258 | } | 258 | } |
259 | ext4_debug("mark block bitmap %#04x (+%ld)\n", input->block_bitmap, | 259 | ext4_debug("mark block bitmap %#04llx (+%llu)\n", input->block_bitmap, |
260 | input->block_bitmap - start); | 260 | input->block_bitmap - start); |
261 | ext4_set_bit(input->block_bitmap - start, bh->b_data); | 261 | ext4_set_bit(input->block_bitmap - start, bh->b_data); |
262 | ext4_debug("mark inode bitmap %#04x (+%ld)\n", input->inode_bitmap, | 262 | ext4_debug("mark inode bitmap %#04llx (+%llu)\n", input->inode_bitmap, |
263 | input->inode_bitmap - start); | 263 | input->inode_bitmap - start); |
264 | ext4_set_bit(input->inode_bitmap - start, bh->b_data); | 264 | ext4_set_bit(input->inode_bitmap - start, bh->b_data); |
265 | 265 | ||
@@ -268,7 +268,7 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
268 | i < sbi->s_itb_per_group; i++, bit++, block++) { | 268 | i < sbi->s_itb_per_group; i++, bit++, block++) { |
269 | struct buffer_head *it; | 269 | struct buffer_head *it; |
270 | 270 | ||
271 | ext4_debug("clear inode block %#04lx (+%d)\n", block, bit); | 271 | ext4_debug("clear inode block %#04llx (+%d)\n", block, bit); |
272 | 272 | ||
273 | if ((err = extend_or_restart_transaction(handle, 1, bh))) | 273 | if ((err = extend_or_restart_transaction(handle, 1, bh))) |
274 | goto exit_bh; | 274 | goto exit_bh; |
@@ -291,7 +291,7 @@ static int setup_new_group_blocks(struct super_block *sb, | |||
291 | brelse(bh); | 291 | brelse(bh); |
292 | 292 | ||
293 | /* Mark unused entries in inode bitmap used */ | 293 | /* Mark unused entries in inode bitmap used */ |
294 | ext4_debug("clear inode bitmap %#04x (+%ld)\n", | 294 | ext4_debug("clear inode bitmap %#04llx (+%llu)\n", |
295 | input->inode_bitmap, input->inode_bitmap - start); | 295 | input->inode_bitmap, input->inode_bitmap - start); |
296 | if (IS_ERR(bh = bclean(handle, sb, input->inode_bitmap))) { | 296 | if (IS_ERR(bh = bclean(handle, sb, input->inode_bitmap))) { |
297 | err = PTR_ERR(bh); | 297 | err = PTR_ERR(bh); |
@@ -357,7 +357,7 @@ static int verify_reserved_gdb(struct super_block *sb, | |||
357 | struct buffer_head *primary) | 357 | struct buffer_head *primary) |
358 | { | 358 | { |
359 | const ext4_fsblk_t blk = primary->b_blocknr; | 359 | const ext4_fsblk_t blk = primary->b_blocknr; |
360 | const unsigned long end = EXT4_SB(sb)->s_groups_count; | 360 | const ext4_group_t end = EXT4_SB(sb)->s_groups_count; |
361 | unsigned three = 1; | 361 | unsigned three = 1; |
362 | unsigned five = 5; | 362 | unsigned five = 5; |
363 | unsigned seven = 7; | 363 | unsigned seven = 7; |
@@ -656,12 +656,12 @@ static void update_backups(struct super_block *sb, | |||
656 | int blk_off, char *data, int size) | 656 | int blk_off, char *data, int size) |
657 | { | 657 | { |
658 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 658 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
659 | const unsigned long last = sbi->s_groups_count; | 659 | const ext4_group_t last = sbi->s_groups_count; |
660 | const int bpg = EXT4_BLOCKS_PER_GROUP(sb); | 660 | const int bpg = EXT4_BLOCKS_PER_GROUP(sb); |
661 | unsigned three = 1; | 661 | unsigned three = 1; |
662 | unsigned five = 5; | 662 | unsigned five = 5; |
663 | unsigned seven = 7; | 663 | unsigned seven = 7; |
664 | unsigned group; | 664 | ext4_group_t group; |
665 | int rest = sb->s_blocksize - size; | 665 | int rest = sb->s_blocksize - size; |
666 | handle_t *handle; | 666 | handle_t *handle; |
667 | int err = 0, err2; | 667 | int err = 0, err2; |
@@ -716,7 +716,7 @@ static void update_backups(struct super_block *sb, | |||
716 | exit_err: | 716 | exit_err: |
717 | if (err) { | 717 | if (err) { |
718 | ext4_warning(sb, __FUNCTION__, | 718 | ext4_warning(sb, __FUNCTION__, |
719 | "can't update backup for group %d (err %d), " | 719 | "can't update backup for group %lu (err %d), " |
720 | "forcing fsck on next reboot", group, err); | 720 | "forcing fsck on next reboot", group, err); |
721 | sbi->s_mount_state &= ~EXT4_VALID_FS; | 721 | sbi->s_mount_state &= ~EXT4_VALID_FS; |
722 | sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS); | 722 | sbi->s_es->s_state &= cpu_to_le16(~EXT4_VALID_FS); |
@@ -952,7 +952,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
952 | ext4_fsblk_t n_blocks_count) | 952 | ext4_fsblk_t n_blocks_count) |
953 | { | 953 | { |
954 | ext4_fsblk_t o_blocks_count; | 954 | ext4_fsblk_t o_blocks_count; |
955 | unsigned long o_groups_count; | 955 | ext4_group_t o_groups_count; |
956 | ext4_grpblk_t last; | 956 | ext4_grpblk_t last; |
957 | ext4_grpblk_t add; | 957 | ext4_grpblk_t add; |
958 | struct buffer_head * bh; | 958 | struct buffer_head * bh; |
@@ -1054,7 +1054,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
1054 | ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh); | 1054 | ext4_journal_dirty_metadata(handle, EXT4_SB(sb)->s_sbh); |
1055 | sb->s_dirt = 1; | 1055 | sb->s_dirt = 1; |
1056 | unlock_super(sb); | 1056 | unlock_super(sb); |
1057 | ext4_debug("freeing blocks %lu through %llu\n", o_blocks_count, | 1057 | ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count, |
1058 | o_blocks_count + add); | 1058 | o_blocks_count + add); |
1059 | ext4_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks); | 1059 | ext4_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks); |
1060 | ext4_debug("freed blocks %llu through %llu\n", o_blocks_count, | 1060 | ext4_debug("freed blocks %llu through %llu\n", o_blocks_count, |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 1ca0f546c466..055a0cd0168e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -373,6 +373,66 @@ void ext4_update_dynamic_rev(struct super_block *sb) | |||
373 | */ | 373 | */ |
374 | } | 374 | } |
375 | 375 | ||
376 | int ext4_update_compat_feature(handle_t *handle, | ||
377 | struct super_block *sb, __u32 compat) | ||
378 | { | ||
379 | int err = 0; | ||
380 | if (!EXT4_HAS_COMPAT_FEATURE(sb, compat)) { | ||
381 | err = ext4_journal_get_write_access(handle, | ||
382 | EXT4_SB(sb)->s_sbh); | ||
383 | if (err) | ||
384 | return err; | ||
385 | EXT4_SET_COMPAT_FEATURE(sb, compat); | ||
386 | sb->s_dirt = 1; | ||
387 | handle->h_sync = 1; | ||
388 | BUFFER_TRACE(EXT4_SB(sb)->s_sbh, | ||
389 | "call ext4_journal_dirty_met adata"); | ||
390 | err = ext4_journal_dirty_metadata(handle, | ||
391 | EXT4_SB(sb)->s_sbh); | ||
392 | } | ||
393 | return err; | ||
394 | } | ||
395 | |||
396 | int ext4_update_rocompat_feature(handle_t *handle, | ||
397 | struct super_block *sb, __u32 rocompat) | ||
398 | { | ||
399 | int err = 0; | ||
400 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, rocompat)) { | ||
401 | err = ext4_journal_get_write_access(handle, | ||
402 | EXT4_SB(sb)->s_sbh); | ||
403 | if (err) | ||
404 | return err; | ||
405 | EXT4_SET_RO_COMPAT_FEATURE(sb, rocompat); | ||
406 | sb->s_dirt = 1; | ||
407 | handle->h_sync = 1; | ||
408 | BUFFER_TRACE(EXT4_SB(sb)->s_sbh, | ||
409 | "call ext4_journal_dirty_met adata"); | ||
410 | err = ext4_journal_dirty_metadata(handle, | ||
411 | EXT4_SB(sb)->s_sbh); | ||
412 | } | ||
413 | return err; | ||
414 | } | ||
415 | |||
416 | int ext4_update_incompat_feature(handle_t *handle, | ||
417 | struct super_block *sb, __u32 incompat) | ||
418 | { | ||
419 | int err = 0; | ||
420 | if (!EXT4_HAS_INCOMPAT_FEATURE(sb, incompat)) { | ||
421 | err = ext4_journal_get_write_access(handle, | ||
422 | EXT4_SB(sb)->s_sbh); | ||
423 | if (err) | ||
424 | return err; | ||
425 | EXT4_SET_INCOMPAT_FEATURE(sb, incompat); | ||
426 | sb->s_dirt = 1; | ||
427 | handle->h_sync = 1; | ||
428 | BUFFER_TRACE(EXT4_SB(sb)->s_sbh, | ||
429 | "call ext4_journal_dirty_met adata"); | ||
430 | err = ext4_journal_dirty_metadata(handle, | ||
431 | EXT4_SB(sb)->s_sbh); | ||
432 | } | ||
433 | return err; | ||
434 | } | ||
435 | |||
376 | /* | 436 | /* |
377 | * Open the external journal device | 437 | * Open the external journal device |
378 | */ | 438 | */ |
@@ -443,6 +503,7 @@ static void ext4_put_super (struct super_block * sb) | |||
443 | struct ext4_super_block *es = sbi->s_es; | 503 | struct ext4_super_block *es = sbi->s_es; |
444 | int i; | 504 | int i; |
445 | 505 | ||
506 | ext4_mb_release(sb); | ||
446 | ext4_ext_release(sb); | 507 | ext4_ext_release(sb); |
447 | ext4_xattr_put_super(sb); | 508 | ext4_xattr_put_super(sb); |
448 | jbd2_journal_destroy(sbi->s_journal); | 509 | jbd2_journal_destroy(sbi->s_journal); |
@@ -509,6 +570,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
509 | ei->i_block_alloc_info = NULL; | 570 | ei->i_block_alloc_info = NULL; |
510 | ei->vfs_inode.i_version = 1; | 571 | ei->vfs_inode.i_version = 1; |
511 | memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); | 572 | memset(&ei->i_cached_extent, 0, sizeof(struct ext4_ext_cache)); |
573 | INIT_LIST_HEAD(&ei->i_prealloc_list); | ||
574 | spin_lock_init(&ei->i_prealloc_lock); | ||
512 | return &ei->vfs_inode; | 575 | return &ei->vfs_inode; |
513 | } | 576 | } |
514 | 577 | ||
@@ -533,7 +596,7 @@ static void init_once(struct kmem_cache *cachep, void *foo) | |||
533 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 596 | #ifdef CONFIG_EXT4DEV_FS_XATTR |
534 | init_rwsem(&ei->xattr_sem); | 597 | init_rwsem(&ei->xattr_sem); |
535 | #endif | 598 | #endif |
536 | mutex_init(&ei->truncate_mutex); | 599 | init_rwsem(&ei->i_data_sem); |
537 | inode_init_once(&ei->vfs_inode); | 600 | inode_init_once(&ei->vfs_inode); |
538 | } | 601 | } |
539 | 602 | ||
@@ -605,18 +668,20 @@ static inline void ext4_show_quota_options(struct seq_file *seq, struct super_bl | |||
605 | */ | 668 | */ |
606 | static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | 669 | static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) |
607 | { | 670 | { |
671 | int def_errors; | ||
672 | unsigned long def_mount_opts; | ||
608 | struct super_block *sb = vfs->mnt_sb; | 673 | struct super_block *sb = vfs->mnt_sb; |
609 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 674 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
610 | struct ext4_super_block *es = sbi->s_es; | 675 | struct ext4_super_block *es = sbi->s_es; |
611 | unsigned long def_mount_opts; | ||
612 | 676 | ||
613 | def_mount_opts = le32_to_cpu(es->s_default_mount_opts); | 677 | def_mount_opts = le32_to_cpu(es->s_default_mount_opts); |
678 | def_errors = le16_to_cpu(es->s_errors); | ||
614 | 679 | ||
615 | if (sbi->s_sb_block != 1) | 680 | if (sbi->s_sb_block != 1) |
616 | seq_printf(seq, ",sb=%llu", sbi->s_sb_block); | 681 | seq_printf(seq, ",sb=%llu", sbi->s_sb_block); |
617 | if (test_opt(sb, MINIX_DF)) | 682 | if (test_opt(sb, MINIX_DF)) |
618 | seq_puts(seq, ",minixdf"); | 683 | seq_puts(seq, ",minixdf"); |
619 | if (test_opt(sb, GRPID)) | 684 | if (test_opt(sb, GRPID) && !(def_mount_opts & EXT4_DEFM_BSDGROUPS)) |
620 | seq_puts(seq, ",grpid"); | 685 | seq_puts(seq, ",grpid"); |
621 | if (!test_opt(sb, GRPID) && (def_mount_opts & EXT4_DEFM_BSDGROUPS)) | 686 | if (!test_opt(sb, GRPID) && (def_mount_opts & EXT4_DEFM_BSDGROUPS)) |
622 | seq_puts(seq, ",nogrpid"); | 687 | seq_puts(seq, ",nogrpid"); |
@@ -628,34 +693,33 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
628 | le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) { | 693 | le16_to_cpu(es->s_def_resgid) != EXT4_DEF_RESGID) { |
629 | seq_printf(seq, ",resgid=%u", sbi->s_resgid); | 694 | seq_printf(seq, ",resgid=%u", sbi->s_resgid); |
630 | } | 695 | } |
631 | if (test_opt(sb, ERRORS_CONT)) { | 696 | if (test_opt(sb, ERRORS_RO)) { |
632 | int def_errors = le16_to_cpu(es->s_errors); | ||
633 | |||
634 | if (def_errors == EXT4_ERRORS_PANIC || | 697 | if (def_errors == EXT4_ERRORS_PANIC || |
635 | def_errors == EXT4_ERRORS_RO) { | 698 | def_errors == EXT4_ERRORS_CONTINUE) { |
636 | seq_puts(seq, ",errors=continue"); | 699 | seq_puts(seq, ",errors=remount-ro"); |
637 | } | 700 | } |
638 | } | 701 | } |
639 | if (test_opt(sb, ERRORS_RO)) | 702 | if (test_opt(sb, ERRORS_CONT) && def_errors != EXT4_ERRORS_CONTINUE) |
640 | seq_puts(seq, ",errors=remount-ro"); | 703 | seq_puts(seq, ",errors=continue"); |
641 | if (test_opt(sb, ERRORS_PANIC)) | 704 | if (test_opt(sb, ERRORS_PANIC) && def_errors != EXT4_ERRORS_PANIC) |
642 | seq_puts(seq, ",errors=panic"); | 705 | seq_puts(seq, ",errors=panic"); |
643 | if (test_opt(sb, NO_UID32)) | 706 | if (test_opt(sb, NO_UID32) && !(def_mount_opts & EXT4_DEFM_UID16)) |
644 | seq_puts(seq, ",nouid32"); | 707 | seq_puts(seq, ",nouid32"); |
645 | if (test_opt(sb, DEBUG)) | 708 | if (test_opt(sb, DEBUG) && !(def_mount_opts & EXT4_DEFM_DEBUG)) |
646 | seq_puts(seq, ",debug"); | 709 | seq_puts(seq, ",debug"); |
647 | if (test_opt(sb, OLDALLOC)) | 710 | if (test_opt(sb, OLDALLOC)) |
648 | seq_puts(seq, ",oldalloc"); | 711 | seq_puts(seq, ",oldalloc"); |
649 | #ifdef CONFIG_EXT4_FS_XATTR | 712 | #ifdef CONFIG_EXT4DEV_FS_XATTR |
650 | if (test_opt(sb, XATTR_USER)) | 713 | if (test_opt(sb, XATTR_USER) && |
714 | !(def_mount_opts & EXT4_DEFM_XATTR_USER)) | ||
651 | seq_puts(seq, ",user_xattr"); | 715 | seq_puts(seq, ",user_xattr"); |
652 | if (!test_opt(sb, XATTR_USER) && | 716 | if (!test_opt(sb, XATTR_USER) && |
653 | (def_mount_opts & EXT4_DEFM_XATTR_USER)) { | 717 | (def_mount_opts & EXT4_DEFM_XATTR_USER)) { |
654 | seq_puts(seq, ",nouser_xattr"); | 718 | seq_puts(seq, ",nouser_xattr"); |
655 | } | 719 | } |
656 | #endif | 720 | #endif |
657 | #ifdef CONFIG_EXT4_FS_POSIX_ACL | 721 | #ifdef CONFIG_EXT4DEV_FS_POSIX_ACL |
658 | if (test_opt(sb, POSIX_ACL)) | 722 | if (test_opt(sb, POSIX_ACL) && !(def_mount_opts & EXT4_DEFM_ACL)) |
659 | seq_puts(seq, ",acl"); | 723 | seq_puts(seq, ",acl"); |
660 | if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL)) | 724 | if (!test_opt(sb, POSIX_ACL) && (def_mount_opts & EXT4_DEFM_ACL)) |
661 | seq_puts(seq, ",noacl"); | 725 | seq_puts(seq, ",noacl"); |
@@ -672,7 +736,17 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
672 | seq_puts(seq, ",nobh"); | 736 | seq_puts(seq, ",nobh"); |
673 | if (!test_opt(sb, EXTENTS)) | 737 | if (!test_opt(sb, EXTENTS)) |
674 | seq_puts(seq, ",noextents"); | 738 | seq_puts(seq, ",noextents"); |
739 | if (!test_opt(sb, MBALLOC)) | ||
740 | seq_puts(seq, ",nomballoc"); | ||
741 | if (test_opt(sb, I_VERSION)) | ||
742 | seq_puts(seq, ",i_version"); | ||
675 | 743 | ||
744 | if (sbi->s_stripe) | ||
745 | seq_printf(seq, ",stripe=%lu", sbi->s_stripe); | ||
746 | /* | ||
747 | * journal mode get enabled in different ways | ||
748 | * So just print the value even if we didn't specify it | ||
749 | */ | ||
676 | if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) | 750 | if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) |
677 | seq_puts(seq, ",data=journal"); | 751 | seq_puts(seq, ",data=journal"); |
678 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) | 752 | else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) |
@@ -681,7 +755,6 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
681 | seq_puts(seq, ",data=writeback"); | 755 | seq_puts(seq, ",data=writeback"); |
682 | 756 | ||
683 | ext4_show_quota_options(seq, sb); | 757 | ext4_show_quota_options(seq, sb); |
684 | |||
685 | return 0; | 758 | return 0; |
686 | } | 759 | } |
687 | 760 | ||
@@ -809,11 +882,13 @@ enum { | |||
809 | Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, | 882 | Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, |
810 | Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh, | 883 | Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh, |
811 | Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, | 884 | Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, |
885 | Opt_journal_checksum, Opt_journal_async_commit, | ||
812 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, | 886 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, |
813 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 887 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
814 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, | 888 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, |
815 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, | 889 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, |
816 | Opt_grpquota, Opt_extents, Opt_noextents, | 890 | Opt_grpquota, Opt_extents, Opt_noextents, Opt_i_version, |
891 | Opt_mballoc, Opt_nomballoc, Opt_stripe, | ||
817 | }; | 892 | }; |
818 | 893 | ||
819 | static match_table_t tokens = { | 894 | static match_table_t tokens = { |
@@ -848,6 +923,8 @@ static match_table_t tokens = { | |||
848 | {Opt_journal_update, "journal=update"}, | 923 | {Opt_journal_update, "journal=update"}, |
849 | {Opt_journal_inum, "journal=%u"}, | 924 | {Opt_journal_inum, "journal=%u"}, |
850 | {Opt_journal_dev, "journal_dev=%u"}, | 925 | {Opt_journal_dev, "journal_dev=%u"}, |
926 | {Opt_journal_checksum, "journal_checksum"}, | ||
927 | {Opt_journal_async_commit, "journal_async_commit"}, | ||
851 | {Opt_abort, "abort"}, | 928 | {Opt_abort, "abort"}, |
852 | {Opt_data_journal, "data=journal"}, | 929 | {Opt_data_journal, "data=journal"}, |
853 | {Opt_data_ordered, "data=ordered"}, | 930 | {Opt_data_ordered, "data=ordered"}, |
@@ -865,6 +942,10 @@ static match_table_t tokens = { | |||
865 | {Opt_barrier, "barrier=%u"}, | 942 | {Opt_barrier, "barrier=%u"}, |
866 | {Opt_extents, "extents"}, | 943 | {Opt_extents, "extents"}, |
867 | {Opt_noextents, "noextents"}, | 944 | {Opt_noextents, "noextents"}, |
945 | {Opt_i_version, "i_version"}, | ||
946 | {Opt_mballoc, "mballoc"}, | ||
947 | {Opt_nomballoc, "nomballoc"}, | ||
948 | {Opt_stripe, "stripe=%u"}, | ||
868 | {Opt_err, NULL}, | 949 | {Opt_err, NULL}, |
869 | {Opt_resize, "resize"}, | 950 | {Opt_resize, "resize"}, |
870 | }; | 951 | }; |
@@ -1035,6 +1116,13 @@ static int parse_options (char *options, struct super_block *sb, | |||
1035 | return 0; | 1116 | return 0; |
1036 | *journal_devnum = option; | 1117 | *journal_devnum = option; |
1037 | break; | 1118 | break; |
1119 | case Opt_journal_checksum: | ||
1120 | set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM); | ||
1121 | break; | ||
1122 | case Opt_journal_async_commit: | ||
1123 | set_opt(sbi->s_mount_opt, JOURNAL_ASYNC_COMMIT); | ||
1124 | set_opt(sbi->s_mount_opt, JOURNAL_CHECKSUM); | ||
1125 | break; | ||
1038 | case Opt_noload: | 1126 | case Opt_noload: |
1039 | set_opt (sbi->s_mount_opt, NOLOAD); | 1127 | set_opt (sbi->s_mount_opt, NOLOAD); |
1040 | break; | 1128 | break; |
@@ -1203,6 +1291,23 @@ clear_qf_name: | |||
1203 | case Opt_noextents: | 1291 | case Opt_noextents: |
1204 | clear_opt (sbi->s_mount_opt, EXTENTS); | 1292 | clear_opt (sbi->s_mount_opt, EXTENTS); |
1205 | break; | 1293 | break; |
1294 | case Opt_i_version: | ||
1295 | set_opt(sbi->s_mount_opt, I_VERSION); | ||
1296 | sb->s_flags |= MS_I_VERSION; | ||
1297 | break; | ||
1298 | case Opt_mballoc: | ||
1299 | set_opt(sbi->s_mount_opt, MBALLOC); | ||
1300 | break; | ||
1301 | case Opt_nomballoc: | ||
1302 | clear_opt(sbi->s_mount_opt, MBALLOC); | ||
1303 | break; | ||
1304 | case Opt_stripe: | ||
1305 | if (match_int(&args[0], &option)) | ||
1306 | return 0; | ||
1307 | if (option < 0) | ||
1308 | return 0; | ||
1309 | sbi->s_stripe = option; | ||
1310 | break; | ||
1206 | default: | 1311 | default: |
1207 | printk (KERN_ERR | 1312 | printk (KERN_ERR |
1208 | "EXT4-fs: Unrecognized mount option \"%s\" " | 1313 | "EXT4-fs: Unrecognized mount option \"%s\" " |
@@ -1364,7 +1469,7 @@ static int ext4_check_descriptors (struct super_block * sb) | |||
1364 | struct ext4_group_desc * gdp = NULL; | 1469 | struct ext4_group_desc * gdp = NULL; |
1365 | int desc_block = 0; | 1470 | int desc_block = 0; |
1366 | int flexbg_flag = 0; | 1471 | int flexbg_flag = 0; |
1367 | int i; | 1472 | ext4_group_t i; |
1368 | 1473 | ||
1369 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) | 1474 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) |
1370 | flexbg_flag = 1; | 1475 | flexbg_flag = 1; |
@@ -1386,7 +1491,7 @@ static int ext4_check_descriptors (struct super_block * sb) | |||
1386 | if (block_bitmap < first_block || block_bitmap > last_block) | 1491 | if (block_bitmap < first_block || block_bitmap > last_block) |
1387 | { | 1492 | { |
1388 | ext4_error (sb, "ext4_check_descriptors", | 1493 | ext4_error (sb, "ext4_check_descriptors", |
1389 | "Block bitmap for group %d" | 1494 | "Block bitmap for group %lu" |
1390 | " not in group (block %llu)!", | 1495 | " not in group (block %llu)!", |
1391 | i, block_bitmap); | 1496 | i, block_bitmap); |
1392 | return 0; | 1497 | return 0; |
@@ -1395,7 +1500,7 @@ static int ext4_check_descriptors (struct super_block * sb) | |||
1395 | if (inode_bitmap < first_block || inode_bitmap > last_block) | 1500 | if (inode_bitmap < first_block || inode_bitmap > last_block) |
1396 | { | 1501 | { |
1397 | ext4_error (sb, "ext4_check_descriptors", | 1502 | ext4_error (sb, "ext4_check_descriptors", |
1398 | "Inode bitmap for group %d" | 1503 | "Inode bitmap for group %lu" |
1399 | " not in group (block %llu)!", | 1504 | " not in group (block %llu)!", |
1400 | i, inode_bitmap); | 1505 | i, inode_bitmap); |
1401 | return 0; | 1506 | return 0; |
@@ -1405,17 +1510,16 @@ static int ext4_check_descriptors (struct super_block * sb) | |||
1405 | inode_table + sbi->s_itb_per_group - 1 > last_block) | 1510 | inode_table + sbi->s_itb_per_group - 1 > last_block) |
1406 | { | 1511 | { |
1407 | ext4_error (sb, "ext4_check_descriptors", | 1512 | ext4_error (sb, "ext4_check_descriptors", |
1408 | "Inode table for group %d" | 1513 | "Inode table for group %lu" |
1409 | " not in group (block %llu)!", | 1514 | " not in group (block %llu)!", |
1410 | i, inode_table); | 1515 | i, inode_table); |
1411 | return 0; | 1516 | return 0; |
1412 | } | 1517 | } |
1413 | if (!ext4_group_desc_csum_verify(sbi, i, gdp)) { | 1518 | if (!ext4_group_desc_csum_verify(sbi, i, gdp)) { |
1414 | ext4_error(sb, __FUNCTION__, | 1519 | ext4_error(sb, __FUNCTION__, |
1415 | "Checksum for group %d failed (%u!=%u)\n", i, | 1520 | "Checksum for group %lu failed (%u!=%u)\n", |
1416 | le16_to_cpu(ext4_group_desc_csum(sbi, i, | 1521 | i, le16_to_cpu(ext4_group_desc_csum(sbi, i, |
1417 | gdp)), | 1522 | gdp)), le16_to_cpu(gdp->bg_checksum)); |
1418 | le16_to_cpu(gdp->bg_checksum)); | ||
1419 | return 0; | 1523 | return 0; |
1420 | } | 1524 | } |
1421 | if (!flexbg_flag) | 1525 | if (!flexbg_flag) |
@@ -1429,7 +1533,6 @@ static int ext4_check_descriptors (struct super_block * sb) | |||
1429 | return 1; | 1533 | return 1; |
1430 | } | 1534 | } |
1431 | 1535 | ||
1432 | |||
1433 | /* ext4_orphan_cleanup() walks a singly-linked list of inodes (starting at | 1536 | /* ext4_orphan_cleanup() walks a singly-linked list of inodes (starting at |
1434 | * the superblock) which were deleted from all directories, but held open by | 1537 | * the superblock) which were deleted from all directories, but held open by |
1435 | * a process at the time of a crash. We walk the list and try to delete these | 1538 | * a process at the time of a crash. We walk the list and try to delete these |
@@ -1542,20 +1645,95 @@ static void ext4_orphan_cleanup (struct super_block * sb, | |||
1542 | #endif | 1645 | #endif |
1543 | sb->s_flags = s_flags; /* Restore MS_RDONLY status */ | 1646 | sb->s_flags = s_flags; /* Restore MS_RDONLY status */ |
1544 | } | 1647 | } |
1648 | /* | ||
1649 | * Maximal extent format file size. | ||
1650 | * Resulting logical blkno at s_maxbytes must fit in our on-disk | ||
1651 | * extent format containers, within a sector_t, and within i_blocks | ||
1652 | * in the vfs. ext4 inode has 48 bits of i_block in fsblock units, | ||
1653 | * so that won't be a limiting factor. | ||
1654 | * | ||
1655 | * Note, this does *not* consider any metadata overhead for vfs i_blocks. | ||
1656 | */ | ||
1657 | static loff_t ext4_max_size(int blkbits) | ||
1658 | { | ||
1659 | loff_t res; | ||
1660 | loff_t upper_limit = MAX_LFS_FILESIZE; | ||
1661 | |||
1662 | /* small i_blocks in vfs inode? */ | ||
1663 | if (sizeof(blkcnt_t) < sizeof(u64)) { | ||
1664 | /* | ||
1665 | * CONFIG_LSF is not enabled implies the inode | ||
1666 | * i_block represent total blocks in 512 bytes | ||
1667 | * 32 == size of vfs inode i_blocks * 8 | ||
1668 | */ | ||
1669 | upper_limit = (1LL << 32) - 1; | ||
1670 | |||
1671 | /* total blocks in file system block size */ | ||
1672 | upper_limit >>= (blkbits - 9); | ||
1673 | upper_limit <<= blkbits; | ||
1674 | } | ||
1675 | |||
1676 | /* 32-bit extent-start container, ee_block */ | ||
1677 | res = 1LL << 32; | ||
1678 | res <<= blkbits; | ||
1679 | res -= 1; | ||
1680 | |||
1681 | /* Sanity check against vm- & vfs- imposed limits */ | ||
1682 | if (res > upper_limit) | ||
1683 | res = upper_limit; | ||
1684 | |||
1685 | return res; | ||
1686 | } | ||
1545 | 1687 | ||
1546 | /* | 1688 | /* |
1547 | * Maximal file size. There is a direct, and {,double-,triple-}indirect | 1689 | * Maximal bitmap file size. There is a direct, and {,double-,triple-}indirect |
1548 | * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks. | 1690 | * block limit, and also a limit of (2^48 - 1) 512-byte sectors in i_blocks. |
1549 | * We need to be 1 filesystem block less than the 2^32 sector limit. | 1691 | * We need to be 1 filesystem block less than the 2^48 sector limit. |
1550 | */ | 1692 | */ |
1551 | static loff_t ext4_max_size(int bits) | 1693 | static loff_t ext4_max_bitmap_size(int bits) |
1552 | { | 1694 | { |
1553 | loff_t res = EXT4_NDIR_BLOCKS; | 1695 | loff_t res = EXT4_NDIR_BLOCKS; |
1554 | /* This constant is calculated to be the largest file size for a | 1696 | int meta_blocks; |
1555 | * dense, 4k-blocksize file such that the total number of | 1697 | loff_t upper_limit; |
1698 | /* This is calculated to be the largest file size for a | ||
1699 | * dense, bitmapped file such that the total number of | ||
1556 | * sectors in the file, including data and all indirect blocks, | 1700 | * sectors in the file, including data and all indirect blocks, |
1557 | * does not exceed 2^32. */ | 1701 | * does not exceed 2^48 -1 |
1558 | const loff_t upper_limit = 0x1ff7fffd000LL; | 1702 | * __u32 i_blocks_lo and _u16 i_blocks_high representing the |
1703 | * total number of 512 bytes blocks of the file | ||
1704 | */ | ||
1705 | |||
1706 | if (sizeof(blkcnt_t) < sizeof(u64)) { | ||
1707 | /* | ||
1708 | * CONFIG_LSF is not enabled implies the inode | ||
1709 | * i_block represent total blocks in 512 bytes | ||
1710 | * 32 == size of vfs inode i_blocks * 8 | ||
1711 | */ | ||
1712 | upper_limit = (1LL << 32) - 1; | ||
1713 | |||
1714 | /* total blocks in file system block size */ | ||
1715 | upper_limit >>= (bits - 9); | ||
1716 | |||
1717 | } else { | ||
1718 | /* | ||
1719 | * We use 48 bit ext4_inode i_blocks | ||
1720 | * With EXT4_HUGE_FILE_FL set the i_blocks | ||
1721 | * represent total number of blocks in | ||
1722 | * file system block size | ||
1723 | */ | ||
1724 | upper_limit = (1LL << 48) - 1; | ||
1725 | |||
1726 | } | ||
1727 | |||
1728 | /* indirect blocks */ | ||
1729 | meta_blocks = 1; | ||
1730 | /* double indirect blocks */ | ||
1731 | meta_blocks += 1 + (1LL << (bits-2)); | ||
1732 | /* tripple indirect blocks */ | ||
1733 | meta_blocks += 1 + (1LL << (bits-2)) + (1LL << (2*(bits-2))); | ||
1734 | |||
1735 | upper_limit -= meta_blocks; | ||
1736 | upper_limit <<= bits; | ||
1559 | 1737 | ||
1560 | res += 1LL << (bits-2); | 1738 | res += 1LL << (bits-2); |
1561 | res += 1LL << (2*(bits-2)); | 1739 | res += 1LL << (2*(bits-2)); |
@@ -1563,6 +1741,10 @@ static loff_t ext4_max_size(int bits) | |||
1563 | res <<= bits; | 1741 | res <<= bits; |
1564 | if (res > upper_limit) | 1742 | if (res > upper_limit) |
1565 | res = upper_limit; | 1743 | res = upper_limit; |
1744 | |||
1745 | if (res > MAX_LFS_FILESIZE) | ||
1746 | res = MAX_LFS_FILESIZE; | ||
1747 | |||
1566 | return res; | 1748 | return res; |
1567 | } | 1749 | } |
1568 | 1750 | ||
@@ -1570,7 +1752,7 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb, | |||
1570 | ext4_fsblk_t logical_sb_block, int nr) | 1752 | ext4_fsblk_t logical_sb_block, int nr) |
1571 | { | 1753 | { |
1572 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 1754 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
1573 | unsigned long bg, first_meta_bg; | 1755 | ext4_group_t bg, first_meta_bg; |
1574 | int has_super = 0; | 1756 | int has_super = 0; |
1575 | 1757 | ||
1576 | first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg); | 1758 | first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg); |
@@ -1584,8 +1766,39 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb, | |||
1584 | return (has_super + ext4_group_first_block_no(sb, bg)); | 1766 | return (has_super + ext4_group_first_block_no(sb, bg)); |
1585 | } | 1767 | } |
1586 | 1768 | ||
1769 | /** | ||
1770 | * ext4_get_stripe_size: Get the stripe size. | ||
1771 | * @sbi: In memory super block info | ||
1772 | * | ||
1773 | * If we have specified it via mount option, then | ||
1774 | * use the mount option value. If the value specified at mount time is | ||
1775 | * greater than the blocks per group use the super block value. | ||
1776 | * If the super block value is greater than blocks per group return 0. | ||
1777 | * Allocator needs it be less than blocks per group. | ||
1778 | * | ||
1779 | */ | ||
1780 | static unsigned long ext4_get_stripe_size(struct ext4_sb_info *sbi) | ||
1781 | { | ||
1782 | unsigned long stride = le16_to_cpu(sbi->s_es->s_raid_stride); | ||
1783 | unsigned long stripe_width = | ||
1784 | le32_to_cpu(sbi->s_es->s_raid_stripe_width); | ||
1785 | |||
1786 | if (sbi->s_stripe && sbi->s_stripe <= sbi->s_blocks_per_group) | ||
1787 | return sbi->s_stripe; | ||
1788 | |||
1789 | if (stripe_width <= sbi->s_blocks_per_group) | ||
1790 | return stripe_width; | ||
1791 | |||
1792 | if (stride <= sbi->s_blocks_per_group) | ||
1793 | return stride; | ||
1794 | |||
1795 | return 0; | ||
1796 | } | ||
1587 | 1797 | ||
1588 | static int ext4_fill_super (struct super_block *sb, void *data, int silent) | 1798 | static int ext4_fill_super (struct super_block *sb, void *data, int silent) |
1799 | __releases(kernel_sem) | ||
1800 | __acquires(kernel_sem) | ||
1801 | |||
1589 | { | 1802 | { |
1590 | struct buffer_head * bh; | 1803 | struct buffer_head * bh; |
1591 | struct ext4_super_block *es = NULL; | 1804 | struct ext4_super_block *es = NULL; |
@@ -1599,7 +1812,6 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1599 | unsigned long def_mount_opts; | 1812 | unsigned long def_mount_opts; |
1600 | struct inode *root; | 1813 | struct inode *root; |
1601 | int blocksize; | 1814 | int blocksize; |
1602 | int hblock; | ||
1603 | int db_count; | 1815 | int db_count; |
1604 | int i; | 1816 | int i; |
1605 | int needs_recovery; | 1817 | int needs_recovery; |
@@ -1624,6 +1836,11 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1624 | goto out_fail; | 1836 | goto out_fail; |
1625 | } | 1837 | } |
1626 | 1838 | ||
1839 | if (!sb_set_blocksize(sb, blocksize)) { | ||
1840 | printk(KERN_ERR "EXT4-fs: bad blocksize %d.\n", blocksize); | ||
1841 | goto out_fail; | ||
1842 | } | ||
1843 | |||
1627 | /* | 1844 | /* |
1628 | * The ext4 superblock will not be buffer aligned for other than 1kB | 1845 | * The ext4 superblock will not be buffer aligned for other than 1kB |
1629 | * block sizes. We need to calculate the offset from buffer start. | 1846 | * block sizes. We need to calculate the offset from buffer start. |
@@ -1674,10 +1891,10 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1674 | 1891 | ||
1675 | if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC) | 1892 | if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_PANIC) |
1676 | set_opt(sbi->s_mount_opt, ERRORS_PANIC); | 1893 | set_opt(sbi->s_mount_opt, ERRORS_PANIC); |
1677 | else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_RO) | 1894 | else if (le16_to_cpu(sbi->s_es->s_errors) == EXT4_ERRORS_CONTINUE) |
1678 | set_opt(sbi->s_mount_opt, ERRORS_RO); | ||
1679 | else | ||
1680 | set_opt(sbi->s_mount_opt, ERRORS_CONT); | 1895 | set_opt(sbi->s_mount_opt, ERRORS_CONT); |
1896 | else | ||
1897 | set_opt(sbi->s_mount_opt, ERRORS_RO); | ||
1681 | 1898 | ||
1682 | sbi->s_resuid = le16_to_cpu(es->s_def_resuid); | 1899 | sbi->s_resuid = le16_to_cpu(es->s_def_resuid); |
1683 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); | 1900 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); |
@@ -1689,6 +1906,11 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1689 | * User -o noextents to turn it off | 1906 | * User -o noextents to turn it off |
1690 | */ | 1907 | */ |
1691 | set_opt(sbi->s_mount_opt, EXTENTS); | 1908 | set_opt(sbi->s_mount_opt, EXTENTS); |
1909 | /* | ||
1910 | * turn on mballoc feature by default in ext4 filesystem | ||
1911 | * User -o nomballoc to turn it off | ||
1912 | */ | ||
1913 | set_opt(sbi->s_mount_opt, MBALLOC); | ||
1692 | 1914 | ||
1693 | if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum, | 1915 | if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum, |
1694 | NULL, 0)) | 1916 | NULL, 0)) |
@@ -1723,6 +1945,19 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1723 | sb->s_id, le32_to_cpu(features)); | 1945 | sb->s_id, le32_to_cpu(features)); |
1724 | goto failed_mount; | 1946 | goto failed_mount; |
1725 | } | 1947 | } |
1948 | if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { | ||
1949 | /* | ||
1950 | * Large file size enabled file system can only be | ||
1951 | * mount if kernel is build with CONFIG_LSF | ||
1952 | */ | ||
1953 | if (sizeof(root->i_blocks) < sizeof(u64) && | ||
1954 | !(sb->s_flags & MS_RDONLY)) { | ||
1955 | printk(KERN_ERR "EXT4-fs: %s: Filesystem with huge " | ||
1956 | "files cannot be mounted read-write " | ||
1957 | "without CONFIG_LSF.\n", sb->s_id); | ||
1958 | goto failed_mount; | ||
1959 | } | ||
1960 | } | ||
1726 | blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); | 1961 | blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); |
1727 | 1962 | ||
1728 | if (blocksize < EXT4_MIN_BLOCK_SIZE || | 1963 | if (blocksize < EXT4_MIN_BLOCK_SIZE || |
@@ -1733,20 +1968,16 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1733 | goto failed_mount; | 1968 | goto failed_mount; |
1734 | } | 1969 | } |
1735 | 1970 | ||
1736 | hblock = bdev_hardsect_size(sb->s_bdev); | ||
1737 | if (sb->s_blocksize != blocksize) { | 1971 | if (sb->s_blocksize != blocksize) { |
1738 | /* | 1972 | |
1739 | * Make sure the blocksize for the filesystem is larger | 1973 | /* Validate the filesystem blocksize */ |
1740 | * than the hardware sectorsize for the machine. | 1974 | if (!sb_set_blocksize(sb, blocksize)) { |
1741 | */ | 1975 | printk(KERN_ERR "EXT4-fs: bad block size %d.\n", |
1742 | if (blocksize < hblock) { | 1976 | blocksize); |
1743 | printk(KERN_ERR "EXT4-fs: blocksize %d too small for " | ||
1744 | "device blocksize %d.\n", blocksize, hblock); | ||
1745 | goto failed_mount; | 1977 | goto failed_mount; |
1746 | } | 1978 | } |
1747 | 1979 | ||
1748 | brelse (bh); | 1980 | brelse (bh); |
1749 | sb_set_blocksize(sb, blocksize); | ||
1750 | logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE; | 1981 | logical_sb_block = sb_block * EXT4_MIN_BLOCK_SIZE; |
1751 | offset = do_div(logical_sb_block, blocksize); | 1982 | offset = do_div(logical_sb_block, blocksize); |
1752 | bh = sb_bread(sb, logical_sb_block); | 1983 | bh = sb_bread(sb, logical_sb_block); |
@@ -1764,6 +1995,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1764 | } | 1995 | } |
1765 | } | 1996 | } |
1766 | 1997 | ||
1998 | sbi->s_bitmap_maxbytes = ext4_max_bitmap_size(sb->s_blocksize_bits); | ||
1767 | sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits); | 1999 | sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits); |
1768 | 2000 | ||
1769 | if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) { | 2001 | if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) { |
@@ -1838,6 +2070,17 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1838 | 2070 | ||
1839 | if (EXT4_BLOCKS_PER_GROUP(sb) == 0) | 2071 | if (EXT4_BLOCKS_PER_GROUP(sb) == 0) |
1840 | goto cantfind_ext4; | 2072 | goto cantfind_ext4; |
2073 | |||
2074 | /* ensure blocks_count calculation below doesn't sign-extend */ | ||
2075 | if (ext4_blocks_count(es) + EXT4_BLOCKS_PER_GROUP(sb) < | ||
2076 | le32_to_cpu(es->s_first_data_block) + 1) { | ||
2077 | printk(KERN_WARNING "EXT4-fs: bad geometry: block count %llu, " | ||
2078 | "first data block %u, blocks per group %lu\n", | ||
2079 | ext4_blocks_count(es), | ||
2080 | le32_to_cpu(es->s_first_data_block), | ||
2081 | EXT4_BLOCKS_PER_GROUP(sb)); | ||
2082 | goto failed_mount; | ||
2083 | } | ||
1841 | blocks_count = (ext4_blocks_count(es) - | 2084 | blocks_count = (ext4_blocks_count(es) - |
1842 | le32_to_cpu(es->s_first_data_block) + | 2085 | le32_to_cpu(es->s_first_data_block) + |
1843 | EXT4_BLOCKS_PER_GROUP(sb) - 1); | 2086 | EXT4_BLOCKS_PER_GROUP(sb) - 1); |
@@ -1900,6 +2143,8 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1900 | sbi->s_rsv_window_head.rsv_goal_size = 0; | 2143 | sbi->s_rsv_window_head.rsv_goal_size = 0; |
1901 | ext4_rsv_window_add(sb, &sbi->s_rsv_window_head); | 2144 | ext4_rsv_window_add(sb, &sbi->s_rsv_window_head); |
1902 | 2145 | ||
2146 | sbi->s_stripe = ext4_get_stripe_size(sbi); | ||
2147 | |||
1903 | /* | 2148 | /* |
1904 | * set up enough so that it can read an inode | 2149 | * set up enough so that it can read an inode |
1905 | */ | 2150 | */ |
@@ -1944,6 +2189,21 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
1944 | goto failed_mount4; | 2189 | goto failed_mount4; |
1945 | } | 2190 | } |
1946 | 2191 | ||
2192 | if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) { | ||
2193 | jbd2_journal_set_features(sbi->s_journal, | ||
2194 | JBD2_FEATURE_COMPAT_CHECKSUM, 0, | ||
2195 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); | ||
2196 | } else if (test_opt(sb, JOURNAL_CHECKSUM)) { | ||
2197 | jbd2_journal_set_features(sbi->s_journal, | ||
2198 | JBD2_FEATURE_COMPAT_CHECKSUM, 0, 0); | ||
2199 | jbd2_journal_clear_features(sbi->s_journal, 0, 0, | ||
2200 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); | ||
2201 | } else { | ||
2202 | jbd2_journal_clear_features(sbi->s_journal, | ||
2203 | JBD2_FEATURE_COMPAT_CHECKSUM, 0, | ||
2204 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT); | ||
2205 | } | ||
2206 | |||
1947 | /* We have now updated the journal if required, so we can | 2207 | /* We have now updated the journal if required, so we can |
1948 | * validate the data journaling mode. */ | 2208 | * validate the data journaling mode. */ |
1949 | switch (test_opt(sb, DATA_FLAGS)) { | 2209 | switch (test_opt(sb, DATA_FLAGS)) { |
@@ -2044,6 +2304,7 @@ static int ext4_fill_super (struct super_block *sb, void *data, int silent) | |||
2044 | "writeback"); | 2304 | "writeback"); |
2045 | 2305 | ||
2046 | ext4_ext_init(sb); | 2306 | ext4_ext_init(sb); |
2307 | ext4_mb_init(sb, needs_recovery); | ||
2047 | 2308 | ||
2048 | lock_kernel(); | 2309 | lock_kernel(); |
2049 | return 0; | 2310 | return 0; |
@@ -2673,7 +2934,7 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
2673 | if (test_opt(sb, MINIX_DF)) { | 2934 | if (test_opt(sb, MINIX_DF)) { |
2674 | sbi->s_overhead_last = 0; | 2935 | sbi->s_overhead_last = 0; |
2675 | } else if (sbi->s_blocks_last != ext4_blocks_count(es)) { | 2936 | } else if (sbi->s_blocks_last != ext4_blocks_count(es)) { |
2676 | unsigned long ngroups = sbi->s_groups_count, i; | 2937 | ext4_group_t ngroups = sbi->s_groups_count, i; |
2677 | ext4_fsblk_t overhead = 0; | 2938 | ext4_fsblk_t overhead = 0; |
2678 | smp_rmb(); | 2939 | smp_rmb(); |
2679 | 2940 | ||
@@ -2909,7 +3170,7 @@ static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, | |||
2909 | size_t len, loff_t off) | 3170 | size_t len, loff_t off) |
2910 | { | 3171 | { |
2911 | struct inode *inode = sb_dqopt(sb)->files[type]; | 3172 | struct inode *inode = sb_dqopt(sb)->files[type]; |
2912 | sector_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb); | 3173 | ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb); |
2913 | int err = 0; | 3174 | int err = 0; |
2914 | int offset = off & (sb->s_blocksize - 1); | 3175 | int offset = off & (sb->s_blocksize - 1); |
2915 | int tocopy; | 3176 | int tocopy; |
@@ -2947,7 +3208,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type, | |||
2947 | const char *data, size_t len, loff_t off) | 3208 | const char *data, size_t len, loff_t off) |
2948 | { | 3209 | { |
2949 | struct inode *inode = sb_dqopt(sb)->files[type]; | 3210 | struct inode *inode = sb_dqopt(sb)->files[type]; |
2950 | sector_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb); | 3211 | ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb); |
2951 | int err = 0; | 3212 | int err = 0; |
2952 | int offset = off & (sb->s_blocksize - 1); | 3213 | int offset = off & (sb->s_blocksize - 1); |
2953 | int tocopy; | 3214 | int tocopy; |
@@ -3002,7 +3263,6 @@ out: | |||
3002 | i_size_write(inode, off+len-towrite); | 3263 | i_size_write(inode, off+len-towrite); |
3003 | EXT4_I(inode)->i_disksize = inode->i_size; | 3264 | EXT4_I(inode)->i_disksize = inode->i_size; |
3004 | } | 3265 | } |
3005 | inode->i_version++; | ||
3006 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 3266 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
3007 | ext4_mark_inode_dirty(handle, inode); | 3267 | ext4_mark_inode_dirty(handle, inode); |
3008 | mutex_unlock(&inode->i_mutex); | 3268 | mutex_unlock(&inode->i_mutex); |
@@ -3027,9 +3287,15 @@ static struct file_system_type ext4dev_fs_type = { | |||
3027 | 3287 | ||
3028 | static int __init init_ext4_fs(void) | 3288 | static int __init init_ext4_fs(void) |
3029 | { | 3289 | { |
3030 | int err = init_ext4_xattr(); | 3290 | int err; |
3291 | |||
3292 | err = init_ext4_mballoc(); | ||
3031 | if (err) | 3293 | if (err) |
3032 | return err; | 3294 | return err; |
3295 | |||
3296 | err = init_ext4_xattr(); | ||
3297 | if (err) | ||
3298 | goto out2; | ||
3033 | err = init_inodecache(); | 3299 | err = init_inodecache(); |
3034 | if (err) | 3300 | if (err) |
3035 | goto out1; | 3301 | goto out1; |
@@ -3041,6 +3307,8 @@ out: | |||
3041 | destroy_inodecache(); | 3307 | destroy_inodecache(); |
3042 | out1: | 3308 | out1: |
3043 | exit_ext4_xattr(); | 3309 | exit_ext4_xattr(); |
3310 | out2: | ||
3311 | exit_ext4_mballoc(); | ||
3044 | return err; | 3312 | return err; |
3045 | } | 3313 | } |
3046 | 3314 | ||
@@ -3049,6 +3317,7 @@ static void __exit exit_ext4_fs(void) | |||
3049 | unregister_filesystem(&ext4dev_fs_type); | 3317 | unregister_filesystem(&ext4dev_fs_type); |
3050 | destroy_inodecache(); | 3318 | destroy_inodecache(); |
3051 | exit_ext4_xattr(); | 3319 | exit_ext4_xattr(); |
3320 | exit_ext4_mballoc(); | ||
3052 | } | 3321 | } |
3053 | 3322 | ||
3054 | MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); | 3323 | MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 86387302c2a9..d7962139c010 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -480,7 +480,7 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, | |||
480 | ea_bdebug(bh, "refcount now=0; freeing"); | 480 | ea_bdebug(bh, "refcount now=0; freeing"); |
481 | if (ce) | 481 | if (ce) |
482 | mb_cache_entry_free(ce); | 482 | mb_cache_entry_free(ce); |
483 | ext4_free_blocks(handle, inode, bh->b_blocknr, 1); | 483 | ext4_free_blocks(handle, inode, bh->b_blocknr, 1, 1); |
484 | get_bh(bh); | 484 | get_bh(bh); |
485 | ext4_forget(handle, 1, inode, bh, bh->b_blocknr); | 485 | ext4_forget(handle, 1, inode, bh, bh->b_blocknr); |
486 | } else { | 486 | } else { |
@@ -821,7 +821,7 @@ inserted: | |||
821 | new_bh = sb_getblk(sb, block); | 821 | new_bh = sb_getblk(sb, block); |
822 | if (!new_bh) { | 822 | if (!new_bh) { |
823 | getblk_failed: | 823 | getblk_failed: |
824 | ext4_free_blocks(handle, inode, block, 1); | 824 | ext4_free_blocks(handle, inode, block, 1, 1); |
825 | error = -EIO; | 825 | error = -EIO; |
826 | goto cleanup; | 826 | goto cleanup; |
827 | } | 827 | } |
diff --git a/fs/inode.c b/fs/inode.c index ed35383d0b6c..276ffd6b6fdd 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -1276,6 +1276,11 @@ void file_update_time(struct file *file) | |||
1276 | sync_it = 1; | 1276 | sync_it = 1; |
1277 | } | 1277 | } |
1278 | 1278 | ||
1279 | if (IS_I_VERSION(inode)) { | ||
1280 | inode_inc_iversion(inode); | ||
1281 | sync_it = 1; | ||
1282 | } | ||
1283 | |||
1279 | if (sync_it) | 1284 | if (sync_it) |
1280 | mark_inode_dirty_sync(inode); | 1285 | mark_inode_dirty_sync(inode); |
1281 | } | 1286 | } |
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 3fccde7ba008..1b7f282c1ae9 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -232,7 +232,8 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) | |||
232 | * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it | 232 | * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it |
233 | */ | 233 | */ |
234 | static int __process_buffer(journal_t *journal, struct journal_head *jh, | 234 | static int __process_buffer(journal_t *journal, struct journal_head *jh, |
235 | struct buffer_head **bhs, int *batch_count) | 235 | struct buffer_head **bhs, int *batch_count, |
236 | transaction_t *transaction) | ||
236 | { | 237 | { |
237 | struct buffer_head *bh = jh2bh(jh); | 238 | struct buffer_head *bh = jh2bh(jh); |
238 | int ret = 0; | 239 | int ret = 0; |
@@ -250,6 +251,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
250 | transaction_t *t = jh->b_transaction; | 251 | transaction_t *t = jh->b_transaction; |
251 | tid_t tid = t->t_tid; | 252 | tid_t tid = t->t_tid; |
252 | 253 | ||
254 | transaction->t_chp_stats.cs_forced_to_close++; | ||
253 | spin_unlock(&journal->j_list_lock); | 255 | spin_unlock(&journal->j_list_lock); |
254 | jbd_unlock_bh_state(bh); | 256 | jbd_unlock_bh_state(bh); |
255 | jbd2_log_start_commit(journal, tid); | 257 | jbd2_log_start_commit(journal, tid); |
@@ -279,6 +281,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
279 | bhs[*batch_count] = bh; | 281 | bhs[*batch_count] = bh; |
280 | __buffer_relink_io(jh); | 282 | __buffer_relink_io(jh); |
281 | jbd_unlock_bh_state(bh); | 283 | jbd_unlock_bh_state(bh); |
284 | transaction->t_chp_stats.cs_written++; | ||
282 | (*batch_count)++; | 285 | (*batch_count)++; |
283 | if (*batch_count == NR_BATCH) { | 286 | if (*batch_count == NR_BATCH) { |
284 | spin_unlock(&journal->j_list_lock); | 287 | spin_unlock(&journal->j_list_lock); |
@@ -322,6 +325,8 @@ int jbd2_log_do_checkpoint(journal_t *journal) | |||
322 | if (!journal->j_checkpoint_transactions) | 325 | if (!journal->j_checkpoint_transactions) |
323 | goto out; | 326 | goto out; |
324 | transaction = journal->j_checkpoint_transactions; | 327 | transaction = journal->j_checkpoint_transactions; |
328 | if (transaction->t_chp_stats.cs_chp_time == 0) | ||
329 | transaction->t_chp_stats.cs_chp_time = jiffies; | ||
325 | this_tid = transaction->t_tid; | 330 | this_tid = transaction->t_tid; |
326 | restart: | 331 | restart: |
327 | /* | 332 | /* |
@@ -346,7 +351,8 @@ restart: | |||
346 | retry = 1; | 351 | retry = 1; |
347 | break; | 352 | break; |
348 | } | 353 | } |
349 | retry = __process_buffer(journal, jh, bhs,&batch_count); | 354 | retry = __process_buffer(journal, jh, bhs, &batch_count, |
355 | transaction); | ||
350 | if (!retry && lock_need_resched(&journal->j_list_lock)){ | 356 | if (!retry && lock_need_resched(&journal->j_list_lock)){ |
351 | spin_unlock(&journal->j_list_lock); | 357 | spin_unlock(&journal->j_list_lock); |
352 | retry = 1; | 358 | retry = 1; |
@@ -602,15 +608,15 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) | |||
602 | 608 | ||
603 | /* | 609 | /* |
604 | * There is one special case to worry about: if we have just pulled the | 610 | * There is one special case to worry about: if we have just pulled the |
605 | * buffer off a committing transaction's forget list, then even if the | 611 | * buffer off a running or committing transaction's checkpoing list, |
606 | * checkpoint list is empty, the transaction obviously cannot be | 612 | * then even if the checkpoint list is empty, the transaction obviously |
607 | * dropped! | 613 | * cannot be dropped! |
608 | * | 614 | * |
609 | * The locking here around j_committing_transaction is a bit sleazy. | 615 | * The locking here around t_state is a bit sleazy. |
610 | * See the comment at the end of jbd2_journal_commit_transaction(). | 616 | * See the comment at the end of jbd2_journal_commit_transaction(). |
611 | */ | 617 | */ |
612 | if (transaction == journal->j_committing_transaction) { | 618 | if (transaction->t_state != T_FINISHED) { |
613 | JBUFFER_TRACE(jh, "belongs to committing transaction"); | 619 | JBUFFER_TRACE(jh, "belongs to running/committing transaction"); |
614 | goto out; | 620 | goto out; |
615 | } | 621 | } |
616 | 622 | ||
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 6986f334c643..da8d0eb3b7b9 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
23 | #include <linux/jiffies.h> | ||
24 | #include <linux/crc32.h> | ||
23 | 25 | ||
24 | /* | 26 | /* |
25 | * Default IO end handler for temporary BJ_IO buffer_heads. | 27 | * Default IO end handler for temporary BJ_IO buffer_heads. |
@@ -92,19 +94,23 @@ static int inverted_lock(journal_t *journal, struct buffer_head *bh) | |||
92 | return 1; | 94 | return 1; |
93 | } | 95 | } |
94 | 96 | ||
95 | /* Done it all: now write the commit record. We should have | 97 | /* |
98 | * Done it all: now submit the commit record. We should have | ||
96 | * cleaned up our previous buffers by now, so if we are in abort | 99 | * cleaned up our previous buffers by now, so if we are in abort |
97 | * mode we can now just skip the rest of the journal write | 100 | * mode we can now just skip the rest of the journal write |
98 | * entirely. | 101 | * entirely. |
99 | * | 102 | * |
100 | * Returns 1 if the journal needs to be aborted or 0 on success | 103 | * Returns 1 if the journal needs to be aborted or 0 on success |
101 | */ | 104 | */ |
102 | static int journal_write_commit_record(journal_t *journal, | 105 | static int journal_submit_commit_record(journal_t *journal, |
103 | transaction_t *commit_transaction) | 106 | transaction_t *commit_transaction, |
107 | struct buffer_head **cbh, | ||
108 | __u32 crc32_sum) | ||
104 | { | 109 | { |
105 | struct journal_head *descriptor; | 110 | struct journal_head *descriptor; |
111 | struct commit_header *tmp; | ||
106 | struct buffer_head *bh; | 112 | struct buffer_head *bh; |
107 | int i, ret; | 113 | int ret; |
108 | int barrier_done = 0; | 114 | int barrier_done = 0; |
109 | 115 | ||
110 | if (is_journal_aborted(journal)) | 116 | if (is_journal_aborted(journal)) |
@@ -116,21 +122,33 @@ static int journal_write_commit_record(journal_t *journal, | |||
116 | 122 | ||
117 | bh = jh2bh(descriptor); | 123 | bh = jh2bh(descriptor); |
118 | 124 | ||
119 | /* AKPM: buglet - add `i' to tmp! */ | 125 | tmp = (struct commit_header *)bh->b_data; |
120 | for (i = 0; i < bh->b_size; i += 512) { | 126 | tmp->h_magic = cpu_to_be32(JBD2_MAGIC_NUMBER); |
121 | journal_header_t *tmp = (journal_header_t*)bh->b_data; | 127 | tmp->h_blocktype = cpu_to_be32(JBD2_COMMIT_BLOCK); |
122 | tmp->h_magic = cpu_to_be32(JBD2_MAGIC_NUMBER); | 128 | tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid); |
123 | tmp->h_blocktype = cpu_to_be32(JBD2_COMMIT_BLOCK); | 129 | |
124 | tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid); | 130 | if (JBD2_HAS_COMPAT_FEATURE(journal, |
131 | JBD2_FEATURE_COMPAT_CHECKSUM)) { | ||
132 | tmp->h_chksum_type = JBD2_CRC32_CHKSUM; | ||
133 | tmp->h_chksum_size = JBD2_CRC32_CHKSUM_SIZE; | ||
134 | tmp->h_chksum[0] = cpu_to_be32(crc32_sum); | ||
125 | } | 135 | } |
126 | 136 | ||
127 | JBUFFER_TRACE(descriptor, "write commit block"); | 137 | JBUFFER_TRACE(descriptor, "submit commit block"); |
138 | lock_buffer(bh); | ||
139 | |||
128 | set_buffer_dirty(bh); | 140 | set_buffer_dirty(bh); |
129 | if (journal->j_flags & JBD2_BARRIER) { | 141 | set_buffer_uptodate(bh); |
142 | bh->b_end_io = journal_end_buffer_io_sync; | ||
143 | |||
144 | if (journal->j_flags & JBD2_BARRIER && | ||
145 | !JBD2_HAS_COMPAT_FEATURE(journal, | ||
146 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { | ||
130 | set_buffer_ordered(bh); | 147 | set_buffer_ordered(bh); |
131 | barrier_done = 1; | 148 | barrier_done = 1; |
132 | } | 149 | } |
133 | ret = sync_dirty_buffer(bh); | 150 | ret = submit_bh(WRITE, bh); |
151 | |||
134 | /* is it possible for another commit to fail at roughly | 152 | /* is it possible for another commit to fail at roughly |
135 | * the same time as this one? If so, we don't want to | 153 | * the same time as this one? If so, we don't want to |
136 | * trust the barrier flag in the super, but instead want | 154 | * trust the barrier flag in the super, but instead want |
@@ -151,14 +169,72 @@ static int journal_write_commit_record(journal_t *journal, | |||
151 | clear_buffer_ordered(bh); | 169 | clear_buffer_ordered(bh); |
152 | set_buffer_uptodate(bh); | 170 | set_buffer_uptodate(bh); |
153 | set_buffer_dirty(bh); | 171 | set_buffer_dirty(bh); |
154 | ret = sync_dirty_buffer(bh); | 172 | ret = submit_bh(WRITE, bh); |
155 | } | 173 | } |
156 | put_bh(bh); /* One for getblk() */ | 174 | *cbh = bh; |
157 | jbd2_journal_put_journal_head(descriptor); | 175 | return ret; |
176 | } | ||
177 | |||
178 | /* | ||
179 | * This function along with journal_submit_commit_record | ||
180 | * allows to write the commit record asynchronously. | ||
181 | */ | ||
182 | static int journal_wait_on_commit_record(struct buffer_head *bh) | ||
183 | { | ||
184 | int ret = 0; | ||
185 | |||
186 | clear_buffer_dirty(bh); | ||
187 | wait_on_buffer(bh); | ||
188 | |||
189 | if (unlikely(!buffer_uptodate(bh))) | ||
190 | ret = -EIO; | ||
191 | put_bh(bh); /* One for getblk() */ | ||
192 | jbd2_journal_put_journal_head(bh2jh(bh)); | ||
158 | 193 | ||
159 | return (ret == -EIO); | 194 | return ret; |
160 | } | 195 | } |
161 | 196 | ||
197 | /* | ||
198 | * Wait for all submitted IO to complete. | ||
199 | */ | ||
200 | static int journal_wait_on_locked_list(journal_t *journal, | ||
201 | transaction_t *commit_transaction) | ||
202 | { | ||
203 | int ret = 0; | ||
204 | struct journal_head *jh; | ||
205 | |||
206 | while (commit_transaction->t_locked_list) { | ||
207 | struct buffer_head *bh; | ||
208 | |||
209 | jh = commit_transaction->t_locked_list->b_tprev; | ||
210 | bh = jh2bh(jh); | ||
211 | get_bh(bh); | ||
212 | if (buffer_locked(bh)) { | ||
213 | spin_unlock(&journal->j_list_lock); | ||
214 | wait_on_buffer(bh); | ||
215 | if (unlikely(!buffer_uptodate(bh))) | ||
216 | ret = -EIO; | ||
217 | spin_lock(&journal->j_list_lock); | ||
218 | } | ||
219 | if (!inverted_lock(journal, bh)) { | ||
220 | put_bh(bh); | ||
221 | spin_lock(&journal->j_list_lock); | ||
222 | continue; | ||
223 | } | ||
224 | if (buffer_jbd(bh) && jh->b_jlist == BJ_Locked) { | ||
225 | __jbd2_journal_unfile_buffer(jh); | ||
226 | jbd_unlock_bh_state(bh); | ||
227 | jbd2_journal_remove_journal_head(bh); | ||
228 | put_bh(bh); | ||
229 | } else { | ||
230 | jbd_unlock_bh_state(bh); | ||
231 | } | ||
232 | put_bh(bh); | ||
233 | cond_resched_lock(&journal->j_list_lock); | ||
234 | } | ||
235 | return ret; | ||
236 | } | ||
237 | |||
162 | static void journal_do_submit_data(struct buffer_head **wbuf, int bufs) | 238 | static void journal_do_submit_data(struct buffer_head **wbuf, int bufs) |
163 | { | 239 | { |
164 | int i; | 240 | int i; |
@@ -274,7 +350,21 @@ write_out_data: | |||
274 | journal_do_submit_data(wbuf, bufs); | 350 | journal_do_submit_data(wbuf, bufs); |
275 | } | 351 | } |
276 | 352 | ||
277 | static inline void write_tag_block(int tag_bytes, journal_block_tag_t *tag, | 353 | static __u32 jbd2_checksum_data(__u32 crc32_sum, struct buffer_head *bh) |
354 | { | ||
355 | struct page *page = bh->b_page; | ||
356 | char *addr; | ||
357 | __u32 checksum; | ||
358 | |||
359 | addr = kmap_atomic(page, KM_USER0); | ||
360 | checksum = crc32_be(crc32_sum, | ||
361 | (void *)(addr + offset_in_page(bh->b_data)), bh->b_size); | ||
362 | kunmap_atomic(addr, KM_USER0); | ||
363 | |||
364 | return checksum; | ||
365 | } | ||
366 | |||
367 | static void write_tag_block(int tag_bytes, journal_block_tag_t *tag, | ||
278 | unsigned long long block) | 368 | unsigned long long block) |
279 | { | 369 | { |
280 | tag->t_blocknr = cpu_to_be32(block & (u32)~0); | 370 | tag->t_blocknr = cpu_to_be32(block & (u32)~0); |
@@ -290,6 +380,7 @@ static inline void write_tag_block(int tag_bytes, journal_block_tag_t *tag, | |||
290 | */ | 380 | */ |
291 | void jbd2_journal_commit_transaction(journal_t *journal) | 381 | void jbd2_journal_commit_transaction(journal_t *journal) |
292 | { | 382 | { |
383 | struct transaction_stats_s stats; | ||
293 | transaction_t *commit_transaction; | 384 | transaction_t *commit_transaction; |
294 | struct journal_head *jh, *new_jh, *descriptor; | 385 | struct journal_head *jh, *new_jh, *descriptor; |
295 | struct buffer_head **wbuf = journal->j_wbuf; | 386 | struct buffer_head **wbuf = journal->j_wbuf; |
@@ -305,6 +396,8 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
305 | int tag_flag; | 396 | int tag_flag; |
306 | int i; | 397 | int i; |
307 | int tag_bytes = journal_tag_bytes(journal); | 398 | int tag_bytes = journal_tag_bytes(journal); |
399 | struct buffer_head *cbh = NULL; /* For transactional checksums */ | ||
400 | __u32 crc32_sum = ~0; | ||
308 | 401 | ||
309 | /* | 402 | /* |
310 | * First job: lock down the current transaction and wait for | 403 | * First job: lock down the current transaction and wait for |
@@ -337,6 +430,11 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
337 | spin_lock(&journal->j_state_lock); | 430 | spin_lock(&journal->j_state_lock); |
338 | commit_transaction->t_state = T_LOCKED; | 431 | commit_transaction->t_state = T_LOCKED; |
339 | 432 | ||
433 | stats.u.run.rs_wait = commit_transaction->t_max_wait; | ||
434 | stats.u.run.rs_locked = jiffies; | ||
435 | stats.u.run.rs_running = jbd2_time_diff(commit_transaction->t_start, | ||
436 | stats.u.run.rs_locked); | ||
437 | |||
340 | spin_lock(&commit_transaction->t_handle_lock); | 438 | spin_lock(&commit_transaction->t_handle_lock); |
341 | while (commit_transaction->t_updates) { | 439 | while (commit_transaction->t_updates) { |
342 | DEFINE_WAIT(wait); | 440 | DEFINE_WAIT(wait); |
@@ -407,6 +505,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
407 | */ | 505 | */ |
408 | jbd2_journal_switch_revoke_table(journal); | 506 | jbd2_journal_switch_revoke_table(journal); |
409 | 507 | ||
508 | stats.u.run.rs_flushing = jiffies; | ||
509 | stats.u.run.rs_locked = jbd2_time_diff(stats.u.run.rs_locked, | ||
510 | stats.u.run.rs_flushing); | ||
511 | |||
410 | commit_transaction->t_state = T_FLUSH; | 512 | commit_transaction->t_state = T_FLUSH; |
411 | journal->j_committing_transaction = commit_transaction; | 513 | journal->j_committing_transaction = commit_transaction; |
412 | journal->j_running_transaction = NULL; | 514 | journal->j_running_transaction = NULL; |
@@ -440,38 +542,15 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
440 | journal_submit_data_buffers(journal, commit_transaction); | 542 | journal_submit_data_buffers(journal, commit_transaction); |
441 | 543 | ||
442 | /* | 544 | /* |
443 | * Wait for all previously submitted IO to complete. | 545 | * Wait for all previously submitted IO to complete if commit |
546 | * record is to be written synchronously. | ||
444 | */ | 547 | */ |
445 | spin_lock(&journal->j_list_lock); | 548 | spin_lock(&journal->j_list_lock); |
446 | while (commit_transaction->t_locked_list) { | 549 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, |
447 | struct buffer_head *bh; | 550 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) |
551 | err = journal_wait_on_locked_list(journal, | ||
552 | commit_transaction); | ||
448 | 553 | ||
449 | jh = commit_transaction->t_locked_list->b_tprev; | ||
450 | bh = jh2bh(jh); | ||
451 | get_bh(bh); | ||
452 | if (buffer_locked(bh)) { | ||
453 | spin_unlock(&journal->j_list_lock); | ||
454 | wait_on_buffer(bh); | ||
455 | if (unlikely(!buffer_uptodate(bh))) | ||
456 | err = -EIO; | ||
457 | spin_lock(&journal->j_list_lock); | ||
458 | } | ||
459 | if (!inverted_lock(journal, bh)) { | ||
460 | put_bh(bh); | ||
461 | spin_lock(&journal->j_list_lock); | ||
462 | continue; | ||
463 | } | ||
464 | if (buffer_jbd(bh) && jh->b_jlist == BJ_Locked) { | ||
465 | __jbd2_journal_unfile_buffer(jh); | ||
466 | jbd_unlock_bh_state(bh); | ||
467 | jbd2_journal_remove_journal_head(bh); | ||
468 | put_bh(bh); | ||
469 | } else { | ||
470 | jbd_unlock_bh_state(bh); | ||
471 | } | ||
472 | put_bh(bh); | ||
473 | cond_resched_lock(&journal->j_list_lock); | ||
474 | } | ||
475 | spin_unlock(&journal->j_list_lock); | 554 | spin_unlock(&journal->j_list_lock); |
476 | 555 | ||
477 | if (err) | 556 | if (err) |
@@ -498,6 +577,12 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
498 | */ | 577 | */ |
499 | commit_transaction->t_state = T_COMMIT; | 578 | commit_transaction->t_state = T_COMMIT; |
500 | 579 | ||
580 | stats.u.run.rs_logging = jiffies; | ||
581 | stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing, | ||
582 | stats.u.run.rs_logging); | ||
583 | stats.u.run.rs_blocks = commit_transaction->t_outstanding_credits; | ||
584 | stats.u.run.rs_blocks_logged = 0; | ||
585 | |||
501 | descriptor = NULL; | 586 | descriptor = NULL; |
502 | bufs = 0; | 587 | bufs = 0; |
503 | while (commit_transaction->t_buffers) { | 588 | while (commit_transaction->t_buffers) { |
@@ -639,6 +724,15 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
639 | start_journal_io: | 724 | start_journal_io: |
640 | for (i = 0; i < bufs; i++) { | 725 | for (i = 0; i < bufs; i++) { |
641 | struct buffer_head *bh = wbuf[i]; | 726 | struct buffer_head *bh = wbuf[i]; |
727 | /* | ||
728 | * Compute checksum. | ||
729 | */ | ||
730 | if (JBD2_HAS_COMPAT_FEATURE(journal, | ||
731 | JBD2_FEATURE_COMPAT_CHECKSUM)) { | ||
732 | crc32_sum = | ||
733 | jbd2_checksum_data(crc32_sum, bh); | ||
734 | } | ||
735 | |||
642 | lock_buffer(bh); | 736 | lock_buffer(bh); |
643 | clear_buffer_dirty(bh); | 737 | clear_buffer_dirty(bh); |
644 | set_buffer_uptodate(bh); | 738 | set_buffer_uptodate(bh); |
@@ -646,6 +740,7 @@ start_journal_io: | |||
646 | submit_bh(WRITE, bh); | 740 | submit_bh(WRITE, bh); |
647 | } | 741 | } |
648 | cond_resched(); | 742 | cond_resched(); |
743 | stats.u.run.rs_blocks_logged += bufs; | ||
649 | 744 | ||
650 | /* Force a new descriptor to be generated next | 745 | /* Force a new descriptor to be generated next |
651 | time round the loop. */ | 746 | time round the loop. */ |
@@ -654,6 +749,23 @@ start_journal_io: | |||
654 | } | 749 | } |
655 | } | 750 | } |
656 | 751 | ||
752 | /* Done it all: now write the commit record asynchronously. */ | ||
753 | |||
754 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | ||
755 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { | ||
756 | err = journal_submit_commit_record(journal, commit_transaction, | ||
757 | &cbh, crc32_sum); | ||
758 | if (err) | ||
759 | __jbd2_journal_abort_hard(journal); | ||
760 | |||
761 | spin_lock(&journal->j_list_lock); | ||
762 | err = journal_wait_on_locked_list(journal, | ||
763 | commit_transaction); | ||
764 | spin_unlock(&journal->j_list_lock); | ||
765 | if (err) | ||
766 | __jbd2_journal_abort_hard(journal); | ||
767 | } | ||
768 | |||
657 | /* Lo and behold: we have just managed to send a transaction to | 769 | /* Lo and behold: we have just managed to send a transaction to |
658 | the log. Before we can commit it, wait for the IO so far to | 770 | the log. Before we can commit it, wait for the IO so far to |
659 | complete. Control buffers being written are on the | 771 | complete. Control buffers being written are on the |
@@ -753,8 +865,14 @@ wait_for_iobuf: | |||
753 | 865 | ||
754 | jbd_debug(3, "JBD: commit phase 6\n"); | 866 | jbd_debug(3, "JBD: commit phase 6\n"); |
755 | 867 | ||
756 | if (journal_write_commit_record(journal, commit_transaction)) | 868 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, |
757 | err = -EIO; | 869 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { |
870 | err = journal_submit_commit_record(journal, commit_transaction, | ||
871 | &cbh, crc32_sum); | ||
872 | if (err) | ||
873 | __jbd2_journal_abort_hard(journal); | ||
874 | } | ||
875 | err = journal_wait_on_commit_record(cbh); | ||
758 | 876 | ||
759 | if (err) | 877 | if (err) |
760 | jbd2_journal_abort(journal, err); | 878 | jbd2_journal_abort(journal, err); |
@@ -816,6 +934,7 @@ restart_loop: | |||
816 | cp_transaction = jh->b_cp_transaction; | 934 | cp_transaction = jh->b_cp_transaction; |
817 | if (cp_transaction) { | 935 | if (cp_transaction) { |
818 | JBUFFER_TRACE(jh, "remove from old cp transaction"); | 936 | JBUFFER_TRACE(jh, "remove from old cp transaction"); |
937 | cp_transaction->t_chp_stats.cs_dropped++; | ||
819 | __jbd2_journal_remove_checkpoint(jh); | 938 | __jbd2_journal_remove_checkpoint(jh); |
820 | } | 939 | } |
821 | 940 | ||
@@ -867,10 +986,10 @@ restart_loop: | |||
867 | } | 986 | } |
868 | spin_unlock(&journal->j_list_lock); | 987 | spin_unlock(&journal->j_list_lock); |
869 | /* | 988 | /* |
870 | * This is a bit sleazy. We borrow j_list_lock to protect | 989 | * This is a bit sleazy. We use j_list_lock to protect transition |
871 | * journal->j_committing_transaction in __jbd2_journal_remove_checkpoint. | 990 | * of a transaction into T_FINISHED state and calling |
872 | * Really, __jbd2_journal_remove_checkpoint should be using j_state_lock but | 991 | * __jbd2_journal_drop_transaction(). Otherwise we could race with |
873 | * it's a bit hassle to hold that across __jbd2_journal_remove_checkpoint | 992 | * other checkpointing code processing the transaction... |
874 | */ | 993 | */ |
875 | spin_lock(&journal->j_state_lock); | 994 | spin_lock(&journal->j_state_lock); |
876 | spin_lock(&journal->j_list_lock); | 995 | spin_lock(&journal->j_list_lock); |
@@ -890,6 +1009,36 @@ restart_loop: | |||
890 | 1009 | ||
891 | J_ASSERT(commit_transaction->t_state == T_COMMIT); | 1010 | J_ASSERT(commit_transaction->t_state == T_COMMIT); |
892 | 1011 | ||
1012 | commit_transaction->t_start = jiffies; | ||
1013 | stats.u.run.rs_logging = jbd2_time_diff(stats.u.run.rs_logging, | ||
1014 | commit_transaction->t_start); | ||
1015 | |||
1016 | /* | ||
1017 | * File the transaction for history | ||
1018 | */ | ||
1019 | stats.ts_type = JBD2_STATS_RUN; | ||
1020 | stats.ts_tid = commit_transaction->t_tid; | ||
1021 | stats.u.run.rs_handle_count = commit_transaction->t_handle_count; | ||
1022 | spin_lock(&journal->j_history_lock); | ||
1023 | memcpy(journal->j_history + journal->j_history_cur, &stats, | ||
1024 | sizeof(stats)); | ||
1025 | if (++journal->j_history_cur == journal->j_history_max) | ||
1026 | journal->j_history_cur = 0; | ||
1027 | |||
1028 | /* | ||
1029 | * Calculate overall stats | ||
1030 | */ | ||
1031 | journal->j_stats.ts_tid++; | ||
1032 | journal->j_stats.u.run.rs_wait += stats.u.run.rs_wait; | ||
1033 | journal->j_stats.u.run.rs_running += stats.u.run.rs_running; | ||
1034 | journal->j_stats.u.run.rs_locked += stats.u.run.rs_locked; | ||
1035 | journal->j_stats.u.run.rs_flushing += stats.u.run.rs_flushing; | ||
1036 | journal->j_stats.u.run.rs_logging += stats.u.run.rs_logging; | ||
1037 | journal->j_stats.u.run.rs_handle_count += stats.u.run.rs_handle_count; | ||
1038 | journal->j_stats.u.run.rs_blocks += stats.u.run.rs_blocks; | ||
1039 | journal->j_stats.u.run.rs_blocks_logged += stats.u.run.rs_blocks_logged; | ||
1040 | spin_unlock(&journal->j_history_lock); | ||
1041 | |||
893 | commit_transaction->t_state = T_FINISHED; | 1042 | commit_transaction->t_state = T_FINISHED; |
894 | J_ASSERT(commit_transaction == journal->j_committing_transaction); | 1043 | J_ASSERT(commit_transaction == journal->j_committing_transaction); |
895 | journal->j_commit_sequence = commit_transaction->t_tid; | 1044 | journal->j_commit_sequence = commit_transaction->t_tid; |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 6ddc5531587c..96ba846992e9 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/poison.h> | 36 | #include <linux/poison.h> |
37 | #include <linux/proc_fs.h> | 37 | #include <linux/proc_fs.h> |
38 | #include <linux/debugfs.h> | 38 | #include <linux/debugfs.h> |
39 | #include <linux/seq_file.h> | ||
39 | 40 | ||
40 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
41 | #include <asm/page.h> | 42 | #include <asm/page.h> |
@@ -640,6 +641,312 @@ struct journal_head *jbd2_journal_get_descriptor_buffer(journal_t *journal) | |||
640 | return jbd2_journal_add_journal_head(bh); | 641 | return jbd2_journal_add_journal_head(bh); |
641 | } | 642 | } |
642 | 643 | ||
644 | struct jbd2_stats_proc_session { | ||
645 | journal_t *journal; | ||
646 | struct transaction_stats_s *stats; | ||
647 | int start; | ||
648 | int max; | ||
649 | }; | ||
650 | |||
651 | static void *jbd2_history_skip_empty(struct jbd2_stats_proc_session *s, | ||
652 | struct transaction_stats_s *ts, | ||
653 | int first) | ||
654 | { | ||
655 | if (ts == s->stats + s->max) | ||
656 | ts = s->stats; | ||
657 | if (!first && ts == s->stats + s->start) | ||
658 | return NULL; | ||
659 | while (ts->ts_type == 0) { | ||
660 | ts++; | ||
661 | if (ts == s->stats + s->max) | ||
662 | ts = s->stats; | ||
663 | if (ts == s->stats + s->start) | ||
664 | return NULL; | ||
665 | } | ||
666 | return ts; | ||
667 | |||
668 | } | ||
669 | |||
670 | static void *jbd2_seq_history_start(struct seq_file *seq, loff_t *pos) | ||
671 | { | ||
672 | struct jbd2_stats_proc_session *s = seq->private; | ||
673 | struct transaction_stats_s *ts; | ||
674 | int l = *pos; | ||
675 | |||
676 | if (l == 0) | ||
677 | return SEQ_START_TOKEN; | ||
678 | ts = jbd2_history_skip_empty(s, s->stats + s->start, 1); | ||
679 | if (!ts) | ||
680 | return NULL; | ||
681 | l--; | ||
682 | while (l) { | ||
683 | ts = jbd2_history_skip_empty(s, ++ts, 0); | ||
684 | if (!ts) | ||
685 | break; | ||
686 | l--; | ||
687 | } | ||
688 | return ts; | ||
689 | } | ||
690 | |||
691 | static void *jbd2_seq_history_next(struct seq_file *seq, void *v, loff_t *pos) | ||
692 | { | ||
693 | struct jbd2_stats_proc_session *s = seq->private; | ||
694 | struct transaction_stats_s *ts = v; | ||
695 | |||
696 | ++*pos; | ||
697 | if (v == SEQ_START_TOKEN) | ||
698 | return jbd2_history_skip_empty(s, s->stats + s->start, 1); | ||
699 | else | ||
700 | return jbd2_history_skip_empty(s, ++ts, 0); | ||
701 | } | ||
702 | |||
703 | static int jbd2_seq_history_show(struct seq_file *seq, void *v) | ||
704 | { | ||
705 | struct transaction_stats_s *ts = v; | ||
706 | if (v == SEQ_START_TOKEN) { | ||
707 | seq_printf(seq, "%-4s %-5s %-5s %-5s %-5s %-5s %-5s %-6s %-5s " | ||
708 | "%-5s %-5s %-5s %-5s %-5s\n", "R/C", "tid", | ||
709 | "wait", "run", "lock", "flush", "log", "hndls", | ||
710 | "block", "inlog", "ctime", "write", "drop", | ||
711 | "close"); | ||
712 | return 0; | ||
713 | } | ||
714 | if (ts->ts_type == JBD2_STATS_RUN) | ||
715 | seq_printf(seq, "%-4s %-5lu %-5u %-5u %-5u %-5u %-5u " | ||
716 | "%-6lu %-5lu %-5lu\n", "R", ts->ts_tid, | ||
717 | jiffies_to_msecs(ts->u.run.rs_wait), | ||
718 | jiffies_to_msecs(ts->u.run.rs_running), | ||
719 | jiffies_to_msecs(ts->u.run.rs_locked), | ||
720 | jiffies_to_msecs(ts->u.run.rs_flushing), | ||
721 | jiffies_to_msecs(ts->u.run.rs_logging), | ||
722 | ts->u.run.rs_handle_count, | ||
723 | ts->u.run.rs_blocks, | ||
724 | ts->u.run.rs_blocks_logged); | ||
725 | else if (ts->ts_type == JBD2_STATS_CHECKPOINT) | ||
726 | seq_printf(seq, "%-4s %-5lu %48s %-5u %-5lu %-5lu %-5lu\n", | ||
727 | "C", ts->ts_tid, " ", | ||
728 | jiffies_to_msecs(ts->u.chp.cs_chp_time), | ||
729 | ts->u.chp.cs_written, ts->u.chp.cs_dropped, | ||
730 | ts->u.chp.cs_forced_to_close); | ||
731 | else | ||
732 | J_ASSERT(0); | ||
733 | return 0; | ||
734 | } | ||
735 | |||
736 | static void jbd2_seq_history_stop(struct seq_file *seq, void *v) | ||
737 | { | ||
738 | } | ||
739 | |||
740 | static struct seq_operations jbd2_seq_history_ops = { | ||
741 | .start = jbd2_seq_history_start, | ||
742 | .next = jbd2_seq_history_next, | ||
743 | .stop = jbd2_seq_history_stop, | ||
744 | .show = jbd2_seq_history_show, | ||
745 | }; | ||
746 | |||
747 | static int jbd2_seq_history_open(struct inode *inode, struct file *file) | ||
748 | { | ||
749 | journal_t *journal = PDE(inode)->data; | ||
750 | struct jbd2_stats_proc_session *s; | ||
751 | int rc, size; | ||
752 | |||
753 | s = kmalloc(sizeof(*s), GFP_KERNEL); | ||
754 | if (s == NULL) | ||
755 | return -ENOMEM; | ||
756 | size = sizeof(struct transaction_stats_s) * journal->j_history_max; | ||
757 | s->stats = kmalloc(size, GFP_KERNEL); | ||
758 | if (s->stats == NULL) { | ||
759 | kfree(s); | ||
760 | return -ENOMEM; | ||
761 | } | ||
762 | spin_lock(&journal->j_history_lock); | ||
763 | memcpy(s->stats, journal->j_history, size); | ||
764 | s->max = journal->j_history_max; | ||
765 | s->start = journal->j_history_cur % s->max; | ||
766 | spin_unlock(&journal->j_history_lock); | ||
767 | |||
768 | rc = seq_open(file, &jbd2_seq_history_ops); | ||
769 | if (rc == 0) { | ||
770 | struct seq_file *m = file->private_data; | ||
771 | m->private = s; | ||
772 | } else { | ||
773 | kfree(s->stats); | ||
774 | kfree(s); | ||
775 | } | ||
776 | return rc; | ||
777 | |||
778 | } | ||
779 | |||
780 | static int jbd2_seq_history_release(struct inode *inode, struct file *file) | ||
781 | { | ||
782 | struct seq_file *seq = file->private_data; | ||
783 | struct jbd2_stats_proc_session *s = seq->private; | ||
784 | |||
785 | kfree(s->stats); | ||
786 | kfree(s); | ||
787 | return seq_release(inode, file); | ||
788 | } | ||
789 | |||
790 | static struct file_operations jbd2_seq_history_fops = { | ||
791 | .owner = THIS_MODULE, | ||
792 | .open = jbd2_seq_history_open, | ||
793 | .read = seq_read, | ||
794 | .llseek = seq_lseek, | ||
795 | .release = jbd2_seq_history_release, | ||
796 | }; | ||
797 | |||
798 | static void *jbd2_seq_info_start(struct seq_file *seq, loff_t *pos) | ||
799 | { | ||
800 | return *pos ? NULL : SEQ_START_TOKEN; | ||
801 | } | ||
802 | |||
803 | static void *jbd2_seq_info_next(struct seq_file *seq, void *v, loff_t *pos) | ||
804 | { | ||
805 | return NULL; | ||
806 | } | ||
807 | |||
808 | static int jbd2_seq_info_show(struct seq_file *seq, void *v) | ||
809 | { | ||
810 | struct jbd2_stats_proc_session *s = seq->private; | ||
811 | |||
812 | if (v != SEQ_START_TOKEN) | ||
813 | return 0; | ||
814 | seq_printf(seq, "%lu transaction, each upto %u blocks\n", | ||
815 | s->stats->ts_tid, | ||
816 | s->journal->j_max_transaction_buffers); | ||
817 | if (s->stats->ts_tid == 0) | ||
818 | return 0; | ||
819 | seq_printf(seq, "average: \n %ums waiting for transaction\n", | ||
820 | jiffies_to_msecs(s->stats->u.run.rs_wait / s->stats->ts_tid)); | ||
821 | seq_printf(seq, " %ums running transaction\n", | ||
822 | jiffies_to_msecs(s->stats->u.run.rs_running / s->stats->ts_tid)); | ||
823 | seq_printf(seq, " %ums transaction was being locked\n", | ||
824 | jiffies_to_msecs(s->stats->u.run.rs_locked / s->stats->ts_tid)); | ||
825 | seq_printf(seq, " %ums flushing data (in ordered mode)\n", | ||
826 | jiffies_to_msecs(s->stats->u.run.rs_flushing / s->stats->ts_tid)); | ||
827 | seq_printf(seq, " %ums logging transaction\n", | ||
828 | jiffies_to_msecs(s->stats->u.run.rs_logging / s->stats->ts_tid)); | ||
829 | seq_printf(seq, " %lu handles per transaction\n", | ||
830 | s->stats->u.run.rs_handle_count / s->stats->ts_tid); | ||
831 | seq_printf(seq, " %lu blocks per transaction\n", | ||
832 | s->stats->u.run.rs_blocks / s->stats->ts_tid); | ||
833 | seq_printf(seq, " %lu logged blocks per transaction\n", | ||
834 | s->stats->u.run.rs_blocks_logged / s->stats->ts_tid); | ||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | static void jbd2_seq_info_stop(struct seq_file *seq, void *v) | ||
839 | { | ||
840 | } | ||
841 | |||
842 | static struct seq_operations jbd2_seq_info_ops = { | ||
843 | .start = jbd2_seq_info_start, | ||
844 | .next = jbd2_seq_info_next, | ||
845 | .stop = jbd2_seq_info_stop, | ||
846 | .show = jbd2_seq_info_show, | ||
847 | }; | ||
848 | |||
849 | static int jbd2_seq_info_open(struct inode *inode, struct file *file) | ||
850 | { | ||
851 | journal_t *journal = PDE(inode)->data; | ||
852 | struct jbd2_stats_proc_session *s; | ||
853 | int rc, size; | ||
854 | |||
855 | s = kmalloc(sizeof(*s), GFP_KERNEL); | ||
856 | if (s == NULL) | ||
857 | return -ENOMEM; | ||
858 | size = sizeof(struct transaction_stats_s); | ||
859 | s->stats = kmalloc(size, GFP_KERNEL); | ||
860 | if (s->stats == NULL) { | ||
861 | kfree(s); | ||
862 | return -ENOMEM; | ||
863 | } | ||
864 | spin_lock(&journal->j_history_lock); | ||
865 | memcpy(s->stats, &journal->j_stats, size); | ||
866 | s->journal = journal; | ||
867 | spin_unlock(&journal->j_history_lock); | ||
868 | |||
869 | rc = seq_open(file, &jbd2_seq_info_ops); | ||
870 | if (rc == 0) { | ||
871 | struct seq_file *m = file->private_data; | ||
872 | m->private = s; | ||
873 | } else { | ||
874 | kfree(s->stats); | ||
875 | kfree(s); | ||
876 | } | ||
877 | return rc; | ||
878 | |||
879 | } | ||
880 | |||
881 | static int jbd2_seq_info_release(struct inode *inode, struct file *file) | ||
882 | { | ||
883 | struct seq_file *seq = file->private_data; | ||
884 | struct jbd2_stats_proc_session *s = seq->private; | ||
885 | kfree(s->stats); | ||
886 | kfree(s); | ||
887 | return seq_release(inode, file); | ||
888 | } | ||
889 | |||
890 | static struct file_operations jbd2_seq_info_fops = { | ||
891 | .owner = THIS_MODULE, | ||
892 | .open = jbd2_seq_info_open, | ||
893 | .read = seq_read, | ||
894 | .llseek = seq_lseek, | ||
895 | .release = jbd2_seq_info_release, | ||
896 | }; | ||
897 | |||
898 | static struct proc_dir_entry *proc_jbd2_stats; | ||
899 | |||
900 | static void jbd2_stats_proc_init(journal_t *journal) | ||
901 | { | ||
902 | char name[BDEVNAME_SIZE]; | ||
903 | |||
904 | snprintf(name, sizeof(name) - 1, "%s", bdevname(journal->j_dev, name)); | ||
905 | journal->j_proc_entry = proc_mkdir(name, proc_jbd2_stats); | ||
906 | if (journal->j_proc_entry) { | ||
907 | struct proc_dir_entry *p; | ||
908 | p = create_proc_entry("history", S_IRUGO, | ||
909 | journal->j_proc_entry); | ||
910 | if (p) { | ||
911 | p->proc_fops = &jbd2_seq_history_fops; | ||
912 | p->data = journal; | ||
913 | p = create_proc_entry("info", S_IRUGO, | ||
914 | journal->j_proc_entry); | ||
915 | if (p) { | ||
916 | p->proc_fops = &jbd2_seq_info_fops; | ||
917 | p->data = journal; | ||
918 | } | ||
919 | } | ||
920 | } | ||
921 | } | ||
922 | |||
923 | static void jbd2_stats_proc_exit(journal_t *journal) | ||
924 | { | ||
925 | char name[BDEVNAME_SIZE]; | ||
926 | |||
927 | snprintf(name, sizeof(name) - 1, "%s", bdevname(journal->j_dev, name)); | ||
928 | remove_proc_entry("info", journal->j_proc_entry); | ||
929 | remove_proc_entry("history", journal->j_proc_entry); | ||
930 | remove_proc_entry(name, proc_jbd2_stats); | ||
931 | } | ||
932 | |||
933 | static void journal_init_stats(journal_t *journal) | ||
934 | { | ||
935 | int size; | ||
936 | |||
937 | if (!proc_jbd2_stats) | ||
938 | return; | ||
939 | |||
940 | journal->j_history_max = 100; | ||
941 | size = sizeof(struct transaction_stats_s) * journal->j_history_max; | ||
942 | journal->j_history = kzalloc(size, GFP_KERNEL); | ||
943 | if (!journal->j_history) { | ||
944 | journal->j_history_max = 0; | ||
945 | return; | ||
946 | } | ||
947 | spin_lock_init(&journal->j_history_lock); | ||
948 | } | ||
949 | |||
643 | /* | 950 | /* |
644 | * Management for journal control blocks: functions to create and | 951 | * Management for journal control blocks: functions to create and |
645 | * destroy journal_t structures, and to initialise and read existing | 952 | * destroy journal_t structures, and to initialise and read existing |
@@ -681,6 +988,9 @@ static journal_t * journal_init_common (void) | |||
681 | kfree(journal); | 988 | kfree(journal); |
682 | goto fail; | 989 | goto fail; |
683 | } | 990 | } |
991 | |||
992 | journal_init_stats(journal); | ||
993 | |||
684 | return journal; | 994 | return journal; |
685 | fail: | 995 | fail: |
686 | return NULL; | 996 | return NULL; |
@@ -735,6 +1045,7 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev, | |||
735 | journal->j_fs_dev = fs_dev; | 1045 | journal->j_fs_dev = fs_dev; |
736 | journal->j_blk_offset = start; | 1046 | journal->j_blk_offset = start; |
737 | journal->j_maxlen = len; | 1047 | journal->j_maxlen = len; |
1048 | jbd2_stats_proc_init(journal); | ||
738 | 1049 | ||
739 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); | 1050 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); |
740 | J_ASSERT(bh != NULL); | 1051 | J_ASSERT(bh != NULL); |
@@ -773,6 +1084,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
773 | 1084 | ||
774 | journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits; | 1085 | journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits; |
775 | journal->j_blocksize = inode->i_sb->s_blocksize; | 1086 | journal->j_blocksize = inode->i_sb->s_blocksize; |
1087 | jbd2_stats_proc_init(journal); | ||
776 | 1088 | ||
777 | /* journal descriptor can store up to n blocks -bzzz */ | 1089 | /* journal descriptor can store up to n blocks -bzzz */ |
778 | n = journal->j_blocksize / sizeof(journal_block_tag_t); | 1090 | n = journal->j_blocksize / sizeof(journal_block_tag_t); |
@@ -1153,6 +1465,8 @@ void jbd2_journal_destroy(journal_t *journal) | |||
1153 | brelse(journal->j_sb_buffer); | 1465 | brelse(journal->j_sb_buffer); |
1154 | } | 1466 | } |
1155 | 1467 | ||
1468 | if (journal->j_proc_entry) | ||
1469 | jbd2_stats_proc_exit(journal); | ||
1156 | if (journal->j_inode) | 1470 | if (journal->j_inode) |
1157 | iput(journal->j_inode); | 1471 | iput(journal->j_inode); |
1158 | if (journal->j_revoke) | 1472 | if (journal->j_revoke) |
@@ -1264,6 +1578,32 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, | |||
1264 | return 1; | 1578 | return 1; |
1265 | } | 1579 | } |
1266 | 1580 | ||
1581 | /* | ||
1582 | * jbd2_journal_clear_features () - Clear a given journal feature in the | ||
1583 | * superblock | ||
1584 | * @journal: Journal to act on. | ||
1585 | * @compat: bitmask of compatible features | ||
1586 | * @ro: bitmask of features that force read-only mount | ||
1587 | * @incompat: bitmask of incompatible features | ||
1588 | * | ||
1589 | * Clear a given journal feature as present on the | ||
1590 | * superblock. | ||
1591 | */ | ||
1592 | void jbd2_journal_clear_features(journal_t *journal, unsigned long compat, | ||
1593 | unsigned long ro, unsigned long incompat) | ||
1594 | { | ||
1595 | journal_superblock_t *sb; | ||
1596 | |||
1597 | jbd_debug(1, "Clear features 0x%lx/0x%lx/0x%lx\n", | ||
1598 | compat, ro, incompat); | ||
1599 | |||
1600 | sb = journal->j_superblock; | ||
1601 | |||
1602 | sb->s_feature_compat &= ~cpu_to_be32(compat); | ||
1603 | sb->s_feature_ro_compat &= ~cpu_to_be32(ro); | ||
1604 | sb->s_feature_incompat &= ~cpu_to_be32(incompat); | ||
1605 | } | ||
1606 | EXPORT_SYMBOL(jbd2_journal_clear_features); | ||
1267 | 1607 | ||
1268 | /** | 1608 | /** |
1269 | * int jbd2_journal_update_format () - Update on-disk journal structure. | 1609 | * int jbd2_journal_update_format () - Update on-disk journal structure. |
@@ -1633,7 +1973,7 @@ static int journal_init_jbd2_journal_head_cache(void) | |||
1633 | jbd2_journal_head_cache = kmem_cache_create("jbd2_journal_head", | 1973 | jbd2_journal_head_cache = kmem_cache_create("jbd2_journal_head", |
1634 | sizeof(struct journal_head), | 1974 | sizeof(struct journal_head), |
1635 | 0, /* offset */ | 1975 | 0, /* offset */ |
1636 | 0, /* flags */ | 1976 | SLAB_TEMPORARY, /* flags */ |
1637 | NULL); /* ctor */ | 1977 | NULL); /* ctor */ |
1638 | retval = 0; | 1978 | retval = 0; |
1639 | if (jbd2_journal_head_cache == 0) { | 1979 | if (jbd2_journal_head_cache == 0) { |
@@ -1900,6 +2240,28 @@ static void __exit jbd2_remove_debugfs_entry(void) | |||
1900 | 2240 | ||
1901 | #endif | 2241 | #endif |
1902 | 2242 | ||
2243 | #ifdef CONFIG_PROC_FS | ||
2244 | |||
2245 | #define JBD2_STATS_PROC_NAME "fs/jbd2" | ||
2246 | |||
2247 | static void __init jbd2_create_jbd_stats_proc_entry(void) | ||
2248 | { | ||
2249 | proc_jbd2_stats = proc_mkdir(JBD2_STATS_PROC_NAME, NULL); | ||
2250 | } | ||
2251 | |||
2252 | static void __exit jbd2_remove_jbd_stats_proc_entry(void) | ||
2253 | { | ||
2254 | if (proc_jbd2_stats) | ||
2255 | remove_proc_entry(JBD2_STATS_PROC_NAME, NULL); | ||
2256 | } | ||
2257 | |||
2258 | #else | ||
2259 | |||
2260 | #define jbd2_create_jbd_stats_proc_entry() do {} while (0) | ||
2261 | #define jbd2_remove_jbd_stats_proc_entry() do {} while (0) | ||
2262 | |||
2263 | #endif | ||
2264 | |||
1903 | struct kmem_cache *jbd2_handle_cache; | 2265 | struct kmem_cache *jbd2_handle_cache; |
1904 | 2266 | ||
1905 | static int __init journal_init_handle_cache(void) | 2267 | static int __init journal_init_handle_cache(void) |
@@ -1907,7 +2269,7 @@ static int __init journal_init_handle_cache(void) | |||
1907 | jbd2_handle_cache = kmem_cache_create("jbd2_journal_handle", | 2269 | jbd2_handle_cache = kmem_cache_create("jbd2_journal_handle", |
1908 | sizeof(handle_t), | 2270 | sizeof(handle_t), |
1909 | 0, /* offset */ | 2271 | 0, /* offset */ |
1910 | 0, /* flags */ | 2272 | SLAB_TEMPORARY, /* flags */ |
1911 | NULL); /* ctor */ | 2273 | NULL); /* ctor */ |
1912 | if (jbd2_handle_cache == NULL) { | 2274 | if (jbd2_handle_cache == NULL) { |
1913 | printk(KERN_EMERG "JBD: failed to create handle cache\n"); | 2275 | printk(KERN_EMERG "JBD: failed to create handle cache\n"); |
@@ -1955,6 +2317,7 @@ static int __init journal_init(void) | |||
1955 | if (ret != 0) | 2317 | if (ret != 0) |
1956 | jbd2_journal_destroy_caches(); | 2318 | jbd2_journal_destroy_caches(); |
1957 | jbd2_create_debugfs_entry(); | 2319 | jbd2_create_debugfs_entry(); |
2320 | jbd2_create_jbd_stats_proc_entry(); | ||
1958 | return ret; | 2321 | return ret; |
1959 | } | 2322 | } |
1960 | 2323 | ||
@@ -1966,6 +2329,7 @@ static void __exit journal_exit(void) | |||
1966 | printk(KERN_EMERG "JBD: leaked %d journal_heads!\n", n); | 2329 | printk(KERN_EMERG "JBD: leaked %d journal_heads!\n", n); |
1967 | #endif | 2330 | #endif |
1968 | jbd2_remove_debugfs_entry(); | 2331 | jbd2_remove_debugfs_entry(); |
2332 | jbd2_remove_jbd_stats_proc_entry(); | ||
1969 | jbd2_journal_destroy_caches(); | 2333 | jbd2_journal_destroy_caches(); |
1970 | } | 2334 | } |
1971 | 2335 | ||
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index d0ce627539ef..921680663fa2 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/jbd2.h> | 21 | #include <linux/jbd2.h> |
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/crc32.h> | ||
24 | #endif | 25 | #endif |
25 | 26 | ||
26 | /* | 27 | /* |
@@ -316,6 +317,37 @@ static inline unsigned long long read_tag_block(int tag_bytes, journal_block_tag | |||
316 | return block; | 317 | return block; |
317 | } | 318 | } |
318 | 319 | ||
320 | /* | ||
321 | * calc_chksums calculates the checksums for the blocks described in the | ||
322 | * descriptor block. | ||
323 | */ | ||
324 | static int calc_chksums(journal_t *journal, struct buffer_head *bh, | ||
325 | unsigned long *next_log_block, __u32 *crc32_sum) | ||
326 | { | ||
327 | int i, num_blks, err; | ||
328 | unsigned long io_block; | ||
329 | struct buffer_head *obh; | ||
330 | |||
331 | num_blks = count_tags(journal, bh); | ||
332 | /* Calculate checksum of the descriptor block. */ | ||
333 | *crc32_sum = crc32_be(*crc32_sum, (void *)bh->b_data, bh->b_size); | ||
334 | |||
335 | for (i = 0; i < num_blks; i++) { | ||
336 | io_block = (*next_log_block)++; | ||
337 | wrap(journal, *next_log_block); | ||
338 | err = jread(&obh, journal, io_block); | ||
339 | if (err) { | ||
340 | printk(KERN_ERR "JBD: IO error %d recovering block " | ||
341 | "%lu in log\n", err, io_block); | ||
342 | return 1; | ||
343 | } else { | ||
344 | *crc32_sum = crc32_be(*crc32_sum, (void *)obh->b_data, | ||
345 | obh->b_size); | ||
346 | } | ||
347 | } | ||
348 | return 0; | ||
349 | } | ||
350 | |||
319 | static int do_one_pass(journal_t *journal, | 351 | static int do_one_pass(journal_t *journal, |
320 | struct recovery_info *info, enum passtype pass) | 352 | struct recovery_info *info, enum passtype pass) |
321 | { | 353 | { |
@@ -328,6 +360,7 @@ static int do_one_pass(journal_t *journal, | |||
328 | unsigned int sequence; | 360 | unsigned int sequence; |
329 | int blocktype; | 361 | int blocktype; |
330 | int tag_bytes = journal_tag_bytes(journal); | 362 | int tag_bytes = journal_tag_bytes(journal); |
363 | __u32 crc32_sum = ~0; /* Transactional Checksums */ | ||
331 | 364 | ||
332 | /* Precompute the maximum metadata descriptors in a descriptor block */ | 365 | /* Precompute the maximum metadata descriptors in a descriptor block */ |
333 | int MAX_BLOCKS_PER_DESC; | 366 | int MAX_BLOCKS_PER_DESC; |
@@ -419,12 +452,26 @@ static int do_one_pass(journal_t *journal, | |||
419 | switch(blocktype) { | 452 | switch(blocktype) { |
420 | case JBD2_DESCRIPTOR_BLOCK: | 453 | case JBD2_DESCRIPTOR_BLOCK: |
421 | /* If it is a valid descriptor block, replay it | 454 | /* If it is a valid descriptor block, replay it |
422 | * in pass REPLAY; otherwise, just skip over the | 455 | * in pass REPLAY; if journal_checksums enabled, then |
423 | * blocks it describes. */ | 456 | * calculate checksums in PASS_SCAN, otherwise, |
457 | * just skip over the blocks it describes. */ | ||
424 | if (pass != PASS_REPLAY) { | 458 | if (pass != PASS_REPLAY) { |
459 | if (pass == PASS_SCAN && | ||
460 | JBD2_HAS_COMPAT_FEATURE(journal, | ||
461 | JBD2_FEATURE_COMPAT_CHECKSUM) && | ||
462 | !info->end_transaction) { | ||
463 | if (calc_chksums(journal, bh, | ||
464 | &next_log_block, | ||
465 | &crc32_sum)) { | ||
466 | put_bh(bh); | ||
467 | break; | ||
468 | } | ||
469 | put_bh(bh); | ||
470 | continue; | ||
471 | } | ||
425 | next_log_block += count_tags(journal, bh); | 472 | next_log_block += count_tags(journal, bh); |
426 | wrap(journal, next_log_block); | 473 | wrap(journal, next_log_block); |
427 | brelse(bh); | 474 | put_bh(bh); |
428 | continue; | 475 | continue; |
429 | } | 476 | } |
430 | 477 | ||
@@ -516,9 +563,96 @@ static int do_one_pass(journal_t *journal, | |||
516 | continue; | 563 | continue; |
517 | 564 | ||
518 | case JBD2_COMMIT_BLOCK: | 565 | case JBD2_COMMIT_BLOCK: |
519 | /* Found an expected commit block: not much to | 566 | /* How to differentiate between interrupted commit |
520 | * do other than move on to the next sequence | 567 | * and journal corruption ? |
568 | * | ||
569 | * {nth transaction} | ||
570 | * Checksum Verification Failed | ||
571 | * | | ||
572 | * ____________________ | ||
573 | * | | | ||
574 | * async_commit sync_commit | ||
575 | * | | | ||
576 | * | GO TO NEXT "Journal Corruption" | ||
577 | * | TRANSACTION | ||
578 | * | | ||
579 | * {(n+1)th transanction} | ||
580 | * | | ||
581 | * _______|______________ | ||
582 | * | | | ||
583 | * Commit block found Commit block not found | ||
584 | * | | | ||
585 | * "Journal Corruption" | | ||
586 | * _____________|_________ | ||
587 | * | | | ||
588 | * nth trans corrupt OR nth trans | ||
589 | * and (n+1)th interrupted interrupted | ||
590 | * before commit block | ||
591 | * could reach the disk. | ||
592 | * (Cannot find the difference in above | ||
593 | * mentioned conditions. Hence assume | ||
594 | * "Interrupted Commit".) | ||
595 | */ | ||
596 | |||
597 | /* Found an expected commit block: if checksums | ||
598 | * are present verify them in PASS_SCAN; else not | ||
599 | * much to do other than move on to the next sequence | ||
521 | * number. */ | 600 | * number. */ |
601 | if (pass == PASS_SCAN && | ||
602 | JBD2_HAS_COMPAT_FEATURE(journal, | ||
603 | JBD2_FEATURE_COMPAT_CHECKSUM)) { | ||
604 | int chksum_err, chksum_seen; | ||
605 | struct commit_header *cbh = | ||
606 | (struct commit_header *)bh->b_data; | ||
607 | unsigned found_chksum = | ||
608 | be32_to_cpu(cbh->h_chksum[0]); | ||
609 | |||
610 | chksum_err = chksum_seen = 0; | ||
611 | |||
612 | if (info->end_transaction) { | ||
613 | printk(KERN_ERR "JBD: Transaction %u " | ||
614 | "found to be corrupt.\n", | ||
615 | next_commit_ID - 1); | ||
616 | brelse(bh); | ||
617 | break; | ||
618 | } | ||
619 | |||
620 | if (crc32_sum == found_chksum && | ||
621 | cbh->h_chksum_type == JBD2_CRC32_CHKSUM && | ||
622 | cbh->h_chksum_size == | ||
623 | JBD2_CRC32_CHKSUM_SIZE) | ||
624 | chksum_seen = 1; | ||
625 | else if (!(cbh->h_chksum_type == 0 && | ||
626 | cbh->h_chksum_size == 0 && | ||
627 | found_chksum == 0 && | ||
628 | !chksum_seen)) | ||
629 | /* | ||
630 | * If fs is mounted using an old kernel and then | ||
631 | * kernel with journal_chksum is used then we | ||
632 | * get a situation where the journal flag has | ||
633 | * checksum flag set but checksums are not | ||
634 | * present i.e chksum = 0, in the individual | ||
635 | * commit blocks. | ||
636 | * Hence to avoid checksum failures, in this | ||
637 | * situation, this extra check is added. | ||
638 | */ | ||
639 | chksum_err = 1; | ||
640 | |||
641 | if (chksum_err) { | ||
642 | info->end_transaction = next_commit_ID; | ||
643 | |||
644 | if (!JBD2_HAS_COMPAT_FEATURE(journal, | ||
645 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)){ | ||
646 | printk(KERN_ERR | ||
647 | "JBD: Transaction %u " | ||
648 | "found to be corrupt.\n", | ||
649 | next_commit_ID); | ||
650 | brelse(bh); | ||
651 | break; | ||
652 | } | ||
653 | } | ||
654 | crc32_sum = ~0; | ||
655 | } | ||
522 | brelse(bh); | 656 | brelse(bh); |
523 | next_commit_ID++; | 657 | next_commit_ID++; |
524 | continue; | 658 | continue; |
@@ -554,9 +688,10 @@ static int do_one_pass(journal_t *journal, | |||
554 | * transaction marks the end of the valid log. | 688 | * transaction marks the end of the valid log. |
555 | */ | 689 | */ |
556 | 690 | ||
557 | if (pass == PASS_SCAN) | 691 | if (pass == PASS_SCAN) { |
558 | info->end_transaction = next_commit_ID; | 692 | if (!info->end_transaction) |
559 | else { | 693 | info->end_transaction = next_commit_ID; |
694 | } else { | ||
560 | /* It's really bad news if different passes end up at | 695 | /* It's really bad news if different passes end up at |
561 | * different places (but possible due to IO errors). */ | 696 | * different places (but possible due to IO errors). */ |
562 | if (info->end_transaction != next_commit_ID) { | 697 | if (info->end_transaction != next_commit_ID) { |
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index 3595fd432d5b..df36f42e19e1 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c | |||
@@ -171,13 +171,15 @@ int __init jbd2_journal_init_revoke_caches(void) | |||
171 | { | 171 | { |
172 | jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record", | 172 | jbd2_revoke_record_cache = kmem_cache_create("jbd2_revoke_record", |
173 | sizeof(struct jbd2_revoke_record_s), | 173 | sizeof(struct jbd2_revoke_record_s), |
174 | 0, SLAB_HWCACHE_ALIGN, NULL); | 174 | 0, |
175 | SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, | ||
176 | NULL); | ||
175 | if (jbd2_revoke_record_cache == 0) | 177 | if (jbd2_revoke_record_cache == 0) |
176 | return -ENOMEM; | 178 | return -ENOMEM; |
177 | 179 | ||
178 | jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table", | 180 | jbd2_revoke_table_cache = kmem_cache_create("jbd2_revoke_table", |
179 | sizeof(struct jbd2_revoke_table_s), | 181 | sizeof(struct jbd2_revoke_table_s), |
180 | 0, 0, NULL); | 182 | 0, SLAB_TEMPORARY, NULL); |
181 | if (jbd2_revoke_table_cache == 0) { | 183 | if (jbd2_revoke_table_cache == 0) { |
182 | kmem_cache_destroy(jbd2_revoke_record_cache); | 184 | kmem_cache_destroy(jbd2_revoke_record_cache); |
183 | jbd2_revoke_record_cache = NULL; | 185 | jbd2_revoke_record_cache = NULL; |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index b1fcf2b3dca3..b9b0b6f899b9 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -54,11 +54,13 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction) | |||
54 | spin_lock_init(&transaction->t_handle_lock); | 54 | spin_lock_init(&transaction->t_handle_lock); |
55 | 55 | ||
56 | /* Set up the commit timer for the new transaction. */ | 56 | /* Set up the commit timer for the new transaction. */ |
57 | journal->j_commit_timer.expires = transaction->t_expires; | 57 | journal->j_commit_timer.expires = round_jiffies(transaction->t_expires); |
58 | add_timer(&journal->j_commit_timer); | 58 | add_timer(&journal->j_commit_timer); |
59 | 59 | ||
60 | J_ASSERT(journal->j_running_transaction == NULL); | 60 | J_ASSERT(journal->j_running_transaction == NULL); |
61 | journal->j_running_transaction = transaction; | 61 | journal->j_running_transaction = transaction; |
62 | transaction->t_max_wait = 0; | ||
63 | transaction->t_start = jiffies; | ||
62 | 64 | ||
63 | return transaction; | 65 | return transaction; |
64 | } | 66 | } |
@@ -85,6 +87,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle) | |||
85 | int nblocks = handle->h_buffer_credits; | 87 | int nblocks = handle->h_buffer_credits; |
86 | transaction_t *new_transaction = NULL; | 88 | transaction_t *new_transaction = NULL; |
87 | int ret = 0; | 89 | int ret = 0; |
90 | unsigned long ts = jiffies; | ||
88 | 91 | ||
89 | if (nblocks > journal->j_max_transaction_buffers) { | 92 | if (nblocks > journal->j_max_transaction_buffers) { |
90 | printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n", | 93 | printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n", |
@@ -217,6 +220,12 @@ repeat_locked: | |||
217 | /* OK, account for the buffers that this operation expects to | 220 | /* OK, account for the buffers that this operation expects to |
218 | * use and add the handle to the running transaction. */ | 221 | * use and add the handle to the running transaction. */ |
219 | 222 | ||
223 | if (time_after(transaction->t_start, ts)) { | ||
224 | ts = jbd2_time_diff(ts, transaction->t_start); | ||
225 | if (ts > transaction->t_max_wait) | ||
226 | transaction->t_max_wait = ts; | ||
227 | } | ||
228 | |||
220 | handle->h_transaction = transaction; | 229 | handle->h_transaction = transaction; |
221 | transaction->t_outstanding_credits += nblocks; | 230 | transaction->t_outstanding_credits += nblocks; |
222 | transaction->t_updates++; | 231 | transaction->t_updates++; |
@@ -232,6 +241,8 @@ out: | |||
232 | return ret; | 241 | return ret; |
233 | } | 242 | } |
234 | 243 | ||
244 | static struct lock_class_key jbd2_handle_key; | ||
245 | |||
235 | /* Allocate a new handle. This should probably be in a slab... */ | 246 | /* Allocate a new handle. This should probably be in a slab... */ |
236 | static handle_t *new_handle(int nblocks) | 247 | static handle_t *new_handle(int nblocks) |
237 | { | 248 | { |
@@ -242,6 +253,9 @@ static handle_t *new_handle(int nblocks) | |||
242 | handle->h_buffer_credits = nblocks; | 253 | handle->h_buffer_credits = nblocks; |
243 | handle->h_ref = 1; | 254 | handle->h_ref = 1; |
244 | 255 | ||
256 | lockdep_init_map(&handle->h_lockdep_map, "jbd2_handle", | ||
257 | &jbd2_handle_key, 0); | ||
258 | |||
245 | return handle; | 259 | return handle; |
246 | } | 260 | } |
247 | 261 | ||
@@ -284,7 +298,11 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks) | |||
284 | jbd2_free_handle(handle); | 298 | jbd2_free_handle(handle); |
285 | current->journal_info = NULL; | 299 | current->journal_info = NULL; |
286 | handle = ERR_PTR(err); | 300 | handle = ERR_PTR(err); |
301 | goto out; | ||
287 | } | 302 | } |
303 | |||
304 | lock_acquire(&handle->h_lockdep_map, 0, 0, 0, 2, _THIS_IP_); | ||
305 | out: | ||
288 | return handle; | 306 | return handle; |
289 | } | 307 | } |
290 | 308 | ||
@@ -1164,7 +1182,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) | |||
1164 | } | 1182 | } |
1165 | 1183 | ||
1166 | /* That test should have eliminated the following case: */ | 1184 | /* That test should have eliminated the following case: */ |
1167 | J_ASSERT_JH(jh, jh->b_frozen_data == 0); | 1185 | J_ASSERT_JH(jh, jh->b_frozen_data == NULL); |
1168 | 1186 | ||
1169 | JBUFFER_TRACE(jh, "file as BJ_Metadata"); | 1187 | JBUFFER_TRACE(jh, "file as BJ_Metadata"); |
1170 | spin_lock(&journal->j_list_lock); | 1188 | spin_lock(&journal->j_list_lock); |
@@ -1410,6 +1428,8 @@ int jbd2_journal_stop(handle_t *handle) | |||
1410 | spin_unlock(&journal->j_state_lock); | 1428 | spin_unlock(&journal->j_state_lock); |
1411 | } | 1429 | } |
1412 | 1430 | ||
1431 | lock_release(&handle->h_lockdep_map, 1, _THIS_IP_); | ||
1432 | |||
1413 | jbd2_free_handle(handle); | 1433 | jbd2_free_handle(handle); |
1414 | return err; | 1434 | return err; |
1415 | } | 1435 | } |
@@ -1512,7 +1532,7 @@ void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh) | |||
1512 | 1532 | ||
1513 | J_ASSERT_JH(jh, jh->b_jlist < BJ_Types); | 1533 | J_ASSERT_JH(jh, jh->b_jlist < BJ_Types); |
1514 | if (jh->b_jlist != BJ_None) | 1534 | if (jh->b_jlist != BJ_None) |
1515 | J_ASSERT_JH(jh, transaction != 0); | 1535 | J_ASSERT_JH(jh, transaction != NULL); |
1516 | 1536 | ||
1517 | switch (jh->b_jlist) { | 1537 | switch (jh->b_jlist) { |
1518 | case BJ_None: | 1538 | case BJ_None: |
@@ -1581,11 +1601,11 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh) | |||
1581 | if (buffer_locked(bh) || buffer_dirty(bh)) | 1601 | if (buffer_locked(bh) || buffer_dirty(bh)) |
1582 | goto out; | 1602 | goto out; |
1583 | 1603 | ||
1584 | if (jh->b_next_transaction != 0) | 1604 | if (jh->b_next_transaction != NULL) |
1585 | goto out; | 1605 | goto out; |
1586 | 1606 | ||
1587 | spin_lock(&journal->j_list_lock); | 1607 | spin_lock(&journal->j_list_lock); |
1588 | if (jh->b_transaction != 0 && jh->b_cp_transaction == 0) { | 1608 | if (jh->b_transaction != NULL && jh->b_cp_transaction == NULL) { |
1589 | if (jh->b_jlist == BJ_SyncData || jh->b_jlist == BJ_Locked) { | 1609 | if (jh->b_jlist == BJ_SyncData || jh->b_jlist == BJ_Locked) { |
1590 | /* A written-back ordered data buffer */ | 1610 | /* A written-back ordered data buffer */ |
1591 | JBUFFER_TRACE(jh, "release data"); | 1611 | JBUFFER_TRACE(jh, "release data"); |
@@ -1593,7 +1613,7 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh) | |||
1593 | jbd2_journal_remove_journal_head(bh); | 1613 | jbd2_journal_remove_journal_head(bh); |
1594 | __brelse(bh); | 1614 | __brelse(bh); |
1595 | } | 1615 | } |
1596 | } else if (jh->b_cp_transaction != 0 && jh->b_transaction == 0) { | 1616 | } else if (jh->b_cp_transaction != NULL && jh->b_transaction == NULL) { |
1597 | /* written-back checkpointed metadata buffer */ | 1617 | /* written-back checkpointed metadata buffer */ |
1598 | if (jh->b_jlist == BJ_None) { | 1618 | if (jh->b_jlist == BJ_None) { |
1599 | JBUFFER_TRACE(jh, "remove from checkpoint list"); | 1619 | JBUFFER_TRACE(jh, "remove from checkpoint list"); |
@@ -1953,7 +1973,7 @@ void __jbd2_journal_file_buffer(struct journal_head *jh, | |||
1953 | 1973 | ||
1954 | J_ASSERT_JH(jh, jh->b_jlist < BJ_Types); | 1974 | J_ASSERT_JH(jh, jh->b_jlist < BJ_Types); |
1955 | J_ASSERT_JH(jh, jh->b_transaction == transaction || | 1975 | J_ASSERT_JH(jh, jh->b_transaction == transaction || |
1956 | jh->b_transaction == 0); | 1976 | jh->b_transaction == NULL); |
1957 | 1977 | ||
1958 | if (jh->b_transaction && jh->b_jlist == jlist) | 1978 | if (jh->b_transaction && jh->b_jlist == jlist) |
1959 | return; | 1979 | return; |
diff --git a/fs/ocfs2/cluster/sys.c b/fs/ocfs2/cluster/sys.c index a4b07730b2e1..0c095ce7723d 100644 --- a/fs/ocfs2/cluster/sys.c +++ b/fs/ocfs2/cluster/sys.c | |||
@@ -64,7 +64,7 @@ int o2cb_sys_init(void) | |||
64 | { | 64 | { |
65 | int ret; | 65 | int ret; |
66 | 66 | ||
67 | o2cb_kset = kset_create_and_add("o2cb", NULL, fs_kobj); | 67 | o2cb_kset = kset_create_and_add("o2cb", NULL, NULL); |
68 | if (!o2cb_kset) | 68 | if (!o2cb_kset) |
69 | return -ENOMEM; | 69 | return -ENOMEM; |
70 | 70 | ||
diff --git a/fs/read_write.c b/fs/read_write.c index c4d3d17923f1..1c177f29e1b7 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
@@ -446,6 +446,7 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to) | |||
446 | } | 446 | } |
447 | return seg; | 447 | return seg; |
448 | } | 448 | } |
449 | EXPORT_SYMBOL(iov_shorten); | ||
449 | 450 | ||
450 | ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov, | 451 | ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov, |
451 | unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn) | 452 | unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn) |
diff --git a/fs/smbfs/Makefile b/fs/smbfs/Makefile index 6673ee82cb4c..4faf8c4722c3 100644 --- a/fs/smbfs/Makefile +++ b/fs/smbfs/Makefile | |||
@@ -16,23 +16,3 @@ EXTRA_CFLAGS += -DSMBFS_PARANOIA | |||
16 | #EXTRA_CFLAGS += -DDEBUG_SMB_TIMESTAMP | 16 | #EXTRA_CFLAGS += -DDEBUG_SMB_TIMESTAMP |
17 | #EXTRA_CFLAGS += -Werror | 17 | #EXTRA_CFLAGS += -Werror |
18 | 18 | ||
19 | # | ||
20 | # Maintainer rules | ||
21 | # | ||
22 | |||
23 | # getopt.c not included. It is intentionally separate | ||
24 | SRC = proc.c dir.c cache.c sock.c inode.c file.c ioctl.c smbiod.c request.c \ | ||
25 | symlink.c | ||
26 | |||
27 | proto: | ||
28 | -rm -f proto.h | ||
29 | @echo > proto2.h "/*" | ||
30 | @echo >> proto2.h " * Autogenerated with cproto on: " `date` | ||
31 | @echo >> proto2.h " */" | ||
32 | @echo >> proto2.h "" | ||
33 | @echo >> proto2.h "struct smb_request;" | ||
34 | @echo >> proto2.h "struct sock;" | ||
35 | @echo >> proto2.h "struct statfs;" | ||
36 | @echo >> proto2.h "" | ||
37 | cproto -E "gcc -E" -e -v -I $(TOPDIR)/include -DMAKING_PROTO -D__KERNEL__ $(SRC) >> proto2.h | ||
38 | mv proto2.h proto.h | ||
diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h index 47a6b086eee2..5c60bfc1a84d 100644 --- a/include/asm-arm/bitops.h +++ b/include/asm-arm/bitops.h | |||
@@ -310,6 +310,8 @@ static inline int constant_fls(int x) | |||
310 | _find_first_zero_bit_le(p,sz) | 310 | _find_first_zero_bit_le(p,sz) |
311 | #define ext2_find_next_zero_bit(p,sz,off) \ | 311 | #define ext2_find_next_zero_bit(p,sz,off) \ |
312 | _find_next_zero_bit_le(p,sz,off) | 312 | _find_next_zero_bit_le(p,sz,off) |
313 | #define ext2_find_next_bit(p, sz, off) \ | ||
314 | _find_next_bit_le(p, sz, off) | ||
313 | 315 | ||
314 | /* | 316 | /* |
315 | * Minix is defined to use little-endian byte ordering. | 317 | * Minix is defined to use little-endian byte ordering. |
diff --git a/include/asm-avr32/setup.h b/include/asm-avr32/setup.h index b0828d43e110..ea3070ff13a5 100644 --- a/include/asm-avr32/setup.h +++ b/include/asm-avr32/setup.h | |||
@@ -110,7 +110,7 @@ struct tagtable { | |||
110 | int (*parse)(struct tag *); | 110 | int (*parse)(struct tag *); |
111 | }; | 111 | }; |
112 | 112 | ||
113 | #define __tag __attribute_used__ __attribute__((__section__(".taglist.init"))) | 113 | #define __tag __used __attribute__((__section__(".taglist.init"))) |
114 | #define __tagtable(tag, fn) \ | 114 | #define __tagtable(tag, fn) \ |
115 | static struct tagtable __tagtable_##fn __tag = { tag, fn } | 115 | static struct tagtable __tagtable_##fn __tag = { tag, fn } |
116 | 116 | ||
diff --git a/include/asm-generic/bitops/ext2-non-atomic.h b/include/asm-generic/bitops/ext2-non-atomic.h index 1697404afa05..63cf822431a2 100644 --- a/include/asm-generic/bitops/ext2-non-atomic.h +++ b/include/asm-generic/bitops/ext2-non-atomic.h | |||
@@ -14,5 +14,7 @@ | |||
14 | generic_find_first_zero_le_bit((unsigned long *)(addr), (size)) | 14 | generic_find_first_zero_le_bit((unsigned long *)(addr), (size)) |
15 | #define ext2_find_next_zero_bit(addr, size, off) \ | 15 | #define ext2_find_next_zero_bit(addr, size, off) \ |
16 | generic_find_next_zero_le_bit((unsigned long *)(addr), (size), (off)) | 16 | generic_find_next_zero_le_bit((unsigned long *)(addr), (size), (off)) |
17 | #define ext2_find_next_bit(addr, size, off) \ | ||
18 | generic_find_next_le_bit((unsigned long *)(addr), (size), (off)) | ||
17 | 19 | ||
18 | #endif /* _ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_ */ | 20 | #endif /* _ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_ */ |
diff --git a/include/asm-generic/bitops/le.h b/include/asm-generic/bitops/le.h index b9c7e5d2d2ad..80e3bf13b2b9 100644 --- a/include/asm-generic/bitops/le.h +++ b/include/asm-generic/bitops/le.h | |||
@@ -20,6 +20,8 @@ | |||
20 | #define generic___test_and_clear_le_bit(nr, addr) __test_and_clear_bit(nr, addr) | 20 | #define generic___test_and_clear_le_bit(nr, addr) __test_and_clear_bit(nr, addr) |
21 | 21 | ||
22 | #define generic_find_next_zero_le_bit(addr, size, offset) find_next_zero_bit(addr, size, offset) | 22 | #define generic_find_next_zero_le_bit(addr, size, offset) find_next_zero_bit(addr, size, offset) |
23 | #define generic_find_next_le_bit(addr, size, offset) \ | ||
24 | find_next_bit(addr, size, offset) | ||
23 | 25 | ||
24 | #elif defined(__BIG_ENDIAN) | 26 | #elif defined(__BIG_ENDIAN) |
25 | 27 | ||
@@ -42,6 +44,8 @@ | |||
42 | 44 | ||
43 | extern unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, | 45 | extern unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, |
44 | unsigned long size, unsigned long offset); | 46 | unsigned long size, unsigned long offset); |
47 | extern unsigned long generic_find_next_le_bit(const unsigned long *addr, | ||
48 | unsigned long size, unsigned long offset); | ||
45 | 49 | ||
46 | #else | 50 | #else |
47 | #error "Please fix <asm/byteorder.h>" | 51 | #error "Please fix <asm/byteorder.h>" |
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 9f584cc5c5fb..76df771be585 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h | |||
@@ -9,10 +9,46 @@ | |||
9 | /* Align . to a 8 byte boundary equals to maximum function alignment. */ | 9 | /* Align . to a 8 byte boundary equals to maximum function alignment. */ |
10 | #define ALIGN_FUNCTION() . = ALIGN(8) | 10 | #define ALIGN_FUNCTION() . = ALIGN(8) |
11 | 11 | ||
12 | /* The actual configuration determine if the init/exit sections | ||
13 | * are handled as text/data or they can be discarded (which | ||
14 | * often happens at runtime) | ||
15 | */ | ||
16 | #ifdef CONFIG_HOTPLUG | ||
17 | #define DEV_KEEP(sec) *(.dev##sec) | ||
18 | #define DEV_DISCARD(sec) | ||
19 | #else | ||
20 | #define DEV_KEEP(sec) | ||
21 | #define DEV_DISCARD(sec) *(.dev##sec) | ||
22 | #endif | ||
23 | |||
24 | #ifdef CONFIG_HOTPLUG_CPU | ||
25 | #define CPU_KEEP(sec) *(.cpu##sec) | ||
26 | #define CPU_DISCARD(sec) | ||
27 | #else | ||
28 | #define CPU_KEEP(sec) | ||
29 | #define CPU_DISCARD(sec) *(.cpu##sec) | ||
30 | #endif | ||
31 | |||
32 | #if defined(CONFIG_MEMORY_HOTPLUG) | ||
33 | #define MEM_KEEP(sec) *(.mem##sec) | ||
34 | #define MEM_DISCARD(sec) | ||
35 | #else | ||
36 | #define MEM_KEEP(sec) | ||
37 | #define MEM_DISCARD(sec) *(.mem##sec) | ||
38 | #endif | ||
39 | |||
40 | |||
12 | /* .data section */ | 41 | /* .data section */ |
13 | #define DATA_DATA \ | 42 | #define DATA_DATA \ |
14 | *(.data) \ | 43 | *(.data) \ |
15 | *(.data.init.refok) \ | 44 | *(.data.init.refok) \ |
45 | *(.ref.data) \ | ||
46 | DEV_KEEP(init.data) \ | ||
47 | DEV_KEEP(exit.data) \ | ||
48 | CPU_KEEP(init.data) \ | ||
49 | CPU_KEEP(exit.data) \ | ||
50 | MEM_KEEP(init.data) \ | ||
51 | MEM_KEEP(exit.data) \ | ||
16 | . = ALIGN(8); \ | 52 | . = ALIGN(8); \ |
17 | VMLINUX_SYMBOL(__start___markers) = .; \ | 53 | VMLINUX_SYMBOL(__start___markers) = .; \ |
18 | *(__markers) \ | 54 | *(__markers) \ |
@@ -132,6 +168,17 @@ | |||
132 | *(__ksymtab_strings) \ | 168 | *(__ksymtab_strings) \ |
133 | } \ | 169 | } \ |
134 | \ | 170 | \ |
171 | /* __*init sections */ \ | ||
172 | __init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) { \ | ||
173 | *(.ref.rodata) \ | ||
174 | DEV_KEEP(init.rodata) \ | ||
175 | DEV_KEEP(exit.rodata) \ | ||
176 | CPU_KEEP(init.rodata) \ | ||
177 | CPU_KEEP(exit.rodata) \ | ||
178 | MEM_KEEP(init.rodata) \ | ||
179 | MEM_KEEP(exit.rodata) \ | ||
180 | } \ | ||
181 | \ | ||
135 | /* Built-in module parameters. */ \ | 182 | /* Built-in module parameters. */ \ |
136 | __param : AT(ADDR(__param) - LOAD_OFFSET) { \ | 183 | __param : AT(ADDR(__param) - LOAD_OFFSET) { \ |
137 | VMLINUX_SYMBOL(__start___param) = .; \ | 184 | VMLINUX_SYMBOL(__start___param) = .; \ |
@@ -139,7 +186,6 @@ | |||
139 | VMLINUX_SYMBOL(__stop___param) = .; \ | 186 | VMLINUX_SYMBOL(__stop___param) = .; \ |
140 | VMLINUX_SYMBOL(__end_rodata) = .; \ | 187 | VMLINUX_SYMBOL(__end_rodata) = .; \ |
141 | } \ | 188 | } \ |
142 | \ | ||
143 | . = ALIGN((align)); | 189 | . = ALIGN((align)); |
144 | 190 | ||
145 | /* RODATA provided for backward compatibility. | 191 | /* RODATA provided for backward compatibility. |
@@ -158,8 +204,16 @@ | |||
158 | #define TEXT_TEXT \ | 204 | #define TEXT_TEXT \ |
159 | ALIGN_FUNCTION(); \ | 205 | ALIGN_FUNCTION(); \ |
160 | *(.text) \ | 206 | *(.text) \ |
207 | *(.ref.text) \ | ||
161 | *(.text.init.refok) \ | 208 | *(.text.init.refok) \ |
162 | *(.exit.text.refok) | 209 | *(.exit.text.refok) \ |
210 | DEV_KEEP(init.text) \ | ||
211 | DEV_KEEP(exit.text) \ | ||
212 | CPU_KEEP(init.text) \ | ||
213 | CPU_KEEP(exit.text) \ | ||
214 | MEM_KEEP(init.text) \ | ||
215 | MEM_KEEP(exit.text) | ||
216 | |||
163 | 217 | ||
164 | /* sched.text is aling to function alignment to secure we have same | 218 | /* sched.text is aling to function alignment to secure we have same |
165 | * address even at second ld pass when generating System.map */ | 219 | * address even at second ld pass when generating System.map */ |
@@ -183,6 +237,37 @@ | |||
183 | *(.kprobes.text) \ | 237 | *(.kprobes.text) \ |
184 | VMLINUX_SYMBOL(__kprobes_text_end) = .; | 238 | VMLINUX_SYMBOL(__kprobes_text_end) = .; |
185 | 239 | ||
240 | /* init and exit section handling */ | ||
241 | #define INIT_DATA \ | ||
242 | *(.init.data) \ | ||
243 | DEV_DISCARD(init.data) \ | ||
244 | DEV_DISCARD(init.rodata) \ | ||
245 | CPU_DISCARD(init.data) \ | ||
246 | CPU_DISCARD(init.rodata) \ | ||
247 | MEM_DISCARD(init.data) \ | ||
248 | MEM_DISCARD(init.rodata) | ||
249 | |||
250 | #define INIT_TEXT \ | ||
251 | *(.init.text) \ | ||
252 | DEV_DISCARD(init.text) \ | ||
253 | CPU_DISCARD(init.text) \ | ||
254 | MEM_DISCARD(init.text) | ||
255 | |||
256 | #define EXIT_DATA \ | ||
257 | *(.exit.data) \ | ||
258 | DEV_DISCARD(exit.data) \ | ||
259 | DEV_DISCARD(exit.rodata) \ | ||
260 | CPU_DISCARD(exit.data) \ | ||
261 | CPU_DISCARD(exit.rodata) \ | ||
262 | MEM_DISCARD(exit.data) \ | ||
263 | MEM_DISCARD(exit.rodata) | ||
264 | |||
265 | #define EXIT_TEXT \ | ||
266 | *(.exit.text) \ | ||
267 | DEV_DISCARD(exit.text) \ | ||
268 | CPU_DISCARD(exit.text) \ | ||
269 | MEM_DISCARD(exit.text) | ||
270 | |||
186 | /* DWARF debug sections. | 271 | /* DWARF debug sections. |
187 | Symbols in the DWARF debugging sections are relative to | 272 | Symbols in the DWARF debugging sections are relative to |
188 | the beginning of the section so we begin them at 0. */ | 273 | the beginning of the section so we begin them at 0. */ |
diff --git a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h index e58d3298fa10..5b6665c754c9 100644 --- a/include/asm-ia64/gcc_intrin.h +++ b/include/asm-ia64/gcc_intrin.h | |||
@@ -24,7 +24,7 @@ | |||
24 | extern void ia64_bad_param_for_setreg (void); | 24 | extern void ia64_bad_param_for_setreg (void); |
25 | extern void ia64_bad_param_for_getreg (void); | 25 | extern void ia64_bad_param_for_getreg (void); |
26 | 26 | ||
27 | register unsigned long ia64_r13 asm ("r13") __attribute_used__; | 27 | register unsigned long ia64_r13 asm ("r13") __used; |
28 | 28 | ||
29 | #define ia64_setreg(regnum, val) \ | 29 | #define ia64_setreg(regnum, val) \ |
30 | ({ \ | 30 | ({ \ |
diff --git a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h index 2976b5d68e96..83d1f286230b 100644 --- a/include/asm-m68k/bitops.h +++ b/include/asm-m68k/bitops.h | |||
@@ -410,6 +410,8 @@ static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size, | |||
410 | res = ext2_find_first_zero_bit (p, size - 32 * (p - addr)); | 410 | res = ext2_find_first_zero_bit (p, size - 32 * (p - addr)); |
411 | return (p - addr) * 32 + res; | 411 | return (p - addr) * 32 + res; |
412 | } | 412 | } |
413 | #define ext2_find_next_bit(addr, size, off) \ | ||
414 | generic_find_next_le_bit((unsigned long *)(addr), (size), (off)) | ||
413 | 415 | ||
414 | #endif /* __KERNEL__ */ | 416 | #endif /* __KERNEL__ */ |
415 | 417 | ||
diff --git a/include/asm-m68knommu/bitops.h b/include/asm-m68knommu/bitops.h index f8dfb7ba2e25..f43afe1fc3b3 100644 --- a/include/asm-m68knommu/bitops.h +++ b/include/asm-m68knommu/bitops.h | |||
@@ -294,6 +294,8 @@ found_middle: | |||
294 | return result + ffz(__swab32(tmp)); | 294 | return result + ffz(__swab32(tmp)); |
295 | } | 295 | } |
296 | 296 | ||
297 | #define ext2_find_next_bit(addr, size, off) \ | ||
298 | generic_find_next_le_bit((unsigned long *)(addr), (size), (off)) | ||
297 | #include <asm-generic/bitops/minix.h> | 299 | #include <asm-generic/bitops/minix.h> |
298 | 300 | ||
299 | #endif /* __KERNEL__ */ | 301 | #endif /* __KERNEL__ */ |
diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h index 0bb7a93b7a5e..569f80aacbd2 100644 --- a/include/asm-mips/addrspace.h +++ b/include/asm-mips/addrspace.h | |||
@@ -127,7 +127,7 @@ | |||
127 | #define PHYS_TO_XKSEG_CACHED(p) PHYS_TO_XKPHYS(K_CALG_COH_SHAREABLE, (p)) | 127 | #define PHYS_TO_XKSEG_CACHED(p) PHYS_TO_XKPHYS(K_CALG_COH_SHAREABLE, (p)) |
128 | #define XKPHYS_TO_PHYS(p) ((p) & TO_PHYS_MASK) | 128 | #define XKPHYS_TO_PHYS(p) ((p) & TO_PHYS_MASK) |
129 | #define PHYS_TO_XKPHYS(cm, a) (_CONST64_(0x8000000000000000) | \ | 129 | #define PHYS_TO_XKPHYS(cm, a) (_CONST64_(0x8000000000000000) | \ |
130 | ((cm)<<59) | (a)) | 130 | (_CONST64_(cm) << 59) | (a)) |
131 | 131 | ||
132 | /* | 132 | /* |
133 | * The ultimate limited of the 64-bit MIPS architecture: 2 bits for selecting | 133 | * The ultimate limited of the 64-bit MIPS architecture: 2 bits for selecting |
diff --git a/include/asm-mips/asm.h b/include/asm-mips/asm.h index 12e17581b823..608cfcfbb3ea 100644 --- a/include/asm-mips/asm.h +++ b/include/asm-mips/asm.h | |||
@@ -398,4 +398,12 @@ symbol = value | |||
398 | 398 | ||
399 | #define SSNOP sll zero, zero, 1 | 399 | #define SSNOP sll zero, zero, 1 |
400 | 400 | ||
401 | #ifdef CONFIG_SGI_IP28 | ||
402 | /* Inhibit speculative stores to volatile (e.g.DMA) or invalid addresses. */ | ||
403 | #include <asm/cacheops.h> | ||
404 | #define R10KCBARRIER(addr) cache Cache_Barrier, addr; | ||
405 | #else | ||
406 | #define R10KCBARRIER(addr) | ||
407 | #endif | ||
408 | |||
401 | #endif /* __ASM_ASM_H */ | 409 | #endif /* __ASM_ASM_H */ |
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h index b2dd9b33de8f..e031bdff9920 100644 --- a/include/asm-mips/bootinfo.h +++ b/include/asm-mips/bootinfo.h | |||
@@ -48,22 +48,11 @@ | |||
48 | #define MACH_DS5900 10 /* DECsystem 5900 */ | 48 | #define MACH_DS5900 10 /* DECsystem 5900 */ |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * Valid machtype for group ARC | ||
52 | */ | ||
53 | #define MACH_DESKSTATION_RPC44 0 /* Deskstation rPC44 */ | ||
54 | #define MACH_DESKSTATION_TYNE 1 /* Deskstation Tyne */ | ||
55 | |||
56 | /* | ||
57 | * Valid machtype for group SNI_RM | 51 | * Valid machtype for group SNI_RM |
58 | */ | 52 | */ |
59 | #define MACH_SNI_RM200_PCI 0 /* RM200/RM300/RM400 PCI series */ | 53 | #define MACH_SNI_RM200_PCI 0 /* RM200/RM300/RM400 PCI series */ |
60 | 54 | ||
61 | /* | 55 | /* |
62 | * Valid machtype for group ACN | ||
63 | */ | ||
64 | #define MACH_ACN_MIPS_BOARD 0 /* ACN MIPS single board */ | ||
65 | |||
66 | /* | ||
67 | * Valid machtype for group SGI | 56 | * Valid machtype for group SGI |
68 | */ | 57 | */ |
69 | #define MACH_SGI_IP22 0 /* Indy, Indigo2, Challenge S */ | 58 | #define MACH_SGI_IP22 0 /* Indy, Indigo2, Challenge S */ |
@@ -73,44 +62,6 @@ | |||
73 | #define MACH_SGI_IP30 4 /* Octane, Octane2 */ | 62 | #define MACH_SGI_IP30 4 /* Octane, Octane2 */ |
74 | 63 | ||
75 | /* | 64 | /* |
76 | * Valid machtype for group COBALT | ||
77 | */ | ||
78 | #define MACH_COBALT_27 0 /* Proto "27" hardware */ | ||
79 | |||
80 | /* | ||
81 | * Valid machtype for group BAGET | ||
82 | */ | ||
83 | #define MACH_BAGET201 0 /* BT23-201 */ | ||
84 | #define MACH_BAGET202 1 /* BT23-202 */ | ||
85 | |||
86 | /* | ||
87 | * Cosine boards. | ||
88 | */ | ||
89 | #define MACH_COSINE_ORION 0 | ||
90 | |||
91 | /* | ||
92 | * Valid machtype for group MOMENCO | ||
93 | */ | ||
94 | #define MACH_MOMENCO_OCELOT 0 | ||
95 | #define MACH_MOMENCO_OCELOT_G 1 /* no more supported (may 2007) */ | ||
96 | #define MACH_MOMENCO_OCELOT_C 2 /* no more supported (jun 2007) */ | ||
97 | #define MACH_MOMENCO_JAGUAR_ATX 3 /* no more supported (may 2007) */ | ||
98 | #define MACH_MOMENCO_OCELOT_3 4 | ||
99 | |||
100 | /* | ||
101 | * Valid machtype for group PHILIPS | ||
102 | */ | ||
103 | #define MACH_PHILIPS_NINO 0 /* Nino */ | ||
104 | #define MACH_PHILIPS_VELO 1 /* Velo */ | ||
105 | #define MACH_PHILIPS_JBS 2 /* JBS */ | ||
106 | #define MACH_PHILIPS_STB810 3 /* STB810 */ | ||
107 | |||
108 | /* | ||
109 | * Valid machtype for group SIBYTE | ||
110 | */ | ||
111 | #define MACH_SWARM 0 | ||
112 | |||
113 | /* | ||
114 | * Valid machtypes for group Toshiba | 65 | * Valid machtypes for group Toshiba |
115 | */ | 66 | */ |
116 | #define MACH_PALLAS 0 | 67 | #define MACH_PALLAS 0 |
@@ -122,64 +73,17 @@ | |||
122 | #define MACH_TOSHIBA_RBTX4938 6 | 73 | #define MACH_TOSHIBA_RBTX4938 6 |
123 | 74 | ||
124 | /* | 75 | /* |
125 | * Valid machtype for group Alchemy | ||
126 | */ | ||
127 | #define MACH_PB1000 0 /* Au1000-based eval board */ | ||
128 | #define MACH_PB1100 1 /* Au1100-based eval board */ | ||
129 | #define MACH_PB1500 2 /* Au1500-based eval board */ | ||
130 | #define MACH_DB1000 3 /* Au1000-based eval board */ | ||
131 | #define MACH_DB1100 4 /* Au1100-based eval board */ | ||
132 | #define MACH_DB1500 5 /* Au1500-based eval board */ | ||
133 | #define MACH_XXS1500 6 /* Au1500-based eval board */ | ||
134 | #define MACH_MTX1 7 /* 4G MTX-1 Au1500-based board */ | ||
135 | #define MACH_PB1550 8 /* Au1550-based eval board */ | ||
136 | #define MACH_DB1550 9 /* Au1550-based eval board */ | ||
137 | #define MACH_PB1200 10 /* Au1200-based eval board */ | ||
138 | #define MACH_DB1200 11 /* Au1200-based eval board */ | ||
139 | |||
140 | /* | ||
141 | * Valid machtype for group NEC_VR41XX | ||
142 | * | ||
143 | * Various NEC-based devices. | ||
144 | * | ||
145 | * FIXME: MACH_GROUPs should be by _MANUFACTURER_ of * the device, not by | ||
146 | * technical properties, so no new additions to this group. | ||
147 | */ | ||
148 | #define MACH_NEC_OSPREY 0 /* Osprey eval board */ | ||
149 | #define MACH_NEC_EAGLE 1 /* NEC Eagle/Hawk board */ | ||
150 | #define MACH_ZAO_CAPCELLA 2 /* ZAO Networks Capcella */ | ||
151 | #define MACH_VICTOR_MPC30X 3 /* Victor MP-C303/304 */ | ||
152 | #define MACH_IBM_WORKPAD 4 /* IBM WorkPad z50 */ | ||
153 | #define MACH_CASIO_E55 5 /* CASIO CASSIOPEIA E-10/15/55/65 */ | ||
154 | #define MACH_TANBAC_TB0226 6 /* TANBAC TB0226 (Mbase) */ | ||
155 | #define MACH_TANBAC_TB0229 7 /* TANBAC TB0229 (VR4131DIMM) */ | ||
156 | #define MACH_NEC_CMBVR4133 8 /* CMB VR4133 Board */ | ||
157 | |||
158 | #define MACH_HP_LASERJET 1 | ||
159 | |||
160 | /* | ||
161 | * Valid machtype for group LASAT | 76 | * Valid machtype for group LASAT |
162 | */ | 77 | */ |
163 | #define MACH_LASAT_100 0 /* Masquerade II/SP100/SP50/SP25 */ | 78 | #define MACH_LASAT_100 0 /* Masquerade II/SP100/SP50/SP25 */ |
164 | #define MACH_LASAT_200 1 /* Masquerade PRO/SP200 */ | 79 | #define MACH_LASAT_200 1 /* Masquerade PRO/SP200 */ |
165 | 80 | ||
166 | /* | 81 | /* |
167 | * Valid machtype for group TITAN | ||
168 | */ | ||
169 | #define MACH_TITAN_YOSEMITE 1 /* PMC-Sierra Yosemite */ | ||
170 | #define MACH_TITAN_EXCITE 2 /* Basler eXcite */ | ||
171 | |||
172 | /* | ||
173 | * Valid machtype for group NEC EMMA2RH | 82 | * Valid machtype for group NEC EMMA2RH |
174 | */ | 83 | */ |
175 | #define MACH_NEC_MARKEINS 0 /* NEC EMMA2RH Mark-eins */ | 84 | #define MACH_NEC_MARKEINS 0 /* NEC EMMA2RH Mark-eins */ |
176 | 85 | ||
177 | /* | 86 | /* |
178 | * Valid machtype for group LEMOTE | ||
179 | */ | ||
180 | #define MACH_LEMOTE_FULONG 0 | ||
181 | |||
182 | /* | ||
183 | * Valid machtype for group PMC-MSP | 87 | * Valid machtype for group PMC-MSP |
184 | */ | 88 | */ |
185 | #define MACH_MSP4200_EVAL 0 /* PMC-Sierra MSP4200 Evaluation */ | 89 | #define MACH_MSP4200_EVAL 0 /* PMC-Sierra MSP4200 Evaluation */ |
@@ -190,16 +94,9 @@ | |||
190 | #define MACH_MSP7120_FPGA 5 /* PMC-Sierra MSP7120 Emulation */ | 94 | #define MACH_MSP7120_FPGA 5 /* PMC-Sierra MSP7120 Emulation */ |
191 | #define MACH_MSP_OTHER 255 /* PMC-Sierra unknown board type */ | 95 | #define MACH_MSP_OTHER 255 /* PMC-Sierra unknown board type */ |
192 | 96 | ||
193 | #define MACH_WRPPMC 1 | ||
194 | |||
195 | /* | ||
196 | * Valid machtype for group Broadcom | ||
197 | */ | ||
198 | #define MACH_GROUP_BRCM 23 /* Broadcom */ | ||
199 | #define MACH_BCM47XX 1 /* Broadcom BCM47XX */ | ||
200 | |||
201 | #define CL_SIZE COMMAND_LINE_SIZE | 97 | #define CL_SIZE COMMAND_LINE_SIZE |
202 | 98 | ||
99 | extern char *system_type; | ||
203 | const char *get_system_type(void); | 100 | const char *get_system_type(void); |
204 | 101 | ||
205 | extern unsigned long mips_machtype; | 102 | extern unsigned long mips_machtype; |
diff --git a/include/asm-mips/bugs.h b/include/asm-mips/bugs.h index 0d7f9c1f5546..9dc10df32078 100644 --- a/include/asm-mips/bugs.h +++ b/include/asm-mips/bugs.h | |||
@@ -1,19 +1,34 @@ | |||
1 | /* | 1 | /* |
2 | * This is included by init/main.c to check for architecture-dependent bugs. | 2 | * This is included by init/main.c to check for architecture-dependent bugs. |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Maciej W. Rozycki | ||
5 | * | ||
4 | * Needs: | 6 | * Needs: |
5 | * void check_bugs(void); | 7 | * void check_bugs(void); |
6 | */ | 8 | */ |
7 | #ifndef _ASM_BUGS_H | 9 | #ifndef _ASM_BUGS_H |
8 | #define _ASM_BUGS_H | 10 | #define _ASM_BUGS_H |
9 | 11 | ||
12 | #include <linux/bug.h> | ||
10 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | |||
11 | #include <asm/cpu.h> | 15 | #include <asm/cpu.h> |
12 | #include <asm/cpu-info.h> | 16 | #include <asm/cpu-info.h> |
13 | 17 | ||
18 | extern int daddiu_bug; | ||
19 | |||
20 | extern void check_bugs64_early(void); | ||
21 | |||
14 | extern void check_bugs32(void); | 22 | extern void check_bugs32(void); |
15 | extern void check_bugs64(void); | 23 | extern void check_bugs64(void); |
16 | 24 | ||
25 | static inline void check_bugs_early(void) | ||
26 | { | ||
27 | #ifdef CONFIG_64BIT | ||
28 | check_bugs64_early(); | ||
29 | #endif | ||
30 | } | ||
31 | |||
17 | static inline void check_bugs(void) | 32 | static inline void check_bugs(void) |
18 | { | 33 | { |
19 | unsigned int cpu = smp_processor_id(); | 34 | unsigned int cpu = smp_processor_id(); |
@@ -25,4 +40,14 @@ static inline void check_bugs(void) | |||
25 | #endif | 40 | #endif |
26 | } | 41 | } |
27 | 42 | ||
43 | static inline int r4k_daddiu_bug(void) | ||
44 | { | ||
45 | #ifdef CONFIG_64BIT | ||
46 | WARN_ON(daddiu_bug < 0); | ||
47 | return daddiu_bug != 0; | ||
48 | #else | ||
49 | return 0; | ||
50 | #endif | ||
51 | } | ||
52 | |||
28 | #endif /* _ASM_BUGS_H */ | 53 | #endif /* _ASM_BUGS_H */ |
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h index ed5c02c6afbb..0c5a358863f3 100644 --- a/include/asm-mips/cpu-info.h +++ b/include/asm-mips/cpu-info.h | |||
@@ -55,6 +55,7 @@ struct cpuinfo_mips { | |||
55 | struct cache_desc scache; /* Secondary cache */ | 55 | struct cache_desc scache; /* Secondary cache */ |
56 | struct cache_desc tcache; /* Tertiary/split secondary cache */ | 56 | struct cache_desc tcache; /* Tertiary/split secondary cache */ |
57 | int srsets; /* Shadow register sets */ | 57 | int srsets; /* Shadow register sets */ |
58 | int core; /* physical core number */ | ||
58 | #if defined(CONFIG_MIPS_MT_SMTC) | 59 | #if defined(CONFIG_MIPS_MT_SMTC) |
59 | /* | 60 | /* |
60 | * In the MIPS MT "SMTC" model, each TC is considered | 61 | * In the MIPS MT "SMTC" model, each TC is considered |
@@ -63,8 +64,10 @@ struct cpuinfo_mips { | |||
63 | * to all TCs within the same VPE. | 64 | * to all TCs within the same VPE. |
64 | */ | 65 | */ |
65 | int vpe_id; /* Virtual Processor number */ | 66 | int vpe_id; /* Virtual Processor number */ |
66 | int tc_id; /* Thread Context number */ | ||
67 | #endif /* CONFIG_MIPS_MT */ | 67 | #endif /* CONFIG_MIPS_MT */ |
68 | #ifdef CONFIG_MIPS_MT_SMTC | ||
69 | int tc_id; /* Thread Context number */ | ||
70 | #endif | ||
68 | void *data; /* Additional data */ | 71 | void *data; /* Additional data */ |
69 | } __attribute__((aligned(SMP_CACHE_BYTES))); | 72 | } __attribute__((aligned(SMP_CACHE_BYTES))); |
70 | 73 | ||
diff --git a/include/asm-mips/cpu.h b/include/asm-mips/cpu.h index 54fc18a4e5a8..bf5bbc78a9f7 100644 --- a/include/asm-mips/cpu.h +++ b/include/asm-mips/cpu.h | |||
@@ -195,8 +195,8 @@ enum cpu_type_enum { | |||
195 | * MIPS32 class processors | 195 | * MIPS32 class processors |
196 | */ | 196 | */ |
197 | CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_74K, CPU_AU1000, | 197 | CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_74K, CPU_AU1000, |
198 | CPU_AU1100, CPU_AU1200, CPU_AU1500, CPU_AU1550, CPU_PR4450, | 198 | CPU_AU1100, CPU_AU1200, CPU_AU1210, CPU_AU1250, CPU_AU1500, CPU_AU1550, |
199 | CPU_BCM3302, CPU_BCM4710, | 199 | CPU_PR4450, CPU_BCM3302, CPU_BCM4710, |
200 | 200 | ||
201 | /* | 201 | /* |
202 | * MIPS64 class processors | 202 | * MIPS64 class processors |
diff --git a/include/asm-mips/delay.h b/include/asm-mips/delay.h index fab32131e9b4..b0bccd2c4ed5 100644 --- a/include/asm-mips/delay.h +++ b/include/asm-mips/delay.h | |||
@@ -6,13 +6,16 @@ | |||
6 | * Copyright (C) 1994 by Waldorf Electronics | 6 | * Copyright (C) 1994 by Waldorf Electronics |
7 | * Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle | 7 | * Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle |
8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
9 | * Copyright (C) 2007 Maciej W. Rozycki | ||
9 | */ | 10 | */ |
10 | #ifndef _ASM_DELAY_H | 11 | #ifndef _ASM_DELAY_H |
11 | #define _ASM_DELAY_H | 12 | #define _ASM_DELAY_H |
12 | 13 | ||
13 | #include <linux/param.h> | 14 | #include <linux/param.h> |
14 | #include <linux/smp.h> | 15 | #include <linux/smp.h> |
16 | |||
15 | #include <asm/compiler.h> | 17 | #include <asm/compiler.h> |
18 | #include <asm/war.h> | ||
16 | 19 | ||
17 | static inline void __delay(unsigned long loops) | 20 | static inline void __delay(unsigned long loops) |
18 | { | 21 | { |
@@ -25,7 +28,7 @@ static inline void __delay(unsigned long loops) | |||
25 | " .set reorder \n" | 28 | " .set reorder \n" |
26 | : "=r" (loops) | 29 | : "=r" (loops) |
27 | : "0" (loops)); | 30 | : "0" (loops)); |
28 | else if (sizeof(long) == 8) | 31 | else if (sizeof(long) == 8 && !DADDI_WAR) |
29 | __asm__ __volatile__ ( | 32 | __asm__ __volatile__ ( |
30 | " .set noreorder \n" | 33 | " .set noreorder \n" |
31 | " .align 3 \n" | 34 | " .align 3 \n" |
@@ -34,6 +37,15 @@ static inline void __delay(unsigned long loops) | |||
34 | " .set reorder \n" | 37 | " .set reorder \n" |
35 | : "=r" (loops) | 38 | : "=r" (loops) |
36 | : "0" (loops)); | 39 | : "0" (loops)); |
40 | else if (sizeof(long) == 8 && DADDI_WAR) | ||
41 | __asm__ __volatile__ ( | ||
42 | " .set noreorder \n" | ||
43 | " .align 3 \n" | ||
44 | "1: bnez %0, 1b \n" | ||
45 | " dsubu %0, %2 \n" | ||
46 | " .set reorder \n" | ||
47 | : "=r" (loops) | ||
48 | : "0" (loops), "r" (1)); | ||
37 | } | 49 | } |
38 | 50 | ||
39 | 51 | ||
@@ -50,7 +62,7 @@ static inline void __delay(unsigned long loops) | |||
50 | 62 | ||
51 | static inline void __udelay(unsigned long usecs, unsigned long lpj) | 63 | static inline void __udelay(unsigned long usecs, unsigned long lpj) |
52 | { | 64 | { |
53 | unsigned long lo; | 65 | unsigned long hi, lo; |
54 | 66 | ||
55 | /* | 67 | /* |
56 | * The rates of 128 is rounded wrongly by the catchall case | 68 | * The rates of 128 is rounded wrongly by the catchall case |
@@ -70,11 +82,16 @@ static inline void __udelay(unsigned long usecs, unsigned long lpj) | |||
70 | : "=h" (usecs), "=l" (lo) | 82 | : "=h" (usecs), "=l" (lo) |
71 | : "r" (usecs), "r" (lpj) | 83 | : "r" (usecs), "r" (lpj) |
72 | : GCC_REG_ACCUM); | 84 | : GCC_REG_ACCUM); |
73 | else if (sizeof(long) == 8) | 85 | else if (sizeof(long) == 8 && !R4000_WAR) |
74 | __asm__("dmultu\t%2, %3" | 86 | __asm__("dmultu\t%2, %3" |
75 | : "=h" (usecs), "=l" (lo) | 87 | : "=h" (usecs), "=l" (lo) |
76 | : "r" (usecs), "r" (lpj) | 88 | : "r" (usecs), "r" (lpj) |
77 | : GCC_REG_ACCUM); | 89 | : GCC_REG_ACCUM); |
90 | else if (sizeof(long) == 8 && R4000_WAR) | ||
91 | __asm__("dmultu\t%3, %4\n\tmfhi\t%0" | ||
92 | : "=r" (usecs), "=h" (hi), "=l" (lo) | ||
93 | : "r" (usecs), "r" (lpj) | ||
94 | : GCC_REG_ACCUM); | ||
78 | 95 | ||
79 | __delay(usecs); | 96 | __delay(usecs); |
80 | } | 97 | } |
diff --git a/include/asm-mips/dma.h b/include/asm-mips/dma.h index d6a6c21f16db..1353c81065d1 100644 --- a/include/asm-mips/dma.h +++ b/include/asm-mips/dma.h | |||
@@ -84,10 +84,9 @@ | |||
84 | * Deskstations or Acer PICA but not the much more versatile DMA logic used | 84 | * Deskstations or Acer PICA but not the much more versatile DMA logic used |
85 | * for the local devices on Acer PICA or Magnums. | 85 | * for the local devices on Acer PICA or Magnums. |
86 | */ | 86 | */ |
87 | #ifdef CONFIG_SGI_IP22 | 87 | #if defined(CONFIG_SGI_IP22) || defined(CONFIG_SGI_IP28) |
88 | /* Horrible hack to have a correct DMA window on IP22 */ | 88 | /* don't care; ISA bus master won't work, ISA slave DMA supports 32bit addr */ |
89 | #include <asm/sgi/mc.h> | 89 | #define MAX_DMA_ADDRESS PAGE_OFFSET |
90 | #define MAX_DMA_ADDRESS (PAGE_OFFSET + SGIMC_SEG0_BADDR + 0x01000000) | ||
91 | #else | 90 | #else |
92 | #define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x01000000) | 91 | #define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x01000000) |
93 | #endif | 92 | #endif |
diff --git a/include/asm-mips/fixmap.h b/include/asm-mips/fixmap.h index f27b96cfac2e..9cc8522a394f 100644 --- a/include/asm-mips/fixmap.h +++ b/include/asm-mips/fixmap.h | |||
@@ -60,16 +60,6 @@ enum fixed_addresses { | |||
60 | __end_of_fixed_addresses | 60 | __end_of_fixed_addresses |
61 | }; | 61 | }; |
62 | 62 | ||
63 | extern void __set_fixmap(enum fixed_addresses idx, | ||
64 | unsigned long phys, pgprot_t flags); | ||
65 | |||
66 | #define set_fixmap(idx, phys) \ | ||
67 | __set_fixmap(idx, phys, PAGE_KERNEL) | ||
68 | /* | ||
69 | * Some hardware wants to get fixmapped without caching. | ||
70 | */ | ||
71 | #define set_fixmap_nocache(idx, phys) \ | ||
72 | __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE) | ||
73 | /* | 63 | /* |
74 | * used by vmalloc.c. | 64 | * used by vmalloc.c. |
75 | * | 65 | * |
diff --git a/include/asm-mips/fw/cfe/cfe_api.h b/include/asm-mips/fw/cfe/cfe_api.h index 1003e7156bfc..0995575db320 100644 --- a/include/asm-mips/fw/cfe/cfe_api.h +++ b/include/asm-mips/fw/cfe/cfe_api.h | |||
@@ -15,49 +15,27 @@ | |||
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | /* | |
19 | /* ********************************************************************* | 19 | * Broadcom Common Firmware Environment (CFE) |
20 | * | 20 | * |
21 | * Broadcom Common Firmware Environment (CFE) | 21 | * This file contains declarations for doing callbacks to |
22 | * | 22 | * cfe from an application. It should be the only header |
23 | * Device function prototypes File: cfe_api.h | 23 | * needed by the application to use this library |
24 | * | 24 | * |
25 | * This file contains declarations for doing callbacks to | 25 | * Authors: Mitch Lichtenberg, Chris Demetriou |
26 | * cfe from an application. It should be the only header | 26 | */ |
27 | * needed by the application to use this library | ||
28 | * | ||
29 | * Authors: Mitch Lichtenberg, Chris Demetriou | ||
30 | * | ||
31 | ********************************************************************* */ | ||
32 | |||
33 | #ifndef CFE_API_H | 27 | #ifndef CFE_API_H |
34 | #define CFE_API_H | 28 | #define CFE_API_H |
35 | 29 | ||
36 | /* | ||
37 | * Apply customizations here for different OSes. These need to: | ||
38 | * * typedef uint64_t, int64_t, intptr_t, uintptr_t. | ||
39 | * * define cfe_strlen() if use of an existing function is desired. | ||
40 | * * define CFE_API_IMPL_NAMESPACE if API functions are to use | ||
41 | * names in the implementation namespace. | ||
42 | * Also, optionally, if the build environment does not do so automatically, | ||
43 | * CFE_API_* can be defined here as desired. | ||
44 | */ | ||
45 | /* Begin customization. */ | ||
46 | #include <linux/types.h> | 30 | #include <linux/types.h> |
47 | #include <linux/string.h> | 31 | #include <linux/string.h> |
48 | 32 | ||
49 | typedef long intptr_t; | 33 | typedef long intptr_t; |
50 | 34 | ||
51 | #define cfe_strlen strlen | ||
52 | 35 | ||
53 | #define CFE_API_ALL | 36 | /* |
54 | #define CFE_API_STRLEN_CUSTOM | 37 | * Constants |
55 | /* End customization. */ | 38 | */ |
56 | |||
57 | |||
58 | /* ********************************************************************* | ||
59 | * Constants | ||
60 | ********************************************************************* */ | ||
61 | 39 | ||
62 | /* Seal indicating CFE's presence, passed to user program. */ | 40 | /* Seal indicating CFE's presence, passed to user program. */ |
63 | #define CFE_EPTSEAL 0x43464531 | 41 | #define CFE_EPTSEAL 0x43464531 |
@@ -109,54 +87,13 @@ typedef struct { | |||
109 | 87 | ||
110 | 88 | ||
111 | /* | 89 | /* |
112 | * cfe_strlen is handled specially: If already defined, it has been | ||
113 | * overridden in this environment with a standard strlen-like function. | ||
114 | */ | ||
115 | #ifdef cfe_strlen | ||
116 | # define CFE_API_STRLEN_CUSTOM | ||
117 | #else | ||
118 | # ifdef CFE_API_IMPL_NAMESPACE | ||
119 | # define cfe_strlen(a) __cfe_strlen(a) | ||
120 | # endif | ||
121 | int cfe_strlen(char *name); | ||
122 | #endif | ||
123 | |||
124 | /* | ||
125 | * Defines and prototypes for functions which take no arguments. | 90 | * Defines and prototypes for functions which take no arguments. |
126 | */ | 91 | */ |
127 | #ifdef CFE_API_IMPL_NAMESPACE | ||
128 | int64_t __cfe_getticks(void); | ||
129 | #define cfe_getticks() __cfe_getticks() | ||
130 | #else | ||
131 | int64_t cfe_getticks(void); | 92 | int64_t cfe_getticks(void); |
132 | #endif | ||
133 | 93 | ||
134 | /* | 94 | /* |
135 | * Defines and prototypes for the rest of the functions. | 95 | * Defines and prototypes for the rest of the functions. |
136 | */ | 96 | */ |
137 | #ifdef CFE_API_IMPL_NAMESPACE | ||
138 | #define cfe_close(a) __cfe_close(a) | ||
139 | #define cfe_cpu_start(a, b, c, d, e) __cfe_cpu_start(a, b, c, d, e) | ||
140 | #define cfe_cpu_stop(a) __cfe_cpu_stop(a) | ||
141 | #define cfe_enumenv(a, b, d, e, f) __cfe_enumenv(a, b, d, e, f) | ||
142 | #define cfe_enummem(a, b, c, d, e) __cfe_enummem(a, b, c, d, e) | ||
143 | #define cfe_exit(a, b) __cfe_exit(a, b) | ||
144 | #define cfe_flushcache(a) __cfe_cacheflush(a) | ||
145 | #define cfe_getdevinfo(a) __cfe_getdevinfo(a) | ||
146 | #define cfe_getenv(a, b, c) __cfe_getenv(a, b, c) | ||
147 | #define cfe_getfwinfo(a) __cfe_getfwinfo(a) | ||
148 | #define cfe_getstdhandle(a) __cfe_getstdhandle(a) | ||
149 | #define cfe_init(a, b) __cfe_init(a, b) | ||
150 | #define cfe_inpstat(a) __cfe_inpstat(a) | ||
151 | #define cfe_ioctl(a, b, c, d, e, f) __cfe_ioctl(a, b, c, d, e, f) | ||
152 | #define cfe_open(a) __cfe_open(a) | ||
153 | #define cfe_read(a, b, c) __cfe_read(a, b, c) | ||
154 | #define cfe_readblk(a, b, c, d) __cfe_readblk(a, b, c, d) | ||
155 | #define cfe_setenv(a, b) __cfe_setenv(a, b) | ||
156 | #define cfe_write(a, b, c) __cfe_write(a, b, c) | ||
157 | #define cfe_writeblk(a, b, c, d) __cfe_writeblk(a, b, c, d) | ||
158 | #endif /* CFE_API_IMPL_NAMESPACE */ | ||
159 | |||
160 | int cfe_close(int handle); | 97 | int cfe_close(int handle); |
161 | int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1); | 98 | int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1); |
162 | int cfe_cpu_stop(int cpu); | 99 | int cfe_cpu_stop(int cpu); |
diff --git a/include/asm-mips/fw/cfe/cfe_error.h b/include/asm-mips/fw/cfe/cfe_error.h index 975f00002cbe..b80374636279 100644 --- a/include/asm-mips/fw/cfe/cfe_error.h +++ b/include/asm-mips/fw/cfe/cfe_error.h | |||
@@ -16,18 +16,13 @@ | |||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | /* ********************************************************************* | 19 | /* |
20 | * | 20 | * Broadcom Common Firmware Environment (CFE) |
21 | * Broadcom Common Firmware Environment (CFE) | 21 | * |
22 | * | 22 | * CFE's global error code list is here. |
23 | * Error codes File: cfe_error.h | 23 | * |
24 | * | 24 | * Author: Mitch Lichtenberg |
25 | * CFE's global error code list is here. | 25 | */ |
26 | * | ||
27 | * Author: Mitch Lichtenberg | ||
28 | * | ||
29 | ********************************************************************* */ | ||
30 | |||
31 | 26 | ||
32 | #define CFE_OK 0 | 27 | #define CFE_OK 0 |
33 | #define CFE_ERR -1 /* generic error */ | 28 | #define CFE_ERR -1 /* generic error */ |
diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h index a79e7caf3a86..5b9fce73f11d 100644 --- a/include/asm-mips/mach-cobalt/cobalt.h +++ b/include/asm-mips/mach-cobalt/cobalt.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Lowlevel hardware stuff for the MIPS based Cobalt microservers. | 2 | * The Cobalt board ID information. |
3 | * | 3 | * |
4 | * This file is subject to the terms and conditions of the GNU General Public | 4 | * This file is subject to the terms and conditions of the GNU General Public |
5 | * License. See the file "COPYING" in the main directory of this archive | 5 | * License. See the file "COPYING" in the main directory of this archive |
@@ -12,9 +12,6 @@ | |||
12 | #ifndef __ASM_COBALT_H | 12 | #ifndef __ASM_COBALT_H |
13 | #define __ASM_COBALT_H | 13 | #define __ASM_COBALT_H |
14 | 14 | ||
15 | /* | ||
16 | * The Cobalt board ID information. | ||
17 | */ | ||
18 | extern int cobalt_board_id; | 15 | extern int cobalt_board_id; |
19 | 16 | ||
20 | #define COBALT_BRD_ID_QUBE1 0x3 | 17 | #define COBALT_BRD_ID_QUBE1 0x3 |
@@ -22,14 +19,4 @@ extern int cobalt_board_id; | |||
22 | #define COBALT_BRD_ID_QUBE2 0x5 | 19 | #define COBALT_BRD_ID_QUBE2 0x5 |
23 | #define COBALT_BRD_ID_RAQ2 0x6 | 20 | #define COBALT_BRD_ID_RAQ2 0x6 |
24 | 21 | ||
25 | #define COBALT_KEY_PORT ((~*(volatile unsigned int *) CKSEG1ADDR(0x1d000000) >> 24) & COBALT_KEY_MASK) | ||
26 | # define COBALT_KEY_CLEAR (1 << 1) | ||
27 | # define COBALT_KEY_LEFT (1 << 2) | ||
28 | # define COBALT_KEY_UP (1 << 3) | ||
29 | # define COBALT_KEY_DOWN (1 << 4) | ||
30 | # define COBALT_KEY_RIGHT (1 << 5) | ||
31 | # define COBALT_KEY_ENTER (1 << 6) | ||
32 | # define COBALT_KEY_SELECT (1 << 7) | ||
33 | # define COBALT_KEY_MASK 0xfe | ||
34 | |||
35 | #endif /* __ASM_COBALT_H */ | 22 | #endif /* __ASM_COBALT_H */ |
diff --git a/include/asm-mips/mach-ip28/cpu-feature-overrides.h b/include/asm-mips/mach-ip28/cpu-feature-overrides.h new file mode 100644 index 000000000000..9a53b326f848 --- /dev/null +++ b/include/asm-mips/mach-ip28/cpu-feature-overrides.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2003 Ralf Baechle | ||
7 | * 6/2004 pf | ||
8 | */ | ||
9 | #ifndef __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H | ||
10 | #define __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H | ||
11 | |||
12 | /* | ||
13 | * IP28 only comes with R10000 family processors all using the same config | ||
14 | */ | ||
15 | #define cpu_has_watch 1 | ||
16 | #define cpu_has_mips16 0 | ||
17 | #define cpu_has_divec 0 | ||
18 | #define cpu_has_vce 0 | ||
19 | #define cpu_has_cache_cdex_p 0 | ||
20 | #define cpu_has_cache_cdex_s 0 | ||
21 | #define cpu_has_prefetch 1 | ||
22 | #define cpu_has_mcheck 0 | ||
23 | #define cpu_has_ejtag 0 | ||
24 | |||
25 | #define cpu_has_llsc 1 | ||
26 | #define cpu_has_vtag_icache 0 | ||
27 | #define cpu_has_dc_aliases 0 /* see probe_pcache() */ | ||
28 | #define cpu_has_ic_fills_f_dc 0 | ||
29 | #define cpu_has_dsp 0 | ||
30 | #define cpu_icache_snoops_remote_store 1 | ||
31 | #define cpu_has_mipsmt 0 | ||
32 | #define cpu_has_userlocal 0 | ||
33 | |||
34 | #define cpu_has_nofpuex 0 | ||
35 | #define cpu_has_64bits 1 | ||
36 | |||
37 | #define cpu_has_4kex 1 | ||
38 | #define cpu_has_4k_cache 1 | ||
39 | |||
40 | #define cpu_has_inclusive_pcaches 1 | ||
41 | |||
42 | #define cpu_dcache_line_size() 32 | ||
43 | #define cpu_icache_line_size() 64 | ||
44 | |||
45 | #define cpu_has_mips32r1 0 | ||
46 | #define cpu_has_mips32r2 0 | ||
47 | #define cpu_has_mips64r1 0 | ||
48 | #define cpu_has_mips64r2 0 | ||
49 | |||
50 | #endif /* __ASM_MACH_IP28_CPU_FEATURE_OVERRIDES_H */ | ||
diff --git a/include/asm-mips/mach-ip28/ds1286.h b/include/asm-mips/mach-ip28/ds1286.h new file mode 100644 index 000000000000..471bb9a33e0f --- /dev/null +++ b/include/asm-mips/mach-ip28/ds1286.h | |||
@@ -0,0 +1,4 @@ | |||
1 | #ifndef __ASM_MACH_IP28_DS1286_H | ||
2 | #define __ASM_MACH_IP28_DS1286_H | ||
3 | #include <asm/mach-ip22/ds1286.h> | ||
4 | #endif /* __ASM_MACH_IP28_DS1286_H */ | ||
diff --git a/include/asm-mips/mach-ip28/spaces.h b/include/asm-mips/mach-ip28/spaces.h new file mode 100644 index 000000000000..05aabb27e5e7 --- /dev/null +++ b/include/asm-mips/mach-ip28/spaces.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle | ||
7 | * Copyright (C) 2000, 2002 Maciej W. Rozycki | ||
8 | * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. | ||
9 | * 2004 pf | ||
10 | */ | ||
11 | #ifndef _ASM_MACH_IP28_SPACES_H | ||
12 | #define _ASM_MACH_IP28_SPACES_H | ||
13 | |||
14 | #define CAC_BASE 0xa800000000000000 | ||
15 | |||
16 | #define HIGHMEM_START (~0UL) | ||
17 | |||
18 | #define PHYS_OFFSET _AC(0x20000000, UL) | ||
19 | |||
20 | #include <asm/mach-generic/spaces.h> | ||
21 | |||
22 | #endif /* _ASM_MACH_IP28_SPACES_H */ | ||
diff --git a/include/asm-mips/mach-qemu/war.h b/include/asm-mips/mach-ip28/war.h index 0eaf0c548a47..a1baafab486a 100644 --- a/include/asm-mips/mach-qemu/war.h +++ b/include/asm-mips/mach-ip28/war.h | |||
@@ -5,8 +5,8 @@ | |||
5 | * | 5 | * |
6 | * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> | 6 | * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> |
7 | */ | 7 | */ |
8 | #ifndef __ASM_MIPS_MACH_QEMU_WAR_H | 8 | #ifndef __ASM_MIPS_MACH_IP28_WAR_H |
9 | #define __ASM_MIPS_MACH_QEMU_WAR_H | 9 | #define __ASM_MIPS_MACH_IP28_WAR_H |
10 | 10 | ||
11 | #define R4600_V1_INDEX_ICACHEOP_WAR 0 | 11 | #define R4600_V1_INDEX_ICACHEOP_WAR 0 |
12 | #define R4600_V1_HIT_CACHEOP_WAR 0 | 12 | #define R4600_V1_HIT_CACHEOP_WAR 0 |
@@ -19,7 +19,7 @@ | |||
19 | #define TX49XX_ICACHE_INDEX_INV_WAR 0 | 19 | #define TX49XX_ICACHE_INDEX_INV_WAR 0 |
20 | #define RM9000_CDEX_SMP_WAR 0 | 20 | #define RM9000_CDEX_SMP_WAR 0 |
21 | #define ICACHE_REFILLS_WORKAROUND_WAR 0 | 21 | #define ICACHE_REFILLS_WORKAROUND_WAR 0 |
22 | #define R10000_LLSC_WAR 0 | 22 | #define R10000_LLSC_WAR 1 |
23 | #define MIPS34K_MISSED_ITLB_WAR 0 | 23 | #define MIPS34K_MISSED_ITLB_WAR 0 |
24 | 24 | ||
25 | #endif /* __ASM_MIPS_MACH_QEMU_WAR_H */ | 25 | #endif /* __ASM_MIPS_MACH_IP28_WAR_H */ |
diff --git a/include/asm-mips/mach-qemu/cpu-feature-overrides.h b/include/asm-mips/mach-qemu/cpu-feature-overrides.h deleted file mode 100644 index d2daaed235d5..000000000000 --- a/include/asm-mips/mach-qemu/cpu-feature-overrides.h +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2003, 07 Ralf Baechle | ||
7 | */ | ||
8 | #ifndef __ASM_MACH_QEMU_CPU_FEATURE_OVERRIDES_H | ||
9 | #define __ASM_MACH_QEMU_CPU_FEATURE_OVERRIDES_H | ||
10 | |||
11 | /* | ||
12 | * QEMU only comes with a hazard-free MIPS32 processor, so things are easy. | ||
13 | */ | ||
14 | #define cpu_has_mips16 0 | ||
15 | #define cpu_has_divec 0 | ||
16 | #define cpu_has_cache_cdex_p 0 | ||
17 | #define cpu_has_prefetch 0 | ||
18 | #define cpu_has_mcheck 0 | ||
19 | #define cpu_has_ejtag 0 | ||
20 | |||
21 | #define cpu_has_llsc 1 | ||
22 | #define cpu_has_vtag_icache 0 | ||
23 | #define cpu_has_dc_aliases 0 | ||
24 | #define cpu_has_ic_fills_f_dc 0 | ||
25 | |||
26 | #define cpu_has_dsp 0 | ||
27 | #define cpu_has_mipsmt 0 | ||
28 | |||
29 | #define cpu_has_nofpuex 0 | ||
30 | #define cpu_has_64bits 0 | ||
31 | |||
32 | #endif /* __ASM_MACH_QEMU_CPU_FEATURE_OVERRIDES_H */ | ||
diff --git a/include/asm-mips/mips-boards/generic.h b/include/asm-mips/mips-boards/generic.h index d58977483534..1c39d339521e 100644 --- a/include/asm-mips/mips-boards/generic.h +++ b/include/asm-mips/mips-boards/generic.h | |||
@@ -97,10 +97,16 @@ extern int mips_revision_corid; | |||
97 | 97 | ||
98 | extern int mips_revision_sconid; | 98 | extern int mips_revision_sconid; |
99 | 99 | ||
100 | extern void mips_reboot_setup(void); | ||
101 | |||
100 | #ifdef CONFIG_PCI | 102 | #ifdef CONFIG_PCI |
101 | extern void mips_pcibios_init(void); | 103 | extern void mips_pcibios_init(void); |
102 | #else | 104 | #else |
103 | #define mips_pcibios_init() do { } while (0) | 105 | #define mips_pcibios_init() do { } while (0) |
104 | #endif | 106 | #endif |
105 | 107 | ||
108 | #ifdef CONFIG_KGDB | ||
109 | extern void kgdb_config(void); | ||
110 | #endif | ||
111 | |||
106 | #endif /* __ASM_MIPS_BOARDS_GENERIC_H */ | 112 | #endif /* __ASM_MIPS_BOARDS_GENERIC_H */ |
diff --git a/include/asm-mips/mipsprom.h b/include/asm-mips/mipsprom.h index ce7cff7f1e8e..146d41b67adc 100644 --- a/include/asm-mips/mipsprom.h +++ b/include/asm-mips/mipsprom.h | |||
@@ -71,4 +71,6 @@ | |||
71 | #define PROM_NV_GET 53 /* XXX */ | 71 | #define PROM_NV_GET 53 /* XXX */ |
72 | #define PROM_NV_SET 54 /* XXX */ | 72 | #define PROM_NV_SET 54 /* XXX */ |
73 | 73 | ||
74 | extern char *prom_getenv(char *); | ||
75 | |||
74 | #endif /* __ASM_MIPS_PROM_H */ | 76 | #endif /* __ASM_MIPS_PROM_H */ |
diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h b/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h index 0b56f55206c6..603eb737b4a8 100644 --- a/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h +++ b/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h | |||
@@ -585,11 +585,7 @@ | |||
585 | * UART defines * | 585 | * UART defines * |
586 | *************************************************************************** | 586 | *************************************************************************** |
587 | */ | 587 | */ |
588 | #ifndef CONFIG_MSP_FPGA | ||
589 | #define MSP_BASE_BAUD 25000000 | 588 | #define MSP_BASE_BAUD 25000000 |
590 | #else | ||
591 | #define MSP_BASE_BAUD 6000000 | ||
592 | #endif | ||
593 | #define MSP_UART_REG_LEN 0x20 | 589 | #define MSP_UART_REG_LEN 0x20 |
594 | 590 | ||
595 | /* | 591 | /* |
diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h index 2b8466ffd3ca..4c140db36786 100644 --- a/include/asm-mips/r4kcache.h +++ b/include/asm-mips/r4kcache.h | |||
@@ -403,6 +403,13 @@ __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) | |||
403 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) | 403 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64) |
404 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) | 404 | __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128) |
405 | 405 | ||
406 | __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16) | ||
407 | __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32) | ||
408 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16) | ||
409 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32) | ||
410 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64) | ||
411 | __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128) | ||
412 | |||
406 | /* build blast_xxx_range, protected_blast_xxx_range */ | 413 | /* build blast_xxx_range, protected_blast_xxx_range */ |
407 | #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \ | 414 | #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \ |
408 | static inline void prot##blast_##pfx##cache##_range(unsigned long start, \ | 415 | static inline void prot##blast_##pfx##cache##_range(unsigned long start, \ |
diff --git a/include/asm-mips/sgi/ioc.h b/include/asm-mips/sgi/ioc.h index f3e3dc9bb732..343ed15f8dc4 100644 --- a/include/asm-mips/sgi/ioc.h +++ b/include/asm-mips/sgi/ioc.h | |||
@@ -138,8 +138,8 @@ struct sgioc_regs { | |||
138 | u8 _sysid[3]; | 138 | u8 _sysid[3]; |
139 | volatile u8 sysid; | 139 | volatile u8 sysid; |
140 | #define SGIOC_SYSID_FULLHOUSE 0x01 | 140 | #define SGIOC_SYSID_FULLHOUSE 0x01 |
141 | #define SGIOC_SYSID_BOARDREV(x) ((x & 0xe0) > 5) | 141 | #define SGIOC_SYSID_BOARDREV(x) (((x) & 0x1e) >> 1) |
142 | #define SGIOC_SYSID_CHIPREV(x) ((x & 0x1e) > 1) | 142 | #define SGIOC_SYSID_CHIPREV(x) (((x) & 0xe0) >> 5) |
143 | u32 _unused2; | 143 | u32 _unused2; |
144 | u8 _read[3]; | 144 | u8 _read[3]; |
145 | volatile u8 read; | 145 | volatile u8 read; |
diff --git a/include/asm-mips/sibyte/board.h b/include/asm-mips/sibyte/board.h index da198a1c8c81..25372ae0e814 100644 --- a/include/asm-mips/sibyte/board.h +++ b/include/asm-mips/sibyte/board.h | |||
@@ -19,10 +19,8 @@ | |||
19 | #ifndef _SIBYTE_BOARD_H | 19 | #ifndef _SIBYTE_BOARD_H |
20 | #define _SIBYTE_BOARD_H | 20 | #define _SIBYTE_BOARD_H |
21 | 21 | ||
22 | #if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_PTSWARM) || \ | 22 | #if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_CRHONE) || \ |
23 | defined(CONFIG_SIBYTE_PT1120) || defined(CONFIG_SIBYTE_PT1125) || \ | 23 | defined(CONFIG_SIBYTE_CRHINE) || defined(CONFIG_SIBYTE_LITTLESUR) |
24 | defined(CONFIG_SIBYTE_CRHONE) || defined(CONFIG_SIBYTE_CRHINE) || \ | ||
25 | defined(CONFIG_SIBYTE_LITTLESUR) | ||
26 | #include <asm/sibyte/swarm.h> | 24 | #include <asm/sibyte/swarm.h> |
27 | #endif | 25 | #endif |
28 | 26 | ||
diff --git a/include/asm-mips/sibyte/sb1250.h b/include/asm-mips/sibyte/sb1250.h index 0dad844a3b5b..80c1a052662a 100644 --- a/include/asm-mips/sibyte/sb1250.h +++ b/include/asm-mips/sibyte/sb1250.h | |||
@@ -48,12 +48,10 @@ extern unsigned int zbbus_mhz; | |||
48 | extern void sb1250_time_init(void); | 48 | extern void sb1250_time_init(void); |
49 | extern void sb1250_mask_irq(int cpu, int irq); | 49 | extern void sb1250_mask_irq(int cpu, int irq); |
50 | extern void sb1250_unmask_irq(int cpu, int irq); | 50 | extern void sb1250_unmask_irq(int cpu, int irq); |
51 | extern void sb1250_smp_finish(void); | ||
52 | 51 | ||
53 | extern void bcm1480_time_init(void); | 52 | extern void bcm1480_time_init(void); |
54 | extern void bcm1480_mask_irq(int cpu, int irq); | 53 | extern void bcm1480_mask_irq(int cpu, int irq); |
55 | extern void bcm1480_unmask_irq(int cpu, int irq); | 54 | extern void bcm1480_unmask_irq(int cpu, int irq); |
56 | extern void bcm1480_smp_finish(void); | ||
57 | 55 | ||
58 | #define AT_spin \ | 56 | #define AT_spin \ |
59 | __asm__ __volatile__ ( \ | 57 | __asm__ __volatile__ ( \ |
diff --git a/include/asm-mips/sibyte/swarm.h b/include/asm-mips/sibyte/swarm.h index 540865fa7ec3..114d9d29ca9d 100644 --- a/include/asm-mips/sibyte/swarm.h +++ b/include/asm-mips/sibyte/swarm.h | |||
@@ -26,24 +26,6 @@ | |||
26 | #define SIBYTE_HAVE_PCMCIA 1 | 26 | #define SIBYTE_HAVE_PCMCIA 1 |
27 | #define SIBYTE_HAVE_IDE 1 | 27 | #define SIBYTE_HAVE_IDE 1 |
28 | #endif | 28 | #endif |
29 | #ifdef CONFIG_SIBYTE_PTSWARM | ||
30 | #define SIBYTE_BOARD_NAME "PTSWARM" | ||
31 | #define SIBYTE_HAVE_PCMCIA 1 | ||
32 | #define SIBYTE_HAVE_IDE 1 | ||
33 | #define SIBYTE_DEFAULT_CONSOLE "ttyS0,115200" | ||
34 | #endif | ||
35 | #ifdef CONFIG_SIBYTE_PT1120 | ||
36 | #define SIBYTE_BOARD_NAME "PT1120" | ||
37 | #define SIBYTE_HAVE_PCMCIA 1 | ||
38 | #define SIBYTE_HAVE_IDE 1 | ||
39 | #define SIBYTE_DEFAULT_CONSOLE "ttyS0,115200" | ||
40 | #endif | ||
41 | #ifdef CONFIG_SIBYTE_PT1125 | ||
42 | #define SIBYTE_BOARD_NAME "PT1125" | ||
43 | #define SIBYTE_HAVE_PCMCIA 1 | ||
44 | #define SIBYTE_HAVE_IDE 1 | ||
45 | #define SIBYTE_DEFAULT_CONSOLE "ttyS0,115200" | ||
46 | #endif | ||
47 | #ifdef CONFIG_SIBYTE_LITTLESUR | 29 | #ifdef CONFIG_SIBYTE_LITTLESUR |
48 | #define SIBYTE_BOARD_NAME "BCM91250C2 (LittleSur)" | 30 | #define SIBYTE_BOARD_NAME "BCM91250C2 (LittleSur)" |
49 | #define SIBYTE_HAVE_PCMCIA 0 | 31 | #define SIBYTE_HAVE_PCMCIA 0 |
diff --git a/include/asm-mips/smp-ops.h b/include/asm-mips/smp-ops.h new file mode 100644 index 000000000000..b17fdfb5d818 --- /dev/null +++ b/include/asm-mips/smp-ops.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General | ||
3 | * Public License. See the file "COPYING" in the main directory of this | ||
4 | * archive for more details. | ||
5 | * | ||
6 | * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com) | ||
7 | * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. | ||
8 | * Copyright (C) 2000, 2001, 2002 Ralf Baechle | ||
9 | * Copyright (C) 2000, 2001 Broadcom Corporation | ||
10 | */ | ||
11 | #ifndef __ASM_SMP_OPS_H | ||
12 | #define __ASM_SMP_OPS_H | ||
13 | |||
14 | #ifdef CONFIG_SMP | ||
15 | |||
16 | #include <linux/cpumask.h> | ||
17 | |||
18 | struct plat_smp_ops { | ||
19 | void (*send_ipi_single)(int cpu, unsigned int action); | ||
20 | void (*send_ipi_mask)(cpumask_t mask, unsigned int action); | ||
21 | void (*init_secondary)(void); | ||
22 | void (*smp_finish)(void); | ||
23 | void (*cpus_done)(void); | ||
24 | void (*boot_secondary)(int cpu, struct task_struct *idle); | ||
25 | void (*smp_setup)(void); | ||
26 | void (*prepare_cpus)(unsigned int max_cpus); | ||
27 | }; | ||
28 | |||
29 | extern void register_smp_ops(struct plat_smp_ops *ops); | ||
30 | |||
31 | static inline void plat_smp_setup(void) | ||
32 | { | ||
33 | extern struct plat_smp_ops *mp_ops; /* private */ | ||
34 | |||
35 | mp_ops->smp_setup(); | ||
36 | } | ||
37 | |||
38 | #else /* !CONFIG_SMP */ | ||
39 | |||
40 | struct plat_smp_ops; | ||
41 | |||
42 | static inline void plat_smp_setup(void) | ||
43 | { | ||
44 | /* UP, nothing to do ... */ | ||
45 | } | ||
46 | |||
47 | static inline void register_smp_ops(struct plat_smp_ops *ops) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | #endif /* !CONFIG_SMP */ | ||
52 | |||
53 | extern struct plat_smp_ops up_smp_ops; | ||
54 | extern struct plat_smp_ops vsmp_smp_ops; | ||
55 | |||
56 | #endif /* __ASM_SMP_OPS_H */ | ||
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h index dc770025a9b0..84fef1aeec0c 100644 --- a/include/asm-mips/smp.h +++ b/include/asm-mips/smp.h | |||
@@ -11,14 +11,16 @@ | |||
11 | #ifndef __ASM_SMP_H | 11 | #ifndef __ASM_SMP_H |
12 | #define __ASM_SMP_H | 12 | #define __ASM_SMP_H |
13 | 13 | ||
14 | |||
15 | #ifdef CONFIG_SMP | ||
16 | |||
17 | #include <linux/bitops.h> | 14 | #include <linux/bitops.h> |
18 | #include <linux/linkage.h> | 15 | #include <linux/linkage.h> |
19 | #include <linux/threads.h> | 16 | #include <linux/threads.h> |
20 | #include <linux/cpumask.h> | 17 | #include <linux/cpumask.h> |
18 | |||
21 | #include <asm/atomic.h> | 19 | #include <asm/atomic.h> |
20 | #include <asm/smp-ops.h> | ||
21 | |||
22 | extern int smp_num_siblings; | ||
23 | extern cpumask_t cpu_sibling_map[]; | ||
22 | 24 | ||
23 | #define raw_smp_processor_id() (current_thread_info()->cpu) | 25 | #define raw_smp_processor_id() (current_thread_info()->cpu) |
24 | 26 | ||
@@ -49,56 +51,6 @@ extern struct call_data_struct *call_data; | |||
49 | extern cpumask_t phys_cpu_present_map; | 51 | extern cpumask_t phys_cpu_present_map; |
50 | #define cpu_possible_map phys_cpu_present_map | 52 | #define cpu_possible_map phys_cpu_present_map |
51 | 53 | ||
52 | /* | ||
53 | * These are defined by the board-specific code. | ||
54 | */ | ||
55 | |||
56 | /* | ||
57 | * Cause the function described by call_data to be executed on the passed | ||
58 | * cpu. When the function has finished, increment the finished field of | ||
59 | * call_data. | ||
60 | */ | ||
61 | extern void core_send_ipi(int cpu, unsigned int action); | ||
62 | |||
63 | static inline void core_send_ipi_mask(cpumask_t mask, unsigned int action) | ||
64 | { | ||
65 | unsigned int i; | ||
66 | |||
67 | for_each_cpu_mask(i, mask) | ||
68 | core_send_ipi(i, action); | ||
69 | } | ||
70 | |||
71 | |||
72 | /* | ||
73 | * Firmware CPU startup hook | ||
74 | */ | ||
75 | extern void prom_boot_secondary(int cpu, struct task_struct *idle); | ||
76 | |||
77 | /* | ||
78 | * After we've done initial boot, this function is called to allow the | ||
79 | * board code to clean up state, if needed | ||
80 | */ | ||
81 | extern void prom_init_secondary(void); | ||
82 | |||
83 | /* | ||
84 | * Populate cpu_possible_map before smp_init, called from setup_arch. | ||
85 | */ | ||
86 | extern void plat_smp_setup(void); | ||
87 | |||
88 | /* | ||
89 | * Called in smp_prepare_cpus. | ||
90 | */ | ||
91 | extern void plat_prepare_cpus(unsigned int max_cpus); | ||
92 | |||
93 | /* | ||
94 | * Last chance for the board code to finish SMP initialization before | ||
95 | * the CPU is "online". | ||
96 | */ | ||
97 | extern void prom_smp_finish(void); | ||
98 | |||
99 | /* Hook for after all CPUs are online */ | ||
100 | extern void prom_cpus_done(void); | ||
101 | |||
102 | extern void asmlinkage smp_bootstrap(void); | 54 | extern void asmlinkage smp_bootstrap(void); |
103 | 55 | ||
104 | /* | 56 | /* |
@@ -108,11 +60,11 @@ extern void asmlinkage smp_bootstrap(void); | |||
108 | */ | 60 | */ |
109 | static inline void smp_send_reschedule(int cpu) | 61 | static inline void smp_send_reschedule(int cpu) |
110 | { | 62 | { |
111 | core_send_ipi(cpu, SMP_RESCHEDULE_YOURSELF); | 63 | extern struct plat_smp_ops *mp_ops; /* private */ |
64 | |||
65 | mp_ops->send_ipi_single(cpu, SMP_RESCHEDULE_YOURSELF); | ||
112 | } | 66 | } |
113 | 67 | ||
114 | extern asmlinkage void smp_call_function_interrupt(void); | 68 | extern asmlinkage void smp_call_function_interrupt(void); |
115 | 69 | ||
116 | #endif /* CONFIG_SMP */ | ||
117 | |||
118 | #endif /* __ASM_SMP_H */ | 70 | #endif /* __ASM_SMP_H */ |
diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h index af081457f847..e716447e5e03 100644 --- a/include/asm-mips/sni.h +++ b/include/asm-mips/sni.h | |||
@@ -35,23 +35,23 @@ extern unsigned int sni_brd_type; | |||
35 | #define SNI_CPU_M8050 0x0b | 35 | #define SNI_CPU_M8050 0x0b |
36 | #define SNI_CPU_M8053 0x0d | 36 | #define SNI_CPU_M8053 0x0d |
37 | 37 | ||
38 | #define SNI_PORT_BASE 0xb4000000 | 38 | #define SNI_PORT_BASE CKSEG1ADDR(0xb4000000) |
39 | 39 | ||
40 | #ifndef __MIPSEL__ | 40 | #ifndef __MIPSEL__ |
41 | /* | 41 | /* |
42 | * ASIC PCI registers for big endian configuration. | 42 | * ASIC PCI registers for big endian configuration. |
43 | */ | 43 | */ |
44 | #define PCIMT_UCONF 0xbfff0004 | 44 | #define PCIMT_UCONF CKSEG1ADDR(0xbfff0004) |
45 | #define PCIMT_IOADTIMEOUT2 0xbfff000c | 45 | #define PCIMT_IOADTIMEOUT2 CKSEG1ADDR(0xbfff000c) |
46 | #define PCIMT_IOMEMCONF 0xbfff0014 | 46 | #define PCIMT_IOMEMCONF CKSEG1ADDR(0xbfff0014) |
47 | #define PCIMT_IOMMU 0xbfff001c | 47 | #define PCIMT_IOMMU CKSEG1ADDR(0xbfff001c) |
48 | #define PCIMT_IOADTIMEOUT1 0xbfff0024 | 48 | #define PCIMT_IOADTIMEOUT1 CKSEG1ADDR(0xbfff0024) |
49 | #define PCIMT_DMAACCESS 0xbfff002c | 49 | #define PCIMT_DMAACCESS CKSEG1ADDR(0xbfff002c) |
50 | #define PCIMT_DMAHIT 0xbfff0034 | 50 | #define PCIMT_DMAHIT CKSEG1ADDR(0xbfff0034) |
51 | #define PCIMT_ERRSTATUS 0xbfff003c | 51 | #define PCIMT_ERRSTATUS CKSEG1ADDR(0xbfff003c) |
52 | #define PCIMT_ERRADDR 0xbfff0044 | 52 | #define PCIMT_ERRADDR CKSEG1ADDR(0xbfff0044) |
53 | #define PCIMT_SYNDROME 0xbfff004c | 53 | #define PCIMT_SYNDROME CKSEG1ADDR(0xbfff004c) |
54 | #define PCIMT_ITPEND 0xbfff0054 | 54 | #define PCIMT_ITPEND CKSEG1ADDR(0xbfff0054) |
55 | #define IT_INT2 0x01 | 55 | #define IT_INT2 0x01 |
56 | #define IT_INTD 0x02 | 56 | #define IT_INTD 0x02 |
57 | #define IT_INTC 0x04 | 57 | #define IT_INTC 0x04 |
@@ -60,32 +60,32 @@ extern unsigned int sni_brd_type; | |||
60 | #define IT_EISA 0x20 | 60 | #define IT_EISA 0x20 |
61 | #define IT_SCSI 0x40 | 61 | #define IT_SCSI 0x40 |
62 | #define IT_ETH 0x80 | 62 | #define IT_ETH 0x80 |
63 | #define PCIMT_IRQSEL 0xbfff005c | 63 | #define PCIMT_IRQSEL CKSEG1ADDR(0xbfff005c) |
64 | #define PCIMT_TESTMEM 0xbfff0064 | 64 | #define PCIMT_TESTMEM CKSEG1ADDR(0xbfff0064) |
65 | #define PCIMT_ECCREG 0xbfff006c | 65 | #define PCIMT_ECCREG CKSEG1ADDR(0xbfff006c) |
66 | #define PCIMT_CONFIG_ADDRESS 0xbfff0074 | 66 | #define PCIMT_CONFIG_ADDRESS CKSEG1ADDR(0xbfff0074) |
67 | #define PCIMT_ASIC_ID 0xbfff007c /* read */ | 67 | #define PCIMT_ASIC_ID CKSEG1ADDR(0xbfff007c) /* read */ |
68 | #define PCIMT_SOFT_RESET 0xbfff007c /* write */ | 68 | #define PCIMT_SOFT_RESET CKSEG1ADDR(0xbfff007c) /* write */ |
69 | #define PCIMT_PIA_OE 0xbfff0084 | 69 | #define PCIMT_PIA_OE CKSEG1ADDR(0xbfff0084) |
70 | #define PCIMT_PIA_DATAOUT 0xbfff008c | 70 | #define PCIMT_PIA_DATAOUT CKSEG1ADDR(0xbfff008c) |
71 | #define PCIMT_PIA_DATAIN 0xbfff0094 | 71 | #define PCIMT_PIA_DATAIN CKSEG1ADDR(0xbfff0094) |
72 | #define PCIMT_CACHECONF 0xbfff009c | 72 | #define PCIMT_CACHECONF CKSEG1ADDR(0xbfff009c) |
73 | #define PCIMT_INVSPACE 0xbfff00a4 | 73 | #define PCIMT_INVSPACE CKSEG1ADDR(0xbfff00a4) |
74 | #else | 74 | #else |
75 | /* | 75 | /* |
76 | * ASIC PCI registers for little endian configuration. | 76 | * ASIC PCI registers for little endian configuration. |
77 | */ | 77 | */ |
78 | #define PCIMT_UCONF 0xbfff0000 | 78 | #define PCIMT_UCONF CKSEG1ADDR(0xbfff0000) |
79 | #define PCIMT_IOADTIMEOUT2 0xbfff0008 | 79 | #define PCIMT_IOADTIMEOUT2 CKSEG1ADDR(0xbfff0008) |
80 | #define PCIMT_IOMEMCONF 0xbfff0010 | 80 | #define PCIMT_IOMEMCONF CKSEG1ADDR(0xbfff0010) |
81 | #define PCIMT_IOMMU 0xbfff0018 | 81 | #define PCIMT_IOMMU CKSEG1ADDR(0xbfff0018) |
82 | #define PCIMT_IOADTIMEOUT1 0xbfff0020 | 82 | #define PCIMT_IOADTIMEOUT1 CKSEG1ADDR(0xbfff0020) |
83 | #define PCIMT_DMAACCESS 0xbfff0028 | 83 | #define PCIMT_DMAACCESS CKSEG1ADDR(0xbfff0028) |
84 | #define PCIMT_DMAHIT 0xbfff0030 | 84 | #define PCIMT_DMAHIT CKSEG1ADDR(0xbfff0030) |
85 | #define PCIMT_ERRSTATUS 0xbfff0038 | 85 | #define PCIMT_ERRSTATUS CKSEG1ADDR(0xbfff0038) |
86 | #define PCIMT_ERRADDR 0xbfff0040 | 86 | #define PCIMT_ERRADDR CKSEG1ADDR(0xbfff0040) |
87 | #define PCIMT_SYNDROME 0xbfff0048 | 87 | #define PCIMT_SYNDROME CKSEG1ADDR(0xbfff0048) |
88 | #define PCIMT_ITPEND 0xbfff0050 | 88 | #define PCIMT_ITPEND CKSEG1ADDR(0xbfff0050) |
89 | #define IT_INT2 0x01 | 89 | #define IT_INT2 0x01 |
90 | #define IT_INTD 0x02 | 90 | #define IT_INTD 0x02 |
91 | #define IT_INTC 0x04 | 91 | #define IT_INTC 0x04 |
@@ -94,20 +94,20 @@ extern unsigned int sni_brd_type; | |||
94 | #define IT_EISA 0x20 | 94 | #define IT_EISA 0x20 |
95 | #define IT_SCSI 0x40 | 95 | #define IT_SCSI 0x40 |
96 | #define IT_ETH 0x80 | 96 | #define IT_ETH 0x80 |
97 | #define PCIMT_IRQSEL 0xbfff0058 | 97 | #define PCIMT_IRQSEL CKSEG1ADDR(0xbfff0058) |
98 | #define PCIMT_TESTMEM 0xbfff0060 | 98 | #define PCIMT_TESTMEM CKSEG1ADDR(0xbfff0060) |
99 | #define PCIMT_ECCREG 0xbfff0068 | 99 | #define PCIMT_ECCREG CKSEG1ADDR(0xbfff0068) |
100 | #define PCIMT_CONFIG_ADDRESS 0xbfff0070 | 100 | #define PCIMT_CONFIG_ADDRESS CKSEG1ADDR(0xbfff0070) |
101 | #define PCIMT_ASIC_ID 0xbfff0078 /* read */ | 101 | #define PCIMT_ASIC_ID CKSEG1ADDR(0xbfff0078) /* read */ |
102 | #define PCIMT_SOFT_RESET 0xbfff0078 /* write */ | 102 | #define PCIMT_SOFT_RESET CKSEG1ADDR(0xbfff0078) /* write */ |
103 | #define PCIMT_PIA_OE 0xbfff0080 | 103 | #define PCIMT_PIA_OE CKSEG1ADDR(0xbfff0080) |
104 | #define PCIMT_PIA_DATAOUT 0xbfff0088 | 104 | #define PCIMT_PIA_DATAOUT CKSEG1ADDR(0xbfff0088) |
105 | #define PCIMT_PIA_DATAIN 0xbfff0090 | 105 | #define PCIMT_PIA_DATAIN CKSEG1ADDR(0xbfff0090) |
106 | #define PCIMT_CACHECONF 0xbfff0098 | 106 | #define PCIMT_CACHECONF CKSEG1ADDR(0xbfff0098) |
107 | #define PCIMT_INVSPACE 0xbfff00a0 | 107 | #define PCIMT_INVSPACE CKSEG1ADDR(0xbfff00a0) |
108 | #endif | 108 | #endif |
109 | 109 | ||
110 | #define PCIMT_PCI_CONF 0xbfff0100 | 110 | #define PCIMT_PCI_CONF CKSEG1ADDR(0xbfff0100) |
111 | 111 | ||
112 | /* | 112 | /* |
113 | * Data port for the PCI bus in IO space | 113 | * Data port for the PCI bus in IO space |
@@ -117,34 +117,34 @@ extern unsigned int sni_brd_type; | |||
117 | /* | 117 | /* |
118 | * Board specific registers | 118 | * Board specific registers |
119 | */ | 119 | */ |
120 | #define PCIMT_CSMSR 0xbfd00000 | 120 | #define PCIMT_CSMSR CKSEG1ADDR(0xbfd00000) |
121 | #define PCIMT_CSSWITCH 0xbfd10000 | 121 | #define PCIMT_CSSWITCH CKSEG1ADDR(0xbfd10000) |
122 | #define PCIMT_CSITPEND 0xbfd20000 | 122 | #define PCIMT_CSITPEND CKSEG1ADDR(0xbfd20000) |
123 | #define PCIMT_AUTO_PO_EN 0xbfd30000 | 123 | #define PCIMT_AUTO_PO_EN CKSEG1ADDR(0xbfd30000) |
124 | #define PCIMT_CLR_TEMP 0xbfd40000 | 124 | #define PCIMT_CLR_TEMP CKSEG1ADDR(0xbfd40000) |
125 | #define PCIMT_AUTO_PO_DIS 0xbfd50000 | 125 | #define PCIMT_AUTO_PO_DIS CKSEG1ADDR(0xbfd50000) |
126 | #define PCIMT_EXMSR 0xbfd60000 | 126 | #define PCIMT_EXMSR CKSEG1ADDR(0xbfd60000) |
127 | #define PCIMT_UNUSED1 0xbfd70000 | 127 | #define PCIMT_UNUSED1 CKSEG1ADDR(0xbfd70000) |
128 | #define PCIMT_CSWCSM 0xbfd80000 | 128 | #define PCIMT_CSWCSM CKSEG1ADDR(0xbfd80000) |
129 | #define PCIMT_UNUSED2 0xbfd90000 | 129 | #define PCIMT_UNUSED2 CKSEG1ADDR(0xbfd90000) |
130 | #define PCIMT_CSLED 0xbfda0000 | 130 | #define PCIMT_CSLED CKSEG1ADDR(0xbfda0000) |
131 | #define PCIMT_CSMAPISA 0xbfdb0000 | 131 | #define PCIMT_CSMAPISA CKSEG1ADDR(0xbfdb0000) |
132 | #define PCIMT_CSRSTBP 0xbfdc0000 | 132 | #define PCIMT_CSRSTBP CKSEG1ADDR(0xbfdc0000) |
133 | #define PCIMT_CLRPOFF 0xbfdd0000 | 133 | #define PCIMT_CLRPOFF CKSEG1ADDR(0xbfdd0000) |
134 | #define PCIMT_CSTIMER 0xbfde0000 | 134 | #define PCIMT_CSTIMER CKSEG1ADDR(0xbfde0000) |
135 | #define PCIMT_PWDN 0xbfdf0000 | 135 | #define PCIMT_PWDN CKSEG1ADDR(0xbfdf0000) |
136 | 136 | ||
137 | /* | 137 | /* |
138 | * A20R based boards | 138 | * A20R based boards |
139 | */ | 139 | */ |
140 | #define A20R_PT_CLOCK_BASE 0xbc040000 | 140 | #define A20R_PT_CLOCK_BASE CKSEG1ADDR(0xbc040000) |
141 | #define A20R_PT_TIM0_ACK 0xbc050000 | 141 | #define A20R_PT_TIM0_ACK CKSEG1ADDR(0xbc050000) |
142 | #define A20R_PT_TIM1_ACK 0xbc060000 | 142 | #define A20R_PT_TIM1_ACK CKSEG1ADDR(0xbc060000) |
143 | 143 | ||
144 | #define SNI_A20R_IRQ_BASE MIPS_CPU_IRQ_BASE | 144 | #define SNI_A20R_IRQ_BASE MIPS_CPU_IRQ_BASE |
145 | #define SNI_A20R_IRQ_TIMER (SNI_A20R_IRQ_BASE+5) | 145 | #define SNI_A20R_IRQ_TIMER (SNI_A20R_IRQ_BASE+5) |
146 | 146 | ||
147 | #define SNI_PCIT_INT_REG 0xbfff000c | 147 | #define SNI_PCIT_INT_REG CKSEG1ADDR(0xbfff000c) |
148 | 148 | ||
149 | #define SNI_PCIT_INT_START 24 | 149 | #define SNI_PCIT_INT_START 24 |
150 | #define SNI_PCIT_INT_END 30 | 150 | #define SNI_PCIT_INT_END 30 |
@@ -186,10 +186,30 @@ extern unsigned int sni_brd_type; | |||
186 | /* | 186 | /* |
187 | * Base address for the mapped 16mb EISA bus segment. | 187 | * Base address for the mapped 16mb EISA bus segment. |
188 | */ | 188 | */ |
189 | #define PCIMT_EISA_BASE 0xb0000000 | 189 | #define PCIMT_EISA_BASE CKSEG1ADDR(0xb0000000) |
190 | 190 | ||
191 | /* PCI EISA Interrupt acknowledge */ | 191 | /* PCI EISA Interrupt acknowledge */ |
192 | #define PCIMT_INT_ACKNOWLEDGE 0xba000000 | 192 | #define PCIMT_INT_ACKNOWLEDGE CKSEG1ADDR(0xba000000) |
193 | |||
194 | /* | ||
195 | * SNI ID PROM | ||
196 | * | ||
197 | * SNI_IDPROM_MEMSIZE Memsize in 16MB quantities | ||
198 | * SNI_IDPROM_BRDTYPE Board Type | ||
199 | * SNI_IDPROM_CPUTYPE CPU Type on RM400 | ||
200 | */ | ||
201 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
202 | #define __SNI_END 0 | ||
203 | #endif | ||
204 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | ||
205 | #define __SNI_END 3 | ||
206 | #endif | ||
207 | #define SNI_IDPROM_BASE CKSEG1ADDR(0x1ff00000) | ||
208 | #define SNI_IDPROM_MEMSIZE (SNI_IDPROM_BASE + (0x28 ^ __SNI_END)) | ||
209 | #define SNI_IDPROM_BRDTYPE (SNI_IDPROM_BASE + (0x29 ^ __SNI_END)) | ||
210 | #define SNI_IDPROM_CPUTYPE (SNI_IDPROM_BASE + (0x30 ^ __SNI_END)) | ||
211 | |||
212 | #define SNI_IDPROM_SIZE 0x1000 | ||
193 | 213 | ||
194 | /* board specific init functions */ | 214 | /* board specific init functions */ |
195 | extern void sni_a20r_init(void); | 215 | extern void sni_a20r_init(void); |
@@ -207,6 +227,9 @@ extern void sni_pcimt_irq_init(void); | |||
207 | /* timer inits */ | 227 | /* timer inits */ |
208 | extern void sni_cpu_time_init(void); | 228 | extern void sni_cpu_time_init(void); |
209 | 229 | ||
230 | /* eisa init for RM200/400 */ | ||
231 | extern int sni_eisa_root_init(void); | ||
232 | |||
210 | /* common irq stuff */ | 233 | /* common irq stuff */ |
211 | extern void (*sni_hwint)(void); | 234 | extern void (*sni_hwint)(void); |
212 | extern struct irqaction sni_isa_irq; | 235 | extern struct irqaction sni_isa_irq; |
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h index fb41a8d76392..051e1af0bb95 100644 --- a/include/asm-mips/stackframe.h +++ b/include/asm-mips/stackframe.h | |||
@@ -6,6 +6,7 @@ | |||
6 | * Copyright (C) 1994, 95, 96, 99, 2001 Ralf Baechle | 6 | * Copyright (C) 1994, 95, 96, 99, 2001 Ralf Baechle |
7 | * Copyright (C) 1994, 1995, 1996 Paul M. Antoine. | 7 | * Copyright (C) 1994, 1995, 1996 Paul M. Antoine. |
8 | * Copyright (C) 1999 Silicon Graphics, Inc. | 8 | * Copyright (C) 1999 Silicon Graphics, Inc. |
9 | * Copyright (C) 2007 Maciej W. Rozycki | ||
9 | */ | 10 | */ |
10 | #ifndef _ASM_STACKFRAME_H | 11 | #ifndef _ASM_STACKFRAME_H |
11 | #define _ASM_STACKFRAME_H | 12 | #define _ASM_STACKFRAME_H |
@@ -145,8 +146,16 @@ | |||
145 | .set reorder | 146 | .set reorder |
146 | /* Called from user mode, new stack. */ | 147 | /* Called from user mode, new stack. */ |
147 | get_saved_sp | 148 | get_saved_sp |
149 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS | ||
148 | 8: move k0, sp | 150 | 8: move k0, sp |
149 | PTR_SUBU sp, k1, PT_SIZE | 151 | PTR_SUBU sp, k1, PT_SIZE |
152 | #else | ||
153 | .set at=k0 | ||
154 | 8: PTR_SUBU k1, PT_SIZE | ||
155 | .set noat | ||
156 | move k0, sp | ||
157 | move sp, k1 | ||
158 | #endif | ||
150 | LONG_S k0, PT_R29(sp) | 159 | LONG_S k0, PT_R29(sp) |
151 | LONG_S $3, PT_R3(sp) | 160 | LONG_S $3, PT_R3(sp) |
152 | /* | 161 | /* |
diff --git a/include/asm-mips/time.h b/include/asm-mips/time.h index 7717934f94c3..a8fd16e1981f 100644 --- a/include/asm-mips/time.h +++ b/include/asm-mips/time.h | |||
@@ -31,20 +31,13 @@ extern int rtc_mips_set_time(unsigned long); | |||
31 | extern int rtc_mips_set_mmss(unsigned long); | 31 | extern int rtc_mips_set_mmss(unsigned long); |
32 | 32 | ||
33 | /* | 33 | /* |
34 | * Timer interrupt functions. | ||
35 | * mips_timer_state is needed for high precision timer calibration. | ||
36 | */ | ||
37 | extern int (*mips_timer_state)(void); | ||
38 | |||
39 | /* | ||
40 | * board specific routines required by time_init(). | 34 | * board specific routines required by time_init(). |
41 | */ | 35 | */ |
42 | extern void plat_time_init(void); | 36 | extern void plat_time_init(void); |
43 | 37 | ||
44 | /* | 38 | /* |
45 | * mips_hpt_frequency - must be set if you intend to use an R4k-compatible | 39 | * mips_hpt_frequency - must be set if you intend to use an R4k-compatible |
46 | * counter as a timer interrupt source; otherwise it can be set up | 40 | * counter as a timer interrupt source. |
47 | * automagically with an aid of mips_timer_state. | ||
48 | */ | 41 | */ |
49 | extern unsigned int mips_hpt_frequency; | 42 | extern unsigned int mips_hpt_frequency; |
50 | 43 | ||
diff --git a/include/asm-mips/topology.h b/include/asm-mips/topology.h index 0440fb9f2180..259145e07e97 100644 --- a/include/asm-mips/topology.h +++ b/include/asm-mips/topology.h | |||
@@ -1 +1,17 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2007 by Ralf Baechle | ||
7 | */ | ||
8 | #ifndef __ASM_TOPOLOGY_H | ||
9 | #define __ASM_TOPOLOGY_H | ||
10 | |||
1 | #include <topology.h> | 11 | #include <topology.h> |
12 | |||
13 | #ifdef CONFIG_SMP | ||
14 | #define smt_capable() (smp_num_siblings > 1) | ||
15 | #endif | ||
16 | |||
17 | #endif /* __ASM_TOPOLOGY_H */ | ||
diff --git a/include/asm-mips/tx4927/tx4927_pci.h b/include/asm-mips/tx4927/tx4927_pci.h index 3f1e470192e3..0be77df70f2b 100644 --- a/include/asm-mips/tx4927/tx4927_pci.h +++ b/include/asm-mips/tx4927/tx4927_pci.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #define __ASM_TX4927_TX4927_PCI_H | 9 | #define __ASM_TX4927_TX4927_PCI_H |
10 | 10 | ||
11 | #define TX4927_CCFG_TOE 0x00004000 | 11 | #define TX4927_CCFG_TOE 0x00004000 |
12 | #define TX4927_CCFG_WR 0x00008000 | ||
12 | #define TX4927_CCFG_TINTDIS 0x01000000 | 13 | #define TX4927_CCFG_TINTDIS 0x01000000 |
13 | 14 | ||
14 | #define TX4927_PCIMEM 0x08000000 | 15 | #define TX4927_PCIMEM 0x08000000 |
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h index c30c718994c9..66523d610950 100644 --- a/include/asm-mips/uaccess.h +++ b/include/asm-mips/uaccess.h | |||
@@ -5,6 +5,7 @@ | |||
5 | * | 5 | * |
6 | * Copyright (C) 1996, 1997, 1998, 1999, 2000, 03, 04 by Ralf Baechle | 6 | * Copyright (C) 1996, 1997, 1998, 1999, 2000, 03, 04 by Ralf Baechle |
7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
8 | * Copyright (C) 2007 Maciej W. Rozycki | ||
8 | */ | 9 | */ |
9 | #ifndef _ASM_UACCESS_H | 10 | #ifndef _ASM_UACCESS_H |
10 | #define _ASM_UACCESS_H | 11 | #define _ASM_UACCESS_H |
@@ -387,6 +388,12 @@ extern void __put_user_unknown(void); | |||
387 | "jal\t" #destination "\n\t" | 388 | "jal\t" #destination "\n\t" |
388 | #endif | 389 | #endif |
389 | 390 | ||
391 | #ifndef CONFIG_CPU_DADDI_WORKAROUNDS | ||
392 | #define DADDI_SCRATCH "$0" | ||
393 | #else | ||
394 | #define DADDI_SCRATCH "$3" | ||
395 | #endif | ||
396 | |||
390 | extern size_t __copy_user(void *__to, const void *__from, size_t __n); | 397 | extern size_t __copy_user(void *__to, const void *__from, size_t __n); |
391 | 398 | ||
392 | #define __invoke_copy_to_user(to, from, n) \ | 399 | #define __invoke_copy_to_user(to, from, n) \ |
@@ -403,7 +410,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n); | |||
403 | : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ | 410 | : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ |
404 | : \ | 411 | : \ |
405 | : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ | 412 | : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ |
406 | "memory"); \ | 413 | DADDI_SCRATCH, "memory"); \ |
407 | __cu_len_r; \ | 414 | __cu_len_r; \ |
408 | }) | 415 | }) |
409 | 416 | ||
@@ -512,7 +519,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); | |||
512 | : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ | 519 | : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ |
513 | : \ | 520 | : \ |
514 | : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ | 521 | : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ |
515 | "memory"); \ | 522 | DADDI_SCRATCH, "memory"); \ |
516 | __cu_len_r; \ | 523 | __cu_len_r; \ |
517 | }) | 524 | }) |
518 | 525 | ||
@@ -535,7 +542,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); | |||
535 | : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ | 542 | : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ |
536 | : \ | 543 | : \ |
537 | : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ | 544 | : "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ |
538 | "memory"); \ | 545 | DADDI_SCRATCH, "memory"); \ |
539 | __cu_len_r; \ | 546 | __cu_len_r; \ |
540 | }) | 547 | }) |
541 | 548 | ||
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h index d2808edfd4e9..22361d5e3bf0 100644 --- a/include/asm-mips/war.h +++ b/include/asm-mips/war.h | |||
@@ -4,6 +4,7 @@ | |||
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2002, 2004, 2007 by Ralf Baechle | 6 | * Copyright (C) 2002, 2004, 2007 by Ralf Baechle |
7 | * Copyright (C) 2007 Maciej W. Rozycki | ||
7 | */ | 8 | */ |
8 | #ifndef _ASM_WAR_H | 9 | #ifndef _ASM_WAR_H |
9 | #define _ASM_WAR_H | 10 | #define _ASM_WAR_H |
@@ -11,6 +12,67 @@ | |||
11 | #include <war.h> | 12 | #include <war.h> |
12 | 13 | ||
13 | /* | 14 | /* |
15 | * Work around certain R4000 CPU errata (as implemented by GCC): | ||
16 | * | ||
17 | * - A double-word or a variable shift may give an incorrect result | ||
18 | * if executed immediately after starting an integer division: | ||
19 | * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", | ||
20 | * erratum #28 | ||
21 | * "MIPS R4000MC Errata, Processor Revision 2.2 and 3.0", erratum | ||
22 | * #19 | ||
23 | * | ||
24 | * - A double-word or a variable shift may give an incorrect result | ||
25 | * if executed while an integer multiplication is in progress: | ||
26 | * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", | ||
27 | * errata #16 & #28 | ||
28 | * | ||
29 | * - An integer division may give an incorrect result if started in | ||
30 | * a delay slot of a taken branch or a jump: | ||
31 | * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", | ||
32 | * erratum #52 | ||
33 | */ | ||
34 | #ifdef CONFIG_CPU_R4000_WORKAROUNDS | ||
35 | #define R4000_WAR 1 | ||
36 | #else | ||
37 | #define R4000_WAR 0 | ||
38 | #endif | ||
39 | |||
40 | /* | ||
41 | * Work around certain R4400 CPU errata (as implemented by GCC): | ||
42 | * | ||
43 | * - A double-word or a variable shift may give an incorrect result | ||
44 | * if executed immediately after starting an integer division: | ||
45 | * "MIPS R4400MC Errata, Processor Revision 1.0", erratum #10 | ||
46 | * "MIPS R4400MC Errata, Processor Revision 2.0 & 3.0", erratum #4 | ||
47 | */ | ||
48 | #ifdef CONFIG_CPU_R4400_WORKAROUNDS | ||
49 | #define R4400_WAR 1 | ||
50 | #else | ||
51 | #define R4400_WAR 0 | ||
52 | #endif | ||
53 | |||
54 | /* | ||
55 | * Work around the "daddi" and "daddiu" CPU errata: | ||
56 | * | ||
57 | * - The `daddi' instruction fails to trap on overflow. | ||
58 | * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", | ||
59 | * erratum #23 | ||
60 | * | ||
61 | * - The `daddiu' instruction can produce an incorrect result. | ||
62 | * "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0", | ||
63 | * erratum #41 | ||
64 | * "MIPS R4000MC Errata, Processor Revision 2.2 and 3.0", erratum | ||
65 | * #15 | ||
66 | * "MIPS R4400PC/SC Errata, Processor Revision 1.0", erratum #7 | ||
67 | * "MIPS R4400MC Errata, Processor Revision 1.0", erratum #5 | ||
68 | */ | ||
69 | #ifdef CONFIG_CPU_DADDI_WORKAROUNDS | ||
70 | #define DADDI_WAR 1 | ||
71 | #else | ||
72 | #define DADDI_WAR 0 | ||
73 | #endif | ||
74 | |||
75 | /* | ||
14 | * Another R4600 erratum. Due to the lack of errata information the exact | 76 | * Another R4600 erratum. Due to the lack of errata information the exact |
15 | * technical details aren't known. I've experimentally found that disabling | 77 | * technical details aren't known. I've experimentally found that disabling |
16 | * interrupts during indexed I-cache flushes seems to be sufficient to deal | 78 | * interrupts during indexed I-cache flushes seems to be sufficient to deal |
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h index 733b4af7f4f1..220d9a781ab9 100644 --- a/include/asm-powerpc/bitops.h +++ b/include/asm-powerpc/bitops.h | |||
@@ -359,6 +359,8 @@ static __inline__ int test_le_bit(unsigned long nr, | |||
359 | unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, | 359 | unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, |
360 | unsigned long size, unsigned long offset); | 360 | unsigned long size, unsigned long offset); |
361 | 361 | ||
362 | unsigned long generic_find_next_le_bit(const unsigned long *addr, | ||
363 | unsigned long size, unsigned long offset); | ||
362 | /* Bitmap functions for the ext2 filesystem */ | 364 | /* Bitmap functions for the ext2 filesystem */ |
363 | 365 | ||
364 | #define ext2_set_bit(nr,addr) \ | 366 | #define ext2_set_bit(nr,addr) \ |
@@ -378,6 +380,8 @@ unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, | |||
378 | #define ext2_find_next_zero_bit(addr, size, off) \ | 380 | #define ext2_find_next_zero_bit(addr, size, off) \ |
379 | generic_find_next_zero_le_bit((unsigned long*)addr, size, off) | 381 | generic_find_next_zero_le_bit((unsigned long*)addr, size, off) |
380 | 382 | ||
383 | #define ext2_find_next_bit(addr, size, off) \ | ||
384 | generic_find_next_le_bit((unsigned long *)addr, size, off) | ||
381 | /* Bitmap functions for the minix filesystem. */ | 385 | /* Bitmap functions for the minix filesystem. */ |
382 | 386 | ||
383 | #define minix_test_and_set_bit(nr,addr) \ | 387 | #define minix_test_and_set_bit(nr,addr) \ |
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h index 34d9a6357c38..dba6fecad0be 100644 --- a/include/asm-s390/bitops.h +++ b/include/asm-s390/bitops.h | |||
@@ -772,6 +772,8 @@ static inline int sched_find_first_bit(unsigned long *b) | |||
772 | test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) | 772 | test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) |
773 | #define ext2_test_bit(nr, addr) \ | 773 | #define ext2_test_bit(nr, addr) \ |
774 | test_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) | 774 | test_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) |
775 | #define ext2_find_next_bit(addr, size, off) \ | ||
776 | generic_find_next_le_bit((unsigned long *)(addr), (size), (off)) | ||
775 | 777 | ||
776 | #ifndef __s390x__ | 778 | #ifndef __s390x__ |
777 | 779 | ||
diff --git a/include/asm-sh/machvec.h b/include/asm-sh/machvec.h index ddb18ad23303..b2e4124070ae 100644 --- a/include/asm-sh/machvec.h +++ b/include/asm-sh/machvec.h | |||
@@ -65,6 +65,6 @@ extern struct sh_machine_vector sh_mv; | |||
65 | #define get_system_type() sh_mv.mv_name | 65 | #define get_system_type() sh_mv.mv_name |
66 | 66 | ||
67 | #define __initmv \ | 67 | #define __initmv \ |
68 | __attribute_used__ __attribute__((__section__ (".machvec.init"))) | 68 | __used __section(.machvec.init) |
69 | 69 | ||
70 | #endif /* _ASM_SH_MACHVEC_H */ | 70 | #endif /* _ASM_SH_MACHVEC_H */ |
diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h index c6577d3dc46d..c50e5d35fe84 100644 --- a/include/asm-sh/thread_info.h +++ b/include/asm-sh/thread_info.h | |||
@@ -68,7 +68,7 @@ struct thread_info { | |||
68 | #define init_stack (init_thread_union.stack) | 68 | #define init_stack (init_thread_union.stack) |
69 | 69 | ||
70 | /* how to get the current stack pointer from C */ | 70 | /* how to get the current stack pointer from C */ |
71 | register unsigned long current_stack_pointer asm("r15") __attribute_used__; | 71 | register unsigned long current_stack_pointer asm("r15") __used; |
72 | 72 | ||
73 | /* how to get the thread information struct from C */ | 73 | /* how to get the thread information struct from C */ |
74 | static inline struct thread_info *current_thread_info(void) | 74 | static inline struct thread_info *current_thread_info(void) |
diff --git a/include/asm-x86/thread_info_32.h b/include/asm-x86/thread_info_32.h index ef58fd2a6eb0..a516e9192f11 100644 --- a/include/asm-x86/thread_info_32.h +++ b/include/asm-x86/thread_info_32.h | |||
@@ -85,7 +85,7 @@ struct thread_info { | |||
85 | 85 | ||
86 | 86 | ||
87 | /* how to get the current stack pointer from C */ | 87 | /* how to get the current stack pointer from C */ |
88 | register unsigned long current_stack_pointer asm("esp") __attribute_used__; | 88 | register unsigned long current_stack_pointer asm("esp") __used; |
89 | 89 | ||
90 | /* how to get the thread information struct from C */ | 90 | /* how to get the thread information struct from C */ |
91 | static inline struct thread_info *current_thread_info(void) | 91 | static inline struct thread_info *current_thread_info(void) |
diff --git a/include/linux/Kbuild b/include/linux/Kbuild index bc33a5c87d64..27b9350052b4 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild | |||
@@ -35,7 +35,6 @@ header-y += atmsap.h | |||
35 | header-y += atmsvc.h | 35 | header-y += atmsvc.h |
36 | header-y += atm_zatm.h | 36 | header-y += atm_zatm.h |
37 | header-y += auto_fs4.h | 37 | header-y += auto_fs4.h |
38 | header-y += auxvec.h | ||
39 | header-y += ax25.h | 38 | header-y += ax25.h |
40 | header-y += b1lli.h | 39 | header-y += b1lli.h |
41 | header-y += baycom.h | 40 | header-y += baycom.h |
@@ -75,7 +74,7 @@ header-y += gen_stats.h | |||
75 | header-y += gigaset_dev.h | 74 | header-y += gigaset_dev.h |
76 | header-y += hdsmart.h | 75 | header-y += hdsmart.h |
77 | header-y += hysdn_if.h | 76 | header-y += hysdn_if.h |
78 | header-y += i2c-dev.h | 77 | header-y += i2o-dev.h |
79 | header-y += i8k.h | 78 | header-y += i8k.h |
80 | header-y += if_arcnet.h | 79 | header-y += if_arcnet.h |
81 | header-y += if_bonding.h | 80 | header-y += if_bonding.h |
@@ -160,7 +159,6 @@ header-y += veth.h | |||
160 | header-y += video_decoder.h | 159 | header-y += video_decoder.h |
161 | header-y += video_encoder.h | 160 | header-y += video_encoder.h |
162 | header-y += videotext.h | 161 | header-y += videotext.h |
163 | header-y += vt.h | ||
164 | header-y += x25.h | 162 | header-y += x25.h |
165 | 163 | ||
166 | unifdef-y += acct.h | 164 | unifdef-y += acct.h |
@@ -175,6 +173,7 @@ unifdef-y += atm.h | |||
175 | unifdef-y += atm_tcp.h | 173 | unifdef-y += atm_tcp.h |
176 | unifdef-y += audit.h | 174 | unifdef-y += audit.h |
177 | unifdef-y += auto_fs.h | 175 | unifdef-y += auto_fs.h |
176 | unifdef-y += auxvec.h | ||
178 | unifdef-y += binfmts.h | 177 | unifdef-y += binfmts.h |
179 | unifdef-y += capability.h | 178 | unifdef-y += capability.h |
180 | unifdef-y += capi.h | 179 | unifdef-y += capi.h |
@@ -216,7 +215,7 @@ unifdef-y += hdreg.h | |||
216 | unifdef-y += hiddev.h | 215 | unifdef-y += hiddev.h |
217 | unifdef-y += hpet.h | 216 | unifdef-y += hpet.h |
218 | unifdef-y += i2c.h | 217 | unifdef-y += i2c.h |
219 | unifdef-y += i2o-dev.h | 218 | unifdef-y += i2c-dev.h |
220 | unifdef-y += icmp.h | 219 | unifdef-y += icmp.h |
221 | unifdef-y += icmpv6.h | 220 | unifdef-y += icmpv6.h |
222 | unifdef-y += if_addr.h | 221 | unifdef-y += if_addr.h |
@@ -350,6 +349,7 @@ unifdef-y += videodev.h | |||
350 | unifdef-y += virtio_config.h | 349 | unifdef-y += virtio_config.h |
351 | unifdef-y += virtio_blk.h | 350 | unifdef-y += virtio_blk.h |
352 | unifdef-y += virtio_net.h | 351 | unifdef-y += virtio_net.h |
352 | unifdef-y += vt.h | ||
353 | unifdef-y += wait.h | 353 | unifdef-y += wait.h |
354 | unifdef-y += wanrouter.h | 354 | unifdef-y += wanrouter.h |
355 | unifdef-y += watchdog.h | 355 | unifdef-y += watchdog.h |
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index da0d83fbadc0..e98801f06dcc 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h | |||
@@ -192,6 +192,8 @@ int sync_dirty_buffer(struct buffer_head *bh); | |||
192 | int submit_bh(int, struct buffer_head *); | 192 | int submit_bh(int, struct buffer_head *); |
193 | void write_boundary_block(struct block_device *bdev, | 193 | void write_boundary_block(struct block_device *bdev, |
194 | sector_t bblock, unsigned blocksize); | 194 | sector_t bblock, unsigned blocksize); |
195 | int bh_uptodate_or_lock(struct buffer_head *bh); | ||
196 | int bh_submit_read(struct buffer_head *bh); | ||
195 | 197 | ||
196 | extern int buffer_heads_over_limit; | 198 | extern int buffer_heads_over_limit; |
197 | 199 | ||
diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h index 2d8c0f48f55e..e5eb795f78a1 100644 --- a/include/linux/compiler-gcc3.h +++ b/include/linux/compiler-gcc3.h | |||
@@ -7,10 +7,8 @@ | |||
7 | 7 | ||
8 | #if __GNUC_MINOR__ >= 3 | 8 | #if __GNUC_MINOR__ >= 3 |
9 | # define __used __attribute__((__used__)) | 9 | # define __used __attribute__((__used__)) |
10 | # define __attribute_used__ __used /* deprecated */ | ||
11 | #else | 10 | #else |
12 | # define __used __attribute__((__unused__)) | 11 | # define __used __attribute__((__unused__)) |
13 | # define __attribute_used__ __used /* deprecated */ | ||
14 | #endif | 12 | #endif |
15 | 13 | ||
16 | #if __GNUC_MINOR__ >= 4 | 14 | #if __GNUC_MINOR__ >= 4 |
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index ee7ca5de970c..0ab3a3232330 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h | |||
@@ -15,7 +15,6 @@ | |||
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | #define __used __attribute__((__used__)) | 17 | #define __used __attribute__((__used__)) |
18 | #define __attribute_used__ __used /* deprecated */ | ||
19 | #define __must_check __attribute__((warn_unused_result)) | 18 | #define __must_check __attribute__((warn_unused_result)) |
20 | #define __compiler_offsetof(a,b) __builtin_offsetof(a,b) | 19 | #define __compiler_offsetof(a,b) __builtin_offsetof(a,b) |
21 | #define __always_inline inline __attribute__((always_inline)) | 20 | #define __always_inline inline __attribute__((always_inline)) |
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index c68b67b86ef1..d0e17e1657dc 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h | |||
@@ -126,10 +126,6 @@ extern void __chk_io_ptr(const volatile void __iomem *); | |||
126 | * Mark functions that are referenced only in inline assembly as __used so | 126 | * Mark functions that are referenced only in inline assembly as __used so |
127 | * the code is emitted even though it appears to be unreferenced. | 127 | * the code is emitted even though it appears to be unreferenced. |
128 | */ | 128 | */ |
129 | #ifndef __attribute_used__ | ||
130 | # define __attribute_used__ /* deprecated */ | ||
131 | #endif | ||
132 | |||
133 | #ifndef __used | 129 | #ifndef __used |
134 | # define __used /* unimplemented */ | 130 | # define __used /* unimplemented */ |
135 | #endif | 131 | #endif |
@@ -175,4 +171,9 @@ extern void __chk_io_ptr(const volatile void __iomem *); | |||
175 | #define __cold | 171 | #define __cold |
176 | #endif | 172 | #endif |
177 | 173 | ||
174 | /* Simple shorthand for a section definition */ | ||
175 | #ifndef __section | ||
176 | # define __section(S) __attribute__ ((__section__(#S))) | ||
177 | #endif | ||
178 | |||
178 | #endif /* __LINUX_COMPILER_H */ | 179 | #endif /* __LINUX_COMPILER_H */ |
diff --git a/include/linux/elfnote.h b/include/linux/elfnote.h index e831759b2fb5..278e3ef05336 100644 --- a/include/linux/elfnote.h +++ b/include/linux/elfnote.h | |||
@@ -76,7 +76,7 @@ | |||
76 | typeof(desc) _desc \ | 76 | typeof(desc) _desc \ |
77 | __attribute__((aligned(sizeof(Elf##size##_Word)))); \ | 77 | __attribute__((aligned(sizeof(Elf##size##_Word)))); \ |
78 | } _ELFNOTE_PASTE(_note_, unique) \ | 78 | } _ELFNOTE_PASTE(_note_, unique) \ |
79 | __attribute_used__ \ | 79 | __used \ |
80 | __attribute__((section(".note." name), \ | 80 | __attribute__((section(".note." name), \ |
81 | aligned(sizeof(Elf##size##_Word)), \ | 81 | aligned(sizeof(Elf##size##_Word)), \ |
82 | unused)) = { \ | 82 | unused)) = { \ |
diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h index 97dd409d5f4a..1852313fc7c7 100644 --- a/include/linux/ext4_fs.h +++ b/include/linux/ext4_fs.h | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/blkdev.h> | 20 | #include <linux/blkdev.h> |
21 | #include <linux/magic.h> | 21 | #include <linux/magic.h> |
22 | 22 | ||
23 | #include <linux/ext4_fs_i.h> | ||
24 | |||
23 | /* | 25 | /* |
24 | * The second extended filesystem constants/structures | 26 | * The second extended filesystem constants/structures |
25 | */ | 27 | */ |
@@ -51,6 +53,50 @@ | |||
51 | #define ext4_debug(f, a...) do {} while (0) | 53 | #define ext4_debug(f, a...) do {} while (0) |
52 | #endif | 54 | #endif |
53 | 55 | ||
56 | #define EXT4_MULTIBLOCK_ALLOCATOR 1 | ||
57 | |||
58 | /* prefer goal again. length */ | ||
59 | #define EXT4_MB_HINT_MERGE 1 | ||
60 | /* blocks already reserved */ | ||
61 | #define EXT4_MB_HINT_RESERVED 2 | ||
62 | /* metadata is being allocated */ | ||
63 | #define EXT4_MB_HINT_METADATA 4 | ||
64 | /* first blocks in the file */ | ||
65 | #define EXT4_MB_HINT_FIRST 8 | ||
66 | /* search for the best chunk */ | ||
67 | #define EXT4_MB_HINT_BEST 16 | ||
68 | /* data is being allocated */ | ||
69 | #define EXT4_MB_HINT_DATA 32 | ||
70 | /* don't preallocate (for tails) */ | ||
71 | #define EXT4_MB_HINT_NOPREALLOC 64 | ||
72 | /* allocate for locality group */ | ||
73 | #define EXT4_MB_HINT_GROUP_ALLOC 128 | ||
74 | /* allocate goal blocks or none */ | ||
75 | #define EXT4_MB_HINT_GOAL_ONLY 256 | ||
76 | /* goal is meaningful */ | ||
77 | #define EXT4_MB_HINT_TRY_GOAL 512 | ||
78 | |||
79 | struct ext4_allocation_request { | ||
80 | /* target inode for block we're allocating */ | ||
81 | struct inode *inode; | ||
82 | /* logical block in target inode */ | ||
83 | ext4_lblk_t logical; | ||
84 | /* phys. target (a hint) */ | ||
85 | ext4_fsblk_t goal; | ||
86 | /* the closest logical allocated block to the left */ | ||
87 | ext4_lblk_t lleft; | ||
88 | /* phys. block for ^^^ */ | ||
89 | ext4_fsblk_t pleft; | ||
90 | /* the closest logical allocated block to the right */ | ||
91 | ext4_lblk_t lright; | ||
92 | /* phys. block for ^^^ */ | ||
93 | ext4_fsblk_t pright; | ||
94 | /* how many blocks we want to allocate */ | ||
95 | unsigned long len; | ||
96 | /* flags. see above EXT4_MB_HINT_* */ | ||
97 | unsigned long flags; | ||
98 | }; | ||
99 | |||
54 | /* | 100 | /* |
55 | * Special inodes numbers | 101 | * Special inodes numbers |
56 | */ | 102 | */ |
@@ -73,8 +119,8 @@ | |||
73 | * Macro-instructions used to manage several block sizes | 119 | * Macro-instructions used to manage several block sizes |
74 | */ | 120 | */ |
75 | #define EXT4_MIN_BLOCK_SIZE 1024 | 121 | #define EXT4_MIN_BLOCK_SIZE 1024 |
76 | #define EXT4_MAX_BLOCK_SIZE 4096 | 122 | #define EXT4_MAX_BLOCK_SIZE 65536 |
77 | #define EXT4_MIN_BLOCK_LOG_SIZE 10 | 123 | #define EXT4_MIN_BLOCK_LOG_SIZE 10 |
78 | #ifdef __KERNEL__ | 124 | #ifdef __KERNEL__ |
79 | # define EXT4_BLOCK_SIZE(s) ((s)->s_blocksize) | 125 | # define EXT4_BLOCK_SIZE(s) ((s)->s_blocksize) |
80 | #else | 126 | #else |
@@ -118,6 +164,11 @@ struct ext4_group_desc | |||
118 | __le32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */ | 164 | __le32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */ |
119 | __le32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */ | 165 | __le32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */ |
120 | __le32 bg_inode_table_hi; /* Inodes table block MSB */ | 166 | __le32 bg_inode_table_hi; /* Inodes table block MSB */ |
167 | __le16 bg_free_blocks_count_hi;/* Free blocks count MSB */ | ||
168 | __le16 bg_free_inodes_count_hi;/* Free inodes count MSB */ | ||
169 | __le16 bg_used_dirs_count_hi; /* Directories count MSB */ | ||
170 | __le16 bg_itable_unused_hi; /* Unused inodes count MSB */ | ||
171 | __u32 bg_reserved2[3]; | ||
121 | }; | 172 | }; |
122 | 173 | ||
123 | #define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */ | 174 | #define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */ |
@@ -178,8 +229,9 @@ struct ext4_group_desc | |||
178 | #define EXT4_NOTAIL_FL 0x00008000 /* file tail should not be merged */ | 229 | #define EXT4_NOTAIL_FL 0x00008000 /* file tail should not be merged */ |
179 | #define EXT4_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */ | 230 | #define EXT4_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */ |
180 | #define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ | 231 | #define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ |
181 | #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ | 232 | #define EXT4_HUGE_FILE_FL 0x00040000 /* Set to each huge file */ |
182 | #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ | 233 | #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ |
234 | #define EXT4_RESERVED_FL 0x80000000 /* reserved for ext4 lib */ | ||
183 | 235 | ||
184 | #define EXT4_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */ | 236 | #define EXT4_FL_USER_VISIBLE 0x000BDFFF /* User visible flags */ |
185 | #define EXT4_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */ | 237 | #define EXT4_FL_USER_MODIFIABLE 0x000380FF /* User modifiable flags */ |
@@ -237,6 +289,7 @@ struct ext4_new_group_data { | |||
237 | #endif | 289 | #endif |
238 | #define EXT4_IOC_GETRSVSZ _IOR('f', 5, long) | 290 | #define EXT4_IOC_GETRSVSZ _IOR('f', 5, long) |
239 | #define EXT4_IOC_SETRSVSZ _IOW('f', 6, long) | 291 | #define EXT4_IOC_SETRSVSZ _IOW('f', 6, long) |
292 | #define EXT4_IOC_MIGRATE _IO('f', 7) | ||
240 | 293 | ||
241 | /* | 294 | /* |
242 | * ioctl commands in 32 bit emulation | 295 | * ioctl commands in 32 bit emulation |
@@ -275,18 +328,18 @@ struct ext4_mount_options { | |||
275 | struct ext4_inode { | 328 | struct ext4_inode { |
276 | __le16 i_mode; /* File mode */ | 329 | __le16 i_mode; /* File mode */ |
277 | __le16 i_uid; /* Low 16 bits of Owner Uid */ | 330 | __le16 i_uid; /* Low 16 bits of Owner Uid */ |
278 | __le32 i_size; /* Size in bytes */ | 331 | __le32 i_size_lo; /* Size in bytes */ |
279 | __le32 i_atime; /* Access time */ | 332 | __le32 i_atime; /* Access time */ |
280 | __le32 i_ctime; /* Inode Change time */ | 333 | __le32 i_ctime; /* Inode Change time */ |
281 | __le32 i_mtime; /* Modification time */ | 334 | __le32 i_mtime; /* Modification time */ |
282 | __le32 i_dtime; /* Deletion Time */ | 335 | __le32 i_dtime; /* Deletion Time */ |
283 | __le16 i_gid; /* Low 16 bits of Group Id */ | 336 | __le16 i_gid; /* Low 16 bits of Group Id */ |
284 | __le16 i_links_count; /* Links count */ | 337 | __le16 i_links_count; /* Links count */ |
285 | __le32 i_blocks; /* Blocks count */ | 338 | __le32 i_blocks_lo; /* Blocks count */ |
286 | __le32 i_flags; /* File flags */ | 339 | __le32 i_flags; /* File flags */ |
287 | union { | 340 | union { |
288 | struct { | 341 | struct { |
289 | __u32 l_i_reserved1; | 342 | __le32 l_i_version; |
290 | } linux1; | 343 | } linux1; |
291 | struct { | 344 | struct { |
292 | __u32 h_i_translator; | 345 | __u32 h_i_translator; |
@@ -297,12 +350,12 @@ struct ext4_inode { | |||
297 | } osd1; /* OS dependent 1 */ | 350 | } osd1; /* OS dependent 1 */ |
298 | __le32 i_block[EXT4_N_BLOCKS];/* Pointers to blocks */ | 351 | __le32 i_block[EXT4_N_BLOCKS];/* Pointers to blocks */ |
299 | __le32 i_generation; /* File version (for NFS) */ | 352 | __le32 i_generation; /* File version (for NFS) */ |
300 | __le32 i_file_acl; /* File ACL */ | 353 | __le32 i_file_acl_lo; /* File ACL */ |
301 | __le32 i_dir_acl; /* Directory ACL */ | 354 | __le32 i_size_high; |
302 | __le32 i_obso_faddr; /* Obsoleted fragment address */ | 355 | __le32 i_obso_faddr; /* Obsoleted fragment address */ |
303 | union { | 356 | union { |
304 | struct { | 357 | struct { |
305 | __le16 l_i_reserved1; /* Obsoleted fragment number/size which are removed in ext4 */ | 358 | __le16 l_i_blocks_high; /* were l_i_reserved1 */ |
306 | __le16 l_i_file_acl_high; | 359 | __le16 l_i_file_acl_high; |
307 | __le16 l_i_uid_high; /* these 2 fields */ | 360 | __le16 l_i_uid_high; /* these 2 fields */ |
308 | __le16 l_i_gid_high; /* were reserved2[0] */ | 361 | __le16 l_i_gid_high; /* were reserved2[0] */ |
@@ -328,9 +381,9 @@ struct ext4_inode { | |||
328 | __le32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */ | 381 | __le32 i_atime_extra; /* extra Access time (nsec << 2 | epoch) */ |
329 | __le32 i_crtime; /* File Creation time */ | 382 | __le32 i_crtime; /* File Creation time */ |
330 | __le32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */ | 383 | __le32 i_crtime_extra; /* extra FileCreationtime (nsec << 2 | epoch) */ |
384 | __le32 i_version_hi; /* high 32 bits for 64-bit version */ | ||
331 | }; | 385 | }; |
332 | 386 | ||
333 | #define i_size_high i_dir_acl | ||
334 | 387 | ||
335 | #define EXT4_EPOCH_BITS 2 | 388 | #define EXT4_EPOCH_BITS 2 |
336 | #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1) | 389 | #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1) |
@@ -402,9 +455,12 @@ do { \ | |||
402 | raw_inode->xtime ## _extra); \ | 455 | raw_inode->xtime ## _extra); \ |
403 | } while (0) | 456 | } while (0) |
404 | 457 | ||
458 | #define i_disk_version osd1.linux1.l_i_version | ||
459 | |||
405 | #if defined(__KERNEL__) || defined(__linux__) | 460 | #if defined(__KERNEL__) || defined(__linux__) |
406 | #define i_reserved1 osd1.linux1.l_i_reserved1 | 461 | #define i_reserved1 osd1.linux1.l_i_reserved1 |
407 | #define i_file_acl_high osd2.linux2.l_i_file_acl_high | 462 | #define i_file_acl_high osd2.linux2.l_i_file_acl_high |
463 | #define i_blocks_high osd2.linux2.l_i_blocks_high | ||
408 | #define i_uid_low i_uid | 464 | #define i_uid_low i_uid |
409 | #define i_gid_low i_gid | 465 | #define i_gid_low i_gid |
410 | #define i_uid_high osd2.linux2.l_i_uid_high | 466 | #define i_uid_high osd2.linux2.l_i_uid_high |
@@ -461,7 +517,10 @@ do { \ | |||
461 | #define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */ | 517 | #define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */ |
462 | #define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */ | 518 | #define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */ |
463 | #define EXT4_MOUNT_EXTENTS 0x400000 /* Extents support */ | 519 | #define EXT4_MOUNT_EXTENTS 0x400000 /* Extents support */ |
464 | 520 | #define EXT4_MOUNT_JOURNAL_CHECKSUM 0x800000 /* Journal checksums */ | |
521 | #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ | ||
522 | #define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */ | ||
523 | #define EXT4_MOUNT_MBALLOC 0x4000000 /* Buddy allocation support */ | ||
465 | /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */ | 524 | /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */ |
466 | #ifndef _LINUX_EXT2_FS_H | 525 | #ifndef _LINUX_EXT2_FS_H |
467 | #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt | 526 | #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt |
@@ -481,6 +540,7 @@ do { \ | |||
481 | #define ext4_test_bit ext2_test_bit | 540 | #define ext4_test_bit ext2_test_bit |
482 | #define ext4_find_first_zero_bit ext2_find_first_zero_bit | 541 | #define ext4_find_first_zero_bit ext2_find_first_zero_bit |
483 | #define ext4_find_next_zero_bit ext2_find_next_zero_bit | 542 | #define ext4_find_next_zero_bit ext2_find_next_zero_bit |
543 | #define ext4_find_next_bit ext2_find_next_bit | ||
484 | 544 | ||
485 | /* | 545 | /* |
486 | * Maximal mount counts between two filesystem checks | 546 | * Maximal mount counts between two filesystem checks |
@@ -671,6 +731,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) | |||
671 | #define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 | 731 | #define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 |
672 | #define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 | 732 | #define EXT4_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 |
673 | #define EXT4_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 | 733 | #define EXT4_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 |
734 | #define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008 | ||
674 | #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 | 735 | #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 |
675 | #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 | 736 | #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 |
676 | #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 | 737 | #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 |
@@ -682,6 +743,7 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) | |||
682 | #define EXT4_FEATURE_INCOMPAT_META_BG 0x0010 | 743 | #define EXT4_FEATURE_INCOMPAT_META_BG 0x0010 |
683 | #define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ | 744 | #define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ |
684 | #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 | 745 | #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 |
746 | #define EXT4_FEATURE_INCOMPAT_MMP 0x0100 | ||
685 | #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 | 747 | #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 |
686 | 748 | ||
687 | #define EXT4_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR | 749 | #define EXT4_FEATURE_COMPAT_SUPP EXT2_FEATURE_COMPAT_EXT_ATTR |
@@ -696,7 +758,8 @@ static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) | |||
696 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \ | 758 | EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \ |
697 | EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \ | 759 | EXT4_FEATURE_RO_COMPAT_DIR_NLINK | \ |
698 | EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \ | 760 | EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE | \ |
699 | EXT4_FEATURE_RO_COMPAT_BTREE_DIR) | 761 | EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\ |
762 | EXT4_FEATURE_RO_COMPAT_HUGE_FILE) | ||
700 | 763 | ||
701 | /* | 764 | /* |
702 | * Default values for user and/or group using reserved blocks | 765 | * Default values for user and/or group using reserved blocks |
@@ -767,6 +830,26 @@ struct ext4_dir_entry_2 { | |||
767 | #define EXT4_DIR_ROUND (EXT4_DIR_PAD - 1) | 830 | #define EXT4_DIR_ROUND (EXT4_DIR_PAD - 1) |
768 | #define EXT4_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT4_DIR_ROUND) & \ | 831 | #define EXT4_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT4_DIR_ROUND) & \ |
769 | ~EXT4_DIR_ROUND) | 832 | ~EXT4_DIR_ROUND) |
833 | #define EXT4_MAX_REC_LEN ((1<<16)-1) | ||
834 | |||
835 | static inline unsigned ext4_rec_len_from_disk(__le16 dlen) | ||
836 | { | ||
837 | unsigned len = le16_to_cpu(dlen); | ||
838 | |||
839 | if (len == EXT4_MAX_REC_LEN) | ||
840 | return 1 << 16; | ||
841 | return len; | ||
842 | } | ||
843 | |||
844 | static inline __le16 ext4_rec_len_to_disk(unsigned len) | ||
845 | { | ||
846 | if (len == (1 << 16)) | ||
847 | return cpu_to_le16(EXT4_MAX_REC_LEN); | ||
848 | else if (len > (1 << 16)) | ||
849 | BUG(); | ||
850 | return cpu_to_le16(len); | ||
851 | } | ||
852 | |||
770 | /* | 853 | /* |
771 | * Hash Tree Directory indexing | 854 | * Hash Tree Directory indexing |
772 | * (c) Daniel Phillips, 2001 | 855 | * (c) Daniel Phillips, 2001 |
@@ -810,7 +893,7 @@ struct ext4_iloc | |||
810 | { | 893 | { |
811 | struct buffer_head *bh; | 894 | struct buffer_head *bh; |
812 | unsigned long offset; | 895 | unsigned long offset; |
813 | unsigned long block_group; | 896 | ext4_group_t block_group; |
814 | }; | 897 | }; |
815 | 898 | ||
816 | static inline struct ext4_inode *ext4_raw_inode(struct ext4_iloc *iloc) | 899 | static inline struct ext4_inode *ext4_raw_inode(struct ext4_iloc *iloc) |
@@ -835,7 +918,7 @@ struct dir_private_info { | |||
835 | 918 | ||
836 | /* calculate the first block number of the group */ | 919 | /* calculate the first block number of the group */ |
837 | static inline ext4_fsblk_t | 920 | static inline ext4_fsblk_t |
838 | ext4_group_first_block_no(struct super_block *sb, unsigned long group_no) | 921 | ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no) |
839 | { | 922 | { |
840 | return group_no * (ext4_fsblk_t)EXT4_BLOCKS_PER_GROUP(sb) + | 923 | return group_no * (ext4_fsblk_t)EXT4_BLOCKS_PER_GROUP(sb) + |
841 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); | 924 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); |
@@ -866,21 +949,24 @@ extern unsigned int ext4_block_group(struct super_block *sb, | |||
866 | ext4_fsblk_t blocknr); | 949 | ext4_fsblk_t blocknr); |
867 | extern ext4_grpblk_t ext4_block_group_offset(struct super_block *sb, | 950 | extern ext4_grpblk_t ext4_block_group_offset(struct super_block *sb, |
868 | ext4_fsblk_t blocknr); | 951 | ext4_fsblk_t blocknr); |
869 | extern int ext4_bg_has_super(struct super_block *sb, int group); | 952 | extern int ext4_bg_has_super(struct super_block *sb, ext4_group_t group); |
870 | extern unsigned long ext4_bg_num_gdb(struct super_block *sb, int group); | 953 | extern unsigned long ext4_bg_num_gdb(struct super_block *sb, |
954 | ext4_group_t group); | ||
871 | extern ext4_fsblk_t ext4_new_block (handle_t *handle, struct inode *inode, | 955 | extern ext4_fsblk_t ext4_new_block (handle_t *handle, struct inode *inode, |
872 | ext4_fsblk_t goal, int *errp); | 956 | ext4_fsblk_t goal, int *errp); |
873 | extern ext4_fsblk_t ext4_new_blocks (handle_t *handle, struct inode *inode, | 957 | extern ext4_fsblk_t ext4_new_blocks (handle_t *handle, struct inode *inode, |
874 | ext4_fsblk_t goal, unsigned long *count, int *errp); | 958 | ext4_fsblk_t goal, unsigned long *count, int *errp); |
959 | extern ext4_fsblk_t ext4_new_blocks_old(handle_t *handle, struct inode *inode, | ||
960 | ext4_fsblk_t goal, unsigned long *count, int *errp); | ||
875 | extern void ext4_free_blocks (handle_t *handle, struct inode *inode, | 961 | extern void ext4_free_blocks (handle_t *handle, struct inode *inode, |
876 | ext4_fsblk_t block, unsigned long count); | 962 | ext4_fsblk_t block, unsigned long count, int metadata); |
877 | extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb, | 963 | extern void ext4_free_blocks_sb (handle_t *handle, struct super_block *sb, |
878 | ext4_fsblk_t block, unsigned long count, | 964 | ext4_fsblk_t block, unsigned long count, |
879 | unsigned long *pdquot_freed_blocks); | 965 | unsigned long *pdquot_freed_blocks); |
880 | extern ext4_fsblk_t ext4_count_free_blocks (struct super_block *); | 966 | extern ext4_fsblk_t ext4_count_free_blocks (struct super_block *); |
881 | extern void ext4_check_blocks_bitmap (struct super_block *); | 967 | extern void ext4_check_blocks_bitmap (struct super_block *); |
882 | extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, | 968 | extern struct ext4_group_desc * ext4_get_group_desc(struct super_block * sb, |
883 | unsigned int block_group, | 969 | ext4_group_t block_group, |
884 | struct buffer_head ** bh); | 970 | struct buffer_head ** bh); |
885 | extern int ext4_should_retry_alloc(struct super_block *sb, int *retries); | 971 | extern int ext4_should_retry_alloc(struct super_block *sb, int *retries); |
886 | extern void ext4_init_block_alloc_info(struct inode *); | 972 | extern void ext4_init_block_alloc_info(struct inode *); |
@@ -911,15 +997,32 @@ extern unsigned long ext4_count_dirs (struct super_block *); | |||
911 | extern void ext4_check_inodes_bitmap (struct super_block *); | 997 | extern void ext4_check_inodes_bitmap (struct super_block *); |
912 | extern unsigned long ext4_count_free (struct buffer_head *, unsigned); | 998 | extern unsigned long ext4_count_free (struct buffer_head *, unsigned); |
913 | 999 | ||
1000 | /* mballoc.c */ | ||
1001 | extern long ext4_mb_stats; | ||
1002 | extern long ext4_mb_max_to_scan; | ||
1003 | extern int ext4_mb_init(struct super_block *, int); | ||
1004 | extern int ext4_mb_release(struct super_block *); | ||
1005 | extern ext4_fsblk_t ext4_mb_new_blocks(handle_t *, | ||
1006 | struct ext4_allocation_request *, int *); | ||
1007 | extern int ext4_mb_reserve_blocks(struct super_block *, int); | ||
1008 | extern void ext4_mb_discard_inode_preallocations(struct inode *); | ||
1009 | extern int __init init_ext4_mballoc(void); | ||
1010 | extern void exit_ext4_mballoc(void); | ||
1011 | extern void ext4_mb_free_blocks(handle_t *, struct inode *, | ||
1012 | unsigned long, unsigned long, int, unsigned long *); | ||
1013 | |||
914 | 1014 | ||
915 | /* inode.c */ | 1015 | /* inode.c */ |
916 | int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, | 1016 | int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode, |
917 | struct buffer_head *bh, ext4_fsblk_t blocknr); | 1017 | struct buffer_head *bh, ext4_fsblk_t blocknr); |
918 | struct buffer_head * ext4_getblk (handle_t *, struct inode *, long, int, int *); | 1018 | struct buffer_head *ext4_getblk(handle_t *, struct inode *, |
919 | struct buffer_head * ext4_bread (handle_t *, struct inode *, int, int, int *); | 1019 | ext4_lblk_t, int, int *); |
1020 | struct buffer_head *ext4_bread(handle_t *, struct inode *, | ||
1021 | ext4_lblk_t, int, int *); | ||
920 | int ext4_get_blocks_handle(handle_t *handle, struct inode *inode, | 1022 | int ext4_get_blocks_handle(handle_t *handle, struct inode *inode, |
921 | sector_t iblock, unsigned long maxblocks, struct buffer_head *bh_result, | 1023 | ext4_lblk_t iblock, unsigned long maxblocks, |
922 | int create, int extend_disksize); | 1024 | struct buffer_head *bh_result, |
1025 | int create, int extend_disksize); | ||
923 | 1026 | ||
924 | extern void ext4_read_inode (struct inode *); | 1027 | extern void ext4_read_inode (struct inode *); |
925 | extern int ext4_write_inode (struct inode *, int); | 1028 | extern int ext4_write_inode (struct inode *, int); |
@@ -943,6 +1046,9 @@ extern int ext4_ioctl (struct inode *, struct file *, unsigned int, | |||
943 | unsigned long); | 1046 | unsigned long); |
944 | extern long ext4_compat_ioctl (struct file *, unsigned int, unsigned long); | 1047 | extern long ext4_compat_ioctl (struct file *, unsigned int, unsigned long); |
945 | 1048 | ||
1049 | /* migrate.c */ | ||
1050 | extern int ext4_ext_migrate(struct inode *, struct file *, unsigned int, | ||
1051 | unsigned long); | ||
946 | /* namei.c */ | 1052 | /* namei.c */ |
947 | extern int ext4_orphan_add(handle_t *, struct inode *); | 1053 | extern int ext4_orphan_add(handle_t *, struct inode *); |
948 | extern int ext4_orphan_del(handle_t *, struct inode *); | 1054 | extern int ext4_orphan_del(handle_t *, struct inode *); |
@@ -965,6 +1071,12 @@ extern void ext4_abort (struct super_block *, const char *, const char *, ...) | |||
965 | extern void ext4_warning (struct super_block *, const char *, const char *, ...) | 1071 | extern void ext4_warning (struct super_block *, const char *, const char *, ...) |
966 | __attribute__ ((format (printf, 3, 4))); | 1072 | __attribute__ ((format (printf, 3, 4))); |
967 | extern void ext4_update_dynamic_rev (struct super_block *sb); | 1073 | extern void ext4_update_dynamic_rev (struct super_block *sb); |
1074 | extern int ext4_update_compat_feature(handle_t *handle, struct super_block *sb, | ||
1075 | __u32 compat); | ||
1076 | extern int ext4_update_rocompat_feature(handle_t *handle, | ||
1077 | struct super_block *sb, __u32 rocompat); | ||
1078 | extern int ext4_update_incompat_feature(handle_t *handle, | ||
1079 | struct super_block *sb, __u32 incompat); | ||
968 | extern ext4_fsblk_t ext4_block_bitmap(struct super_block *sb, | 1080 | extern ext4_fsblk_t ext4_block_bitmap(struct super_block *sb, |
969 | struct ext4_group_desc *bg); | 1081 | struct ext4_group_desc *bg); |
970 | extern ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb, | 1082 | extern ext4_fsblk_t ext4_inode_bitmap(struct super_block *sb, |
@@ -1017,6 +1129,29 @@ static inline void ext4_r_blocks_count_set(struct ext4_super_block *es, | |||
1017 | es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32); | 1129 | es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32); |
1018 | } | 1130 | } |
1019 | 1131 | ||
1132 | static inline loff_t ext4_isize(struct ext4_inode *raw_inode) | ||
1133 | { | ||
1134 | return ((loff_t)le32_to_cpu(raw_inode->i_size_high) << 32) | | ||
1135 | le32_to_cpu(raw_inode->i_size_lo); | ||
1136 | } | ||
1137 | |||
1138 | static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size) | ||
1139 | { | ||
1140 | raw_inode->i_size_lo = cpu_to_le32(i_size); | ||
1141 | raw_inode->i_size_high = cpu_to_le32(i_size >> 32); | ||
1142 | } | ||
1143 | |||
1144 | static inline | ||
1145 | struct ext4_group_info *ext4_get_group_info(struct super_block *sb, | ||
1146 | ext4_group_t group) | ||
1147 | { | ||
1148 | struct ext4_group_info ***grp_info; | ||
1149 | long indexv, indexh; | ||
1150 | grp_info = EXT4_SB(sb)->s_group_info; | ||
1151 | indexv = group >> (EXT4_DESC_PER_BLOCK_BITS(sb)); | ||
1152 | indexh = group & ((EXT4_DESC_PER_BLOCK(sb)) - 1); | ||
1153 | return grp_info[indexv][indexh]; | ||
1154 | } | ||
1020 | 1155 | ||
1021 | 1156 | ||
1022 | #define ext4_std_error(sb, errno) \ | 1157 | #define ext4_std_error(sb, errno) \ |
@@ -1048,7 +1183,7 @@ extern const struct inode_operations ext4_fast_symlink_inode_operations; | |||
1048 | extern int ext4_ext_tree_init(handle_t *handle, struct inode *); | 1183 | extern int ext4_ext_tree_init(handle_t *handle, struct inode *); |
1049 | extern int ext4_ext_writepage_trans_blocks(struct inode *, int); | 1184 | extern int ext4_ext_writepage_trans_blocks(struct inode *, int); |
1050 | extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, | 1185 | extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, |
1051 | ext4_fsblk_t iblock, | 1186 | ext4_lblk_t iblock, |
1052 | unsigned long max_blocks, struct buffer_head *bh_result, | 1187 | unsigned long max_blocks, struct buffer_head *bh_result, |
1053 | int create, int extend_disksize); | 1188 | int create, int extend_disksize); |
1054 | extern void ext4_ext_truncate(struct inode *, struct page *); | 1189 | extern void ext4_ext_truncate(struct inode *, struct page *); |
@@ -1056,19 +1191,10 @@ extern void ext4_ext_init(struct super_block *); | |||
1056 | extern void ext4_ext_release(struct super_block *); | 1191 | extern void ext4_ext_release(struct super_block *); |
1057 | extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset, | 1192 | extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset, |
1058 | loff_t len); | 1193 | loff_t len); |
1059 | static inline int | 1194 | extern int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, |
1060 | ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | 1195 | sector_t block, unsigned long max_blocks, |
1061 | unsigned long max_blocks, struct buffer_head *bh, | 1196 | struct buffer_head *bh, int create, |
1062 | int create, int extend_disksize) | 1197 | int extend_disksize); |
1063 | { | ||
1064 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) | ||
1065 | return ext4_ext_get_blocks(handle, inode, block, max_blocks, | ||
1066 | bh, create, extend_disksize); | ||
1067 | return ext4_get_blocks_handle(handle, inode, block, max_blocks, bh, | ||
1068 | create, extend_disksize); | ||
1069 | } | ||
1070 | |||
1071 | |||
1072 | #endif /* __KERNEL__ */ | 1198 | #endif /* __KERNEL__ */ |
1073 | 1199 | ||
1074 | #endif /* _LINUX_EXT4_FS_H */ | 1200 | #endif /* _LINUX_EXT4_FS_H */ |
diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h index d2045a26195d..697da4bce6c5 100644 --- a/include/linux/ext4_fs_extents.h +++ b/include/linux/ext4_fs_extents.h | |||
@@ -124,20 +124,6 @@ struct ext4_ext_path { | |||
124 | #define EXT4_EXT_CACHE_GAP 1 | 124 | #define EXT4_EXT_CACHE_GAP 1 |
125 | #define EXT4_EXT_CACHE_EXTENT 2 | 125 | #define EXT4_EXT_CACHE_EXTENT 2 |
126 | 126 | ||
127 | /* | ||
128 | * to be called by ext4_ext_walk_space() | ||
129 | * negative retcode - error | ||
130 | * positive retcode - signal for ext4_ext_walk_space(), see below | ||
131 | * callback must return valid extent (passed or newly created) | ||
132 | */ | ||
133 | typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *, | ||
134 | struct ext4_ext_cache *, | ||
135 | void *); | ||
136 | |||
137 | #define EXT_CONTINUE 0 | ||
138 | #define EXT_BREAK 1 | ||
139 | #define EXT_REPEAT 2 | ||
140 | |||
141 | 127 | ||
142 | #define EXT_MAX_BLOCK 0xffffffff | 128 | #define EXT_MAX_BLOCK 0xffffffff |
143 | 129 | ||
@@ -226,6 +212,8 @@ static inline int ext4_ext_get_actual_len(struct ext4_extent *ext) | |||
226 | (le16_to_cpu(ext->ee_len) - EXT_INIT_MAX_LEN)); | 212 | (le16_to_cpu(ext->ee_len) - EXT_INIT_MAX_LEN)); |
227 | } | 213 | } |
228 | 214 | ||
215 | extern ext4_fsblk_t idx_pblock(struct ext4_extent_idx *); | ||
216 | extern void ext4_ext_store_pblock(struct ext4_extent *, ext4_fsblk_t); | ||
229 | extern int ext4_extent_tree_init(handle_t *, struct inode *); | 217 | extern int ext4_extent_tree_init(handle_t *, struct inode *); |
230 | extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *); | 218 | extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *); |
231 | extern int ext4_ext_try_to_merge(struct inode *inode, | 219 | extern int ext4_ext_try_to_merge(struct inode *inode, |
@@ -233,8 +221,11 @@ extern int ext4_ext_try_to_merge(struct inode *inode, | |||
233 | struct ext4_extent *); | 221 | struct ext4_extent *); |
234 | extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *); | 222 | extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *); |
235 | extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *); | 223 | extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *); |
236 | extern int ext4_ext_walk_space(struct inode *, unsigned long, unsigned long, ext_prepare_callback, void *); | 224 | extern struct ext4_ext_path *ext4_ext_find_extent(struct inode *, ext4_lblk_t, |
237 | extern struct ext4_ext_path * ext4_ext_find_extent(struct inode *, int, struct ext4_ext_path *); | 225 | struct ext4_ext_path *); |
238 | 226 | extern int ext4_ext_search_left(struct inode *, struct ext4_ext_path *, | |
227 | ext4_lblk_t *, ext4_fsblk_t *); | ||
228 | extern int ext4_ext_search_right(struct inode *, struct ext4_ext_path *, | ||
229 | ext4_lblk_t *, ext4_fsblk_t *); | ||
239 | #endif /* _LINUX_EXT4_EXTENTS */ | 230 | #endif /* _LINUX_EXT4_EXTENTS */ |
240 | 231 | ||
diff --git a/include/linux/ext4_fs_i.h b/include/linux/ext4_fs_i.h index 86ddfe2089f3..d5508d3cf290 100644 --- a/include/linux/ext4_fs_i.h +++ b/include/linux/ext4_fs_i.h | |||
@@ -27,6 +27,12 @@ typedef int ext4_grpblk_t; | |||
27 | /* data type for filesystem-wide blocks number */ | 27 | /* data type for filesystem-wide blocks number */ |
28 | typedef unsigned long long ext4_fsblk_t; | 28 | typedef unsigned long long ext4_fsblk_t; |
29 | 29 | ||
30 | /* data type for file logical block number */ | ||
31 | typedef __u32 ext4_lblk_t; | ||
32 | |||
33 | /* data type for block group number */ | ||
34 | typedef unsigned long ext4_group_t; | ||
35 | |||
30 | struct ext4_reserve_window { | 36 | struct ext4_reserve_window { |
31 | ext4_fsblk_t _rsv_start; /* First byte reserved */ | 37 | ext4_fsblk_t _rsv_start; /* First byte reserved */ |
32 | ext4_fsblk_t _rsv_end; /* Last byte reserved or 0 */ | 38 | ext4_fsblk_t _rsv_end; /* Last byte reserved or 0 */ |
@@ -48,7 +54,7 @@ struct ext4_block_alloc_info { | |||
48 | * most-recently-allocated block in this file. | 54 | * most-recently-allocated block in this file. |
49 | * We use this for detecting linearly ascending allocation requests. | 55 | * We use this for detecting linearly ascending allocation requests. |
50 | */ | 56 | */ |
51 | __u32 last_alloc_logical_block; | 57 | ext4_lblk_t last_alloc_logical_block; |
52 | /* | 58 | /* |
53 | * Was i_next_alloc_goal in ext4_inode_info | 59 | * Was i_next_alloc_goal in ext4_inode_info |
54 | * is the *physical* companion to i_next_alloc_block. | 60 | * is the *physical* companion to i_next_alloc_block. |
@@ -67,7 +73,7 @@ struct ext4_block_alloc_info { | |||
67 | */ | 73 | */ |
68 | struct ext4_ext_cache { | 74 | struct ext4_ext_cache { |
69 | ext4_fsblk_t ec_start; | 75 | ext4_fsblk_t ec_start; |
70 | __u32 ec_block; | 76 | ext4_lblk_t ec_block; |
71 | __u32 ec_len; /* must be 32bit to return holes */ | 77 | __u32 ec_len; /* must be 32bit to return holes */ |
72 | __u32 ec_type; | 78 | __u32 ec_type; |
73 | }; | 79 | }; |
@@ -79,7 +85,6 @@ struct ext4_inode_info { | |||
79 | __le32 i_data[15]; /* unconverted */ | 85 | __le32 i_data[15]; /* unconverted */ |
80 | __u32 i_flags; | 86 | __u32 i_flags; |
81 | ext4_fsblk_t i_file_acl; | 87 | ext4_fsblk_t i_file_acl; |
82 | __u32 i_dir_acl; | ||
83 | __u32 i_dtime; | 88 | __u32 i_dtime; |
84 | 89 | ||
85 | /* | 90 | /* |
@@ -89,13 +94,13 @@ struct ext4_inode_info { | |||
89 | * place a file's data blocks near its inode block, and new inodes | 94 | * place a file's data blocks near its inode block, and new inodes |
90 | * near to their parent directory's inode. | 95 | * near to their parent directory's inode. |
91 | */ | 96 | */ |
92 | __u32 i_block_group; | 97 | ext4_group_t i_block_group; |
93 | __u32 i_state; /* Dynamic state flags for ext4 */ | 98 | __u32 i_state; /* Dynamic state flags for ext4 */ |
94 | 99 | ||
95 | /* block reservation info */ | 100 | /* block reservation info */ |
96 | struct ext4_block_alloc_info *i_block_alloc_info; | 101 | struct ext4_block_alloc_info *i_block_alloc_info; |
97 | 102 | ||
98 | __u32 i_dir_start_lookup; | 103 | ext4_lblk_t i_dir_start_lookup; |
99 | #ifdef CONFIG_EXT4DEV_FS_XATTR | 104 | #ifdef CONFIG_EXT4DEV_FS_XATTR |
100 | /* | 105 | /* |
101 | * Extended attributes can be read independently of the main file | 106 | * Extended attributes can be read independently of the main file |
@@ -134,16 +139,16 @@ struct ext4_inode_info { | |||
134 | __u16 i_extra_isize; | 139 | __u16 i_extra_isize; |
135 | 140 | ||
136 | /* | 141 | /* |
137 | * truncate_mutex is for serialising ext4_truncate() against | 142 | * i_data_sem is for serialising ext4_truncate() against |
138 | * ext4_getblock(). In the 2.4 ext2 design, great chunks of inode's | 143 | * ext4_getblock(). In the 2.4 ext2 design, great chunks of inode's |
139 | * data tree are chopped off during truncate. We can't do that in | 144 | * data tree are chopped off during truncate. We can't do that in |
140 | * ext4 because whenever we perform intermediate commits during | 145 | * ext4 because whenever we perform intermediate commits during |
141 | * truncate, the inode and all the metadata blocks *must* be in a | 146 | * truncate, the inode and all the metadata blocks *must* be in a |
142 | * consistent state which allows truncation of the orphans to restart | 147 | * consistent state which allows truncation of the orphans to restart |
143 | * during recovery. Hence we must fix the get_block-vs-truncate race | 148 | * during recovery. Hence we must fix the get_block-vs-truncate race |
144 | * by other means, so we have truncate_mutex. | 149 | * by other means, so we have i_data_sem. |
145 | */ | 150 | */ |
146 | struct mutex truncate_mutex; | 151 | struct rw_semaphore i_data_sem; |
147 | struct inode vfs_inode; | 152 | struct inode vfs_inode; |
148 | 153 | ||
149 | unsigned long i_ext_generation; | 154 | unsigned long i_ext_generation; |
@@ -153,6 +158,10 @@ struct ext4_inode_info { | |||
153 | * struct timespec i_{a,c,m}time in the generic inode. | 158 | * struct timespec i_{a,c,m}time in the generic inode. |
154 | */ | 159 | */ |
155 | struct timespec i_crtime; | 160 | struct timespec i_crtime; |
161 | |||
162 | /* mballoc */ | ||
163 | struct list_head i_prealloc_list; | ||
164 | spinlock_t i_prealloc_lock; | ||
156 | }; | 165 | }; |
157 | 166 | ||
158 | #endif /* _LINUX_EXT4_FS_I */ | 167 | #endif /* _LINUX_EXT4_FS_I */ |
diff --git a/include/linux/ext4_fs_sb.h b/include/linux/ext4_fs_sb.h index b40e827cd495..abaae2c8cccf 100644 --- a/include/linux/ext4_fs_sb.h +++ b/include/linux/ext4_fs_sb.h | |||
@@ -35,9 +35,10 @@ struct ext4_sb_info { | |||
35 | unsigned long s_itb_per_group; /* Number of inode table blocks per group */ | 35 | unsigned long s_itb_per_group; /* Number of inode table blocks per group */ |
36 | unsigned long s_gdb_count; /* Number of group descriptor blocks */ | 36 | unsigned long s_gdb_count; /* Number of group descriptor blocks */ |
37 | unsigned long s_desc_per_block; /* Number of group descriptors per block */ | 37 | unsigned long s_desc_per_block; /* Number of group descriptors per block */ |
38 | unsigned long s_groups_count; /* Number of groups in the fs */ | 38 | ext4_group_t s_groups_count; /* Number of groups in the fs */ |
39 | unsigned long s_overhead_last; /* Last calculated overhead */ | 39 | unsigned long s_overhead_last; /* Last calculated overhead */ |
40 | unsigned long s_blocks_last; /* Last seen block count */ | 40 | unsigned long s_blocks_last; /* Last seen block count */ |
41 | loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ | ||
41 | struct buffer_head * s_sbh; /* Buffer containing the super block */ | 42 | struct buffer_head * s_sbh; /* Buffer containing the super block */ |
42 | struct ext4_super_block * s_es; /* Pointer to the super block in the buffer */ | 43 | struct ext4_super_block * s_es; /* Pointer to the super block in the buffer */ |
43 | struct buffer_head ** s_group_desc; | 44 | struct buffer_head ** s_group_desc; |
@@ -90,6 +91,58 @@ struct ext4_sb_info { | |||
90 | unsigned long s_ext_blocks; | 91 | unsigned long s_ext_blocks; |
91 | unsigned long s_ext_extents; | 92 | unsigned long s_ext_extents; |
92 | #endif | 93 | #endif |
94 | |||
95 | /* for buddy allocator */ | ||
96 | struct ext4_group_info ***s_group_info; | ||
97 | struct inode *s_buddy_cache; | ||
98 | long s_blocks_reserved; | ||
99 | spinlock_t s_reserve_lock; | ||
100 | struct list_head s_active_transaction; | ||
101 | struct list_head s_closed_transaction; | ||
102 | struct list_head s_committed_transaction; | ||
103 | spinlock_t s_md_lock; | ||
104 | tid_t s_last_transaction; | ||
105 | unsigned short *s_mb_offsets, *s_mb_maxs; | ||
106 | |||
107 | /* tunables */ | ||
108 | unsigned long s_stripe; | ||
109 | unsigned long s_mb_stream_request; | ||
110 | unsigned long s_mb_max_to_scan; | ||
111 | unsigned long s_mb_min_to_scan; | ||
112 | unsigned long s_mb_stats; | ||
113 | unsigned long s_mb_order2_reqs; | ||
114 | unsigned long s_mb_group_prealloc; | ||
115 | /* where last allocation was done - for stream allocation */ | ||
116 | unsigned long s_mb_last_group; | ||
117 | unsigned long s_mb_last_start; | ||
118 | |||
119 | /* history to debug policy */ | ||
120 | struct ext4_mb_history *s_mb_history; | ||
121 | int s_mb_history_cur; | ||
122 | int s_mb_history_max; | ||
123 | int s_mb_history_num; | ||
124 | struct proc_dir_entry *s_mb_proc; | ||
125 | spinlock_t s_mb_history_lock; | ||
126 | int s_mb_history_filter; | ||
127 | |||
128 | /* stats for buddy allocator */ | ||
129 | spinlock_t s_mb_pa_lock; | ||
130 | atomic_t s_bal_reqs; /* number of reqs with len > 1 */ | ||
131 | atomic_t s_bal_success; /* we found long enough chunks */ | ||
132 | atomic_t s_bal_allocated; /* in blocks */ | ||
133 | atomic_t s_bal_ex_scanned; /* total extents scanned */ | ||
134 | atomic_t s_bal_goals; /* goal hits */ | ||
135 | atomic_t s_bal_breaks; /* too long searches */ | ||
136 | atomic_t s_bal_2orders; /* 2^order hits */ | ||
137 | spinlock_t s_bal_lock; | ||
138 | unsigned long s_mb_buddies_generated; | ||
139 | unsigned long long s_mb_generation_time; | ||
140 | atomic_t s_mb_lost_chunks; | ||
141 | atomic_t s_mb_preallocated; | ||
142 | atomic_t s_mb_discarded; | ||
143 | |||
144 | /* locality groups */ | ||
145 | struct ext4_locality_group *s_locality_groups; | ||
93 | }; | 146 | }; |
94 | 147 | ||
95 | #endif /* _LINUX_EXT4_FS_SB */ | 148 | #endif /* _LINUX_EXT4_FS_SB */ |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 21398a5d688d..a516b6716870 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -124,6 +124,7 @@ extern int dir_notify_enable; | |||
124 | #define MS_SHARED (1<<20) /* change to shared */ | 124 | #define MS_SHARED (1<<20) /* change to shared */ |
125 | #define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */ | 125 | #define MS_RELATIME (1<<21) /* Update atime relative to mtime/ctime. */ |
126 | #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ | 126 | #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ |
127 | #define MS_I_VERSION (1<<23) /* Update inode I_version field */ | ||
127 | #define MS_ACTIVE (1<<30) | 128 | #define MS_ACTIVE (1<<30) |
128 | #define MS_NOUSER (1<<31) | 129 | #define MS_NOUSER (1<<31) |
129 | 130 | ||
@@ -173,6 +174,7 @@ extern int dir_notify_enable; | |||
173 | ((inode)->i_flags & (S_SYNC|S_DIRSYNC))) | 174 | ((inode)->i_flags & (S_SYNC|S_DIRSYNC))) |
174 | #define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK) | 175 | #define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK) |
175 | #define IS_NOATIME(inode) __IS_FLG(inode, MS_RDONLY|MS_NOATIME) | 176 | #define IS_NOATIME(inode) __IS_FLG(inode, MS_RDONLY|MS_NOATIME) |
177 | #define IS_I_VERSION(inode) __IS_FLG(inode, MS_I_VERSION) | ||
176 | 178 | ||
177 | #define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) | 179 | #define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) |
178 | #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) | 180 | #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) |
@@ -599,7 +601,7 @@ struct inode { | |||
599 | uid_t i_uid; | 601 | uid_t i_uid; |
600 | gid_t i_gid; | 602 | gid_t i_gid; |
601 | dev_t i_rdev; | 603 | dev_t i_rdev; |
602 | unsigned long i_version; | 604 | u64 i_version; |
603 | loff_t i_size; | 605 | loff_t i_size; |
604 | #ifdef __NEED_I_SIZE_ORDERED | 606 | #ifdef __NEED_I_SIZE_ORDERED |
605 | seqcount_t i_size_seqcount; | 607 | seqcount_t i_size_seqcount; |
@@ -1394,6 +1396,21 @@ static inline void inode_dec_link_count(struct inode *inode) | |||
1394 | mark_inode_dirty(inode); | 1396 | mark_inode_dirty(inode); |
1395 | } | 1397 | } |
1396 | 1398 | ||
1399 | /** | ||
1400 | * inode_inc_iversion - increments i_version | ||
1401 | * @inode: inode that need to be updated | ||
1402 | * | ||
1403 | * Every time the inode is modified, the i_version field will be incremented. | ||
1404 | * The filesystem has to be mounted with i_version flag | ||
1405 | */ | ||
1406 | |||
1407 | static inline void inode_inc_iversion(struct inode *inode) | ||
1408 | { | ||
1409 | spin_lock(&inode->i_lock); | ||
1410 | inode->i_version++; | ||
1411 | spin_unlock(&inode->i_lock); | ||
1412 | } | ||
1413 | |||
1397 | extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry); | 1414 | extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry); |
1398 | static inline void file_accessed(struct file *file) | 1415 | static inline void file_accessed(struct file *file) |
1399 | { | 1416 | { |
diff --git a/include/linux/init.h b/include/linux/init.h index 5141381a7527..2efbda016741 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
@@ -40,10 +40,10 @@ | |||
40 | 40 | ||
41 | /* These are for everybody (although not all archs will actually | 41 | /* These are for everybody (although not all archs will actually |
42 | discard it in modules) */ | 42 | discard it in modules) */ |
43 | #define __init __attribute__ ((__section__ (".init.text"))) __cold | 43 | #define __init __section(.init.text) __cold |
44 | #define __initdata __attribute__ ((__section__ (".init.data"))) | 44 | #define __initdata __section(.init.data) |
45 | #define __exitdata __attribute__ ((__section__(".exit.data"))) | 45 | #define __exitdata __section(.exit.data) |
46 | #define __exit_call __attribute_used__ __attribute__ ((__section__ (".exitcall.exit"))) | 46 | #define __exit_call __used __section(.exitcall.exit) |
47 | 47 | ||
48 | /* modpost check for section mismatches during the kernel build. | 48 | /* modpost check for section mismatches during the kernel build. |
49 | * A section mismatch happens when there are references from a | 49 | * A section mismatch happens when there are references from a |
@@ -52,25 +52,81 @@ | |||
52 | * when early init has completed so all such references are potential bugs. | 52 | * when early init has completed so all such references are potential bugs. |
53 | * For exit sections the same issue exists. | 53 | * For exit sections the same issue exists. |
54 | * The following markers are used for the cases where the reference to | 54 | * The following markers are used for the cases where the reference to |
55 | * the init/exit section (code or data) is valid and will teach modpost | 55 | * the *init / *exit section (code or data) is valid and will teach |
56 | * not to issue a warning. | 56 | * modpost not to issue a warning. |
57 | * The markers follow same syntax rules as __init / __initdata. */ | 57 | * The markers follow same syntax rules as __init / __initdata. */ |
58 | #define __init_refok noinline __attribute__ ((__section__ (".text.init.refok"))) | 58 | #define __ref __section(.ref.text) noinline |
59 | #define __initdata_refok __attribute__ ((__section__ (".data.init.refok"))) | 59 | #define __refdata __section(.ref.data) |
60 | #define __exit_refok noinline __attribute__ ((__section__ (".exit.text.refok"))) | 60 | #define __refconst __section(.ref.rodata) |
61 | |||
62 | /* backward compatibility note | ||
63 | * A few places hardcode the old section names: | ||
64 | * .text.init.refok | ||
65 | * .data.init.refok | ||
66 | * .exit.text.refok | ||
67 | * They should be converted to use the defines from this file | ||
68 | */ | ||
69 | |||
70 | /* compatibility defines */ | ||
71 | #define __init_refok __ref | ||
72 | #define __initdata_refok __refdata | ||
73 | #define __exit_refok __ref | ||
74 | |||
61 | 75 | ||
62 | #ifdef MODULE | 76 | #ifdef MODULE |
63 | #define __exit __attribute__ ((__section__(".exit.text"))) __cold | 77 | #define __exitused |
64 | #else | 78 | #else |
65 | #define __exit __attribute_used__ __attribute__ ((__section__(".exit.text"))) __cold | 79 | #define __exitused __used |
66 | #endif | 80 | #endif |
67 | 81 | ||
82 | #define __exit __section(.exit.text) __exitused __cold | ||
83 | |||
84 | /* Used for HOTPLUG */ | ||
85 | #define __devinit __section(.devinit.text) __cold | ||
86 | #define __devinitdata __section(.devinit.data) | ||
87 | #define __devinitconst __section(.devinit.rodata) | ||
88 | #define __devexit __section(.devexit.text) __exitused __cold | ||
89 | #define __devexitdata __section(.devexit.data) | ||
90 | #define __devexitconst __section(.devexit.rodata) | ||
91 | |||
92 | /* Used for HOTPLUG_CPU */ | ||
93 | #define __cpuinit __section(.cpuinit.text) __cold | ||
94 | #define __cpuinitdata __section(.cpuinit.data) | ||
95 | #define __cpuinitconst __section(.cpuinit.rodata) | ||
96 | #define __cpuexit __section(.cpuexit.text) __exitused __cold | ||
97 | #define __cpuexitdata __section(.cpuexit.data) | ||
98 | #define __cpuexitconst __section(.cpuexit.rodata) | ||
99 | |||
100 | /* Used for MEMORY_HOTPLUG */ | ||
101 | #define __meminit __section(.meminit.text) __cold | ||
102 | #define __meminitdata __section(.meminit.data) | ||
103 | #define __meminitconst __section(.meminit.rodata) | ||
104 | #define __memexit __section(.memexit.text) __exitused __cold | ||
105 | #define __memexitdata __section(.memexit.data) | ||
106 | #define __memexitconst __section(.memexit.rodata) | ||
107 | |||
68 | /* For assembly routines */ | 108 | /* For assembly routines */ |
69 | #define __INIT .section ".init.text","ax" | 109 | #define __INIT .section ".init.text","ax" |
70 | #define __INIT_REFOK .section ".text.init.refok","ax" | ||
71 | #define __FINIT .previous | 110 | #define __FINIT .previous |
111 | |||
72 | #define __INITDATA .section ".init.data","aw" | 112 | #define __INITDATA .section ".init.data","aw" |
73 | #define __INITDATA_REFOK .section ".data.init.refok","aw" | 113 | |
114 | #define __DEVINIT .section ".devinit.text", "ax" | ||
115 | #define __DEVINITDATA .section ".devinit.data", "aw" | ||
116 | |||
117 | #define __CPUINIT .section ".cpuinit.text", "ax" | ||
118 | #define __CPUINITDATA .section ".cpuinit.data", "aw" | ||
119 | |||
120 | #define __MEMINIT .section ".meminit.text", "ax" | ||
121 | #define __MEMINITDATA .section ".meminit.data", "aw" | ||
122 | |||
123 | /* silence warnings when references are OK */ | ||
124 | #define __REF .section ".ref.text", "ax" | ||
125 | #define __REFDATA .section ".ref.data", "aw" | ||
126 | #define __REFCONST .section ".ref.rodata", "aw" | ||
127 | /* backward compatibility */ | ||
128 | #define __INIT_REFOK .section __REF | ||
129 | #define __INITDATA_REFOK .section __REFDATA | ||
74 | 130 | ||
75 | #ifndef __ASSEMBLY__ | 131 | #ifndef __ASSEMBLY__ |
76 | /* | 132 | /* |
@@ -108,7 +164,7 @@ void prepare_namespace(void); | |||
108 | */ | 164 | */ |
109 | 165 | ||
110 | #define __define_initcall(level,fn,id) \ | 166 | #define __define_initcall(level,fn,id) \ |
111 | static initcall_t __initcall_##fn##id __attribute_used__ \ | 167 | static initcall_t __initcall_##fn##id __used \ |
112 | __attribute__((__section__(".initcall" level ".init"))) = fn | 168 | __attribute__((__section__(".initcall" level ".init"))) = fn |
113 | 169 | ||
114 | /* | 170 | /* |
@@ -142,11 +198,11 @@ void prepare_namespace(void); | |||
142 | 198 | ||
143 | #define console_initcall(fn) \ | 199 | #define console_initcall(fn) \ |
144 | static initcall_t __initcall_##fn \ | 200 | static initcall_t __initcall_##fn \ |
145 | __attribute_used__ __attribute__((__section__(".con_initcall.init")))=fn | 201 | __used __section(.con_initcall.init) = fn |
146 | 202 | ||
147 | #define security_initcall(fn) \ | 203 | #define security_initcall(fn) \ |
148 | static initcall_t __initcall_##fn \ | 204 | static initcall_t __initcall_##fn \ |
149 | __attribute_used__ __attribute__((__section__(".security_initcall.init"))) = fn | 205 | __used __section(.security_initcall.init) = fn |
150 | 206 | ||
151 | struct obs_kernel_param { | 207 | struct obs_kernel_param { |
152 | const char *str; | 208 | const char *str; |
@@ -163,8 +219,7 @@ struct obs_kernel_param { | |||
163 | #define __setup_param(str, unique_id, fn, early) \ | 219 | #define __setup_param(str, unique_id, fn, early) \ |
164 | static char __setup_str_##unique_id[] __initdata __aligned(1) = str; \ | 220 | static char __setup_str_##unique_id[] __initdata __aligned(1) = str; \ |
165 | static struct obs_kernel_param __setup_##unique_id \ | 221 | static struct obs_kernel_param __setup_##unique_id \ |
166 | __attribute_used__ \ | 222 | __used __section(.init.setup) \ |
167 | __attribute__((__section__(".init.setup"))) \ | ||
168 | __attribute__((aligned((sizeof(long))))) \ | 223 | __attribute__((aligned((sizeof(long))))) \ |
169 | = { __setup_str_##unique_id, fn, early } | 224 | = { __setup_str_##unique_id, fn, early } |
170 | 225 | ||
@@ -242,7 +297,7 @@ void __init parse_early_param(void); | |||
242 | #endif | 297 | #endif |
243 | 298 | ||
244 | /* Data marked not to be saved by software suspend */ | 299 | /* Data marked not to be saved by software suspend */ |
245 | #define __nosavedata __attribute__ ((__section__ (".data.nosave"))) | 300 | #define __nosavedata __section(.data.nosave) |
246 | 301 | ||
247 | /* This means "can be init if no module support, otherwise module load | 302 | /* This means "can be init if no module support, otherwise module load |
248 | may call it." */ | 303 | may call it." */ |
@@ -254,43 +309,6 @@ void __init parse_early_param(void); | |||
254 | #define __initdata_or_module __initdata | 309 | #define __initdata_or_module __initdata |
255 | #endif /*CONFIG_MODULES*/ | 310 | #endif /*CONFIG_MODULES*/ |
256 | 311 | ||
257 | #ifdef CONFIG_HOTPLUG | ||
258 | #define __devinit | ||
259 | #define __devinitdata | ||
260 | #define __devexit | ||
261 | #define __devexitdata | ||
262 | #else | ||
263 | #define __devinit __init | ||
264 | #define __devinitdata __initdata | ||
265 | #define __devexit __exit | ||
266 | #define __devexitdata __exitdata | ||
267 | #endif | ||
268 | |||
269 | #ifdef CONFIG_HOTPLUG_CPU | ||
270 | #define __cpuinit | ||
271 | #define __cpuinitdata | ||
272 | #define __cpuexit | ||
273 | #define __cpuexitdata | ||
274 | #else | ||
275 | #define __cpuinit __init | ||
276 | #define __cpuinitdata __initdata | ||
277 | #define __cpuexit __exit | ||
278 | #define __cpuexitdata __exitdata | ||
279 | #endif | ||
280 | |||
281 | #if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \ | ||
282 | || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE) | ||
283 | #define __meminit | ||
284 | #define __meminitdata | ||
285 | #define __memexit | ||
286 | #define __memexitdata | ||
287 | #else | ||
288 | #define __meminit __init | ||
289 | #define __meminitdata __initdata | ||
290 | #define __memexit __exit | ||
291 | #define __memexitdata __exitdata | ||
292 | #endif | ||
293 | |||
294 | /* Functions marked as __devexit may be discarded at kernel link time, depending | 312 | /* Functions marked as __devexit may be discarded at kernel link time, depending |
295 | on config options. Newer versions of binutils detect references from | 313 | on config options. Newer versions of binutils detect references from |
296 | retained sections to discarded sections and flag an error. Pointers to | 314 | retained sections to discarded sections and flag an error. Pointers to |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 06ef11457051..2cbf6fdb1799 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
@@ -149,6 +149,28 @@ typedef struct journal_header_s | |||
149 | __be32 h_sequence; | 149 | __be32 h_sequence; |
150 | } journal_header_t; | 150 | } journal_header_t; |
151 | 151 | ||
152 | /* | ||
153 | * Checksum types. | ||
154 | */ | ||
155 | #define JBD2_CRC32_CHKSUM 1 | ||
156 | #define JBD2_MD5_CHKSUM 2 | ||
157 | #define JBD2_SHA1_CHKSUM 3 | ||
158 | |||
159 | #define JBD2_CRC32_CHKSUM_SIZE 4 | ||
160 | |||
161 | #define JBD2_CHECKSUM_BYTES (32 / sizeof(u32)) | ||
162 | /* | ||
163 | * Commit block header for storing transactional checksums: | ||
164 | */ | ||
165 | struct commit_header { | ||
166 | __be32 h_magic; | ||
167 | __be32 h_blocktype; | ||
168 | __be32 h_sequence; | ||
169 | unsigned char h_chksum_type; | ||
170 | unsigned char h_chksum_size; | ||
171 | unsigned char h_padding[2]; | ||
172 | __be32 h_chksum[JBD2_CHECKSUM_BYTES]; | ||
173 | }; | ||
152 | 174 | ||
153 | /* | 175 | /* |
154 | * The block tag: used to describe a single buffer in the journal. | 176 | * The block tag: used to describe a single buffer in the journal. |
@@ -242,31 +264,25 @@ typedef struct journal_superblock_s | |||
242 | ((j)->j_format_version >= 2 && \ | 264 | ((j)->j_format_version >= 2 && \ |
243 | ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask)))) | 265 | ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask)))) |
244 | 266 | ||
245 | #define JBD2_FEATURE_INCOMPAT_REVOKE 0x00000001 | 267 | #define JBD2_FEATURE_COMPAT_CHECKSUM 0x00000001 |
246 | #define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002 | 268 | |
269 | #define JBD2_FEATURE_INCOMPAT_REVOKE 0x00000001 | ||
270 | #define JBD2_FEATURE_INCOMPAT_64BIT 0x00000002 | ||
271 | #define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT 0x00000004 | ||
247 | 272 | ||
248 | /* Features known to this kernel version: */ | 273 | /* Features known to this kernel version: */ |
249 | #define JBD2_KNOWN_COMPAT_FEATURES 0 | 274 | #define JBD2_KNOWN_COMPAT_FEATURES JBD2_FEATURE_COMPAT_CHECKSUM |
250 | #define JBD2_KNOWN_ROCOMPAT_FEATURES 0 | 275 | #define JBD2_KNOWN_ROCOMPAT_FEATURES 0 |
251 | #define JBD2_KNOWN_INCOMPAT_FEATURES (JBD2_FEATURE_INCOMPAT_REVOKE | \ | 276 | #define JBD2_KNOWN_INCOMPAT_FEATURES (JBD2_FEATURE_INCOMPAT_REVOKE | \ |
252 | JBD2_FEATURE_INCOMPAT_64BIT) | 277 | JBD2_FEATURE_INCOMPAT_64BIT | \ |
278 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) | ||
253 | 279 | ||
254 | #ifdef __KERNEL__ | 280 | #ifdef __KERNEL__ |
255 | 281 | ||
256 | #include <linux/fs.h> | 282 | #include <linux/fs.h> |
257 | #include <linux/sched.h> | 283 | #include <linux/sched.h> |
258 | 284 | ||
259 | #define JBD2_ASSERTIONS | 285 | #define J_ASSERT(assert) BUG_ON(!(assert)) |
260 | #ifdef JBD2_ASSERTIONS | ||
261 | #define J_ASSERT(assert) \ | ||
262 | do { \ | ||
263 | if (!(assert)) { \ | ||
264 | printk (KERN_EMERG \ | ||
265 | "Assertion failure in %s() at %s:%d: \"%s\"\n", \ | ||
266 | __FUNCTION__, __FILE__, __LINE__, # assert); \ | ||
267 | BUG(); \ | ||
268 | } \ | ||
269 | } while (0) | ||
270 | 286 | ||
271 | #if defined(CONFIG_BUFFER_DEBUG) | 287 | #if defined(CONFIG_BUFFER_DEBUG) |
272 | void buffer_assertion_failure(struct buffer_head *bh); | 288 | void buffer_assertion_failure(struct buffer_head *bh); |
@@ -282,10 +298,6 @@ void buffer_assertion_failure(struct buffer_head *bh); | |||
282 | #define J_ASSERT_JH(jh, expr) J_ASSERT(expr) | 298 | #define J_ASSERT_JH(jh, expr) J_ASSERT(expr) |
283 | #endif | 299 | #endif |
284 | 300 | ||
285 | #else | ||
286 | #define J_ASSERT(assert) do { } while (0) | ||
287 | #endif /* JBD2_ASSERTIONS */ | ||
288 | |||
289 | #if defined(JBD2_PARANOID_IOFAIL) | 301 | #if defined(JBD2_PARANOID_IOFAIL) |
290 | #define J_EXPECT(expr, why...) J_ASSERT(expr) | 302 | #define J_EXPECT(expr, why...) J_ASSERT(expr) |
291 | #define J_EXPECT_BH(bh, expr, why...) J_ASSERT_BH(bh, expr) | 303 | #define J_EXPECT_BH(bh, expr, why...) J_ASSERT_BH(bh, expr) |
@@ -406,9 +418,23 @@ struct handle_s | |||
406 | unsigned int h_sync: 1; /* sync-on-close */ | 418 | unsigned int h_sync: 1; /* sync-on-close */ |
407 | unsigned int h_jdata: 1; /* force data journaling */ | 419 | unsigned int h_jdata: 1; /* force data journaling */ |
408 | unsigned int h_aborted: 1; /* fatal error on handle */ | 420 | unsigned int h_aborted: 1; /* fatal error on handle */ |
421 | |||
422 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
423 | struct lockdep_map h_lockdep_map; | ||
424 | #endif | ||
409 | }; | 425 | }; |
410 | 426 | ||
411 | 427 | ||
428 | /* | ||
429 | * Some stats for checkpoint phase | ||
430 | */ | ||
431 | struct transaction_chp_stats_s { | ||
432 | unsigned long cs_chp_time; | ||
433 | unsigned long cs_forced_to_close; | ||
434 | unsigned long cs_written; | ||
435 | unsigned long cs_dropped; | ||
436 | }; | ||
437 | |||
412 | /* The transaction_t type is the guts of the journaling mechanism. It | 438 | /* The transaction_t type is the guts of the journaling mechanism. It |
413 | * tracks a compound transaction through its various states: | 439 | * tracks a compound transaction through its various states: |
414 | * | 440 | * |
@@ -456,6 +482,8 @@ struct transaction_s | |||
456 | /* | 482 | /* |
457 | * Transaction's current state | 483 | * Transaction's current state |
458 | * [no locking - only kjournald2 alters this] | 484 | * [no locking - only kjournald2 alters this] |
485 | * [j_list_lock] guards transition of a transaction into T_FINISHED | ||
486 | * state and subsequent call of __jbd2_journal_drop_transaction() | ||
459 | * FIXME: needs barriers | 487 | * FIXME: needs barriers |
460 | * KLUDGE: [use j_state_lock] | 488 | * KLUDGE: [use j_state_lock] |
461 | */ | 489 | */ |
@@ -544,6 +572,21 @@ struct transaction_s | |||
544 | spinlock_t t_handle_lock; | 572 | spinlock_t t_handle_lock; |
545 | 573 | ||
546 | /* | 574 | /* |
575 | * Longest time some handle had to wait for running transaction | ||
576 | */ | ||
577 | unsigned long t_max_wait; | ||
578 | |||
579 | /* | ||
580 | * When transaction started | ||
581 | */ | ||
582 | unsigned long t_start; | ||
583 | |||
584 | /* | ||
585 | * Checkpointing stats [j_checkpoint_sem] | ||
586 | */ | ||
587 | struct transaction_chp_stats_s t_chp_stats; | ||
588 | |||
589 | /* | ||
547 | * Number of outstanding updates running on this transaction | 590 | * Number of outstanding updates running on this transaction |
548 | * [t_handle_lock] | 591 | * [t_handle_lock] |
549 | */ | 592 | */ |
@@ -574,6 +617,39 @@ struct transaction_s | |||
574 | 617 | ||
575 | }; | 618 | }; |
576 | 619 | ||
620 | struct transaction_run_stats_s { | ||
621 | unsigned long rs_wait; | ||
622 | unsigned long rs_running; | ||
623 | unsigned long rs_locked; | ||
624 | unsigned long rs_flushing; | ||
625 | unsigned long rs_logging; | ||
626 | |||
627 | unsigned long rs_handle_count; | ||
628 | unsigned long rs_blocks; | ||
629 | unsigned long rs_blocks_logged; | ||
630 | }; | ||
631 | |||
632 | struct transaction_stats_s { | ||
633 | int ts_type; | ||
634 | unsigned long ts_tid; | ||
635 | union { | ||
636 | struct transaction_run_stats_s run; | ||
637 | struct transaction_chp_stats_s chp; | ||
638 | } u; | ||
639 | }; | ||
640 | |||
641 | #define JBD2_STATS_RUN 1 | ||
642 | #define JBD2_STATS_CHECKPOINT 2 | ||
643 | |||
644 | static inline unsigned long | ||
645 | jbd2_time_diff(unsigned long start, unsigned long end) | ||
646 | { | ||
647 | if (end >= start) | ||
648 | return end - start; | ||
649 | |||
650 | return end + (MAX_JIFFY_OFFSET - start); | ||
651 | } | ||
652 | |||
577 | /** | 653 | /** |
578 | * struct journal_s - The journal_s type is the concrete type associated with | 654 | * struct journal_s - The journal_s type is the concrete type associated with |
579 | * journal_t. | 655 | * journal_t. |
@@ -635,6 +711,12 @@ struct transaction_s | |||
635 | * @j_wbufsize: maximum number of buffer_heads allowed in j_wbuf, the | 711 | * @j_wbufsize: maximum number of buffer_heads allowed in j_wbuf, the |
636 | * number that will fit in j_blocksize | 712 | * number that will fit in j_blocksize |
637 | * @j_last_sync_writer: most recent pid which did a synchronous write | 713 | * @j_last_sync_writer: most recent pid which did a synchronous write |
714 | * @j_history: Buffer storing the transactions statistics history | ||
715 | * @j_history_max: Maximum number of transactions in the statistics history | ||
716 | * @j_history_cur: Current number of transactions in the statistics history | ||
717 | * @j_history_lock: Protect the transactions statistics history | ||
718 | * @j_proc_entry: procfs entry for the jbd statistics directory | ||
719 | * @j_stats: Overall statistics | ||
638 | * @j_private: An opaque pointer to fs-private information. | 720 | * @j_private: An opaque pointer to fs-private information. |
639 | */ | 721 | */ |
640 | 722 | ||
@@ -827,6 +909,19 @@ struct journal_s | |||
827 | pid_t j_last_sync_writer; | 909 | pid_t j_last_sync_writer; |
828 | 910 | ||
829 | /* | 911 | /* |
912 | * Journal statistics | ||
913 | */ | ||
914 | struct transaction_stats_s *j_history; | ||
915 | int j_history_max; | ||
916 | int j_history_cur; | ||
917 | /* | ||
918 | * Protect the transactions statistics history | ||
919 | */ | ||
920 | spinlock_t j_history_lock; | ||
921 | struct proc_dir_entry *j_proc_entry; | ||
922 | struct transaction_stats_s j_stats; | ||
923 | |||
924 | /* | ||
830 | * An opaque pointer to fs-private information. ext3 puts its | 925 | * An opaque pointer to fs-private information. ext3 puts its |
831 | * superblock pointer here | 926 | * superblock pointer here |
832 | */ | 927 | */ |
@@ -932,6 +1027,8 @@ extern int jbd2_journal_check_available_features | |||
932 | (journal_t *, unsigned long, unsigned long, unsigned long); | 1027 | (journal_t *, unsigned long, unsigned long, unsigned long); |
933 | extern int jbd2_journal_set_features | 1028 | extern int jbd2_journal_set_features |
934 | (journal_t *, unsigned long, unsigned long, unsigned long); | 1029 | (journal_t *, unsigned long, unsigned long, unsigned long); |
1030 | extern void jbd2_journal_clear_features | ||
1031 | (journal_t *, unsigned long, unsigned long, unsigned long); | ||
935 | extern int jbd2_journal_create (journal_t *); | 1032 | extern int jbd2_journal_create (journal_t *); |
936 | extern int jbd2_journal_load (journal_t *journal); | 1033 | extern int jbd2_journal_load (journal_t *journal); |
937 | extern void jbd2_journal_destroy (journal_t *); | 1034 | extern void jbd2_journal_destroy (journal_t *); |
diff --git a/include/linux/module.h b/include/linux/module.h index c97bdb7eb957..ac481e2094fd 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -178,7 +178,7 @@ void *__symbol_get_gpl(const char *symbol); | |||
178 | #define __CRC_SYMBOL(sym, sec) \ | 178 | #define __CRC_SYMBOL(sym, sec) \ |
179 | extern void *__crc_##sym __attribute__((weak)); \ | 179 | extern void *__crc_##sym __attribute__((weak)); \ |
180 | static const unsigned long __kcrctab_##sym \ | 180 | static const unsigned long __kcrctab_##sym \ |
181 | __attribute_used__ \ | 181 | __used \ |
182 | __attribute__((section("__kcrctab" sec), unused)) \ | 182 | __attribute__((section("__kcrctab" sec), unused)) \ |
183 | = (unsigned long) &__crc_##sym; | 183 | = (unsigned long) &__crc_##sym; |
184 | #else | 184 | #else |
@@ -193,7 +193,7 @@ void *__symbol_get_gpl(const char *symbol); | |||
193 | __attribute__((section("__ksymtab_strings"))) \ | 193 | __attribute__((section("__ksymtab_strings"))) \ |
194 | = MODULE_SYMBOL_PREFIX #sym; \ | 194 | = MODULE_SYMBOL_PREFIX #sym; \ |
195 | static const struct kernel_symbol __ksymtab_##sym \ | 195 | static const struct kernel_symbol __ksymtab_##sym \ |
196 | __attribute_used__ \ | 196 | __used \ |
197 | __attribute__((section("__ksymtab" sec), unused)) \ | 197 | __attribute__((section("__ksymtab" sec), unused)) \ |
198 | = { (unsigned long)&sym, __kstrtab_##sym } | 198 | = { (unsigned long)&sym, __kstrtab_##sym } |
199 | 199 | ||
@@ -446,11 +446,14 @@ static inline void __module_get(struct module *module) | |||
446 | __mod ? __mod->name : "kernel"; \ | 446 | __mod ? __mod->name : "kernel"; \ |
447 | }) | 447 | }) |
448 | 448 | ||
449 | /* For kallsyms to ask for address resolution. NULL means not found. */ | 449 | /* For kallsyms to ask for address resolution. namebuf should be at |
450 | const char *module_address_lookup(unsigned long addr, | 450 | * least KSYM_NAME_LEN long: a pointer to namebuf is returned if |
451 | unsigned long *symbolsize, | 451 | * found, otherwise NULL. */ |
452 | unsigned long *offset, | 452 | char *module_address_lookup(unsigned long addr, |
453 | char **modname); | 453 | unsigned long *symbolsize, |
454 | unsigned long *offset, | ||
455 | char **modname, | ||
456 | char *namebuf); | ||
454 | int lookup_module_symbol_name(unsigned long addr, char *symname); | 457 | int lookup_module_symbol_name(unsigned long addr, char *symname); |
455 | int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name); | 458 | int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name); |
456 | 459 | ||
@@ -516,10 +519,11 @@ static inline void module_put(struct module *module) | |||
516 | #define module_name(mod) "kernel" | 519 | #define module_name(mod) "kernel" |
517 | 520 | ||
518 | /* For kallsyms to ask for address resolution. NULL means not found. */ | 521 | /* For kallsyms to ask for address resolution. NULL means not found. */ |
519 | static inline const char *module_address_lookup(unsigned long addr, | 522 | static inline char *module_address_lookup(unsigned long addr, |
520 | unsigned long *symbolsize, | 523 | unsigned long *symbolsize, |
521 | unsigned long *offset, | 524 | unsigned long *offset, |
522 | char **modname) | 525 | char **modname, |
526 | char *namebuf) | ||
523 | { | 527 | { |
524 | return NULL; | 528 | return NULL; |
525 | } | 529 | } |
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 13410b20600f..8126e55c5bdc 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -18,7 +18,7 @@ | |||
18 | #define __module_cat(a,b) ___module_cat(a,b) | 18 | #define __module_cat(a,b) ___module_cat(a,b) |
19 | #define __MODULE_INFO(tag, name, info) \ | 19 | #define __MODULE_INFO(tag, name, info) \ |
20 | static const char __module_cat(name,__LINE__)[] \ | 20 | static const char __module_cat(name,__LINE__)[] \ |
21 | __attribute_used__ \ | 21 | __used \ |
22 | __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info | 22 | __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info |
23 | #else /* !MODULE */ | 23 | #else /* !MODULE */ |
24 | #define __MODULE_INFO(tag, name, info) | 24 | #define __MODULE_INFO(tag, name, info) |
@@ -72,7 +72,7 @@ struct kparam_array | |||
72 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)); \ | 72 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)); \ |
73 | static const char __param_str_##name[] = prefix #name; \ | 73 | static const char __param_str_##name[] = prefix #name; \ |
74 | static struct kernel_param const __param_##name \ | 74 | static struct kernel_param const __param_##name \ |
75 | __attribute_used__ \ | 75 | __used \ |
76 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ | 76 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ |
77 | = { __param_str_##name, perm, set, get, { arg } } | 77 | = { __param_str_##name, perm, set, get, { arg } } |
78 | 78 | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index 0dd93bb62fbe..ae1006322f80 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -867,7 +867,7 @@ enum pci_fixup_pass { | |||
867 | 867 | ||
868 | /* Anonymous variables would be nice... */ | 868 | /* Anonymous variables would be nice... */ |
869 | #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, hook) \ | 869 | #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, hook) \ |
870 | static const struct pci_fixup __pci_fixup_##name __attribute_used__ \ | 870 | static const struct pci_fixup __pci_fixup_##name __used \ |
871 | __attribute__((__section__(#section))) = { vendor, device, hook }; | 871 | __attribute__((__section__(#section))) = { vendor, device, hook }; |
872 | #define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook) \ | 872 | #define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook) \ |
873 | DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early, \ | 873 | DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early, \ |
diff --git a/init/Kconfig b/init/Kconfig index 288444b4cd8a..0d0bbf218f1f 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -1,3 +1,11 @@ | |||
1 | config ARCH | ||
2 | string | ||
3 | option env="ARCH" | ||
4 | |||
5 | config KERNELVERSION | ||
6 | string | ||
7 | option env="KERNELVERSION" | ||
8 | |||
1 | config DEFCONFIG_LIST | 9 | config DEFCONFIG_LIST |
2 | string | 10 | string |
3 | depends on !UML | 11 | depends on !UML |
diff --git a/kernel/extable.c b/kernel/extable.c index 7fe262855317..a26cb2e17023 100644 --- a/kernel/extable.c +++ b/kernel/extable.c | |||
@@ -46,7 +46,8 @@ int core_kernel_text(unsigned long addr) | |||
46 | addr <= (unsigned long)_etext) | 46 | addr <= (unsigned long)_etext) |
47 | return 1; | 47 | return 1; |
48 | 48 | ||
49 | if (addr >= (unsigned long)_sinittext && | 49 | if (system_state == SYSTEM_BOOTING && |
50 | addr >= (unsigned long)_sinittext && | ||
50 | addr <= (unsigned long)_einittext) | 51 | addr <= (unsigned long)_einittext) |
51 | return 1; | 52 | return 1; |
52 | return 0; | 53 | return 0; |
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 2fc25810509e..7dadc71ce516 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c | |||
@@ -233,10 +233,11 @@ static unsigned long get_symbol_pos(unsigned long addr, | |||
233 | int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize, | 233 | int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize, |
234 | unsigned long *offset) | 234 | unsigned long *offset) |
235 | { | 235 | { |
236 | char namebuf[KSYM_NAME_LEN]; | ||
236 | if (is_ksym_addr(addr)) | 237 | if (is_ksym_addr(addr)) |
237 | return !!get_symbol_pos(addr, symbolsize, offset); | 238 | return !!get_symbol_pos(addr, symbolsize, offset); |
238 | 239 | ||
239 | return !!module_address_lookup(addr, symbolsize, offset, NULL); | 240 | return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf); |
240 | } | 241 | } |
241 | 242 | ||
242 | /* | 243 | /* |
@@ -251,8 +252,6 @@ const char *kallsyms_lookup(unsigned long addr, | |||
251 | unsigned long *offset, | 252 | unsigned long *offset, |
252 | char **modname, char *namebuf) | 253 | char **modname, char *namebuf) |
253 | { | 254 | { |
254 | const char *msym; | ||
255 | |||
256 | namebuf[KSYM_NAME_LEN - 1] = 0; | 255 | namebuf[KSYM_NAME_LEN - 1] = 0; |
257 | namebuf[0] = 0; | 256 | namebuf[0] = 0; |
258 | 257 | ||
@@ -268,10 +267,8 @@ const char *kallsyms_lookup(unsigned long addr, | |||
268 | } | 267 | } |
269 | 268 | ||
270 | /* see if it's in a module */ | 269 | /* see if it's in a module */ |
271 | msym = module_address_lookup(addr, symbolsize, offset, modname); | 270 | return module_address_lookup(addr, symbolsize, offset, modname, |
272 | if (msym) | 271 | namebuf); |
273 | return strncpy(namebuf, msym, KSYM_NAME_LEN - 1); | ||
274 | |||
275 | return NULL; | 272 | return NULL; |
276 | } | 273 | } |
277 | 274 | ||
diff --git a/kernel/module.c b/kernel/module.c index 1bb4c5e0d56e..f6a4e721fd49 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -65,6 +65,9 @@ | |||
65 | static DEFINE_MUTEX(module_mutex); | 65 | static DEFINE_MUTEX(module_mutex); |
66 | static LIST_HEAD(modules); | 66 | static LIST_HEAD(modules); |
67 | 67 | ||
68 | /* Waiting for a module to finish initializing? */ | ||
69 | static DECLARE_WAIT_QUEUE_HEAD(module_wq); | ||
70 | |||
68 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); | 71 | static BLOCKING_NOTIFIER_HEAD(module_notify_list); |
69 | 72 | ||
70 | int register_module_notifier(struct notifier_block * nb) | 73 | int register_module_notifier(struct notifier_block * nb) |
@@ -84,8 +87,11 @@ EXPORT_SYMBOL(unregister_module_notifier); | |||
84 | static inline int strong_try_module_get(struct module *mod) | 87 | static inline int strong_try_module_get(struct module *mod) |
85 | { | 88 | { |
86 | if (mod && mod->state == MODULE_STATE_COMING) | 89 | if (mod && mod->state == MODULE_STATE_COMING) |
90 | return -EBUSY; | ||
91 | if (try_module_get(mod)) | ||
87 | return 0; | 92 | return 0; |
88 | return try_module_get(mod); | 93 | else |
94 | return -ENOENT; | ||
89 | } | 95 | } |
90 | 96 | ||
91 | static inline void add_taint_module(struct module *mod, unsigned flag) | 97 | static inline void add_taint_module(struct module *mod, unsigned flag) |
@@ -539,11 +545,21 @@ static int already_uses(struct module *a, struct module *b) | |||
539 | static int use_module(struct module *a, struct module *b) | 545 | static int use_module(struct module *a, struct module *b) |
540 | { | 546 | { |
541 | struct module_use *use; | 547 | struct module_use *use; |
542 | int no_warn; | 548 | int no_warn, err; |
543 | 549 | ||
544 | if (b == NULL || already_uses(a, b)) return 1; | 550 | if (b == NULL || already_uses(a, b)) return 1; |
545 | 551 | ||
546 | if (!strong_try_module_get(b)) | 552 | /* If we're interrupted or time out, we fail. */ |
553 | if (wait_event_interruptible_timeout( | ||
554 | module_wq, (err = strong_try_module_get(b)) != -EBUSY, | ||
555 | 30 * HZ) <= 0) { | ||
556 | printk("%s: gave up waiting for init of module %s.\n", | ||
557 | a->name, b->name); | ||
558 | return 0; | ||
559 | } | ||
560 | |||
561 | /* If strong_try_module_get() returned a different error, we fail. */ | ||
562 | if (err) | ||
547 | return 0; | 563 | return 0; |
548 | 564 | ||
549 | DEBUGP("Allocating new usage for %s.\n", a->name); | 565 | DEBUGP("Allocating new usage for %s.\n", a->name); |
@@ -722,7 +738,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags) | |||
722 | mutex_lock(&module_mutex); | 738 | mutex_lock(&module_mutex); |
723 | } | 739 | } |
724 | /* Store the name of the last unloaded module for diagnostic purposes */ | 740 | /* Store the name of the last unloaded module for diagnostic purposes */ |
725 | sprintf(last_unloaded_module, mod->name); | 741 | strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); |
726 | free_module(mod); | 742 | free_module(mod); |
727 | 743 | ||
728 | out: | 744 | out: |
@@ -816,7 +832,7 @@ static inline void module_unload_free(struct module *mod) | |||
816 | 832 | ||
817 | static inline int use_module(struct module *a, struct module *b) | 833 | static inline int use_module(struct module *a, struct module *b) |
818 | { | 834 | { |
819 | return strong_try_module_get(b); | 835 | return strong_try_module_get(b) == 0; |
820 | } | 836 | } |
821 | 837 | ||
822 | static inline void module_unload_init(struct module *mod) | 838 | static inline void module_unload_init(struct module *mod) |
@@ -1214,6 +1230,7 @@ void module_remove_modinfo_attrs(struct module *mod) | |||
1214 | int mod_sysfs_init(struct module *mod) | 1230 | int mod_sysfs_init(struct module *mod) |
1215 | { | 1231 | { |
1216 | int err; | 1232 | int err; |
1233 | struct kobject *kobj; | ||
1217 | 1234 | ||
1218 | if (!module_sysfs_initialized) { | 1235 | if (!module_sysfs_initialized) { |
1219 | printk(KERN_ERR "%s: module sysfs not initialized\n", | 1236 | printk(KERN_ERR "%s: module sysfs not initialized\n", |
@@ -1221,6 +1238,15 @@ int mod_sysfs_init(struct module *mod) | |||
1221 | err = -EINVAL; | 1238 | err = -EINVAL; |
1222 | goto out; | 1239 | goto out; |
1223 | } | 1240 | } |
1241 | |||
1242 | kobj = kset_find_obj(module_kset, mod->name); | ||
1243 | if (kobj) { | ||
1244 | printk(KERN_ERR "%s: module is already loaded\n", mod->name); | ||
1245 | kobject_put(kobj); | ||
1246 | err = -EINVAL; | ||
1247 | goto out; | ||
1248 | } | ||
1249 | |||
1224 | mod->mkobj.mod = mod; | 1250 | mod->mkobj.mod = mod; |
1225 | 1251 | ||
1226 | memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); | 1252 | memset(&mod->mkobj.kobj, 0, sizeof(mod->mkobj.kobj)); |
@@ -1278,6 +1304,17 @@ static void mod_kobject_remove(struct module *mod) | |||
1278 | } | 1304 | } |
1279 | 1305 | ||
1280 | /* | 1306 | /* |
1307 | * link the module with the whole machine is stopped with interrupts off | ||
1308 | * - this defends against kallsyms not taking locks | ||
1309 | */ | ||
1310 | static int __link_module(void *_mod) | ||
1311 | { | ||
1312 | struct module *mod = _mod; | ||
1313 | list_add(&mod->list, &modules); | ||
1314 | return 0; | ||
1315 | } | ||
1316 | |||
1317 | /* | ||
1281 | * unlink the module with the whole machine is stopped with interrupts off | 1318 | * unlink the module with the whole machine is stopped with interrupts off |
1282 | * - this defends against kallsyms not taking locks | 1319 | * - this defends against kallsyms not taking locks |
1283 | */ | 1320 | */ |
@@ -1326,7 +1363,7 @@ void *__symbol_get(const char *symbol) | |||
1326 | 1363 | ||
1327 | preempt_disable(); | 1364 | preempt_disable(); |
1328 | value = __find_symbol(symbol, &owner, &crc, 1); | 1365 | value = __find_symbol(symbol, &owner, &crc, 1); |
1329 | if (value && !strong_try_module_get(owner)) | 1366 | if (value && strong_try_module_get(owner) != 0) |
1330 | value = 0; | 1367 | value = 0; |
1331 | preempt_enable(); | 1368 | preempt_enable(); |
1332 | 1369 | ||
@@ -1889,7 +1926,7 @@ static struct module *load_module(void __user *umod, | |||
1889 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); | 1926 | set_license(mod, get_modinfo(sechdrs, infoindex, "license")); |
1890 | 1927 | ||
1891 | if (strcmp(mod->name, "ndiswrapper") == 0) | 1928 | if (strcmp(mod->name, "ndiswrapper") == 0) |
1892 | add_taint(TAINT_PROPRIETARY_MODULE); | 1929 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); |
1893 | if (strcmp(mod->name, "driverloader") == 0) | 1930 | if (strcmp(mod->name, "driverloader") == 0) |
1894 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); | 1931 | add_taint_module(mod, TAINT_PROPRIETARY_MODULE); |
1895 | 1932 | ||
@@ -2019,6 +2056,11 @@ static struct module *load_module(void __user *umod, | |||
2019 | printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", | 2056 | printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", |
2020 | mod->name); | 2057 | mod->name); |
2021 | 2058 | ||
2059 | /* Now sew it into the lists so we can get lockdep and oops | ||
2060 | * info during argument parsing. Noone should access us, since | ||
2061 | * strong_try_module_get() will fail. */ | ||
2062 | stop_machine_run(__link_module, mod, NR_CPUS); | ||
2063 | |||
2022 | /* Size of section 0 is 0, so this works well if no params */ | 2064 | /* Size of section 0 is 0, so this works well if no params */ |
2023 | err = parse_args(mod->name, mod->args, | 2065 | err = parse_args(mod->name, mod->args, |
2024 | (struct kernel_param *) | 2066 | (struct kernel_param *) |
@@ -2027,7 +2069,7 @@ static struct module *load_module(void __user *umod, | |||
2027 | / sizeof(struct kernel_param), | 2069 | / sizeof(struct kernel_param), |
2028 | NULL); | 2070 | NULL); |
2029 | if (err < 0) | 2071 | if (err < 0) |
2030 | goto arch_cleanup; | 2072 | goto unlink; |
2031 | 2073 | ||
2032 | err = mod_sysfs_setup(mod, | 2074 | err = mod_sysfs_setup(mod, |
2033 | (struct kernel_param *) | 2075 | (struct kernel_param *) |
@@ -2035,7 +2077,7 @@ static struct module *load_module(void __user *umod, | |||
2035 | sechdrs[setupindex].sh_size | 2077 | sechdrs[setupindex].sh_size |
2036 | / sizeof(struct kernel_param)); | 2078 | / sizeof(struct kernel_param)); |
2037 | if (err < 0) | 2079 | if (err < 0) |
2038 | goto arch_cleanup; | 2080 | goto unlink; |
2039 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 2081 | add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); |
2040 | add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); | 2082 | add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); |
2041 | 2083 | ||
@@ -2050,7 +2092,8 @@ static struct module *load_module(void __user *umod, | |||
2050 | /* Done! */ | 2092 | /* Done! */ |
2051 | return mod; | 2093 | return mod; |
2052 | 2094 | ||
2053 | arch_cleanup: | 2095 | unlink: |
2096 | stop_machine_run(__unlink_module, mod, NR_CPUS); | ||
2054 | module_arch_cleanup(mod); | 2097 | module_arch_cleanup(mod); |
2055 | cleanup: | 2098 | cleanup: |
2056 | kobject_del(&mod->mkobj.kobj); | 2099 | kobject_del(&mod->mkobj.kobj); |
@@ -2075,17 +2118,6 @@ static struct module *load_module(void __user *umod, | |||
2075 | goto free_hdr; | 2118 | goto free_hdr; |
2076 | } | 2119 | } |
2077 | 2120 | ||
2078 | /* | ||
2079 | * link the module with the whole machine is stopped with interrupts off | ||
2080 | * - this defends against kallsyms not taking locks | ||
2081 | */ | ||
2082 | static int __link_module(void *_mod) | ||
2083 | { | ||
2084 | struct module *mod = _mod; | ||
2085 | list_add(&mod->list, &modules); | ||
2086 | return 0; | ||
2087 | } | ||
2088 | |||
2089 | /* This is where the real work happens */ | 2121 | /* This is where the real work happens */ |
2090 | asmlinkage long | 2122 | asmlinkage long |
2091 | sys_init_module(void __user *umod, | 2123 | sys_init_module(void __user *umod, |
@@ -2110,10 +2142,6 @@ sys_init_module(void __user *umod, | |||
2110 | return PTR_ERR(mod); | 2142 | return PTR_ERR(mod); |
2111 | } | 2143 | } |
2112 | 2144 | ||
2113 | /* Now sew it into the lists. They won't access us, since | ||
2114 | strong_try_module_get() will fail. */ | ||
2115 | stop_machine_run(__link_module, mod, NR_CPUS); | ||
2116 | |||
2117 | /* Drop lock so they can recurse */ | 2145 | /* Drop lock so they can recurse */ |
2118 | mutex_unlock(&module_mutex); | 2146 | mutex_unlock(&module_mutex); |
2119 | 2147 | ||
@@ -2132,6 +2160,7 @@ sys_init_module(void __user *umod, | |||
2132 | mutex_lock(&module_mutex); | 2160 | mutex_lock(&module_mutex); |
2133 | free_module(mod); | 2161 | free_module(mod); |
2134 | mutex_unlock(&module_mutex); | 2162 | mutex_unlock(&module_mutex); |
2163 | wake_up(&module_wq); | ||
2135 | return ret; | 2164 | return ret; |
2136 | } | 2165 | } |
2137 | 2166 | ||
@@ -2146,6 +2175,7 @@ sys_init_module(void __user *umod, | |||
2146 | mod->init_size = 0; | 2175 | mod->init_size = 0; |
2147 | mod->init_text_size = 0; | 2176 | mod->init_text_size = 0; |
2148 | mutex_unlock(&module_mutex); | 2177 | mutex_unlock(&module_mutex); |
2178 | wake_up(&module_wq); | ||
2149 | 2179 | ||
2150 | return 0; | 2180 | return 0; |
2151 | } | 2181 | } |
@@ -2210,14 +2240,13 @@ static const char *get_ksymbol(struct module *mod, | |||
2210 | return mod->strtab + mod->symtab[best].st_name; | 2240 | return mod->strtab + mod->symtab[best].st_name; |
2211 | } | 2241 | } |
2212 | 2242 | ||
2213 | /* For kallsyms to ask for address resolution. NULL means not found. | 2243 | /* For kallsyms to ask for address resolution. NULL means not found. Careful |
2214 | We don't lock, as this is used for oops resolution and races are a | 2244 | * not to lock to avoid deadlock on oopses, simply disable preemption. */ |
2215 | lesser concern. */ | 2245 | char *module_address_lookup(unsigned long addr, |
2216 | /* FIXME: Risky: returns a pointer into a module w/o lock */ | 2246 | unsigned long *size, |
2217 | const char *module_address_lookup(unsigned long addr, | 2247 | unsigned long *offset, |
2218 | unsigned long *size, | 2248 | char **modname, |
2219 | unsigned long *offset, | 2249 | char *namebuf) |
2220 | char **modname) | ||
2221 | { | 2250 | { |
2222 | struct module *mod; | 2251 | struct module *mod; |
2223 | const char *ret = NULL; | 2252 | const char *ret = NULL; |
@@ -2232,8 +2261,13 @@ const char *module_address_lookup(unsigned long addr, | |||
2232 | break; | 2261 | break; |
2233 | } | 2262 | } |
2234 | } | 2263 | } |
2264 | /* Make a copy in here where it's safe */ | ||
2265 | if (ret) { | ||
2266 | strncpy(namebuf, ret, KSYM_NAME_LEN - 1); | ||
2267 | ret = namebuf; | ||
2268 | } | ||
2235 | preempt_enable(); | 2269 | preempt_enable(); |
2236 | return ret; | 2270 | return (char *)ret; |
2237 | } | 2271 | } |
2238 | 2272 | ||
2239 | int lookup_module_symbol_name(unsigned long addr, char *symname) | 2273 | int lookup_module_symbol_name(unsigned long addr, char *symname) |
diff --git a/kernel/params.c b/kernel/params.c index 67f65ee7211d..42fe5e6126c0 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -376,8 +376,6 @@ int param_get_string(char *buffer, struct kernel_param *kp) | |||
376 | 376 | ||
377 | extern struct kernel_param __start___param[], __stop___param[]; | 377 | extern struct kernel_param __start___param[], __stop___param[]; |
378 | 378 | ||
379 | #define MAX_KBUILD_MODNAME KOBJ_NAME_LEN | ||
380 | |||
381 | struct param_attribute | 379 | struct param_attribute |
382 | { | 380 | { |
383 | struct module_attribute mattr; | 381 | struct module_attribute mattr; |
@@ -587,7 +585,7 @@ static void __init param_sysfs_builtin(void) | |||
587 | { | 585 | { |
588 | struct kernel_param *kp, *kp_begin = NULL; | 586 | struct kernel_param *kp, *kp_begin = NULL; |
589 | unsigned int i, name_len, count = 0; | 587 | unsigned int i, name_len, count = 0; |
590 | char modname[MAX_KBUILD_MODNAME + 1] = ""; | 588 | char modname[MODULE_NAME_LEN + 1] = ""; |
591 | 589 | ||
592 | for (i=0; i < __stop___param - __start___param; i++) { | 590 | for (i=0; i < __stop___param - __start___param; i++) { |
593 | char *dot; | 591 | char *dot; |
@@ -595,12 +593,12 @@ static void __init param_sysfs_builtin(void) | |||
595 | 593 | ||
596 | kp = &__start___param[i]; | 594 | kp = &__start___param[i]; |
597 | max_name_len = | 595 | max_name_len = |
598 | min_t(size_t, MAX_KBUILD_MODNAME, strlen(kp->name)); | 596 | min_t(size_t, MODULE_NAME_LEN, strlen(kp->name)); |
599 | 597 | ||
600 | dot = memchr(kp->name, '.', max_name_len); | 598 | dot = memchr(kp->name, '.', max_name_len); |
601 | if (!dot) { | 599 | if (!dot) { |
602 | DEBUGP("couldn't find period in first %d characters " | 600 | DEBUGP("couldn't find period in first %d characters " |
603 | "of %s\n", MAX_KBUILD_MODNAME, kp->name); | 601 | "of %s\n", MODULE_NAME_LEN, kp->name); |
604 | continue; | 602 | continue; |
605 | } | 603 | } |
606 | name_len = dot - kp->name; | 604 | name_len = dot - kp->name; |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 14fb355e3caa..c4ecb2994ba3 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -79,6 +79,38 @@ config HEADERS_CHECK | |||
79 | exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in | 79 | exported to $(INSTALL_HDR_PATH) (usually 'usr/include' in |
80 | your build tree), to make sure they're suitable. | 80 | your build tree), to make sure they're suitable. |
81 | 81 | ||
82 | config DEBUG_SECTION_MISMATCH | ||
83 | bool "Enable full Section mismatch analysis" | ||
84 | default n | ||
85 | help | ||
86 | The section mismatch analysis checks if there are illegal | ||
87 | references from one section to another section. | ||
88 | Linux will during link or during runtime drop some sections | ||
89 | and any use of code/data previously in these sections will | ||
90 | most likely result in an oops. | ||
91 | In the code functions and variables are annotated with | ||
92 | __init, __devinit etc. (see full list in include/linux/init.h) | ||
93 | which result in the code/data being placed in specific sections. | ||
94 | The section mismatch anaylsis are always done after a full | ||
95 | kernel build but enabling this options will in addition | ||
96 | do the following: | ||
97 | - Add the option -fno-inline-functions-called-once to gcc | ||
98 | When inlining a function annotated __init in a non-init | ||
99 | function we would loose the section information and thus | ||
100 | the analysis would not catch the illegal reference. | ||
101 | This options tell gcc to inline less but will also | ||
102 | result in a larger kernel. | ||
103 | - Run the section mismatch analysis for each module/built-in.o | ||
104 | When we run the section mismatch analysis on vmlinux.o we | ||
105 | looses valueable information about where the mismatch was | ||
106 | introduced. | ||
107 | Running the analysis for each module/built-in.o file | ||
108 | will tell where the mismatch happens much closer to the | ||
109 | source. The drawback is that we will report the same | ||
110 | mismatch at least twice. | ||
111 | - Enable verbose reporting from modpost to help solving | ||
112 | the section mismatches reported. | ||
113 | |||
82 | config DEBUG_KERNEL | 114 | config DEBUG_KERNEL |
83 | bool "Kernel debugging" | 115 | bool "Kernel debugging" |
84 | help | 116 | help |
diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c index bda0d71a2514..78ccd73a8841 100644 --- a/lib/find_next_bit.c +++ b/lib/find_next_bit.c | |||
@@ -178,4 +178,47 @@ found_middle_swap: | |||
178 | 178 | ||
179 | EXPORT_SYMBOL(generic_find_next_zero_le_bit); | 179 | EXPORT_SYMBOL(generic_find_next_zero_le_bit); |
180 | 180 | ||
181 | unsigned long generic_find_next_le_bit(const unsigned long *addr, unsigned | ||
182 | long size, unsigned long offset) | ||
183 | { | ||
184 | const unsigned long *p = addr + BITOP_WORD(offset); | ||
185 | unsigned long result = offset & ~(BITS_PER_LONG - 1); | ||
186 | unsigned long tmp; | ||
187 | |||
188 | if (offset >= size) | ||
189 | return size; | ||
190 | size -= result; | ||
191 | offset &= (BITS_PER_LONG - 1UL); | ||
192 | if (offset) { | ||
193 | tmp = ext2_swabp(p++); | ||
194 | tmp &= (~0UL << offset); | ||
195 | if (size < BITS_PER_LONG) | ||
196 | goto found_first; | ||
197 | if (tmp) | ||
198 | goto found_middle; | ||
199 | size -= BITS_PER_LONG; | ||
200 | result += BITS_PER_LONG; | ||
201 | } | ||
202 | |||
203 | while (size & ~(BITS_PER_LONG - 1)) { | ||
204 | tmp = *(p++); | ||
205 | if (tmp) | ||
206 | goto found_middle_swap; | ||
207 | result += BITS_PER_LONG; | ||
208 | size -= BITS_PER_LONG; | ||
209 | } | ||
210 | if (!size) | ||
211 | return result; | ||
212 | tmp = ext2_swabp(p); | ||
213 | found_first: | ||
214 | tmp &= (~0UL >> (BITS_PER_LONG - size)); | ||
215 | if (tmp == 0UL) /* Are any bits set? */ | ||
216 | return result + size; /* Nope. */ | ||
217 | found_middle: | ||
218 | return result + __ffs(tmp); | ||
219 | |||
220 | found_middle_swap: | ||
221 | return result + __ffs(ext2_swab(tmp)); | ||
222 | } | ||
223 | EXPORT_SYMBOL(generic_find_next_le_bit); | ||
181 | #endif /* __BIG_ENDIAN */ | 224 | #endif /* __BIG_ENDIAN */ |
diff --git a/scripts/Makefile.build b/scripts/Makefile.build index de9836eee8bb..67fb4530a6ff 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build | |||
@@ -83,10 +83,12 @@ ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(lib-target)),) | |||
83 | builtin-target := $(obj)/built-in.o | 83 | builtin-target := $(obj)/built-in.o |
84 | endif | 84 | endif |
85 | 85 | ||
86 | modorder-target := $(obj)/modules.order | ||
87 | |||
86 | # We keep a list of all modules in $(MODVERDIR) | 88 | # We keep a list of all modules in $(MODVERDIR) |
87 | 89 | ||
88 | __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ | 90 | __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ |
89 | $(if $(KBUILD_MODULES),$(obj-m)) \ | 91 | $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \ |
90 | $(subdir-ym) $(always) | 92 | $(subdir-ym) $(always) |
91 | @: | 93 | @: |
92 | 94 | ||
@@ -101,6 +103,10 @@ ifneq ($(KBUILD_CHECKSRC),0) | |||
101 | endif | 103 | endif |
102 | endif | 104 | endif |
103 | 105 | ||
106 | # Do section mismatch analysis for each module/built-in.o | ||
107 | ifdef CONFIG_DEBUG_SECTION_MISMATCH | ||
108 | cmd_secanalysis = ; scripts/mod/modpost $@ | ||
109 | endif | ||
104 | 110 | ||
105 | # Compile C sources (.c) | 111 | # Compile C sources (.c) |
106 | # --------------------------------------------------------------------------- | 112 | # --------------------------------------------------------------------------- |
@@ -266,7 +272,8 @@ ifdef builtin-target | |||
266 | quiet_cmd_link_o_target = LD $@ | 272 | quiet_cmd_link_o_target = LD $@ |
267 | # If the list of objects to link is empty, just create an empty built-in.o | 273 | # If the list of objects to link is empty, just create an empty built-in.o |
268 | cmd_link_o_target = $(if $(strip $(obj-y)),\ | 274 | cmd_link_o_target = $(if $(strip $(obj-y)),\ |
269 | $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^),\ | 275 | $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \ |
276 | $(cmd_secanalysis),\ | ||
270 | rm -f $@; $(AR) rcs $@) | 277 | rm -f $@; $(AR) rcs $@) |
271 | 278 | ||
272 | $(builtin-target): $(obj-y) FORCE | 279 | $(builtin-target): $(obj-y) FORCE |
@@ -276,6 +283,19 @@ targets += $(builtin-target) | |||
276 | endif # builtin-target | 283 | endif # builtin-target |
277 | 284 | ||
278 | # | 285 | # |
286 | # Rule to create modules.order file | ||
287 | # | ||
288 | # Create commands to either record .ko file or cat modules.order from | ||
289 | # a subdirectory | ||
290 | modorder-cmds = \ | ||
291 | $(foreach m, $(modorder), \ | ||
292 | $(if $(filter %/modules.order, $m), \ | ||
293 | cat $m;, echo kernel/$m;)) | ||
294 | |||
295 | $(modorder-target): $(subdir-ym) FORCE | ||
296 | $(Q)(cat /dev/null; $(modorder-cmds)) > $@ | ||
297 | |||
298 | # | ||
279 | # Rule to compile a set of .o files into one .a file | 299 | # Rule to compile a set of .o files into one .a file |
280 | # | 300 | # |
281 | ifdef lib-target | 301 | ifdef lib-target |
@@ -301,7 +321,7 @@ $($(subst $(obj)/,,$(@:.o=-objs))) \ | |||
301 | $($(subst $(obj)/,,$(@:.o=-y)))), $^) | 321 | $($(subst $(obj)/,,$(@:.o=-y)))), $^) |
302 | 322 | ||
303 | quiet_cmd_link_multi-y = LD $@ | 323 | quiet_cmd_link_multi-y = LD $@ |
304 | cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) | 324 | cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) $(cmd_secanalysis) |
305 | 325 | ||
306 | quiet_cmd_link_multi-m = LD [M] $@ | 326 | quiet_cmd_link_multi-m = LD [M] $@ |
307 | cmd_link_multi-m = $(cmd_link_multi-y) | 327 | cmd_link_multi-m = $(cmd_link_multi-y) |
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 3c5e88bfecf1..8e440233c27d 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib | |||
@@ -25,6 +25,11 @@ lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m))) | |||
25 | # o if we encounter foo/ in $(obj-m), remove it from $(obj-m) | 25 | # o if we encounter foo/ in $(obj-m), remove it from $(obj-m) |
26 | # and add the directory to the list of dirs to descend into: $(subdir-m) | 26 | # and add the directory to the list of dirs to descend into: $(subdir-m) |
27 | 27 | ||
28 | # Determine modorder. | ||
29 | # Unfortunately, we don't have information about ordering between -y | ||
30 | # and -m subdirs. Just put -y's first. | ||
31 | modorder := $(patsubst %/,%/modules.order, $(filter %/, $(obj-y)) $(obj-m:.o=.ko)) | ||
32 | |||
28 | __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) | 33 | __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) |
29 | subdir-y += $(__subdir-y) | 34 | subdir-y += $(__subdir-y) |
30 | __subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m))) | 35 | __subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m))) |
@@ -64,6 +69,7 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y) | |||
64 | extra-y := $(addprefix $(obj)/,$(extra-y)) | 69 | extra-y := $(addprefix $(obj)/,$(extra-y)) |
65 | always := $(addprefix $(obj)/,$(always)) | 70 | always := $(addprefix $(obj)/,$(always)) |
66 | targets := $(addprefix $(obj)/,$(targets)) | 71 | targets := $(addprefix $(obj)/,$(targets)) |
72 | modorder := $(addprefix $(obj)/,$(modorder)) | ||
67 | obj-y := $(addprefix $(obj)/,$(obj-y)) | 73 | obj-y := $(addprefix $(obj)/,$(obj-y)) |
68 | obj-m := $(addprefix $(obj)/,$(obj-m)) | 74 | obj-m := $(addprefix $(obj)/,$(obj-m)) |
69 | lib-y := $(addprefix $(obj)/,$(lib-y)) | 75 | lib-y := $(addprefix $(obj)/,$(lib-y)) |
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst index f0ff248f5e6f..efa5d940e632 100644 --- a/scripts/Makefile.modinst +++ b/scripts/Makefile.modinst | |||
@@ -21,7 +21,7 @@ quiet_cmd_modules_install = INSTALL $@ | |||
21 | 21 | ||
22 | # Modules built outside the kernel source tree go into extra by default | 22 | # Modules built outside the kernel source tree go into extra by default |
23 | INSTALL_MOD_DIR ?= extra | 23 | INSTALL_MOD_DIR ?= extra |
24 | ext-mod-dir = $(INSTALL_MOD_DIR)$(subst $(KBUILD_EXTMOD),,$(@D)) | 24 | ext-mod-dir = $(INSTALL_MOD_DIR)$(subst $(patsubst %/,%,$(KBUILD_EXTMOD)),,$(@D)) |
25 | 25 | ||
26 | modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) | 26 | modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) |
27 | 27 | ||
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index d988f5d21e3d..65e707e1ffc3 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost | |||
@@ -62,6 +62,7 @@ modpost = scripts/mod/modpost \ | |||
62 | $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \ | 62 | $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \ |
63 | $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ | 63 | $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ |
64 | $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ | 64 | $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ |
65 | $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ | ||
65 | $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) | 66 | $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) |
66 | 67 | ||
67 | quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules | 68 | quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules |
diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c index 0e4bd5459df4..35bdc68b6e66 100644 --- a/scripts/basic/docproc.c +++ b/scripts/basic/docproc.c | |||
@@ -30,6 +30,7 @@ | |||
30 | * !Ifilename | 30 | * !Ifilename |
31 | * !Dfilename | 31 | * !Dfilename |
32 | * !Ffilename | 32 | * !Ffilename |
33 | * !Pfilename | ||
33 | * | 34 | * |
34 | */ | 35 | */ |
35 | 36 | ||
@@ -57,6 +58,7 @@ FILEONLY *symbolsonly; | |||
57 | typedef void FILELINE(char * file, char * line); | 58 | typedef void FILELINE(char * file, char * line); |
58 | FILELINE * singlefunctions; | 59 | FILELINE * singlefunctions; |
59 | FILELINE * entity_system; | 60 | FILELINE * entity_system; |
61 | FILELINE * docsection; | ||
60 | 62 | ||
61 | #define MAXLINESZ 2048 | 63 | #define MAXLINESZ 2048 |
62 | #define MAXFILES 250 | 64 | #define MAXFILES 250 |
@@ -65,6 +67,7 @@ FILELINE * entity_system; | |||
65 | #define DOCBOOK "-docbook" | 67 | #define DOCBOOK "-docbook" |
66 | #define FUNCTION "-function" | 68 | #define FUNCTION "-function" |
67 | #define NOFUNCTION "-nofunction" | 69 | #define NOFUNCTION "-nofunction" |
70 | #define NODOCSECTIONS "-no-doc-sections" | ||
68 | 71 | ||
69 | char *srctree; | 72 | char *srctree; |
70 | 73 | ||
@@ -231,13 +234,14 @@ void docfunctions(char * filename, char * type) | |||
231 | 234 | ||
232 | for (i=0; i <= symfilecnt; i++) | 235 | for (i=0; i <= symfilecnt; i++) |
233 | symcnt += symfilelist[i].symbolcnt; | 236 | symcnt += symfilelist[i].symbolcnt; |
234 | vec = malloc((2 + 2 * symcnt + 2) * sizeof(char*)); | 237 | vec = malloc((2 + 2 * symcnt + 3) * sizeof(char *)); |
235 | if (vec == NULL) { | 238 | if (vec == NULL) { |
236 | perror("docproc: "); | 239 | perror("docproc: "); |
237 | exit(1); | 240 | exit(1); |
238 | } | 241 | } |
239 | vec[idx++] = KERNELDOC; | 242 | vec[idx++] = KERNELDOC; |
240 | vec[idx++] = DOCBOOK; | 243 | vec[idx++] = DOCBOOK; |
244 | vec[idx++] = NODOCSECTIONS; | ||
241 | for (i=0; i < symfilecnt; i++) { | 245 | for (i=0; i < symfilecnt; i++) { |
242 | struct symfile * sym = &symfilelist[i]; | 246 | struct symfile * sym = &symfilelist[i]; |
243 | for (j=0; j < sym->symbolcnt; j++) { | 247 | for (j=0; j < sym->symbolcnt; j++) { |
@@ -287,12 +291,36 @@ void singfunc(char * filename, char * line) | |||
287 | } | 291 | } |
288 | 292 | ||
289 | /* | 293 | /* |
294 | * Insert specific documentation section from a file. | ||
295 | * Call kernel-doc with the following parameters: | ||
296 | * kernel-doc -docbook -function "doc section" filename | ||
297 | */ | ||
298 | void docsect(char *filename, char *line) | ||
299 | { | ||
300 | char *vec[6]; /* kerneldoc -docbook -function "section" file NULL */ | ||
301 | char *s; | ||
302 | |||
303 | for (s = line; *s; s++) | ||
304 | if (*s == '\n') | ||
305 | *s = '\0'; | ||
306 | |||
307 | vec[0] = KERNELDOC; | ||
308 | vec[1] = DOCBOOK; | ||
309 | vec[2] = FUNCTION; | ||
310 | vec[3] = line; | ||
311 | vec[4] = filename; | ||
312 | vec[5] = NULL; | ||
313 | exec_kernel_doc(vec); | ||
314 | } | ||
315 | |||
316 | /* | ||
290 | * Parse file, calling action specific functions for: | 317 | * Parse file, calling action specific functions for: |
291 | * 1) Lines containing !E | 318 | * 1) Lines containing !E |
292 | * 2) Lines containing !I | 319 | * 2) Lines containing !I |
293 | * 3) Lines containing !D | 320 | * 3) Lines containing !D |
294 | * 4) Lines containing !F | 321 | * 4) Lines containing !F |
295 | * 5) Default lines - lines not matching the above | 322 | * 5) Lines containing !P |
323 | * 6) Default lines - lines not matching the above | ||
296 | */ | 324 | */ |
297 | void parse_file(FILE *infile) | 325 | void parse_file(FILE *infile) |
298 | { | 326 | { |
@@ -326,6 +354,15 @@ void parse_file(FILE *infile) | |||
326 | s++; | 354 | s++; |
327 | singlefunctions(line +2, s); | 355 | singlefunctions(line +2, s); |
328 | break; | 356 | break; |
357 | case 'P': | ||
358 | /* filename */ | ||
359 | while (*s && !isspace(*s)) s++; | ||
360 | *s++ = '\0'; | ||
361 | /* DOC: section name */ | ||
362 | while (isspace(*s)) | ||
363 | s++; | ||
364 | docsection(line + 2, s); | ||
365 | break; | ||
329 | default: | 366 | default: |
330 | defaultline(line); | 367 | defaultline(line); |
331 | } | 368 | } |
@@ -372,6 +409,7 @@ int main(int argc, char *argv[]) | |||
372 | externalfunctions = find_export_symbols; | 409 | externalfunctions = find_export_symbols; |
373 | symbolsonly = find_export_symbols; | 410 | symbolsonly = find_export_symbols; |
374 | singlefunctions = noaction2; | 411 | singlefunctions = noaction2; |
412 | docsection = noaction2; | ||
375 | parse_file(infile); | 413 | parse_file(infile); |
376 | 414 | ||
377 | /* Rewind to start from beginning of file again */ | 415 | /* Rewind to start from beginning of file again */ |
@@ -381,6 +419,7 @@ int main(int argc, char *argv[]) | |||
381 | externalfunctions = extfunc; | 419 | externalfunctions = extfunc; |
382 | symbolsonly = printline; | 420 | symbolsonly = printline; |
383 | singlefunctions = singfunc; | 421 | singlefunctions = singfunc; |
422 | docsection = docsect; | ||
384 | 423 | ||
385 | parse_file(infile); | 424 | parse_file(infile); |
386 | } | 425 | } |
@@ -394,6 +433,7 @@ int main(int argc, char *argv[]) | |||
394 | externalfunctions = adddep; | 433 | externalfunctions = adddep; |
395 | symbolsonly = adddep; | 434 | symbolsonly = adddep; |
396 | singlefunctions = adddep2; | 435 | singlefunctions = adddep2; |
436 | docsection = adddep2; | ||
397 | parse_file(infile); | 437 | parse_file(infile); |
398 | printf("\n"); | 438 | printf("\n"); |
399 | } | 439 | } |
diff --git a/scripts/decodecode b/scripts/decodecode index 1e1a8f620c47..235d3938529d 100644 --- a/scripts/decodecode +++ b/scripts/decodecode | |||
@@ -6,7 +6,19 @@ | |||
6 | # e.g., to decode an i386 oops on an x86_64 system, use: | 6 | # e.g., to decode an i386 oops on an x86_64 system, use: |
7 | # AFLAGS=--32 decodecode < 386.oops | 7 | # AFLAGS=--32 decodecode < 386.oops |
8 | 8 | ||
9 | T=`mktemp` | 9 | cleanup() { |
10 | rm -f $T $T.s $T.o | ||
11 | exit 1 | ||
12 | } | ||
13 | |||
14 | die() { | ||
15 | echo "$@" | ||
16 | exit 1 | ||
17 | } | ||
18 | |||
19 | trap cleanup EXIT | ||
20 | |||
21 | T=`mktemp` || die "cannot create temp file" | ||
10 | code= | 22 | code= |
11 | 23 | ||
12 | while read i ; do | 24 | while read i ; do |
@@ -20,6 +32,7 @@ esac | |||
20 | done | 32 | done |
21 | 33 | ||
22 | if [ -z "$code" ]; then | 34 | if [ -z "$code" ]; then |
35 | rm $T | ||
23 | exit | 36 | exit |
24 | fi | 37 | fi |
25 | 38 | ||
@@ -48,4 +61,4 @@ echo -n " .byte 0x" > $T.s | |||
48 | echo $code >> $T.s | 61 | echo $code >> $T.s |
49 | as $AFLAGS -o $T.o $T.s | 62 | as $AFLAGS -o $T.o $T.s |
50 | objdump -S $T.o | 63 | objdump -S $T.o |
51 | rm $T.o $T.s | 64 | rm $T $T.s $T.o |
diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh index a5121a6d8949..cc767b388baf 100644 --- a/scripts/gcc-version.sh +++ b/scripts/gcc-version.sh | |||
@@ -9,7 +9,10 @@ | |||
9 | # gcc-2.95.3, `030301' for gcc-3.3.1, etc. | 9 | # gcc-2.95.3, `030301' for gcc-3.3.1, etc. |
10 | # | 10 | # |
11 | 11 | ||
12 | if [[ $1 = "-p" ]] ; then with_patchlevel=1; shift; fi | 12 | if [ "$1" = "-p" ] ; then |
13 | with_patchlevel=1; | ||
14 | shift; | ||
15 | fi | ||
13 | 16 | ||
14 | compiler="$*" | 17 | compiler="$*" |
15 | 18 | ||
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index 511023b430a8..dca5e0dd09bf 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c | |||
@@ -440,17 +440,21 @@ void error_with_pos(const char *fmt, ...) | |||
440 | 440 | ||
441 | static void genksyms_usage(void) | 441 | static void genksyms_usage(void) |
442 | { | 442 | { |
443 | fputs("Usage:\n" "genksyms [-dDwqhV] > /path/to/.tmp_obj.ver\n" "\n" | 443 | fputs("Usage:\n" "genksyms [-adDTwqhV] > /path/to/.tmp_obj.ver\n" "\n" |
444 | #ifdef __GNU_LIBRARY__ | 444 | #ifdef __GNU_LIBRARY__ |
445 | " -a, --arch Select architecture\n" | ||
445 | " -d, --debug Increment the debug level (repeatable)\n" | 446 | " -d, --debug Increment the debug level (repeatable)\n" |
446 | " -D, --dump Dump expanded symbol defs (for debugging only)\n" | 447 | " -D, --dump Dump expanded symbol defs (for debugging only)\n" |
448 | " -T, --dump-types file Dump expanded types into file (for debugging only)\n" | ||
447 | " -w, --warnings Enable warnings\n" | 449 | " -w, --warnings Enable warnings\n" |
448 | " -q, --quiet Disable warnings (default)\n" | 450 | " -q, --quiet Disable warnings (default)\n" |
449 | " -h, --help Print this message\n" | 451 | " -h, --help Print this message\n" |
450 | " -V, --version Print the release version\n" | 452 | " -V, --version Print the release version\n" |
451 | #else /* __GNU_LIBRARY__ */ | 453 | #else /* __GNU_LIBRARY__ */ |
454 | " -a Select architecture\n" | ||
452 | " -d Increment the debug level (repeatable)\n" | 455 | " -d Increment the debug level (repeatable)\n" |
453 | " -D Dump expanded symbol defs (for debugging only)\n" | 456 | " -D Dump expanded symbol defs (for debugging only)\n" |
457 | " -T file Dump expanded types into file (for debugging only)\n" | ||
454 | " -w Enable warnings\n" | 458 | " -w Enable warnings\n" |
455 | " -q Disable warnings (default)\n" | 459 | " -q Disable warnings (default)\n" |
456 | " -h Print this message\n" | 460 | " -h Print this message\n" |
@@ -477,10 +481,10 @@ int main(int argc, char **argv) | |||
477 | {0, 0, 0, 0} | 481 | {0, 0, 0, 0} |
478 | }; | 482 | }; |
479 | 483 | ||
480 | while ((o = getopt_long(argc, argv, "a:dwqVDT:k:p:", | 484 | while ((o = getopt_long(argc, argv, "a:dwqVDT:h", |
481 | &long_opts[0], NULL)) != EOF) | 485 | &long_opts[0], NULL)) != EOF) |
482 | #else /* __GNU_LIBRARY__ */ | 486 | #else /* __GNU_LIBRARY__ */ |
483 | while ((o = getopt(argc, argv, "a:dwqVDT:k:p:")) != EOF) | 487 | while ((o = getopt(argc, argv, "a:dwqVDT:h")) != EOF) |
484 | #endif /* __GNU_LIBRARY__ */ | 488 | #endif /* __GNU_LIBRARY__ */ |
485 | switch (o) { | 489 | switch (o) { |
486 | case 'a': | 490 | case 'a': |
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 1ad6f7fc490a..32e8c5a227c3 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile | |||
@@ -24,22 +24,25 @@ oldconfig: $(obj)/conf | |||
24 | silentoldconfig: $(obj)/conf | 24 | silentoldconfig: $(obj)/conf |
25 | $< -s $(Kconfig) | 25 | $< -s $(Kconfig) |
26 | 26 | ||
27 | # Create new linux.po file | 27 | # Create new linux.pot file |
28 | # Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files | 28 | # Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files |
29 | # The symlink is used to repair a deficiency in arch/um | 29 | # The symlink is used to repair a deficiency in arch/um |
30 | update-po-config: $(obj)/kxgettext | 30 | update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h |
31 | xgettext --default-domain=linux \ | 31 | $(Q)echo " GEN config" |
32 | $(Q)xgettext --default-domain=linux \ | ||
32 | --add-comments --keyword=_ --keyword=N_ \ | 33 | --add-comments --keyword=_ --keyword=N_ \ |
33 | --from-code=UTF-8 \ | 34 | --from-code=UTF-8 \ |
34 | --files-from=scripts/kconfig/POTFILES.in \ | 35 | --files-from=scripts/kconfig/POTFILES.in \ |
35 | --output $(obj)/config.pot | 36 | --output $(obj)/config.pot |
36 | $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot | 37 | $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot |
37 | $(Q)ln -fs Kconfig.i386 arch/um/Kconfig.arch | 38 | $(Q)ln -fs Kconfig.i386 arch/um/Kconfig.arch |
38 | (for i in `ls arch/`; \ | 39 | $(Q)(for i in `ls arch/`; \ |
39 | do \ | 40 | do \ |
40 | $(obj)/kxgettext arch/$$i/Kconfig; \ | 41 | echo " GEN $$i"; \ |
41 | done ) >> $(obj)/config.pot | 42 | $(obj)/kxgettext arch/$$i/Kconfig \ |
42 | msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \ | 43 | >> $(obj)/config.pot; \ |
44 | done ) | ||
45 | $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \ | ||
43 | --output $(obj)/linux.pot | 46 | --output $(obj)/linux.pot |
44 | $(Q)rm -f arch/um/Kconfig.arch | 47 | $(Q)rm -f arch/um/Kconfig.arch |
45 | $(Q)rm -f $(obj)/config.pot | 48 | $(Q)rm -f $(obj)/config.pot |
@@ -93,12 +96,6 @@ HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) | |||
93 | 96 | ||
94 | HOST_EXTRACFLAGS += -DLOCALE | 97 | HOST_EXTRACFLAGS += -DLOCALE |
95 | 98 | ||
96 | PHONY += $(obj)/dochecklxdialog | ||
97 | $(obj)/dochecklxdialog: | ||
98 | $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_LOADLIBES) | ||
99 | |||
100 | always := dochecklxdialog | ||
101 | |||
102 | 99 | ||
103 | # =========================================================================== | 100 | # =========================================================================== |
104 | # Shared Makefile for the various kconfig executables: | 101 | # Shared Makefile for the various kconfig executables: |
@@ -142,8 +139,17 @@ gconf-objs := gconf.o kconfig_load.o zconf.tab.o | |||
142 | endif | 139 | endif |
143 | 140 | ||
144 | clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ | 141 | clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ |
145 | .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c | 142 | .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c gconf.glade.h |
146 | clean-files += mconf qconf gconf | 143 | clean-files += mconf qconf gconf |
144 | clean-files += config.pot linux.pot | ||
145 | |||
146 | # Check that we have the required ncurses stuff installed for lxdialog (menuconfig) | ||
147 | PHONY += $(obj)/dochecklxdialog | ||
148 | $(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog | ||
149 | $(obj)/dochecklxdialog: | ||
150 | $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOST_LOADLIBES) | ||
151 | |||
152 | always := dochecklxdialog | ||
147 | 153 | ||
148 | # Add environment specific flags | 154 | # Add environment specific flags |
149 | HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS)) | 155 | HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS)) |
@@ -248,6 +254,9 @@ $(obj)/%.moc: $(src)/%.h | |||
248 | $(obj)/lkc_defs.h: $(src)/lkc_proto.h | 254 | $(obj)/lkc_defs.h: $(src)/lkc_proto.h |
249 | sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/' | 255 | sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/' |
250 | 256 | ||
257 | # Extract gconf menu items for I18N support | ||
258 | $(obj)/gconf.glade.h: $(obj)/gconf.glade | ||
259 | intltool-extract --type=gettext/glade $(obj)/gconf.glade | ||
251 | 260 | ||
252 | ### | 261 | ### |
253 | # The following requires flex/bison/gperf | 262 | # The following requires flex/bison/gperf |
diff --git a/scripts/kconfig/POTFILES.in b/scripts/kconfig/POTFILES.in index cc94e46a79e8..967457396990 100644 --- a/scripts/kconfig/POTFILES.in +++ b/scripts/kconfig/POTFILES.in | |||
@@ -1,5 +1,12 @@ | |||
1 | scripts/kconfig/lxdialog/checklist.c | ||
2 | scripts/kconfig/lxdialog/inputbox.c | ||
3 | scripts/kconfig/lxdialog/menubox.c | ||
4 | scripts/kconfig/lxdialog/textbox.c | ||
5 | scripts/kconfig/lxdialog/util.c | ||
6 | scripts/kconfig/lxdialog/yesno.c | ||
1 | scripts/kconfig/mconf.c | 7 | scripts/kconfig/mconf.c |
2 | scripts/kconfig/conf.c | 8 | scripts/kconfig/conf.c |
3 | scripts/kconfig/confdata.c | 9 | scripts/kconfig/confdata.c |
4 | scripts/kconfig/gconf.c | 10 | scripts/kconfig/gconf.c |
11 | scripts/kconfig/gconf.glade.h | ||
5 | scripts/kconfig/qconf.cc | 12 | scripts/kconfig/qconf.cc |
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 8d6f17490c5e..fda63136ae68 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c | |||
@@ -3,12 +3,13 @@ | |||
3 | * Released under the terms of the GNU GPL v2.0. | 3 | * Released under the terms of the GNU GPL v2.0. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <locale.h> | ||
6 | #include <ctype.h> | 7 | #include <ctype.h> |
7 | #include <stdlib.h> | ||
8 | #include <stdio.h> | 8 | #include <stdio.h> |
9 | #include <stdlib.h> | ||
9 | #include <string.h> | 10 | #include <string.h> |
10 | #include <unistd.h> | ||
11 | #include <time.h> | 11 | #include <time.h> |
12 | #include <unistd.h> | ||
12 | #include <sys/stat.h> | 13 | #include <sys/stat.h> |
13 | 14 | ||
14 | #define LKC_DIRECT_LINK | 15 | #define LKC_DIRECT_LINK |
@@ -40,7 +41,7 @@ static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n" | |||
40 | static const char *get_help(struct menu *menu) | 41 | static const char *get_help(struct menu *menu) |
41 | { | 42 | { |
42 | if (menu_has_help(menu)) | 43 | if (menu_has_help(menu)) |
43 | return menu_get_help(menu); | 44 | return _(menu_get_help(menu)); |
44 | else | 45 | else |
45 | return nohelp_text; | 46 | return nohelp_text; |
46 | } | 47 | } |
@@ -78,7 +79,7 @@ static int conf_askvalue(struct symbol *sym, const char *def) | |||
78 | tristate val; | 79 | tristate val; |
79 | 80 | ||
80 | if (!sym_has_value(sym)) | 81 | if (!sym_has_value(sym)) |
81 | printf("(NEW) "); | 82 | printf(_("(NEW) ")); |
82 | 83 | ||
83 | line[0] = '\n'; | 84 | line[0] = '\n'; |
84 | line[1] = 0; | 85 | line[1] = 0; |
@@ -160,7 +161,7 @@ static int conf_askvalue(struct symbol *sym, const char *def) | |||
160 | } | 161 | } |
161 | case set_random: | 162 | case set_random: |
162 | do { | 163 | do { |
163 | val = (tristate)(random() % 3); | 164 | val = (tristate)(rand() % 3); |
164 | } while (!sym_tristate_within_range(sym, val)); | 165 | } while (!sym_tristate_within_range(sym, val)); |
165 | switch (val) { | 166 | switch (val) { |
166 | case no: line[0] = 'n'; break; | 167 | case no: line[0] = 'n'; break; |
@@ -183,7 +184,7 @@ int conf_string(struct menu *menu) | |||
183 | const char *def; | 184 | const char *def; |
184 | 185 | ||
185 | while (1) { | 186 | while (1) { |
186 | printf("%*s%s ", indent - 1, "", menu->prompt->text); | 187 | printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); |
187 | printf("(%s) ", sym->name); | 188 | printf("(%s) ", sym->name); |
188 | def = sym_get_string_value(sym); | 189 | def = sym_get_string_value(sym); |
189 | if (sym_get_string_value(sym)) | 190 | if (sym_get_string_value(sym)) |
@@ -216,7 +217,7 @@ static int conf_sym(struct menu *menu) | |||
216 | tristate oldval, newval; | 217 | tristate oldval, newval; |
217 | 218 | ||
218 | while (1) { | 219 | while (1) { |
219 | printf("%*s%s ", indent - 1, "", menu->prompt->text); | 220 | printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); |
220 | if (sym->name) | 221 | if (sym->name) |
221 | printf("(%s) ", sym->name); | 222 | printf("(%s) ", sym->name); |
222 | type = sym_get_type(sym); | 223 | type = sym_get_type(sym); |
@@ -306,7 +307,7 @@ static int conf_choice(struct menu *menu) | |||
306 | case no: | 307 | case no: |
307 | return 1; | 308 | return 1; |
308 | case mod: | 309 | case mod: |
309 | printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); | 310 | printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); |
310 | return 0; | 311 | return 0; |
311 | case yes: | 312 | case yes: |
312 | break; | 313 | break; |
@@ -316,7 +317,7 @@ static int conf_choice(struct menu *menu) | |||
316 | while (1) { | 317 | while (1) { |
317 | int cnt, def; | 318 | int cnt, def; |
318 | 319 | ||
319 | printf("%*s%s\n", indent - 1, "", menu_get_prompt(menu)); | 320 | printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); |
320 | def_sym = sym_get_choice_value(sym); | 321 | def_sym = sym_get_choice_value(sym); |
321 | cnt = def = 0; | 322 | cnt = def = 0; |
322 | line[0] = 0; | 323 | line[0] = 0; |
@@ -324,7 +325,7 @@ static int conf_choice(struct menu *menu) | |||
324 | if (!menu_is_visible(child)) | 325 | if (!menu_is_visible(child)) |
325 | continue; | 326 | continue; |
326 | if (!child->sym) { | 327 | if (!child->sym) { |
327 | printf("%*c %s\n", indent, '*', menu_get_prompt(child)); | 328 | printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); |
328 | continue; | 329 | continue; |
329 | } | 330 | } |
330 | cnt++; | 331 | cnt++; |
@@ -333,14 +334,14 @@ static int conf_choice(struct menu *menu) | |||
333 | printf("%*c", indent, '>'); | 334 | printf("%*c", indent, '>'); |
334 | } else | 335 | } else |
335 | printf("%*c", indent, ' '); | 336 | printf("%*c", indent, ' '); |
336 | printf(" %d. %s", cnt, menu_get_prompt(child)); | 337 | printf(" %d. %s", cnt, _(menu_get_prompt(child))); |
337 | if (child->sym->name) | 338 | if (child->sym->name) |
338 | printf(" (%s)", child->sym->name); | 339 | printf(" (%s)", child->sym->name); |
339 | if (!sym_has_value(child->sym)) | 340 | if (!sym_has_value(child->sym)) |
340 | printf(" (NEW)"); | 341 | printf(_(" (NEW)")); |
341 | printf("\n"); | 342 | printf("\n"); |
342 | } | 343 | } |
343 | printf("%*schoice", indent - 1, ""); | 344 | printf(_("%*schoice"), indent - 1, ""); |
344 | if (cnt == 1) { | 345 | if (cnt == 1) { |
345 | printf("[1]: 1\n"); | 346 | printf("[1]: 1\n"); |
346 | goto conf_childs; | 347 | goto conf_childs; |
@@ -375,7 +376,7 @@ static int conf_choice(struct menu *menu) | |||
375 | break; | 376 | break; |
376 | case set_random: | 377 | case set_random: |
377 | if (is_new) | 378 | if (is_new) |
378 | def = (random() % cnt) + 1; | 379 | def = (rand() % cnt) + 1; |
379 | case set_default: | 380 | case set_default: |
380 | case set_yes: | 381 | case set_yes: |
381 | case set_mod: | 382 | case set_mod: |
@@ -399,9 +400,9 @@ static int conf_choice(struct menu *menu) | |||
399 | continue; | 400 | continue; |
400 | } | 401 | } |
401 | sym_set_choice_value(sym, child->sym); | 402 | sym_set_choice_value(sym, child->sym); |
402 | if (child->list) { | 403 | for (child = child->list; child; child = child->next) { |
403 | indent += 2; | 404 | indent += 2; |
404 | conf(child->list); | 405 | conf(child); |
405 | indent -= 2; | 406 | indent -= 2; |
406 | } | 407 | } |
407 | return 1; | 408 | return 1; |
@@ -433,7 +434,7 @@ static void conf(struct menu *menu) | |||
433 | if (prompt) | 434 | if (prompt) |
434 | printf("%*c\n%*c %s\n%*c\n", | 435 | printf("%*c\n%*c %s\n%*c\n", |
435 | indent, '*', | 436 | indent, '*', |
436 | indent, '*', prompt, | 437 | indent, '*', _(prompt), |
437 | indent, '*'); | 438 | indent, '*'); |
438 | default: | 439 | default: |
439 | ; | 440 | ; |
@@ -495,12 +496,16 @@ static void check_conf(struct menu *menu) | |||
495 | 496 | ||
496 | int main(int ac, char **av) | 497 | int main(int ac, char **av) |
497 | { | 498 | { |
498 | int i = 1; | 499 | int opt; |
499 | const char *name; | 500 | const char *name; |
500 | struct stat tmpstat; | 501 | struct stat tmpstat; |
501 | 502 | ||
502 | if (ac > i && av[i][0] == '-') { | 503 | setlocale(LC_ALL, ""); |
503 | switch (av[i++][1]) { | 504 | bindtextdomain(PACKAGE, LOCALEDIR); |
505 | textdomain(PACKAGE); | ||
506 | |||
507 | while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) { | ||
508 | switch (opt) { | ||
504 | case 'o': | 509 | case 'o': |
505 | input_mode = ask_new; | 510 | input_mode = ask_new; |
506 | break; | 511 | break; |
@@ -513,12 +518,7 @@ int main(int ac, char **av) | |||
513 | break; | 518 | break; |
514 | case 'D': | 519 | case 'D': |
515 | input_mode = set_default; | 520 | input_mode = set_default; |
516 | defconfig_file = av[i++]; | 521 | defconfig_file = optarg; |
517 | if (!defconfig_file) { | ||
518 | printf(_("%s: No default config file specified\n"), | ||
519 | av[0]); | ||
520 | exit(1); | ||
521 | } | ||
522 | break; | 522 | break; |
523 | case 'n': | 523 | case 'n': |
524 | input_mode = set_no; | 524 | input_mode = set_no; |
@@ -531,19 +531,22 @@ int main(int ac, char **av) | |||
531 | break; | 531 | break; |
532 | case 'r': | 532 | case 'r': |
533 | input_mode = set_random; | 533 | input_mode = set_random; |
534 | srandom(time(NULL)); | 534 | srand(time(NULL)); |
535 | break; | 535 | break; |
536 | case 'h': | 536 | case 'h': |
537 | case '?': | 537 | printf(_("See README for usage info\n")); |
538 | fprintf(stderr, "See README for usage info\n"); | ||
539 | exit(0); | 538 | exit(0); |
539 | break; | ||
540 | default: | ||
541 | fprintf(stderr, _("See README for usage info\n")); | ||
542 | exit(1); | ||
540 | } | 543 | } |
541 | } | 544 | } |
542 | name = av[i]; | 545 | if (ac == optind) { |
543 | if (!name) { | ||
544 | printf(_("%s: Kconfig file missing\n"), av[0]); | 546 | printf(_("%s: Kconfig file missing\n"), av[0]); |
545 | exit(1); | 547 | exit(1); |
546 | } | 548 | } |
549 | name = av[optind]; | ||
547 | conf_parse(name); | 550 | conf_parse(name); |
548 | //zconfdump(stdout); | 551 | //zconfdump(stdout); |
549 | switch (input_mode) { | 552 | switch (input_mode) { |
@@ -551,9 +554,9 @@ int main(int ac, char **av) | |||
551 | if (!defconfig_file) | 554 | if (!defconfig_file) |
552 | defconfig_file = conf_get_default_confname(); | 555 | defconfig_file = conf_get_default_confname(); |
553 | if (conf_read(defconfig_file)) { | 556 | if (conf_read(defconfig_file)) { |
554 | printf("***\n" | 557 | printf(_("***\n" |
555 | "*** Can't find default configuration \"%s\"!\n" | 558 | "*** Can't find default configuration \"%s\"!\n" |
556 | "***\n", defconfig_file); | 559 | "***\n"), defconfig_file); |
557 | exit(1); | 560 | exit(1); |
558 | } | 561 | } |
559 | break; | 562 | break; |
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index e0f402f3b75d..ee5fe943d58d 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c | |||
@@ -232,8 +232,7 @@ load: | |||
232 | sym->type = S_BOOLEAN; | 232 | sym->type = S_BOOLEAN; |
233 | } | 233 | } |
234 | if (sym->flags & def_flags) { | 234 | if (sym->flags & def_flags) { |
235 | conf_warning("trying to reassign symbol %s", sym->name); | 235 | conf_warning("override: reassigning to symbol %s", sym->name); |
236 | break; | ||
237 | } | 236 | } |
238 | switch (sym->type) { | 237 | switch (sym->type) { |
239 | case S_BOOLEAN: | 238 | case S_BOOLEAN: |
@@ -272,8 +271,7 @@ load: | |||
272 | sym->type = S_OTHER; | 271 | sym->type = S_OTHER; |
273 | } | 272 | } |
274 | if (sym->flags & def_flags) { | 273 | if (sym->flags & def_flags) { |
275 | conf_warning("trying to reassign symbol %s", sym->name); | 274 | conf_warning("override: reassigning to symbol %s", sym->name); |
276 | break; | ||
277 | } | 275 | } |
278 | if (conf_set_sym_val(sym, def, def_flags, p)) | 276 | if (conf_set_sym_val(sym, def, def_flags, p)) |
279 | continue; | 277 | continue; |
@@ -297,14 +295,12 @@ load: | |||
297 | } | 295 | } |
298 | break; | 296 | break; |
299 | case yes: | 297 | case yes: |
300 | if (cs->def[def].tri != no) { | 298 | if (cs->def[def].tri != no) |
301 | conf_warning("%s creates inconsistent choice state", sym->name); | 299 | conf_warning("override: %s changes choice state", sym->name); |
302 | cs->flags &= ~def_flags; | 300 | cs->def[def].val = sym; |
303 | } else | ||
304 | cs->def[def].val = sym; | ||
305 | break; | 301 | break; |
306 | } | 302 | } |
307 | cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri); | 303 | cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); |
308 | } | 304 | } |
309 | } | 305 | } |
310 | fclose(in); | 306 | fclose(in); |
@@ -316,7 +312,7 @@ load: | |||
316 | 312 | ||
317 | int conf_read(const char *name) | 313 | int conf_read(const char *name) |
318 | { | 314 | { |
319 | struct symbol *sym; | 315 | struct symbol *sym, *choice_sym; |
320 | struct property *prop; | 316 | struct property *prop; |
321 | struct expr *e; | 317 | struct expr *e; |
322 | int i, flags; | 318 | int i, flags; |
@@ -357,9 +353,9 @@ int conf_read(const char *name) | |||
357 | */ | 353 | */ |
358 | prop = sym_get_choice_prop(sym); | 354 | prop = sym_get_choice_prop(sym); |
359 | flags = sym->flags; | 355 | flags = sym->flags; |
360 | for (e = prop->expr; e; e = e->left.expr) | 356 | expr_list_for_each_sym(prop->expr, e, choice_sym) |
361 | if (e->right.sym->visible != no) | 357 | if (choice_sym->visible != no) |
362 | flags &= e->right.sym->flags; | 358 | flags &= choice_sym->flags; |
363 | sym->flags &= flags | ~SYMBOL_DEF_USER; | 359 | sym->flags &= flags | ~SYMBOL_DEF_USER; |
364 | } | 360 | } |
365 | 361 | ||
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c index 6f98dbfe70cf..579ece4fa584 100644 --- a/scripts/kconfig/expr.c +++ b/scripts/kconfig/expr.c | |||
@@ -87,7 +87,7 @@ struct expr *expr_copy(struct expr *org) | |||
87 | break; | 87 | break; |
88 | case E_AND: | 88 | case E_AND: |
89 | case E_OR: | 89 | case E_OR: |
90 | case E_CHOICE: | 90 | case E_LIST: |
91 | e->left.expr = expr_copy(org->left.expr); | 91 | e->left.expr = expr_copy(org->left.expr); |
92 | e->right.expr = expr_copy(org->right.expr); | 92 | e->right.expr = expr_copy(org->right.expr); |
93 | break; | 93 | break; |
@@ -217,7 +217,7 @@ int expr_eq(struct expr *e1, struct expr *e2) | |||
217 | expr_free(e2); | 217 | expr_free(e2); |
218 | trans_count = old_count; | 218 | trans_count = old_count; |
219 | return res; | 219 | return res; |
220 | case E_CHOICE: | 220 | case E_LIST: |
221 | case E_RANGE: | 221 | case E_RANGE: |
222 | case E_NONE: | 222 | case E_NONE: |
223 | /* panic */; | 223 | /* panic */; |
@@ -648,7 +648,7 @@ struct expr *expr_transform(struct expr *e) | |||
648 | case E_EQUAL: | 648 | case E_EQUAL: |
649 | case E_UNEQUAL: | 649 | case E_UNEQUAL: |
650 | case E_SYMBOL: | 650 | case E_SYMBOL: |
651 | case E_CHOICE: | 651 | case E_LIST: |
652 | break; | 652 | break; |
653 | default: | 653 | default: |
654 | e->left.expr = expr_transform(e->left.expr); | 654 | e->left.expr = expr_transform(e->left.expr); |
@@ -932,7 +932,7 @@ struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symb | |||
932 | break; | 932 | break; |
933 | case E_SYMBOL: | 933 | case E_SYMBOL: |
934 | return expr_alloc_comp(type, e->left.sym, sym); | 934 | return expr_alloc_comp(type, e->left.sym, sym); |
935 | case E_CHOICE: | 935 | case E_LIST: |
936 | case E_RANGE: | 936 | case E_RANGE: |
937 | case E_NONE: | 937 | case E_NONE: |
938 | /* panic */; | 938 | /* panic */; |
@@ -955,14 +955,14 @@ tristate expr_calc_value(struct expr *e) | |||
955 | case E_AND: | 955 | case E_AND: |
956 | val1 = expr_calc_value(e->left.expr); | 956 | val1 = expr_calc_value(e->left.expr); |
957 | val2 = expr_calc_value(e->right.expr); | 957 | val2 = expr_calc_value(e->right.expr); |
958 | return E_AND(val1, val2); | 958 | return EXPR_AND(val1, val2); |
959 | case E_OR: | 959 | case E_OR: |
960 | val1 = expr_calc_value(e->left.expr); | 960 | val1 = expr_calc_value(e->left.expr); |
961 | val2 = expr_calc_value(e->right.expr); | 961 | val2 = expr_calc_value(e->right.expr); |
962 | return E_OR(val1, val2); | 962 | return EXPR_OR(val1, val2); |
963 | case E_NOT: | 963 | case E_NOT: |
964 | val1 = expr_calc_value(e->left.expr); | 964 | val1 = expr_calc_value(e->left.expr); |
965 | return E_NOT(val1); | 965 | return EXPR_NOT(val1); |
966 | case E_EQUAL: | 966 | case E_EQUAL: |
967 | sym_calc_value(e->left.sym); | 967 | sym_calc_value(e->left.sym); |
968 | sym_calc_value(e->right.sym); | 968 | sym_calc_value(e->right.sym); |
@@ -1000,9 +1000,9 @@ int expr_compare_type(enum expr_type t1, enum expr_type t2) | |||
1000 | if (t2 == E_OR) | 1000 | if (t2 == E_OR) |
1001 | return 1; | 1001 | return 1; |
1002 | case E_OR: | 1002 | case E_OR: |
1003 | if (t2 == E_CHOICE) | 1003 | if (t2 == E_LIST) |
1004 | return 1; | 1004 | return 1; |
1005 | case E_CHOICE: | 1005 | case E_LIST: |
1006 | if (t2 == 0) | 1006 | if (t2 == 0) |
1007 | return 1; | 1007 | return 1; |
1008 | default: | 1008 | default: |
@@ -1034,12 +1034,18 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char * | |||
1034 | expr_print(e->left.expr, fn, data, E_NOT); | 1034 | expr_print(e->left.expr, fn, data, E_NOT); |
1035 | break; | 1035 | break; |
1036 | case E_EQUAL: | 1036 | case E_EQUAL: |
1037 | fn(data, e->left.sym, e->left.sym->name); | 1037 | if (e->left.sym->name) |
1038 | fn(data, e->left.sym, e->left.sym->name); | ||
1039 | else | ||
1040 | fn(data, NULL, "<choice>"); | ||
1038 | fn(data, NULL, "="); | 1041 | fn(data, NULL, "="); |
1039 | fn(data, e->right.sym, e->right.sym->name); | 1042 | fn(data, e->right.sym, e->right.sym->name); |
1040 | break; | 1043 | break; |
1041 | case E_UNEQUAL: | 1044 | case E_UNEQUAL: |
1042 | fn(data, e->left.sym, e->left.sym->name); | 1045 | if (e->left.sym->name) |
1046 | fn(data, e->left.sym, e->left.sym->name); | ||
1047 | else | ||
1048 | fn(data, NULL, "<choice>"); | ||
1043 | fn(data, NULL, "!="); | 1049 | fn(data, NULL, "!="); |
1044 | fn(data, e->right.sym, e->right.sym->name); | 1050 | fn(data, e->right.sym, e->right.sym->name); |
1045 | break; | 1051 | break; |
@@ -1053,11 +1059,11 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char * | |||
1053 | fn(data, NULL, " && "); | 1059 | fn(data, NULL, " && "); |
1054 | expr_print(e->right.expr, fn, data, E_AND); | 1060 | expr_print(e->right.expr, fn, data, E_AND); |
1055 | break; | 1061 | break; |
1056 | case E_CHOICE: | 1062 | case E_LIST: |
1057 | fn(data, e->right.sym, e->right.sym->name); | 1063 | fn(data, e->right.sym, e->right.sym->name); |
1058 | if (e->left.expr) { | 1064 | if (e->left.expr) { |
1059 | fn(data, NULL, " ^ "); | 1065 | fn(data, NULL, " ^ "); |
1060 | expr_print(e->left.expr, fn, data, E_CHOICE); | 1066 | expr_print(e->left.expr, fn, data, E_LIST); |
1061 | } | 1067 | } |
1062 | break; | 1068 | break; |
1063 | case E_RANGE: | 1069 | case E_RANGE: |
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index a195986eec6f..9d4cba1c001d 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h | |||
@@ -25,14 +25,13 @@ struct file { | |||
25 | 25 | ||
26 | #define FILE_BUSY 0x0001 | 26 | #define FILE_BUSY 0x0001 |
27 | #define FILE_SCANNED 0x0002 | 27 | #define FILE_SCANNED 0x0002 |
28 | #define FILE_PRINTED 0x0004 | ||
29 | 28 | ||
30 | typedef enum tristate { | 29 | typedef enum tristate { |
31 | no, mod, yes | 30 | no, mod, yes |
32 | } tristate; | 31 | } tristate; |
33 | 32 | ||
34 | enum expr_type { | 33 | enum expr_type { |
35 | E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_CHOICE, E_SYMBOL, E_RANGE | 34 | E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE |
36 | }; | 35 | }; |
37 | 36 | ||
38 | union expr_data { | 37 | union expr_data { |
@@ -45,9 +44,12 @@ struct expr { | |||
45 | union expr_data left, right; | 44 | union expr_data left, right; |
46 | }; | 45 | }; |
47 | 46 | ||
48 | #define E_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) | 47 | #define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) |
49 | #define E_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) | 48 | #define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) |
50 | #define E_NOT(dep) (2-(dep)) | 49 | #define EXPR_NOT(dep) (2-(dep)) |
50 | |||
51 | #define expr_list_for_each_sym(l, e, s) \ | ||
52 | for (e = (l); e && (s = e->right.sym); e = e->left.expr) | ||
51 | 53 | ||
52 | struct expr_value { | 54 | struct expr_value { |
53 | struct expr *expr; | 55 | struct expr *expr; |
@@ -86,7 +88,6 @@ struct symbol { | |||
86 | #define SYMBOL_CHECK 0x0008 | 88 | #define SYMBOL_CHECK 0x0008 |
87 | #define SYMBOL_CHOICE 0x0010 | 89 | #define SYMBOL_CHOICE 0x0010 |
88 | #define SYMBOL_CHOICEVAL 0x0020 | 90 | #define SYMBOL_CHOICEVAL 0x0020 |
89 | #define SYMBOL_PRINTED 0x0040 | ||
90 | #define SYMBOL_VALID 0x0080 | 91 | #define SYMBOL_VALID 0x0080 |
91 | #define SYMBOL_OPTIONAL 0x0100 | 92 | #define SYMBOL_OPTIONAL 0x0100 |
92 | #define SYMBOL_WRITE 0x0200 | 93 | #define SYMBOL_WRITE 0x0200 |
@@ -105,7 +106,8 @@ struct symbol { | |||
105 | #define SYMBOL_HASHMASK 0xff | 106 | #define SYMBOL_HASHMASK 0xff |
106 | 107 | ||
107 | enum prop_type { | 108 | enum prop_type { |
108 | P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, P_SELECT, P_RANGE | 109 | P_UNKNOWN, P_PROMPT, P_COMMENT, P_MENU, P_DEFAULT, P_CHOICE, |
110 | P_SELECT, P_RANGE, P_ENV | ||
109 | }; | 111 | }; |
110 | 112 | ||
111 | struct property { | 113 | struct property { |
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c index 262908cfc2ac..199b22bb49e2 100644 --- a/scripts/kconfig/gconf.c +++ b/scripts/kconfig/gconf.c | |||
@@ -119,8 +119,6 @@ const char *dbg_print_flags(int val) | |||
119 | strcat(buf, "choice/"); | 119 | strcat(buf, "choice/"); |
120 | if (val & SYMBOL_CHOICEVAL) | 120 | if (val & SYMBOL_CHOICEVAL) |
121 | strcat(buf, "choiceval/"); | 121 | strcat(buf, "choiceval/"); |
122 | if (val & SYMBOL_PRINTED) | ||
123 | strcat(buf, "printed/"); | ||
124 | if (val & SYMBOL_VALID) | 122 | if (val & SYMBOL_VALID) |
125 | strcat(buf, "valid/"); | 123 | strcat(buf, "valid/"); |
126 | if (val & SYMBOL_OPTIONAL) | 124 | if (val & SYMBOL_OPTIONAL) |
@@ -457,14 +455,18 @@ static void text_insert_help(struct menu *menu) | |||
457 | { | 455 | { |
458 | GtkTextBuffer *buffer; | 456 | GtkTextBuffer *buffer; |
459 | GtkTextIter start, end; | 457 | GtkTextIter start, end; |
460 | const char *prompt = menu_get_prompt(menu); | 458 | const char *prompt = _(menu_get_prompt(menu)); |
461 | gchar *name; | 459 | gchar *name; |
462 | const char *help; | 460 | const char *help; |
463 | 461 | ||
464 | help = _(menu_get_help(menu)); | 462 | help = menu_get_help(menu); |
463 | |||
464 | /* Gettextize if the help text not empty */ | ||
465 | if ((help != 0) && (help[0] != 0)) | ||
466 | help = _(help); | ||
465 | 467 | ||
466 | if (menu->sym && menu->sym->name) | 468 | if (menu->sym && menu->sym->name) |
467 | name = g_strdup_printf(_(menu->sym->name)); | 469 | name = g_strdup_printf(menu->sym->name); |
468 | else | 470 | else |
469 | name = g_strdup(""); | 471 | name = g_strdup(""); |
470 | 472 | ||
@@ -1171,7 +1173,7 @@ static gchar **fill_row(struct menu *menu) | |||
1171 | bzero(row, sizeof(row)); | 1173 | bzero(row, sizeof(row)); |
1172 | 1174 | ||
1173 | row[COL_OPTION] = | 1175 | row[COL_OPTION] = |
1174 | g_strdup_printf("%s %s", menu_get_prompt(menu), | 1176 | g_strdup_printf("%s %s", _(menu_get_prompt(menu)), |
1175 | sym && sym_has_value(sym) ? "(NEW)" : ""); | 1177 | sym && sym_has_value(sym) ? "(NEW)" : ""); |
1176 | 1178 | ||
1177 | if (show_all && !menu_is_visible(menu)) | 1179 | if (show_all && !menu_is_visible(menu)) |
@@ -1221,7 +1223,7 @@ static gchar **fill_row(struct menu *menu) | |||
1221 | 1223 | ||
1222 | if (def_menu) | 1224 | if (def_menu) |
1223 | row[COL_VALUE] = | 1225 | row[COL_VALUE] = |
1224 | g_strdup(menu_get_prompt(def_menu)); | 1226 | g_strdup(_(menu_get_prompt(def_menu))); |
1225 | } | 1227 | } |
1226 | if (sym->flags & SYMBOL_CHOICEVAL) | 1228 | if (sym->flags & SYMBOL_CHOICEVAL) |
1227 | row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); | 1229 | row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); |
diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped index a065d5a57c01..bed0f4e2d2f7 100644 --- a/scripts/kconfig/lex.zconf.c_shipped +++ b/scripts/kconfig/lex.zconf.c_shipped | |||
@@ -1275,6 +1275,11 @@ YY_RULE_SETUP | |||
1275 | case 32: | 1275 | case 32: |
1276 | YY_RULE_SETUP | 1276 | YY_RULE_SETUP |
1277 | { | 1277 | { |
1278 | while (zconfleng) { | ||
1279 | if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t')) | ||
1280 | break; | ||
1281 | zconfleng--; | ||
1282 | } | ||
1278 | append_string(zconftext, zconfleng); | 1283 | append_string(zconftext, zconfleng); |
1279 | if (!first_ts) | 1284 | if (!first_ts) |
1280 | first_ts = last_ts; | 1285 | first_ts = last_ts; |
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index 8a07ee4f6bd4..4bc68f20a73c 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h | |||
@@ -44,6 +44,7 @@ extern "C" { | |||
44 | 44 | ||
45 | #define T_OPT_MODULES 1 | 45 | #define T_OPT_MODULES 1 |
46 | #define T_OPT_DEFCONFIG_LIST 2 | 46 | #define T_OPT_DEFCONFIG_LIST 2 |
47 | #define T_OPT_ENV 3 | ||
47 | 48 | ||
48 | struct kconf_id { | 49 | struct kconf_id { |
49 | int name; | 50 | int name; |
@@ -74,6 +75,7 @@ void kconfig_load(void); | |||
74 | 75 | ||
75 | /* menu.c */ | 76 | /* menu.c */ |
76 | void menu_init(void); | 77 | void menu_init(void); |
78 | void menu_warn(struct menu *menu, const char *fmt, ...); | ||
77 | struct menu *menu_add_menu(void); | 79 | struct menu *menu_add_menu(void); |
78 | void menu_end_menu(void); | 80 | void menu_end_menu(void); |
79 | void menu_add_entry(struct symbol *sym); | 81 | void menu_add_entry(struct symbol *sym); |
@@ -103,6 +105,8 @@ void str_printf(struct gstr *gs, const char *fmt, ...); | |||
103 | const char *str_get(struct gstr *gs); | 105 | const char *str_get(struct gstr *gs); |
104 | 106 | ||
105 | /* symbol.c */ | 107 | /* symbol.c */ |
108 | extern struct expr *sym_env_list; | ||
109 | |||
106 | void sym_init(void); | 110 | void sym_init(void); |
107 | void sym_clear_all_valid(void); | 111 | void sym_clear_all_valid(void); |
108 | void sym_set_all_changed(void); | 112 | void sym_set_all_changed(void); |
@@ -110,6 +114,7 @@ void sym_set_changed(struct symbol *sym); | |||
110 | struct symbol *sym_check_deps(struct symbol *sym); | 114 | struct symbol *sym_check_deps(struct symbol *sym); |
111 | struct property *prop_alloc(enum prop_type type, struct symbol *sym); | 115 | struct property *prop_alloc(enum prop_type type, struct symbol *sym); |
112 | struct symbol *prop_get_symbol(struct property *prop); | 116 | struct symbol *prop_get_symbol(struct property *prop); |
117 | struct property *sym_get_env_prop(struct symbol *sym); | ||
113 | 118 | ||
114 | static inline tristate sym_get_tristate_value(struct symbol *sym) | 119 | static inline tristate sym_get_tristate_value(struct symbol *sym) |
115 | { | 120 | { |
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh index 9681476b96e7..62e1e02126e6 100644 --- a/scripts/kconfig/lxdialog/check-lxdialog.sh +++ b/scripts/kconfig/lxdialog/check-lxdialog.sh | |||
@@ -36,14 +36,16 @@ trap "rm -f $tmp" 0 1 2 3 15 | |||
36 | 36 | ||
37 | # Check if we can link to ncurses | 37 | # Check if we can link to ncurses |
38 | check() { | 38 | check() { |
39 | echo "main() {}" | $cc -xc - -o $tmp 2> /dev/null | 39 | echo -e " #include CURSES_LOC \n main() {}" | |
40 | $cc -xc - -o $tmp 2> /dev/null | ||
40 | if [ $? != 0 ]; then | 41 | if [ $? != 0 ]; then |
41 | echo " *** Unable to find the ncurses libraries." 1>&2 | 42 | echo " *** Unable to find the ncurses libraries or the" 1>&2 |
42 | echo " *** make menuconfig require the ncurses libraries" 1>&2 | 43 | echo " *** required header files." 1>&2 |
43 | echo " *** " 1>&2 | 44 | echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 |
44 | echo " *** Install ncurses (ncurses-devel) and try again" 1>&2 | 45 | echo " *** " 1>&2 |
45 | echo " *** " 1>&2 | 46 | echo " *** Install ncurses (ncurses-devel) and try again." 1>&2 |
46 | exit 1 | 47 | echo " *** " 1>&2 |
48 | exit 1 | ||
47 | fi | 49 | fi |
48 | } | 50 | } |
49 | 51 | ||
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c index cf697080dddd..b2a878c936d6 100644 --- a/scripts/kconfig/lxdialog/checklist.c +++ b/scripts/kconfig/lxdialog/checklist.c | |||
@@ -97,8 +97,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) | |||
97 | int x = width / 2 - 11; | 97 | int x = width / 2 - 11; |
98 | int y = height - 2; | 98 | int y = height - 2; |
99 | 99 | ||
100 | print_button(dialog, "Select", y, x, selected == 0); | 100 | print_button(dialog, gettext("Select"), y, x, selected == 0); |
101 | print_button(dialog, " Help ", y, x + 14, selected == 1); | 101 | print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); |
102 | 102 | ||
103 | wmove(dialog, y, x + 1 + 14 * selected); | 103 | wmove(dialog, y, x + 1 + 14 * selected); |
104 | wrefresh(dialog); | 104 | wrefresh(dialog); |
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h index 7e17eba75ae8..b5211fce0d94 100644 --- a/scripts/kconfig/lxdialog/dialog.h +++ b/scripts/kconfig/lxdialog/dialog.h | |||
@@ -26,6 +26,12 @@ | |||
26 | #include <string.h> | 26 | #include <string.h> |
27 | #include <stdbool.h> | 27 | #include <stdbool.h> |
28 | 28 | ||
29 | #ifndef KBUILD_NO_NLS | ||
30 | # include <libintl.h> | ||
31 | #else | ||
32 | # define gettext(Msgid) ((const char *) (Msgid)) | ||
33 | #endif | ||
34 | |||
29 | #ifdef __sun__ | 35 | #ifdef __sun__ |
30 | #define CURS_MACROS | 36 | #define CURS_MACROS |
31 | #endif | 37 | #endif |
@@ -187,10 +193,9 @@ int item_is_tag(char tag); | |||
187 | int on_key_esc(WINDOW *win); | 193 | int on_key_esc(WINDOW *win); |
188 | int on_key_resize(void); | 194 | int on_key_resize(void); |
189 | 195 | ||
190 | void init_dialog(const char *backtitle); | 196 | int init_dialog(const char *backtitle); |
191 | void set_dialog_backtitle(const char *backtitle); | 197 | void set_dialog_backtitle(const char *backtitle); |
192 | void reset_dialog(void); | 198 | void end_dialog(int x, int y); |
193 | void end_dialog(void); | ||
194 | void attr_clear(WINDOW * win, int height, int width, chtype attr); | 199 | void attr_clear(WINDOW * win, int height, int width, chtype attr); |
195 | void dialog_clear(void); | 200 | void dialog_clear(void); |
196 | void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); | 201 | void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); |
diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c index 05e72066b359..4946bd02b46d 100644 --- a/scripts/kconfig/lxdialog/inputbox.c +++ b/scripts/kconfig/lxdialog/inputbox.c | |||
@@ -31,8 +31,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) | |||
31 | int x = width / 2 - 11; | 31 | int x = width / 2 - 11; |
32 | int y = height - 2; | 32 | int y = height - 2; |
33 | 33 | ||
34 | print_button(dialog, " Ok ", y, x, selected == 0); | 34 | print_button(dialog, gettext(" Ok "), y, x, selected == 0); |
35 | print_button(dialog, " Help ", y, x + 14, selected == 1); | 35 | print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); |
36 | 36 | ||
37 | wmove(dialog, y, x + 1 + 14 * selected); | 37 | wmove(dialog, y, x + 1 + 14 * selected); |
38 | wrefresh(dialog); | 38 | wrefresh(dialog); |
diff --git a/scripts/kconfig/lxdialog/menubox.c b/scripts/kconfig/lxdialog/menubox.c index 0d83159d9012..fa9d633f293c 100644 --- a/scripts/kconfig/lxdialog/menubox.c +++ b/scripts/kconfig/lxdialog/menubox.c | |||
@@ -157,9 +157,9 @@ static void print_buttons(WINDOW * win, int height, int width, int selected) | |||
157 | int x = width / 2 - 16; | 157 | int x = width / 2 - 16; |
158 | int y = height - 2; | 158 | int y = height - 2; |
159 | 159 | ||
160 | print_button(win, "Select", y, x, selected == 0); | 160 | print_button(win, gettext("Select"), y, x, selected == 0); |
161 | print_button(win, " Exit ", y, x + 12, selected == 1); | 161 | print_button(win, gettext(" Exit "), y, x + 12, selected == 1); |
162 | print_button(win, " Help ", y, x + 24, selected == 2); | 162 | print_button(win, gettext(" Help "), y, x + 24, selected == 2); |
163 | 163 | ||
164 | wmove(win, y, x + 1 + 12 * selected); | 164 | wmove(win, y, x + 1 + 12 * selected); |
165 | wrefresh(win); | 165 | wrefresh(win); |
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c index fabfc1ad789d..c704712d0227 100644 --- a/scripts/kconfig/lxdialog/textbox.c +++ b/scripts/kconfig/lxdialog/textbox.c | |||
@@ -114,7 +114,7 @@ do_resize: | |||
114 | 114 | ||
115 | print_title(dialog, title, width); | 115 | print_title(dialog, title, width); |
116 | 116 | ||
117 | print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE); | 117 | print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); |
118 | wnoutrefresh(dialog); | 118 | wnoutrefresh(dialog); |
119 | getyx(dialog, cur_y, cur_x); /* Save cursor position */ | 119 | getyx(dialog, cur_y, cur_x); /* Save cursor position */ |
120 | 120 | ||
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c index a1bddefe73d0..86d95cca46a7 100644 --- a/scripts/kconfig/lxdialog/util.c +++ b/scripts/kconfig/lxdialog/util.c | |||
@@ -266,31 +266,41 @@ void dialog_clear(void) | |||
266 | /* | 266 | /* |
267 | * Do some initialization for dialog | 267 | * Do some initialization for dialog |
268 | */ | 268 | */ |
269 | void init_dialog(const char *backtitle) | 269 | int init_dialog(const char *backtitle) |
270 | { | 270 | { |
271 | dlg.backtitle = backtitle; | 271 | int height, width; |
272 | color_setup(getenv("MENUCONFIG_COLOR")); | 272 | |
273 | } | 273 | initscr(); /* Init curses */ |
274 | getmaxyx(stdscr, height, width); | ||
275 | if (height < 19 || width < 80) { | ||
276 | endwin(); | ||
277 | return -ERRDISPLAYTOOSMALL; | ||
278 | } | ||
274 | 279 | ||
275 | void set_dialog_backtitle(const char *backtitle) | ||
276 | { | ||
277 | dlg.backtitle = backtitle; | 280 | dlg.backtitle = backtitle; |
278 | } | 281 | color_setup(getenv("MENUCONFIG_COLOR")); |
279 | 282 | ||
280 | void reset_dialog(void) | ||
281 | { | ||
282 | initscr(); /* Init curses */ | ||
283 | keypad(stdscr, TRUE); | 283 | keypad(stdscr, TRUE); |
284 | cbreak(); | 284 | cbreak(); |
285 | noecho(); | 285 | noecho(); |
286 | dialog_clear(); | 286 | dialog_clear(); |
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | void set_dialog_backtitle(const char *backtitle) | ||
292 | { | ||
293 | dlg.backtitle = backtitle; | ||
287 | } | 294 | } |
288 | 295 | ||
289 | /* | 296 | /* |
290 | * End using dialog functions. | 297 | * End using dialog functions. |
291 | */ | 298 | */ |
292 | void end_dialog(void) | 299 | void end_dialog(int x, int y) |
293 | { | 300 | { |
301 | /* move cursor back to original position */ | ||
302 | move(y, x); | ||
303 | refresh(); | ||
294 | endwin(); | 304 | endwin(); |
295 | } | 305 | } |
296 | 306 | ||
diff --git a/scripts/kconfig/lxdialog/yesno.c b/scripts/kconfig/lxdialog/yesno.c index ee0a04e3e012..4e6e8090c20b 100644 --- a/scripts/kconfig/lxdialog/yesno.c +++ b/scripts/kconfig/lxdialog/yesno.c | |||
@@ -29,8 +29,8 @@ static void print_buttons(WINDOW * dialog, int height, int width, int selected) | |||
29 | int x = width / 2 - 10; | 29 | int x = width / 2 - 10; |
30 | int y = height - 2; | 30 | int y = height - 2; |
31 | 31 | ||
32 | print_button(dialog, " Yes ", y, x, selected == 0); | 32 | print_button(dialog, gettext(" Yes "), y, x, selected == 0); |
33 | print_button(dialog, " No ", y, x + 13, selected == 1); | 33 | print_button(dialog, gettext(" No "), y, x + 13, selected == 1); |
34 | 34 | ||
35 | wmove(dialog, y, x + 1 + 13 * selected); | 35 | wmove(dialog, y, x + 1 + 13 * selected); |
36 | wrefresh(dialog); | 36 | wrefresh(dialog); |
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 47e226fdedd7..50e61c411bc0 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c | |||
@@ -8,17 +8,13 @@ | |||
8 | * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 8 | * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <sys/ioctl.h> | ||
12 | #include <sys/wait.h> | ||
13 | #include <ctype.h> | 11 | #include <ctype.h> |
14 | #include <errno.h> | 12 | #include <errno.h> |
15 | #include <fcntl.h> | 13 | #include <fcntl.h> |
16 | #include <limits.h> | 14 | #include <limits.h> |
17 | #include <signal.h> | ||
18 | #include <stdarg.h> | 15 | #include <stdarg.h> |
19 | #include <stdlib.h> | 16 | #include <stdlib.h> |
20 | #include <string.h> | 17 | #include <string.h> |
21 | #include <termios.h> | ||
22 | #include <unistd.h> | 18 | #include <unistd.h> |
23 | #include <locale.h> | 19 | #include <locale.h> |
24 | 20 | ||
@@ -275,8 +271,6 @@ search_help[] = N_( | |||
275 | "\n"); | 271 | "\n"); |
276 | 272 | ||
277 | static int indent; | 273 | static int indent; |
278 | static struct termios ios_org; | ||
279 | static int rows = 0, cols = 0; | ||
280 | static struct menu *current_menu; | 274 | static struct menu *current_menu; |
281 | static int child_count; | 275 | static int child_count; |
282 | static int single_menu_mode; | 276 | static int single_menu_mode; |
@@ -290,51 +284,16 @@ static void show_textbox(const char *title, const char *text, int r, int c); | |||
290 | static void show_helptext(const char *title, const char *text); | 284 | static void show_helptext(const char *title, const char *text); |
291 | static void show_help(struct menu *menu); | 285 | static void show_help(struct menu *menu); |
292 | 286 | ||
293 | static void init_wsize(void) | ||
294 | { | ||
295 | struct winsize ws; | ||
296 | char *env; | ||
297 | |||
298 | if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) { | ||
299 | rows = ws.ws_row; | ||
300 | cols = ws.ws_col; | ||
301 | } | ||
302 | |||
303 | if (!rows) { | ||
304 | env = getenv("LINES"); | ||
305 | if (env) | ||
306 | rows = atoi(env); | ||
307 | if (!rows) | ||
308 | rows = 24; | ||
309 | } | ||
310 | if (!cols) { | ||
311 | env = getenv("COLUMNS"); | ||
312 | if (env) | ||
313 | cols = atoi(env); | ||
314 | if (!cols) | ||
315 | cols = 80; | ||
316 | } | ||
317 | |||
318 | if (rows < 19 || cols < 80) { | ||
319 | fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); | ||
320 | fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); | ||
321 | exit(1); | ||
322 | } | ||
323 | |||
324 | rows -= 4; | ||
325 | cols -= 5; | ||
326 | } | ||
327 | |||
328 | static void get_prompt_str(struct gstr *r, struct property *prop) | 287 | static void get_prompt_str(struct gstr *r, struct property *prop) |
329 | { | 288 | { |
330 | int i, j; | 289 | int i, j; |
331 | struct menu *submenu[8], *menu; | 290 | struct menu *submenu[8], *menu; |
332 | 291 | ||
333 | str_printf(r, "Prompt: %s\n", prop->text); | 292 | str_printf(r, _("Prompt: %s\n"), _(prop->text)); |
334 | str_printf(r, " Defined at %s:%d\n", prop->menu->file->name, | 293 | str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, |
335 | prop->menu->lineno); | 294 | prop->menu->lineno); |
336 | if (!expr_is_yes(prop->visible.expr)) { | 295 | if (!expr_is_yes(prop->visible.expr)) { |
337 | str_append(r, " Depends on: "); | 296 | str_append(r, _(" Depends on: ")); |
338 | expr_gstr_print(prop->visible.expr, r); | 297 | expr_gstr_print(prop->visible.expr, r); |
339 | str_append(r, "\n"); | 298 | str_append(r, "\n"); |
340 | } | 299 | } |
@@ -342,13 +301,13 @@ static void get_prompt_str(struct gstr *r, struct property *prop) | |||
342 | for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) | 301 | for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) |
343 | submenu[i++] = menu; | 302 | submenu[i++] = menu; |
344 | if (i > 0) { | 303 | if (i > 0) { |
345 | str_printf(r, " Location:\n"); | 304 | str_printf(r, _(" Location:\n")); |
346 | for (j = 4; --i >= 0; j += 2) { | 305 | for (j = 4; --i >= 0; j += 2) { |
347 | menu = submenu[i]; | 306 | menu = submenu[i]; |
348 | str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu)); | 307 | str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); |
349 | if (menu->sym) { | 308 | if (menu->sym) { |
350 | str_printf(r, " (%s [=%s])", menu->sym->name ? | 309 | str_printf(r, " (%s [=%s])", menu->sym->name ? |
351 | menu->sym->name : "<choice>", | 310 | menu->sym->name : _("<choice>"), |
352 | sym_get_string_value(menu->sym)); | 311 | sym_get_string_value(menu->sym)); |
353 | } | 312 | } |
354 | str_append(r, "\n"); | 313 | str_append(r, "\n"); |
@@ -378,7 +337,7 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym) | |||
378 | if (hit) | 337 | if (hit) |
379 | str_append(r, "\n"); | 338 | str_append(r, "\n"); |
380 | if (sym->rev_dep.expr) { | 339 | if (sym->rev_dep.expr) { |
381 | str_append(r, " Selected by: "); | 340 | str_append(r, _(" Selected by: ")); |
382 | expr_gstr_print(sym->rev_dep.expr, r); | 341 | expr_gstr_print(sym->rev_dep.expr, r); |
383 | str_append(r, "\n"); | 342 | str_append(r, "\n"); |
384 | } | 343 | } |
@@ -394,7 +353,7 @@ static struct gstr get_relations_str(struct symbol **sym_arr) | |||
394 | for (i = 0; sym_arr && (sym = sym_arr[i]); i++) | 353 | for (i = 0; sym_arr && (sym = sym_arr[i]); i++) |
395 | get_symbol_str(&res, sym); | 354 | get_symbol_str(&res, sym); |
396 | if (!i) | 355 | if (!i) |
397 | str_append(&res, "No matches found.\n"); | 356 | str_append(&res, _("No matches found.\n")); |
398 | return res; | 357 | return res; |
399 | } | 358 | } |
400 | 359 | ||
@@ -474,6 +433,7 @@ static void build_conf(struct menu *menu) | |||
474 | switch (prop->type) { | 433 | switch (prop->type) { |
475 | case P_MENU: | 434 | case P_MENU: |
476 | child_count++; | 435 | child_count++; |
436 | prompt = _(prompt); | ||
477 | if (single_menu_mode) { | 437 | if (single_menu_mode) { |
478 | item_make("%s%*c%s", | 438 | item_make("%s%*c%s", |
479 | menu->data ? "-->" : "++>", | 439 | menu->data ? "-->" : "++>", |
@@ -489,7 +449,7 @@ static void build_conf(struct menu *menu) | |||
489 | case P_COMMENT: | 449 | case P_COMMENT: |
490 | if (prompt) { | 450 | if (prompt) { |
491 | child_count++; | 451 | child_count++; |
492 | item_make(" %*c*** %s ***", indent + 1, ' ', prompt); | 452 | item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt)); |
493 | item_set_tag(':'); | 453 | item_set_tag(':'); |
494 | item_set_data(menu); | 454 | item_set_data(menu); |
495 | } | 455 | } |
@@ -497,7 +457,7 @@ static void build_conf(struct menu *menu) | |||
497 | default: | 457 | default: |
498 | if (prompt) { | 458 | if (prompt) { |
499 | child_count++; | 459 | child_count++; |
500 | item_make("---%*c%s", indent + 1, ' ', prompt); | 460 | item_make("---%*c%s", indent + 1, ' ', _(prompt)); |
501 | item_set_tag(':'); | 461 | item_set_tag(':'); |
502 | item_set_data(menu); | 462 | item_set_data(menu); |
503 | } | 463 | } |
@@ -541,10 +501,10 @@ static void build_conf(struct menu *menu) | |||
541 | item_set_data(menu); | 501 | item_set_data(menu); |
542 | } | 502 | } |
543 | 503 | ||
544 | item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu)); | 504 | item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); |
545 | if (val == yes) { | 505 | if (val == yes) { |
546 | if (def_menu) { | 506 | if (def_menu) { |
547 | item_add_str(" (%s)", menu_get_prompt(def_menu)); | 507 | item_add_str(" (%s)", _(menu_get_prompt(def_menu))); |
548 | item_add_str(" --->"); | 508 | item_add_str(" --->"); |
549 | if (def_menu->list) { | 509 | if (def_menu->list) { |
550 | indent += 2; | 510 | indent += 2; |
@@ -556,7 +516,7 @@ static void build_conf(struct menu *menu) | |||
556 | } | 516 | } |
557 | } else { | 517 | } else { |
558 | if (menu == current_menu) { | 518 | if (menu == current_menu) { |
559 | item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu)); | 519 | item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); |
560 | item_set_tag(':'); | 520 | item_set_tag(':'); |
561 | item_set_data(menu); | 521 | item_set_data(menu); |
562 | goto conf_childs; | 522 | goto conf_childs; |
@@ -599,17 +559,17 @@ static void build_conf(struct menu *menu) | |||
599 | tmp = indent - tmp + 4; | 559 | tmp = indent - tmp + 4; |
600 | if (tmp < 0) | 560 | if (tmp < 0) |
601 | tmp = 0; | 561 | tmp = 0; |
602 | item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu), | 562 | item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), |
603 | (sym_has_value(sym) || !sym_is_changable(sym)) ? | 563 | (sym_has_value(sym) || !sym_is_changable(sym)) ? |
604 | "" : " (NEW)"); | 564 | "" : _(" (NEW)")); |
605 | item_set_tag('s'); | 565 | item_set_tag('s'); |
606 | item_set_data(menu); | 566 | item_set_data(menu); |
607 | goto conf_childs; | 567 | goto conf_childs; |
608 | } | 568 | } |
609 | } | 569 | } |
610 | item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu), | 570 | item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), |
611 | (sym_has_value(sym) || !sym_is_changable(sym)) ? | 571 | (sym_has_value(sym) || !sym_is_changable(sym)) ? |
612 | "" : " (NEW)"); | 572 | "" : _(" (NEW)")); |
613 | if (menu->prompt->type == P_MENU) { | 573 | if (menu->prompt->type == P_MENU) { |
614 | item_add_str(" --->"); | 574 | item_add_str(" --->"); |
615 | return; | 575 | return; |
@@ -647,7 +607,7 @@ static void conf(struct menu *menu) | |||
647 | item_set_tag('S'); | 607 | item_set_tag('S'); |
648 | } | 608 | } |
649 | dialog_clear(); | 609 | dialog_clear(); |
650 | res = dialog_menu(prompt ? prompt : _("Main Menu"), | 610 | res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), |
651 | _(menu_instructions), | 611 | _(menu_instructions), |
652 | active_menu, &s_scroll); | 612 | active_menu, &s_scroll); |
653 | if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) | 613 | if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) |
@@ -694,7 +654,7 @@ static void conf(struct menu *menu) | |||
694 | if (sym) | 654 | if (sym) |
695 | show_help(submenu); | 655 | show_help(submenu); |
696 | else | 656 | else |
697 | show_helptext("README", _(mconf_readme)); | 657 | show_helptext(_("README"), _(mconf_readme)); |
698 | break; | 658 | break; |
699 | case 3: | 659 | case 3: |
700 | if (item_is_tag('t')) { | 660 | if (item_is_tag('t')) { |
@@ -752,13 +712,13 @@ static void show_help(struct menu *menu) | |||
752 | str_append(&help, nohelp_text); | 712 | str_append(&help, nohelp_text); |
753 | } | 713 | } |
754 | get_symbol_str(&help, sym); | 714 | get_symbol_str(&help, sym); |
755 | show_helptext(menu_get_prompt(menu), str_get(&help)); | 715 | show_helptext(_(menu_get_prompt(menu)), str_get(&help)); |
756 | str_free(&help); | 716 | str_free(&help); |
757 | } | 717 | } |
758 | 718 | ||
759 | static void conf_choice(struct menu *menu) | 719 | static void conf_choice(struct menu *menu) |
760 | { | 720 | { |
761 | const char *prompt = menu_get_prompt(menu); | 721 | const char *prompt = _(menu_get_prompt(menu)); |
762 | struct menu *child; | 722 | struct menu *child; |
763 | struct symbol *active; | 723 | struct symbol *active; |
764 | 724 | ||
@@ -772,7 +732,7 @@ static void conf_choice(struct menu *menu) | |||
772 | for (child = menu->list; child; child = child->next) { | 732 | for (child = menu->list; child; child = child->next) { |
773 | if (!menu_is_visible(child)) | 733 | if (!menu_is_visible(child)) |
774 | continue; | 734 | continue; |
775 | item_make("%s", menu_get_prompt(child)); | 735 | item_make("%s", _(menu_get_prompt(child))); |
776 | item_set_data(child); | 736 | item_set_data(child); |
777 | if (child->sym == active) | 737 | if (child->sym == active) |
778 | item_set_selected(1); | 738 | item_set_selected(1); |
@@ -780,7 +740,7 @@ static void conf_choice(struct menu *menu) | |||
780 | item_set_tag('X'); | 740 | item_set_tag('X'); |
781 | } | 741 | } |
782 | dialog_clear(); | 742 | dialog_clear(); |
783 | res = dialog_checklist(prompt ? prompt : _("Main Menu"), | 743 | res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), |
784 | _(radiolist_instructions), | 744 | _(radiolist_instructions), |
785 | 15, 70, 6); | 745 | 15, 70, 6); |
786 | selected = item_activate_selected(); | 746 | selected = item_activate_selected(); |
@@ -826,10 +786,10 @@ static void conf_string(struct menu *menu) | |||
826 | heading = _(inputbox_instructions_string); | 786 | heading = _(inputbox_instructions_string); |
827 | break; | 787 | break; |
828 | default: | 788 | default: |
829 | heading = "Internal mconf error!"; | 789 | heading = _("Internal mconf error!"); |
830 | } | 790 | } |
831 | dialog_clear(); | 791 | dialog_clear(); |
832 | res = dialog_inputbox(prompt ? prompt : _("Main Menu"), | 792 | res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), |
833 | heading, 10, 75, | 793 | heading, 10, 75, |
834 | sym_get_string_value(menu->sym)); | 794 | sym_get_string_value(menu->sym)); |
835 | switch (res) { | 795 | switch (res) { |
@@ -900,13 +860,9 @@ static void conf_save(void) | |||
900 | } | 860 | } |
901 | } | 861 | } |
902 | 862 | ||
903 | static void conf_cleanup(void) | ||
904 | { | ||
905 | tcsetattr(1, TCSAFLUSH, &ios_org); | ||
906 | } | ||
907 | |||
908 | int main(int ac, char **av) | 863 | int main(int ac, char **av) |
909 | { | 864 | { |
865 | int saved_x, saved_y; | ||
910 | char *mode; | 866 | char *mode; |
911 | int res; | 867 | int res; |
912 | 868 | ||
@@ -923,11 +879,13 @@ int main(int ac, char **av) | |||
923 | single_menu_mode = 1; | 879 | single_menu_mode = 1; |
924 | } | 880 | } |
925 | 881 | ||
926 | tcgetattr(1, &ios_org); | 882 | getyx(stdscr, saved_y, saved_x); |
927 | atexit(conf_cleanup); | 883 | if (init_dialog(NULL)) { |
928 | init_wsize(); | 884 | fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); |
929 | reset_dialog(); | 885 | fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); |
930 | init_dialog(NULL); | 886 | return 1; |
887 | } | ||
888 | |||
931 | set_config_filename(conf_get_configname()); | 889 | set_config_filename(conf_get_configname()); |
932 | do { | 890 | do { |
933 | conf(&rootmenu); | 891 | conf(&rootmenu); |
@@ -941,7 +899,7 @@ int main(int ac, char **av) | |||
941 | else | 899 | else |
942 | res = -1; | 900 | res = -1; |
943 | } while (res == KEY_ESC); | 901 | } while (res == KEY_ESC); |
944 | end_dialog(); | 902 | end_dialog(saved_x, saved_y); |
945 | 903 | ||
946 | switch (res) { | 904 | switch (res) { |
947 | case 0: | 905 | case 0: |
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index f9d0d91a3fe4..fdad17367f61 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c | |||
@@ -15,7 +15,7 @@ static struct menu **last_entry_ptr; | |||
15 | struct file *file_list; | 15 | struct file *file_list; |
16 | struct file *current_file; | 16 | struct file *current_file; |
17 | 17 | ||
18 | static void menu_warn(struct menu *menu, const char *fmt, ...) | 18 | void menu_warn(struct menu *menu, const char *fmt, ...) |
19 | { | 19 | { |
20 | va_list ap; | 20 | va_list ap; |
21 | va_start(ap, fmt); | 21 | va_start(ap, fmt); |
@@ -172,6 +172,9 @@ void menu_add_option(int token, char *arg) | |||
172 | else if (sym_defconfig_list != current_entry->sym) | 172 | else if (sym_defconfig_list != current_entry->sym) |
173 | zconf_error("trying to redefine defconfig symbol"); | 173 | zconf_error("trying to redefine defconfig symbol"); |
174 | break; | 174 | break; |
175 | case T_OPT_ENV: | ||
176 | prop_add_env(arg); | ||
177 | break; | ||
175 | } | 178 | } |
176 | } | 179 | } |
177 | 180 | ||
@@ -239,9 +242,11 @@ void menu_finalize(struct menu *parent) | |||
239 | for (menu = parent->list; menu; menu = menu->next) { | 242 | for (menu = parent->list; menu; menu = menu->next) { |
240 | if (menu->sym) { | 243 | if (menu->sym) { |
241 | current_entry = parent; | 244 | current_entry = parent; |
242 | menu_set_type(menu->sym->type); | 245 | if (sym->type == S_UNKNOWN) |
246 | menu_set_type(menu->sym->type); | ||
243 | current_entry = menu; | 247 | current_entry = menu; |
244 | menu_set_type(sym->type); | 248 | if (menu->sym->type == S_UNKNOWN) |
249 | menu_set_type(sym->type); | ||
245 | break; | 250 | break; |
246 | } | 251 | } |
247 | } | 252 | } |
@@ -326,12 +331,42 @@ void menu_finalize(struct menu *parent) | |||
326 | "values not supported"); | 331 | "values not supported"); |
327 | } | 332 | } |
328 | current_entry = menu; | 333 | current_entry = menu; |
329 | menu_set_type(sym->type); | 334 | if (menu->sym->type == S_UNKNOWN) |
335 | menu_set_type(sym->type); | ||
336 | /* Non-tristate choice values of tristate choices must | ||
337 | * depend on the choice being set to Y. The choice | ||
338 | * values' dependencies were propagated to their | ||
339 | * properties above, so the change here must be re- | ||
340 | * propagated. */ | ||
341 | if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { | ||
342 | basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); | ||
343 | basedep = expr_alloc_and(basedep, menu->dep); | ||
344 | basedep = expr_eliminate_dups(basedep); | ||
345 | menu->dep = basedep; | ||
346 | for (prop = menu->sym->prop; prop; prop = prop->next) { | ||
347 | if (prop->menu != menu) | ||
348 | continue; | ||
349 | dep = expr_alloc_and(expr_copy(basedep), | ||
350 | prop->visible.expr); | ||
351 | dep = expr_eliminate_dups(dep); | ||
352 | dep = expr_trans_bool(dep); | ||
353 | prop->visible.expr = dep; | ||
354 | if (prop->type == P_SELECT) { | ||
355 | struct symbol *es = prop_get_symbol(prop); | ||
356 | dep2 = expr_alloc_symbol(menu->sym); | ||
357 | dep = expr_alloc_and(dep2, | ||
358 | expr_copy(dep)); | ||
359 | dep = expr_alloc_or(es->rev_dep.expr, dep); | ||
360 | dep = expr_eliminate_dups(dep); | ||
361 | es->rev_dep.expr = dep; | ||
362 | } | ||
363 | } | ||
364 | } | ||
330 | menu_add_symbol(P_CHOICE, sym, NULL); | 365 | menu_add_symbol(P_CHOICE, sym, NULL); |
331 | prop = sym_get_choice_prop(sym); | 366 | prop = sym_get_choice_prop(sym); |
332 | for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) | 367 | for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) |
333 | ; | 368 | ; |
334 | *ep = expr_alloc_one(E_CHOICE, NULL); | 369 | *ep = expr_alloc_one(E_LIST, NULL); |
335 | (*ep)->right.sym = menu->sym; | 370 | (*ep)->right.sym = menu->sym; |
336 | } | 371 | } |
337 | if (menu->list && (!menu->prompt || !menu->prompt->text)) { | 372 | if (menu->list && (!menu->prompt || !menu->prompt->text)) { |
@@ -394,9 +429,9 @@ bool menu_is_visible(struct menu *menu) | |||
394 | const char *menu_get_prompt(struct menu *menu) | 429 | const char *menu_get_prompt(struct menu *menu) |
395 | { | 430 | { |
396 | if (menu->prompt) | 431 | if (menu->prompt) |
397 | return _(menu->prompt->text); | 432 | return menu->prompt->text; |
398 | else if (menu->sym) | 433 | else if (menu->sym) |
399 | return _(menu->sym->name); | 434 | return menu->sym->name; |
400 | return NULL; | 435 | return NULL; |
401 | } | 436 | } |
402 | 437 | ||
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index b9bb32dfd628..5d0fd38b089b 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc | |||
@@ -114,7 +114,7 @@ void ConfigItem::updateMenu(void) | |||
114 | 114 | ||
115 | sym = menu->sym; | 115 | sym = menu->sym; |
116 | prop = menu->prompt; | 116 | prop = menu->prompt; |
117 | prompt = QString::fromLocal8Bit(menu_get_prompt(menu)); | 117 | prompt = _(menu_get_prompt(menu)); |
118 | 118 | ||
119 | if (prop) switch (prop->type) { | 119 | if (prop) switch (prop->type) { |
120 | case P_MENU: | 120 | case P_MENU: |
@@ -208,7 +208,7 @@ void ConfigItem::updateMenu(void) | |||
208 | break; | 208 | break; |
209 | } | 209 | } |
210 | if (!sym_has_value(sym) && visible) | 210 | if (!sym_has_value(sym) && visible) |
211 | prompt += " (NEW)"; | 211 | prompt += _(" (NEW)"); |
212 | set_prompt: | 212 | set_prompt: |
213 | setText(promptColIdx, prompt); | 213 | setText(promptColIdx, prompt); |
214 | } | 214 | } |
@@ -346,7 +346,7 @@ ConfigList::ConfigList(ConfigView* p, const char *name) | |||
346 | 346 | ||
347 | for (i = 0; i < colNr; i++) | 347 | for (i = 0; i < colNr; i++) |
348 | colMap[i] = colRevMap[i] = -1; | 348 | colMap[i] = colRevMap[i] = -1; |
349 | addColumn(promptColIdx, "Option"); | 349 | addColumn(promptColIdx, _("Option")); |
350 | 350 | ||
351 | reinit(); | 351 | reinit(); |
352 | } | 352 | } |
@@ -360,14 +360,14 @@ void ConfigList::reinit(void) | |||
360 | removeColumn(nameColIdx); | 360 | removeColumn(nameColIdx); |
361 | 361 | ||
362 | if (showName) | 362 | if (showName) |
363 | addColumn(nameColIdx, "Name"); | 363 | addColumn(nameColIdx, _("Name")); |
364 | if (showRange) { | 364 | if (showRange) { |
365 | addColumn(noColIdx, "N"); | 365 | addColumn(noColIdx, "N"); |
366 | addColumn(modColIdx, "M"); | 366 | addColumn(modColIdx, "M"); |
367 | addColumn(yesColIdx, "Y"); | 367 | addColumn(yesColIdx, "Y"); |
368 | } | 368 | } |
369 | if (showData) | 369 | if (showData) |
370 | addColumn(dataColIdx, "Value"); | 370 | addColumn(dataColIdx, _("Value")); |
371 | 371 | ||
372 | updateListAll(); | 372 | updateListAll(); |
373 | } | 373 | } |
@@ -803,7 +803,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) | |||
803 | QAction *action; | 803 | QAction *action; |
804 | 804 | ||
805 | headerPopup = new QPopupMenu(this); | 805 | headerPopup = new QPopupMenu(this); |
806 | action = new QAction(NULL, "Show Name", 0, this); | 806 | action = new QAction(NULL, _("Show Name"), 0, this); |
807 | action->setToggleAction(TRUE); | 807 | action->setToggleAction(TRUE); |
808 | connect(action, SIGNAL(toggled(bool)), | 808 | connect(action, SIGNAL(toggled(bool)), |
809 | parent(), SLOT(setShowName(bool))); | 809 | parent(), SLOT(setShowName(bool))); |
@@ -811,7 +811,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) | |||
811 | action, SLOT(setOn(bool))); | 811 | action, SLOT(setOn(bool))); |
812 | action->setOn(showName); | 812 | action->setOn(showName); |
813 | action->addTo(headerPopup); | 813 | action->addTo(headerPopup); |
814 | action = new QAction(NULL, "Show Range", 0, this); | 814 | action = new QAction(NULL, _("Show Range"), 0, this); |
815 | action->setToggleAction(TRUE); | 815 | action->setToggleAction(TRUE); |
816 | connect(action, SIGNAL(toggled(bool)), | 816 | connect(action, SIGNAL(toggled(bool)), |
817 | parent(), SLOT(setShowRange(bool))); | 817 | parent(), SLOT(setShowRange(bool))); |
@@ -819,7 +819,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) | |||
819 | action, SLOT(setOn(bool))); | 819 | action, SLOT(setOn(bool))); |
820 | action->setOn(showRange); | 820 | action->setOn(showRange); |
821 | action->addTo(headerPopup); | 821 | action->addTo(headerPopup); |
822 | action = new QAction(NULL, "Show Data", 0, this); | 822 | action = new QAction(NULL, _("Show Data"), 0, this); |
823 | action->setToggleAction(TRUE); | 823 | action->setToggleAction(TRUE); |
824 | connect(action, SIGNAL(toggled(bool)), | 824 | connect(action, SIGNAL(toggled(bool)), |
825 | parent(), SLOT(setShowData(bool))); | 825 | parent(), SLOT(setShowData(bool))); |
@@ -1041,7 +1041,12 @@ void ConfigInfoView::menuInfo(void) | |||
1041 | if (showDebug()) | 1041 | if (showDebug()) |
1042 | debug = debug_info(sym); | 1042 | debug = debug_info(sym); |
1043 | 1043 | ||
1044 | help = print_filter(_(menu_get_help(menu))); | 1044 | help = menu_get_help(menu); |
1045 | /* Gettextize if the help text not empty */ | ||
1046 | if (help.isEmpty()) | ||
1047 | help = print_filter(menu_get_help(menu)); | ||
1048 | else | ||
1049 | help = print_filter(_(menu_get_help(menu))); | ||
1045 | } else if (menu->prompt) { | 1050 | } else if (menu->prompt) { |
1046 | head += "<big><b>"; | 1051 | head += "<big><b>"; |
1047 | head += print_filter(_(menu->prompt->text)); | 1052 | head += print_filter(_(menu->prompt->text)); |
@@ -1083,7 +1088,11 @@ QString ConfigInfoView::debug_info(struct symbol *sym) | |||
1083 | debug += "</a><br>"; | 1088 | debug += "</a><br>"; |
1084 | break; | 1089 | break; |
1085 | case P_DEFAULT: | 1090 | case P_DEFAULT: |
1086 | debug += "default: "; | 1091 | case P_SELECT: |
1092 | case P_RANGE: | ||
1093 | case P_ENV: | ||
1094 | debug += prop_get_type_name(prop->type); | ||
1095 | debug += ": "; | ||
1087 | expr_print(prop->expr, expr_print_help, &debug, E_NONE); | 1096 | expr_print(prop->expr, expr_print_help, &debug, E_NONE); |
1088 | debug += "<br>"; | 1097 | debug += "<br>"; |
1089 | break; | 1098 | break; |
@@ -1094,16 +1103,6 @@ QString ConfigInfoView::debug_info(struct symbol *sym) | |||
1094 | debug += "<br>"; | 1103 | debug += "<br>"; |
1095 | } | 1104 | } |
1096 | break; | 1105 | break; |
1097 | case P_SELECT: | ||
1098 | debug += "select: "; | ||
1099 | expr_print(prop->expr, expr_print_help, &debug, E_NONE); | ||
1100 | debug += "<br>"; | ||
1101 | break; | ||
1102 | case P_RANGE: | ||
1103 | debug += "range: "; | ||
1104 | expr_print(prop->expr, expr_print_help, &debug, E_NONE); | ||
1105 | debug += "<br>"; | ||
1106 | break; | ||
1107 | default: | 1106 | default: |
1108 | debug += "unknown property: "; | 1107 | debug += "unknown property: "; |
1109 | debug += prop_get_type_name(prop->type); | 1108 | debug += prop_get_type_name(prop->type); |
@@ -1167,7 +1166,7 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char | |||
1167 | QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos) | 1166 | QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos) |
1168 | { | 1167 | { |
1169 | QPopupMenu* popup = Parent::createPopupMenu(pos); | 1168 | QPopupMenu* popup = Parent::createPopupMenu(pos); |
1170 | QAction* action = new QAction(NULL,"Show Debug Info", 0, popup); | 1169 | QAction* action = new QAction(NULL, _("Show Debug Info"), 0, popup); |
1171 | action->setToggleAction(TRUE); | 1170 | action->setToggleAction(TRUE); |
1172 | connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); | 1171 | connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); |
1173 | connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); | 1172 | connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); |
@@ -1189,11 +1188,11 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam | |||
1189 | 1188 | ||
1190 | QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6); | 1189 | QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6); |
1191 | QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6); | 1190 | QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6); |
1192 | layout2->addWidget(new QLabel("Find:", this)); | 1191 | layout2->addWidget(new QLabel(_("Find:"), this)); |
1193 | editField = new QLineEdit(this); | 1192 | editField = new QLineEdit(this); |
1194 | connect(editField, SIGNAL(returnPressed()), SLOT(search())); | 1193 | connect(editField, SIGNAL(returnPressed()), SLOT(search())); |
1195 | layout2->addWidget(editField); | 1194 | layout2->addWidget(editField); |
1196 | searchButton = new QPushButton("Search", this); | 1195 | searchButton = new QPushButton(_("Search"), this); |
1197 | searchButton->setAutoDefault(FALSE); | 1196 | searchButton->setAutoDefault(FALSE); |
1198 | connect(searchButton, SIGNAL(clicked()), SLOT(search())); | 1197 | connect(searchButton, SIGNAL(clicked()), SLOT(search())); |
1199 | layout2->addWidget(searchButton); | 1198 | layout2->addWidget(searchButton); |
@@ -1313,58 +1312,58 @@ ConfigMainWindow::ConfigMainWindow(void) | |||
1313 | menu = menuBar(); | 1312 | menu = menuBar(); |
1314 | toolBar = new QToolBar("Tools", this); | 1313 | toolBar = new QToolBar("Tools", this); |
1315 | 1314 | ||
1316 | backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this); | 1315 | backAction = new QAction("Back", QPixmap(xpm_back), _("Back"), 0, this); |
1317 | connect(backAction, SIGNAL(activated()), SLOT(goBack())); | 1316 | connect(backAction, SIGNAL(activated()), SLOT(goBack())); |
1318 | backAction->setEnabled(FALSE); | 1317 | backAction->setEnabled(FALSE); |
1319 | QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this); | 1318 | QAction *quitAction = new QAction("Quit", _("&Quit"), CTRL+Key_Q, this); |
1320 | connect(quitAction, SIGNAL(activated()), SLOT(close())); | 1319 | connect(quitAction, SIGNAL(activated()), SLOT(close())); |
1321 | QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this); | 1320 | QAction *loadAction = new QAction("Load", QPixmap(xpm_load), _("&Load"), CTRL+Key_L, this); |
1322 | connect(loadAction, SIGNAL(activated()), SLOT(loadConfig())); | 1321 | connect(loadAction, SIGNAL(activated()), SLOT(loadConfig())); |
1323 | saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this); | 1322 | saveAction = new QAction("Save", QPixmap(xpm_save), _("&Save"), CTRL+Key_S, this); |
1324 | connect(saveAction, SIGNAL(activated()), SLOT(saveConfig())); | 1323 | connect(saveAction, SIGNAL(activated()), SLOT(saveConfig())); |
1325 | conf_set_changed_callback(conf_changed); | 1324 | conf_set_changed_callback(conf_changed); |
1326 | // Set saveAction's initial state | 1325 | // Set saveAction's initial state |
1327 | conf_changed(); | 1326 | conf_changed(); |
1328 | QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this); | 1327 | QAction *saveAsAction = new QAction("Save As...", _("Save &As..."), 0, this); |
1329 | connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs())); | 1328 | connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs())); |
1330 | QAction *searchAction = new QAction("Find", "&Find", CTRL+Key_F, this); | 1329 | QAction *searchAction = new QAction("Find", _("&Find"), CTRL+Key_F, this); |
1331 | connect(searchAction, SIGNAL(activated()), SLOT(searchConfig())); | 1330 | connect(searchAction, SIGNAL(activated()), SLOT(searchConfig())); |
1332 | QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this); | 1331 | QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this); |
1333 | connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView())); | 1332 | connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView())); |
1334 | QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this); | 1333 | QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this); |
1335 | connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView())); | 1334 | connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView())); |
1336 | QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this); | 1335 | QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this); |
1337 | connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView())); | 1336 | connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView())); |
1338 | 1337 | ||
1339 | QAction *showNameAction = new QAction(NULL, "Show Name", 0, this); | 1338 | QAction *showNameAction = new QAction(NULL, _("Show Name"), 0, this); |
1340 | showNameAction->setToggleAction(TRUE); | 1339 | showNameAction->setToggleAction(TRUE); |
1341 | connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); | 1340 | connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); |
1342 | connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool))); | 1341 | connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool))); |
1343 | showNameAction->setOn(configView->showName()); | 1342 | showNameAction->setOn(configView->showName()); |
1344 | QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this); | 1343 | QAction *showRangeAction = new QAction(NULL, _("Show Range"), 0, this); |
1345 | showRangeAction->setToggleAction(TRUE); | 1344 | showRangeAction->setToggleAction(TRUE); |
1346 | connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); | 1345 | connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); |
1347 | connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool))); | 1346 | connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool))); |
1348 | showRangeAction->setOn(configList->showRange); | 1347 | showRangeAction->setOn(configList->showRange); |
1349 | QAction *showDataAction = new QAction(NULL, "Show Data", 0, this); | 1348 | QAction *showDataAction = new QAction(NULL, _("Show Data"), 0, this); |
1350 | showDataAction->setToggleAction(TRUE); | 1349 | showDataAction->setToggleAction(TRUE); |
1351 | connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); | 1350 | connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); |
1352 | connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool))); | 1351 | connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool))); |
1353 | showDataAction->setOn(configList->showData); | 1352 | showDataAction->setOn(configList->showData); |
1354 | QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this); | 1353 | QAction *showAllAction = new QAction(NULL, _("Show All Options"), 0, this); |
1355 | showAllAction->setToggleAction(TRUE); | 1354 | showAllAction->setToggleAction(TRUE); |
1356 | connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool))); | 1355 | connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool))); |
1357 | connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool))); | 1356 | connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool))); |
1358 | showAllAction->setOn(configList->showAll); | 1357 | showAllAction->setOn(configList->showAll); |
1359 | QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this); | 1358 | QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this); |
1360 | showDebugAction->setToggleAction(TRUE); | 1359 | showDebugAction->setToggleAction(TRUE); |
1361 | connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); | 1360 | connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); |
1362 | connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool))); | 1361 | connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool))); |
1363 | showDebugAction->setOn(helpText->showDebug()); | 1362 | showDebugAction->setOn(helpText->showDebug()); |
1364 | 1363 | ||
1365 | QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this); | 1364 | QAction *showIntroAction = new QAction(NULL, _("Introduction"), 0, this); |
1366 | connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro())); | 1365 | connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro())); |
1367 | QAction *showAboutAction = new QAction(NULL, "About", 0, this); | 1366 | QAction *showAboutAction = new QAction(NULL, _("About"), 0, this); |
1368 | connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout())); | 1367 | connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout())); |
1369 | 1368 | ||
1370 | // init tool bar | 1369 | // init tool bar |
@@ -1379,7 +1378,7 @@ ConfigMainWindow::ConfigMainWindow(void) | |||
1379 | 1378 | ||
1380 | // create config menu | 1379 | // create config menu |
1381 | QPopupMenu* config = new QPopupMenu(this); | 1380 | QPopupMenu* config = new QPopupMenu(this); |
1382 | menu->insertItem("&File", config); | 1381 | menu->insertItem(_("&File"), config); |
1383 | loadAction->addTo(config); | 1382 | loadAction->addTo(config); |
1384 | saveAction->addTo(config); | 1383 | saveAction->addTo(config); |
1385 | saveAsAction->addTo(config); | 1384 | saveAsAction->addTo(config); |
@@ -1388,12 +1387,12 @@ ConfigMainWindow::ConfigMainWindow(void) | |||
1388 | 1387 | ||
1389 | // create edit menu | 1388 | // create edit menu |
1390 | QPopupMenu* editMenu = new QPopupMenu(this); | 1389 | QPopupMenu* editMenu = new QPopupMenu(this); |
1391 | menu->insertItem("&Edit", editMenu); | 1390 | menu->insertItem(_("&Edit"), editMenu); |
1392 | searchAction->addTo(editMenu); | 1391 | searchAction->addTo(editMenu); |
1393 | 1392 | ||
1394 | // create options menu | 1393 | // create options menu |
1395 | QPopupMenu* optionMenu = new QPopupMenu(this); | 1394 | QPopupMenu* optionMenu = new QPopupMenu(this); |
1396 | menu->insertItem("&Option", optionMenu); | 1395 | menu->insertItem(_("&Option"), optionMenu); |
1397 | showNameAction->addTo(optionMenu); | 1396 | showNameAction->addTo(optionMenu); |
1398 | showRangeAction->addTo(optionMenu); | 1397 | showRangeAction->addTo(optionMenu); |
1399 | showDataAction->addTo(optionMenu); | 1398 | showDataAction->addTo(optionMenu); |
@@ -1404,7 +1403,7 @@ ConfigMainWindow::ConfigMainWindow(void) | |||
1404 | // create help menu | 1403 | // create help menu |
1405 | QPopupMenu* helpMenu = new QPopupMenu(this); | 1404 | QPopupMenu* helpMenu = new QPopupMenu(this); |
1406 | menu->insertSeparator(); | 1405 | menu->insertSeparator(); |
1407 | menu->insertItem("&Help", helpMenu); | 1406 | menu->insertItem(_("&Help"), helpMenu); |
1408 | showIntroAction->addTo(helpMenu); | 1407 | showIntroAction->addTo(helpMenu); |
1409 | showAboutAction->addTo(helpMenu); | 1408 | showAboutAction->addTo(helpMenu); |
1410 | 1409 | ||
@@ -1452,14 +1451,14 @@ void ConfigMainWindow::loadConfig(void) | |||
1452 | if (s.isNull()) | 1451 | if (s.isNull()) |
1453 | return; | 1452 | return; |
1454 | if (conf_read(QFile::encodeName(s))) | 1453 | if (conf_read(QFile::encodeName(s))) |
1455 | QMessageBox::information(this, "qconf", "Unable to load configuration!"); | 1454 | QMessageBox::information(this, "qconf", _("Unable to load configuration!")); |
1456 | ConfigView::updateListAll(); | 1455 | ConfigView::updateListAll(); |
1457 | } | 1456 | } |
1458 | 1457 | ||
1459 | void ConfigMainWindow::saveConfig(void) | 1458 | void ConfigMainWindow::saveConfig(void) |
1460 | { | 1459 | { |
1461 | if (conf_write(NULL)) | 1460 | if (conf_write(NULL)) |
1462 | QMessageBox::information(this, "qconf", "Unable to save configuration!"); | 1461 | QMessageBox::information(this, "qconf", _("Unable to save configuration!")); |
1463 | } | 1462 | } |
1464 | 1463 | ||
1465 | void ConfigMainWindow::saveConfigAs(void) | 1464 | void ConfigMainWindow::saveConfigAs(void) |
@@ -1468,7 +1467,7 @@ void ConfigMainWindow::saveConfigAs(void) | |||
1468 | if (s.isNull()) | 1467 | if (s.isNull()) |
1469 | return; | 1468 | return; |
1470 | if (conf_write(QFile::encodeName(s))) | 1469 | if (conf_write(QFile::encodeName(s))) |
1471 | QMessageBox::information(this, "qconf", "Unable to save configuration!"); | 1470 | QMessageBox::information(this, "qconf", _("Unable to save configuration!")); |
1472 | } | 1471 | } |
1473 | 1472 | ||
1474 | void ConfigMainWindow::searchConfig(void) | 1473 | void ConfigMainWindow::searchConfig(void) |
@@ -1612,11 +1611,11 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e) | |||
1612 | e->accept(); | 1611 | e->accept(); |
1613 | return; | 1612 | return; |
1614 | } | 1613 | } |
1615 | QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning, | 1614 | QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning, |
1616 | QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); | 1615 | QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); |
1617 | mb.setButtonText(QMessageBox::Yes, "&Save Changes"); | 1616 | mb.setButtonText(QMessageBox::Yes, _("&Save Changes")); |
1618 | mb.setButtonText(QMessageBox::No, "&Discard Changes"); | 1617 | mb.setButtonText(QMessageBox::No, _("&Discard Changes")); |
1619 | mb.setButtonText(QMessageBox::Cancel, "Cancel Exit"); | 1618 | mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit")); |
1620 | switch (mb.exec()) { | 1619 | switch (mb.exec()) { |
1621 | case QMessageBox::Yes: | 1620 | case QMessageBox::Yes: |
1622 | conf_write(NULL); | 1621 | conf_write(NULL); |
@@ -1631,7 +1630,7 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e) | |||
1631 | 1630 | ||
1632 | void ConfigMainWindow::showIntro(void) | 1631 | void ConfigMainWindow::showIntro(void) |
1633 | { | 1632 | { |
1634 | static char str[] = "Welcome to the qconf graphical kernel configuration tool for Linux.\n\n" | 1633 | static const QString str = _("Welcome to the qconf graphical kernel configuration tool for Linux.\n\n" |
1635 | "For each option, a blank box indicates the feature is disabled, a check\n" | 1634 | "For each option, a blank box indicates the feature is disabled, a check\n" |
1636 | "indicates it is enabled, and a dot indicates that it is to be compiled\n" | 1635 | "indicates it is enabled, and a dot indicates that it is to be compiled\n" |
1637 | "as a module. Clicking on the box will cycle through the three states.\n\n" | 1636 | "as a module. Clicking on the box will cycle through the three states.\n\n" |
@@ -1641,15 +1640,15 @@ void ConfigMainWindow::showIntro(void) | |||
1641 | "options must be enabled to support the option you are interested in, you can\n" | 1640 | "options must be enabled to support the option you are interested in, you can\n" |
1642 | "still view the help of a grayed-out option.\n\n" | 1641 | "still view the help of a grayed-out option.\n\n" |
1643 | "Toggling Show Debug Info under the Options menu will show the dependencies,\n" | 1642 | "Toggling Show Debug Info under the Options menu will show the dependencies,\n" |
1644 | "which you can then match by examining other options.\n\n"; | 1643 | "which you can then match by examining other options.\n\n"); |
1645 | 1644 | ||
1646 | QMessageBox::information(this, "qconf", str); | 1645 | QMessageBox::information(this, "qconf", str); |
1647 | } | 1646 | } |
1648 | 1647 | ||
1649 | void ConfigMainWindow::showAbout(void) | 1648 | void ConfigMainWindow::showAbout(void) |
1650 | { | 1649 | { |
1651 | static char str[] = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n" | 1650 | static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n\n" |
1652 | "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"; | 1651 | "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"); |
1653 | 1652 | ||
1654 | QMessageBox::information(this, "qconf", str); | 1653 | QMessageBox::information(this, "qconf", str); |
1655 | } | 1654 | } |
@@ -1707,7 +1706,7 @@ static const char *progname; | |||
1707 | 1706 | ||
1708 | static void usage(void) | 1707 | static void usage(void) |
1709 | { | 1708 | { |
1710 | printf("%s <config>\n", progname); | 1709 | printf(_("%s <config>\n"), progname); |
1711 | exit(0); | 1710 | exit(0); |
1712 | } | 1711 | } |
1713 | 1712 | ||
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index c35dcc5d6189..3929e5b35e79 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c | |||
@@ -34,6 +34,8 @@ struct symbol *sym_defconfig_list; | |||
34 | struct symbol *modules_sym; | 34 | struct symbol *modules_sym; |
35 | tristate modules_val; | 35 | tristate modules_val; |
36 | 36 | ||
37 | struct expr *sym_env_list; | ||
38 | |||
37 | void sym_add_default(struct symbol *sym, const char *def) | 39 | void sym_add_default(struct symbol *sym, const char *def) |
38 | { | 40 | { |
39 | struct property *prop = prop_alloc(P_DEFAULT, sym); | 41 | struct property *prop = prop_alloc(P_DEFAULT, sym); |
@@ -45,7 +47,6 @@ void sym_init(void) | |||
45 | { | 47 | { |
46 | struct symbol *sym; | 48 | struct symbol *sym; |
47 | struct utsname uts; | 49 | struct utsname uts; |
48 | char *p; | ||
49 | static bool inited = false; | 50 | static bool inited = false; |
50 | 51 | ||
51 | if (inited) | 52 | if (inited) |
@@ -54,20 +55,6 @@ void sym_init(void) | |||
54 | 55 | ||
55 | uname(&uts); | 56 | uname(&uts); |
56 | 57 | ||
57 | sym = sym_lookup("ARCH", 0); | ||
58 | sym->type = S_STRING; | ||
59 | sym->flags |= SYMBOL_AUTO; | ||
60 | p = getenv("ARCH"); | ||
61 | if (p) | ||
62 | sym_add_default(sym, p); | ||
63 | |||
64 | sym = sym_lookup("KERNELVERSION", 0); | ||
65 | sym->type = S_STRING; | ||
66 | sym->flags |= SYMBOL_AUTO; | ||
67 | p = getenv("KERNELVERSION"); | ||
68 | if (p) | ||
69 | sym_add_default(sym, p); | ||
70 | |||
71 | sym = sym_lookup("UNAME_RELEASE", 0); | 58 | sym = sym_lookup("UNAME_RELEASE", 0); |
72 | sym->type = S_STRING; | 59 | sym->type = S_STRING; |
73 | sym->flags |= SYMBOL_AUTO; | 60 | sym->flags |= SYMBOL_AUTO; |
@@ -117,6 +104,15 @@ struct property *sym_get_choice_prop(struct symbol *sym) | |||
117 | return NULL; | 104 | return NULL; |
118 | } | 105 | } |
119 | 106 | ||
107 | struct property *sym_get_env_prop(struct symbol *sym) | ||
108 | { | ||
109 | struct property *prop; | ||
110 | |||
111 | for_all_properties(sym, prop, P_ENV) | ||
112 | return prop; | ||
113 | return NULL; | ||
114 | } | ||
115 | |||
120 | struct property *sym_get_default_prop(struct symbol *sym) | 116 | struct property *sym_get_default_prop(struct symbol *sym) |
121 | { | 117 | { |
122 | struct property *prop; | 118 | struct property *prop; |
@@ -199,7 +195,7 @@ static void sym_calc_visibility(struct symbol *sym) | |||
199 | tri = no; | 195 | tri = no; |
200 | for_all_prompts(sym, prop) { | 196 | for_all_prompts(sym, prop) { |
201 | prop->visible.tri = expr_calc_value(prop->visible.expr); | 197 | prop->visible.tri = expr_calc_value(prop->visible.expr); |
202 | tri = E_OR(tri, prop->visible.tri); | 198 | tri = EXPR_OR(tri, prop->visible.tri); |
203 | } | 199 | } |
204 | if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) | 200 | if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) |
205 | tri = yes; | 201 | tri = yes; |
@@ -247,8 +243,7 @@ static struct symbol *sym_calc_choice(struct symbol *sym) | |||
247 | 243 | ||
248 | /* just get the first visible value */ | 244 | /* just get the first visible value */ |
249 | prop = sym_get_choice_prop(sym); | 245 | prop = sym_get_choice_prop(sym); |
250 | for (e = prop->expr; e; e = e->left.expr) { | 246 | expr_list_for_each_sym(prop->expr, e, def_sym) { |
251 | def_sym = e->right.sym; | ||
252 | sym_calc_visibility(def_sym); | 247 | sym_calc_visibility(def_sym); |
253 | if (def_sym->visible != no) | 248 | if (def_sym->visible != no) |
254 | return def_sym; | 249 | return def_sym; |
@@ -303,7 +298,7 @@ void sym_calc_value(struct symbol *sym) | |||
303 | if (sym_is_choice_value(sym) && sym->visible == yes) { | 298 | if (sym_is_choice_value(sym) && sym->visible == yes) { |
304 | prop = sym_get_choice_prop(sym); | 299 | prop = sym_get_choice_prop(sym); |
305 | newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; | 300 | newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; |
306 | } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) { | 301 | } else if (EXPR_OR(sym->visible, sym->rev_dep.tri) != no) { |
307 | sym->flags |= SYMBOL_WRITE; | 302 | sym->flags |= SYMBOL_WRITE; |
308 | if (sym_has_value(sym)) | 303 | if (sym_has_value(sym)) |
309 | newval.tri = sym->def[S_DEF_USER].tri; | 304 | newval.tri = sym->def[S_DEF_USER].tri; |
@@ -312,7 +307,7 @@ void sym_calc_value(struct symbol *sym) | |||
312 | if (prop) | 307 | if (prop) |
313 | newval.tri = expr_calc_value(prop->expr); | 308 | newval.tri = expr_calc_value(prop->expr); |
314 | } | 309 | } |
315 | newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri); | 310 | newval.tri = EXPR_OR(EXPR_AND(newval.tri, sym->visible), sym->rev_dep.tri); |
316 | } else if (!sym_is_choice(sym)) { | 311 | } else if (!sym_is_choice(sym)) { |
317 | prop = sym_get_default_prop(sym); | 312 | prop = sym_get_default_prop(sym); |
318 | if (prop) { | 313 | if (prop) { |
@@ -347,6 +342,9 @@ void sym_calc_value(struct symbol *sym) | |||
347 | ; | 342 | ; |
348 | } | 343 | } |
349 | 344 | ||
345 | if (sym->flags & SYMBOL_AUTO) | ||
346 | sym->flags &= ~SYMBOL_WRITE; | ||
347 | |||
350 | sym->curr = newval; | 348 | sym->curr = newval; |
351 | if (sym_is_choice(sym) && newval.tri == yes) | 349 | if (sym_is_choice(sym) && newval.tri == yes) |
352 | sym->curr.val = sym_calc_choice(sym); | 350 | sym->curr.val = sym_calc_choice(sym); |
@@ -361,12 +359,14 @@ void sym_calc_value(struct symbol *sym) | |||
361 | } | 359 | } |
362 | 360 | ||
363 | if (sym_is_choice(sym)) { | 361 | if (sym_is_choice(sym)) { |
362 | struct symbol *choice_sym; | ||
364 | int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); | 363 | int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); |
364 | |||
365 | prop = sym_get_choice_prop(sym); | 365 | prop = sym_get_choice_prop(sym); |
366 | for (e = prop->expr; e; e = e->left.expr) { | 366 | expr_list_for_each_sym(prop->expr, e, choice_sym) { |
367 | e->right.sym->flags |= flags; | 367 | choice_sym->flags |= flags; |
368 | if (flags & SYMBOL_CHANGED) | 368 | if (flags & SYMBOL_CHANGED) |
369 | sym_set_changed(e->right.sym); | 369 | sym_set_changed(choice_sym); |
370 | } | 370 | } |
371 | } | 371 | } |
372 | } | 372 | } |
@@ -849,7 +849,7 @@ struct property *prop_alloc(enum prop_type type, struct symbol *sym) | |||
849 | struct symbol *prop_get_symbol(struct property *prop) | 849 | struct symbol *prop_get_symbol(struct property *prop) |
850 | { | 850 | { |
851 | if (prop->expr && (prop->expr->type == E_SYMBOL || | 851 | if (prop->expr && (prop->expr->type == E_SYMBOL || |
852 | prop->expr->type == E_CHOICE)) | 852 | prop->expr->type == E_LIST)) |
853 | return prop->expr->left.sym; | 853 | return prop->expr->left.sym; |
854 | return NULL; | 854 | return NULL; |
855 | } | 855 | } |
@@ -859,6 +859,8 @@ const char *prop_get_type_name(enum prop_type type) | |||
859 | switch (type) { | 859 | switch (type) { |
860 | case P_PROMPT: | 860 | case P_PROMPT: |
861 | return "prompt"; | 861 | return "prompt"; |
862 | case P_ENV: | ||
863 | return "env"; | ||
862 | case P_COMMENT: | 864 | case P_COMMENT: |
863 | return "comment"; | 865 | return "comment"; |
864 | case P_MENU: | 866 | case P_MENU: |
@@ -876,3 +878,32 @@ const char *prop_get_type_name(enum prop_type type) | |||
876 | } | 878 | } |
877 | return "unknown"; | 879 | return "unknown"; |
878 | } | 880 | } |
881 | |||
882 | void prop_add_env(const char *env) | ||
883 | { | ||
884 | struct symbol *sym, *sym2; | ||
885 | struct property *prop; | ||
886 | char *p; | ||
887 | |||
888 | sym = current_entry->sym; | ||
889 | sym->flags |= SYMBOL_AUTO; | ||
890 | for_all_properties(sym, prop, P_ENV) { | ||
891 | sym2 = prop_get_symbol(prop); | ||
892 | if (strcmp(sym2->name, env)) | ||
893 | menu_warn(current_entry, "redefining environment symbol from %s", | ||
894 | sym2->name); | ||
895 | return; | ||
896 | } | ||
897 | |||
898 | prop = prop_alloc(P_ENV, sym); | ||
899 | prop->expr = expr_alloc_symbol(sym_lookup(env, 1)); | ||
900 | |||
901 | sym_env_list = expr_alloc_one(E_LIST, sym_env_list); | ||
902 | sym_env_list->right.sym = sym; | ||
903 | |||
904 | p = getenv(env); | ||
905 | if (p) | ||
906 | sym_add_default(sym, p); | ||
907 | else | ||
908 | menu_warn(current_entry, "environment variable %s undefined", env); | ||
909 | } | ||
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c index e1cad924c0a4..f8e73c039dc8 100644 --- a/scripts/kconfig/util.c +++ b/scripts/kconfig/util.c | |||
@@ -29,6 +29,8 @@ struct file *file_lookup(const char *name) | |||
29 | /* write a dependency file as used by kbuild to track dependencies */ | 29 | /* write a dependency file as used by kbuild to track dependencies */ |
30 | int file_write_dep(const char *name) | 30 | int file_write_dep(const char *name) |
31 | { | 31 | { |
32 | struct symbol *sym, *env_sym; | ||
33 | struct expr *e; | ||
32 | struct file *file; | 34 | struct file *file; |
33 | FILE *out; | 35 | FILE *out; |
34 | 36 | ||
@@ -45,8 +47,25 @@ int file_write_dep(const char *name) | |||
45 | fprintf(out, "\t%s\n", file->name); | 47 | fprintf(out, "\t%s\n", file->name); |
46 | } | 48 | } |
47 | fprintf(out, "\ninclude/config/auto.conf: \\\n" | 49 | fprintf(out, "\ninclude/config/auto.conf: \\\n" |
48 | "\t$(deps_config)\n\n" | 50 | "\t$(deps_config)\n\n"); |
49 | "$(deps_config): ;\n"); | 51 | |
52 | expr_list_for_each_sym(sym_env_list, e, sym) { | ||
53 | struct property *prop; | ||
54 | const char *value; | ||
55 | |||
56 | prop = sym_get_env_prop(sym); | ||
57 | env_sym = prop_get_symbol(prop); | ||
58 | if (!env_sym) | ||
59 | continue; | ||
60 | value = getenv(env_sym->name); | ||
61 | if (!value) | ||
62 | value = ""; | ||
63 | fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value); | ||
64 | fprintf(out, "include/config/auto.conf: FORCE\n"); | ||
65 | fprintf(out, "endif\n"); | ||
66 | } | ||
67 | |||
68 | fprintf(out, "\n$(deps_config): ;\n"); | ||
50 | fclose(out); | 69 | fclose(out); |
51 | rename("..config.tmp", name); | 70 | rename("..config.tmp", name); |
52 | return 0; | 71 | return 0; |
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf index 93538e567bda..25ef5d01c0af 100644 --- a/scripts/kconfig/zconf.gperf +++ b/scripts/kconfig/zconf.gperf | |||
@@ -35,10 +35,10 @@ int, T_TYPE, TF_COMMAND, S_INT | |||
35 | hex, T_TYPE, TF_COMMAND, S_HEX | 35 | hex, T_TYPE, TF_COMMAND, S_HEX |
36 | string, T_TYPE, TF_COMMAND, S_STRING | 36 | string, T_TYPE, TF_COMMAND, S_STRING |
37 | select, T_SELECT, TF_COMMAND | 37 | select, T_SELECT, TF_COMMAND |
38 | enable, T_SELECT, TF_COMMAND | ||
39 | range, T_RANGE, TF_COMMAND | 38 | range, T_RANGE, TF_COMMAND |
40 | option, T_OPTION, TF_COMMAND | 39 | option, T_OPTION, TF_COMMAND |
41 | on, T_ON, TF_PARAM | 40 | on, T_ON, TF_PARAM |
42 | modules, T_OPT_MODULES, TF_OPTION | 41 | modules, T_OPT_MODULES, TF_OPTION |
43 | defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION | 42 | defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION |
43 | env, T_OPT_ENV, TF_OPTION | ||
44 | %% | 44 | %% |
diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped index ab28b18153a7..5c73d51339d8 100644 --- a/scripts/kconfig/zconf.hash.c_shipped +++ b/scripts/kconfig/zconf.hash.c_shipped | |||
@@ -1,4 +1,4 @@ | |||
1 | /* ANSI-C code produced by gperf version 3.0.2 */ | 1 | /* ANSI-C code produced by gperf version 3.0.3 */ |
2 | /* Command-line: gperf */ | 2 | /* Command-line: gperf */ |
3 | /* Computed positions: -k'1,3' */ | 3 | /* Computed positions: -k'1,3' */ |
4 | 4 | ||
@@ -53,9 +53,9 @@ kconf_id_hash (register const char *str, register unsigned int len) | |||
53 | 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, | 53 | 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |
54 | 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, | 54 | 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |
55 | 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, | 55 | 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |
56 | 49, 49, 49, 49, 49, 49, 49, 18, 11, 5, | 56 | 49, 49, 49, 49, 49, 49, 49, 49, 11, 5, |
57 | 0, 0, 5, 49, 5, 20, 49, 49, 5, 20, | 57 | 0, 0, 5, 49, 5, 20, 49, 49, 5, 20, |
58 | 5, 0, 30, 49, 0, 15, 0, 10, 49, 49, | 58 | 5, 0, 30, 49, 0, 15, 0, 10, 0, 49, |
59 | 25, 49, 49, 49, 49, 49, 49, 49, 49, 49, | 59 | 25, 49, 49, 49, 49, 49, 49, 49, 49, 49, |
60 | 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, | 60 | 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |
61 | 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, | 61 | 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, |
@@ -89,6 +89,7 @@ kconf_id_hash (register const char *str, register unsigned int len) | |||
89 | struct kconf_id_strings_t | 89 | struct kconf_id_strings_t |
90 | { | 90 | { |
91 | char kconf_id_strings_str2[sizeof("on")]; | 91 | char kconf_id_strings_str2[sizeof("on")]; |
92 | char kconf_id_strings_str3[sizeof("env")]; | ||
92 | char kconf_id_strings_str5[sizeof("endif")]; | 93 | char kconf_id_strings_str5[sizeof("endif")]; |
93 | char kconf_id_strings_str6[sizeof("option")]; | 94 | char kconf_id_strings_str6[sizeof("option")]; |
94 | char kconf_id_strings_str7[sizeof("endmenu")]; | 95 | char kconf_id_strings_str7[sizeof("endmenu")]; |
@@ -107,7 +108,6 @@ struct kconf_id_strings_t | |||
107 | char kconf_id_strings_str21[sizeof("string")]; | 108 | char kconf_id_strings_str21[sizeof("string")]; |
108 | char kconf_id_strings_str22[sizeof("if")]; | 109 | char kconf_id_strings_str22[sizeof("if")]; |
109 | char kconf_id_strings_str23[sizeof("int")]; | 110 | char kconf_id_strings_str23[sizeof("int")]; |
110 | char kconf_id_strings_str24[sizeof("enable")]; | ||
111 | char kconf_id_strings_str26[sizeof("select")]; | 111 | char kconf_id_strings_str26[sizeof("select")]; |
112 | char kconf_id_strings_str27[sizeof("modules")]; | 112 | char kconf_id_strings_str27[sizeof("modules")]; |
113 | char kconf_id_strings_str28[sizeof("tristate")]; | 113 | char kconf_id_strings_str28[sizeof("tristate")]; |
@@ -123,6 +123,7 @@ struct kconf_id_strings_t | |||
123 | static struct kconf_id_strings_t kconf_id_strings_contents = | 123 | static struct kconf_id_strings_t kconf_id_strings_contents = |
124 | { | 124 | { |
125 | "on", | 125 | "on", |
126 | "env", | ||
126 | "endif", | 127 | "endif", |
127 | "option", | 128 | "option", |
128 | "endmenu", | 129 | "endmenu", |
@@ -141,7 +142,6 @@ static struct kconf_id_strings_t kconf_id_strings_contents = | |||
141 | "string", | 142 | "string", |
142 | "if", | 143 | "if", |
143 | "int", | 144 | "int", |
144 | "enable", | ||
145 | "select", | 145 | "select", |
146 | "modules", | 146 | "modules", |
147 | "tristate", | 147 | "tristate", |
@@ -157,6 +157,9 @@ static struct kconf_id_strings_t kconf_id_strings_contents = | |||
157 | #define kconf_id_strings ((const char *) &kconf_id_strings_contents) | 157 | #define kconf_id_strings ((const char *) &kconf_id_strings_contents) |
158 | #ifdef __GNUC__ | 158 | #ifdef __GNUC__ |
159 | __inline | 159 | __inline |
160 | #ifdef __GNUC_STDC_INLINE__ | ||
161 | __attribute__ ((__gnu_inline__)) | ||
162 | #endif | ||
160 | #endif | 163 | #endif |
161 | struct kconf_id * | 164 | struct kconf_id * |
162 | kconf_id_lookup (register const char *str, register unsigned int len) | 165 | kconf_id_lookup (register const char *str, register unsigned int len) |
@@ -174,7 +177,8 @@ kconf_id_lookup (register const char *str, register unsigned int len) | |||
174 | { | 177 | { |
175 | {-1}, {-1}, | 178 | {-1}, {-1}, |
176 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM}, | 179 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM}, |
177 | {-1}, {-1}, | 180 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_OPT_ENV, TF_OPTION}, |
181 | {-1}, | ||
178 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, | 182 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, |
179 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_OPTION, TF_COMMAND}, | 183 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_OPTION, TF_COMMAND}, |
180 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND}, | 184 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND}, |
@@ -194,8 +198,7 @@ kconf_id_lookup (register const char *str, register unsigned int len) | |||
194 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_TYPE, TF_COMMAND, S_STRING}, | 198 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_TYPE, TF_COMMAND, S_STRING}, |
195 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_IF, TF_COMMAND|TF_PARAM}, | 199 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_IF, TF_COMMAND|TF_PARAM}, |
196 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_INT}, | 200 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_INT}, |
197 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str24, T_SELECT, TF_COMMAND}, | 201 | {-1}, {-1}, |
198 | {-1}, | ||
199 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SELECT, TF_COMMAND}, | 202 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SELECT, TF_COMMAND}, |
200 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION}, | 203 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION}, |
201 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_TRISTATE}, | 204 | {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_TRISTATE}, |
diff --git a/scripts/kconfig/zconf.l b/scripts/kconfig/zconf.l index 187d38ccadd5..4cea5c85cd0a 100644 --- a/scripts/kconfig/zconf.l +++ b/scripts/kconfig/zconf.l | |||
@@ -217,6 +217,11 @@ n [A-Za-z0-9_] | |||
217 | append_string("\n", 1); | 217 | append_string("\n", 1); |
218 | } | 218 | } |
219 | [^ \t\n].* { | 219 | [^ \t\n].* { |
220 | while (yyleng) { | ||
221 | if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) | ||
222 | break; | ||
223 | yyleng--; | ||
224 | } | ||
220 | append_string(yytext, yyleng); | 225 | append_string(yytext, yyleng); |
221 | if (!first_ts) | 226 | if (!first_ts) |
222 | first_ts = last_ts; | 227 | first_ts = last_ts; |
diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 1d1401807e95..ec54f12f57b0 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc | |||
@@ -46,21 +46,24 @@ use strict; | |||
46 | # Note: This only supports 'c'. | 46 | # Note: This only supports 'c'. |
47 | 47 | ||
48 | # usage: | 48 | # usage: |
49 | # kernel-doc [ -docbook | -html | -text | -man ] | 49 | # kernel-doc [ -docbook | -html | -text | -man ] [ -no-doc-sections ] |
50 | # [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile | 50 | # [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile |
51 | # or | 51 | # or |
52 | # [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile | 52 | # [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile |
53 | # | 53 | # |
54 | # Set output format using one of -docbook -html -text or -man. Default is man. | 54 | # Set output format using one of -docbook -html -text or -man. Default is man. |
55 | # | 55 | # |
56 | # -no-doc-sections | ||
57 | # Do not output DOC: sections | ||
58 | # | ||
56 | # -function funcname | 59 | # -function funcname |
57 | # If set, then only generate documentation for the given function(s). All | 60 | # If set, then only generate documentation for the given function(s) or |
58 | # other functions are ignored. | 61 | # DOC: section titles. All other functions and DOC: sections are ignored. |
59 | # | 62 | # |
60 | # -nofunction funcname | 63 | # -nofunction funcname |
61 | # If set, then only generate documentation for the other function(s). | 64 | # If set, then only generate documentation for the other function(s)/DOC: |
62 | # Cannot be used together with -function | 65 | # sections. Cannot be used together with -function (yes, that's a bug -- |
63 | # (yes, that's a bug -- perl hackers can fix it 8)) | 66 | # perl hackers can fix it 8)) |
64 | # | 67 | # |
65 | # c files - list of 'c' files to process | 68 | # c files - list of 'c' files to process |
66 | # | 69 | # |
@@ -182,10 +185,10 @@ my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>" | |||
182 | my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>", | 185 | my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>", |
183 | $type_constant, "<constant>\$1</constant>", | 186 | $type_constant, "<constant>\$1</constant>", |
184 | $type_func, "<function>\$1</function>", | 187 | $type_func, "<function>\$1</function>", |
185 | $type_struct, "<structname>\$1</structname>", | 188 | $type_struct_xml, "<structname>\$1</structname>", |
186 | $type_env, "<envar>\$1</envar>", | 189 | $type_env, "<envar>\$1</envar>", |
187 | $type_param, "<parameter>\$1</parameter>" ); | 190 | $type_param, "<parameter>\$1</parameter>" ); |
188 | my $blankline_xml = "</para><para>\n"; | 191 | my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n"; |
189 | 192 | ||
190 | # gnome, docbook format | 193 | # gnome, docbook format |
191 | my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>", | 194 | my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>", |
@@ -211,7 +214,7 @@ my $blankline_text = ""; | |||
211 | 214 | ||
212 | 215 | ||
213 | sub usage { | 216 | sub usage { |
214 | print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n"; | 217 | print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ] [ -no-doc-sections ]\n"; |
215 | print " [ -function funcname [ -function funcname ...] ]\n"; | 218 | print " [ -function funcname [ -function funcname ...] ]\n"; |
216 | print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; | 219 | print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; |
217 | print " c source file(s) > outputfile\n"; | 220 | print " c source file(s) > outputfile\n"; |
@@ -225,6 +228,7 @@ if ($#ARGV==-1) { | |||
225 | 228 | ||
226 | my $verbose = 0; | 229 | my $verbose = 0; |
227 | my $output_mode = "man"; | 230 | my $output_mode = "man"; |
231 | my $no_doc_sections = 0; | ||
228 | my %highlights = %highlights_man; | 232 | my %highlights = %highlights_man; |
229 | my $blankline = $blankline_man; | 233 | my $blankline = $blankline_man; |
230 | my $modulename = "Kernel API"; | 234 | my $modulename = "Kernel API"; |
@@ -329,12 +333,14 @@ while ($ARGV[0] =~ m/^-(.*)/) { | |||
329 | usage(); | 333 | usage(); |
330 | } elsif ($cmd eq '-filelist') { | 334 | } elsif ($cmd eq '-filelist') { |
331 | $filelist = shift @ARGV; | 335 | $filelist = shift @ARGV; |
336 | } elsif ($cmd eq '-no-doc-sections') { | ||
337 | $no_doc_sections = 1; | ||
332 | } | 338 | } |
333 | } | 339 | } |
334 | 340 | ||
335 | # get kernel version from env | 341 | # get kernel version from env |
336 | sub get_kernel_version() { | 342 | sub get_kernel_version() { |
337 | my $version; | 343 | my $version = 'unknown kernel version'; |
338 | 344 | ||
339 | if (defined($ENV{'KERNELVERSION'})) { | 345 | if (defined($ENV{'KERNELVERSION'})) { |
340 | $version = $ENV{'KERNELVERSION'}; | 346 | $version = $ENV{'KERNELVERSION'}; |
@@ -374,6 +380,29 @@ sub dump_section { | |||
374 | } | 380 | } |
375 | 381 | ||
376 | ## | 382 | ## |
383 | # dump DOC: section after checking that it should go out | ||
384 | # | ||
385 | sub dump_doc_section { | ||
386 | my $name = shift; | ||
387 | my $contents = join "\n", @_; | ||
388 | |||
389 | if ($no_doc_sections) { | ||
390 | return; | ||
391 | } | ||
392 | |||
393 | if (($function_only == 0) || | ||
394 | ( $function_only == 1 && defined($function_table{$name})) || | ||
395 | ( $function_only == 2 && !defined($function_table{$name}))) | ||
396 | { | ||
397 | dump_section $name, $contents; | ||
398 | output_blockhead({'sectionlist' => \@sectionlist, | ||
399 | 'sections' => \%sections, | ||
400 | 'module' => $modulename, | ||
401 | 'content-only' => ($function_only != 0), }); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | ## | ||
377 | # output function | 406 | # output function |
378 | # | 407 | # |
379 | # parameterdescs, a hash. | 408 | # parameterdescs, a hash. |
@@ -394,7 +423,7 @@ sub output_highlight { | |||
394 | # confess "output_highlight got called with no args?\n"; | 423 | # confess "output_highlight got called with no args?\n"; |
395 | # } | 424 | # } |
396 | 425 | ||
397 | if ($output_mode eq "html") { | 426 | if ($output_mode eq "html" || $output_mode eq "xml") { |
398 | $contents = local_unescape($contents); | 427 | $contents = local_unescape($contents); |
399 | # convert data read & converted thru xml_escape() into &xyz; format: | 428 | # convert data read & converted thru xml_escape() into &xyz; format: |
400 | $contents =~ s/\\\\\\/&/g; | 429 | $contents =~ s/\\\\\\/&/g; |
@@ -564,8 +593,8 @@ sub output_function_html(%) { | |||
564 | print "<hr>\n"; | 593 | print "<hr>\n"; |
565 | } | 594 | } |
566 | 595 | ||
567 | # output intro in html | 596 | # output DOC: block header in html |
568 | sub output_intro_html(%) { | 597 | sub output_blockhead_html(%) { |
569 | my %args = %{$_[0]}; | 598 | my %args = %{$_[0]}; |
570 | my ($parameter, $section); | 599 | my ($parameter, $section); |
571 | my $count; | 600 | my $count; |
@@ -871,7 +900,7 @@ sub output_typedef_xml(%) { | |||
871 | } | 900 | } |
872 | 901 | ||
873 | # output in XML DocBook | 902 | # output in XML DocBook |
874 | sub output_intro_xml(%) { | 903 | sub output_blockhead_xml(%) { |
875 | my %args = %{$_[0]}; | 904 | my %args = %{$_[0]}; |
876 | my ($parameter, $section); | 905 | my ($parameter, $section); |
877 | my $count; | 906 | my $count; |
@@ -882,15 +911,23 @@ sub output_intro_xml(%) { | |||
882 | # print out each section | 911 | # print out each section |
883 | $lineprefix=" "; | 912 | $lineprefix=" "; |
884 | foreach $section (@{$args{'sectionlist'}}) { | 913 | foreach $section (@{$args{'sectionlist'}}) { |
885 | print "<refsect1>\n <title>$section</title>\n <para>\n"; | 914 | if (!$args{'content-only'}) { |
915 | print "<refsect1>\n <title>$section</title>\n"; | ||
916 | } | ||
886 | if ($section =~ m/EXAMPLE/i) { | 917 | if ($section =~ m/EXAMPLE/i) { |
887 | print "<example><para>\n"; | 918 | print "<example><para>\n"; |
919 | } else { | ||
920 | print "<para>\n"; | ||
888 | } | 921 | } |
889 | output_highlight($args{'sections'}{$section}); | 922 | output_highlight($args{'sections'}{$section}); |
890 | if ($section =~ m/EXAMPLE/i) { | 923 | if ($section =~ m/EXAMPLE/i) { |
891 | print "</para></example>\n"; | 924 | print "</para></example>\n"; |
925 | } else { | ||
926 | print "</para>"; | ||
927 | } | ||
928 | if (!$args{'content-only'}) { | ||
929 | print "\n</refsect1>\n"; | ||
892 | } | 930 | } |
893 | print " </para>\n</refsect1>\n"; | ||
894 | } | 931 | } |
895 | 932 | ||
896 | print "\n\n"; | 933 | print "\n\n"; |
@@ -1137,7 +1174,7 @@ sub output_typedef_man(%) { | |||
1137 | } | 1174 | } |
1138 | } | 1175 | } |
1139 | 1176 | ||
1140 | sub output_intro_man(%) { | 1177 | sub output_blockhead_man(%) { |
1141 | my %args = %{$_[0]}; | 1178 | my %args = %{$_[0]}; |
1142 | my ($parameter, $section); | 1179 | my ($parameter, $section); |
1143 | my $count; | 1180 | my $count; |
@@ -1294,7 +1331,7 @@ sub output_struct_text(%) { | |||
1294 | output_section_text(@_); | 1331 | output_section_text(@_); |
1295 | } | 1332 | } |
1296 | 1333 | ||
1297 | sub output_intro_text(%) { | 1334 | sub output_blockhead_text(%) { |
1298 | my %args = %{$_[0]}; | 1335 | my %args = %{$_[0]}; |
1299 | my ($parameter, $section); | 1336 | my ($parameter, $section); |
1300 | 1337 | ||
@@ -1325,9 +1362,9 @@ sub output_declaration { | |||
1325 | 1362 | ||
1326 | ## | 1363 | ## |
1327 | # generic output function - calls the right one based on current output mode. | 1364 | # generic output function - calls the right one based on current output mode. |
1328 | sub output_intro { | 1365 | sub output_blockhead { |
1329 | no strict 'refs'; | 1366 | no strict 'refs'; |
1330 | my $func = "output_intro_".$output_mode; | 1367 | my $func = "output_blockhead_".$output_mode; |
1331 | &$func(@_); | 1368 | &$func(@_); |
1332 | $section_counter++; | 1369 | $section_counter++; |
1333 | } | 1370 | } |
@@ -1926,9 +1963,7 @@ sub process_file($) { | |||
1926 | } elsif ($state == 4) { | 1963 | } elsif ($state == 4) { |
1927 | # Documentation block | 1964 | # Documentation block |
1928 | if (/$doc_block/) { | 1965 | if (/$doc_block/) { |
1929 | dump_section($section, xml_escape($contents)); | 1966 | dump_doc_section($section, xml_escape($contents)); |
1930 | output_intro({'sectionlist' => \@sectionlist, | ||
1931 | 'sections' => \%sections }); | ||
1932 | $contents = ""; | 1967 | $contents = ""; |
1933 | $function = ""; | 1968 | $function = ""; |
1934 | %constants = (); | 1969 | %constants = (); |
@@ -1946,9 +1981,7 @@ sub process_file($) { | |||
1946 | } | 1981 | } |
1947 | elsif (/$doc_end/) | 1982 | elsif (/$doc_end/) |
1948 | { | 1983 | { |
1949 | dump_section($section, xml_escape($contents)); | 1984 | dump_doc_section($section, xml_escape($contents)); |
1950 | output_intro({'sectionlist' => \@sectionlist, | ||
1951 | 'sections' => \%sections }); | ||
1952 | $contents = ""; | 1985 | $contents = ""; |
1953 | $function = ""; | 1986 | $function = ""; |
1954 | %constants = (); | 1987 | %constants = (); |
diff --git a/scripts/mkmakefile b/scripts/mkmakefile index e0f54b9d8fec..e65d8b33faa4 100644 --- a/scripts/mkmakefile +++ b/scripts/mkmakefile | |||
@@ -25,8 +25,11 @@ cat << EOF > $2/Makefile | |||
25 | VERSION = $3 | 25 | VERSION = $3 |
26 | PATCHLEVEL = $4 | 26 | PATCHLEVEL = $4 |
27 | 27 | ||
28 | KERNELSRC := $1 | 28 | lastword = \$(word \$(words \$(1)),\$(1)) |
29 | KERNELOUTPUT := $2 | 29 | makedir := \$(dir \$(call lastword,\$(MAKEFILE_LIST))) |
30 | |||
31 | MAKEARGS := -C $1 | ||
32 | MAKEARGS += O=\$(if \$(patsubst /%,,\$(makedir)),\$(CURDIR)/)\$(patsubst %/,%,\$(makedir)) | ||
30 | 33 | ||
31 | MAKEFLAGS += --no-print-directory | 34 | MAKEFLAGS += --no-print-directory |
32 | 35 | ||
@@ -35,10 +38,11 @@ MAKEFLAGS += --no-print-directory | |||
35 | all := \$(filter-out all Makefile,\$(MAKECMDGOALS)) | 38 | all := \$(filter-out all Makefile,\$(MAKECMDGOALS)) |
36 | 39 | ||
37 | all: | 40 | all: |
38 | \$(MAKE) -C \$(KERNELSRC) O=\$(KERNELOUTPUT) \$(all) | 41 | \$(MAKE) \$(MAKEARGS) \$(all) |
39 | 42 | ||
40 | Makefile:; | 43 | Makefile:; |
41 | 44 | ||
42 | \$(all) %/: all | 45 | \$(all) %/: all |
43 | @: | 46 | @: |
47 | |||
44 | EOF | 48 | EOF |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 93ac52adb498..f8efc93eb700 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright 2003 Kai Germaschewski | 3 | * Copyright 2003 Kai Germaschewski |
4 | * Copyright 2002-2004 Rusty Russell, IBM Corporation | 4 | * Copyright 2002-2004 Rusty Russell, IBM Corporation |
5 | * Copyright 2006 Sam Ravnborg | 5 | * Copyright 2006-2008 Sam Ravnborg |
6 | * Based in part on module-init-tools/depmod.c,file2alias | 6 | * Based in part on module-init-tools/depmod.c,file2alias |
7 | * | 7 | * |
8 | * This software may be used and distributed according to the terms | 8 | * This software may be used and distributed according to the terms |
@@ -28,12 +28,17 @@ static int vmlinux_section_warnings = 1; | |||
28 | /* Only warn about unresolved symbols */ | 28 | /* Only warn about unresolved symbols */ |
29 | static int warn_unresolved = 0; | 29 | static int warn_unresolved = 0; |
30 | /* How a symbol is exported */ | 30 | /* How a symbol is exported */ |
31 | static int sec_mismatch_count = 0; | ||
32 | static int sec_mismatch_verbose = 1; | ||
33 | |||
31 | enum export { | 34 | enum export { |
32 | export_plain, export_unused, export_gpl, | 35 | export_plain, export_unused, export_gpl, |
33 | export_unused_gpl, export_gpl_future, export_unknown | 36 | export_unused_gpl, export_gpl_future, export_unknown |
34 | }; | 37 | }; |
35 | 38 | ||
36 | void fatal(const char *fmt, ...) | 39 | #define PRINTF __attribute__ ((format (printf, 1, 2))) |
40 | |||
41 | PRINTF void fatal(const char *fmt, ...) | ||
37 | { | 42 | { |
38 | va_list arglist; | 43 | va_list arglist; |
39 | 44 | ||
@@ -46,7 +51,7 @@ void fatal(const char *fmt, ...) | |||
46 | exit(1); | 51 | exit(1); |
47 | } | 52 | } |
48 | 53 | ||
49 | void warn(const char *fmt, ...) | 54 | PRINTF void warn(const char *fmt, ...) |
50 | { | 55 | { |
51 | va_list arglist; | 56 | va_list arglist; |
52 | 57 | ||
@@ -57,7 +62,7 @@ void warn(const char *fmt, ...) | |||
57 | va_end(arglist); | 62 | va_end(arglist); |
58 | } | 63 | } |
59 | 64 | ||
60 | void merror(const char *fmt, ...) | 65 | PRINTF void merror(const char *fmt, ...) |
61 | { | 66 | { |
62 | va_list arglist; | 67 | va_list arglist; |
63 | 68 | ||
@@ -72,7 +77,8 @@ static int is_vmlinux(const char *modname) | |||
72 | { | 77 | { |
73 | const char *myname; | 78 | const char *myname; |
74 | 79 | ||
75 | if ((myname = strrchr(modname, '/'))) | 80 | myname = strrchr(modname, '/'); |
81 | if (myname) | ||
76 | myname++; | 82 | myname++; |
77 | else | 83 | else |
78 | myname = modname; | 84 | myname = modname; |
@@ -83,14 +89,13 @@ static int is_vmlinux(const char *modname) | |||
83 | 89 | ||
84 | void *do_nofail(void *ptr, const char *expr) | 90 | void *do_nofail(void *ptr, const char *expr) |
85 | { | 91 | { |
86 | if (!ptr) { | 92 | if (!ptr) |
87 | fatal("modpost: Memory allocation failure: %s.\n", expr); | 93 | fatal("modpost: Memory allocation failure: %s.\n", expr); |
88 | } | 94 | |
89 | return ptr; | 95 | return ptr; |
90 | } | 96 | } |
91 | 97 | ||
92 | /* A list of all modules we processed */ | 98 | /* A list of all modules we processed */ |
93 | |||
94 | static struct module *modules; | 99 | static struct module *modules; |
95 | 100 | ||
96 | static struct module *find_module(char *modname) | 101 | static struct module *find_module(char *modname) |
@@ -113,7 +118,8 @@ static struct module *new_module(char *modname) | |||
113 | p = NOFAIL(strdup(modname)); | 118 | p = NOFAIL(strdup(modname)); |
114 | 119 | ||
115 | /* strip trailing .o */ | 120 | /* strip trailing .o */ |
116 | if ((s = strrchr(p, '.')) != NULL) | 121 | s = strrchr(p, '.'); |
122 | if (s != NULL) | ||
117 | if (strcmp(s, ".o") == 0) | 123 | if (strcmp(s, ".o") == 0) |
118 | *s = '\0'; | 124 | *s = '\0'; |
119 | 125 | ||
@@ -154,7 +160,7 @@ static inline unsigned int tdb_hash(const char *name) | |||
154 | unsigned i; /* Used to cycle through random values. */ | 160 | unsigned i; /* Used to cycle through random values. */ |
155 | 161 | ||
156 | /* Set the initial value from the key size. */ | 162 | /* Set the initial value from the key size. */ |
157 | for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++) | 163 | for (value = 0x238F13AF * strlen(name), i = 0; name[i]; i++) |
158 | value = (value + (((unsigned char *)name)[i] << (i*5 % 24))); | 164 | value = (value + (((unsigned char *)name)[i] << (i*5 % 24))); |
159 | 165 | ||
160 | return (1103515243 * value + 12345); | 166 | return (1103515243 * value + 12345); |
@@ -198,7 +204,7 @@ static struct symbol *find_symbol(const char *name) | |||
198 | if (name[0] == '.') | 204 | if (name[0] == '.') |
199 | name++; | 205 | name++; |
200 | 206 | ||
201 | for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s=s->next) { | 207 | for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s = s->next) { |
202 | if (strcmp(s->name, name) == 0) | 208 | if (strcmp(s->name, name) == 0) |
203 | return s; | 209 | return s; |
204 | } | 210 | } |
@@ -223,9 +229,10 @@ static const char *export_str(enum export ex) | |||
223 | return export_list[ex].str; | 229 | return export_list[ex].str; |
224 | } | 230 | } |
225 | 231 | ||
226 | static enum export export_no(const char * s) | 232 | static enum export export_no(const char *s) |
227 | { | 233 | { |
228 | int i; | 234 | int i; |
235 | |||
229 | if (!s) | 236 | if (!s) |
230 | return export_unknown; | 237 | return export_unknown; |
231 | for (i = 0; export_list[i].export != export_unknown; i++) { | 238 | for (i = 0; export_list[i].export != export_unknown; i++) { |
@@ -315,7 +322,7 @@ void *grab_file(const char *filename, unsigned long *size) | |||
315 | * spaces in the beginning of the line is trimmed away. | 322 | * spaces in the beginning of the line is trimmed away. |
316 | * Return a pointer to a static buffer. | 323 | * Return a pointer to a static buffer. |
317 | **/ | 324 | **/ |
318 | char* get_next_line(unsigned long *pos, void *file, unsigned long size) | 325 | char *get_next_line(unsigned long *pos, void *file, unsigned long size) |
319 | { | 326 | { |
320 | static char line[4096]; | 327 | static char line[4096]; |
321 | int skip = 1; | 328 | int skip = 1; |
@@ -323,8 +330,7 @@ char* get_next_line(unsigned long *pos, void *file, unsigned long size) | |||
323 | signed char *p = (signed char *)file + *pos; | 330 | signed char *p = (signed char *)file + *pos; |
324 | char *s = line; | 331 | char *s = line; |
325 | 332 | ||
326 | for (; *pos < size ; (*pos)++) | 333 | for (; *pos < size ; (*pos)++) { |
327 | { | ||
328 | if (skip && isspace(*p)) { | 334 | if (skip && isspace(*p)) { |
329 | p++; | 335 | p++; |
330 | continue; | 336 | continue; |
@@ -386,7 +392,9 @@ static int parse_elf(struct elf_info *info, const char *filename) | |||
386 | 392 | ||
387 | /* Check if file offset is correct */ | 393 | /* Check if file offset is correct */ |
388 | if (hdr->e_shoff > info->size) { | 394 | if (hdr->e_shoff > info->size) { |
389 | fatal("section header offset=%u in file '%s' is bigger then filesize=%lu\n", hdr->e_shoff, filename, info->size); | 395 | fatal("section header offset=%lu in file '%s' is bigger than " |
396 | "filesize=%lu\n", (unsigned long)hdr->e_shoff, | ||
397 | filename, info->size); | ||
390 | return 0; | 398 | return 0; |
391 | } | 399 | } |
392 | 400 | ||
@@ -407,7 +415,10 @@ static int parse_elf(struct elf_info *info, const char *filename) | |||
407 | const char *secname; | 415 | const char *secname; |
408 | 416 | ||
409 | if (sechdrs[i].sh_offset > info->size) { | 417 | if (sechdrs[i].sh_offset > info->size) { |
410 | fatal("%s is truncated. sechdrs[i].sh_offset=%u > sizeof(*hrd)=%ul\n", filename, (unsigned int)sechdrs[i].sh_offset, sizeof(*hdr)); | 418 | fatal("%s is truncated. sechdrs[i].sh_offset=%lu > " |
419 | "sizeof(*hrd)=%zu\n", filename, | ||
420 | (unsigned long)sechdrs[i].sh_offset, | ||
421 | sizeof(*hdr)); | ||
411 | return 0; | 422 | return 0; |
412 | } | 423 | } |
413 | secname = secstrings + sechdrs[i].sh_name; | 424 | secname = secstrings + sechdrs[i].sh_name; |
@@ -434,9 +445,9 @@ static int parse_elf(struct elf_info *info, const char *filename) | |||
434 | info->strtab = (void *)hdr + | 445 | info->strtab = (void *)hdr + |
435 | sechdrs[sechdrs[i].sh_link].sh_offset; | 446 | sechdrs[sechdrs[i].sh_link].sh_offset; |
436 | } | 447 | } |
437 | if (!info->symtab_start) { | 448 | if (!info->symtab_start) |
438 | fatal("%s has no symtab?\n", filename); | 449 | fatal("%s has no symtab?\n", filename); |
439 | } | 450 | |
440 | /* Fix endianness in symbols */ | 451 | /* Fix endianness in symbols */ |
441 | for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { | 452 | for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { |
442 | sym->st_shndx = TO_NATIVE(sym->st_shndx); | 453 | sym->st_shndx = TO_NATIVE(sym->st_shndx); |
@@ -505,11 +516,13 @@ static void handle_modversions(struct module *mod, struct elf_info *info, | |||
505 | #endif | 516 | #endif |
506 | 517 | ||
507 | if (memcmp(symname, MODULE_SYMBOL_PREFIX, | 518 | if (memcmp(symname, MODULE_SYMBOL_PREFIX, |
508 | strlen(MODULE_SYMBOL_PREFIX)) == 0) | 519 | strlen(MODULE_SYMBOL_PREFIX)) == 0) { |
509 | mod->unres = alloc_symbol(symname + | 520 | mod->unres = |
510 | strlen(MODULE_SYMBOL_PREFIX), | 521 | alloc_symbol(symname + |
511 | ELF_ST_BIND(sym->st_info) == STB_WEAK, | 522 | strlen(MODULE_SYMBOL_PREFIX), |
512 | mod->unres); | 523 | ELF_ST_BIND(sym->st_info) == STB_WEAK, |
524 | mod->unres); | ||
525 | } | ||
513 | break; | 526 | break; |
514 | default: | 527 | default: |
515 | /* All exported symbols */ | 528 | /* All exported symbols */ |
@@ -578,69 +591,303 @@ static char *get_modinfo(void *modinfo, unsigned long modinfo_len, | |||
578 | **/ | 591 | **/ |
579 | static int strrcmp(const char *s, const char *sub) | 592 | static int strrcmp(const char *s, const char *sub) |
580 | { | 593 | { |
581 | int slen, sublen; | 594 | int slen, sublen; |
582 | 595 | ||
583 | if (!s || !sub) | 596 | if (!s || !sub) |
584 | return 1; | 597 | return 1; |
585 | 598 | ||
586 | slen = strlen(s); | 599 | slen = strlen(s); |
587 | sublen = strlen(sub); | 600 | sublen = strlen(sub); |
588 | 601 | ||
589 | if ((slen == 0) || (sublen == 0)) | 602 | if ((slen == 0) || (sublen == 0)) |
590 | return 1; | 603 | return 1; |
591 | 604 | ||
592 | if (sublen > slen) | 605 | if (sublen > slen) |
593 | return 1; | 606 | return 1; |
594 | 607 | ||
595 | return memcmp(s + slen - sublen, sub, sublen); | 608 | return memcmp(s + slen - sublen, sub, sublen); |
596 | } | 609 | } |
597 | 610 | ||
598 | /* | 611 | static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) |
599 | * Functions used only during module init is marked __init and is stored in | 612 | { |
600 | * a .init.text section. Likewise data is marked __initdata and stored in | 613 | if (sym) |
601 | * a .init.data section. | 614 | return elf->strtab + sym->st_name; |
602 | * If this section is one of these sections return 1 | 615 | else |
603 | * See include/linux/init.h for the details | 616 | return ""; |
617 | } | ||
618 | |||
619 | static const char *sec_name(struct elf_info *elf, int shndx) | ||
620 | { | ||
621 | Elf_Shdr *sechdrs = elf->sechdrs; | ||
622 | return (void *)elf->hdr + | ||
623 | elf->sechdrs[elf->hdr->e_shstrndx].sh_offset + | ||
624 | sechdrs[shndx].sh_name; | ||
625 | } | ||
626 | |||
627 | static const char *sech_name(struct elf_info *elf, Elf_Shdr *sechdr) | ||
628 | { | ||
629 | return (void *)elf->hdr + | ||
630 | elf->sechdrs[elf->hdr->e_shstrndx].sh_offset + | ||
631 | sechdr->sh_name; | ||
632 | } | ||
633 | |||
634 | /* if sym is empty or point to a string | ||
635 | * like ".[0-9]+" then return 1. | ||
636 | * This is the optional prefix added by ld to some sections | ||
604 | */ | 637 | */ |
605 | static int init_section(const char *name) | 638 | static int number_prefix(const char *sym) |
606 | { | 639 | { |
607 | if (strcmp(name, ".init") == 0) | 640 | if (*sym++ == '\0') |
608 | return 1; | ||
609 | if (strncmp(name, ".init.", strlen(".init.")) == 0) | ||
610 | return 1; | 641 | return 1; |
642 | if (*sym != '.') | ||
643 | return 0; | ||
644 | do { | ||
645 | char c = *sym++; | ||
646 | if (c < '0' || c > '9') | ||
647 | return 0; | ||
648 | } while (*sym); | ||
649 | return 1; | ||
650 | } | ||
651 | |||
652 | /* The pattern is an array of simple patterns. | ||
653 | * "foo" will match an exact string equal to "foo" | ||
654 | * "*foo" will match a string that ends with "foo" | ||
655 | * "foo*" will match a string that begins with "foo" | ||
656 | * "foo$" will match a string equal to "foo" or "foo.1" | ||
657 | * where the '1' can be any number including several digits. | ||
658 | * The $ syntax is for sections where ld append a dot number | ||
659 | * to make section name unique. | ||
660 | */ | ||
661 | int match(const char *sym, const char * const pat[]) | ||
662 | { | ||
663 | const char *p; | ||
664 | while (*pat) { | ||
665 | p = *pat++; | ||
666 | const char *endp = p + strlen(p) - 1; | ||
667 | |||
668 | /* "*foo" */ | ||
669 | if (*p == '*') { | ||
670 | if (strrcmp(sym, p + 1) == 0) | ||
671 | return 1; | ||
672 | } | ||
673 | /* "foo*" */ | ||
674 | else if (*endp == '*') { | ||
675 | if (strncmp(sym, p, strlen(p) - 1) == 0) | ||
676 | return 1; | ||
677 | } | ||
678 | /* "foo$" */ | ||
679 | else if (*endp == '$') { | ||
680 | if (strncmp(sym, p, strlen(p) - 1) == 0) { | ||
681 | if (number_prefix(sym + strlen(p) - 1)) | ||
682 | return 1; | ||
683 | } | ||
684 | } | ||
685 | /* no wildcards */ | ||
686 | else { | ||
687 | if (strcmp(p, sym) == 0) | ||
688 | return 1; | ||
689 | } | ||
690 | } | ||
691 | /* no match */ | ||
611 | return 0; | 692 | return 0; |
612 | } | 693 | } |
613 | 694 | ||
695 | /* sections that we do not want to do full section mismatch check on */ | ||
696 | static const char *section_white_list[] = | ||
697 | { ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL }; | ||
698 | |||
614 | /* | 699 | /* |
615 | * Functions used only during module exit is marked __exit and is stored in | 700 | * Is this section one we do not want to check? |
616 | * a .exit.text section. Likewise data is marked __exitdata and stored in | 701 | * This is often debug sections. |
617 | * a .exit.data section. | 702 | * If we are going to check this section then |
618 | * If this section is one of these sections return 1 | 703 | * test if section name ends with a dot and a number. |
619 | * See include/linux/init.h for the details | 704 | * This is used to find sections where the linker have |
620 | **/ | 705 | * appended a dot-number to make the name unique. |
621 | static int exit_section(const char *name) | 706 | * The cause of this is often a section specified in assembler |
707 | * without "ax" / "aw" and the same section used in .c | ||
708 | * code where gcc add these. | ||
709 | */ | ||
710 | static int check_section(const char *modname, const char *sec) | ||
622 | { | 711 | { |
623 | if (strcmp(name, ".exit.text") == 0) | 712 | const char *e = sec + strlen(sec) - 1; |
624 | return 1; | 713 | if (match(sec, section_white_list)) |
625 | if (strcmp(name, ".exit.data") == 0) | ||
626 | return 1; | 714 | return 1; |
627 | return 0; | ||
628 | 715 | ||
716 | if (*e && isdigit(*e)) { | ||
717 | /* consume all digits */ | ||
718 | while (*e && e != sec && isdigit(*e)) | ||
719 | e--; | ||
720 | if (*e == '.') { | ||
721 | warn("%s (%s): unexpected section name.\n" | ||
722 | "The (.[number]+) following section name are " | ||
723 | "ld generated and not expected.\n" | ||
724 | "Did you forget to use \"ax\"/\"aw\" " | ||
725 | "in a .S file?\n" | ||
726 | "Note that for example <linux/init.h> contains\n" | ||
727 | "section definitions for use in .S files.\n\n", | ||
728 | modname, sec); | ||
729 | } | ||
730 | } | ||
731 | return 0; | ||
629 | } | 732 | } |
630 | 733 | ||
631 | /* | 734 | |
632 | * Data sections are named like this: | 735 | |
633 | * .data | .data.rel | .data.rel.* | 736 | #define ALL_INIT_DATA_SECTIONS \ |
634 | * Return 1 if the specified section is a data section | 737 | ".init.data$", ".devinit.data$", ".cpuinit.data$", ".meminit.data$" |
738 | #define ALL_EXIT_DATA_SECTIONS \ | ||
739 | ".exit.data$", ".devexit.data$", ".cpuexit.data$", ".memexit.data$" | ||
740 | |||
741 | #define ALL_INIT_TEXT_SECTIONS \ | ||
742 | ".init.text$", ".devinit.text$", ".cpuinit.text$", ".meminit.text$" | ||
743 | #define ALL_EXIT_TEXT_SECTIONS \ | ||
744 | ".exit.text$", ".devexit.text$", ".cpuexit.text$", ".memexit.text$" | ||
745 | |||
746 | #define ALL_INIT_SECTIONS ALL_INIT_DATA_SECTIONS, ALL_INIT_TEXT_SECTIONS | ||
747 | #define ALL_EXIT_SECTIONS ALL_EXIT_DATA_SECTIONS, ALL_EXIT_TEXT_SECTIONS | ||
748 | |||
749 | #define DATA_SECTIONS ".data$", ".data.rel$" | ||
750 | #define TEXT_SECTIONS ".text$" | ||
751 | |||
752 | #define INIT_SECTIONS ".init.data$", ".init.text$" | ||
753 | #define DEV_INIT_SECTIONS ".devinit.data$", ".devinit.text$" | ||
754 | #define CPU_INIT_SECTIONS ".cpuinit.data$", ".cpuinit.text$" | ||
755 | #define MEM_INIT_SECTIONS ".meminit.data$", ".meminit.text$" | ||
756 | |||
757 | #define EXIT_SECTIONS ".exit.data$", ".exit.text$" | ||
758 | #define DEV_EXIT_SECTIONS ".devexit.data$", ".devexit.text$" | ||
759 | #define CPU_EXIT_SECTIONS ".cpuexit.data$", ".cpuexit.text$" | ||
760 | #define MEM_EXIT_SECTIONS ".memexit.data$", ".memexit.text$" | ||
761 | |||
762 | /* init data sections */ | ||
763 | static const char *init_data_sections[] = { ALL_INIT_DATA_SECTIONS, NULL }; | ||
764 | |||
765 | /* all init sections */ | ||
766 | static const char *init_sections[] = { ALL_INIT_SECTIONS, NULL }; | ||
767 | |||
768 | /* All init and exit sections (code + data) */ | ||
769 | static const char *init_exit_sections[] = | ||
770 | {ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }; | ||
771 | |||
772 | /* data section */ | ||
773 | static const char *data_sections[] = { DATA_SECTIONS, NULL }; | ||
774 | |||
775 | /* sections that may refer to an init/exit section with no warning */ | ||
776 | static const char *initref_sections[] = | ||
777 | { | ||
778 | ".text.init.refok*", | ||
779 | ".exit.text.refok*", | ||
780 | ".data.init.refok*", | ||
781 | NULL | ||
782 | }; | ||
783 | |||
784 | |||
785 | /* symbols in .data that may refer to init/exit sections */ | ||
786 | static const char *symbol_white_list[] = | ||
787 | { | ||
788 | "*driver", | ||
789 | "*_template", /* scsi uses *_template a lot */ | ||
790 | "*_timer", /* arm uses ops structures named _timer a lot */ | ||
791 | "*_sht", /* scsi also used *_sht to some extent */ | ||
792 | "*_ops", | ||
793 | "*_probe", | ||
794 | "*_probe_one", | ||
795 | "*_console", | ||
796 | NULL | ||
797 | }; | ||
798 | |||
799 | static const char *head_sections[] = { ".head.text*", NULL }; | ||
800 | static const char *linker_symbols[] = | ||
801 | { "__init_begin", "_sinittext", "_einittext", NULL }; | ||
802 | |||
803 | enum mismatch { | ||
804 | NO_MISMATCH, | ||
805 | TEXT_TO_INIT, | ||
806 | DATA_TO_INIT, | ||
807 | TEXT_TO_EXIT, | ||
808 | DATA_TO_EXIT, | ||
809 | XXXINIT_TO_INIT, | ||
810 | XXXEXIT_TO_EXIT, | ||
811 | INIT_TO_EXIT, | ||
812 | EXIT_TO_INIT, | ||
813 | EXPORT_TO_INIT_EXIT, | ||
814 | }; | ||
815 | |||
816 | struct sectioncheck { | ||
817 | const char *fromsec[20]; | ||
818 | const char *tosec[20]; | ||
819 | enum mismatch mismatch; | ||
820 | }; | ||
821 | |||
822 | const struct sectioncheck sectioncheck[] = { | ||
823 | /* Do not reference init/exit code/data from | ||
824 | * normal code and data | ||
635 | */ | 825 | */ |
636 | static int data_section(const char *name) | ||
637 | { | 826 | { |
638 | if ((strcmp(name, ".data") == 0) || | 827 | .fromsec = { TEXT_SECTIONS, NULL }, |
639 | (strcmp(name, ".data.rel") == 0) || | 828 | .tosec = { ALL_INIT_SECTIONS, NULL }, |
640 | (strncmp(name, ".data.rel.", strlen(".data.rel.")) == 0)) | 829 | .mismatch = TEXT_TO_INIT, |
641 | return 1; | 830 | }, |
642 | else | 831 | { |
643 | return 0; | 832 | .fromsec = { DATA_SECTIONS, NULL }, |
833 | .tosec = { ALL_INIT_SECTIONS, NULL }, | ||
834 | .mismatch = DATA_TO_INIT, | ||
835 | }, | ||
836 | { | ||
837 | .fromsec = { TEXT_SECTIONS, NULL }, | ||
838 | .tosec = { ALL_EXIT_SECTIONS, NULL }, | ||
839 | .mismatch = TEXT_TO_EXIT, | ||
840 | }, | ||
841 | { | ||
842 | .fromsec = { DATA_SECTIONS, NULL }, | ||
843 | .tosec = { ALL_EXIT_SECTIONS, NULL }, | ||
844 | .mismatch = DATA_TO_EXIT, | ||
845 | }, | ||
846 | /* Do not reference init code/data from devinit/cpuinit/meminit code/data */ | ||
847 | { | ||
848 | .fromsec = { DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, MEM_INIT_SECTIONS, NULL }, | ||
849 | .tosec = { INIT_SECTIONS, NULL }, | ||
850 | .mismatch = XXXINIT_TO_INIT, | ||
851 | }, | ||
852 | /* Do not reference exit code/data from devexit/cpuexit/memexit code/data */ | ||
853 | { | ||
854 | .fromsec = { DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, MEM_EXIT_SECTIONS, NULL }, | ||
855 | .tosec = { EXIT_SECTIONS, NULL }, | ||
856 | .mismatch = XXXEXIT_TO_EXIT, | ||
857 | }, | ||
858 | /* Do not use exit code/data from init code */ | ||
859 | { | ||
860 | .fromsec = { ALL_INIT_SECTIONS, NULL }, | ||
861 | .tosec = { ALL_EXIT_SECTIONS, NULL }, | ||
862 | .mismatch = INIT_TO_EXIT, | ||
863 | }, | ||
864 | /* Do not use init code/data from exit code */ | ||
865 | { | ||
866 | .fromsec = { ALL_EXIT_SECTIONS, NULL }, | ||
867 | .tosec = { ALL_INIT_SECTIONS, NULL }, | ||
868 | .mismatch = EXIT_TO_INIT, | ||
869 | }, | ||
870 | /* Do not export init/exit functions or data */ | ||
871 | { | ||
872 | .fromsec = { "__ksymtab*", NULL }, | ||
873 | .tosec = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL }, | ||
874 | .mismatch = EXPORT_TO_INIT_EXIT | ||
875 | } | ||
876 | }; | ||
877 | |||
878 | static int section_mismatch(const char *fromsec, const char *tosec) | ||
879 | { | ||
880 | int i; | ||
881 | int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck); | ||
882 | const struct sectioncheck *check = §ioncheck[0]; | ||
883 | |||
884 | for (i = 0; i < elems; i++) { | ||
885 | if (match(fromsec, check->fromsec) && | ||
886 | match(tosec, check->tosec)) | ||
887 | return check->mismatch; | ||
888 | check++; | ||
889 | } | ||
890 | return NO_MISMATCH; | ||
644 | } | 891 | } |
645 | 892 | ||
646 | /** | 893 | /** |
@@ -669,7 +916,8 @@ static int data_section(const char *name) | |||
669 | * the pattern is identified by: | 916 | * the pattern is identified by: |
670 | * tosec = init or exit section | 917 | * tosec = init or exit section |
671 | * fromsec = data section | 918 | * fromsec = data section |
672 | * atsym = *driver, *_template, *_sht, *_ops, *_probe, *probe_one, *_console, *_timer | 919 | * atsym = *driver, *_template, *_sht, *_ops, *_probe, |
920 | * *probe_one, *_console, *_timer | ||
673 | * | 921 | * |
674 | * Pattern 3: | 922 | * Pattern 3: |
675 | * Whitelist all refereces from .text.head to .init.data | 923 | * Whitelist all refereces from .text.head to .init.data |
@@ -684,77 +932,36 @@ static int data_section(const char *name) | |||
684 | * This pattern is identified by | 932 | * This pattern is identified by |
685 | * refsymname = __init_begin, _sinittext, _einittext | 933 | * refsymname = __init_begin, _sinittext, _einittext |
686 | * | 934 | * |
687 | * Pattern 5: | ||
688 | * Xtensa uses literal sections for constants that are accessed PC-relative. | ||
689 | * Literal sections may safely reference their text sections. | ||
690 | * (Note that the name for the literal section omits any trailing '.text') | ||
691 | * tosec = <section>[.text] | ||
692 | * fromsec = <section>.literal | ||
693 | **/ | 935 | **/ |
694 | static int secref_whitelist(const char *modname, const char *tosec, | 936 | static int secref_whitelist(const char *fromsec, const char *fromsym, |
695 | const char *fromsec, const char *atsym, | 937 | const char *tosec, const char *tosym) |
696 | const char *refsymname) | ||
697 | { | 938 | { |
698 | int len; | ||
699 | const char **s; | ||
700 | const char *pat2sym[] = { | ||
701 | "driver", | ||
702 | "_template", /* scsi uses *_template a lot */ | ||
703 | "_timer", /* arm uses ops structures named _timer a lot */ | ||
704 | "_sht", /* scsi also used *_sht to some extent */ | ||
705 | "_ops", | ||
706 | "_probe", | ||
707 | "_probe_one", | ||
708 | "_console", | ||
709 | NULL | ||
710 | }; | ||
711 | |||
712 | const char *pat3refsym[] = { | ||
713 | "__init_begin", | ||
714 | "_sinittext", | ||
715 | "_einittext", | ||
716 | NULL | ||
717 | }; | ||
718 | |||
719 | /* Check for pattern 0 */ | 939 | /* Check for pattern 0 */ |
720 | if ((strncmp(fromsec, ".text.init.refok", strlen(".text.init.refok")) == 0) || | 940 | if (match(fromsec, initref_sections)) |
721 | (strncmp(fromsec, ".exit.text.refok", strlen(".exit.text.refok")) == 0) || | 941 | return 0; |
722 | (strncmp(fromsec, ".data.init.refok", strlen(".data.init.refok")) == 0)) | ||
723 | return 1; | ||
724 | 942 | ||
725 | /* Check for pattern 1 */ | 943 | /* Check for pattern 1 */ |
726 | if ((strcmp(tosec, ".init.data") == 0) && | 944 | if (match(tosec, init_data_sections) && |
727 | (strncmp(fromsec, ".data", strlen(".data")) == 0) && | 945 | match(fromsec, data_sections) && |
728 | (strncmp(atsym, "__param", strlen("__param")) == 0)) | 946 | (strncmp(fromsym, "__param", strlen("__param")) == 0)) |
729 | return 1; | 947 | return 0; |
730 | 948 | ||
731 | /* Check for pattern 2 */ | 949 | /* Check for pattern 2 */ |
732 | if ((init_section(tosec) || exit_section(tosec)) && data_section(fromsec)) | 950 | if (match(tosec, init_exit_sections) && |
733 | for (s = pat2sym; *s; s++) | 951 | match(fromsec, data_sections) && |
734 | if (strrcmp(atsym, *s) == 0) | 952 | match(fromsym, symbol_white_list)) |
735 | return 1; | 953 | return 0; |
736 | 954 | ||
737 | /* Check for pattern 3 */ | 955 | /* Check for pattern 3 */ |
738 | if ((strcmp(fromsec, ".text.head") == 0) && | 956 | if (match(fromsec, head_sections) && |
739 | ((strcmp(tosec, ".init.data") == 0) || | 957 | match(tosec, init_sections)) |
740 | (strcmp(tosec, ".init.text") == 0))) | 958 | return 0; |
741 | return 1; | ||
742 | 959 | ||
743 | /* Check for pattern 4 */ | 960 | /* Check for pattern 4 */ |
744 | for (s = pat3refsym; *s; s++) | 961 | if (match(tosym, linker_symbols)) |
745 | if (strcmp(refsymname, *s) == 0) | 962 | return 0; |
746 | return 1; | ||
747 | |||
748 | /* Check for pattern 5 */ | ||
749 | if (strrcmp(tosec, ".text") == 0) | ||
750 | len = strlen(tosec) - strlen(".text"); | ||
751 | else | ||
752 | len = strlen(tosec); | ||
753 | if ((strncmp(tosec, fromsec, len) == 0) && (strlen(fromsec) > len) && | ||
754 | (strcmp(fromsec + len, ".literal") == 0)) | ||
755 | return 1; | ||
756 | 963 | ||
757 | return 0; | 964 | return 1; |
758 | } | 965 | } |
759 | 966 | ||
760 | /** | 967 | /** |
@@ -764,10 +971,13 @@ static int secref_whitelist(const char *modname, const char *tosec, | |||
764 | * In other cases the symbol needs to be looked up in the symbol table | 971 | * In other cases the symbol needs to be looked up in the symbol table |
765 | * based on section and address. | 972 | * based on section and address. |
766 | * **/ | 973 | * **/ |
767 | static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr, | 974 | static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, |
768 | Elf_Sym *relsym) | 975 | Elf_Sym *relsym) |
769 | { | 976 | { |
770 | Elf_Sym *sym; | 977 | Elf_Sym *sym; |
978 | Elf_Sym *near = NULL; | ||
979 | Elf64_Sword distance = 20; | ||
980 | Elf64_Sword d; | ||
771 | 981 | ||
772 | if (relsym->st_name != 0) | 982 | if (relsym->st_name != 0) |
773 | return relsym; | 983 | return relsym; |
@@ -778,8 +988,20 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr, | |||
778 | continue; | 988 | continue; |
779 | if (sym->st_value == addr) | 989 | if (sym->st_value == addr) |
780 | return sym; | 990 | return sym; |
991 | /* Find a symbol nearby - addr are maybe negative */ | ||
992 | d = sym->st_value - addr; | ||
993 | if (d < 0) | ||
994 | d = addr - sym->st_value; | ||
995 | if (d < distance) { | ||
996 | distance = d; | ||
997 | near = sym; | ||
998 | } | ||
781 | } | 999 | } |
782 | return NULL; | 1000 | /* We need a close match */ |
1001 | if (distance < 20) | ||
1002 | return near; | ||
1003 | else | ||
1004 | return NULL; | ||
783 | } | 1005 | } |
784 | 1006 | ||
785 | static inline int is_arm_mapping_symbol(const char *str) | 1007 | static inline int is_arm_mapping_symbol(const char *str) |
@@ -812,121 +1034,245 @@ static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym) | |||
812 | * The ELF format may have a better way to detect what type of symbol | 1034 | * The ELF format may have a better way to detect what type of symbol |
813 | * it is, but this works for now. | 1035 | * it is, but this works for now. |
814 | **/ | 1036 | **/ |
815 | static void find_symbols_between(struct elf_info *elf, Elf_Addr addr, | 1037 | static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, |
816 | const char *sec, | 1038 | const char *sec) |
817 | Elf_Sym **before, Elf_Sym **after) | ||
818 | { | 1039 | { |
819 | Elf_Sym *sym; | 1040 | Elf_Sym *sym; |
820 | Elf_Ehdr *hdr = elf->hdr; | 1041 | Elf_Sym *near = NULL; |
821 | Elf_Addr beforediff = ~0; | 1042 | Elf_Addr distance = ~0; |
822 | Elf_Addr afterdiff = ~0; | ||
823 | const char *secstrings = (void *)hdr + | ||
824 | elf->sechdrs[hdr->e_shstrndx].sh_offset; | ||
825 | |||
826 | *before = NULL; | ||
827 | *after = NULL; | ||
828 | 1043 | ||
829 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { | 1044 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { |
830 | const char *symsec; | 1045 | const char *symsec; |
831 | 1046 | ||
832 | if (sym->st_shndx >= SHN_LORESERVE) | 1047 | if (sym->st_shndx >= SHN_LORESERVE) |
833 | continue; | 1048 | continue; |
834 | symsec = secstrings + elf->sechdrs[sym->st_shndx].sh_name; | 1049 | symsec = sec_name(elf, sym->st_shndx); |
835 | if (strcmp(symsec, sec) != 0) | 1050 | if (strcmp(symsec, sec) != 0) |
836 | continue; | 1051 | continue; |
837 | if (!is_valid_name(elf, sym)) | 1052 | if (!is_valid_name(elf, sym)) |
838 | continue; | 1053 | continue; |
839 | if (sym->st_value <= addr) { | 1054 | if (sym->st_value <= addr) { |
840 | if ((addr - sym->st_value) < beforediff) { | 1055 | if ((addr - sym->st_value) < distance) { |
841 | beforediff = addr - sym->st_value; | 1056 | distance = addr - sym->st_value; |
842 | *before = sym; | 1057 | near = sym; |
843 | } | 1058 | } else if ((addr - sym->st_value) == distance) { |
844 | else if ((addr - sym->st_value) == beforediff) { | 1059 | near = sym; |
845 | *before = sym; | ||
846 | } | 1060 | } |
847 | } | 1061 | } |
1062 | } | ||
1063 | return near; | ||
1064 | } | ||
1065 | |||
1066 | /* | ||
1067 | * Convert a section name to the function/data attribute | ||
1068 | * .init.text => __init | ||
1069 | * .cpuinit.data => __cpudata | ||
1070 | * .memexitconst => __memconst | ||
1071 | * etc. | ||
1072 | */ | ||
1073 | static char *sec2annotation(const char *s) | ||
1074 | { | ||
1075 | if (match(s, init_exit_sections)) { | ||
1076 | char *p = malloc(20); | ||
1077 | char *r = p; | ||
1078 | |||
1079 | *p++ = '_'; | ||
1080 | *p++ = '_'; | ||
1081 | if (*s == '.') | ||
1082 | s++; | ||
1083 | while (*s && *s != '.') | ||
1084 | *p++ = *s++; | ||
1085 | *p = '\0'; | ||
1086 | if (*s == '.') | ||
1087 | s++; | ||
1088 | if (strstr(s, "rodata") != NULL) | ||
1089 | strcat(p, "const "); | ||
1090 | else if (strstr(s, "data") != NULL) | ||
1091 | strcat(p, "data "); | ||
848 | else | 1092 | else |
849 | { | 1093 | strcat(p, " "); |
850 | if ((sym->st_value - addr) < afterdiff) { | 1094 | return r; /* we leak her but we do not care */ |
851 | afterdiff = sym->st_value - addr; | 1095 | } else { |
852 | *after = sym; | 1096 | return ""; |
853 | } | ||
854 | else if ((sym->st_value - addr) == afterdiff) { | ||
855 | *after = sym; | ||
856 | } | ||
857 | } | ||
858 | } | 1097 | } |
859 | } | 1098 | } |
860 | 1099 | ||
861 | /** | 1100 | static int is_function(Elf_Sym *sym) |
1101 | { | ||
1102 | if (sym) | ||
1103 | return ELF_ST_TYPE(sym->st_info) == STT_FUNC; | ||
1104 | else | ||
1105 | return 0; | ||
1106 | } | ||
1107 | |||
1108 | /* | ||
862 | * Print a warning about a section mismatch. | 1109 | * Print a warning about a section mismatch. |
863 | * Try to find symbols near it so user can find it. | 1110 | * Try to find symbols near it so user can find it. |
864 | * Check whitelist before warning - it may be a false positive. | 1111 | * Check whitelist before warning - it may be a false positive. |
865 | **/ | 1112 | */ |
866 | static void warn_sec_mismatch(const char *modname, const char *fromsec, | 1113 | static void report_sec_mismatch(const char *modname, enum mismatch mismatch, |
867 | struct elf_info *elf, Elf_Sym *sym, Elf_Rela r) | 1114 | const char *fromsec, |
1115 | unsigned long long fromaddr, | ||
1116 | const char *fromsym, | ||
1117 | int from_is_func, | ||
1118 | const char *tosec, const char *tosym, | ||
1119 | int to_is_func) | ||
868 | { | 1120 | { |
869 | const char *refsymname = ""; | 1121 | const char *from, *from_p; |
870 | Elf_Sym *before, *after; | 1122 | const char *to, *to_p; |
871 | Elf_Sym *refsym; | 1123 | from = from_is_func ? "function" : "variable"; |
872 | Elf_Ehdr *hdr = elf->hdr; | 1124 | from_p = from_is_func ? "()" : ""; |
873 | Elf_Shdr *sechdrs = elf->sechdrs; | 1125 | to = to_is_func ? "function" : "variable"; |
874 | const char *secstrings = (void *)hdr + | 1126 | to_p = to_is_func ? "()" : ""; |
875 | sechdrs[hdr->e_shstrndx].sh_offset; | 1127 | |
876 | const char *secname = secstrings + sechdrs[sym->st_shndx].sh_name; | 1128 | fprintf(stderr, "WARNING: %s(%s+0x%llx): Section mismatch in" |
877 | 1129 | " reference from the %s %s%s to the %s %s:%s%s\n", | |
878 | find_symbols_between(elf, r.r_offset, fromsec, &before, &after); | 1130 | modname, fromsec, fromaddr, from, fromsym, from_p, |
879 | 1131 | to, tosec, tosym, to_p); | |
880 | refsym = find_elf_symbol(elf, r.r_addend, sym); | 1132 | |
881 | if (refsym && strlen(elf->strtab + refsym->st_name)) | 1133 | sec_mismatch_count++; |
882 | refsymname = elf->strtab + refsym->st_name; | 1134 | if (!sec_mismatch_verbose) |
883 | |||
884 | /* check whitelist - we may ignore it */ | ||
885 | if (secref_whitelist(modname, secname, fromsec, | ||
886 | before ? elf->strtab + before->st_name : "", | ||
887 | refsymname)) | ||
888 | return; | 1135 | return; |
889 | 1136 | ||
890 | if (before && after) { | 1137 | switch (mismatch) { |
891 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " | 1138 | case TEXT_TO_INIT: |
892 | "(between '%s' and '%s')\n", | 1139 | fprintf(stderr, |
893 | modname, fromsec, (unsigned long long)r.r_offset, | 1140 | "The function %s %s() references\n" |
894 | secname, refsymname, | 1141 | "the %s %s%s%s.\n" |
895 | elf->strtab + before->st_name, | 1142 | "This is often because %s lacks a %s\n" |
896 | elf->strtab + after->st_name); | 1143 | "annotation or the annotation of %s is wrong.\n", |
897 | } else if (before) { | 1144 | sec2annotation(fromsec), fromsym, |
898 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " | 1145 | to, sec2annotation(tosec), tosym, to_p, |
899 | "(after '%s')\n", | 1146 | fromsym, sec2annotation(tosec), tosym); |
900 | modname, fromsec, (unsigned long long)r.r_offset, | 1147 | break; |
901 | secname, refsymname, | 1148 | case DATA_TO_INIT: { |
902 | elf->strtab + before->st_name); | 1149 | const char **s = symbol_white_list; |
903 | } else if (after) { | 1150 | fprintf(stderr, |
904 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s " | 1151 | "The variable %s references\n" |
905 | "before '%s' (at offset -0x%llx)\n", | 1152 | "the %s %s%s%s\n" |
906 | modname, fromsec, (unsigned long long)r.r_offset, | 1153 | "If the reference is valid then annotate the\n" |
907 | secname, refsymname, | 1154 | "variable with __init* (see linux/init.h) " |
908 | elf->strtab + after->st_name); | 1155 | "or name the variable:\n", |
909 | } else { | 1156 | fromsym, to, sec2annotation(tosec), tosym, to_p); |
910 | warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n", | 1157 | while (*s) |
911 | modname, fromsec, (unsigned long long)r.r_offset, | 1158 | fprintf(stderr, "%s, ", *s++); |
912 | secname, refsymname); | 1159 | fprintf(stderr, "\n"); |
1160 | break; | ||
1161 | } | ||
1162 | case TEXT_TO_EXIT: | ||
1163 | fprintf(stderr, | ||
1164 | "The function %s() references a %s in an exit section.\n" | ||
1165 | "Often the %s %s%s has valid usage outside the exit section\n" | ||
1166 | "and the fix is to remove the %sannotation of %s.\n", | ||
1167 | fromsym, to, to, tosym, to_p, sec2annotation(tosec), tosym); | ||
1168 | break; | ||
1169 | case DATA_TO_EXIT: { | ||
1170 | const char **s = symbol_white_list; | ||
1171 | fprintf(stderr, | ||
1172 | "The variable %s references\n" | ||
1173 | "the %s %s%s%s\n" | ||
1174 | "If the reference is valid then annotate the\n" | ||
1175 | "variable with __exit* (see linux/init.h) or " | ||
1176 | "name the variable:\n", | ||
1177 | fromsym, to, sec2annotation(tosec), tosym, to_p); | ||
1178 | while (*s) | ||
1179 | fprintf(stderr, "%s, ", *s++); | ||
1180 | fprintf(stderr, "\n"); | ||
1181 | break; | ||
1182 | } | ||
1183 | case XXXINIT_TO_INIT: | ||
1184 | case XXXEXIT_TO_EXIT: | ||
1185 | fprintf(stderr, | ||
1186 | "The %s %s%s%s references\n" | ||
1187 | "a %s %s%s%s.\n" | ||
1188 | "If %s is only used by %s then\n" | ||
1189 | "annotate %s with a matching annotation.\n", | ||
1190 | from, sec2annotation(fromsec), fromsym, from_p, | ||
1191 | to, sec2annotation(tosec), tosym, to_p, | ||
1192 | fromsym, tosym, fromsym); | ||
1193 | break; | ||
1194 | case INIT_TO_EXIT: | ||
1195 | fprintf(stderr, | ||
1196 | "The %s %s%s%s references\n" | ||
1197 | "a %s %s%s%s.\n" | ||
1198 | "This is often seen when error handling " | ||
1199 | "in the init function\n" | ||
1200 | "uses functionality in the exit path.\n" | ||
1201 | "The fix is often to remove the %sannotation of\n" | ||
1202 | "%s%s so it may be used outside an exit section.\n", | ||
1203 | from, sec2annotation(fromsec), fromsym, from_p, | ||
1204 | to, sec2annotation(tosec), tosym, to_p, | ||
1205 | sec2annotation(tosec), tosym, to_p); | ||
1206 | break; | ||
1207 | case EXIT_TO_INIT: | ||
1208 | fprintf(stderr, | ||
1209 | "The %s %s%s%s references\n" | ||
1210 | "a %s %s%s%s.\n" | ||
1211 | "This is often seen when error handling " | ||
1212 | "in the exit function\n" | ||
1213 | "uses functionality in the init path.\n" | ||
1214 | "The fix is often to remove the %sannotation of\n" | ||
1215 | "%s%s so it may be used outside an init section.\n", | ||
1216 | from, sec2annotation(fromsec), fromsym, from_p, | ||
1217 | to, sec2annotation(tosec), tosym, to_p, | ||
1218 | sec2annotation(tosec), tosym, to_p); | ||
1219 | break; | ||
1220 | case EXPORT_TO_INIT_EXIT: | ||
1221 | fprintf(stderr, | ||
1222 | "The symbol %s is exported and annotated %s\n" | ||
1223 | "Fix this by removing the %sannotation of %s " | ||
1224 | "or drop the export.\n", | ||
1225 | tosym, sec2annotation(tosec), sec2annotation(tosec), tosym); | ||
1226 | case NO_MISMATCH: | ||
1227 | /* To get warnings on missing members */ | ||
1228 | break; | ||
1229 | } | ||
1230 | fprintf(stderr, "\n"); | ||
1231 | } | ||
1232 | |||
1233 | static void check_section_mismatch(const char *modname, struct elf_info *elf, | ||
1234 | Elf_Rela *r, Elf_Sym *sym, const char *fromsec) | ||
1235 | { | ||
1236 | const char *tosec; | ||
1237 | enum mismatch mismatch; | ||
1238 | |||
1239 | tosec = sec_name(elf, sym->st_shndx); | ||
1240 | mismatch = section_mismatch(fromsec, tosec); | ||
1241 | if (mismatch != NO_MISMATCH) { | ||
1242 | Elf_Sym *to; | ||
1243 | Elf_Sym *from; | ||
1244 | const char *tosym; | ||
1245 | const char *fromsym; | ||
1246 | |||
1247 | from = find_elf_symbol2(elf, r->r_offset, fromsec); | ||
1248 | fromsym = sym_name(elf, from); | ||
1249 | to = find_elf_symbol(elf, r->r_addend, sym); | ||
1250 | tosym = sym_name(elf, to); | ||
1251 | |||
1252 | /* check whitelist - we may ignore it */ | ||
1253 | if (secref_whitelist(fromsec, fromsym, tosec, tosym)) { | ||
1254 | report_sec_mismatch(modname, mismatch, | ||
1255 | fromsec, r->r_offset, fromsym, | ||
1256 | is_function(from), tosec, tosym, | ||
1257 | is_function(to)); | ||
1258 | } | ||
913 | } | 1259 | } |
914 | } | 1260 | } |
915 | 1261 | ||
916 | static unsigned int *reloc_location(struct elf_info *elf, | 1262 | static unsigned int *reloc_location(struct elf_info *elf, |
917 | int rsection, Elf_Rela *r) | 1263 | Elf_Shdr *sechdr, Elf_Rela *r) |
918 | { | 1264 | { |
919 | Elf_Shdr *sechdrs = elf->sechdrs; | 1265 | Elf_Shdr *sechdrs = elf->sechdrs; |
920 | int section = sechdrs[rsection].sh_info; | 1266 | int section = sechdr->sh_info; |
921 | 1267 | ||
922 | return (void *)elf->hdr + sechdrs[section].sh_offset + | 1268 | return (void *)elf->hdr + sechdrs[section].sh_offset + |
923 | (r->r_offset - sechdrs[section].sh_addr); | 1269 | (r->r_offset - sechdrs[section].sh_addr); |
924 | } | 1270 | } |
925 | 1271 | ||
926 | static int addend_386_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | 1272 | static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) |
927 | { | 1273 | { |
928 | unsigned int r_typ = ELF_R_TYPE(r->r_info); | 1274 | unsigned int r_typ = ELF_R_TYPE(r->r_info); |
929 | unsigned int *location = reloc_location(elf, rsection, r); | 1275 | unsigned int *location = reloc_location(elf, sechdr, r); |
930 | 1276 | ||
931 | switch (r_typ) { | 1277 | switch (r_typ) { |
932 | case R_386_32: | 1278 | case R_386_32: |
@@ -942,19 +1288,21 @@ static int addend_386_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | |||
942 | return 0; | 1288 | return 0; |
943 | } | 1289 | } |
944 | 1290 | ||
945 | static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | 1291 | static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) |
946 | { | 1292 | { |
947 | unsigned int r_typ = ELF_R_TYPE(r->r_info); | 1293 | unsigned int r_typ = ELF_R_TYPE(r->r_info); |
948 | 1294 | ||
949 | switch (r_typ) { | 1295 | switch (r_typ) { |
950 | case R_ARM_ABS32: | 1296 | case R_ARM_ABS32: |
951 | /* From ARM ABI: (S + A) | T */ | 1297 | /* From ARM ABI: (S + A) | T */ |
952 | r->r_addend = (int)(long)(elf->symtab_start + ELF_R_SYM(r->r_info)); | 1298 | r->r_addend = (int)(long) |
1299 | (elf->symtab_start + ELF_R_SYM(r->r_info)); | ||
953 | break; | 1300 | break; |
954 | case R_ARM_PC24: | 1301 | case R_ARM_PC24: |
955 | /* From ARM ABI: ((S + A) | T) - P */ | 1302 | /* From ARM ABI: ((S + A) | T) - P */ |
956 | r->r_addend = (int)(long)(elf->hdr + elf->sechdrs[rsection].sh_offset + | 1303 | r->r_addend = (int)(long)(elf->hdr + |
957 | (r->r_offset - elf->sechdrs[rsection].sh_addr)); | 1304 | sechdr->sh_offset + |
1305 | (r->r_offset - sechdr->sh_addr)); | ||
958 | break; | 1306 | break; |
959 | default: | 1307 | default: |
960 | return 1; | 1308 | return 1; |
@@ -962,10 +1310,10 @@ static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | |||
962 | return 0; | 1310 | return 0; |
963 | } | 1311 | } |
964 | 1312 | ||
965 | static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | 1313 | static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) |
966 | { | 1314 | { |
967 | unsigned int r_typ = ELF_R_TYPE(r->r_info); | 1315 | unsigned int r_typ = ELF_R_TYPE(r->r_info); |
968 | unsigned int *location = reloc_location(elf, rsection, r); | 1316 | unsigned int *location = reloc_location(elf, sechdr, r); |
969 | unsigned int inst; | 1317 | unsigned int inst; |
970 | 1318 | ||
971 | if (r_typ == R_MIPS_HI16) | 1319 | if (r_typ == R_MIPS_HI16) |
@@ -985,6 +1333,108 @@ static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | |||
985 | return 0; | 1333 | return 0; |
986 | } | 1334 | } |
987 | 1335 | ||
1336 | static void section_rela(const char *modname, struct elf_info *elf, | ||
1337 | Elf_Shdr *sechdr) | ||
1338 | { | ||
1339 | Elf_Sym *sym; | ||
1340 | Elf_Rela *rela; | ||
1341 | Elf_Rela r; | ||
1342 | unsigned int r_sym; | ||
1343 | const char *fromsec; | ||
1344 | |||
1345 | Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; | ||
1346 | Elf_Rela *stop = (void *)start + sechdr->sh_size; | ||
1347 | |||
1348 | fromsec = sech_name(elf, sechdr); | ||
1349 | fromsec += strlen(".rela"); | ||
1350 | /* if from section (name) is know good then skip it */ | ||
1351 | if (check_section(modname, fromsec)) | ||
1352 | return; | ||
1353 | |||
1354 | for (rela = start; rela < stop; rela++) { | ||
1355 | r.r_offset = TO_NATIVE(rela->r_offset); | ||
1356 | #if KERNEL_ELFCLASS == ELFCLASS64 | ||
1357 | if (elf->hdr->e_machine == EM_MIPS) { | ||
1358 | unsigned int r_typ; | ||
1359 | r_sym = ELF64_MIPS_R_SYM(rela->r_info); | ||
1360 | r_sym = TO_NATIVE(r_sym); | ||
1361 | r_typ = ELF64_MIPS_R_TYPE(rela->r_info); | ||
1362 | r.r_info = ELF64_R_INFO(r_sym, r_typ); | ||
1363 | } else { | ||
1364 | r.r_info = TO_NATIVE(rela->r_info); | ||
1365 | r_sym = ELF_R_SYM(r.r_info); | ||
1366 | } | ||
1367 | #else | ||
1368 | r.r_info = TO_NATIVE(rela->r_info); | ||
1369 | r_sym = ELF_R_SYM(r.r_info); | ||
1370 | #endif | ||
1371 | r.r_addend = TO_NATIVE(rela->r_addend); | ||
1372 | sym = elf->symtab_start + r_sym; | ||
1373 | /* Skip special sections */ | ||
1374 | if (sym->st_shndx >= SHN_LORESERVE) | ||
1375 | continue; | ||
1376 | check_section_mismatch(modname, elf, &r, sym, fromsec); | ||
1377 | } | ||
1378 | } | ||
1379 | |||
1380 | static void section_rel(const char *modname, struct elf_info *elf, | ||
1381 | Elf_Shdr *sechdr) | ||
1382 | { | ||
1383 | Elf_Sym *sym; | ||
1384 | Elf_Rel *rel; | ||
1385 | Elf_Rela r; | ||
1386 | unsigned int r_sym; | ||
1387 | const char *fromsec; | ||
1388 | |||
1389 | Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; | ||
1390 | Elf_Rel *stop = (void *)start + sechdr->sh_size; | ||
1391 | |||
1392 | fromsec = sech_name(elf, sechdr); | ||
1393 | fromsec += strlen(".rel"); | ||
1394 | /* if from section (name) is know good then skip it */ | ||
1395 | if (check_section(modname, fromsec)) | ||
1396 | return; | ||
1397 | |||
1398 | for (rel = start; rel < stop; rel++) { | ||
1399 | r.r_offset = TO_NATIVE(rel->r_offset); | ||
1400 | #if KERNEL_ELFCLASS == ELFCLASS64 | ||
1401 | if (elf->hdr->e_machine == EM_MIPS) { | ||
1402 | unsigned int r_typ; | ||
1403 | r_sym = ELF64_MIPS_R_SYM(rel->r_info); | ||
1404 | r_sym = TO_NATIVE(r_sym); | ||
1405 | r_typ = ELF64_MIPS_R_TYPE(rel->r_info); | ||
1406 | r.r_info = ELF64_R_INFO(r_sym, r_typ); | ||
1407 | } else { | ||
1408 | r.r_info = TO_NATIVE(rel->r_info); | ||
1409 | r_sym = ELF_R_SYM(r.r_info); | ||
1410 | } | ||
1411 | #else | ||
1412 | r.r_info = TO_NATIVE(rel->r_info); | ||
1413 | r_sym = ELF_R_SYM(r.r_info); | ||
1414 | #endif | ||
1415 | r.r_addend = 0; | ||
1416 | switch (elf->hdr->e_machine) { | ||
1417 | case EM_386: | ||
1418 | if (addend_386_rel(elf, sechdr, &r)) | ||
1419 | continue; | ||
1420 | break; | ||
1421 | case EM_ARM: | ||
1422 | if (addend_arm_rel(elf, sechdr, &r)) | ||
1423 | continue; | ||
1424 | break; | ||
1425 | case EM_MIPS: | ||
1426 | if (addend_mips_rel(elf, sechdr, &r)) | ||
1427 | continue; | ||
1428 | break; | ||
1429 | } | ||
1430 | sym = elf->symtab_start + r_sym; | ||
1431 | /* Skip special sections */ | ||
1432 | if (sym->st_shndx >= SHN_LORESERVE) | ||
1433 | continue; | ||
1434 | check_section_mismatch(modname, elf, &r, sym, fromsec); | ||
1435 | } | ||
1436 | } | ||
1437 | |||
988 | /** | 1438 | /** |
989 | * A module includes a number of sections that are discarded | 1439 | * A module includes a number of sections that are discarded |
990 | * either when loaded or when used as built-in. | 1440 | * either when loaded or when used as built-in. |
@@ -998,257 +1448,21 @@ static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r) | |||
998 | * be discarded and warns about it. | 1448 | * be discarded and warns about it. |
999 | **/ | 1449 | **/ |
1000 | static void check_sec_ref(struct module *mod, const char *modname, | 1450 | static void check_sec_ref(struct module *mod, const char *modname, |
1001 | struct elf_info *elf, | 1451 | struct elf_info *elf) |
1002 | int section(const char*), | ||
1003 | int section_ref_ok(const char *)) | ||
1004 | { | 1452 | { |
1005 | int i; | 1453 | int i; |
1006 | Elf_Sym *sym; | ||
1007 | Elf_Ehdr *hdr = elf->hdr; | ||
1008 | Elf_Shdr *sechdrs = elf->sechdrs; | 1454 | Elf_Shdr *sechdrs = elf->sechdrs; |
1009 | const char *secstrings = (void *)hdr + | ||
1010 | sechdrs[hdr->e_shstrndx].sh_offset; | ||
1011 | 1455 | ||
1012 | /* Walk through all sections */ | 1456 | /* Walk through all sections */ |
1013 | for (i = 0; i < hdr->e_shnum; i++) { | 1457 | for (i = 0; i < elf->hdr->e_shnum; i++) { |
1014 | const char *name = secstrings + sechdrs[i].sh_name; | ||
1015 | const char *secname; | ||
1016 | Elf_Rela r; | ||
1017 | unsigned int r_sym; | ||
1018 | /* We want to process only relocation sections and not .init */ | 1458 | /* We want to process only relocation sections and not .init */ |
1019 | if (sechdrs[i].sh_type == SHT_RELA) { | 1459 | if (sechdrs[i].sh_type == SHT_RELA) |
1020 | Elf_Rela *rela; | 1460 | section_rela(modname, elf, &elf->sechdrs[i]); |
1021 | Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset; | 1461 | else if (sechdrs[i].sh_type == SHT_REL) |
1022 | Elf_Rela *stop = (void*)start + sechdrs[i].sh_size; | 1462 | section_rel(modname, elf, &elf->sechdrs[i]); |
1023 | name += strlen(".rela"); | ||
1024 | if (section_ref_ok(name)) | ||
1025 | continue; | ||
1026 | |||
1027 | for (rela = start; rela < stop; rela++) { | ||
1028 | r.r_offset = TO_NATIVE(rela->r_offset); | ||
1029 | #if KERNEL_ELFCLASS == ELFCLASS64 | ||
1030 | if (hdr->e_machine == EM_MIPS) { | ||
1031 | unsigned int r_typ; | ||
1032 | r_sym = ELF64_MIPS_R_SYM(rela->r_info); | ||
1033 | r_sym = TO_NATIVE(r_sym); | ||
1034 | r_typ = ELF64_MIPS_R_TYPE(rela->r_info); | ||
1035 | r.r_info = ELF64_R_INFO(r_sym, r_typ); | ||
1036 | } else { | ||
1037 | r.r_info = TO_NATIVE(rela->r_info); | ||
1038 | r_sym = ELF_R_SYM(r.r_info); | ||
1039 | } | ||
1040 | #else | ||
1041 | r.r_info = TO_NATIVE(rela->r_info); | ||
1042 | r_sym = ELF_R_SYM(r.r_info); | ||
1043 | #endif | ||
1044 | r.r_addend = TO_NATIVE(rela->r_addend); | ||
1045 | sym = elf->symtab_start + r_sym; | ||
1046 | /* Skip special sections */ | ||
1047 | if (sym->st_shndx >= SHN_LORESERVE) | ||
1048 | continue; | ||
1049 | |||
1050 | secname = secstrings + | ||
1051 | sechdrs[sym->st_shndx].sh_name; | ||
1052 | if (section(secname)) | ||
1053 | warn_sec_mismatch(modname, name, | ||
1054 | elf, sym, r); | ||
1055 | } | ||
1056 | } else if (sechdrs[i].sh_type == SHT_REL) { | ||
1057 | Elf_Rel *rel; | ||
1058 | Elf_Rel *start = (void *)hdr + sechdrs[i].sh_offset; | ||
1059 | Elf_Rel *stop = (void*)start + sechdrs[i].sh_size; | ||
1060 | name += strlen(".rel"); | ||
1061 | if (section_ref_ok(name)) | ||
1062 | continue; | ||
1063 | |||
1064 | for (rel = start; rel < stop; rel++) { | ||
1065 | r.r_offset = TO_NATIVE(rel->r_offset); | ||
1066 | #if KERNEL_ELFCLASS == ELFCLASS64 | ||
1067 | if (hdr->e_machine == EM_MIPS) { | ||
1068 | unsigned int r_typ; | ||
1069 | r_sym = ELF64_MIPS_R_SYM(rel->r_info); | ||
1070 | r_sym = TO_NATIVE(r_sym); | ||
1071 | r_typ = ELF64_MIPS_R_TYPE(rel->r_info); | ||
1072 | r.r_info = ELF64_R_INFO(r_sym, r_typ); | ||
1073 | } else { | ||
1074 | r.r_info = TO_NATIVE(rel->r_info); | ||
1075 | r_sym = ELF_R_SYM(r.r_info); | ||
1076 | } | ||
1077 | #else | ||
1078 | r.r_info = TO_NATIVE(rel->r_info); | ||
1079 | r_sym = ELF_R_SYM(r.r_info); | ||
1080 | #endif | ||
1081 | r.r_addend = 0; | ||
1082 | switch (hdr->e_machine) { | ||
1083 | case EM_386: | ||
1084 | if (addend_386_rel(elf, i, &r)) | ||
1085 | continue; | ||
1086 | break; | ||
1087 | case EM_ARM: | ||
1088 | if(addend_arm_rel(elf, i, &r)) | ||
1089 | continue; | ||
1090 | break; | ||
1091 | case EM_MIPS: | ||
1092 | if (addend_mips_rel(elf, i, &r)) | ||
1093 | continue; | ||
1094 | break; | ||
1095 | } | ||
1096 | sym = elf->symtab_start + r_sym; | ||
1097 | /* Skip special sections */ | ||
1098 | if (sym->st_shndx >= SHN_LORESERVE) | ||
1099 | continue; | ||
1100 | |||
1101 | secname = secstrings + | ||
1102 | sechdrs[sym->st_shndx].sh_name; | ||
1103 | if (section(secname)) | ||
1104 | warn_sec_mismatch(modname, name, | ||
1105 | elf, sym, r); | ||
1106 | } | ||
1107 | } | ||
1108 | } | 1463 | } |
1109 | } | 1464 | } |
1110 | 1465 | ||
1111 | /* | ||
1112 | * Identify sections from which references to either a | ||
1113 | * .init or a .exit section is OK. | ||
1114 | * | ||
1115 | * [OPD] Keith Ownes <kaos@sgi.com> commented: | ||
1116 | * For our future {in}sanity, add a comment that this is the ppc .opd | ||
1117 | * section, not the ia64 .opd section. | ||
1118 | * ia64 .opd should not point to discarded sections. | ||
1119 | * [.rodata] like for .init.text we ignore .rodata references -same reason | ||
1120 | */ | ||
1121 | static int initexit_section_ref_ok(const char *name) | ||
1122 | { | ||
1123 | const char **s; | ||
1124 | /* Absolute section names */ | ||
1125 | const char *namelist1[] = { | ||
1126 | "__bug_table", /* used by powerpc for BUG() */ | ||
1127 | "__ex_table", | ||
1128 | ".altinstructions", | ||
1129 | ".cranges", /* used by sh64 */ | ||
1130 | ".fixup", | ||
1131 | ".machvec", /* ia64 + powerpc uses these */ | ||
1132 | ".machine.desc", | ||
1133 | ".opd", /* See comment [OPD] */ | ||
1134 | "__dbe_table", | ||
1135 | ".parainstructions", | ||
1136 | ".pdr", | ||
1137 | ".plt", /* seen on ARCH=um build on x86_64. Harmless */ | ||
1138 | ".smp_locks", | ||
1139 | ".stab", | ||
1140 | ".m68k_fixup", | ||
1141 | ".xt.prop", /* xtensa informational section */ | ||
1142 | ".xt.lit", /* xtensa informational section */ | ||
1143 | NULL | ||
1144 | }; | ||
1145 | /* Start of section names */ | ||
1146 | const char *namelist2[] = { | ||
1147 | ".debug", | ||
1148 | ".eh_frame", | ||
1149 | ".note", /* ignore ELF notes - may contain anything */ | ||
1150 | ".got", /* powerpc - global offset table */ | ||
1151 | ".toc", /* powerpc - table of contents */ | ||
1152 | NULL | ||
1153 | }; | ||
1154 | /* part of section name */ | ||
1155 | const char *namelist3 [] = { | ||
1156 | ".unwind", /* Sample: IA_64.unwind.exit.text */ | ||
1157 | NULL | ||
1158 | }; | ||
1159 | |||
1160 | for (s = namelist1; *s; s++) | ||
1161 | if (strcmp(*s, name) == 0) | ||
1162 | return 1; | ||
1163 | for (s = namelist2; *s; s++) | ||
1164 | if (strncmp(*s, name, strlen(*s)) == 0) | ||
1165 | return 1; | ||
1166 | for (s = namelist3; *s; s++) | ||
1167 | if (strstr(name, *s) != NULL) | ||
1168 | return 1; | ||
1169 | return 0; | ||
1170 | } | ||
1171 | |||
1172 | |||
1173 | /* | ||
1174 | * Identify sections from which references to a .init section is OK. | ||
1175 | * | ||
1176 | * Unfortunately references to read only data that referenced .init | ||
1177 | * sections had to be excluded. Almost all of these are false | ||
1178 | * positives, they are created by gcc. The downside of excluding rodata | ||
1179 | * is that there really are some user references from rodata to | ||
1180 | * init code, e.g. drivers/video/vgacon.c: | ||
1181 | * | ||
1182 | * const struct consw vga_con = { | ||
1183 | * con_startup: vgacon_startup, | ||
1184 | * | ||
1185 | * where vgacon_startup is __init. If you want to wade through the false | ||
1186 | * positives, take out the check for rodata. | ||
1187 | */ | ||
1188 | static int init_section_ref_ok(const char *name) | ||
1189 | { | ||
1190 | const char **s; | ||
1191 | /* Absolute section names */ | ||
1192 | const char *namelist1[] = { | ||
1193 | "__dbe_table", /* MIPS generate these */ | ||
1194 | "__ftr_fixup", /* powerpc cpu feature fixup */ | ||
1195 | "__fw_ftr_fixup", /* powerpc firmware feature fixup */ | ||
1196 | "__param", | ||
1197 | ".data.rel.ro", /* used by parisc64 */ | ||
1198 | ".init", | ||
1199 | ".text.lock", | ||
1200 | NULL | ||
1201 | }; | ||
1202 | /* Start of section names */ | ||
1203 | const char *namelist2[] = { | ||
1204 | ".init.", | ||
1205 | ".pci_fixup", | ||
1206 | ".rodata", | ||
1207 | NULL | ||
1208 | }; | ||
1209 | |||
1210 | if (initexit_section_ref_ok(name)) | ||
1211 | return 1; | ||
1212 | |||
1213 | for (s = namelist1; *s; s++) | ||
1214 | if (strcmp(*s, name) == 0) | ||
1215 | return 1; | ||
1216 | for (s = namelist2; *s; s++) | ||
1217 | if (strncmp(*s, name, strlen(*s)) == 0) | ||
1218 | return 1; | ||
1219 | |||
1220 | /* If section name ends with ".init" we allow references | ||
1221 | * as is the case with .initcallN.init, .early_param.init, .taglist.init etc | ||
1222 | */ | ||
1223 | if (strrcmp(name, ".init") == 0) | ||
1224 | return 1; | ||
1225 | return 0; | ||
1226 | } | ||
1227 | |||
1228 | /* | ||
1229 | * Identify sections from which references to a .exit section is OK. | ||
1230 | */ | ||
1231 | static int exit_section_ref_ok(const char *name) | ||
1232 | { | ||
1233 | const char **s; | ||
1234 | /* Absolute section names */ | ||
1235 | const char *namelist1[] = { | ||
1236 | ".exit.data", | ||
1237 | ".exit.text", | ||
1238 | ".exitcall.exit", | ||
1239 | ".rodata", | ||
1240 | NULL | ||
1241 | }; | ||
1242 | |||
1243 | if (initexit_section_ref_ok(name)) | ||
1244 | return 1; | ||
1245 | |||
1246 | for (s = namelist1; *s; s++) | ||
1247 | if (strcmp(*s, name) == 0) | ||
1248 | return 1; | ||
1249 | return 0; | ||
1250 | } | ||
1251 | |||
1252 | static void read_symbols(char *modname) | 1466 | static void read_symbols(char *modname) |
1253 | { | 1467 | { |
1254 | const char *symname; | 1468 | const char *symname; |
@@ -1288,10 +1502,9 @@ static void read_symbols(char *modname) | |||
1288 | handle_modversions(mod, &info, sym, symname); | 1502 | handle_modversions(mod, &info, sym, symname); |
1289 | handle_moddevtable(mod, &info, sym, symname); | 1503 | handle_moddevtable(mod, &info, sym, symname); |
1290 | } | 1504 | } |
1291 | if (is_vmlinux(modname) && vmlinux_section_warnings) { | 1505 | if (!is_vmlinux(modname) || |
1292 | check_sec_ref(mod, modname, &info, init_section, init_section_ref_ok); | 1506 | (is_vmlinux(modname) && vmlinux_section_warnings)) |
1293 | check_sec_ref(mod, modname, &info, exit_section, exit_section_ref_ok); | 1507 | check_sec_ref(mod, modname, &info); |
1294 | } | ||
1295 | 1508 | ||
1296 | version = get_modinfo(info.modinfo, info.modinfo_len, "version"); | 1509 | version = get_modinfo(info.modinfo, info.modinfo_len, "version"); |
1297 | if (version) | 1510 | if (version) |
@@ -1365,7 +1578,7 @@ static void check_for_gpl_usage(enum export exp, const char *m, const char *s) | |||
1365 | } | 1578 | } |
1366 | } | 1579 | } |
1367 | 1580 | ||
1368 | static void check_for_unused(enum export exp, const char* m, const char* s) | 1581 | static void check_for_unused(enum export exp, const char *m, const char *s) |
1369 | { | 1582 | { |
1370 | const char *e = is_vmlinux(m) ?"":".ko"; | 1583 | const char *e = is_vmlinux(m) ?"":".ko"; |
1371 | 1584 | ||
@@ -1398,7 +1611,7 @@ static void check_exports(struct module *mod) | |||
1398 | if (!mod->gpl_compatible) | 1611 | if (!mod->gpl_compatible) |
1399 | check_for_gpl_usage(exp->export, basename, exp->name); | 1612 | check_for_gpl_usage(exp->export, basename, exp->name); |
1400 | check_for_unused(exp->export, basename, exp->name); | 1613 | check_for_unused(exp->export, basename, exp->name); |
1401 | } | 1614 | } |
1402 | } | 1615 | } |
1403 | 1616 | ||
1404 | /** | 1617 | /** |
@@ -1458,13 +1671,12 @@ static int add_versions(struct buffer *b, struct module *mod) | |||
1458 | 1671 | ||
1459 | buf_printf(b, "\n"); | 1672 | buf_printf(b, "\n"); |
1460 | buf_printf(b, "static const struct modversion_info ____versions[]\n"); | 1673 | buf_printf(b, "static const struct modversion_info ____versions[]\n"); |
1461 | buf_printf(b, "__attribute_used__\n"); | 1674 | buf_printf(b, "__used\n"); |
1462 | buf_printf(b, "__attribute__((section(\"__versions\"))) = {\n"); | 1675 | buf_printf(b, "__attribute__((section(\"__versions\"))) = {\n"); |
1463 | 1676 | ||
1464 | for (s = mod->unres; s; s = s->next) { | 1677 | for (s = mod->unres; s; s = s->next) { |
1465 | if (!s->module) { | 1678 | if (!s->module) |
1466 | continue; | 1679 | continue; |
1467 | } | ||
1468 | if (!s->crc_valid) { | 1680 | if (!s->crc_valid) { |
1469 | warn("\"%s\" [%s.ko] has no CRC!\n", | 1681 | warn("\"%s\" [%s.ko] has no CRC!\n", |
1470 | s->name, mod->name); | 1682 | s->name, mod->name); |
@@ -1485,13 +1697,12 @@ static void add_depends(struct buffer *b, struct module *mod, | |||
1485 | struct module *m; | 1697 | struct module *m; |
1486 | int first = 1; | 1698 | int first = 1; |
1487 | 1699 | ||
1488 | for (m = modules; m; m = m->next) { | 1700 | for (m = modules; m; m = m->next) |
1489 | m->seen = is_vmlinux(m->name); | 1701 | m->seen = is_vmlinux(m->name); |
1490 | } | ||
1491 | 1702 | ||
1492 | buf_printf(b, "\n"); | 1703 | buf_printf(b, "\n"); |
1493 | buf_printf(b, "static const char __module_depends[]\n"); | 1704 | buf_printf(b, "static const char __module_depends[]\n"); |
1494 | buf_printf(b, "__attribute_used__\n"); | 1705 | buf_printf(b, "__used\n"); |
1495 | buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n"); | 1706 | buf_printf(b, "__attribute__((section(\".modinfo\"))) =\n"); |
1496 | buf_printf(b, "\"depends="); | 1707 | buf_printf(b, "\"depends="); |
1497 | for (s = mod->unres; s; s = s->next) { | 1708 | for (s = mod->unres; s; s = s->next) { |
@@ -1503,7 +1714,8 @@ static void add_depends(struct buffer *b, struct module *mod, | |||
1503 | continue; | 1714 | continue; |
1504 | 1715 | ||
1505 | s->module->seen = 1; | 1716 | s->module->seen = 1; |
1506 | if ((p = strrchr(s->module->name, '/')) != NULL) | 1717 | p = strrchr(s->module->name, '/'); |
1718 | if (p) | ||
1507 | p++; | 1719 | p++; |
1508 | else | 1720 | else |
1509 | p = s->module->name; | 1721 | p = s->module->name; |
@@ -1575,7 +1787,7 @@ static void read_dump(const char *fname, unsigned int kernel) | |||
1575 | void *file = grab_file(fname, &size); | 1787 | void *file = grab_file(fname, &size); |
1576 | char *line; | 1788 | char *line; |
1577 | 1789 | ||
1578 | if (!file) | 1790 | if (!file) |
1579 | /* No symbol versions, silently ignore */ | 1791 | /* No symbol versions, silently ignore */ |
1580 | return; | 1792 | return; |
1581 | 1793 | ||
@@ -1598,11 +1810,10 @@ static void read_dump(const char *fname, unsigned int kernel) | |||
1598 | crc = strtoul(line, &d, 16); | 1810 | crc = strtoul(line, &d, 16); |
1599 | if (*symname == '\0' || *modname == '\0' || *d != '\0') | 1811 | if (*symname == '\0' || *modname == '\0' || *d != '\0') |
1600 | goto fail; | 1812 | goto fail; |
1601 | 1813 | mod = find_module(modname); | |
1602 | if (!(mod = find_module(modname))) { | 1814 | if (!mod) { |
1603 | if (is_vmlinux(modname)) { | 1815 | if (is_vmlinux(modname)) |
1604 | have_vmlinux = 1; | 1816 | have_vmlinux = 1; |
1605 | } | ||
1606 | mod = new_module(NOFAIL(strdup(modname))); | 1817 | mod = new_module(NOFAIL(strdup(modname))); |
1607 | mod->skip = 1; | 1818 | mod->skip = 1; |
1608 | } | 1819 | } |
@@ -1653,38 +1864,40 @@ int main(int argc, char **argv) | |||
1653 | { | 1864 | { |
1654 | struct module *mod; | 1865 | struct module *mod; |
1655 | struct buffer buf = { }; | 1866 | struct buffer buf = { }; |
1656 | char fname[SZ]; | ||
1657 | char *kernel_read = NULL, *module_read = NULL; | 1867 | char *kernel_read = NULL, *module_read = NULL; |
1658 | char *dump_write = NULL; | 1868 | char *dump_write = NULL; |
1659 | int opt; | 1869 | int opt; |
1660 | int err; | 1870 | int err; |
1661 | 1871 | ||
1662 | while ((opt = getopt(argc, argv, "i:I:mso:aw")) != -1) { | 1872 | while ((opt = getopt(argc, argv, "i:I:msSo:aw")) != -1) { |
1663 | switch(opt) { | 1873 | switch (opt) { |
1664 | case 'i': | 1874 | case 'i': |
1665 | kernel_read = optarg; | 1875 | kernel_read = optarg; |
1666 | break; | 1876 | break; |
1667 | case 'I': | 1877 | case 'I': |
1668 | module_read = optarg; | 1878 | module_read = optarg; |
1669 | external_module = 1; | 1879 | external_module = 1; |
1670 | break; | 1880 | break; |
1671 | case 'm': | 1881 | case 'm': |
1672 | modversions = 1; | 1882 | modversions = 1; |
1673 | break; | 1883 | break; |
1674 | case 'o': | 1884 | case 'o': |
1675 | dump_write = optarg; | 1885 | dump_write = optarg; |
1676 | break; | 1886 | break; |
1677 | case 'a': | 1887 | case 'a': |
1678 | all_versions = 1; | 1888 | all_versions = 1; |
1679 | break; | 1889 | break; |
1680 | case 's': | 1890 | case 's': |
1681 | vmlinux_section_warnings = 0; | 1891 | vmlinux_section_warnings = 0; |
1682 | break; | 1892 | break; |
1683 | case 'w': | 1893 | case 'S': |
1684 | warn_unresolved = 1; | 1894 | sec_mismatch_verbose = 0; |
1685 | break; | 1895 | break; |
1686 | default: | 1896 | case 'w': |
1687 | exit(1); | 1897 | warn_unresolved = 1; |
1898 | break; | ||
1899 | default: | ||
1900 | exit(1); | ||
1688 | } | 1901 | } |
1689 | } | 1902 | } |
1690 | 1903 | ||
@@ -1693,9 +1906,8 @@ int main(int argc, char **argv) | |||
1693 | if (module_read) | 1906 | if (module_read) |
1694 | read_dump(module_read, 0); | 1907 | read_dump(module_read, 0); |
1695 | 1908 | ||
1696 | while (optind < argc) { | 1909 | while (optind < argc) |
1697 | read_symbols(argv[optind++]); | 1910 | read_symbols(argv[optind++]); |
1698 | } | ||
1699 | 1911 | ||
1700 | for (mod = modules; mod; mod = mod->next) { | 1912 | for (mod = modules; mod; mod = mod->next) { |
1701 | if (mod->skip) | 1913 | if (mod->skip) |
@@ -1706,6 +1918,8 @@ int main(int argc, char **argv) | |||
1706 | err = 0; | 1918 | err = 0; |
1707 | 1919 | ||
1708 | for (mod = modules; mod; mod = mod->next) { | 1920 | for (mod = modules; mod; mod = mod->next) { |
1921 | char fname[strlen(mod->name) + 10]; | ||
1922 | |||
1709 | if (mod->skip) | 1923 | if (mod->skip) |
1710 | continue; | 1924 | continue; |
1711 | 1925 | ||
@@ -1723,6 +1937,12 @@ int main(int argc, char **argv) | |||
1723 | 1937 | ||
1724 | if (dump_write) | 1938 | if (dump_write) |
1725 | write_dump(dump_write); | 1939 | write_dump(dump_write); |
1940 | if (sec_mismatch_count && !sec_mismatch_verbose) | ||
1941 | fprintf(stderr, "modpost: Found %d section mismatch(es).\n" | ||
1942 | "To see additional details select \"Enable full " | ||
1943 | "Section mismatch analysis\"\n" | ||
1944 | "in the Kernel Hacking menu " | ||
1945 | "(CONFIG_SECTION_MISMATCH).\n", sec_mismatch_count); | ||
1726 | 1946 | ||
1727 | return err; | 1947 | return err; |
1728 | } | 1948 | } |
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 0ffed17ec20c..999f15e0e008 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #define Elf_Shdr Elf32_Shdr | 17 | #define Elf_Shdr Elf32_Shdr |
18 | #define Elf_Sym Elf32_Sym | 18 | #define Elf_Sym Elf32_Sym |
19 | #define Elf_Addr Elf32_Addr | 19 | #define Elf_Addr Elf32_Addr |
20 | #define Elf_Sword Elf64_Sword | ||
20 | #define Elf_Section Elf32_Half | 21 | #define Elf_Section Elf32_Half |
21 | #define ELF_ST_BIND ELF32_ST_BIND | 22 | #define ELF_ST_BIND ELF32_ST_BIND |
22 | #define ELF_ST_TYPE ELF32_ST_TYPE | 23 | #define ELF_ST_TYPE ELF32_ST_TYPE |
@@ -31,6 +32,7 @@ | |||
31 | #define Elf_Shdr Elf64_Shdr | 32 | #define Elf_Shdr Elf64_Shdr |
32 | #define Elf_Sym Elf64_Sym | 33 | #define Elf_Sym Elf64_Sym |
33 | #define Elf_Addr Elf64_Addr | 34 | #define Elf_Addr Elf64_Addr |
35 | #define Elf_Sword Elf64_Sxword | ||
34 | #define Elf_Section Elf64_Half | 36 | #define Elf_Section Elf64_Half |
35 | #define ELF_ST_BIND ELF64_ST_BIND | 37 | #define ELF_ST_BIND ELF64_ST_BIND |
36 | #define ELF_ST_TYPE ELF64_ST_TYPE | 38 | #define ELF_ST_TYPE ELF64_ST_TYPE |
diff --git a/scripts/package/Makefile b/scripts/package/Makefile index 7c434e037e7f..5e326078a4a2 100644 --- a/scripts/package/Makefile +++ b/scripts/package/Makefile | |||
@@ -89,9 +89,8 @@ clean-dirs += $(objtree)/tar-install/ | |||
89 | # Help text displayed when executing 'make help' | 89 | # Help text displayed when executing 'make help' |
90 | # --------------------------------------------------------------------------- | 90 | # --------------------------------------------------------------------------- |
91 | help: FORCE | 91 | help: FORCE |
92 | @echo ' rpm-pkg - Build the kernel as an RPM package' | 92 | @echo ' rpm-pkg - Build both source and binary RPM kernel packages' |
93 | @echo ' binrpm-pkg - Build an rpm package containing the compiled kernel' | 93 | @echo ' binrpm-pkg - Build only the binary kernel package' |
94 | @echo ' and modules' | ||
95 | @echo ' deb-pkg - Build the kernel as an deb package' | 94 | @echo ' deb-pkg - Build the kernel as an deb package' |
96 | @echo ' tar-pkg - Build the kernel as an uncompressed tarball' | 95 | @echo ' tar-pkg - Build the kernel as an uncompressed tarball' |
97 | @echo ' targz-pkg - Build the kernel as a gzip compressed tarball' | 96 | @echo ' targz-pkg - Build the kernel as a gzip compressed tarball' |
diff --git a/scripts/package/buildtar b/scripts/package/buildtar index aa0ccdbd1f47..28574ae55170 100644 --- a/scripts/package/buildtar +++ b/scripts/package/buildtar | |||
@@ -69,8 +69,8 @@ cp -v -- "${objtree}/vmlinux" "${tmpdir}/boot/vmlinux-${KERNELRELEASE}" | |||
69 | # Install arch-specific kernel image(s) | 69 | # Install arch-specific kernel image(s) |
70 | # | 70 | # |
71 | case "${ARCH}" in | 71 | case "${ARCH}" in |
72 | i386|x86_64) | 72 | x86|i386|x86_64) |
73 | [ -f "${objtree}/arch/$ARCH/boot/bzImage" ] && cp -v -- "${objtree}/arch/$ARCH/boot/bzImage" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}" | 73 | [ -f "${objtree}/arch/x86/boot/bzImage" ] && cp -v -- "${objtree}/arch/x86/boot/bzImage" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}" |
74 | ;; | 74 | ;; |
75 | alpha) | 75 | alpha) |
76 | [ -f "${objtree}/arch/alpha/boot/vmlinux.gz" ] && cp -v -- "${objtree}/arch/alpha/boot/vmlinux.gz" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}" | 76 | [ -f "${objtree}/arch/alpha/boot/vmlinux.gz" ] && cp -v -- "${objtree}/arch/alpha/boot/vmlinux.gz" "${tmpdir}/boot/vmlinuz-${KERNELRELEASE}" |
diff --git a/scripts/patch-kernel b/scripts/patch-kernel index 67e4b1868e50..ece46ef0ba54 100755 --- a/scripts/patch-kernel +++ b/scripts/patch-kernel | |||
@@ -65,7 +65,7 @@ sourcedir=${1-/usr/src/linux} | |||
65 | patchdir=${2-.} | 65 | patchdir=${2-.} |
66 | stopvers=${3-default} | 66 | stopvers=${3-default} |
67 | 67 | ||
68 | if [ "$1" == -h -o "$1" == --help -o ! -r "$sourcedir/Makefile" ]; then | 68 | if [ "$1" = -h -o "$1" = --help -o ! -r "$sourcedir/Makefile" ]; then |
69 | cat << USAGE | 69 | cat << USAGE |
70 | usage: $PNAME [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ] | 70 | usage: $PNAME [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ] |
71 | source directory defaults to /usr/src/linux, | 71 | source directory defaults to /usr/src/linux, |
@@ -182,10 +182,12 @@ reversePatch () { | |||
182 | } | 182 | } |
183 | 183 | ||
184 | # set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION | 184 | # set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION |
185 | TMPFILE=`mktemp .tmpver.XXXXXX` || { echo "cannot make temp file" ; exit 1; } | 185 | # force $TMPFILEs below to be in local directory: a slash character prevents |
186 | # the dot command from using the search path. | ||
187 | TMPFILE=`mktemp ./.tmpver.XXXXXX` || { echo "cannot make temp file" ; exit 1; } | ||
186 | grep -E "^(VERSION|PATCHLEVEL|SUBLEVEL|EXTRAVERSION)" $sourcedir/Makefile > $TMPFILE | 188 | grep -E "^(VERSION|PATCHLEVEL|SUBLEVEL|EXTRAVERSION)" $sourcedir/Makefile > $TMPFILE |
187 | tr -d [:blank:] < $TMPFILE > $TMPFILE.1 | 189 | tr -d [:blank:] < $TMPFILE > $TMPFILE.1 |
188 | source $TMPFILE.1 | 190 | . $TMPFILE.1 |
189 | rm -f $TMPFILE* | 191 | rm -f $TMPFILE* |
190 | if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ] | 192 | if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ] |
191 | then | 193 | then |
@@ -202,11 +204,7 @@ echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} ($ | |||
202 | EXTRAVER= | 204 | EXTRAVER= |
203 | if [ x$EXTRAVERSION != "x" ] | 205 | if [ x$EXTRAVERSION != "x" ] |
204 | then | 206 | then |
205 | if [ ${EXTRAVERSION:0:1} == "." ]; then | 207 | EXTRAVER=${EXTRAVERSION#.} |
206 | EXTRAVER=${EXTRAVERSION:1} | ||
207 | else | ||
208 | EXTRAVER=$EXTRAVERSION | ||
209 | fi | ||
210 | EXTRAVER=${EXTRAVER%%[[:punct:]]*} | 208 | EXTRAVER=${EXTRAVER%%[[:punct:]]*} |
211 | #echo "$PNAME: changing EXTRAVERSION from $EXTRAVERSION to $EXTRAVER" | 209 | #echo "$PNAME: changing EXTRAVERSION from $EXTRAVERSION to $EXTRAVER" |
212 | fi | 210 | fi |
@@ -251,16 +249,16 @@ while : # incrementing SUBLEVEL (s in v.p.s) | |||
251 | do | 249 | do |
252 | CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" | 250 | CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" |
253 | EXTRAVER= | 251 | EXTRAVER= |
254 | if [ $stopvers == $CURRENTFULLVERSION ]; then | 252 | if [ $stopvers = $CURRENTFULLVERSION ]; then |
255 | echo "Stopping at $CURRENTFULLVERSION base as requested." | 253 | echo "Stopping at $CURRENTFULLVERSION base as requested." |
256 | break | 254 | break |
257 | fi | 255 | fi |
258 | 256 | ||
259 | SUBLEVEL=$((SUBLEVEL + 1)) | 257 | SUBLEVEL=$(($SUBLEVEL + 1)) |
260 | FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" | 258 | FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" |
261 | #echo "#___ trying $FULLVERSION ___" | 259 | #echo "#___ trying $FULLVERSION ___" |
262 | 260 | ||
263 | if [ $((SUBLEVEL)) -gt $((STOPSUBLEVEL)) ]; then | 261 | if [ $(($SUBLEVEL)) -gt $(($STOPSUBLEVEL)) ]; then |
264 | echo "Stopping since sublevel ($SUBLEVEL) is beyond stop-sublevel ($STOPSUBLEVEL)" | 262 | echo "Stopping since sublevel ($SUBLEVEL) is beyond stop-sublevel ($STOPSUBLEVEL)" |
265 | exit 1 | 263 | exit 1 |
266 | fi | 264 | fi |
@@ -297,7 +295,7 @@ fi | |||
297 | if [ x$gotac != x ]; then | 295 | if [ x$gotac != x ]; then |
298 | # Out great user wants the -ac patches | 296 | # Out great user wants the -ac patches |
299 | # They could have done -ac (get latest) or -acxx where xx=version they want | 297 | # They could have done -ac (get latest) or -acxx where xx=version they want |
300 | if [ $gotac == "-ac" ]; then | 298 | if [ $gotac = "-ac" ]; then |
301 | # They want the latest version | 299 | # They want the latest version |
302 | HIGHESTPATCH=0 | 300 | HIGHESTPATCH=0 |
303 | for PATCHNAMES in $patchdir/patch-${CURRENTFULLVERSION}-ac*\.* | 301 | for PATCHNAMES in $patchdir/patch-${CURRENTFULLVERSION}-ac*\.* |
diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 82e4993f0a73..52f032e409a3 100644 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion | |||
@@ -12,11 +12,36 @@ cd "${1:-.}" || usage | |||
12 | if head=`git rev-parse --verify HEAD 2>/dev/null`; then | 12 | if head=`git rev-parse --verify HEAD 2>/dev/null`; then |
13 | # Do we have an untagged version? | 13 | # Do we have an untagged version? |
14 | if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then | 14 | if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then |
15 | printf '%s%s' -g `echo "$head" | cut -c1-8` | 15 | git describe | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' |
16 | fi | 16 | fi |
17 | 17 | ||
18 | # Are there uncommitted changes? | 18 | # Are there uncommitted changes? |
19 | if git diff-index HEAD | read dummy; then | 19 | git update-index --refresh --unmerged > /dev/null |
20 | if git diff-index --name-only HEAD | grep -v "^scripts/package" \ | ||
21 | | read dummy; then | ||
20 | printf '%s' -dirty | 22 | printf '%s' -dirty |
21 | fi | 23 | fi |
24 | |||
25 | # All done with git | ||
26 | exit | ||
27 | fi | ||
28 | |||
29 | # Check for mercurial and a mercurial repo. | ||
30 | if hgid=`hg id 2>/dev/null`; then | ||
31 | tag=`printf '%s' "$hgid" | cut -d' ' -f2` | ||
32 | |||
33 | # Do we have an untagged version? | ||
34 | if [ -z "$tag" -o "$tag" = tip ]; then | ||
35 | id=`printf '%s' "$hgid" | sed 's/[+ ].*//'` | ||
36 | printf '%s%s' -hg "$id" | ||
37 | fi | ||
38 | |||
39 | # Are there uncommitted changes? | ||
40 | # These are represented by + after the changeset id. | ||
41 | case "$hgid" in | ||
42 | *+|*+\ *) printf '%s' -dirty ;; | ||
43 | esac | ||
44 | |||
45 | # All done with mercurial | ||
46 | exit | ||
22 | fi | 47 | fi |